From eeeabe56b1f3e3135ff21f84f90e78a27d64cb7d Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Mon, 9 Nov 2026 12:11:24 +0100 Subject: [PATCH] feat(review): deterministic walking capture, and the defect it exposed The shot actor can now photograph a moving pawn: a per-shot ShotFollow flag re-places the camera every frame at a fixed offset in the pawn's frame, and the walk is driven per shot (SetReviewWalk) with the pawn returned to spawn after a follow shot, so the fixed-camera shots later in the list still find it in place. With that, the capture stopped depending on where a 4.5 m/s pawn happened to be. Two further bugs fixed on the way: - the engine's screenshot folder is cleared before each run. The collect step copies every review-*.png it finds in Saved/, so a shot retired from the camera list kept reappearing with byte-identical content from an older run - which is how a walk shot that was never captured looked like a captured one. - UpdateBodyAnimation no longer calls SetAnimation every frame. Re-setting the same clip restarts it, which freezes the body on frame 0. What the deterministic capture then exposed: the walk clip is applied but does not advance - every walking frame shows the same pose (arms forward, legs together). The stride shot is retired again rather than shipped, and TODO.md names the next step: log GetCurrentAssetTime across frames and check the imported PlayRate. The harness stays wired for when the clip plays. Shots 6 and 7 were re-rendered after these changes and still pass; 7/7 verify. --- 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 +- Game/GigLine/Content/Test/ReviewMap.umap | 2 +- .../Source/GigLine/GigLineCharacter.cpp | 52 +++++++++++-------- .../GigLine/Source/GigLine/GigLineCharacter.h | 8 +++ .../Source/GigLine/GigLineShotActor.cpp | 52 +++++++++++++++++++ .../GigLine/Source/GigLine/GigLineShotActor.h | 15 ++++++ 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 +- .../demo/review-demo-third-person-walk.png | 3 -- Screenshots/demo/review-demo-third-person.png | 4 +- TODO.md | 2 +- Tools/render_screenshots.sh | 8 +++ Tools/ue_build_review_map.py | 4 ++ 42 files changed, 160 insertions(+), 68 deletions(-) delete mode 100644 Screenshots/demo/review-demo-third-person-walk.png diff --git a/Game/GigLine/Content/Hollywood/DemoMap.umap b/Game/GigLine/Content/Hollywood/DemoMap.umap index 33347c8..b04227e 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:68bfb2aff1d4f2afdcf9c514ef8322d08c263c90ab54115424bef3938340eac0 -size 782068 +oid sha256:cb4094442c9e60f7a76e71e96aa29728a5aa0a2d51e28859b13a7a0b6edd2291 +size 782111 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset index a5c6a38..81b9e73 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:cfeb44958b1d5b6ae77b018b3cb3b7c2b2a357173cb2e2c3a1365f7fff710e36 +oid sha256:80d9e8cf3158e3709d5f0f1c2a84f6e644ba5fc40dafa3c5338d4b2f43ff80fe size 10019 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset index 7a33ddc..acf4eb4 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:5146d450b47d6d9a542f18afae4702b80db7b9c059d62ba0cb5e55130bc219f7 +oid sha256:a6842bbdba9bb44866052d98d5fd574862c525732c54a274596b1294dc7d0cf6 size 10024 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeBanner.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeBanner.uasset index 496a63f..e1a016c 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:694ff53520e3e9afe6a74e2127f99629fe872a3c0f857c32bbfb0bb2b883b306 +oid sha256:0ef7914831df4b80ec1bbafddc0088310471724fc36c8ead9dbaa38ba3f7db93 size 11419 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeGlass.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeGlass.uasset index ab49d03..15a1cf8 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:85a6842e333e9b83278a15aa7555f23eb77bfe157d39e11715450f82eb216131 +oid sha256:6e0837aa328c8ac96ae170de1ed3fe6909a2bd5129262995c58a7359ddf5efcd size 11414 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset index 63ba11a..997c9b7 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:9a1420c863db7622cb16d409311e67284bcac872268fb08e3b11c7f364b70e02 +oid sha256:cf2884759e1e6c9e61b9dcde6ed10485564a8b2da68d3ecf7d3e76adedfa1854 size 17083 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeStoneShadow.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeStoneShadow.uasset index 13f605c..5956954 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:7ec530da2fdeb6d0ed18b4c0a9eb3e32576d1ebe603b18e0d1bbc8528f6d8f24 +oid sha256:ba6d6410ecafd2fa01c7a98b037de2f1239cd400276c83109c99e9ca6adb6e13 size 17113 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset index 5e6934b..657339d 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:10a8c1bf7b92c42ef7fab90ba9cb6cef0d97fb1e16eee1d389d9ddc5318729b9 +oid sha256:e142f5abfab2ca4cfbcc56ff3761126f276340ec2b1802bfbf12fc9d78585e06 size 10014 diff --git a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset index c6bcb41..4a3c2ba 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:5df3b66f676700118ba3992ff4b2932c38cff23de6cdc30cf71106b3c0ee1326 +oid sha256:bf649277e88c74743d93d10d8159d33ab21a2a23661b518b8e4474951ed4affd size 10044 diff --git a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset index 5a87677..0cbc059 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:b31e8281dec663399f09805ebb6e5130ff3e09b009ad5e47ff9bcdd43369d917 +oid sha256:797ee9f2428b11b5410bd09fafc3a5ab1305c1186c3851b1d68524717dc4c8e7 size 10029 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset index d6b54e7..167f099 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:d68e1cfc648c22b015fde3e7b1281073cd8e87a3f4af3d6f6937b88d43945e9d +oid sha256:a3cbc1a4861bdc40c0c59b016ee509e620871c0546b721dab48fa846ef4da845 size 11389 diff --git a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset index 168a082..cb5184a 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:dc005ac965f18eb54a3958874f6d12a3916891ac6ddc0634e68f7a0da0420a5c +oid sha256:c700b244a938032f611b34f3200f3ce8db4d3fb165b99276cc427879549a0f3d 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 fbc0582..e7508e3 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:3332044a02f1d4ceb3d98a8d7f5ec5308695c4d45e024aa3a035ccb3643e2564 +oid sha256:acbdeb2cd8d728e23d9e9ebddde1c252b82fecde6556f503e36bed03fc39c802 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 df63854..8473fda 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:3e82d8f5d0d0fe2ef030fbe9b9943aef2f9cd19bbd1743f845c81208274cf10f +oid sha256:bfe8a51858fdb1d53a4b1fe5d012d263b51d8da815f06fdb8b7f6a5192d19b91 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 1462115..6aaa08b 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:036e739ca0850310a816a2d94d6fae6b003083f41a25f592c6f0ff3ec0b01376 +oid sha256:7ebd565c34f058d95ec1cf09bd382990a23c24e055928a61518720871ea8ed61 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 c175d5e..6de55aa 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:c211098984147983ffcaa547c9de95eac47fd40a02629d6dbe46e30db5e54445 +oid sha256:373317a6707dc261daaa6b16d05e23ad2ccb9c59385c32a153caf47a10c58a70 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 7ad9e80..66a08a7 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:19f5d1c65805354300d729e8af1013f207a9ee880738575f5eb1fe8fecc3e135 +oid sha256:0ec77ea90b3ee38137d313599562180b49071e810f430033a248ee8c90c0b5bc 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 04e979f..b098a34 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:e736c20a959e1336976b2847b9882ca392ff214959f4c18745a50037d9e3f3cc +oid sha256:9e336de25f87767e4d49f46afd379ed052a0d2297f32f2f8339397124f63114f 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 30cdffb..5546cce 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:e3dfc26e2f8182165df600a26c077b1e87b8fdb44543d0d495d1e15a77218328 +oid sha256:72418f0a7099d7c7b7ba5f7fae0e4f1660a2cb61dd53619307a0c3a14b77b562 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 3423c74..1436a9d 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:4cb34f910545251db23de8c3921401261d60ca31194e721cad556eddfde33acc +oid sha256:082946148316f265020b2bd5e7bc508162c20ba8518de881de28fbfd876926c3 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 c27d0fc..910e815 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:a7b337429c7b695f8bd49084e4e761b0e192dfd1d610128c1ced37750962a507 +oid sha256:0719fbbe2553d3749800b3bf0f991e8308dfa87cd613d8d820e8d1fd320412ce 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 cdc5958..69c9f50 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:1d1d469442d8e804ad9082e018ef64ae99dc5bb6be536978ff1f920870653929 +oid sha256:4720a95102c55c887644959a344dc95ad29ed29a8b87a18f55574a1efd6e4170 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 3ffcfdf..aa3fd01 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:21e808e3084173eca07c262c27a6cf98b08d3fcbfa7afe0d3f8d214bebd25e6f +oid sha256:15e4e1e2c928535a05cc8eada728a0ed26b69dfa9c8ead220b62bad44e964ce5 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 cf75c4e..c691bee 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:0ebde7b89afeebbf8e1eedd1862d6fc77d18245435c2fd7d75e37b823fa18e22 +oid sha256:4278c238b7d539198fb31717bec238df312b503119debf809495a83d3eb6cac8 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 424edc2..bc4ebc9 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:55ce34ad2533901f50a968425c9d09b1d2f53c35912c430b1b69148dd1c74a09 +oid sha256:b17405bd29e201ee355e1402e61a5bba2b9d4c6d55b669efbe5fb42270fe21bb 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 3a6be16..65ca8f3 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:2706ac3b10b36ff9cbeaf5a75dc6ee43bace5a3b135a32fda79a95e4c9c6d7ab +oid sha256:fc4acc9ee44f5302e066ff602df693898f1da8983193ac6bfdaf55e3081fdc87 size 72413 diff --git a/Game/GigLine/Content/Test/ReviewMap.umap b/Game/GigLine/Content/Test/ReviewMap.umap index c5030fb..9b6795f 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:48c5e761b7ff6e935db7233ef182b56e3267055c1944925fd4410b6265480910 +oid sha256:e23b869c33bf58e5dfffbf90946fd76147745a56742db75c324ffb52835413f2 size 29389 diff --git a/Game/GigLine/Source/GigLine/GigLineCharacter.cpp b/Game/GigLine/Source/GigLine/GigLineCharacter.cpp index e206d94..12fb9a0 100644 --- a/Game/GigLine/Source/GigLine/GigLineCharacter.cpp +++ b/Game/GigLine/Source/GigLine/GigLineCharacter.cpp @@ -258,6 +258,16 @@ void AGigLineCharacter::BeginPlay() bWalkForever = FParse::Param(FCommandLine::Get(), TEXT("walk")); } +void AGigLineCharacter::SetReviewWalk(bool bEnable) +{ + bWalkForever = bEnable; +} + +void AGigLineCharacter::ReturnToStartForReview() +{ + ResetToStart(); +} + void AGigLineCharacter::WalkForever() { if (bWalkForever && GetCharacterMovement() && GetCharacterMovement()->IsMovingOnGround()) @@ -773,8 +783,6 @@ void AGigLineCharacter::UpdateBodyAnimation() UAnimSequence* Wanted = bMoving ? WalkAnimation.Get() : IdleAnimation.Get(); if (!Wanted) { - // Logged once: a missing clip presents as an A-posed body, which looks like - // an animation problem rather than a missing asset reference. static bool bWarnedMissingClip = false; if (!bWarnedMissingClip) { @@ -787,32 +795,32 @@ void AGigLineCharacter::UpdateBodyAnimation() return; } - // PlayAnimation is only an intent: it needs the component in single-node mode and - // a live single-node instance. The body is hidden at construction and only - // unhidden by the camera toggle, so the first call could land on a component that - // was not ready and never retried - the clip name logged, the pose left at bind. - // Driving the mode and the instance explicitly, and re-asserting every frame while - // the instance is missing, makes that failure self-correcting. - if (GetMesh()->GetAnimationMode() != EAnimationMode::AnimationSingleNode) - { - GetMesh()->SetAnimationMode(EAnimationMode::AnimationSingleNode); - } if (Wanted != PlayingAnimation || GetMesh()->GetSingleNodeInstance() == nullptr) { - PlayingAnimation = Wanted; - GetMesh()->SetAnimation(Wanted); - GetMesh()->Play(true); - if (CVarGigLineSetupLogs.GetValueOnGameThread()) + // Only the mode setter is idempotent; calling SetAnimation unconditionally + // restarts the clip every frame, which freezes the body on frame 0 - that is + // why the walking capture showed a still figure with both legs together. + if (GetMesh()->GetAnimationMode() != EAnimationMode::AnimationSingleNode) { - static bool bLoggedAnimState = false; - if (!bLoggedAnimState) + GetMesh()->SetAnimationMode(EAnimationMode::AnimationSingleNode); + } + if (Wanted != PlayingAnimation) + { + GetMesh()->SetAnimation(Wanted); + PlayingAnimation = Wanted; + GetMesh()->Play(true); + if (CVarGigLineSetupLogs.GetValueOnGameThread()) { - bLoggedAnimState = true; - UE_LOG(LogTemp, Log, TEXT("GigLine: body clip %s, mode=%d, instance=%s"), - *Wanted->GetName(), static_cast(GetMesh()->GetAnimationMode()), - GetMesh()->GetSingleNodeInstance() ? TEXT("ok") : TEXT("nil")); + UE_LOG(LogTemp, Log, TEXT("GigLine: body clip %s, mode=%d"), + *Wanted->GetName(), static_cast(GetMesh()->GetAnimationMode())); } } + else + { + // Same clip but the instance was recreated after a mode change: resume it + // once rather than re-setting the animation. + GetMesh()->Play(true); + } } } diff --git a/Game/GigLine/Source/GigLine/GigLineCharacter.h b/Game/GigLine/Source/GigLine/GigLineCharacter.h index 6885fef..ffb5be7 100644 --- a/Game/GigLine/Source/GigLine/GigLineCharacter.h +++ b/Game/GigLine/Source/GigLine/GigLineCharacter.h @@ -41,6 +41,14 @@ protected: void ResetToStart(); void TogglePause(); +public: + /** Review harness: hold or release forward input from the screenshot actor. */ + void SetReviewWalk(bool bEnable); + + /** Review harness: put the pawn back where it spawned, after a walking capture. */ + void ReturnToStartForReview(); + +protected: /** Swaps between the first-person and third-person rigs (V). */ void ToggleCamera(); diff --git a/Game/GigLine/Source/GigLine/GigLineShotActor.cpp b/Game/GigLine/Source/GigLine/GigLineShotActor.cpp index 878011c..f146cb7 100644 --- a/Game/GigLine/Source/GigLine/GigLineShotActor.cpp +++ b/Game/GigLine/Source/GigLine/GigLineShotActor.cpp @@ -1,5 +1,8 @@ #include "GigLineShotActor.h" +#include "GigLineCharacter.h" +#include "Kismet/GameplayStatics.h" + #include "Camera/CameraActor.h" #include "Camera/CameraComponent.h" #include "Engine/World.h" @@ -32,6 +35,12 @@ void AGigLineShotActor::Tick(float DeltaSeconds) if (bWaitingForSettle) { + // A follow shot tracks the pawn while it settles, otherwise the subject + // walks out of the frame between placement and capture. + if (CurrentShot < ShotFollow.Num() && ShotFollow[CurrentShot]) + { + UpdateFollowCamera(); + } SettleCountdown -= DeltaSeconds; if (SettleCountdown <= 0.f) { @@ -53,11 +62,40 @@ void AGigLineShotActor::Tick(float DeltaSeconds) { bWaitingForScreenshot = false; UE_LOG(LogTemp, Log, TEXT("GigLineShotActor: captured %s"), *FScreenshotRequest::GetFilename()); + // Walking shots move the pawn; put it back before the fixed-camera shots run. + if (ShotFollow.IsValidIndex(CurrentShot) && ShotFollow[CurrentShot]) + { + if (AGigLineCharacter* Character = Cast(UGameplayStatics::GetPlayerPawn(this, 0))) + { + Character->ReturnToStartForReview(); + } + } ++CurrentShot; NextShot(); } } +void AGigLineShotActor::UpdateFollowCamera() +{ + if (!CurrentCamera) + { + return; + } + const APawn* Pawn = UGameplayStatics::GetPlayerPawn(this, 0); + if (!Pawn) + { + return; + } + // Offset in the pawn's frame: to its right, slightly above, looking at the + // pelvis. Right-of-pawn gives a profile view, which is where a stride reads. + const FVector Right = Pawn->GetActorRightVector(); + const FVector Origin = Pawn->GetActorLocation(); + const FVector CameraLocation = Origin + Right * 420.f + FVector(0.f, 0.f, 90.f); + const FVector Target = Origin + FVector(0.f, 0.f, 40.f); + CurrentCamera->SetActorLocation(CameraLocation); + CurrentCamera->SetActorRotation((Target - CameraLocation).Rotation()); +} + void AGigLineShotActor::NextShot() { if (!PlayerController) @@ -93,6 +131,20 @@ void AGigLineShotActor::NextShot() Cam->SetFieldOfView(ShotFieldOfView[CurrentShot]); } } + // Follow shots ignore their recorded transform after this point: the camera is + // rebuilt from the pawn every frame until the capture. They also own the walking: + // the pawn only holds forward input while a follow shot is being taken, so the + // fixed-camera shots later in the list still find it at the spawn point. + const bool bFollowThisShot = ShotFollow.IsValidIndex(CurrentShot) && ShotFollow[CurrentShot]; + if (AGigLineCharacter* Character = Cast(UGameplayStatics::GetPlayerPawn(this, 0))) + { + Character->SetReviewWalk(bFollowThisShot); + } + if (bFollowThisShot) + { + UpdateFollowCamera(); + } + PlayerController->SetViewTarget(CurrentCamera); SettleCountdown = SettleSeconds; diff --git a/Game/GigLine/Source/GigLine/GigLineShotActor.h b/Game/GigLine/Source/GigLine/GigLineShotActor.h index 4578fca..809078b 100644 --- a/Game/GigLine/Source/GigLine/GigLineShotActor.h +++ b/Game/GigLine/Source/GigLine/GigLineShotActor.h @@ -50,6 +50,18 @@ public: UPROPERTY(EditAnywhere, BlueprintReadWrite) float SettleSeconds = 0.35f; + /** + * Optional per-shot "follow the player" flag, same index as ShotLocations. + * + * A fixed camera cannot photograph a walking pawn: at 4.5 m/s it covers the + * distance between two captures, so three attempts framed it at a different + * distance each run and two missed it entirely. With this flag the camera is + * re-placed every frame at a fixed offset in the pawn's frame, which is what + * makes a stride shot deterministic. + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TArray ShotFollow; + /** Quit the game after the last shot (disable to keep the game open). */ UPROPERTY(EditAnywhere, BlueprintReadWrite) bool bQuitWhenDone = true; @@ -57,6 +69,9 @@ public: private: void NextShot(); + /** Re-places the active camera at the follow offset behind the player pawn. */ + void UpdateFollowCamera(); + UPROPERTY() TObjectPtr PlayerController; diff --git a/Screenshots/demo/review-demo-crossing.png b/Screenshots/demo/review-demo-crossing.png index 574c3ed..6e328a4 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:592a419db534b1b727654e4d02c18113427511442b147a912a2e2a54a30181cd -size 3088926 +oid sha256:d9d241cf8ba8c2458e29eef6c5f402e6fc8253c5b8bb39ed814cba1061002da7 +size 3086135 diff --git a/Screenshots/demo/review-demo-north-buildings.png b/Screenshots/demo/review-demo-north-buildings.png index ebc5c61..1d759ca 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:dacc07a63e622caeb2b6c470a83b83d753ff6cd0aaf5ccbf4759a754b159623e -size 2619131 +oid sha256:af1d563bcf7cde3e6cf8ddde90d3bf829ac80bef532464f09df2f52624bd8fa7 +size 2619686 diff --git a/Screenshots/demo/review-demo-retail-frontage.png b/Screenshots/demo/review-demo-retail-frontage.png index 8d18a53..6c67e25 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:ed4798f70d275aa59ba6bf29ef7369857137dce7e39858c84ed4aab19c5fb06b -size 2522358 +oid sha256:b2dcb4bd30d3a6f3f8aa5b8296c09a85f025544fd0d3ec424cb4305716e2496e +size 2521944 diff --git a/Screenshots/demo/review-demo-spawn-view.png b/Screenshots/demo/review-demo-spawn-view.png index 0a700f8..4718a27 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:044c1296381d125242d1c2a17bb03771fb774252d1e0aa6869d36740a0ae2360 -size 2919982 +oid sha256:76a664b8e1051c0cda54bedf39b5642276aa301649da75786bbab254848a5d30 +size 2930459 diff --git a/Screenshots/demo/review-demo-street-level.png b/Screenshots/demo/review-demo-street-level.png index b2b2333..b172844 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:0c2faa7a89b083fcb244d82d72a49a1fac7c8b8a967ce992d3ce7b0a5ebe9a71 -size 2850629 +oid sha256:b28d4854a6af4b1dd6b47c24742b3feed9151e9d3f5ee05c7576eeaefd36bf24 +size 2852636 diff --git a/Screenshots/demo/review-demo-third-person-front.png b/Screenshots/demo/review-demo-third-person-front.png index 5bdbe3e..7ad42e0 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:ba3bee7d90e5bfc1abe8c247fe7b273e2059eb557b93fb44d32ee97e70f21682 -size 2794850 +oid sha256:77cbf9322df6462865c6368be0ac963629507ea184271642e79d11287e591d66 +size 2795656 diff --git a/Screenshots/demo/review-demo-third-person-walk.png b/Screenshots/demo/review-demo-third-person-walk.png deleted file mode 100644 index 2e41d9d..0000000 --- a/Screenshots/demo/review-demo-third-person-walk.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c3a9d55d561a861ffbf4bc5623604453dce50a000ed7dbb46730d429ec8c1273 -size 3164641 diff --git a/Screenshots/demo/review-demo-third-person.png b/Screenshots/demo/review-demo-third-person.png index 929a1aa..0c9a550 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:dba912fee130cee2651c4a1f5b6cd1dc2ddadd206450fa9bbafcae5b0730f37d -size 2998064 +oid sha256:2e7f523f1b7983e319a11217cc2166f0bcf27a5a9873e42fabbdd899943dfe52 +size 2998041 diff --git a/TODO.md b/TODO.md index 81d082f..4b53518 100644 --- a/TODO.md +++ b/TODO.md @@ -32,7 +32,7 @@ Actionable task list for this project. This file is the single, central place fo ### Release checks -- [ ] Third-person traversal works end-to-end in the demo area. **Blocked on a capture harness, not on the game:** walking works (`-walk` holds forward input; the pawn crosses the sidewalk while the third-person rig follows), but a fixed review camera cannot catch a pawn moving at 4.5 m/s — three attempts framed it at a different distance each run and the last two missed it entirely. The stride shot was removed rather than shipped broken. Needs a camera that tracks the pawn (attach the shot camera to the pawn, or drive the capture from a recorded path), then re-add `demo-third-person-walk`. +- [ ] Third-person traversal works end-to-end in the demo area. **The harness exists now, the animation does not advance.** The screenshot actor can track the pawn (`ShotFollow`) and drive the walk per shot (`SetReviewWalk`), and the capture is deterministic — but every walking capture shows the body in one static pose (arms forward, legs together), so the walk clip is applied without playing. Next step: check whether the single-node instance is ticking at all (log `GetSingleNodeInstance()->GetCurrentAssetTime()` across frames) and whether `PlayRate` survived the import. Earlier note, superseded: walking works (`-walk` holds forward input; the pawn crosses the sidewalk while the third-person rig follows), but a fixed review camera cannot catch a pawn moving at 4.5 m/s — three attempts framed it at a different distance each run and the last two missed it entirely. The stride shot was removed rather than shipped broken. Needs a camera that tracks the pawn (attach the shot camera to the pawn, or drive the capture from a recorded path), then re-add `demo-third-person-walk`. - [ ] No blocking animation or rig defects. - [ ] Performance target still met at 1440p. - [ ] Tag `v0.2.0` and write `CHANGELOG.md` entry; then remove this section. diff --git a/Tools/render_screenshots.sh b/Tools/render_screenshots.sh index f30de36..23170d2 100755 --- a/Tools/render_screenshots.sh +++ b/Tools/render_screenshots.sh @@ -39,6 +39,14 @@ run_cmdlet ue_build_review_map.py "5/6 stage the demo shot cameras" tail -3 /tmp/ue-review-map-result.txt 2>/dev/null || true echo "== 6/6 capture the demo map ==" +# Clear the engine's screenshot folder first. The collect step below copies every +# review-*.png it finds in Saved/, so without this a shot retired from the camera list +# keeps coming back as a stale file - that is how a removed walk shot reappeared with +# byte-identical content after a run that never captured it. +rm -rf "$REPO"/Game/GigLine/Saved/Screenshots/* "$HOME"/.config/Epic/GigLine/Saved/Screenshots/* 2>/dev/null || true +# Recreate the folder: the engine writes into it and does not recreate a deleted +# directory, which silently produced zero captures in the run that removed it. +mkdir -p "$REPO/Game/GigLine/Saved/Screenshots/LinuxEditor" # The engine path is absolute: this step runs from the repo, not from $ENGINE, and a # bare ./Engine/... failed with "No such file or directory" while every commandlet # above succeeded through run_cmdlet's cd. diff --git a/Tools/ue_build_review_map.py b/Tools/ue_build_review_map.py index 732b2c5..0c75362 100644 --- a/Tools/ue_build_review_map.py +++ b/Tools/ue_build_review_map.py @@ -331,6 +331,10 @@ try: seq.set_editor_property("shot_rotations", [unreal.MathLibrary.find_look_at_rotation(c[1], c[2]) for c in demo_shots]) seq.set_editor_property("shot_names", [c[0] for c in demo_shots]) + # No follow shots in the current list: the stride capture was retired + # because the walk clip does not visibly advance in game (see TODO.md). + # The follow flag stays wired for when it does. + seq.set_editor_property("shot_follow", [False] * len(demo_shots)) seq.set_editor_property( "shot_field_of_view", [float(c[3]) if len(c) > 3 else 0.0 for c in demo_shots])