The interactive 2-node playtest wave -- every fix decomp-grounded and live-verified: COLLISION ECONOMY (the ram one-shot): StaticBounce mutates worldLinearVelocity per contact and ProcessCollisionList walks EVERY touched solid per frame; with 2007 terrain-as-solids the reflections compounded x4-x40 within one frame and a walking bump one-shot a pristine mech for 112,375 pts (62-pt authentic economy). Fix: frameEntryWorldVelocity restore per contact (damage always priced at the real approach speed -- all the binary's physics ever saw); Mech::Reset zeroes the mover motion (respawn = teleport); [collide-tx]/[mp-hdlr] telemetry. Gotcha #16 (engine-facility drift class). MISSILES: peer-visible salvos (the launcher record extension carries a salvo counter + aim point; ForceUpdate actually enqueues it -- the dirty flag alone never serialized), the authentic arc (authored MuzzleVelocity vector + the Seeker's 200m/0.1/300 loft + gain-4 steering, decoded from @004beae4/@004bef78), world-impact bursts (rounds detonate on cave geometry instead of phasing through), contact-only damage (flight-cap expiry = fizzle, no more teleport damage), live re-lead, and ballistic (unguided) shells for autocannons. projweap's stale BTPushProjectile extern (the /FORCE signature trap, gotcha #6 corollary) crashed the Avatar's first AFC100 shot -- fixed + sweep rule recorded. RADAR: two transcription bugs made the scope permanently empty -- FUN_0040b244 is the affine INVERSE (not a copy) and FUN_0040adec writes ONLY the 3x3 rotation (never the translation); worldToView now Invert(view) built rotation-first. CulturalIcons sorted out of the moving grid (the phantom red pips were map props), visible-radius culls on all three draw passes, live pip verified at |delta| x ppm px. Gotcha #17 (verify the FUN_ body, not its call shape). WEAPON PANELS (the frozen-dial hunt): the binary's *(subsystem+0x40) means FAILED -- the recon's 'operating' name was backwards, inverting the destroyed-X lamps, the panel look, the children enable and the ready-lamp gate (which had NEVER executed). Polarity chain corrected end-to-end (failedState, fed by real damage saturation). Root cause of the freezes: MFD page-mode gating -- the dev composite shows ALL pages at once, so off-page dials legitimately stopped; under BT_DEV_GAUGES the 15 page-plane bits stay active (the exclusive secondary trio untouched). The SEH gauge guard now names its kills; repaint-heal resets the incremental arc after panel repaints; [panel]/[arc] probes added. COMM/SCORE: MessageBoard LIVE (the engine already shipped the whole Player__StatusMessage queue; wired the binary's one producer -- the kill branch, victim's name, 6s -- plus the consumer bridge and a lazy source bind); MP DEATHS counted via the observed-death tally (each node scores every pilot from locally observed events, the same model as the KILLS credit) and the -2/-1 engine seed clamped for display. DEV UX: node-tagged window titles (-net port), gauge panel reworked (1320x480, true 4:3 MFD cells, the portrait secondary UNROTATED upright, linear filtering, BT_GAUGE_SCALE), fixed close spawns via BT_SPAWN_XZ, Boreas flies an Avatar (first second-chassis live outing). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1679 lines
43 KiB
C++
1679 lines
43 KiB
C++
#include "mungal4.h"
|
|
#pragma hdrstop
|
|
|
|
#include "..\munga\fileutil.h"
|
|
#include "l4gauima.h"
|
|
#include "l4app.h"
|
|
#include "..\munga\notation.h"
|
|
#include "..\munga\namelist.h"
|
|
|
|
// #define LOCAL_TEST
|
|
|
|
#if defined(LOCAL_TEST)
|
|
# define Test_Tell(n) std::cout << n << std::flush
|
|
#else
|
|
# define Test_Tell(n)
|
|
#endif
|
|
|
|
|
|
//############################################################################
|
|
// GroupAttribute
|
|
// - this is a private class used nowhere else.
|
|
// It is initialized from a .GAT notation file, after which it
|
|
// holds a list of attribute group names with associated color and
|
|
// attribute fields. It may then be searched to find the values for
|
|
// that attribute group.
|
|
//############################################################################
|
|
class GroupAttribute SIGNATURED
|
|
{
|
|
public:
|
|
enum
|
|
{
|
|
nameLength=64
|
|
};
|
|
|
|
int color;
|
|
int attribute;
|
|
char name[nameLength];
|
|
|
|
GroupAttribute
|
|
*next;
|
|
|
|
GroupAttribute(const char *new_name, int new_color, int new_attrib);
|
|
~GroupAttribute()
|
|
{}
|
|
|
|
Logical
|
|
TestInstance() const
|
|
{ return True; }
|
|
|
|
static Logical
|
|
Initialize(const char *gat_file_name);
|
|
static void
|
|
Terminate();
|
|
static Logical
|
|
Search(const char *name, int *color, int *attribute);
|
|
protected:
|
|
static
|
|
GroupAttribute
|
|
*head;
|
|
};
|
|
|
|
GroupAttribute
|
|
*GroupAttribute::head;
|
|
|
|
GroupAttribute::GroupAttribute(
|
|
const char *new_name,
|
|
int new_color,
|
|
int new_attrib
|
|
)
|
|
{
|
|
Test_Tell(
|
|
"GroupAttribute::GroupAttribute(" << new_name <<
|
|
", " << new_color <<
|
|
", " << new_attrib <<
|
|
")\n"
|
|
);
|
|
Check_Pointer(this);
|
|
Check_Pointer(new_name);
|
|
|
|
name[0] = '\0'; // safety check
|
|
Str_Copy(name, new_name, nameLength-1);
|
|
name[nameLength-1] = '\0';
|
|
|
|
color = new_color;
|
|
attribute = new_attrib;
|
|
|
|
next = head;
|
|
head = this;
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
GroupAttribute::Initialize(const char *gat_filename)
|
|
{
|
|
Test_Tell("GroupAttribute::Initialize(" << gat_filename << ")\n");
|
|
Check_Pointer(gat_filename);
|
|
|
|
Logical
|
|
result = False;
|
|
|
|
//-------------------------------------------------------------
|
|
// Open the associated .GAT file
|
|
//-------------------------------------------------------------
|
|
NotationFile
|
|
*gat_file = new NotationFile(gat_filename);
|
|
Check(gat_file);
|
|
Register_Object(gat_file);
|
|
|
|
//-------------------------------------------------------------
|
|
// Create group, attribute, color name lists
|
|
//-------------------------------------------------------------
|
|
NameList
|
|
*color_namelist = gat_file->MakeEntryList("colors");
|
|
if (color_namelist == NULL)
|
|
{
|
|
DEBUG_STREAM << gat_filename << " has no 'colors' page!" << std::endl;
|
|
}
|
|
|
|
NameList
|
|
*attribute_namelist = gat_file->MakeEntryList("attributes");
|
|
if (attribute_namelist == NULL)
|
|
{
|
|
DEBUG_STREAM << gat_filename << " has no 'attributes' page!" << std::endl;
|
|
}
|
|
|
|
NameList
|
|
*group_namelist = gat_file->MakeEntryList("groups");
|
|
if (group_namelist == NULL)
|
|
{
|
|
DEBUG_STREAM << gat_filename << " has no 'groups' page!" << std::endl;
|
|
}
|
|
|
|
if (
|
|
(attribute_namelist != NULL) &&
|
|
(color_namelist != NULL) &&
|
|
(group_namelist != NULL)
|
|
)
|
|
{
|
|
//-------------------------------------------------------------
|
|
// Register the name lists
|
|
//-------------------------------------------------------------
|
|
Register_Object(color_namelist);
|
|
Register_Object(attribute_namelist);
|
|
Register_Object(group_namelist);
|
|
//-------------------------------------------------------------
|
|
// Clear the chain header
|
|
//-------------------------------------------------------------
|
|
head = NULL;
|
|
//-------------------------------------------------------------
|
|
// For all group names, build a GroupAttribute object
|
|
//-------------------------------------------------------------
|
|
NameList::Entry
|
|
*group_entry,
|
|
*color_entry,
|
|
*attribute_entry;
|
|
int
|
|
i,
|
|
new_attribute,
|
|
new_color;
|
|
Logical
|
|
found;
|
|
|
|
for (
|
|
group_entry = group_namelist->GetFirstEntry();
|
|
group_entry != NULL;
|
|
group_entry = group_entry->GetNextEntry()
|
|
)
|
|
{
|
|
Check(group_entry);
|
|
|
|
char
|
|
buffer[256];
|
|
char
|
|
*dest,
|
|
*text = group_entry->GetChar();
|
|
|
|
new_attribute = 0;
|
|
new_color = 0;
|
|
|
|
if (text == NULL)
|
|
{
|
|
DEBUG_STREAM << text << " is an empty .GAT group!" << std::endl;
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------------------------------------
|
|
// Skip white space
|
|
//-------------------------------------------------------------
|
|
while (*text != '\0')
|
|
{
|
|
while (isspace(*text))
|
|
{
|
|
++text;
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Parse out one name
|
|
//-------------------------------------------------------------
|
|
for (
|
|
i=0,dest=buffer;
|
|
i<(sizeof(buffer)-1);
|
|
++i,++dest,++text
|
|
)
|
|
{
|
|
if (!isalnum(*text))
|
|
{
|
|
break;
|
|
}
|
|
|
|
*dest = *text;
|
|
}
|
|
*dest = '\0';
|
|
|
|
Test_Tell("attribute item= <" << buffer << ">\n");
|
|
//-------------------------------------------------------------
|
|
// Search color list for name
|
|
//-------------------------------------------------------------
|
|
found = False;
|
|
|
|
for (
|
|
color_entry = color_namelist->GetFirstEntry();
|
|
color_entry != NULL;
|
|
color_entry = color_entry->GetNextEntry()
|
|
)
|
|
{
|
|
Check(color_entry);
|
|
if (strcmp(color_entry->GetName(), buffer) == 0)
|
|
{
|
|
Check_Pointer(color_entry->GetData());
|
|
new_color = color_entry->GetAtoi();
|
|
Test_Tell("color=" << new_color << "\n");
|
|
found = True;
|
|
break;
|
|
}
|
|
}
|
|
if (! found)
|
|
{
|
|
//----------------------------------------------------------
|
|
// Search attribute list for name
|
|
//----------------------------------------------------------
|
|
found = False;
|
|
|
|
for (
|
|
attribute_entry =attribute_namelist->GetFirstEntry();
|
|
attribute_entry != NULL;
|
|
attribute_entry = attribute_entry->GetNextEntry()
|
|
)
|
|
{
|
|
Check(attribute_entry);
|
|
if (strcmp(attribute_entry->GetName(), buffer) == 0)
|
|
{
|
|
Check_Pointer(attribute_entry->GetData());
|
|
new_attribute |= attribute_entry->GetAtoi();
|
|
Test_Tell(
|
|
"attribute=" << std::hex << new_attribute << std::dec << ">\n"
|
|
);
|
|
found = True;
|
|
break;
|
|
}
|
|
}
|
|
if (! found)
|
|
{
|
|
DEBUG_STREAM <<
|
|
"Attribute '" << buffer << "' not found!" << std::endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Check(group_entry);
|
|
Check_Pointer(group_entry->GetName());
|
|
|
|
# if DEBUG_LEVEL == 0
|
|
new GroupAttribute(
|
|
group_entry->GetName(),
|
|
new_color,
|
|
new_attribute
|
|
);
|
|
# else
|
|
GroupAttribute
|
|
*group_attribute =
|
|
new GroupAttribute(
|
|
group_entry->GetName(),
|
|
new_color,
|
|
new_attribute
|
|
);
|
|
Check(group_attribute);
|
|
Register_Object(group_attribute);
|
|
Test_Tell("object created\n");
|
|
# endif
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Release the name lists
|
|
//-------------------------------------------------------------
|
|
Test_Tell("loop finished, deleting namelists\n");
|
|
Check(color_namelist);
|
|
Unregister_Object(color_namelist);
|
|
delete color_namelist;
|
|
|
|
Check(attribute_namelist);
|
|
Unregister_Object(attribute_namelist);
|
|
delete attribute_namelist;
|
|
|
|
Check(group_namelist);
|
|
Unregister_Object(group_namelist);
|
|
delete group_namelist;
|
|
|
|
result = True;
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Release the notation file
|
|
//-------------------------------------------------------------
|
|
Test_Tell("deleting .GAT notation file\n");
|
|
Check(gat_file);
|
|
Unregister_Object(gat_file);
|
|
delete gat_file;
|
|
|
|
Test_Tell("returning " << result <<"\n");
|
|
Check_Fpu();
|
|
return result;
|
|
}
|
|
|
|
void
|
|
GroupAttribute::Terminate()
|
|
{
|
|
Test_Tell("GroupAttribute::Terminate\n");
|
|
GroupAttribute
|
|
*group_attribute,
|
|
*next;
|
|
|
|
for(
|
|
group_attribute= head;
|
|
group_attribute != NULL;
|
|
group_attribute = next
|
|
)
|
|
{
|
|
Check(group_attribute);
|
|
next = group_attribute->next;
|
|
|
|
Unregister_Object(group_attribute);
|
|
delete group_attribute;
|
|
}
|
|
|
|
head = NULL;
|
|
Test_Tell("Termination completed\n");
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
Logical
|
|
GroupAttribute::Search(const char *name, int *color_dest, int *attrib_dest)
|
|
{
|
|
Test_Tell("GroupAttribute::Search("<< name <<")\n");
|
|
GroupAttribute
|
|
*group_attribute;
|
|
|
|
for(
|
|
group_attribute= head;
|
|
group_attribute != NULL;
|
|
group_attribute = group_attribute->next
|
|
)
|
|
{
|
|
Check(group_attribute);
|
|
if (
|
|
strncmp(
|
|
name,
|
|
group_attribute->name,
|
|
GroupAttribute::nameLength
|
|
) == 0
|
|
)
|
|
{
|
|
Test_Tell("Found!\n");
|
|
*color_dest = group_attribute->color;
|
|
*attrib_dest = group_attribute->attribute;
|
|
Check_Fpu();
|
|
return True;
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
return False;
|
|
}
|
|
|
|
//############################################################################
|
|
// L4GaugeImage
|
|
//############################################################################
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Construction and Destruction
|
|
//
|
|
L4GaugeImage *
|
|
L4GaugeImage::Make(const char */*file_name*/)
|
|
{
|
|
return NULL; // Gauge images come exclusively from resources
|
|
}
|
|
|
|
L4GaugeImage *
|
|
L4GaugeImage::Make(ResourceDescription::ResourceID new_resource_id)
|
|
{
|
|
Check(application);
|
|
Check(application->GetResourceFile());
|
|
|
|
L4GaugeImage
|
|
*image = NULL;
|
|
//-------------------------------------------
|
|
// Attempt to find the specified resource
|
|
//-------------------------------------------
|
|
ResourceDescription
|
|
*stream_resource_description =
|
|
application->GetResourceFile()->SearchList(
|
|
new_resource_id,
|
|
ResourceDescription::GaugeImageStreamResourceType
|
|
);
|
|
|
|
if (stream_resource_description == NULL)
|
|
{
|
|
Tell(
|
|
"L4GaugeImage::Make: resource ID '" << new_resource_id <<
|
|
"' does not exist\n"
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------------------
|
|
// Found it, open a DynamicMemoryStream
|
|
//-------------------------------------------
|
|
Check(stream_resource_description);
|
|
stream_resource_description->Lock();
|
|
MemoryStream
|
|
memory_stream(
|
|
stream_resource_description->resourceAddress,
|
|
stream_resource_description->resourceSize
|
|
);
|
|
if (stream_resource_description->resourceAddress == NULL)
|
|
{
|
|
Tell("L4GaugeImage::Make: couldn't open stream\n");
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------------------
|
|
// Create the object
|
|
//-------------------------------------------
|
|
image = new L4GaugeImage(&memory_stream);
|
|
}
|
|
stream_resource_description->Unlock();
|
|
}
|
|
Check_Fpu();
|
|
return image;
|
|
}
|
|
|
|
L4GaugeImage::L4GaugeImage(MemoryStream *mem_stream)
|
|
{
|
|
Test_Tell("L4GaugeImage::L4GaugeImage\n");
|
|
Check_Pointer(this);
|
|
Check(mem_stream);
|
|
|
|
int
|
|
i;
|
|
|
|
//-------------------------------------------------------------
|
|
// Read the number of vertices
|
|
//-------------------------------------------------------------
|
|
MemoryStream_Read(mem_stream, &vertexCount);
|
|
Verify(vertexCount > 0);
|
|
//-------------------------------------------------------------
|
|
// Allocate the vertex array
|
|
//-------------------------------------------------------------
|
|
vertexArray = new Point3D[vertexCount];
|
|
Check_Pointer(vertexArray);
|
|
Register_Pointer(vertexArray);
|
|
//-------------------------------------------------------------
|
|
// Read in the vertex values
|
|
//-------------------------------------------------------------
|
|
for(i=0; i<vertexCount; ++i)
|
|
{
|
|
MemoryStream_Read(mem_stream, &vertexArray[i]);
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Read the number of LOD's from the stream
|
|
//-------------------------------------------------------------
|
|
MemoryStream_Read(mem_stream, &LODCount);
|
|
Verify(LODCount > 0);
|
|
//-------------------------------------------------------------
|
|
// Allocate the LOD scales
|
|
//-------------------------------------------------------------
|
|
LODScales = new Scalar[LODCount];
|
|
Check_Pointer(LODScales);
|
|
Register_Pointer(LODScales);
|
|
//-------------------------------------------------------------
|
|
// Read the LOD scales
|
|
//-------------------------------------------------------------
|
|
for(i=0; i<LODCount; ++i)
|
|
{
|
|
MemoryStream_Read(mem_stream, &LODScales[i]);
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Allocate the LOD lists
|
|
//-------------------------------------------------------------
|
|
LODList = new L4GaugeImageList*[LODCount];
|
|
Check_Pointer(LODList);
|
|
Register_Pointer(LODList);
|
|
//-------------------------------------------------------------
|
|
// Read the LOD lists
|
|
//-------------------------------------------------------------
|
|
for(i=0; i<LODCount; ++i)
|
|
{
|
|
LODList[i] = new L4GaugeImageList(mem_stream);
|
|
Check(LODList[i]);
|
|
Register_Object(LODList[i]);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
L4GaugeImage::~L4GaugeImage()
|
|
{
|
|
Test_Tell("L4GaugeImage::~L4GaugeImage\n");
|
|
Check(this);
|
|
|
|
int
|
|
i;
|
|
|
|
//-------------------------------------------------------------
|
|
// Delete the vertices
|
|
//-------------------------------------------------------------
|
|
Check_Pointer(vertexArray);
|
|
Unregister_Pointer(vertexArray);
|
|
delete[] vertexArray;
|
|
//-------------------------------------------------------------
|
|
// Delete the LOD scales
|
|
//-------------------------------------------------------------
|
|
Check_Pointer(LODScales);
|
|
Unregister_Pointer(LODScales);
|
|
delete[] LODScales;
|
|
//-------------------------------------------------------------
|
|
// Delete the LOD list items
|
|
//-------------------------------------------------------------
|
|
Check_Pointer(LODList);
|
|
for(i=0; i<LODCount; ++i)
|
|
{
|
|
Check(LODList[i]);
|
|
Unregister_Object(LODList[i]);
|
|
delete LODList[i];
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Delete the LOD list
|
|
//-------------------------------------------------------------
|
|
Unregister_Pointer(LODList);
|
|
delete[] LODList;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ResourceDescription::ResourceID
|
|
L4GaugeImage::CreateL4GaugeImageStream(
|
|
ResourceFile *resource_file,
|
|
const char *model_name,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories
|
|
)
|
|
{
|
|
Check(resource_file);
|
|
Check_Pointer(model_name);
|
|
Check(model_file);
|
|
Check_Pointer(directories);
|
|
|
|
ResourceDescription::ResourceID
|
|
res_id = ResourceDescription::NullResourceID;
|
|
|
|
//----------------------------------------------------------------------
|
|
// Check to see if the model has a gauge image specified...
|
|
//----------------------------------------------------------------------
|
|
const char *gauge_filename;
|
|
|
|
if (model_file->GetEntry("gauge", "image", &gauge_filename) != 0)
|
|
{
|
|
//-------------------------------------------------------------
|
|
// It does, attempt to open the given notation file
|
|
//-------------------------------------------------------------
|
|
Tell("Opening gauge image " << gauge_filename << "\n");
|
|
|
|
char *gim_filename =
|
|
MakePathedFilename(directories->gaugeDirectory, gauge_filename);
|
|
Register_Pointer(gim_filename);
|
|
|
|
NotationFile
|
|
*gim_file = new NotationFile(gim_filename);
|
|
Check(gim_file);
|
|
Register_Object(gim_file);
|
|
|
|
//--------------------------------------------------------
|
|
// Search for the name of the .GAT file
|
|
//--------------------------------------------------------
|
|
const char
|
|
*gat_entry;
|
|
|
|
if (gim_file->GetEntry("object", "gatfile", &gat_entry) == 0)
|
|
{
|
|
DEBUG_STREAM << "Missing .gat specification!" << std::endl;
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------------------------------------
|
|
// Create the GroupAttribute data
|
|
//-------------------------------------------------------------
|
|
char *gat_filename =
|
|
MakePathedFilename(directories->gaugeDirectory, gat_entry);
|
|
Register_Pointer(gat_filename);
|
|
|
|
if (GroupAttribute::Initialize(gat_filename))
|
|
{
|
|
//-------------------------------------------------------------
|
|
// Create a dynamic memory stream, write out the data
|
|
// (note: the call to L4GaugeImage::DynamicMemoryStreamWrite()
|
|
// internally calls the dynamic stream writes for all of the
|
|
// 'owned' sub-parts as well)
|
|
//-------------------------------------------------------------
|
|
DynamicMemoryStream
|
|
*gim_stream = new DynamicMemoryStream();
|
|
|
|
Check(gim_stream);
|
|
Register_Object(gim_stream);
|
|
|
|
if (
|
|
L4GaugeImage::MemoryStreamWrite(
|
|
gim_stream,
|
|
gim_file
|
|
) == True
|
|
)
|
|
{
|
|
//-------------------------------------------------------------
|
|
// Create the resource description, assign an ID
|
|
//-------------------------------------------------------------
|
|
ResourceDescription
|
|
*res_desc_stream =
|
|
resource_file->ResourceFile::AddResourceMemoryStream(
|
|
model_name,
|
|
ResourceDescription::GaugeImageStreamResourceType,
|
|
1,
|
|
ResourceDescription::Preload,
|
|
gim_stream
|
|
);
|
|
|
|
Check(res_desc_stream);
|
|
res_id = res_desc_stream->resourceID;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Release the GroupAttribute data
|
|
//-------------------------------------------------------------
|
|
GroupAttribute::Terminate();
|
|
|
|
Check(gim_stream);
|
|
Unregister_Object(gim_stream);
|
|
delete gim_stream;
|
|
}
|
|
Check_Pointer(gat_filename);
|
|
Unregister_Pointer(gat_filename);
|
|
delete gat_filename;
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Release variables
|
|
//-------------------------------------------------------------
|
|
Check(gim_file);
|
|
Unregister_Object(gim_file);
|
|
delete gim_file;
|
|
|
|
Check_Pointer(gim_filename);
|
|
Unregister_Pointer(gim_filename);
|
|
delete gim_filename;
|
|
|
|
Tell("Closed gauge image\n" << std::flush);
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Return the new ResourceID
|
|
//-------------------------------------------------------------
|
|
Test_Tell("res_id = " << res_id << "\n");
|
|
Check_Fpu();
|
|
return res_id;
|
|
}
|
|
|
|
|
|
Logical
|
|
L4GaugeImage::MemoryStreamWrite(
|
|
MemoryStream *mem_stream,
|
|
NotationFile *gim_file
|
|
)
|
|
{
|
|
Test_Tell(" L4GaugeImage::MemoryStreamWrite(" << mem_stream <<
|
|
", " << gim_file <<
|
|
")\n"
|
|
);
|
|
Check(mem_stream);
|
|
Check(gim_file);
|
|
|
|
int
|
|
i;
|
|
//-------------------------------------------------------------
|
|
// 'result' is set to False if an error occurs.
|
|
//-------------------------------------------------------------
|
|
Logical
|
|
result = True;
|
|
//-------------------------------------------------------------
|
|
// Write the vertices
|
|
//-------------------------------------------------------------
|
|
NameList
|
|
*vertex_list = gim_file->MakeEntryList("vertices");
|
|
|
|
if (vertex_list == NULL)
|
|
{
|
|
DEBUG_STREAM << "No 'vertices' page in the .GIM file!" << std::endl;
|
|
result = False;
|
|
}
|
|
else
|
|
{
|
|
Check(vertex_list);
|
|
Register_Object(vertex_list);
|
|
//-------------------------------------------------------------
|
|
// Get the number of vertices
|
|
//-------------------------------------------------------------
|
|
int
|
|
vertex_count = vertex_list->EntryCount();
|
|
|
|
Test_Tell("vertex_count = " << vertex_count << "\n");
|
|
if (vertex_count <= 0)
|
|
{
|
|
DEBUG_STREAM <<
|
|
"The 'vertices' page in the .GIM file has no entries!" <<std::endl;
|
|
result = False;
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------------------------------------
|
|
// Write the number of vertices to the stream
|
|
//-------------------------------------------------------------
|
|
MemoryStream_Write(mem_stream, &vertex_count);
|
|
//-------------------------------------------------------------
|
|
// Write the vertices
|
|
//-------------------------------------------------------------
|
|
Point3D
|
|
point_3d;
|
|
NameList::Entry
|
|
*vertex_entry = vertex_list->GetFirstEntry();
|
|
|
|
for (int i=0; i<vertex_count; ++i)
|
|
{
|
|
Verify(vertex_entry != NULL);
|
|
|
|
Convert_From_Ascii(vertex_entry->GetChar(), &point_3d);
|
|
Test_Tell(" " << point_3d << "\n");
|
|
MemoryStream_Write(mem_stream, &point_3d);
|
|
|
|
vertex_entry = vertex_entry->GetNextEntry();
|
|
}
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Delete the vertex list
|
|
//-------------------------------------------------------------
|
|
Check(vertex_list);
|
|
Unregister_Object(vertex_list);
|
|
delete vertex_list;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Write the levels of detail
|
|
//-------------------------------------------------------------
|
|
if (result == True)
|
|
{
|
|
NameList
|
|
*lod_namelist = gim_file->MakeEntryList("lods");
|
|
|
|
if (lod_namelist == NULL)
|
|
{
|
|
DEBUG_STREAM << "No 'lods' page in the .GIM file!" << std::endl;
|
|
result = False;
|
|
}
|
|
else
|
|
{
|
|
Check(lod_namelist);
|
|
Register_Object(lod_namelist);
|
|
//-------------------------------------------------------------
|
|
// Get the number of LOD's
|
|
//-------------------------------------------------------------
|
|
int
|
|
lod_count = lod_namelist->EntryCount();
|
|
Test_Tell("lod_count = " << lod_count << "\n");
|
|
if (lod_count <= 0)
|
|
{
|
|
DEBUG_STREAM <<
|
|
"The 'lod' page in the .GIM file has no entries!" << std::endl;
|
|
result = False;
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------------------------------------
|
|
// Write the number of LOD's to the stream
|
|
//-------------------------------------------------------------
|
|
MemoryStream_Write(mem_stream, &lod_count);
|
|
//-------------------------------------------------------------
|
|
// Write the LOD scales
|
|
//-------------------------------------------------------------
|
|
NameList::Entry
|
|
*scale_entry;
|
|
Scalar
|
|
scale;
|
|
|
|
const char
|
|
*text;
|
|
|
|
scale_entry = lod_namelist->GetFirstEntry();
|
|
for (i=0; i<lod_count; ++i)
|
|
{
|
|
Verify(scale_entry != NULL);
|
|
text = scale_entry->GetChar();
|
|
if (text == NULL)
|
|
{
|
|
DEBUG_STREAM << "Missing scale value!" << std::endl;
|
|
result = False;
|
|
break;
|
|
}
|
|
scale = (Scalar) atof(text);
|
|
|
|
Test_Tell(" " << scale << "\n");
|
|
MemoryStream_Write(mem_stream, &scale);
|
|
|
|
scale_entry = scale_entry->GetNextEntry();
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Write the LOD lists
|
|
//-------------------------------------------------------------
|
|
scale_entry = lod_namelist->GetFirstEntry();
|
|
for (i=0; i<lod_count; ++i)
|
|
{
|
|
Verify(scale_entry != NULL);
|
|
|
|
result = L4GaugeImageList::MemoryStreamWrite(
|
|
mem_stream,
|
|
gim_file,
|
|
scale_entry->GetName()
|
|
);
|
|
|
|
if (result == False)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scale_entry = scale_entry->GetNextEntry();
|
|
}
|
|
}
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Delete the LOD list
|
|
//-------------------------------------------------------------
|
|
Check(lod_namelist);
|
|
Unregister_Object(lod_namelist);
|
|
delete lod_namelist;
|
|
}
|
|
Check_Fpu();
|
|
return result;
|
|
}
|
|
|
|
|
|
void
|
|
L4GaugeImage::Draw(
|
|
Scalar LOD_value, // smaller = more detail (1.0 = 'normal')
|
|
Scalar scale_value, // metersPerPixel
|
|
GraphicsView *graphics_view,
|
|
int default_color,
|
|
AffineMatrix &localToView,
|
|
int boxed_color
|
|
)
|
|
{
|
|
Test_Tell(
|
|
"L4GaugeImage::Draw(" << scale_value <<
|
|
", " << graphics_view <<
|
|
", " << default_color <<
|
|
", " << localToView <<
|
|
", " << boxed_color <<
|
|
")\n"
|
|
);
|
|
Check(this);
|
|
Check(graphics_view);
|
|
// localToView allowed to be NULL
|
|
Check_Pointer(LODScales);
|
|
Check_Pointer(LODList);
|
|
|
|
# define VERTEX_ALLOTMENT 100 // HACK - I'm guessing this is big enough.
|
|
|
|
Verify(vertexCount <= VERTEX_ALLOTMENT);
|
|
|
|
static
|
|
Point3D
|
|
local_vertex_array[VERTEX_ALLOTMENT];
|
|
|
|
static
|
|
Logical
|
|
local_flag_array[VERTEX_ALLOTMENT];
|
|
|
|
int
|
|
lod_index;
|
|
|
|
if (localToView == NULL)
|
|
{
|
|
return;
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Find LOD index
|
|
//-------------------------------------------------------------
|
|
for(lod_index=0; lod_index<LODCount; ++lod_index)
|
|
{
|
|
if (LOD_value <= LODScales[lod_index])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (getenv("BT_MAP_LOG"))
|
|
{
|
|
static int s_gi = 0;
|
|
if ((s_gi++ % 30) == 0)
|
|
{
|
|
DEBUG_STREAM << "[gauima] lodVal=" << LOD_value
|
|
<< " lodCount=" << LODCount << " chosen=" << lod_index
|
|
<< " scales={";
|
|
for (int gi = 0; gi < LODCount && gi < 4; ++gi)
|
|
DEBUG_STREAM << LODScales[gi] << (gi + 1 < LODCount ? "," : "");
|
|
DEBUG_STREAM << "} verts=" << vertexCount << "\n" << std::flush;
|
|
}
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Continue if the index is within range
|
|
//-------------------------------------------------------------
|
|
if (lod_index < LODCount)
|
|
{
|
|
//-------------------------------------------------------------
|
|
// Clear transformed vertex flag array
|
|
//-------------------------------------------------------------
|
|
Logical
|
|
*flag_pointer = &local_flag_array[0];
|
|
int
|
|
i;
|
|
|
|
for(i=0; i<vertexCount; ++i)
|
|
{
|
|
*flag_pointer++ = False;
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Draw LODList item
|
|
//-------------------------------------------------------------
|
|
Check(LODList[lod_index]);
|
|
|
|
LODList[lod_index]->Draw(
|
|
graphics_view,
|
|
default_color,
|
|
localToView,
|
|
vertexArray,
|
|
local_vertex_array,
|
|
local_flag_array,
|
|
scale_value,
|
|
boxed_color
|
|
);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Test Instance
|
|
//
|
|
Logical
|
|
L4GaugeImage::TestInstance() const
|
|
{
|
|
return True;
|
|
}
|
|
//############################################################################
|
|
// L4GaugeImageList
|
|
//############################################################################
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Construction and Destruction
|
|
//
|
|
L4GaugeImageList::L4GaugeImageList(MemoryStream *mem_stream)
|
|
{
|
|
Test_Tell("L4GaugeImageList::L4GaugeImageList\n");
|
|
Check_Pointer(this);
|
|
Check(mem_stream);
|
|
|
|
int
|
|
i;
|
|
|
|
//-------------------------------------------------------------
|
|
// Read the number of primitives from the stream
|
|
//-------------------------------------------------------------
|
|
MemoryStream_Read(mem_stream, &primitiveCount);
|
|
Verify(primitiveCount > 0);
|
|
//-------------------------------------------------------------
|
|
// Allocate the primitive list
|
|
//-------------------------------------------------------------
|
|
primitiveList = new L4GaugeImagePrimitive*[primitiveCount];
|
|
Check_Pointer(primitiveList);
|
|
Register_Pointer(primitiveList);
|
|
//-------------------------------------------------------------
|
|
// Read the primitives
|
|
//-------------------------------------------------------------
|
|
for(i=0; i<primitiveCount; ++i)
|
|
{
|
|
primitiveList[i] = new L4GaugeImagePrimitive(mem_stream);
|
|
Check(primitiveList[i]);
|
|
Register_Object(primitiveList[i]);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
L4GaugeImageList::~L4GaugeImageList()
|
|
{
|
|
Test_Tell("L4GaugeImageList::~L4GaugeImageList\n");
|
|
Check(this);
|
|
Check_Pointer(primitiveList);
|
|
|
|
int
|
|
i;
|
|
|
|
for(i=0; i<primitiveCount; ++i)
|
|
{
|
|
Check(primitiveList[i]);
|
|
Unregister_Object(primitiveList[i]);
|
|
delete primitiveList[i];
|
|
}
|
|
Unregister_Pointer(primitiveList);
|
|
delete[] primitiveList;
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
L4GaugeImageList::MemoryStreamWrite(
|
|
MemoryStream *mem_stream,
|
|
NotationFile *gim_file,
|
|
const char *page_name
|
|
)
|
|
{
|
|
Test_Tell(" L4GaugeImageList::MemoryStreamWrite(" << mem_stream <<
|
|
", " << gim_file <<
|
|
", " << page_name <<
|
|
")\n"
|
|
);
|
|
Check(mem_stream);
|
|
Check(gim_file);
|
|
|
|
int
|
|
i;
|
|
Logical
|
|
result = True;
|
|
NameList
|
|
*primitive_list = gim_file->MakeEntryList(page_name);
|
|
|
|
if (primitive_list == NULL)
|
|
{
|
|
DEBUG_STREAM << "Can't find the '" << page_name << "' page in the .GIM file!"
|
|
<< std::endl;
|
|
result = False;
|
|
}
|
|
else
|
|
{
|
|
Check(primitive_list);
|
|
Register_Object(primitive_list);
|
|
//-------------------------------------------------------------
|
|
// Get the number of primitives
|
|
//-------------------------------------------------------------
|
|
int
|
|
primitive_count = primitive_list->EntryCount();
|
|
|
|
Test_Tell(" primitive_count = " << primitive_count << "\n");
|
|
if (primitive_count <= 0)
|
|
{
|
|
DEBUG_STREAM << "The '"<<page_name<<"' page in the .GIM file has no entries!"
|
|
<< std::endl;
|
|
result = False;
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------------------------------------
|
|
// Write the number of primitives to the stream
|
|
//-------------------------------------------------------------
|
|
MemoryStream_Write(mem_stream, &primitive_count);
|
|
//-------------------------------------------------------------
|
|
// Write the primitives
|
|
//-------------------------------------------------------------
|
|
NameList::Entry
|
|
*primitive_entry = primitive_list->GetFirstEntry();
|
|
for (i=0; i<primitive_count; ++i)
|
|
{
|
|
Verify(primitive_entry != NULL);
|
|
|
|
result = L4GaugeImagePrimitive::MemoryStreamWrite(
|
|
mem_stream,
|
|
primitive_entry->GetName(),
|
|
primitive_entry->GetChar()
|
|
);
|
|
|
|
if (result == False)
|
|
{
|
|
break;
|
|
}
|
|
|
|
primitive_entry = primitive_entry->GetNextEntry();
|
|
}
|
|
}
|
|
//-------------------------------------------------------------
|
|
// Delete the primitive list
|
|
//-------------------------------------------------------------
|
|
Check(primitive_list);
|
|
Unregister_Object(primitive_list);
|
|
delete primitive_list;
|
|
}
|
|
Check_Fpu();
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Test Support
|
|
//
|
|
Logical
|
|
L4GaugeImageList::TestInstance() const
|
|
{
|
|
return True;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
L4GaugeImageList::Draw(
|
|
GraphicsView *graphics_view,
|
|
int default_color,
|
|
AffineMatrix &localToView,
|
|
Point3D *untransformed_vertex_array,
|
|
Point3D *transformed_vertex_array,
|
|
Logical *transformed_flag_array,
|
|
Scalar scale_factor,
|
|
int boxed_color
|
|
)
|
|
{
|
|
Test_Tell(
|
|
"L4GaugeImageList::Draw(" << graphics_view <<
|
|
", " << default_color <<
|
|
", " << localToView <<
|
|
", " << untransformed_vertex_array <<
|
|
", " << transformed_vertex_array <<
|
|
", " << transformed_flag_array <<
|
|
", " << scale_factor <<
|
|
", " << boxed_color <<
|
|
")\n"
|
|
);
|
|
Check(this);
|
|
Check(graphics_view);
|
|
Check(&localToView);
|
|
Check_Pointer(untransformed_vertex_array);
|
|
Check_Pointer(transformed_vertex_array);
|
|
Check_Pointer(transformed_flag_array);
|
|
|
|
Check_Pointer(primitiveList);
|
|
|
|
int
|
|
i;
|
|
L4GaugeImagePrimitive
|
|
**array_pointer = primitiveList;
|
|
|
|
if (boxed_color != 0)
|
|
{
|
|
//--------------------------------------------------------
|
|
// Initialize bounding box
|
|
//--------------------------------------------------------
|
|
Rectangle2D
|
|
bounds(9999,9999,-9999,-9999);
|
|
//--------------------------------------------------------
|
|
// Draw primitives, collect bounding data
|
|
//--------------------------------------------------------
|
|
for(i=0; i<primitiveCount; ++i)
|
|
{
|
|
Test_Tell("List #" << i << " of " << primitiveCount << "\n");
|
|
Check(*array_pointer);
|
|
(*array_pointer++)->Draw(
|
|
graphics_view,
|
|
default_color,
|
|
localToView,
|
|
untransformed_vertex_array,
|
|
transformed_vertex_array,
|
|
transformed_flag_array,
|
|
scale_factor,
|
|
&bounds
|
|
);
|
|
}
|
|
//--------------------------------------------------------
|
|
// Draw the bounding box
|
|
//--------------------------------------------------------
|
|
graphics_view->SetColor(boxed_color);
|
|
|
|
graphics_view->MoveToAbsolute(
|
|
bounds.bottomLeft.x-4,
|
|
bounds.bottomLeft.y-4
|
|
);
|
|
graphics_view->DrawRectangleToAbsolute(
|
|
bounds.topRight.x+4,
|
|
bounds.topRight.y+4
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//--------------------------------------------------------
|
|
// Just draw it
|
|
//--------------------------------------------------------
|
|
for(i=0; i<primitiveCount; ++i)
|
|
{
|
|
Test_Tell("List #" << i << " of " << primitiveCount << "\n");
|
|
Check(*array_pointer);
|
|
(*array_pointer++)->Draw(
|
|
graphics_view,
|
|
default_color,
|
|
localToView,
|
|
untransformed_vertex_array,
|
|
transformed_vertex_array,
|
|
transformed_flag_array,
|
|
scale_factor,
|
|
NULL
|
|
);
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//############################################################################
|
|
// L4GaugeImagePrimitive
|
|
//############################################################################
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Construction and Destruction
|
|
//
|
|
L4GaugeImagePrimitive::L4GaugeImagePrimitive(MemoryStream *mem_stream)
|
|
{
|
|
Test_Tell("L4GaugeImagePrimitive::L4GaugeImagePrimitive\n");
|
|
Check_Pointer(this);
|
|
Check(mem_stream);
|
|
|
|
int
|
|
i,
|
|
n;
|
|
//--------------------------------------------------------------
|
|
// Read the primitive type ID, use the input stream accordingly
|
|
//--------------------------------------------------------------
|
|
MemoryStream_Read(mem_stream, &n);
|
|
type = (primitiveType) n;
|
|
|
|
switch(type)
|
|
{
|
|
case primitiveVector:
|
|
Test_Tell(" primitiveVector\n");
|
|
//--------------------------------------------------------
|
|
// Read the attribute and color
|
|
//--------------------------------------------------------
|
|
MemoryStream_Read(mem_stream, &color);
|
|
MemoryStream_Read(mem_stream, &attributes);
|
|
Test_Tell(" color = " << color << "\n");
|
|
Test_Tell(" attributes = " << std::hex << attributes << std::dec << "\n");
|
|
//--------------------------------------------------------
|
|
// Read the vertex index count
|
|
//--------------------------------------------------------
|
|
MemoryStream_Read(mem_stream, &data.vector.indexCount);
|
|
Test_Tell(" indexCount = " << data.vector.indexCount << "\n");
|
|
Verify(data.vector.indexCount > 0);
|
|
//--------------------------------------------------------
|
|
// Allocate the index table
|
|
//--------------------------------------------------------
|
|
data.vector.indexList = new int[data.vector.indexCount];
|
|
Check_Pointer(data.vector.indexList);
|
|
Register_Pointer(data.vector.indexList);
|
|
//--------------------------------------------------------
|
|
// Read the indices
|
|
//--------------------------------------------------------
|
|
for(i=0; i<data.vector.indexCount; ++i)
|
|
{
|
|
MemoryStream_Read(mem_stream, &data.vector.indexList[i]);
|
|
Test_Tell(" " << data.vector.indexList[i] << "\n");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Warn(
|
|
"L4GaugeImagePrimitive::L4GaugeImagePrimitive: Evil type_id!");
|
|
break;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
L4GaugeImagePrimitive::~L4GaugeImagePrimitive()
|
|
{
|
|
Test_Tell("L4GaugeImagePrimitive destructor\n");
|
|
Check(this);
|
|
|
|
switch(type)
|
|
{
|
|
case primitiveVector:
|
|
Check_Pointer(data.vector.indexList);
|
|
Unregister_Pointer(data.vector.indexList);
|
|
delete[] data.vector.indexList;
|
|
break;
|
|
|
|
default:
|
|
Warn("L4GaugeImagePrimitive::~L4GaugeImagePrimitive: Evil type_id!");
|
|
break;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
Logical
|
|
L4GaugeImagePrimitive::MemoryStreamWrite(
|
|
MemoryStream *mem_stream,
|
|
const char *type_name,
|
|
const char *data
|
|
)
|
|
{
|
|
Test_Tell("L4GaugeImagePrimitive::MemoryStreamWrite(" <<mem_stream<<
|
|
", " << type_name <<
|
|
", " << data <<
|
|
")\n"
|
|
);
|
|
Check(mem_stream);
|
|
Check_Pointer(type_name);
|
|
Check_Pointer(data);
|
|
|
|
# define MAX_INDICES 64
|
|
|
|
int
|
|
i,
|
|
type_number,
|
|
attribute_value = 0,
|
|
color_value = 0,
|
|
index[MAX_INDICES],
|
|
index_count = 0;
|
|
Logical
|
|
result = True;
|
|
|
|
//--------------------------------------------------------
|
|
// LINELIST primitive
|
|
//--------------------------------------------------------
|
|
if (stricmp(type_name, "linelist") == 0)
|
|
{
|
|
Test_Tell(" LINELIST\n");
|
|
//--------------------------------------------------------
|
|
// Write the primitive type ID
|
|
//--------------------------------------------------------
|
|
type_number = L4GaugeImagePrimitive::primitiveVector;
|
|
MemoryStream_Write(mem_stream, &type_number);
|
|
//--------------------------------------------------------
|
|
// Parse vertices (which start with 'v')
|
|
// and parse attributes (which start with 'a')
|
|
//--------------------------------------------------------
|
|
const char
|
|
*scan = data;
|
|
|
|
# if (DEBUG_LEVEL > 0)
|
|
int
|
|
check_length = strlen(data)+1;
|
|
# endif
|
|
|
|
while(*scan != '\0')
|
|
{
|
|
Verify((scan-data) < check_length);
|
|
//--------------------------------------------------------
|
|
// Skip white space
|
|
//--------------------------------------------------------
|
|
while (isspace(*scan))
|
|
{
|
|
++scan;
|
|
}
|
|
//--------------------------------------------------------
|
|
// Parse non-space string
|
|
//--------------------------------------------------------
|
|
if (*scan == 'v')
|
|
{
|
|
int
|
|
n;
|
|
//--------------------------------------------------------
|
|
// Convert to value, save in array
|
|
//--------------------------------------------------------
|
|
++scan; // ignore 'v'
|
|
for(n=0; isdigit(*scan); ++scan)
|
|
{
|
|
n = (n*10) + (*scan - '0');
|
|
}
|
|
Test_Tell(" " << n << "\n");
|
|
|
|
if (index_count < MAX_INDICES)
|
|
{
|
|
index[index_count++] = n;
|
|
}
|
|
}
|
|
else if (*scan == 'a')
|
|
{
|
|
char
|
|
buffer[64],
|
|
*dest;
|
|
//--------------------------------------------------------
|
|
// Collect the name
|
|
//--------------------------------------------------------
|
|
for(
|
|
i=0, dest=buffer;
|
|
i<(sizeof(buffer)-1);
|
|
++i,++scan,++dest
|
|
)
|
|
{
|
|
if (isspace(*scan))
|
|
{
|
|
break;
|
|
}
|
|
if (*scan == '\0')
|
|
{
|
|
break;
|
|
}
|
|
*dest = *scan;
|
|
}
|
|
*dest = '\0';
|
|
//--------------------------------------------------------
|
|
// Search for the name
|
|
//--------------------------------------------------------
|
|
if (
|
|
GroupAttribute::Search(
|
|
buffer,
|
|
&color_value,
|
|
&attribute_value
|
|
) == False
|
|
)
|
|
{
|
|
DEBUG_STREAM << "Couldn't find attribute group '" <<
|
|
buffer << "'!" << std::endl;
|
|
}
|
|
}
|
|
}
|
|
//--------------------------------------------------------
|
|
// Write the attributes
|
|
//--------------------------------------------------------
|
|
Test_Tell(" color=" << color_value << "\n");
|
|
MemoryStream_Write(mem_stream, &color_value);
|
|
Test_Tell(" attribute=" << attribute_value << "\n");
|
|
MemoryStream_Write(mem_stream, &attribute_value);
|
|
//--------------------------------------------------------
|
|
// Write the vertex index count
|
|
//--------------------------------------------------------
|
|
if (index_count == 0)
|
|
{
|
|
DEBUG_STREAM << "No vertex indices in primitive!" << std::endl;
|
|
result = False;
|
|
}
|
|
else
|
|
{
|
|
Test_Tell(" index_count=" << index_count << "\n");
|
|
MemoryStream_Write(mem_stream, &index_count);
|
|
//--------------------------------------------------------
|
|
// Write the indices
|
|
//--------------------------------------------------------
|
|
for(i=0; i < index_count; ++i)
|
|
{
|
|
MemoryStream_Write(mem_stream, &index[i]);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DEBUG_STREAM << "Unsupported primitive ("<< type_name << ") in .GIM file!"
|
|
<< std::endl;
|
|
result = False;
|
|
}
|
|
Check_Fpu();
|
|
return result;
|
|
}
|
|
|
|
|
|
//============================================================================
|
|
// TestInstance
|
|
//============================================================================
|
|
Logical
|
|
L4GaugeImagePrimitive::TestInstance() const
|
|
{
|
|
return True;
|
|
}
|
|
//============================================================================
|
|
// Draw
|
|
//============================================================================
|
|
void
|
|
L4GaugeImagePrimitive::Draw(
|
|
GraphicsView *graphics_view,
|
|
int default_color,
|
|
AffineMatrix &localToView,
|
|
Point3D *untransformed_vertex_array,
|
|
Point3D *transformed_vertex_array,
|
|
Logical *transformed_flag_array,
|
|
Scalar scale_factor,
|
|
Rectangle2D *bounds
|
|
)
|
|
{
|
|
Test_Tell(
|
|
"L4GaugeImagePrimitive::Draw(" << graphics_view <<
|
|
", " << default_color <<
|
|
", " << localToView <<
|
|
", " << untransformed_vertex_array <<
|
|
", " << transformed_vertex_array <<
|
|
", " << transformed_flag_array <<
|
|
", " << scale_factor <<
|
|
", " << bounds <<
|
|
")\n"
|
|
);
|
|
|
|
Check(this);
|
|
Check(graphics_view);
|
|
Check(&localToView);
|
|
Check_Pointer(untransformed_vertex_array);
|
|
Check_Pointer(transformed_vertex_array);
|
|
Check_Pointer(transformed_flag_array);
|
|
|
|
//-----------------------------------------------
|
|
// Draw primitive
|
|
//-----------------------------------------------
|
|
switch(type)
|
|
{
|
|
case primitiveVector:
|
|
if (data.vector.indexCount > 1)
|
|
{
|
|
//-----------------------------------------------
|
|
// Set color
|
|
//-----------------------------------------------
|
|
if (color != 0)
|
|
{
|
|
default_color = color;
|
|
}
|
|
graphics_view->SetColor(default_color);
|
|
|
|
int
|
|
i,
|
|
*index_pointer(data.vector.indexList),
|
|
index;
|
|
Point3D
|
|
*dest;
|
|
//-----------------------------------------------
|
|
// Move to starting point
|
|
//-----------------------------------------------
|
|
index = *index_pointer++;
|
|
|
|
dest = &transformed_vertex_array[index];
|
|
|
|
TransformVertex(
|
|
localToView,
|
|
untransformed_vertex_array[index],
|
|
dest,
|
|
transformed_flag_array[index],
|
|
scale_factor,
|
|
bounds
|
|
);
|
|
|
|
|
|
Test_Tell("Start at " << index << "=" << *dest << "\n");
|
|
graphics_view->MoveToAbsolute((int)dest->x,(int)dest->z);
|
|
//-----------------------------------------------
|
|
// Draw subsequent lines
|
|
//-----------------------------------------------
|
|
for(i=data.vector.indexCount-1; i>0; --i)
|
|
{
|
|
index = *index_pointer++;
|
|
|
|
dest = &transformed_vertex_array[index];
|
|
|
|
TransformVertex(
|
|
localToView,
|
|
untransformed_vertex_array[index],
|
|
dest,
|
|
transformed_flag_array[index],
|
|
scale_factor,
|
|
bounds
|
|
);
|
|
|
|
Test_Tell("Draw to " << index << "=" << *dest << "\n");
|
|
graphics_view->DrawLineToAbsolute((int)(dest->x),(int)(dest->z));
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
Warn("L4GaugeImagePrimitive::Draw: Evil type_id!");
|
|
break;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
L4GaugeImagePrimitive::TransformVertex(
|
|
AffineMatrix &local_to_view,
|
|
Point3D &untransformed_vertex,
|
|
Point3D *transformed_vertex,
|
|
Logical &transformed_flag,
|
|
Scalar scale_factor,
|
|
Rectangle2D *bounds
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(transformed_vertex);
|
|
|
|
//-----------------------------------------
|
|
// Transform only if not already done
|
|
//-----------------------------------------
|
|
if (! transformed_flag)
|
|
{
|
|
if (attributes & attributeUnscaled)
|
|
{
|
|
//-----------------------------------------
|
|
// Unscaled: pre-multiply by scaling factor
|
|
//-----------------------------------------
|
|
Point3D
|
|
temp;
|
|
|
|
temp = untransformed_vertex;
|
|
temp *= scale_factor;
|
|
Check_Fpu();
|
|
|
|
transformed_vertex->Multiply(
|
|
temp,
|
|
local_to_view
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
else
|
|
{
|
|
//-----------------------------------------
|
|
// Normally scaled: transform the vertex
|
|
//-----------------------------------------
|
|
transformed_vertex->Multiply(
|
|
untransformed_vertex,
|
|
local_to_view
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Round, and fix 'y' sign
|
|
//-----------------------------------------
|
|
transformed_vertex->x += .5;
|
|
transformed_vertex->z = -transformed_vertex->z + .5;
|
|
|
|
//-----------------------------------------------
|
|
// Set the 'transformed' flag
|
|
//-----------------------------------------------
|
|
transformed_flag = True;
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
// Accumulate bounds
|
|
//-----------------------------------------------
|
|
if (bounds != NULL)
|
|
{
|
|
if (transformed_vertex->x < bounds->bottomLeft.x)
|
|
{
|
|
bounds->bottomLeft.x = transformed_vertex->x;
|
|
}
|
|
if (transformed_vertex->x > bounds->topRight.x)
|
|
{
|
|
bounds->topRight.x = transformed_vertex->x;
|
|
}
|
|
|
|
if (transformed_vertex->z < bounds->bottomLeft.y)
|
|
{
|
|
bounds->bottomLeft.y = transformed_vertex->z;
|
|
}
|
|
if (transformed_vertex->z > bounds->topRight.y)
|
|
{
|
|
bounds->topRight.y = transformed_vertex->z;
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|