35 lines
3.1 KiB
Python
35 lines
3.1 KiB
Python
import unreal as u,json,time,math,traceback
|
|
from pathlib import Path
|
|
ROOT=Path(__file__).resolve().parents[3];LEVEL=u.get_editor_subsystem(u.LevelEditorSubsystem);EDITOR=u.get_editor_subsystem(u.UnrealEditorSubsystem);report={'floor_traces':{},'movement':None};u.EditorPythonScripting.set_keep_python_script_alive(True)
|
|
state={'start':time.monotonic(),'phase':'load','t':0,'positions':[]}
|
|
def pos(v):return u.Vector(v[0]*100,-v[1]*100,v[2]*100)
|
|
def tick(dt):
|
|
try:
|
|
elapsed=time.monotonic()-state['start']
|
|
if state['phase']=='finish':
|
|
if time.monotonic()-state['t']>3:
|
|
u.unregister_slate_post_tick_callback(handle);u.log('HOMESTEAD_WALK_VERIFIED '+json.dumps(report['movement']));u.SystemLibrary.quit_editor()
|
|
return
|
|
if elapsed>90:raise RuntimeError('Play-in-editor movement test timed out')
|
|
if state['phase']=='load':
|
|
if elapsed<12:return
|
|
u.AutomationLibrary.finish_loading_before_screenshot();LEVEL.editor_request_begin_play();state['phase']='settle';state['t']=time.monotonic();return
|
|
game=EDITOR.get_game_world()
|
|
if not game:return
|
|
pawn=u.GameplayStatics.get_player_pawn(game,0)
|
|
if not pawn:return
|
|
if state['phase']=='settle':
|
|
if time.monotonic()-state['t']<4:return
|
|
assert 'HomesteadWalker' in pawn.get_class().get_name(),pawn.get_class().get_name()
|
|
for name,xy in [('verandah',(0,4)),('living',(-1.8,1)),('corridor',(-7.5,-1.8)),('bedroom',(-10.7,-3.5)),('meditation',(-11.8,10.8)),('garage',(2,-18)),('garden',(0,13)),('training',(-10,-19))]:
|
|
result=u.SystemLibrary.line_trace_single(game,pos((*xy,2.9)),pos((*xy,-2)),u.TraceTypeQuery.TRACE_TYPE_QUERY1,True,[pawn],u.DrawDebugTrace.NONE,True);assert result is not None,name;report['floor_traces'][name]='hit'
|
|
p=pawn.get_actor_location();state['initial']=[p.x,p.y,p.z];assert 170<p.z<240,('Spawn not on floor',p.z);state['phase']='walk';state['t']=time.monotonic()
|
|
elif state['phase']=='walk':
|
|
p=pawn.get_actor_location();state['positions'].append([p.x,p.y,p.z]);pawn.add_movement_input(u.Vector(0,1,0),1)
|
|
if time.monotonic()-state['t']>2.5:
|
|
a=state['initial'];dist=math.hypot(p.x-a[0],p.y-a[1]);assert dist>100,('No meaningful movement',dist);assert 170<p.z<240,('Pawn left walking floor',p.z)
|
|
report['movement']={'pawn':pawn.get_class().get_name(),'start_cm':a,'end_cm':[p.x,p.y,p.z],'distance_cm':dist,'movement_mode':str(pawn.character_movement.movement_mode),'controller_possessed':pawn.get_controller() is not None,'sampled_positions':len(state['positions'])};report['status']='PASS: saved level, eight floor traces and possessed character walking from verandah into living entry';(ROOT/'unreal-walkthrough-verification.json').write_text(json.dumps(report,indent=2));LEVEL.editor_request_end_play();state['phase']='finish';state['t']=time.monotonic()
|
|
except Exception:
|
|
report['status']='FAILED';report['error']=traceback.format_exc();(ROOT/'unreal-walkthrough-verification.json').write_text(json.dumps(report,indent=2));u.log_error(report['error']);u.unregister_slate_post_tick_callback(handle);LEVEL.editor_request_end_play();u.SystemLibrary.quit_editor()
|
|
handle=u.register_slate_post_tick_callback(tick)
|