/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** *********************************************************************************************** * * * Project Name : WWPhys * * * * $Archive:: /Commando/Code/wwphys/widgetuser.cpp $* * * * Author:: Greg Hjelstrom * * * * $Modtime:: 10/11/01 2:29p $* * * * $Revision:: 5 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "widgetuser.h" #include "widgets.h" #include "mempool.h" #include "vertmaterial.h" #include "matinfo.h" #include "boxrobj.h" #include "ww3d.h" /* ** WidgetRenderOpClass ** This class encapsulates the instructions from a physics object to render ** a debug widget. Each physics object has a list of these hanging off it ** for rendering vectors, points, etc. ** Since instances of this class are constantly allocated and deallocated ** each frame they are derived from AutoPoolClass. */ class WidgetRenderOpClass : public AutoPoolClass { public: WidgetRenderOpClass(void); void Set_Color(const Vector3 & color); void Set_Opacity(float opacity); void Init_Point(const Vector3 & point); void Init_Vector(const Vector3 & point,const Vector3 & vector); void Init_AABox(const AABoxClass & box); void Init_OBBox(const OBBoxClass & box); void Init_Coord_Axes(const Matrix3D & tm); void Render(RenderInfoClass & rinfo); void Set_Next(WidgetRenderOpClass * next) { Next = next; } WidgetRenderOpClass * Get_Next(void) { return Next; } protected: void render_point(RenderInfoClass & rinfo); void render_vector(RenderInfoClass & rinfo); void render_aabox(RenderInfoClass & rinfo); void render_obbox(RenderInfoClass & rinfo); void render_axes(RenderInfoClass & rinfo); enum { RENDER_NONE = 0, RENDER_POINT, RENDER_VECTOR, RENDER_AABOX, RENDER_OBBOX, RENDER_AXES }; int RenderOp; Vector3 Color; float Opacity; Vector3 V0; // these are all re-used depending on the render op Vector3 V1; Vector3 V2; Matrix3D Transform; WidgetRenderOpClass * Next; }; /* ** declare the instance of the pool object for all WidgetRenderOpClass's */ DEFINE_AUTO_POOL(WidgetRenderOpClass,256); /******************************************* ** ** WidgetRenderOpClass Implementation ** *******************************************/ WidgetRenderOpClass::WidgetRenderOpClass(void) : RenderOp(RENDER_NONE), Next(NULL) { } void WidgetRenderOpClass::Set_Color(const Vector3 & color) { Color = color; } void WidgetRenderOpClass::Set_Opacity(float opacity) { Opacity = opacity; } void WidgetRenderOpClass::Init_Point(const Vector3 & p0) { RenderOp = RENDER_POINT; V0 = p0; } void WidgetRenderOpClass::Init_Vector(const Vector3 & point,const Vector3 & vector) { RenderOp = RENDER_VECTOR; V0 = point; V1 = vector; } void WidgetRenderOpClass::Init_AABox(const AABoxClass & box) { RenderOp = RENDER_AABOX; V0 = box.Center; V1 = box.Extent; } void WidgetRenderOpClass::Init_OBBox(const OBBoxClass & box) { RenderOp = RENDER_OBBOX; V0 = Vector3(0,0,0); V1 = box.Extent; Transform.Set(box.Basis,box.Center); } void WidgetRenderOpClass::Init_Coord_Axes(const Matrix3D & tm) { RenderOp = RENDER_AXES; Transform = tm; } void WidgetRenderOpClass::Render(RenderInfoClass & rinfo) { switch(RenderOp) { case RENDER_NONE: break; case RENDER_POINT: render_point(rinfo); break; case RENDER_VECTOR: render_vector(rinfo); break; case RENDER_AABOX: render_aabox(rinfo); break; case RENDER_OBBOX: render_obbox(rinfo); break; case RENDER_AXES: render_axes(rinfo); break; }; } void WidgetRenderOpClass::render_point(RenderInfoClass & rinfo) { #ifdef WWDEBUG // Get the point model RenderObjClass * model = WidgetSystem::Get_Debug_Widget(WidgetSystem::WIDGET_POINT); if (model == NULL) return; if (model->Class_ID() != RenderObjClass::CLASSID_MESH) { model->Release_Ref(); return; } // Set its color MaterialInfoClass * matinfo = model->Get_Material_Info(); if (matinfo) { VertexMaterialClass * vmat = matinfo->Peek_Vertex_Material(0); if (vmat) { vmat->Set_Emissive(Color); } matinfo->Release_Ref(); } // Render it model->Set_Transform(Matrix3D(V0)); model->Render(rinfo); model->Release_Ref(); #endif } void WidgetRenderOpClass::render_vector(RenderInfoClass & rinfo) { #ifdef WWDEBUG if (V1.Length2() < WWMATH_EPSILON) return; RenderObjClass * vecmodel = WidgetSystem::Get_Debug_Widget(WidgetSystem::WIDGET_VECTOR); if (vecmodel) { // set the color, the vector model is a skin so we have to get the // first sub-object, get its material info, then get the first vertex material RenderObjClass * subobj = vecmodel->Get_Sub_Object(0); if (subobj) { MaterialInfoClass * matinfo = subobj->Get_Material_Info(); if (matinfo) { VertexMaterialClass * vmat = matinfo->Peek_Vertex_Material(0); if (vmat) { vmat->Set_Emissive(Color); } matinfo->Release_Ref(); } subobj->Release_Ref(); } // set the transform to be at p0, pointing -z at p1 Matrix3D tm0; Matrix3D tm1(1); tm0.Look_At(V0,V0+V1,0.0f); // point -z from pt along vec tm1.Translate(Vector3(0,0,1.0f - V1.Length())); // p1 is along -z (Point1 starts at -1) vecmodel->Set_Transform(tm0); // set bone "Point1" to be at p1 int p1index = vecmodel->Get_Bone_Index("Point1"); vecmodel->Capture_Bone(p1index); vecmodel->Control_Bone(p1index,tm1); vecmodel->Render(rinfo); vecmodel->Release_Ref(); } #endif } void WidgetRenderOpClass::render_aabox(RenderInfoClass & rinfo) { #ifdef WWDEBUG RenderObjClass * model = WidgetSystem::Get_Debug_Widget(WidgetSystem::WIDGET_AABOX); if (model == NULL) return; if (model->Class_ID() != RenderObjClass::CLASSID_AABOX) { model->Release_Ref(); return; } // force this box to get rendered (bypass the built in collision bit masking) int oldmask = WW3D::Get_Collision_Box_Display_Mask(); int newmask = oldmask | 0x01; WW3D::Set_Collision_Box_Display_Mask(newmask); AABoxRenderObjClass * boxmodel = (AABoxRenderObjClass *)model; boxmodel->Set_Local_Center_Extent(V0,V1); boxmodel->Set_Transform(Matrix3D(1)); boxmodel->Set_Color(Color); boxmodel->Set_Opacity(Opacity); boxmodel->Render(rinfo); boxmodel->Release_Ref(); // restore the old mask WW3D::Set_Collision_Box_Display_Mask(oldmask); #endif } void WidgetRenderOpClass::render_obbox(RenderInfoClass & rinfo) { #ifdef WWDEBUG RenderObjClass * model = WidgetSystem::Get_Debug_Widget(WidgetSystem::WIDGET_OBBOX); if (model == NULL) return; if (model->Class_ID() != RenderObjClass::CLASSID_OBBOX) { model->Release_Ref(); return; } // force this box to get rendered (bypass the built in collision bit masking) int oldmask = WW3D::Get_Collision_Box_Display_Mask(); int newmask = oldmask | 0x01; WW3D::Set_Collision_Box_Display_Mask(newmask); OBBoxRenderObjClass * boxmodel = (OBBoxRenderObjClass *)model; boxmodel->Set_Collision_Type(0xFF); boxmodel->Set_Transform(Transform); boxmodel->Set_Local_Center_Extent(V0,V1); boxmodel->Set_Color(Color); boxmodel->Set_Opacity(Opacity); boxmodel->Render(rinfo); boxmodel->Release_Ref(); // restore the old mask WW3D::Set_Collision_Box_Display_Mask(oldmask); #endif } void WidgetRenderOpClass::render_axes(RenderInfoClass & rinfo) { #ifdef WWDEBUG RenderObjClass * model = WidgetSystem::Get_Debug_Widget(WidgetSystem::WIDGET_AXES); if (model == NULL) return; if (model->Class_ID() != RenderObjClass::CLASSID_MESH) { model->Release_Ref(); return; } model->Set_Transform(Transform); model->Render(rinfo); model->Release_Ref(); #endif } /******************************************* ** ** WidgetUserClass Implementation ** *******************************************/ WidgetUserClass::WidgetUserClass(void) { #ifdef WWDEBUG WidgetRenderOpList = NULL; #endif } WidgetUserClass::~WidgetUserClass(void) { Reset_Debug_Widget_List(); } #ifdef WWDEBUG void WidgetUserClass::Reset_Debug_Widget_List(void) { WidgetRenderOpClass * op = WidgetRenderOpList; while (op) { WidgetRenderOpClass * nextop = op->Get_Next(); delete op; op = nextop; } WidgetRenderOpList = NULL; } #endif #ifdef WWDEBUG void WidgetUserClass::Add_Debug_Widget(WidgetRenderOpClass * op) { WWASSERT(op->Get_Next() == NULL); op->Set_Next(WidgetRenderOpList); WidgetRenderOpList = op; } #endif #ifdef WWDEBUG void WidgetUserClass::Add_Debug_Point(const Vector3 & p,const Vector3 & color) { WidgetRenderOpClass * op = new WidgetRenderOpClass; op->Set_Color(color); op->Init_Point(p); Add_Debug_Widget(op); } #endif #ifdef WWDEBUG void WidgetUserClass::Add_Debug_Vector(const Vector3 & p,const Vector3 & v,const Vector3 & color) { if (v.Length2() > 0.0f) { WidgetRenderOpClass * op = new WidgetRenderOpClass; op->Set_Color(color); op->Init_Vector(p,v); Add_Debug_Widget(op); } } #endif #ifdef WWDEBUG void WidgetUserClass::Add_Debug_AABox(const AABoxClass & box,const Vector3 & color,float opacity) { WidgetRenderOpClass * op = new WidgetRenderOpClass; op->Set_Color(color); op->Set_Opacity(opacity); op->Init_AABox(box); Add_Debug_Widget(op); } #endif #ifdef WWDEBUG void WidgetUserClass::Add_Debug_OBBox(const OBBoxClass & box,const Vector3 & color,float opacity) { WidgetRenderOpClass * op = new WidgetRenderOpClass; op->Set_Color(color); op->Set_Opacity(opacity); op->Init_OBBox(box); Add_Debug_Widget(op); } #endif #ifdef WWDEBUG void WidgetUserClass::Add_Debug_Axes(const Matrix3D & transform,const Vector3 & color) { WidgetRenderOpClass * op = new WidgetRenderOpClass; op->Set_Color(color); op->Init_Coord_Axes(transform); Add_Debug_Widget(op); } #endif #ifdef WWDEBUG void WidgetUserClass::Render_Debug_Widgets(RenderInfoClass & rinfo) { WW3D::Flush(rinfo); WidgetRenderOpClass * op = WidgetRenderOpList; while (op) { op->Render(rinfo); op = op->Get_Next(); WW3D::Flush(rinfo); } } #endif