//===========================================================================//
// File:	btl4gaug.hpp                                                        //
// Project: BattleTech          Brick: Gauge Renderer Manager                 //
// Contents: The cockpit instrument gauge library -- the family of small      //
//           "widget" gauges that the BattleTech HUD is assembled from:        //
//             * ColorMapper*     -- palette-animating tint gauges driven by   //
//                                    subsystem state (heat / armour / crit)    //
//             * Horiz/VertTwoPartBar, VertNormalSlider                         //
//                                 -- two-colour fill bars (throttle / damage)  //
//             * OneOfSeveral*     -- multi-frame bitmap selectors (state lamp) //
//             * HeadingPointer     -- rotating numeric heading readout         //
//             * SegmentArc270/Ratio-- arc / dial style gauges                  //
//             * BitMap wipe gauges -- bitmap "fuel / leak" wipe indicators     //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 02/22/96  CPB  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved //
//                      PROPRIETARY AND CONFIDENTIAL                         //
//===========================================================================//
//
// RECONSTRUCTED.  No BTL4GAUG.HPP survived (the BT_L4 source tree retains only
// BTL4RDR.HPP and BTL4GALM.HPP).  This declaration is recovered from the
// shipped binary (BTL4OPT.EXE); the Ghidra pseudo-C is in
//   recovered/all/part_013.c  (@004c2f94..@004c5e84)
//   recovered/all/part_014.c  (@004c5e84..@004c6394)
// The module is the .obj that links immediately after btl4rdr.obj and before
// btl4gau2.obj (see BTL4.MAK), so it owns the contiguous code run
//   [ @004c2f94 .. @004c6771 ]   (btl4gau2.cpp begins at @004c6798).
//
// The sole address with a surviving embedded assert path -- the anchor --
// is ColorMapperHeat's constructor:
//   @004c3f6c  "d:\tesla\bt\bt_l4\BTL4GAUG.CPP", line 0x68a
//
// Class names are recovered verbatim from the CODE name-string pool
// (section_dump.txt @0x518480..0x51859e):
//   ColorMapper ColorMapperArmor ColorMapperMultiArmor ColorMapperCritical
//   ColorMapperHeat HorizTwoPartBar VertTwoPartBar VertNormalSlider
//   OneOfSeveral OneOfSeveralInt OneOfSeveralPixInt OneOfSeveralStates
//   HeadingPointer  BitMapInverseWipe BitMapInverseWipeScalar
//   SegmentArc270 SegmentArcRatio
//
// Field offsets in comments are the byte offsets observed in the decompiled
// object (e.g. "@0x90" == this[0x24]).  The two base gauges are the MUNGA L4
// gauge primitives:
//   Gauge          ctor FUN_00444308  dtor FUN_00444360  -- non-graphic;
//                  used by the ColorMapper family (they tint a palette, they
//                  do not own a GraphicsView).
//   GraphicGauge   ctor FUN_00444818  dtor FUN_00444870  -- owns a GraphicsView
//                  embedded at +0x48 (this[0x12]); used by every drawing gauge.
//                  (Same base as MapDisplay in btl4rdr.cpp.)
//
// Names flagged "(name unconfirmed)" are best-effort: the class exists in the
// binary but its identification string could not be tied to it unambiguously.
//

#if !defined(BTL4GAUG_HPP)
#	define BTL4GAUG_HPP

#	if !defined(SLOT_HPP)
#		include <slot.hpp>
#	endif

#	if !defined(L4GREND_HPP)
#		include <l4grend.hpp>
#	endif

#	if !defined(L4GAUGE_HPP)
#		include <l4gauge.hpp>
#	endif

