Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.
Layout:
engine/ MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
models) + image codec; the minimal rp/ headers the audio HAL needs
game/ reconstructed BT logic + surviving-original BT source + fwd shims
+ WinMain launcher
content/ full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
docs/ format specs + reconstruction ledgers
reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
tools/ MP console emulator + map/resource scanners
One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1032 lines
26 KiB
C++
1032 lines
26 KiB
C++
#include "munga.h"
|
|
#pragma hdrstop
|
|
|
|
#include "renderer.h"
|
|
#include "rndorgn.h"
|
|
#include "explode.h"
|
|
#include "app.h"
|
|
#include "objstrm.h"
|
|
#include "hostmgr.h"
|
|
#include "subsystm.h"
|
|
|
|
//#############################################################################
|
|
//############################ Renderer #################################
|
|
//#############################################################################
|
|
|
|
const RendererRate DefaultRendererRate = 30.0f;
|
|
const RendererComplexity MaxRendererComplexity = 3.0f;
|
|
const RendererComplexity MinRendererComplexity = 0.0f;
|
|
const RendererFrameBudget DefaultRendererFrameBudget = 0.14f; //0.12f; // 0.16f;
|
|
|
|
//#############################################################################
|
|
// Message Support
|
|
//
|
|
const Receiver::HandlerEntry
|
|
Renderer::MessageHandlerEntries[]=
|
|
{
|
|
{
|
|
Renderer::NotifyOfNewInterestingEntityMessageID,
|
|
"NotifyOfNewInterestingEntity",
|
|
(Renderer::Handler)&Renderer::NotifyOfNewInterestingEntityMessageHandler
|
|
},
|
|
{
|
|
Renderer::NotifyOfBecomingUninterestingEntityMessageID,
|
|
"NotifyOfBecomingUninterestingEntity",
|
|
(Renderer::Handler)&Renderer::NotifyOfBecomingUninterestingEntityMessageHandler
|
|
},
|
|
{
|
|
Renderer::StartEntityEffectMessageID,
|
|
"StartEntityEffect",
|
|
(Renderer::Handler)&Renderer::StartEntityEffectMessageHandler
|
|
},
|
|
{
|
|
Renderer::StopAllEntityEffectsMessageID,
|
|
"StopAllEntityEffects",
|
|
(Renderer::Handler)&Renderer::StopAllEntityEffectsMessageHandler
|
|
},
|
|
{
|
|
Renderer::StartEntityAlarmMessageID,
|
|
"StartEntityAlarm",
|
|
(Renderer::Handler)&Renderer::StartEntityAlarmMessageHandler
|
|
},
|
|
{
|
|
Renderer::StopEntityAlarmMessageID,
|
|
"StopEntityAlarm",
|
|
(Renderer::Handler)&Renderer::StopEntityAlarmMessageHandler
|
|
}
|
|
};
|
|
|
|
Renderer::MessageHandlerSet& Renderer::GetMessageHandlers()
|
|
{
|
|
static Renderer::MessageHandlerSet messageHandlers(ELEMENTS(Renderer::MessageHandlerEntries), Renderer::MessageHandlerEntries, Receiver::GetMessageHandlers());
|
|
return messageHandlers;
|
|
}
|
|
|
|
//#############################################################################
|
|
// Shared Data Support
|
|
//
|
|
Derivation* Renderer::GetClassDerivations()
|
|
{
|
|
static Derivation classDerivations(Receiver::GetClassDerivations(), "Renderer");
|
|
return &classDerivations;
|
|
}
|
|
|
|
Renderer::SharedData
|
|
Renderer::DefaultData(
|
|
Renderer::GetClassDerivations(),
|
|
Renderer::GetMessageHandlers()
|
|
);
|
|
|
|
//
|
|
//#############################################################################
|
|
// Renderer
|
|
//#############################################################################
|
|
//
|
|
Renderer::Renderer(
|
|
RendererRate calibration_rate,
|
|
RendererComplexity calibration_complexity,
|
|
RendererPriority calibration_priority,
|
|
InterestType interest_type,
|
|
InterestDepth depth_calibration,
|
|
ClassID class_ID,
|
|
SharedData &virtual_data
|
|
):
|
|
Receiver(class_ID, virtual_data),
|
|
rendererOriginSocket(NULL),
|
|
entitySocket(NULL)
|
|
{
|
|
rendererStatus = InactiveRendererStatus;
|
|
|
|
calibrationRate = calibration_rate;
|
|
calibrationFrameDuration = 1.0f / calibration_rate;
|
|
nextRenderTime = 0.0f;
|
|
|
|
Verify(MinRendererComplexity < calibration_complexity);
|
|
Verify(calibration_complexity <= MaxRendererComplexity);
|
|
calibrationComplexity = calibration_complexity;
|
|
|
|
calibrationPriority = calibration_priority;
|
|
interestType = interest_type;
|
|
depthCalibration = depth_calibration;
|
|
framePercentBudget = DefaultRendererFrameBudget;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// ~Renderer
|
|
//#############################################################################
|
|
//
|
|
Renderer::~Renderer()
|
|
{
|
|
UnlinkFromEntity();
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// TestInstance
|
|
//#############################################################################
|
|
//
|
|
Logical
|
|
Renderer::TestInstance() const
|
|
{
|
|
if (!IsDerivedFrom(*GetClassDerivations()))
|
|
{
|
|
return False;
|
|
}
|
|
Check(&rendererOriginSocket);
|
|
Check(&entitySocket);
|
|
return True;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// LinkToEntity
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::LinkToEntity(Entity *entity)
|
|
{
|
|
Check(this);
|
|
Check(entity);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Unlink from current entity and add new entity
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
UnlinkFromEntity();
|
|
entitySocket.Add(entity);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Make an interest origin for the given entity
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
RendererOrigin *rendererOrigin;
|
|
|
|
rendererOrigin =
|
|
new RendererOrigin(
|
|
this,
|
|
entity,
|
|
interestType,
|
|
depthCalibration
|
|
);
|
|
Register_Object(rendererOrigin);
|
|
|
|
Check(application);
|
|
application->GetInterestManager()->AdoptInterestOrigin(rendererOrigin);
|
|
rendererOriginSocket.Add(rendererOrigin);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// UnlinkFromEntity
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::UnlinkFromEntity()
|
|
{
|
|
Check(this);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Delete current interest origin
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
RendererOrigin *rendererOrigin;
|
|
|
|
if ((rendererOrigin = rendererOriginSocket.GetCurrent()) != NULL)
|
|
{
|
|
Check(rendererOrigin);
|
|
|
|
//
|
|
// Remove entity from socket
|
|
//
|
|
entitySocket.Remove();
|
|
|
|
//
|
|
// Delete the interest origin
|
|
//
|
|
Check(application);
|
|
Check(application->GetInterestManager());
|
|
application->GetInterestManager()->OrphanInterestOrigin(rendererOrigin);
|
|
Unregister_Object(rendererOrigin);
|
|
delete rendererOrigin;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// LoadMission
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::LoadMission(Mission *mission)
|
|
{
|
|
Check(this);
|
|
|
|
Verify(rendererStatus == InactiveRendererStatus);
|
|
rendererStatus = LoadingRendererStatus;
|
|
nextRenderTime = Now();
|
|
|
|
Check(application);
|
|
application->GetRendererManager()->StartRenderer(this);
|
|
LoadMissionImplementation(mission);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// Shutdown
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::Shutdown()
|
|
{
|
|
Check(this);
|
|
|
|
//
|
|
//-------------------------------------------------
|
|
// Shutdown and unhook the renderer if it is active
|
|
//-------------------------------------------------
|
|
//
|
|
if (rendererStatus == InactiveRendererStatus)
|
|
{
|
|
return;
|
|
}
|
|
|
|
rendererStatus = InactiveRendererStatus;
|
|
Check(application);
|
|
application->GetRendererManager()->StopRenderer(this);
|
|
|
|
ShutdownImplementation();
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// SetRendererStatusToRunning
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::SetRendererStatusToRunning()
|
|
{
|
|
Verify(rendererStatus == LoadingRendererStatus);
|
|
rendererStatus = RunningRendererStatus;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// UpdateRendererOrigin
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::UpdateInterestOrigin(Time target_render_time)
|
|
{
|
|
Check(this);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// If the renderer is inactive, skip it
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
if (rendererStatus == InactiveRendererStatus)
|
|
return;
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Does the renderer need to run this frame to meet its frame rate?
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
if (nextRenderTime > target_render_time)
|
|
return;
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Update the interest origin
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
Entity *entity;
|
|
RendererOrigin *rendererOrigin;
|
|
|
|
entity = entitySocket.GetCurrent();
|
|
Check(entity);
|
|
rendererOrigin = rendererOriginSocket.GetCurrent();
|
|
Check(rendererOrigin);
|
|
rendererOrigin->Update(entity->GetInterestZoneID());
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// Execute
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::Execute(
|
|
Time target_render_time,
|
|
RendererComplexity complexity_update
|
|
)
|
|
{
|
|
Check(this);
|
|
|
|
mTargetRenderTime = target_render_time;
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// If the renderer is suspended, skip it
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
if (rendererStatus == InactiveRendererStatus)
|
|
return;
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Does the renderer need to run this frame to meet its frame rate?
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// if (nextRenderTime > target_render_time)
|
|
// return;
|
|
// nextRenderTime += calibrationFrameDuration;
|
|
nextRenderTime = Now();
|
|
nextRenderTime += calibrationFrameDuration;
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Keep track of renderers frame budget
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
RendererFrameBudget start_percent;
|
|
RendererFrameBudget end_percent;
|
|
|
|
start_percent = Get_Frame_Percent_Used();
|
|
end_percent = start_percent + framePercentBudget;
|
|
Clamp(end_percent, 0.0f, 1.0f);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Get interest orign
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
RendererOrigin *rendererOrigin;
|
|
|
|
rendererOrigin = rendererOriginSocket.GetCurrent();
|
|
Check(rendererOrigin);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Get iterators for the renderers interest origin and execute
|
|
// renderer
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
RendererOrigin::InterestingEntityIterator
|
|
interesting_entity_iterator(rendererOrigin);
|
|
|
|
Check(&interesting_entity_iterator);
|
|
|
|
Time startImplementation = Now();
|
|
ExecuteImplementation(
|
|
complexity_update,
|
|
&interesting_entity_iterator
|
|
);
|
|
Time endImplementation = Now();
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// If the renderer is under budget then run background if available
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
RendererFrameBudget current_frame_use;
|
|
/*for (
|
|
current_frame_use = Get_Frame_Percent_Used();
|
|
(start_percent < current_frame_use) && (current_frame_use < end_percent);
|
|
current_frame_use = Get_Frame_Percent_Used()
|
|
)
|
|
{
|
|
if (!ExecuteBackground())
|
|
break;
|
|
}*/
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// NotifyOfNewInterestingEntityMessageHandler
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::NotifyOfNewInterestingEntityMessageHandler(
|
|
NotifyOfNewInterestingEntityMessage *message
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(message);
|
|
Verify(message->messageID == NotifyOfNewInterestingEntityMessageID);
|
|
|
|
Entity *entity;
|
|
|
|
if ((entity = message->GetInterestingEntity()) != NULL)
|
|
{
|
|
Check(entity);
|
|
NotifyOfNewInterestingEntity(entity);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// NotifyOfBecomingUninterestingEntityMessageHandler
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::NotifyOfBecomingUninterestingEntityMessageHandler(
|
|
NotifyOfBecomingUninterestingEntityMessage *message
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(message);
|
|
Verify(message->messageID == NotifyOfBecomingUninterestingEntityMessageID);
|
|
|
|
NotifyOfBecomingUninterestingEntity(message->GetUninterestingEntity());
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// StartEntityEffectMessageHandler
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::StartEntityEffectMessageHandler(
|
|
StartEntityEffectMessage *message
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(message);
|
|
Verify(message->messageID == StartEntityEffectMessageID);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// If the entity does not exists then return
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
Entity *entity;
|
|
if ((entity = message->GetEntity()) == NULL)
|
|
return;
|
|
Check(entity);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Get the effect model resource
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
ResourceDescription::ResourceID effect_resource_ID;
|
|
ResourceDescription *resource_description;
|
|
Explosion::ModelResource *model_resource;
|
|
|
|
effect_resource_ID = message->GetResourceID();
|
|
Check(application);
|
|
Check(application->GetResourceFile());
|
|
resource_description =
|
|
application->GetResourceFile()->SearchList(
|
|
effect_resource_ID,
|
|
ResourceDescription::GameModelResourceType
|
|
);
|
|
Check(resource_description);
|
|
resource_description->Lock();
|
|
model_resource =
|
|
(Explosion::ModelResource*)resource_description->resourceAddress;
|
|
Check_Pointer(model_resource);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// If an explosion resource table is being used then use it to set
|
|
// the resource
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
if (model_resource->resourceTableObjectID != NullObjectID)
|
|
{
|
|
//
|
|
// Get resource table pointer,
|
|
// Then set the appropriate resource ID
|
|
//
|
|
Plug *plug;
|
|
ExplosionResourceTable *resource_table;
|
|
ResourceDescription::ResourceID new_resource_ID;
|
|
|
|
plug = PlugStreamManager::FindPlug(model_resource->resourceTableObjectID);
|
|
resource_table = Cast_Object(ExplosionResourceTable*, plug);
|
|
Check(resource_table);
|
|
new_resource_ID = resource_table->FindResourceID(entity);
|
|
if (new_resource_ID != ResourceDescription::NullResourceID)
|
|
{
|
|
effect_resource_ID = new_resource_ID;
|
|
}
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Call the start effect implementation
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
StartEntityEffectImplementation(
|
|
entity,
|
|
message->GetDamageZone(),
|
|
effect_resource_ID
|
|
);
|
|
resource_description->Unlock();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// StopAllEntityEffectsMessageHandler
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::StopAllEntityEffectsMessageHandler(
|
|
StopAllEntityEffectsMessage *message
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(message);
|
|
Verify(message->messageID == StopAllEntityEffectsMessageID);
|
|
|
|
Entity *entity;
|
|
if ((entity = message->GetEntity()) != NULL)
|
|
{
|
|
Check(entity);
|
|
StopAllEntityEffectsImplementation(entity);
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// StartEntityAlarmMessageHandler
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::StartEntityAlarmMessageHandler(
|
|
StartEntityAlarmMessage *message
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(message);
|
|
Verify(message->messageID == StartEntityAlarmMessageID);
|
|
|
|
Entity *entity;
|
|
if ((entity = message->GetEntity()) != NULL)
|
|
{
|
|
Check(entity);
|
|
StartEntityAlarmImplementation(
|
|
entity,
|
|
message->GetSubsystem(),
|
|
message->GetCondition(),
|
|
message->GetResourceID()
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// StopEntityAlarmMessageHandler
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::StopEntityAlarmMessageHandler(
|
|
StopEntityAlarmMessage *message
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(message);
|
|
Verify(message->messageID == StopEntityAlarmMessageID);
|
|
|
|
Entity *entity;
|
|
if ((entity = message->GetEntity()) != NULL)
|
|
{
|
|
Check(entity);
|
|
StopEntityAlarmImplementation(
|
|
entity,
|
|
message->GetSubsystem(),
|
|
message->GetCondition()
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// ExecuteImplementation
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::ExecuteImplementation(
|
|
RendererComplexity,
|
|
RendererOrigin::InterestingEntityIterator*
|
|
)
|
|
{
|
|
Fail("Renderer::ExecuteImplementation - Should never reach here");
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// LoadMissionImplementation
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::LoadMissionImplementation(Mission*)
|
|
{
|
|
Fail("Renderer::LoadMissionImplementation - Should never reach here");
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// ShutdownImplementation
|
|
//#############################################################################
|
|
//
|
|
void
|
|
Renderer::ShutdownImplementation()
|
|
{
|
|
Fail("Renderer::ShutdownImplementation - Should never reach here");
|
|
}
|
|
|
|
//#############################################################################
|
|
//######################### RendererManager #############################
|
|
//#############################################################################
|
|
|
|
//
|
|
//#############################################################################
|
|
// RendererManager
|
|
//#############################################################################
|
|
//
|
|
RendererManager::RendererManager():
|
|
Receiver(RendererManagerClassID, DefaultData),
|
|
renderers(NULL)
|
|
{
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// ~RendererManager
|
|
//#############################################################################
|
|
//
|
|
RendererManager::~RendererManager()
|
|
{
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// TestInstance
|
|
//#############################################################################
|
|
//
|
|
Logical
|
|
RendererManager::TestInstance() const
|
|
{
|
|
Receiver::TestInstance();
|
|
Check(&renderers);
|
|
Check_Fpu();
|
|
return True;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// StartRenderer
|
|
//#############################################################################
|
|
//
|
|
void
|
|
RendererManager::StartRenderer(Renderer *renderer)
|
|
{
|
|
Check(this);
|
|
Check(renderer);
|
|
|
|
#if DEBUG_LEVEL>0
|
|
SChainIterator iterator(&renderers);
|
|
Verify(iterator.IsPlugMember(renderer) == False);
|
|
#endif
|
|
|
|
renderers.Add(renderer);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// StopRenderer
|
|
//#############################################################################
|
|
//
|
|
void
|
|
RendererManager::StopRenderer(Renderer *renderer)
|
|
{
|
|
Check(this);
|
|
Check(renderer);
|
|
|
|
#if DEBUG_LEVEL>0
|
|
{
|
|
SChainIteratorOf<Renderer*> iterator(&renderers);
|
|
Verify(iterator.IsPlugMember(renderer) == True);
|
|
}
|
|
#endif
|
|
|
|
SChainIteratorOf<Renderer*> iterator(&renderers);
|
|
iterator.RemovePlug(renderer);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// AreRenderersRunning
|
|
//#############################################################################
|
|
//
|
|
Logical
|
|
RendererManager::AreRenderersRunning()
|
|
{
|
|
Check(this);
|
|
|
|
Renderer
|
|
*renderer;
|
|
SChainIteratorOf<Renderer*>
|
|
renderers_iterator(&renderers);
|
|
|
|
if (renderers_iterator.GetCurrent() == NULL)
|
|
return False;
|
|
|
|
while ((renderer = renderers_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check(renderer);
|
|
if (renderer->GetRendererStatus() != RunningRendererStatus)
|
|
return False;
|
|
}
|
|
Check_Fpu();
|
|
return True;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// UpdateInterestOrigins
|
|
//#############################################################################
|
|
//
|
|
void
|
|
RendererManager::UpdateInterestOrigins(Time target_render_time)
|
|
{
|
|
Check(this);
|
|
|
|
//
|
|
// HACK - under construction, does not include complexity or priorities
|
|
//
|
|
Renderer
|
|
*renderer;
|
|
SChainIteratorOf<Renderer*>
|
|
renderers_iterator(&renderers);
|
|
|
|
while ((renderer = renderers_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check(renderer);
|
|
renderer->UpdateInterestOrigin(target_render_time);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// Execute
|
|
//#############################################################################
|
|
//
|
|
void
|
|
RendererManager::Execute(
|
|
Time target_render_time,
|
|
Time,
|
|
Time
|
|
)
|
|
{
|
|
Check(this);
|
|
|
|
//
|
|
// HACK - under construction, does not include complexity or priorities
|
|
//
|
|
Renderer *renderer;
|
|
RendererComplexity complexity_update;
|
|
SChainIteratorOf<Renderer*> renderers_iterator(&renderers);
|
|
Time startRender = Now();
|
|
int renderItem = 0;
|
|
while ((renderer = renderers_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check(renderer);
|
|
|
|
// Calculate current complexity
|
|
// HACK - use calibration complexity for now
|
|
Time startComplexity = Now();
|
|
complexity_update = renderer->GetCalibrationComplexity();
|
|
Time endComplexity = Now();
|
|
|
|
renderer->Execute(target_render_time, complexity_update);
|
|
renderItem++;
|
|
}
|
|
Time endRender = Now();
|
|
endRender = endRender;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// ExecuteIdle
|
|
//#############################################################################
|
|
//
|
|
void RendererManager::ExecuteIdle()
|
|
{
|
|
Renderer *renderer;
|
|
SChainIteratorOf<Renderer*> renderers_iterator(&renderers);
|
|
|
|
while ((renderer = renderers_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check(renderer);
|
|
|
|
renderer->ExecuteIdle();
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// PostRendererEvent
|
|
//#############################################################################
|
|
//
|
|
void
|
|
RendererManager::PostRendererEvent(
|
|
Entity *entity,
|
|
Receiver::Message *message
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(entity);
|
|
Check(message);
|
|
|
|
Renderer
|
|
*renderer;
|
|
SChainIteratorOf<Renderer*>
|
|
renderers_iterator(&renderers);
|
|
|
|
while ((renderer = renderers_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check(renderer);
|
|
Check(application);
|
|
Check(application->GetInterestManager());
|
|
application->GetInterestManager()->PostRendererEvent(
|
|
entity,
|
|
renderer,
|
|
message
|
|
);
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~ Renderer__NotifyOfNewInterestingEntityMessage ~~~~~~~~~~~~~
|
|
|
|
Renderer__NotifyOfNewInterestingEntityMessage::
|
|
Renderer__NotifyOfNewInterestingEntityMessage(
|
|
Entity *interesting_entity
|
|
):
|
|
Receiver::Message(
|
|
Renderer::NotifyOfNewInterestingEntityMessageID,
|
|
sizeof(Renderer__NotifyOfNewInterestingEntityMessage)
|
|
)
|
|
{
|
|
Check(interesting_entity);
|
|
entityID = interesting_entity->GetEntityID();
|
|
Check_Fpu();
|
|
}
|
|
|
|
Entity*
|
|
Renderer__NotifyOfNewInterestingEntityMessage::GetInterestingEntity()
|
|
{
|
|
Check(this);
|
|
Check(application);
|
|
Check(application->GetHostManager());
|
|
|
|
Check_Fpu();
|
|
return application->GetHostManager()->GetEntityPointer(entityID);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~ Renderer__NotifyOfBecomingUninterestingEntityMessage ~~~~~~~~~
|
|
|
|
Renderer__NotifyOfBecomingUninterestingEntityMessage::
|
|
Renderer__NotifyOfBecomingUninterestingEntityMessage(
|
|
Entity *uninteresting_entity
|
|
):
|
|
Receiver::Message(
|
|
Renderer::NotifyOfBecomingUninterestingEntityMessageID,
|
|
sizeof(Renderer__NotifyOfBecomingUninterestingEntityMessage)
|
|
)
|
|
{
|
|
uninterestingEntity = uninteresting_entity;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~ Renderer__EntityMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Renderer__EntityMessage::Renderer__EntityMessage(
|
|
Receiver::MessageID message_ID,
|
|
size_t message_size,
|
|
Entity *entity
|
|
):
|
|
Receiver::Message(
|
|
message_ID,
|
|
message_size
|
|
)
|
|
{
|
|
Check(entity);
|
|
entityID = entity->GetEntityID();
|
|
}
|
|
|
|
Entity*
|
|
Renderer__EntityMessage::GetEntity()
|
|
{
|
|
Check(this);
|
|
Check(application);
|
|
Check(application->GetHostManager());
|
|
return application->GetHostManager()->GetEntityPointer(entityID);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~ Renderer__StartEntityEffectMessage ~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Renderer__StartEntityEffectMessage::Renderer__StartEntityEffectMessage(
|
|
Entity *entity,
|
|
DamageZone *damage_zone,
|
|
ResourceDescription::ResourceID resource_ID
|
|
):
|
|
Renderer__EntityMessage(
|
|
Renderer::StartEntityEffectMessageID,
|
|
sizeof(Renderer__StartEntityEffectMessage),
|
|
entity
|
|
)
|
|
{
|
|
Check(damage_zone);
|
|
Verify(resource_ID != ResourceDescription::NullResourceID);
|
|
damageZone = damage_zone;
|
|
resourceID = resource_ID;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~ Renderer__StopAllEntityEffectsMessage ~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Renderer__StopAllEntityEffectsMessage::Renderer__StopAllEntityEffectsMessage(
|
|
Entity *entity
|
|
):
|
|
Renderer__EntityMessage(
|
|
Renderer::StopAllEntityEffectsMessageID,
|
|
sizeof(Renderer__StopAllEntityEffectsMessage),
|
|
entity
|
|
)
|
|
{
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~ Renderer__StartEntityAlarmMessage ~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Renderer__StartEntityAlarmMessage::Renderer__StartEntityAlarmMessage(
|
|
Entity *entity,
|
|
Subsystem *alarm_subsystem,
|
|
Enumeration alarm_condition,
|
|
ResourceDescription::ResourceID resource_ID
|
|
):
|
|
Renderer__EntityMessage(
|
|
Renderer::StartEntityAlarmMessageID,
|
|
sizeof(Renderer__StartEntityAlarmMessage),
|
|
entity
|
|
)
|
|
{
|
|
Check(alarm_subsystem);
|
|
#if DEBUG_LEVEL>0
|
|
if (resource_ID == ResourceDescription::NullResourceID)
|
|
{
|
|
Dump(alarm_subsystem->GetClassID());
|
|
Dump(alarm_condition);
|
|
}
|
|
#endif
|
|
Warn(resource_ID == ResourceDescription::NullResourceID); // HACK - ECH Why is this sometimes NULL?
|
|
subsystem = alarm_subsystem;
|
|
condition = alarm_condition;
|
|
resourceID = resource_ID;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~ Renderer__StopEntityAlarmMessage ~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Renderer__StopEntityAlarmMessage::Renderer__StopEntityAlarmMessage(
|
|
Entity *entity,
|
|
Subsystem *alarm_subsystem,
|
|
Enumeration alarm_condition
|
|
):
|
|
Renderer__EntityMessage(
|
|
Renderer::StopEntityAlarmMessageID,
|
|
sizeof(Renderer__StopEntityAlarmMessage),
|
|
entity
|
|
)
|
|
{
|
|
Check(alarm_subsystem);
|
|
subsystem = alarm_subsystem;
|
|
condition = alarm_condition;
|
|
}
|
|
|
|
#ifdef TEST_CLASS
|
|
# include "renderer.tcp"
|
|
#endif
|