//===========================================================================//
// File:	btl4vid.hpp                                                         //
// Project: BattleTech       Brick: Video Renderer Manager                    //
// Contents: BTL4VideoRenderer -- the BattleTech L4 out-the-window 3D WORLD   //
//           renderer manager.  Builds the per-entity renderable tree for the //
//           main view each time an interesting entity becomes visible:       //
//           the player mech + its weapons/effects/reticle, terrain, and      //
//           other movers, walking the jointed-mover segment table and the    //
//           subsystem roster and submitting renderables to the scene.        //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 02/13/95  CPB  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1996, Virtual World Entertainment, Inc.                //
//                      PROPRIETARY and CONFIDENTIAL                         //
//===========================================================================//
//
// RECONSTRUCTED from the shipped binary (BTL4OPT.EXE).  NO header survived.
// Class/member/method names are taken from the embedded assert path
// "d:\tesla\bt\bt_l4\BTL4VID.CPP", the embedded class name string
// "BTL4VideoRenderer::Material name ..." (@0051d6f8), and the direct
// Red Planet analogue RP_L4/RPL4VID.cpp (RPL4VideoRenderer) plus the surviving
// MUNGA headers MUNGA_L4/L4VIDEO.HPP and MUNGA_L4/L4VIDRND.HPP.  Each method
// cites its originating @ADDR.
//
// PORTING NOTES (reconstruction -> WinTesla engine)
//   * BTL4VideoRenderer is the BattleTech analogue of RPL4VideoRenderer; both
//     subclass the concrete L4 manager DPLRenderer (L4VIDEO.HPP).  Deriving
//     from DPLRenderer supplies SetFogStyle/AddDynamicRenderable, the fog
//     colour/plane fields, dplMainView/dplMainZone/dplDeathZone and the
//     vehicleReticle slot the recovered code touches.
//   * The 1996 BattleTech build drove a pre-DPL renderable hierarchy whose
//     joint renderables parent on a dpl_DCS* (rather than the WinTesla
//     HierarchicalDrawComponent* parent).  That hierarchy did NOT survive in
//     source, so the BT-specific renderables it constructs are declared here
//     (BTRootRenderable / BTHingeRenderable / ... ) with the signatures the
//     recovered code actually calls.  They are distinct from the modern
//     L4VIDRND.HPP renderables of the same role (which is why the targeting
//     reticle is BTReticleRenderable, NOT the engine's ReticleRenderable --
//     the BT object is 0x358 bytes and carries up to 10 AddWeapon pip markers).
//

#if !defined(BTL4VID_HPP)
#	define BTL4VID_HPP

//
// Forward declaration so MUNGA_L4/l4vidrnd.h (which references DPLRenderer in
// HierarchicalDrawComponent before l4video.h defines it) parses cleanly
// regardless of include order.
//
class DPLRenderer;

#if !defined(L4VIDEO_HPP)
#	include <l4video.hpp>			// DPLRenderer / VideoRenderer / INTERSECT_ALL
#endif
#if !defined(L4VIDRND_HPP)
#	include <l4vidrnd.hpp>			// VideoComponent / the *Renderable hierarchy
#endif
#if !defined(RETICLE_HPP)
#	include <reticle.hpp>
#endif
#if !defined(STATE_HPP)
#	include <state.hpp>				// StateIndicator
#endif
#if !defined(JMOVER_HPP)
#	include <jmover.hpp>			// JointedMover
#endif
#if !defined(JOINT_HPP)
#	include <joint.hpp>				// Joint / JointSubsystem / Hinge
#endif
#if !defined(SEGMENT_HPP)
#	include <segment.hpp>			// EntitySegment
#endif
#if !defined(SUBSYSTM_HPP)
#	include <subsystm.hpp>			// Subsystem
#endif
#if !defined(NAMELIST_HPP)
#	include <namelist.hpp>			// NameList / NameList::Entry
#endif

	class Entity;
	class Mission;
	class ResourceDescription;
	class NotationFile;

	//
	// BT "scene" handle.  In the 1996 build the world-view renderables were
	// built against an opaque scene root (the analogue of RP's dpl_ZONE pair);
	// it is used pointer-only in this module, so a forward declaration suffices.
	//
	class Scene;

