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