v0.4.0
A breaking release that renames the Manipulation modality to Grabber
(gRPC route / C# surface / Python module all change), makes Cursor
SetPosition a persistent hold until Release, switches Grab to a
ray-based targeting model, and redesigns the CLI
(manipulate → grab, locomotion drive → drive,
display split into get / set). Update the ResoniteIO mod and the
resoio Python package in lockstep.
Changed
- Breaking — the Manipulation modality is renamed to Grabber: the gRPC
route changed from/resonite_io.v1.Manipulation/*to
/resonite_io.v1.Grabber/*(manipulation.proto→grabber.proto,
Manipulation*messages →Grabber*), the C# surface is now
GrabberService/IGrabberBridge/FrooxEngineGrabberBridge, and the
Python module and client areresoio.grabber/GrabberClient(the
GrabResult/GrabStatedataclasses keep their names). An old mod and a
new client (or vice versa) cannot talk over the renamed route — update the
ResoniteIO mod and theresoioPython package in lockstep - Breaking — Cursor
SetPositionnow holds the cursor untilRelease:
SetPositionwas a one-shot warp (the engine cursor reverted to the OS
pointer on the next frame, especially under Wine/Proton). It now registers a
persistent engine-side cursor lock so the in-engine cursor stays at the set
position across RPCs, while a Harmony patch on
InputInterface.CollectOutputStatemasks the lock from the renderer so the
real OS mouse pointer is never captured (no warp, no confine, no
center-pin).InputInterface.SetMousePosition(OS warp) is no longer called.
While held, real mouse movement does not move the in-engine cursor (clicks
still fire at the held position); switching world focus deactivates the hold - Breaking —
Manipulation.Grabis now ray-based:
ManipulationGrabRequest.point(WorldPoint) was removed (field 2 is
reserved). Grab always targets the point where the desktop cursor ray hits
the world and grabs grabbables withinradiusof that point. A ray miss
returnsgrabbed=false(not an error); VR mode (screen output inactive)
returnsFAILED_PRECONDITION. The Python client'sManipulationClient.grab
lost itspointparameter and the CLI lost--point. Aim with
resoio cursor set X Y(held until release), thenresoio grab - Breaking —
resoio displayis split intoget/setsubcommands: the
implicit branching ("no flags = get, any flag = set") is gone.
resoio display getprints the current snapshot;resoio display set
requires at least one of-W/--width,-H/--height,-F/--max-fpsand
prints the post-apply snapshot - Breaking —
resoio locomotion driveis flattened toresoio drive: the
locomotioncommand group is removed; the flags
(--sprint/--look-rate/--no-wait) are unchanged - Breaking —
resoio manipulateis renamed toresoio grab(following
the modality rename): the action positional
(grab/release/state/interactive) is optional and defaults to
grab, and--hand/--radiusare accepted before or after the action - CLI required arguments are now enforced by argparse:
resoio cursor set <x> <y>,resoio dash invoke <ref_id>, and
resoio context-menu highlight/invoke <index>reject missing positionals as
a usage error at parse time instead of failing mid-command. The argv shape
of valid invocations is unchanged
Added
Cursor.ReleaseRPC: releases the held cursor and returns control to the
OS pointer. Idempotent (releasing while not held succeeds and returns the
current state). Exposed asCursorClient.release()and
resoio cursor releaseCursorState.heldfield: reports whether the cursor is currently held,
returned bySetPosition/GetPosition/Releaseand shown in the CLI
output (held=True/False)
Fixed
- Grabbed objects no longer fly behind the user's head: in desktop mode
the hand moves from its rest pose to a holding pose right after a grab, and
a far-away grab left a large holder-local offset that got swung around with
the hand. The bridge now pins the grabbed object at its grab-time pose (the
cursor position) until the hand settles, so it stays where it was grabbed
and follows the hand from there