mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 23:51:41 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
208
Code/Tools/LevelEdit/AttenuationSphere.cpp
Normal file
208
Code/Tools/LevelEdit/AttenuationSphere.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/AttenuationSphere.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 5/04/00 9:58a $*
|
||||
* *
|
||||
* $Revision:: 3 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "AttenuationSphere.h"
|
||||
#include "SphereObj.h"
|
||||
#include "Utils.h"
|
||||
#include "Node.h"
|
||||
#include "SceneEditor.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AttenuationSphereClass
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
AttenuationSphereClass::AttenuationSphereClass (void)
|
||||
: m_IsInScene (false),
|
||||
m_Color (1, 1, 1),
|
||||
m_Radius (1.0F),
|
||||
m_Opacity (1.0F)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~AttenuationSphereClass
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
AttenuationSphereClass::~AttenuationSphereClass (void)
|
||||
{
|
||||
Remove_From_Scene ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Display_Around_Node
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
AttenuationSphereClass::Display_Around_Node (const NodeClass &node)
|
||||
{
|
||||
RenderObjClass *render_obj = node.Peek_Render_Obj ();
|
||||
if (render_obj != NULL) {
|
||||
Display_Around_Node (*render_obj);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Display_Around_Node
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
AttenuationSphereClass::Display_Around_Node (const RenderObjClass &render_obj)
|
||||
{
|
||||
//
|
||||
// Make sure we have a sphere object
|
||||
//
|
||||
SphereRenderObjClass *sphere = (SphereRenderObjClass *)Peek_Model ();
|
||||
if (sphere == NULL) {
|
||||
sphere = new SphereRenderObjClass;
|
||||
sphere->Set_Flag (SphereRenderObjClass::USE_ALPHA_VECTOR, false);
|
||||
Set_Model (sphere);
|
||||
|
||||
Set_Color (m_Color);
|
||||
Set_Radius (m_Radius);
|
||||
Set_Opacity (m_Opacity);
|
||||
|
||||
MEMBER_RELEASE (sphere);
|
||||
}
|
||||
|
||||
//
|
||||
// Update the sphere's position
|
||||
//
|
||||
Set_Transform (render_obj.Get_Transform ());
|
||||
|
||||
//
|
||||
// Put the sphere into the scene
|
||||
//
|
||||
if (m_IsInScene == false) {
|
||||
::Get_Scene_Editor ()->Add_Dynamic_Object (this);
|
||||
m_IsInScene = true;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Remove_From_Scene
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
AttenuationSphereClass::Remove_From_Scene (void)
|
||||
{
|
||||
//
|
||||
// Remove the sphere from the scene
|
||||
//
|
||||
if (m_IsInScene) {
|
||||
::Get_Scene_Editor ()->Remove_Object (this);
|
||||
m_IsInScene = false;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Color
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
AttenuationSphereClass::Set_Color (const Vector3 &color)
|
||||
{
|
||||
SphereRenderObjClass *sphere = (SphereRenderObjClass *)Peek_Model ();
|
||||
SANITY_CHECK (sphere != NULL) {
|
||||
return ;
|
||||
}
|
||||
|
||||
m_Color = color;
|
||||
sphere->Set_Color (m_Color);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Radius
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
AttenuationSphereClass::Set_Radius (float radius)
|
||||
{
|
||||
SphereRenderObjClass *sphere = (SphereRenderObjClass *)Peek_Model ();
|
||||
SANITY_CHECK (sphere != NULL) {
|
||||
return ;
|
||||
}
|
||||
|
||||
m_Radius = radius;
|
||||
sphere->Set_Extent (Vector3 (m_Radius, m_Radius, m_Radius));
|
||||
sphere->Set_Transform (sphere->Get_Transform ());
|
||||
Update_Cull_Box ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Opacity
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
AttenuationSphereClass::Set_Opacity (float opacity)
|
||||
{
|
||||
SphereRenderObjClass *sphere = (SphereRenderObjClass *)Peek_Model ();
|
||||
SANITY_CHECK (sphere != NULL) {
|
||||
return ;
|
||||
}
|
||||
|
||||
m_Opacity = opacity;
|
||||
sphere->Set_Alpha (m_Opacity);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
94
Code/Tools/LevelEdit/AttenuationSphere.h
Normal file
94
Code/Tools/LevelEdit/AttenuationSphere.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/AttenuationSphere.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 4/04/00 8:02p $*
|
||||
* *
|
||||
* $Revision:: 2 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __ATTENUATIONSPHERE_H
|
||||
#define __ATTENUATIONSPHERE_H
|
||||
|
||||
|
||||
#include "Utils.h"
|
||||
#include "EditorPhys.h"
|
||||
#include "Vector3.h"
|
||||
|
||||
|
||||
// Forward declarations
|
||||
class NodeClass;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AttenuationSphereClass
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class AttenuationSphereClass : public EditorPhysClass
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Public contsructors/destructors
|
||||
////////////////////////////////////////////////////////
|
||||
AttenuationSphereClass (void);
|
||||
virtual ~AttenuationSphereClass (void);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
////////////////////////////////////////////////////////
|
||||
void Display_Around_Node (const NodeClass &node);
|
||||
void Display_Around_Node (const RenderObjClass &render_obj);
|
||||
void Remove_From_Scene (void);
|
||||
void Set_Color (const Vector3 &color);
|
||||
void Set_Radius (float radius);
|
||||
void Set_Opacity (float opacity);
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
////////////////////////////////////////////////////////
|
||||
bool m_IsInScene;
|
||||
Vector3 m_Color;
|
||||
float m_Radius;
|
||||
float m_Opacity;
|
||||
};
|
||||
|
||||
|
||||
#endif //__ATTENUATIONSPHERE_H
|
||||
|
||||
870
Code/Tools/LevelEdit/Box3D.cpp
Normal file
870
Code/Tools/LevelEdit/Box3D.cpp
Normal file
@@ -0,0 +1,870 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/Box3D.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 3/28/01 3:11p $*
|
||||
* *
|
||||
* $Revision:: 9 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// Following is a diagram specifying which entries in the m_Verticies array
|
||||
// correspond to which verticies in the box (in object space).
|
||||
// I don't know how well this diagram is going to hold up to different editors/font sizes, etc
|
||||
// so I apologize in advance if its unreadable... ;>
|
||||
//
|
||||
//
|
||||
// 2 --------------- 3
|
||||
// /| /|
|
||||
// / | / |
|
||||
// / | / |
|
||||
// 6 --------------- 7 |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | 1|_________|___| 0
|
||||
// | / | /
|
||||
// | / | /
|
||||
// |/ |/
|
||||
// 5 --------------- 4
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "box3d.h"
|
||||
#include "coltest.h"
|
||||
#include "tri.h"
|
||||
#include "leveleditdoc.h"
|
||||
#include "cameramgr.h"
|
||||
#include "camera.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Local constants and typedefs
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
typedef enum
|
||||
{
|
||||
FACE_FRONT = 0,
|
||||
FACE_BACK,
|
||||
FACE_TOP,
|
||||
FACE_BOTTOM,
|
||||
FACE_RIGHT,
|
||||
FACE_LEFT,
|
||||
FACE_COUNT
|
||||
} FACE_INDEX;
|
||||
|
||||
const int FACE_VERTICIES[6][4] = {
|
||||
{ 5, 4, 6, 7 }, { 0, 1, 3, 2 },
|
||||
{ 3, 2, 7, 6 }, { 4, 5, 0, 1 },
|
||||
{ 1, 5, 2, 6 }, { 4, 0, 7, 3 }
|
||||
};
|
||||
|
||||
const float MIN_SIZE = 0.01F;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Local prototypes
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
static bool Find_Intersection_Point (const AABoxClass &box, const Vector3 &p0, const Vector3 &p1, float *percent, Vector3 *intersection_point);
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create_Model
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Create_Model (void)
|
||||
{
|
||||
//
|
||||
// Assign a default vertex material for the model
|
||||
//
|
||||
VertexMaterialClass *vmat = new VertexMaterialClass ();
|
||||
vmat->Set_Lighting (false);
|
||||
vmat->Set_Ambient(0,0,0);
|
||||
vmat->Set_Diffuse(0,0,0);
|
||||
vmat->Set_Specular(0,0,0);
|
||||
vmat->Set_Emissive(1,1,1);
|
||||
vmat->Set_Opacity(0.5F);
|
||||
vmat->Set_Shininess(0.0f);
|
||||
|
||||
//vmat->Set_Opacity (0.5F);
|
||||
Set_Vertex_Material (vmat);
|
||||
MEMBER_RELEASE (vmat);
|
||||
|
||||
//
|
||||
// Use an alpha shader so the box will be transparent
|
||||
//
|
||||
Set_Shader (ShaderClass::_PresetAlphaSolidShader);
|
||||
Enable_Sort ();
|
||||
|
||||
float half_width = m_Dimensions.Y / 2.0F;
|
||||
float half_height = m_Dimensions.Z / 2.0F;
|
||||
float half_depth = m_Dimensions.X / 2.0F;
|
||||
|
||||
// Determine the object space coords of our 8 verticies
|
||||
m_Verticies[0].X = -half_depth;
|
||||
m_Verticies[0].Y = half_width;
|
||||
m_Verticies[0].Z = -half_height;
|
||||
|
||||
m_Verticies[1].X = -half_depth;
|
||||
m_Verticies[1].Y = -half_width;
|
||||
m_Verticies[1].Z = -half_height;
|
||||
|
||||
m_Verticies[2].X = -half_depth;
|
||||
m_Verticies[2].Y = -half_width;
|
||||
m_Verticies[2].Z = half_height;
|
||||
|
||||
m_Verticies[3].X = -half_depth;
|
||||
m_Verticies[3].Y = half_width;
|
||||
m_Verticies[3].Z = half_height;
|
||||
|
||||
m_Verticies[4].X = half_depth;
|
||||
m_Verticies[4].Y = half_width;
|
||||
m_Verticies[4].Z = -half_height;
|
||||
|
||||
m_Verticies[5].X = half_depth;
|
||||
m_Verticies[5].Y = -half_width;
|
||||
m_Verticies[5].Z = -half_height;
|
||||
|
||||
m_Verticies[6].X = half_depth;
|
||||
m_Verticies[6].Y = -half_width;
|
||||
m_Verticies[6].Z = half_height;
|
||||
|
||||
m_Verticies[7].X = half_depth;
|
||||
m_Verticies[7].Y = half_width;
|
||||
m_Verticies[7].Z = half_height;
|
||||
|
||||
|
||||
//Set_Vertex_Color (Vector3 (0.0F, 0.0F, ((float)(iface)) * 0.15F));
|
||||
Set_Vertex_Color (Vector4 (0.0F, 0.5F, 0.0F, 0.5f));
|
||||
//Set_Vertex_Alpha (0.5F);
|
||||
|
||||
// Loop through all the faces and create them from triangle strips.
|
||||
for (int iface = 0; iface < FACE_COUNT; iface ++) {
|
||||
|
||||
Begin_Tri_Strip ();
|
||||
Easy_Vertex (m_Verticies[FACE_VERTICIES[iface][0]]);
|
||||
Easy_Vertex (m_Verticies[FACE_VERTICIES[iface][1]]);
|
||||
Easy_Vertex (m_Verticies[FACE_VERTICIES[iface][2]]);
|
||||
Easy_Vertex (m_Verticies[FACE_VERTICIES[iface][3]]);
|
||||
End_Tri_Strip ();
|
||||
}
|
||||
|
||||
Set_Collision_Type (COLLISION_TYPE_0);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Dimensions
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Set_Dimensions (const Vector3 &dimensions)
|
||||
{
|
||||
Set_Width (dimensions.Y);
|
||||
Set_Height (dimensions.Z);
|
||||
Set_Depth (dimensions.X);
|
||||
Update_Verticies ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Width
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Set_Width (float width)
|
||||
{
|
||||
width = ::fabs (width);
|
||||
|
||||
// Determine if the widht actually changed or not
|
||||
float curr_width = m_Dimensions.Y;
|
||||
if (curr_width != width) {
|
||||
|
||||
// Recalc the obj-space positions of our 8 verticies
|
||||
float half_width = width / 2.0F;
|
||||
m_Verticies[0].Y = half_width;
|
||||
m_Verticies[1].Y = -half_width;
|
||||
m_Verticies[2].Y = -half_width;
|
||||
m_Verticies[3].Y = half_width;
|
||||
m_Verticies[4].Y = half_width;
|
||||
m_Verticies[5].Y = -half_width;
|
||||
m_Verticies[6].Y = -half_width;
|
||||
m_Verticies[7].Y = half_width;
|
||||
|
||||
// Keep a flag around that will tell us we need
|
||||
// to update the verticies in the model when we're ready
|
||||
m_bDirty = true;
|
||||
m_Dimensions.Y = width;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Height
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Set_Height (float height)
|
||||
{
|
||||
height = ::fabs (height);
|
||||
|
||||
// Determine if the height actually changed or not
|
||||
float curr_height = m_Dimensions.Z;
|
||||
if (curr_height != height) {
|
||||
|
||||
// Recalc the obj-space positions of our 8 verticies
|
||||
float half_height = height / 2.0F;
|
||||
m_Verticies[0].Z = -half_height;
|
||||
m_Verticies[1].Z = -half_height;
|
||||
m_Verticies[2].Z = half_height;
|
||||
m_Verticies[3].Z = half_height;
|
||||
m_Verticies[4].Z = -half_height;
|
||||
m_Verticies[5].Z = -half_height;
|
||||
m_Verticies[6].Z = half_height;
|
||||
m_Verticies[7].Z = half_height;
|
||||
|
||||
// Keep a flag around that will tell us we need
|
||||
// to update the verticies in the model when we're ready
|
||||
m_bDirty = true;
|
||||
m_Dimensions.Z = height;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Depth
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Set_Depth (float depth)
|
||||
{
|
||||
depth = ::fabs (depth);
|
||||
|
||||
// Determine if the depth actually changed or not
|
||||
float curr_depth = m_Dimensions.X;
|
||||
if (curr_depth != depth) {
|
||||
|
||||
// Recalc the obj-space positions of our 8 verticies
|
||||
float half_depth = depth / 2.0F;
|
||||
m_Verticies[0].X = -half_depth;
|
||||
m_Verticies[1].X = -half_depth;
|
||||
m_Verticies[2].X = -half_depth;
|
||||
m_Verticies[3].X = -half_depth;
|
||||
m_Verticies[4].X = half_depth;
|
||||
m_Verticies[5].X = half_depth;
|
||||
m_Verticies[6].X = half_depth;
|
||||
m_Verticies[7].X = half_depth;
|
||||
|
||||
// Keep a flag around that will tell us we need
|
||||
// to update the verticies in the model when we're ready
|
||||
m_bDirty = true;
|
||||
m_Dimensions.X = depth;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Verticies
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Update_Verticies (void)
|
||||
{
|
||||
if (m_bDirty) {
|
||||
|
||||
// Loop through all 24 verticies in the model and
|
||||
// update their obj-space positions
|
||||
int ivertex = 0;
|
||||
for (int iface = 0; iface < FACE_COUNT; iface ++) {
|
||||
|
||||
Easy_Move_Vertex (ivertex++, m_Verticies[FACE_VERTICIES[iface][0]]);
|
||||
Easy_Move_Vertex (ivertex++, m_Verticies[FACE_VERTICIES[iface][1]]);
|
||||
Easy_Move_Vertex (ivertex++, m_Verticies[FACE_VERTICIES[iface][2]]);
|
||||
Easy_Move_Vertex (ivertex++, m_Verticies[FACE_VERTICIES[iface][3]]);
|
||||
}
|
||||
|
||||
// We're no longer dirty
|
||||
m_bDirty = false;
|
||||
Set_Dirty_Bounds ();
|
||||
Set_Dirty ();
|
||||
Invalidate_Cached_Bounding_Volumes ();
|
||||
Update_Cached_Bounding_Volumes ();
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Vertex_Lock_Position
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
Vector3
|
||||
Box3DClass::Get_Vertex_Lock_Position (int vertex)
|
||||
{
|
||||
Vector3 position (0, 0, 0);
|
||||
|
||||
// Params OK?
|
||||
if ((vertex >= 0) && (vertex < 8)) {
|
||||
|
||||
switch (vertex) {
|
||||
case 0:
|
||||
position = m_Verticies[6];
|
||||
break;
|
||||
|
||||
case 1:
|
||||
position = m_Verticies[7];
|
||||
break;
|
||||
|
||||
case 2:
|
||||
position = m_Verticies[4];
|
||||
break;
|
||||
|
||||
case 3:
|
||||
position = m_Verticies[5];
|
||||
break;
|
||||
|
||||
case 4:
|
||||
position = m_Verticies[2];
|
||||
break;
|
||||
|
||||
case 5:
|
||||
position = m_Verticies[3];
|
||||
break;
|
||||
|
||||
case 6:
|
||||
position = m_Verticies[0];
|
||||
break;
|
||||
|
||||
case 7:
|
||||
position = m_Verticies[1];
|
||||
break;
|
||||
}
|
||||
|
||||
// Convert the vertex position from obj space to world space
|
||||
//position += Get_Transform ().Get_Translation ();
|
||||
position = Get_Transform () * position;
|
||||
}
|
||||
|
||||
// Return the vertex position
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Position_Vertex
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Position_Vertex
|
||||
(
|
||||
int vertex,
|
||||
const Vector3 &new_position
|
||||
)
|
||||
{
|
||||
// Params OK?
|
||||
if ((vertex >= 0) && (vertex < 8)) {
|
||||
|
||||
// Make a box from the vertex that we are 'locking' and
|
||||
// the new position
|
||||
Make_Box (Get_Vertex_Lock_Position (vertex), new_position);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Translate_Vertex
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Translate_Vertex
|
||||
(
|
||||
int vertex,
|
||||
const Vector3 &translation
|
||||
)
|
||||
{
|
||||
// Params OK?
|
||||
if ((vertex >= 0) && (vertex < 8)) {
|
||||
|
||||
float new_width = m_Dimensions.Y;
|
||||
float new_height = m_Dimensions.Z;
|
||||
float new_depth = m_Dimensions.X;
|
||||
|
||||
// Modifiy the dimensions of the box
|
||||
new_width += translation.Y * 2.0F;
|
||||
new_height += translation.Z * 2.0F;
|
||||
new_depth += translation.X * 2.0F;
|
||||
|
||||
// Modify the dimensions of the box if they are all valid
|
||||
if ((new_width >= MIN_SIZE) &&
|
||||
(new_height >= MIN_SIZE) &&
|
||||
(new_depth >= MIN_SIZE)) {
|
||||
Set_Dimensions (Vector3 (new_depth, new_width, new_height));
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Make_Box
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Make_Box
|
||||
(
|
||||
const Vector3 &point1,
|
||||
const Vector3 &point2
|
||||
)
|
||||
{
|
||||
// Calculate the new center point for the box
|
||||
Vector3 delta = point2 - point1;
|
||||
Vector3 center = point1 + (delta / 2.0F);
|
||||
|
||||
// Recalc the box's position to be centered around the 2 points
|
||||
Matrix3D transform = Get_Transform ();
|
||||
transform.Set_Translation (center);
|
||||
Set_Transform (transform);
|
||||
|
||||
// Convert the 2 points to object space
|
||||
Matrix3D transform_inv;
|
||||
transform.Get_Orthogonal_Inverse (transform_inv);
|
||||
Vector3 obj_point1 = transform_inv * point1;
|
||||
Vector3 obj_point2 = transform_inv * point2;
|
||||
//Vector3 obj_point1 = point1 - center;
|
||||
//Vector3 obj_point2 = point2 - center;
|
||||
|
||||
// Use these 2 points to determine the bottom left
|
||||
// and upper right points of the box
|
||||
Vector3 bottom_left;
|
||||
Vector3 upper_right;
|
||||
bottom_left.X = max (obj_point1.X, obj_point2.X);
|
||||
bottom_left.Y = min (obj_point1.Y, obj_point2.Y);
|
||||
bottom_left.Z = min (obj_point1.Z, obj_point2.Z);
|
||||
upper_right.X = min (obj_point1.X, obj_point2.X);
|
||||
upper_right.Y = max (obj_point1.Y, obj_point2.Y);
|
||||
upper_right.Z = max (obj_point1.Z, obj_point2.Z);
|
||||
|
||||
// Given the bottom left and upper right coords, determine
|
||||
// what each of the 8 verticies are...
|
||||
m_Verticies[0].X = upper_right.X;
|
||||
m_Verticies[0].Y = upper_right.Y;
|
||||
m_Verticies[0].Z = bottom_left.Z;
|
||||
|
||||
m_Verticies[1].X = upper_right.X;
|
||||
m_Verticies[1].Y = bottom_left.Y;
|
||||
m_Verticies[1].Z = bottom_left.Z;
|
||||
|
||||
m_Verticies[2].X = upper_right.X;
|
||||
m_Verticies[2].Y = bottom_left.Y;
|
||||
m_Verticies[2].Z = upper_right.Z;
|
||||
|
||||
m_Verticies[3].X = upper_right.X;
|
||||
m_Verticies[3].Y = upper_right.Y;
|
||||
m_Verticies[3].Z = upper_right.Z;
|
||||
|
||||
m_Verticies[4].X = bottom_left.X;
|
||||
m_Verticies[4].Y = upper_right.Y;
|
||||
m_Verticies[4].Z = bottom_left.Z;
|
||||
|
||||
m_Verticies[5].X = bottom_left.X;
|
||||
m_Verticies[5].Y = bottom_left.Y;
|
||||
m_Verticies[5].Z = bottom_left.Z;
|
||||
|
||||
m_Verticies[6].X = bottom_left.X;
|
||||
m_Verticies[6].Y = bottom_left.Y;
|
||||
m_Verticies[6].Z = upper_right.Z;
|
||||
|
||||
m_Verticies[7].X = bottom_left.X;
|
||||
m_Verticies[7].Y = upper_right.Y;
|
||||
m_Verticies[7].Z = upper_right.Z;
|
||||
|
||||
// Recalc the box's dimensions and update its mesh
|
||||
m_Dimensions = upper_right - bottom_left;
|
||||
m_Dimensions.X = fabs (m_Dimensions.X);
|
||||
m_Dimensions.Y = fabs (m_Dimensions.Y);
|
||||
m_Dimensions.Z = fabs (m_Dimensions.Z);
|
||||
m_bDirty = true;
|
||||
Update_Verticies ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Cast_Ray
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
Box3DClass::Cast_Ray (RayCollisionTestClass & raytest)
|
||||
{
|
||||
if ((Get_Collision_Type() & raytest.CollisionType) == 0) return false;
|
||||
|
||||
Matrix3D world_to_obj;
|
||||
Get_Transform().Get_Orthogonal_Inverse(world_to_obj);
|
||||
RayCollisionTestClass objray(raytest,world_to_obj);
|
||||
|
||||
AABoxClass box;
|
||||
box.Center.Set (0, 0, 0);
|
||||
box.Extent = m_Dimensions * 0.5F;
|
||||
bool hit = CollisionMath::Collide (objray.Ray, box, raytest.Result);
|
||||
|
||||
/*OBBoxClass obbox;
|
||||
obbox.Center = Get_Transform ().Get_Translation ();
|
||||
obbox.Extent = m_Dimensions * 0.5F;
|
||||
obbox.Basis = Matrix3 (Get_Transform ());
|
||||
|
||||
CastResultStruct test_result = *raytest.Result;
|
||||
bool obb_hit = CollisionMath::Collide (raytest.Ray, obbox, &test_result);
|
||||
|
||||
WWASSERT (hit == obb_hit);*/
|
||||
|
||||
//
|
||||
// Transform result back into original coordinate system
|
||||
//
|
||||
if (hit) {
|
||||
raytest.CollidedRenderObj = this;
|
||||
if (raytest.Result->ComputeContactPoint) {
|
||||
Matrix3D::Transform_Vector (Get_Transform (), raytest.Result->ContactPoint, &(raytest.Result->ContactPoint));
|
||||
}
|
||||
}
|
||||
|
||||
return hit;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Obj_Space_Bounding_Box
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
|
||||
{
|
||||
box.Center = Vector3 (0,0,0);
|
||||
box.Extent = m_Dimensions * 0.5F;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Color
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Set_Color (const Vector3 &color)
|
||||
{
|
||||
for (int vertex = 0; vertex < VertCount; vertex ++) {
|
||||
Change_Vertex_Color (vertex, Vector4 (color.X, color.Y, color.Z, 0.5F), 0);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Render
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Render (RenderInfoClass &rinfo)
|
||||
{
|
||||
// Only render if we if flagged visible
|
||||
if (Is_Not_Hidden_At_All ()) {
|
||||
DynamicMeshClass::Render (rinfo);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Vertex_Position
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
Vector3
|
||||
Box3DClass::Get_Vertex_Position (int vertex)
|
||||
{
|
||||
// The vertex position is simply the box's world position + the vertex offset
|
||||
//Vector3 position = Get_Transform ().Get_Translation ();
|
||||
//position += m_Verticies[vertex];
|
||||
|
||||
Vector3 position = Get_Transform () * m_Verticies[vertex];
|
||||
|
||||
// Return the vertex position
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Drag_VertexXY
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Drag_VertexXY (int vertex_index, POINT point, const Vector3 &locked_vertex)
|
||||
{
|
||||
//
|
||||
// The start of the ray is simply the camera's position
|
||||
//
|
||||
Vector3 ray_start = ::Get_Camera_Mgr ()->Get_Camera ()->Get_Transform ().Get_Translation ();
|
||||
|
||||
//
|
||||
// Ensure the 'point' is correct for this mode (fullscreen/windowed)
|
||||
//
|
||||
float xpos = point.x;
|
||||
float ypos = point.y;
|
||||
::Constrain_Point_To_Aspect_Ratio (xpos, ypos);
|
||||
|
||||
//
|
||||
// The 'end' of the ray is the world coordinates of the supplied point
|
||||
//
|
||||
Vector3 ray_end;
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Device_To_World_Space (Vector2 (xpos, ypos), &ray_end);
|
||||
ray_end = ray_start + ((ray_end-ray_start) * 1000.00F);
|
||||
|
||||
//
|
||||
// If the ray isn't parallel to the z-axis, then move the corner vertex
|
||||
//
|
||||
if (fabs(ray_end.Z - ray_start.Z) > 1.0F) {
|
||||
|
||||
Vector3 vertex_pos = Get_Vertex_Position (vertex_index);
|
||||
|
||||
// Calculate the fraction of the distance along the ray where the
|
||||
// Z value of the ray is the same as the Z value of the vertex we are moving.
|
||||
// This simulates an intersection of the ray with the x-y plane at height 'z'.
|
||||
double fraction = double(vertex_pos.Z - ray_start.Z) / double(ray_end.Z - ray_start.Z);
|
||||
|
||||
// Now calcuate the 2nd point based on this fraction.
|
||||
// To do this we use the parameterized form of a line equation:
|
||||
// P = P1 + (P2 - P1) * t
|
||||
// (Where t is a percentage between 0 and 1)
|
||||
Vector3 new_point = ray_start + ((ray_end - ray_start) * fraction);
|
||||
Make_Box (locked_vertex, new_point);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Drag_VertexZ
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Box3DClass::Drag_VertexZ (int vertex_index, POINT point, const Vector3 &locked_vertex)
|
||||
{
|
||||
//
|
||||
// The start of the ray is simply the camera's position
|
||||
//
|
||||
Vector3 ray_start = ::Get_Camera_Mgr ()->Get_Camera ()->Get_Transform ().Get_Translation ();
|
||||
|
||||
//
|
||||
// Ensure the 'point' is correct for this mode (fullscreen/windowed)
|
||||
//
|
||||
float xpos = point.x;
|
||||
float ypos = point.y;
|
||||
::Constrain_Point_To_Aspect_Ratio (xpos, ypos);
|
||||
|
||||
//
|
||||
// The 'end' of the ray is the world coordinates of the supplied point
|
||||
//
|
||||
Vector3 ray_end;
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Device_To_World_Space (Vector2 (xpos, ypos), &ray_end);
|
||||
ray_end = ray_start + ((ray_end-ray_start) * 1000.00F);
|
||||
|
||||
//
|
||||
// Determine which plane (y-z or x-z) to base the movement on
|
||||
//
|
||||
float deltax = ::fabs (ray_end.X - ray_start.X);
|
||||
float deltay = ::fabs (ray_end.Y - ray_start.Y);
|
||||
|
||||
//
|
||||
// Determine where the ray intersects this plane
|
||||
//
|
||||
double fraction = 0;
|
||||
Vector3 vertex_pos = Get_Vertex_Position (vertex_index);
|
||||
if ((deltax > deltay) && (deltax != 0.0F)) {
|
||||
|
||||
// Calculate the fraction of the distance along the ray where the
|
||||
// X value of the ray is the same as the X value of the vertex.
|
||||
// This simulates an intersection of the ray with the y-z plane at depth 'x'.
|
||||
fraction = double(vertex_pos.X - ray_start.X) / double(ray_end.X - ray_start.X);
|
||||
|
||||
} else if ((deltay > deltax) && (deltay != 0.0F)) {
|
||||
|
||||
// Calculate the fraction of the distance along the ray where the
|
||||
// X value of the ray is the same as the X value of the vertex.
|
||||
// This simulates an intersection of the ray with the x-z plane at depth 'y'.
|
||||
fraction = double(vertex_pos.Y - ray_start.Y) / double(ray_end.Y - ray_start.Y);
|
||||
}
|
||||
|
||||
// If we calculated a valid fraction, then use it
|
||||
// to determine the new vertex position.
|
||||
if (min (deltax, deltay) != 0.0F) {
|
||||
|
||||
// Now calcuate the 2nd point based on this fraction.
|
||||
// To do this we use the parameterized form of a line equation:
|
||||
// P = P1 + (P2 - P1) * t
|
||||
// (Where t is a percentage between 0 and 1)
|
||||
Vector3 new_point = vertex_pos;
|
||||
new_point.Z = ray_start.Z + ((ray_end.Z - ray_start.Z) * fraction);
|
||||
Make_Box (locked_vertex, new_point);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Find_Intersection_Point
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
Find_Intersection_Point
|
||||
(
|
||||
const AABoxClass & box,
|
||||
const Vector3 & p0,
|
||||
const Vector3 & p1,
|
||||
float * percent,
|
||||
Vector3 * intersection_point
|
||||
)
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
//
|
||||
// Find the locations of each of the 6 "planes"
|
||||
// we will be testing against
|
||||
//
|
||||
float x1 = box.Center.X - box.Extent.X;
|
||||
float x2 = box.Center.X + box.Extent.X;
|
||||
float y1 = box.Center.Y - box.Extent.Y;
|
||||
float y2 = box.Center.Y + box.Extent.Y;
|
||||
float z1 = box.Center.Z - box.Extent.Z;
|
||||
float z2 = box.Center.Z + box.Extent.Z;
|
||||
|
||||
float t_values[6] = { -1, -1, -1, -1, -1, -1 };
|
||||
|
||||
Vector3 delta = p1 - p0;
|
||||
|
||||
//
|
||||
// Find the "t" values where the line intersects the
|
||||
// 2 "Y-Z" planes
|
||||
//
|
||||
if (delta.X != 0) {
|
||||
t_values[0] = (x1 - p0.X) / delta.X;
|
||||
t_values[1] = (x2 - p0.X) / delta.X;
|
||||
}
|
||||
|
||||
//
|
||||
// Find the "t" values where the line intersects the
|
||||
// 2 "X-Z" planes
|
||||
//
|
||||
if (delta.Y != 0) {
|
||||
t_values[2] = (y1 - p0.Y) / delta.Y;
|
||||
t_values[3] = (y2 - p0.Y) / delta.Y;
|
||||
}
|
||||
|
||||
//
|
||||
// Find the "t" values where the line intersects the
|
||||
// 2 "X-Y" planes
|
||||
//
|
||||
if (delta.Z != 0) {
|
||||
t_values[4] = (z1 - p0.Z) / delta.Z;
|
||||
t_values[5] = (z2 - p0.Z) / delta.Z;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop over all the "t" values we've calculated
|
||||
//
|
||||
(*percent) = 2.0F;
|
||||
for (int index = 0; index < 6; index ++) {
|
||||
|
||||
//
|
||||
// Is this "t" value the smallest in-range value we've
|
||||
// found yet?
|
||||
//
|
||||
if ( t_values[index] >= 0 &&
|
||||
t_values[index] <= 1.0F &&
|
||||
t_values[index] < (*percent))
|
||||
{
|
||||
//
|
||||
// Find the point which exists at this "t" value along the line segment
|
||||
//
|
||||
Vector3 point = p0 + delta * t_values[index];
|
||||
|
||||
//
|
||||
// If this point isn't outside the box, then we'll consider it good enough
|
||||
//
|
||||
if ( (WWMath::Fabs (point.X - box.Center.X) <= (box.Extent.X + WWMATH_EPSILON)) &&
|
||||
(WWMath::Fabs (point.Y - box.Center.Y) <= (box.Extent.Y + WWMATH_EPSILON)) &&
|
||||
(WWMath::Fabs (point.Z - box.Center.Z) <= (box.Extent.Z + WWMATH_EPSILON)))
|
||||
{
|
||||
(*percent) = t_values[index];
|
||||
(*intersection_point) = point;
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
199
Code/Tools/LevelEdit/Box3D.h
Normal file
199
Code/Tools/LevelEdit/Box3D.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/Box3D.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 3/26/01 2:05p $*
|
||||
* *
|
||||
* $Revision:: 5 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __BOX3D_H
|
||||
#define __BOX3D_H
|
||||
|
||||
|
||||
#include "Dynamesh.H"
|
||||
#include "EditorPhys.H"
|
||||
#include "Utils.H"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
class RayCollisionTestClass;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Box3DClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
class Box3DClass : public DynamicMeshClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////
|
||||
Box3DClass (void)
|
||||
: m_Dimensions (1, 1, 1),
|
||||
m_bDirty (false),
|
||||
DynamicMeshClass (12, 24) { Create_Model (); }
|
||||
|
||||
Box3DClass (float width, float height, float depth)
|
||||
: m_Dimensions (depth, width, height),
|
||||
m_bDirty (false),
|
||||
DynamicMeshClass (12, 24) { Create_Model (); }
|
||||
|
||||
Box3DClass (const Vector3 &dimensions)
|
||||
: m_Dimensions (dimensions),
|
||||
m_bDirty (false),
|
||||
DynamicMeshClass (12, 24) { Create_Model (); }
|
||||
|
||||
virtual ~Box3DClass (void) {}
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Base class overrides
|
||||
//
|
||||
bool Cast_Ray (RayCollisionTestClass &raytest);
|
||||
void Get_Obj_Space_Bounding_Box(AABoxClass & box) const;
|
||||
void Render (RenderInfoClass &rinfo);
|
||||
|
||||
|
||||
//
|
||||
// Dimension methods
|
||||
//
|
||||
void Set_Dimensions (const Vector3 &dimensions);
|
||||
void Set_Width (float width);
|
||||
void Set_Height (float height);
|
||||
void Set_Depth (float depth);
|
||||
|
||||
void Get_Dimensions (Vector3 &dimensions) const { dimensions = m_Dimensions; }
|
||||
const Vector3 & Get_Dimensions (void) const { return m_Dimensions; }
|
||||
float Get_Width (void) const { return m_Dimensions.Y; }
|
||||
float Get_Height (void) const { return m_Dimensions.Z; }
|
||||
float Get_Depth (void) const { return m_Dimensions.X; }
|
||||
|
||||
//
|
||||
// Vertex methods
|
||||
//
|
||||
void Position_Vertex (int vertex, const Vector3 &new_position);
|
||||
void Translate_Vertex (int vertex, const Vector3 &translation);
|
||||
Vector3 Get_Vertex_Position (int vertex);
|
||||
void Get_Vertex_Position (int vertex, Vector3 &position);
|
||||
Vector3 Get_Vertex_Lock_Position (int vertex);
|
||||
|
||||
//
|
||||
// Creation routines
|
||||
//
|
||||
void Make_Box (const Vector3 &point1, const Vector3 &point2);
|
||||
void Set_Color (const Vector3 &color);
|
||||
|
||||
//
|
||||
// Dynamic modification
|
||||
//
|
||||
void Drag_VertexXY (int vertex, POINT new_point, const Vector3 &locked_vertex);
|
||||
void Drag_VertexZ (int vertex, POINT new_point, const Vector3 &locked_vertex);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
//////////////////////////////////////////////////////////
|
||||
void Create_Model (void);
|
||||
void Easy_Vertex (const Vector3 &vertex) { DynamicMeshClass::Vertex (vertex.X, vertex.Y, vertex.Z, 0, 0); }
|
||||
void Easy_Move_Vertex (int vertex_index, const Vector3 &vertex) { DynamicMeshClass::Move_Vertex (vertex_index, vertex.X, vertex.Y, vertex.Z); }
|
||||
void Update_Verticies (void);
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////
|
||||
Vector3 m_Dimensions;
|
||||
Vector3 m_Verticies[8];
|
||||
bool m_bDirty;
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Box3DPhysClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
class Box3DPhysClass : public EditorPhysClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////
|
||||
Box3DPhysClass (void)
|
||||
: m_pBox (NULL) { Initialize (1, 1, 1); }
|
||||
|
||||
Box3DPhysClass (const Vector3 &dimensions)
|
||||
: m_pBox (NULL) { Initialize (dimensions.X, dimensions.Y, dimensions.Z); }
|
||||
|
||||
virtual ~Box3DPhysClass (void) { MEMBER_RELEASE (m_pBox); }
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public operators/methods
|
||||
//////////////////////////////////////////////////////////
|
||||
operator Box3DClass * (void) const { return m_pBox; }
|
||||
Box3DClass * Get_Box (void) const { return m_pBox; }
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Protected member data
|
||||
//////////////////////////////////////////////////////////
|
||||
void Initialize (float x, float y, float z) { m_pBox = new Box3DClass (x, y, z); Set_Model (m_pBox); }
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////
|
||||
Box3DClass * m_pBox;
|
||||
};
|
||||
|
||||
|
||||
#endif //__BOX3D_H
|
||||
|
||||
626
Code/Tools/LevelEdit/BuildingNode.cpp
Normal file
626
Code/Tools/LevelEdit/BuildingNode.cpp
Normal file
@@ -0,0 +1,626 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/BuildingNode.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 9/13/01 9:44a $*
|
||||
* *
|
||||
* $Revision:: 7 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "buildingnode.h"
|
||||
#include "buildingchildnode.h"
|
||||
#include "sceneeditor.h"
|
||||
#include "filemgr.h"
|
||||
#include "_assetmgr.h"
|
||||
#include "editorassetmgr.h"
|
||||
#include "w3d_file.h"
|
||||
#include "cameramgr.h"
|
||||
#include "collisiongroups.h"
|
||||
#include "persistfactory.h"
|
||||
#include "preset.h"
|
||||
#include "editorchunkids.h"
|
||||
#include "modelutils.h"
|
||||
#include "vehiclefactorygameobj.h"
|
||||
#include "refinerygameobj.h"
|
||||
#include "nodemgr.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Persist factory
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
SimplePersistFactoryClass<BuildingNodeClass, CHUNKID_NODE_BUILDING> _BuildingNodePersistFactory;
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
CHUNKID_VARIABLES = 0x09071125,
|
||||
CHUNKID_BASE_CLASS,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VARID_VISOBJECTID = 0x01,
|
||||
VARID_VISSECTORID,
|
||||
VARID_CHILD_NODE
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BuildingNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
BuildingNodeClass::BuildingNodeClass (PresetClass *preset)
|
||||
: m_PhysObj (NULL),
|
||||
ObjectNodeClass (preset)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BuildingNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
BuildingNodeClass::BuildingNodeClass (const BuildingNodeClass &src)
|
||||
: m_PhysObj (NULL),
|
||||
ObjectNodeClass (NULL)
|
||||
{
|
||||
(*this) = src;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~BuildingNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
BuildingNodeClass::~BuildingNodeClass (void)
|
||||
{
|
||||
Free_Child_Nodes ();
|
||||
Remove_From_Scene ();
|
||||
MEMBER_RELEASE (m_PhysObj);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Initialize
|
||||
//
|
||||
// Note: This may be called more than once. It is used as an 'initialize'
|
||||
// and a 're-initialize'.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
BuildingNodeClass::Initialize (void)
|
||||
{
|
||||
MEMBER_RELEASE (m_PhysObj);
|
||||
|
||||
//
|
||||
// Load the model we want to use to identify the building controller
|
||||
//
|
||||
RenderObjClass *render_obj = ::Create_Render_Obj ("BUILDINGICON");
|
||||
if (render_obj != NULL) {
|
||||
|
||||
//
|
||||
// Create the new physics object
|
||||
//
|
||||
m_PhysObj = new DecorationPhysClass;
|
||||
m_PhysObj->Set_Model (render_obj);
|
||||
m_PhysObj->Set_Collision_Group (EDITOR_COLLISION_GROUP);
|
||||
m_PhysObj->Peek_Model ()->Set_User_Data ((PVOID)&m_HitTestInfo, FALSE);
|
||||
m_PhysObj->Set_Transform (m_Transform);
|
||||
::Set_Model_Collision_Type (m_PhysObj->Peek_Model (), COLLISION_TYPE_0);
|
||||
render_obj->Release_Ref ();
|
||||
}
|
||||
|
||||
ObjectNodeClass::Initialize ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Factory
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
const PersistFactoryClass &
|
||||
BuildingNodeClass::Get_Factory (void) const
|
||||
{
|
||||
return _BuildingNodePersistFactory;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// operator=
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
const BuildingNodeClass &
|
||||
BuildingNodeClass::operator= (const BuildingNodeClass &src)
|
||||
{
|
||||
//
|
||||
// Start fresh
|
||||
//
|
||||
Free_Child_Nodes ();
|
||||
|
||||
//
|
||||
// Copy the child node list
|
||||
//
|
||||
for (int index = 0; index < src.m_ChildNodes.Count (); index ++) {
|
||||
NodeClass *child_node = src.m_ChildNodes[index];
|
||||
if (child_node != NULL) {
|
||||
Add_Child_Node (child_node->Get_Transform ());
|
||||
}
|
||||
}
|
||||
|
||||
NodeClass::operator= (src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
BuildingNodeClass::Save (ChunkSaveClass &csave)
|
||||
{
|
||||
csave.Begin_Chunk (CHUNKID_BASE_CLASS);
|
||||
ObjectNodeClass::Save (csave);
|
||||
csave.End_Chunk ();
|
||||
|
||||
csave.Begin_Chunk (CHUNKID_VARIABLES);
|
||||
|
||||
//
|
||||
// Save the list of child node transforms
|
||||
//
|
||||
for (int index = 0; index < m_ChildNodes.Count (); index ++) {
|
||||
NodeClass *child_node = m_ChildNodes[index];
|
||||
if (child_node != NULL) {
|
||||
Matrix3D tm = child_node->Get_Transform ();
|
||||
WRITE_MICRO_CHUNK (csave, VARID_CHILD_NODE, tm);
|
||||
}
|
||||
}
|
||||
|
||||
csave.End_Chunk ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
BuildingNodeClass::Load (ChunkLoadClass &cload)
|
||||
{
|
||||
while (cload.Open_Chunk ()) {
|
||||
switch (cload.Cur_Chunk_ID ()) {
|
||||
|
||||
case CHUNKID_BASE_CLASS:
|
||||
ObjectNodeClass::Load (cload);
|
||||
break;
|
||||
|
||||
case CHUNKID_VARIABLES:
|
||||
Load_Variables (cload);
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Chunk ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_Variables
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
BuildingNodeClass::Load_Variables (ChunkLoadClass &cload)
|
||||
{
|
||||
while (cload.Open_Micro_Chunk ()) {
|
||||
switch (cload.Cur_Micro_Chunk_ID ()) {
|
||||
|
||||
case VARID_CHILD_NODE:
|
||||
{
|
||||
//
|
||||
// Read the child node's transfrom from the chunk
|
||||
//
|
||||
Matrix3D tm;
|
||||
cload.Read (&tm, sizeof (tm));
|
||||
|
||||
//
|
||||
// Add a new child node at this location
|
||||
//
|
||||
Add_Child_Node (tm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Micro_Chunk ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Pre_Export
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
BuildingNodeClass::Pre_Export (void)
|
||||
{
|
||||
Add_Ref ();
|
||||
if (m_PhysObj != NULL && m_IsInScene) {
|
||||
::Get_Scene_Editor ()->Remove_Object (m_PhysObj);
|
||||
|
||||
//
|
||||
// Configure the building object (if necessary)
|
||||
//
|
||||
BuildingGameObj *building = Get_Building ();
|
||||
if (building != NULL) {
|
||||
|
||||
//
|
||||
// What type of building is this?
|
||||
//
|
||||
if (building->As_VehicleFactoryGameObj () != NULL) {
|
||||
VehicleFactoryGameObj *airstrip = building->As_VehicleFactoryGameObj ();
|
||||
|
||||
//
|
||||
// Configure the factory's creation transform
|
||||
//
|
||||
if (m_ChildNodes.Count () > 0) {
|
||||
airstrip->Set_Creation_TM (m_ChildNodes[0]->Get_Transform ());
|
||||
}
|
||||
|
||||
} else if (building->As_RefineryGameObj () != NULL) {
|
||||
RefineryGameObj *refinery = building->As_RefineryGameObj ();
|
||||
|
||||
//
|
||||
// Configure the refinery's docking transform
|
||||
//
|
||||
if (m_ChildNodes.Count () > 0) {
|
||||
refinery->Set_Dock_TM (m_ChildNodes[0]->Get_Transform ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Pass the Pre_Export call onto any child nodes as well
|
||||
//
|
||||
for (int index = 0; index < m_ChildNodes.Count (); index ++) {
|
||||
NodeClass *child_node = m_ChildNodes[index];
|
||||
EditorLineClass *line = m_ChildLines[index];
|
||||
|
||||
//
|
||||
// Remove the line from the scene
|
||||
//
|
||||
::Get_Scene_Editor ()->Remove_Object (line);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Post_Export
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
BuildingNodeClass::Post_Export (void)
|
||||
{
|
||||
if (m_PhysObj != NULL && m_IsInScene) {
|
||||
::Get_Scene_Editor ()->Add_Dynamic_Object (m_PhysObj);
|
||||
|
||||
//
|
||||
// Pass the Post_Export call onto any child nodes as well
|
||||
//
|
||||
for (int index = 0; index < m_ChildNodes.Count (); index ++) {
|
||||
NodeClass *child_node = m_ChildNodes[index];
|
||||
EditorLineClass *line = m_ChildLines[index];
|
||||
|
||||
//
|
||||
// Add the line back into the world
|
||||
//
|
||||
::Get_Scene_Editor ()->Add_Dynamic_Object (line);
|
||||
}
|
||||
}
|
||||
|
||||
Release_Ref ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Add_Child_Node
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
NodeClass *
|
||||
BuildingNodeClass::Add_Child_Node (const Matrix3D &tm)
|
||||
{
|
||||
BuildingChildNodeClass *child_node = new BuildingChildNodeClass;
|
||||
child_node->Initialize ();
|
||||
child_node->Set_Transform (tm);
|
||||
child_node->Set_Building (this);
|
||||
NodeMgrClass::Setup_Node_Identity (*child_node);
|
||||
m_ChildNodes.Add (child_node);
|
||||
|
||||
//
|
||||
// Create and add the line from the building to the child node
|
||||
//
|
||||
EditorLineClass *line = new EditorLineClass;
|
||||
line->Reset (m_Transform.Get_Translation (), tm.Get_Translation ());
|
||||
m_ChildLines.Add (line);
|
||||
|
||||
//
|
||||
// Add the objects to the scene if necessary
|
||||
//
|
||||
if (m_IsInScene) {
|
||||
child_node->Add_To_Scene ();
|
||||
::Get_Scene_Editor ()->Add_Dynamic_Object (line);
|
||||
}
|
||||
|
||||
return child_node;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Can_Add_Child_Nodes
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
BuildingNodeClass::Can_Add_Child_Nodes (void) const
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
BuildingGameObj *building = Get_Building ();
|
||||
if (building != NULL) {
|
||||
|
||||
//
|
||||
// Is this one of the types of buildings which need
|
||||
// child nodes?
|
||||
//
|
||||
if (building->As_VehicleFactoryGameObj () != NULL) {
|
||||
|
||||
//
|
||||
// This type of building can only have one child node
|
||||
//
|
||||
if (m_ChildNodes.Count () == 0) {
|
||||
retval = true;
|
||||
}
|
||||
|
||||
} else if (building->As_RefineryGameObj () != NULL) {
|
||||
|
||||
//
|
||||
// This type of building can only have one child node
|
||||
//
|
||||
if (m_ChildNodes.Count () == 0) {
|
||||
retval = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Remove_Child_Node
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
BuildingNodeClass::Remove_Child_Node (NodeClass *child_node)
|
||||
{
|
||||
//
|
||||
// Try to find the child node
|
||||
//
|
||||
for (int index = 0; index < m_ChildNodes.Count (); index ++) {
|
||||
if (child_node == m_ChildNodes[index]) {
|
||||
|
||||
//
|
||||
// Free the child node
|
||||
//
|
||||
MEMBER_RELEASE (child_node);
|
||||
m_ChildNodes.Delete (index);
|
||||
|
||||
//
|
||||
// Remove and free the line to the child node
|
||||
//
|
||||
::Get_Scene_Editor ()->Remove_Object (m_ChildLines[index]);
|
||||
m_ChildLines[index]->Release_Ref ();
|
||||
m_ChildLines.Delete (index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Free_Child_Nodes
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
BuildingNodeClass::Free_Child_Nodes (void)
|
||||
{
|
||||
SceneEditorClass *scene = ::Get_Scene_Editor ();
|
||||
|
||||
//
|
||||
// Release our hold on each child node
|
||||
//
|
||||
for (int index = 0; index < m_ChildNodes.Count (); index ++) {
|
||||
NodeClass *child_node = m_ChildNodes[index];
|
||||
EditorLineClass *line = m_ChildLines[index];
|
||||
|
||||
scene->Remove_Object (line);
|
||||
child_node->Remove_From_Scene ();
|
||||
MEMBER_RELEASE (child_node);
|
||||
MEMBER_RELEASE (line);
|
||||
}
|
||||
|
||||
//
|
||||
// Remove all the child nodes from the list
|
||||
//
|
||||
m_ChildNodes.Delete_All ();
|
||||
m_ChildLines.Delete_All ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Add_To_Scene
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
BuildingNodeClass::Add_To_Scene (void)
|
||||
{
|
||||
SceneEditorClass *scene = ::Get_Scene_Editor ();
|
||||
|
||||
//
|
||||
// Add all the waypoints to the scene
|
||||
//
|
||||
for (int index = 0; index < m_ChildNodes.Count (); index ++) {
|
||||
NodeClass *child_node = m_ChildNodes[index];
|
||||
EditorLineClass *line = m_ChildLines[index];
|
||||
child_node->Add_To_Scene ();
|
||||
scene->Add_Dynamic_Object (line);
|
||||
}
|
||||
|
||||
NodeClass::Add_To_Scene ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Remove_From_Scene
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
BuildingNodeClass::Remove_From_Scene (void)
|
||||
{
|
||||
SceneEditorClass *scene = ::Get_Scene_Editor ();
|
||||
if (scene != NULL && m_IsInScene) {
|
||||
|
||||
//
|
||||
// Remove all the waypoints from the scene
|
||||
//
|
||||
for (int index = 0; index < m_ChildNodes.Count (); index ++) {
|
||||
NodeClass *child_node = m_ChildNodes[index];
|
||||
EditorLineClass *line = m_ChildLines[index];
|
||||
child_node->Remove_From_Scene ();
|
||||
scene->Remove_Object (line);
|
||||
}
|
||||
}
|
||||
|
||||
NodeClass::Remove_From_Scene ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Lines
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
BuildingNodeClass::Update_Lines (void)
|
||||
{
|
||||
for (int index = 0; index < m_ChildNodes.Count (); index ++) {
|
||||
NodeClass *child_node = m_ChildNodes[index];
|
||||
EditorLineClass *line = m_ChildLines[index];
|
||||
|
||||
//
|
||||
// Update the line between the node and its child
|
||||
//
|
||||
line->Reset (Get_Transform ().Get_Translation (), child_node->Get_Position ());
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Hide
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
BuildingNodeClass::Hide (bool hide)
|
||||
{
|
||||
//
|
||||
// Apply the same operation to all the child nodes and lines
|
||||
//
|
||||
for (int index = 0; index < m_ChildNodes.Count (); index ++) {
|
||||
NodeClass *child_node = m_ChildNodes[index];
|
||||
EditorLineClass *line = m_ChildLines[index];
|
||||
child_node->Hide (hide);
|
||||
line->Hide (hide);
|
||||
}
|
||||
|
||||
NodeClass::Hide (hide);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Sub_Node
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
NodeClass *
|
||||
BuildingNodeClass::Get_Sub_Node (int index)
|
||||
{
|
||||
return m_ChildNodes[index];
|
||||
}
|
||||
241
Code/Tools/LevelEdit/BuildingNode.h
Normal file
241
Code/Tools/LevelEdit/BuildingNode.h
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/BuildingNode.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 5/11/01 9:04a $*
|
||||
* *
|
||||
* $Revision:: 6 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __BUILDING_NODE_H
|
||||
#define __BUILDING_NODE_H
|
||||
|
||||
#include "objectnode.h"
|
||||
#include "vector.h"
|
||||
#include "icons.h"
|
||||
#include "decophys.h"
|
||||
#include "building.h"
|
||||
#include "editorline.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class PresetClass;
|
||||
class BuildingChildNodeClass;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BuildingNodeClass
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class BuildingNodeClass : public ObjectNodeClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////////////
|
||||
BuildingNodeClass (PresetClass *preset = NULL);
|
||||
BuildingNodeClass (const BuildingNodeClass &src);
|
||||
~BuildingNodeClass (void);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public operators
|
||||
//////////////////////////////////////////////////////////////
|
||||
const BuildingNodeClass &operator= (const BuildingNodeClass &src);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
// From PersistClass
|
||||
virtual const PersistFactoryClass & Get_Factory (void) const;
|
||||
|
||||
// From NodeClass
|
||||
void Initialize (void);
|
||||
NodeClass * Clone (void) { return new BuildingNodeClass (*this); }
|
||||
NODE_TYPE Get_Type (void) const { return NODE_TYPE_BUILDING; }
|
||||
int Get_Icon_Index (void) const { return BUILDING_ICON; }
|
||||
PhysClass * Peek_Physics_Obj (void) const { return m_PhysObj; }
|
||||
bool Is_Static (void) const { return false; }
|
||||
bool Can_Be_Rotated_Freely (void) const { return true; }
|
||||
void On_Rotate (void);
|
||||
void On_Translate (void);
|
||||
void On_Transform (void);
|
||||
void Add_To_Scene (void);
|
||||
void Remove_From_Scene (void);
|
||||
void Hide (bool hide);
|
||||
NodeClass * Add_Child_Node (const Matrix3D &tm);
|
||||
bool Can_Add_Child_Nodes (void) const;
|
||||
|
||||
int Get_Sub_Node_Count (void) const { return m_ChildNodes.Count (); }
|
||||
NodeClass * Get_Sub_Node (int index);
|
||||
|
||||
//
|
||||
// Export methods
|
||||
//
|
||||
void Pre_Export (void);
|
||||
void Post_Export (void);
|
||||
|
||||
//
|
||||
// From PersistClass
|
||||
//
|
||||
bool Save (ChunkSaveClass &csave);
|
||||
bool Load (ChunkLoadClass &cload);
|
||||
|
||||
//
|
||||
// Building specific
|
||||
//
|
||||
void Enable_Power (bool onoff);
|
||||
bool Is_Power_Enabled (void) const;
|
||||
void Set_Normalized_Health (float health);
|
||||
void Remove_Child_Node (NodeClass *child_node);
|
||||
void Update_Lines (void);
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
//////////////////////////////////////////////////////////////////
|
||||
bool Load_Variables (ChunkLoadClass &cload);
|
||||
void Free_Child_Nodes (void);
|
||||
BuildingGameObj * Get_Building (void) const { return reinterpret_cast<BuildingGameObj *> (m_GameObj); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Protected member data
|
||||
//////////////////////////////////////////////////////////////////
|
||||
DecorationPhysClass * m_PhysObj;
|
||||
DynamicVectorClass<BuildingChildNodeClass *> m_ChildNodes;
|
||||
DynamicVectorClass<EditorLineClass *> m_ChildLines;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Rotate
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
BuildingNodeClass::On_Rotate (void)
|
||||
{
|
||||
if (m_GameObj != NULL) {
|
||||
((BuildingGameObj *)m_GameObj)->Set_Position (m_Transform.Get_Translation ());
|
||||
}
|
||||
|
||||
Update_Lines ();
|
||||
NodeClass::On_Rotate ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Translate
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
BuildingNodeClass::On_Translate (void)
|
||||
{
|
||||
if (m_GameObj != NULL) {
|
||||
((BuildingGameObj *)m_GameObj)->Set_Position (m_Transform.Get_Translation ());
|
||||
}
|
||||
|
||||
Update_Lines ();
|
||||
NodeClass::On_Translate ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Transform
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
BuildingNodeClass::On_Transform (void)
|
||||
{
|
||||
if (m_GameObj != NULL) {
|
||||
((BuildingGameObj *)m_GameObj)->Set_Position (m_Transform.Get_Translation ());
|
||||
}
|
||||
|
||||
Update_Lines ();
|
||||
NodeClass::On_Transform ();
|
||||
return ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Enable_Power
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
BuildingNodeClass::Enable_Power (bool onoff)
|
||||
{
|
||||
if (m_GameObj != NULL) {
|
||||
((BuildingGameObj *)m_GameObj)->Enable_Power (onoff);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Is_Power_Enabled
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline bool
|
||||
BuildingNodeClass::Is_Power_Enabled (void) const
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
if (m_GameObj != NULL) {
|
||||
retval = ((BuildingGameObj *)m_GameObj)->Is_Power_Enabled ();
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Set_Normalized_Health
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
BuildingNodeClass::Set_Normalized_Health (float health)
|
||||
{
|
||||
if (m_GameObj != NULL) {
|
||||
((BuildingGameObj *)m_GameObj)->Set_Normalized_Health (health);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif //__BUILDING_NODE_H
|
||||
|
||||
1314
Code/Tools/LevelEdit/CameraMgr.cpp
Normal file
1314
Code/Tools/LevelEdit/CameraMgr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
220
Code/Tools/LevelEdit/CameraMgr.h
Normal file
220
Code/Tools/LevelEdit/CameraMgr.h
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/CameraMgr.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 11/02/00 5:57p $*
|
||||
* *
|
||||
* $Revision:: 11 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __CAMERAMGR_H
|
||||
#define __CAMERAMGR_H
|
||||
|
||||
|
||||
#include "refcount.h"
|
||||
#include "utils.h"
|
||||
#include "rendobj.h"
|
||||
#include "assetmgr.h"
|
||||
#include "camera.h"
|
||||
#include "physcontrol.h"
|
||||
#include "hermitespline.h"
|
||||
|
||||
|
||||
// Forward declarations
|
||||
class NodeClass;
|
||||
class SoldierGameObj;
|
||||
class SoldierGameObjDef;
|
||||
|
||||
|
||||
/*class CamaraCharPhys : public CharPhysClass
|
||||
{
|
||||
public:
|
||||
CamaraCharPhys (void);
|
||||
virtual ~CamaraCharPhys (void);
|
||||
|
||||
protected:
|
||||
RenderObjClass * m_pRenderObj;
|
||||
};*/
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CameraMgr
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
class CameraMgr
|
||||
{
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
///////////////////////////////////////////////////
|
||||
CameraMgr (void);
|
||||
virtual ~CameraMgr (void);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Public data types
|
||||
///////////////////////////////////////////////////
|
||||
typedef enum
|
||||
{
|
||||
MODE_MOVE_PLANE = 0,
|
||||
MODE_MOVE_UPDOWN = 1,
|
||||
MODE_FLY_THROUGH = 2,
|
||||
MODE_WALK_THROUGH = 3,
|
||||
MODE_ROTATE_FREE = 4,
|
||||
MODE_ROTATE_X = 5,
|
||||
MODE_ROTATE_Y = 6,
|
||||
MODE_ROTATE_Z = 7,
|
||||
MODE_ORBIT = 8,
|
||||
MODE_FLYTO = 9,
|
||||
MODE_COUNT
|
||||
|
||||
} CAMERA_MODE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CAMERA_FRONT = 1,
|
||||
CAMERA_BACK,
|
||||
CAMERA_TOP,
|
||||
CAMERA_BOTTOM,
|
||||
CAMERA_LEFT,
|
||||
CAMERA_RIGHT,
|
||||
CAMERA_COUNT
|
||||
|
||||
} CAMERA_POS;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////
|
||||
CameraMgr::CAMERA_MODE Get_Camera_Mode (void) const { return m_CameraMode; }
|
||||
void Set_Camera_Mode (CAMERA_MODE new_mode);
|
||||
void Update_Camera (float deltax, float deltay);
|
||||
void Update_Camera_Animation (void);
|
||||
void On_Frame (void);
|
||||
Matrix3D Get_Character_TM (void);
|
||||
|
||||
//
|
||||
// Position methods
|
||||
//
|
||||
void Set_Camera_Pos (CAMERA_POS position);
|
||||
void Set_Transform (const Matrix3D &transform);
|
||||
void Set_Position (const Vector3 &position);
|
||||
void Move_Fwd (void) {}
|
||||
void Move_Bkwd (void) {}
|
||||
void Turn_Left (void) {}
|
||||
void Turn_Right (void) {}
|
||||
void Look_Up (void) {}
|
||||
void Look_Dn (void) {}
|
||||
void Look_Center (void) {}
|
||||
void Increase_Speed (void);
|
||||
void Decrease_Speed (void);
|
||||
void Level_Camera (void);
|
||||
void Goto_Node (NodeClass *node);
|
||||
void Goto_Group (GroupMgrClass *pgroup);
|
||||
void Fly_To_Transform (const Matrix3D &transform);
|
||||
|
||||
//
|
||||
// Inline accessors
|
||||
//
|
||||
CameraClass * Get_Camera (void) const { return m_pCamera; }
|
||||
//CamaraCharPhys * Get_Walkthru_Character (void) const { return m_pWalkThroughPhys; }
|
||||
float Get_Speed_Modifier (void) const { return m_SpeedModifier; }
|
||||
|
||||
protected:
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Friends
|
||||
///////////////////////////////////////////////////
|
||||
friend LRESULT CALLBACK fnCameraKeyboardHook (int code, WPARAM wParam, LPARAM lParam);
|
||||
friend class CLevelEditView;
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
///////////////////////////////////////////////////
|
||||
void Init_Camera (void);
|
||||
void Auto_Level (void);
|
||||
void Update_Fly_To (void);
|
||||
|
||||
static void Update_Camera_MOVE_ZOOM (CameraClass &camera, float deltax, float deltay);
|
||||
static void Update_Camera_MOVE_PLANE (CameraClass &camera, float deltax, float deltay);
|
||||
static void Update_Camera_FLY_THROUGH (CameraClass &camera, float deltax, float deltay);
|
||||
static void Update_Camera_WALK_THROUGH (CameraClass &camera, float deltax, float deltay);
|
||||
static void Update_Camera_ROTATE_FREE (CameraClass &camera, float deltax, float deltay);
|
||||
static void Update_Camera_ROTATE_X (CameraClass &camera, float deltax, float deltay);
|
||||
static void Update_Camera_ROTATE_Y (CameraClass &camera, float deltax, float deltay);
|
||||
static void Update_Camera_ROTATE_Z (CameraClass &camera, float deltax, float deltay);
|
||||
static void Update_Camera_ORBIT (CameraClass &camera, float deltax, float deltay);
|
||||
static void Update_Camera_FLY_TO (CameraClass &camera, float deltax, float deltay);
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Protected data types
|
||||
///////////////////////////////////////////////////
|
||||
typedef void (*UPDATE_CAMERA_FN) (CameraClass &camera, float deltax, float deltay);
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Static member data
|
||||
///////////////////////////////////////////////////
|
||||
static bool _pKeyboardState[256];
|
||||
static UPDATE_CAMERA_FN _pfnUpdateMethods[CAMERA_MODE::MODE_COUNT];
|
||||
static HHOOK _hHook;
|
||||
|
||||
private:
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Private member data
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
bool m_bAutoLevel;
|
||||
CameraClass * m_pCamera;
|
||||
CAMERA_MODE m_CameraMode;
|
||||
Matrix3D m_AutoLevelInitalMatrix;
|
||||
Matrix3D m_AutoLevelEndMatrix;
|
||||
double m_AutoLevelPercent;
|
||||
//CamaraCharPhys * m_pWalkThroughPhys;
|
||||
PhysControllerClass m_VJoystick;
|
||||
float m_SpeedModifier;
|
||||
HermiteSpline3DClass m_FlyToSpline;
|
||||
Matrix3D m_FlyToStartTransform;
|
||||
Matrix3D m_FlyToEndTransform;
|
||||
DWORD m_FlyToStartTime;
|
||||
|
||||
SoldierGameObj * m_WalkThruObj;
|
||||
SoldierGameObjDef * m_WalkThruDef;
|
||||
};
|
||||
|
||||
|
||||
#endif //__CAMERAMGR_H
|
||||
241
Code/Tools/LevelEdit/CameraSettingsForm.cpp
Normal file
241
Code/Tools/LevelEdit/CameraSettingsForm.cpp
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// ameraSettingsFormClass.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "leveledit.h"
|
||||
#include "CameraSettingsForm.H"
|
||||
#include "Utils.H"
|
||||
#include "CameraMgr.H"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CameraSettingsFormClass
|
||||
//
|
||||
CameraSettingsFormClass::CameraSettingsFormClass (void)
|
||||
: DockableFormClass(CameraSettingsFormClass::IDD)
|
||||
{
|
||||
//{{AFX_DATA_INIT(CameraSettingsFormClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~CameraSettingsFormClass
|
||||
//
|
||||
CameraSettingsFormClass::~CameraSettingsFormClass (void)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
void
|
||||
CameraSettingsFormClass::DoDataExchange (CDataExchange* pDX)
|
||||
{
|
||||
DockableFormClass::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(CameraSettingsFormClass)
|
||||
// NOTE: the ClassWizard will add DDX and DDV calls here
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(CameraSettingsFormClass, DockableFormClass)
|
||||
//{{AFX_MSG_MAP(CameraSettingsFormClass)
|
||||
ON_NOTIFY(UDN_DELTAPOS, IDC_DEPTH_SPIN, OnDeltaPosDepthSpin)
|
||||
ON_EN_UPDATE(IDC_DEPTH_EDIT, OnUpdateDepthEdit)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CameraSettingsFormClass diagnostics
|
||||
|
||||
#ifdef _DEBUG
|
||||
void CameraSettingsFormClass::AssertValid() const
|
||||
{
|
||||
DockableFormClass::AssertValid();
|
||||
}
|
||||
|
||||
void CameraSettingsFormClass::Dump(CDumpContext& dc) const
|
||||
{
|
||||
DockableFormClass::Dump(dc);
|
||||
}
|
||||
#endif //_DEBUG
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// HandleInitDialog
|
||||
//
|
||||
void
|
||||
CameraSettingsFormClass::HandleInitDialog (void)
|
||||
{
|
||||
// Set the depth range
|
||||
SendDlgItemMessage (IDC_DEPTH_SPIN, UDM_SETRANGE, 0, MAKELPARAM (4000, 20));
|
||||
|
||||
// Put the current camera information into the controls
|
||||
Update_Controls ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Controls
|
||||
//
|
||||
void
|
||||
CameraSettingsFormClass::Update_Controls (void)
|
||||
{
|
||||
CameraMgr *pcamera_mgr = ::Get_Camera_Mgr ();
|
||||
if (pcamera_mgr != NULL) {
|
||||
const Matrix3D &transform = pcamera_mgr->Get_Camera ()->Get_Transform ();
|
||||
CString temp_string;
|
||||
|
||||
// Put the x position of the camera into the controls
|
||||
temp_string.Format ("%.2f", transform.Get_X_Translation ());
|
||||
SetDlgItemText (IDC_POSX_EDIT, temp_string);
|
||||
|
||||
// Put the y position of the camera into the controls
|
||||
temp_string.Format ("%.2f", transform.Get_Y_Translation ());
|
||||
SetDlgItemText (IDC_POSY_EDIT, temp_string);
|
||||
|
||||
// Put the z position of the camera into the controls
|
||||
temp_string.Format ("%.2f", transform.Get_Z_Translation ());
|
||||
SetDlgItemText (IDC_POSZ_EDIT, temp_string);
|
||||
|
||||
// Put the x rotation of the camera into the controls
|
||||
temp_string.Format ("%.2f", (float)RAD_TO_DEG (transform.Get_X_Rotation ()));
|
||||
SetDlgItemText (IDC_ROTATEX_EDIT, temp_string);
|
||||
|
||||
// Put the y rotation of the camera into the controls
|
||||
temp_string.Format ("%.2f", (float)RAD_TO_DEG (transform.Get_Y_Rotation ()));
|
||||
SetDlgItemText (IDC_ROTATEY_EDIT, temp_string);
|
||||
|
||||
// Put the z rotation of the camera into the controls
|
||||
temp_string.Format ("%.2f", (float)RAD_TO_DEG (transform.Get_Z_Rotation ()));
|
||||
SetDlgItemText (IDC_ROTATEZ_EDIT, temp_string);
|
||||
|
||||
// Put the current depth of the camera into its dialog control
|
||||
float near_plane = 0;
|
||||
float far_plane = 0;
|
||||
pcamera_mgr->Get_Camera ()->Get_Clip_Planes (near_plane, far_plane);
|
||||
SetDlgItemInt (IDC_DEPTH_EDIT, (int)far_plane);
|
||||
SendDlgItemMessage (IDC_DEPTH_SPIN, 0, MAKELPARAM ((short)far_plane, 0));
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDeltaPosDepthSpin
|
||||
//
|
||||
void
|
||||
CameraSettingsFormClass::OnDeltaPosDepthSpin
|
||||
(
|
||||
NMHDR* pNMHDR,
|
||||
LRESULT* pResult
|
||||
)
|
||||
{
|
||||
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
|
||||
if (pNMUpDown) {
|
||||
Set_Depth (pNMUpDown->iPos);
|
||||
}
|
||||
|
||||
*pResult = 0;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnUpdateDepthEdit
|
||||
//
|
||||
void
|
||||
CameraSettingsFormClass::OnUpdateDepthEdit (void)
|
||||
{
|
||||
Set_Depth (GetDlgItemInt (IDC_DEPTH_EDIT));
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Depth
|
||||
//
|
||||
void
|
||||
CameraSettingsFormClass::Set_Depth (int new_depth)
|
||||
{
|
||||
CameraMgr *pcamera_mgr = ::Get_Camera_Mgr ();
|
||||
if (pcamera_mgr != NULL) {
|
||||
|
||||
// Get the current 'near' clip plane
|
||||
double near_plane = 0;
|
||||
double far_plane = 0;
|
||||
//pcamera_mgr->Get_Camera ()->Get_Clip_Planes (near_plane, far_plane);
|
||||
|
||||
// Set the new 'far' clip plane
|
||||
//pcamera_mgr->Get_Camera ()->Set_Clip_Planes (near_plane, (double)new_depth);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WindowProc
|
||||
//
|
||||
LRESULT
|
||||
CameraSettingsFormClass::WindowProc
|
||||
(
|
||||
UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam
|
||||
)
|
||||
{
|
||||
// Is this the message we are expecting?
|
||||
if ((message == WM_SHOWWINDOW) || (message == WM_ACTIVATE)) {
|
||||
|
||||
// Make sure the controls reflect the current state when we are
|
||||
// shown
|
||||
if ((BOOL)LOWORD (wParam)) {
|
||||
Update_Controls ();
|
||||
}
|
||||
}
|
||||
|
||||
// Allow the base class to process this message
|
||||
return DockableFormClass::WindowProc(message, wParam, lParam);
|
||||
}
|
||||
|
||||
161
Code/Tools/LevelEdit/CheckinStyleDialog.cpp
Normal file
161
Code/Tools/LevelEdit/CheckinStyleDialog.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// CheckinStyleDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveledit.h"
|
||||
#include "CheckinStyleDialog.h"
|
||||
#include "RegKeys.H"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constants
|
||||
//
|
||||
const TCHAR * const REG_NOT_CACHED = TEXT ("NotCached");
|
||||
const TCHAR * const REG_NOW = TEXT ("Now");
|
||||
const TCHAR * const REG_LATER = TEXT ("Later");
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CheckinStyleDialogClass
|
||||
//
|
||||
CheckinStyleDialogClass::CheckinStyleDialogClass(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(CheckinStyleDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(CheckinStyleDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
}
|
||||
|
||||
|
||||
void CheckinStyleDialogClass::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(CheckinStyleDialogClass)
|
||||
// NOTE: the ClassWizard will add DDX and DDV calls here
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(CheckinStyleDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(CheckinStyleDialogClass)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CheckinStyleDialogClass message handlers
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOK
|
||||
//
|
||||
void
|
||||
CheckinStyleDialogClass::OnOK (void)
|
||||
{
|
||||
UINT ret_code = IDC_UPDATE_NOW;
|
||||
CString cache_value = REG_NOW;
|
||||
|
||||
if (SendDlgItemMessage (IDC_UPDATE_LATER, BM_GETCHECK) == 1) {
|
||||
ret_code = IDC_UPDATE_LATER;
|
||||
cache_value = REG_LATER;
|
||||
}
|
||||
|
||||
// Cache the value in the registry if necessary
|
||||
if (SendDlgItemMessage (IDC_DONT_ASK_ME_AGAIN, BM_GETCHECK) == 1) {
|
||||
theApp.WriteProfileString (CONFIG_KEY, CHECKIN_STYLE_VALUE, cache_value);
|
||||
}
|
||||
|
||||
// Close the dialog with the appropriate control ID
|
||||
EndDialog (ret_code);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnCommand
|
||||
//
|
||||
BOOL
|
||||
CheckinStyleDialogClass::OnCommand
|
||||
(
|
||||
WPARAM wParam,
|
||||
LPARAM lParam
|
||||
)
|
||||
{
|
||||
// Don't allow the user to cancel out of this dialog
|
||||
if (LOWORD (wParam) == IDCANCEL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Allow the base class to process this message
|
||||
return CDialog::OnCommand (wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoModal
|
||||
//
|
||||
int
|
||||
CheckinStyleDialogClass::DoModal (void)
|
||||
{
|
||||
UINT ret_code = IDC_UPDATE_NOW;
|
||||
|
||||
// Get the cached 'checkin' style if possible
|
||||
CString checkin_style = theApp.GetProfileString (CONFIG_KEY, CHECKIN_STYLE_VALUE, REG_NOT_CACHED);
|
||||
if (checkin_style.CompareNoCase (REG_NOT_CACHED) == 0) {
|
||||
|
||||
// Allow the base class to show the dialog
|
||||
ret_code = CDialog::DoModal ();
|
||||
} else {
|
||||
if (checkin_style.CompareNoCase (REG_LATER) == 0) {
|
||||
ret_code = IDC_UPDATE_LATER;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the dialog control's ID
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
BOOL
|
||||
CheckinStyleDialogClass::OnInitDialog (void)
|
||||
{
|
||||
// Allow the base class to process this message
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
// Check 'update now' by default
|
||||
SendDlgItemMessage (IDC_UPDATE_NOW, BM_SETCHECK, (WPARAM)TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
68
Code/Tools/LevelEdit/CheckinStyleDialog.h
Normal file
68
Code/Tools/LevelEdit/CheckinStyleDialog.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_CHECKINSTYLEDIALOG_H__2057225F_9559_11D2_9FED_00104B791122__INCLUDED_)
|
||||
#define AFX_CHECKINSTYLEDIALOG_H__2057225F_9559_11D2_9FED_00104B791122__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
// CheckinStyleDialog.h : header file
|
||||
//
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CheckinStyleDialogClass dialog
|
||||
|
||||
class CheckinStyleDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
CheckinStyleDialogClass(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(CheckinStyleDialogClass)
|
||||
enum { IDD = IDD_CHECKIN_STYLE };
|
||||
// NOTE: the ClassWizard will add data members here
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CheckinStyleDialogClass)
|
||||
public:
|
||||
virtual int DoModal();
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(CheckinStyleDialogClass)
|
||||
virtual void OnOK();
|
||||
virtual BOOL OnInitDialog();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_CHECKINSTYLEDIALOG_H__2057225F_9559_11D2_9FED_00104B791122__INCLUDED_)
|
||||
113
Code/Tools/LevelEdit/CheckingOutDialog.cpp
Normal file
113
Code/Tools/LevelEdit/CheckingOutDialog.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// CheckingOutDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveledit.h"
|
||||
#include "CheckingOutDialog.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CheckingOutDialogClass dialog
|
||||
|
||||
|
||||
CheckingOutDialogClass::CheckingOutDialogClass(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(CheckingOutDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(CheckingOutDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
}
|
||||
|
||||
|
||||
void CheckingOutDialogClass::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(CheckingOutDialogClass)
|
||||
// NOTE: the ClassWizard will add DDX and DDV calls here
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(CheckingOutDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(CheckingOutDialogClass)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WindowProc
|
||||
//
|
||||
LRESULT
|
||||
CheckingOutDialogClass::WindowProc
|
||||
(
|
||||
UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam
|
||||
)
|
||||
{
|
||||
if (message == WM_USER+101) {
|
||||
EndDialog (1);
|
||||
}
|
||||
|
||||
// Allow the base class to process this message
|
||||
return CDialog::WindowProc(message, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnCommand
|
||||
//
|
||||
BOOL
|
||||
CheckingOutDialogClass::OnCommand
|
||||
(
|
||||
WPARAM wParam,
|
||||
LPARAM lParam
|
||||
)
|
||||
{
|
||||
// Don't let the dialog be closed by hitting enter or escape
|
||||
if (LOWORD (wParam) == IDOK || LOWORD (wParam) == IDCANCEL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Allow the base class to process this message
|
||||
return CDialog::OnCommand(wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
BOOL
|
||||
CheckingOutDialogClass::OnInitDialog (void)
|
||||
{
|
||||
// Allow the base class to process this message
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
66
Code/Tools/LevelEdit/CheckingOutDialog.h
Normal file
66
Code/Tools/LevelEdit/CheckingOutDialog.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_CHECKINGOUTDIALOG_H__2057225E_9559_11D2_9FED_00104B791122__INCLUDED_)
|
||||
#define AFX_CHECKINGOUTDIALOG_H__2057225E_9559_11D2_9FED_00104B791122__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
// CheckingOutDialog.h : header file
|
||||
//
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CheckingOutDialogClass dialog
|
||||
|
||||
class CheckingOutDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
CheckingOutDialogClass(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(CheckingOutDialogClass)
|
||||
enum { IDD = IDD_CHECKING_OUT };
|
||||
// NOTE: the ClassWizard will add data members here
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CheckingOutDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(CheckingOutDialogClass)
|
||||
virtual BOOL OnInitDialog();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_CHECKINGOUTDIALOG_H__2057225E_9559_11D2_9FED_00104B791122__INCLUDED_)
|
||||
218
Code/Tools/LevelEdit/ChooseModPackageDialog.cpp
Normal file
218
Code/Tools/LevelEdit/ChooseModPackageDialog.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// ChooseModPackageDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveledit.h"
|
||||
#include "choosemodpackagedialog.h"
|
||||
#include "assetpackagemgr.h"
|
||||
#include "newassetpackagedialog.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ChooseModPackageDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
ChooseModPackageDialogClass::ChooseModPackageDialogClass(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(ChooseModPackageDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(ChooseModPackageDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ChooseModPackageDialogClass::DoDataExchange (CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(ChooseModPackageDialogClass)
|
||||
DDX_Control(pDX, IDC_MOD_LIST_CTRL, ListCtrl);
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(ChooseModPackageDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(ChooseModPackageDialogClass)
|
||||
ON_BN_CLICKED(IDC_NEW_BUTTON, OnNewButton)
|
||||
ON_NOTIFY(NM_DBLCLK, IDC_MOD_LIST_CTRL, OnDblclkModListCtrl)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
ChooseModPackageDialogClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
//
|
||||
// Configure the columns
|
||||
//
|
||||
ListCtrl.InsertColumn (0, "");
|
||||
ListCtrl.SetExtendedStyle (ListCtrl.GetExtendedStyle () | LVS_EX_FULLROWSELECT);
|
||||
|
||||
//
|
||||
// Choose an appropriate size for the column
|
||||
//
|
||||
CRect rect;
|
||||
ListCtrl.GetClientRect (&rect);
|
||||
rect.right -= ::GetSystemMetrics (SM_CXVSCROLL) + 2;
|
||||
ListCtrl.SetColumnWidth (0, rect.Width ());
|
||||
|
||||
//
|
||||
// Build a list of all the packages that are currently available
|
||||
//
|
||||
STRING_LIST package_list;
|
||||
AssetPackageMgrClass::Build_Package_List (package_list);
|
||||
|
||||
//
|
||||
// Add an entry to the control for each package
|
||||
//
|
||||
bool found = false;
|
||||
for (int index = 0; index < package_list.Count (); index ++) {
|
||||
int item_index = ListCtrl.InsertItem (index, package_list[index]);
|
||||
if (item_index >= 0) {
|
||||
|
||||
//
|
||||
// Is this the default entry?
|
||||
//
|
||||
if (::lstrcmpi (AssetPackageMgrClass::Get_Current_Package (), package_list[index]) == 0) {
|
||||
ListCtrl.SetItemState (item_index, LVIS_SELECTED, LVIS_SELECTED);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Select the first entry by default
|
||||
//
|
||||
if (package_list.Count () > 0 && found) {
|
||||
ListCtrl.SetItemState (0, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOK
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ChooseModPackageDialogClass::OnOK (void)
|
||||
{
|
||||
int curr_index = ListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
|
||||
if (curr_index >= 0) {
|
||||
|
||||
//
|
||||
// Set the current mod package
|
||||
//
|
||||
CString package_name = ListCtrl.GetItemText (curr_index, 0);
|
||||
AssetPackageMgrClass::Set_Current_Package (package_name);
|
||||
|
||||
//
|
||||
// Close the dialog
|
||||
//
|
||||
CDialog::OnOK ();
|
||||
|
||||
} else {
|
||||
|
||||
//
|
||||
// Warn the user
|
||||
//
|
||||
MessageBox ("You must select (or create) a Mod Package before continuing.", "Invalid Selection", MB_ICONERROR | MB_OK);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnNewButton
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ChooseModPackageDialogClass::OnNewButton (void)
|
||||
{
|
||||
//
|
||||
// Display a dialog to the user allowing them to create a new mod package
|
||||
//
|
||||
NewAssetPackageDialogClass dialog (this);
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Create the new asset package
|
||||
//
|
||||
AssetPackageMgrClass::Create_Package (dialog.Get_Package_Name ());
|
||||
|
||||
//
|
||||
// Add this package to the list
|
||||
//
|
||||
int item_index = ListCtrl.InsertItem (0xFF, dialog.Get_Package_Name ());
|
||||
if (item_index >= 0) {
|
||||
|
||||
//
|
||||
// Select the new package
|
||||
//
|
||||
ListCtrl.SetItemState (item_index, LVIS_SELECTED, LVIS_SELECTED);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDblclkModListCtrl
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ChooseModPackageDialogClass::OnDblclkModListCtrl (NMHDR *pNMHDR, LRESULT *pResult)
|
||||
{
|
||||
(*pResult) = 0;
|
||||
|
||||
//
|
||||
// Simulate pressing the OK button
|
||||
//
|
||||
SendMessage (WM_COMMAND, MAKELONG (IDOK, BN_CLICKED), 0);
|
||||
return ;
|
||||
}
|
||||
75
Code/Tools/LevelEdit/ChooseModPackageDialog.h
Normal file
75
Code/Tools/LevelEdit/ChooseModPackageDialog.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_CHOOSEMODPACKAGEDIALOG_H__86FFB2F7_5103_422D_B327_5DCF8343713C__INCLUDED_)
|
||||
#define AFX_CHOOSEMODPACKAGEDIALOG_H__86FFB2F7_5103_422D_B327_5DCF8343713C__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ChooseModPackageDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class ChooseModPackageDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
ChooseModPackageDialogClass(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(ChooseModPackageDialogClass)
|
||||
enum { IDD = IDD_CHOOSE_MOD_PACKAGE };
|
||||
CListCtrl ListCtrl;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(ChooseModPackageDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(ChooseModPackageDialogClass)
|
||||
virtual BOOL OnInitDialog();
|
||||
virtual void OnOK();
|
||||
afx_msg void OnNewButton();
|
||||
afx_msg void OnDblclkModListCtrl(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_CHOOSEMODPACKAGEDIALOG_H__86FFB2F7_5103_422D_B327_5DCF8343713C__INCLUDED_)
|
||||
57
Code/Tools/LevelEdit/CollisionGroups.h
Normal file
57
Code/Tools/LevelEdit/CollisionGroups.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/CollisionGroups.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 10/06/00 3:38p $*
|
||||
* *
|
||||
* $Revision:: 5 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __COLLISION_GROUPS_H
|
||||
#define __COLLISION_GROUPS_H
|
||||
|
||||
|
||||
typedef enum {
|
||||
DEF_COLLISION_GROUP = 10, // collides with itself and mouse clicks
|
||||
EDITOR_COLLISION_GROUP, // doesn't collide with anything (other than mouse clicks)
|
||||
MOUSE_CLICK_COLLISION_GROUP, // collides with everything
|
||||
GAME_COLLISION_GROUP, // collides with everything except for EDITOR_COLLISION_GROUP
|
||||
STATIC_OBJ_COLLISION_GROUP // only collides with static objects (group 15)
|
||||
} COLLISION_GROUPS;
|
||||
|
||||
|
||||
#endif //__COLLISION_GROUPS_H
|
||||
|
||||
1929
Code/Tools/LevelEdit/ColorBar.cpp
Normal file
1929
Code/Tools/LevelEdit/ColorBar.cpp
Normal file
File diff suppressed because it is too large
Load Diff
252
Code/Tools/LevelEdit/ColorBar.h
Normal file
252
Code/Tools/LevelEdit/ColorBar.h
Normal file
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_COLORBAR_H__D1243F40_D4D2_11D2_8DDF_00104B6FD9E3__INCLUDED_)
|
||||
#define AFX_COLORBAR_H__D1243F40_D4D2_11D2_8DDF_00104B6FD9E3__INCLUDED_
|
||||
|
||||
#if _MSC_VER >= 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER >= 1000
|
||||
// ColorBar.h : header file
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constants
|
||||
//
|
||||
const int MAX_COLOR_POINTS = 15;
|
||||
|
||||
//
|
||||
// Window styles
|
||||
//
|
||||
#define CBRS_SUNKEN 0x00000001
|
||||
#define CBRS_RAISED 0x00000002
|
||||
#define CBRS_FRAME 0x00000004
|
||||
#define CBRS_FRAME_MASK CBRS_FRAME | CBRS_RAISED | CBRS_SUNKEN
|
||||
#define CBRS_HORZ 0x00000008
|
||||
#define CBRS_VERT 0x00000010
|
||||
#define CBRS_HAS_SEL 0x00000020
|
||||
#define CBRS_SHOW_FRAMES 0x00000040
|
||||
#define CBRS_PAINT_GRAPH 0x00000080
|
||||
|
||||
//
|
||||
// Window messages and notifications
|
||||
//
|
||||
#define CBRN_MOVED_POINT 0x0001
|
||||
#define CBRN_MOVING_POINT 0x0002
|
||||
#define CBRN_DBLCLK_POINT 0x0003
|
||||
#define CBRN_SEL_CHANGED 0x0004
|
||||
#define CBRN_DEL_POINT 0x0005
|
||||
#define CBRN_DELETED_POINT 0x0006
|
||||
#define CBRN_INSERTED_POINT 0x0007
|
||||
#define CBRM_GETCOLOR (WM_USER+101)
|
||||
#define CBRM_SETCOLOR ( WM_USER+102)
|
||||
|
||||
//
|
||||
// Point styles
|
||||
//
|
||||
#define POINT_VISIBLE 0x00000001
|
||||
#define POINT_CAN_MOVE 0x00000002
|
||||
|
||||
//
|
||||
// Return values for WM_NOTIFY
|
||||
//
|
||||
#define STOP_EVENT 0x00000077
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Structures
|
||||
//
|
||||
|
||||
// Structure used to send notifications via WM_NOTIFY
|
||||
typedef struct
|
||||
{
|
||||
NMHDR hdr;
|
||||
int key_index;
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
float position;
|
||||
} CBR_NMHDR;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ColorBarClass
|
||||
//
|
||||
class ColorBarClass : public CWnd
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
ColorBarClass();
|
||||
|
||||
// Attributes
|
||||
public:
|
||||
|
||||
// Operations
|
||||
public:
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(ColorBarClass)
|
||||
public:
|
||||
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
virtual ~ColorBarClass();
|
||||
|
||||
// Generated message map functions
|
||||
protected:
|
||||
//{{AFX_MSG(ColorBarClass)
|
||||
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
|
||||
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||
afx_msg void OnPaint();
|
||||
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
|
||||
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
|
||||
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
|
||||
afx_msg void OnKillFocus(CWnd* pNewWnd);
|
||||
afx_msg void OnSetFocus(CWnd* pOldWnd);
|
||||
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
|
||||
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
friend LRESULT WINAPI fnColorBarProc (HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Public methods
|
||||
//
|
||||
bool Insert_Point (int index, float position, float red, float green, float blue, DWORD flags = POINT_VISIBLE | POINT_CAN_MOVE);
|
||||
bool Insert_Point (CPoint point, DWORD flags = POINT_VISIBLE | POINT_CAN_MOVE);
|
||||
bool Modify_Point (int index, float position, float red, float green, float blue, DWORD flags = POINT_VISIBLE | POINT_CAN_MOVE);
|
||||
bool Set_User_Data (int index, DWORD data);
|
||||
DWORD Get_User_Data (int index);
|
||||
bool Set_Graph_Percent (int index, float percent);
|
||||
float Get_Graph_Percent (int index);
|
||||
bool Delete_Point (int index);
|
||||
void Clear_Points (void);
|
||||
|
||||
int Get_Point_Count (void) const { return m_iColorPoints; }
|
||||
bool Get_Point (int index, float *position, float *red, float *green, float *blue);
|
||||
|
||||
int Marker_From_Point (CPoint point);
|
||||
void Set_Selection_Pos (float pos);
|
||||
float Get_Selection_Pos (void) const { return m_SelectionPos; }
|
||||
void Get_Color (float position, float *red, float *green, float *blue);
|
||||
|
||||
void Get_Range (float &min, float &max) const { min = m_MinPos; max = m_MaxPos; }
|
||||
void Set_Range (float min, float max);
|
||||
|
||||
void Set_Redraw (bool redraw = true);
|
||||
LRESULT Send_Notification (int code, int key);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Static members
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static ColorBarClass *Get_Color_Bar (HWND window_handle) { return (ColorBarClass *)::GetProp (window_handle, "CLASSPOINTER"); }
|
||||
|
||||
protected:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Protected data types
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
float PosPercent;
|
||||
int StartPos;
|
||||
int EndPos;
|
||||
|
||||
float StartGraphPercent;
|
||||
float GraphPercentInc;
|
||||
|
||||
float StartRed;
|
||||
float StartGreen;
|
||||
float StartBlue;
|
||||
|
||||
float RedInc;
|
||||
float GreenInc;
|
||||
float BlueInc;
|
||||
|
||||
DWORD user_data;
|
||||
int flags;
|
||||
|
||||
} COLOR_POINT;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Protected methods
|
||||
//
|
||||
void Paint_DIB (void);
|
||||
void Create_Bitmap (void);
|
||||
void Free_Bitmap (void);
|
||||
void Free_Marker_Bitmap (void);
|
||||
void Paint_Bar_Horz (int x_pos, int y_pos, int width, int height, UCHAR *pbits);
|
||||
void Paint_Bar_Vert (int x_pos, int y_pos, int width, int height, UCHAR *pbits);
|
||||
void Update_Point_Info (void);
|
||||
void Load_Key_Frame_BMP (void);
|
||||
void Paint_Key_Frame (int x_pos, int y_pos);
|
||||
void Paint_Screen (HDC hwnd_dc);
|
||||
void Get_Selection_Rectangle (CRect &rect);
|
||||
void Move_Selection (CPoint point, bool send_notify = true);
|
||||
void Move_Selection (float new_pos, bool send_notify = true);
|
||||
void Repaint (void);
|
||||
|
||||
private:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Private member data
|
||||
//
|
||||
HBITMAP m_hBitmap;
|
||||
HBITMAP m_KeyFrameDIB;
|
||||
HDC m_hMemDC;
|
||||
UCHAR * m_pBits;
|
||||
UCHAR * m_pKeyFrameBits;
|
||||
int m_iColorWidth;
|
||||
int m_iColorHeight;
|
||||
int m_iBMPWidth;
|
||||
int m_iBMPHeight;
|
||||
int m_iMarkerWidth;
|
||||
int m_iMarkerHeight;
|
||||
int m_iScanlineSize;
|
||||
int m_iColorPoints;
|
||||
float m_MinPos;
|
||||
float m_MaxPos;
|
||||
COLOR_POINT m_ColorPoints[MAX_COLOR_POINTS];
|
||||
CRect m_ColorArea;
|
||||
int m_iCurrentKey;
|
||||
bool m_bMoving;
|
||||
bool m_bMoved;
|
||||
bool m_bRedraw;
|
||||
float m_SelectionPos;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_COLORBAR_H__D1243F40_D4D2_11D2_8DDF_00104B6FD9E3__INCLUDED_)
|
||||
985
Code/Tools/LevelEdit/ColorPicker.cpp
Normal file
985
Code/Tools/LevelEdit/ColorPicker.cpp
Normal file
@@ -0,0 +1,985 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ColorPicker.cpp : implementation file
|
||||
//
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "colorpicker.h"
|
||||
#include "colorpickerdialogclass.h"
|
||||
#include <math.h>
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//extern HINSTANCE _hinstance;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ColorPickerClass
|
||||
//
|
||||
ColorPickerClass::ColorPickerClass (void)
|
||||
: m_hBitmap (NULL),
|
||||
m_iWidth (0),
|
||||
m_iHeight (0),
|
||||
m_CurrentPoint (0, 0),
|
||||
m_CurrentColor (0),
|
||||
m_bSelecting (false),
|
||||
m_pBits (NULL),
|
||||
m_hMemDC (NULL),
|
||||
m_CurrentHue (0),
|
||||
CWnd ()
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~ColorPickerClass
|
||||
//
|
||||
ColorPickerClass::~ColorPickerClass (void)
|
||||
{
|
||||
if (m_hMemDC != NULL) {
|
||||
::DeleteObject (m_hMemDC);
|
||||
m_hMemDC = NULL;
|
||||
}
|
||||
|
||||
Free_Bitmap ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(ColorPickerClass, CWnd)
|
||||
//{{AFX_MSG_MAP(ColorPickerClass)
|
||||
ON_WM_PAINT()
|
||||
ON_WM_CREATE()
|
||||
ON_WM_SIZE()
|
||||
ON_WM_ERASEBKGND()
|
||||
ON_WM_LBUTTONDOWN()
|
||||
ON_WM_LBUTTONUP()
|
||||
ON_WM_MOUSEMOVE()
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnPaint
|
||||
//
|
||||
void
|
||||
ColorPickerClass::OnPaint (void)
|
||||
{
|
||||
CPaintDC dc (this);
|
||||
|
||||
if (m_hMemDC != NULL) {
|
||||
|
||||
HBITMAP hold_bmp = (HBITMAP)::SelectObject (m_hMemDC, m_hBitmap);
|
||||
|
||||
CRect rect;
|
||||
GetClientRect (&rect);
|
||||
::BitBlt (dc, 0, 0, rect.Width (), rect.Height (), m_hMemDC, 0, 0, SRCCOPY);
|
||||
|
||||
::SelectObject (m_hMemDC, hold_bmp);
|
||||
Paint_Marker ();
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// RegisterColorPicker
|
||||
//
|
||||
void
|
||||
RegisterColorPicker (HINSTANCE hinst)
|
||||
{
|
||||
// Has the class already been registered?
|
||||
WNDCLASS wndclass = { 0 };
|
||||
if (::GetClassInfo (hinst, "WWCOLORPICKER", &wndclass) == FALSE) {
|
||||
|
||||
wndclass.style = CS_GLOBALCLASS | CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
|
||||
wndclass.lpfnWndProc = fnColorPickerProc;
|
||||
wndclass.hInstance = hinst;
|
||||
wndclass.hbrBackground = (HBRUSH)COLOR_3DFACE + 1;
|
||||
wndclass.hCursor = ::LoadCursor (NULL, IDC_ARROW);
|
||||
wndclass.lpszClassName = "WWCOLORPICKER";
|
||||
|
||||
// Let the windows manager know about this global class
|
||||
::RegisterClass (&wndclass);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// fnColorPickerProc
|
||||
//
|
||||
LRESULT WINAPI
|
||||
fnColorPickerProc
|
||||
(
|
||||
HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam
|
||||
)
|
||||
{
|
||||
//static ColorPickerClass *pwnd = NULL;
|
||||
//static bool bcreated = false;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_CREATE:
|
||||
{
|
||||
LPCREATESTRUCT pcreate_info = (LPCREATESTRUCT)lparam;
|
||||
if (pcreate_info != NULL) {
|
||||
|
||||
// Should we create a new class manager for this window?
|
||||
ColorPickerClass *pwnd = (ColorPickerClass *)pcreate_info->lpCreateParams;
|
||||
BOOL created = FALSE;
|
||||
if (pwnd == NULL) {
|
||||
pwnd = new ColorPickerClass;
|
||||
created = TRUE;
|
||||
}
|
||||
|
||||
// Pull some hacks to get MFC to use the message map
|
||||
pwnd->Attach (hwnd);
|
||||
|
||||
// Let the window know its being created
|
||||
pwnd->OnCreate (pcreate_info);
|
||||
|
||||
WNDPROC *pOldWndProc = pwnd->GetSuperWndProcAddr ();
|
||||
if (pOldWndProc) {
|
||||
WNDPROC pold_proc = (WNDPROC)::SetWindowLong (hwnd, GWL_WNDPROC, (DWORD)::AfxGetAfxWndProc ());
|
||||
ASSERT (pold_proc != NULL);
|
||||
(*pOldWndProc) = pold_proc;
|
||||
}
|
||||
|
||||
// Store some information in the window handle
|
||||
::SetProp (hwnd, "CLASSPOINTER", (HANDLE)pwnd);
|
||||
::SetProp (hwnd, "CREATED", (HANDLE)created);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
{
|
||||
/*pwnd->Detach ();
|
||||
|
||||
WNDPROC *pOldWndProc = pwnd->GetSuperWndProcAddr ();
|
||||
if (pOldWndProc) {
|
||||
::SetWindowLong (hwnd, GWL_WNDPROC, (DWORD)(*pOldWndProc));
|
||||
(*pOldWndProc) = NULL;
|
||||
}
|
||||
|
||||
if (bcreated) {
|
||||
delete pwnd;
|
||||
pwnd = NULL;
|
||||
}*/
|
||||
|
||||
// Get the creation information from the window handle
|
||||
ColorPickerClass *pwnd = (ColorPickerClass *)::GetProp (hwnd, "CLASSPOINTER");
|
||||
BOOL created = (BOOL)::GetProp (hwnd, "CREATED");
|
||||
|
||||
if (pwnd != NULL) {
|
||||
pwnd->Detach ();
|
||||
|
||||
WNDPROC *pOldWndProc = pwnd->GetSuperWndProcAddr ();
|
||||
if (pOldWndProc) {
|
||||
::SetWindowLong (hwnd, GWL_WNDPROC, (DWORD)(*pOldWndProc));
|
||||
(*pOldWndProc) = NULL;
|
||||
}
|
||||
|
||||
if (created) {
|
||||
delete pwnd;
|
||||
pwnd = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Allow default processing to occur
|
||||
return ::DefWindowProc (hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnCreate
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
int
|
||||
ColorPickerClass::OnCreate (LPCREATESTRUCT lpCreateStruct)
|
||||
{
|
||||
if (CWnd::OnCreate(lpCreateStruct) == -1)
|
||||
return -1;
|
||||
|
||||
m_hMemDC = ::CreateCompatibleDC (NULL);
|
||||
Create_Bitmap ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
ColorPickerClass::Create
|
||||
(
|
||||
LPCTSTR /*lpszClassName*/,
|
||||
LPCTSTR lpszWindowName,
|
||||
DWORD dwStyle,
|
||||
const RECT &rect,
|
||||
CWnd *pparent_wnd,
|
||||
UINT nID,
|
||||
CCreateContext * /*pContext*/
|
||||
)
|
||||
{
|
||||
// Create the window (it will force the message map and everthing)
|
||||
HWND hparent_wnd = (pparent_wnd != NULL) ? pparent_wnd->m_hWnd : NULL;
|
||||
HWND hwnd = ::CreateWindow ("WWCOLORPICKER",
|
||||
lpszWindowName,
|
||||
dwStyle,
|
||||
rect.left,
|
||||
rect.top,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
hparent_wnd,
|
||||
(HMENU)nID,
|
||||
::AfxGetInstanceHandle (),
|
||||
this);
|
||||
|
||||
// Return the true/false result code
|
||||
return (hwnd != NULL);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create_Bitmap
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerClass::Create_Bitmap (void)
|
||||
{
|
||||
// Start fresh
|
||||
Free_Bitmap ();
|
||||
|
||||
CRect rect;
|
||||
GetClientRect (&rect);
|
||||
m_iWidth = rect.Width ();
|
||||
m_iHeight = rect.Height ();
|
||||
|
||||
// Set-up the fields of the BITMAPINFOHEADER
|
||||
BITMAPINFOHEADER bitmap_info;
|
||||
bitmap_info.biSize = sizeof (BITMAPINFOHEADER);
|
||||
bitmap_info.biWidth = m_iWidth;
|
||||
bitmap_info.biHeight = -m_iHeight; // Top-down DIB uses negative height
|
||||
bitmap_info.biPlanes = 1;
|
||||
bitmap_info.biBitCount = 24;
|
||||
bitmap_info.biCompression = BI_RGB;
|
||||
bitmap_info.biSizeImage = ((m_iWidth * m_iHeight) * 3);
|
||||
bitmap_info.biXPelsPerMeter = 0;
|
||||
bitmap_info.biYPelsPerMeter = 0;
|
||||
bitmap_info.biClrUsed = 0;
|
||||
bitmap_info.biClrImportant = 0;
|
||||
|
||||
// Get a temporary screen DC
|
||||
HDC hscreen_dc = ::GetDC (NULL);
|
||||
|
||||
// Create a bitmap that we can access the bits directly of
|
||||
m_hBitmap = ::CreateDIBSection (hscreen_dc,
|
||||
(const BITMAPINFO *)&bitmap_info,
|
||||
DIB_RGB_COLORS,
|
||||
(void **)&m_pBits,
|
||||
NULL,
|
||||
0L);
|
||||
|
||||
// Release our temporary screen DC
|
||||
::ReleaseDC (NULL, hscreen_dc);
|
||||
|
||||
// Paint the color range into this bitmap
|
||||
Paint_DIB (m_iWidth, m_iHeight, m_pBits);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Fill_Rect
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerClass::Fill_Rect
|
||||
(
|
||||
UCHAR *pbits,
|
||||
const RECT &rect,
|
||||
COLORREF color,
|
||||
int scanline_size
|
||||
)
|
||||
{
|
||||
UCHAR red = GetRValue (color);
|
||||
UCHAR green = GetRValue (color);
|
||||
UCHAR blue = GetRValue (color);
|
||||
|
||||
for (int irow = rect.top; irow < rect.bottom; irow ++) {
|
||||
int index = irow * scanline_size;
|
||||
index += (rect.left * 3);
|
||||
|
||||
for (int col = rect.left; col < rect.right; col ++) {
|
||||
pbits[index++] = blue;
|
||||
pbits[index++] = green;
|
||||
pbits[index++] = red;
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Color_From_Point
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
COLORREF
|
||||
ColorPickerClass::Color_From_Point
|
||||
(
|
||||
int x,
|
||||
int y
|
||||
)
|
||||
{
|
||||
COLORREF color = RGB (0,0,0);
|
||||
|
||||
// x,y location inside boundaries?
|
||||
if ((x >= 0) && (x < m_iWidth) &&
|
||||
(y >= 0) && (y < m_iHeight)) {
|
||||
|
||||
// Window's bitmaps are DWORD aligned, so make sure
|
||||
// we take that into account.
|
||||
int alignment_offset = (m_iWidth * 3) % 4;
|
||||
alignment_offset = (alignment_offset != 0) ? (4 - alignment_offset) : 0;
|
||||
int scanline_size = (m_iWidth * 3) + alignment_offset;
|
||||
|
||||
// Read the color value straight from the BMP
|
||||
int index = (scanline_size * y) + (x * 3);
|
||||
int blue = m_pBits[index];
|
||||
int green = m_pBits[index + 1];
|
||||
int red = m_pBits[index + 2];
|
||||
|
||||
// Turn the individual compenents into a color
|
||||
color = RGB (red, green, blue);
|
||||
|
||||
RECT rect;
|
||||
Calc_Display_Rect (rect);
|
||||
int width = rect.right-rect.left;
|
||||
m_CurrentHue = ((float)x) / ((float)width);
|
||||
}
|
||||
|
||||
// Return the color
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Polar_To_Rect
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Polar_To_Rect (float radius, float angle, float &x, float &y)
|
||||
{
|
||||
x = radius * float(cos(angle));
|
||||
y = radius * float(sin(angle));
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Rect_To_Polar
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Rect_To_Polar (float x, float y, float &radius, float &angle)
|
||||
{
|
||||
if (x == 0 && y == 0) {
|
||||
radius = 0;
|
||||
angle = 0;
|
||||
} else {
|
||||
radius = (float)::sqrt ((x * x) + (y * y));
|
||||
angle = (float)::atan2 (y, x);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// RGB_to_Hue
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
RGB_to_Hue (int red_val, int green_val, int blue_val, float &hue, float &value)
|
||||
{
|
||||
float red_radius = (float)red_val;
|
||||
float green_radius = (float)green_val;
|
||||
float blue_radius = (float)blue_val;
|
||||
|
||||
float red_angle = 0;
|
||||
float green_angle = (3.1415926535F * 2.0F) / 3.0F;
|
||||
float blue_angle = (3.1415926535F * 4.0F) / 3.0F;
|
||||
|
||||
struct Color2D
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
Color2D red = { 0 };
|
||||
Color2D green = { 0 };
|
||||
Color2D blue = { 0 };
|
||||
Color2D result = { 0 };
|
||||
|
||||
::Polar_To_Rect (red_radius, red_angle, red.x, red.y);
|
||||
::Polar_To_Rect (green_radius, green_angle, green.x, green.y);
|
||||
::Polar_To_Rect (blue_radius, blue_angle, blue.x, blue.y);
|
||||
|
||||
result.x = red.x + green.x + blue.x;
|
||||
result.y = red.y + green.y + blue.y;
|
||||
|
||||
float hue_angle = 0;
|
||||
float hue_radius = 0;
|
||||
::Rect_To_Polar (result.x, result.y, hue_radius, hue_angle);
|
||||
|
||||
hue = hue_angle / (3.14159265359F * 2.0F);
|
||||
if (hue < 0) {
|
||||
hue += 1;
|
||||
} else if (hue > 1) {
|
||||
hue -= 1;
|
||||
}
|
||||
|
||||
value = (float)::fabs (hue_radius / 255);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Point_From_Color
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
CPoint
|
||||
ColorPickerClass::Point_From_Color (COLORREF color)
|
||||
{
|
||||
// Window's bitmaps are DWORD aligned, so make sure
|
||||
// we take that into account.
|
||||
int alignment_offset = (m_iWidth * 3) % 4;
|
||||
alignment_offset = (alignment_offset != 0) ? (4 - alignment_offset) : 0;
|
||||
int scanline_size = (m_iWidth * 3) + alignment_offset;
|
||||
|
||||
int red = GetRValue (color);
|
||||
int green = GetGValue (color);
|
||||
int blue = GetBValue (color);
|
||||
|
||||
float hue = 0;
|
||||
float value = 0;
|
||||
RGB_to_Hue (red, green, blue, hue, value);
|
||||
|
||||
RECT rect;
|
||||
Calc_Display_Rect (rect);
|
||||
int width = rect.right-rect.left;
|
||||
int height = rect.bottom-rect.top;
|
||||
|
||||
float whiteness = (float)min (min (red, green), blue);
|
||||
float percent = whiteness / 255;
|
||||
float darkness = 0;
|
||||
|
||||
//
|
||||
// Determine what the 'darkness' of the hue should be
|
||||
//
|
||||
if (percent != 1) {
|
||||
float start_red = (red - whiteness) / (1 - percent);
|
||||
float start_green = (green - whiteness) / (1 - percent);
|
||||
float start_blue = (blue - whiteness) / (1 - percent);
|
||||
darkness = max (max (start_red, start_green), start_blue);
|
||||
}
|
||||
|
||||
int x = int(width * hue);
|
||||
int y = ((255 - (int)darkness) * height) / 255;
|
||||
|
||||
// Return the point
|
||||
return CPoint (x, y);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Paint_DIB
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerClass::Paint_DIB
|
||||
(
|
||||
int width,
|
||||
int height,
|
||||
UCHAR *pbits
|
||||
)
|
||||
{
|
||||
// Window's bitmaps are DWORD aligned, so make sure
|
||||
// we take that into account.
|
||||
int alignment_offset = (width * 3) % 4;
|
||||
alignment_offset = (alignment_offset != 0) ? (4 - alignment_offset) : 0;
|
||||
int scanline_size = (width * 3) + alignment_offset;
|
||||
|
||||
//
|
||||
// Paint the border (if any)
|
||||
//
|
||||
CRect rect (0, 0, width, height);
|
||||
LONG lstyle = ::GetWindowLong (m_hWnd, GWL_STYLE);
|
||||
if (lstyle & CPS_SUNKEN) {
|
||||
::Draw_Sunken_Rect (pbits, rect, scanline_size);
|
||||
rect.DeflateRect (1, 1);
|
||||
} else if (lstyle & CPS_RAISED) {
|
||||
::Draw_Raised_Rect (pbits, rect, scanline_size);
|
||||
rect.DeflateRect (1, 1);
|
||||
} else if (lstyle & WS_BORDER) {
|
||||
::Frame_Rect (pbits, rect, RGB (255, 255, 255), scanline_size);
|
||||
rect.DeflateRect (1, 1);
|
||||
}
|
||||
|
||||
// Recalc the width and height (it could of changed)
|
||||
width = rect.Width ();
|
||||
height = rect.Height ();
|
||||
|
||||
// Build an array of column indicies where we will switch color
|
||||
// components...
|
||||
int col_remainder = (width % 6);
|
||||
int channel_switch_cols[6];
|
||||
for (int channel = 0; channel < 6; channel ++) {
|
||||
|
||||
// Each column has at least X/6 pixels
|
||||
channel_switch_cols[channel] = width / 6;
|
||||
|
||||
// Do we need to add a remainder to this col?
|
||||
// (Occurs when the width isn't evenly divisible by 6)
|
||||
if (col_remainder > 0) {
|
||||
channel_switch_cols[channel] += 1;
|
||||
col_remainder --;
|
||||
}
|
||||
|
||||
// Add the previous column's switching index
|
||||
if (channel > 0) {
|
||||
channel_switch_cols[channel] += channel_switch_cols[channel - 1];
|
||||
}
|
||||
}
|
||||
|
||||
// Start with max red
|
||||
float red = 255.0F;
|
||||
float green = 0;
|
||||
float blue = 0;
|
||||
|
||||
// Calculate some starting channel variables
|
||||
int curr_channel = 0;
|
||||
float curr_inc = (255.0F / ((float)channel_switch_cols[0]));
|
||||
float *pcurr_component = &green;
|
||||
|
||||
//
|
||||
// Paint the image
|
||||
//
|
||||
for (int icol = rect.left; icol < rect.right; icol ++) {
|
||||
|
||||
// Determine how much to 'darken' the current hue by for each row (goes to black)
|
||||
float red_dec = -((float)(red) / (float)(height-1));
|
||||
float green_dec = -((float)(green) / (float)(height-1));
|
||||
float blue_dec = -((float)(blue) / (float)(height-1));
|
||||
|
||||
// Start with the normal hue color
|
||||
float curr_red = red;
|
||||
float curr_green = green;
|
||||
float curr_blue = blue;
|
||||
|
||||
// Paint all pixels in this row
|
||||
int bitmap_index = (icol * 3) + (rect.left * scanline_size);
|
||||
for (int irow = rect.top; irow < rect.bottom; irow ++) {
|
||||
|
||||
// Put these values into the bitmap
|
||||
pbits[bitmap_index] = UCHAR(((int)curr_blue) & 0xFF);
|
||||
pbits[bitmap_index + 1] = UCHAR(((int)curr_green) & 0xFF);
|
||||
pbits[bitmap_index + 2] = UCHAR(((int)curr_red) & 0xFF);
|
||||
|
||||
// Determine the current red, green, and blue values
|
||||
curr_red = curr_red + red_dec;
|
||||
curr_green = curr_green + green_dec;
|
||||
curr_blue = curr_blue + blue_dec;
|
||||
|
||||
// Increment our offset into the bitmap
|
||||
bitmap_index += scanline_size;
|
||||
}
|
||||
|
||||
// Is it time to switch to a new color channel?
|
||||
if ((icol - rect.left) == channel_switch_cols[curr_channel]) {
|
||||
|
||||
// Recompute values for the new channel
|
||||
curr_channel ++;
|
||||
curr_inc = (255.0F / ((float)(channel_switch_cols[curr_channel] - channel_switch_cols[curr_channel-1])));
|
||||
|
||||
// Which channel are we painting?
|
||||
if (curr_channel == 1) {
|
||||
pcurr_component = &red;
|
||||
curr_inc = -curr_inc;
|
||||
} else if (curr_channel == 2) {
|
||||
pcurr_component = &blue;
|
||||
} else if (curr_channel == 3) {
|
||||
pcurr_component = &green;
|
||||
curr_inc = -curr_inc;
|
||||
} else if (curr_channel == 4) {
|
||||
pcurr_component = &red;
|
||||
} else if (curr_channel == 5) {
|
||||
pcurr_component = &blue;
|
||||
curr_inc = -curr_inc;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment the current color component
|
||||
(*pcurr_component) = (*pcurr_component) + curr_inc;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Free_Bitmap
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerClass::Free_Bitmap (void)
|
||||
{
|
||||
if (m_hBitmap != NULL) {
|
||||
::DeleteObject (m_hBitmap);
|
||||
m_hBitmap = NULL;
|
||||
m_pBits = NULL;
|
||||
}
|
||||
|
||||
m_iWidth = 0;
|
||||
m_iHeight = 0;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnSize
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerClass::OnSize
|
||||
(
|
||||
UINT nType,
|
||||
int cx,
|
||||
int cy
|
||||
)
|
||||
{
|
||||
// Allow the base class to process this message
|
||||
CWnd::OnSize (nType, cx, cy);
|
||||
|
||||
// Recreate the BMP to reflect the new window size
|
||||
Create_Bitmap ();
|
||||
|
||||
// Determine the new point based on the current color
|
||||
//m_CurrentColor = RGB (128, 222, 199);
|
||||
//m_CurrentPoint = Point_From_Color (m_CurrentColor);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnEraseBkgnd
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
ColorPickerClass::OnEraseBkgnd (CDC * /*pDC*/)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnLButtonDown
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerClass::OnLButtonDown
|
||||
(
|
||||
UINT nFlags,
|
||||
CPoint point
|
||||
)
|
||||
{
|
||||
SetCapture ();
|
||||
m_bSelecting = true;
|
||||
|
||||
RECT rect;
|
||||
Calc_Display_Rect (rect);
|
||||
ClientToScreen (&rect);
|
||||
::ClipCursor (&rect);
|
||||
|
||||
Erase_Marker ();
|
||||
|
||||
m_CurrentPoint = point;
|
||||
m_CurrentColor = Color_From_Point (point.x, point.y);
|
||||
|
||||
//
|
||||
// Notify the parent window that the user double-clicked
|
||||
// one of the keyframes
|
||||
//
|
||||
LONG id = ::GetWindowLong (m_hWnd, GWL_ID);
|
||||
CP_NMHDR notify_hdr = { 0 };
|
||||
notify_hdr.hdr.hwndFrom = m_hWnd;
|
||||
notify_hdr.hdr.idFrom = id;
|
||||
notify_hdr.hdr.code = CPN_COLORCHANGE;
|
||||
notify_hdr.red = GetRValue (m_CurrentColor);
|
||||
notify_hdr.green = GetGValue (m_CurrentColor);
|
||||
notify_hdr.blue = GetBValue (m_CurrentColor);
|
||||
notify_hdr.hue = m_CurrentHue;
|
||||
::SendMessage (::GetParent (m_hWnd),
|
||||
WM_NOTIFY,
|
||||
id,
|
||||
(LPARAM)¬ify_hdr);
|
||||
|
||||
Paint_Marker ();
|
||||
|
||||
// Allow the base class to process this message
|
||||
CWnd::OnLButtonDown (nFlags, point);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnLButtonUp
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerClass::OnLButtonUp
|
||||
(
|
||||
UINT nFlags,
|
||||
CPoint point
|
||||
)
|
||||
{
|
||||
if (m_bSelecting) {
|
||||
::ClipCursor (NULL);
|
||||
ReleaseCapture ();
|
||||
m_bSelecting = false;
|
||||
}
|
||||
|
||||
// Allow the base class to process this message
|
||||
CWnd::OnLButtonUp (nFlags, point);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnMouseMove
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerClass::OnMouseMove
|
||||
(
|
||||
UINT nFlags,
|
||||
CPoint point
|
||||
)
|
||||
{
|
||||
if (m_bSelecting) {
|
||||
Erase_Marker ();
|
||||
|
||||
m_CurrentPoint = point;
|
||||
m_CurrentColor = Color_From_Point (point.x, point.y);
|
||||
|
||||
//
|
||||
// Notify the parent window that the user double-clicked
|
||||
// one of the keyframes
|
||||
//
|
||||
LONG id = ::GetWindowLong (m_hWnd, GWL_ID);
|
||||
CP_NMHDR notify_hdr = { 0 };
|
||||
notify_hdr.hdr.hwndFrom = m_hWnd;
|
||||
notify_hdr.hdr.idFrom = id;
|
||||
notify_hdr.hdr.code = CPN_COLORCHANGE;
|
||||
notify_hdr.red = GetRValue (m_CurrentColor);
|
||||
notify_hdr.green = GetGValue (m_CurrentColor);
|
||||
notify_hdr.blue = GetBValue (m_CurrentColor);
|
||||
notify_hdr.hue = m_CurrentHue;
|
||||
::SendMessage (::GetParent (m_hWnd),
|
||||
WM_NOTIFY,
|
||||
id,
|
||||
(LPARAM)¬ify_hdr);
|
||||
|
||||
Paint_Marker ();
|
||||
}
|
||||
|
||||
// Allow the base class to process this message
|
||||
CWnd::OnMouseMove (nFlags, point);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Calc_Display_Rect
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerClass::Calc_Display_Rect (RECT &rect)
|
||||
{
|
||||
GetClientRect (&rect);
|
||||
|
||||
LONG lstyle = ::GetWindowLong (m_hWnd, GWL_STYLE);
|
||||
if ((lstyle & CPS_SUNKEN) || (lstyle & CPS_RAISED) || (lstyle & WS_BORDER)) {
|
||||
rect.left += 1;
|
||||
rect.right -= 1;
|
||||
rect.top += 1;
|
||||
rect.bottom -= 1;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Erase_Marker
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerClass::Erase_Marker (void)
|
||||
{
|
||||
HDC hdc = ::GetDC (m_hWnd);
|
||||
if (m_hMemDC != NULL) {
|
||||
|
||||
HBITMAP hold_bmp = (HBITMAP)::SelectObject (m_hMemDC, m_hBitmap);
|
||||
|
||||
CRect rect;
|
||||
GetClientRect (&rect);
|
||||
::BitBlt (hdc,
|
||||
m_CurrentPoint.x - 5,
|
||||
m_CurrentPoint.y - 5,
|
||||
11,
|
||||
11,
|
||||
m_hMemDC,
|
||||
m_CurrentPoint.x - 5,
|
||||
m_CurrentPoint.y - 5,
|
||||
SRCCOPY);
|
||||
|
||||
::SelectObject (m_hMemDC, hold_bmp);
|
||||
}
|
||||
|
||||
::ReleaseDC (m_hWnd, hdc);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Paint_Marker
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerClass::Paint_Marker (void)
|
||||
{
|
||||
HDC hdc = ::GetDC (m_hWnd);
|
||||
if (m_hMemDC != NULL) {
|
||||
|
||||
HBITMAP hmarker_bmp = ::LoadBitmap (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDB_MARKER));
|
||||
HBITMAP hold_bmp = (HBITMAP)::SelectObject (m_hMemDC, hmarker_bmp);
|
||||
|
||||
CRect rect;
|
||||
GetClientRect (&rect);
|
||||
::BitBlt (hdc,
|
||||
m_CurrentPoint.x - 5,
|
||||
m_CurrentPoint.y - 5,
|
||||
11,
|
||||
11,
|
||||
m_hMemDC,
|
||||
0,
|
||||
0,
|
||||
SRCINVERT);
|
||||
|
||||
::SelectObject (m_hMemDC, hold_bmp);
|
||||
::DeleteObject (hmarker_bmp);
|
||||
}
|
||||
|
||||
::ReleaseDC (m_hWnd, hdc);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Select_Color
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerClass::Select_Color (int red, int green, int blue)
|
||||
{
|
||||
m_CurrentColor = RGB (red, green, blue);
|
||||
m_CurrentPoint = Point_From_Color (m_CurrentColor);
|
||||
m_CurrentColor = Color_From_Point (m_CurrentPoint.x, m_CurrentPoint.y);
|
||||
|
||||
// Refresh the window
|
||||
InvalidateRect (NULL, FALSE);
|
||||
UpdateWindow ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Current_Color
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerClass::Get_Current_Color (int *red, int *green, int *blue)
|
||||
{
|
||||
(*red) = GetRValue (m_CurrentColor);
|
||||
(*green) = GetGValue (m_CurrentColor);
|
||||
(*blue) = GetBValue (m_CurrentColor);
|
||||
return ;
|
||||
}
|
||||
161
Code/Tools/LevelEdit/ColorPicker.h
Normal file
161
Code/Tools/LevelEdit/ColorPicker.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_COLORPICKER_H__C943A7EC_CAA3_11D2_8DDF_00104B6FD9E3__INCLUDED_)
|
||||
#define AFX_COLORPICKER_H__C943A7EC_CAA3_11D2_8DDF_00104B6FD9E3__INCLUDED_
|
||||
|
||||
#if _MSC_VER >= 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER >= 1000
|
||||
// ColorPicker.h : header file
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constants
|
||||
//
|
||||
|
||||
//
|
||||
// Window styles
|
||||
//
|
||||
#define CPS_SUNKEN 0x00000001
|
||||
#define CPS_RAISED 0x00000002
|
||||
|
||||
//
|
||||
// Window messages and notifications
|
||||
//
|
||||
#define CPN_COLORCHANGE 0x0001
|
||||
#define CPM_GETCOLOR (WM_USER+101)
|
||||
#define CPM_SETCOLOR (WM_USER+102)
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Structures
|
||||
//
|
||||
|
||||
// Structure used to send notifications via WM_NOTIFY
|
||||
typedef struct
|
||||
{
|
||||
NMHDR hdr;
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
float hue;
|
||||
} CP_NMHDR;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ColorPickerClass window
|
||||
//
|
||||
class ColorPickerClass : public CWnd
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
ColorPickerClass();
|
||||
|
||||
// Attributes
|
||||
public:
|
||||
|
||||
// Operations
|
||||
public:
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(ColorPickerClass)
|
||||
public:
|
||||
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
virtual ~ColorPickerClass();
|
||||
|
||||
// Generated message map functions
|
||||
protected:
|
||||
//{{AFX_MSG(ColorPickerClass)
|
||||
afx_msg void OnPaint();
|
||||
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
|
||||
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
|
||||
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
|
||||
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
|
||||
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
friend LRESULT WINAPI fnColorPickerProc (HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Public members
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Select_Color (int red, int green, int blue);
|
||||
void Get_Current_Color (int *red, int *green, int *blue);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Static members
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static ColorPickerClass *Get_Color_Picker (HWND window_handle) { return (ColorPickerClass *)::GetProp (window_handle, "CLASSPOINTER"); }
|
||||
|
||||
protected:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Private member data
|
||||
//
|
||||
void Paint_DIB (int width, int height, UCHAR *pbits);
|
||||
void Create_Bitmap (void);
|
||||
void Free_Bitmap (void);
|
||||
void Fill_Rect (UCHAR *pbits, const RECT &rect, COLORREF color, int scanline_size);
|
||||
void Frame_Rect (UCHAR *pbits, const RECT &rect, COLORREF color, int scanline_size);
|
||||
void Draw_Horz_Line (UCHAR *pbits, int x, int y, int len, COLORREF color, int scanline_size);
|
||||
void Draw_Vert_Line (UCHAR *pbits, int x, int y, int len, COLORREF color, int scanline_size);
|
||||
COLORREF Color_From_Point (int x, int y);
|
||||
CPoint Point_From_Color (COLORREF color);
|
||||
void Paint_Marker (void);
|
||||
void Erase_Marker (void);
|
||||
void Calc_Display_Rect (RECT &rect);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Private member data
|
||||
//
|
||||
HBITMAP m_hBitmap;
|
||||
HDC m_hMemDC;
|
||||
UCHAR * m_pBits;
|
||||
int m_iWidth;
|
||||
int m_iHeight;
|
||||
CPoint m_CurrentPoint;
|
||||
COLORREF m_CurrentColor;
|
||||
bool m_bSelecting;
|
||||
float m_CurrentHue;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_COLORPICKER_H__C943A7EC_CAA3_11D2_8DDF_00104B6FD9E3__INCLUDED_)
|
||||
653
Code/Tools/LevelEdit/ColorPickerDialogClass.cpp
Normal file
653
Code/Tools/LevelEdit/ColorPickerDialogClass.cpp
Normal file
@@ -0,0 +1,653 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// ColorPickerDialogClass.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "colorpickerdialogclass.h"
|
||||
#include "colorbar.h"
|
||||
#include "colorpicker.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
//extern HINSTANCE _hinstance;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Local constants
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
const DWORD UPDATE_COLOR_BARS = 0x00000001;
|
||||
const DWORD UPDATE_WHITENESS = 0x00000002;
|
||||
const DWORD UPDATE_HUE_PICKER = 0x00000004;
|
||||
|
||||
/*class MyManageStateClass
|
||||
{
|
||||
public:
|
||||
MyManageStateClass (void)
|
||||
{
|
||||
m_hResHandle = ::AfxGetResourceHandle ();
|
||||
::AfxSetResourceHandle (_hinstance);
|
||||
}
|
||||
|
||||
~MyManageStateClass (void) { ::AfxSetResourceHandle (m_hResHandle); }
|
||||
|
||||
private:
|
||||
HINSTANCE m_hResHandle;
|
||||
};*/
|
||||
|
||||
//#define MY_MANAGE_STATE() MyManageStateClass _xmystate;
|
||||
|
||||
HWND
|
||||
Create_Color_Picker_Form (HWND parent, int red, int green, int blue)
|
||||
{
|
||||
//MY_MANAGE_STATE ()
|
||||
|
||||
CWnd *parent_wnd = CWnd::FromHandle (parent);
|
||||
|
||||
ColorPickerDialogClass *dialog = new ColorPickerDialogClass (red, green, blue, parent_wnd, IDD_COLOR_FORM);
|
||||
dialog->Create_Form (parent_wnd);
|
||||
|
||||
//HINSTANCE old_handle = ::AfxGetResourceHandle ();
|
||||
//::AfxSetResourceHandle (_hinstance);
|
||||
return dialog->m_hWnd;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Get_Form_Color (HWND form_wnd, int *red, int *green, int *blue)
|
||||
{
|
||||
//MY_MANAGE_STATE ()
|
||||
|
||||
BOOL retval = FALSE;
|
||||
|
||||
ColorPickerDialogClass *dialog = (ColorPickerDialogClass *)::GetProp (form_wnd, "COLORPICKERDLGCLASS");
|
||||
if (dialog != NULL) {
|
||||
(*red) = dialog->Get_Red ();
|
||||
(*green) = dialog->Get_Green ();
|
||||
(*blue) = dialog->Get_Blue ();
|
||||
retval = TRUE;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
Set_Form_Color (HWND form_wnd, int red, int green, int blue)
|
||||
{
|
||||
//MY_MANAGE_STATE ()
|
||||
|
||||
BOOL retval = FALSE;
|
||||
|
||||
ColorPickerDialogClass *dialog = (ColorPickerDialogClass *)::GetProp (form_wnd, "COLORPICKERDLGCLASS");
|
||||
if (dialog != NULL) {
|
||||
dialog->Set_Color (red, green, blue);
|
||||
retval = TRUE;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
Set_Form_Original_Color (HWND form_wnd, int red, int green, int blue)
|
||||
{
|
||||
//MY_MANAGE_STATE ()
|
||||
|
||||
BOOL retval = FALSE;
|
||||
|
||||
ColorPickerDialogClass *dialog = (ColorPickerDialogClass *)::GetProp (form_wnd, "COLORPICKERDLGCLASS");
|
||||
if (dialog != NULL) {
|
||||
dialog->Set_Original_Color (red, green, blue);
|
||||
retval = TRUE;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
Show_Color_Picker (int *red, int *green, int *blue)
|
||||
{
|
||||
//MY_MANAGE_STATE ()
|
||||
|
||||
BOOL retval = FALSE;
|
||||
|
||||
ColorPickerDialogClass dialog (*red, *green, *blue);
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
(*red) = dialog.Get_Red ();
|
||||
(*green) = dialog.Get_Green ();
|
||||
(*blue) = dialog.Get_Blue ();
|
||||
retval = TRUE;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
Set_Update_Callback (HWND form_wnd, WWCTRL_COLORCALLBACK callback, void *arg)
|
||||
{
|
||||
//MY_MANAGE_STATE()
|
||||
|
||||
BOOL retval = FALSE;
|
||||
|
||||
ColorPickerDialogClass *dialog = (ColorPickerDialogClass *)::GetProp (form_wnd, "COLORPICKERDLGCLASS");
|
||||
if (dialog != NULL) {
|
||||
dialog->Set_Update_Callback(callback, arg);
|
||||
retval = TRUE;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ColorPickerDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
ColorPickerDialogClass::ColorPickerDialogClass
|
||||
(
|
||||
int red,
|
||||
int green,
|
||||
int blue,
|
||||
CWnd *pParent,
|
||||
UINT res_id
|
||||
)
|
||||
: m_OrigRed ((float)red),
|
||||
m_OrigGreen ((float)green),
|
||||
m_OrigBlue ((float)blue),
|
||||
m_CurrentRed ((float)red),
|
||||
m_CurrentGreen ((float)green),
|
||||
m_CurrentBlue ((float)blue),
|
||||
m_CurrentColorBar (NULL),
|
||||
m_OrigColorBar (NULL),
|
||||
m_RedColorBar (NULL),
|
||||
m_GreenColorBar (NULL),
|
||||
m_BlueColorBar (NULL),
|
||||
m_WhitenessColorBar (NULL),
|
||||
m_HuePicker (NULL),
|
||||
m_bDeleteOnClose (false),
|
||||
m_UpdateCallback(NULL),
|
||||
CDialog(res_id, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(ColorPickerDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create_Form
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerDialogClass::Create_Form (CWnd *parent)
|
||||
{
|
||||
Create (IDD_COLOR_FORM, parent);
|
||||
SetProp (m_hWnd, "COLORPICKERDLGCLASS", (HANDLE)this);
|
||||
m_bDeleteOnClose = true;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerDialogClass::DoDataExchange (CDataExchange *pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(ColorPickerDialogClass)
|
||||
DDX_Control(pDX, IDC_BLUE_SPIN, m_BlueSpin);
|
||||
DDX_Control(pDX, IDC_GREEN_SPIN, m_GreenSpin);
|
||||
DDX_Control(pDX, IDC_RED_SPIN, m_RedSpin);
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(ColorPickerDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(ColorPickerDialogClass)
|
||||
ON_BN_CLICKED(IDC_RESET, OnReset)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
ColorPickerDialogClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
//
|
||||
// Setup the spin controls
|
||||
//
|
||||
m_BlueSpin.SetRange (0, 255);
|
||||
m_GreenSpin.SetRange (0, 255);
|
||||
m_RedSpin.SetRange (0, 255);
|
||||
m_BlueSpin.SetPos ((int)m_CurrentBlue);
|
||||
m_GreenSpin.SetPos ((int)m_CurrentGreen);
|
||||
m_RedSpin.SetPos ((int)m_CurrentRed);
|
||||
|
||||
//
|
||||
// Get control of all the color bars on the dialog
|
||||
//
|
||||
m_CurrentColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_CURRENT_COLOR_BAR));
|
||||
m_OrigColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_ORIG_COLOR_BAR));
|
||||
m_RedColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_RED_BAR));
|
||||
m_GreenColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_GREEN_BAR));
|
||||
m_BlueColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_BLUE_BAR));
|
||||
m_WhitenessColorBar = ColorBarClass::Get_Color_Bar (::GetDlgItem (m_hWnd, IDC_WHITENESS_BAR));
|
||||
m_HuePicker = ColorPickerClass::Get_Color_Picker (::GetDlgItem (m_hWnd, IDC_HUE_PICKER));
|
||||
|
||||
// Setup the original color bar
|
||||
m_OrigColorBar->Modify_Point (0, 0, m_OrigRed, m_OrigGreen, m_OrigBlue);
|
||||
m_HuePicker->Select_Color ((int)m_OrigRed, (int)m_OrigGreen, (int)m_OrigBlue);
|
||||
//m_WhitenessColorBar->Modify_Point (0, 0, m_OrigRed, m_OrigGreen, m_OrigBlue);
|
||||
|
||||
m_RedColorBar->Set_Range (0, 255);
|
||||
m_GreenColorBar->Set_Range (0, 255);
|
||||
m_BlueColorBar->Set_Range (0, 255);
|
||||
m_WhitenessColorBar->Set_Range (0, 255);
|
||||
|
||||
m_WhitenessColorBar->Insert_Point (1, 255, 255, 255, 255);
|
||||
|
||||
//
|
||||
// Setup the red/green/blue color bars
|
||||
//
|
||||
//m_RedColorBar->Insert_Point (1, 1, 255, 0, 0);
|
||||
//m_GreenColorBar->Insert_Point (1, 1, 0, 255, 0);
|
||||
//m_BlueColorBar->Insert_Point (1, 1, 0, 0, 255);
|
||||
|
||||
//
|
||||
// Update the remaining color bars to reflect the initial color
|
||||
//
|
||||
Update_Red_Bar ();
|
||||
Update_Green_Bar ();
|
||||
Update_Blue_Bar ();
|
||||
Update_Current_Color_Bar ();
|
||||
Update_Whiteness_Bar ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Red_Bar
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerDialogClass::Update_Red_Bar (void)
|
||||
{
|
||||
m_RedColorBar->Set_Selection_Pos (m_CurrentRed);
|
||||
m_RedColorBar->Modify_Point (0, 0, 0, (float)m_CurrentGreen, (float)m_CurrentBlue);
|
||||
m_RedColorBar->Modify_Point (1, 255, 255, (float)m_CurrentGreen, (float)m_CurrentBlue);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Green_Bar
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerDialogClass::Update_Green_Bar (void)
|
||||
{
|
||||
m_GreenColorBar->Set_Selection_Pos (m_CurrentGreen);
|
||||
m_GreenColorBar->Modify_Point (0, 0, m_CurrentRed, 0, m_CurrentBlue);
|
||||
m_GreenColorBar->Modify_Point (1, 255, m_CurrentRed, 255, m_CurrentBlue);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Blue_Bar
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerDialogClass::Update_Blue_Bar (void)
|
||||
{
|
||||
m_BlueColorBar->Set_Selection_Pos (m_CurrentBlue);
|
||||
m_BlueColorBar->Modify_Point (0, 0, m_CurrentRed, m_CurrentGreen, 0);
|
||||
m_BlueColorBar->Modify_Point (1, 255, m_CurrentRed, m_CurrentGreen, 255);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Current_Color_Bar
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerDialogClass::Update_Current_Color_Bar (void)
|
||||
{
|
||||
m_CurrentColorBar->Modify_Point (0, 0, m_CurrentRed, m_CurrentGreen, m_CurrentBlue);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Whiteness_Bar
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerDialogClass::Update_Whiteness_Bar (void)
|
||||
{
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
m_HuePicker->Get_Current_Color (&red, &green, &blue);
|
||||
|
||||
//
|
||||
// Given the current color, determine the 'whiteness' and update
|
||||
//
|
||||
float whiteness = min (m_CurrentRed, m_CurrentGreen);
|
||||
whiteness = min (whiteness, m_CurrentBlue);
|
||||
float percent = whiteness / 255;
|
||||
m_WhitenessColorBar->Set_Selection_Pos (whiteness);
|
||||
|
||||
m_WhitenessColorBar->Modify_Point (0, 0, (float)red, (float)green, (float)blue);
|
||||
|
||||
// Can we extrapolate the starting color from the whiteness factor?
|
||||
/*if (percent == 1) {
|
||||
m_WhitenessColorBar->Modify_Point (0, 0, 0, 0, 0);
|
||||
} else {
|
||||
|
||||
//
|
||||
// Extrapolate the starting color
|
||||
//
|
||||
float start_red = (m_CurrentRed - whiteness) / (1 - percent);
|
||||
float start_green = (m_CurrentGreen - whiteness) / (1 - percent);
|
||||
float start_blue = (m_CurrentBlue - whiteness) / (1 - percent);
|
||||
m_WhitenessColorBar->Modify_Point (0, 0, start_red, start_green, start_blue);
|
||||
}*/
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnNotify
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
ColorPickerDialogClass::OnNotify
|
||||
(
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
LRESULT *pResult
|
||||
)
|
||||
{
|
||||
CBR_NMHDR *color_bar_hdr = (CBR_NMHDR *)lParam;
|
||||
switch (color_bar_hdr->hdr.idFrom)
|
||||
{
|
||||
case IDC_RED_BAR:
|
||||
{
|
||||
if (color_bar_hdr->hdr.code == CBRN_SEL_CHANGED) {
|
||||
float red = color_bar_hdr->red;
|
||||
float green = m_CurrentGreen;
|
||||
float blue = m_CurrentBlue;
|
||||
Update_Color (red, green, blue);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_GREEN_BAR:
|
||||
{
|
||||
if (color_bar_hdr->hdr.code == CBRN_SEL_CHANGED) {
|
||||
float red = m_CurrentRed;
|
||||
float green = color_bar_hdr->green;
|
||||
float blue = m_CurrentBlue;
|
||||
Update_Color (red, green, blue);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_BLUE_BAR:
|
||||
{
|
||||
if (color_bar_hdr->hdr.code == CBRN_SEL_CHANGED) {
|
||||
float red = m_CurrentRed;
|
||||
float green = m_CurrentGreen;
|
||||
float blue = color_bar_hdr->blue;
|
||||
Update_Color (red, green, blue);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_WHITENESS_BAR:
|
||||
{
|
||||
if (color_bar_hdr->hdr.code == CBRN_SEL_CHANGED) {
|
||||
float red = color_bar_hdr->red;
|
||||
float green = color_bar_hdr->green;
|
||||
float blue = color_bar_hdr->blue;
|
||||
Update_Color (red, green, blue, UPDATE_COLOR_BARS);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_HUE_PICKER:
|
||||
{
|
||||
CP_NMHDR *picker_hdr = (CP_NMHDR *)lParam;
|
||||
if (picker_hdr->hdr.code == CPN_COLORCHANGE) {
|
||||
float red = picker_hdr->red;
|
||||
float green = picker_hdr->green;
|
||||
float blue = picker_hdr->blue;
|
||||
float whiteness = m_WhitenessColorBar->Get_Selection_Pos () / 255;
|
||||
red = red + ((255 - red) * whiteness);
|
||||
green = green + ((255 - green) * whiteness);
|
||||
blue = blue + ((255 - blue) * whiteness);
|
||||
Update_Color (red, green, blue, UPDATE_COLOR_BARS | UPDATE_WHITENESS);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_RED_SPIN:
|
||||
case IDC_GREEN_SPIN:
|
||||
case IDC_BLUE_SPIN:
|
||||
{
|
||||
if (color_bar_hdr->hdr.code == UDN_DELTAPOS) {
|
||||
float red = (float)m_RedSpin.GetPos ();
|
||||
float green = (float)m_GreenSpin.GetPos ();
|
||||
float blue = (float)m_BlueSpin.GetPos ();
|
||||
Update_Color (red, green, blue, UPDATE_COLOR_BARS | UPDATE_WHITENESS | UPDATE_HUE_PICKER);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CDialog::OnNotify (wParam, lParam, pResult);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Color
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerDialogClass::Update_Color
|
||||
(
|
||||
float red,
|
||||
float green,
|
||||
float blue,
|
||||
DWORD flags
|
||||
)
|
||||
{
|
||||
/*bool update_red = m_CurrentRed != red;
|
||||
bool update_green = m_CurrentGreen != green;
|
||||
bool update_blue = m_CurrentBlue != blue;*/
|
||||
|
||||
m_CurrentRed = red;
|
||||
m_CurrentGreen = green;
|
||||
m_CurrentBlue = blue;
|
||||
|
||||
int int_blue = (int)blue;
|
||||
int int_green = (int)green;
|
||||
int int_red = (int)red;
|
||||
if (int_blue != m_BlueSpin.GetPos ()) {
|
||||
m_BlueSpin.SetPos (int_blue);
|
||||
}
|
||||
if (int_green != m_GreenSpin.GetPos ()) {
|
||||
m_GreenSpin.SetPos (int_green);
|
||||
}
|
||||
if (int_red != m_RedSpin.GetPos ()) {
|
||||
m_RedSpin.SetPos (int_red);
|
||||
}
|
||||
|
||||
// Hack to get the edit controls to update in a timely fashion
|
||||
::UpdateWindow (::GetDlgItem (m_hWnd, IDC_RED_EDIT));
|
||||
::UpdateWindow (::GetDlgItem (m_hWnd, IDC_GREEN_EDIT));
|
||||
::UpdateWindow (::GetDlgItem (m_hWnd, IDC_BLUE_EDIT));
|
||||
|
||||
//
|
||||
// Update the red, green and blue color bars
|
||||
//
|
||||
if (flags & UPDATE_COLOR_BARS) {
|
||||
Update_Red_Bar ();
|
||||
Update_Green_Bar ();
|
||||
Update_Blue_Bar ();
|
||||
}
|
||||
|
||||
//
|
||||
// Update the hue picker
|
||||
//
|
||||
if (flags & UPDATE_HUE_PICKER) {
|
||||
m_HuePicker->Select_Color ((int)red, (int)green, (int)blue);
|
||||
}
|
||||
|
||||
//
|
||||
// Update the whiteness color bar
|
||||
//
|
||||
if (flags & UPDATE_WHITENESS) {
|
||||
Update_Whiteness_Bar ();
|
||||
}
|
||||
|
||||
Update_Current_Color_Bar ();
|
||||
|
||||
// If a callback is registered, call it.
|
||||
if (m_UpdateCallback)
|
||||
m_UpdateCallback((int)red, (int)green, (int)blue, m_CallArg);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Original_Color
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void ColorPickerDialogClass::Set_Original_Color (int r, int g, int b)
|
||||
{
|
||||
m_OrigRed = (float)r;
|
||||
m_OrigGreen = (float)g;
|
||||
m_OrigBlue = (float)b;
|
||||
m_OrigColorBar->Modify_Point (0, 0, m_OrigRed, m_OrigGreen, m_OrigBlue);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnReset
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerDialogClass::OnReset (void)
|
||||
{
|
||||
Update_Color (m_OrigRed,
|
||||
m_OrigGreen,
|
||||
m_OrigBlue,
|
||||
UPDATE_COLOR_BARS| UPDATE_WHITENESS | UPDATE_HUE_PICKER);
|
||||
return ;
|
||||
}
|
||||
|
||||
LRESULT ColorPickerDialogClass::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return CDialog::WindowProc(message, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnCommand
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
ColorPickerDialogClass::OnCommand
|
||||
(
|
||||
WPARAM wParam,
|
||||
LPARAM lParam
|
||||
)
|
||||
{
|
||||
switch (LOWORD (wParam))
|
||||
{
|
||||
case IDC_RED_EDIT:
|
||||
case IDC_GREEN_EDIT:
|
||||
case IDC_BLUE_EDIT:
|
||||
{
|
||||
if (HIWORD (wParam) == EN_KILLFOCUS) {
|
||||
float red = (float)GetDlgItemInt (IDC_RED_EDIT);
|
||||
float green = (float)GetDlgItemInt (IDC_GREEN_EDIT);
|
||||
float blue = (float)GetDlgItemInt (IDC_BLUE_EDIT);
|
||||
Update_Color (red, green, blue, UPDATE_COLOR_BARS| UPDATE_WHITENESS | UPDATE_HUE_PICKER);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CDialog::OnCommand(wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PostNcDestroy
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ColorPickerDialogClass::PostNcDestroy (void)
|
||||
{
|
||||
CDialog::PostNcDestroy();
|
||||
|
||||
if (m_bDeleteOnClose) {
|
||||
delete this;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
136
Code/Tools/LevelEdit/ColorPickerDialogClass.h
Normal file
136
Code/Tools/LevelEdit/ColorPickerDialogClass.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_COLORPICKERDIALOGCLASS_H__C943A7F1_CAA3_11D2_8DDF_00104B6FD9E3__INCLUDED_)
|
||||
#define AFX_COLORPICKERDIALOGCLASS_H__C943A7F1_CAA3_11D2_8DDF_00104B6FD9E3__INCLUDED_
|
||||
|
||||
#if _MSC_VER >= 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER >= 1000
|
||||
// ColorPickerDialogClass.h : header file
|
||||
//
|
||||
|
||||
#include "resource.h"
|
||||
#include "colorutils.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class ColorBarClass;
|
||||
class ColorPickerClass;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ColorPickerDialogClass dialog
|
||||
//
|
||||
class ColorPickerDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
ColorPickerDialogClass (int red, int green, int blue, CWnd* pParent = NULL, UINT res_id = ColorPickerDialogClass::IDD);
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(ColorPickerDialogClass)
|
||||
enum { IDD = IDD_COLOR_PICKER };
|
||||
CSpinButtonCtrl m_BlueSpin;
|
||||
CSpinButtonCtrl m_GreenSpin;
|
||||
CSpinButtonCtrl m_RedSpin;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(ColorPickerDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
|
||||
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
|
||||
virtual void PostNcDestroy();
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(ColorPickerDialogClass)
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnReset();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
/////////////////////////////////////////////////////////////
|
||||
int Get_Red (void) const { return (int)m_CurrentRed; }
|
||||
int Get_Green (void) const { return (int)m_CurrentGreen; }
|
||||
int Get_Blue (void) const { return (int)m_CurrentBlue; }
|
||||
void Set_Color (int r, int g, int b)
|
||||
{ Update_Color((float)r, (float)g, (float)b); }
|
||||
void Set_Original_Color (int r, int g, int b);
|
||||
void Create_Form (CWnd *parent);
|
||||
void Set_Update_Callback (WWCTRL_COLORCALLBACK callme, void *arg)
|
||||
{ m_UpdateCallback = callme; m_CallArg = arg; }
|
||||
|
||||
protected:
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
/////////////////////////////////////////////////////////////
|
||||
void Update_Red_Bar (void);
|
||||
void Update_Green_Bar (void);
|
||||
void Update_Blue_Bar (void);
|
||||
void Update_Current_Color_Bar (void);
|
||||
void Update_Whiteness_Bar (void);
|
||||
void Update_Color (float red, float green, float blue, DWORD flags = 0xFFFFFFFF);
|
||||
|
||||
private:
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
/////////////////////////////////////////////////////////////
|
||||
float m_OrigRed;
|
||||
float m_OrigGreen;
|
||||
float m_OrigBlue;
|
||||
|
||||
float m_CurrentRed;
|
||||
float m_CurrentGreen;
|
||||
float m_CurrentBlue;
|
||||
|
||||
ColorBarClass * m_CurrentColorBar;
|
||||
ColorBarClass * m_OrigColorBar;
|
||||
ColorBarClass * m_RedColorBar;
|
||||
ColorBarClass * m_GreenColorBar;
|
||||
ColorBarClass * m_BlueColorBar;
|
||||
ColorBarClass * m_WhitenessColorBar;
|
||||
ColorPickerClass *m_HuePicker;
|
||||
|
||||
bool m_bDeleteOnClose;
|
||||
|
||||
// Callback function when color is updated.
|
||||
WWCTRL_COLORCALLBACK m_UpdateCallback;
|
||||
void * m_CallArg;
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_COLORPICKERDIALOGCLASS_H__C943A7F1_CAA3_11D2_8DDF_00104B6FD9E3__INCLUDED_)
|
||||
247
Code/Tools/LevelEdit/ColorSelectionDialog.cpp
Normal file
247
Code/Tools/LevelEdit/ColorSelectionDialog.cpp
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// ColorSelectionDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "StdAfx.H"
|
||||
#include "LevelEdit.H"
|
||||
#include "ColorSelectionDialog.H"
|
||||
#include "Utils.H"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ColorSelectionDialogClass
|
||||
//
|
||||
ColorSelectionDialogClass::ColorSelectionDialogClass
|
||||
(
|
||||
const Vector3 &def_color,
|
||||
CWnd *pParent
|
||||
)
|
||||
: m_Color (def_color),
|
||||
m_PaintColor (def_color),
|
||||
CDialog(ColorSelectionDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(ColorSelectionDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
void
|
||||
ColorSelectionDialogClass::DoDataExchange (CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(ColorSelectionDialogClass)
|
||||
DDX_Control(pDX, IDC_COLOR_WINDOW, m_ColorWindow);
|
||||
DDX_Control(pDX, IDC_SLIDER_BLUE, m_BlueSlider);
|
||||
DDX_Control(pDX, IDC_SLIDER_GREEN, m_GreenSlider);
|
||||
DDX_Control(pDX, IDC_SLIDER_RED, m_RedSlider);
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(ColorSelectionDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(ColorSelectionDialogClass)
|
||||
ON_WM_HSCROLL()
|
||||
ON_WM_PAINT()
|
||||
ON_BN_CLICKED(IDC_GRAYSCALE_CHECK, OnGrayscaleCheck)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ColorSelectionDialogClass
|
||||
//
|
||||
BOOL
|
||||
ColorSelectionDialogClass::OnInitDialog (void)
|
||||
{
|
||||
// Allow the base class to process this message
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
// Set the ranges of the slider controls
|
||||
m_RedSlider.SetRange (0, 100);
|
||||
m_GreenSlider.SetRange (0, 100);
|
||||
m_BlueSlider.SetRange (0, 100);
|
||||
|
||||
// Determine the initial settings (in integers)
|
||||
int red_value = int(m_Color.X * 100.00F);
|
||||
int green_value = int(m_Color.Y * 100.00F);
|
||||
int blue_value = int(m_Color.Z * 100.00F);
|
||||
|
||||
if ((red_value == green_value) &&
|
||||
(red_value == blue_value)) {
|
||||
|
||||
// Check the grayscale checkbox
|
||||
SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_SETCHECK, (WPARAM)TRUE);
|
||||
}
|
||||
|
||||
// Set the initial slider positions
|
||||
m_RedSlider.SetPos (red_value);
|
||||
m_GreenSlider.SetPos (green_value);
|
||||
m_BlueSlider.SetPos (blue_value);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ColorSelectionDialogClass
|
||||
//
|
||||
void
|
||||
ColorSelectionDialogClass::OnOK (void)
|
||||
{
|
||||
// Record the color
|
||||
m_Color = m_PaintColor;
|
||||
|
||||
// Allow the base class to process this message
|
||||
CDialog::OnOK ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnHScroll
|
||||
//
|
||||
void
|
||||
ColorSelectionDialogClass::OnHScroll
|
||||
(
|
||||
UINT nSBCode,
|
||||
UINT nPos,
|
||||
CScrollBar *pScrollBar
|
||||
)
|
||||
{
|
||||
// Are the sliders moving together?
|
||||
if (SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_GETCHECK)) {
|
||||
int position = 0;
|
||||
|
||||
// Determine which slider sent this message and
|
||||
// use its current positions
|
||||
if (pScrollBar == GetDlgItem (IDC_SLIDER_RED)) {
|
||||
position = m_RedSlider.GetPos ();
|
||||
} else if (pScrollBar == GetDlgItem (IDC_SLIDER_GREEN)) {
|
||||
position = m_GreenSlider.GetPos ();
|
||||
} else {
|
||||
position = m_BlueSlider.GetPos ();
|
||||
}
|
||||
|
||||
// Make all the sliders the same pos
|
||||
m_RedSlider.SetPos (position);
|
||||
m_GreenSlider.SetPos (position);
|
||||
m_BlueSlider.SetPos (position);
|
||||
}
|
||||
|
||||
// Record the selected color for later use
|
||||
m_PaintColor.X = float(m_RedSlider.GetPos ()) / 100.00F;
|
||||
m_PaintColor.Y = float(m_GreenSlider.GetPos ()) / 100.00F;
|
||||
m_PaintColor.Z = float(m_BlueSlider.GetPos ()) / 100.00F;
|
||||
|
||||
// Update the window that displays the color the user has selected
|
||||
Paint_Color_Window ();
|
||||
|
||||
// Allow the base class to process this message
|
||||
CDialog::OnHScroll (nSBCode, nPos, pScrollBar);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnPaint
|
||||
//
|
||||
void
|
||||
ColorSelectionDialogClass::OnPaint (void)
|
||||
{
|
||||
CPaintDC dc (this);
|
||||
|
||||
// Paint the gradients for each color
|
||||
::Paint_Gradient (::GetDlgItem (m_hWnd, IDC_RED_GRADIENT), 1, 0, 0);
|
||||
::Paint_Gradient (::GetDlgItem (m_hWnd, IDC_GREEN_GRADIENT), 0, 1, 0);
|
||||
::Paint_Gradient (::GetDlgItem (m_hWnd, IDC_BLUE_GRADIENT), 0, 0, 1);
|
||||
|
||||
// Update the window that displays the color the user has selected
|
||||
Paint_Color_Window ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Paint_Color_Window
|
||||
//
|
||||
void
|
||||
ColorSelectionDialogClass::Paint_Color_Window (void)
|
||||
{
|
||||
// Get the client coords of the 'color' window
|
||||
CRect rect;
|
||||
m_ColorWindow.GetClientRect (&rect);
|
||||
|
||||
// Fill the window with the selected color
|
||||
CDC *pdc = m_ColorWindow.GetDC ();
|
||||
::FrameRect (*pdc, &rect, (HBRUSH)::GetStockObject (BLACK_BRUSH));
|
||||
rect.DeflateRect (1, 1);
|
||||
pdc->FillSolidRect (&rect, RGB (int(m_PaintColor.X * 255), int(m_PaintColor.Y * 255), int(m_PaintColor.Z * 255)));
|
||||
m_ColorWindow.ReleaseDC (pdc);
|
||||
|
||||
// Let the window know it doesn't need to be repainted
|
||||
m_ColorWindow.ValidateRect (NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnGrayscaleCheck
|
||||
//
|
||||
void
|
||||
ColorSelectionDialogClass::OnGrayscaleCheck (void)
|
||||
{
|
||||
// Is the checkbox checked?
|
||||
if (SendDlgItemMessage (IDC_GRAYSCALE_CHECK, BM_GETCHECK)) {
|
||||
|
||||
// Make the green and blue sliders the same as red
|
||||
m_GreenSlider.SetPos (m_RedSlider.GetPos ());
|
||||
m_BlueSlider.SetPos (m_RedSlider.GetPos ());
|
||||
|
||||
Vector3 light_settings;
|
||||
light_settings.X = float(m_RedSlider.GetPos ()) / 100.00F;
|
||||
light_settings.Y = float(m_GreenSlider.GetPos ()) / 100.00F;
|
||||
light_settings.Z = float(m_BlueSlider.GetPos ()) / 100.00F;
|
||||
|
||||
// Update the window that displays the color the user has selected
|
||||
Paint_Color_Window ();
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
102
Code/Tools/LevelEdit/ColorSelectionDialog.h
Normal file
102
Code/Tools/LevelEdit/ColorSelectionDialog.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_OLORSELECTIONDIALOG_H__C0BCECAE_B6EA_11D2_9FF8_00104B791122__INCLUDED_)
|
||||
#define AFX_OLORSELECTIONDIALOG_H__C0BCECAE_B6EA_11D2_9FF8_00104B791122__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
// ColorSelectionDialog.h : header file
|
||||
//
|
||||
|
||||
#include "Resource.H"
|
||||
#include "Vector3.H"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ColorSelectionDialogClass dialog
|
||||
//
|
||||
class ColorSelectionDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
ColorSelectionDialogClass (const Vector3 &def_color, CWnd *pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(ColorSelectionDialogClass)
|
||||
enum { IDD = IDD_COLOR_SEL };
|
||||
CStatic m_ColorWindow;
|
||||
CSliderCtrl m_BlueSlider;
|
||||
CSliderCtrl m_GreenSlider;
|
||||
CSliderCtrl m_RedSlider;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(ColorSelectionDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(ColorSelectionDialogClass)
|
||||
virtual BOOL OnInitDialog();
|
||||
virtual void OnOK();
|
||||
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
|
||||
afx_msg void OnPaint();
|
||||
afx_msg void OnGrayscaleCheck();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// Public methods
|
||||
//
|
||||
const Vector3 & Get_Color (void) const { return m_Color; }
|
||||
void Set_Color (const Vector3 &color) { m_Color = color; }
|
||||
|
||||
protected:
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// Inline accessors
|
||||
//
|
||||
void Paint_Color_Window (void);
|
||||
|
||||
private:
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// Private member data
|
||||
//
|
||||
Vector3 m_Color;
|
||||
Vector3 m_PaintColor;
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_OLORSELECTIONDIALOG_H__C0BCECAE_B6EA_11D2_9FF8_00104B791122__INCLUDED_)
|
||||
188
Code/Tools/LevelEdit/ColorUtils.cpp
Normal file
188
Code/Tools/LevelEdit/ColorUtils.cpp
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Utils.cpp
|
||||
//
|
||||
//
|
||||
|
||||
#include "StdAfx.H"
|
||||
#include "ColorUtils.H"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Draw_Sunken_Rect
|
||||
//
|
||||
void
|
||||
Draw_Sunken_Rect
|
||||
(
|
||||
UCHAR *pbits,
|
||||
const RECT &rect,
|
||||
int scanline_size
|
||||
)
|
||||
{
|
||||
int width = rect.right - rect.left;
|
||||
int height = rect.bottom - rect.top;
|
||||
|
||||
// Draw the 4 lines that compose the rectangle
|
||||
::Draw_Vert_Line (pbits, rect.left, rect.top, height, ::GetSysColor (COLOR_3DSHADOW), scanline_size);
|
||||
::Draw_Vert_Line (pbits, rect.right-1, rect.top, height, ::GetSysColor (COLOR_3DHIGHLIGHT), scanline_size);
|
||||
::Draw_Horz_Line (pbits, rect.left, rect.top, width, ::GetSysColor (COLOR_3DSHADOW), scanline_size);
|
||||
::Draw_Horz_Line (pbits, rect.left, rect.bottom-1, width, ::GetSysColor (COLOR_3DHIGHLIGHT), scanline_size);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Draw_Raised_Rect
|
||||
//
|
||||
void
|
||||
Draw_Raised_Rect
|
||||
(
|
||||
UCHAR *pbits,
|
||||
const RECT &rect,
|
||||
int scanline_size
|
||||
)
|
||||
{
|
||||
int width = rect.right - rect.left;
|
||||
int height = rect.bottom - rect.top;
|
||||
|
||||
// Draw the 4 lines that compose the rectangle
|
||||
::Draw_Vert_Line (pbits, rect.left, rect.top, height, ::GetSysColor (COLOR_3DHIGHLIGHT), scanline_size);
|
||||
::Draw_Vert_Line (pbits, rect.right-1, rect.top, height, ::GetSysColor (COLOR_3DSHADOW), scanline_size);
|
||||
::Draw_Horz_Line (pbits, rect.left, rect.top, width, ::GetSysColor (COLOR_3DHIGHLIGHT), scanline_size);
|
||||
::Draw_Horz_Line (pbits, rect.left, rect.bottom-1, width, ::GetSysColor (COLOR_3DSHADOW), scanline_size);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Frame_Rect
|
||||
//
|
||||
void
|
||||
Frame_Rect
|
||||
(
|
||||
UCHAR *pbits,
|
||||
const RECT &rect,
|
||||
COLORREF color,
|
||||
int scanline_size
|
||||
)
|
||||
{
|
||||
UCHAR red = GetRValue (color);
|
||||
UCHAR green = GetRValue (color);
|
||||
UCHAR blue = GetRValue (color);
|
||||
|
||||
int index = (rect.top * scanline_size) + (rect.left * 3);
|
||||
for (int col = rect.left; col < rect.right; col ++) {
|
||||
pbits[index++] = blue;
|
||||
pbits[index++] = green;
|
||||
pbits[index++] = red;
|
||||
}
|
||||
|
||||
index = ((rect.bottom-1) * scanline_size) + (rect.left * 3);
|
||||
for (col = rect.left; col < rect.right; col ++) {
|
||||
pbits[index++] = blue;
|
||||
pbits[index++] = green;
|
||||
pbits[index++] = red;
|
||||
}
|
||||
|
||||
index = (rect.top * scanline_size) + (rect.left * 3);
|
||||
for (int row = rect.top; row < rect.bottom; row ++) {
|
||||
pbits[index] = blue;
|
||||
pbits[index + 1] = green;
|
||||
pbits[index + 2] = red;
|
||||
index += scanline_size;
|
||||
}
|
||||
|
||||
index = (rect.top * scanline_size) + ((rect.right-1) * 3);
|
||||
for (row = rect.top; row < rect.bottom; row ++) {
|
||||
pbits[index] = blue;
|
||||
pbits[index + 1] = green;
|
||||
pbits[index + 2] = red;
|
||||
index += scanline_size;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Draw_Vert_Line
|
||||
//
|
||||
void
|
||||
Draw_Vert_Line
|
||||
(
|
||||
UCHAR *pbits,
|
||||
int x,
|
||||
int y,
|
||||
int len,
|
||||
COLORREF color,
|
||||
int scanline_size
|
||||
)
|
||||
{
|
||||
UCHAR red = GetRValue (color);
|
||||
UCHAR green = GetRValue (color);
|
||||
UCHAR blue = GetRValue (color);
|
||||
|
||||
int index = (y * scanline_size) + (x * 3);
|
||||
for (int row = y; row < len; row ++) {
|
||||
pbits[index] = blue;
|
||||
pbits[index + 1] = green;
|
||||
pbits[index + 2] = red;
|
||||
index += scanline_size;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Draw_Horz_Line
|
||||
//
|
||||
void
|
||||
Draw_Horz_Line
|
||||
(
|
||||
UCHAR *pbits,
|
||||
int x,
|
||||
int y,
|
||||
int len,
|
||||
COLORREF color,
|
||||
int scanline_size
|
||||
)
|
||||
{
|
||||
UCHAR red = GetRValue (color);
|
||||
UCHAR green = GetRValue (color);
|
||||
UCHAR blue = GetRValue (color);
|
||||
|
||||
int index = (y * scanline_size) + (x * 3);
|
||||
for (int col = x; col < len; col ++) {
|
||||
pbits[index++] = blue;
|
||||
pbits[index++] = green;
|
||||
pbits[index++] = red;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
51
Code/Tools/LevelEdit/ColorUtils.h
Normal file
51
Code/Tools/LevelEdit/ColorUtils.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ColorUtils.H
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __COLORUTILS_H
|
||||
#define __COLORUTILS_H
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Callbacks
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
typedef void (*WWCTRL_COLORCALLBACK)(int,int,int,void*);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Prototypes
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void Frame_Rect (UCHAR *pbits, const RECT &rect, COLORREF color, int scanline_size);
|
||||
void Draw_Vert_Line (UCHAR *pbits, int x, int y, int len, COLORREF color, int scanline_size);
|
||||
void Draw_Horz_Line (UCHAR *pbits, int x, int y, int len, COLORREF color, int scanline_size);
|
||||
void Draw_Sunken_Rect (UCHAR *pbits, const RECT &rect, int scanline_size);
|
||||
void Draw_Raised_Rect (UCHAR *pbits, const RECT &rect, int scanline_size);
|
||||
BOOL Show_Color_Picker (int *red, int *green, int *blue);
|
||||
HWND Create_Color_Picker_Form (HWND parent, int red, int green, int blue);
|
||||
BOOL Get_Form_Color (HWND form_wnd, int *red, int *green, int *blue);
|
||||
BOOL Set_Form_Color (HWND form_wnd, int red, int green, int blue);
|
||||
BOOL Set_Form_Original_Color (HWND form_wnd, int red, int green, int blue);
|
||||
BOOL Set_Update_Callback (HWND form_wnd, WWCTRL_COLORCALLBACK callback, void *arg=NULL);
|
||||
void RegisterColorPicker (HINSTANCE hinst);
|
||||
void RegisterColorBar (HINSTANCE hinst);
|
||||
|
||||
|
||||
#endif //__COLORUTILS_H
|
||||
266
Code/Tools/LevelEdit/ConversationEditorMgr.cpp
Normal file
266
Code/Tools/LevelEdit/ConversationEditorMgr.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/ConversationEditorMgr.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 1/23/02 1:12p $*
|
||||
* *
|
||||
* $Revision:: 4 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "conversationeditormgr.h"
|
||||
#include "filelocations.h"
|
||||
#include "filemgr.h"
|
||||
#include "assetdatabase.h"
|
||||
#include "chunkio.h"
|
||||
#include "rawfile.h"
|
||||
#include "saveload.h"
|
||||
#include "translatedb.h"
|
||||
#include "conversationmgr.h"
|
||||
#include "conversationpage.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create_Database_If_Necessary
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationEditorMgrClass::Create_Database_If_Necessary (void)
|
||||
{
|
||||
FileMgrClass *file_mgr = ::Get_File_Mgr ();
|
||||
AssetDatabaseClass &asset_db = file_mgr->Get_Database_Interface ();
|
||||
|
||||
//
|
||||
// Determine where the file should exist locally
|
||||
//
|
||||
CString filename = ::Get_File_Mgr ()->Make_Full_Path (CONV_DB_PATH);
|
||||
|
||||
//
|
||||
// Check to see if the file exists in VSS
|
||||
//
|
||||
if (asset_db.Does_File_Exist (filename) == false) {
|
||||
|
||||
//
|
||||
// Save a copy of the database to disk and add it to VSS
|
||||
//
|
||||
Save_Global_Database ();
|
||||
asset_db.Add_File (filename);
|
||||
} else {
|
||||
|
||||
//
|
||||
// The file exists in VSS, so update our local copy
|
||||
//
|
||||
Get_Latest_Version ();
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save_Global_Database
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationEditorMgrClass::Save_Global_Database (void)
|
||||
{
|
||||
CString filename = ::Get_File_Mgr ()->Make_Full_Path (CONV_DB_PATH);
|
||||
|
||||
//
|
||||
// Create the file
|
||||
//
|
||||
HANDLE file = ::CreateFile (filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||||
0L, NULL);
|
||||
|
||||
ASSERT (file != INVALID_HANDLE_VALUE);
|
||||
if (file != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (file);
|
||||
ChunkSaveClass chunk_save (&file_obj);
|
||||
|
||||
//
|
||||
// Save the conversation database subsystem
|
||||
//
|
||||
_ConversationMgrSaveLoad.Set_Category_To_Save (ConversationMgrClass::CATEGORY_GLOBAL);
|
||||
SaveLoadSystemClass::Save (chunk_save, _ConversationMgrSaveLoad);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_Global_Database
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationEditorMgrClass::Load_Global_Database (void)
|
||||
{
|
||||
CString filename = ::Get_File_Mgr ()->Make_Full_Path (CONV_DB_PATH);
|
||||
|
||||
//
|
||||
// Open the file
|
||||
//
|
||||
HANDLE file = ::CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, 0L, NULL);
|
||||
|
||||
ASSERT (file != INVALID_HANDLE_VALUE);
|
||||
if (file != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (file);
|
||||
ChunkLoadClass chunk_load (&file_obj);
|
||||
|
||||
//
|
||||
// Let the save/load system handle the laod
|
||||
//
|
||||
SaveLoadSystemClass::Load (chunk_load);
|
||||
|
||||
//
|
||||
// Update the UI
|
||||
//
|
||||
ConversationPageClass *conversation_form = ::Get_Conversation_Form ();
|
||||
if (conversation_form) {
|
||||
conversation_form->Reload_Data ();
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Latest_Version
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
ConversationEditorMgrClass::Get_Latest_Version (void)
|
||||
{
|
||||
FileMgrClass *file_mgr = ::Get_File_Mgr ();
|
||||
AssetDatabaseClass &asset_db = file_mgr->Get_Database_Interface ();
|
||||
|
||||
//
|
||||
// Determine where the file should exist locally
|
||||
//
|
||||
CString filename = ::Get_File_Mgr ()->Make_Full_Path (CONV_DB_PATH);
|
||||
|
||||
//
|
||||
// Ask VSS to get the latest version of the file for us
|
||||
//
|
||||
return asset_db.Get (filename);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Check_Out
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
ConversationEditorMgrClass::Check_Out (void)
|
||||
{
|
||||
FileMgrClass *file_mgr = ::Get_File_Mgr ();
|
||||
AssetDatabaseClass &asset_db = file_mgr->Get_Database_Interface ();
|
||||
|
||||
//
|
||||
// Determine where the file should exist locally
|
||||
//
|
||||
CString filename = ::Get_File_Mgr ()->Make_Full_Path (CONV_DB_PATH);
|
||||
|
||||
bool retval = true;
|
||||
if (asset_db.Does_File_Exist (filename)) {
|
||||
|
||||
//
|
||||
// Ask VSS to check out the file to us
|
||||
//
|
||||
retval = asset_db.Check_Out_Ex (filename, ::AfxGetMainWnd ()->m_hWnd);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Check_In
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
ConversationEditorMgrClass::Check_In (void)
|
||||
{
|
||||
FileMgrClass *file_mgr = ::Get_File_Mgr ();
|
||||
AssetDatabaseClass &asset_db = file_mgr->Get_Database_Interface ();
|
||||
|
||||
//
|
||||
// Determine where the file should exist locally
|
||||
//
|
||||
CString filename = ::Get_File_Mgr ()->Make_Full_Path (CONV_DB_PATH);
|
||||
|
||||
//
|
||||
// Ask VSS to check in the file for us
|
||||
//
|
||||
return asset_db.Check_In_Ex (filename, ::AfxGetMainWnd ()->m_hWnd);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Undo_Check_Out
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
ConversationEditorMgrClass::Undo_Check_Out (void)
|
||||
{
|
||||
FileMgrClass *file_mgr = ::Get_File_Mgr ();
|
||||
AssetDatabaseClass &asset_db = file_mgr->Get_Database_Interface ();
|
||||
bool retval = false;
|
||||
|
||||
//
|
||||
// Determine where the file should exist locally
|
||||
//
|
||||
CString filename = ::Get_File_Mgr ()->Make_Full_Path (CONV_DB_PATH);
|
||||
|
||||
//
|
||||
// We only undo the checkout if its checked out to us
|
||||
//
|
||||
if (asset_db.Get_File_Status (filename) == AssetDatabaseClass::CHECKED_OUT_TO_ME) {
|
||||
retval = asset_db.Undo_Check_Out (filename);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
90
Code/Tools/LevelEdit/ConversationEditorMgr.h
Normal file
90
Code/Tools/LevelEdit/ConversationEditorMgr.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/ConversationEditorMgr.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 1/31/01 1:26p $*
|
||||
* *
|
||||
* $Revision:: 2 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __CONVERSATIONEDITORMGR_H
|
||||
#define __CONVERSATIONEDITORMGR_H
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ConversationEditorMgrClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
class ConversationEditorMgrClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Database save/load
|
||||
//
|
||||
static void Save_Global_Database (void);
|
||||
static void Load_Global_Database (void);
|
||||
static void Create_Database_If_Necessary (void);
|
||||
|
||||
//
|
||||
// Database version control
|
||||
//
|
||||
static bool Get_Latest_Version (void);
|
||||
static bool Check_Out (void);
|
||||
static bool Check_In (void);
|
||||
static bool Undo_Check_Out (void);
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
|
||||
#endif //__CONVERSATIONEDITORMGR_H
|
||||
896
Code/Tools/LevelEdit/ConversationPage.cpp
Normal file
896
Code/Tools/LevelEdit/ConversationPage.cpp
Normal file
@@ -0,0 +1,896 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/ConversationPage.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 2/12/02 9:57a $*
|
||||
* *
|
||||
* $Revision:: 5 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "leveledit.h"
|
||||
#include "conversationpage.h"
|
||||
#include "nodemgr.h"
|
||||
#include "node.h"
|
||||
#include "icons.h"
|
||||
#include "conversation.h"
|
||||
#include "conversationmgr.h"
|
||||
#include "editconversationdialog.h"
|
||||
#include "conversationeditormgr.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Helper objects
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
class TreeStateCaptureClass
|
||||
{
|
||||
public:
|
||||
TreeStateCaptureClass (CTreeCtrl &tree_ctrl, HTREEITEM *item_handle, ConversationClass **conversation_ptr)
|
||||
: ConversationID (0),
|
||||
ConversationPtr (conversation_ptr),
|
||||
ItemHandle (item_handle),
|
||||
TreeCtrl (tree_ctrl)
|
||||
{
|
||||
if (conversation_ptr != NULL) {
|
||||
ConversationID = (*conversation_ptr)->Get_ID ();
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
void Restore (void)
|
||||
{
|
||||
if (ItemHandle != NULL) {
|
||||
(*ItemHandle) = NULL;
|
||||
}
|
||||
|
||||
if (ConversationPtr != NULL) {
|
||||
(*ConversationPtr) = NULL;
|
||||
}
|
||||
|
||||
Find_Entry (TVI_ROOT);
|
||||
|
||||
//
|
||||
// Ensure the item is visible
|
||||
//
|
||||
if (ItemHandle != NULL && (*ItemHandle) != NULL) {
|
||||
TreeCtrl.SelectItem (*ItemHandle);
|
||||
TreeCtrl.EnsureVisible (*ItemHandle);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
bool Find_Entry (HTREEITEM parent_item)
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
//
|
||||
// Loop over all the children of this tree item
|
||||
//
|
||||
for ( HTREEITEM child_item = TreeCtrl.GetNextItem (parent_item, TVGN_CHILD);
|
||||
retval == false && child_item != NULL;
|
||||
child_item = TreeCtrl.GetNextItem (child_item, TVGN_NEXT))
|
||||
{
|
||||
//
|
||||
// Is this the conversation we are looking for?
|
||||
//
|
||||
ConversationClass *conversation = (ConversationClass *)TreeCtrl.GetItemData (child_item);
|
||||
if (conversation != NULL && conversation->Get_ID () == ConversationID) {
|
||||
|
||||
if (ItemHandle != NULL) {
|
||||
(*ItemHandle) = child_item;
|
||||
}
|
||||
|
||||
if (ConversationPtr != NULL) {
|
||||
(*ConversationPtr) = conversation;
|
||||
}
|
||||
|
||||
retval = true;
|
||||
break ;
|
||||
}
|
||||
|
||||
//
|
||||
// Recurse into this child (if necessary)
|
||||
//
|
||||
if (TreeCtrl.ItemHasChildren (child_item)) {
|
||||
retval = Find_Entry (child_item);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
private:
|
||||
int ConversationID;
|
||||
CTreeCtrl & TreeCtrl;
|
||||
HTREEITEM * ItemHandle;
|
||||
ConversationClass ** ConversationPtr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Static member initialization
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
ConversationPageClass * ConversationPageClass::_TheInstance = NULL;
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Local constants
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
static const int TOOLBAR_HEIGHT = 36;
|
||||
static const int TOOLBAR_V_SPACING = 5;
|
||||
static const int TOOLBAR_V_BORDER = TOOLBAR_V_SPACING * 2;
|
||||
static const int TOOLBAR_H_SPACING = 5;
|
||||
static const int TOOLBAR_H_BORDER = TOOLBAR_H_SPACING * 2;
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ConversationPageClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
ConversationPageClass::ConversationPageClass(CWnd* pParent /*=NULL*/) :
|
||||
m_GlobalsRoot (NULL),
|
||||
m_LevelsRoot (NULL),
|
||||
CDialog(ConversationPageClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(ConversationPageClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
Create (ConversationPageClass::IDD, pParent);
|
||||
_TheInstance = this;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~ConversationPageClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
ConversationPageClass::~ConversationPageClass (void)
|
||||
{
|
||||
_TheInstance = NULL;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::DoDataExchange (CDataExchange *pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(ConversationPageClass)
|
||||
DDX_Control(pDX, IDC_CONVERSATION_TREE, m_TreeCtrl);
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(ConversationPageClass, CDialog)
|
||||
//{{AFX_MSG_MAP(ConversationPageClass)
|
||||
ON_NOTIFY(TVN_DELETEITEM, IDC_CONVERSATION_TREE, OnDeleteItemConversationTree)
|
||||
ON_WM_SIZE()
|
||||
ON_WM_DESTROY()
|
||||
ON_NOTIFY(NM_DBLCLK, IDC_CONVERSATION_TREE, OnDblclkConversationTree)
|
||||
ON_NOTIFY(TVN_ITEMEXPANDED, IDC_CONVERSATION_TREE, OnItemexpandedConversationTree)
|
||||
ON_COMMAND(IDC_ADD, OnAdd)
|
||||
ON_COMMAND(IDC_DELETE, OnDelete)
|
||||
ON_COMMAND(IDC_EDIT, OnEdit)
|
||||
ON_COMMAND(IDC_SWAP, OnSwap)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnSize
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::OnSize
|
||||
(
|
||||
UINT nType,
|
||||
int cx,
|
||||
int cy
|
||||
)
|
||||
{
|
||||
// Allow the base class to process this message
|
||||
CDialog::OnSize (nType, cx, cy);
|
||||
|
||||
if (::IsWindow (m_TreeCtrl) && (cx > 0) && (cy > 0)) {
|
||||
|
||||
// Get the bounding rectangle of the form window
|
||||
CRect parentrect;
|
||||
GetWindowRect (&parentrect);
|
||||
|
||||
// Get the bounding rectangle of the toolbar
|
||||
CRect toolbar_rect;
|
||||
m_Toolbar.GetWindowRect (&toolbar_rect);
|
||||
ScreenToClient (&toolbar_rect);
|
||||
|
||||
// Move the toolbar so it is in its correct position
|
||||
m_Toolbar.SetWindowPos (NULL,
|
||||
TOOLBAR_H_SPACING,
|
||||
(cy - TOOLBAR_V_SPACING) - toolbar_rect.Height (),
|
||||
cx - TOOLBAR_H_BORDER,
|
||||
toolbar_rect.Height (),
|
||||
SWP_NOZORDER);
|
||||
|
||||
// Get the bounding rectnagle of the list ctrl
|
||||
RECT list_rect;
|
||||
m_TreeCtrl.GetWindowRect (&list_rect);
|
||||
|
||||
CRect client_rect = list_rect;
|
||||
ScreenToClient (&client_rect);
|
||||
int list_height = ((cy - TOOLBAR_V_BORDER) - toolbar_rect.Height ()) - client_rect.top;
|
||||
|
||||
// Resize the tab control to fill the entire contents of the client area
|
||||
m_TreeCtrl.SetWindowPos ( NULL,
|
||||
0,
|
||||
0,
|
||||
cx-((list_rect.left - parentrect.left) << 1),
|
||||
list_height,
|
||||
SWP_NOZORDER | SWP_NOMOVE);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDestroy
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::OnDestroy (void)
|
||||
{
|
||||
// Free the state image list we associated with the control
|
||||
CImageList *imagelist = m_TreeCtrl.GetImageList (TVSIL_STATE);
|
||||
m_TreeCtrl.SetImageList (NULL, TVSIL_STATE);
|
||||
SAFE_DELETE (imagelist);
|
||||
|
||||
// Remove the main image list we associated with the control
|
||||
m_TreeCtrl.SetImageList (NULL, TVSIL_NORMAL);
|
||||
m_TreeCtrl.DeleteAllItems ();
|
||||
|
||||
::RemoveProp (m_TreeCtrl, "TRANS_ACCS");
|
||||
::RemoveProp (m_hWnd, "TRANS_ACCS");
|
||||
|
||||
// Allow the base class to process this message
|
||||
CDialog::OnDestroy ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
ConversationPageClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
m_Toolbar.CreateEx (this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP, CRect(0, 0, 0, 0), 101);
|
||||
m_Toolbar.SetOwner (this);
|
||||
m_Toolbar.LoadToolBar (IDR_CONVERSATION_TOOLBAR);
|
||||
m_Toolbar.SetBarStyle (m_Toolbar.GetBarStyle () | CBRS_TOOLTIPS | CBRS_FLYBY);
|
||||
|
||||
//
|
||||
// Size the toolbar
|
||||
//
|
||||
CRect parentrect;
|
||||
GetWindowRect (&parentrect);
|
||||
m_Toolbar.SetWindowPos (NULL, 0, 0, parentrect.Width () - TOOLBAR_H_BORDER, TOOLBAR_HEIGHT, SWP_NOZORDER | SWP_NOMOVE);
|
||||
|
||||
//
|
||||
// Pass the general use imagelist onto the tree control
|
||||
//
|
||||
m_TreeCtrl.SetImageList (::Get_Global_Image_List (), TVSIL_NORMAL);
|
||||
|
||||
SetProp (m_TreeCtrl, "TRANS_ACCS", (HANDLE)1);
|
||||
SetProp (m_hWnd, "TRANS_ACCS", (HANDLE)1);
|
||||
|
||||
Reload_Data ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDeleteItemConversationTree
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::OnDeleteItemConversationTree
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT *pResult
|
||||
)
|
||||
{
|
||||
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
|
||||
(*pResult) = 0;
|
||||
|
||||
//
|
||||
// Release our hold on the conversation object
|
||||
//
|
||||
ConversationClass *conversation = (ConversationClass *)pNMTreeView->itemOld.lParam;
|
||||
REF_PTR_RELEASE (conversation);
|
||||
m_TreeCtrl.SetItemData (pNMTreeView->itemOld.hItem, 0);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Insert_Entry
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::Insert_Entry (ConversationClass *conversation, bool sort_items)
|
||||
{
|
||||
//
|
||||
// Determine which folder this conversation goes under
|
||||
//
|
||||
HTREEITEM parent_item = m_LevelsRoot;
|
||||
if (conversation->Get_Category_ID () != ConversationMgrClass::CATEGORY_LEVEL) {
|
||||
parent_item = m_GlobalsRoot;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert this item into the tree
|
||||
//
|
||||
HTREEITEM tree_item = m_TreeCtrl.InsertItem (conversation->Get_Name (), DIALOGUE_ICON,
|
||||
DIALOGUE_ICON, parent_item);
|
||||
if (tree_item != NULL) {
|
||||
|
||||
//
|
||||
// Lock a reference on the object
|
||||
//
|
||||
conversation->Add_Ref ();
|
||||
|
||||
//
|
||||
// Associate the conversation with the entry in the tree
|
||||
//
|
||||
m_TreeCtrl.SetItemData (tree_item, (DWORD)conversation);
|
||||
|
||||
//
|
||||
// Sort the items
|
||||
//
|
||||
if (sort_items) {
|
||||
m_TreeCtrl.InvalidateRect (NULL, TRUE);
|
||||
m_TreeCtrl.SortChildren (parent_item);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Reload_Data
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::Reload_Data (void)
|
||||
{
|
||||
Reset_Tree ();
|
||||
|
||||
//
|
||||
// Add all the conversations to the tree
|
||||
//
|
||||
int count = ConversationMgrClass::Get_Conversation_Count ();
|
||||
for (int index = 0; index < count; index ++) {
|
||||
Insert_Entry (ConversationMgrClass::Peek_Conversation (index), false);
|
||||
}
|
||||
|
||||
m_TreeCtrl.InvalidateRect (NULL, TRUE);
|
||||
m_TreeCtrl.SortChildren (m_GlobalsRoot);
|
||||
m_TreeCtrl.SortChildren (m_LevelsRoot);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Reset_Tree
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::Reset_Tree (void)
|
||||
{
|
||||
m_TreeCtrl.DeleteAllItems ();
|
||||
|
||||
//
|
||||
// Insert the root nodes
|
||||
//
|
||||
|
||||
m_GlobalsRoot = m_TreeCtrl.InsertItem ("Globals", FOLDER_ICON, FOLDER_ICON);
|
||||
m_LevelsRoot = m_TreeCtrl.InsertItem ("Level Specific", FOLDER_ICON, FOLDER_ICON);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDblclkConversationTree
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::OnDblclkConversationTree
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT * pResult
|
||||
)
|
||||
{
|
||||
//
|
||||
// Determine what client-coord location was double-clicked on
|
||||
//
|
||||
DWORD mouse_pos = ::GetMessagePos ();
|
||||
POINT hit_point = { GET_X_LPARAM (mouse_pos), GET_Y_LPARAM (mouse_pos) };
|
||||
m_TreeCtrl.ScreenToClient (&hit_point);
|
||||
|
||||
//
|
||||
// Goto the node that was double-clicked on (if possible)
|
||||
//
|
||||
UINT flags = 0;
|
||||
HTREEITEM tree_item = m_TreeCtrl.HitTest (hit_point, &flags);
|
||||
if (tree_item != NULL && flags & TVHT_ONITEMLABEL) {
|
||||
|
||||
//
|
||||
// Edit the entry the user double-clicked on
|
||||
//
|
||||
Edit_Entry (tree_item);
|
||||
(*pResult) = 1;
|
||||
|
||||
} else {
|
||||
(*pResult) = 0;
|
||||
}
|
||||
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnItemexpandedConversationTree
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::OnItemexpandedConversationTree
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT * pResult
|
||||
)
|
||||
{
|
||||
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
|
||||
|
||||
//
|
||||
// If this is a folder, then change its image based
|
||||
// on its expanded state.
|
||||
//
|
||||
if (m_TreeCtrl.GetItemData (pNMTreeView->itemNew.hItem) == NULL) {
|
||||
|
||||
if (pNMTreeView->itemNew.state & TVIS_EXPANDED) {
|
||||
m_TreeCtrl.SetItemImage (pNMTreeView->itemNew.hItem, OPEN_FOLDER_ICON, OPEN_FOLDER_ICON);
|
||||
} else {
|
||||
m_TreeCtrl.SetItemImage (pNMTreeView->itemNew.hItem, FOLDER_ICON, FOLDER_ICON);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
(*pResult) = 0;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnAdd
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::OnAdd (void)
|
||||
{
|
||||
HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
|
||||
if (selected_item != NULL) {
|
||||
|
||||
//
|
||||
// Determine if this is a global conversation
|
||||
//
|
||||
bool is_global = false;
|
||||
bool can_edit = true;
|
||||
bool check_in = false;
|
||||
if ( selected_item == m_GlobalsRoot ||
|
||||
m_TreeCtrl.GetParentItem (selected_item) == m_GlobalsRoot)
|
||||
{
|
||||
is_global = true;
|
||||
|
||||
//
|
||||
// Check out the database
|
||||
//
|
||||
CWaitCursor wait_cursor;
|
||||
check_in = ConversationEditorMgrClass::Check_Out ();
|
||||
can_edit = check_in;
|
||||
|
||||
//
|
||||
// Reload the tree
|
||||
//
|
||||
if (can_edit) {
|
||||
Reload_Tree (&selected_item, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (can_edit) {
|
||||
|
||||
//
|
||||
// Show a dialog to the user that will allow them to edit this conversation
|
||||
//
|
||||
EditConversationDialogClass dialog;
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
ConversationClass *conversation = dialog.Peek_Conversation ();
|
||||
|
||||
//
|
||||
// Determine which folder to put this conversation under
|
||||
//
|
||||
if (is_global) {
|
||||
conversation->Set_Category_ID (ConversationMgrClass::CATEGORY_GLOBAL);
|
||||
} else {
|
||||
conversation->Set_Category_ID (ConversationMgrClass::CATEGORY_LEVEL);
|
||||
::Set_Modified ();
|
||||
}
|
||||
|
||||
//
|
||||
// Add the conversation to the manager
|
||||
//
|
||||
ConversationMgrClass::Add_Conversation (conversation);
|
||||
|
||||
//
|
||||
// Add the conversation to the tree
|
||||
//
|
||||
Insert_Entry (conversation);
|
||||
m_TreeCtrl.UpdateWindow ();
|
||||
|
||||
//
|
||||
// Check in the global conversation database
|
||||
//
|
||||
if (check_in) {
|
||||
CWaitCursor wait_cursor;
|
||||
ConversationEditorMgrClass::Save_Global_Database ();
|
||||
ConversationEditorMgrClass::Check_In ();
|
||||
}
|
||||
|
||||
} else if (check_in) {
|
||||
CWaitCursor wait_cursor;
|
||||
ConversationEditorMgrClass::Undo_Check_Out ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDelete
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::OnDelete (void)
|
||||
{
|
||||
HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
|
||||
if (selected_item != NULL) {
|
||||
|
||||
//
|
||||
// Get the conversation associated with the selected item
|
||||
//
|
||||
ConversationClass *conversation = NULL;
|
||||
conversation = (ConversationClass *)m_TreeCtrl.GetItemData (selected_item);
|
||||
if (conversation != NULL) {
|
||||
|
||||
//
|
||||
// This "dirties" the level, so mark it as modified...
|
||||
//
|
||||
if (conversation->Get_Category_ID () == ConversationMgrClass::CATEGORY_LEVEL) {
|
||||
::Set_Modified ();
|
||||
}
|
||||
|
||||
//
|
||||
// Check out the global conversation database (if necessary)
|
||||
//
|
||||
bool check_in = false;
|
||||
bool can_edit = true;
|
||||
if (conversation->Get_Category_ID () == ConversationMgrClass::CATEGORY_GLOBAL) {
|
||||
CWaitCursor wait_cursor;
|
||||
check_in = ConversationEditorMgrClass::Check_Out ();
|
||||
can_edit = check_in;
|
||||
|
||||
//
|
||||
// Reload the tree
|
||||
//
|
||||
if (can_edit) {
|
||||
Reload_Tree (&selected_item, &conversation);
|
||||
}
|
||||
}
|
||||
|
||||
if (can_edit && selected_item != NULL && conversation != NULL) {
|
||||
|
||||
//
|
||||
// Remove this conversation from the manager
|
||||
//
|
||||
ConversationMgrClass::Remove_Conversation (conversation);
|
||||
|
||||
//
|
||||
// Remove this conversation from the tree
|
||||
//
|
||||
m_TreeCtrl.DeleteItem (selected_item);
|
||||
m_TreeCtrl.UpdateWindow ();
|
||||
|
||||
//
|
||||
// Check in the global conversation database
|
||||
//
|
||||
if (check_in) {
|
||||
ConversationEditorMgrClass::Save_Global_Database ();
|
||||
ConversationEditorMgrClass::Check_In ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnEdit
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::OnEdit (void)
|
||||
{
|
||||
HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
|
||||
if (selected_item != NULL) {
|
||||
|
||||
//
|
||||
// Edit the selected entry
|
||||
//
|
||||
Edit_Entry (selected_item);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Edit_Entry
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::Edit_Entry (HTREEITEM tree_item)
|
||||
{
|
||||
if (tree_item != NULL) {
|
||||
|
||||
//
|
||||
// Edit the conversation (if necessary)
|
||||
//
|
||||
ConversationClass *conversation = (ConversationClass *)m_TreeCtrl.GetItemData (tree_item);
|
||||
if (conversation != NULL) {
|
||||
|
||||
//
|
||||
// Check out the global conversation database (if necessary)
|
||||
//
|
||||
bool check_in = false;
|
||||
bool can_edit = true;
|
||||
if (conversation->Get_Category_ID () == ConversationMgrClass::CATEGORY_GLOBAL) {
|
||||
CWaitCursor wait_cursor;
|
||||
check_in = ConversationEditorMgrClass::Check_Out ();
|
||||
can_edit = check_in;
|
||||
|
||||
//
|
||||
// Reload the tree
|
||||
//
|
||||
if (can_edit) {
|
||||
Reload_Tree (&tree_item, &conversation);
|
||||
}
|
||||
}
|
||||
|
||||
if (can_edit && tree_item != NULL && conversation != NULL) {
|
||||
|
||||
//
|
||||
// Display a dialog to the user allowing them to edit the conversation
|
||||
//
|
||||
EditConversationDialogClass dialog;
|
||||
dialog.Set_Conversation (conversation);
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
m_TreeCtrl.SetItemText (tree_item, conversation->Get_Name ());
|
||||
m_TreeCtrl.UpdateWindow ();
|
||||
|
||||
//
|
||||
// This "dirties" the level, so mark it as modified...
|
||||
//
|
||||
if (conversation->Get_Category_ID () == ConversationMgrClass::CATEGORY_LEVEL) {
|
||||
::Set_Modified ();
|
||||
}
|
||||
|
||||
//
|
||||
// Check in the global conversation database
|
||||
//
|
||||
if (check_in) {
|
||||
CWaitCursor wait_cursor;
|
||||
ConversationEditorMgrClass::Save_Global_Database ();
|
||||
ConversationEditorMgrClass::Check_In ();
|
||||
}
|
||||
|
||||
} else if (check_in) {
|
||||
CWaitCursor wait_cursor;
|
||||
ConversationEditorMgrClass::Undo_Check_Out ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnSwap
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::OnSwap (void)
|
||||
{
|
||||
HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
|
||||
if (selected_item != NULL) {
|
||||
|
||||
//
|
||||
// Get the conversation associated with the selected item
|
||||
//
|
||||
ConversationClass *conversation = NULL;
|
||||
conversation = (ConversationClass *)m_TreeCtrl.GetItemData (selected_item);
|
||||
if (conversation != NULL) {
|
||||
|
||||
//
|
||||
// Check out the global conversation database
|
||||
//
|
||||
CWaitCursor wait_cursor;
|
||||
if (ConversationEditorMgrClass::Check_Out ()) {
|
||||
|
||||
//
|
||||
// Reload the tree
|
||||
//
|
||||
Reload_Tree (&selected_item, &conversation);
|
||||
if (selected_item != NULL && conversation != NULL) {
|
||||
|
||||
//
|
||||
// Remove the conversation from the system
|
||||
//
|
||||
ConversationMgrClass::Remove_Conversation (conversation);
|
||||
|
||||
//
|
||||
// Swap categories
|
||||
//
|
||||
int category_id = conversation->Get_Category_ID ();
|
||||
if (category_id == ConversationMgrClass::CATEGORY_LEVEL) {
|
||||
conversation->Set_Category_ID (ConversationMgrClass::CATEGORY_GLOBAL);
|
||||
} else {
|
||||
conversation->Set_Category_ID (ConversationMgrClass::CATEGORY_LEVEL);
|
||||
}
|
||||
|
||||
//
|
||||
// Re-add the conversation to the manager and the UI
|
||||
//
|
||||
ConversationMgrClass::Add_Conversation (conversation);
|
||||
Insert_Entry (conversation);
|
||||
|
||||
//
|
||||
// Remove the old entry
|
||||
//
|
||||
m_TreeCtrl.DeleteItem (selected_item);
|
||||
m_TreeCtrl.UpdateWindow ();
|
||||
|
||||
//
|
||||
// This "dirties" the level, so mark it as modified...
|
||||
//
|
||||
::Set_Modified ();
|
||||
|
||||
//
|
||||
// Checkin the global conversation database
|
||||
//
|
||||
ConversationEditorMgrClass::Save_Global_Database ();
|
||||
ConversationEditorMgrClass::Check_In ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Reload_Tree
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPageClass::Reload_Tree (HTREEITEM *item_handle, ConversationClass **conversation_ptr)
|
||||
{
|
||||
m_TreeCtrl.SetRedraw (FALSE);
|
||||
|
||||
//
|
||||
// Reload the database while capturing its state
|
||||
//
|
||||
TreeStateCaptureClass capture_obj (m_TreeCtrl, item_handle, conversation_ptr);
|
||||
ConversationEditorMgrClass::Load_Global_Database ();
|
||||
capture_obj.Restore ();
|
||||
|
||||
//
|
||||
// Expand the two root folders by default
|
||||
//
|
||||
m_TreeCtrl.Expand (m_GlobalsRoot, TVE_EXPAND);
|
||||
m_TreeCtrl.Expand (m_LevelsRoot, TVE_EXPAND);
|
||||
|
||||
m_TreeCtrl.SetRedraw (TRUE);
|
||||
return ;
|
||||
}
|
||||
|
||||
115
Code/Tools/LevelEdit/ConversationPage.h
Normal file
115
Code/Tools/LevelEdit/ConversationPage.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_CONVERSATIONPAGE_H__69EA03B9_0F32_11D4_A098_00104B791122__INCLUDED_)
|
||||
#define AFX_CONVERSATIONPAGE_H__69EA03B9_0F32_11D4_A098_00104B791122__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "resource.h"
|
||||
#include "dialogtoolbar.h"
|
||||
#include "nodetypes.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class NodeClass;
|
||||
class ConversationClass;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ConversationPageClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class ConversationPageClass : public CDialog
|
||||
{
|
||||
public:
|
||||
ConversationPageClass (CWnd *parent_wnd);
|
||||
virtual ~ConversationPageClass (void);
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(ConversationPageClass)
|
||||
enum { IDD = IDD_CONVERSATION_FORM };
|
||||
CTreeCtrl m_TreeCtrl;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(ConversationPageClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(ConversationPageClass)
|
||||
afx_msg void OnDeleteItemConversationTree(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnDestroy();
|
||||
afx_msg void OnDblclkConversationTree(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnItemexpandedConversationTree(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnAdd();
|
||||
afx_msg void OnDelete();
|
||||
afx_msg void OnEdit();
|
||||
afx_msg void OnSwap();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////////
|
||||
void Reload_Data (void);
|
||||
void Reset_Tree (void);
|
||||
|
||||
static ConversationPageClass * Get_Instance (void) { return _TheInstance; }
|
||||
|
||||
protected:
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
///////////////////////////////////////////////////////
|
||||
void Insert_Entry (ConversationClass *conversation, bool sort_items = true);
|
||||
void Edit_Entry (HTREEITEM tree_item);
|
||||
|
||||
void Reload_Tree (HTREEITEM *item_handle, ConversationClass **conversation_ptr);
|
||||
|
||||
private:
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
///////////////////////////////////////////////////////
|
||||
DialogToolbarClass m_Toolbar;
|
||||
HTREEITEM m_GlobalsRoot;
|
||||
HTREEITEM m_LevelsRoot;
|
||||
|
||||
static ConversationPageClass * _TheInstance;
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_CONVERSATIONPAGE_H__69EA03B9_0F32_11D4_A098_00104B791122__INCLUDED_)
|
||||
206
Code/Tools/LevelEdit/ConversationPickerDialog.cpp
Normal file
206
Code/Tools/LevelEdit/ConversationPickerDialog.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// ConversationPickerDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveledit.h"
|
||||
#include "conversationpickerdialog.h"
|
||||
#include "conversationmgr.h"
|
||||
#include "conversation.h"
|
||||
#include "utils.h"
|
||||
#include "icons.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ConversationPickerDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
ConversationPickerDialogClass::ConversationPickerDialogClass (CWnd *pParent /*=NULL*/)
|
||||
: Conversation (NULL),
|
||||
GlobalsRoot (NULL),
|
||||
LevelsRoot (NULL),
|
||||
CDialog (ConversationPickerDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(ConversationPickerDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPickerDialogClass::DoDataExchange (CDataExchange *pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(ConversationPickerDialogClass)
|
||||
DDX_Control(pDX, IDC_CONVERSATION_TREE, m_TreeCtrl);
|
||||
//}}AFX_DATA_MAP
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(ConversationPickerDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(ConversationPickerDialogClass)
|
||||
ON_NOTIFY(TVN_SELCHANGED, IDC_CONVERSATION_TREE, OnSelchangedConversationTree)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnSelchangedConversationTree
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPickerDialogClass::OnSelchangedConversationTree
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT * pResult
|
||||
)
|
||||
{
|
||||
NM_TREEVIEW *pNMTreeView = (NM_TREEVIEW *)pNMHDR;
|
||||
(*pResult) = 0;
|
||||
|
||||
Conversation = NULL;
|
||||
|
||||
//
|
||||
// Lookup the currently selected conversation
|
||||
//
|
||||
HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
|
||||
if (selected_item != NULL) {
|
||||
Conversation = (ConversationClass *)m_TreeCtrl.GetItemData (selected_item);
|
||||
}
|
||||
|
||||
//
|
||||
// Update the enable state based on whether or not a conversation was selected
|
||||
//
|
||||
::EnableWindow (::GetDlgItem (m_hWnd, IDOK), (Conversation != NULL));
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
ConversationPickerDialogClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
//
|
||||
// Pass the general use imagelist onto the tree control
|
||||
//
|
||||
m_TreeCtrl.SetImageList (::Get_Global_Image_List (), TVSIL_NORMAL);
|
||||
|
||||
//
|
||||
// Insert the folders
|
||||
//
|
||||
GlobalsRoot = m_TreeCtrl.InsertItem ("Globals", FOLDER_ICON, FOLDER_ICON);
|
||||
LevelsRoot = m_TreeCtrl.InsertItem ("Level Specific", FOLDER_ICON, FOLDER_ICON);
|
||||
|
||||
//
|
||||
// Add all the conversations to the tree
|
||||
//
|
||||
int count = ConversationMgrClass::Get_Conversation_Count ();
|
||||
for (int index = 0; index < count; index ++) {
|
||||
Insert_Entry (ConversationMgrClass::Peek_Conversation (index));
|
||||
}
|
||||
|
||||
//
|
||||
// Open the globals and levels folders
|
||||
//
|
||||
m_TreeCtrl.Expand (GlobalsRoot, TVE_EXPAND);
|
||||
m_TreeCtrl.Expand (LevelsRoot, TVE_EXPAND);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOK
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPickerDialogClass::OnOK (void)
|
||||
{
|
||||
if (Conversation != NULL) {
|
||||
CDialog::OnOK ();
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Insert_Entry
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ConversationPickerDialogClass::Insert_Entry (ConversationClass *conversation)
|
||||
{
|
||||
//
|
||||
// Determine which folder this conversation goes under
|
||||
//
|
||||
HTREEITEM parent_item = LevelsRoot;
|
||||
if (conversation->Get_Category_ID () != ConversationMgrClass::CATEGORY_LEVEL) {
|
||||
parent_item = GlobalsRoot;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert this item into the tree
|
||||
//
|
||||
HTREEITEM tree_item = m_TreeCtrl.InsertItem (conversation->Get_Name (), DIALOGUE_ICON,
|
||||
DIALOGUE_ICON, parent_item);
|
||||
if (tree_item != NULL) {
|
||||
|
||||
//
|
||||
// Associate the conversation with the entry in the tree
|
||||
//
|
||||
m_TreeCtrl.SetItemData (tree_item, (DWORD)conversation);
|
||||
m_TreeCtrl.SortChildren (parent_item);
|
||||
|
||||
//
|
||||
// Select this conversation if necessary
|
||||
//
|
||||
if (conversation == Conversation) {
|
||||
m_TreeCtrl.SelectItem (tree_item);
|
||||
m_TreeCtrl.EnsureVisible (tree_item);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
96
Code/Tools/LevelEdit/ConversationPickerDialog.h
Normal file
96
Code/Tools/LevelEdit/ConversationPickerDialog.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_CONVERSATIONPICKERDIALOG_H__45E7AEA7_6692_43BF_B169_555904929404__INCLUDED_)
|
||||
#define AFX_CONVERSATIONPICKERDIALOG_H__45E7AEA7_6692_43BF_B169_555904929404__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class ConversationClass;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ConversationPickerDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class ConversationPickerDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
ConversationPickerDialogClass(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(ConversationPickerDialogClass)
|
||||
enum { IDD = IDD_CONVERSATION_PICKER };
|
||||
CTreeCtrl m_TreeCtrl;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(ConversationPickerDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(ConversationPickerDialogClass)
|
||||
afx_msg void OnSelchangedConversationTree(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
virtual BOOL OnInitDialog();
|
||||
virtual void OnOK();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void Set_Conversation (ConversationClass *conversation) { Conversation = conversation; }
|
||||
ConversationClass * Get_Conversation (void) { return Conversation; }
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void Insert_Entry (ConversationClass *conversation);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
ConversationClass * Conversation;
|
||||
HTREEITEM GlobalsRoot;
|
||||
HTREEITEM LevelsRoot;
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_CONVERSATIONPICKERDIALOG_H__45E7AEA7_6692_43BF_B169_555904929404__INCLUDED_)
|
||||
361
Code/Tools/LevelEdit/CoverAttackPointNode.cpp
Normal file
361
Code/Tools/LevelEdit/CoverAttackPointNode.cpp
Normal file
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/CoverAttackPointNode.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 5/22/01 11:17a $*
|
||||
* *
|
||||
* $Revision:: 10 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "coverspotnode.h"
|
||||
#include "coverattackpointnode.h"
|
||||
#include "sceneeditor.h"
|
||||
#include "collisiongroups.h"
|
||||
#include "persistfactory.h"
|
||||
#include "editorchunkids.h"
|
||||
#include "preset.h"
|
||||
#include "chunkio.h"
|
||||
#include "nodemgr.h"
|
||||
#include "modelutils.h"
|
||||
#include "soldier.h"
|
||||
#include "presetmgr.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Persist factory
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
SimplePersistFactoryClass<CoverAttackPointNodeClass, CHUNKID_NODE_COVER_ATTACK_POINT> _CoverAttackPointNodePersistFactory;
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
CHUNKID_VARIABLES = 0x05260946,
|
||||
CHUNKID_BASE_CLASS
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VARID_REQUIRES_CROUCH = 0x01,
|
||||
VARID_ATTACK_POINT,
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Static member initialization
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
PhysClass * CoverAttackPointNodeClass::_TheCollisionObj = NULL;
|
||||
int CoverAttackPointNodeClass::_InstanceCount = 0;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CoverAttackPointNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
CoverAttackPointNodeClass::CoverAttackPointNodeClass (PresetClass *preset)
|
||||
: m_PhysObj (NULL),
|
||||
m_CoverSpot (NULL),
|
||||
NodeClass (preset)
|
||||
{
|
||||
_InstanceCount ++;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CoverAttackPointNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
CoverAttackPointNodeClass::CoverAttackPointNodeClass (const CoverAttackPointNodeClass &src)
|
||||
: m_PhysObj (NULL),
|
||||
m_CoverSpot (NULL),
|
||||
NodeClass (NULL)
|
||||
{
|
||||
_InstanceCount ++;
|
||||
*this = src;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~CoverAttackPointNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
CoverAttackPointNodeClass::~CoverAttackPointNodeClass (void)
|
||||
{
|
||||
Remove_From_Scene ();
|
||||
MEMBER_RELEASE (m_PhysObj);
|
||||
|
||||
//
|
||||
// Free the collision object when all instances have gone away
|
||||
//
|
||||
_InstanceCount --;
|
||||
if (_InstanceCount == 0) {
|
||||
MEMBER_RELEASE (_TheCollisionObj);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Initialize
|
||||
//
|
||||
// Note: This may be called more than once. It is used as an 'initialize'
|
||||
// and a 're-initialize'.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverAttackPointNodeClass::Initialize (void)
|
||||
{
|
||||
MEMBER_RELEASE (m_PhysObj);
|
||||
|
||||
//
|
||||
// Create the attack-point render object
|
||||
//
|
||||
RenderObjClass *render_obj = ::Create_Render_Obj ("WAY_B");
|
||||
WWASSERT (render_obj != NULL);
|
||||
if (render_obj != NULL) {
|
||||
|
||||
// Create the new physics object
|
||||
m_PhysObj = new DecorationPhysClass;
|
||||
|
||||
//
|
||||
// Configure the physics object with information about
|
||||
// its new render object and collision data.
|
||||
//
|
||||
m_PhysObj->Set_Model (render_obj);
|
||||
m_PhysObj->Set_Transform (Matrix3D(1));
|
||||
m_PhysObj->Set_Collision_Group (EDITOR_COLLISION_GROUP);
|
||||
m_PhysObj->Peek_Model ()->Set_User_Data ((PVOID)&m_HitTestInfo, FALSE);
|
||||
m_PhysObj->Set_Transform (m_Transform);
|
||||
::Set_Model_Collision_Type (m_PhysObj->Peek_Model (), COLLISION_TYPE_0);
|
||||
|
||||
// Release our hold on the render object pointer
|
||||
MEMBER_RELEASE (render_obj);
|
||||
}
|
||||
|
||||
if (_TheCollisionObj == NULL) {
|
||||
|
||||
//
|
||||
// Create the collision physics object
|
||||
//
|
||||
PresetClass *preset = PresetMgrClass::Find_Preset ("Walk-Thru");
|
||||
if (preset != NULL && preset->Get_Definition () != NULL) {
|
||||
|
||||
//
|
||||
// Load the assets for this preset and get its definition
|
||||
//
|
||||
preset->Load_All_Assets ();
|
||||
SoldierGameObjDef *definition = (SoldierGameObjDef *)preset->Get_Definition ();
|
||||
|
||||
//
|
||||
// Create the collision physics object
|
||||
//
|
||||
SoldierGameObj *game_obj = new SoldierGameObj;
|
||||
game_obj->Init (*definition);
|
||||
MEMBER_ADD (_TheCollisionObj, game_obj->Peek_Physical_Object ());
|
||||
game_obj->Set_Delete_Pending ();
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Factory
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
const PersistFactoryClass &
|
||||
CoverAttackPointNodeClass::Get_Factory (void) const
|
||||
{
|
||||
return _CoverAttackPointNodePersistFactory;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
CoverAttackPointNodeClass::Save (ChunkSaveClass &csave)
|
||||
{
|
||||
csave.Begin_Chunk (CHUNKID_BASE_CLASS);
|
||||
NodeClass::Save (csave);
|
||||
csave.End_Chunk ();
|
||||
|
||||
csave.Begin_Chunk (CHUNKID_VARIABLES);
|
||||
csave.End_Chunk ();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
CoverAttackPointNodeClass::Load (ChunkLoadClass &cload)
|
||||
{
|
||||
while (cload.Open_Chunk ()) {
|
||||
switch (cload.Cur_Chunk_ID ()) {
|
||||
|
||||
case CHUNKID_BASE_CLASS:
|
||||
NodeClass::Load (cload);
|
||||
break;
|
||||
|
||||
case CHUNKID_VARIABLES:
|
||||
Load_Variables (cload);
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Chunk ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_Variables
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
CoverAttackPointNodeClass::Load_Variables (ChunkLoadClass &cload)
|
||||
{
|
||||
//
|
||||
// Loop through all the microchunks that define the variables
|
||||
//
|
||||
while (cload.Open_Micro_Chunk ()) {
|
||||
/*switch (cload.Cur_Micro_Chunk_ID ()) {
|
||||
}*/
|
||||
|
||||
cload.Close_Micro_Chunk ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// operator=
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
const CoverAttackPointNodeClass &
|
||||
CoverAttackPointNodeClass::operator= (const CoverAttackPointNodeClass &src)
|
||||
{
|
||||
NodeClass::operator= (src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Pre_Export
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverAttackPointNodeClass::Pre_Export (void)
|
||||
{
|
||||
//
|
||||
// Remove ourselves from the 'system' so we don't get accidentally
|
||||
// saved during the export.
|
||||
//
|
||||
Add_Ref ();
|
||||
if (m_PhysObj != NULL && m_IsInScene) {
|
||||
::Get_Scene_Editor ()->Remove_Object (m_PhysObj);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Post_Export
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverAttackPointNodeClass::Post_Export (void)
|
||||
{
|
||||
//
|
||||
// Put ourselves back into the system
|
||||
//
|
||||
if (m_PhysObj != NULL && m_IsInScene) {
|
||||
::Get_Scene_Editor ()->Add_Dynamic_Object (m_PhysObj);
|
||||
}
|
||||
|
||||
Release_Ref ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// On_Delete
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverAttackPointNodeClass::On_Delete (void)
|
||||
{
|
||||
//
|
||||
// Remove ourselves from the cover spot
|
||||
//
|
||||
if (m_CoverSpot) {
|
||||
m_CoverSpot->Remove_Attack_Point (this);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Peek_Collision_Obj
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
PhysClass *
|
||||
CoverAttackPointNodeClass::Peek_Collision_Obj (void) const
|
||||
{
|
||||
if (_TheCollisionObj != NULL) {
|
||||
_TheCollisionObj->Set_Transform (m_Transform);
|
||||
}
|
||||
|
||||
return _TheCollisionObj;
|
||||
}
|
||||
191
Code/Tools/LevelEdit/CoverAttackPointNode.h
Normal file
191
Code/Tools/LevelEdit/CoverAttackPointNode.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/CoverAttackPointNode.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 5/11/01 9:30a $*
|
||||
* *
|
||||
* $Revision:: 6 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __COVER_ATTACK_POINT_NODE_H
|
||||
#define __COVER_ATTACK_POINT_NODE_H
|
||||
|
||||
#include "node.h"
|
||||
#include "vector.h"
|
||||
#include "icons.h"
|
||||
#include "decophys.h"
|
||||
#include "coverspotnode.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class PresetClass;
|
||||
class CoverSpotNode;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CoverAttackPointNodeClass
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class CoverAttackPointNodeClass : public NodeClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////////////
|
||||
CoverAttackPointNodeClass (PresetClass *preset = NULL);
|
||||
CoverAttackPointNodeClass (const CoverAttackPointNodeClass &src);
|
||||
~CoverAttackPointNodeClass (void);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public operators
|
||||
//////////////////////////////////////////////////////////////
|
||||
const CoverAttackPointNodeClass &operator= (const CoverAttackPointNodeClass &src);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// CoverAttackPointNodeClass specific
|
||||
//
|
||||
CoverSpotNodeClass * Peek_Cover_Spot (void) const { return m_CoverSpot; }
|
||||
void Set_Cover_Spot (CoverSpotNodeClass *spot) { m_CoverSpot = spot; }
|
||||
|
||||
//
|
||||
// From PersistClass
|
||||
//
|
||||
virtual const PersistFactoryClass & Get_Factory (void) const;
|
||||
|
||||
//
|
||||
// From NodeClass
|
||||
//
|
||||
void Initialize (void);
|
||||
NodeClass * Clone (void) { return new CoverAttackPointNodeClass (*this); }
|
||||
NODE_TYPE Get_Type (void) const { return NODE_TYPE_COVER_ATTACK_POINT; }
|
||||
int Get_Icon_Index (void) const { return OBJECT_ICON; }
|
||||
PhysClass * Peek_Physics_Obj (void) const { return m_PhysObj; }
|
||||
PhysClass * Peek_Collision_Obj (void) const;
|
||||
bool Is_Static (void) const { return false; }
|
||||
bool Show_Settings_Dialog (void) { return true; }
|
||||
bool Can_Be_Rotated_Freely (void) const { return true; }
|
||||
void On_Delete (void);
|
||||
NodeClass * Get_Parent_Node (void) const { return m_CoverSpot; }
|
||||
|
||||
//
|
||||
// Notifications
|
||||
//
|
||||
void On_Rotate (void);
|
||||
void On_Translate (void);
|
||||
void On_Transform (void);
|
||||
//
|
||||
// Export methods
|
||||
//
|
||||
void Pre_Export (void);
|
||||
void Post_Export (void);
|
||||
|
||||
|
||||
// From PersistClass
|
||||
bool Save (ChunkSaveClass &csave);
|
||||
bool Load (ChunkLoadClass &cload);
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
//////////////////////////////////////////////////////////////////
|
||||
bool Load_Variables (ChunkLoadClass &cload);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Protected member data
|
||||
//////////////////////////////////////////////////////////////////
|
||||
DecorationPhysClass * m_PhysObj;
|
||||
CoverSpotNodeClass * m_CoverSpot;
|
||||
|
||||
static PhysClass * _TheCollisionObj;
|
||||
static int _InstanceCount;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Rotate
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
CoverAttackPointNodeClass::On_Rotate (void)
|
||||
{
|
||||
if (m_CoverSpot != NULL) {
|
||||
m_CoverSpot->Update_Lines ();
|
||||
}
|
||||
|
||||
NodeClass::On_Rotate ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Translate
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
CoverAttackPointNodeClass::On_Translate (void)
|
||||
{
|
||||
if (m_CoverSpot != NULL) {
|
||||
m_CoverSpot->Update_Lines ();
|
||||
}
|
||||
|
||||
NodeClass::On_Translate ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Transform
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
CoverAttackPointNodeClass::On_Transform (void)
|
||||
{
|
||||
if (m_CoverSpot != NULL) {
|
||||
m_CoverSpot->Update_Lines ();
|
||||
}
|
||||
|
||||
NodeClass::On_Transform ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
#endif //__COVER_ATTACK_POINT_NODE_H
|
||||
|
||||
198
Code/Tools/LevelEdit/CoverSpotDefinition.cpp
Normal file
198
Code/Tools/LevelEdit/CoverSpotDefinition.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/CoverSpotDefinition.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 5/26/00 10:49a $*
|
||||
* *
|
||||
* $Revision:: 2 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "coverspotdefinition.h"
|
||||
#include "simpledefinitionfactory.h"
|
||||
#include "definitionclassids.h"
|
||||
#include "definitionmgr.h"
|
||||
#include "persistfactory.h"
|
||||
#include "editorchunkids.h"
|
||||
#include "coverspotnode.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
CHUNKID_VARIABLES = 0x00000100,
|
||||
CHUNKID_BASE_CLASS = 0x00000200,
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Static factories
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
DECLARE_DEFINITION_FACTORY(CoverSpotDefinitionClass, CLASSID_COVERSPOT, "Cover Spot") _CoverSpotDefFactory;
|
||||
SimplePersistFactoryClass<CoverSpotDefinitionClass, CHUNKID_COVERSPOT_DEF> _CoverSpotPersistFactory;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CoverSpotDefinitionClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
CoverSpotDefinitionClass::CoverSpotDefinitionClass (void)
|
||||
: DefinitionClass ()
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~CoverSpotDefinitionClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
CoverSpotDefinitionClass::~CoverSpotDefinitionClass (void)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Factory
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
const PersistFactoryClass &
|
||||
CoverSpotDefinitionClass::Get_Factory (void) const
|
||||
{
|
||||
return _CoverSpotPersistFactory;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
CoverSpotDefinitionClass::Save (ChunkSaveClass &csave)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
csave.Begin_Chunk (CHUNKID_VARIABLES);
|
||||
retval &= Save_Variables (csave);
|
||||
csave.End_Chunk ();
|
||||
|
||||
csave.Begin_Chunk (CHUNKID_BASE_CLASS);
|
||||
retval &= DefinitionClass::Save (csave);
|
||||
csave.End_Chunk ();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
CoverSpotDefinitionClass::Load (ChunkLoadClass &cload)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
while (cload.Open_Chunk ()) {
|
||||
switch (cload.Cur_Chunk_ID ()) {
|
||||
|
||||
case CHUNKID_VARIABLES:
|
||||
retval &= Load_Variables (cload);
|
||||
break;
|
||||
|
||||
case CHUNKID_BASE_CLASS:
|
||||
retval &= DefinitionClass::Load (cload);
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Chunk ();
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save_Variables
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
CoverSpotDefinitionClass::Save_Variables (ChunkSaveClass &csave)
|
||||
{
|
||||
bool retval = true;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_Variables
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
CoverSpotDefinitionClass::Load_Variables (ChunkLoadClass &cload)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
//
|
||||
// Loop through all the microchunks that define the variables
|
||||
//
|
||||
while (cload.Open_Micro_Chunk ()) {
|
||||
/*switch (cload.Cur_Micro_Chunk_ID ()) {
|
||||
}*/
|
||||
|
||||
cload.Close_Micro_Chunk ();
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
PersistClass *
|
||||
CoverSpotDefinitionClass::Create (void) const
|
||||
{
|
||||
return new CoverSpotNodeClass ();
|
||||
}
|
||||
|
||||
95
Code/Tools/LevelEdit/CoverSpotDefinition.h
Normal file
95
Code/Tools/LevelEdit/CoverSpotDefinition.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/CoverSpotDefinition.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 5/26/00 10:47a $*
|
||||
* *
|
||||
* $Revision:: 2 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __COVERSPOT_DEFINITION_H
|
||||
#define __COVERSPOT_DEFINITION_H
|
||||
|
||||
#include "definition.h"
|
||||
#include "vector.h"
|
||||
#include "wwstring.h"
|
||||
#include "editorchunkids.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CoverSpotDefinitionClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
class CoverSpotDefinitionClass : public DefinitionClass
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Editable interface requirements
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
DECLARE_EDITABLE(CoverSpotDefinitionClass, DefinitionClass);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////////
|
||||
CoverSpotDefinitionClass (void);
|
||||
virtual ~CoverSpotDefinitionClass (void);
|
||||
|
||||
// From DefinitionClass
|
||||
virtual uint32 Get_Class_ID (void) const { return CLASSID_COVERSPOT; }
|
||||
|
||||
// From PersistClass
|
||||
virtual const PersistFactoryClass & Get_Factory (void) const;
|
||||
virtual bool Save (ChunkSaveClass &csave);
|
||||
virtual bool Load (ChunkLoadClass &cload);
|
||||
virtual PersistClass * Create (void) const;
|
||||
|
||||
private:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
bool Save_Variables (ChunkSaveClass &csave);
|
||||
bool Load_Variables (ChunkLoadClass &cload);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
|
||||
#endif //__COVERSPOT_DEFINITION_H
|
||||
170
Code/Tools/LevelEdit/CoverSpotInfoPage.cpp
Normal file
170
Code/Tools/LevelEdit/CoverSpotInfoPage.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// CoverSpotInfoPage.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "CoverSpotInfoPage.h"
|
||||
#include "leveledit.h"
|
||||
#include "coverspotnode.h"
|
||||
#include "node.h"
|
||||
#include "utils.h"
|
||||
#include "sceneeditor.h"
|
||||
#include "mousemgr.h"
|
||||
#include "coverattackpointnode.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CoverSpotInfoPageClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
CoverSpotInfoPageClass::CoverSpotInfoPageClass (void)
|
||||
: m_CoverSpot (NULL),
|
||||
DockableFormClass (CoverSpotInfoPageClass::IDD)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CoverSpotInfoPageClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
CoverSpotInfoPageClass::CoverSpotInfoPageClass (CoverSpotNodeClass *cover_spot)
|
||||
: m_CoverSpot (cover_spot),
|
||||
DockableFormClass (CoverSpotInfoPageClass::IDD)
|
||||
{
|
||||
//{{AFX_DATA_INIT(CoverSpotInfoPageClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~CoverSpotInfoPageClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
CoverSpotInfoPageClass::~CoverSpotInfoPageClass (void)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverSpotInfoPageClass::DoDataExchange (CDataExchange* pDX)
|
||||
{
|
||||
DockableFormClass::DoDataExchange (pDX);
|
||||
//{{AFX_DATA_MAP(CoverSpotInfoPageClass)
|
||||
// NOTE: the ClassWizard will add DDX and DDV calls here
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(CoverSpotInfoPageClass, DockableFormClass)
|
||||
//{{AFX_MSG_MAP(CoverSpotInfoPageClass)
|
||||
ON_BN_CLICKED(IDC_ADD_ATTACK_LOCATION, OnAddAttackLocation)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CoverSpotInfoPageClass diagnostics
|
||||
|
||||
#ifdef _DEBUG
|
||||
void CoverSpotInfoPageClass::AssertValid() const
|
||||
{
|
||||
DockableFormClass::AssertValid();
|
||||
}
|
||||
|
||||
void CoverSpotInfoPageClass::Dump(CDumpContext& dc) const
|
||||
{
|
||||
DockableFormClass::Dump(dc);
|
||||
}
|
||||
#endif //_DEBUG
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// HandleInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverSpotInfoPageClass::HandleInitDialog (void)
|
||||
{
|
||||
ASSERT (m_CoverSpot != NULL);
|
||||
|
||||
SendDlgItemMessage (IDC_CROUCH_CHECK, BM_SETCHECK, m_CoverSpot->Requires_Crouch ());
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Apply_Changes
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
CoverSpotInfoPageClass::Apply_Changes (void)
|
||||
{
|
||||
BOOL crouch = SendDlgItemMessage (IDC_CROUCH_CHECK, BM_GETCHECK);
|
||||
m_CoverSpot->Set_Requires_Crouch (bool(crouch == 1));
|
||||
|
||||
// Return true to allow the dialog to close
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnAddAttackLocation
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverSpotInfoPageClass::OnAddAttackLocation (void)
|
||||
{
|
||||
//
|
||||
// Add a new attack point to the world
|
||||
//
|
||||
CoverAttackPointNodeClass *attack_point = m_CoverSpot->Add_Attack_Point (Matrix3D(1));
|
||||
if (attack_point != NULL) {
|
||||
::Get_Mouse_Mgr ()->Move_Node (attack_point);
|
||||
}
|
||||
|
||||
//
|
||||
// Simulate pressing the OK button
|
||||
//
|
||||
::PostMessage (::GetParent (m_hWnd), WM_COMMAND, MAKELPARAM(IDC_OK, BN_CLICKED), 0L);
|
||||
return ;
|
||||
}
|
||||
108
Code/Tools/LevelEdit/CoverSpotInfoPage.h
Normal file
108
Code/Tools/LevelEdit/CoverSpotInfoPage.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_COVERSPOTINFOPAGE_H__2D902CA1_3328_11D4_A0A1_00104B791122__INCLUDED_)
|
||||
#define AFX_COVERSPOTINFOPAGE_H__2D902CA1_3328_11D4_A0A1_00104B791122__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
|
||||
#ifndef __AFXEXT_H__
|
||||
#include <afxext.h>
|
||||
#endif
|
||||
|
||||
|
||||
class CoverSpotNodeClass;
|
||||
#include "DockableForm.h"
|
||||
#include "resource.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CoverSpotInfoPageClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class CoverSpotInfoPageClass : public DockableFormClass
|
||||
{
|
||||
public:
|
||||
CoverSpotInfoPageClass (void);
|
||||
CoverSpotInfoPageClass (CoverSpotNodeClass *cover_spot);
|
||||
virtual ~CoverSpotInfoPageClass (void);
|
||||
|
||||
// Form Data
|
||||
public:
|
||||
//{{AFX_DATA(CoverSpotInfoPageClass)
|
||||
enum { IDD = IDD_COVERSPOT_INFO };
|
||||
// NOTE: the ClassWizard will add data members here
|
||||
//}}AFX_DATA
|
||||
|
||||
// Attributes
|
||||
public:
|
||||
|
||||
// Operations
|
||||
public:
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CoverSpotInfoPageClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
#ifdef _DEBUG
|
||||
virtual void AssertValid() const;
|
||||
virtual void Dump(CDumpContext& dc) const;
|
||||
#endif
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(CoverSpotInfoPageClass)
|
||||
afx_msg void OnAddAttackLocation();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////////
|
||||
void HandleInitDialog (void);
|
||||
bool Apply_Changes (void);
|
||||
|
||||
protected:
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Inline accessors
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
///////////////////////////////////////////////////////
|
||||
CoverSpotNodeClass * m_CoverSpot;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_COVERSPOTINFOPAGE_H__2D902CA1_3328_11D4_A0A1_00104B791122__INCLUDED_)
|
||||
717
Code/Tools/LevelEdit/CoverSpotNode.cpp
Normal file
717
Code/Tools/LevelEdit/CoverSpotNode.cpp
Normal file
@@ -0,0 +1,717 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/CoverSpotNode.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 9/13/01 9:44a $*
|
||||
* *
|
||||
* $Revision:: 15 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "coverspotnode.h"
|
||||
#include "coverattackpointnode.h"
|
||||
#include "sceneeditor.h"
|
||||
#include "collisiongroups.h"
|
||||
#include "persistfactory.h"
|
||||
#include "editorchunkids.h"
|
||||
#include "preset.h"
|
||||
#include "chunkio.h"
|
||||
#include "nodemgr.h"
|
||||
#include "coverspotinfopage.h"
|
||||
#include "nodeinfopage.h"
|
||||
#include "positionpage.h"
|
||||
#include "editorpropsheet.h"
|
||||
#include "cover.h"
|
||||
#include "modelutils.h"
|
||||
#include "soldier.h"
|
||||
#include "presetmgr.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Persist factory
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
SimplePersistFactoryClass<CoverSpotNodeClass, CHUNKID_NODE_COVER_SPOT> _CoverSpotNodePersistFactory;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Save/load constants
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
CHUNKID_VARIABLES = 0x05260946,
|
||||
CHUNKID_BASE_CLASS
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VARID_REQUIRES_CROUCH = 0x01,
|
||||
VARID_ATTACK_POINT,
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
static const Vector3 LINE_OFFSET (0, 0, 0.2F);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Static member initialization
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
PhysClass * CoverSpotNodeClass::_TheCollisionObj = NULL;
|
||||
int CoverSpotNodeClass::_InstanceCount = 0;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CoverSpotNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
CoverSpotNodeClass::CoverSpotNodeClass (PresetClass *preset)
|
||||
: m_PhysObj (NULL),
|
||||
m_RequiresCrouch (false),
|
||||
m_GameCoverSpot (NULL),
|
||||
NodeClass (preset)
|
||||
{
|
||||
_InstanceCount ++;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CoverSpotNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
CoverSpotNodeClass::CoverSpotNodeClass (const CoverSpotNodeClass &src)
|
||||
: m_PhysObj (NULL),
|
||||
m_RequiresCrouch (false),
|
||||
m_GameCoverSpot (NULL),
|
||||
NodeClass (NULL)
|
||||
{
|
||||
_InstanceCount ++;
|
||||
*this = src;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~CoverSpotNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
CoverSpotNodeClass::~CoverSpotNodeClass (void)
|
||||
{
|
||||
Free_Attack_Points ();
|
||||
Remove_From_Scene ();
|
||||
MEMBER_RELEASE (m_PhysObj);
|
||||
|
||||
//
|
||||
// Free the collision object when all instances have gone away
|
||||
//
|
||||
_InstanceCount --;
|
||||
if (_InstanceCount == 0) {
|
||||
MEMBER_RELEASE (_TheCollisionObj);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Initialize
|
||||
//
|
||||
// Note: This may be called more than once. It is used as an 'initialize'
|
||||
// and a 're-initialize'.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverSpotNodeClass::Initialize (void)
|
||||
{
|
||||
MEMBER_RELEASE (m_PhysObj);
|
||||
|
||||
//
|
||||
// Create the camera render object
|
||||
//
|
||||
RenderObjClass *render_obj = ::Create_Render_Obj ("COVERSPOT");
|
||||
WWASSERT (render_obj != NULL);
|
||||
if (render_obj != NULL) {
|
||||
|
||||
// Create the new physics object
|
||||
m_PhysObj = new DecorationPhysClass;
|
||||
|
||||
//
|
||||
// Configure the physics object with information about
|
||||
// its new render object and collision data.
|
||||
//
|
||||
m_PhysObj->Set_Model (render_obj);
|
||||
m_PhysObj->Set_Transform (Matrix3D(1));
|
||||
m_PhysObj->Set_Collision_Group (EDITOR_COLLISION_GROUP);
|
||||
m_PhysObj->Peek_Model ()->Set_User_Data ((PVOID)&m_HitTestInfo, FALSE);
|
||||
m_PhysObj->Set_Transform (m_Transform);
|
||||
::Set_Model_Collision_Type (m_PhysObj->Peek_Model (), COLLISION_TYPE_0);
|
||||
|
||||
// Release our hold on the render object pointer
|
||||
MEMBER_RELEASE (render_obj);
|
||||
}
|
||||
|
||||
if (_TheCollisionObj == NULL) {
|
||||
|
||||
//
|
||||
// Create the collision physics object
|
||||
//
|
||||
PresetClass *preset = PresetMgrClass::Find_Preset ("Walk-Thru");
|
||||
if (preset != NULL && preset->Get_Definition () != NULL) {
|
||||
|
||||
//
|
||||
// Load the assets for this preset and get its definition
|
||||
//
|
||||
preset->Load_All_Assets ();
|
||||
SoldierGameObjDef *definition = (SoldierGameObjDef *)preset->Get_Definition ();
|
||||
|
||||
//
|
||||
// Create the collision physics object
|
||||
//
|
||||
SoldierGameObj *game_obj = new SoldierGameObj;
|
||||
game_obj->Init (*definition);
|
||||
MEMBER_ADD (_TheCollisionObj, game_obj->Peek_Physical_Object ());
|
||||
game_obj->Set_Delete_Pending ();
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Factory
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
const PersistFactoryClass &
|
||||
CoverSpotNodeClass::Get_Factory (void) const
|
||||
{
|
||||
return _CoverSpotNodePersistFactory;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
CoverSpotNodeClass::Save (ChunkSaveClass &csave)
|
||||
{
|
||||
csave.Begin_Chunk (CHUNKID_BASE_CLASS);
|
||||
NodeClass::Save (csave);
|
||||
csave.End_Chunk ();
|
||||
|
||||
csave.Begin_Chunk (CHUNKID_VARIABLES);
|
||||
WRITE_MICRO_CHUNK (csave, VARID_REQUIRES_CROUCH, m_RequiresCrouch);
|
||||
|
||||
//
|
||||
// Save the list of cover point attack positions
|
||||
//
|
||||
for (int index = 0; index < m_AttackPointNodes.Count (); index ++) {
|
||||
CoverAttackPointNodeClass *attack_point = m_AttackPointNodes[index];
|
||||
if (attack_point != NULL) {
|
||||
Matrix3D tm = attack_point->Get_Transform ();
|
||||
WRITE_MICRO_CHUNK (csave, VARID_ATTACK_POINT, tm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
csave.End_Chunk ();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
CoverSpotNodeClass::Load (ChunkLoadClass &cload)
|
||||
{
|
||||
while (cload.Open_Chunk ()) {
|
||||
switch (cload.Cur_Chunk_ID ()) {
|
||||
|
||||
case CHUNKID_BASE_CLASS:
|
||||
NodeClass::Load (cload);
|
||||
break;
|
||||
|
||||
case CHUNKID_VARIABLES:
|
||||
Load_Variables (cload);
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Chunk ();
|
||||
}
|
||||
|
||||
SaveLoadSystemClass::Register_Post_Load_Callback (this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_Variables
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
CoverSpotNodeClass::Load_Variables (ChunkLoadClass &cload)
|
||||
{
|
||||
//
|
||||
// Loop through all the microchunks that define the variables
|
||||
//
|
||||
while (cload.Open_Micro_Chunk ()) {
|
||||
switch (cload.Cur_Micro_Chunk_ID ()) {
|
||||
|
||||
READ_MICRO_CHUNK (cload, VARID_REQUIRES_CROUCH, m_RequiresCrouch);
|
||||
|
||||
case VARID_ATTACK_POINT:
|
||||
{
|
||||
//
|
||||
// Read the attack points transfrom from the chunk
|
||||
//
|
||||
Matrix3D tm;
|
||||
cload.Read (&tm, sizeof (tm));
|
||||
m_AttackPointLoadList.Add (tm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Micro_Chunk ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// On_Post_Load
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverSpotNodeClass::On_Post_Load (void)
|
||||
{
|
||||
//
|
||||
// If the spawner isn't valid, then remove it from the system
|
||||
//
|
||||
if (m_Preset == NULL) {
|
||||
::Get_Scene_Editor ()->Delete_Node (this, false);
|
||||
} else {
|
||||
|
||||
//
|
||||
// Add each attack point at the given locations
|
||||
//
|
||||
for (int index = 0; index < m_AttackPointLoadList.Count (); index ++) {
|
||||
Add_Attack_Point (m_AttackPointLoadList[index]);
|
||||
}
|
||||
|
||||
//
|
||||
// Reset the list
|
||||
//
|
||||
m_AttackPointLoadList.Delete_All ();
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// operator=
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
const CoverSpotNodeClass &
|
||||
CoverSpotNodeClass::operator= (const CoverSpotNodeClass &src)
|
||||
{
|
||||
//
|
||||
// Copy the attach point list
|
||||
//
|
||||
Free_Attack_Points ();
|
||||
for (int index = 0; index < src.m_AttackPointNodes.Count (); index ++) {
|
||||
CoverAttackPointNodeClass *attack_point = src.m_AttackPointNodes[index];
|
||||
if (attack_point != NULL) {
|
||||
Add_Attack_Point (attack_point->Get_Transform ());
|
||||
}
|
||||
}
|
||||
|
||||
m_RequiresCrouch = src.m_RequiresCrouch;
|
||||
NodeClass::operator= (src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Pre_Export
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverSpotNodeClass::Pre_Export (void)
|
||||
{
|
||||
//
|
||||
// Remove ourselves from the 'system' so we don't get accidentally
|
||||
// saved during the export.
|
||||
//
|
||||
Add_Ref ();
|
||||
if (m_PhysObj != NULL && m_IsInScene) {
|
||||
::Get_Scene_Editor ()->Remove_Object (m_PhysObj);
|
||||
|
||||
//
|
||||
// Build a cover spot entry that we can pass off the game
|
||||
// so it will get exported
|
||||
//
|
||||
MEMBER_RELEASE (m_GameCoverSpot);
|
||||
m_GameCoverSpot = new CoverEntryClass;
|
||||
m_GameCoverSpot->Set_Transform (Get_Transform ());
|
||||
m_GameCoverSpot->Set_Crouch (m_RequiresCrouch);
|
||||
AttackPositionListType *attack_list = m_GameCoverSpot->Get_Attack_Position_List ();
|
||||
|
||||
//
|
||||
// Remove the unnecessary UI elements from the scene
|
||||
//
|
||||
for (int index = 0; index < m_AttackPointNodes.Count (); index ++) {
|
||||
CoverAttackPointNodeClass *attack_point = m_AttackPointNodes[index];
|
||||
EditorLineClass *line = m_AttackPointLines[index];
|
||||
::Get_Scene_Editor ()->Remove_Object (line);
|
||||
|
||||
attack_list->Add (attack_point->Get_Position ());
|
||||
}
|
||||
|
||||
//
|
||||
// Add this cover spot to the game
|
||||
//
|
||||
CoverManager::Add_Entry (m_GameCoverSpot);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Post_Export
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverSpotNodeClass::Post_Export (void)
|
||||
{
|
||||
//
|
||||
// Put ourselves back into the system
|
||||
//
|
||||
if (m_PhysObj != NULL && m_IsInScene) {
|
||||
::Get_Scene_Editor ()->Add_Dynamic_Object (m_PhysObj);
|
||||
|
||||
//
|
||||
// Pass the Post_Export call onto any attack points as well
|
||||
//
|
||||
for (int index = 0; index < m_AttackPointNodes.Count (); index ++) {
|
||||
CoverAttackPointNodeClass *attack_point = m_AttackPointNodes[index];
|
||||
EditorLineClass *line = m_AttackPointLines[index];
|
||||
::Get_Scene_Editor ()->Add_Dynamic_Object (line);
|
||||
}
|
||||
|
||||
//
|
||||
// Remove the cover spot from the game
|
||||
//
|
||||
CoverManager::Remove_Entry (m_GameCoverSpot);
|
||||
MEMBER_RELEASE (m_GameCoverSpot);
|
||||
}
|
||||
|
||||
Release_Ref ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Add_Attack_Point
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
CoverAttackPointNodeClass *
|
||||
CoverSpotNodeClass::Add_Attack_Point (const Matrix3D &tm)
|
||||
{
|
||||
//
|
||||
// Create and add the new point
|
||||
//
|
||||
CoverAttackPointNodeClass *attack_point = new CoverAttackPointNodeClass;
|
||||
attack_point->Initialize ();
|
||||
attack_point->Set_Transform (tm);
|
||||
attack_point->Set_Cover_Spot (this);
|
||||
NodeMgrClass::Setup_Node_Identity (*attack_point);
|
||||
m_AttackPointNodes.Add (attack_point);
|
||||
|
||||
//
|
||||
// Create and add the line from the coverspot to the attack point
|
||||
//
|
||||
EditorLineClass *line = new EditorLineClass;
|
||||
line->Reset (m_Transform.Get_Translation () + LINE_OFFSET, tm.Get_Translation () + LINE_OFFSET);
|
||||
m_AttackPointLines.Add (line);
|
||||
|
||||
if (m_IsInScene) {
|
||||
attack_point->Add_To_Scene ();
|
||||
::Get_Scene_Editor ()->Add_Dynamic_Object (line);
|
||||
}
|
||||
|
||||
return attack_point;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Remove_Attack_Point
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverSpotNodeClass::Remove_Attack_Point (CoverAttackPointNodeClass *attack_point)
|
||||
{
|
||||
//
|
||||
// Try to find the attack point
|
||||
//
|
||||
for (int index = 0; index < m_AttackPointNodes.Count (); index ++) {
|
||||
if (attack_point == m_AttackPointNodes[index]) {
|
||||
|
||||
//
|
||||
// Free the attack point
|
||||
//
|
||||
MEMBER_RELEASE (attack_point);
|
||||
m_AttackPointNodes.Delete (index);
|
||||
|
||||
//
|
||||
// Remove and free the line to the attack point
|
||||
//
|
||||
::Get_Scene_Editor ()->Remove_Object (m_AttackPointLines[index]);
|
||||
m_AttackPointLines[index]->Release_Ref ();
|
||||
m_AttackPointLines.Delete (index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Free_Attack_Points
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverSpotNodeClass::Free_Attack_Points (void)
|
||||
{
|
||||
SceneEditorClass *scene = ::Get_Scene_Editor ();
|
||||
|
||||
//
|
||||
// Release our hold on each attack point
|
||||
//
|
||||
for (int index = 0; index < m_AttackPointNodes.Count (); index ++) {
|
||||
CoverAttackPointNodeClass *attack_point = m_AttackPointNodes[index];
|
||||
EditorLineClass *line = m_AttackPointLines[index];
|
||||
|
||||
scene->Remove_Object (line);
|
||||
attack_point->Remove_From_Scene ();
|
||||
MEMBER_RELEASE (attack_point);
|
||||
MEMBER_RELEASE (line);
|
||||
}
|
||||
|
||||
//
|
||||
// Remove all the attack points from the list
|
||||
//
|
||||
m_AttackPointNodes.Delete_All ();
|
||||
m_AttackPointLines.Delete_All ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Show_Settings_Dialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
CoverSpotNodeClass::Show_Settings_Dialog (void)
|
||||
{
|
||||
NodeInfoPageClass info_tab (this);
|
||||
PositionPageClass pos_tab (this);
|
||||
CoverSpotInfoPageClass cover_info_tab (this);
|
||||
|
||||
EditorPropSheetClass prop_sheet;
|
||||
prop_sheet.Add_Page (&info_tab);
|
||||
prop_sheet.Add_Page (&pos_tab);
|
||||
prop_sheet.Add_Page (&cover_info_tab);
|
||||
|
||||
// Show the property sheet
|
||||
UINT ret_code = prop_sheet.DoModal ();
|
||||
|
||||
// Return true if the user clicked OK
|
||||
return (ret_code == IDOK);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Add_To_Scene
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverSpotNodeClass::Add_To_Scene (void)
|
||||
{
|
||||
SceneEditorClass *scene = ::Get_Scene_Editor ();
|
||||
|
||||
//
|
||||
// Add all the waypoints to the scene
|
||||
//
|
||||
for (int index = 0; index < m_AttackPointNodes.Count (); index ++) {
|
||||
CoverAttackPointNodeClass *attack_point = m_AttackPointNodes[index];
|
||||
EditorLineClass *line = m_AttackPointLines[index];
|
||||
attack_point->Add_To_Scene ();
|
||||
scene->Add_Dynamic_Object (line);
|
||||
}
|
||||
|
||||
NodeClass::Add_To_Scene ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Remove_From_Scene
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverSpotNodeClass::Remove_From_Scene (void)
|
||||
{
|
||||
SceneEditorClass *scene = ::Get_Scene_Editor ();
|
||||
if (scene != NULL && m_IsInScene) {
|
||||
|
||||
//
|
||||
// Remove all the waypoints from the scene
|
||||
//
|
||||
for (int index = 0; index < m_AttackPointNodes.Count (); index ++) {
|
||||
CoverAttackPointNodeClass *attack_point = m_AttackPointNodes[index];
|
||||
EditorLineClass *line = m_AttackPointLines[index];
|
||||
attack_point->Remove_From_Scene ();
|
||||
scene->Remove_Object (line);
|
||||
}
|
||||
}
|
||||
|
||||
NodeClass::Remove_From_Scene ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Lines
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverSpotNodeClass::Update_Lines (void)
|
||||
{
|
||||
for (int index = 0; index < m_AttackPointNodes.Count (); index ++) {
|
||||
CoverAttackPointNodeClass *attack_point = m_AttackPointNodes[index];
|
||||
EditorLineClass *line = m_AttackPointLines[index];
|
||||
|
||||
line->Reset (Get_Transform ().Get_Translation () + LINE_OFFSET,
|
||||
attack_point->Get_Position () + LINE_OFFSET);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Peek_Collision_Obj
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
PhysClass *
|
||||
CoverSpotNodeClass::Peek_Collision_Obj (void) const
|
||||
{
|
||||
if (_TheCollisionObj != NULL) {
|
||||
_TheCollisionObj->Set_Transform (m_Transform);
|
||||
}
|
||||
|
||||
return _TheCollisionObj;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Hide
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
CoverSpotNodeClass::Hide (bool hide)
|
||||
{
|
||||
//
|
||||
// Apply the same operation to all the attack points and lines
|
||||
//
|
||||
for (int index = 0; index < m_AttackPointNodes.Count (); index ++) {
|
||||
CoverAttackPointNodeClass *attack_point = m_AttackPointNodes[index];
|
||||
EditorLineClass *line = m_AttackPointLines[index];
|
||||
attack_point->Hide (hide);
|
||||
line->Hide (hide);
|
||||
}
|
||||
|
||||
NodeClass::Hide (hide);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Add_Child_Node
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
NodeClass *
|
||||
CoverSpotNodeClass::Add_Child_Node (const Matrix3D &tm)
|
||||
{
|
||||
return Add_Attack_Point (tm);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Sub_Node
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
NodeClass *
|
||||
CoverSpotNodeClass::Get_Sub_Node (int index)
|
||||
{
|
||||
return m_AttackPointNodes[index];
|
||||
}
|
||||
205
Code/Tools/LevelEdit/CoverSpotNode.h
Normal file
205
Code/Tools/LevelEdit/CoverSpotNode.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/CoverSpotNode.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 7/25/01 4:26p $*
|
||||
* *
|
||||
* $Revision:: 11 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __COVERSPOT_NODE_H
|
||||
#define __COVERSPOT_NODE_H
|
||||
|
||||
#include "node.h"
|
||||
#include "vector.h"
|
||||
#include "icons.h"
|
||||
#include "decophys.h"
|
||||
#include "editorphys.h"
|
||||
#include "segline.h"
|
||||
#include "editorline.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class PresetClass;
|
||||
class CoverAttackPointNodeClass;
|
||||
class CoverEntryClass;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CoverSpotNodeClass
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class CoverSpotNodeClass : public NodeClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////////////
|
||||
CoverSpotNodeClass (PresetClass *preset = NULL);
|
||||
CoverSpotNodeClass (const CoverSpotNodeClass &src);
|
||||
~CoverSpotNodeClass (void);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public operators
|
||||
//////////////////////////////////////////////////////////////
|
||||
const CoverSpotNodeClass &operator= (const CoverSpotNodeClass &src);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// CoverSpotNodeClass specific
|
||||
//
|
||||
CoverAttackPointNodeClass *Add_Attack_Point (const Matrix3D &tm);
|
||||
void Remove_Attack_Point (CoverAttackPointNodeClass *attack_point);
|
||||
bool Requires_Crouch (void) const { return m_RequiresCrouch; }
|
||||
void Set_Requires_Crouch (bool onoff) { m_RequiresCrouch = onoff; }
|
||||
void Update_Lines (void);
|
||||
|
||||
//
|
||||
// From PersistClass
|
||||
//
|
||||
virtual const PersistFactoryClass & Get_Factory (void) const;
|
||||
void On_Post_Load (void);
|
||||
|
||||
//
|
||||
// From NodeClass
|
||||
//
|
||||
void Initialize (void);
|
||||
NodeClass * Clone (void) { return new CoverSpotNodeClass (*this); }
|
||||
NODE_TYPE Get_Type (void) const { return NODE_TYPE_COVER_SPOT; }
|
||||
int Get_Icon_Index (void) const { return OBJECT_ICON; }
|
||||
PhysClass * Peek_Physics_Obj (void) const { return m_PhysObj; }
|
||||
PhysClass * Peek_Collision_Obj (void) const;
|
||||
bool Is_Static (void) const { return false; }
|
||||
bool Show_Settings_Dialog (void);
|
||||
bool Can_Be_Rotated_Freely (void) const { return true; }
|
||||
void Add_To_Scene (void);
|
||||
void Remove_From_Scene (void);
|
||||
void Hide (bool hide);
|
||||
NodeClass * Add_Child_Node (const Matrix3D &tm);
|
||||
bool Can_Add_Child_Nodes (void) const { return true; }
|
||||
|
||||
int Get_Sub_Node_Count (void) const { return m_AttackPointNodes.Count (); }
|
||||
NodeClass * Get_Sub_Node (int index);
|
||||
|
||||
//
|
||||
// Notifications
|
||||
//
|
||||
void On_Rotate (void);
|
||||
void On_Translate (void);
|
||||
void On_Transform (void);
|
||||
|
||||
//
|
||||
// Export methods
|
||||
//
|
||||
void Pre_Export (void);
|
||||
void Post_Export (void);
|
||||
|
||||
|
||||
// From PersistClass
|
||||
bool Save (ChunkSaveClass &csave);
|
||||
bool Load (ChunkLoadClass &cload);
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
//////////////////////////////////////////////////////////////////
|
||||
bool Load_Variables (ChunkLoadClass &cload);
|
||||
void Free_Attack_Points (void);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Protected member data
|
||||
//////////////////////////////////////////////////////////////////
|
||||
DecorationPhysClass * m_PhysObj;
|
||||
DynamicVectorClass<CoverAttackPointNodeClass *> m_AttackPointNodes;
|
||||
DynamicVectorClass<EditorLineClass *> m_AttackPointLines;
|
||||
DynamicVectorClass<Matrix3D> m_AttackPointLoadList;
|
||||
bool m_RequiresCrouch;
|
||||
CoverEntryClass * m_GameCoverSpot;
|
||||
|
||||
static PhysClass * _TheCollisionObj;
|
||||
static int _InstanceCount;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Rotate
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
CoverSpotNodeClass::On_Rotate (void)
|
||||
{
|
||||
Update_Lines ();
|
||||
|
||||
NodeClass::On_Rotate ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Translate
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
CoverSpotNodeClass::On_Translate (void)
|
||||
{
|
||||
Update_Lines ();
|
||||
|
||||
NodeClass::On_Translate ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Transform
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
CoverSpotNodeClass::On_Transform (void)
|
||||
{
|
||||
Update_Lines ();
|
||||
|
||||
NodeClass::On_Transform ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif //__COVERSPOT_NODE_H
|
||||
|
||||
485
Code/Tools/LevelEdit/DamageZoneNode.cpp
Normal file
485
Code/Tools/LevelEdit/DamageZoneNode.cpp
Normal file
@@ -0,0 +1,485 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/DamageZoneNode.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 5/22/01 11:17a $*
|
||||
* *
|
||||
* $Revision:: 5 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "damagezonenode.h"
|
||||
#include "sceneeditor.h"
|
||||
|
||||
#include "filemgr.h"
|
||||
#include "_assetmgr.h"
|
||||
#include "editorassetmgr.h"
|
||||
#include "w3d_file.h"
|
||||
#include "cameramgr.h"
|
||||
#include "collisiongroups.h"
|
||||
#include "persistfactory.h"
|
||||
#include "editorchunkids.h"
|
||||
#include "preset.h"
|
||||
#include "presetmgr.h"
|
||||
#include "decophys.h"
|
||||
#include "damagezone.h"
|
||||
#include "chunkio.h"
|
||||
#include "nodemgr.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Persist factory
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
SimplePersistFactoryClass<DamageZoneNodeClass, CHUNKID_NODE_DAMAGE_ZONE> _DamageZoneNodePersistFactory;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
CHUNKID_VARIABLES = 0x06291059,
|
||||
CHUNKID_BASE_CLASS
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VARID_ZONE_SIZE = 1
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DamageZoneNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
DamageZoneNodeClass::DamageZoneNodeClass (PresetClass *preset)
|
||||
: m_PhysObj (NULL),
|
||||
m_GameObj (NULL),
|
||||
m_CachedSize (1, 1, 1),
|
||||
NodeClass (preset)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DamageZoneNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
DamageZoneNodeClass::DamageZoneNodeClass (const DamageZoneNodeClass &src)
|
||||
: m_PhysObj (NULL),
|
||||
m_GameObj (NULL),
|
||||
m_CachedSize (1, 1, 1),
|
||||
NodeClass (NULL)
|
||||
{
|
||||
*this = src;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~DamageZoneNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
DamageZoneNodeClass::~DamageZoneNodeClass (void)
|
||||
{
|
||||
Destroy_Game_Obj ();
|
||||
Remove_From_Scene ();
|
||||
MEMBER_RELEASE (m_PhysObj);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Initialize
|
||||
//
|
||||
// Note: This may be called more than once. It is used as an 'initialize'
|
||||
// and a 're-initialize'.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DamageZoneNodeClass::Initialize (void)
|
||||
{
|
||||
MEMBER_RELEASE (m_PhysObj);
|
||||
Destroy_Game_Obj ();
|
||||
|
||||
DefinitionClass *definition = m_Preset->Get_Definition ();
|
||||
if (definition != NULL) {
|
||||
|
||||
//
|
||||
// Create the new box physics object
|
||||
//
|
||||
m_PhysObj = new Box3DPhysClass;
|
||||
m_PhysObj->Set_Collision_Group (EDITOR_COLLISION_GROUP);
|
||||
m_PhysObj->Peek_Model ()->Set_User_Data ((PVOID)&m_HitTestInfo, FALSE);
|
||||
m_PhysObj->Peek_Model ()->Set_Collision_Type (COLLISION_TYPE_0);
|
||||
m_PhysObj->Set_Transform (m_Transform);
|
||||
m_PhysObj->Get_Box ()->Set_Color (((DamageZoneGameObjDef *)definition)->Get_Color ());
|
||||
m_PhysObj->Get_Box ()->Set_Dimensions (m_CachedSize);
|
||||
|
||||
//
|
||||
// Create the game object
|
||||
//
|
||||
Create_Game_Obj ();
|
||||
|
||||
//
|
||||
// Make sure the physics object has the correct position
|
||||
//
|
||||
Set_Transform (m_Transform);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Factory
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
const PersistFactoryClass &
|
||||
DamageZoneNodeClass::Get_Factory (void) const
|
||||
{
|
||||
return _DamageZoneNodePersistFactory;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// operator=
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
const DamageZoneNodeClass &
|
||||
DamageZoneNodeClass::operator= (const DamageZoneNodeClass &src)
|
||||
{
|
||||
m_CachedSize = src.m_CachedSize;
|
||||
NodeClass::operator= (src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Add_To_Scene
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DamageZoneNodeClass::Add_To_Scene (void)
|
||||
{
|
||||
Create_Game_Obj ();
|
||||
|
||||
m_GrabHandles.Position_Around_Node (this);
|
||||
NodeClass::Add_To_Scene ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Remove_From_Scene
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DamageZoneNodeClass::Remove_From_Scene (void)
|
||||
{
|
||||
Destroy_Game_Obj ();
|
||||
|
||||
m_GrabHandles.Remove_From_Scene ();
|
||||
NodeClass::Remove_From_Scene ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// On_Vertex_Drag_Begin
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DamageZoneNodeClass::On_Vertex_Drag_Begin (int vertex_index)
|
||||
{
|
||||
//
|
||||
// Store the location of the 'locked' vertex, so we can
|
||||
// use this when resizing the box
|
||||
//
|
||||
m_FirstPoint = m_PhysObj->Get_Box ()->Get_Vertex_Lock_Position (vertex_index);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// On_Vertex_Drag
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DamageZoneNodeClass::On_Vertex_Drag
|
||||
(
|
||||
int vertex_index,
|
||||
POINT point
|
||||
)
|
||||
{
|
||||
//
|
||||
// Resize the box render object based on the new point
|
||||
//
|
||||
Box3DClass *box = m_PhysObj->Get_Box ();
|
||||
if (::GetKeyState (VK_SHIFT) < 0) {
|
||||
box->Drag_VertexZ (vertex_index, point, m_FirstPoint);
|
||||
} else {
|
||||
box->Drag_VertexXY (vertex_index, point, m_FirstPoint);
|
||||
}
|
||||
|
||||
//
|
||||
// Position the grab handles around ourselves
|
||||
//
|
||||
m_GrabHandles.Position_Around_Node (this);
|
||||
|
||||
//
|
||||
// Update the zone's bounding box
|
||||
//
|
||||
m_Transform = box->Get_Transform ();
|
||||
Update_Game_Obj ();
|
||||
|
||||
//
|
||||
// Cache the size of the box
|
||||
//
|
||||
m_CachedSize = box->Get_Dimensions ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Game_Obj
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DamageZoneNodeClass::Update_Game_Obj (void)
|
||||
{
|
||||
Box3DClass *box = m_PhysObj->Get_Box ();
|
||||
|
||||
//
|
||||
// Update the zone's bounding box
|
||||
//
|
||||
if (box != NULL && m_GameObj != NULL) {
|
||||
Vector3 pos = box->Get_Transform ().Get_Translation ();
|
||||
Vector3 size = box->Get_Dimensions () / 2;
|
||||
|
||||
OBBoxClass obbox;
|
||||
obbox.Center = pos;
|
||||
obbox.Extent = size;
|
||||
obbox.Basis.Set (m_Transform);
|
||||
m_GameObj->Set_Bounding_Box (obbox);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
DamageZoneNodeClass::Save (ChunkSaveClass &csave)
|
||||
{
|
||||
csave.Begin_Chunk (CHUNKID_BASE_CLASS);
|
||||
NodeClass::Save (csave);
|
||||
csave.End_Chunk ();
|
||||
|
||||
csave.Begin_Chunk (CHUNKID_VARIABLES);
|
||||
WRITE_MICRO_CHUNK (csave, VARID_ZONE_SIZE, m_CachedSize);
|
||||
csave.End_Chunk ();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
DamageZoneNodeClass::Load (ChunkLoadClass &cload)
|
||||
{
|
||||
while (cload.Open_Chunk ()) {
|
||||
switch (cload.Cur_Chunk_ID ()) {
|
||||
|
||||
case CHUNKID_BASE_CLASS:
|
||||
NodeClass::Load (cload);
|
||||
break;
|
||||
|
||||
|
||||
case CHUNKID_VARIABLES:
|
||||
{
|
||||
//
|
||||
// Read all the variables from their micro-chunks
|
||||
//
|
||||
while (cload.Open_Micro_Chunk ()) {
|
||||
switch (cload.Cur_Micro_Chunk_ID ()) {
|
||||
|
||||
READ_MICRO_CHUNK (cload, VARID_ZONE_SIZE, m_CachedSize);
|
||||
}
|
||||
|
||||
cload.Close_Micro_Chunk ();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Chunk ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Pre_Export
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DamageZoneNodeClass::Pre_Export (void)
|
||||
{
|
||||
//
|
||||
// Make sure the game object's size and position is up to date
|
||||
//
|
||||
Update_Game_Obj ();
|
||||
|
||||
//
|
||||
// Remove ourselves from the 'system' so we don't get accidentally
|
||||
// saved during the export.
|
||||
//
|
||||
Add_Ref ();
|
||||
if (m_PhysObj != NULL && m_IsInScene) {
|
||||
::Get_Scene_Editor ()->Remove_Object (m_PhysObj);
|
||||
m_GrabHandles.Remove_From_Scene ();
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Post_Export
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DamageZoneNodeClass::Post_Export (void)
|
||||
{
|
||||
//
|
||||
// Put ourselves back into the system
|
||||
//
|
||||
if (m_PhysObj != NULL && m_IsInScene) {
|
||||
::Get_Scene_Editor ()->Add_Dynamic_Object (m_PhysObj);
|
||||
m_GrabHandles.Position_Around_Node (this);
|
||||
}
|
||||
|
||||
Release_Ref ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Destroy_Game_Obj
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DamageZoneNodeClass::Destroy_Game_Obj (void)
|
||||
{
|
||||
if (m_GameObj != NULL) {
|
||||
m_GameObj->Set_Delete_Pending ();
|
||||
m_GameObj = NULL;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create_Game_Obj
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DamageZoneNodeClass::Create_Game_Obj (void)
|
||||
{
|
||||
if (m_GameObj == NULL) {
|
||||
|
||||
//
|
||||
// Get a pointer to the definition that this object uses
|
||||
//
|
||||
DefinitionClass *definition = m_Preset->Get_Definition ();
|
||||
if (definition != NULL) {
|
||||
|
||||
//
|
||||
// Create the game object
|
||||
//
|
||||
m_GameObj = (DamageZoneGameObj *)definition->Create ();
|
||||
|
||||
//
|
||||
// Assign 'hit-test' information to this game object
|
||||
//
|
||||
if (m_GameObj != NULL) {
|
||||
|
||||
//
|
||||
// Update the zone object we embed
|
||||
//
|
||||
Update_Game_Obj ();
|
||||
m_GameObj->Set_ID (m_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Hide
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DamageZoneNodeClass::Hide (bool hide)
|
||||
{
|
||||
m_GrabHandles.Hide (hide);
|
||||
NodeClass::Hide (hide);
|
||||
return ;
|
||||
}
|
||||
227
Code/Tools/LevelEdit/DamageZoneNode.h
Normal file
227
Code/Tools/LevelEdit/DamageZoneNode.h
Normal file
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/DamageZoneNode.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 10/09/00 1:10p $*
|
||||
* *
|
||||
* $Revision:: 3 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __DAMAGE_ZONE_NODE_H
|
||||
#define __DAMAGE_ZONE_NODE_H
|
||||
|
||||
#include "objectnode.h"
|
||||
#include "icons.h"
|
||||
#include "spawn.h"
|
||||
#include "grabhandles.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class PresetClass;
|
||||
class DamageZoneGameObj;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DamageZoneNodeClass
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class DamageZoneNodeClass : public NodeClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////////////
|
||||
DamageZoneNodeClass (PresetClass *preset = NULL);
|
||||
DamageZoneNodeClass (const DamageZoneNodeClass &src);
|
||||
~DamageZoneNodeClass (void);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public operators
|
||||
//////////////////////////////////////////////////////////////
|
||||
const DamageZoneNodeClass &operator= (const DamageZoneNodeClass &src);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// From PersistClass
|
||||
//
|
||||
virtual const PersistFactoryClass & Get_Factory (void) const;
|
||||
virtual bool Save (ChunkSaveClass &csave);
|
||||
virtual bool Load (ChunkLoadClass &cload);
|
||||
|
||||
|
||||
// From NodeClass
|
||||
NodeClass * Clone (void) { return new DamageZoneNodeClass (*this); }
|
||||
void Initialize (void);
|
||||
NODE_TYPE Get_Type (void) const { return NODE_TYPE_DAMAGE_ZONE; }
|
||||
int Get_Icon_Index (void) const { return ZONE_ICON; }
|
||||
PhysClass * Peek_Physics_Obj (void) const;
|
||||
bool Is_Static (void) const { return false; }
|
||||
void Hide (bool hide);
|
||||
|
||||
//
|
||||
// Scene methods
|
||||
//
|
||||
void Add_To_Scene (void);
|
||||
void Remove_From_Scene (void);
|
||||
|
||||
//
|
||||
// Notifications
|
||||
//
|
||||
void On_Rotate (void);
|
||||
void On_Translate (void);
|
||||
void On_Transform (void);
|
||||
|
||||
//
|
||||
// Export methods
|
||||
//
|
||||
void Pre_Export (void);
|
||||
void Post_Export (void);
|
||||
|
||||
//
|
||||
// Zone edit methods
|
||||
//
|
||||
void On_Vertex_Drag_Begin (int vertex_index);
|
||||
void On_Vertex_Drag (int vertex_index, POINT point);
|
||||
|
||||
//
|
||||
// DamageZoneNodeClass specific
|
||||
//
|
||||
Box3DClass * Get_Box (void);
|
||||
//DamageZoneGameObj * Get_Zone_Obj (void) const { return DamageZoneGameObj; }
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
//////////////////////////////////////////////////////////////////
|
||||
void Update_Game_Obj (void);
|
||||
void Create_Game_Obj (void);
|
||||
void Destroy_Game_Obj (void);
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////////////
|
||||
Box3DPhysClass * m_PhysObj;
|
||||
DamageZoneGameObj * m_GameObj;
|
||||
GrabHandlesClass m_GrabHandles;
|
||||
Vector3 m_FirstPoint;
|
||||
Vector3 m_CachedSize;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Peek_Physics_Obj
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline PhysClass *
|
||||
DamageZoneNodeClass::Peek_Physics_Obj (void) const
|
||||
{
|
||||
return m_PhysObj;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Rotate
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
DamageZoneNodeClass::On_Rotate (void)
|
||||
{
|
||||
if (m_IsInScene) {
|
||||
m_GrabHandles.Position_Around_Node (this);
|
||||
}
|
||||
|
||||
Update_Game_Obj ();
|
||||
NodeClass::On_Rotate ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Translate
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
DamageZoneNodeClass::On_Translate (void)
|
||||
{
|
||||
if (m_IsInScene) {
|
||||
m_GrabHandles.Position_Around_Node (this);
|
||||
}
|
||||
|
||||
Update_Game_Obj ();
|
||||
NodeClass::On_Translate ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Transform
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
DamageZoneNodeClass::On_Transform (void)
|
||||
{
|
||||
if (m_IsInScene) {
|
||||
m_GrabHandles.Position_Around_Node (this);
|
||||
}
|
||||
|
||||
Update_Game_Obj ();
|
||||
NodeClass::On_Transform ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Get_Box
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline Box3DClass *
|
||||
DamageZoneNodeClass::Get_Box (void)
|
||||
{
|
||||
Box3DClass *box = NULL;
|
||||
if (m_PhysObj != NULL) {
|
||||
box = m_PhysObj->Get_Box ();
|
||||
}
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
|
||||
#endif //__DAMAGE_ZONE_NODE_H
|
||||
|
||||
BIN
Code/Tools/LevelEdit/DebugE/LevelEdit.pch
Normal file
BIN
Code/Tools/LevelEdit/DebugE/LevelEdit.pch
Normal file
Binary file not shown.
BIN
Code/Tools/LevelEdit/DebugE/LevelEdit.res
Normal file
BIN
Code/Tools/LevelEdit/DebugE/LevelEdit.res
Normal file
Binary file not shown.
BIN
Code/Tools/LevelEdit/DebugE/VSS.tlb
Normal file
BIN
Code/Tools/LevelEdit/DebugE/VSS.tlb
Normal file
Binary file not shown.
109
Code/Tools/LevelEdit/DefinitionParameter.h
Normal file
109
Code/Tools/LevelEdit/DefinitionParameter.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/DefinitionParameter.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 6/12/00 6:29p $*
|
||||
* *
|
||||
* $Revision:: 2 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __DEFINITION_PARAMETER_H
|
||||
#define __DEFINITION_PARAMETER_H
|
||||
|
||||
#include "refcount.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class DefinitionClass;
|
||||
class ParameterClass;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DefinitionParameterClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class DefinitionParameterClass : public RefCountClass
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Public constructors/destructor
|
||||
////////////////////////////////////////////////////////////
|
||||
DefinitionParameterClass (void)
|
||||
: m_Definition (NULL),
|
||||
m_Parameter (NULL),
|
||||
m_Index (0),
|
||||
m_Parent (NULL) {}
|
||||
|
||||
virtual ~DefinitionParameterClass (void) { MEMBER_RELEASE (m_Parent); }
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Parameter info
|
||||
//
|
||||
DefinitionClass * Get_Definition (void) const { return m_Definition; }
|
||||
ParameterClass * Get_Parameter (void) const { return m_Parameter; }
|
||||
int Get_Index (void) const { return m_Index; }
|
||||
void Set_Definition (DefinitionClass *def) { m_Definition = def; }
|
||||
void Set_Parameter (ParameterClass *param) { m_Parameter = param; }
|
||||
void Set_Index (int index) { m_Index = index; }
|
||||
|
||||
//
|
||||
// Parent info
|
||||
//
|
||||
DefinitionParameterClass * Peek_Parent (void) const { return m_Parent; }
|
||||
void Set_Parent (DefinitionParameterClass * parent) { MEMBER_ADD (m_Parent, parent); }
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
////////////////////////////////////////////////////////////
|
||||
DefinitionClass * m_Definition;
|
||||
ParameterClass * m_Parameter;
|
||||
int m_Index;
|
||||
|
||||
DefinitionParameterClass * m_Parent;
|
||||
};
|
||||
|
||||
|
||||
#endif //__DEFINITION_PARAMETER_H
|
||||
458
Code/Tools/LevelEdit/DefinitionUtils.cpp
Normal file
458
Code/Tools/LevelEdit/DefinitionUtils.cpp
Normal file
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/DefinitionUtils.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 8/24/01 12:15p $*
|
||||
* *
|
||||
* $Revision:: 11 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "definition.h"
|
||||
#include "definitionmgr.h"
|
||||
#include "definitionfactorymgr.h"
|
||||
#include "definitionfactory.h"
|
||||
#include "phys.h"
|
||||
#include "Utils.h"
|
||||
#include "physicalgameobj.h"
|
||||
#include "tiledefinition.h"
|
||||
#include "combatchunkid.h"
|
||||
#include "dialogue.h"
|
||||
#include "soldier.h"
|
||||
#include "presetmgr.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create_Physics_Definition
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
DefinitionClass *
|
||||
Create_Physics_Definition (LPCTSTR base_class_name, bool is_temp)
|
||||
{
|
||||
DefinitionClass *definition = NULL;
|
||||
|
||||
//
|
||||
// Loop over all the factories, until we've found one that matches
|
||||
// the base we are looking for
|
||||
//
|
||||
DefinitionFactoryClass *factory = NULL;
|
||||
for ( factory = DefinitionFactoryMgrClass::Get_First (CLASSID_PHYSICS);
|
||||
factory != NULL && definition == NULL;
|
||||
factory = DefinitionFactoryMgrClass::Get_Next (factory, CLASSID_PHYSICS))
|
||||
{
|
||||
//
|
||||
// Instantiate a definition
|
||||
//
|
||||
definition = factory->Create ();
|
||||
if (definition != NULL) {
|
||||
|
||||
//
|
||||
// Is this the definition 'type' we want?
|
||||
//
|
||||
if (((PhysDefClass *)definition)->Is_Type (base_class_name) == false) {
|
||||
SAFE_DELETE (definition);
|
||||
} else {
|
||||
|
||||
if (is_temp) {
|
||||
definition->Set_ID (::Get_Next_Temp_ID ());
|
||||
} else {
|
||||
definition->Set_ID (DefinitionMgrClass::Get_New_ID (definition->Get_Class_ID ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create_Definition
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
DefinitionClass *
|
||||
Create_Definition (int class_id, bool is_temp)
|
||||
{
|
||||
DefinitionClass *definition = NULL;
|
||||
|
||||
//
|
||||
// Attempt to find a factory for this definition
|
||||
//
|
||||
DefinitionFactoryClass *factory = DefinitionFactoryMgrClass::Find_Factory (class_id);
|
||||
if (factory != NULL) {
|
||||
|
||||
//
|
||||
// Create a new instance of the definition
|
||||
//
|
||||
definition = factory->Create ();
|
||||
ASSERT (definition != NULL);
|
||||
|
||||
//
|
||||
// Give the definition a new id
|
||||
//
|
||||
if (is_temp) {
|
||||
definition->Set_ID (::Get_Next_Temp_ID ());
|
||||
} else {
|
||||
definition->Set_ID (DefinitionMgrClass::Get_New_ID (definition->Get_Class_ID ()));
|
||||
}
|
||||
}
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copy_Definition
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Copy_Definition (DefinitionClass *src_def, DefinitionClass *dest_def, bool is_temp)
|
||||
{
|
||||
SANITY_CHECK(src_def != NULL && dest_def != NULL) {
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure the definitions are of the same type.
|
||||
//
|
||||
uint32 class_id1 = dest_def->Get_Class_ID ();
|
||||
uint32 class_id2 = src_def->Get_Class_ID ();
|
||||
if (class_id1 == class_id2) {
|
||||
|
||||
//
|
||||
// Loop over all the parameters contained in the definitions
|
||||
//
|
||||
int count = dest_def->Get_Parameter_Count ();
|
||||
for (int index = 0; index < count; index ++) {
|
||||
ParameterClass *dest_param = dest_def->Lock_Parameter (index);
|
||||
ParameterClass *src_param = src_def->Lock_Parameter (index);
|
||||
|
||||
if ((dest_param != NULL) && (src_param != NULL)) {
|
||||
|
||||
//
|
||||
// Is this parameter type a 'phys-def' parameter?
|
||||
///If it is, we need to make sure we don't copy the phys-def ID value,
|
||||
// we need to copy the properties of the phys-definition that the parameter
|
||||
// points to.
|
||||
//
|
||||
if (dest_param->Get_Type () == ParameterClass::TYPE_MODELDEFINITIONID) {
|
||||
|
||||
int dest_def_id = ((ModelDefParameterClass *)dest_param)->Get_Value ();
|
||||
int src_def_id = ((ModelDefParameterClass *)src_param)->Get_Value ();
|
||||
DefinitionClass *dest_phys_def = DefinitionMgrClass::Find_Definition (dest_def_id, false);
|
||||
DefinitionClass *src_phys_def = DefinitionMgrClass::Find_Definition (src_def_id, false);
|
||||
|
||||
//
|
||||
// Create a new phys-def for the destination param
|
||||
//
|
||||
if (dest_phys_def == NULL && src_phys_def != NULL) {
|
||||
dest_phys_def = ::Create_Definition (src_phys_def->Get_Class_ID (), is_temp);
|
||||
if (dest_phys_def != NULL) {
|
||||
((ModelDefParameterClass *)dest_param)->Set_Value (dest_phys_def->Get_ID ());
|
||||
DefinitionMgrClass::Register_Definition (dest_phys_def);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If both the src and dest params point to valid physics-definitions,
|
||||
// then, copy the properties from the src to the dest (recursion)
|
||||
//
|
||||
if (dest_phys_def != NULL && src_phys_def != NULL) {
|
||||
::Copy_Definition (src_phys_def, dest_phys_def, is_temp);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
//
|
||||
// Copy the parameter value
|
||||
//
|
||||
dest_param->Copy_Value (*src_param);
|
||||
}
|
||||
}
|
||||
|
||||
dest_def->Unlock_Parameter (index);
|
||||
src_def->Unlock_Parameter (index);
|
||||
}
|
||||
|
||||
//
|
||||
// Should we copy the dialogue list as well?
|
||||
//
|
||||
if (class_id1 == CLASSID_GAME_OBJECT_DEF_SOLDIER) {
|
||||
|
||||
SoldierGameObjDef *src_soldier = reinterpret_cast<SoldierGameObjDef *> (src_def);
|
||||
SoldierGameObjDef *dest_soldier = reinterpret_cast<SoldierGameObjDef *> (dest_def);
|
||||
|
||||
DialogueClass *src_list = src_soldier->Get_Dialog_List ();
|
||||
DialogueClass *dest_list = dest_soldier->Get_Dialog_List ();
|
||||
|
||||
//
|
||||
// Copy the settings from the base to the derived...
|
||||
//
|
||||
for (int index = 0; index < DIALOG_MAX; index ++) {
|
||||
dest_list[index] = src_list[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Build_Embedded_Definition_List
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Build_Embedded_Definition_List (DEFINITION_LIST &list, DefinitionClass *parent)
|
||||
{
|
||||
SANITY_CHECK(parent != NULL) {
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop over all the parameters of this definition
|
||||
//
|
||||
int count = parent->Get_Parameter_Count ();
|
||||
for (int index = 0; index < count; index ++) {
|
||||
ParameterClass *param = parent->Lock_Parameter (index);
|
||||
|
||||
//
|
||||
// If this is the paramter type we are looking for, get the
|
||||
// definition pointer from it and return the pointer to the caller
|
||||
//
|
||||
if (param != NULL ) {
|
||||
|
||||
if (param->Get_Type () == ParameterClass::TYPE_MODELDEFINITIONID) {
|
||||
int def_id = ((ModelDefParameterClass *)param)->Get_Value ();
|
||||
DefinitionClass *definition = DefinitionMgrClass::Find_Definition (def_id, false);
|
||||
if (definition != NULL) {
|
||||
list.Add (definition);
|
||||
|
||||
//
|
||||
// Now recurse into the model definition
|
||||
//
|
||||
Build_Embedded_Definition_List (list, definition);
|
||||
}
|
||||
|
||||
} else if (param->Get_Type () == ParameterClass::TYPE_PHYSDEFINITIONID) {
|
||||
int def_id = ((PhysDefParameterClass *)param)->Get_Value ();
|
||||
DefinitionClass *definition = DefinitionMgrClass::Find_Definition (def_id, false);
|
||||
if (definition != NULL) {
|
||||
list.Add (definition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parent->Unlock_Parameter (index);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Fix_Embedded_Definition_IDs
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
Fix_Embedded_Definition_IDs (DefinitionClass *parent)
|
||||
{
|
||||
SANITY_CHECK(parent != NULL) {
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Loop over all the parameters of this definition
|
||||
//
|
||||
int count = parent->Get_Parameter_Count ();
|
||||
for (int index = 0; index < count; index ++) {
|
||||
ParameterClass *param = parent->Lock_Parameter (index);
|
||||
|
||||
//
|
||||
// If this is the paramter type we are looking for, get the
|
||||
// definition pointer from it and return the pointer to the caller
|
||||
//
|
||||
if (param != NULL ) {
|
||||
|
||||
if (param->Get_Type () == ParameterClass::TYPE_MODELDEFINITIONID) {
|
||||
int def_id = ((ModelDefParameterClass *)param)->Get_Value ();
|
||||
DefinitionClass *definition = DefinitionMgrClass::Find_Definition (def_id, false);
|
||||
if (definition != NULL) {
|
||||
|
||||
//
|
||||
// Give this definition a new ID if necessary
|
||||
//
|
||||
if (definition->Get_ID () >= TEMP_DEF_ID_START) {
|
||||
definition->Set_ID (DefinitionMgrClass::Get_New_ID (definition->Get_Class_ID ()));
|
||||
((ModelDefParameterClass *)param)->Set_Value (definition->Get_ID ());
|
||||
}
|
||||
|
||||
//
|
||||
// Now recurse into the model definition
|
||||
//
|
||||
Fix_Embedded_Definition_IDs (definition);
|
||||
}
|
||||
|
||||
} else if (param->Get_Type () == ParameterClass::TYPE_PHYSDEFINITIONID) {
|
||||
|
||||
int def_id = ((PhysDefParameterClass *)param)->Get_Value ();
|
||||
DefinitionClass *definition = DefinitionMgrClass::Find_Definition (def_id, false);
|
||||
if (definition != NULL) {
|
||||
|
||||
//
|
||||
// Give this definition a new ID if necessary
|
||||
//
|
||||
if (definition->Get_ID () >= TEMP_DEF_ID_START) {
|
||||
definition->Set_ID (DefinitionMgrClass::Get_New_ID (definition->Get_Class_ID ()));
|
||||
((PhysDefParameterClass *)param)->Set_Value (definition->Get_ID ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parent->Unlock_Parameter (index);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Find_Physics_Definition
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
DefinitionClass *
|
||||
Find_Physics_Definition (DefinitionClass *parent)
|
||||
{
|
||||
SANITY_CHECK(parent != NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DefinitionClass *definition = NULL;
|
||||
|
||||
//
|
||||
// Loop over all the parameters of this definition
|
||||
//
|
||||
int count = parent->Get_Parameter_Count ();
|
||||
for (int index = 0; index < count && definition == NULL; index ++) {
|
||||
ParameterClass *param = parent->Lock_Parameter (index);
|
||||
|
||||
//
|
||||
// If this is the paramter type we are looking for, get the
|
||||
// definition pointer from it and return the pointer to the caller
|
||||
//
|
||||
if (param != NULL && param->Get_Type () == ParameterClass::TYPE_MODELDEFINITIONID) {
|
||||
int def_id = ((ModelDefParameterClass *)param)->Get_Value ();
|
||||
definition = DefinitionMgrClass::Find_Definition (def_id, false);
|
||||
}
|
||||
|
||||
parent->Unlock_Parameter (index);
|
||||
}
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Phys_Obj_From_Definition
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
PhysClass *
|
||||
Get_Phys_Obj_From_Definition (DefinitionClass *definition)
|
||||
{
|
||||
SANITY_CHECK (definition != NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PhysClass *retval = NULL;
|
||||
|
||||
//
|
||||
// What type of object will this definition create?
|
||||
//
|
||||
int class_id = definition->Get_Class_ID ();
|
||||
switch (::SuperClassID_From_ClassID (class_id))
|
||||
{
|
||||
/*case CLASSID_TERRAIN:
|
||||
{
|
||||
//
|
||||
// Create the terrain and pull out its physics object
|
||||
//
|
||||
TerrainNodeClass *node = (TerrainNodeClass *)definition->Create ();
|
||||
if (node != NULL) {
|
||||
MEMBER_ADD (retval, node->Peek_Physics_Obj ());
|
||||
MEMBER_RELEASE (node);
|
||||
}
|
||||
}
|
||||
break;*/
|
||||
|
||||
case CLASSID_TILE:
|
||||
{
|
||||
//
|
||||
// Create the tile and pull out its physics object
|
||||
//
|
||||
int phys_def_id = ((TileDefinitionClass *)definition)->Get_Phys_Def_ID ();
|
||||
if (phys_def_id != 0) {
|
||||
DefinitionClass *phys_def = DefinitionMgrClass::Find_Definition (phys_def_id, false);
|
||||
if (phys_def != NULL) {
|
||||
retval = (PhysClass *)phys_def->Create ();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CLASSID_GAME_OBJECTS:
|
||||
{
|
||||
//
|
||||
// Create the game object and pull out its physics object
|
||||
//
|
||||
BaseGameObj *game_obj = (BaseGameObj *)definition->Create ();
|
||||
if (game_obj != NULL) {
|
||||
PhysicalGameObj *phys_game_obj = game_obj->As_PhysicalGameObj ();
|
||||
if (phys_game_obj != NULL) {
|
||||
MEMBER_ADD (retval, phys_game_obj->Peek_Physical_Object ());
|
||||
}
|
||||
|
||||
game_obj->Set_Delete_Pending ();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
68
Code/Tools/LevelEdit/DefinitionUtils.h
Normal file
68
Code/Tools/LevelEdit/DefinitionUtils.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/DefinitionUtils.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 9/20/00 7:40p $*
|
||||
* *
|
||||
* $Revision:: 6 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __DEFINITION_UTILS_H
|
||||
#define __DEFINITION_UTILS_H
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
class DefinitionClass;
|
||||
class PhysClass;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Prototypes
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
DefinitionClass * Create_Physics_Definition (LPCTSTR base_class_name, bool is_temp = false);
|
||||
DefinitionClass * Create_Definition (int class_id);
|
||||
void Copy_Definition (DefinitionClass *src, DefinitionClass *dest, bool is_temp);
|
||||
DefinitionClass * Find_Physics_Definition (DefinitionClass *parent);
|
||||
|
||||
PhysClass * Get_Phys_Obj_From_Definition (DefinitionClass *definition);
|
||||
|
||||
void Build_Embedded_Definition_List (DEFINITION_LIST &list, DefinitionClass *parent);
|
||||
void Fix_Embedded_Definition_IDs (DefinitionClass *parent);
|
||||
|
||||
|
||||
#endif //__DEFINITION_UTILS_H
|
||||
251
Code/Tools/LevelEdit/DeviceSelectionDialog.cpp
Normal file
251
Code/Tools/LevelEdit/DeviceSelectionDialog.cpp
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// DeviceSelectionDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "leveledit.h"
|
||||
#include "deviceselectiondialog.h"
|
||||
#include "ww3d.h"
|
||||
#include "resource.h"
|
||||
#include "utils.h"
|
||||
#include "rddesc.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CDeviceSelectionDialog dialog
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CDeviceSelectionDialog
|
||||
//
|
||||
CDeviceSelectionDialog::CDeviceSelectionDialog
|
||||
(
|
||||
BOOL bLookupCachedInfo,
|
||||
CWnd* pParent /*=NULL*/
|
||||
)
|
||||
: m_iDeviceIndex (1),
|
||||
m_iBitsPerPixel (16),
|
||||
m_bLookupCachedInfo (bLookupCachedInfo),
|
||||
CDialog(CDeviceSelectionDialog::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(CDeviceSelectionDialog)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
void
|
||||
CDeviceSelectionDialog::DoDataExchange (CDataExchange* pDX)
|
||||
{
|
||||
// Allow the base class to process this message
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(CDeviceSelectionDialog)
|
||||
DDX_Control(pDX, IDC_RENDER_DEVICE_COMBO, m_deviceListComboBox);
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(CDeviceSelectionDialog, CDialog)
|
||||
//{{AFX_MSG_MAP(CDeviceSelectionDialog)
|
||||
ON_CBN_SELCHANGE(IDC_RENDER_DEVICE_COMBO, OnSelchangeRenderDeviceCombo)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CDeviceSelectionDialog message handlers
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
BOOL
|
||||
CDeviceSelectionDialog::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
//
|
||||
// Loop through all the devices and add them to the combobox
|
||||
//
|
||||
int device_count = WW3D::Get_Render_Device_Count ();
|
||||
int selected_index = 0;
|
||||
for (int index = 0; index < device_count; index ++) {
|
||||
|
||||
//
|
||||
// Add this device to the combobox
|
||||
//
|
||||
const char *name = WW3D::Get_Render_Device_Name(index);
|
||||
int combo_index = m_deviceListComboBox.InsertString (index, name);
|
||||
if (m_DriverName.CompareNoCase (name) == 0) {
|
||||
selected_index = combo_index;
|
||||
}
|
||||
|
||||
// Associate the index of this device with the item we just inserted
|
||||
m_deviceListComboBox.SetItemData (combo_index, index);
|
||||
}
|
||||
|
||||
// Check the '16bpp' radio by default
|
||||
SendDlgItemMessage (IDC_COLORDEPTH_16, BM_SETCHECK, (WPARAM)TRUE);
|
||||
|
||||
// Force the first entry in the combobox to be selected.
|
||||
//m_deviceListComboBox.SetCurSel (0);
|
||||
m_deviceListComboBox.SetCurSel (selected_index);
|
||||
|
||||
// Update the static controls on the dialog to reflect the device
|
||||
UpdateDeviceDescription ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnSelchangeRenderDeviceCombo
|
||||
//
|
||||
void
|
||||
CDeviceSelectionDialog::OnSelchangeRenderDeviceCombo (void)
|
||||
{
|
||||
int index = m_deviceListComboBox.GetCurSel ();
|
||||
if (index != CB_ERR) {
|
||||
//WW3D::Set_Render_Device ();
|
||||
|
||||
// Update the static controls with the information from the device
|
||||
UpdateDeviceDescription ();
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UpdateDeviceDescription
|
||||
//
|
||||
void
|
||||
CDeviceSelectionDialog::UpdateDeviceDescription (void)
|
||||
{
|
||||
const RenderDeviceDescClass &device_desc = WW3D::Get_Render_Device_Desc ();
|
||||
|
||||
//
|
||||
// Reload the static text controls on the dialog
|
||||
//
|
||||
SetDlgItemText (IDC_DRIVER_NAME, m_DriverName);
|
||||
SetDlgItemText (IDC_DEVICE_NAME_STATIC, device_desc.Get_Device_Name());
|
||||
SetDlgItemText (IDC_DEVICE_VENDOR_STATIC, device_desc.Get_Device_Vendor());
|
||||
SetDlgItemText (IDC_DEVICE_PLATFORM_STATIC, device_desc.Get_Device_Platform());
|
||||
SetDlgItemText (IDC_DRIVER_NAME_STATIC, device_desc.Get_Driver_Name());
|
||||
SetDlgItemText (IDC_DRIVER_VENDOR_STATIC, device_desc.Get_Driver_Vendor());
|
||||
SetDlgItemText (IDC_DRIVER_VERSION_STATIC, device_desc.Get_Driver_Version());
|
||||
SetDlgItemText (IDC_HARDWARE_NAME_STATIC, device_desc.Get_Hardware_Name());
|
||||
SetDlgItemText (IDC_HARDWARE_VENDOR_STATIC, device_desc.Get_Hardware_Vendor());
|
||||
SetDlgItemText (IDC_HARDWARE_CHIPSET_STATIC, device_desc.Get_Hardware_Chipset());
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOK
|
||||
//
|
||||
void
|
||||
CDeviceSelectionDialog::OnOK (void)
|
||||
{
|
||||
// Ask the combobox for its current selection
|
||||
m_iDeviceIndex = m_deviceListComboBox.GetItemData (m_deviceListComboBox.GetCurSel ());
|
||||
m_iBitsPerPixel = (SendDlgItemMessage (IDC_COLORDEPTH_16, BM_GETCHECK) == TRUE) ? 16 : 24;
|
||||
|
||||
// Get the device name of the currently selected device
|
||||
CString stringDeviceName;
|
||||
m_deviceListComboBox.GetLBText (m_deviceListComboBox.GetCurSel (), stringDeviceName);
|
||||
m_DriverName = stringDeviceName;
|
||||
|
||||
// Cache this information in the registry
|
||||
theApp.WriteProfileString ("Config", "DeviceName", stringDeviceName);
|
||||
theApp.WriteProfileInt ("Config", "DeviceBitsPerPix", m_iBitsPerPixel);
|
||||
|
||||
// Allow the base class to process this message
|
||||
CDialog::OnOK();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoModal
|
||||
//
|
||||
int
|
||||
CDeviceSelectionDialog::DoModal (void)
|
||||
{
|
||||
BOOL bFoundDevice = FALSE;
|
||||
int iReturn = IDOK;
|
||||
|
||||
// Get the name of the last used device driver from the registry
|
||||
m_DriverName = theApp.GetProfileString ("Config", "DeviceName");
|
||||
if (m_bLookupCachedInfo &&
|
||||
(m_DriverName.GetLength () > 0) &&
|
||||
!(::GetKeyState (VK_SHIFT) & 0xF000)) {
|
||||
|
||||
if (Is_Silent_Mode ()) {
|
||||
m_DriverName = "Software2(0)";
|
||||
}
|
||||
|
||||
//
|
||||
// Loop through all the devices and see if we can find the right one
|
||||
//
|
||||
int device_count = WW3D::Get_Render_Device_Count ();
|
||||
for (int index = 0; (index < device_count) && !bFoundDevice; index ++) {
|
||||
|
||||
//
|
||||
// Is this the device we are looking for?
|
||||
//
|
||||
const char *name = WW3D::Get_Render_Device_Name (index);
|
||||
if (m_DriverName.CompareNoCase (name) == 0) {
|
||||
|
||||
//
|
||||
// Set the internal device information to simulate 'showing' the dialog
|
||||
//
|
||||
m_iDeviceIndex = index;
|
||||
m_iBitsPerPixel = theApp.GetProfileInt ("Config", "DeviceBitsPerPix", 16);
|
||||
|
||||
// Found it!
|
||||
bFoundDevice = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show the dialog and allow the user to select the device
|
||||
if (bFoundDevice == FALSE) {
|
||||
iReturn = CDialog::DoModal ();
|
||||
}
|
||||
|
||||
// Return the integer return code
|
||||
return iReturn;
|
||||
}
|
||||
90
Code/Tools/LevelEdit/DeviceSelectionDialog.h
Normal file
90
Code/Tools/LevelEdit/DeviceSelectionDialog.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_DEVICESELECTIONDIALOG_H__49E2DFF9_5D3F_11D2_9FC6_00104B791122__INCLUDED_)
|
||||
#define AFX_DEVICESELECTIONDIALOG_H__49E2DFF9_5D3F_11D2_9FC6_00104B791122__INCLUDED_
|
||||
|
||||
#if _MSC_VER >= 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER >= 1000
|
||||
// DeviceSelectionDialog.h : header file
|
||||
//
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CDeviceSelectionDialog dialog
|
||||
|
||||
class CDeviceSelectionDialog : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
CDeviceSelectionDialog(BOOL bLookupCachedInfo = TRUE, CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(CDeviceSelectionDialog)
|
||||
enum { IDD = IDD_RENDER_DEVICE_SELECTOR };
|
||||
CComboBox m_deviceListComboBox;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CDeviceSelectionDialog)
|
||||
public:
|
||||
virtual int DoModal();
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(CDeviceSelectionDialog)
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnSelchangeRenderDeviceCombo();
|
||||
virtual void OnOK();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
// Return the selected device index
|
||||
int GetDeviceIndex () const
|
||||
{ return m_iDeviceIndex; }
|
||||
|
||||
// Return the selected bits per pixel
|
||||
int GetBitsPerPixel () const
|
||||
{ return m_iBitsPerPixel; }
|
||||
|
||||
const CString &GetDriverName () const
|
||||
{ return m_DriverName; }
|
||||
|
||||
protected:
|
||||
void UpdateDeviceDescription (void);
|
||||
|
||||
private:
|
||||
BOOL m_bLookupCachedInfo;
|
||||
int m_iDeviceIndex;
|
||||
int m_iBitsPerPixel;
|
||||
CString m_DriverName;
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_DEVICESELECTIONDIALOG_H__49E2DFF9_5D3F_11D2_9FC6_00104B791122__INCLUDED_)
|
||||
147
Code/Tools/LevelEdit/DialogToolbar.cpp
Normal file
147
Code/Tools/LevelEdit/DialogToolbar.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/DialogToolbar.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 2/17/99 2:02p $*
|
||||
* *
|
||||
* $Revision:: 1 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "StdAfx.H"
|
||||
#include "DialogToolbar.H"
|
||||
#include "AfxPriv.H"
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(DialogToolbarClass, CToolBar)
|
||||
//{{AFX_MSG_MAP(DialogToolbarClass)
|
||||
ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
|
||||
ON_MESSAGE_VOID(WM_INITIALUPDATE, OnInitialUpdate)
|
||||
ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnNeedToolTipText)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
DialogToolbarClass::DialogToolbarClass (void)
|
||||
: CToolBar ()
|
||||
{
|
||||
//{{AFX_DATA_INIT(DialogToolbarClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
void DialogToolbarClass::AssertValid() const
|
||||
{
|
||||
CToolBar::AssertValid();
|
||||
}
|
||||
|
||||
void DialogToolbarClass::Dump(CDumpContext& dc) const
|
||||
{
|
||||
CToolBar::Dump(dc);
|
||||
}
|
||||
#endif //_DEBUG
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Enable_Button
|
||||
//
|
||||
void
|
||||
DialogToolbarClass::Enable_Button
|
||||
(
|
||||
int id,
|
||||
bool benable
|
||||
)
|
||||
{
|
||||
// Get the button's style (we enable by using a style bit)
|
||||
int index = CommandToIndex (id);
|
||||
UINT style = GetButtonStyle (index) & (~TBBS_DISABLED);
|
||||
|
||||
// If we are disabling the button, set the
|
||||
// disabled style bit.
|
||||
if (benable == false) {
|
||||
style |= TBBS_DISABLED;
|
||||
style &= ~TBBS_PRESSED;
|
||||
}
|
||||
|
||||
// If the button isn't a separator, then modify its style
|
||||
if (!(style & TBBS_SEPARATOR)) {
|
||||
SetButtonStyle (index, style);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnIdleUpdateCmdUI
|
||||
//
|
||||
LRESULT
|
||||
DialogToolbarClass::OnIdleUpdateCmdUI (WPARAM, LPARAM)
|
||||
{
|
||||
return 0L;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitialUpdate
|
||||
//
|
||||
void
|
||||
DialogToolbarClass::OnInitialUpdate (void)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnNotify
|
||||
//
|
||||
BOOL
|
||||
DialogToolbarClass::OnNeedToolTipText
|
||||
(
|
||||
UINT id,
|
||||
NMHDR *pTTTStruct,
|
||||
LRESULT *pResult
|
||||
)
|
||||
{
|
||||
if (pTTTStruct->code == TTN_NEEDTEXTA) {
|
||||
|
||||
TOOLTIPTEXTA *ptooltip_info = (TOOLTIPTEXTA*)pTTTStruct;
|
||||
::lstrcpy (ptooltip_info->szText, "test");
|
||||
}
|
||||
|
||||
(*pResult) = 0L;
|
||||
return TRUE;
|
||||
}
|
||||
105
Code/Tools/LevelEdit/DialogToolbar.h
Normal file
105
Code/Tools/LevelEdit/DialogToolbar.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/DialogToolbar.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 2/17/99 2:02p $*
|
||||
* *
|
||||
* $Revision:: 1 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __DIALOGTOOLBAR_H
|
||||
#define __DIALOGTOOLBAR_H
|
||||
|
||||
#include "Resource.H"
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DialogToolbarClass
|
||||
//
|
||||
class DialogToolbarClass : public CToolBar
|
||||
{
|
||||
public:
|
||||
DialogToolbarClass (void);
|
||||
virtual ~DialogToolbarClass (void) {}
|
||||
|
||||
// Form Data
|
||||
public:
|
||||
//{{AFX_DATA(DialogToolbarClass)
|
||||
//}}AFX_DATA
|
||||
|
||||
// Attributes
|
||||
public:
|
||||
|
||||
// Operations
|
||||
public:
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(DialogToolbarClass)
|
||||
protected:
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
#ifdef _DEBUG
|
||||
virtual void AssertValid() const;
|
||||
virtual void Dump(CDumpContext& dc) const;
|
||||
#endif
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(DialogToolbarClass)
|
||||
afx_msg LRESULT OnIdleUpdateCmdUI(WPARAM wParam, LPARAM lParam);
|
||||
afx_msg void OnInitialUpdate();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
//virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
|
||||
BOOL OnNeedToolTipText (UINT id, NMHDR *pTTTStruct, LRESULT *pResult);
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// Public methods
|
||||
//
|
||||
void Enable_Button (int id, bool benable = true);
|
||||
};
|
||||
|
||||
|
||||
#endif //__DIALOGTOOLBAR_H
|
||||
|
||||
170
Code/Tools/LevelEdit/DockableForm.cpp
Normal file
170
Code/Tools/LevelEdit/DockableForm.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// DockableFormClass.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "DockableForm.H"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DockableFormClass
|
||||
//
|
||||
DockableFormClass::DockableFormClass (UINT nIDTemplate)
|
||||
: m_uiTemplateID (nIDTemplate),
|
||||
CWnd ()
|
||||
{
|
||||
//{{AFX_DATA_INIT(DockableFormClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~DockableFormClass
|
||||
//
|
||||
DockableFormClass::~DockableFormClass (void)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
BEGIN_MESSAGE_MAP(DockableFormClass, CWnd)
|
||||
//{{AFX_MSG_MAP(DockableFormClass)
|
||||
ON_WM_CREATE()
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create
|
||||
//
|
||||
BOOL
|
||||
DockableFormClass::Create
|
||||
(
|
||||
LPCTSTR /*lpszClassName*/,
|
||||
LPCTSTR /*lpszWindowName*/,
|
||||
DWORD dwRequestedStyle,
|
||||
const RECT& rect,
|
||||
CWnd* pParentWnd,
|
||||
UINT nID,
|
||||
CCreateContext* pContext
|
||||
)
|
||||
{
|
||||
ASSERT(pParentWnd != NULL);
|
||||
|
||||
// call PreCreateWindow to get prefered extended style
|
||||
CREATESTRUCT cs; memset(&cs, 0, sizeof(CREATESTRUCT));
|
||||
if (dwRequestedStyle == 0) {
|
||||
dwRequestedStyle = AFX_WS_DEFAULT_VIEW;
|
||||
}
|
||||
cs.style = dwRequestedStyle;
|
||||
if (!PreCreateWindow(cs)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// create a modeless dialog
|
||||
if (!CreateDlg(MAKEINTRESOURCE (m_uiTemplateID), pParentWnd)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ExecuteDlgInit(MAKEINTRESOURCE (m_uiTemplateID));
|
||||
|
||||
::SetWindowLong (m_hWnd, GWL_STYLE, ::GetWindowLong (m_hWnd, GWL_STYLE) & (~WS_CAPTION));
|
||||
|
||||
|
||||
SetDlgCtrlID(nID);
|
||||
|
||||
GetWindowRect (m_rectForm);
|
||||
|
||||
// force the size requested
|
||||
SetWindowPos(NULL, rect.left, rect.top,
|
||||
rect.right - rect.left, rect.bottom - rect.top,
|
||||
SWP_NOZORDER|SWP_NOACTIVATE);
|
||||
|
||||
// make visible if requested
|
||||
if (dwRequestedStyle & WS_VISIBLE) {
|
||||
ShowWindow(SW_NORMAL);
|
||||
}
|
||||
|
||||
// To support dynamic data exchange...
|
||||
UpdateData (FALSE);
|
||||
HandleInitDialog ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnCreate
|
||||
//
|
||||
int
|
||||
DockableFormClass::OnCreate (LPCREATESTRUCT lpCreateStruct)
|
||||
{
|
||||
// Allow the base class to process this message
|
||||
if (CWnd::OnCreate(lpCreateStruct) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// we use the style from the template - but make sure that
|
||||
// the WS_BORDER bit is correct
|
||||
// the WS_BORDER bit will be whatever is in dwRequestedStyle
|
||||
ModifyStyle(WS_BORDER|WS_CAPTION, lpCreateStruct->style & (WS_BORDER|WS_CAPTION));
|
||||
ModifyStyleEx(WS_EX_CLIENTEDGE, lpCreateStruct->dwExStyle & WS_EX_CLIENTEDGE);
|
||||
|
||||
// initialize controls etc
|
||||
/*if (!ExecuteDlgInit(MAKEINTRESOURCE (m_uiTemplateID))) {
|
||||
return -1;
|
||||
}*/
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WindowProc
|
||||
//
|
||||
LRESULT
|
||||
DockableFormClass::WindowProc
|
||||
(
|
||||
UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam
|
||||
)
|
||||
{
|
||||
// Is this the message we are expecting?
|
||||
if (message == WM_SHOWWINDOW) {
|
||||
|
||||
// Make sure the controls reflect the current state when we are
|
||||
// shown
|
||||
if ((BOOL)wParam) {
|
||||
//Update_Controls ();
|
||||
}
|
||||
}
|
||||
|
||||
// Allow the base class to process this message
|
||||
return CWnd::WindowProc(message, wParam, lParam);
|
||||
}
|
||||
108
Code/Tools/LevelEdit/DockableForm.h
Normal file
108
Code/Tools/LevelEdit/DockableForm.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_DOCKABLEFORMCLASS_H__53843321_66CC_11D2_8DDF_00104B6FD9E3__INCLUDED_)
|
||||
#define AFX_DOCKABLEFORMCLASS_H__53843321_66CC_11D2_8DDF_00104B6FD9E3__INCLUDED_
|
||||
|
||||
#if _MSC_VER >= 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER >= 1000
|
||||
// DockableFormClass.h : header file
|
||||
//
|
||||
|
||||
|
||||
#ifndef __AFXEXT_H__
|
||||
#include <afxext.h>
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DockableFormClass form view
|
||||
//
|
||||
class DockableFormClass : public CWnd
|
||||
{
|
||||
public:
|
||||
DockableFormClass (UINT nIDTemplate);
|
||||
virtual ~DockableFormClass ();
|
||||
|
||||
|
||||
// Attributes
|
||||
public:
|
||||
|
||||
// Operations
|
||||
public:
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(DockableFormClass)
|
||||
protected:
|
||||
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(DockableFormClass)
|
||||
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Protected methods
|
||||
//
|
||||
BOOL Create(LPCTSTR /*lpszClassName*/, LPCTSTR /*lpszWindowName*/,
|
||||
DWORD dwRequestedStyle, const RECT& rect, CWnd* pParentWnd, UINT nID,
|
||||
CCreateContext* pContext);
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Public Methods
|
||||
//
|
||||
BOOL Create (CWnd *pCParentWnd, UINT uiID) { return Create (NULL, NULL, WS_CHILD | WS_VISIBLE, CRect (0, 0, 100, 100), pCParentWnd, uiID, NULL); }
|
||||
virtual void HandleInitDialog (void) {}
|
||||
virtual bool Apply_Changes (void) { return true; }
|
||||
virtual void Discard_Changes (void) {}
|
||||
|
||||
//
|
||||
// Inline accessors
|
||||
//
|
||||
const CRect & Get_Form_Rect (void) const
|
||||
{ return m_rectForm; }
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Private member data
|
||||
//
|
||||
UINT m_uiTemplateID;
|
||||
CRect m_rectForm;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_DOCKABLEFORMCLASS_H__53843321_66CC_11D2_8DDF_00104B6FD9E3__INCLUDED_)
|
||||
0
Code/Tools/LevelEdit/DummyObject.h
Normal file
0
Code/Tools/LevelEdit/DummyObject.h
Normal file
210
Code/Tools/LevelEdit/DummyObjectDefinition.cpp
Normal file
210
Code/Tools/LevelEdit/DummyObjectDefinition.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/DummyObjectDefinition.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 4/06/00 4:11p $*
|
||||
* *
|
||||
* $Revision:: 4 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "dummyobjectdefinition.h"
|
||||
#include "simpledefinitionfactory.h"
|
||||
#include "definitionclassids.h"
|
||||
#include "definitionmgr.h"
|
||||
#include "persistfactory.h"
|
||||
#include "editorchunkids.h"
|
||||
#include "dummyobjectnode.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
CHUNKID_VARIABLES = 0x00000100,
|
||||
CHUNKID_BASE_CLASS = 0x00000200,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VARID_MODEL_NAME = 0x01,
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Static factories
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
DECLARE_DEFINITION_FACTORY(DummyObjectDefinitionClass, CLASSID_DUMMY_OBJECTS, "Dummy Object") _DummyObjDefFactory;
|
||||
SimplePersistFactoryClass<DummyObjectDefinitionClass, CHUNKID_DUMMY_OBJECT_DEF> _DummyObjDefPersistFactory;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DummyObjectDefinitionClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
DummyObjectDefinitionClass::DummyObjectDefinitionClass (void)
|
||||
: DefinitionClass ()
|
||||
|
||||
{
|
||||
FILENAME_PARAM (DummyObjectDefinitionClass, m_ModelName, "Westwood 3D Files", ".w3d");
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~DummyObjectDefinitionClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
DummyObjectDefinitionClass::~DummyObjectDefinitionClass (void)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Factory
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
const PersistFactoryClass &
|
||||
DummyObjectDefinitionClass::Get_Factory (void) const
|
||||
{
|
||||
return _DummyObjDefPersistFactory;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
DummyObjectDefinitionClass::Save (ChunkSaveClass &csave)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
csave.Begin_Chunk (CHUNKID_VARIABLES);
|
||||
retval &= Save_Variables (csave);
|
||||
csave.End_Chunk ();
|
||||
|
||||
csave.Begin_Chunk (CHUNKID_BASE_CLASS);
|
||||
retval &= DefinitionClass::Save (csave);
|
||||
csave.End_Chunk ();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
DummyObjectDefinitionClass::Load (ChunkLoadClass &cload)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
while (cload.Open_Chunk ()) {
|
||||
switch (cload.Cur_Chunk_ID ()) {
|
||||
|
||||
case CHUNKID_VARIABLES:
|
||||
retval &= Load_Variables (cload);
|
||||
break;
|
||||
|
||||
case CHUNKID_BASE_CLASS:
|
||||
retval &= DefinitionClass::Load (cload);
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Chunk ();
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save_Variables
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
DummyObjectDefinitionClass::Save_Variables (ChunkSaveClass &csave)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_MODEL_NAME, m_ModelName)
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_Variables
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
DummyObjectDefinitionClass::Load_Variables (ChunkLoadClass &cload)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
//
|
||||
// Loop through all the microchunks that define the variables
|
||||
//
|
||||
while (cload.Open_Micro_Chunk ()) {
|
||||
switch (cload.Cur_Micro_Chunk_ID ()) {
|
||||
|
||||
READ_MICRO_CHUNK_WWSTRING (cload, VARID_MODEL_NAME, m_ModelName)
|
||||
}
|
||||
|
||||
cload.Close_Micro_Chunk ();
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
PersistClass *
|
||||
DummyObjectDefinitionClass::Create (void) const
|
||||
{
|
||||
return new DummyObjectNodeClass ();
|
||||
}
|
||||
|
||||
111
Code/Tools/LevelEdit/DummyObjectDefinition.h
Normal file
111
Code/Tools/LevelEdit/DummyObjectDefinition.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/DummyObjectDefinition.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 1/14/00 11:52a $*
|
||||
* *
|
||||
* $Revision:: 3 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __DUMMY_OBJ_DEFINITION_H
|
||||
#define __DUMMY_OBJ_DEFINITION_H
|
||||
|
||||
#include "definition.h"
|
||||
#include "vector.h"
|
||||
#include "wwstring.h"
|
||||
#include "editorchunkids.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DummyObjectDefinitionClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
class DummyObjectDefinitionClass : public DefinitionClass
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Editable interface requirements
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
DECLARE_EDITABLE(DummyObjectDefinitionClass, DefinitionClass);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////////
|
||||
DummyObjectDefinitionClass (void);
|
||||
virtual ~DummyObjectDefinitionClass (void);
|
||||
|
||||
// From DefinitionClass
|
||||
virtual uint32 Get_Class_ID (void) const { return CLASSID_DUMMY_OBJECTS; }
|
||||
|
||||
// From PersistClass
|
||||
virtual const PersistFactoryClass & Get_Factory (void) const;
|
||||
virtual bool Save (ChunkSaveClass &csave);
|
||||
virtual bool Load (ChunkLoadClass &cload);
|
||||
virtual PersistClass * Create (void) const;
|
||||
|
||||
// Terrain definition specific
|
||||
virtual const char * Get_Model_Name (void) const;
|
||||
|
||||
private:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
bool Save_Variables (ChunkSaveClass &csave);
|
||||
bool Load_Variables (ChunkLoadClass &cload);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////////
|
||||
StringClass m_ModelName;
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Get_Model_Name
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
inline const char *
|
||||
DummyObjectDefinitionClass::Get_Model_Name (void) const
|
||||
{
|
||||
return m_ModelName;
|
||||
}
|
||||
|
||||
|
||||
#endif //__DUMMY_OBJ_DEFINITION_H
|
||||
|
||||
351
Code/Tools/LevelEdit/DummyObjectNode.cpp
Normal file
351
Code/Tools/LevelEdit/DummyObjectNode.cpp
Normal file
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/DummyObjectNode.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 12/01/00 2:25p $*
|
||||
* *
|
||||
* $Revision:: 11 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "phys.h"
|
||||
#include "rendobj.h"
|
||||
|
||||
#include "dummyobjectnode.h"
|
||||
#include "dummyobjectdefinition.h"
|
||||
#include "sceneeditor.h"
|
||||
|
||||
#include "filemgr.h"
|
||||
#include "_assetmgr.h"
|
||||
#include "editorassetmgr.h"
|
||||
#include "w3d_file.h"
|
||||
#include "cameramgr.h"
|
||||
#include "collisiongroups.h"
|
||||
#include "persistfactory.h"
|
||||
#include "editorchunkids.h"
|
||||
#include "preset.h"
|
||||
#include "presetmgr.h"
|
||||
#include "nodemgr.h"
|
||||
#include "part_emt.h"
|
||||
#include "modelutils.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Local prototypes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void Remove_Particle_Buffers (RenderObjClass *render_obj);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Persist factory
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
SimplePersistFactoryClass<DummyObjectNodeClass, CHUNKID_DUMMY_OBJECT> _DummyNodePersistFactory;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DummyObjectNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
DummyObjectNodeClass::DummyObjectNodeClass (PresetClass *preset)
|
||||
: m_DisplayObj (NULL),
|
||||
m_RealObj (NULL),
|
||||
NodeClass (preset)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DummyObjectNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
DummyObjectNodeClass::DummyObjectNodeClass (const DummyObjectNodeClass &src)
|
||||
: m_DisplayObj (NULL),
|
||||
m_RealObj (NULL),
|
||||
NodeClass (NULL)
|
||||
{
|
||||
*this = src;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~DummyObjectNodeClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
DummyObjectNodeClass::~DummyObjectNodeClass (void)
|
||||
{
|
||||
Remove_From_Scene ();
|
||||
MEMBER_RELEASE (m_DisplayObj);
|
||||
MEMBER_RELEASE (m_RealObj);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Initialize
|
||||
//
|
||||
// Note: This may be called more than once. It is used as an 'initialize'
|
||||
// and a 're-initialize'.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DummyObjectNodeClass::Initialize (void)
|
||||
{
|
||||
//
|
||||
// Build the phys obj that is used as the position locator in the world.
|
||||
// This is usefull for things like emitters which do not have anything
|
||||
// to 'grab'...
|
||||
//
|
||||
if (m_DisplayObj == NULL) {
|
||||
m_DisplayObj = new DecorationPhysClass;
|
||||
m_DisplayObj->Set_Model_By_Name ("DUMMY");
|
||||
m_DisplayObj->Set_Collision_Group (EDITOR_COLLISION_GROUP);
|
||||
m_DisplayObj->Peek_Model ()->Set_User_Data ((PVOID)&m_HitTestInfo, FALSE);
|
||||
::Set_Model_Collision_Type (m_DisplayObj->Peek_Model (), COLLISION_TYPE_0);
|
||||
}
|
||||
|
||||
DummyObjectDefinitionClass *definition = static_cast<DummyObjectDefinitionClass *> (m_Preset->Get_Definition ());
|
||||
if (definition != NULL) {
|
||||
MEMBER_RELEASE (m_RealObj);
|
||||
|
||||
//
|
||||
// Make sure we have all the assets loaded into memory that this object needs.
|
||||
//
|
||||
m_Preset->Load_All_Assets ();
|
||||
|
||||
//
|
||||
// Create the real physics object that will get exported to the game
|
||||
//
|
||||
m_RealObj = new DecorationPhysClass;
|
||||
CString render_obj_name = ::Asset_Name_From_Filename (definition->Get_Model_Name ());
|
||||
RenderObjClass *render_obj = ::Create_Render_Obj (render_obj_name);
|
||||
if (render_obj != NULL) {
|
||||
|
||||
//
|
||||
// Start the emitter if necessary
|
||||
//
|
||||
if (render_obj->Class_ID () == RenderObjClass::CLASSID_PARTICLEEMITTER) {
|
||||
((ParticleEmitterClass *)render_obj)->Start ();
|
||||
render_obj->Set_User_Data (m_RealObj);
|
||||
}
|
||||
|
||||
m_RealObj->Set_Model (render_obj);
|
||||
MEMBER_RELEASE (render_obj);
|
||||
}
|
||||
|
||||
//
|
||||
// Update the transforms of both objects
|
||||
//
|
||||
Set_Transform (m_Transform);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Factory
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
const PersistFactoryClass &
|
||||
DummyObjectNodeClass::Get_Factory (void) const
|
||||
{
|
||||
return _DummyNodePersistFactory;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// operator=
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
const DummyObjectNodeClass &
|
||||
DummyObjectNodeClass::operator= (const DummyObjectNodeClass &src)
|
||||
{
|
||||
NodeClass::operator= (src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Pre_Export
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DummyObjectNodeClass::Pre_Export (void)
|
||||
{
|
||||
//
|
||||
// Remove ourselves from the 'system' so we don't get accidentally
|
||||
// saved during the export.
|
||||
//
|
||||
Add_Ref ();
|
||||
if (m_DisplayObj != NULL && m_IsInScene) {
|
||||
::Get_Scene_Editor ()->Remove_Object (m_DisplayObj);
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Post_Export
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DummyObjectNodeClass::Post_Export (void)
|
||||
{
|
||||
//
|
||||
// Put ourselves back into the system
|
||||
//
|
||||
if (m_DisplayObj != NULL && m_IsInScene) {
|
||||
::Get_Scene_Editor ()->Add_Dynamic_Object (m_DisplayObj);
|
||||
}
|
||||
Release_Ref ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Add_To_Scene
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DummyObjectNodeClass::Add_To_Scene (void)
|
||||
{
|
||||
if (m_RealObj == NULL) {
|
||||
Initialize ();
|
||||
}
|
||||
|
||||
if (m_RealObj != NULL && m_RealObj->Peek_Model ()->Peek_Scene () == NULL) {
|
||||
::Get_Scene_Editor ()->Add_Dynamic_Object (m_RealObj);
|
||||
::Get_Scene_Editor ()->Add_To_Dirty_Cull_List (m_RealObj);
|
||||
}
|
||||
|
||||
NodeClass::Add_To_Scene ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Remove_From_Scene
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DummyObjectNodeClass::Remove_From_Scene (void)
|
||||
{
|
||||
if (m_RealObj != NULL && m_RealObj->Peek_Model ()->Peek_Scene () != NULL) {
|
||||
|
||||
//
|
||||
// If this is a particle emitter, then be sure to remove the buffer as well
|
||||
//
|
||||
RenderObjClass *render_obj = m_RealObj->Peek_Model ();
|
||||
Remove_Particle_Buffers (render_obj);
|
||||
|
||||
::Get_Scene_Editor ()->Remove_From_Dirty_Cull_List (m_RealObj);
|
||||
::Get_Scene_Editor ()->Remove_Object (m_RealObj);
|
||||
|
||||
MEMBER_RELEASE (m_RealObj);
|
||||
}
|
||||
|
||||
NodeClass::Remove_From_Scene ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Handle_Emitter_Transform
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
DummyObjectNodeClass::Handle_Emitter_Transform (void)
|
||||
{
|
||||
if (m_RealObj != NULL && m_RealObj->Peek_Model () != NULL) {
|
||||
|
||||
//
|
||||
// If this is a particle emitter, then be sure to move the buffer as well
|
||||
//
|
||||
RenderObjClass *render_obj = m_RealObj->Peek_Model ();
|
||||
if (render_obj->Class_ID () == RenderObjClass::CLASSID_PARTICLEEMITTER) {
|
||||
ParticleBufferClass *buffer = ((ParticleEmitterClass *)render_obj)->Peek_Buffer ();
|
||||
if (buffer != NULL) {
|
||||
buffer->Set_Transform (m_Transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Remove_Particle_Buffers
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
void
|
||||
Remove_Particle_Buffers (RenderObjClass *render_obj)
|
||||
{
|
||||
//
|
||||
// Recursively walk through the objects in the scene
|
||||
//
|
||||
for (int index = 0; index < render_obj->Get_Num_Sub_Objects (); index ++) {
|
||||
RenderObjClass *sub_obj = render_obj->Get_Sub_Object (index);
|
||||
if (sub_obj != NULL) {
|
||||
Remove_Particle_Buffers (sub_obj);
|
||||
}
|
||||
MEMBER_RELEASE (sub_obj);
|
||||
}
|
||||
|
||||
//
|
||||
// Is this the emitter we are requesting?
|
||||
//
|
||||
if ((render_obj != NULL) &&
|
||||
(render_obj->Class_ID () == RenderObjClass::CLASSID_PARTICLEEMITTER))
|
||||
{
|
||||
ParticleBufferClass *buffer = ((ParticleEmitterClass *)render_obj)->Peek_Buffer ();
|
||||
if (buffer != NULL && buffer->Peek_Scene () != NULL) {
|
||||
::Get_Scene_Editor ()->Remove_Render_Object (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
182
Code/Tools/LevelEdit/DummyObjectNode.h
Normal file
182
Code/Tools/LevelEdit/DummyObjectNode.h
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/DummyObjectNode.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 5/02/00 5:56p $*
|
||||
* *
|
||||
* $Revision:: 4 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __DUMMY_OBJECT_NODE_H
|
||||
#define __DUMMY_OBJECT_NODE_H
|
||||
|
||||
#include "node.h"
|
||||
#include "icons.h"
|
||||
#include "decophys.h"
|
||||
|
||||
|
||||
// Forward declarations
|
||||
class PresetClass;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DummyObjectNodeClass
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class DummyObjectNodeClass : public NodeClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////////////
|
||||
DummyObjectNodeClass (PresetClass *preset = NULL);
|
||||
DummyObjectNodeClass (const DummyObjectNodeClass &src);
|
||||
~DummyObjectNodeClass (void);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public operators
|
||||
//////////////////////////////////////////////////////////////
|
||||
const DummyObjectNodeClass &operator= (const DummyObjectNodeClass &src);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// From PersistClass
|
||||
//
|
||||
virtual const PersistFactoryClass & Get_Factory (void) const;
|
||||
|
||||
//
|
||||
// From NodeClass
|
||||
//
|
||||
NodeClass * Clone (void) { return new DummyObjectNodeClass (*this); }
|
||||
void Initialize (void);
|
||||
NODE_TYPE Get_Type (void) const { return NODE_TYPE_DUMMY_OBJECT; }
|
||||
int Get_Icon_Index (void) const { return OBJECT_ICON; }
|
||||
PhysClass * Peek_Physics_Obj (void) const;
|
||||
bool Is_Static (void) const { return false; }
|
||||
void Add_To_Scene (void);
|
||||
void Remove_From_Scene (void);
|
||||
|
||||
void Handle_Emitter_Transform (void);
|
||||
|
||||
//
|
||||
// Notifications
|
||||
//
|
||||
void On_Rotate (void);
|
||||
void On_Translate (void);
|
||||
void On_Transform (void);
|
||||
|
||||
//
|
||||
// Export methods
|
||||
//
|
||||
void Pre_Export (void);
|
||||
void Post_Export (void);
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////////////
|
||||
DecorationPhysClass * m_DisplayObj;
|
||||
DecorationPhysClass * m_RealObj;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Peek_Physics_Obj
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline PhysClass *
|
||||
DummyObjectNodeClass::Peek_Physics_Obj (void) const
|
||||
{
|
||||
return m_DisplayObj;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Rotate
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
DummyObjectNodeClass::On_Rotate (void)
|
||||
{
|
||||
if (m_RealObj != NULL) {
|
||||
m_RealObj->Set_Transform (m_Transform);
|
||||
Handle_Emitter_Transform ();
|
||||
}
|
||||
NodeClass::On_Rotate ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Translate
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
DummyObjectNodeClass::On_Translate (void)
|
||||
{
|
||||
if (m_RealObj != NULL) {
|
||||
m_RealObj->Set_Transform (m_Transform);
|
||||
Handle_Emitter_Transform ();
|
||||
}
|
||||
NodeClass::On_Translate ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// On_Transform
|
||||
//////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
DummyObjectNodeClass::On_Transform (void)
|
||||
{
|
||||
if (m_RealObj != NULL) {
|
||||
m_RealObj->Set_Transform (m_Transform);
|
||||
Handle_Emitter_Transform ();
|
||||
}
|
||||
NodeClass::On_Transform ();
|
||||
return ;
|
||||
}
|
||||
|
||||
#endif //__DUMMY_OBJECT_NODE_H
|
||||
|
||||
830
Code/Tools/LevelEdit/EditConversationDialog.cpp
Normal file
830
Code/Tools/LevelEdit/EditConversationDialog.cpp
Normal file
@@ -0,0 +1,830 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// EditConversationDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveledit.h"
|
||||
#include "editconversationdialog.h"
|
||||
#include "conversation.h"
|
||||
#include "translatedb.h"
|
||||
#include "translateobj.h"
|
||||
#include "editconversationremarkdialog.h"
|
||||
#include "playertype.h"
|
||||
#include "orator.h"
|
||||
#include "oratortypes.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
COL_ORATOR = 0,
|
||||
COL_REMARK
|
||||
};
|
||||
|
||||
static const int ORATOR_MAX = 6;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int button_id;
|
||||
int combo_id;
|
||||
int check_id;
|
||||
int icon_id;
|
||||
} ORATOR_UI_INFO;
|
||||
|
||||
const ORATOR_UI_INFO ORATOR_CTRLS[ORATOR_MAX] =
|
||||
{
|
||||
{ IDC_ORATOR1_CHECK, IDC_ORATOR1_COMBO, IDC_ORATOR1_VISBLE_CHECK, IDI_ORATOR1 },
|
||||
{ IDC_ORATOR2_CHECK, IDC_ORATOR2_COMBO, IDC_ORATOR2_VISBLE_CHECK, IDI_ORATOR2 },
|
||||
{ IDC_ORATOR3_CHECK, IDC_ORATOR3_COMBO, IDC_ORATOR3_VISBLE_CHECK, IDI_ORATOR3 },
|
||||
{ IDC_ORATOR4_CHECK, IDC_ORATOR4_COMBO, IDC_ORATOR4_VISBLE_CHECK, IDI_ORATOR4 },
|
||||
{ IDC_ORATOR5_CHECK, IDC_ORATOR5_COMBO, IDC_ORATOR5_VISBLE_CHECK, IDI_ORATOR5 },
|
||||
{ IDC_ORATOR6_CHECK, IDC_ORATOR6_COMBO, IDC_ORATOR6_VISBLE_CHECK, IDI_ORATOR6 },
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditConversationDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
EditConversationDialogClass::EditConversationDialogClass(CWnd* pParent /*=NULL*/)
|
||||
: m_Conversation (NULL),
|
||||
CDialog(EditConversationDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(EditConversationDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~EditConversationDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
EditConversationDialogClass::~EditConversationDialogClass (void)
|
||||
{
|
||||
REF_PTR_RELEASE (m_Conversation);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::DoDataExchange (CDataExchange *pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(EditConversationDialogClass)
|
||||
DDX_Control(pDX, IDC_REMARK_LIST, m_ListCtrl);
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(EditConversationDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(EditConversationDialogClass)
|
||||
ON_NOTIFY(NM_DBLCLK, IDC_REMARK_LIST, OnDblclkRemarkList)
|
||||
ON_NOTIFY(LVN_KEYDOWN, IDC_REMARK_LIST, OnKeydownRemarkList)
|
||||
ON_BN_CLICKED(IDC_ADD, OnAdd)
|
||||
ON_BN_CLICKED(IDC_INSERT, OnInsert)
|
||||
ON_NOTIFY(LVN_ITEMCHANGED, IDC_REMARK_LIST, OnItemchangedRemarkList)
|
||||
ON_NOTIFY(LVN_DELETEITEM, IDC_REMARK_LIST, OnDeleteitemRemarkList)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
EditConversationDialogClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
//
|
||||
// Create a new conversation if we don't already have one to edit
|
||||
//
|
||||
if (m_Conversation == NULL) {
|
||||
m_Conversation = new ConversationClass;
|
||||
|
||||
OratorClass orator;
|
||||
m_Conversation->Add_Orator (orator);
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the state combo box
|
||||
//
|
||||
SendDlgItemMessage (IDC_STATE_COMBO, CB_ADDSTRING, 0, (LPARAM)"Idle");
|
||||
SendDlgItemMessage (IDC_STATE_COMBO, CB_ADDSTRING, 0, (LPARAM)"Idle (Secondary)");
|
||||
SendDlgItemMessage (IDC_STATE_COMBO, CB_ADDSTRING, 0, (LPARAM)"Search");
|
||||
SendDlgItemMessage (IDC_STATE_COMBO, CB_ADDSTRING, 0, (LPARAM)"Combat");
|
||||
SendDlgItemMessage (IDC_STATE_COMBO, CB_SETCURSEL, (WPARAM)m_Conversation->Get_AI_State ());
|
||||
|
||||
//
|
||||
// Configure the orator controls
|
||||
//
|
||||
for (int index = 0; index < ORATOR_MAX; index ++) {
|
||||
|
||||
//
|
||||
// Put the icon into the button control
|
||||
//
|
||||
HICON icon = ::LoadIcon (::AfxGetResourceHandle (), MAKEINTRESOURCE (ORATOR_CTRLS[index].icon_id));
|
||||
SendDlgItemMessage (ORATOR_CTRLS[index].button_id, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icon);
|
||||
|
||||
//
|
||||
// Put the "visible" icon into the checkbox control
|
||||
//
|
||||
icon = (HICON)::LoadImage (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_EYE2), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
|
||||
SendDlgItemMessage (ORATOR_CTRLS[index].check_id, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icon);
|
||||
SendDlgItemMessage (ORATOR_CTRLS[index].check_id, BM_SETCHECK, (WPARAM)TRUE);
|
||||
|
||||
//
|
||||
// Configure the orator type combo-box
|
||||
//
|
||||
int type_count = OratorTypeClass::Get_Count ();
|
||||
for (int type_index = 0; type_index < type_count; type_index ++) {
|
||||
|
||||
//
|
||||
// Lookup information about this orator type
|
||||
//
|
||||
const char *type_name = OratorTypeClass::Get_Description (type_index);
|
||||
int type_id = OratorTypeClass::Get_ID (type_index);
|
||||
int combobox_id = ORATOR_CTRLS[index].combo_id;
|
||||
|
||||
//
|
||||
// Add this orator type to the combobox
|
||||
//
|
||||
int item_index = SendDlgItemMessage (combobox_id, CB_ADDSTRING, 0, (LPARAM)type_name);
|
||||
SendDlgItemMessage (combobox_id, CB_SETITEMDATA, (WPARAM)item_index, (LPARAM)type_id);
|
||||
}
|
||||
|
||||
//
|
||||
// Select the first item by default
|
||||
//
|
||||
SendDlgItemMessage (ORATOR_CTRLS[index].combo_id, CB_SETCURSEL, (WPARAM)0);
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the orator controls
|
||||
//
|
||||
bool is_locked = true;
|
||||
int orator_count = m_Conversation->Get_Orator_Count ();
|
||||
for (index = 0; index < orator_count; index ++) {
|
||||
OratorClass *orator = m_Conversation->Get_Orator (index);
|
||||
|
||||
//
|
||||
// Check the checkbox control and enable the combobox control
|
||||
//
|
||||
SendDlgItemMessage (ORATOR_CTRLS[index].button_id, BM_SETCHECK, (WPARAM)TRUE);
|
||||
SendDlgItemMessage (ORATOR_CTRLS[index].check_id, BM_SETCHECK, (WPARAM)(!orator->Is_Invisible ()));
|
||||
::EnableWindow (::GetDlgItem (m_hWnd, ORATOR_CTRLS[index].combo_id), TRUE);
|
||||
::EnableWindow (::GetDlgItem (m_hWnd, ORATOR_CTRLS[index].check_id), TRUE);
|
||||
|
||||
//
|
||||
// Select the current orator type in the combobox
|
||||
//
|
||||
int orator_type = orator->Get_Orator_Type ();
|
||||
int item_index = Find_Combobox_Entry (orator_type);
|
||||
if (item_index >= 0) {
|
||||
SendDlgItemMessage (ORATOR_CTRLS[index].combo_id, CB_SETCURSEL, (WPARAM)item_index);
|
||||
}
|
||||
|
||||
//
|
||||
// If any of the orator types disagree, then don't lock the controls
|
||||
//
|
||||
if (orator_type != m_Conversation->Get_Orator (0)->Get_Orator_Type ()) {
|
||||
is_locked = false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the "lock" checkbox
|
||||
//
|
||||
HICON lock_icon = (HICON)::LoadImage (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_LOCK), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
|
||||
SendDlgItemMessage (IDC_LOCKED_CHECK, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)lock_icon);
|
||||
SendDlgItemMessage (IDC_LOCKED_CHECK, BM_SETCHECK, (WPARAM)is_locked);
|
||||
|
||||
//
|
||||
// Set the check state of the "Is Innate" and "Is Key" checkboxes
|
||||
//
|
||||
SendDlgItemMessage (IDC_INNATE_CHECK, BM_SETCHECK, (WPARAM)m_Conversation->Is_Innate ());
|
||||
SendDlgItemMessage (IDC_KEY_CONVESATION_CHECK, BM_SETCHECK, (WPARAM)m_Conversation->Is_Key ());
|
||||
|
||||
//
|
||||
// Configure the columns
|
||||
//
|
||||
m_ListCtrl.InsertColumn (COL_ORATOR, "Orator");
|
||||
m_ListCtrl.InsertColumn (COL_REMARK, "Remark");
|
||||
m_ListCtrl.SetExtendedStyle (m_ListCtrl.GetExtendedStyle () | LVS_EX_FULLROWSELECT);
|
||||
|
||||
//
|
||||
// Choose an appropriate size for the columns
|
||||
//
|
||||
CRect rect;
|
||||
m_ListCtrl.GetClientRect (&rect);
|
||||
rect.right -= ::GetSystemMetrics (SM_CXVSCROLL) + 2;
|
||||
m_ListCtrl.SetColumnWidth (COL_ORATOR, rect.Width () / 4);
|
||||
m_ListCtrl.SetColumnWidth (COL_REMARK, (rect.Width () * 3) / 4);
|
||||
|
||||
//
|
||||
// Fill in the conversation's name into the appropriate control
|
||||
//
|
||||
SetDlgItemText (IDC_CONVERSATION_NAME, m_Conversation->Get_Name ());
|
||||
|
||||
//
|
||||
// Add all the remark's to the list control
|
||||
//
|
||||
int count = m_Conversation->Get_Remark_Count ();
|
||||
for (index = 0; index < count; index ++) {
|
||||
|
||||
ConversationRemarkClass remark;
|
||||
if (m_Conversation->Get_Remark_Info (index, remark)) {
|
||||
Add_Entry (remark);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDblclkRemarkList
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::OnDblclkRemarkList
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT* pResult
|
||||
)
|
||||
{
|
||||
(*pResult) = 0;
|
||||
|
||||
//
|
||||
// Determine which entry the user double-clicked on
|
||||
//
|
||||
int sel_index = m_ListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
|
||||
if (sel_index != -1) {
|
||||
|
||||
//
|
||||
// Lookup the information about this entry
|
||||
//
|
||||
ConversationRemarkClass *remark = Get_Entry_Data (sel_index);
|
||||
|
||||
//
|
||||
// Make a bitmask of the orators that are configured
|
||||
//
|
||||
int orator_bitmask = 0;
|
||||
for (int index = 0; index < ORATOR_MAX; index ++) {
|
||||
if (SendDlgItemMessage (ORATOR_CTRLS[index].button_id, BM_GETCHECK) == 1) {
|
||||
orator_bitmask |= (1 << index);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Show a dialog to the user that will let them choose an orator and
|
||||
// a remark
|
||||
//
|
||||
EditConversationRemarkDialogClass dialog (this);
|
||||
dialog.Set_Remark (*remark);
|
||||
dialog.Set_Orator_Bitmask (orator_bitmask);
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Get the new values from the dialog
|
||||
//
|
||||
(*remark) = dialog.Get_Remark ();
|
||||
|
||||
//
|
||||
// Update the orator id in the list control
|
||||
//
|
||||
CString orator_text;
|
||||
orator_text.Format ("%d", remark->Get_Orator_ID () + 1);
|
||||
m_ListCtrl.SetItemText (sel_index, COL_ORATOR, orator_text);
|
||||
|
||||
//
|
||||
// Update the text entry in the list control
|
||||
//
|
||||
TDBObjClass *translate_obj = TranslateDBClass::Find_Object (remark->Get_Text_ID ());
|
||||
if (translate_obj != NULL) {
|
||||
m_ListCtrl.SetItemText (sel_index, COL_REMARK, translate_obj->Get_English_String ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnKeydownRemarkList
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::OnKeydownRemarkList
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT * pResult
|
||||
)
|
||||
{
|
||||
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
|
||||
(*pResult) = 0;
|
||||
|
||||
if (pLVKeyDow->wVKey == VK_DELETE) {
|
||||
|
||||
//
|
||||
// Delete all the selected items
|
||||
//
|
||||
int index = -1;
|
||||
while ((index = m_ListCtrl.GetNextItem (-1, LVNI_SELECTED | LVNI_ALL)) >= 0) {
|
||||
m_ListCtrl.DeleteItem (index);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOK
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::OnOK (void)
|
||||
{
|
||||
CDialog::OnOK ();
|
||||
|
||||
//
|
||||
// Read the state this conversation is active for
|
||||
//
|
||||
int ai_state = SendDlgItemMessage (IDC_STATE_COMBO, CB_GETCURSEL);
|
||||
if (ai_state != CB_ERR) {
|
||||
m_Conversation->Set_AI_State (SoldierAIState(ai_state));
|
||||
}
|
||||
|
||||
//
|
||||
// Pass the name onto the conversation
|
||||
//
|
||||
CString name;
|
||||
GetDlgItemText (IDC_CONVERSATION_NAME, name);
|
||||
m_Conversation->Set_Name (name);
|
||||
|
||||
//
|
||||
// Start fresh
|
||||
//
|
||||
m_Conversation->Clear_Remarks ();
|
||||
m_Conversation->Clear_Orators ();
|
||||
|
||||
//
|
||||
// Get all the conversations from the list control and add them to the
|
||||
// conversation manager
|
||||
//
|
||||
for (int index = 0; index < m_ListCtrl.GetItemCount (); index ++) {
|
||||
ConversationRemarkClass *remark = Get_Entry_Data (index);
|
||||
m_Conversation->Add_Remark (*remark);
|
||||
}
|
||||
|
||||
//
|
||||
// Build a list of orators for the conversation
|
||||
//
|
||||
for (index = 0; index < ORATOR_MAX; index ++) {
|
||||
|
||||
//
|
||||
// Is this orator configured?
|
||||
//
|
||||
if (SendDlgItemMessage (ORATOR_CTRLS[index].button_id, BM_GETCHECK) == 1) {
|
||||
bool is_invisible = (SendDlgItemMessage (ORATOR_CTRLS[index].check_id, BM_GETCHECK) != 1);
|
||||
|
||||
//
|
||||
// Add the orator to the conversation
|
||||
//
|
||||
OratorClass orator;
|
||||
orator.Set_ID (index);
|
||||
orator.Set_Orator_Type (Get_Orator_Type (index));
|
||||
orator.Set_Is_Invisible (is_invisible);
|
||||
m_Conversation->Add_Orator (orator);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get the ID of the object to look at (if any)
|
||||
//
|
||||
int obj_id = GetDlgItemInt (IDC_OBJECT_ID);
|
||||
m_Conversation->Set_Look_At_Obj_ID (obj_id);
|
||||
|
||||
//
|
||||
// Read the users "innate" selection
|
||||
//
|
||||
bool is_innate = bool(SendDlgItemMessage (IDC_INNATE_CHECK, BM_GETCHECK) == 1);
|
||||
m_Conversation->Set_Is_Innate (is_innate);
|
||||
|
||||
bool is_key = bool(SendDlgItemMessage (IDC_KEY_CONVESATION_CHECK, BM_GETCHECK) == 1);
|
||||
m_Conversation->Set_Is_Key (is_key);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnAdd
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::OnAdd (void)
|
||||
{
|
||||
//
|
||||
// Make a bitmask of the orators that are configured
|
||||
//
|
||||
int orator_bitmask = 0;
|
||||
for (int index = 0; index < ORATOR_MAX; index ++) {
|
||||
if (SendDlgItemMessage (ORATOR_CTRLS[index].button_id, BM_GETCHECK) == 1) {
|
||||
orator_bitmask |= (1 << index);
|
||||
}
|
||||
}
|
||||
|
||||
EditConversationRemarkDialogClass dialog (this);
|
||||
dialog.Set_Orator_Bitmask (orator_bitmask);
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Insert a new entry into the list control
|
||||
//
|
||||
Add_Entry (dialog.Get_Remark ());
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Conversation
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::Set_Conversation (ConversationClass *conversation)
|
||||
{
|
||||
REF_PTR_SET (m_Conversation, conversation);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Entry_Data
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
ConversationRemarkClass *
|
||||
EditConversationDialogClass::Get_Entry_Data (int index)
|
||||
{
|
||||
return (ConversationRemarkClass *)m_ListCtrl.GetItemData (index);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Add_Entry
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::Add_Entry (const ConversationRemarkClass &remark, int insert_index)
|
||||
{
|
||||
//
|
||||
// Insert this item into the list control
|
||||
//
|
||||
CString orator_text;
|
||||
orator_text.Format ("%d", remark.Get_Orator_ID () + 1);
|
||||
int item_index = m_ListCtrl.InsertItem (insert_index, orator_text);
|
||||
if (item_index >= 0) {
|
||||
|
||||
//
|
||||
// Lookup the text to display for this remark
|
||||
//
|
||||
TDBObjClass *translate_obj = TranslateDBClass::Find_Object (remark.Get_Text_ID ());
|
||||
if (translate_obj != NULL) {
|
||||
m_ListCtrl.SetItemText (item_index, COL_REMARK, translate_obj->Get_English_String ());
|
||||
|
||||
//
|
||||
// Allocate a remark object to associate with this entry in the list control
|
||||
//
|
||||
ConversationRemarkClass *associated_remark = new ConversationRemarkClass (remark);
|
||||
m_ListCtrl.SetItemData (item_index, (DWORD)associated_remark);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInsert
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::OnInsert (void)
|
||||
{
|
||||
int sel_index = m_ListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
|
||||
if (sel_index != -1) {
|
||||
|
||||
//
|
||||
// Make a bitmask of the orators that are configured
|
||||
//
|
||||
int orator_bitmask = 0;
|
||||
for (int index = 0; index < ORATOR_MAX; index ++) {
|
||||
if (SendDlgItemMessage (ORATOR_CTRLS[index].button_id, BM_GETCHECK) == 1) {
|
||||
orator_bitmask |= (1 << index);
|
||||
}
|
||||
}
|
||||
|
||||
EditConversationRemarkDialogClass dialog (this);
|
||||
dialog.Set_Orator_Bitmask (orator_bitmask);
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Insert the new entry into the appropriate place in the list
|
||||
//
|
||||
Add_Entry (dialog.Get_Remark (), sel_index);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnItemchangedRemarkList
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::OnItemchangedRemarkList
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT * pResult
|
||||
)
|
||||
{
|
||||
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
|
||||
(*pResult) = 0;
|
||||
|
||||
Update_Button_States ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Button_States
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::Update_Button_States (void)
|
||||
{
|
||||
int sel_index = m_ListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
|
||||
::EnableWindow (::GetDlgItem (m_hWnd, IDC_INSERT), static_cast<bool>(sel_index != -1));
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnCommand
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
EditConversationDialogClass::OnCommand
|
||||
(
|
||||
WPARAM wParam,
|
||||
LPARAM lParam
|
||||
)
|
||||
{
|
||||
|
||||
switch (LOWORD (wParam)) {
|
||||
|
||||
case IDC_ORATOR1_CHECK:
|
||||
case IDC_ORATOR2_CHECK:
|
||||
case IDC_ORATOR3_CHECK:
|
||||
case IDC_ORATOR4_CHECK:
|
||||
case IDC_ORATOR5_CHECK:
|
||||
case IDC_ORATOR6_CHECK:
|
||||
{
|
||||
Update_Enable_State (LOWORD (wParam) - IDC_ORATOR1_CHECK);
|
||||
Update_Remarks (LOWORD (wParam) - IDC_ORATOR1_CHECK);
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_ORATOR1_COMBO:
|
||||
case IDC_ORATOR2_COMBO:
|
||||
case IDC_ORATOR3_COMBO:
|
||||
case IDC_ORATOR4_COMBO:
|
||||
case IDC_ORATOR5_COMBO:
|
||||
case IDC_ORATOR6_COMBO:
|
||||
{
|
||||
if (HIWORD (wParam) == CBN_SELCHANGE) {
|
||||
Update_Player_Type_Combos (LOWORD (wParam) - IDC_ORATOR1_COMBO);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CDialog::OnCommand (wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Remarks
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::Update_Remarks (int orator_index)
|
||||
{
|
||||
BOOL is_checked = (SendDlgItemMessage (ORATOR_CTRLS[orator_index].button_id, BM_GETCHECK) == 1);
|
||||
if (is_checked == false) {
|
||||
|
||||
//
|
||||
// Remove any remarks made by the specified orator
|
||||
//
|
||||
int item_count = m_ListCtrl.GetItemCount ();
|
||||
for (int index = 0; index < item_count; index ++) {
|
||||
ConversationRemarkClass *remark = Get_Entry_Data (index);
|
||||
|
||||
//
|
||||
// Remove this entry if it was made by the orator in question
|
||||
//
|
||||
if (remark != NULL && remark->Get_Orator_ID () == orator_index) {
|
||||
m_ListCtrl.DeleteItem (index);
|
||||
index --;
|
||||
item_count --;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Enable_State
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::Update_Enable_State (int orator_index)
|
||||
{
|
||||
BOOL is_checked = (SendDlgItemMessage (ORATOR_CTRLS[orator_index].button_id, BM_GETCHECK) == 1);
|
||||
::EnableWindow (::GetDlgItem (m_hWnd, ORATOR_CTRLS[orator_index].combo_id), is_checked);
|
||||
::EnableWindow (::GetDlgItem (m_hWnd, ORATOR_CTRLS[orator_index].check_id), is_checked);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Player_Type_Combos
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::Update_Player_Type_Combos (int orator_index)
|
||||
{
|
||||
BOOL is_locked = (SendDlgItemMessage (IDC_LOCKED_CHECK, BM_GETCHECK) == 1);
|
||||
|
||||
if (is_locked) {
|
||||
|
||||
//
|
||||
// Get the current selection
|
||||
//
|
||||
int curr_sel = SendDlgItemMessage (ORATOR_CTRLS[orator_index].combo_id, CB_GETCURSEL);
|
||||
|
||||
//
|
||||
// Update all the combo boxes to reflect the current selection
|
||||
//
|
||||
for (int index = 0; index < ORATOR_MAX; index ++) {
|
||||
SendDlgItemMessage (ORATOR_CTRLS[index].combo_id, CB_SETCURSEL, (WPARAM)curr_sel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Orator_Type
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
int
|
||||
EditConversationDialogClass::Get_Orator_Type (int orator_index)
|
||||
{
|
||||
int retval = -1;
|
||||
|
||||
//
|
||||
// Get the current selection
|
||||
//
|
||||
int curr_sel = SendDlgItemMessage (ORATOR_CTRLS[orator_index].combo_id, CB_GETCURSEL);
|
||||
if (curr_sel >= 0) {
|
||||
retval = SendDlgItemMessage (ORATOR_CTRLS[orator_index].combo_id, CB_GETITEMDATA, (WPARAM)curr_sel);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDeleteitemRemarkList
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationDialogClass::OnDeleteitemRemarkList
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT * pResult
|
||||
)
|
||||
{
|
||||
NM_LISTVIEW *pNMListView = (NM_LISTVIEW *)pNMHDR;
|
||||
(*pResult) = 0;
|
||||
|
||||
//
|
||||
// Lookup the associated remark object
|
||||
//
|
||||
ConversationRemarkClass *remark = NULL;
|
||||
remark = (ConversationRemarkClass *)m_ListCtrl.GetItemData (pNMListView->iItem);
|
||||
|
||||
//
|
||||
// Free the object
|
||||
//
|
||||
SAFE_DELETE (remark);
|
||||
m_ListCtrl.SetItemData (pNMListView->iItem, 0);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Find_Combobox_Entry
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
int
|
||||
EditConversationDialogClass::Find_Combobox_Entry (int orator_type)
|
||||
{
|
||||
int retval = -1;
|
||||
|
||||
//
|
||||
// Loop over all the entries in the combobox until we've found
|
||||
// the one that's associated with the given orator type
|
||||
//
|
||||
int count = SendDlgItemMessage (IDC_ORATOR1_COMBO, CB_GETCOUNT);
|
||||
for (int index = 0; index < count; index ++) {
|
||||
|
||||
//
|
||||
// Is this the orator we are looking for?
|
||||
//
|
||||
int item_data = SendDlgItemMessage (IDC_ORATOR1_COMBO, CB_GETITEMDATA, (WPARAM)index);
|
||||
if (item_data == orator_type) {
|
||||
retval = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
110
Code/Tools/LevelEdit/EditConversationDialog.h
Normal file
110
Code/Tools/LevelEdit/EditConversationDialog.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_EDITCONVERSATIONDIALOG_H__77BB0B01_5D9E_4BFF_9D25_CE964576950D__INCLUDED_)
|
||||
#define AFX_EDITCONVERSATIONDIALOG_H__77BB0B01_5D9E_4BFF_9D25_CE964576950D__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class ConversationClass;
|
||||
class ConversationRemarkClass;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditConversationDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class EditConversationDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
EditConversationDialogClass (CWnd *pParent = NULL);
|
||||
~EditConversationDialogClass (void);
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(EditConversationDialogClass)
|
||||
enum { IDD = IDD_EDIT_CONVERSATION };
|
||||
CListCtrl m_ListCtrl;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(EditConversationDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(EditConversationDialogClass)
|
||||
afx_msg void OnDblclkRemarkList(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnKeydownRemarkList(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
virtual void OnOK();
|
||||
afx_msg void OnAdd();
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnInsert();
|
||||
afx_msg void OnItemchangedRemarkList(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnDeleteitemRemarkList(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void Set_Conversation (ConversationClass *conversation);
|
||||
ConversationClass * Peek_Conversation (void) { return m_Conversation; }
|
||||
|
||||
protected:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
ConversationRemarkClass *Get_Entry_Data (int index);
|
||||
void Add_Entry (const ConversationRemarkClass &remark, int insert_index = 0xFFFF);
|
||||
void Update_Button_States (void);
|
||||
void Update_Enable_State (int orator_index);
|
||||
void Update_Player_Type_Combos (int orator_index);
|
||||
void Update_Remarks (int orator_index);
|
||||
int Get_Orator_Type (int orator_index);
|
||||
|
||||
int Find_Combobox_Entry (int orator_type);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Protected member data
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
ConversationClass * m_Conversation;
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_EDITCONVERSATIONDIALOG_H__77BB0B01_5D9E_4BFF_9D25_CE964576950D__INCLUDED_)
|
||||
311
Code/Tools/LevelEdit/EditConversationListDialog.cpp
Normal file
311
Code/Tools/LevelEdit/EditConversationListDialog.cpp
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// EditConversationListDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveledit.h"
|
||||
#include "editconversationlistdialog.h"
|
||||
#include "conversationmgr.h"
|
||||
#include "editconversationdialog.h"
|
||||
#include "conversation.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditConversationListDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
EditConversationListDialogClass::EditConversationListDialogClass(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(EditConversationListDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(EditConversationListDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationListDialogClass::DoDataExchange (CDataExchange *pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(EditConversationListDialogClass)
|
||||
DDX_Control(pDX, IDC_CONVERSATION_LIST, m_ListCtrl);
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(EditConversationListDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(EditConversationListDialogClass)
|
||||
ON_BN_CLICKED(IDC_ADD, OnAdd)
|
||||
ON_NOTIFY(NM_DBLCLK, IDC_CONVERSATION_LIST, OnDblclkConversationList)
|
||||
ON_NOTIFY(LVN_DELETEITEM, IDC_CONVERSATION_LIST, OnDeleteitemConversationList)
|
||||
ON_NOTIFY(LVN_KEYDOWN, IDC_CONVERSATION_LIST, OnKeydownConversationList)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
EditConversationListDialogClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
//
|
||||
// Configure the columns
|
||||
//
|
||||
m_ListCtrl.InsertColumn (0, "Name");
|
||||
m_ListCtrl.SetExtendedStyle (m_ListCtrl.GetExtendedStyle () | LVS_EX_FULLROWSELECT);
|
||||
|
||||
//
|
||||
// Choose an appropriate size for the columns
|
||||
//
|
||||
CRect rect;
|
||||
m_ListCtrl.GetClientRect (&rect);
|
||||
rect.right -= ::GetSystemMetrics (SM_CXVSCROLL);
|
||||
m_ListCtrl.SetColumnWidth (0, rect.Width ());
|
||||
|
||||
//
|
||||
// Add all the conversations to the list control
|
||||
//
|
||||
int count = ConversationMgrClass::Get_Conversation_Count ();
|
||||
for (int index = 0; index < count; index ++) {
|
||||
ConversationClass *conversation = ConversationMgrClass::Peek_Conversation (index);
|
||||
Add_Conversation (conversation);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnAdd
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationListDialogClass::OnAdd (void)
|
||||
{
|
||||
//
|
||||
// Let the user create a new conversation
|
||||
//
|
||||
EditConversationDialogClass dialog (this);
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Add this new conversation to the list control
|
||||
//
|
||||
ConversationClass *conversation = dialog.Peek_Conversation ();
|
||||
if (conversation != NULL) {
|
||||
Add_Conversation (conversation);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOK
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationListDialogClass::OnOK (void)
|
||||
{
|
||||
//
|
||||
// Start fresh
|
||||
//
|
||||
ConversationMgrClass::Reset ();
|
||||
|
||||
//
|
||||
// Get all the conversations from the list control and add them to the
|
||||
// conversation manager
|
||||
//
|
||||
for (int index = 0; index < m_ListCtrl.GetItemCount (); index ++) {
|
||||
ConversationClass *conversation = (ConversationClass *)m_ListCtrl.GetItemData (index);
|
||||
if (conversation != NULL) {
|
||||
ConversationMgrClass::Add_Conversation (conversation);
|
||||
}
|
||||
}
|
||||
|
||||
::Set_Modified (true);
|
||||
CDialog::OnOK ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Add_Conversation
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationListDialogClass::Add_Conversation (ConversationClass *conversation)
|
||||
{
|
||||
ASSERT (conversation != NULL);
|
||||
if (conversation == NULL) {
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert this conversation into the list control
|
||||
//
|
||||
int item_index = m_ListCtrl.InsertItem (0xFFFF, conversation->Get_Name ());
|
||||
if (item_index != -1) {
|
||||
conversation->Add_Ref ();
|
||||
m_ListCtrl.SetItemData (item_index, (DWORD)conversation);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Conversation
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationListDialogClass::Update_Conversation (int index)
|
||||
{
|
||||
//
|
||||
// Update the conversation's name in the list control
|
||||
//
|
||||
ConversationClass *conversation = (ConversationClass *)m_ListCtrl.GetItemData (index);
|
||||
if (conversation != NULL) {
|
||||
m_ListCtrl.SetItemText (index, 0, conversation->Get_Name ());
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDblclkConversationList
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationListDialogClass::OnDblclkConversationList
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT * pResult
|
||||
)
|
||||
{
|
||||
(*pResult) = 0;
|
||||
|
||||
//
|
||||
// Lookup the conversation object associated with the entry the user
|
||||
// double clicked on
|
||||
//
|
||||
int sel_index = m_ListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
|
||||
if (sel_index >= 0) {
|
||||
ConversationClass *conversation = (ConversationClass *)m_ListCtrl.GetItemData (sel_index);
|
||||
if (conversation != NULL) {
|
||||
|
||||
//
|
||||
// Allow the user to edit this entry
|
||||
//
|
||||
EditConversationDialogClass dialog (this);
|
||||
dialog.Set_Conversation (conversation);
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
Update_Conversation (sel_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDeleteitemConversationList
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationListDialogClass::OnDeleteitemConversationList
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT* pResult
|
||||
)
|
||||
{
|
||||
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
|
||||
(*pResult) = 0;
|
||||
|
||||
//
|
||||
// Release our hold on this conversation object
|
||||
//
|
||||
ConversationClass *conversation = (ConversationClass *)m_ListCtrl.GetItemData (pNMListView->iItem);
|
||||
REF_PTR_RELEASE (conversation);
|
||||
|
||||
m_ListCtrl.SetItemData (pNMListView->iItem, 0L);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDeleteitemConversationList
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationListDialogClass::OnKeydownConversationList
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT * pResult
|
||||
)
|
||||
{
|
||||
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
|
||||
(*pResult) = 0;
|
||||
|
||||
if (pLVKeyDow->wVKey == VK_DELETE) {
|
||||
|
||||
//
|
||||
// Delete all the selected items
|
||||
//
|
||||
int index = -1;
|
||||
while ((index = m_ListCtrl.GetNextItem (-1, LVNI_SELECTED | LVNI_ALL)) >= 0) {
|
||||
m_ListCtrl.DeleteItem (index);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
91
Code/Tools/LevelEdit/EditConversationListDialog.h
Normal file
91
Code/Tools/LevelEdit/EditConversationListDialog.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_EDITCONVERSATIONLISTDIALOG_H__29A296FF_374F_46F9_A2F8_496C5307D103__INCLUDED_)
|
||||
#define AFX_EDITCONVERSATIONLISTDIALOG_H__29A296FF_374F_46F9_A2F8_496C5307D103__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class ConversationClass;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditConversationListDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class EditConversationListDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
EditConversationListDialogClass(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(EditConversationListDialogClass)
|
||||
enum { IDD = IDD_CONVERSATION_LIST };
|
||||
CListCtrl m_ListCtrl;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(EditConversationListDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(EditConversationListDialogClass)
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnAdd();
|
||||
virtual void OnOK();
|
||||
afx_msg void OnDblclkConversationList(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnDeleteitemConversationList(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnKeydownConversationList(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void Add_Conversation (ConversationClass *conversation);
|
||||
void Update_Conversation (int sel_index);
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_EDITCONVERSATIONLISTDIALOG_H__29A296FF_374F_46F9_A2F8_496C5307D103__INCLUDED_)
|
||||
188
Code/Tools/LevelEdit/EditConversationRemarkDialog.cpp
Normal file
188
Code/Tools/LevelEdit/EditConversationRemarkDialog.cpp
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// EditConversationRemarkDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveledit.h"
|
||||
#include "editconversationremarkdialog.h"
|
||||
#include "stringsmgr.h"
|
||||
#include "translatedb.h"
|
||||
#include "translateobj.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const int ORATOR_MAX = 7;
|
||||
|
||||
typedef struct _ORATOR_BUTTON_INFO
|
||||
{
|
||||
int button_id;
|
||||
int icon_id;
|
||||
} ORATOR_BUTTON_INFO;
|
||||
|
||||
const ORATOR_BUTTON_INFO ORATOR_BUTTONS[ORATOR_MAX] =
|
||||
{
|
||||
{ IDC_ORATOR1_RADIO, IDI_ORATOR1 },
|
||||
{ IDC_ORATOR2_RADIO, IDI_ORATOR2 },
|
||||
{ IDC_ORATOR3_RADIO, IDI_ORATOR3 },
|
||||
{ IDC_ORATOR4_RADIO, IDI_ORATOR4 },
|
||||
{ IDC_ORATOR5_RADIO, IDI_ORATOR5 },
|
||||
{ IDC_ORATOR6_RADIO, IDI_ORATOR6 },
|
||||
{ IDC_ORATOR7_RADIO, IDI_ORATOR7 }
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditConversationRemarkDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
EditConversationRemarkDialogClass::EditConversationRemarkDialogClass(CWnd* pParent /*=NULL*/)
|
||||
: m_OratorBitmask (1),
|
||||
CDialog(EditConversationRemarkDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(EditConversationRemarkDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationRemarkDialogClass::DoDataExchange (CDataExchange *pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(EditConversationRemarkDialogClass)
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(EditConversationRemarkDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(EditConversationRemarkDialogClass)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
EditConversationRemarkDialogClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
//
|
||||
// Assign icons to each of the orator buttons
|
||||
//
|
||||
for (int index = 0; index < ORATOR_MAX; index ++) {
|
||||
HICON icon = ::LoadIcon (::AfxGetResourceHandle (), MAKEINTRESOURCE (ORATOR_BUTTONS[index].icon_id));
|
||||
SendDlgItemMessage (ORATOR_BUTTONS[index].button_id, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icon);
|
||||
|
||||
//
|
||||
// Disable this button if the user hasn't configured the orator
|
||||
//
|
||||
if ((m_OratorBitmask & (1 << index)) == false) {
|
||||
::EnableWindow (::GetDlgItem (m_hWnd, ORATOR_BUTTONS[index].button_id), FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Select the current orator
|
||||
//
|
||||
SendDlgItemMessage (ORATOR_BUTTONS[Remark.Get_Orator_ID ()].button_id, BM_SETCHECK, TRUE);
|
||||
|
||||
//
|
||||
// Put the animation name into the text field
|
||||
//
|
||||
SetDlgItemText (IDC_ANIMATION_NAME, Remark.Get_Animation_Name ());
|
||||
|
||||
//
|
||||
// Calculate the rectangle where we are to display the string picker
|
||||
//
|
||||
CRect rect;
|
||||
::GetWindowRect (::GetDlgItem (m_hWnd, IDC_PICKER_AREA), &rect);
|
||||
ScreenToClient (&rect);
|
||||
|
||||
//
|
||||
// Create the string picker
|
||||
//
|
||||
StringPicker.Set_Selection (Remark.Get_Text_ID ());
|
||||
StringPicker.Create (this);
|
||||
StringPicker.SetWindowPos (NULL, rect.left, rect.top, rect.Width (), rect.Height (), SWP_NOZORDER);
|
||||
StringPicker.ShowWindow (SW_SHOW);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOK
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditConversationRemarkDialogClass::OnOK (void)
|
||||
{
|
||||
//
|
||||
// Assign icons to each of the orator buttons
|
||||
//
|
||||
for (int index = 0; index < ORATOR_MAX; index ++) {
|
||||
if (SendDlgItemMessage (ORATOR_BUTTONS[index].button_id, BM_GETCHECK) == 1) {
|
||||
Remark.Set_Orator_ID (index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get the selected string from the picker object
|
||||
//
|
||||
Remark.Set_Text_ID (StringPicker.Get_Selection ());
|
||||
|
||||
//
|
||||
// Get the animation name from the text field
|
||||
//
|
||||
CString animation_name;
|
||||
GetDlgItemText (IDC_ANIMATION_NAME, animation_name);
|
||||
|
||||
//
|
||||
// Pass the animation name onto the remark object
|
||||
//
|
||||
Remark.Set_Animation_Name (animation_name);
|
||||
|
||||
CDialog::OnOK ();
|
||||
return ;
|
||||
}
|
||||
|
||||
94
Code/Tools/LevelEdit/EditConversationRemarkDialog.h
Normal file
94
Code/Tools/LevelEdit/EditConversationRemarkDialog.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_EDITCONVERSATIONREMARKDIALOG_H__9FDB5AC9_9866_40F9_B912_2679C63EB92D__INCLUDED_)
|
||||
#define AFX_EDITCONVERSATIONREMARKDIALOG_H__9FDB5AC9_9866_40F9_B912_2679C63EB92D__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "resource.h"
|
||||
#include "stringpickerdialog.h"
|
||||
#include "conversationremark.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditConversationRemarkDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class EditConversationRemarkDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
EditConversationRemarkDialogClass(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(EditConversationRemarkDialogClass)
|
||||
enum { IDD = IDD_EDIT_CONVERSATION_REMARK };
|
||||
CSpinButtonCtrl m_OratorIDSpin;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(EditConversationRemarkDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(EditConversationRemarkDialogClass)
|
||||
virtual BOOL OnInitDialog();
|
||||
virtual void OnOK();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Set_Remark (const ConversationRemarkClass &remark) { Remark = remark; }
|
||||
const ConversationRemarkClass & Get_Remark (void) const { return Remark; }
|
||||
|
||||
void Set_Orator_Bitmask (int mask = 0x00000001) { m_OratorBitmask = mask; }
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Protected member data
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int m_OratorBitmask;
|
||||
ConversationRemarkClass Remark;
|
||||
|
||||
StringPickerDialogClass StringPicker;
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_EDITCONVERSATIONREMARKDIALOG_H__9FDB5AC9_9866_40F9_B912_2679C63EB92D__INCLUDED_)
|
||||
548
Code/Tools/LevelEdit/EditDialogueDialog.cpp
Normal file
548
Code/Tools/LevelEdit/EditDialogueDialog.cpp
Normal file
@@ -0,0 +1,548 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// EditDialogueDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveledit.h"
|
||||
#include "editdialoguedialog.h"
|
||||
#include "dialogue.h"
|
||||
#include "translatedb.h"
|
||||
#include "translateobj.h"
|
||||
#include "utils.h"
|
||||
#include "conversationpickerdialog.h"
|
||||
#include "conversationmgr.h"
|
||||
#include "conversation.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
COL_WEIGHT = 0,
|
||||
COL_TEXT
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditDialogueDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
EditDialogueDialogClass::EditDialogueDialogClass(CWnd* pParent /*=NULL*/)
|
||||
: m_Dialogue (NULL),
|
||||
CDialog(EditDialogueDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(EditDialogueDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::DoDataExchange (CDataExchange *pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(EditDialogueDialogClass)
|
||||
DDX_Control(pDX, IDC_SELECTED_WEIGHT_SPIN, m_SelectedWeightSpin);
|
||||
DDX_Control(pDX, IDC_SILENCE_WEIGHT_SPIN, m_SilenceWeightSpin);
|
||||
DDX_Control(pDX, IDC_REMARK_LIST, m_ListCtrl);
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(EditDialogueDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(EditDialogueDialogClass)
|
||||
ON_BN_CLICKED(IDC_ADD, OnAdd)
|
||||
ON_BN_CLICKED(IDC_DELETE, OnDelete)
|
||||
ON_NOTIFY(NM_DBLCLK, IDC_REMARK_LIST, OnDblclkOptionList)
|
||||
ON_NOTIFY(LVN_DELETEITEM, IDC_REMARK_LIST, OnDeleteitemOptionList)
|
||||
ON_NOTIFY(LVN_ITEMCHANGED, IDC_REMARK_LIST, OnItemchangedRemarkList)
|
||||
ON_NOTIFY(UDN_DELTAPOS, IDC_SELECTED_WEIGHT_SPIN, OnDeltaposSelectedWeightSpin)
|
||||
ON_EN_KILLFOCUS(IDC_SELECTED_WEIGHT_EDIT, OnKillfocusSelectedWeightEdit)
|
||||
ON_WM_VSCROLL()
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
EditDialogueDialogClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
ASSERT (m_Dialogue != NULL);
|
||||
|
||||
//
|
||||
// Configure the list control
|
||||
//
|
||||
m_ListCtrl.InsertColumn (COL_WEIGHT, "Weight");
|
||||
m_ListCtrl.InsertColumn (COL_TEXT, "Text");
|
||||
m_ListCtrl.SetExtendedStyle (m_ListCtrl.GetExtendedStyle () | LVS_EX_FULLROWSELECT);
|
||||
|
||||
//
|
||||
// Choose a size for the list control's columns
|
||||
//
|
||||
CRect rect;
|
||||
m_ListCtrl.GetClientRect (&rect);
|
||||
rect.right -= ::GetSystemMetrics (SM_CXVSCROLL);
|
||||
m_ListCtrl.SetColumnWidth (COL_WEIGHT, rect.Width () / 6);
|
||||
m_ListCtrl.SetColumnWidth (COL_TEXT, (rect.Width () * 5) / 6);
|
||||
|
||||
//
|
||||
// Insert all of the options into the list control
|
||||
//
|
||||
DIALOGUE_OPTION_LIST &option_list = m_Dialogue->Get_Option_List ();
|
||||
for (int index = 0; index < option_list.Count (); index ++) {
|
||||
|
||||
//
|
||||
// Make a copy of the option and add it to our list
|
||||
//
|
||||
DialogueOptionClass *option = new DialogueOptionClass (*(option_list[index]));
|
||||
Insert_Entry (option);
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the silence controls
|
||||
//
|
||||
m_SilenceWeightSpin.SetRange (0, 100);
|
||||
m_SilenceWeightSpin.SetPos ((int)m_Dialogue->Get_Silence_Weight ());
|
||||
SetDlgItemInt (IDC_SILENCE_WEIGHT_EDIT, (int)m_Dialogue->Get_Silence_Weight ());
|
||||
|
||||
//
|
||||
// Configure the other weight controls
|
||||
//
|
||||
m_SelectedWeightSpin.SetRange (0, 10000);
|
||||
m_SelectedWeightSpin.SetPos (0);
|
||||
|
||||
//
|
||||
// Update the enabled state of some of the controls on the dialog
|
||||
//
|
||||
Update_Enabled_State ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOK
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::OnOK (void)
|
||||
{
|
||||
//
|
||||
// Read the silence configuration
|
||||
//
|
||||
int new_weight = GetDlgItemInt (IDC_SILENCE_WEIGHT_EDIT);
|
||||
m_Dialogue->Set_Silence_Weight (new_weight);
|
||||
|
||||
//
|
||||
// Start with a fresh list of options
|
||||
//
|
||||
m_Dialogue->Free_Options ();
|
||||
DIALOGUE_OPTION_LIST &option_list = m_Dialogue->Get_Option_List ();
|
||||
|
||||
//
|
||||
// Read all the options from the list control
|
||||
//
|
||||
int count = m_ListCtrl.GetItemCount ();
|
||||
for (int index = 0; index < count; index ++) {
|
||||
|
||||
//
|
||||
// Add this option to the dialogue's list
|
||||
//
|
||||
DialogueOptionClass *option = (DialogueOptionClass *)m_ListCtrl.GetItemData (index);
|
||||
if (option != NULL) {
|
||||
option_list.Add (option);
|
||||
m_ListCtrl.SetItemData (index, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
CDialog::OnOK ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnAdd
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::OnAdd (void)
|
||||
{
|
||||
//
|
||||
// Display a dialog that allows the user to edit this option
|
||||
//
|
||||
ConversationPickerDialogClass dialog (this);
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Create a new dialog option
|
||||
//
|
||||
DialogueOptionClass *option = new DialogueOptionClass;
|
||||
option->Set_Weight (1);
|
||||
option->Set_Conversation_ID (dialog.Get_Conversation ()->Get_ID ());
|
||||
|
||||
//
|
||||
// Add the new option to the list
|
||||
//
|
||||
Insert_Entry (option);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDelete
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::OnDelete (void)
|
||||
{
|
||||
//
|
||||
// Remove the currently selected item from the list control
|
||||
//
|
||||
int index = m_ListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
|
||||
if (index >= 0) {
|
||||
m_ListCtrl.DeleteItem (index);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDblclkOptionList
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::OnDblclkOptionList
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT * pResult
|
||||
)
|
||||
{
|
||||
//
|
||||
// Get the currently selected option
|
||||
//
|
||||
int index = m_ListCtrl.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
|
||||
if (index >= 0) {
|
||||
|
||||
DialogueOptionClass *option = (DialogueOptionClass *)m_ListCtrl.GetItemData (index);
|
||||
if (option != NULL) {
|
||||
|
||||
//
|
||||
// Display a dialog that allows the user to edit this option
|
||||
//
|
||||
ConversationPickerDialogClass dialog (this);
|
||||
|
||||
ConversationClass *conversation = NULL;
|
||||
conversation = ConversationMgrClass::Find_Conversation (option->Get_Conversation_ID ());
|
||||
dialog.Set_Conversation (conversation);
|
||||
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Update the entry in the list
|
||||
//
|
||||
option->Set_Conversation_ID (dialog.Get_Conversation ()->Get_ID ());
|
||||
Update_Entry (index);
|
||||
}
|
||||
|
||||
REF_PTR_RELEASE (conversation);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDeleteitemOptionList
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::OnDeleteitemOptionList
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT * pResult
|
||||
)
|
||||
{
|
||||
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
|
||||
(*pResult) = 0;
|
||||
|
||||
//
|
||||
// Free the associated DialogueOptionClass object
|
||||
//
|
||||
DialogueOptionClass *option = (DialogueOptionClass *)m_ListCtrl.GetItemData (pNMListView->iItem);
|
||||
if (option != NULL) {
|
||||
SAFE_DELETE (option);
|
||||
m_ListCtrl.SetItemData (pNMListView->iItem, NULL);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Entry
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::Update_Entry (int index)
|
||||
{
|
||||
DialogueOptionClass *option = (DialogueOptionClass *)m_ListCtrl.GetItemData (index);
|
||||
if (option != NULL) {
|
||||
|
||||
//
|
||||
// Update the weight column of the list control
|
||||
//
|
||||
CString weight_text;
|
||||
weight_text.Format ("%d", (int)option->Get_Weight ());
|
||||
m_ListCtrl.SetItemText (index, COL_WEIGHT, weight_text);
|
||||
|
||||
//
|
||||
// Lookup the string entry in our translation database
|
||||
//
|
||||
int conversation_id = option->Get_Conversation_ID ();
|
||||
ConversationClass *conversation = ConversationMgrClass::Find_Conversation (conversation_id);
|
||||
if (conversation != NULL) {
|
||||
|
||||
//
|
||||
// Put this text into the appropriate column in the list control
|
||||
//
|
||||
m_ListCtrl.SetItemText (index, COL_TEXT, conversation->Get_Name ());
|
||||
REF_PTR_RELEASE (conversation);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Insert_Entry
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::Insert_Entry (DialogueOptionClass *option)
|
||||
{
|
||||
ASSERT (option != NULL);
|
||||
if (option != NULL) {
|
||||
|
||||
CString weight_text;
|
||||
weight_text.Format ("%d", (int)option->Get_Weight ());
|
||||
|
||||
//
|
||||
// Add this option to the list control
|
||||
//
|
||||
int item_index = m_ListCtrl.InsertItem (m_ListCtrl.GetItemCount (), weight_text);
|
||||
if (item_index >= 0) {
|
||||
|
||||
//
|
||||
// Associate the object with the entry in the list control
|
||||
//
|
||||
m_ListCtrl.SetItemData (item_index, (DWORD)option);
|
||||
|
||||
//
|
||||
// Lookup the string entry in our translation database
|
||||
//
|
||||
int conversation_id = option->Get_Conversation_ID ();
|
||||
ConversationClass *conversation = ConversationMgrClass::Find_Conversation (conversation_id);
|
||||
if (conversation != NULL) {
|
||||
|
||||
//
|
||||
// Put this text into the appropriate column in the list control
|
||||
//
|
||||
m_ListCtrl.SetItemText (item_index, COL_TEXT, conversation->Get_Name ());
|
||||
REF_PTR_RELEASE (conversation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnItemchangedRemarkList
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::OnItemchangedRemarkList
|
||||
(
|
||||
NMHDR * pNMHDR,
|
||||
LRESULT * pResult
|
||||
)
|
||||
{
|
||||
NM_LISTVIEW *pNMListView = (NM_LISTVIEW *)pNMHDR;
|
||||
(*pResult) = 0;
|
||||
|
||||
if (pNMListView->uChanged & LVIF_STATE) {
|
||||
Update_Enabled_State ();
|
||||
|
||||
//
|
||||
// Is there a currently selected item?
|
||||
//
|
||||
int item_index = m_ListCtrl.GetNextItem (-1, LVNI_SELECTED | LVNI_ALL);
|
||||
if (item_index >= 0) {
|
||||
|
||||
//
|
||||
// Update the weight of the selected item
|
||||
//
|
||||
DialogueOptionClass *option = (DialogueOptionClass *)m_ListCtrl.GetItemData (item_index);
|
||||
if (option != NULL) {
|
||||
SetDlgItemInt (IDC_SELECTED_WEIGHT_EDIT, (int)option->Get_Weight ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Enabled_State
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::Update_Enabled_State (void)
|
||||
{
|
||||
int item_index = m_ListCtrl.GetNextItem (-1, LVNI_SELECTED | LVNI_ALL);
|
||||
bool enabled = (item_index >= 0);
|
||||
|
||||
::EnableWindow (::GetDlgItem (m_hWnd, IDC_DELETE), enabled);
|
||||
::EnableWindow (::GetDlgItem (m_hWnd, IDC_SELECTED_WEIGHT_EDIT), enabled);
|
||||
::EnableWindow (::GetDlgItem (m_hWnd, IDC_SELECTED_WEIGHT_SPIN), enabled);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnDeltaposSelectedWeightSpin
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::OnDeltaposSelectedWeightSpin
|
||||
(
|
||||
NMHDR *pNMHDR,
|
||||
LRESULT *pResult
|
||||
)
|
||||
{
|
||||
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
|
||||
(*pResult) = 0;
|
||||
|
||||
//Update_Current_Weight ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnKillfocusSelectedWeightEdit
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::OnKillfocusSelectedWeightEdit (void)
|
||||
{
|
||||
Update_Current_Weight ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Current_Weight
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::Update_Current_Weight (void)
|
||||
{
|
||||
//
|
||||
// Is there a currently selected item?
|
||||
//
|
||||
int item_index = m_ListCtrl.GetNextItem (-1, LVNI_SELECTED | LVNI_ALL);
|
||||
if (item_index >= 0) {
|
||||
|
||||
DialogueOptionClass *option = (DialogueOptionClass *)m_ListCtrl.GetItemData (item_index);
|
||||
if (option != NULL) {
|
||||
|
||||
//
|
||||
// Get the weight
|
||||
//
|
||||
int weight = GetDlgItemInt (IDC_SELECTED_WEIGHT_EDIT);
|
||||
|
||||
//
|
||||
// Update the weight
|
||||
//
|
||||
option->Set_Weight ((float)weight);
|
||||
Update_Entry (item_index);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnVScroll
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditDialogueDialogClass::OnVScroll
|
||||
(
|
||||
UINT nSBCode,
|
||||
UINT nPos,
|
||||
CScrollBar *pScrollBar
|
||||
)
|
||||
{
|
||||
Update_Current_Weight ();
|
||||
return ;
|
||||
}
|
||||
111
Code/Tools/LevelEdit/EditDialogueDialog.h
Normal file
111
Code/Tools/LevelEdit/EditDialogueDialog.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_EDITDIALOGUEDIALOG_H__BC974F00_1204_4644_96D7_7BFC1BC5BBCC__INCLUDED_)
|
||||
#define AFX_EDITDIALOGUEDIALOG_H__BC974F00_1204_4644_96D7_7BFC1BC5BBCC__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class DialogueClass;
|
||||
class DialogueOptionClass;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditDialogueDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class EditDialogueDialogClass : public CDialog
|
||||
{
|
||||
public:
|
||||
EditDialogueDialogClass (CWnd *pParent = NULL);
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(EditDialogueDialogClass)
|
||||
enum { IDD = IDD_EDIT_DIALOGUE };
|
||||
CSpinButtonCtrl m_SelectedWeightSpin;
|
||||
CSpinButtonCtrl m_SilenceWeightSpin;
|
||||
CListCtrl m_ListCtrl;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(EditDialogueDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(EditDialogueDialogClass)
|
||||
virtual BOOL OnInitDialog();
|
||||
virtual void OnOK();
|
||||
afx_msg void OnAdd();
|
||||
afx_msg void OnDelete();
|
||||
afx_msg void OnDblclkOptionList(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnDeleteitemOptionList(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnItemchangedRemarkList(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnDeltaposSelectedWeightSpin(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
afx_msg void OnKillfocusSelectedWeightEdit();
|
||||
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////
|
||||
void Set_Dialogue (DialogueClass *dialogue) { m_Dialogue = dialogue; }
|
||||
DialogueClass * Get_Dialogue (void) const { return m_Dialogue; }
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Update_Entry (int index);
|
||||
void Insert_Entry (DialogueOptionClass *option);
|
||||
|
||||
void Update_Enabled_State (void);
|
||||
void Update_Current_Weight (void);
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////////
|
||||
DialogueClass * m_Dialogue;
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_EDITDIALOGUEDIALOG_H__BC974F00_1204_4644_96D7_7BFC1BC5BBCC__INCLUDED_)
|
||||
208
Code/Tools/LevelEdit/EditFilenameListDialog.cpp
Normal file
208
Code/Tools/LevelEdit/EditFilenameListDialog.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// EditFilenameListDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveledit.h"
|
||||
#include "editfilenamelistdialog.h"
|
||||
#include "utils.h"
|
||||
#include "filemgr.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditFilenameListDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
EditFilenameListDialogClass::EditFilenameListDialogClass(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(EditFilenameListDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(EditFilenameListDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditFilenameListDialogClass::DoDataExchange (CDataExchange *pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(EditFilenameListDialogClass)
|
||||
DDX_Control(pDX, IDC_FILENAME_LIST_CTRL, m_ListCtrl);
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(EditFilenameListDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(EditFilenameListDialogClass)
|
||||
ON_BN_CLICKED(IDC_ADD, OnAdd)
|
||||
ON_NOTIFY(LVN_KEYDOWN, IDC_FILENAME_LIST_CTRL, OnKeydownFilenameListCtrl)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnAdd
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditFilenameListDialogClass::OnAdd (void)
|
||||
{
|
||||
CFileDialog dialog ( TRUE,
|
||||
".w3d",
|
||||
NULL,
|
||||
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_ALLOWMULTISELECT,
|
||||
"Westwood 3D Files (*.w3d)|*.w3d|Texture Files (*.tga)|*.tga|Sound Files (*.wav,*.mp3)|*.wav;*.mp3|All Files|*.*||",
|
||||
this);
|
||||
|
||||
TCHAR filename_list[MAX_PATH*20] = { 0 };
|
||||
dialog.m_ofn.lpstrFile = filename_list;
|
||||
dialog.m_ofn.nMaxFile = sizeof (filename_list);
|
||||
|
||||
//
|
||||
// Start the user off in the assets directory
|
||||
//
|
||||
dialog.m_ofn.lpstrInitialDir = ::Get_File_Mgr ()->Get_Base_Path ();
|
||||
|
||||
//
|
||||
// Ask the user to select the files
|
||||
//
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Add all the new filenames to the list
|
||||
//
|
||||
POSITION pos = dialog.GetStartPosition ();
|
||||
while (pos != NULL) {
|
||||
CString full_path = (LPCTSTR)dialog.GetNextPathName (pos);
|
||||
if (::Get_File_Mgr ()->Is_Path_Valid (full_path)) {
|
||||
m_ListCtrl.InsertItem (0xFF, (LPCTSTR)::Get_File_Mgr ()->Make_Relative_Path (full_path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnKeydownFilenameListCtrl
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditFilenameListDialogClass::OnKeydownFilenameListCtrl
|
||||
(
|
||||
NMHDR *pNMHDR,
|
||||
LRESULT *pResult
|
||||
)
|
||||
{
|
||||
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
|
||||
(*pResult) = 0;
|
||||
|
||||
|
||||
if (pLVKeyDow->wVKey == VK_DELETE) {
|
||||
|
||||
//
|
||||
// Delete all the selected items
|
||||
//
|
||||
int index = -1;
|
||||
while ((index = m_ListCtrl.GetNextItem (-1, LVNI_SELECTED | LVNI_ALL)) >= 0) {
|
||||
m_ListCtrl.DeleteItem (index);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
EditFilenameListDialogClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
//
|
||||
// Add a single column to the list control
|
||||
//
|
||||
m_ListCtrl.InsertColumn (0, "Filename");
|
||||
|
||||
//
|
||||
// Size the column
|
||||
//
|
||||
CRect rect;
|
||||
m_ListCtrl.GetClientRect (&rect);
|
||||
rect.right -= ::GetSystemMetrics (SM_CXVSCROLL);
|
||||
m_ListCtrl.SetColumnWidth(0, rect.Width ());
|
||||
|
||||
//
|
||||
// Add all the initial filenames to the list control
|
||||
//
|
||||
for (int index = 0; index < m_List.Count (); index ++) {
|
||||
m_ListCtrl.InsertItem (0xFF, m_List[index]);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOK
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditFilenameListDialogClass::OnOK (void)
|
||||
{
|
||||
//
|
||||
// Start fresh
|
||||
//
|
||||
m_List.Delete_All ();
|
||||
|
||||
//
|
||||
// Rebuild the list from the user's entries in the list control
|
||||
//
|
||||
for (int index = 0; index < m_ListCtrl.GetItemCount (); index ++) {
|
||||
StringClass filename = (LPCTSTR)m_ListCtrl.GetItemText (index, 0);
|
||||
m_List.Add (filename);
|
||||
}
|
||||
|
||||
CDialog::OnOK ();
|
||||
return ;
|
||||
}
|
||||
87
Code/Tools/LevelEdit/EditFilenameListDialog.h
Normal file
87
Code/Tools/LevelEdit/EditFilenameListDialog.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_EDITFILENAMELISTDIALOG_H__C6B399CD_EACA_4457_9796_05B81F576E82__INCLUDED_)
|
||||
#define AFX_EDITFILENAMELISTDIALOG_H__C6B399CD_EACA_4457_9796_05B81F576E82__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "resource.h"
|
||||
#include "vector.h"
|
||||
#include "wwstring.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditFilenameListDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class EditFilenameListDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
EditFilenameListDialogClass(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(EditFilenameListDialogClass)
|
||||
enum { IDD = IDD_EDIT_FILENAME_LIST };
|
||||
CListCtrl m_ListCtrl;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(EditFilenameListDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(EditFilenameListDialogClass)
|
||||
afx_msg void OnAdd();
|
||||
afx_msg void OnKeydownFilenameListCtrl(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
virtual BOOL OnInitDialog();
|
||||
virtual void OnOK();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DynamicVectorClass<StringClass> & Get_List (void) { return m_List; }
|
||||
void Set_List (DynamicVectorClass<StringClass> &list) { m_List = list; }
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DynamicVectorClass<StringClass> m_List;
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_EDITFILENAMELISTDIALOG_H__C6B399CD_EACA_4457_9796_05B81F576E82__INCLUDED_)
|
||||
146
Code/Tools/LevelEdit/EditRemarkDialog.cpp
Normal file
146
Code/Tools/LevelEdit/EditRemarkDialog.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// EditRemarkDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#if 0
|
||||
|
||||
#include "leveledit.h"
|
||||
#include "editremarkdialog.h"
|
||||
#include "dialogue.h"
|
||||
#include "translatedb.h"
|
||||
#include "translateobj.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
COL_TEXT = 0
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditRemarkDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
EditRemarkDialogClass::EditRemarkDialogClass(CWnd* pParent /*=NULL*/)
|
||||
: m_Remark (NULL),
|
||||
CDialog(EditRemarkDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(EditRemarkDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditRemarkDialogClass::DoDataExchange (CDataExchange *pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(EditRemarkDialogClass)
|
||||
DDX_Control(pDX, IDC_WEIGHT_SPIN, m_WeightSpin);
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(EditRemarkDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(EditRemarkDialogClass)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
EditRemarkDialogClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog ();
|
||||
ASSERT (m_Remark != NULL);
|
||||
|
||||
//
|
||||
// Calculate the rectangle where we are to display the string picker
|
||||
//
|
||||
CRect rect;
|
||||
::GetWindowRect (::GetDlgItem (m_hWnd, IDC_PICKER_AREA), &rect);
|
||||
ScreenToClient (&rect);
|
||||
|
||||
//
|
||||
// Create the string picker
|
||||
//
|
||||
StringPicker.Set_Selection (m_Remark->Get_Text_ID ());
|
||||
StringPicker.Create (this);
|
||||
StringPicker.SetWindowPos (NULL, rect.left, rect.top, rect.Width (), rect.Height (), SWP_NOZORDER);
|
||||
StringPicker.ShowWindow (SW_SHOW);
|
||||
|
||||
//
|
||||
// Configure the weight controls
|
||||
//
|
||||
m_WeightSpin.SetRange (0, 100);
|
||||
m_WeightSpin.SetPos ((int)m_Remark->Get_Weight ());
|
||||
SetDlgItemInt (IDC_WEIGHT_EDIT, (int)m_Remark->Get_Weight ());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOK
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditRemarkDialogClass::OnOK (void)
|
||||
{
|
||||
//
|
||||
// Read the silence configuration
|
||||
//
|
||||
int new_weight = GetDlgItemInt (IDC_WEIGHT_EDIT);
|
||||
m_Remark->Set_Weight (new_weight);
|
||||
|
||||
//
|
||||
// Get the selected string from the picker object
|
||||
//
|
||||
m_Remark->Set_Text_ID (StringPicker.Get_Selection ());
|
||||
|
||||
CDialog::OnOK ();
|
||||
return ;
|
||||
}
|
||||
|
||||
#endif //0
|
||||
91
Code/Tools/LevelEdit/EditRemarkDialog.h
Normal file
91
Code/Tools/LevelEdit/EditRemarkDialog.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_EDITREMARKDIALOG_H__6A88EE92_3F48_4C4D_A4EA_5C519713E6A9__INCLUDED_)
|
||||
#define AFX_EDITREMARKDIALOG_H__6A88EE92_3F48_4C4D_A4EA_5C519713E6A9__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "resource.h"
|
||||
#include "stringpickerdialog.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class DialogueRemarkClass;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditRemarkDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class EditRemarkDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
EditRemarkDialogClass(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(EditRemarkDialogClass)
|
||||
enum { IDD = IDD_EDIT_REMARK };
|
||||
CSpinButtonCtrl m_WeightSpin;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(EditRemarkDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(EditRemarkDialogClass)
|
||||
virtual BOOL OnInitDialog();
|
||||
virtual void OnOK();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Set_Remark (DialogueRemarkClass *remark) { m_Remark = remark; }
|
||||
DialogueRemarkClass * Get_Remark (void) const { return m_Remark; }
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DialogueRemarkClass * m_Remark;
|
||||
StringPickerDialogClass StringPicker;
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_EDITREMARKDIALOG_H__6A88EE92_3F48_4C4D_A4EA_5C519713E6A9__INCLUDED_)
|
||||
402
Code/Tools/LevelEdit/EditScript.cpp
Normal file
402
Code/Tools/LevelEdit/EditScript.cpp
Normal file
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/EditScript.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 11/02/00 4:17p $*
|
||||
* *
|
||||
* $Revision:: 6 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "editscript.h"
|
||||
#include "..\..\scripts\ScriptEvents.H"
|
||||
#include "scripts.h"
|
||||
#include "chunkio.h"
|
||||
#include "scriptmgr.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
CHUNKID_VARIABLES = 0x10271120,
|
||||
CHUNKID_VALUES
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VARID_NAME = 0x01,
|
||||
VARID_PARAM_DESC,
|
||||
VARID_VALUES
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditScriptClass
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
EditScriptClass::EditScriptClass (void)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditScriptClass
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
EditScriptClass::EditScriptClass (const EditScriptClass &src)
|
||||
{
|
||||
*this = src;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~EditScriptClass
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
EditScriptClass::~EditScriptClass (void)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// operator=
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
const EditScriptClass &
|
||||
EditScriptClass::operator= (const EditScriptClass &src)
|
||||
{
|
||||
m_Name = src.m_Name;
|
||||
m_ParamValues = src.m_ParamValues;
|
||||
m_ParamDescription = src.m_ParamDescription;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// operator==
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditScriptClass::operator== (const EditScriptClass &src)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
// Are the params the same?
|
||||
retval &= bool(m_ParamValues.Count () == src.m_ParamValues.Count ());
|
||||
retval &= bool(m_ParamDescription.Compare_No_Case (src.m_ParamDescription) == 0);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set_Composite_Values
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditScriptClass::Set_Composite_Values (LPCTSTR values)
|
||||
{
|
||||
// Build a list of values from the composite string
|
||||
CString *value_list = NULL;
|
||||
int count = ::Build_List_From_String (values, ",", &value_list);
|
||||
|
||||
// Pass these values onto our list
|
||||
for (int index = 0; (index < m_ParamValues.Count ()) && (index < count); index ++) {
|
||||
m_ParamValues[index].value = value_list[index];
|
||||
}
|
||||
|
||||
SAFE_DELETE_ARRAY (value_list);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Build_Composite_String
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
CString
|
||||
EditScriptClass::Build_Composite_String (void) const
|
||||
{
|
||||
CString composite_string;
|
||||
|
||||
// Build a composite string out of the values for each param
|
||||
int count = m_ParamValues.Count ();
|
||||
for (int index = 0; index < count; index ++) {
|
||||
const PARAM_VALUE &value = m_ParamValues[index];
|
||||
composite_string += value.value;
|
||||
|
||||
// Make sure the entries are comma delimited
|
||||
if (index != (count - 1)) {
|
||||
composite_string += ",";
|
||||
}
|
||||
}
|
||||
|
||||
// Return a string object containing the values
|
||||
return composite_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update_Data
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditScriptClass::Update_Data (void)
|
||||
{
|
||||
// Start with a clean list of values
|
||||
m_ParamValues.Delete_All ();
|
||||
|
||||
// Build a list of parameters from the description string
|
||||
CString *param_list = NULL;
|
||||
int count = ::Build_List_From_String (m_ParamDescription, ",", ¶m_list);
|
||||
|
||||
// Loop through the paramter descriptions
|
||||
for (int index = 0; index < count; index ++) {
|
||||
CString param_desc = param_list[index];
|
||||
|
||||
CString name = param_desc;
|
||||
CString def_value;
|
||||
CString type;
|
||||
|
||||
// Look for a default value and a type specifier
|
||||
int def_index = param_desc.Find ('=');
|
||||
int type_index = param_desc.Find (':');
|
||||
|
||||
// Was there a type specifier?
|
||||
if (type_index != -1) {
|
||||
name = param_desc.Left (type_index);
|
||||
type = &(((LPCTSTR)param_desc)[type_index+1]);
|
||||
type.TrimLeft ();
|
||||
type.TrimRight ();
|
||||
param_desc = name;
|
||||
}
|
||||
|
||||
// Was there a default value?
|
||||
if (def_index != -1) {
|
||||
name = param_desc.Left (def_index);
|
||||
def_value = &(((LPCTSTR)param_desc)[def_index+1]);
|
||||
}
|
||||
|
||||
//
|
||||
// Add this parameter to our list
|
||||
//
|
||||
PARAM_VALUE value;
|
||||
value.name = name;
|
||||
value.value = def_value;
|
||||
value.type = String_To_Type (type);
|
||||
m_ParamValues.Add (value);
|
||||
}
|
||||
|
||||
SAFE_DELETE_ARRAY (param_list);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String_To_Type
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
PARAM_TYPES
|
||||
EditScriptClass::String_To_Type (LPCTSTR type_name)
|
||||
{
|
||||
// Look through all the known specifiers and see if any match
|
||||
PARAM_TYPES type = PARAM_TYPE_INT;
|
||||
bool found = false;
|
||||
for (int type_index = 0; (type_index < PARAM_TYPE_COUNT) && (found == false); type_index ++) {
|
||||
|
||||
// Is this the type specifier we were looking for?
|
||||
if (::lstrcmpi (type_name, PARAM_TYPE_STRINGS[type_index]) == 0) {
|
||||
type = (PARAM_TYPES)type_index;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the type specifier ID
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create_Script
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
ScriptClass *
|
||||
EditScriptClass::Create_Script (void)
|
||||
{
|
||||
//
|
||||
// Create the new script
|
||||
//
|
||||
ScriptClass *script = ScriptManager::Create_Script (m_Name);
|
||||
if (script != NULL) {
|
||||
|
||||
//
|
||||
// Convert our params to a string and pass them
|
||||
// onto the script
|
||||
//
|
||||
CString params = Build_Composite_String ();
|
||||
script->Set_Parameters_String (params);
|
||||
}
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditScriptClass::Save (ChunkSaveClass &csave)
|
||||
{
|
||||
csave.Begin_Chunk (CHUNKID_VARIABLES);
|
||||
|
||||
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_NAME, m_Name);
|
||||
//WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_PARAM_DESC, m_ParamDescription);
|
||||
|
||||
//StringClass values = (LPCTSTR)Build_Composite_String ();
|
||||
//WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_VALUES, values);
|
||||
|
||||
csave.End_Chunk ();
|
||||
|
||||
csave.Begin_Chunk (CHUNKID_VALUES);
|
||||
StringClass values = (LPCTSTR)Build_Composite_String ();
|
||||
csave.Write ((const char *)values, values.Get_Length () + 1);
|
||||
csave.End_Chunk ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditScriptClass::Load (ChunkLoadClass &cload)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
while (cload.Open_Chunk ()) {
|
||||
switch (cload.Cur_Chunk_ID ())
|
||||
{
|
||||
case CHUNKID_VARIABLES:
|
||||
retval &= Load_Variables (cload);
|
||||
break;
|
||||
|
||||
case CHUNKID_VALUES:
|
||||
{
|
||||
//
|
||||
// Read the parameter value string from the chunk
|
||||
//
|
||||
StringClass values;
|
||||
int len = cload.Cur_Chunk_Length ();
|
||||
cload.Read (values.Get_Buffer (len), len);
|
||||
|
||||
//
|
||||
// Store the parameter values in our internal data structures
|
||||
//
|
||||
Set_Composite_Values (values);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Chunk ();
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_Variables
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditScriptClass::Load_Variables (ChunkLoadClass &cload)
|
||||
{
|
||||
StringClass values;
|
||||
|
||||
//
|
||||
// Loop through all the microchunks that define the variables
|
||||
//
|
||||
while (cload.Open_Micro_Chunk ()) {
|
||||
switch (cload.Cur_Micro_Chunk_ID ()) {
|
||||
|
||||
READ_MICRO_CHUNK_WWSTRING (cload, VARID_NAME, m_Name);
|
||||
READ_MICRO_CHUNK_WWSTRING (cload, VARID_VALUES, values);
|
||||
}
|
||||
|
||||
cload.Close_Micro_Chunk ();
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure we use the current version of the parameter list
|
||||
//
|
||||
Lookup_Param_Description ();
|
||||
Set_Composite_Values (values);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Lookup_Param_Description
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditScriptClass::Lookup_Param_Description (void)
|
||||
{
|
||||
//
|
||||
// Try to find the default instance of the script
|
||||
//
|
||||
EditScriptClass *current_version = ScriptMgrClass::Find_Script (m_Name);
|
||||
if (current_version != NULL) {
|
||||
m_ParamDescription = current_version->m_ParamDescription;
|
||||
} else {
|
||||
m_ParamDescription = "";
|
||||
}
|
||||
|
||||
Update_Data ();
|
||||
return ;
|
||||
}
|
||||
230
Code/Tools/LevelEdit/EditScript.h
Normal file
230
Code/Tools/LevelEdit/EditScript.h
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/EditScript.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 11/02/00 3:57p $*
|
||||
* *
|
||||
* $Revision:: 3 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __EDIT_SCRIPT_H
|
||||
#define __EDIT_SCRIPT_H
|
||||
|
||||
#include "..\..\scripts\scriptevents.h"
|
||||
#include "vector.h"
|
||||
#include "utils.h"
|
||||
#include "wwstring.h"
|
||||
|
||||
|
||||
// Forward declarations
|
||||
class ChunkSaveClass;
|
||||
class ChunkLoadClass;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditScriptClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class EditScriptClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////////
|
||||
EditScriptClass (void);
|
||||
EditScriptClass (const EditScriptClass &src);
|
||||
virtual ~EditScriptClass (void);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public operators
|
||||
//////////////////////////////////////////////////////////////
|
||||
const EditScriptClass & operator= (const EditScriptClass &src);
|
||||
bool operator== (const EditScriptClass &src);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////
|
||||
EditScriptClass * Clone (void) { return new EditScriptClass (*this); }
|
||||
ScriptClass * Create_Script (void);
|
||||
|
||||
//
|
||||
// Name/string methods
|
||||
//
|
||||
LPCTSTR Get_Name (void) const;
|
||||
void Set_Name (LPCTSTR name);
|
||||
void Set_Param_Desc (LPCTSTR param_desc);
|
||||
void Lookup_Param_Description (void);
|
||||
CString Get_Composite_String (void) { return Build_Composite_String (); }
|
||||
void Set_Composite_Values (LPCTSTR values);
|
||||
|
||||
//
|
||||
// Param methods
|
||||
//
|
||||
int Get_Param_Count (void);
|
||||
LPCTSTR Get_Param_Value (int index);
|
||||
LPCTSTR Get_Param_Name (int index);
|
||||
PARAM_TYPES Get_Param_Type (int index);
|
||||
void Set_Param_Value (int index, LPCTSTR value);
|
||||
|
||||
//
|
||||
// Persistance methods
|
||||
//
|
||||
bool Save (ChunkSaveClass &csave);
|
||||
bool Load (ChunkLoadClass &cload);
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Protected data types
|
||||
//////////////////////////////////////////////////////////////
|
||||
typedef struct _PARAM_VALUE
|
||||
{
|
||||
CString name;
|
||||
CString value;
|
||||
PARAM_TYPES type;
|
||||
|
||||
bool operator== (const _PARAM_VALUE &src) { return (type == src.type) && (value == src.value) && (name == src.name); }
|
||||
bool operator!= (const _PARAM_VALUE &src) { return !(*this == src); }
|
||||
} PARAM_VALUE;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
//////////////////////////////////////////////////////////////
|
||||
bool Load_Variables (ChunkLoadClass &cload);
|
||||
CString Build_Composite_String (void) const;
|
||||
void Update_Data (void);
|
||||
PARAM_TYPES String_To_Type (LPCTSTR type_name);
|
||||
bool Valid_Index (int index) const { return (index >= 0) && (index < m_ParamValues.Count ()); }
|
||||
|
||||
private:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
StringClass m_Name;
|
||||
DynamicVectorClass<PARAM_VALUE> m_ParamValues;
|
||||
StringClass m_ParamDescription;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Set_Param_Desc
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
EditScriptClass::Set_Param_Desc (LPCTSTR param_desc)
|
||||
{
|
||||
m_ParamDescription = param_desc;
|
||||
Update_Data ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Get_Param_Count
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline int
|
||||
EditScriptClass::Get_Param_Count (void)
|
||||
{
|
||||
return m_ParamValues.Count ();;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Get_Param_Value
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline LPCTSTR
|
||||
EditScriptClass::Get_Param_Value (int index)
|
||||
{
|
||||
LPCTSTR value = NULL;
|
||||
|
||||
if (Valid_Index (index)) {
|
||||
value = m_ParamValues[index].value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Get_Param_Name
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline LPCTSTR
|
||||
EditScriptClass::Get_Param_Name (int index)
|
||||
{
|
||||
LPCTSTR name = NULL;
|
||||
|
||||
if (Valid_Index (index)) {
|
||||
name = m_ParamValues[index].name;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Get_Param_Type
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline PARAM_TYPES
|
||||
EditScriptClass::Get_Param_Type (int index)
|
||||
{
|
||||
PARAM_TYPES type = PARAM_TYPE_INT;
|
||||
|
||||
if (Valid_Index (index)) {
|
||||
type = m_ParamValues[index].type;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Set_Param_Value
|
||||
//////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
EditScriptClass::Set_Param_Value (int index, LPCTSTR value)
|
||||
{
|
||||
if (Valid_Index (index)) {
|
||||
m_ParamValues[index].value = value;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
INLINE_ACCESSOR_CONST (LPCTSTR, EditScriptClass, Name);
|
||||
|
||||
#endif //__EDIT_SCRIPT_H
|
||||
375
Code/Tools/LevelEdit/EditStringDialog.cpp
Normal file
375
Code/Tools/LevelEdit/EditStringDialog.cpp
Normal file
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// EditStringDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveledit.h"
|
||||
#include "editstringdialog.h"
|
||||
#include "translateobj.h"
|
||||
#include "definitionclassids.h"
|
||||
#include "presetmgr.h"
|
||||
#include "preset.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Local prototypes
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool Is_Valid_ID_Char (char ch);
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditStringDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
EditStringDialogClass::EditStringDialogClass(CWnd* pParent /*=NULL*/)
|
||||
: m_Object (NULL),
|
||||
CDialog(EditStringDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(EditStringDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditStringDialogClass::DoDataExchange (CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(EditStringDialogClass)
|
||||
// NOTE: the ClassWizard will add DDX and DDV calls here
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(EditStringDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(EditStringDialogClass)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
EditStringDialogClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
//
|
||||
// Get information about the location where we want to create the
|
||||
// sound preset picker control
|
||||
//
|
||||
HWND placeholder_wnd = ::GetDlgItem (m_hWnd, IDC_SOUND_PRESET_EDIT);
|
||||
CRect rect;
|
||||
::GetWindowRect (placeholder_wnd, &rect);
|
||||
ScreenToClient (&rect);
|
||||
::DestroyWindow (placeholder_wnd);
|
||||
|
||||
//
|
||||
// Create the preset picker control
|
||||
//
|
||||
m_PresetPicker.Create_Picker (WS_CHILD | WS_TABSTOP | WS_VISIBLE, rect, this, 101);
|
||||
m_PresetPicker.Set_Read_Only (true);
|
||||
|
||||
//
|
||||
// Configure the preset picker control
|
||||
//
|
||||
m_PresetPicker.Set_Class_ID (CLASSID_SOUND);
|
||||
if (m_Object != NULL && m_Object->Get_Sound_ID () > 0) {
|
||||
PresetClass *preset = PresetMgrClass::Find_Preset (m_Object->Get_Sound_ID ());
|
||||
m_PresetPicker.Set_Preset (preset);
|
||||
}
|
||||
|
||||
//
|
||||
// Fill in the text controls
|
||||
//
|
||||
if (m_Object != NULL) {
|
||||
CString text = m_Object->Get_English_String ();
|
||||
Convert_Newline_To_Chars (text);
|
||||
|
||||
SetDlgItemText (IDC_CODEID_EDIT, m_Object->Get_ID_Desc ());
|
||||
SetDlgItemText (IDC_STRING_EDIT, text);
|
||||
SetDlgItemText (IDC_ANIMATION_NAME_EDIT, m_Object->Get_Animation_Name ());
|
||||
|
||||
//
|
||||
// Select the string so the user can readily modify its contents
|
||||
//
|
||||
::SetFocus (::GetDlgItem (m_hWnd, IDC_STRING_EDIT));
|
||||
SendDlgItemMessage (IDC_STRING_EDIT, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
|
||||
|
||||
} else {
|
||||
SetDlgItemText (IDC_CODEID_EDIT, "IDS_");
|
||||
|
||||
//
|
||||
// Select the CODE ID so the user can enter a valid ID
|
||||
//
|
||||
::SetFocus (::GetDlgItem (m_hWnd, IDC_CODEID_EDIT));
|
||||
SendDlgItemMessage (IDC_CODEID_EDIT, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Convert_Newline_To_Chars
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditStringDialogClass::Convert_Newline_To_Chars (CString &string)
|
||||
{
|
||||
CString retval;
|
||||
|
||||
//
|
||||
// Take a guess as to how large to make the final string
|
||||
//
|
||||
int count = string.GetLength ();
|
||||
|
||||
//
|
||||
// Copy characters between the strings
|
||||
//
|
||||
for (int index = 0; index < count; index ++) {
|
||||
|
||||
if (string[index] == '\n') {
|
||||
retval += "\\n";
|
||||
} else if (string[index] == '\t') {
|
||||
retval += "\\t";
|
||||
} else {
|
||||
retval += string[index];
|
||||
}
|
||||
}
|
||||
|
||||
string = retval;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Convert_Chars_To_Newline
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditStringDialogClass::Convert_Chars_To_Newline (CString &string)
|
||||
{
|
||||
CString retval;
|
||||
|
||||
//
|
||||
// Take a guess as to how large to make the final string
|
||||
//
|
||||
int count = string.GetLength ();
|
||||
//retval.GetBufferSetLength (count);
|
||||
|
||||
//
|
||||
// Copy characters between the strings
|
||||
//
|
||||
for (int index = 0; index < count; index ++) {
|
||||
|
||||
if (index + 1 < count && string[index] == '\\' && string[index + 1] == 'n') {
|
||||
retval += '\n';
|
||||
index ++;
|
||||
} else if (index + 1 < count && string[index] == '\\' && string[index + 1] == 't') {
|
||||
retval += '\t';
|
||||
index ++;
|
||||
} else {
|
||||
retval += string[index];
|
||||
}
|
||||
}
|
||||
|
||||
string = retval;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOK
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditStringDialogClass::OnOK (void)
|
||||
{
|
||||
if (Validate_ID ()) {
|
||||
|
||||
//
|
||||
// Create a new translation object (if necessary)
|
||||
//
|
||||
if (m_Object == NULL) {
|
||||
m_Object = new TDBObjClass;
|
||||
}
|
||||
|
||||
//
|
||||
// Read the strings the user entered
|
||||
//
|
||||
CString code_id;
|
||||
GetDlgItemText (IDC_CODEID_EDIT, code_id);
|
||||
|
||||
CString text;
|
||||
GetDlgItemText (IDC_STRING_EDIT, text);
|
||||
Convert_Chars_To_Newline (text);
|
||||
|
||||
CString anim_name;
|
||||
GetDlgItemText (IDC_ANIMATION_NAME_EDIT, anim_name);
|
||||
|
||||
//
|
||||
// Pass the new strings onto the translation object
|
||||
//
|
||||
m_Object->Set_ID_Desc (code_id);
|
||||
m_Object->Set_English_String (text);
|
||||
m_Object->Set_Animation_Name (anim_name);
|
||||
|
||||
//
|
||||
// Pass the sound preset ID onto the translation object
|
||||
//
|
||||
int sound_id = -1;
|
||||
PresetClass *sound_preset = m_PresetPicker.Get_Preset ();
|
||||
if (sound_preset != NULL) {
|
||||
sound_id = sound_preset->Get_ID ();
|
||||
}
|
||||
m_Object->Set_Sound_ID (sound_id);
|
||||
|
||||
CDialog::OnOK ();
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Validate_ID
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditStringDialogClass::Validate_ID (void)
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
//
|
||||
// Get the string ID from the control
|
||||
//
|
||||
CString code_id;
|
||||
GetDlgItemText (IDC_CODEID_EDIT, code_id);
|
||||
|
||||
//
|
||||
// Validate the ID
|
||||
//
|
||||
return Validate_String_ID (m_hWnd, code_id);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Validate_String_ID
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
Validate_String_ID (HWND wnd, const char *string_id)
|
||||
{
|
||||
bool retval = false;
|
||||
CString code_id = string_id;
|
||||
|
||||
if (code_id.GetLength () == 0) {
|
||||
|
||||
//
|
||||
// Warn the user they need to enter some ID
|
||||
//
|
||||
::MessageBox (wnd, "Please enter a descriptive token for the code identifier.", "Invalid Code ID", MB_ICONERROR | MB_OK);
|
||||
|
||||
} else if (code_id.GetLength () < 4) {
|
||||
|
||||
//
|
||||
// Warn the user they should enter a descriptive name
|
||||
//
|
||||
::MessageBox (wnd, "Code identifier is too short. Please enter a more descriptive token for the code identifier.", "Invalid Code ID", MB_ICONERROR | MB_OK);
|
||||
|
||||
} else if (code_id[0] < 0x41 || code_id[0] > 0x7A || (code_id[0] >= 0x5B && code_id[0] <= 0x60)) {
|
||||
|
||||
//
|
||||
// Warn the user the name must start with a character
|
||||
//
|
||||
::MessageBox (wnd, "The code identifier must begin with a character (not a number), please enter a valid identifier.", "Invalid Code ID", MB_ICONERROR | MB_OK);
|
||||
|
||||
} else {
|
||||
|
||||
//
|
||||
// Check each character in the string to make sure its exceptable
|
||||
//
|
||||
int count = code_id.GetLength ();
|
||||
bool is_valid = true;
|
||||
for (int index = 1; is_valid && index < count; index ++) {
|
||||
is_valid &= Is_Valid_ID_Char (code_id[index]);
|
||||
}
|
||||
|
||||
if (is_valid == false) {
|
||||
|
||||
//
|
||||
// Warn the user that the code ID contains an illegal character
|
||||
//
|
||||
::MessageBox (wnd, "The code identifier can only contain characters (a-z, A-Z), numbers (0-9), and the underscore character (_), please enter a valid identifier.", "Invalid Code ID", MB_ICONERROR | MB_OK);
|
||||
|
||||
} else {
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Is_Valid_ID_Char
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
Is_Valid_ID_Char (char ch)
|
||||
{
|
||||
bool is_valid = false;
|
||||
|
||||
//
|
||||
// The character if valid if its either a character, a number, or an underscore
|
||||
//
|
||||
is_valid |= (ch >= '0' && ch <= '9');
|
||||
is_valid |= (ch >= 'A' && ch <= 'Z');
|
||||
is_valid |= (ch >= 'a' && ch <= 'z');
|
||||
is_valid |= (ch == '_');
|
||||
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
104
Code/Tools/LevelEdit/EditStringDialog.h
Normal file
104
Code/Tools/LevelEdit/EditStringDialog.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_EDITSTRINGDIALOG_H__E438BDAC_5DB9_11D4_A0A8_00104B791122__INCLUDED_)
|
||||
#define AFX_EDITSTRINGDIALOG_H__E438BDAC_5DB9_11D4_A0A8_00104B791122__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "resource.h"
|
||||
#include "presetpicker.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Forward delcarations
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class TDBObjClass;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Utiltity functions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool Validate_String_ID (HWND wnd, const char *string_id);
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditStringDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class EditStringDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
EditStringDialogClass(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(EditStringDialogClass)
|
||||
enum { IDD = IDD_EDIT_STRING };
|
||||
// NOTE: the ClassWizard will add data members here
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(EditStringDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(EditStringDialogClass)
|
||||
virtual void OnOK();
|
||||
virtual BOOL OnInitDialog();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
/////////////////////////////////////////////////////////////
|
||||
void Set_Translate_Object (TDBObjClass *object) { m_Object = object; }
|
||||
TDBObjClass * Get_Translate_Object (void) const { return m_Object; }
|
||||
|
||||
private:
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
/////////////////////////////////////////////////////////////
|
||||
bool Validate_ID (void);
|
||||
void Convert_Newline_To_Chars (CString &string);
|
||||
void Convert_Chars_To_Newline (CString &string);
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
/////////////////////////////////////////////////////////////
|
||||
TDBObjClass * m_Object;
|
||||
PresetPickerClass m_PresetPicker;
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_EDITSTRINGDIALOG_H__E438BDAC_5DB9_11D4_A0A8_00104B791122__INCLUDED_)
|
||||
250
Code/Tools/LevelEdit/EditStringTwiddlerDialog.cpp
Normal file
250
Code/Tools/LevelEdit/EditStringTwiddlerDialog.cpp
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// EditStringTwiddlerDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveledit.h"
|
||||
#include "editstringtwiddlerdialog.h"
|
||||
#include "editstringdialog.h"
|
||||
#include "stringtwiddler.h"
|
||||
#include "stringpickermaindialog.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditStringTwiddlerDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
EditStringTwiddlerDialogClass::EditStringTwiddlerDialogClass (CWnd *pParent /*=NULL*/) :
|
||||
StringObject (NULL),
|
||||
CDialog (EditStringTwiddlerDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(EditStringTwiddlerDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditStringTwiddlerDialogClass::DoDataExchange (CDataExchange *pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(EditStringTwiddlerDialogClass)
|
||||
DDX_Control(pDX, IDC_LISTCTRL, ListCtrl);
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(EditStringTwiddlerDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(EditStringTwiddlerDialogClass)
|
||||
ON_BN_CLICKED(IDC_ADD_BUTTON, OnAddButton)
|
||||
ON_NOTIFY(LVN_KEYDOWN, IDC_LISTCTRL, OnKeydownListctrl)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
EditStringTwiddlerDialogClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
//
|
||||
// Configure the list control
|
||||
//
|
||||
ListCtrl.InsertColumn (0, "String ID");
|
||||
|
||||
//
|
||||
// Size the column
|
||||
//
|
||||
CRect rect;
|
||||
ListCtrl.GetClientRect (&rect);
|
||||
rect.right -= ::GetSystemMetrics (SM_CXVSCROLL) + 2;
|
||||
ListCtrl.SetColumnWidth (0, rect.Width ());
|
||||
|
||||
//
|
||||
// Fill in the text control
|
||||
//
|
||||
if (StringObject != NULL) {
|
||||
SetDlgItemText (IDC_CODEID_EDIT, StringObject->Get_ID_Desc ());
|
||||
|
||||
//
|
||||
// Add the list of strings to the database
|
||||
//
|
||||
for (int index = 0; index < StringObject->Get_String_Count (); index ++) {
|
||||
Insert_String (StringObject->Get_String (index));
|
||||
}
|
||||
|
||||
} else {
|
||||
SetDlgItemText (IDC_CODEID_EDIT, "IDS_");
|
||||
}
|
||||
|
||||
//
|
||||
// Select the CODE ID so the user can enter a valid ID
|
||||
//
|
||||
::SetFocus (::GetDlgItem (m_hWnd, IDC_CODEID_EDIT));
|
||||
SendDlgItemMessage (IDC_CODEID_EDIT, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Insert_String
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditStringTwiddlerDialogClass::Insert_String (int string_id)
|
||||
{
|
||||
//
|
||||
// Lookup the object for this ID
|
||||
//
|
||||
TDBObjClass *object = TranslateDBClass::Find_Object (string_id);
|
||||
if (object != NULL) {
|
||||
const StringClass &text = object->Get_ID_Desc ();
|
||||
|
||||
//
|
||||
// Add an entry to the list for this string
|
||||
//
|
||||
int item_index = ListCtrl.InsertItem (0xFF, text);
|
||||
if (item_index != -1) {
|
||||
ListCtrl.SetItemData (item_index, string_id);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnAddButton
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditStringTwiddlerDialogClass::OnAddButton (void)
|
||||
{
|
||||
//
|
||||
// Show the dialog to the user so they can pick a string
|
||||
//
|
||||
StringPickerMainDialogClass dialog (this);
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Add this string to our list
|
||||
//
|
||||
Insert_String (dialog.Get_String_ID ());
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOK
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditStringTwiddlerDialogClass::OnOK (void)
|
||||
{
|
||||
//
|
||||
// Get the strind ID the user entered
|
||||
//
|
||||
CString string_id;
|
||||
GetDlgItemText (IDC_CODEID_EDIT, string_id);
|
||||
|
||||
//
|
||||
// Is this a valid ID?
|
||||
//
|
||||
if (Validate_String_ID (m_hWnd, string_id)) {
|
||||
|
||||
//
|
||||
// Create a new twiddler (if necessary)
|
||||
//
|
||||
if (StringObject == NULL) {
|
||||
StringObject = new StringTwiddlerClass;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the twiddler
|
||||
//
|
||||
StringObject->Reset_String_List ();
|
||||
StringObject->Set_ID_Desc (string_id);
|
||||
|
||||
//
|
||||
// Add the list of strings to the twiddler
|
||||
//
|
||||
int count = ListCtrl.GetItemCount ();
|
||||
for (int index = 0; index < count; index ++) {
|
||||
int string_id = (int)ListCtrl.GetItemData (index);
|
||||
StringObject->Add_String (string_id);
|
||||
}
|
||||
|
||||
CDialog::OnOK ();
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnKeydownListctrl
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditStringTwiddlerDialogClass::OnKeydownListctrl (NMHDR *pNMHDR, LRESULT *pResult)
|
||||
{
|
||||
LV_KEYDOWN *pLVKeyDown = (LV_KEYDOWN*)pNMHDR;
|
||||
*pResult = 0;
|
||||
|
||||
if (pLVKeyDown->wVKey == VK_DELETE) {
|
||||
|
||||
//
|
||||
// Delete all the selected items (except for the last item)
|
||||
//
|
||||
int index = -1;
|
||||
while ((index = ListCtrl.GetNextItem (-1, LVNI_SELECTED | LVNI_ALL)) >= 0) {
|
||||
ListCtrl.DeleteItem (index);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
95
Code/Tools/LevelEdit/EditStringTwiddlerDialog.h
Normal file
95
Code/Tools/LevelEdit/EditStringTwiddlerDialog.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_EDITSTRINGTWIDDLERDIALOG_H__05FF8A6C_8212_44F5_A971_94BE7B9A0F16__INCLUDED_)
|
||||
#define AFX_EDITSTRINGTWIDDLERDIALOG_H__05FF8A6C_8212_44F5_A971_94BE7B9A0F16__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class StringTwiddlerClass;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditStringTwiddlerDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class EditStringTwiddlerDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
EditStringTwiddlerDialogClass (CWnd *pParent = NULL);
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(EditStringTwiddlerDialogClass)
|
||||
enum { IDD = IDD_EDIT_STRING_TWIDDLER };
|
||||
CListCtrl ListCtrl;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(EditStringTwiddlerDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(EditStringTwiddlerDialogClass)
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnAddButton();
|
||||
virtual void OnOK();
|
||||
afx_msg void OnKeydownListctrl(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void Set_Twiddler (StringTwiddlerClass *twiddler) { StringObject = twiddler; }
|
||||
StringTwiddlerClass * Get_Twiddler (void) const { return StringObject; }
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void Insert_String (int string_id);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
StringTwiddlerClass * StringObject;
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_EDITSTRINGTWIDDLERDIALOG_H__05FF8A6C_8212_44F5_A971_94BE7B9A0F16__INCLUDED_)
|
||||
666
Code/Tools/LevelEdit/EditorAssetMgr.cpp
Normal file
666
Code/Tools/LevelEdit/EditorAssetMgr.cpp
Normal file
@@ -0,0 +1,666 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/EditorAssetMgr.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 1/29/02 3:16p $*
|
||||
* *
|
||||
* $Revision:: 29 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "editorassetmgr.h"
|
||||
#include "texture.h"
|
||||
#include "proto.h"
|
||||
#include "editorini.h"
|
||||
#include "ffactory.h"
|
||||
#include "ww3d.h"
|
||||
#include "utils.h"
|
||||
#include "filemgr.h"
|
||||
#include "rawfile.h"
|
||||
#include "rcfile.h"
|
||||
#include "filelocations.h"
|
||||
#include "editorbuild.h"
|
||||
#include "assetdatabase.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
DynamicVectorClass<StringClass> EditorFileFactoryClass::SearchPathList;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditorAssetMgrClass
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
EditorAssetMgrClass::EditorAssetMgrClass (void)
|
||||
{
|
||||
Set_Activate_Fog_On_Load (true);
|
||||
m_CurrentDir = ::Get_Startup_Directory ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Reload_File
|
||||
//
|
||||
void
|
||||
EditorAssetMgrClass::Reload_File (const char *filename)
|
||||
{
|
||||
// Param OK?
|
||||
ASSERT (filename != NULL);
|
||||
if (filename != NULL) {
|
||||
CString extension = ::strrchr (filename, '.');
|
||||
|
||||
// Is this a W3D file?
|
||||
if (extension.CompareNoCase (".W3D") == 0) {
|
||||
CString asset_name = ::Asset_Name_From_Filename (filename);
|
||||
Remove_Prototype (asset_name);
|
||||
Load_3D_Assets (filename);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Is_File_Here
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditorAssetMgrClass::Is_File_Here (LPCTSTR full_path, bool get_from_vss)
|
||||
{
|
||||
//
|
||||
// Output this file lookup to the message window
|
||||
//
|
||||
CString message;
|
||||
message.Format ("Attempting to load: %s\r\n", full_path);
|
||||
::Output_Message (message);
|
||||
|
||||
//
|
||||
// Check to see if the file exists in this location
|
||||
//
|
||||
return ::Get_File_Mgr ()->Does_File_Exist (full_path, get_from_vss);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Determine_Real_Location
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditorAssetMgrClass::Determine_Real_Location
|
||||
(
|
||||
LPCTSTR path,
|
||||
CString & real_location
|
||||
)
|
||||
{
|
||||
bool retval = false;
|
||||
TCHAR full_path[MAX_PATH];
|
||||
|
||||
//
|
||||
// Did the caller supply a path?
|
||||
//
|
||||
if (Is_Full_Path (path)) {
|
||||
::lstrcpy (full_path, path);
|
||||
} else {
|
||||
|
||||
//
|
||||
// Make a full path out of the filename
|
||||
//
|
||||
CString test_path = Make_Path (m_CurrentDir, path);
|
||||
|
||||
//
|
||||
// If the file doesn't exist here, then try the search paths
|
||||
//
|
||||
if (::GetFileAttributes (test_path) == 0xFFFFFFFF) {
|
||||
|
||||
//
|
||||
// Try to find the file in our search path list
|
||||
//
|
||||
DynamicVectorClass<StringClass> &path_list = EditorFileFactoryClass::Get_Search_Path ();
|
||||
for (int index = 0; index < path_list.Count (); index ++) {
|
||||
|
||||
//
|
||||
// Does the file exist in this directoy?
|
||||
//
|
||||
StringClass full_path = Make_Path (path_list[index], path);
|
||||
if (::GetFileAttributes (full_path) != 0xFFFFFFFF) {
|
||||
test_path = full_path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::lstrcpy (full_path, test_path);
|
||||
}
|
||||
|
||||
//
|
||||
// Find out if the file lives in the directory
|
||||
//
|
||||
if (Is_File_Here (full_path, true) == false) {
|
||||
|
||||
//
|
||||
// Hmmm... not here, try up a directory level
|
||||
//
|
||||
CString parent_dir = ::Up_One_Directory (::Strip_Filename_From_Path (full_path));
|
||||
CString filename = ::Get_Filename_From_Path (full_path);
|
||||
parent_dir = ::Make_Path (parent_dir, filename);
|
||||
|
||||
//
|
||||
// Does the file live in the parent directory?
|
||||
//
|
||||
if (Is_File_Here (parent_dir, true) == false) {
|
||||
|
||||
//
|
||||
// Is this a texture file?
|
||||
//
|
||||
if (Is_Texture_Filename (full_path)) {
|
||||
|
||||
#ifndef PUBLIC_EDITOR_VER
|
||||
|
||||
//
|
||||
// Does the file live in the global texture directory?
|
||||
//
|
||||
CString texture_path = ::Make_Path (GLOBAL_TEXTURE_PATH, filename);
|
||||
if (Is_File_Here (texture_path, false)) {
|
||||
real_location = texture_path;
|
||||
retval = true;
|
||||
}
|
||||
|
||||
#endif //!PUBLIC_EDITOR_VER
|
||||
|
||||
} else if (::strnicmp ("h_a_", filename, 4) == 0) {
|
||||
|
||||
//
|
||||
// We are 'assuming' this is a human animation file, so
|
||||
// try to find it in the human animation directory.
|
||||
//
|
||||
CString anim_path = ::Make_Path (CHAR_ANIMS_PATH, filename);
|
||||
if (Is_File_Here (anim_path, true)) {
|
||||
real_location = anim_path;
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
real_location = parent_dir;
|
||||
retval = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
real_location = full_path;
|
||||
retval = true;
|
||||
}
|
||||
|
||||
#ifdef PUBLIC_EDITOR_VER
|
||||
|
||||
//
|
||||
// If the file does not exist locally, then use the one from the mix file
|
||||
//
|
||||
if (retval == false && ::Get_File_Mgr ()->Is_File_In_VSS (full_path)) {
|
||||
real_location = full_path;
|
||||
retval = true;
|
||||
}
|
||||
|
||||
#endif //PUBLIC_EDITOR_VER
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create_Render_Obj
|
||||
//
|
||||
RenderObjClass *
|
||||
EditorAssetMgrClass::Create_Render_Obj (const char * name)
|
||||
{
|
||||
// Let windows do some processing
|
||||
::Pump_Messages ();
|
||||
|
||||
// Assume failure
|
||||
RenderObjClass *prenderobj = NULL;
|
||||
|
||||
// Try to find a prototype
|
||||
PrototypeClass * proto = Find_Prototype(name);
|
||||
|
||||
if (WW3D_Load_On_Demand && proto == NULL) { // If we didn't find one, try to load on demand
|
||||
char filename[ MAX_PATH ];
|
||||
sprintf( filename, "%s.W3D", name);
|
||||
char *mesh_name = ::strchr (name, '.');
|
||||
if (mesh_name != NULL) {
|
||||
::lstrcpyn (filename, name, ((int)mesh_name) - ((int)name) + 1);
|
||||
::lstrcat (filename, ".W3D");
|
||||
} else {
|
||||
sprintf( filename, "%s.W3D", name);
|
||||
}
|
||||
|
||||
// See if we can determine where this file exists
|
||||
CString real_location;
|
||||
if (Determine_Real_Location (filename, real_location)) {
|
||||
::lstrcpy (filename, real_location);
|
||||
} else {
|
||||
TRACE ("Asset file not found!\n");
|
||||
}
|
||||
|
||||
// Load the assets from this file into the manager
|
||||
Load_3D_Assets (filename);
|
||||
|
||||
// Attempt to find the prototype loader now.
|
||||
proto = Find_Prototype (name);
|
||||
}
|
||||
|
||||
// If we found a prototype for this object, then
|
||||
// use it to create a new instance of the requested asset.
|
||||
if (proto != NULL) {
|
||||
prenderobj = proto->Create ();
|
||||
}
|
||||
|
||||
// Return a pointer to the render object
|
||||
return prenderobj;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_HAnim
|
||||
//
|
||||
HAnimClass *
|
||||
EditorAssetMgrClass::Get_HAnim (const char * name)
|
||||
{
|
||||
// Let windows do some processing
|
||||
::Pump_Messages ();
|
||||
|
||||
// Try to find the animation
|
||||
HAnimClass *panim = HAnimManager.Get_Anim(name);
|
||||
|
||||
if (WW3D_Load_On_Demand && panim == NULL) { // If we didn't find it, try to load on demand
|
||||
|
||||
char filename[ MAX_PATH ];
|
||||
char *animname = strchr( name, '.');
|
||||
if (animname != NULL) {
|
||||
sprintf( filename, "%s.W3D", animname+1);
|
||||
} else {
|
||||
TRACE ("Animation has no . in the name\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// See if we can determine where this file exists
|
||||
CString real_location;
|
||||
if (Determine_Real_Location (filename, real_location)) {
|
||||
::lstrcpy (filename, real_location);
|
||||
} else {
|
||||
TRACE ("Asset file not found!\n");
|
||||
}
|
||||
|
||||
// Load the assets from this file into the manager
|
||||
Load_3D_Assets (filename);
|
||||
|
||||
// Attempt to find the prototype loader now.
|
||||
panim = HAnimManager.Get_Anim(name);
|
||||
}
|
||||
|
||||
// Return a pointer to the animation
|
||||
return panim;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_HTree
|
||||
//
|
||||
HTreeClass *
|
||||
EditorAssetMgrClass::Get_HTree (const char * name)
|
||||
{
|
||||
// Let windows do some processing
|
||||
::Pump_Messages ();
|
||||
|
||||
// Try to find the htree
|
||||
HTreeClass *phtree = HTreeManager.Get_Tree(name);
|
||||
|
||||
if (WW3D_Load_On_Demand && phtree == NULL) { // If we didn't find it, try to load on demand
|
||||
|
||||
char filename[ MAX_PATH ];
|
||||
sprintf( filename, "%s.W3D", name);
|
||||
|
||||
// See if we can determine where this file exists
|
||||
CString real_location;
|
||||
if (Determine_Real_Location (filename, real_location)) {
|
||||
::lstrcpy (filename, real_location);
|
||||
} else {
|
||||
TRACE ("Asset file not found!\n");
|
||||
}
|
||||
|
||||
// Load the assets from this file into the manager
|
||||
Load_3D_Assets (filename);
|
||||
|
||||
// Attempt to find the object loader now.
|
||||
phtree = HTreeManager.Get_Tree(name);
|
||||
}
|
||||
|
||||
// Return a pointer to the animation
|
||||
return phtree;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_INI
|
||||
//
|
||||
EditorINIClass *
|
||||
EditorAssetMgrClass::Get_INI (const char *filename)
|
||||
{
|
||||
EditorINIClass *pini = NULL;
|
||||
|
||||
FileClass * pini_file = _TheFileFactory->Get_File (filename);
|
||||
if (pini_file) {
|
||||
pini = new EditorINIClass (*pini_file);
|
||||
_TheFileFactory->Return_File (pini_file);
|
||||
}
|
||||
|
||||
// Return a pointer to the INI file class
|
||||
return pini;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Texture
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
TextureClass *
|
||||
EditorAssetMgrClass::Get_Texture
|
||||
(
|
||||
const char * tga_filename,
|
||||
TextureClass::MipCountType mip_level_count,
|
||||
WW3DFormat texture_format,
|
||||
bool allow_compression
|
||||
)
|
||||
{
|
||||
//
|
||||
// Let windows do some processing
|
||||
//
|
||||
::Pump_Messages ();
|
||||
|
||||
/*
|
||||
** Bail if the user isn't really asking for anything
|
||||
*/
|
||||
if ((tga_filename == NULL) || (strlen(tga_filename) == 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Determine what the texture's "name" should be
|
||||
//
|
||||
CString texture_name;
|
||||
if (::strstr (tga_filename, "+\\") != NULL) {
|
||||
texture_name = ::Get_Subdir_And_Filename_From_Path (tga_filename);
|
||||
} else {
|
||||
texture_name = ::Get_Filename_From_Path (tga_filename);
|
||||
}
|
||||
texture_name.MakeLower ();
|
||||
|
||||
/*
|
||||
** See if the texture has already been loaded.
|
||||
*/
|
||||
TextureClass* tex = TextureHash.Get ((const char *)texture_name);
|
||||
if (tex && texture_format!=WW3D_FORMAT_UNKNOWN) {
|
||||
WWASSERT_PRINT(tex->Get_Texture_Format()==texture_format,("Texture %s has already been loaded witt different format",(const char *)texture_name));
|
||||
}
|
||||
|
||||
/*
|
||||
** Didn't have it so we have to create a new texture
|
||||
*/
|
||||
if (!tex) {
|
||||
|
||||
//
|
||||
// See if we can determine where this file exists
|
||||
//
|
||||
CString real_location;
|
||||
if (Determine_Real_Location (tga_filename, real_location) == false) {
|
||||
CString message;
|
||||
message.Format ("Texture file not found: %s\r\n", (LPCTSTR)texture_name);
|
||||
::Output_Message (message);
|
||||
real_location = tga_filename;
|
||||
}
|
||||
|
||||
/*
|
||||
** Didn't have it so we have to create a new texture
|
||||
*/
|
||||
tex = NEW_REF(TextureClass,(texture_name, real_location, mip_level_count, texture_format, allow_compression));
|
||||
TextureHash.Insert(tex->Get_Texture_Name(),tex);
|
||||
}
|
||||
|
||||
tex->Add_Ref();
|
||||
return tex;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_Resource_Texture
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorAssetMgrClass::Load_Resource_Texture (const char *filename)
|
||||
{
|
||||
CString texture_path = ::Get_File_Mgr ()->Get_Texture_Cache_Path ();
|
||||
CString texture_filename = ::Make_Path (texture_path, filename);
|
||||
|
||||
//
|
||||
// Open the resource texture and create the
|
||||
// real file.
|
||||
//
|
||||
ResourceFileClass res_texture (NULL, filename);
|
||||
RawFileClass texture_file (texture_filename);
|
||||
if (texture_file.Create () == 1) {
|
||||
texture_file.Open (FileClass::WRITE);
|
||||
|
||||
//
|
||||
// Copy the contents of the resource (memory) texture
|
||||
// to a file.
|
||||
//
|
||||
BYTE buffer[2048];
|
||||
int size = res_texture.Size ();
|
||||
int total_written = 0;
|
||||
while (total_written < size) {
|
||||
int bytes_read = res_texture.Read (buffer, sizeof (buffer));
|
||||
int bytes_written = texture_file.Write (buffer, bytes_read);
|
||||
total_written += bytes_written;
|
||||
if (bytes_written == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
texture_file.Close ();
|
||||
|
||||
//
|
||||
// Force the texture to be loaded into memory
|
||||
//
|
||||
TextureClass *texture = Get_Texture (texture_filename);
|
||||
REF_PTR_RELEASE (texture);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_3D_Assets
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditorAssetMgrClass::Load_3D_Assets (const char *path)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
//
|
||||
// Check to see if the asset is already in the asset manager
|
||||
//
|
||||
CString filename = ::Get_Filename_From_Path (path);
|
||||
CString asset_name = ::Asset_Name_From_Filename (filename);
|
||||
PrototypeClass *prototype = Find_Prototype (asset_name);
|
||||
|
||||
//
|
||||
// Load the asset fresh if necessary
|
||||
//
|
||||
if (prototype == NULL) {
|
||||
CString full_path = ::Get_File_Mgr ()->Make_Full_Path (path);
|
||||
retval = false;
|
||||
|
||||
#ifdef PUBLIC_EDITOR_VER
|
||||
|
||||
//
|
||||
// If the file exists locally, or its coming from the mix file
|
||||
// then load it.
|
||||
//
|
||||
if ( ::Get_File_Mgr ()->Does_File_Exist (full_path) ||
|
||||
::Get_File_Mgr ()->Is_File_In_VSS (full_path))
|
||||
{
|
||||
retval = WW3DAssetManager::Load_3D_Assets (full_path);
|
||||
}
|
||||
#else
|
||||
|
||||
//
|
||||
// If the file exists, then load it.
|
||||
//
|
||||
if (::Get_File_Mgr ()->Does_File_Exist (full_path, true)) {
|
||||
retval = WW3DAssetManager::Load_3D_Assets (full_path);
|
||||
}
|
||||
|
||||
#endif //PUBLIC_EDITOR_VER
|
||||
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_File
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
FileClass *
|
||||
EditorFileFactoryClass::Get_File (char const *filename)
|
||||
{
|
||||
CString path;
|
||||
|
||||
//
|
||||
// If the filename contains a relative path, then
|
||||
// turn it into an absolute path.
|
||||
//
|
||||
if (::Is_Path (filename)) {
|
||||
path = ::Get_File_Mgr ()->Make_Full_Path (filename);
|
||||
} else {
|
||||
|
||||
//
|
||||
// Make a full path out of the filename
|
||||
//
|
||||
const char *curr_dir = _pThe3DAssetManager->Get_Current_Directory ();
|
||||
path = Make_Path (curr_dir, filename);
|
||||
|
||||
//
|
||||
// If the file doesn't exist here, then try the search paths
|
||||
//
|
||||
if (::GetFileAttributes (path) == 0xFFFFFFFF) {
|
||||
|
||||
//
|
||||
// Try to find the file in our search path list
|
||||
//
|
||||
for (int index = 0; index < SearchPathList.Count (); index ++) {
|
||||
|
||||
//
|
||||
// Does the file exist in this directoy?
|
||||
//
|
||||
StringClass full_path = Make_Path (SearchPathList[index], filename);
|
||||
if (::GetFileAttributes (full_path) != 0xFFFFFFFF) {
|
||||
path = full_path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get the file from the database
|
||||
//
|
||||
return ::Get_File_Mgr ()->Get_Database_Interface ().Get_File (path);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Return_File
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorFileFactoryClass::Return_File (FileClass *file)
|
||||
{
|
||||
if (file != NULL) {
|
||||
delete file;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Open_Texture_File_Cache
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorAssetMgrClass::Open_Texture_File_Cache (const char * /*prefix*/)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Close_Texture_File_Cache
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorAssetMgrClass::Close_Texture_File_Cache (void)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
153
Code/Tools/LevelEdit/EditorAssetMgr.h
Normal file
153
Code/Tools/LevelEdit/EditorAssetMgr.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/EditorAssetMgr.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 1/29/02 10:33a $*
|
||||
* *
|
||||
* $Revision:: 15 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __LEVELEDITASSETMGR_H
|
||||
#define __LEVELEDITASSETMGR_H
|
||||
|
||||
#include "AssetMgr.H"
|
||||
#include "FFactory.H"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditorFileFactoryClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class EditorFileFactoryClass : public FileFactoryClass
|
||||
{
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////
|
||||
virtual FileClass * Get_File (char const *filename);
|
||||
virtual void Return_File (FileClass *file);
|
||||
|
||||
//
|
||||
// Search path support
|
||||
//
|
||||
static void Add_Search_Path (const char *path) { SearchPathList.Add (path); }
|
||||
static DynamicVectorClass<StringClass> & Get_Search_Path (void) { return SearchPathList; }
|
||||
|
||||
private:
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Private data
|
||||
///////////////////////////////////////////////////
|
||||
static DynamicVectorClass<StringClass> SearchPathList;
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditorAssetMgrClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class EditorAssetMgrClass : public WW3DAssetManager
|
||||
{
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
///////////////////////////////////////////////////
|
||||
EditorAssetMgrClass (void);
|
||||
virtual ~EditorAssetMgrClass (void) {}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Base class overrides
|
||||
//
|
||||
virtual RenderObjClass * Create_Render_Obj (const char * name);
|
||||
virtual HAnimClass * Get_HAnim (const char * name);
|
||||
virtual HTreeClass * Get_HTree (const char * name);
|
||||
virtual TextureClass * Get_Texture (const char *filename, TextureClass::MipCountType mip_level_count=TextureClass::MIP_LEVELS_ALL,WW3DFormat texture_format=WW3D_FORMAT_UNKNOWN, bool allow_compression=true);
|
||||
|
||||
|
||||
//
|
||||
// INI methods
|
||||
//
|
||||
virtual class EditorINIClass *Get_INI (const char *filename);
|
||||
|
||||
//
|
||||
// Asset managment
|
||||
//
|
||||
virtual void Reload_File (const char *filename);
|
||||
virtual void Load_Resource_Texture (const char *filename);
|
||||
|
||||
//
|
||||
// Directory methods
|
||||
//
|
||||
void Set_Current_Directory (LPCTSTR path) { m_CurrentDir = path; ::SetCurrentDirectory (m_CurrentDir); }
|
||||
const char * Get_Current_Directory (void) { return m_CurrentDir; }
|
||||
|
||||
//
|
||||
// Load data from any type of w3d file
|
||||
//
|
||||
virtual bool Load_3D_Assets (const char * filename);
|
||||
|
||||
//
|
||||
// Texture caching overrides
|
||||
//
|
||||
virtual void Open_Texture_File_Cache(const char * /*prefix*/);
|
||||
virtual void Close_Texture_File_Cache();
|
||||
|
||||
protected:
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
///////////////////////////////////////////////////
|
||||
virtual bool Determine_Real_Location (LPCTSTR filename, CString &real_location);
|
||||
virtual bool Is_File_Here (LPCTSTR full_path, bool get_from_vss);
|
||||
|
||||
private:
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
//
|
||||
// Private member data
|
||||
//
|
||||
CString m_CurrentDir;
|
||||
};
|
||||
|
||||
|
||||
#endif //__LEVELEDITASSETMGR_H
|
||||
120
Code/Tools/LevelEdit/EditorChunkIDs.h
Normal file
120
Code/Tools/LevelEdit/EditorChunkIDs.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/EditorChunkIDs.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 3/05/02 3:25p $*
|
||||
* *
|
||||
* $Revision:: 22 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __EDITOR_CHUNK_IDS_H
|
||||
#define __EDITOR_CHUNK_IDS_H
|
||||
|
||||
#include "saveloadids.h"
|
||||
#include "definitionclassids.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// These are the chunk IDs that serve as 'globally-unique' persist identifiers for
|
||||
// all persist objects inside the editor. These are used when building the
|
||||
// PersistFactoryClass's for definitions.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
CHUNKID_TERRAIN_DEF = CHUNKID_COMMANDO_EDITOR_BEGIN,
|
||||
CHUNKID_TILE_DEF,
|
||||
CHUNKID_LIGHT_DEF,
|
||||
CHUNKID_WAYPATH_DEF,
|
||||
CHUNKID_EDITOR_ZONE_DEF,
|
||||
CHUNKID_TRANSITION_DEF,
|
||||
CHUNKID_EDITOR_PHYS,
|
||||
CHUNKID_PRESET,
|
||||
CHUNKID_PRESETMGR,
|
||||
CHUNKID_NODEMGR,
|
||||
CHUNKID_NODE_TERRAIN,
|
||||
CHUNKID_NODE_TILE,
|
||||
CHUNKID_NODE_OBJECTS,
|
||||
CHUNKID_NODE_LIGHT,
|
||||
CHUNKID_NODE_OLD_SOUND,
|
||||
CHUNKID_NODE_WAYPATH,
|
||||
CHUNKID_NODE_ZONE,
|
||||
CHUNKID_NODE_TRANSITION,
|
||||
CHUNKID_EDITOR_SAVELOAD,
|
||||
CHUNKID_XXX,
|
||||
CHUNKID_NODE_TERRAIN_SECTION,
|
||||
CHUNKID_NODE_VIS_POINT,
|
||||
CHUNKID_VIS_POINT_DEF,
|
||||
CHUNKID_NODE_PATHFIND_START,
|
||||
CHUNKID_PATHFIND_START_DEF,
|
||||
CHUNKID_DUMMY_OBJECT_DEF,
|
||||
CHUNKID_DUMMY_OBJECT,
|
||||
CHUNKID_NODE_WAYPOINT,
|
||||
CHUNKID_COVERSPOT_DEF,
|
||||
CHUNKID_NODE_COVER_ATTACK_POINT,
|
||||
CHUNKID_NODE_COVER_SPOT,
|
||||
CHUNKID_NODE_DAMAGE_ZONE,
|
||||
XXX_CHUNKID_NODE_BUILDING,
|
||||
CHUNKID_NODE_SPAWN_POINT,
|
||||
CHUNKID_NODE_SPAWNER,
|
||||
CHUNKID_NODE_BUILDING,
|
||||
CHUNKID_NODE_BUILDING_CHILD,
|
||||
CHUNKID_NODE_NEW_SOUND,
|
||||
CHUNKID_EDITOR_ONLY_OBJECTS_DEF,
|
||||
CHUNKID_EDITOR_ONLY_OBJECTS,
|
||||
CHUNKID_EDITOR_PATHFIND_IMPORTER_EXPORTER,
|
||||
CHUNKID_EDITOR_LIGHT_SOLVE_SAVELOAD,
|
||||
CHUNKID_HEIGHTFIELD_MGR
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// These are the globally-unique class identifiers that the definition system
|
||||
// uses inside the editor.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
CLASSID_EDITOR_START = CLASSID_EDITOR_OBJECTS + 1,
|
||||
CLASSID_VIS_POINT_DEF,
|
||||
CLASSID_PATHFIND_START_DEF,
|
||||
CLASSID_LIGHT_DEF,
|
||||
CLASSID_COVERSPOT,
|
||||
CLASSID_EDITOR_ONLY_OBJECTS
|
||||
};
|
||||
|
||||
#endif //__EDITOR_CHUNK_IDS_H
|
||||
245
Code/Tools/LevelEdit/EditorINI.cpp
Normal file
245
Code/Tools/LevelEdit/EditorINI.cpp
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/EditorINI.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 8/04/99 3:26p $*
|
||||
* *
|
||||
* $Revision:: 3 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "StdAfx.H"
|
||||
#include "EditorINI.H"
|
||||
#include "b64pipe.h"
|
||||
#include "b64straw.h"
|
||||
#include "xstraw.h"
|
||||
#include "xpipe.h"
|
||||
#include "xstraw.h"
|
||||
#include "INISup.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Vector3
|
||||
//
|
||||
Vector3
|
||||
EditorINIClass::Get_Vector3
|
||||
(
|
||||
LPCTSTR section,
|
||||
LPCTSTR entry,
|
||||
const Vector3 &defvalue
|
||||
) const
|
||||
{
|
||||
if (section != NULL && entry != NULL) {
|
||||
INIEntry * entryptr = Find_Entry(section, entry);
|
||||
if (entryptr && entryptr->Value != NULL) {
|
||||
Vector3 ret;
|
||||
if ( sscanf( entryptr->Value, "%f,%f,%f", &ret[0], &ret[1], &ret[2] ) == 3 ) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return defvalue;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Vector4
|
||||
//
|
||||
Vector4
|
||||
EditorINIClass::Get_Vector4
|
||||
(
|
||||
LPCTSTR section,
|
||||
LPCTSTR entry,
|
||||
const Vector4 &defvalue
|
||||
) const
|
||||
{
|
||||
if (section != NULL && entry != NULL) {
|
||||
INIEntry * entryptr = Find_Entry(section, entry);
|
||||
if (entryptr && entryptr->Value != NULL) {
|
||||
Vector4 ret;
|
||||
if ( sscanf( entryptr->Value, "%f,%f,%f,%f", &ret[0], &ret[1], &ret[2], &ret[3] ) == 4 ) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return defvalue;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_CString
|
||||
//
|
||||
CString
|
||||
EditorINIClass::Get_CString
|
||||
(
|
||||
LPCTSTR section,
|
||||
LPCTSTR entry,
|
||||
LPCTSTR defvalue
|
||||
) const
|
||||
{
|
||||
// Read the string from the INI file
|
||||
TCHAR temp_string[128];
|
||||
Get_String (section, entry, defvalue, temp_string, sizeof (temp_string));
|
||||
|
||||
// Convert the string to a CString object and return it to the caller
|
||||
return CString (temp_string);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Matrix3D
|
||||
//
|
||||
Matrix3D
|
||||
EditorINIClass::Get_Matrix3D
|
||||
(
|
||||
LPCTSTR section,
|
||||
LPCTSTR entry,
|
||||
Matrix3D &defvalue
|
||||
) const
|
||||
{
|
||||
// check input parameters
|
||||
if ( section == NULL || entry == NULL ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// read UU string
|
||||
char buffer[128];
|
||||
int length = Get_String(section, entry, "", buffer, sizeof(buffer));
|
||||
|
||||
Matrix3D tm(1);
|
||||
if (buffer[0] != 0) {
|
||||
ASSERT( strlen( buffer ) == 4*4*4 );
|
||||
|
||||
// convert UU string to Matrix3D
|
||||
|
||||
ASSERT( sizeof( Matrix3D ) == 3*4*4 );
|
||||
Base64Pipe b64pipe(Base64Pipe::DECODE);
|
||||
BufferPipe bpipe((void*)&tm, sizeof( Matrix3D ) );
|
||||
b64pipe.Put_To(&bpipe);
|
||||
int outcount = b64pipe.Put(buffer, length);
|
||||
outcount += b64pipe.End();
|
||||
ASSERT( outcount == sizeof( Matrix3D ) );
|
||||
}
|
||||
|
||||
// Pass the matrix back to the caller
|
||||
return tm;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Put_Matrix3D
|
||||
//
|
||||
bool
|
||||
EditorINIClass::Put_Matrix3D
|
||||
(
|
||||
LPCTSTR section,
|
||||
LPCTSTR entry,
|
||||
const Matrix3D &value
|
||||
)
|
||||
{
|
||||
// check input parameters
|
||||
if ( section == NULL || entry == NULL ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert Matrix3D to UU string
|
||||
ASSERT( sizeof( Matrix3D ) == 3*4*4 );
|
||||
BufferStraw straw( (void*)&value, sizeof( Matrix3D ) );
|
||||
Base64Straw bstraw(Base64Straw::ENCODE);
|
||||
bstraw.Get_From(straw);
|
||||
static char mat_str[4*4*4 + 1];
|
||||
int length = bstraw.Get(mat_str, sizeof(mat_str)-1);
|
||||
ASSERT( length == 4*4*4 );
|
||||
mat_str[length] = '\0';
|
||||
|
||||
// save the UU string
|
||||
Put_String(section, entry, mat_str);
|
||||
|
||||
// Return the true result code
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Put_Vector3
|
||||
//
|
||||
bool
|
||||
EditorINIClass::Put_Vector3
|
||||
(
|
||||
LPCTSTR section,
|
||||
LPCTSTR entry,
|
||||
const Vector3 &value
|
||||
)
|
||||
{
|
||||
// Assume failure
|
||||
bool retval = false;
|
||||
|
||||
// Convert the vector to a string and write the string to the INI
|
||||
CString string_value;
|
||||
string_value.Format ("%f, %f, %f", value.X, value.Y, value.Z);
|
||||
retval = Put_String (section, entry, (LPCTSTR)string_value);
|
||||
|
||||
// Return the true/false result code
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Put_Vector4
|
||||
//
|
||||
bool
|
||||
EditorINIClass::Put_Vector4
|
||||
(
|
||||
LPCTSTR section,
|
||||
LPCTSTR entry,
|
||||
const Vector4 &value
|
||||
)
|
||||
{
|
||||
// Assume failure
|
||||
bool retval = false;
|
||||
|
||||
// Convert the vector to a string and write the string to the INI
|
||||
CString string_value;
|
||||
string_value.Format ("%f, %f, %f, %f", value.X, value.Y, value.Z, value.W);
|
||||
retval = Put_String (section, entry, (LPCTSTR)string_value);
|
||||
|
||||
// Return the true/false result code
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
82
Code/Tools/LevelEdit/EditorINI.h
Normal file
82
Code/Tools/LevelEdit/EditorINI.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/EditorINI.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 1/20/99 11:22a $*
|
||||
* *
|
||||
* $Revision:: 1 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __EDITORINI_H
|
||||
#define __EDITORINI_H
|
||||
|
||||
#include "INI.H"
|
||||
#include "Vector3.H"
|
||||
#include "Vector4.H"
|
||||
#include "Matrix3D.H"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditorINIClass
|
||||
//
|
||||
class EditorINIClass : public INIClass
|
||||
{
|
||||
public:
|
||||
|
||||
EditorINIClass (void)
|
||||
: INIClass () {}
|
||||
|
||||
EditorINIClass (FileClass &file)
|
||||
: INIClass (file) {}
|
||||
|
||||
//
|
||||
// Read methods
|
||||
//
|
||||
Vector3 Get_Vector3 (LPCTSTR section, LPCTSTR entry, const Vector3 &defvalue = Vector3 (0,0,0)) const;
|
||||
Vector4 Get_Vector4 (LPCTSTR section, LPCTSTR entry, const Vector4 &defvalue = Vector4 (0,0,0,0)) const;
|
||||
CString Get_CString (LPCTSTR section, LPCTSTR entry, LPCTSTR defvalue = "") const;
|
||||
Matrix3D Get_Matrix3D (LPCTSTR section, LPCTSTR entry_base, Matrix3D &defvalue = Matrix3D(1)) const;
|
||||
|
||||
//
|
||||
// Write methods
|
||||
//
|
||||
bool Put_Vector3 (LPCTSTR section, LPCTSTR entry, const Vector3 &value);
|
||||
bool Put_Vector4 (LPCTSTR section, LPCTSTR entry, const Vector4 &value);
|
||||
bool Put_Matrix3D (LPCTSTR section, LPCTSTR entry_base, const Matrix3D &value);
|
||||
};
|
||||
|
||||
#endif //__EDITORINI_H
|
||||
|
||||
164
Code/Tools/LevelEdit/EditorLine.h
Normal file
164
Code/Tools/LevelEdit/EditorLine.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/EditorLine.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 3/26/01 2:19p $*
|
||||
* *
|
||||
* $Revision:: 3 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __EDITOR_LINE_H
|
||||
#define __EDITOR_LINE_H
|
||||
|
||||
#include "editorphys.h"
|
||||
#include "segline.h"
|
||||
#include "vector3.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditorLineClass
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class EditorLineClass : public EditorPhysClass
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Public contsructors/destructors
|
||||
////////////////////////////////////////////////////////
|
||||
EditorLineClass (void);
|
||||
virtual ~EditorLineClass (void) { MEMBER_RELEASE (Line); }
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Position methods
|
||||
//
|
||||
void Reset (const Vector3 &start, const Vector3 &end);
|
||||
void Reset_Start (const Vector3 &start);
|
||||
void Reset_End (const Vector3 &end);
|
||||
|
||||
void Hide (bool onoff);
|
||||
|
||||
void Set_Color (const Vector3 &color) { Line->Set_Color ((Vector3 &)color); }
|
||||
void Set_Width (float width) { Line->Set_Width (width); Update_Cull_Box (); }
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
////////////////////////////////////////////////////////
|
||||
Vector3 StartPos;
|
||||
Vector3 EndPos;
|
||||
SegmentedLineClass * Line;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// EditorLineClass
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
inline
|
||||
EditorLineClass::EditorLineClass (void) :
|
||||
StartPos (0, 0, 0),
|
||||
EndPos (1, 1, 1),
|
||||
EditorPhysClass ()
|
||||
{
|
||||
Line = new SegmentedLineClass;
|
||||
|
||||
Vector3 locs[2] = { Vector3 (0,0,0), Vector3 (1,1,1) };
|
||||
Line->Set_Points (2, locs);
|
||||
|
||||
Line->Set_Width (0.075F);
|
||||
Line->Set_Color (Vector3 (0, 0, 0.75F));
|
||||
Line->Set_Opacity (1.0F);
|
||||
//Line->Set_Shader (ShaderClass::_PresetOpaqueSolidShader);
|
||||
|
||||
Set_Model (Line);
|
||||
return ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Reset
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
EditorLineClass::Reset (const Vector3 &start, const Vector3 &end)
|
||||
{
|
||||
Reset_Start (start);
|
||||
Reset_End (end);
|
||||
return ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Reset_Start
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
EditorLineClass::Reset_Start (const Vector3 &start)
|
||||
{
|
||||
StartPos = start;
|
||||
Set_Position (StartPos);
|
||||
Update_Cull_Box ();
|
||||
return ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Reset_End
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
EditorLineClass::Reset_End (const Vector3 &end)
|
||||
{
|
||||
Matrix3D::Inverse_Transform_Vector (Get_Transform (), end, &EndPos);
|
||||
Line->Set_Point_Location (1, EndPos);
|
||||
Update_Cull_Box ();
|
||||
return ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Hide
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
inline void
|
||||
EditorLineClass::Hide (bool onoff)
|
||||
{
|
||||
if (Line != NULL) {
|
||||
Line->Set_Hidden (onoff);
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
#endif //__EDITOR_LINE_H
|
||||
|
||||
105
Code/Tools/LevelEdit/EditorPhys.cpp
Normal file
105
Code/Tools/LevelEdit/EditorPhys.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/EditorPhys.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 11/11/99 5:47p $*
|
||||
* *
|
||||
* $Revision:: 4 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "StdAfx.H"
|
||||
#include "EditorPhys.H"
|
||||
#include "persist.h"
|
||||
#include "persistfactory.h"
|
||||
#include "editorchunkids.h"
|
||||
|
||||
//
|
||||
// Persist factory for EditorPhysClass
|
||||
//
|
||||
SimplePersistFactoryClass<EditorPhysClass, CHUNKID_EDITOR_PHYS> _EditorPhysFactory;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Bounding_Box
|
||||
//
|
||||
const AABoxClass &
|
||||
EditorPhysClass::Get_Bounding_Box (void) const
|
||||
{
|
||||
assert(Model);
|
||||
return Model->Get_Bounding_Box ();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Transform
|
||||
//
|
||||
const Matrix3D &
|
||||
EditorPhysClass::Get_Transform (void) const
|
||||
{
|
||||
assert(Model);
|
||||
return Model->Get_Transform();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Transform
|
||||
//
|
||||
void
|
||||
EditorPhysClass::Set_Transform (const Matrix3D &transform)
|
||||
{
|
||||
// Note: this kind of object never causes collisions so we
|
||||
// can just warp it to the users desired position. However,
|
||||
// we do need to tell the base class that we moved so that
|
||||
// it can tell the scene to update us in the culling system
|
||||
assert(Model);
|
||||
Model->Set_Transform (transform);
|
||||
Update_Cull_Box();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get_Factory
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
const PersistFactoryClass &
|
||||
EditorPhysClass::Get_Factory (void) const
|
||||
{
|
||||
//
|
||||
// This should NEVER be called...
|
||||
//
|
||||
ASSERT (0);
|
||||
return _EditorPhysFactory;
|
||||
}
|
||||
102
Code/Tools/LevelEdit/EditorPhys.h
Normal file
102
Code/Tools/LevelEdit/EditorPhys.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/EditorPhys.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 8/24/00 1:27p $*
|
||||
* *
|
||||
* $Revision:: 5 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __EDITORPHYS_H
|
||||
#define __EDITORPHYS_H
|
||||
|
||||
|
||||
#include "dynamicphys.h"
|
||||
#include "pscene.h"
|
||||
#include "wwdebug.h"
|
||||
#include "physcoltest.h"
|
||||
#include "rendobj.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditorPhysClass
|
||||
//
|
||||
// Editor's representation of a physics object.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
class EditorPhysClass : public DynamicPhysClass
|
||||
{
|
||||
public:
|
||||
|
||||
virtual bool Cast_Ray(PhysRayCollisionTestClass & raytest);
|
||||
virtual bool Cast_AABox(PhysAABoxCollisionTestClass & boxtest) { return false; }
|
||||
virtual bool Cast_OBBox(PhysOBBoxCollisionTestClass & boxtest) { return false; }
|
||||
virtual void Timestep (float dt) {};
|
||||
|
||||
virtual const AABoxClass & Get_Bounding_Box (void) const;
|
||||
virtual const Matrix3D & Get_Transform (void) const;
|
||||
virtual void Set_Transform (const Matrix3D &transform);
|
||||
|
||||
virtual const PersistFactoryClass & Get_Factory (void) const;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Cast_Ray
|
||||
//
|
||||
inline bool
|
||||
EditorPhysClass::Cast_Ray (PhysRayCollisionTestClass &raytest)
|
||||
{
|
||||
// State OK?
|
||||
WWASSERT (Model != NULL);
|
||||
|
||||
// Cast the ray and return the result
|
||||
bool retval = false;
|
||||
if ((Model != NULL) &&
|
||||
(Model->Cast_Ray (raytest))) {
|
||||
|
||||
// Success!
|
||||
raytest.CollidedPhysObj = this;
|
||||
retval = true;
|
||||
}
|
||||
|
||||
// Return the true/false result code
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif //__EDITORPHYS_H
|
||||
|
||||
428
Code/Tools/LevelEdit/EditorPropSheet.cpp
Normal file
428
Code/Tools/LevelEdit/EditorPropSheet.cpp
Normal file
@@ -0,0 +1,428 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// EditorPropSheetClass.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "leveledit.h"
|
||||
#include "EditorPropSheet.H"
|
||||
#include "Utils.H"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Local constants
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
static const int BORDER_BUTTON_X = 6;
|
||||
static const int BORDER_BUTTON_Y = 6;
|
||||
static const int BORDER_TAB_X = 6;
|
||||
static const int BORDER_TAB_Y = 6;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditorPropSheetClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
EditorPropSheetClass::EditorPropSheetClass (void)
|
||||
: m_iCurrentTab (0),
|
||||
m_IsReadOnly (false),
|
||||
CDialog(EditorPropSheetClass::IDD, ::AfxGetMainWnd ())
|
||||
{
|
||||
//{{AFX_DATA_INIT(EditorPropSheetClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~EditorPropSheetClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
EditorPropSheetClass::~EditorPropSheetClass (void)
|
||||
{
|
||||
m_TabList.Delete_All ();
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorPropSheetClass::DoDataExchange (CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(EditorPropSheetClass)
|
||||
DDX_Control(pDX, IDC_TABCTRL, m_TabCtrl);
|
||||
//}}AFX_DATA_MAP
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(EditorPropSheetClass, CDialog)
|
||||
//{{AFX_MSG_MAP(EditorPropSheetClass)
|
||||
ON_WM_SIZE()
|
||||
ON_NOTIFY(TCN_SELCHANGE, IDC_TABCTRL, OnSelchangeTabCtrl)
|
||||
ON_BN_CLICKED(IDC_OK, OnOk)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// EditorPropSheetClass diagnostics
|
||||
|
||||
#ifdef _DEBUG
|
||||
void EditorPropSheetClass::AssertValid() const
|
||||
{
|
||||
CDialog::AssertValid();
|
||||
}
|
||||
|
||||
void EditorPropSheetClass::Dump(CDumpContext& dc) const
|
||||
{
|
||||
CDialog::Dump(dc);
|
||||
}
|
||||
#endif //_DEBUG
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Reposition_Buttons
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorPropSheetClass::Reposition_Buttons (int cx, int cy)
|
||||
{
|
||||
//
|
||||
// Get the dimensions of the buttons
|
||||
//
|
||||
CRect button_rect;
|
||||
::GetWindowRect (::GetDlgItem (m_hWnd, IDCANCEL), &button_rect);
|
||||
ScreenToClient (&button_rect);
|
||||
|
||||
//
|
||||
// Reposition the OK and Cancel buttons
|
||||
//
|
||||
::SetWindowPos (::GetDlgItem (m_hWnd, IDCANCEL),
|
||||
NULL,
|
||||
(cx - button_rect.Width ()) - BORDER_BUTTON_X,
|
||||
(cy - button_rect.Height ()) - BORDER_BUTTON_Y,
|
||||
0,
|
||||
0,
|
||||
SWP_NOZORDER | SWP_NOSIZE);
|
||||
|
||||
::SetWindowPos (::GetDlgItem (m_hWnd, IDC_OK),
|
||||
NULL,
|
||||
(cx - (button_rect.Width () << 1)) - (BORDER_BUTTON_X * 2),
|
||||
(cy - button_rect.Height ()) - BORDER_BUTTON_Y,
|
||||
0,
|
||||
0,
|
||||
SWP_NOZORDER | SWP_NOSIZE);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnSize
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorPropSheetClass::OnSize
|
||||
(
|
||||
UINT nType,
|
||||
int cx,
|
||||
int cy
|
||||
)
|
||||
{
|
||||
// Allow the base class to process this message
|
||||
CDialog::OnSize (nType, cx, cy);
|
||||
|
||||
if (::IsWindow (m_TabCtrl) && (cx > 0) && (cy > 0)) {
|
||||
|
||||
//
|
||||
// Get the dimensions of the buttons
|
||||
//
|
||||
CRect button_rect;
|
||||
::GetWindowRect (::GetDlgItem (m_hWnd, IDCANCEL), &button_rect);
|
||||
ScreenToClient (&button_rect);
|
||||
|
||||
//
|
||||
// Move the buttons so they continue to be in the lower right corner
|
||||
//
|
||||
Reposition_Buttons (cx, cy);
|
||||
|
||||
//
|
||||
// Shrink the bounds by BORDER_TAB_X (to give a little border)
|
||||
//
|
||||
cx -= BORDER_TAB_X * 2;
|
||||
cy -= (BORDER_TAB_Y * 2) + (button_rect.Height () + BORDER_BUTTON_Y);
|
||||
|
||||
// Resize the tab control to fill the entire contents of the client area
|
||||
m_TabCtrl.SetWindowPos (NULL, 0, 0, cx, cy, SWP_NOZORDER | SWP_NOMOVE);
|
||||
|
||||
// Get the display rectangle of the tab control
|
||||
CRect rect;
|
||||
m_TabCtrl.GetWindowRect (&rect);
|
||||
m_TabCtrl.AdjustRect (FALSE, &rect);
|
||||
|
||||
// Convert the display rectangle from screen to client coords
|
||||
ScreenToClient (&rect);
|
||||
|
||||
// Loop through all the tabs in the property sheet
|
||||
for (int tab = 0;
|
||||
tab < m_TabList.Count ();
|
||||
tab ++) {
|
||||
|
||||
// Get a pointer to this tab
|
||||
DockableFormClass *ptab = m_TabList[tab];
|
||||
if (ptab != NULL) {
|
||||
// Resize this tab
|
||||
ptab->SetWindowPos (NULL, rect.left, rect.top, rect.Width (), rect.Height (), SWP_NOZORDER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnSelchangeTabCtrl
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorPropSheetClass::OnSelchangeTabCtrl
|
||||
(
|
||||
NMHDR* pNMHDR,
|
||||
LRESULT* pResult
|
||||
)
|
||||
{
|
||||
// Which tab is selected?
|
||||
int newtab = m_TabCtrl.GetCurSel ();
|
||||
|
||||
// Is this a new tab?
|
||||
if (m_iCurrentTab != newtab) {
|
||||
|
||||
// Is the old tab valid?
|
||||
if (m_TabList[m_iCurrentTab] != NULL) {
|
||||
// Hide the contents of the old tab
|
||||
m_TabList[m_iCurrentTab]->ShowWindow (SW_HIDE);
|
||||
}
|
||||
|
||||
// Is the new tab valid?
|
||||
if (m_TabList[newtab] != NULL) {
|
||||
// Show the contents of the new tab
|
||||
m_TabList[newtab]->ShowWindow (SW_SHOW);
|
||||
}
|
||||
|
||||
// Remember what our new current tab is
|
||||
m_iCurrentTab = newtab;
|
||||
}
|
||||
|
||||
(*pResult) = 0;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
EditorPropSheetClass::OnInitDialog (void)
|
||||
{
|
||||
// Allow the base class to process this message
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
// Move the tab control so it starts at 2, 2
|
||||
m_TabCtrl.SetWindowPos (NULL, BORDER_TAB_X, BORDER_TAB_Y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
||||
|
||||
// Loop through all the tabs in our list
|
||||
int cx = 0;
|
||||
int cy = 0;
|
||||
for (int tab = 0;
|
||||
tab < m_TabList.Count ();
|
||||
tab ++) {
|
||||
|
||||
// Get a pointer to this tab
|
||||
DockableFormClass *ptab = m_TabList[tab];
|
||||
|
||||
// Was the tab pointer valid?
|
||||
ASSERT (ptab != NULL);
|
||||
if (ptab != NULL) {
|
||||
|
||||
// Create the window associated with this tab
|
||||
ptab->Create (this, 100 + tab);
|
||||
|
||||
// Hide the tab if it isn't the first one
|
||||
ptab->ShowWindow ((tab == 0) ? SW_SHOW : SW_HIDE);
|
||||
|
||||
// Get the name of this tab from its form
|
||||
CString tab_name;
|
||||
ptab->GetWindowText (tab_name);
|
||||
|
||||
// Determine if we need to stretch our cx and cy
|
||||
CRect rect = ptab->Get_Form_Rect ();
|
||||
cx = (rect.Width () > cx) ? rect.Width () : cx;
|
||||
cy = (rect.Height () > cy) ? rect.Height() : cy;
|
||||
|
||||
ptab->SetWindowPos (NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER);
|
||||
|
||||
// Now insert a tab into the tab control for this form
|
||||
TC_ITEM tabInfo = { 0 };
|
||||
tabInfo.mask = TCIF_TEXT;
|
||||
tabInfo.pszText = (LPTSTR)(LPCTSTR)tab_name;
|
||||
m_TabCtrl.InsertItem (tab, &tabInfo);
|
||||
}
|
||||
}
|
||||
|
||||
m_TabList[0]->SetFocus ();
|
||||
|
||||
if ((cx > 0) && (cy > 0)) {
|
||||
|
||||
// Get the display rectangle of the tab control
|
||||
CRect rect (0, 0, cx, cy);
|
||||
m_TabCtrl.AdjustRect (TRUE, &rect);
|
||||
|
||||
CRect button_rect;
|
||||
::GetWindowRect (::GetDlgItem (m_hWnd, IDCANCEL), &button_rect);
|
||||
ScreenToClient (&button_rect);
|
||||
|
||||
// Find a rectangle large enough to hold the tab control
|
||||
::AdjustWindowRectEx (&rect, ::GetWindowLong (m_hWnd, GWL_STYLE), FALSE, ::GetWindowLong (m_hWnd, GWL_EXSTYLE));
|
||||
rect.bottom += button_rect.Height () + BORDER_BUTTON_Y;
|
||||
rect.InflateRect (BORDER_TAB_X, BORDER_TAB_Y);
|
||||
|
||||
// Resize the dialog to be large enough to hold the tab control
|
||||
SetWindowPos (NULL, 0, 0, rect.Width (), rect.Height (), SWP_NOZORDER | SWP_NOMOVE);
|
||||
}
|
||||
|
||||
if (m_IsReadOnly) {
|
||||
::ShowWindow (::GetDlgItem (m_hWnd, IDC_OK), SW_HIDE);
|
||||
SetDlgItemText (IDCANCEL, "Close");
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnCommand
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
EditorPropSheetClass::OnCommand
|
||||
(
|
||||
WPARAM wParam,
|
||||
LPARAM lParam
|
||||
)
|
||||
{
|
||||
// Did the user hit the enter button?
|
||||
if (LOWORD (wParam) == IDOK) {
|
||||
m_TabList[m_iCurrentTab]->SendMessage (WM_COMMAND, wParam, lParam);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Allow the base class to process this message
|
||||
return CDialog::OnCommand(wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOk
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorPropSheetClass::OnOk (void)
|
||||
{
|
||||
if (Apply_Changes ()) {
|
||||
EndDialog (IDOK);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Apply_Changes
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditorPropSheetClass::Apply_Changes (void)
|
||||
{
|
||||
bool is_valid = true;
|
||||
|
||||
for (int index = 0; index < m_TabList.Count (); index ++) {
|
||||
DockableFormClass *tab = m_TabList[index];
|
||||
ASSERT (tab != NULL);
|
||||
if (tab != NULL) {
|
||||
|
||||
//
|
||||
// Have the tab apply its changes
|
||||
//
|
||||
is_valid &= tab->Apply_Changes ();
|
||||
}
|
||||
}
|
||||
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnCancel
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorPropSheetClass::OnCancel (void)
|
||||
{
|
||||
for (int tab = 0;
|
||||
tab < m_TabList.Count ();
|
||||
tab ++) {
|
||||
|
||||
// Get a pointer to this tab
|
||||
DockableFormClass *ptab = m_TabList[tab];
|
||||
|
||||
// Was the tab pointer valid?
|
||||
ASSERT (ptab != NULL);
|
||||
if (ptab != NULL) {
|
||||
|
||||
// Have the tab discard its changes
|
||||
ptab->Discard_Changes ();
|
||||
}
|
||||
}
|
||||
|
||||
CDialog::OnCancel ();
|
||||
return ;
|
||||
}
|
||||
124
Code/Tools/LevelEdit/EditorPropSheet.h
Normal file
124
Code/Tools/LevelEdit/EditorPropSheet.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_EDITORPROPSHEETCLASS_H__E2623E75_740A_11D2_9FD0_00104B791122__INCLUDED_)
|
||||
#define AFX_EDITORPROPSHEETCLASS_H__E2623E75_740A_11D2_9FD0_00104B791122__INCLUDED_
|
||||
|
||||
#if _MSC_VER >= 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER >= 1000
|
||||
// EditorPropSheetClass.h : header file
|
||||
//
|
||||
|
||||
#include "dockableform.h"
|
||||
#include "vector.h"
|
||||
#include "resource.h"
|
||||
|
||||
#ifndef __AFXEXT_H__
|
||||
#include <afxext.h>
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditorPropSheetClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class EditorPropSheetClass : public CDialog
|
||||
{
|
||||
public:
|
||||
EditorPropSheetClass (void);
|
||||
virtual ~EditorPropSheetClass (void);
|
||||
|
||||
// Form Data
|
||||
public:
|
||||
//{{AFX_DATA(EditorPropSheetClass)
|
||||
enum { IDD = IDD_PROP_SHEET_TEMPLATE };
|
||||
CTabCtrl m_TabCtrl;
|
||||
//}}AFX_DATA
|
||||
|
||||
// Attributes
|
||||
public:
|
||||
|
||||
// Operations
|
||||
public:
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(EditorPropSheetClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
#ifdef _DEBUG
|
||||
virtual void AssertValid() const;
|
||||
virtual void Dump(CDumpContext& dc) const;
|
||||
#endif
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(EditorPropSheetClass)
|
||||
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||
afx_msg void OnSelchangeTabCtrl(NMHDR* pNMHDR, LRESULT* pResult);
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnOk();
|
||||
virtual void OnCancel();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////
|
||||
virtual void Add_Page (DockableFormClass *pnew_tab) { if (m_hWnd == NULL) m_TabList.Add (pnew_tab); }
|
||||
|
||||
bool Is_Read_Only (void) const { return m_IsReadOnly; }
|
||||
void Set_Read_Only (bool onoff) { m_IsReadOnly = onoff; }
|
||||
|
||||
protected:
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
///////////////////////////////////////////////////
|
||||
virtual void Reposition_Buttons (int cx, int cy);
|
||||
virtual bool Apply_Changes (void);
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Protected member data
|
||||
///////////////////////////////////////////////////
|
||||
DynamicVectorClass<DockableFormClass *> m_TabList;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Private member data
|
||||
///////////////////////////////////////////////////
|
||||
int m_iCurrentTab;
|
||||
bool m_IsReadOnly;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_EDITORPROPSHEETCLASS_H__E2623E75_740A_11D2_9FD0_00104B791122__INCLUDED_)
|
||||
856
Code/Tools/LevelEdit/EditorSaveLoad.cpp
Normal file
856
Code/Tools/LevelEdit/EditorSaveLoad.cpp
Normal file
@@ -0,0 +1,856 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/EditorSaveLoad.cpp $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 3/05/02 3:30p $*
|
||||
* *
|
||||
* $Revision:: 37 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveleditdoc.h"
|
||||
#include "editorsaveload.h"
|
||||
#include "persist.h"
|
||||
#include "persistfactory.h"
|
||||
#include "preset.h"
|
||||
#include "utils.h"
|
||||
#include "definition.h"
|
||||
#include "editorchunkids.h"
|
||||
#include "physstaticsavesystem.h"
|
||||
#include "chunkio.h"
|
||||
#include "cameramgr.h"
|
||||
#include "filemgr.h"
|
||||
#include "matrix3d.h"
|
||||
#include "rawfile.h"
|
||||
#include "nodemgr.h"
|
||||
#include "sceneeditor.h"
|
||||
#include "node.h"
|
||||
#include "lightambientform.h"
|
||||
#include "soundscene.h"
|
||||
#include "backgroundmgr.h"
|
||||
#include "conversationmgr.h"
|
||||
#include "weathermgr.h"
|
||||
#include "combat.h"
|
||||
#include "mapmgr.h"
|
||||
#include "pathfind.h"
|
||||
#include "lightsolvesavesystem.h"
|
||||
#include "heightfieldmgr.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Global singleton instance
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
EditorSaveLoadClass _TheEditorSaveLoadSubsystem;
|
||||
PathfindImportExportSaveLoadClass _ThePathfindImporterExporter;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Static member initialization
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool EditorSaveLoadClass::m_LoadedValidVis = true;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
CHUNKID_MICRO_CHUNKS = 0x10140738,
|
||||
CHUNKID_OBSOLETE,
|
||||
CHUNKID_PATHFIND_DATA
|
||||
};
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
VARID_INCLUDE_FILE = 0x01,
|
||||
VARID_CAMERA_TM,
|
||||
VARID_OBSOLETE_0,
|
||||
VARID_BACK_MUSIC,
|
||||
VARID_AMBIENT_LIGHT,
|
||||
VARID_OBSOLETE_1,
|
||||
VARID_OBSOLETE_2,
|
||||
VARID_FAR_CLIP_PLANE_DOUBLE,
|
||||
VARID_FOG_COLOR,
|
||||
VARID_FOG_PLANES,
|
||||
VARID_FOG_ENABLED,
|
||||
VARID_FAR_CLIP_PLANE,
|
||||
VARID_RESTART_SCRIPT_NAME,
|
||||
VARID_RESPAWN_SCRIPT_NAME,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHUNKID_LVL_DATA = 304021447,
|
||||
CHUNKID_LIGHT_SOLVE,
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Chunk_ID
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
uint32
|
||||
EditorSaveLoadClass::Chunk_ID (void) const
|
||||
{
|
||||
return CHUNKID_EDITOR_SAVELOAD;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Contains_Data
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditorSaveLoadClass::Contains_Data (void) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditorSaveLoadClass::Save (ChunkSaveClass &csave)
|
||||
{
|
||||
bool retval = true;
|
||||
int index;
|
||||
|
||||
csave.Begin_Chunk (CHUNKID_MICRO_CHUNKS);
|
||||
|
||||
//
|
||||
// Write the camera transform to the chunk
|
||||
//
|
||||
Matrix3D camera_tm = ::Get_Camera_Mgr ()->Get_Camera ()->Get_Transform ();
|
||||
WRITE_MICRO_CHUNK (csave, VARID_CAMERA_TM, camera_tm);
|
||||
|
||||
//
|
||||
// Write the miscellaneous level settings to the chunk
|
||||
//
|
||||
Vector3 ambient_light = ::Get_Scene_Editor ()->Get_Ambient_Light ();
|
||||
WRITE_MICRO_CHUNK (csave, VARID_AMBIENT_LIGHT, ambient_light);
|
||||
|
||||
//
|
||||
// Save the fog settings
|
||||
//
|
||||
bool fog_enabled = false;
|
||||
struct
|
||||
{
|
||||
float z_near;
|
||||
float z_far;
|
||||
} fog_planes = { 50.0F, 100.0F };
|
||||
|
||||
Vector3 fog_color (0, 0, 0);
|
||||
::Get_Scene_Editor ()->Get_Fog_Range (&fog_planes.z_near, &fog_planes.z_far);
|
||||
fog_color = ::Get_Scene_Editor ()->Get_Fog_Color ();
|
||||
fog_enabled = ::Get_Scene_Editor ()->Get_Fog_Enable ();
|
||||
|
||||
WRITE_MICRO_CHUNK (csave, VARID_FOG_ENABLED, fog_enabled);
|
||||
WRITE_MICRO_CHUNK (csave, VARID_FOG_COLOR, fog_color);
|
||||
WRITE_MICRO_CHUNK (csave, VARID_FOG_PLANES, fog_planes);
|
||||
|
||||
//
|
||||
// Save the restart and respawn script names
|
||||
//
|
||||
StringClass restart_script_name = CombatManager::Get_Start_Script ();
|
||||
StringClass respawn_script_name = CombatManager::Get_Respawn_Script ();
|
||||
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_RESTART_SCRIPT_NAME, restart_script_name);
|
||||
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_RESPAWN_SCRIPT_NAME, respawn_script_name);
|
||||
|
||||
//
|
||||
// Save the far clip plane...
|
||||
//
|
||||
float znear = 0;
|
||||
float zfar = 0;
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Get_Clip_Planes (znear, zfar);
|
||||
WRITE_MICRO_CHUNK (csave, VARID_FAR_CLIP_PLANE, zfar);
|
||||
|
||||
//
|
||||
// Write the background music filename out to the chunk
|
||||
//
|
||||
CString filename = ::Get_Scene_Editor ()->Get_Background_Music_Filename ();
|
||||
CString path = ::Get_File_Mgr ()->Make_Relative_Path (filename);
|
||||
WRITE_MICRO_CHUNK_STRING (csave, VARID_BACK_MUSIC, (LPCTSTR)path);
|
||||
|
||||
//
|
||||
// Write the list of include files for the level to the chunk.
|
||||
//
|
||||
STRING_LIST &include_list = ::Get_File_Mgr ()->Get_Include_File_List ();
|
||||
for (index = 0; index < include_list.Count (); index ++) {
|
||||
StringClass filename = (LPCTSTR)include_list[index];
|
||||
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_INCLUDE_FILE, filename);
|
||||
}
|
||||
|
||||
csave.End_Chunk ();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditorSaveLoadClass::Load (ChunkLoadClass &cload)
|
||||
{
|
||||
bool retval = true;
|
||||
while (cload.Open_Chunk ()) {
|
||||
switch (cload.Cur_Chunk_ID ()) {
|
||||
|
||||
//
|
||||
// Load all the presets from this chunk
|
||||
//
|
||||
case CHUNKID_MICRO_CHUNKS:
|
||||
retval &= Load_Micro_Chunks (cload);
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Chunk ();
|
||||
}
|
||||
|
||||
SaveLoadSystemClass::Register_Post_Load_Callback (this);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_Micro_Chunks
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
EditorSaveLoadClass::Load_Micro_Chunks (ChunkLoadClass &cload)
|
||||
{
|
||||
bool retval = true;
|
||||
|
||||
Vector3 fog_color (0, 0, 0);
|
||||
bool fog_enabled = false;
|
||||
|
||||
StringClass restart_script_name;
|
||||
StringClass respawn_script_name;
|
||||
|
||||
while (cload.Open_Micro_Chunk ()) {
|
||||
switch (cload.Cur_Micro_Chunk_ID ()) {
|
||||
|
||||
//
|
||||
// Read the camera's transformation matrix from the chunk
|
||||
// and pass it onto the camera.
|
||||
//
|
||||
case VARID_CAMERA_TM:
|
||||
{
|
||||
Matrix3D camera_tm;
|
||||
cload.Read(&camera_tm,sizeof (camera_tm));
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Set_Transform (camera_tm);
|
||||
}
|
||||
break;
|
||||
|
||||
//
|
||||
// Read the include file from the chunk and add it to the list
|
||||
// of level include files.
|
||||
//
|
||||
case VARID_INCLUDE_FILE:
|
||||
{
|
||||
StringClass filename;
|
||||
cload.Read(filename.Get_Buffer(cload.Cur_Micro_Chunk_Length()),cload.Cur_Micro_Chunk_Length());
|
||||
::Get_File_Mgr ()->Get_Include_File_List ().Add ((LPCTSTR)filename);
|
||||
}
|
||||
break;
|
||||
|
||||
case VARID_FAR_CLIP_PLANE_DOUBLE:
|
||||
{
|
||||
float znear = 0;
|
||||
float zfar = 0;
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Get_Clip_Planes (znear, zfar);
|
||||
|
||||
double double_zfar = 0;
|
||||
cload.Read (&double_zfar, sizeof (double_zfar));
|
||||
zfar = double_zfar;
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Set_Clip_Planes (znear, zfar);
|
||||
}
|
||||
break;
|
||||
|
||||
case VARID_FAR_CLIP_PLANE:
|
||||
{
|
||||
float znear = 0;
|
||||
float zfar = 0;
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Get_Clip_Planes (znear, zfar);
|
||||
cload.Read (&zfar, sizeof (zfar));
|
||||
::Get_Camera_Mgr ()->Get_Camera ()->Set_Clip_Planes (znear, zfar);
|
||||
}
|
||||
break;
|
||||
|
||||
case VARID_AMBIENT_LIGHT:
|
||||
{
|
||||
Vector3 ambient_light;
|
||||
cload.Read (&ambient_light, sizeof (ambient_light));
|
||||
::Get_Scene_Editor ()->Set_Ambient_Light (ambient_light);
|
||||
::Get_Scene_Editor ()->Update_Lighting ();
|
||||
|
||||
LightAmbientFormClass *light_form = Get_Ambient_Light_Form ();
|
||||
light_form->Update_Settings ();
|
||||
}
|
||||
break;
|
||||
|
||||
READ_MICRO_CHUNK (cload, VARID_FOG_ENABLED, fog_enabled);
|
||||
READ_MICRO_CHUNK (cload, VARID_FOG_COLOR, fog_color);
|
||||
|
||||
READ_MICRO_CHUNK_WWSTRING (cload, VARID_RESTART_SCRIPT_NAME, restart_script_name);
|
||||
READ_MICRO_CHUNK_WWSTRING (cload, VARID_RESPAWN_SCRIPT_NAME, respawn_script_name);
|
||||
|
||||
case VARID_FOG_PLANES:
|
||||
{
|
||||
struct
|
||||
{
|
||||
float z_near;
|
||||
float z_far;
|
||||
} fog_planes = { 50.0F, 100.0F };
|
||||
|
||||
cload.Read (&fog_planes, sizeof (fog_planes));
|
||||
::Get_Scene_Editor ()->Set_Fog_Range (fog_planes.z_near, fog_planes.z_far);
|
||||
}
|
||||
break;
|
||||
|
||||
case VARID_BACK_MUSIC:
|
||||
{
|
||||
StringClass filename;
|
||||
cload.Read(filename.Get_Buffer(cload.Cur_Micro_Chunk_Length()),cload.Cur_Micro_Chunk_Length());
|
||||
::Get_Scene_Editor ()->Set_Background_Music (filename);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Micro_Chunk ();
|
||||
}
|
||||
|
||||
//
|
||||
// Apply the script settings
|
||||
//
|
||||
CombatManager::Set_Start_Script (restart_script_name);
|
||||
CombatManager::Set_Respawn_Script (respawn_script_name);
|
||||
|
||||
//
|
||||
// Apply the fog settings
|
||||
//
|
||||
::Get_Scene_Editor ()->Set_Fog_Color (fog_color);
|
||||
::Get_Scene_Editor ()->Set_Fog_Enable (fog_enabled);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save_Level
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorSaveLoadClass::Save_Level (LPCTSTR filename)
|
||||
{
|
||||
//
|
||||
// Create the file
|
||||
//
|
||||
HANDLE hfile = ::CreateFile (filename,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
0L,
|
||||
NULL);
|
||||
|
||||
ASSERT (hfile != INVALID_HANDLE_VALUE);
|
||||
if (hfile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (hfile);
|
||||
ChunkSaveClass chunk_save (&file_obj);
|
||||
|
||||
//
|
||||
// (gth) March 4, 2002 - modifying this function to embed two "save files" into this
|
||||
// file. The first chunk will contain an entire save for the normal level data. The second
|
||||
// chunk will contain the lighting save
|
||||
//
|
||||
chunk_save.Begin_Chunk(CHUNKID_LVL_DATA);
|
||||
Save_Level_Data(chunk_save);
|
||||
chunk_save.End_Chunk();
|
||||
|
||||
chunk_save.Begin_Chunk(CHUNKID_LIGHT_SOLVE);
|
||||
Save_Light_Solve(chunk_save);
|
||||
chunk_save.End_Chunk();
|
||||
|
||||
|
||||
//
|
||||
// Remember that we are now up-to-date
|
||||
//
|
||||
Set_Modified (false);
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save_Level_Data - saves the level data for an LVL file
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorSaveLoadClass::Save_Level_Data(ChunkSaveClass & chunk_save)
|
||||
{
|
||||
//
|
||||
// Repartition the static culling systems
|
||||
// (gth) can't re-partition the object culling systems or
|
||||
// we'll lose hierarchical vis
|
||||
//
|
||||
::Get_Scene_Editor ()->Re_Partition_Static_Lights ();
|
||||
::Get_Scene_Editor ()->Re_Partition_Audio_System ();
|
||||
|
||||
//
|
||||
// Basically just save the list of nodes and some other
|
||||
// miscellaneous information (camera, sky, etc).
|
||||
//
|
||||
SaveLoadSystemClass::Save (chunk_save, _PhysStaticDataSaveSystem);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheNodeMgr);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheEditorSaveLoadSubsystem);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheBackgroundMgr);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheWeatherMgr);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheMapMgrSaveLoadSubsystem);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheHeightfieldMgrSaveLoadSubsystem);
|
||||
|
||||
//
|
||||
// Save the level-specific conversations
|
||||
//
|
||||
_ConversationMgrSaveLoad.Set_Category_To_Save (ConversationMgrClass::CATEGORY_LEVEL);
|
||||
SaveLoadSystemClass::Save (chunk_save, _ConversationMgrSaveLoad);
|
||||
return ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save_Light_Solve - saves the light-solve data for an LVL file
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void EditorSaveLoadClass::Save_Light_Solve(ChunkSaveClass & chunk_save)
|
||||
{
|
||||
SaveLoadSystemClass::Save( chunk_save, _TheLightSolveSaveSystem);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load_Level
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorSaveLoadClass::Load_Level (LPCTSTR filename)
|
||||
{
|
||||
//
|
||||
// Create the file
|
||||
//
|
||||
HANDLE hfile = ::CreateFile (filename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0L,
|
||||
NULL);
|
||||
|
||||
ASSERT (hfile != INVALID_HANDLE_VALUE);
|
||||
if (hfile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (hfile);
|
||||
ChunkLoadClass chunk_load (&file_obj);
|
||||
|
||||
SoundSceneClass *sound_scene = WWAudioClass::Get_Instance ()->Get_Sound_Scene ();
|
||||
if (sound_scene != NULL) {
|
||||
sound_scene->Set_Batch_Mode (true);
|
||||
}
|
||||
|
||||
//
|
||||
// Get the save-load subsystem to load
|
||||
//
|
||||
m_LoadedValidVis = true;
|
||||
NodeMgrClass::Free_Nodes ();
|
||||
|
||||
//
|
||||
// (gth) March 4, 2002 - LVL files are now two independent save-load operations,
|
||||
// one for the normal level data and one for the light solve data. Here, we
|
||||
// detect whether we are loading a file that was created before this change.
|
||||
//
|
||||
uint32 id,size;
|
||||
if (chunk_load.Peek_Next_Chunk(&id,&size) && (id == CHUNKID_LVL_DATA)) {
|
||||
|
||||
// Current file format, multiple saves embedded into this file
|
||||
while (chunk_load.Open_Chunk()) {
|
||||
|
||||
switch (chunk_load.Cur_Chunk_ID()) {
|
||||
case CHUNKID_LVL_DATA:
|
||||
case CHUNKID_LIGHT_SOLVE:
|
||||
SaveLoadSystemClass::Load (chunk_load);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
chunk_load.Close_Chunk();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Legacy file format support
|
||||
SaveLoadSystemClass::Load (chunk_load);
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Repartition the static culling systems
|
||||
// (gth) can't re-partition the object culling systems or
|
||||
// we'll lose hierarchical vis
|
||||
//
|
||||
::Get_Scene_Editor ()->Re_Partition_Static_Lights ();
|
||||
::Get_Scene_Editor ()->Re_Partition_Audio_System ();
|
||||
|
||||
//
|
||||
// Now create any embedded nodes (nodes that are embedded inside
|
||||
// the preset of any nodes that are currently in the level).
|
||||
//
|
||||
NodeMgrClass::Create_All_Embedded_Nodes ();
|
||||
|
||||
//
|
||||
// Validate VIS information if necessary
|
||||
//
|
||||
if (m_LoadedValidVis) {
|
||||
::Get_Scene_Editor ()->Validate_Vis ();
|
||||
::Get_Scene_Editor ()->Update_Culling_System_Bounding_Boxes ();
|
||||
} else {
|
||||
::MessageBox (NULL, "Static geometry has changed since the last time this level was loaded. All previously generated VIS data has been discarded.", "Vis Discarded", MB_ICONEXCLAMATION | MB_OK);
|
||||
::Get_Scene_Editor ()->Discard_Vis ();
|
||||
}
|
||||
|
||||
if (sound_scene != NULL) {
|
||||
sound_scene->Set_Batch_Mode (false);
|
||||
}
|
||||
|
||||
//
|
||||
// Remember that we are now up-to-date
|
||||
//
|
||||
Set_Modified (false);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Export_Dynamic_Objects
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorSaveLoadClass::Export_Dynamic_Objects (LPCTSTR filename)
|
||||
{
|
||||
//
|
||||
// Create the file
|
||||
//
|
||||
HANDLE hfile = ::CreateFile (filename,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
0L,
|
||||
NULL);
|
||||
|
||||
ASSERT (hfile != INVALID_HANDLE_VALUE);
|
||||
if (hfile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (hfile);
|
||||
ChunkSaveClass chunk_save (&file_obj);
|
||||
|
||||
//
|
||||
// Remove the static objects from the level, save the nodes,
|
||||
// then put the static objects back
|
||||
//
|
||||
NODE_LIST static_obj_list;
|
||||
NodeMgrClass::Remove_Static_Objects (static_obj_list);
|
||||
SaveLoadSystemClass::Save (chunk_save, _TheNodeMgr);
|
||||
NodeMgrClass::Put_Objects_Back (static_obj_list);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Import_Dynamic_Objects
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorSaveLoadClass::Import_Dynamic_Objects (LPCTSTR filename)
|
||||
{
|
||||
//
|
||||
// Create the file
|
||||
//
|
||||
HANDLE hfile = ::CreateFile (filename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0L,
|
||||
NULL);
|
||||
|
||||
ASSERT (hfile != INVALID_HANDLE_VALUE);
|
||||
if (hfile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (hfile);
|
||||
ChunkLoadClass chunk_load (&file_obj);
|
||||
|
||||
//
|
||||
// Find the largest used ID
|
||||
//
|
||||
uint32 start_id = (NodeMgrClass::Get_Max_Used_ID () + 1);
|
||||
|
||||
//
|
||||
// Remove the dynamic objects from the level and load the new objects.
|
||||
//
|
||||
NODE_LIST dynamic_obj_list;
|
||||
NodeMgrClass::Remove_Dynamic_Objects (dynamic_obj_list);
|
||||
SaveLoadSystemClass::Load (chunk_load);
|
||||
|
||||
::Output_Message ("Resetting existing static node IDs.\r\n");
|
||||
|
||||
//
|
||||
// Re-assign IDs to the existing static nodes
|
||||
//
|
||||
for ( NodeClass *node = NodeMgrClass::Get_First ();
|
||||
node != NULL;
|
||||
node = NodeMgrClass::Get_Next (node))
|
||||
{
|
||||
if (node->Is_Static ()) {
|
||||
node->Set_ID (start_id++);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check all the dynamic objects for ID collision
|
||||
//
|
||||
CString id_collision_msg = "The following dynamic object IDs collided on import:\n\n";
|
||||
bool show_msg = false;
|
||||
DynamicVectorClass<NodeClass *> bad_node_list;
|
||||
for (int index = 0; index < dynamic_obj_list.Count (); index ++) {
|
||||
NodeClass *node = dynamic_obj_list[index];
|
||||
if (NodeMgrClass::Find_Node (node->Get_ID ()) != NULL) {
|
||||
CString entry;
|
||||
entry.Format ("Object %d\n", node->Get_ID ());
|
||||
id_collision_msg += entry;
|
||||
bad_node_list.Add (node);
|
||||
show_msg = true;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Put the original objects back
|
||||
//
|
||||
NodeMgrClass::Put_Objects_Back (dynamic_obj_list);
|
||||
NodeMgrClass::Reset_New_ID ();
|
||||
|
||||
//
|
||||
// Let the user know we had ID collision (if necessary)
|
||||
//
|
||||
if (show_msg) {
|
||||
::MessageBox (NULL, id_collision_msg, "ID Collision", MB_ICONERROR | MB_OK);
|
||||
|
||||
//
|
||||
// Ask the user if we should fix the collisions or not
|
||||
//
|
||||
if (::MessageBox (NULL, "Would you like to repair the newly imported objects with ambiguous IDs?", "ID Collision", MB_ICONQUESTION | MB_YESNO) == IDYES) {
|
||||
|
||||
//
|
||||
// Repair all collisions
|
||||
//
|
||||
for (int index = 0; index < bad_node_list.Count (); index ++) {
|
||||
NodeClass *node = bad_node_list[index];
|
||||
if (node != NULL) {
|
||||
node->Set_ID (NodeMgrClass::Get_Node_ID (node->Get_Type ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// On_Post_Load
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
EditorSaveLoadClass::On_Post_Load (void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Export_Pathfind
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
PathfindImportExportSaveLoadClass::Export_Pathfind (LPCTSTR filename)
|
||||
{
|
||||
//
|
||||
// Create the file
|
||||
//
|
||||
HANDLE hfile = ::CreateFile (filename,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
0L,
|
||||
NULL);
|
||||
|
||||
ASSERT (hfile != INVALID_HANDLE_VALUE);
|
||||
if (hfile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (hfile);
|
||||
ChunkSaveClass chunk_save (&file_obj);
|
||||
|
||||
//
|
||||
//
|
||||
// Basically just save the list of nodes and some other
|
||||
// miscellaneous information (camera, sky, etc).
|
||||
//
|
||||
SaveLoadSystemClass::Save (chunk_save, _ThePathfindImporterExporter);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Import_Pathfind
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
PathfindImportExportSaveLoadClass::Import_Pathfind (LPCTSTR filename)
|
||||
{
|
||||
//
|
||||
// Create the file
|
||||
//
|
||||
HANDLE hfile = ::CreateFile (filename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0L,
|
||||
NULL);
|
||||
|
||||
ASSERT (hfile != INVALID_HANDLE_VALUE);
|
||||
if (hfile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
RawFileClass file_obj;
|
||||
file_obj.Attach (hfile);
|
||||
ChunkLoadClass chunk_load (&file_obj);
|
||||
|
||||
//
|
||||
// Get the save-load subsystem to load
|
||||
//
|
||||
SaveLoadSystemClass::Load (chunk_load);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Save
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
PathfindImportExportSaveLoadClass::Save (ChunkSaveClass &csave)
|
||||
{
|
||||
//
|
||||
// Save the pathfind data
|
||||
//
|
||||
csave.Begin_Chunk (CHUNKID_PATHFIND_DATA);
|
||||
PathfindClass::Get_Instance()->Save (csave);
|
||||
csave.End_Chunk ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Load
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
bool
|
||||
PathfindImportExportSaveLoadClass::Load (ChunkLoadClass &cload)
|
||||
{
|
||||
while (cload.Open_Chunk ()) {
|
||||
switch (cload.Cur_Chunk_ID ()) {
|
||||
|
||||
//
|
||||
// Import the pathfind data...
|
||||
//
|
||||
case CHUNKID_PATHFIND_DATA:
|
||||
PathfindClass::Get_Instance()->Load (cload);
|
||||
break;
|
||||
}
|
||||
|
||||
cload.Close_Chunk ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
166
Code/Tools/LevelEdit/EditorSaveLoad.h
Normal file
166
Code/Tools/LevelEdit/EditorSaveLoad.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/EditorSaveLoad.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 3/04/02 4:03p $*
|
||||
* *
|
||||
* $Revision:: 8 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __EDITOR_SAVE_LOAD_H
|
||||
#define __EDITOR_SAVE_LOAD_H
|
||||
|
||||
#include "saveloadsubsystem.h"
|
||||
#include "vector.h"
|
||||
#include "bittype.h"
|
||||
#include "editorchunkids.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Singleton instance
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
extern class EditorSaveLoadClass _TheEditorSaveLoadSubsystem;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// EditorSaveLoadClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class EditorSaveLoadClass : public SaveLoadSubSystemClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////////
|
||||
EditorSaveLoadClass (void) { }
|
||||
virtual ~EditorSaveLoadClass (void) { }
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// From SaveLoadSubSystemClass
|
||||
virtual uint32 Chunk_ID (void) const;
|
||||
virtual void On_Post_Load (void);
|
||||
virtual const char * Name (void) const { return "EditorSaveLoadClass"; }
|
||||
|
||||
static void Load_Level (LPCTSTR filename);
|
||||
static void Save_Level (LPCTSTR filename);
|
||||
|
||||
static void Export_Dynamic_Objects (LPCTSTR filename);
|
||||
static void Import_Dynamic_Objects (LPCTSTR filename);
|
||||
|
||||
// Vis methods
|
||||
static void Set_Loaded_Vis_Valid (bool onoff) { m_LoadedValidVis = onoff; }
|
||||
static bool Is_Loaded_Vis_Valid (void) { return m_LoadedValidVis; }
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
//////////////////////////////////////////////////////////////
|
||||
virtual bool Contains_Data(void) const;
|
||||
virtual bool Save (ChunkSaveClass &csave);
|
||||
virtual bool Load (ChunkLoadClass &cload);
|
||||
|
||||
|
||||
//bool Save_Presets (ChunkSaveClass &csave);
|
||||
bool Load_Micro_Chunks (ChunkLoadClass &cload);
|
||||
|
||||
static void Save_Level_Data(ChunkSaveClass & chunk_save);
|
||||
static void Save_Light_Solve(ChunkSaveClass & chunk_save);
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////////
|
||||
static bool m_LoadedValidVis;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PathfindImportExportSaveLoadClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class PathfindImportExportSaveLoadClass : public SaveLoadSubSystemClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////////
|
||||
PathfindImportExportSaveLoadClass (void) { }
|
||||
virtual ~PathfindImportExportSaveLoadClass (void) { }
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Inherited
|
||||
//
|
||||
virtual uint32 Chunk_ID (void) const { return CHUNKID_EDITOR_PATHFIND_IMPORTER_EXPORTER; }
|
||||
virtual void On_Post_Load (void) {}
|
||||
virtual const char * Name (void) const { return "PathfindImportExportSaveLoadClass"; }
|
||||
|
||||
static void Export_Pathfind (LPCTSTR filename);
|
||||
static void Import_Pathfind (LPCTSTR filename);
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
//////////////////////////////////////////////////////////////
|
||||
virtual bool Contains_Data(void) const { return true; }
|
||||
virtual bool Save (ChunkSaveClass &csave);
|
||||
virtual bool Load (ChunkLoadClass &cload);
|
||||
|
||||
bool Load_Micro_Chunks (ChunkLoadClass &cload);
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
|
||||
#endif //__EDITOR_SAVE_LOAD_H
|
||||
1015
Code/Tools/LevelEdit/Export.cpp
Normal file
1015
Code/Tools/LevelEdit/Export.cpp
Normal file
File diff suppressed because it is too large
Load Diff
124
Code/Tools/LevelEdit/Export.h
Normal file
124
Code/Tools/LevelEdit/Export.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/Export.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 1/31/02 1:57p $*
|
||||
* *
|
||||
* $Revision:: 16 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __EXPORT_H
|
||||
#define __EXPORT_H
|
||||
|
||||
#include "vector.h"
|
||||
#include "listtypes.h"
|
||||
#include "wwstring.h"
|
||||
#include "editormixfile.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ExporterClass
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
class ExporterClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////
|
||||
ExporterClass (void) :
|
||||
DontGetVersionsFromVSS (false) {}
|
||||
virtual ~ExporterClass (void) {}
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public Methods
|
||||
//////////////////////////////////////////////////////////
|
||||
void Export_Level (LPCTSTR filename);
|
||||
void Export_Always_Files (LPCTSTR path);
|
||||
void Export_Database_Mix (LPCTSTR path);
|
||||
|
||||
void Export_Package (LPCTSTR path);
|
||||
void Export_Level_Only (LPCTSTR path);
|
||||
|
||||
//
|
||||
// VSS Support
|
||||
//
|
||||
void Dont_Get_Latest_Versions (bool onoff) { DontGetVersionsFromVSS = onoff; }
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
//////////////////////////////////////////////////////////
|
||||
void Process_Include_Files (const STRING_LIST &search_list);
|
||||
bool Build_File_List (const STRING_LIST &search_list, STRING_LIST &file_list);
|
||||
bool Export_Include_Files (const STRING_LIST &file_list);
|
||||
bool Export_Definition_Databases (bool use_temp_strings_library);
|
||||
bool Export_Level_File (void);
|
||||
bool Export_Level_Data (void);
|
||||
void Export_Dependency_File (void);
|
||||
|
||||
bool Delete_File (LPCTSTR filename);
|
||||
bool Clean_Directory (LPCTSTR local_dir);
|
||||
|
||||
void Delete_Temp_Directory (void);
|
||||
void Make_Temp_Directory (void);
|
||||
|
||||
void Pre_Level_Export (DynamicVectorClass<NodeClass *> &node_list);
|
||||
void Post_Level_Export (DynamicVectorClass<NodeClass *> &node_list);
|
||||
|
||||
void Find_Files (const char *search_mask, STRING_LIST &file_list);
|
||||
|
||||
void Add_Files_To_Mod_Package (LPCTSTR full_path);
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////
|
||||
CString Path;
|
||||
CString FilenameBase;
|
||||
CString TempDirectory;
|
||||
|
||||
DynamicVectorClass<StringClass> m_AssetList;
|
||||
|
||||
EditorMixFileCreator MixFileCreator;
|
||||
|
||||
bool DontGetVersionsFromVSS;
|
||||
};
|
||||
|
||||
#endif //__EXPORT_H
|
||||
223
Code/Tools/LevelEdit/ExportPresetsDialog.cpp
Normal file
223
Code/Tools/LevelEdit/ExportPresetsDialog.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// ExportPresetsDialog.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveledit.h"
|
||||
#include "exportpresetsdialog.h"
|
||||
#include "presetmgr.h"
|
||||
#include "nodecategories.h"
|
||||
#include "utils.h"
|
||||
#include "definitionfactory.h"
|
||||
#include "definitionfactorymgr.h"
|
||||
#include "presetexport.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ExportPresetsDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
ExportPresetsDialogClass::ExportPresetsDialogClass(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(ExportPresetsDialogClass::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(ExportPresetsDialogClass)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DoDataExchange
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ExportPresetsDialogClass::DoDataExchange (CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(ExportPresetsDialogClass)
|
||||
DDX_Control(pDX, IDC_TREE_CTRL, m_TreeCtrl);
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(ExportPresetsDialogClass, CDialog)
|
||||
//{{AFX_MSG_MAP(ExportPresetsDialogClass)
|
||||
ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnInitDialog
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BOOL
|
||||
ExportPresetsDialogClass::OnInitDialog (void)
|
||||
{
|
||||
CDialog::OnInitDialog ();
|
||||
|
||||
//
|
||||
// Configure the tree control
|
||||
//
|
||||
m_TreeCtrl.SetImageList (::Get_Global_Image_List (), TVSIL_NORMAL);
|
||||
Fill_Tree ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnBrowse
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ExportPresetsDialogClass::OnBrowse (void)
|
||||
{
|
||||
CFileDialog dialog (FALSE, ".txt", "presets.txt",
|
||||
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
|
||||
"Text Files (*.txt)|*.txt||", ::AfxGetMainWnd ());
|
||||
|
||||
//
|
||||
// Ask the user what file they want to create
|
||||
//
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
//
|
||||
// Check to make sure the destination filename is not read-only
|
||||
//
|
||||
CString path = dialog.GetPathName ();
|
||||
DWORD file_attributes = ::GetFileAttributes (path);
|
||||
if (file_attributes != 0xFFFFFFFF && file_attributes & FILE_ATTRIBUTE_READONLY) {
|
||||
::MessageBox (::AfxGetMainWnd ()->m_hWnd, "File is read-only, export operation can not complete.", "File Error", MB_ICONERROR | MB_OK);
|
||||
} else {
|
||||
SetDlgItemText (IDC_FILENAME_EDIT, path);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnOK
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ExportPresetsDialogClass::OnOK (void)
|
||||
{
|
||||
//
|
||||
// Get the filename the user entered
|
||||
//
|
||||
CString filename;
|
||||
GetDlgItemText (IDC_FILENAME_EDIT, filename);
|
||||
|
||||
if (filename.IsEmpty ()) {
|
||||
::MessageBox (m_hWnd, "Please enter a filename.", "Invalid Setting", MB_ICONERROR | MB_OK);
|
||||
} else {
|
||||
|
||||
//
|
||||
// Lookup the class ID of the selected preset category
|
||||
//
|
||||
HTREEITEM selected_item = m_TreeCtrl.GetSelectedItem ();
|
||||
int class_id = 0;
|
||||
if (selected_item != NULL) {
|
||||
class_id = m_TreeCtrl.GetItemData (selected_item);
|
||||
}
|
||||
|
||||
if (class_id == 0) {
|
||||
::MessageBox (m_hWnd, "Please select a preset category to export.", "Invalid Setting", MB_ICONERROR | MB_OK);
|
||||
} else {
|
||||
|
||||
//
|
||||
// Export the settings to the given filename
|
||||
//
|
||||
PresetExportClass::Export (class_id, filename);
|
||||
CDialog::OnOK ();
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Fill_Tree
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
ExportPresetsDialogClass::Fill_Tree (void)
|
||||
{
|
||||
//
|
||||
// Add all the node categories to the tree control
|
||||
//
|
||||
for (int index = 0; index < PRESET_CATEGORY_COUNT; index ++) {
|
||||
|
||||
//
|
||||
// Add this factory to the tree
|
||||
//
|
||||
HTREEITEM tree_item = m_TreeCtrl.InsertItem (PRESET_CATEGORIES[index].name, FOLDER_ICON, FOLDER_ICON);
|
||||
|
||||
//
|
||||
// Is there a factory to create this class of defintion?
|
||||
//
|
||||
DefinitionFactoryClass *factory = DefinitionFactoryMgrClass::Find_Factory (PRESET_CATEGORIES[index].clsid);
|
||||
if (factory == NULL) {
|
||||
|
||||
//
|
||||
// Find all the sub-factories
|
||||
//
|
||||
for ( factory = DefinitionFactoryMgrClass::Get_First (PRESET_CATEGORIES[index].clsid);
|
||||
factory != NULL;
|
||||
factory = DefinitionFactoryMgrClass::Get_Next (factory, PRESET_CATEGORIES[index].clsid))
|
||||
{
|
||||
//
|
||||
// Add this sub-factory to the tree
|
||||
//
|
||||
if (factory->Is_Displayed ()) {
|
||||
LPCTSTR name = factory->Get_Name ();
|
||||
HTREEITEM child_item = m_TreeCtrl.InsertItem (factory->Get_Name (), FOLDER_ICON, FOLDER_ICON, tree_item);
|
||||
m_TreeCtrl.SetItemData (child_item, (DWORD)factory->Get_Class_ID ());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Sort the entries we just made
|
||||
//
|
||||
m_TreeCtrl.SortChildren (tree_item);
|
||||
} else {
|
||||
m_TreeCtrl.SetItemData (tree_item, (DWORD)PRESET_CATEGORIES[index].clsid);
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
83
Code/Tools/LevelEdit/ExportPresetsDialog.h
Normal file
83
Code/Tools/LevelEdit/ExportPresetsDialog.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_EXPORTPRESETSDIALOG_H__6A8D6C2E_8041_4FC3_AF0D_6C418730CE62__INCLUDED_)
|
||||
#define AFX_EXPORTPRESETSDIALOG_H__6A8D6C2E_8041_4FC3_AF0D_6C418730CE62__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ExportPresetsDialogClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class ExportPresetsDialogClass : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
ExportPresetsDialogClass(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(ExportPresetsDialogClass)
|
||||
enum { IDD = IDD_EXPORT_PRESET_SETTINGS };
|
||||
CTreeCtrl m_TreeCtrl;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(ExportPresetsDialogClass)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(ExportPresetsDialogClass)
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnBrowse();
|
||||
virtual void OnOK();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
///////////////////////////////////////////////////////////////
|
||||
void Fill_Tree (void);
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_EXPORTPRESETSDIALOG_H__6A8D6C2E_8041_4FC3_AF0D_6C418730CE62__INCLUDED_)
|
||||
91
Code/Tools/LevelEdit/FileLocations.h
Normal file
91
Code/Tools/LevelEdit/FileLocations.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/FileLocations.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 1/31/02 1:56p $*
|
||||
* *
|
||||
* $Revision:: 24 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __FILE_LOCATIONS_H
|
||||
#define __FILE_LOCATIONS_H
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constants
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
const TCHAR * const ALWAYS_INI_PATH = TEXT ("INI\\Always.ini");
|
||||
const TCHAR * const PRESET_INI_PATH = TEXT ("INI\\GlobalPresetLib.INI");
|
||||
const TCHAR * const PROPERTY_INI_PATH = TEXT ("INI\\PropertyPresets.INI");
|
||||
const TCHAR * const SERIAL_INI_PATH = TEXT ("INI\\Serial.INI");
|
||||
const TCHAR * const TRANS_INI_PATH = TEXT ("INI\\TransitionPresets.INI");
|
||||
const TCHAR * const UPDATE_INI_PATH = TEXT ("INI\\UpdateInfo.INI");
|
||||
const TCHAR * const TEMP_INI_PATH = TEXT ("INI\\TempPresets.INI");
|
||||
const TCHAR * const ALWAYS_INI_DIR = TEXT ("ALWAYS\\INI");
|
||||
const TCHAR * const ALWAYS_DEP_INI_PATH = TEXT ("INI\\always_dep.ini");
|
||||
|
||||
const TCHAR * const OBJECTS_DDB_PATH = TEXT ("presets\\objects.ddb");
|
||||
|
||||
const TCHAR * const TEMP_DB_PATH = TEXT ("Presets\\temps20.ddb");
|
||||
const TCHAR * const TEMP_DB_FILENAME = TEXT ("temps20.ddb");
|
||||
const TCHAR * const PRESETS_PATH = TEXT ("Presets");
|
||||
|
||||
const TCHAR * const CONV_DB_PATH = TEXT ("Presets\\conv10.cdb");
|
||||
const TCHAR * const CONV_DB_FILENAME = TEXT ("conv10.cdb");
|
||||
|
||||
const TCHAR * const STRINGS_DB_PATH = TEXT ("Always\\TranslationDB\\strings.tdb");
|
||||
const TCHAR * const STRINGS_DB_NAME = TEXT ("strings.tdb");
|
||||
|
||||
const TCHAR * const WEATHER_DIR = TEXT ("Always\\Weather");
|
||||
const TCHAR * const SKY_DIR = TEXT ("Always\\Sky");
|
||||
const TCHAR * const DAZZLE_INI_PATH = TEXT ("Always\\INI\\Dazzle.ini");
|
||||
const TCHAR * const SHATTER_DIR = TEXT ("Always\\Shatter");
|
||||
|
||||
const TCHAR * const COMMAND_ASSET_NAME = TEXT ("C_HAVOC");
|
||||
const TCHAR * const CHAR_ANIMS_PATH = TEXT ("Always\\Characters\\Anims");
|
||||
const TCHAR * const DEF_ASSET_PATH = TEXT ("Projects\\Commando\\Assets");
|
||||
const TCHAR * const SCRIPTS_PATH = TEXT ("Scripts");
|
||||
|
||||
const TCHAR * const HUMAN_SKEL_PATH = TEXT ("Characters\\s_a_human.w3d");
|
||||
|
||||
const TCHAR * const DEF_VSS_DB = TEXT ("\\\\mobius\\project7\\projects\\renegade\\asset management\\asset database\\srcsafe.ini");
|
||||
const TCHAR * const GLOBAL_TEXTURE_PATH = TEXT ("\\\\mobius\\project7\\projects\\renegade\\art\\_source\\texturemaps");
|
||||
|
||||
const TCHAR * const LEVELS_ASSET_DIR = TEXT ("Levels");
|
||||
|
||||
#endif //__FILE_LOCATIONS_H
|
||||
|
||||
1573
Code/Tools/LevelEdit/FileMgr.cpp
Normal file
1573
Code/Tools/LevelEdit/FileMgr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
279
Code/Tools/LevelEdit/FileMgr.h
Normal file
279
Code/Tools/LevelEdit/FileMgr.h
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 : LevelEdit *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Tools/LevelEdit/FileMgr.h $*
|
||||
* *
|
||||
* Author:: Patrick Smith *
|
||||
* *
|
||||
* $Modtime:: 1/29/02 11:48a $*
|
||||
* *
|
||||
* $Revision:: 17 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __FILEMGR_H
|
||||
#define __FILEMGR_H
|
||||
|
||||
|
||||
#include "vector.h"
|
||||
#include "bittype.h"
|
||||
#include "listtypes.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
class RenderObjClass;
|
||||
class PresetClass;
|
||||
class AssetDatabaseClass;
|
||||
class NodeClass;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
extern const char *SPECIAL_USER_FOLDER;
|
||||
extern const char *PROXY_TESTS_FOLDER;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// FileInfoStruct
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct FileInfoStruct
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////
|
||||
FileInfoStruct (void)
|
||||
: m_SubdirImportant (false) { }
|
||||
|
||||
FileInfoStruct (const CString &filename, bool subdir_important)
|
||||
: m_Filename (filename),
|
||||
m_SubdirImportant (subdir_important) { }
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public operators
|
||||
//////////////////////////////////////////////////////////
|
||||
bool operator== (const FileInfoStruct &src) { return false; }
|
||||
bool operator!= (const FileInfoStruct &src) { return true; }
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public fields
|
||||
//////////////////////////////////////////////////////////
|
||||
CString m_Filename;
|
||||
bool m_SubdirImportant;
|
||||
};
|
||||
|
||||
typedef DynamicVectorClass<FileInfoStruct> FILE_LIST;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LevelFileStruct
|
||||
//
|
||||
// Struct definition for a level editor file. This is used by the manager
|
||||
// to represent a file.
|
||||
//
|
||||
struct LevelFileStruct
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////
|
||||
LevelFileStruct (void)
|
||||
: m_SubdirImportant (false),
|
||||
m_RefCount (1L) { }
|
||||
|
||||
virtual ~LevelFileStruct (void) { }
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public fields
|
||||
//////////////////////////////////////////////////////////
|
||||
CString m_Filename;
|
||||
ULONG m_RefCount;
|
||||
bool m_SubdirImportant;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// FileMgrClass
|
||||
//
|
||||
// Class definition for a level editor file manager which controls:
|
||||
// - Versioning
|
||||
// - Reference counting
|
||||
// - VSS integration
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
class FileMgrClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public constructors/destructors
|
||||
//////////////////////////////////////////////////////////
|
||||
FileMgrClass (void);
|
||||
virtual ~FileMgrClass (void) { Free_Data (); }
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Public Methods
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Initialization routines
|
||||
//
|
||||
void Initialize (void);
|
||||
|
||||
|
||||
//
|
||||
// Enumeration routines
|
||||
//
|
||||
int Get_File_Count (void) const { return m_FileList.Count (); }
|
||||
CString Get_File_Name (int index) const { return m_FileList[index]->m_Filename; }
|
||||
bool Is_File_Path_Important (int index) const { return m_FileList[index]->m_SubdirImportant; }
|
||||
|
||||
//
|
||||
// Management
|
||||
//
|
||||
void Update (NodeClass *node, bool add_node = true);
|
||||
void Update (PresetClass *preset, bool add_node = true);
|
||||
void Add_Asset (LPCTSTR filename);
|
||||
void Remove_Asset (LPCTSTR filename);
|
||||
int Add_File (LPCTSTR filename, bool subdir_important = false);
|
||||
bool Remove_File (int prop_index);
|
||||
int Find_File (LPCTSTR filename) const;
|
||||
void Build_File_List (LPCTSTR start_path, RenderObjClass *prender_obj, FILE_LIST &file_list);
|
||||
void Find_Files (LPCTSTR path, LPCTSTR wildcard, DynamicVectorClass<CString> &file_list, bool brecurse);
|
||||
|
||||
//
|
||||
// File base path management
|
||||
//
|
||||
void Set_Base_Path (LPCTSTR base);
|
||||
LPCTSTR Get_Base_Path (void) const { return m_BasePath; }
|
||||
|
||||
//
|
||||
// Preset library information
|
||||
//
|
||||
void Get_Preset_Library_Path (uint32 class_id, bool is_temp, CString &path);
|
||||
|
||||
//
|
||||
// Texture methods
|
||||
//
|
||||
bool Update_Texture_Cache (LPCTSTR start_path, RenderObjClass *prender_obj);
|
||||
int Build_Texture_List (LPCTSTR start_path, RenderObjClass *prender_obj, DynamicVectorClass<CString> &texture_list, bool brecurse = true);
|
||||
const CString & Get_Texture_Cache_Path (void) const { return m_TextureCachePath; }
|
||||
|
||||
//
|
||||
// File information
|
||||
//
|
||||
bool Does_File_Exist (LPCTSTR filename, bool bupdate_from_vss = false);
|
||||
CString Make_Full_Path (LPCTSTR rel_path);
|
||||
CString Make_Relative_Path (LPCTSTR full_path);
|
||||
bool Is_Path_Valid (LPCTSTR path);
|
||||
bool Is_Empty_Path (LPCTSTR path);
|
||||
bool Is_Path_In_Asset_Tree (LPCTSTR path);
|
||||
bool Determine_File_Location (LPCTSTR full_path, CString &real_location);
|
||||
|
||||
//
|
||||
// Include file methods
|
||||
//
|
||||
void Build_Global_Include_List (void);
|
||||
bool Update_Global_Include_File_List (void);
|
||||
DynamicVectorClass<CString> & Get_Global_Include_File_List (void) { return m_GlobalIncludeFiles; }
|
||||
DynamicVectorClass<CString> & Get_Include_File_List (void) { return m_IncludeFiles; }
|
||||
void Build_Include_List (LPCTSTR ini_filename, DynamicVectorClass<CString> &list);
|
||||
|
||||
//
|
||||
// VSS integration methods
|
||||
//
|
||||
bool Initialize_VSS (LPCTSTR ini_file_path, LPCTSTR username = NULL, LPCTSTR password = NULL);
|
||||
int Build_Update_List (DynamicVectorClass<LevelFileStruct *> &update_list);
|
||||
bool Update_Files (DynamicVectorClass<LevelFileStruct *> *pupdate_list = NULL);
|
||||
bool Update_File (int index);
|
||||
bool Update_File (LPCTSTR filename);
|
||||
bool Update_All_Files (LPCTSTR dest_path, LPCTSTR search_mask);
|
||||
bool Update_Model (LPCTSTR local_path, LPCTSTR new_filename);
|
||||
bool Add_Files_To_Database (LPCTSTR filename);
|
||||
bool Add_File_To_Database (LPCTSTR filename);
|
||||
bool Is_VSS_Integration_Enabled (void) { return m_bVSSInitialized; }
|
||||
bool Is_File_In_VSS (LPCTSTR filename);
|
||||
bool Get_Subproject (LPCTSTR path);
|
||||
AssetDatabaseClass & Get_Database_Interface (void) { return *m_DatabaseInterface; }
|
||||
void Set_Read_Only_VSS (bool bread_only = true) { m_bReadOnlyVSS = bread_only; }
|
||||
bool Is_VSS_Read_Only (void) { return m_bReadOnlyVSS; }
|
||||
bool Is_Special_User (void) { return m_IsSpecialUser; }
|
||||
bool Update_Asset_Tree (void);
|
||||
|
||||
void Build_Dependency_List (LPCTSTR filename, UniqueListClass<CString> &list);
|
||||
|
||||
//
|
||||
// Static member data
|
||||
//
|
||||
static bool _bAutoUpdateOn;
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Protected methods
|
||||
//////////////////////////////////////////////////////////
|
||||
void Free_Data (void);
|
||||
|
||||
CDialog * m_pUpdateDlg;
|
||||
CString m_CurrentFile;
|
||||
void Add_Files_To_Database (void);
|
||||
|
||||
friend UINT fnUpdateVSSThread (LPVOID pParam);
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////
|
||||
DynamicVectorClass<LevelFileStruct *> m_FileList;
|
||||
CString m_BasePath;
|
||||
CString m_TextureCachePath;
|
||||
AssetDatabaseClass * m_DatabaseInterface;
|
||||
bool m_bVSSInitialized;
|
||||
bool m_bReadOnlyVSS;
|
||||
bool m_IsSpecialUser;
|
||||
|
||||
DynamicVectorClass<CString> m_GlobalIncludeFiles;
|
||||
DynamicVectorClass<CString> m_IncludeFiles;
|
||||
};
|
||||
|
||||
|
||||
#endif //__FILEMGR_H
|
||||
|
||||
112
Code/Tools/LevelEdit/FilePicker.cpp
Normal file
112
Code/Tools/LevelEdit/FilePicker.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// FilePickerClass.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "leveledit.h"
|
||||
#include "filepicker.h"
|
||||
#include "utils.h"
|
||||
#include "filemgr.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// FilePickerClass
|
||||
//
|
||||
///////////////////////////////////////////////////////////
|
||||
FilePickerClass::FilePickerClass (void)
|
||||
: m_AssetTreeOnly (true),
|
||||
PickerClass ()
|
||||
{
|
||||
m_ExtensionString = "*.*";
|
||||
m_FilterString = "All Files (*.*)|*.*||";
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~FilePickerClass
|
||||
//
|
||||
///////////////////////////////////////////////////////////
|
||||
FilePickerClass::~FilePickerClass (void)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// On_Pick
|
||||
//
|
||||
///////////////////////////////////////////////////////////
|
||||
void
|
||||
FilePickerClass::On_Pick (void)
|
||||
{
|
||||
CString window_text;
|
||||
GetWindowText (window_text);
|
||||
CString full_path = ::Get_File_Mgr ()->Make_Full_Path (window_text);
|
||||
CString filename = ::Get_Filename_From_Path (full_path);
|
||||
CString path;
|
||||
|
||||
DWORD attribs = ::GetFileAttributes (full_path);
|
||||
if ((attribs != 0xFFFFFFFF) && !(attribs & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
path = ::Strip_Filename_From_Path (full_path);
|
||||
} else if ((attribs == 0xFFFFFFFF) && (::strchr (filename, '*') != NULL)) {
|
||||
path = ::Strip_Filename_From_Path (full_path);
|
||||
} else if ((attribs == 0xFFFFFFFF) && m_AssetTreeOnly) {
|
||||
path = ::Get_File_Mgr ()->Get_Base_Path ();
|
||||
} else {
|
||||
path = full_path;
|
||||
}
|
||||
|
||||
CFileDialog dialog (TRUE,
|
||||
m_ExtensionString,
|
||||
filename,
|
||||
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
|
||||
m_FilterString,
|
||||
this);
|
||||
|
||||
//
|
||||
// Set the path, so it opens in the correct directory
|
||||
//
|
||||
if (path.GetLength () > 0) {
|
||||
dialog.m_ofn.lpstrInitialDir = path;
|
||||
}
|
||||
|
||||
//
|
||||
// Show the dialog to the user
|
||||
//
|
||||
if (dialog.DoModal () == IDOK) {
|
||||
|
||||
path = dialog.GetPathName ();
|
||||
if (::Get_File_Mgr ()->Is_Empty_Path (path) == false)
|
||||
{
|
||||
if (m_AssetTreeOnly == false || ::Get_File_Mgr ()->Is_Path_Valid (path)) {
|
||||
CString rel_path = ::Get_File_Mgr ()->Make_Relative_Path (dialog.GetPathName ());
|
||||
SetWindowText (rel_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PickerClass::On_Pick ();
|
||||
return ;
|
||||
}
|
||||
|
||||
77
Code/Tools/LevelEdit/FilePicker.h
Normal file
77
Code/Tools/LevelEdit/FilePicker.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_FILEPICKERCLASS_H__1A8EC040_8874_11D2_9FE1_00104B791122__INCLUDED_)
|
||||
#define AFX_FILEPICKERCLASS_H__1A8EC040_8874_11D2_9FE1_00104B791122__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "picker.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// FilePickerClass
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
class FilePickerClass : public PickerClass
|
||||
{
|
||||
public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Public constructors/destructor
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
FilePickerClass (void);
|
||||
virtual ~FilePickerClass (void);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Public methods
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// From PickerClass
|
||||
//
|
||||
void On_Pick (void);
|
||||
|
||||
//
|
||||
// FilePickerClass specific
|
||||
//
|
||||
void Set_Extension_String (LPCTSTR extension) { m_ExtensionString = extension; }
|
||||
void Set_Filter_String (LPCTSTR filter) { m_FilterString = filter; }
|
||||
void Set_Default_Filename (LPCTSTR filename) { m_DefaultFilename = filename; }
|
||||
void Set_Asset_Tree_Only (bool onoff) { m_AssetTreeOnly = onoff; }
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Private member data
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
CString m_ExtensionString;
|
||||
CString m_FilterString;
|
||||
CString m_DefaultFilename;
|
||||
bool m_AssetTreeOnly;
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_FILEPICKERCLASS_H__1A8EC040_8874_11D2_9FE1_00104B791122__INCLUDED_)
|
||||
171
Code/Tools/LevelEdit/FormToolbar.cpp
Normal file
171
Code/Tools/LevelEdit/FormToolbar.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// FormToolbarClass.CPP
|
||||
//
|
||||
// Module defining a CControlBar derived class which is used to implement
|
||||
// floating or dockable toolbars containing dialogs.
|
||||
//
|
||||
//
|
||||
|
||||
#include "StdAfx.H"
|
||||
#include "FormToolbar.H"
|
||||
#include "DockableForm.H"
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(FormToolbarClass, CControlBar)
|
||||
//{{AFX_MSG_MAP(FormToolbarClass)
|
||||
ON_WM_SIZE()
|
||||
ON_WM_ERASEBKGND()
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Local constants
|
||||
//
|
||||
const int BORDER_TOP = 6;
|
||||
const int BORDER_BOTTOM = 6;
|
||||
const int BORDER_LEFT = 6;
|
||||
const int BORDER_RIGHT = 6;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// FormToolbarClass
|
||||
//
|
||||
FormToolbarClass::FormToolbarClass (void)
|
||||
: m_pCForm (NULL)
|
||||
{
|
||||
m_minSize.cx = 100;
|
||||
m_minSize.cy = 100;
|
||||
return ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ~FormToolbarClass
|
||||
//
|
||||
FormToolbarClass::~FormToolbarClass (void)
|
||||
{
|
||||
if (m_pCForm) {
|
||||
// Free the dockable form
|
||||
delete m_pCForm;
|
||||
m_pCForm = NULL;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Create
|
||||
//
|
||||
BOOL
|
||||
FormToolbarClass::Create
|
||||
(
|
||||
DockableFormClass *pCFormClass,
|
||||
LPCTSTR pszWindowName,
|
||||
CWnd *pCParentWnd,
|
||||
UINT uiID
|
||||
)
|
||||
{
|
||||
ASSERT (pCFormClass);
|
||||
m_pCForm = pCFormClass;
|
||||
|
||||
// Allow the base class to process this message
|
||||
RECT rect = { 0 };
|
||||
BOOL retval = CWnd::Create (NULL, pszWindowName, WS_CHILD | WS_VISIBLE, rect, pCParentWnd, uiID);
|
||||
if (retval) {
|
||||
|
||||
// Ask the dockable form to create itself
|
||||
retval = m_pCForm->Create (this, 101);
|
||||
|
||||
|
||||
CRect rect;
|
||||
rect = m_pCForm->Get_Form_Rect ();
|
||||
m_minSize.cx = rect.Width ();
|
||||
m_minSize.cy = rect.Height ();
|
||||
m_minSize.cx += BORDER_LEFT + BORDER_RIGHT;
|
||||
m_minSize.cy += BORDER_TOP + BORDER_BOTTOM;
|
||||
SetWindowPos (NULL, 0, 0, m_minSize.cx, m_minSize.cy, SWP_NOZORDER | SWP_NOMOVE);
|
||||
m_pCForm->SetWindowPos (NULL, BORDER_LEFT, BORDER_TOP, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
|
||||
|
||||
// Allow the toolbar to be resized
|
||||
// Allow the toolbar to be docked either to the right or left
|
||||
SetBarStyle (GetBarStyle() | CBRS_SIZE_DYNAMIC);
|
||||
EnableDocking (CBRS_ALIGN_RIGHT | CBRS_ALIGN_LEFT);
|
||||
}
|
||||
|
||||
// Return the TRUE/FALSE result code
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnSize
|
||||
//
|
||||
void
|
||||
FormToolbarClass::OnSize
|
||||
(
|
||||
UINT nType,
|
||||
int cx,
|
||||
int cy
|
||||
)
|
||||
{
|
||||
// Allow the base class to process this message
|
||||
CControlBar::OnSize(nType, cx, cy);
|
||||
|
||||
if (m_pCForm && (cx > 0) && (cy > 0)) {
|
||||
// Get the bounding rectangle
|
||||
CRect rect;
|
||||
GetClientRect (rect);
|
||||
|
||||
// Resize the dockable form window
|
||||
m_pCForm->SetWindowPos (NULL,
|
||||
0,
|
||||
0,
|
||||
rect.Width () - (BORDER_LEFT + BORDER_RIGHT),
|
||||
rect.Height () - (BORDER_TOP + BORDER_BOTTOM),
|
||||
SWP_NOZORDER | SWP_NOMOVE);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OnEraseBkgnd
|
||||
//
|
||||
BOOL
|
||||
FormToolbarClass::OnEraseBkgnd (CDC* pDC)
|
||||
{
|
||||
// Get the bounding rectangle
|
||||
RECT rect;
|
||||
GetClientRect (&rect);
|
||||
|
||||
// Paint the background light gray
|
||||
::FillRect (*pDC, &rect, (HBRUSH)(COLOR_3DFACE + 1));
|
||||
|
||||
// Allow the base class to process this message
|
||||
return CControlBar::OnEraseBkgnd(pDC);
|
||||
}
|
||||
128
Code/Tools/LevelEdit/FormToolbar.h
Normal file
128
Code/Tools/LevelEdit/FormToolbar.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// FormToolbarClass.H
|
||||
//
|
||||
// Module declaring a CControlBar derived class which is used to implement
|
||||
// floating or dockable toolbars containing dialogs.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __FORMTOOLBARCLASS_H
|
||||
#define __FORMTOOLBARCLASS_H
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// FormToolbarClass
|
||||
//
|
||||
class FormToolbarClass : public CControlBar
|
||||
{
|
||||
|
||||
// Operations
|
||||
public:
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(FormToolbarClass)
|
||||
protected:
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(FormToolbarClass)
|
||||
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Public Contructors
|
||||
//
|
||||
FormToolbarClass ();
|
||||
virtual ~FormToolbarClass ();
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Public Methods
|
||||
//
|
||||
|
||||
//
|
||||
// Required methods
|
||||
//
|
||||
CSize CalcFixedLayout (BOOL, BOOL) { return CSize (100, 100); }
|
||||
CSize CalcDynamicLayout( int nLength, DWORD dwMode )
|
||||
{
|
||||
if (dwMode & LM_VERTDOCK)
|
||||
{
|
||||
if (::AfxGetMainWnd () &&
|
||||
::AfxGetMainWnd ()->GetDlgItem (AFX_IDW_PANE_FIRST))
|
||||
{
|
||||
CRect rect;
|
||||
::AfxGetMainWnd ()->GetDlgItem (AFX_IDW_PANE_FIRST)->GetClientRect (&rect);
|
||||
return CSize (m_minSize.cx, rect.Height ()+8);
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_minSize;
|
||||
}
|
||||
}
|
||||
else if (dwMode & LM_HORZDOCK)
|
||||
{
|
||||
if (::AfxGetMainWnd ())
|
||||
{
|
||||
CRect rect;
|
||||
::AfxGetMainWnd ()->GetClientRect (&rect);
|
||||
return CSize (rect.Width ()+8, m_minSize.cy);
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_minSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_minSize;
|
||||
}
|
||||
}
|
||||
|
||||
void OnUpdateCmdUI (class CFrameWnd*, int) {}
|
||||
BOOL Create (class DockableFormClass *pCFormClass, LPCTSTR pszWindowName, CWnd *pCParentWnd, UINT uiID);
|
||||
|
||||
class DockableFormClass * Get_Form (void) const { return m_pCForm; }
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// Private member data
|
||||
//
|
||||
class DockableFormClass *m_pCForm;
|
||||
CSize m_minSize;
|
||||
};
|
||||
|
||||
|
||||
#endif //__FORMTOOLBARCLASS_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user