The pod's secondary/radar cockpit surface now renders as an inset in the 800x600 dev window under BT_DEV_GAUGES: radar/tactical grid, SPEED/HEADING/ MAGNETIC/PROP dials, and the color-coded ARMOR DAMAGE mech schematic -- real gauge content (nzSec=27247), composited from the shared CPU pixelBuffer. Composite pass (engine): SVGA16::DrawDevInset palette-expands the secondary plane into a MANAGED texture on the MAIN device and draws an XYZRHW inset quad; BTDrawGaugeInset() reaches the gauge renderer's 'sec' port and is called from DPLRenderer::ExecuteImplementation as the last draw before EndScene. Three reconstruction bugs fixed to get real content: 1. BTL4Application::MakeGaugeRenderer signature mismatch (REAL fix): the reconstructed no-arg override only HID the 2007-engine's widened 3-arg virtual MakeGaugeRenderer(int*,int*,int*), so the engine built a base L4GaugeRenderer whose ctor never parsed gauge/l4gauge.cfg -> empty symbol table -> "undefined label 'bhk1Init'" -> no ports/gauges. Matched the 3-arg signature so it truly overrides (args ignored; BT is fullscreen). Same bug class as the BTL4GaugeRenderer(false,NULL,NULL,NULL) ctor fix. 2. Parse hung on undefined primitives (gated dev accommodation): the BT gauge primitive table (BTL4MethodDescription) is still a stub, so an unknown primitive -> ReportParsingError -> Fail() -> a MODAL dialog freezing the parse. Under BT_DEV_GAUGES, skip the unknown primitive's params so labels register and the base "configure" primitive builds the ports. 3. Gauge widgets AV on NULL data bindings (gated): NumericDisplayScalar's NULL value_pointer -> GaugeConnectionDirectOf ctor deref (bind NULL->static zero); RankAndScore::Execute derefs unreconstructed game state (Gauge::GuardedExecute SEH wrapper -> Disable(True) on first fault). All guards gated on BT_DEV_GAUGES: default DEV un-regressed (TARGET DESTROYED, 0 crashes) and the pod path is byte-unchanged (strict Fail, no guards). Remaining (docs/GAUGE_COMPOSITE.md): the real gauge WIDGET reconstruction (BTL4MethodDescription method table + gauge->game-state data bindings), then Step 2 (RP<->BT MFD port-name reconcile) + Step 3 (2-window layout). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
818 lines
17 KiB
C++
818 lines
17 KiB
C++
#include "munga.h"
|
|
#pragma hdrstop
|
|
|
|
#include "gauge.h"
|
|
#include "gaugrend.h"
|
|
|
|
extern void
|
|
indent(int level); // in graph2d.cc
|
|
|
|
//#########################################################################
|
|
//############################# GaugeBase #################################
|
|
//#########################################################################
|
|
GaugeBase::GaugeBase(
|
|
ModeMask mode_mask,
|
|
GaugeRenderer *new_renderer,
|
|
unsigned int owner_ID,
|
|
const char *identification_string
|
|
) :
|
|
Node(Gauge::GaugeClassID),
|
|
alreadyActivatedFlag(False)
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
modeMask = mode_mask;
|
|
ownerID = owner_ID;
|
|
renderer = new_renderer;
|
|
identificationString = identification_string;
|
|
|
|
stayInactive = True; // used by GaugeRenderer during activation
|
|
//---------------------------------------------------
|
|
// If renderer exists, add to object list
|
|
// (Not having a renderer allows for independent testing)
|
|
//---------------------------------------------------
|
|
if (renderer != NULL)
|
|
{
|
|
Check(renderer);
|
|
renderer->Add(this);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
GaugeBase::~GaugeBase()
|
|
{
|
|
Check(this);
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
GaugeBase::TestInstance() const
|
|
{
|
|
return True;
|
|
}
|
|
|
|
void
|
|
GaugeBase::BecameActive()
|
|
{
|
|
Check(this);
|
|
//------------------------------------------------------
|
|
// Default method immediately inactivates the gaugeBase
|
|
//------------------------------------------------------
|
|
DEBUG_STREAM <<
|
|
"BecameActive() has not been defined for '" << identificationString <<
|
|
"'. About to call Inactivate()\n";
|
|
Inactivate();
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
GaugeBase::BecameInactive()
|
|
{
|
|
Check(this);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
GaugeBase::Inactivate()
|
|
{
|
|
Check(this);
|
|
if (renderer != NULL)
|
|
{
|
|
Check(renderer);
|
|
renderer->Inactivate(this);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
GaugeBase::Update(GaugeRate /*rate_mask*/)
|
|
{
|
|
Check(this);
|
|
//------------------------------------------------------
|
|
// Default method immediately inactivates the gaugeBase
|
|
//------------------------------------------------------
|
|
DEBUG_STREAM <<
|
|
"Update() has not been defined for '" << identificationString <<
|
|
"'. About to call Inactivate()\n";
|
|
Inactivate();
|
|
Check_Fpu();
|
|
return False;
|
|
}
|
|
|
|
void
|
|
GaugeBase::UpdateProfile(Scalar /*frame_percentage*/)
|
|
{
|
|
Check(this);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
GaugeBase::ReportProfile()
|
|
{
|
|
Check(this);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
GaugeBase::LinkToEntity(Entity */*entity*/)
|
|
{
|
|
Check(this);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
GaugeBase::NotifyOfNewInterestingEntity(Entity */*entity*/)
|
|
{
|
|
Check(this);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
GaugeBase::NotifyOfBecomingUninterestingEntity(Entity */*entity*/)
|
|
{
|
|
Check(this);
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
int
|
|
GaugeBase::DiscernTier()
|
|
{
|
|
Check(this);
|
|
Check_Fpu();
|
|
return 0;
|
|
}
|
|
|
|
|
|
//#########################################################################
|
|
//########################## GaugeBackground ##############################
|
|
//#########################################################################
|
|
GaugeBackground::GaugeBackground(
|
|
ModeMask mode_mask,
|
|
GaugeRenderer *new_renderer,
|
|
unsigned int owner_ID,
|
|
const char *identification_string
|
|
) :
|
|
GaugeBase(mode_mask, new_renderer, owner_ID, identification_string)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//#########################################################################
|
|
//######################## GraphicGaugeBackground #########################
|
|
//#########################################################################
|
|
GraphicGaugeBackground::GraphicGaugeBackground(
|
|
ModeMask mode_mask,
|
|
GaugeRenderer *renderer,
|
|
unsigned int owner_ID,
|
|
int graphics_port_number,
|
|
const char *identification_string
|
|
) :
|
|
localView(
|
|
renderer == NULL ?
|
|
NULL :
|
|
renderer->GetGraphicsPort(graphics_port_number)
|
|
),
|
|
GaugeBackground(mode_mask, renderer, owner_ID, identification_string)
|
|
{
|
|
Check_Fpu();
|
|
}
|
|
|
|
//#########################################################################
|
|
//########################## GaugeConnection ##############################
|
|
//#########################################################################
|
|
|
|
GaugeConnection::GaugeConnection(int parameter_id)
|
|
{
|
|
Check_Pointer(this);
|
|
parameterID = parameter_id;
|
|
Check_Fpu();
|
|
}
|
|
|
|
GaugeConnection::~GaugeConnection()
|
|
{
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
GaugeConnection::TestInstance() const
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
return True;
|
|
}
|
|
|
|
void GaugeConnection::Update()
|
|
{
|
|
Fail("GaugeConnection::Update should not be called!\n");
|
|
}
|
|
|
|
void
|
|
GaugeConnection::ShowInstance(char *indent)
|
|
{
|
|
Check(this);
|
|
|
|
std::cout << indent << "GaugeConnection:\n";
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
std::cout << temp << "parameterID=" << parameterID << "\n" << std::flush;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//#########################################################################
|
|
//################################# Gauge #################################
|
|
//#########################################################################
|
|
|
|
//----------------------------------------------------------------------------
|
|
// GaugeRate masks are used to spread out workload in a priority-based
|
|
// manner. Each GaugeRate refers to the branch of a binary tree as shown:
|
|
//
|
|
// A = every frame
|
|
// /--------------^--------------\ :
|
|
// FIRST TIER: B C = 1/2
|
|
// /------^-------\ /------^-------\ :
|
|
// 2ND: D E F G = 1/4
|
|
// /--^---\ /--^---\ /--^---\ /--^---\ :
|
|
// H I J K L M N O = 1/8
|
|
// / \ / \ / \ / \ / \ / \ / \ / \ :
|
|
// P Q R S T U V W X Y Z Z0 Z1 Z2 Z3 Z4 = 1/16
|
|
//
|
|
// Each 'tier' down indicates an update rate half that of the one above it.
|
|
//
|
|
// Note that rates Z0..Z4 cannot be specified through the gauge renderer's
|
|
// interpreter. They are available to automatically generated gauges, though.
|
|
//----------------------------------------------------------------------------
|
|
|
|
GaugeRate
|
|
Gauge::rateTable[31] =
|
|
{
|
|
gaugeRate_A, // every frame
|
|
|
|
gaugeRate_B, // every other frame
|
|
gaugeRate_C,
|
|
|
|
gaugeRate_D, // every 4th frame
|
|
gaugeRate_E,
|
|
gaugeRate_F,
|
|
gaugeRate_G,
|
|
|
|
gaugeRate_H, // every 8th frame
|
|
gaugeRate_I,
|
|
gaugeRate_J,
|
|
gaugeRate_K,
|
|
gaugeRate_L,
|
|
gaugeRate_M,
|
|
gaugeRate_N,
|
|
gaugeRate_O,
|
|
|
|
gaugeRate_P, // every 16th frame
|
|
gaugeRate_Q,
|
|
gaugeRate_R,
|
|
gaugeRate_S,
|
|
gaugeRate_T,
|
|
gaugeRate_U,
|
|
gaugeRate_V,
|
|
gaugeRate_W,
|
|
gaugeRate_X,
|
|
gaugeRate_Y,
|
|
gaugeRate_Z,
|
|
gaugeRate_Z0,
|
|
gaugeRate_Z1,
|
|
gaugeRate_Z2,
|
|
gaugeRate_Z3,
|
|
gaugeRate_Z4
|
|
};
|
|
|
|
//-------------------------------------------------------------------
|
|
// Gauge::NextXXXTierGaugeRate()
|
|
// - These functions attempt to spead out workload by returning the
|
|
// next available 'GaugeRate' in a given 'tier'.
|
|
//
|
|
// The higher level tiers bump the lower level tier indices to
|
|
// attempt to avoid placing too much load on the same higher-order
|
|
// branch of the tree.
|
|
//-------------------------------------------------------------------
|
|
|
|
static int
|
|
first_index = -1,
|
|
second_index = -1,
|
|
third_index = -1,
|
|
fourth_index = -1;
|
|
|
|
GaugeRate
|
|
Gauge::NextFirstTierGaugeRate()
|
|
{
|
|
//----------------------------------------
|
|
// Generate first index
|
|
//----------------------------------------
|
|
first_index = (++first_index) & 1;
|
|
//----------------------------------------
|
|
// Bump other indices to avoid same branch
|
|
//----------------------------------------
|
|
second_index += 2;
|
|
third_index += 4;
|
|
fourth_index += 8;
|
|
//----------------------------------------
|
|
// Return rate mask
|
|
//----------------------------------------
|
|
return rateTable[first_index + 1];
|
|
}
|
|
|
|
GaugeRate
|
|
Gauge::NextSecondTierGaugeRate()
|
|
{
|
|
//----------------------------------------
|
|
// Generate first index
|
|
//----------------------------------------
|
|
second_index = (++second_index) & 3;
|
|
//----------------------------------------
|
|
// Bump other indices to avoid same branch
|
|
//----------------------------------------
|
|
third_index += 2;
|
|
fourth_index += 4;
|
|
//----------------------------------------
|
|
// Return rate mask
|
|
//----------------------------------------
|
|
return rateTable[second_index + 3];
|
|
}
|
|
|
|
GaugeRate
|
|
Gauge::NextThirdTierGaugeRate()
|
|
{
|
|
//----------------------------------------
|
|
// Generate first index
|
|
//----------------------------------------
|
|
third_index = (++third_index) & 7;
|
|
//----------------------------------------
|
|
// Bump other indices to avoid same branch
|
|
//----------------------------------------
|
|
fourth_index += 2;
|
|
//----------------------------------------
|
|
// Return rate mask
|
|
//----------------------------------------
|
|
return rateTable[third_index + 7];
|
|
}
|
|
|
|
GaugeRate
|
|
Gauge::NextFourthTierGaugeRate()
|
|
{
|
|
//----------------------------------------
|
|
// Generate first index
|
|
//----------------------------------------
|
|
fourth_index = (++fourth_index) & 15;
|
|
//----------------------------------------
|
|
// Return rate mask
|
|
//----------------------------------------
|
|
return rateTable[fourth_index + 15];
|
|
}
|
|
|
|
GaugeRate
|
|
Gauge::ConvertIndexToRate(int index)
|
|
{
|
|
Verify(index >= 0);
|
|
Verify(index < 32);
|
|
|
|
return rateTable[index];
|
|
}
|
|
|
|
Gauge::Gauge(
|
|
GaugeRate new_rate,
|
|
ModeMask mode_mask,
|
|
GaugeRenderer *renderer,
|
|
unsigned int owner_ID,
|
|
const char *identification_string
|
|
):
|
|
GaugeBase(mode_mask, renderer, owner_ID, identification_string),
|
|
instanceList(this)
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
rate = new_rate;
|
|
oldRate = new_rate;
|
|
|
|
stayInactive = False;
|
|
|
|
profileFramePercentage = (Scalar) 0;
|
|
profileMaxFramePercentage = (Scalar) 0;
|
|
profileCycles = 0;
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
Gauge::~Gauge()
|
|
{
|
|
Check(this);
|
|
RemoveAllConnections();
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
Gauge::TestInstance() const
|
|
{
|
|
Check(&instanceList);
|
|
# if 0
|
|
//--------------------------------------------------------------------
|
|
// Check all owned GaugeConnections
|
|
//--------------------------------------------------------------------
|
|
ChainIteratorOf<GaugeConnection*>
|
|
i(instanceList);
|
|
|
|
GaugeConnection
|
|
*the_connection;
|
|
|
|
while ((the_connection=i.ReadAndNext()) != NULL)
|
|
{
|
|
Check(the_connection);
|
|
}
|
|
# endif
|
|
//--------------------------------------------------------------------
|
|
// Check the base object
|
|
//--------------------------------------------------------------------
|
|
return GaugeBase::TestInstance();
|
|
}
|
|
|
|
void
|
|
Gauge::ShowInstance(char *indent)
|
|
{
|
|
Check(this);
|
|
|
|
ChainIteratorOf<GaugeConnection*>
|
|
i(instanceList);
|
|
|
|
GaugeConnection
|
|
*the_connection;
|
|
|
|
std::cout << indent << "Gauge:\n";
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
std::cout << temp << "modeMask =" << modeMask << "\n";
|
|
std::cout << temp << "renderer =" << renderer << "\n";
|
|
std::cout << temp << "ownerID =" << ownerID << "\n";
|
|
std::cout << temp << "InstanceList -\n" << std::flush;
|
|
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
while ((the_connection=i.ReadAndNext()) != NULL)
|
|
{
|
|
Check(the_connection);
|
|
the_connection->ShowInstance(temp);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
Gauge::AddConnection(GaugeConnection *connection)
|
|
{
|
|
Check(this);
|
|
Check(connection);
|
|
instanceList.Add(connection);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
Gauge::RemoveConnection(int parameter_ID)
|
|
{
|
|
Check(this);
|
|
|
|
ChainIteratorOf<GaugeConnection*>
|
|
i(instanceList);
|
|
|
|
GaugeConnection
|
|
*gauge_connection;
|
|
|
|
while ((gauge_connection=i.ReadAndNext()) != NULL)
|
|
{
|
|
Check(gauge_connection);
|
|
if (gauge_connection->parameterID == parameter_ID)
|
|
{
|
|
Unregister_Object(gauge_connection);
|
|
delete gauge_connection;
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
Gauge::RemoveAllConnections()
|
|
{
|
|
Check(this);
|
|
|
|
ChainIteratorOf<GaugeConnection*>
|
|
i(instanceList);
|
|
|
|
GaugeConnection
|
|
*gauge_connection;
|
|
|
|
while ((gauge_connection=i.ReadAndNext()) != NULL)
|
|
{
|
|
Check(gauge_connection);
|
|
Unregister_Object(gauge_connection);
|
|
delete gauge_connection;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
Gauge::Disable(Logical disable_state)
|
|
{
|
|
Check(this);
|
|
if (disable_state)
|
|
{
|
|
rate = 0;
|
|
BecameInactive();
|
|
}
|
|
else
|
|
{
|
|
rate = oldRate;
|
|
BecameActive();
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
Gauge::Update(GaugeRate rate_mask)
|
|
{
|
|
Check(this);
|
|
|
|
Logical
|
|
actually_ran = False;
|
|
//-----------------------------------------
|
|
// Update only if rate mask allows it
|
|
//-----------------------------------------
|
|
if (rate & rate_mask)
|
|
{
|
|
//-----------------------------------------
|
|
// Update parameters
|
|
//-----------------------------------------
|
|
ChainIteratorOf<GaugeConnection*>
|
|
i(instanceList);
|
|
|
|
GaugeConnection
|
|
*gauge_connection;
|
|
|
|
while ((gauge_connection=i.ReadAndNext()) != NULL)
|
|
{
|
|
Check(gauge_connection);
|
|
gauge_connection->Update();
|
|
}
|
|
//-----------------------------------------
|
|
// Execute gauge code
|
|
//-----------------------------------------
|
|
{
|
|
// BT DEV-GAUGES bring-up: run Execute() under SEH so a gauge whose
|
|
// game-state binding isn't reconstructed yet is DISABLED (rate=0)
|
|
// after its first fault instead of AV'ing every frame. Gated on
|
|
// BT_DEV_GAUGES; the pod build calls Execute() directly.
|
|
static int s_devGaugesUpd = -1;
|
|
if (s_devGaugesUpd < 0)
|
|
s_devGaugesUpd = (getenv("BT_DEV_GAUGES") != NULL) ? 1 : 0;
|
|
if (s_devGaugesUpd)
|
|
{
|
|
if (!GuardedExecute())
|
|
Disable(True);
|
|
}
|
|
else
|
|
{
|
|
Execute();
|
|
}
|
|
}
|
|
actually_ran = True;
|
|
}
|
|
Check_Fpu();
|
|
return actually_ran;
|
|
}
|
|
|
|
void
|
|
Gauge::Execute()
|
|
{
|
|
Fail("Gauge::Execute not overridden");
|
|
}
|
|
|
|
//
|
|
// GuardedExecute -- BT DEV-GAUGES bring-up. Run Execute() under a structured
|
|
// exception handler so a gauge whose game-state data binding is not yet
|
|
// reconstructed is skipped instead of AV'ing the whole game. (A separate
|
|
// function because __try/__except may not share a frame with C++ objects that
|
|
// require unwinding, which Gauge::Update does.) Returns False on fault.
|
|
//
|
|
Logical
|
|
Gauge::GuardedExecute()
|
|
{
|
|
__try
|
|
{
|
|
Execute();
|
|
return True;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
|
|
struct TierLookup
|
|
{
|
|
GaugeRate rate;
|
|
int tier;
|
|
};
|
|
|
|
int
|
|
Gauge::DiscernTier()
|
|
{
|
|
Check(this);
|
|
|
|
TierLookup
|
|
*tier_pointer;
|
|
static TierLookup
|
|
tier_lookup[] =
|
|
{
|
|
{gaugeRate_A, 0 },
|
|
|
|
{gaugeRate_B, 1 },
|
|
{gaugeRate_C, 1 },
|
|
|
|
{gaugeRate_D, 2 },
|
|
{gaugeRate_E, 2 },
|
|
{gaugeRate_F, 2 },
|
|
{gaugeRate_G, 2 },
|
|
|
|
{gaugeRate_H, 3 },
|
|
{gaugeRate_I, 3 },
|
|
{gaugeRate_J, 3 },
|
|
{gaugeRate_K, 3 },
|
|
{gaugeRate_L, 3 },
|
|
{gaugeRate_M, 3 },
|
|
{gaugeRate_N, 3 },
|
|
{gaugeRate_O, 3 },
|
|
|
|
{gaugeRate_P, 4 },
|
|
{gaugeRate_Q, 4 },
|
|
{gaugeRate_R, 4 },
|
|
{gaugeRate_S, 4 },
|
|
{gaugeRate_T, 4 },
|
|
{gaugeRate_U, 4 },
|
|
{gaugeRate_V, 4 },
|
|
{gaugeRate_W, 4 },
|
|
{gaugeRate_X, 4 },
|
|
{gaugeRate_Y, 4 },
|
|
{gaugeRate_Z, 4 },
|
|
{gaugeRate_Z0,4 },
|
|
{gaugeRate_Z1,4 },
|
|
{gaugeRate_Z2,4 },
|
|
{gaugeRate_Z3,4 },
|
|
{gaugeRate_Z4,4 },
|
|
{0,0}
|
|
};
|
|
|
|
for (tier_pointer=tier_lookup; tier_pointer->rate != 0; ++tier_pointer)
|
|
{
|
|
if (tier_pointer->rate == rate)
|
|
{
|
|
Check_Fpu();
|
|
return tier_pointer->tier;
|
|
}
|
|
}
|
|
|
|
Check_Fpu();
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
Gauge::UpdateProfile(Scalar frame_percentage)
|
|
{
|
|
Check(this);
|
|
|
|
//---------------------------------------------
|
|
// Keep worst case
|
|
//---------------------------------------------
|
|
if (profileMaxFramePercentage < frame_percentage)
|
|
{
|
|
profileMaxFramePercentage = frame_percentage;
|
|
}
|
|
//---------------------------------------------
|
|
// Keep running total
|
|
//---------------------------------------------
|
|
profileFramePercentage += frame_percentage;
|
|
//---------------------------------------------
|
|
// Prevent overflow
|
|
//---------------------------------------------
|
|
if (++profileCycles > 16384)
|
|
{
|
|
profileFramePercentage /= (Scalar) 2;
|
|
profileCycles >>= 1;
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
Gauge::ReportProfile()
|
|
{
|
|
Check(this);
|
|
|
|
int
|
|
i;
|
|
|
|
DEBUG_STREAM << identificationString << std::flush;
|
|
for(i=strlen(identificationString); i<32; ++i)
|
|
{
|
|
DEBUG_STREAM << "." << std::flush;
|
|
}
|
|
|
|
if (profileCycles > 0)
|
|
{
|
|
Scalar
|
|
average = profileFramePercentage / (Scalar)profileCycles;
|
|
|
|
char
|
|
buffer[80];
|
|
|
|
sprintf(buffer, "%6d %6.4f %6.4f\n",
|
|
profileCycles,
|
|
average,
|
|
profileMaxFramePercentage
|
|
);
|
|
DEBUG_STREAM << buffer << std::flush;
|
|
}
|
|
else
|
|
{
|
|
DEBUG_STREAM << "never ran.\n" << std::flush;
|
|
}
|
|
|
|
//----------------------------------------
|
|
// Reset maximum percentage
|
|
//----------------------------------------
|
|
profileMaxFramePercentage = (Scalar) 0;
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//#########################################################################
|
|
//############################# GraphicGauge #############################
|
|
//#########################################################################
|
|
|
|
GraphicGauge::GraphicGauge(
|
|
GaugeRate new_rate,
|
|
ModeMask mode_mask,
|
|
GaugeRenderer *renderer,
|
|
unsigned int owner_ID,
|
|
int graphics_port_number,
|
|
const char *identification_string
|
|
) :
|
|
Gauge(new_rate, mode_mask, renderer, owner_ID, identification_string),
|
|
localView(
|
|
renderer == NULL ?
|
|
NULL :
|
|
renderer->GetGraphicsPort(graphics_port_number)
|
|
)
|
|
{
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
GraphicGauge::~GraphicGauge()
|
|
{
|
|
Check(this);
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
GraphicGauge::TestInstance() const
|
|
{
|
|
Check(&localView);
|
|
Check_Fpu();
|
|
return Gauge::TestInstance();
|
|
}
|
|
|
|
void
|
|
GraphicGauge::ShowInstance(char *indent)
|
|
{
|
|
Check(this);
|
|
|
|
std::cout << indent << "GraphicGauge:\n";
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
localView.ShowInstance(temp);
|
|
Gauge::ShowInstance(temp);
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
#if defined(TEST_CLASS)
|
|
# include "gauge.tcp"
|
|
#endif
|