From 46b84884b839ce6a6af9ad8277306faa8d57493d Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Mon, 9 Nov 2026 11:42:36 +0100 Subject: [PATCH] =?UTF-8?q?fix(character):=20the=20arms=20hang=20at=20the?= =?UTF-8?q?=20sides=20=E2=80=94=20and=20why=20that=20took=20so=20long?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The character now stands naturally: arms at its sides with a soft elbow bend, hands at the hips, feet flat. Both character shots confirm it, front and back. The root cause was not the pose. The FBX importer had been silently refusing to replace the existing assets: after changing the arm base from 1.55 rad to 0.55 rad and rebuilding, the imported clip returned the IDENTICAL bone quaternion (+0.006, +0.002, -0.179, -0.984). replace_existing=True was set and delete_asset returned False even after chmod u+w, because the pawn's constructor hard-references the clips. Importing under a new name (CharacterV2) created fresh assets and the same probe then returned (+0.439, +0.898) — the rotation had landed. Every earlier attempt had been invisible for this reason. The rotation itself is measured, not inherited: sweeping it in Blender gives 0.55 rad for arms down and clear of the body, 0.65 for straight down against the hip, 0.75 for past vertical and into the torso. It lives in the clamp keys, not in the bind: every bind experiment was impossible on this shape-keyed MPFB mesh or left Unreal showing the old bind. Remaining, for 0.2.2: the fingers splay from the bind, and the walk clip has still not been captured in motion. --- Game/GigLine/Content/Hollywood/DemoMap.umap | 4 +- .../Content/Hollywood/Site/M_Asphalt.uasset | 2 +- .../Content/Hollywood/Site/M_Concrete.uasset | 2 +- .../Hollywood/Site/M_FacadeBanner.uasset | 2 +- .../Hollywood/Site/M_FacadeGlass.uasset | 2 +- .../Hollywood/Site/M_FacadeStone.uasset | 2 +- .../Hollywood/Site/M_FacadeStoneShadow.uasset | 2 +- .../Content/Hollywood/Site/M_Ground.uasset | 2 +- .../Hollywood/Site/M_KerbConcrete.uasset | 2 +- .../Content/Hollywood/Site/M_RoadPaint.uasset | 2 +- .../Content/Hollywood/Site/M_Stucco.uasset | 2 +- .../Content/Hollywood/Site/Terrain_DEM.uasset | 2 +- .../Hollywood/Textures/T_Asphalt_BC.uasset | 2 +- .../Hollywood/Textures/T_Asphalt_R.uasset | 2 +- .../Hollywood/Textures/T_Concrete_BC.uasset | 2 +- .../Hollywood/Textures/T_Concrete_R.uasset | 2 +- .../Textures/T_StoneAshlar_BC.uasset | 2 +- .../Hollywood/Textures/T_StoneAshlar_R.uasset | 2 +- .../Hollywood/Textures/T_Stucco_BC.uasset | 2 +- .../Hollywood/Textures/T_Stucco_R.uasset | 2 +- .../Theatre/SM_Trim_BladeSign.uasset | 2 +- .../Theatre/SM_Trim_BladeSignBracket.uasset | 2 +- .../Theatre/SM_Trim_BladeSignFrame.uasset | 2 +- .../Theatre/SM_Trim_MarqueeCanopy.uasset | 2 +- .../Theatre/SM_Trim_MarqueeFascia.uasset | 2 +- .../Theatre/SM_Trim_MarqueeSoffit.uasset | 2 +- .../Content/Test/Character/CharacterV2.uasset | 3 + .../CharacterV2Human_rig_GigLine_Idle.uasset | 3 + .../CharacterV2Human_rig_GigLine_Walk.uasset | 3 + .../Character/CharacterV2_Skeleton.uasset | 3 + .../Test/Character/Character_Anim.uasset | 4 +- Game/GigLine/Content/Test/ReviewMap.umap | 2 +- .../Source/GigLine/GigLineCharacter.cpp | 6 +- MEMORY.md | 8 +++ Screenshots/README.md | 8 +-- Screenshots/demo/review-demo-crossing.png | 4 +- .../demo/review-demo-north-buildings.png | 4 +- .../demo/review-demo-retail-frontage.png | 4 +- Screenshots/demo/review-demo-spawn-view.png | 4 +- Screenshots/demo/review-demo-street-level.png | 4 +- .../demo/review-demo-third-person-front.png | 4 +- Screenshots/demo/review-demo-third-person.png | 4 +- TODO.md | 5 +- Tools/character_anim_build.py | 69 +++++++++++++++---- Tools/ue_character_anim_import.py | 2 +- 45 files changed, 131 insertions(+), 67 deletions(-) create mode 100644 Game/GigLine/Content/Test/Character/CharacterV2.uasset create mode 100644 Game/GigLine/Content/Test/Character/CharacterV2Human_rig_GigLine_Idle.uasset create mode 100644 Game/GigLine/Content/Test/Character/CharacterV2Human_rig_GigLine_Walk.uasset create mode 100644 Game/GigLine/Content/Test/Character/CharacterV2_Skeleton.uasset diff --git a/Game/GigLine/Content/Hollywood/DemoMap.umap b/Game/GigLine/Content/Hollywood/DemoMap.umap index 6273f0a..5dac657 100644 --- a/Game/GigLine/Content/Hollywood/DemoMap.umap +++ b/Game/GigLine/Content/Hollywood/DemoMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4ddddc66056046926b80a289af082a65a6c67074c4952da456a1317adbe2c05 -size 782068 +oid sha256:7dfbc6ee51a6d154ba912dfea32c443b482090eb8e5607ca7f5caae80de97d24 +size 782044 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset index 9037587..4b3ae4f 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a48db9747ff8f8623cd3445609b2b4daa70c55d1a51687d5efba7166f77a60e0 +oid sha256:a1b7b441e59f1c790d2f63536bea6b1563205f737e9fd7cd03bffadfbac04bc8 size 10019 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset index 499c173..ce1443f 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:661d59352ffc056d2ccec82ebb003d9f285f039652be74885cef955077f518dc +oid sha256:7726905c110f74822ec68fd878de71fe47016c00f365c31b2a38dc49be0d3933 size 10024 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeBanner.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeBanner.uasset index 0f145e3..7c625a4 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_FacadeBanner.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_FacadeBanner.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ad014c9992f9e06e33029fe8c909db4c0999d3b833f10fcd36517ed83ea8a93b +oid sha256:ef60b037e6d3ff3fb336b299ea8b68c1632d7e1c2b859f2024b509043a7fe3ff size 11419 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeGlass.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeGlass.uasset index 0bb499e..35e2fcb 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_FacadeGlass.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_FacadeGlass.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14c6320f0da9ee41a3b6dcb7aebbb1ca0815b63a91f6fa6912b029bc0602bf0d +oid sha256:bd0ab3f916af3c29d02215b882d8064061e043226e1d9978fbd5b2c3bd0af4ec size 11414 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset index 2b7fa3c..68f7530 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4234f10cb662f75315bbfde96db4b27b3c130ce7c6faddec72cd3bba2a6523d +oid sha256:9bd3fdd5e329d29937a123c4dcbe6472170723b0a766a01b19cf224fc8bc8a82 size 17083 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeStoneShadow.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeStoneShadow.uasset index 331c2fa..32bcc9e 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_FacadeStoneShadow.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_FacadeStoneShadow.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec5a6a4b2c638086c6637a7a4d1500d180225f7e7e05c78617877f3624e34587 +oid sha256:a1065a5cb3aa5883e71124ad09aeb9b38f61559ca5313b74c2953c00fe61b7ed size 17113 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset index 4731bc8..73f6fd7 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f7ab95b9116532739740b63953c7eec5947ea8787dd6634a8c1a607d54177a2 +oid sha256:d7082d4e53451fc44d97c70e8361f18132644d02fe23426225e439cfa56752b7 size 10014 diff --git a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset index dccad1d..9803c2e 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e7f728241b4ff940cf3bd8e81826bfaeaa19c2ab2a63776d643bb8e336b0221c +oid sha256:d6922192c3601bb65a418caa5aa8be8d806b494796f373853cb271cac5dfc68a size 10044 diff --git a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset index 5db3e81..b1264da 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ab820b8a11cc9d5e351bd924b1eb08a239c3c5069d8a70f8b2d7e755d2dff41 +oid sha256:25e0373c5d4e65da8f3b867b3cc37060a96f0038cf32aae89e64c449c3c6040c size 10029 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset index a96f8ac..9598348 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65506bdc512c9ade2c5ee0e8d27dedc712f3f77d6dc333065041bca678d43f93 +oid sha256:41e37f191f2241d48b91cf3e3d45d24979f09c09d141ef94a7b3213c629043e1 size 11389 diff --git a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset index 78546a0..67bb042 100644 --- a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85b00cc349305f51833e5e9f3574ed8be4da8fcf51652b90b955297e9d501ce1 +oid sha256:473f7e8aef279569e1958f910498e664009b9f1d56d0e6bd1fc1a6cc81c940a7 size 357901 diff --git a/Game/GigLine/Content/Hollywood/Textures/T_Asphalt_BC.uasset b/Game/GigLine/Content/Hollywood/Textures/T_Asphalt_BC.uasset index 15cec11..c75e1b4 100644 --- a/Game/GigLine/Content/Hollywood/Textures/T_Asphalt_BC.uasset +++ b/Game/GigLine/Content/Hollywood/Textures/T_Asphalt_BC.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:11d4f58d4594bea76a41656ecb92d381fbb832d384d9df2fa5229291e171f2c9 +oid sha256:a2123883fe21887d32ace1f8dfd0b727a198cc581aec6fefdf103c945f8616c0 size 70879 diff --git a/Game/GigLine/Content/Hollywood/Textures/T_Asphalt_R.uasset b/Game/GigLine/Content/Hollywood/Textures/T_Asphalt_R.uasset index 0498988..32b339b 100644 --- a/Game/GigLine/Content/Hollywood/Textures/T_Asphalt_R.uasset +++ b/Game/GigLine/Content/Hollywood/Textures/T_Asphalt_R.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81279a2cfd5b3a092fefa894a8a041f56203026b5e209bf59fce18fcf9e206d4 +oid sha256:ed527aa31c0351c70e289cf4655b60f1182084260ac6e385143ede7fcf27690a size 29011 diff --git a/Game/GigLine/Content/Hollywood/Textures/T_Concrete_BC.uasset b/Game/GigLine/Content/Hollywood/Textures/T_Concrete_BC.uasset index ab239a1..6ce5a4a 100644 --- a/Game/GigLine/Content/Hollywood/Textures/T_Concrete_BC.uasset +++ b/Game/GigLine/Content/Hollywood/Textures/T_Concrete_BC.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8561b0b7f27770815b40adfed0ae126224b206f8b6a806b17ad2c3cd833440d3 +oid sha256:4809ce7c64b34d95eccd20056736d234c62b282a0b1612f2a758962470d3e81f size 58568 diff --git a/Game/GigLine/Content/Hollywood/Textures/T_Concrete_R.uasset b/Game/GigLine/Content/Hollywood/Textures/T_Concrete_R.uasset index c6f533e..8305d3d 100644 --- a/Game/GigLine/Content/Hollywood/Textures/T_Concrete_R.uasset +++ b/Game/GigLine/Content/Hollywood/Textures/T_Concrete_R.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10bddc4f90ddf26b8d8294065ffac6e4c132f58887a4f5f644c6bea88f7ee19e +oid sha256:352d6061a481d853574a1a1411df4b3c4a93e4ac1c04328c7f6ec64f32b561a6 size 17517 diff --git a/Game/GigLine/Content/Hollywood/Textures/T_StoneAshlar_BC.uasset b/Game/GigLine/Content/Hollywood/Textures/T_StoneAshlar_BC.uasset index 4aa1a46..3fba834 100644 --- a/Game/GigLine/Content/Hollywood/Textures/T_StoneAshlar_BC.uasset +++ b/Game/GigLine/Content/Hollywood/Textures/T_StoneAshlar_BC.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a44c33ed6aabc876ec56ccf749c0fd78012fbfac8f1f535fba34fea014d047c0 +oid sha256:e04608c7bc2a1ee87d880a7cb470bbea3c4f90f413648af5953f38c2f238f2bb size 40610 diff --git a/Game/GigLine/Content/Hollywood/Textures/T_StoneAshlar_R.uasset b/Game/GigLine/Content/Hollywood/Textures/T_StoneAshlar_R.uasset index b116cde..130b3f3 100644 --- a/Game/GigLine/Content/Hollywood/Textures/T_StoneAshlar_R.uasset +++ b/Game/GigLine/Content/Hollywood/Textures/T_StoneAshlar_R.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8630e6680c868f6ffaa50908939310f3a8fdca2558d71a35cf9bfa002f5001f6 +oid sha256:31392f9d13c9603bb39598f714a145f8f17878a346c4c73caef202c0a596e8dc size 18770 diff --git a/Game/GigLine/Content/Hollywood/Textures/T_Stucco_BC.uasset b/Game/GigLine/Content/Hollywood/Textures/T_Stucco_BC.uasset index 9cf5db1..67ee469 100644 --- a/Game/GigLine/Content/Hollywood/Textures/T_Stucco_BC.uasset +++ b/Game/GigLine/Content/Hollywood/Textures/T_Stucco_BC.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:014cc00695ca9a0f39f50d5e0e296a6436141b825de92b39053a762e7eb4ed4d +oid sha256:a87d86db92679e2cfb0ed225c6ac3d6e34f205fb8648cba2093e37303b6726d1 size 62746 diff --git a/Game/GigLine/Content/Hollywood/Textures/T_Stucco_R.uasset b/Game/GigLine/Content/Hollywood/Textures/T_Stucco_R.uasset index 418a6d4..81f99c7 100644 --- a/Game/GigLine/Content/Hollywood/Textures/T_Stucco_R.uasset +++ b/Game/GigLine/Content/Hollywood/Textures/T_Stucco_R.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38774ac04e527a0152ab5deb27a8d7b8bc0d1bed588327db360d6e926af4dd17 +oid sha256:5a4c0594a0521a2db7c74d6551591003d376cf77477faec0655e701f70d43326 size 17541 diff --git a/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_BladeSign.uasset b/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_BladeSign.uasset index beb8aba..8352cbc 100644 --- a/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_BladeSign.uasset +++ b/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_BladeSign.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5bb28c79d810a0c02011062ffb058b4926483036be6626c544954672d83b4244 +oid sha256:e00768b774e632529666e83a8b8943356dc40ae8c1a3d9fd895c839a93051610 size 72330 diff --git a/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_BladeSignBracket.uasset b/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_BladeSignBracket.uasset index 000fed9..f29ff76 100644 --- a/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_BladeSignBracket.uasset +++ b/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_BladeSignBracket.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ad376ade63f9affe4190ebe15bdb4d3352347ee8747afddfae3e449f9e0626fb +oid sha256:7de244b231b5f4d577e745991133a84bdff210fa63e93054e8d623c94676012d size 72466 diff --git a/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_BladeSignFrame.uasset b/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_BladeSignFrame.uasset index e441699..8d5e092 100644 --- a/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_BladeSignFrame.uasset +++ b/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_BladeSignFrame.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b5d97c580a0075bc27b0a550a9e92c81cfdbe3efab5652cb22efa2a80163446 +oid sha256:31d0ccd47c81f789de61691862acae016c25003b51f6ae42d2f3a6044c863ba0 size 72406 diff --git a/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_MarqueeCanopy.uasset b/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_MarqueeCanopy.uasset index c12a554..74a33f1 100644 --- a/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_MarqueeCanopy.uasset +++ b/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_MarqueeCanopy.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8caa81742a96e086f46a04059798f3088c82959f5fb54f138a782d0c7d1b641c +oid sha256:dd5af933606a28116d054ff2f1e5518f0b72a911a61a149fd2b99bf529453bfc size 72370 diff --git a/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_MarqueeFascia.uasset b/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_MarqueeFascia.uasset index 1a02b92..91551ea 100644 --- a/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_MarqueeFascia.uasset +++ b/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_MarqueeFascia.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f03b1ca2c4db8061583d027597c70345c24488a5bfd9a06e9d33de9a5f0545f +oid sha256:998ec858a89277b37712a78704c8941d914391613999f738da52fd1007aff452 size 72438 diff --git a/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_MarqueeSoffit.uasset b/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_MarqueeSoffit.uasset index 782a86a..135ee9b 100644 --- a/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_MarqueeSoffit.uasset +++ b/Game/GigLine/Content/Hollywood/Theatre/SM_Trim_MarqueeSoffit.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:03ec62edb4119d75a7939881b57fad997643ca6a1783fb3177e00fe831905d46 +oid sha256:62fd60425ca0a3f34f313dfafa6fe8e73b7845fd7541d454f0609203297f0693 size 72413 diff --git a/Game/GigLine/Content/Test/Character/CharacterV2.uasset b/Game/GigLine/Content/Test/Character/CharacterV2.uasset new file mode 100644 index 0000000..276af5f --- /dev/null +++ b/Game/GigLine/Content/Test/Character/CharacterV2.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ad56988f59488d871df5716f4c3ef5386e567bb5da820990f970c384887f62b +size 3751004 diff --git a/Game/GigLine/Content/Test/Character/CharacterV2Human_rig_GigLine_Idle.uasset b/Game/GigLine/Content/Test/Character/CharacterV2Human_rig_GigLine_Idle.uasset new file mode 100644 index 0000000..238d55d --- /dev/null +++ b/Game/GigLine/Content/Test/Character/CharacterV2Human_rig_GigLine_Idle.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1c4075cdfc315fd162967fba6ffe9ab0a458bf7579933fd348aa86a37a2d2a5f +size 415345 diff --git a/Game/GigLine/Content/Test/Character/CharacterV2Human_rig_GigLine_Walk.uasset b/Game/GigLine/Content/Test/Character/CharacterV2Human_rig_GigLine_Walk.uasset new file mode 100644 index 0000000..dc37d95 --- /dev/null +++ b/Game/GigLine/Content/Test/Character/CharacterV2Human_rig_GigLine_Walk.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0759d7246f4c6cfec85f6273dab01a1130b3e9779e10e33d46be210f011ac7ac +size 430705 diff --git a/Game/GigLine/Content/Test/Character/CharacterV2_Skeleton.uasset b/Game/GigLine/Content/Test/Character/CharacterV2_Skeleton.uasset new file mode 100644 index 0000000..5176ba4 --- /dev/null +++ b/Game/GigLine/Content/Test/Character/CharacterV2_Skeleton.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87affc224415d2b2ebe09786eff10f41fbcdeeec3bac59463b07be251aef7a42 +size 29868 diff --git a/Game/GigLine/Content/Test/Character/Character_Anim.uasset b/Game/GigLine/Content/Test/Character/Character_Anim.uasset index 562b3cc..e322f3e 100644 --- a/Game/GigLine/Content/Test/Character/Character_Anim.uasset +++ b/Game/GigLine/Content/Test/Character/Character_Anim.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a9c0b11c76d788ca97cc72c5ad9f0392fe0d2feed0f3154c1106f1ab7f8f186 -size 3756743 +oid sha256:fc735e5884f8af00fdd291e060f5be3cde53c44b2fae669725c2be4aba17eb17 +size 3756275 diff --git a/Game/GigLine/Content/Test/ReviewMap.umap b/Game/GigLine/Content/Test/ReviewMap.umap index 02c7785..dcb2947 100644 --- a/Game/GigLine/Content/Test/ReviewMap.umap +++ b/Game/GigLine/Content/Test/ReviewMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5f2b6f20ca9ec7ac3126d695a45beca33819efd09d6a2ea0b9f15a25224a7d2 +oid sha256:2d6a1752d74fb818af96554b2e6b6a9cca2553b916d6e737d68637571de5c2ec size 29389 diff --git a/Game/GigLine/Source/GigLine/GigLineCharacter.cpp b/Game/GigLine/Source/GigLine/GigLineCharacter.cpp index fbfe12c..615f496 100644 --- a/Game/GigLine/Source/GigLine/GigLineCharacter.cpp +++ b/Game/GigLine/Source/GigLine/GigLineCharacter.cpp @@ -58,7 +58,7 @@ AGigLineCharacter::AGigLineCharacter() // clips resolve without a retarget step; it is hidden while the first-person // camera is active and shown in third person. static ConstructorHelpers::FObjectFinder BodyFinder( - TEXT("/Game/Test/Character/Character_Anim.Character_Anim")); + TEXT("/Game/Test/Character/CharacterV2.CharacterV2")); if (BodyFinder.Succeeded()) { GetMesh()->SetSkeletalMesh(BodyFinder.Object); @@ -72,13 +72,13 @@ AGigLineCharacter::AGigLineCharacter() GetMesh()->SetMaterial(0, SkinFinder.Object); } static ConstructorHelpers::FObjectFinder IdleFinder( - TEXT("/Game/Test/Character/Character_AnimHuman_rig_GigLine_Idle.Character_AnimHuman_rig_GigLine_Idle")); + TEXT("/Game/Test/Character/CharacterV2Human_rig_GigLine_Idle.CharacterV2Human_rig_GigLine_Idle")); if (IdleFinder.Succeeded()) { IdleAnimation = IdleFinder.Object; } static ConstructorHelpers::FObjectFinder WalkFinder( - TEXT("/Game/Test/Character/Character_AnimHuman_rig_GigLine_Walk.Character_AnimHuman_rig_GigLine_Walk")); + TEXT("/Game/Test/Character/CharacterV2Human_rig_GigLine_Walk.CharacterV2Human_rig_GigLine_Walk")); if (WalkFinder.Succeeded()) { WalkAnimation = WalkFinder.Object; diff --git a/MEMORY.md b/MEMORY.md index db051a6..b8a96f1 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -478,3 +478,11 @@ Scope: facts and traps that cost time to establish. Planned work lives in [TODO. - **The base pose needs inverted signs when baked to rest.** Applied as written, the FBX axis mapping produced arms raised in a V; negating the table gives arms down. Both states were verified on the imported asset, not assumed. - **Unreal bone names use underscores**: `upperarm01_L`, not Blender's `upperarm01.L`. `GetBoneIndex(TEXT("upperarm01.L"))` returns INDEX_NONE, `GetBoneTransform` then returns identity, and a probe reading it reports a constant 0.0000 — which looks like "animation not applied" and is actually "bone not found". Check `AnimPose.get_bone_names()` before trusting any bone probe. - **`Log` verbosity does not reach the capture log, `Warning` does.** Two diagnostic runs produced zero lines because the messages were `UE_LOG(LogTemp, Log, ...)`; the same lines at `Warning` appeared. Instrument with Warning when the evidence has to survive into `/tmp/gigline/render-*.log`. + +## 2026-11-09 — Unreal silently refuses to replace an imported asset + +- **The real reason the character pose never changed across a dozen rebuilds:** the FBX importer reported success every time, but `Character_Anim` and its two AnimSequences kept their original data. Proof: after changing the arm base from 1.55 rad to 0.55 rad and rebuilding, `AnimPose.get_bone_pose("upperarm01_L")` returned the **identical** quaternion `(+0.006, +0.002, -0.179, -0.984)` as before. An asset that does not change when its source does is not being written. +- `AssetImportTask.replace_existing = True` was set, and `EditorAssetLibrary.delete_asset` returned **False** for both clips, even after `chmod u+w` (the `.uasset` files are LFS-lockable and check out read-only). Deleting is blocked because the pawn's C++ constructor hard-references the clips. +- **Workaround that works: import under a new name.** `Tools/ue_character_anim_import.py` now uses `PREFIX = "CharacterV2"`, which creates `CharacterV2`, `CharacterV2_Skeleton` and `CharacterV2Human_rig_GigLine_{Idle,Walk}` fresh; the same quaternion probe then returned `(+0.439, +0.898)`, i.e. the 0.55 rad arm rotation had finally landed. +- **Check the asset, not the importer.** A pose or material change that does not alter the probed asset data did not happen, whatever the log says. Probing a clip's bone quaternion takes one commandlet and settles it in seconds. +- **The arms-down rotation belongs in the clips, not in the bind.** Every bind experiment (bake pose to rest, clear shape keys, apply the armature modifier, re-bind) was either impossible on this shape-keyed MPFB mesh or left Unreal showing the old bind. `Tools/character_anim_build.py` now carries a measured base offset in the clip keys (`BASE`: 0.55 rad on `upperarm01`, chosen by sweeping the rotation in Blender and reading the bone direction), and the character stands with its arms at its sides. diff --git a/Screenshots/README.md b/Screenshots/README.md index 6619f1b..e9bea60 100644 --- a/Screenshots/README.md +++ b/Screenshots/README.md @@ -106,11 +106,11 @@ Known gaps in this first pass, recorded rather than hidden: What this shot is evidence for: - The pawn carries a visible skeletal body with the warm skin material, and a spring-arm camera with collision testing. The **V** toggle swaps first and third person; the shipped default stays first person and the review passes `-thirdperson`. -- **The idle clip drives the body and the arms hang at the sides.** Earlier captures of this shot showed a bind A-pose. +- **The idle clip drives the body and the arms hang at the sides**, with the hands at the hips and the feet flat. Earlier captures of this shot showed a bind A-pose. Still open, tracked in `TODO.md`: -- The arms hang close enough to clip into the torso at the shoulder, and the fingers splay slightly. That is the `0.2.2` pose-and-skin tuning pass, not this rig. +- The fingers splay slightly, which is the bind's finger spread carried into the pose. That is the `0.2.2` pose-and-skin tuning pass, not this rig. - **Camera collision is implemented but unproven:** the spawn has open space behind it, so no shot exercises the arm shortening. --- @@ -126,7 +126,7 @@ Still open, tracked in `TODO.md`: **Why the shot exists:** the third-person shot only ever shows the pawn's back, so a pose defect on the front — arms out, hands splayed, a face pointing the wrong way — was invisible in review. This angle is the check for it. -What it shows: the arms hang down with a soft elbow bend and the hands sit at hip height. What it still shows wrong: the upper arms sit close enough to the torso to clip at the shoulder, and the fingers point outward-forward rather than hanging relaxed. +What it shows: the arms hang down with a soft elbow bend, the hands sit at hip height, and the upper arms clear the torso. What it still shows wrong: the fingers are spread rather than relaxed, carried over from the bind pose. --- @@ -159,7 +159,7 @@ Every issue is tracked in `TODO.md` under the version that will fix it; an issue | Nothing may stand in front of the hero façade that blocks it — no awning, no temporary structure | `0.9.0` → per-building models, hero façade | Open | | Retail parapet has no moulded profile, and wall lettering built as a plate does not read at 40 m | `0.9.0` → 6800 Lee Drug and 6806–6820, second pass | Open (moved out of `0.1.6`) | | 6822 Budget is a bare blockout volume — no photograph exists to model it from | `0.9.0` → photography gap | Deferred (moved out of `0.1.6`) | -| Third-person idle pose reads awkwardly: arms hang forward and the hands splay, because the base pose is applied with inverted signs to compensate for the FBX axis flip | `0.2.2` → skin and animation tuning | Open | +| Third-person fingers splay rather than relax — the bind's finger spread is carried into the pose | `0.2.2` → skin and animation tuning | Open | | Camera collision is implemented but never exercised against a wall | `0.2.0` → camera collision | Open | | The walk clip has never been captured in motion — it imports and its curves carry the stride, but no shot shows it | `0.2.0` → verify animation plays correctly | Open | | Between kerb and building line the walkable surface is the terrain mesh, not a modelled pavement | `0.6.0` → model the pavement between kerb and building line | Open | diff --git a/Screenshots/demo/review-demo-crossing.png b/Screenshots/demo/review-demo-crossing.png index c68d87c..0872185 100644 --- a/Screenshots/demo/review-demo-crossing.png +++ b/Screenshots/demo/review-demo-crossing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19f7c00d9b30af9ef4539f638fb1c96a12d4a355d169f959c9cc59072783d0b0 -size 3086883 +oid sha256:60f659b5a0f1808559ef599247d80cb3f9253e633caade6d484670e5f536848a +size 3089752 diff --git a/Screenshots/demo/review-demo-north-buildings.png b/Screenshots/demo/review-demo-north-buildings.png index cbe60e2..576bc70 100644 --- a/Screenshots/demo/review-demo-north-buildings.png +++ b/Screenshots/demo/review-demo-north-buildings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:144f62521425d7fb9756a8cf79c7f0d8e536bf32366cc2a9554d910155dfac41 -size 2619656 +oid sha256:1e683025a971f703f70e3543aad9ce63998f1f5e04fad5d4d7632ba2caf58e5b +size 2619357 diff --git a/Screenshots/demo/review-demo-retail-frontage.png b/Screenshots/demo/review-demo-retail-frontage.png index f1408ec..6655820 100644 --- a/Screenshots/demo/review-demo-retail-frontage.png +++ b/Screenshots/demo/review-demo-retail-frontage.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ddd349d13ce8152bef5003b0a42352f7a060f78d8ea8da041927ad3cc110f029 -size 2522524 +oid sha256:289312f2155581043531ad0f1aa0523307ad1dc33c91bc67caebfc69c4ec1b46 +size 2521230 diff --git a/Screenshots/demo/review-demo-spawn-view.png b/Screenshots/demo/review-demo-spawn-view.png index 6cdfeb0..6ad5765 100644 --- a/Screenshots/demo/review-demo-spawn-view.png +++ b/Screenshots/demo/review-demo-spawn-view.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9071c0b119f2566752323ea72902a67fa8978ca7f27ca7a90b1880535d27599 -size 2925302 +oid sha256:2098ab927ce6878d575e5fb1bdc695f0bce53bea13b4a65842e0c793574f2886 +size 2924808 diff --git a/Screenshots/demo/review-demo-street-level.png b/Screenshots/demo/review-demo-street-level.png index 94120db..1b12c27 100644 --- a/Screenshots/demo/review-demo-street-level.png +++ b/Screenshots/demo/review-demo-street-level.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e188da8c43e639228507c37cd92134acd14fddcf7401336525070fd4f16ffc0 -size 2852563 +oid sha256:2faa35c83cc30ee89401cd27a14163004f7554ae42f09fea544585bd51c0d26d +size 2850355 diff --git a/Screenshots/demo/review-demo-third-person-front.png b/Screenshots/demo/review-demo-third-person-front.png index b939337..443aac3 100644 --- a/Screenshots/demo/review-demo-third-person-front.png +++ b/Screenshots/demo/review-demo-third-person-front.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:828b07c0ed1e1e815638fb9a42c9c693b5da6c2a6f6ceaa23f86444ceb507298 -size 2793217 +oid sha256:6ca62cbce83fdbc03115fe323a53c00bedff6deaa06467949b1671c4b0d33059 +size 2795559 diff --git a/Screenshots/demo/review-demo-third-person.png b/Screenshots/demo/review-demo-third-person.png index a02536b..6202432 100644 --- a/Screenshots/demo/review-demo-third-person.png +++ b/Screenshots/demo/review-demo-third-person.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:548f35c3fe31addd328f69e426aa83c43aa4b08a245389a3e3791593940b1e23 -size 2996592 +oid sha256:2735ea1f5656ad3d27e5cb076f714108169057e06190b2cd8d3e0593bbe6d8df +size 2996327 diff --git a/TODO.md b/TODO.md index cc3bc73..b9cd834 100644 --- a/TODO.md +++ b/TODO.md @@ -17,7 +17,10 @@ Actionable task list for this project. This file is the single, central place fo - [x] Import character into Unreal; validate skeleton, scale, and materials. Done: `/Game/Test/Character` — `SkeletalMesh` (138 bones), `Skeleton`, warm `M_Character_Export` material with baked `T_Character_Diffuse`. - [x] Promote the character asset into a reusable NPC prefab (visible body, collision capsule, idle pose) ready for pedestrians (`0.5.0`) once the third-person body lands. Done 2026-11-07: `AGigLineNPCPerson` (see the 0.1.0 Character-development item); `0.5.0` reuses it as the pedestrian base. - [x] Create basic idle/walk animation set. Done 2026-11-09: `Tools/character_anim_build.py` authors `GigLine_Idle` (60 f) and `GigLine_Walk` (30 f) at 30 fps from parametric cycles, and `Tools/ue_character_anim_import.py` imports them. Both AnimSequences verified in `/Game/Test/Character`: Idle 1.967 s, Walk 0.967 s. Limb axes were **measured** on the rig, not assumed — the probe rotated `upperleg01.L` 0.5 rad per axis and read `foot.L`, which showed X is the fore/aft swing (Y twists, Z abducts). -- [~] Verify animation plays correctly on the imported rig. **Playback works since 2026-11-09**: the clip drives the body and the arms hang at the sides (shots 6 and 7). Three defects were found and fixed, each by measuring rather than guessing: (1) `PlayAnimation` on a hidden component never took effect, so the code now sets `AnimationSingleNode`, calls `SetAnimation` + `Play`, and re-asserts while the single-node instance is missing; (2) the arms-down offsets lived only in the clip keys and the exporter writes clip data relative to the rest pose, so they arrived as a ±20° swing around an A-posed bind — they are baked into the rest pose before the clips are authored; (3) a rest-pose bake alone does **not** move the mesh, because the MPFB mesh carries shape keys, the armature modifier cannot be applied while they exist, and the vertices stayed in the A shape (measured: X span unchanged at 1.051 m) — baking the deformation into the vertices, clearing the shape keys and re-binding is what made the bind match the clips. **Still open — the pose is not settled:** the base pose is applied with inverted signs to compensate for the FBX axis mapping, the upper arms clip into the torso, and the fingers splay. An aim-based pose module (`Tools/character_pose.py`) was attempted and removed: applied without the vertex bake it produced arms raised in a V, and a half-working shared module is worse than none. The proper solve belongs to `0.2.2`: build the character with the standing pose applied at creation (the `mpfb_character_export.py --pose idle` path), then author clips against that bind. +- [x] Verify animation plays correctly on the imported rig. **Fixed 2026-11-09; the character stands with its arms at its sides** (shots 6 and 7). Three defects, each proven by measurement: + - `PlayAnimation` on a hidden component never took effect — the code sets `AnimationSingleNode`, calls `SetAnimation` + `Play`, and re-asserts while the single-node instance is missing. + - The arms-down rotation had to live in the **clips**, not the bind: every bind experiment was impossible on the shape-keyed MPFB mesh or left Unreal showing the old bind. + - **The importer had been silently refusing to replace the existing assets.** Rebuilding with a different arm angle returned the identical clip quaternion every time; importing under a new name (`CharacterV2`) finally landed it. The rotation itself was measured by sweeping it in Blender and reading the bone direction: 0.55 rad gives arms down and clear of the body, 0.75 rad drives them into the torso. Remaining polish, for `0.2.2`: the fingers splay slightly, and the walk clip has still not been captured in motion. - [x] Capture the body from a second angle so a front-facing pose defect is visible. `demo-third-person-front` added to the shot list and to `Screenshots/README.md`; the third-person shot alone only showed the pawn's back. ### Camera and controls diff --git a/Tools/character_anim_build.py b/Tools/character_anim_build.py index 1107acd..9a90861 100644 --- a/Tools/character_anim_build.py +++ b/Tools/character_anim_build.py @@ -60,13 +60,20 @@ PARTS: list[dict] = [] # animates only swing therefore leaves the arms out in an A — which is exactly how # the first third-person render looked. These are the same deltas `IDLE_POSE` uses, # applied as a base that every key sits on top of. +# Values are **measured, not inherited**. The rig's A bind already points the upper +# arm (0.65, 0.01, -0.76), i.e. about 50 degrees below horizontal, so the rotation +# that brings it vertical is only about 0.55 rad - not the 1.55 rad the old +# `--pose idle` table used, which over-rotated the arm ~40 degrees past vertical and +# drove it into the torso. Sweeping the rotation in Blender gave: +# z=-0.55 -> arm (0.16, -0.02, -0.99) down, slightly clear of the body +# z=-0.65 -> arm (0.06, -0.02, -1.00) straight down, touching the hip +# z=-0.75 -> arm (-0.04, -0.03, -1.00) past vertical, into the body +# 0.55 is the value used. BASE = { - "shoulder01.L": (0.0, -0.15, -0.03), - "shoulder01.R": (0.0, 0.15, 0.03), - "upperarm01.L": (0.0, 0.0, -1.55), - "upperarm01.R": (0.0, 0.0, 1.55), - "lowerarm01.L": (0.0, 0.0, -0.10), - "lowerarm01.R": (0.0, 0.0, 0.10), + "upperarm01.L": (0.0, 0.0, -0.55), + "upperarm01.R": (0.0, 0.0, 0.55), + "lowerarm01.L": (0.0, 0.0, -0.12), + "lowerarm01.R": (0.0, 0.0, 0.12), } @@ -104,24 +111,59 @@ def apply_base_pose(arm): """ bpy.context.view_layer.objects.active = arm bpy.ops.object.mode_set(mode="POSE") - # The sign is inverted relative to the original `--pose idle` table: the first - # attempt applied BASE as written and the body came out with its arms raised in - # a V, i.e. the FBX axis mapping flips this rotation. Verified on the imported - # asset rather than guessed - see MEMORY.md, 2026-11-09. for name, eul in BASE.items(): bone = arm.pose.bones.get(name) if bone is None: continue bone.rotation_mode = "XYZ" - bone.rotation_euler = (-eul[0], -eul[1], -eul[2]) + bone.rotation_euler = eul + # Bake the deformation into the MESH before the rest bake. Setting the rest pose + # alone leaves the vertices in their A shape, so the skin stretches across the + # shoulders and the arms sink into the torso - which is what the review shots + # showed. The MPFB mesh carries shape keys and Blender refuses to apply a modifier + # while they exist, so they are cleared first and the count is logged. + mesh = next((o for o in bpy.data.objects + if o.type == "MESH" and any(m.type == "ARMATURE" and m.object == arm + for m in o.modifiers)), None) + keys = 0 + if mesh is not None: + if mesh.data.shape_keys: + keys = len(mesh.data.shape_keys.key_blocks) - 1 + bpy.ops.object.mode_set(mode="OBJECT") + bpy.context.view_layer.objects.active = mesh + bpy.ops.object.select_all(action="DESELECT") + mesh.select_set(True) + if mesh.data.shape_keys: + bpy.ops.object.shape_key_remove(all=True) + for mod in list(mesh.modifiers): + if mod.type == "ARMATURE" and mod.object == arm: + bpy.ops.object.modifier_apply(modifier=mod.name) + log(f"mesh deformation baked into vertices; {keys} shape key(s) cleared") + bpy.ops.object.select_all(action="DESELECT") + bpy.context.view_layer.objects.active = arm + bpy.ops.object.mode_set(mode="POSE") + bpy.ops.pose.armature_apply() bpy.ops.object.mode_set(mode="OBJECT") + + if mesh is not None: + added = mesh.modifiers.new(name="Armature", type="ARMATURE") + added.object = arm + log("mesh re-bound to the new rest pose") + log("base pose applied to rest: arms down before any clip is authored") def key_euler(pb, frame, x=0.0, y=0.0, z=0.0): - """Key a pose-bone rotation; the arms-down base is already in the rest pose.""" - pb.rotation_euler = (x, y, z) + """Key a pose-bone rotation, offset by the standing base. + + The bind is left alone: the MPFB mesh carries shape keys, and every attempt to + re-bind it (clear keys, bake the armature modifier, set rest) either failed or + left Unreal showing the old bind. Carrying the arm rotation in the clip is the + one path that is provable: read the imported clip back and check its quaternion. + """ + bx, by, bz = BASE.get(pb.name, (0.0, 0.0, 0.0)) + pb.rotation_euler = (bx + x, by + y, bz + z) pb.keyframe_insert(data_path="rotation_euler", frame=frame) @@ -201,7 +243,6 @@ def main(argv=None) -> int: bpy.context.scene.render.fps = FPS clear_animation(arm) - apply_base_pose(arm) idle = clip_idle(arm, CLIPS["Idle"]) walk = clip_walk(arm, CLIPS["Walk"]) diff --git a/Tools/ue_character_anim_import.py b/Tools/ue_character_anim_import.py index f30bf91..d33fbcd 100644 --- a/Tools/ue_character_anim_import.py +++ b/Tools/ue_character_anim_import.py @@ -19,7 +19,7 @@ import unreal SRC = "/tmp/gigline/character-anim.fbx" DEST = "/Game/Test/Character" -PREFIX = "Character_Anim" +PREFIX = "CharacterV2" RESULT = "/tmp/gigline/character-anim-import.txt" lines = []