summaryrefslogtreecommitdiff
path: root/hammer/mapstudiomodel.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/mapstudiomodel.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'hammer/mapstudiomodel.cpp')
-rw-r--r--hammer/mapstudiomodel.cpp904
1 files changed, 904 insertions, 0 deletions
diff --git a/hammer/mapstudiomodel.cpp b/hammer/mapstudiomodel.cpp
new file mode 100644
index 0000000..9d164fc
--- /dev/null
+++ b/hammer/mapstudiomodel.cpp
@@ -0,0 +1,904 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "stdafx.h"
+#include "Box3D.h"
+#include "GlobalFunctions.h"
+#include "MapDefs.h" // dvs: For COORD_NOTINIT
+#include "MapDoc.h"
+#include "MapEntity.h"
+#include "MapStudioModel.h"
+#include "Render2D.h"
+#include "Render3D.h"
+#include "ViewerSettings.h"
+#include "hammer.h"
+#include "materialsystem/imesh.h"
+#include "TextureSystem.h"
+#include "Material.h"
+#include "Options.h"
+#include "camera.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+
+#define STUDIO_RENDER_DISTANCE 400
+
+
+IMPLEMENT_MAPCLASS(CMapStudioModel)
+
+
+float CMapStudioModel::m_fRenderDistance = STUDIO_RENDER_DISTANCE;
+BOOL CMapStudioModel::m_bAnimateModels = TRUE;
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Factory function. Used for creating a CMapStudioModel from a set
+// of string parameters from the FGD file.
+// Input : pInfo - Pointer to helper info class which gives us information
+// about how to create the class.
+// Output : Returns a pointer to the class, NULL if an error occurs.
+//-----------------------------------------------------------------------------
+CMapClass *CMapStudioModel::CreateMapStudioModel(CHelperInfo *pHelperInfo, CMapEntity *pParent)
+{
+ const char *pszModel = pHelperInfo->GetParameter(0);
+
+ //
+ // If we weren't passed a model name as an argument, get it from our parent
+ // entity's "model" key.
+ //
+ if (pszModel == NULL)
+ {
+ pszModel = pParent->GetKeyValue("model");
+ }
+
+ //
+ // If we have a model name, create a studio model object.
+ //
+ if (pszModel != NULL)
+ {
+ bool bLightProp = !stricmp(pHelperInfo->GetName(), "lightprop");
+ bool bOrientedBounds = (bLightProp | !stricmp(pHelperInfo->GetName(), "studioprop"));
+ return CreateMapStudioModel(pszModel, bOrientedBounds, bLightProp);
+ }
+
+ return(NULL);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Factory function. Creates a CMapStudioModel object from a relative
+// path to an MDL file.
+// Input : pszModelPath - Relative path to the .MDL file. The path is appended
+// to each path in the application search path until the model is found.
+// bOrientedBounds - Whether the bounding box should consider the orientation of the model.
+// Output : Returns a pointer to the newly created CMapStudioModel object.
+//-----------------------------------------------------------------------------
+CMapStudioModel *CMapStudioModel::CreateMapStudioModel(const char *pszModelPath, bool bOrientedBounds, bool bReversePitch)
+{
+ CMapStudioModel *pModel = new CMapStudioModel;
+ pModel->m_pStudioModel = CStudioModelCache::CreateModel(pszModelPath);
+ if ( pModel->m_pStudioModel )
+ {
+ pModel->SetOrientedBounds(bOrientedBounds);
+ pModel->ReversePitch(bReversePitch);
+
+ pModel->CalcBounds();
+ }
+ else
+ {
+ delete pModel;
+ pModel = NULL;
+ }
+ return(pModel);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor.
+//-----------------------------------------------------------------------------
+CMapStudioModel::CMapStudioModel(void)
+{
+ Initialize();
+ InitViewerSettings();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor. Releases the studio model cache reference.
+//-----------------------------------------------------------------------------
+CMapStudioModel::~CMapStudioModel(void)
+{
+ if (m_pStudioModel != NULL)
+ {
+ CStudioModelCache::Release(m_pStudioModel);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Called by the renderer before every frame to animate the models.
+//-----------------------------------------------------------------------------
+void CMapStudioModel::AdvanceAnimation(float flInterval)
+{
+ if (m_bAnimateModels)
+ {
+ CStudioModelCache::AdvanceAnimation(flInterval);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : bFullUpdate -
+//-----------------------------------------------------------------------------
+void CMapStudioModel::CalcBounds(BOOL bFullUpdate)
+{
+ CMapClass::CalcBounds(bFullUpdate);
+
+ Vector Mins(0, 0, 0);
+ Vector Maxs(0, 0, 0);
+
+ if (m_pStudioModel != NULL)
+ {
+ //
+ // The 3D bounds are the bounds of the oriented model's first sequence, so that
+ // frustum culling works properly in the 3D view.
+ //
+ QAngle angles;
+ GetRenderAngles(angles);
+
+ m_pStudioModel->SetAngles(angles);
+ m_pStudioModel->ExtractBbox(m_CullBox.bmins, m_CullBox.bmaxs);
+
+ if (m_bOrientedBounds)
+ {
+ //
+ // Oriented bounds - the 2D bounds are the same as the 3D bounds.
+ //
+ Mins = m_CullBox.bmins;
+ Maxs = m_CullBox.bmaxs;
+ }
+ else
+ {
+ //
+ // The 2D bounds are the movement bounding box of the model, which is not affected
+ // by the entity's orientation. This is used for character models for which we want
+ // to render a meaningful collision box in the editor.
+ //
+ m_pStudioModel->ExtractMovementBbox(Mins, Maxs);
+ }
+
+ Mins += m_Origin;
+ Maxs += m_Origin;
+
+ m_CullBox.bmins += m_Origin;
+ m_CullBox.bmaxs += m_Origin;
+ }
+
+ //
+ // If we do not yet have a valid bounding box, use a default box.
+ //
+ if ((Maxs - Mins) == Vector(0, 0, 0))
+ {
+ Mins = m_CullBox.bmins = m_Origin - Vector(10, 10, 10);
+ Maxs = m_CullBox.bmaxs = m_Origin + Vector(10, 10, 10);
+ }
+
+ m_BoundingBox = m_CullBox;
+ m_Render2DBox.UpdateBounds(Mins, Maxs);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : CMapClass
+//-----------------------------------------------------------------------------
+CMapClass *CMapStudioModel::Copy(bool bUpdateDependencies)
+{
+ CMapStudioModel *pCopy = new CMapStudioModel;
+
+ if (pCopy != NULL)
+ {
+ pCopy->CopyFrom(this, bUpdateDependencies);
+ }
+
+ return(pCopy);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Makes this an exact duplicate of pObject.
+// Input : pObject - Object to copy.
+// Output : Returns this.
+//-----------------------------------------------------------------------------
+CMapClass *CMapStudioModel::CopyFrom(CMapClass *pObject, bool bUpdateDependencies)
+{
+ Assert(pObject->IsMapClass(MAPCLASS_TYPE(CMapStudioModel)));
+ CMapStudioModel *pFrom = (CMapStudioModel *)pObject;
+
+ CMapClass::CopyFrom(pObject, bUpdateDependencies);
+
+ m_pStudioModel = pFrom->m_pStudioModel;
+ if (m_pStudioModel != NULL)
+ {
+ CStudioModelCache::AddRef(m_pStudioModel);
+ }
+
+ m_Angles = pFrom->m_Angles;
+ m_Skin = pFrom->m_Skin;
+ m_bOrientedBounds = pFrom->m_bOrientedBounds;
+ m_bReversePitch = pFrom->m_bReversePitch;
+ m_bPitchSet = pFrom->m_bPitchSet;
+ m_flPitch = pFrom->m_flPitch;
+
+ m_bScreenSpaceFade = pFrom->m_bScreenSpaceFade;
+ m_flFadeScale = pFrom->m_flFadeScale;
+ m_flFadeMinDist = pFrom->m_flFadeMinDist;
+ m_flFadeMaxDist = pFrom->m_flFadeMaxDist;
+ m_iSolid = pFrom->m_iSolid;
+
+ return(this);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : bEnable -
+//-----------------------------------------------------------------------------
+void CMapStudioModel::EnableAnimation(BOOL bEnable)
+{
+ m_bAnimateModels = bEnable;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns this object's pitch, yaw, and roll.
+//-----------------------------------------------------------------------------
+void CMapStudioModel::GetAngles(QAngle &Angles)
+{
+ Angles = m_Angles;
+
+ if (m_bPitchSet)
+ {
+ Angles[PITCH] = m_flPitch;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns this object's pitch, yaw, and roll for rendering.
+//-----------------------------------------------------------------------------
+void CMapStudioModel::GetRenderAngles(QAngle &Angles)
+{
+ GetAngles(Angles);
+
+ if (m_bReversePitch)
+ {
+ Angles[PITCH] *= -1;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMapStudioModel::Initialize(void)
+{
+ m_Angles.Init();
+ m_bPitchSet = false;
+ m_flPitch = 0;
+ m_bReversePitch = false;
+ m_pStudioModel = NULL;
+ m_Skin = 0;
+
+ m_bScreenSpaceFade = false;
+ m_flFadeScale = 1.0f;
+ m_flFadeMinDist = 0.0f;
+ m_flFadeMaxDist = 0.0f;
+ m_iSolid = -1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Notifies that this object's parent entity has had a key value change.
+// Input : szKey - The key that changed.
+// szValue - The new value of the key.
+//-----------------------------------------------------------------------------
+void CMapStudioModel::OnParentKeyChanged(const char* szKey, const char* szValue)
+{
+ if (!stricmp(szKey, "angles"))
+ {
+ sscanf(szValue, "%f %f %f", &m_Angles[PITCH], &m_Angles[YAW], &m_Angles[ROLL]);
+ PostUpdate(Notify_Changed);
+ }
+ else if (!stricmp(szKey, "pitch"))
+ {
+ m_flPitch = atof(szValue);
+ m_bPitchSet = true;
+
+ PostUpdate(Notify_Changed);
+ }
+ else if (!stricmp(szKey, "skin"))
+ {
+ m_Skin = atoi(szValue);
+ PostUpdate(Notify_Changed);
+ }
+ else if (!stricmp(szKey, "fademindist"))
+ {
+ m_flFadeMinDist = atoi(szValue);
+ }
+ else if (!stricmp(szKey, "fademaxdist"))
+ {
+ m_flFadeMaxDist = atoi(szValue);
+ }
+ else if (!stricmp(szKey, "screenspacefade"))
+ {
+ m_bScreenSpaceFade = (atoi(szValue) != 0);
+ }
+ else if (!stricmp(szKey, "fadescale"))
+ {
+ m_flFadeScale = atof(szValue);
+ }
+ else if ( !stricmp( szKey, "solid") )
+ {
+ m_iSolid = atof( szValue );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : pRender -
+//-----------------------------------------------------------------------------
+bool CMapStudioModel::RenderPreload(CRender3D *pRender, bool bNewContext)
+{
+ return(m_pStudioModel != NULL);
+}
+
+
+//-----------------------------------------------------------------------------
+// Draws basis vectors
+//-----------------------------------------------------------------------------
+static void DrawBasisVectors( CRender3D* pRender, const Vector &origin, const QAngle &angles)
+{
+ matrix3x4_t fCurrentMatrix;
+ AngleMatrix(angles, fCurrentMatrix);
+
+ pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
+
+ CMeshBuilder meshBuilder;
+ CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
+ IMesh* pMesh = pRenderContext->GetDynamicMesh();
+ meshBuilder.Begin( pMesh, MATERIAL_LINES, 3 );
+
+ meshBuilder.Color3ub(255, 0, 0);
+ meshBuilder.Position3f(origin[0], origin[1], origin[2]);
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Color3ub(255, 0, 0);
+ meshBuilder.Position3f(origin[0] + (100 * fCurrentMatrix[0][0]),
+ origin[1] + (100 * fCurrentMatrix[1][0]), origin[2] + (100 * fCurrentMatrix[2][0]));
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Color3ub(0, 255, 0);
+ meshBuilder.Position3f(origin[0], origin[1], origin[2]);
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Color3ub(0, 255, 0);
+ meshBuilder.Position3f(origin[0] + (100 * fCurrentMatrix[0][1]),
+ origin[1] + (100 * fCurrentMatrix[1][1]), origin[2] + (100 * fCurrentMatrix[2][1]));
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Color3ub(0, 0, 255);
+ meshBuilder.Position3f(origin[0], origin[1], origin[2]);
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Color3ub(0, 0, 255);
+ meshBuilder.Position3f(origin[0] + (100 * fCurrentMatrix[0][2]),
+ origin[1] + (100 * fCurrentMatrix[1][2]), origin[2] + (100 * fCurrentMatrix[2][2]));
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.End();
+ pMesh->Draw();
+
+ pRender->PopRenderMode();
+}
+
+
+//-----------------------------------------------------------------------------
+// It should render last if any of its materials are translucent, or if
+// we are previewing model fades.
+//-----------------------------------------------------------------------------
+bool CMapStudioModel::ShouldRenderLast()
+{
+ return m_pStudioModel->IsTranslucent() || Options.view3d.bPreviewModelFade;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Renders the studio model in the 2D views.
+// Input : pRender - Interface to the 2D renderer.
+//-----------------------------------------------------------------------------
+void CMapStudioModel::Render2D(CRender2D *pRender)
+{
+ Vector vecMins;
+ Vector vecMaxs;
+ GetRender2DBox(vecMins, vecMaxs);
+
+ Vector2D pt,pt2;
+ pRender->TransformPoint(pt, vecMins);
+ pRender->TransformPoint(pt2, vecMaxs);
+
+ color32 rgbColor = GetRenderColor();
+ bool bIsEditable = IsEditable();
+
+ if (GetSelectionState() != SELECT_NONE)
+ {
+ pRender->SetDrawColor( GetRValue(Options.colors.clrSelection), GetGValue(Options.colors.clrSelection), GetBValue(Options.colors.clrSelection) );
+ pRender->SetHandleColor( GetRValue(Options.colors.clrSelection), GetGValue(Options.colors.clrSelection), GetBValue(Options.colors.clrSelection) );
+ }
+ else
+ {
+ pRender->SetDrawColor( rgbColor.r, rgbColor.g, rgbColor.b );
+ pRender->SetHandleColor( rgbColor.r, rgbColor.g, rgbColor.b );
+ }
+
+ int sizeX = abs(pt2.x-pt.x);
+ int sizeY = abs(pt2.y-pt.y);
+
+ //
+ // Don't draw the center handle if the model is smaller than the handle cross
+ //
+ if ( bIsEditable && sizeX >= 8 && sizeY >= 8 && pRender->IsActiveView() )
+ {
+ pRender->SetHandleStyle( HANDLE_RADIUS, CRender::HANDLE_CROSS );
+
+ pRender->DrawHandle( (vecMins+vecMaxs)/2 );
+ }
+
+ QAngle vecAngles;
+ GetRenderAngles(vecAngles);
+
+ bool bDrawAsModel = (Options.view2d.bDrawModels && ((sizeX+sizeY) > 50)) ||
+ IsSelected() || ( pRender->IsInLocalTransformMode() && !pRender->GetInstanceRendering() );
+
+ if ( !bDrawAsModel || IsSelected() )
+ {
+ // Draw the bounding box.
+ pRender->DrawBox( vecMins, vecMaxs );
+ }
+
+ if ( bDrawAsModel )
+ {
+ //
+ // Draw the model as wireframe.
+ //
+
+ m_pStudioModel->SetAngles(vecAngles);
+ m_pStudioModel->SetOrigin(m_Origin[0], m_Origin[1], m_Origin[2]);
+ m_pStudioModel->SetSkin(m_Skin);
+
+ if ( GetSelectionState() == SELECT_NORMAL || ( pRender->IsInLocalTransformMode() && pRender->GetInstanceRendering() == false ) )
+ {
+ // draw textured model half translucent
+ m_pStudioModel->DrawModel2D(pRender, 0.6 , false );
+ }
+ else
+ {
+ // just draw the wireframe
+ m_pStudioModel->DrawModel2D(pRender, 1.0 , true );
+ }
+ }
+
+ if ( IsSelected() )
+ {
+ //
+ // Render the forward vector if the object is selected.
+ //
+
+ Vector Forward;
+ AngleVectors(vecAngles, &Forward, NULL, NULL);
+
+ pRender->SetDrawColor( 255, 255, 0 );
+ pRender->DrawLine(m_Origin, m_Origin + Forward * 24);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+inline float CMapStudioModel::ComputeDistanceFade( CRender3D *pRender ) const
+{
+ Vector vecViewPos;
+ pRender->GetCamera()->GetViewPoint( vecViewPos );
+
+ Vector vecDelta;
+ vecDelta = m_Origin - vecViewPos;
+
+ float flMin = min(m_flFadeMinDist, m_flFadeMaxDist);
+ float flMax = max(m_flFadeMinDist, m_flFadeMaxDist);
+
+ if (flMin < 0)
+ {
+ flMin = 0;
+ }
+
+ float alpha = 1.0f;
+ if (flMax > 0)
+ {
+ float flDist = vecDelta.Length();
+ if ( flDist > flMax )
+ {
+ alpha = 0.0f;
+ }
+ else if ( flDist > flMin )
+ {
+ alpha = RemapValClamped( flDist, flMin, flMax, 1.0f, 0 );
+ }
+ }
+
+ return alpha;
+}
+
+
+//-----------------------------------------------------------------------------
+// Computes fade alpha based on distance fade + screen fade
+//-----------------------------------------------------------------------------
+inline float CMapStudioModel::ComputeScreenFade( CRender3D *pRender ) const
+{
+ return 1.0;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+inline float CMapStudioModel::ComputeFade( CRender3D *pRender ) const
+{
+ if ( m_bScreenSpaceFade )
+ {
+ return ComputeScreenFade( pRender );
+ }
+ else
+ {
+ return ComputeDistanceFade( pRender );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Renders the studio model in the 3D views.
+// Input : pRender - Interface to the 3D renderer.
+//-----------------------------------------------------------------------------
+void CMapStudioModel::Render3D(CRender3D *pRender)
+{
+ Color CurrentColor;
+ CurrentColor.SetColor( r, g, b );
+
+ //
+ // Set to the default rendering mode, unless we're in lightmap mode
+ //
+ if (pRender->GetCurrentRenderMode() == RENDER_MODE_LIGHTMAP_GRID)
+ pRender->PushRenderMode(RENDER_MODE_TEXTURED);
+ else
+ pRender->PushRenderMode(RENDER_MODE_CURRENT);
+
+ //
+ // Set up our angles for rendering.
+ //
+ QAngle vecAngles;
+ GetRenderAngles(vecAngles);
+
+ //
+ // If we have a model, render it if it is close enough to the camera.
+ //
+ if (m_pStudioModel != NULL)
+ {
+ Vector ViewPoint;
+ pRender->GetCamera()->GetViewPoint(ViewPoint);
+
+ Vector Origin( m_Origin );
+ if ( pRender->GetInstanceRendering() )
+ {
+ pRender->TransformInstanceVector( m_Origin, Origin );
+ }
+
+ if ((fabs(ViewPoint[0] - Origin[0]) < m_fRenderDistance) &&
+ (fabs(ViewPoint[1] - Origin[1]) < m_fRenderDistance) &&
+ (fabs(ViewPoint[2] - Origin[2]) < m_fRenderDistance))
+ {
+ color32 rgbColor = GetRenderColor();
+
+ if (GetSelectionState() != SELECT_NONE)
+ {
+ pRender->SetDrawColor( GetRValue(Options.colors.clrSelection), GetGValue(Options.colors.clrSelection), GetBValue(Options.colors.clrSelection) );
+ }
+ else
+ {
+ // If the user disabled collisions on this instance of the model, color the wireframe differently
+ if ( m_iSolid != -1 )
+ {
+ if ( m_iSolid == 0 )
+ {
+ rgbColor.r = GetRValue( Options.colors.clrModelCollisionWireframeDisabled );
+ rgbColor.g = GetGValue( Options.colors.clrModelCollisionWireframeDisabled );
+ rgbColor.b = GetBValue( Options.colors.clrModelCollisionWireframeDisabled );
+ rgbColor.a = 255;
+ }
+ else
+ {
+ rgbColor.r = GetRValue( Options.colors.clrModelCollisionWireframe );
+ rgbColor.g = GetGValue( Options.colors.clrModelCollisionWireframe );
+ rgbColor.b = GetBValue( Options.colors.clrModelCollisionWireframe );
+ rgbColor.a = 255;
+ }
+ }
+ pRender->SetDrawColor( rgbColor.r, rgbColor.g, rgbColor.b );
+ }
+
+ //
+ // Move the model to the proper place and orient it.
+ //
+ m_pStudioModel->SetAngles(vecAngles);
+ m_pStudioModel->SetOrigin(m_Origin[0], m_Origin[1], m_Origin[2]);
+ m_pStudioModel->SetSkin(m_Skin);
+
+ float flAlpha = 1.0;
+ if ( Options.view3d.bPreviewModelFade )
+ {
+ flAlpha = ComputeFade( pRender );
+ }
+
+ bool bWireframe = pRender->GetCurrentRenderMode() == RENDER_MODE_WIREFRAME;
+
+ if ( GetSelectionState() == SELECT_MODIFY )
+ bWireframe = true;
+
+ pRender->BeginRenderHitTarget(this);
+ m_pStudioModel->DrawModel3D(pRender, flAlpha, bWireframe );
+ pRender->EndRenderHitTarget();
+
+ if (IsSelected())
+ {
+ pRender->RenderWireframeBox(m_Render2DBox.bmins, m_Render2DBox.bmaxs, 255, 255, 0);
+ }
+ }
+ else
+ {
+ pRender->BeginRenderHitTarget(this);
+ pRender->RenderBox(m_Render2DBox.bmins, m_Render2DBox.bmaxs, CurrentColor.r(), CurrentColor.g(), CurrentColor.b(), GetSelectionState());
+ pRender->EndRenderHitTarget();
+ }
+ }
+ //
+ // Else no model, render as a bounding box.
+ //
+ else
+ {
+ pRender->BeginRenderHitTarget(this);
+ pRender->RenderBox(m_Render2DBox.bmins, m_Render2DBox.bmaxs, CurrentColor.r(), CurrentColor.g(), CurrentColor.b(), GetSelectionState());
+ pRender->EndRenderHitTarget();
+ }
+
+ //
+ // Draw our basis vectors.
+ //
+ if (IsSelected())
+ {
+ DrawBasisVectors( pRender, m_Origin, vecAngles );
+ }
+
+ pRender->PopRenderMode();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &File -
+// bRMF -
+// Output : int
+//-----------------------------------------------------------------------------
+int CMapStudioModel::SerializeRMF(std::fstream &File, BOOL bRMF)
+{
+ return(0);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &File -
+// bRMF -
+// Output : int
+//-----------------------------------------------------------------------------
+int CMapStudioModel::SerializeMAP(std::fstream &File, BOOL bRMF)
+{
+ return(0);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : Angles -
+//-----------------------------------------------------------------------------
+void CMapStudioModel::SetAngles(QAngle &Angles)
+{
+ m_Angles = Angles;
+
+ //
+ // Round very small angles to zero.
+ //
+ for (int nDim = 0; nDim < 3; nDim++)
+ {
+ if (fabs(m_Angles[nDim]) < 0.001)
+ {
+ m_Angles[nDim] = 0;
+ }
+ }
+
+ while (m_Angles[YAW] < 0)
+ {
+ m_Angles[YAW] += 360;
+ }
+
+ if (m_bPitchSet)
+ {
+ m_flPitch = m_Angles[PITCH];
+ }
+
+ //
+ // Update the angles of our parent entity.
+ //
+ CMapEntity *pEntity = dynamic_cast<CMapEntity *>(m_pParent);
+ if (pEntity != NULL)
+ {
+ char szValue[80];
+ sprintf(szValue, "%g %g %g", m_Angles[0], m_Angles[1], m_Angles[2]);
+ pEntity->NotifyChildKeyChanged(this, "angles", szValue);
+
+ if (m_bPitchSet)
+ {
+ sprintf(szValue, "%g", m_flPitch);
+ pEntity->NotifyChildKeyChanged(this, "pitch", szValue);
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets the distance at which studio models become rendered as bounding
+// boxes. If this is set to zero, studio models are never rendered.
+// Input : fRenderDistance - Distance in world units.
+//-----------------------------------------------------------------------------
+void CMapStudioModel::SetRenderDistance(float fRenderDistance)
+{
+ m_fRenderDistance = fRenderDistance;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : pTransBox -
+//-----------------------------------------------------------------------------
+void CMapStudioModel::DoTransform(const VMatrix &matrix)
+{
+ BaseClass::DoTransform(matrix);
+
+ // rotate model angles
+
+ matrix3x4_t fRotateMatrix, fCurrentMatrix, fMatrixNew;
+ fRotateMatrix = matrix.As3x4();
+
+ // Light entities negate pitch again!
+ if ( m_bReversePitch )
+ {
+ QAngle rotAngles;
+ MatrixAngles(fRotateMatrix, rotAngles);
+ rotAngles[PITCH] *= -1;
+ rotAngles[ROLL] *= -1;
+ AngleMatrix(rotAngles, fRotateMatrix);
+ }
+
+ QAngle angles;
+ GetAngles( angles );
+
+ AngleMatrix( angles, fCurrentMatrix);
+ ConcatTransforms(fRotateMatrix, fCurrentMatrix, fMatrixNew);
+ MatrixAngles( fMatrixNew, angles );
+
+ SetAngles( angles );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : int
+//-----------------------------------------------------------------------------
+int CMapStudioModel::GetFrame(void)
+{
+ // TODO:
+ return 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : nFrame -
+//-----------------------------------------------------------------------------
+void CMapStudioModel::SetFrame(int nFrame)
+{
+ // TODO:
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the current sequence being used for rendering.
+//-----------------------------------------------------------------------------
+int CMapStudioModel::GetSequence(void)
+{
+ if (!m_pStudioModel)
+ {
+ return 0;
+ }
+ return m_pStudioModel->GetSequence();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : int
+//-----------------------------------------------------------------------------
+int CMapStudioModel::GetSequenceCount(void)
+{
+ if (!m_pStudioModel)
+ {
+ return 0;
+ }
+ return m_pStudioModel->GetSequenceCount();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : nIndex -
+// szName -
+//-----------------------------------------------------------------------------
+void CMapStudioModel::GetSequenceName(int nIndex, char *szName)
+{
+ if (m_pStudioModel)
+ {
+ m_pStudioModel->GetSequenceName(nIndex, szName);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : nIndex -
+//-----------------------------------------------------------------------------
+void CMapStudioModel::SetSequence(int nIndex)
+{
+ if (m_pStudioModel)
+ {
+ m_pStudioModel->SetSequence(nIndex);
+ }
+}
+
+
+int CMapStudioModel::GetSequenceIndex( const char *pSequenceName ) const
+{
+ if ( m_pStudioModel )
+ {
+ int cnt = m_pStudioModel->GetSequenceCount();
+ for ( int i=0; i < cnt; i++ )
+ {
+ char name[2048];
+ m_pStudioModel->GetSequenceName( i, name );
+ if ( Q_stricmp( pSequenceName, name ) == 0 )
+ return i;
+ }
+ }
+
+ return -1;
+}