Initial commit of Command & Conquer Renegade source code.

This commit is contained in:
LFeenanEA
2025-02-27 16:39:46 +00:00
parent 74ab8fa5e0
commit 58ed459113
4918 changed files with 1366710 additions and 0 deletions

View 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 ;
}

View 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

View 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;
}

View 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

View 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];
}

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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);
}

View 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;
}

View 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_)

View 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;
}

View 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_)

View 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 ;
}

View 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_)

View 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

File diff suppressed because it is too large Load Diff

View 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_)

View 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)&notify_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)&notify_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 ;
}

View 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_)

View 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 ;
}

View 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_)

View 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 ;
}

View 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_)

View 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 ;
}

View 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

View 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;
}

View 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

View 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 ;
}

View 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_)

View 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 ;
}

View 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_)

View 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;
}

View 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

View 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 ();
}

View 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

View 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 ;
}

View 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_)

View 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];
}

View 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

View 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 ;
}

View 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

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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

View 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;
}

View 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

View 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;
}

View 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_)

View 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;
}

View 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

View 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);
}

View 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_)

View File

View 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 ();
}

View 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

View 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 ;
}

View 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

View 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;
}

View 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_)

View 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 ;
}

View 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_)

View 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 ;
}

View 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_)

View 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 ;
}

View 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_)

View 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 ;
}

View 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_)

View 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

View 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_)

View 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, ",", &param_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 ;
}

View 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

View 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;
}

View 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_)

View 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 ;
}

View 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_)

View 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 ;
}

View 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

View 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

View 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;
}

View 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

View 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

View 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;
}

View 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

View 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 ;
}

View 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_)

View 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;
}

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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 ;
}

View 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_)

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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 ;
}

View 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_)

View 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);
}

View 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