diff --git a/game/reconstructed/btl4gaug.cpp b/game/reconstructed/btl4gaug.cpp index 18384eb..3dca203 100644 --- a/game/reconstructed/btl4gaug.cpp +++ b/game/reconstructed/btl4gaug.cpp @@ -1276,6 +1276,230 @@ void // before chaining to OneOfSeveral::Execute @004c4f28. dtor @004c5500. // +// +// @004c4d88 -- OneOfSeveral base ctor (vtable PTR_FUN_00518bf0). Intern the +// image name, hold a ref, read the source strip size from the appropriate cache +// (PixMap8Cache if !fromImageStrip, else BitMapCache), divide by columns/rows to +// get the per-frame size, and set the graphics-port origin. +// +OneOfSeveral::OneOfSeveral( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer_in, + int graphics_port_number, + int x, + int y, + Logical from_image_strip, + const char *image_name, + int background_color, + int foreground_color, + int columns_in, + int rows_in, + const char *identification_string +): + GraphicGauge(rate, mode_mask, renderer_in, 0, // FUN_00444818 (owner_ID 0) + graphics_port_number, identification_string) +{ + backgroundColor = background_color; // @0x98 + foregroundColor = foreground_color; // @0x9C + columns = columns_in; // @0xA0 + fromImageStrip = from_image_strip; // @0x90 + + imageName = new char[strlen(image_name) + 1]; // @0x94 FUN_004700ac + strcpy(imageName, image_name); + + L4Warehouse *warehouse = (L4Warehouse *)renderer_in->warehousePointer; + if (fromImageStrip == 0) // PixMap8 strip + { + PixelMap8 *pm = warehouse->pixelMap8Bin.Get(imageName); // FUN_00442d2b (held) + frameWidth = (pm != NULL ? pm->Data.Size.x : 0) / columns_in; // @0xA4 + frameHeight = (pm != NULL ? pm->Data.Size.y : 0) / rows_in; // @0xA8 + } + else // BitMap strip + { + BitMap *bm = warehouse->bitMapBin.Get(imageName); // FUN_00442aec (held) + frameWidth = (bm != NULL ? bm->Data.Size.x : 0) / columns_in; + frameHeight = (bm != NULL ? bm->Data.Size.y : 0) / rows_in; + } + + localView.SetOrigin(x, y); // this+0x48 vtbl+0x10 +} + +// +// @004c4e7c -- dtor. Release the image from the matching cache (keyed on +// imageName, before the free); base chain implicit. +// +OneOfSeveral::~OneOfSeveral() +{ + L4Warehouse *warehouse = (L4Warehouse *)renderer->warehousePointer; + if (fromImageStrip == 0) + warehouse->pixelMap8Bin.Release(imageName); // FUN_00442e51 + else + warehouse->bitMapBin.Release(imageName); // FUN_00442c12 + delete[] imageName; // FUN_004022e8 + imageName = NULL; +} + +Logical + OneOfSeveral::TestInstance() const +{ + return GraphicGauge::TestInstance(); +} + +// +// @004c4f14 -- BecameActive: previousSelected = -1 (force the first redraw). +// +void + OneOfSeveral::BecameActive() +{ + previousSelected = -1; // @0xB0 +} + +// +// @004c4f28 -- Execute. On a change of `selected`, compute the frame's (col,row) +// within the strip and blit that sub-rectangle: DrawPixelMap8 (opaque) for a +// pixmap strip, or SetColor(bg)+DrawBitMapOpaque(fg,..) for a bitmap strip. +// +void + OneOfSeveral::Execute() +{ + if (selected == previousSelected) + return; + previousSelected = selected; + + int col, row; + if (columns == 1) + { + col = 0; + row = selected; + } + else + { + col = selected % columns; + row = selected / columns; + } + + int sx0 = col * frameWidth; + int sx1 = frameWidth + sx0 - 1; + int sy0 = row * frameHeight; + int sy1 = frameHeight + sy0 - 1; + + L4Warehouse *warehouse = (L4Warehouse *)renderer->warehousePointer; + if (fromImageStrip == 0) // PixMap8: own palette, no SetColor + { + PixelMap8 *pm = warehouse->pixelMap8Bin.Get(imageName); // FUN_00442d2b + localView.DrawPixelMap8(True, 0, pm, sx0, sy0, sx1, sy1); // vtbl+0x5C (opaque) + warehouse->pixelMap8Bin.Release(imageName); // FUN_00442e51 + } + else // BitMap strip + { + localView.SetColor(backgroundColor); // vtbl+0x18 + BitMap *bm = warehouse->bitMapBin.Get(imageName); // FUN_00442aec + localView.DrawBitMapOpaque(foregroundColor, 0, bm, sx0, sy0, sx1, sy1); // vtbl+0x58 + warehouse->bitMapBin.Release(imageName); // FUN_00442c12 + } +} + +//########################################################################### +// OneOfSeveralPixInt @004c5204 Make / @004c52d8 ctor (vtable PTR_FUN_00518b68) +// +// The cockpit button-state lamps (config "oneOfSeveralPixInt"): a PixMap8 strip +// of N frames selected by an integer game attribute (DuckState / Searchlight/ +// LightOn / ControlsMapper/DisplayMode). Drawing is inherited from OneOfSeveral; +// this subclass just forces the PixMap path and wires the int connection. +//########################################################################### + +MethodDescription + OneOfSeveralPixInt::methodDescription = + { + "oneOfSeveralPixInt", + OneOfSeveralPixInt::Make, + { + // + // CFG shape (L4GAUGE.CFG:5001): + // oneOfSeveralPixInt( rate, mode, strip.pcc, columns, rows, stateAttr ) + // e.g. oneOfSeveralPixInt(E,ModeAlwaysActive,bduck.pcc,3,1,DuckState); + // + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeString, NULL }, // pixmap strip name + { ParameterDescription::typeInteger, NULL }, // columns (frame count) + { ParameterDescription::typeInteger, NULL }, // rows + { ParameterDescription::typeAttribute, NULL }, // integer state selector + PARAMETER_DESCRIPTION_END + } + }; + +// +// @004c5204 -- Make. Allocate + construct, then verify the pixmap strip exists. +// +Logical + OneOfSeveralPixInt::Make( + int display_port_index, + Vector2DOf position, + Entity * /*entity -- unused*/, + GaugeRenderer *gauge_renderer + ) +{ + ParameterDescription *p = methodDescription.parameterList; + + OneOfSeveralPixInt *gauge = (OneOfSeveralPixInt *)operator new(0xb4); // FUN_00402298(0xb4) + if (gauge != NULL) + { + new (gauge) OneOfSeveralPixInt( // FUN_004c52d8 + p[0].data.rate, p[1].data.modeMask, + (L4GaugeRenderer *)gauge_renderer, + display_port_index, // graphics_port_number + position.x, position.y, + p[2].data.string, // pixmap strip + p[3].data.integer, p[4].data.integer, // columns, rows + (int *)p[5].data.attributePointer, // integer state source + "OneOfSeveralPixInt"); + } + + L4Warehouse *warehouse = (L4Warehouse *)gauge_renderer->warehousePointer; + if (warehouse->pixelMap8Bin.Get(p[2].data.string) == NULL) // FUN_00442d2b + { + DebugStream << "OneOfSeveralPixInt: Missing image '" << p[2].data.string << "'\n"; + return False; + } + warehouse->pixelMap8Bin.Release(p[2].data.string); // FUN_00442e51 + return True; +} + +// +// @004c52d8 -- ctor. OneOfSeveral base with fromImageStrip=0 (PixMap8) and +// bg/fg=0 (the pixmap carries its own palette); one int connection -> selected. +// +OneOfSeveralPixInt::OneOfSeveralPixInt( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer_in, + int graphics_port_number, + int x, + int y, + const char *image, + int columns_in, + int rows_in, + int *value_pointer, + const char *identification_string +): + OneOfSeveral(rate, mode_mask, renderer_in, graphics_port_number, x, y, + False, // fromImageStrip = 0 (PixMap) + image, 0, 0, // bg, fg = 0 + columns_in, rows_in, identification_string) +{ + selected = 0; // @0xAC this[0x2B] + AddConnection(new GaugeConnectionDirectOf(0, &selected, value_pointer)); // FUN_004749de +} + +// +// @004c5364 -- deleting-dtor thunk. All teardown is ~OneOfSeveral; implicit. +// +OneOfSeveralPixInt::~OneOfSeveralPixInt() +{ +} + //########################################################################### //########################################################################### diff --git a/game/reconstructed/btl4gaug.hpp b/game/reconstructed/btl4gaug.hpp index b9a6809..db87d65 100644 --- a/game/reconstructed/btl4gaug.hpp +++ b/game/reconstructed/btl4gaug.hpp @@ -358,6 +358,7 @@ Logical fromImageStrip; // @0x90 this[0x24] char *imageName; // @0x94 this[0x25] int backgroundColor; // @0x98 this[0x26] + int foregroundColor; // @0x9C this[0x27] (DrawBitMapOpaque bg arg) int columns; // @0xA0 this[0x28] int selected; // @0xAC this[0x2B] (connection) int previousSelected; // @0xB0 this[0x2C] @@ -387,10 +388,14 @@ public OneOfSeveral { public: - static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); - OneOfSeveralPixInt(GaugeRate, ModeMask, L4GaugeRenderer *, int, + // Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "oneOfSeveralPixInt". + static MethodDescription methodDescription; + + static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); // @004c5204 + OneOfSeveralPixInt( // @004c52d8 + GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number, int x, int y, const char *image, int columns, int rows, - int *value_pointer, const char *); + int *value_pointer, const char *identification_string); ~OneOfSeveralPixInt(); // @004c5364 }; diff --git a/game/reconstructed/btl4grnd.cpp b/game/reconstructed/btl4grnd.cpp index 19cb447..6acc6f3 100644 --- a/game/reconstructed/btl4grnd.cpp +++ b/game/reconstructed/btl4grnd.cpp @@ -136,6 +136,7 @@ MethodDescription &ColorMapperCritical::methodDescription, // "cmCrit" -- subsystem-critical-state tint &VertTwoPartBar::methodDescription, // "vertBar" -- vertical fill bar (coolant/heat) &SegmentArcRatio::methodDescription, // "segmentArcRatio" -- segmented arc dial (speed) + &OneOfSeveralPixInt::methodDescription, // "oneOfSeveralPixInt" -- button-state lamp (duck/light/mode) &BTL4ChainToPrevious };