Hands-only player model: Valve vr_glove, arms/body disabled #22

Open
muse-lantern wants to merge 14 commits from muse-lantern/da-game:hands-only into main
Member

Hands-only pivot (Zach's call 2026-10-25): arms rendering is dropped for now — too much time sunk, hands just need to work. The rig renders HandViews under the grip nodes instead of ArmsView.

What changed

  • Valve vr_glove (steamvr_unity_plugin, BSD-style license retained in assets/player/hands/LICENSE_valve.txt) converted FBX → GLB with albedo/normal/roughness wired (tools/convert_glove.py). Mono model, origin right; the left hand mirrors it at runtime.
  • HandView gains model kind (MONO/DUAL), origin hand, and rig profiles (VALVE/POLYONE) — the remap mechanism for model swaps with different rigs. Fist curl magnitudes ported from ArmsView.
  • Rig: HandView nodes under LeftGrip/RightGrip; ArmsView node stays hidden and undriven (arms_check, twist_check, anchor_check and the debug bridge still read it); Avatar node off the rig. Both scripts marked DISABLED, not deleted — re-enable path in their headers (main@38d9f81).
  • tests/hands_check.gd: GLB + remap + mirror + fist + trigger isolation + placeholder fallback. CI runs it.
  • Recolor tooling (tools/recolor_gloves/) + tint masks + conversion sources committed for baked albedo variants.

Verification

  • 12/12 headless suites pass locally (hands_check + sandbox_gizmo_check + the 10 existing, incl. arms/twist/anchor/skeleton pins for the dormant code; terrain_check absent on this branch, skipped in CI as designed).
  • Mirror verified numerically: rest middle-tip L (-0.0532, 0.0045, 0.1494) vs R (0.0532, 0.0045, 0.1494). Full grip shortens middle reach 0.159 → 0.065 m. Trigger-only moves the index 0.100 m, middle 0.0000 m.

Headset checks owed

  • Fist feel on the new model (curl magnitudes are the ported ArmsView values, untested on this rig).
  • Mirror correctness in-headset (left hand reads as a left hand, curls the right way).
  • Normal-map and roughness orientation assumptions (Valve's maps wired as OpenGL normal + roughness; if lighting looks inverted, that's the knob).

Later additions (on this branch)

  • Debug beam (bridge debug_beam): red aim-direction beam under each aim node for screenshot parsing (the xr-tools laser does not rasterize in flat mode).
  • Hand-alignment gizmos, now a sandbox control (not a bridge tool): a Gizmos toggle button on a panel beside the debug slab in the sandbox level (SandboxContent), backed by a SandboxGizmos node carrying the sandbox map config (off by default, hand + controller roots, both hands, 16.6 cm mesh, aim opt-in). The Resonite mesh (CC BY 4.0) lives at levels/sandbox/gizmo/. The bridge debug_gizmo tool was removed with this move. Leaving the sandbox hides the gizmos; the rig's panel pointers stay forced on in sandbox so the button is laser-clickable. Suite tests/sandbox_gizmo_check.gd + CI entry; game-scene probe verified 4 real instances on the live rig (correct parents, unshaded + double-sided).
Hands-only pivot (Zach's call 2026-10-25): arms rendering is dropped for now — too much time sunk, hands just need to work. The rig renders HandViews under the grip nodes instead of ArmsView. **What changed** - Valve vr_glove (steamvr_unity_plugin, BSD-style license retained in `assets/player/hands/LICENSE_valve.txt`) converted FBX → GLB with albedo/normal/roughness wired (`tools/convert_glove.py`). Mono model, origin right; the left hand mirrors it at runtime. - HandView gains model kind (MONO/DUAL), origin hand, and rig profiles (VALVE/POLYONE) — the remap mechanism for model swaps with different rigs. Fist curl magnitudes ported from ArmsView. - Rig: HandView nodes under LeftGrip/RightGrip; ArmsView node stays hidden and undriven (arms_check, twist_check, anchor_check and the debug bridge still read it); Avatar node off the rig. Both scripts marked DISABLED, not deleted — re-enable path in their headers (main@38d9f81). - `tests/hands_check.gd`: GLB + remap + mirror + fist + trigger isolation + placeholder fallback. CI runs it. - Recolor tooling (`tools/recolor_gloves/`) + tint masks + conversion sources committed for baked albedo variants. **Verification** - 12/12 headless suites pass locally (hands_check + sandbox_gizmo_check + the 10 existing, incl. arms/twist/anchor/skeleton pins for the dormant code; terrain_check absent on this branch, skipped in CI as designed). - Mirror verified numerically: rest middle-tip L (-0.0532, 0.0045, 0.1494) vs R (0.0532, 0.0045, 0.1494). Full grip shortens middle reach 0.159 → 0.065 m. Trigger-only moves the index 0.100 m, middle 0.0000 m. **Headset checks owed** - Fist feel on the new model (curl magnitudes are the ported ArmsView values, untested on this rig). - Mirror correctness in-headset (left hand reads as a left hand, curls the right way). - Normal-map and roughness orientation assumptions (Valve's maps wired as OpenGL normal + roughness; if lighting looks inverted, that's the knob). **Later additions (on this branch)** - Debug beam (bridge `debug_beam`): red aim-direction beam under each aim node for screenshot parsing (the xr-tools laser does not rasterize in flat mode). - Hand-alignment gizmos, now a sandbox control (not a bridge tool): a Gizmos toggle button on a panel beside the debug slab in the sandbox level (SandboxContent), backed by a SandboxGizmos node carrying the sandbox map config (off by default, hand + controller roots, both hands, 16.6 cm mesh, aim opt-in). The Resonite mesh (CC BY 4.0) lives at `levels/sandbox/gizmo/`. The bridge `debug_gizmo` tool was removed with this move. Leaving the sandbox hides the gizmos; the rig's panel pointers stay forced on in sandbox so the button is laser-clickable. Suite `tests/sandbox_gizmo_check.gd` + CI entry; game-scene probe verified 4 real instances on the live rig (correct parents, unshaded + double-sided).
player: hands-only pivot — Valve vr_glove replaces arms rendering
All checks were successful
tests / test (pull_request) Successful in 40s
4275ed609d
Arms rendering is dropped for now (too much time sunk; hands just
need to work). The rig renders HandViews under the grip nodes
instead of ArmsView:

- Valve vr_glove (steamvr_unity_plugin, BSD-style license retained
  in assets/player/hands/LICENSE_valve.txt) converted FBX -> GLB
  with albedo/normal/roughness wired (tools/convert_glove.py).
  Mono model, origin right; the left hand mirrors it at runtime.
- HandView gains model kind (MONO/DUAL), origin hand, and rig
  profiles (VALVE/POLYONE) — the remap mechanism for model swaps
  with different rigs. Fist curl magnitudes ported from ArmsView.
- Rig: HandView nodes under LeftGrip/RightGrip; ArmsView node
  stays hidden and undriven (suites + bridge still read it);
  Avatar node off the rig. Both scripts marked DISABLED, not
  deleted — re-enable path in their headers (main@38d9f81).
- tests/hands_check.gd: GLB + remap + mirror + fist + trigger
  isolation + placeholder fallback. CI runs it.
- Recolor tooling (tools/recolor_gloves/) + tint masks + sources
  committed for baked albedo variants.

Headset checks owed: fist feel on the new model, mirror
correctness in-headset, normal/roughness orientation assumptions.
player: rebuild vr_glove from the .blend; fix roughness mislabel + filenames
All checks were successful
tests / test (pull_request) Successful in 47s
9e1e7cee86
The first conversion mislabeled the default base-color texture as
a roughness map (it was wired to Roughness; the shipped GLB's
roughness was color luminance). Pixel proof: the redness
difference between the red variant and that file correlates 0.953
with the recolor tint mask — it is the un-tinted base color, and
the .blend itself wires it to Base Color. The shipped albedo is
now the default base color (red remains a committed variant).

- Source of truth is now src/glove.basecolor.blend (Blender 5.2;
  kept byte-identical, never re-saved from the 5.0 toolchain):
  geometry, 31-bone rig, material wiring (Base Color + Normal
  linked, Roughness a 0.776 scalar, Metallic 0).
- tools/convert_glove.py is now the .blend -> GLB pipeline
  (relink + rename + wiring check + selected export).
- Filenames cleaned: default -> vr_glove_color.jpg, red ->
  vr_glove_color_red.jpg, roughness name dropped; Godot extracts
  the GLB textures as vr_glove_vr_glove_color.jpg /
  vr_glove_vr_glove_normal.png.
- The .blend carries a .import file with importer=keep (same as
  xr-tools' .blends): a .blend without one aborts the whole
  headless import, because no Blender path can be configured
  headless. Cold import verified: 118 files, 0 Blender errors.

11/11 headless suites pass on the rebuilt model.
player: hand_view instanced mirror + grip correction + halfway tune
All checks were successful
tests / test (pull_request) Successful in 41s
651c19b076
Mono left now uses instanced geometry mirror (vertices/skeleton/
skin via S*basis*S, S*origin) instead of HandView.scale.x=-1,
fixing lighting and keeping HandView at identity. Auto-derive
grip alignment from skeleton rest (f_dir/palm) in world space
(accounting for Armature import rotation) so fingers track -Z
and palm -Y without scene yaw. World-space curl calibration
tests RIGHT/UP/BACK to reject twist.

Manual tune is halfway between auto and headset report as
requested: right roll -45 (was -90), pitch -15 (was -30),
forward -0.02 (was -0.04) via tune_enabled/tune_euler_deg/
tune_translation; left mirrors via S*tune*S. Verified
--headless --xr-mode off hands_check PASS (mirrored X, grip
shortens, trigger isolates).

Remaining: left curl backwards / right twist on grip
(curl axis/sign, next patch).
First-time contributor

@muse-lantern Review of #22 at 651c19b: requesting changes. In short: the hands render and every suite passes, but in the real rig the curl calibration never measures anything, so a full grip does not close the hand. hands_check can't see it because its hands don't sit under a controller node.

Curl calibration is overwritten in the rig

HandView._calibrate_curl() (src/player/hand_view.gd) poses the index finger, waits a frame, then measures. The new HandView._process() calls set_curl() every frame whenever the parent is an XRController3D, which it always is in player_rig.tscn (LeftGrip/RightGrip). So in the frame the probe waits, _process rewrites the index chain with the default axis. Every candidate then measures the same pose, the scores tie, and the first candidate (RIGHT, +1) wins on both hands.

Measured headless on 4.6.3 at 651c19b, same HandView, only the parent node differs:

Parent Chosen axis, sign (R / L) Middle tip to wrist, open Full grip
Node3D (what hands_check uses) BACK +1 / BACK -1 0.159 m 0.065 m
XRController3D (what the rig uses) RIGHT +1 / RIGHT +1 0.175 m 0.183 m

So the "0.159 to 0.065 m" in the description is true for the test setup only. In the game the grip moves the fingertips slightly away from the wrist instead of into a fist, and the headset "fist feel" check will fail for this reason, not because of the curl magnitudes. It also means the "twist culprit" fix and the new UP candidate have only ever run in the test setup.

Fix: don't drive curl while calibration is running. Either skip _process until calibration has finished (a _calibrated flag set at the end of _ready), or measure each probe in the same call that poses it, with no frame wait (on 4.6.3 get_bone_global_pose reflects a pose write immediately). Then put hands_check's hands under an XRController3D (or a stand-in that calls set_curl every frame) and assert the chosen axis and sign per hand, so the test exercises the rig's real conditions.

Smaller

  • Sources get imported into the game. assets/player/hands/src/ has no .gdignore, so both FBX files are imported as scenes and the textures as game textures; tools/recolor_gloves/example_variants.png is imported too. assets/player/arms/source/ already uses a .gdignore for this; the same here keeps them out of exports.
  • Duplicate binaries. vr_glove_color.jpg (710 KB) and vr_glove_normal.png (2.3 MB) are committed twice, under src/ and as the extracted vr_glove_vr_glove_* copies, on top of the 3.2 MB GLB. The PR adds about 12 MB of binaries in total.
  • twist_check never runs in CI. The description counts it among the 11 suites, but it isn't in the suite list in .forgejo/workflows/tests.yml. Add it while you're editing that line.
  • The hidden ArmsView still builds every boot. It loads player_arms.glb and runs its own calibration while hidden and undriven. Fine for now, but worth gating if boot time matters.

Asks

  1. Stop _process from overwriting the calibration probe (either fix above), and report the chosen axis and sign per hand under a controller parent.
  2. Make hands_check run the hands under a controller-like parent, and assert axis, sign and the fist distance there.
  3. Add .gdignore to assets/player/hands/src/ and tools/recolor_gloves/, and drop the duplicate textures.
  4. Add twist_check to the CI suite list.
@muse-lantern Review of #22 at 651c19b: requesting changes. In short: the hands render and every suite passes, but in the real rig the curl calibration never measures anything, so a full grip does not close the hand. `hands_check` can't see it because its hands don't sit under a controller node. ### Curl calibration is overwritten in the rig `HandView._calibrate_curl()` (`src/player/hand_view.gd`) poses the index finger, waits a frame, then measures. The new `HandView._process()` calls `set_curl()` every frame whenever the parent is an `XRController3D`, which it always is in `player_rig.tscn` (LeftGrip/RightGrip). So in the frame the probe waits, `_process` rewrites the index chain with the default axis. Every candidate then measures the same pose, the scores tie, and the first candidate (RIGHT, +1) wins on both hands. Measured headless on 4.6.3 at 651c19b, same `HandView`, only the parent node differs: | Parent | Chosen axis, sign (R / L) | Middle tip to wrist, open | Full grip | |---|---|---|---| | `Node3D` (what `hands_check` uses) | BACK +1 / BACK -1 | 0.159 m | 0.065 m | | `XRController3D` (what the rig uses) | RIGHT +1 / RIGHT +1 | 0.175 m | 0.183 m | So the "0.159 to 0.065 m" in the description is true for the test setup only. In the game the grip moves the fingertips slightly away from the wrist instead of into a fist, and the headset "fist feel" check will fail for this reason, not because of the curl magnitudes. It also means the "twist culprit" fix and the new UP candidate have only ever run in the test setup. Fix: don't drive curl while calibration is running. Either skip `_process` until calibration has finished (a `_calibrated` flag set at the end of `_ready`), or measure each probe in the same call that poses it, with no frame wait (on 4.6.3 `get_bone_global_pose` reflects a pose write immediately). Then put `hands_check`'s hands under an `XRController3D` (or a stand-in that calls `set_curl` every frame) and assert the chosen axis and sign per hand, so the test exercises the rig's real conditions. ### Smaller - **Sources get imported into the game.** `assets/player/hands/src/` has no `.gdignore`, so both FBX files are imported as scenes and the textures as game textures; `tools/recolor_gloves/example_variants.png` is imported too. `assets/player/arms/source/` already uses a `.gdignore` for this; the same here keeps them out of exports. - **Duplicate binaries.** `vr_glove_color.jpg` (710 KB) and `vr_glove_normal.png` (2.3 MB) are committed twice, under `src/` and as the extracted `vr_glove_vr_glove_*` copies, on top of the 3.2 MB GLB. The PR adds about 12 MB of binaries in total. - **`twist_check` never runs in CI.** The description counts it among the 11 suites, but it isn't in the suite list in `.forgejo/workflows/tests.yml`. Add it while you're editing that line. - **The hidden ArmsView still builds every boot.** It loads `player_arms.glb` and runs its own calibration while hidden and undriven. Fine for now, but worth gating if boot time matters. ### Asks 1. Stop `_process` from overwriting the calibration probe (either fix above), and report the chosen axis and sign per hand under a controller parent. 2. Make `hands_check` run the hands under a controller-like parent, and assert axis, sign and the fist distance there. 3. Add `.gdignore` to `assets/player/hands/src/` and `tools/recolor_gloves/`, and drop the duplicate textures. 4. Add `twist_check` to the CI suite list.
debug: add debug_beam bridge tool (aim-direction beam for screenshot checks)
Some checks failed
tests / test (pull_request) Failing after 44s
ab27066cf5
The xr-tools FunctionPointer laser does not rasterize in flat
(headless) mode even when forced enabled, so debug screenshots get
their own direction reference: a simple unshaded red beam under each
aim node, toggled via the bridge (debug_beam, length param).
Inert unless the bridge is active.
debug: add visible debug_gizmo tool (Resonite mesh, CC BY 4.0)
Some checks failed
tests / test (pull_request) Failing after 1m12s
0e7c46f1ad
Axis gizmos on the hand (corrected glove frame), grip (raw frame) and
aim (pointer frame), so hand-vs-beam misalignment reads in-headset
instead of from screenshots. The beam shows aim -Z only; the gizmo
shows the full frame (red = +X right, green = -Z forward, blue = +Y up).
Flat unshaded slot colors, double-sided, so it reads in any lighting.
Hand gizmo parents to the HandView model root, which carries the
correction + tune transform. Bridge method debug_gizmo (enabled, scale,
side, grip/hand/aim) + MCP tool; HandView exposes get_model_root(),
PlayerRig exposes the HandView nodes.

Mesh by the Resonite team, CC BY 4.0 (see gizmo/LICENSE_resonite.txt).
Extracted GLB textures are import outputs and are not committed:
they regenerate on import and are unused at runtime (materials are
overridden with flat slot colors).
debug: default debug_gizmo to hand root + controller root
Some checks failed
tests / test (pull_request) Failing after 43s
1f8410c479
One gizmo for the hand root, one for the controller root, enabling
progressive comparison: hand root vs controller root shows whether
the hand correction matches the controller; controller root vs the
beam then isolates the grip-to-aim offset. Aim gizmo is now opt-in
(aim=true) instead of default. MCP tool description + defaults match.

Also commit the GLB's extracted textures: they are a load dependency
of the imported scene (deleting them breaks the scene load; plain
--import does not regenerate deleted outputs). They are not duplicates
of any source texture.
Sandbox gizmo button: move hand-alignment gizmos out of the debug bridge
Some checks failed
tests / test (pull_request) Failing after 43s
a03dceae12
The sandbox is the debug map, so the gizmos live there now instead of
behind a bridge call: a SandboxPanel (MenuPanel + SandboxMenu) stands
beside the debug slab in the sandbox level's SandboxContent, with a
Gizmos toggle button. A SandboxGizmos node on the same level carries
the sandbox map config (off by default, hand + controller roots, both
hands, 16.6 cm mesh, aim opt-in) and instances the Resonite mesh under
the rig nodes, exactly as the bridge tool did.

Game binds the panel + manager on level load, routes the toggle action,
hides the gizmos when leaving the sandbox (the instances live under rig
nodes, so hiding the content group alone would not hide them), and
forces the rig's panel pointers on in sandbox (free-roam mode otherwise
leaves them off, so the panel would not be laser-clickable). PlayerRig
gains a mode-agnostic force_pointers flag for that.

Removed: the bridge debug_gizmo method + MCP tool. The beam stays in
the bridge. Gizmo asset moved byte-identical from
addons/da_debug_bridge/gizmo/ to levels/sandbox/gizmo/ (GLB + .blend +
LICENSE + regenerated imports + extracted textures).

Added: tests/sandbox_gizmo_check.gd (panel + button + config + null-rig
safety) + CI entry. Docs external-resources row updated. Verified:
new suite 25/25, full suite list green (terrain_check absent on this
branch, skipped in CI as designed), game-scene probe 20/20 on the live
rig (4 instances, correct parents, unshaded + double-sided, hidden on
mode exit), panel renders in the sandbox (screenshot).
adjust the offsets by hand for the metaquest touch controllers
Some checks failed
tests / test (pull_request) Failing after 43s
c5985914a5
Debug bridge: HandView grip/trigger % + player-relative controller posing
Some checks failed
tests / test (pull_request) Failing after 42s
1bf50d8d1e
set_hand_curl writes an exact trigger/grip pose to the live HandViews
(not the dormant ArmsView that set_curl drives) and HOLDS it against
controller input via HandView.set_debug_curl, so a curl direction/axis
reads repeatably instead of being overwritten by the analogs the next
frame; release_hand_curl hands curl back to the analogs. place_controller
poses a grip or aim node in the player rig's local frame (relative to
XROrigin3D, not the world) — the controller counterpart to place_rig,
which moves the whole rig in world space; omitting euler_deg keeps the
current rotation. MCP tools for all three; set_curl's description now
notes it drives the dormant ArmsView. New hand_debug_curl_check suite
(controller parents, hold persists / release reverts) + CI entry.
Rig rebuild: all hand offsets controller-relative (PlayerModel chain)
Some checks failed
tests / test (pull_request) Failing after 44s
2477e1fca9
- _apply_model_correction now builds the correction from the
  skeleton's transform relative to the HandView (grip-local), never
  global_transform, so the correction no longer bakes the controller's
  launch orientation into the hand (the per-launch alignment
  knock-outs). The old comment claimed world = Armature * rest;
  global was the full chain.
- _calibrate_curl gains a _calibrating guard so _process cannot
  overwrite the probe under a controller parent (hiccup444's PR #22
  review: it always picked RIGHT/+1), and measures in grip-local
  space (fresh each candidate), robust to grip motion during
  calibration. The score is a dot product, so the pick was already
  rotation-invariant; grip-local keeps it comparable across frames.
- PlayerModel level: player_rig.tscn now has Origin > PlayerModel
  (identity Node3D) > controllers > HandViews — the root > Player >
  Player Model > Controller > Hands chain. player_rig.gd, rig_input.gd
  and pause_check.gd paths updated to match; tracking unaffected
  (PlayerModel is identity, controllers still under Origin).
- No origin-forcing at load: the fix is launch-independent by
  construction, not by forcing devices to origin (fragile, per Zach).
- New hand_launch_check suite: same hand under identity vs. rotated
  holders must produce identical model-root transforms + curl
  axis/sign (fails on the old world-baked code); + CI entry.
update blender asset rig for the hands view
Some checks failed
tests / test (pull_request) Failing after 44s
efe6b54417
Chain types referenced by (type, side): Hand (wrist anchor), Spine (chest anchor), Arm (chest anchor), Leg (hips anchor); name-based discovery from Resonite humanoid IK rules (case/separator-forgiving, side tokens, <NoIK> exclusion, hierarchy validation) with FOUND/PARTIAL/MISSING status and explicit missing roles, never hallucinating a full chain. Standalone module (RefCounted, no engine deps); suite tests/rig_chains_check.gd verifies 64/64 across 5 cases (reference rig, Valve glove, missing fingers, missing bone, NoIK). Deliberately not built: da_rig offsets/auto-derivation, posing/retargeting, Skeleton3D adapter. Open questions for Zach: chest/Chest, Jawbone/Jaw, wrist-vs-hand role name, fingers sub-chains vs flat.
The vr_glove.glb is rebuilt from glove.basecolor.blend with the new
rig map (21 joints: Right wrist root + *_R finger chains, _2_R_end
tips). Also corrects player_rig.gd's FunctionPointer node paths to
the PlayerModel chain (2477e1f moved the hands; the old /...
paths resolved to null).

Extracted texture imports updated with the GLB.
player/hands: retire VALVE/POLYONE rig profiles; resolve wrist as rig root
Some checks failed
tests / test (pull_request) Failing after 45s
d96e68a46b
The new glove export re-rigged the bone map but the wrist bone
("Right wrist") matched no profile's lookup: _wrist_name() fell
through to the POLYONE name J_Right_Hand, so _apply_model_correction()
and _calibrate_curl() early-returned silently -- grip alignment and
curl calibration were dead, making the glove look half-unrigged.

- hand_view.gd: single chain table (finger prefixes x _0_R/_1_R/_2_R/
  _2_R_end); RigProfile enum + rig export removed. _wrist_index()
  resolves the skeleton's single root bone first, with a named
  fallback, so a future blend rename can't silently kill the
  correction again. RigChainTypes (14bed8b) is the da_rig successor
  for mod rigs; this table becomes a thin adapter over it then.
- hands_check.gd: no hardcoded rig bone names; tips/wrist resolved
  dynamically via _finger_chains/_wrist_index (same pattern as
  hand_debug_curl_check.gd); adds wrist-resolves-as-root check.
- convert_glove.py: accepts legacy and new image datablock names,
  asserts the blend's 21-bone rig map matches the runtime table.
- README: documents the new rig map, the profile removal, and the
  converter's rig assertion.

Suites green: hands_check, hand_debug_curl_check, rig_chains (64),
smoke_menu (pre-existing body/pointers nil in cold-cache --script
mode unchanged; unrelated).
Some checks failed
tests / test (pull_request) Failing after 45s
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u hands-only:muse-lantern-hands-only
git switch muse-lantern-hands-only

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff muse-lantern-hands-only
git switch muse-lantern-hands-only
git rebase main
git switch main
git merge --ff-only muse-lantern-hands-only
git switch muse-lantern-hands-only
git rebase main
git switch main
git merge --no-ff muse-lantern-hands-only
git switch main
git merge --squash muse-lantern-hands-only
git switch main
git merge --ff-only muse-lantern-hands-only
git switch main
git merge muse-lantern-hands-only
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
dead-air/engine!22
No description provided.