//
//===========================================================================//
// Legacy 2D / material-callback DPL entry points
//===========================================================================//
//
// The dpl2d_ display-list layer and the material-name-substitution callback
// hook were part of libDPL (the IG-board driver) and were NOT carried into the
// WinTesla engine.  The recovered reticle builder and material setup call them
// directly; declare them here so the translation unit compiles (resolved at
// link time against the libDPL shim).
//
dpl2d_DISPLAY*	dpl2d_NewDisplayList();
void			dpl2d_Begin(dpl2d_DISPLAY *list, int mode);
void			dpl2d_SetColor(dpl2d_DISPLAY *list, Scalar red, Scalar green, Scalar blue);
void			dpl2d_Circle(dpl2d_DISPLAY *list, Scalar x, Scalar y, Scalar radius, int fill);
void			dpl2d_PushMatrix(dpl2d_DISPLAY *list);
void			dpl2d_PopMatrix(dpl2d_DISPLAY *list);
void			dpl2d_MoveTo(dpl2d_DISPLAY *list, Scalar x, Scalar y);
void			dpl2d_End(dpl2d_DISPLAY *list);
void			dpl2d_Compile(dpl2d_DISPLAY *list);

void			dpl_SetMaterialNameCallback(char *(*callback)(char *source));

//
//===========================================================================//
// BattleTech renderable hierarchy (pre-DPL)
//===========================================================================//
//
// Common base: every BT world renderable carries the dpl_DCS / dpl_INSTANCE it
// creates and offers the graphical (Add) / control (Connect) hook-up the world
// container uses.  Modelled on VideoComponent so a BTRootRenderable can be
// returned as the VideoComponent* mech root.
//
class BTRenderableBase:
	public VideoComponent
{
	public:
		BTRenderableBase(
			Entity				*entity,
			VideoExecutionType	execution_type = DynamicVideoExecutionType)
				: VideoComponent(entity, execution_type), myDCS(0), myInstance(0) {}

		dpl_DCS*		GetDCS()		{ return myDCS; }
		dpl_INSTANCE*	GetInstance()	{ return myInstance; }

		//
		// Graphical / control hook-up.  These hide VideoComponent::Add/Connect
		// (which take VideoComponent*) so the world container can accept any
		// renderable in the BT hierarchy by its common HierarchicalDrawComponent
		// base.
		//
		void	Add(HierarchicalDrawComponent *child)		{ if (child) addChild(child); }
		void	Connect(HierarchicalDrawComponent *child)	{ if (child) addChild(child); }

	protected:
		dpl_DCS			*myDCS;
		dpl_INSTANCE	*myInstance;
};

//
// World container renderable (FUN_00455de4, alloc 0x60).  Holds the death /
// world DCS roots for one entity's tree.
//
class BTWorldContainerRenderable:
	public BTRenderableBase
{
	public:
		BTWorldContainerRenderable(
			Entity	*entity,
			int		execution_type,
			int		in_death_zone,
			Scene	*scene);
};

//
// Root DCS object renderable (FUN_00453578, alloc 0x64).
//
class BTRootRenderable:
	public BTRenderableBase
{
	public:
		BTRootRenderable(
			Entity			*entity,
			int				execution_type,
			d3d_OBJECT		*graphical_object,
			Scene			*scene,
			int				intersect_mode,
			uint32			intersect_mask);
};

//
// Static / jointed child DCS renderables.
//
class BTDCSObjectRenderable:
	public BTRenderableBase
{
	public:
		BTDCSObjectRenderable(			// FUN_0045848c, alloc 0x50
			Entity			*entity,
			Scene			*scene,
			d3d_OBJECT		*graphical_object,
			int				execution_type,
			uint32			intersect_mask,
			LinearMatrix	*offset_matrix,
			dpl_DCS			*parent_DCS);
};

