Files
CydandClaude Fable 5 fdd9ac9d97 Initial import: Tesla Release 4.10 (Tesla:BattleTech & Tesla:Red Planet)
Archival snapshot of the Virtual World Entertainment Tesla cockpit
software, 1994-1996: MUNGA engine and L4 pod layer source (Borland
C++ 5.0), BT/RP game code, and game content (models, audio, maps,
gauges, Division renderer data). Includes third-party libraries:
Division dVS/DPL graphics, HMI SOS audio, WATTCP networking.

Files are preserved byte-for-byte (.gitattributes disables all
line-ending conversion). README.md documents the layout, target
hardware, and toolchain.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 13:21:58 -05:00

1070 lines
28 KiB
C++

//===========================================================================//
// File: renderer.cc //
// Project: MUNGA Brick: Renderer Manager //
// Contents: Interface specification Renderer and Renderer Manager //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 11/21/94 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(RENDERER_HPP)
# include <renderer.hpp>
#endif
#if !defined(RNDORGN_HPP)
# include <rndorgn.hpp>
#endif
#if !defined(EXPLODE_HPP)
# include <explode.hpp>
#endif
#if !defined(APP_HPP)
#include <app.hpp>
#endif
#if !defined(OBJSTRM_HPP)
#include <objstrm.hpp>
#endif
#if !defined(HOSTMGR_HPP)
#include <hostmgr.hpp>
#endif
#if !defined(SUBSYSTM_HPP)
#include <subsystm.hpp>
#endif
//#############################################################################
//############################ 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::MessageHandlers(
ELEMENTS(Renderer::MessageHandlerEntries),
Renderer::MessageHandlerEntries,
Receiver::MessageHandlers
);
//#############################################################################
// Shared Data Support
//
Derivation
Renderer::ClassDerivations(
Receiver::ClassDerivations,
"Renderer"
);
Renderer::SharedData
Renderer::DefaultData(
Renderer::ClassDerivations,
Renderer::MessageHandlers
);
//
//#############################################################################
// 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(ClassDerivations))
{
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);
//
//--------------------------------------------------------------------------
// 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);
ExecuteImplementation(
complexity_update,
&interesting_entity_iterator
);
//
//--------------------------------------------------------------------------
// 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);
while ((renderer = renderers_iterator.ReadAndNext()) != NULL)
{
Check(renderer);
//
// Calculate current complexity
// HACK - use calibration complexity for now
//
complexity_update = renderer->GetCalibrationComplexity();
//
// Execute
//
renderer->Execute(target_render_time, complexity_update);
}
Check_Fpu();
}
//
//#############################################################################
// CompleteCycles
//#############################################################################
//
void
RendererManager::CompleteCycles()
{
Check(this);
Renderer
*renderer;
SChainIteratorOf<Renderer*>
renderers_iterator(&renderers);
while ((renderer = renderers_iterator.ReadAndNext()) != NULL)
{
Check(renderer);
renderer->CompleteCycle();
}
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