P08-03: 配置の通常操作受入
This commit is contained in:
+10
-1
@@ -186,6 +186,11 @@ def make(base, source, checker):
|
||||
def os_meta(row, pid):
|
||||
row['input_method'] = method
|
||||
if method != 'native_os': return
|
||||
p = row['position']
|
||||
p['dispatch'] = {k:copy.deepcopy(v) for k,v in p.items() if k != 'selected_cell'}
|
||||
occupant = next((o['entity_id'] for o in runtime['world']['occupancies'] if p['world_cell'] in o['cells']), '')
|
||||
p['selection'] = {'required':row['id'] == 'pan_zoom', 'entity_id':occupant, 'occupant_id':occupant}
|
||||
p['diagnostics'] = {'getter_cell':[]}
|
||||
requests = [{'action':'cell', 'world_cell':row['position']['world_cell'],
|
||||
'viewport':row['position']['viewport'], 'screen':row['position']['screen'],
|
||||
'viewport_to_screen':[1,0,0,1,0,0], 'guide_visible':False, 'guide_rect':[0,0,0,0]}]
|
||||
@@ -200,7 +205,11 @@ def make(base, source, checker):
|
||||
prefix = directory+'/'+row['id']+'-'+str(sequence)+'/'
|
||||
request.update(target_pid=pid, sequence=sequence)
|
||||
put(out/(prefix+'request.json'), request)
|
||||
put(out/(prefix+'observed.json'), {'pid':pid,'sequence':sequence,'events':[{'synthetic':True}]})
|
||||
events = [{'synthetic':True}]
|
||||
if request['action'] == 'cell':
|
||||
events = [{'synthetic':True, 'button':1, 'pressed':True,
|
||||
'position':p['dispatch']['viewport'], 'dispatch':copy.deepcopy(p['dispatch'])}]
|
||||
put(out/(prefix+'observed.json'), {'pid':pid,'sequence':sequence,'events':events})
|
||||
receipt = directory+'/'+row['id']+'-os.json'
|
||||
put(out/receipt, {'method':'native_os','target_pid':pid,'timestamp_ns':10000,
|
||||
'collector_pid':999,'tool_name':'mock CUA','tool_call_id':'synthetic-only',
|
||||
|
||||
+39
-8
@@ -5,9 +5,11 @@ extends "res://tests/fixtures/p08-03/placement.gd"
|
||||
var receipts: Array = []
|
||||
var all_requests: Array = []
|
||||
var input_observer: Node
|
||||
var last_dispatch: Dictionary = {}
|
||||
|
||||
class InputObserver extends Node:
|
||||
var events: Array = []
|
||||
var endpoint: Node
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseButton or event is InputEventKey:
|
||||
var row := {"ticks_usec": Time.get_ticks_usec(), "text": event.as_text(), "pressed": event.is_pressed()}
|
||||
@@ -15,6 +17,8 @@ class InputObserver extends Node:
|
||||
row["button"] = event.button_index
|
||||
row["position"] = [event.position.x, event.position.y]
|
||||
row["ctrl"] = event.ctrl_pressed
|
||||
if endpoint != null and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
|
||||
row["dispatch"] = endpoint.dispatch_position(event.position)
|
||||
events.append(row)
|
||||
|
||||
func request(action: Dictionary) -> void:
|
||||
@@ -45,6 +49,9 @@ func request(action: Dictionary) -> void:
|
||||
tree.quit(1)
|
||||
return
|
||||
await frames()
|
||||
for event: Dictionary in input_observer.events.slice(first_event):
|
||||
if event.has("dispatch"):
|
||||
last_dispatch = event["dispatch"]
|
||||
json_file(stem + "/observed.json", {"pid": OS.get_process_id(), "sequence": serial,
|
||||
"events": input_observer.events.slice(first_event), "status": main.build_status_label.text})
|
||||
receipts.append("os-pair/" + stem + "/ack.json")
|
||||
@@ -86,6 +93,7 @@ func setup() -> void:
|
||||
tree.root.add_child(main)
|
||||
tree.root.title = "The Tree P08-03 " + role + " PID " + str(OS.get_process_id())
|
||||
input_observer = InputObserver.new()
|
||||
input_observer.endpoint = self
|
||||
tree.root.add_child(input_observer)
|
||||
await frames()
|
||||
json_file(role + "-profile.json", {"pid": OS.get_process_id(), "user_data_dir": OS.get_user_data_dir(), "engine": Engine.get_version_info(), "display": DisplayServer.get_name()})
|
||||
@@ -147,19 +155,23 @@ func click(cell: Vector3i) -> Dictionary:
|
||||
var mapping := affine(view.get_screen_transform() * view.get_global_transform_with_canvas().affine_inverse())
|
||||
var guide_rect: Rect2 = main.opening_guide.get_global_rect()
|
||||
observed_cell = null
|
||||
last_dispatch = {}
|
||||
await request({"action": "cell", "world_cell": vector(cell), "viewport": [viewport.x, viewport.y],
|
||||
"screen": [screen.x, screen.y], "viewport_to_screen": mapping,
|
||||
"guide_rect": [guide_rect.position.x, guide_rect.position.y, guide_rect.size.x, guide_rect.size.y],
|
||||
"guide_visible": main.opening_guide.visible,
|
||||
"instructions": "Click screen coordinates derived from viewport_to_screen (includes canvas stretch and window translation). Retain actual CUA coordinates and screenshots. If clipped or intercepted, recollect; never substitute fixed pixels."})
|
||||
var selected: Variant = observed_cell
|
||||
if not selected is Vector3i:
|
||||
# With no active build tool, the normal preview selects a facility.
|
||||
var occupant: StringName = runtime.world_service.get_occupant(cell)
|
||||
expect(not occupant.is_empty() and view.selected_entity_id == occupant, "actual OS facility selection")
|
||||
selected = view.canvas_to_cell(view.get_local_mouse_position())
|
||||
expect(selected is Vector3i and selected == cell, "observed OS selected cell")
|
||||
return {"world_cell": vector(cell), "selected_cell": vector(selected) if selected is Vector3i else [],
|
||||
var selected: Array = last_dispatch.get("world_cell", [])
|
||||
expect(selected == vector(cell), "observed OS selected cell")
|
||||
var occupant: StringName = runtime.world_service.get_occupant(cell)
|
||||
var selection_required: bool = view.build_definition == null and not view.excavation_mode and not view.demolition_mode and not occupant.is_empty()
|
||||
if selection_required:
|
||||
expect(view.selected_entity_id == occupant, "actual OS facility selection")
|
||||
var getter: Variant = view.canvas_to_cell(view.get_local_mouse_position())
|
||||
return {"world_cell": vector(cell), "selected_cell": selected,
|
||||
"dispatch": last_dispatch.duplicate(true),
|
||||
"selection": {"required": selection_required, "entity_id": String(view.selected_entity_id), "occupant_id": String(occupant)},
|
||||
"diagnostics": {"getter_cell": vector(getter) if getter is Vector3i else []},
|
||||
"local": [local.x, local.y], "viewport": [viewport.x, viewport.y],
|
||||
"viewport_transform": affine(view.get_global_transform_with_canvas()),
|
||||
"screen": [screen.x, screen.y], "screen_transform": affine(view.get_screen_transform()),
|
||||
@@ -168,6 +180,25 @@ func click(cell: Vector3i) -> Dictionary:
|
||||
"bounds": runtime.world_service.get_bounds(), "zoom": view.zoom_level,
|
||||
"pan": [view.pan_offset.x, view.pan_offset.y]}
|
||||
|
||||
func dispatch_position(position: Vector2) -> Dictionary:
|
||||
var view: WorldPreview = main.world_preview
|
||||
var local := view.get_global_transform_with_canvas().affine_inverse() * position
|
||||
var cell: Variant = view.canvas_to_cell(local)
|
||||
return {"world_cell": vector(cell) if cell is Vector3i else [],
|
||||
"entity_id_before": String(view.selected_entity_id),
|
||||
"occupant_id_before": String(runtime.world_service.get_occupant(cell)) if cell is Vector3i else "",
|
||||
"local": [local.x, local.y], "viewport": [position.x, position.y],
|
||||
"viewport_transform": affine(view.get_global_transform_with_canvas()),
|
||||
"screen_transform": affine(view.get_screen_transform()),
|
||||
"screen": vector2(view.get_screen_transform() * local),
|
||||
"bounds": runtime.world_service.get_bounds(),
|
||||
"map_position": vector2(view.get_map_rect().position),
|
||||
"cell_dimensions": vector2(view.get_cell_rect(Vector3i.ZERO).size),
|
||||
"zoom": view.zoom_level, "pan": vector2(view.pan_offset)}
|
||||
|
||||
func vector2(value: Vector2) -> Array:
|
||||
return [value.x, value.y]
|
||||
|
||||
func wheel(event: InputEventMouseButton, move_mode: bool) -> void:
|
||||
var action := point(main.world_preview)
|
||||
action.merge({"action": "wheel", "direction": "up" if event.button_index == MOUSE_BUTTON_WHEEL_UP else "down",
|
||||
|
||||
Reference in New Issue
Block a user