class BTHingeRenderable:
	public BTRenderableBase
{
	public:
		BTHingeRenderable(				// FUN_004537e8, alloc 0x78
			Entity			*entity,
			int				execution_type,
			d3d_OBJECT		*graphical_object,
			Scene			*scene,
			int				exec2,
			uint32			intersect_mask,
			dpl_DCS			*parent_DCS,
			LinearMatrix	*offset_matrix,
			const Hinge		*my_hinge);
};

class BTBallJointRenderable:
	public BTRenderableBase
{
	public:
		BTBallJointRenderable(			// FUN_004539b4, alloc 0x7c
			Entity				*entity,
			int					execution_type,
			d3d_OBJECT			*graphical_object,
			Scene				*scene,
			int					exec2,
			uint32				intersect_mask,
			dpl_DCS				*parent_DCS,
			LinearMatrix		*offset_matrix,
			const EulerAngles	*my_euler);
};

class BTBallTranslateJointRenderable:
	public BTRenderableBase
{
	public:
		BTBallTranslateJointRenderable(	// FUN_00453ac4, alloc 0x8c
			Entity				*entity,
			int					execution_type,
			d3d_OBJECT			*graphical_object,
			Scene				*scene,
			int					exec2,
			uint32				intersect_mask,
			dpl_DCS				*parent_DCS,
			LinearMatrix		*offset_matrix,
			const EulerAngles	*my_euler,
			const Point3D		*my_translation);
};

//
// Inside-view eyepoint (POV/eye) renderable (FUN_004579a8, alloc 0x5c).
//
class BTEyeRenderable:
	public BTRenderableBase
{
	public:
		BTEyeRenderable(
			Entity			*entity,
			Scene			*scene,
			LinearMatrix	*offset_matrix,
			dpl_DCS			*parent_DCS,
			dpl_VIEW		*this_view,
			EulerAngles		*eyepoint_rotation);
};

//
// Death / explosion effect renderable (FUN_00453f18, alloc 0x48).
//
class BTDeathEffectRenderable:
	public BTRenderableBase
{
	public:
		BTDeathEffectRenderable(
			Entity			*entity,
			int				execution_type,
			dpl_VIEW		*this_view,
			Scene			*scene,
			dpl_DCS			*parent_DCS,
			StateIndicator	*death_state,
			int				death_control_state);
};

//
// Marker (timestamp/beacon) watcher renderable (FUN_00458c58, alloc 0x120).
//
class BTMarkerWatcherRenderable:
	public BTRenderableBase
{
	public:
		BTMarkerWatcherRenderable(
			Entity		*entity,
			int			execution_type,
			dpl_VIEW	*this_view,
			dpl_DCS		*parent_DCS);
};

//
// Drop-zone translocation effect renderable (FUN_00458d2c, alloc 0x40).
//
class BTTranslocationRenderable:
	public BTRenderableBase
{
	public:
		BTTranslocationRenderable(
			Entity			*entity,
			int				execution_type,
			dpl_VIEW		*this_view,
			StateIndicator	*effect_trigger,
			Point3D			*drop_zone,
			int				effect_control_state);
};

//
// Player POV mission start/end fade renderable (FUN_00454394, alloc 0x50).
// (BT-local twin of the engine's POVStartEndRenderable; the BT ctor takes the
// main-view handle plus the world/death zones explicitly.)
//
class BTPOVStartEndRenderable:
	public BTRenderableBase
{
	public:
		BTPOVStartEndRenderable(
			Entity			*entity,
			int				execution_type,
			dpl_VIEW		*this_view,
			dpl_ZONE		*main_zone,
			dpl_ZONE		*death_zone,
			StateIndicator	*effect_trigger,
			float			red_fog,
			float			green_fog,
			float			blue_fog,
			float			near_fog,
			float			far_fog,
			int				start_mission_state,
			int				end_mission_state);
};

