Mech milestone: reconstruct SequenceController (helper 2/3), struct+Init verified
The BT keyframe-animation player embedded in the Mech as legAnimation/ bodyAnimation. Struct field layout (from BT411's binary-offset map), default ctor, dtor, and Init(Mech*) reconstructed and compile-verified; Init is ctor-time (Mech ctor calls legAnimation.Init(this)/bodyAnimation.Init(this)) so it's real (binds owner + caches owner->GetJointSubsystem()). The per-frame gait engine (SelectSequence/Advance/Reset) is staged with Fail bodies -- it fires only once the mech is ticking, past the current ctor frontier. BT stage 23 ok; full tree still links clean. Evidence + real/staged split in SEQCTL.NOTES.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,97 @@
|
|||||||
|
//===========================================================================//
|
||||||
|
// File: seqctl.cpp //
|
||||||
|
// Project: BattleTech Brick: Mech animation //
|
||||||
|
// Contents: The Mech keyframe-animation player (leg / body gait clips) //
|
||||||
|
//---------------------------------------------------------------------------//
|
||||||
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
|
||||||
|
// All Rights reserved worldwide //
|
||||||
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
||||||
|
//===========================================================================//
|
||||||
|
|
||||||
|
#include <bt.hpp>
|
||||||
|
#pragma hdrstop
|
||||||
|
|
||||||
|
#if !defined(SEQCTL_HPP)
|
||||||
|
# include <seqctl.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(MECH_HPP)
|
||||||
|
# include <mech.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
//#############################################################################
|
||||||
|
//#############################################################################
|
||||||
|
//
|
||||||
|
SequenceController::SequenceController()
|
||||||
|
{
|
||||||
|
keyframeCount = 0;
|
||||||
|
jointCount = 0;
|
||||||
|
footStepThreshold = NULL;
|
||||||
|
jointIndices = NULL;
|
||||||
|
keyframeTimes = NULL;
|
||||||
|
keyframeBase = NULL;
|
||||||
|
keyframeCursor = NULL;
|
||||||
|
keyframeData = NULL;
|
||||||
|
currentFrame = 0;
|
||||||
|
currentTime = 0.0f;
|
||||||
|
jointSubsystem = NULL;
|
||||||
|
owner = NULL;
|
||||||
|
clipResource = NULL;
|
||||||
|
finishedCallback = NULL;
|
||||||
|
callbackArg2 = 0;
|
||||||
|
callbackArg3 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//#############################################################################
|
||||||
|
// Init Bind the player to its owning mech and cache the joint subsystem the
|
||||||
|
// gait writes through. Called from the Mech ctor for legAnimation/bodyAnimation.
|
||||||
|
//#############################################################################
|
||||||
|
//
|
||||||
|
void
|
||||||
|
SequenceController::Init(Mech *owner_mech)
|
||||||
|
{
|
||||||
|
Check(owner_mech);
|
||||||
|
owner = owner_mech;
|
||||||
|
jointSubsystem = owner_mech->GetJointSubsystem();
|
||||||
|
clipResource = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//#############################################################################
|
||||||
|
//#############################################################################
|
||||||
|
//
|
||||||
|
SequenceController::~SequenceController()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Releases the locked clip resource when reconstructed; nothing is locked
|
||||||
|
// while SelectSequence is staged.
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//#############################################################################
|
||||||
|
// Playback -- the per-frame gait engine (clip parse, keyframe interpolation,
|
||||||
|
// joint writes). Exercised only once the mech is ticking; not yet
|
||||||
|
// reconstructed. See SEQCTL.NOTES.md.
|
||||||
|
//#############################################################################
|
||||||
|
//
|
||||||
|
void
|
||||||
|
SequenceController::SelectSequence(int, void *, unsigned, unsigned)
|
||||||
|
{
|
||||||
|
Fail("SequenceController::SelectSequence -- seqctl.cpp not yet reconstructed");
|
||||||
|
}
|
||||||
|
|
||||||
|
Scalar
|
||||||
|
SequenceController::Advance(Scalar, int)
|
||||||
|
{
|
||||||
|
Fail("SequenceController::Advance -- seqctl.cpp not yet reconstructed");
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SequenceController::Reset(int)
|
||||||
|
{
|
||||||
|
Fail("SequenceController::Reset -- seqctl.cpp not yet reconstructed");
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
#if !defined(SEQCTL_HPP)
|
||||||
|
# define SEQCTL_HPP
|
||||||
|
|
||||||
|
//##################### Forward Class Declarations #######################
|
||||||
|
class Mech;
|
||||||
|
class JointSubsystem;
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
//###################### SequenceController ##########################
|
||||||
|
//##########################################################################
|
||||||
|
//
|
||||||
|
// The BT keyframe-animation player embedded in the Mech as legAnimation and
|
||||||
|
// bodyAnimation. It plays a gait clip: walks the clip's keyframes,
|
||||||
|
// interpolates each animated joint's rotation, writes it through the joint
|
||||||
|
// subsystem, and returns the root-translation distance advanced this step.
|
||||||
|
//
|
||||||
|
// Reconstructed from the shipped binary (ctor/Init @00427768, SelectSequence
|
||||||
|
// @004277a8, Advance @0042790c, Reset @004283b8). Not in the surviving 4.10
|
||||||
|
// archive nor the RP engine. See SEQCTL.NOTES.md.
|
||||||
|
//
|
||||||
|
class SequenceController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//
|
||||||
|
// One root-translation entry (per keyframe); ".stride" is the forward
|
||||||
|
// (local Z) distance the gait reads.
|
||||||
|
//
|
||||||
|
struct Keyframe
|
||||||
|
{
|
||||||
|
Scalar x, y, stride;
|
||||||
|
};
|
||||||
|
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Construction / Destruction
|
||||||
|
//
|
||||||
|
public:
|
||||||
|
SequenceController();
|
||||||
|
~SequenceController();
|
||||||
|
|
||||||
|
void
|
||||||
|
Init(Mech *owner_mech);
|
||||||
|
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Playback
|
||||||
|
//
|
||||||
|
public:
|
||||||
|
void
|
||||||
|
SelectSequence(
|
||||||
|
int clip_id,
|
||||||
|
void *finished_callback,
|
||||||
|
unsigned callback_arg2,
|
||||||
|
unsigned callback_arg3
|
||||||
|
);
|
||||||
|
Scalar
|
||||||
|
Advance(Scalar time_slice, int move_joints);
|
||||||
|
void
|
||||||
|
Reset(int loop);
|
||||||
|
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Clip data (parsed by SelectSequence; keyframe accessors read by the gait)
|
||||||
|
//
|
||||||
|
public:
|
||||||
|
int keyframeCount;
|
||||||
|
int jointCount;
|
||||||
|
Scalar *footStepThreshold;
|
||||||
|
int *jointIndices;
|
||||||
|
Scalar *keyframeTimes;
|
||||||
|
void *keyframeBase;
|
||||||
|
void *keyframeCursor;
|
||||||
|
Keyframe *keyframeData;
|
||||||
|
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Runtime state / links
|
||||||
|
//
|
||||||
|
public:
|
||||||
|
int currentFrame;
|
||||||
|
Scalar currentTime;
|
||||||
|
JointSubsystem *jointSubsystem;
|
||||||
|
Mech *owner;
|
||||||
|
void *clipResource;
|
||||||
|
void *finishedCallback;
|
||||||
|
unsigned callbackArg2;
|
||||||
|
unsigned callbackArg3;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# SEQCTL.HPP / .CPP — reconstruction notes
|
||||||
|
|
||||||
|
**Status: struct + ctor/dtor + Init RECONSTRUCTED (compile-verified); the
|
||||||
|
per-frame playback methods (SelectSequence / Advance / Reset) staged. Helper
|
||||||
|
2/3 of the Mech embedded helpers ([[MECH-LAYOUT]] step 1).**
|
||||||
|
|
||||||
|
`SequenceController` — the BT keyframe-animation player embedded in the Mech as
|
||||||
|
`legAnimation` (@0x65c) and `bodyAnimation` (@0x6bc). Plays a gait clip: walks
|
||||||
|
keyframes, interpolates each animated joint's rotation, writes it through the
|
||||||
|
joint subsystem, returns the root-translation distance advanced. Absent from the
|
||||||
|
4.10 archive and the RP engine; reconstructed from the shipped binary + BT411's
|
||||||
|
seqctl.cpp decomp.
|
||||||
|
|
||||||
|
## What's real vs staged
|
||||||
|
|
||||||
|
- **Real (ctor-time):** default ctor (zeroes all fields) and `Init(Mech*)` — the
|
||||||
|
Mech ctor calls `legAnimation.Init(this)` / `bodyAnimation.Init(this)`
|
||||||
|
(binary; BT411 mech.cpp:685-686), so Init must run at construction. Init binds
|
||||||
|
`owner` and caches `jointSubsystem = owner->GetJointSubsystem()`
|
||||||
|
(JMOVER.HPP:104, returns `JointSubsystem*`), `clipResource = NULL`.
|
||||||
|
- **Staged (per-frame, after boot):** `SelectSequence` (@004277a8, clip parse +
|
||||||
|
resource lock), `Advance` (@0042790c, keyframe interpolation + joint writes —
|
||||||
|
the gait engine, ~145 lines in the decomp), `Reset` (@004283b8). These fire
|
||||||
|
only once the mech is ticking, well past the current ctor frontier, so they
|
||||||
|
Fail loudly until reconstructed.
|
||||||
|
|
||||||
|
## Field layout
|
||||||
|
|
||||||
|
Field set + order from BT411's binary-offset map (keyframeCount +0x14 …
|
||||||
|
callbackArg3 +0x50). Byte-exact offsets are not required for the functional
|
||||||
|
build (only wire/update-record layout needs that, and SequenceController is not
|
||||||
|
serialised) — the members are declared as named fields and BC4.52 lays them out;
|
||||||
|
the Mech's legAnimation/bodyAnimation slots size to `sizeof(SequenceController)`
|
||||||
|
self-consistently.
|
||||||
|
|
||||||
|
## Placement
|
||||||
|
|
||||||
|
1995 filename unknown (decomp-only; BT411 used seqctl.cpp). Filed as
|
||||||
|
BT/SEQCTL.HPP + SEQCTL.CPP. Not in the authentic BT.MAK member list, so the
|
||||||
|
build appends seqctl.obj to bt.lib via the extra-objs fallback (order is
|
||||||
|
immaterial — no static init).
|
||||||
Reference in New Issue
Block a user