#	if !defined(HEAT_HPP)
#		include <heat.hpp>
#	endif

	// NOTE (reconstruction): the original BTL4GAUG.HPP also pulled in
	// <powersub.hpp>, but nothing in this gauge-widget family actually depends
	// on a power-subsystem type (the gauges connect to subsystems by name /
	// attribute index, not by class).  The include is dropped to keep this TU
	// independent of the (separately-reconstructed) powersub header.

	//#######################################################################
	//#######################################################################
	//   ColorMapper family
	//
	//   A ColorMapper is NOT a drawing gauge: every frame it reads a single
	//   subsystem-derived value (0..255), looks the corresponding R/G/B
	//   triple out of a named palette resource, and -- if it has changed --
	//   writes it straight into one hardware palette slot (colorIndex).  The
	//   cockpit art that uses that slot therefore changes colour live.  With
	//   two palette names it alternates between them every frame to flash.
	//
	//   The driving value arrives through a small file-private GaugeConnection
	//   (see btl4gaug.cpp) wired to currentColorIndex.  ColorMapperHeat's
	//   connection reads HeatableSubsystem::currentTemperature (@0x114).
	//#######################################################################
	//#######################################################################

	class ColorMapper :
		public Gauge
	{
	public:
		ColorMapper(
			GaugeRate		rate,
			ModeMask		mode_mask,
			L4GaugeRenderer	*renderer,
			int				graphics_port_number,
			int				color_index,
			const char		*palette_name_a,
			const char		*palette_name_b,
			const char		*identification_string
		);
		~ColorMapper();

		Logical	TestInstance() const;		// inherits Gauge
		void	BecameActive();
		void	Execute();					// @004c3980 -- palette push

	protected:
		char	*paletteName[2];			// @0x48,@0x4C  this[0x12],[0x13]
		Logical	twoColorMode;				// @0x50  this[0x14]  (names differ)
		int		currentColorIndex;			// @0x54  this[0x15]  (connection dst)
		int		previousColorIndex;			// @0x58  this[0x16]
		int		colorSlot;					// @0x5C  this[0x17]  hw palette slot
		int		paletteToggle;				// @0x60  this[0x18]  0/1 flash phase
		unsigned char
				previousRed,				// @0x64  this[0x19].b0
				previousGreen,				// @0x65
				previousBlue;				// @0x66
		GraphicsPort
				*graphicsPort;				// @0x68  this[0x1A]  (renderer port)
	};

	//
	// ColorMapperArmor -- tints by the damage ratio of one named damage zone.
	// Connection: @004c33a4 (reads Subsystem damage-zone array @0x120[index]).
	//
	class ColorMapperArmor :
		public ColorMapper
	{
	public:
		// Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "cmArmor".
		static MethodDescription methodDescription;

		static Logical Make(						// @004c3aa4
			int display_port_index, Vector2DOf<int> position,
			Entity *entity, GaugeRenderer *gauge_renderer);

		ColorMapperArmor(							// @004c3b98
			GaugeRate rate, ModeMask mode_mask, L4GaugeRenderer *renderer,
			int graphics_port_number, int color_index,
			Entity *entity, const char *palette_a, const char *palette_b,
			int damage_zone_index, const char *identification_string);
		~ColorMapperArmor();
	protected:
		int	unused;								// @0x6C  this[0x1B]  (=0)
	};

	//
	// ColorMapperMultiArmor -- worst-of-N damage zones.
	// Connection: @004c346c (copies 8 zone indices, takes the max ratio).
	//
	class ColorMapperMultiArmor :
		public ColorMapper
	{
	public:
		// Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "colorMapperMultiArmor".
		static MethodDescription methodDescription;

		static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);	// @004c3c48
		ColorMapperMultiArmor(					// @004c3d60
			GaugeRate, ModeMask, L4GaugeRenderer *, int, int,
			Entity *, const char *, const char *,
			const int *zone_indices /*[8]*/, const char *);
		~ColorMapperMultiArmor();
	};

	//
	// ColorMapperCritical -- tints by a subsystem's operational state.
	// Connection: @004c3598 (subsystem operational flag @0x40 -> 100, else value).
	//
	class ColorMapperCritical :
		public ColorMapper
	{
	public:
		// Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "cmCrit".
		static MethodDescription methodDescription;

		static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);	// @004c3ddc
		ColorMapperCritical(					// @004c3e40
			GaugeRate, ModeMask, L4GaugeRenderer *, int, int,
			Entity *, const char *, const char *,
			const char *subsystem_name, const char *);
		~ColorMapperCritical();
	};

	//
	// ColorMapperHeat -- the cockpit heat tint.  ANCHOR @004c3f6c.
	// Connection: @004c3664 (reads HeatableSubsystem::currentTemperature@0x114
	// as a 0..100 percentage).  The named subsystem must derive from a heat
	// class (IsDerivedFrom 0x50e3ec or 0x50e604) or the ctor asserts (line 0x68a).
	//
	class ColorMapperHeat :
		public ColorMapper
	{
	public:
		static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);	// @004c3f08
		ColorMapperHeat(						// @004c3f6c
			GaugeRate, ModeMask, L4GaugeRenderer *, int, int,
			Entity *, const char *, const char *,
			const char *heat_subsystem_name, const char *);
		~ColorMapperHeat();

		// Registered in BTL4MethodDescription[] (btl4grnd.cpp) so the config
		// interpreter builds this gauge from the CFG "cmHeat" primitive.
		static MethodDescription methodDescription;
	};


	//#######################################################################
	//#######################################################################
	//   Two-part fill bars  (: GraphicGauge)
	//
	//   A bar is split into a "filled" colour and a "background" colour at a
	//   pixel computed from a Scalar input.  HorizTwoPartBar grows left->right,
	//   VertTwoPartBar grows bottom->top.  Both blit a tile bitmap behind the
	//   fill (FUN_004c2ff8 = tiled blit helper).
	//#######################################################################
	//#######################################################################

	class HorizTwoPartBar :
		public GraphicGauge
	{
	public:
		static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);	// @004c407c
		HorizTwoPartBar(						// @004c4170
			GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number,
			int left, int bottom, int right, int top,
			const char *tile_image,
			int fill_color, int background_color,
			Scalar *value_pointer, Scalar *low_pointer, Scalar *high_pointer,
			const char *identification_string);
		~HorizTwoPartBar();

		Logical	TestInstance() const;
		void	BecameActive();					// @004c4324
		void	Execute();						// @004c4340

	protected:
		Scalar	value;							// @0x90  this[0x24]  (connection)
		Scalar	low;							// @0x94  this[0x25]
		Scalar	high;							// @0x98  this[0x26]
		char	*tileImage;						// @0x9C  this[0x27]
		int		fillColor;						// @0xA0  this[0x28]
		int		backgroundColor;				// @0xA4  this[0x29]
		int		width;							// @0xA8  this[0x2A]  right-left
		int		height;							// @0xAC  this[0x2B]  (top-bottom)-1
		int		previousFill;					// @0xB0  this[0x2C]
		int		previousFull;					// @0xB4  this[0x2D]
	};

	class VertTwoPartBar :
		public GraphicGauge
	{
	public:
		// Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "vertBar".
		static MethodDescription methodDescription;

		static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);	// @004c462c
		VertTwoPartBar(							// @004c4724  (ctor arg order = binary param_12..17)
			GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number,
			int left, int bottom, int right, int top,
			const char *tile_image,
			int background_color, int fill_color, int extra_color,
			Scalar *value_pointer, Scalar *low_pointer, Scalar *high_pointer,
			const char *identification_string);
		~VertTwoPartBar();

		Logical	TestInstance() const;
		void	BecameActive();					// @004c48e0
		void	Execute();						// @004c48fc

	protected:
		char	*tileImage;						// @0x90  this[0x24]
		int		backgroundColor;				// @0x94  this[0x25]
		int		fillColor;						// @0x98  this[0x26]
		int		extraColor;						// @0x9C  this[0x27]
		int		width;							// @0xA0  this[0x28]  (right-left)-1
		int		height;							// @0xA4  this[0x29]  top-bottom
		Scalar	value;							// @0xB0  this[0x2C]  (connection)
		Scalar	low;							// @0xB4  this[0x2D]
		Scalar	high;							// @0xB8  this[0x2E]
		int		previousFill;					// @0xA8  this[0x2A]
		int		previousFull;					// @0xAC  this[0x2B]
	};

	//
	// VertNormalSlider -- a single-colour rectangle whose height tracks a
	// normalised [0,1] value (clamped at @004c4cc0).  (name unconfirmed but
	// matches the "VertNormalSlider" pool entry and the vtable ordering.)
	//
	class VertNormalSlider :
		public GraphicGauge
	{
	public:
		VertNormalSlider(						// @004c4b84
			GaugeRate, ModeMask, L4GaugeRenderer *, int,
			int left, int bottom, int right, int top,
			int fill_color, int background_color, int baseline,
			Scalar *value_pointer, const char *identification_string);
		~VertNormalSlider();

		Logical	TestInstance() const;
		void	BecameActive();					// @004c4cac
		void	Execute();						// @004c4cc0 -> Draw @004c4d48

	protected:
		Scalar	value;							// @0xAC  this[0x2B]  (connection)
		int		previousFill;					// @0x90  this[0x24]
		int		fillColor;						// @0x94  this[0x25]
		int		backgroundColor;				// @0x98  this[0x26]
		int		baseline;						// @0x9C  this[0x27]
		int		width;							// @0xA0  this[0x28]
		int		height;							// @0xA4  this[0x29]
		int		span;							// @0xA8  this[0x2A]
	};


	//#######################################################################
	//#######################################################################
	//   OneOfSeveral family -- multi-frame bitmap selectors
	//
	//   A strip bitmap holds N frames; the gauge blits whichever frame the
	//   driving value selects.  The base (OneOfSeveral) stores the strip and
	//   the per-frame size; subclasses add the value source.
	//#######################################################################
	//#######################################################################

	class OneOfSeveral :
		public GraphicGauge
	{
	public:
		OneOfSeveral(							// @004c4d88
			GaugeRate, ModeMask, L4GaugeRenderer *, int,
			int x, int y, Logical from_image_strip,
			const char *image_name,
			int /*reserved*/, int /*reserved*/,
			int columns, int rows,
			const char *identification_string);
		~OneOfSeveral();

		Logical	TestInstance() const;
		void	BecameActive();					// @004c4f14
		void	Execute();						// @004c4f28

	protected:
		Logical	fromImageStrip;					// @0x90  this[0x24]
		char	*imageName;						// @0x94  this[0x25]
		int		backgroundColor;				// @0x98  this[0x26]
		int		columns;						// @0xA0  this[0x28]
		int		selected;						// @0xAC  this[0x2B]  (connection)
		int		previousSelected;				// @0xB0  this[0x2C]
		int		frameWidth;						// @0xA4  this[0x29]
		int		frameHeight;					// @0xA8  this[0x2A]
	};

	//
	// OneOfSeveralInt -- frame = a direct int input.  @004c5148  Make @004c5068
	//
	class OneOfSeveralInt :
		public OneOfSeveral
	{
	public:
		static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);
		OneOfSeveralInt(GaugeRate, ModeMask, L4GaugeRenderer *, int,
			int x, int y, const char *image, int columns, int rows,
			int *value_pointer, const char *);
		~OneOfSeveralInt();						// @004c51d8
	};

	//
	// OneOfSeveralPixInt -- frame from a packed-pixel int strip.
	// @004c52d8  Make @004c5204
	//
	class OneOfSeveralPixInt :
		public OneOfSeveral
	{
	public:
		static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);
		OneOfSeveralPixInt(GaugeRate, ModeMask, L4GaugeRenderer *, int,
			int x, int y, const char *image, int columns, int rows,
			int *value_pointer, const char *);
		~OneOfSeveralPixInt();					// @004c5364
	};

	//
	// OneOfSeveralStates -- frame from a subsystem state value (clamped >=0).
	// @004c5470  Make @004c5390   Execute clamp @004c552c
	// Connection: @004c3324 (reads Subsystem state @0x14).
	//
	class OneOfSeveralStates :
		public OneOfSeveral
	{
	public:
		static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);
		OneOfSeveralStates(GaugeRate, ModeMask, L4GaugeRenderer *, int,
			int x, int y, const char *image, int columns, int rows,
			Entity *subsystem_source, const char *);
		~OneOfSeveralStates();					// @004c5500
		void	BecameActive();					// @004c552c
	};


	//#######################################################################
	// HeadingPointer -- a rotating numeric compass-heading readout.
	// @004c562c  Make @004c554c  Execute @004c5914 (rotate by torso yaw,
	// degrees = radian * 57.2958).  Owns a NumericDisplay (@0x44 object,
	// FUN_004700bc) and a GraphicsViewRecord (@0xA4) for erase tracking.
	//#######################################################################
	class HeadingPointer :
		public GraphicGauge
	{
	public:
		// Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "headingPointer".
		static MethodDescription methodDescription;

		static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);	// @004c554c

		//
		// The binary ctor (@004c562c) takes 14 args -- the earlier header collapsed
		// owner_ID/graphics_port_number and merged the colours.  Also: fields
		// @0x98/@0x9C are the needle's inner/outer RADIUS (Execute multiplies them
		// by sin/cos of the heading), NOT a colour+spacing as the old names implied.
		//
		HeadingPointer(							// @004c562c
			GaugeRate, ModeMask, L4GaugeRenderer *,
			unsigned int owner_ID,
			int graphics_port_number,
			int x, int y,
			int needle_color,				// -> @0x90  the drawn needle colour
			int numeric_color,				// -> NumericDisplay foreground (readout)
			int erase_color,				// -> @0x94  erase + NumericDisplay background
			int inner_radius,				// -> @0x98  needle near-end radius
			int outer_radius,				// -> @0x9C  needle tip radius (the change key)
			const char *font_name,
			const char *identification_string = "HeadingPointer");
		~HeadingPointer();						// @004c573c

		Logical	TestInstance() const;
		void	ShowInstance(char *indent);		// @004c57d0
		void	BecameActive();					// @004c58e8
		void	Execute();						// @004c5914

	protected:
		int		needleColor;					// @0x90  needle (fg) colour
		int		eraseColor;						// @0x94  erase (bg) colour
		int		innerRadius;					// @0x98  needle near-end radius
		int		outerRadius;					// @0x9C  needle tip radius (change key)
		char	*imageName;						// @0xA0  interned font name
		GraphicsViewRecord
				previousDrawing;				// @0xA4  erase-tracking record
		int		previousX;						// @0xB4
		int		previousY;						// @0xB8
		NumericDisplay
				*numericDisplay;				// @0xBC
	};


	//#######################################################################
	// BitMap "wipe" gauges -- a fuel/leak style bar that reveals a bitmap up
	// to a level.  (names "BitMapInverseWipe" / "BitMapInverseWipeScalar" are
	// best-effort from the pool; the Scalar variant adds a GaugeConnection.)
	//   BitMapInverseWipe        @004c5b7c  (used as a base by btl4gau2 LeakGauge)
	//   <wipe base>              @004c5e84
	//   <wipe base>Scalar        @004c61c8  (adds GaugeConnectionDirectOf<Scalar>)
	//#######################################################################
	class BitMapInverseWipe :					// (name unconfirmed)
		public GraphicGauge
	{
	public:
		BitMapInverseWipe(						// @004c5b7c
			GaugeRate, ModeMask, L4GaugeRenderer *, int,
			int x, int y, const char *image,
			int color_a, int color_b, int third, int frames,
			Scalar *value_pointer, const char *);
		~BitMapInverseWipe();					// @004c5c80
		Logical	TestInstance() const;
		void	BecameActive();					// @004c5cf4
		void	Execute();						// @004c5d08
	protected:
		char	*imageName;						// @0x90  this[0x24]
		int		colorA;							// @0x94  this[0x25]
		int		colorB;							// @0x98  this[0x26]
		int		fullWidth;						// @0x9C  this[0x27]  frames*2
		int		frameWidth;						// @0xA8  this[0x2A]  width/3
		int		frameHeight;					// @0xA4  this[0x29]
		int		frames;							// @0xA0  this[0x28]
		int		previousLevel;					// @0xAC  this[0x2B]
		int		third;							// @0xB0  this[0x2C]
		Scalar	value;							// @0xB4  this[0x2D]  (connection)
	};

	//#######################################################################
	// SegmentArc gauges -- needle / dial over a 270-degree arc.  Derived from
	// the MUNGA L4 arc primitives (FUN_004745e0 / FUN_00473f44).
	//   SegmentArc270   @004c6244
	//   SegmentArcRatio @004c6394  Make @004c62fc  (adds two connections)
	//#######################################################################
	class SegmentArc270 :
		public SegmentArc							// MUNGA L4 base (FUN_004745e0; engine class SegmentArc)
	{
	public:
		SegmentArc270(/* ...arc geometry... */);	// @004c6244
		~SegmentArc270();							// dtor thunk @004c66b3
	protected:
		int		segmentSpan;						// @0xC0  this[0x30]
	};

	class SegmentArcRatio :
		public SegmentArc							// MUNGA L4 base (engine SegmentArc, L4GAUGE.cpp:4827)
	{
	public:
		// Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "segmentArcRatio".
		static MethodDescription methodDescription;

		static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);	// @004c62fc
		SegmentArcRatio(							// @004c6394
			GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number,
			int center_x, int center_y,
			Scalar inner, Scalar outer, Scalar deg0, Scalar deg1,
			int number_of_segs, int background_color, int foreground_color,
			Scalar *numerator_pointer, Scalar *denominator_pointer,
			const char *identification_string);
		~SegmentArcRatio();							// dtor thunk @004c668d

		void	Execute();							// @004c6488 (ratio -> currentValue -> SegmentArc::Execute)

	protected:
		Scalar	numerator;							// @0xC0  this[0x30]  (connection)
		Scalar	denominator;						// @0xC4  this[0x31]  (connection)
		Scalar	segmentSpan;						// @0xC8  this[0x32]  (float, read by Execute)
	};

#endif