//
// Coolant / reservoir / tracer reservoir effect renderable (FUN_00456a68,
// alloc 0x138).
//
class BTTracerEffectRenderable:
	public BTRenderableBase
{
	public:
		BTTracerEffectRenderable(
			Entity			*entity,
			int				execution_type,
			void			*state_attr,
			int				mode,
			dpl_ZONE		*zone,
			dpl_DCS			*parent_DCS,
			LinearMatrix	*offset_matrix);
};

//
// Emitter beam renderable (FUN_004593c0, alloc 0x80).
//
class BTEmitterBeamRenderable:
	public BTRenderableBase
{
	public:
		BTEmitterBeamRenderable(
			Entity			*entity,
			int				execution_type,
			d3d_OBJECT		*graphical_object,
			Scene			*scene,
			int				exec2,
			uint32			intersect_mask,
			dpl_DCS			*parent_DCS,
			LinearMatrix	*offset_matrix,
			void			*sim_state,
			int				flag,
			void			*beam_scale,
			void			*beam_orient);
};

//
// PPC beam renderable (FUN_004590d8, alloc 0x88).
//
class BTPPCBeamRenderable:
	public BTRenderableBase
{
	public:
		BTPPCBeamRenderable(
			Entity			*entity,
			int				execution_type,
			d3d_OBJECT		*graphical_object,
			Scene			*scene,
			int				exec2,
			uint32			intersect_mask,
			dpl_DCS			*parent_DCS,
			LinearMatrix	*offset_matrix,
			void			*sim_state,
			int				flag,
			void			*beam_scale,
			void			*beam_orient,
			float			beam_width);
};

//
// Searchlight LightOn -> spotlight connector (FUN_0045612c, alloc 0x2c).
//
class BTLightConnection:
	public BTRenderableBase
{
	public:
		BTLightConnection(
			Entity			*entity,
			int				execution_type,
			dpl_INSTANCE	*spot_instance,
			int				flag,
			int				*light_on);
};

//
//#############################################################################
// BTReticleRenderable  (BattleTech targeting reticle)
//#############################################################################
//
// File-private to btl4vid.cpp.  Parallels the engine ReticleRenderable
// (L4VIDRND.HPP) but the BT object is 0x358 bytes and carries up to 10 weapon
// pip / range markers built by AddWeapon.  Constructed @004cc40c for the inside
// view; weapon markers are appended by MakeMechRenderables via AddWeapon.
//
//   header layout actually touched (this+...):
//     +0x38   weaponCount (cap 10 -- "Tried to display too many weapons")
//     ...     parallel per-weapon arrays (see members below)
//     reticle geometry: minRange@0x230, maxRange@0x22c, rangeScale@0x234,
//                        originX@0x1fc, originY@0x200, scaleY@0x204, biasX@0x208
//
class BTReticleRenderable:
	public VideoRenderable
{
	public:
		BTReticleRenderable(					// @004cc40c
			Entity			*entity,
			int				execution_type,
			Reticle			**my_reticle,
			dpl_VIEW		*this_view,
			void			*pip_position_template,
			void			*pip_color_template,
			void			*range_template,
			void			*range_lo_template,
			void			*range_hi_template,
			Scalar			max_range,
			int				flag,
			void			*sim_template_a,
			void			*sim_template_b,
			void			*sim_template_c);
		~BTReticleRenderable();

		//
		// Append a weapon range/pip marker to the reticle.  @004cdac0
		//
		void
			AddWeapon(
				Scalar				weapon_range,
				int					pip_position,
				StateIndicator	*within_range_attr,
				int					extended_range,
				Scalar				pip_red,
				Scalar				pip_green,
				Scalar				pip_blue,
				StateIndicator	*sim_state,
				int					arg9,
				int					arg10,
				StateIndicator	*sim_state2,
				int					arg12,
				int					weapon_mode);

		void
			Execute();

	protected:
		//
		// Per-weapon parallel arrays (cap 10).
		//
		int				weaponCount;					// +0x38
		int				weaponMode[10];					// +0x3c
		Scalar			pipColor[10];					// +0x64
		StateIndicator	*withinRangeAttr[10];			// +0x8c
		StateIndicator	*simState[10];					// +0xb4
		int				simState2Value[10];				// +0xdc
		int				arg12Value[10];					// +0x104
		StateIndicator	*simState2Ptr[10];				// +0x130
		int				arg12Ptr[10];					// +0x158
		Scalar			*rangeAttr[10];					// +0x18c
		Scalar			rangeCache[10];					// +0x1b4
		dpl2d_DISPLAY	*pipDisplayListB[10];			// +0x288
		dpl2d_DISPLAY	*pipDisplayListA[10];			// +0x2b0

		//
		// Calibrated reticle geometry.
		//
		Scalar			originX;						// +0x1fc
		Scalar			originY;						// +0x200
		Scalar			scaleY;							// +0x204
		Scalar			biasX;							// +0x208
		Scalar			maxRange;						// +0x22c
		Scalar			minRange;						// +0x230
		Scalar			rangeScale;						// +0x234
};

