|
3 | 3 | """Sequences on screen: the Moves strip and picker, the Timeline's bar, playing a chain, the Clips |
4 | 4 | sort, over the synthetic port.""" |
5 | 5 |
|
| 6 | +import math |
6 | 7 | from pathlib import Path |
7 | 8 | from typing import Any |
8 | 9 |
|
|
11 | 12 | from mhfu_port import continuity |
12 | 13 | from mhfu_port.manifest import Clip |
13 | 14 | from mhfu_studio.monster.clip_browser import SourceClip |
| 15 | +from mhfu_studio.monster.core.scene import Scene |
14 | 16 | from mhfu_studio.monster.panels.clips import ClipsPanel |
15 | 17 | from mhfu_studio.monster.panels.moves import MovesPanel |
16 | 18 | from mhfu_studio.monster.panels.timeline import TimelinePanel |
| 19 | +from mhfu_studio.monster.render.playback import pose_at |
17 | 20 | from mhfu_studio.monster.workspace import MonsterWorkspace |
18 | 21 | from mhfu_studio.shell.studio import Studio |
19 | 22 | from mhfu_studio.ui import kit |
| 23 | +from mhp_formats.anim import Channel, Keyframe, Track, quantize |
| 24 | +from mhp_formats.anim import Clip as AnimClip |
20 | 25 | from PySide6.QtCore import QPoint, Qt |
21 | 26 | from PySide6.QtTest import QTest |
22 | 27 |
|
@@ -271,6 +276,64 @@ def test_the_timeline_follows_the_sequence(timeline: TimelinePanel, ws: MonsterW |
271 | 276 | assert timeline.steps.picked == "a_2" and timeline.frame.text() == "frame 0.0 / 6" |
272 | 277 |
|
273 | 278 |
|
| 279 | +# ---- the body carried across steps ---- |
| 280 | + |
| 281 | + |
| 282 | +@pytest.fixture |
| 283 | +def walking(ws: MonsterWorkspace, synthetic_pac: bytes) -> MonsterWorkspace: |
| 284 | + """`ws` on a rig whose clips both walk the root 100 units forward by frame 10; a turns 90 |
| 285 | + degrees (fixed steer), a_2 and a_3 do not.""" |
| 286 | + assert ws.doc is not None |
| 287 | + scene = Scene.from_bytes(synthetic_pac, "t", manifest=ws.doc.manifest) |
| 288 | + track = Track([Channel(0x100, [Keyframe(0, 0), Keyframe(quantize("loc", 100.0), 10)])]) |
| 289 | + for c in scene.clips: |
| 290 | + c.source = AnimClip([track, Track(), Track()]) |
| 291 | + ws.load(scene, ws.doc) |
| 292 | + ws.select_move("a") |
| 293 | + assert ws.set_steer(turn="fixed", angle=90.0) |
| 294 | + return ws |
| 295 | + |
| 296 | + |
| 297 | +def test_a_sequence_carries_the_body(walking: MonsterWorkspace) -> None: |
| 298 | + ws = walking |
| 299 | + vp = ws.vp |
| 300 | + assert vp is not None and vp.actor is not None and vp.clip is not None |
| 301 | + first, speed = vp.clip, vp.playback.speed |
| 302 | + ws.play_sequence() |
| 303 | + assert vp.actor.carry is None, "the first step starts where clips start" |
| 304 | + at = pose_at(vp.actor.scene, first, first.frames, steer=vp.actor.steer, speed=speed).joints[0] |
| 305 | + ws.frame(1.0) |
| 306 | + c = vp.actor.carry |
| 307 | + assert ws.move == "a_2" and c is not None and c.yaw == pytest.approx(math.pi / 2) |
| 308 | + start = pose_at(vp.actor.scene, vp.clip, 0.0, carry=c).joints[0] |
| 309 | + assert abs(at[0]) > 90.0 and np.allclose(start, at, atol=1e-6), "from where a ended, turned" |
| 310 | + ws.frame(1.0) |
| 311 | + c2 = vp.actor.carry |
| 312 | + assert ws.move == "a_3" and c2 is not None |
| 313 | + assert c2.yaw == pytest.approx(math.pi / 2), "a_2 does not turn" |
| 314 | + assert c2.shift[0] > c.shift[0] + 50.0, "and walked on from there" |
| 315 | + |
| 316 | + |
| 317 | +def test_anything_else_played_starts_where_clips_start(walking: MonsterWorkspace) -> None: |
| 318 | + ws = walking |
| 319 | + vp = ws.vp |
| 320 | + assert vp is not None and vp.actor is not None |
| 321 | + ws.play_sequence() |
| 322 | + ws.frame(1.0) |
| 323 | + assert vp.actor.carry is not None |
| 324 | + ws.select_move("a_2") # the same step, picked again |
| 325 | + assert vp.actor.carry is None |
| 326 | + ws.play_sequence() |
| 327 | + ws.frame(1.0) |
| 328 | + assert vp.actor.carry is not None |
| 329 | + ws.play_slot(2) |
| 330 | + assert vp.actor.carry is None |
| 331 | + ws.play_sequence() |
| 332 | + ws.frame(1.0) |
| 333 | + ws.play_sequence() |
| 334 | + assert vp.actor.carry is None, "again from the head" |
| 335 | + |
| 336 | + |
274 | 337 | # ---- the Clips table ---- |
275 | 338 |
|
276 | 339 |
|
|
0 commit comments