//
//#############################################################################
// BTL4VideoRenderer
//#############################################################################
//
// @ vtable: BattleTech L4 video renderer manager subclass.  Base is the MUNGA
// L4 renderer manager (DPLRenderer, l4video.hpp).  Parallels RPL4VideoRenderer.
//
	class BTL4VideoRenderer:
		public DPLRenderer
	{
	public:
		BTL4VideoRenderer(
			RendererRate			calibration_rate,
			RendererComplexity	calibration_complexity,
			RendererPriority		calibration_priority,
			InterestType			interest_type,
			InterestDepth			depth_calibration
		);
		~BTL4VideoRenderer();

		Logical
			TestInstance() const;

		//
		// Material substitution (mirrors RPL4VideoRenderer).
		//
		void
			SetupMaterialSubstitutionList(Entity *entity);		// @004d0cc0
		void
			TearDownMaterialSubstitutionList();					// @004d11e8

	protected:
		//
		// Renderer-manager overrides
		//
		void
			LoadMissionImplementation(Mission *mission);

		void
			MakeEntityRenderables(								// @004d0774
				Entity					*this_entity,
				ResourceDescription	*model_resource,
				ViewFrom					type);

		HierarchicalDrawComponent*
			MakeMechRenderables(								// @004cef28
				Entity					*entity,
				ResourceDescription	*model_resource,
				ViewFrom					type);

		//
		//--------------------------------------------------------------------
		// BT renderer helpers (recovered).
		//--------------------------------------------------------------------
		//
		Scene*
			GetScene();											// FUN_0045a724

		dpl_VIEW*
			GetMainView()	{ return dplMainView; }			// this[0x124]
		dpl_ZONE*
			GetMainZone()	{ return dplMainZone; }			// this[300]

		d3d_OBJECT*
			LoadObject(const char *object_name);			// FUN_00498448

		void
			AttachToEyeDCS(dpl_DCS *root_dcs, LinearMatrix &local_to_world);	// FUN_00489cec

		void
			AddDynamicRenderable(VideoComponent *renderable, Entity *entity);	// FUN_0045a994

	protected:
		//
		// vtvCount / vtvsExpected analogues (RPL4VideoRenderer).
		//
		int
			mechsExpected,
			mechCount;

		//
		// True once the linked (player) entity exists, so its root DCS is
		// hooked onto the eye.  ([0xb0] in the recovered layout.)
		//
		Logical
			linkedEntityPresent;

		//
		// Effect zones touched by the recovered code.
		//
		dpl_ZONE
			*scene_zone,		// [0x318]  coolant / reservoir effects
			*tracer_zone;		// [0x2e4]  projectile tracers
	};

#endif // BTL4VID_HPP

//===========================================================================//
