This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Tools/LevelEdit/TransitionEditDialog.cpp

1473 lines
36 KiB
C++

/*
** 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/>.
*/
// TransitionEditDialog.cpp : implementation file
//
#include "stdafx.h"
#include "leveledit.h"
#include "leveleditview.h"
#include "transitioneditdialog.h"
#include "ww3d.h"
#include "scene.h"
#include "camera.h"
#include "utils.h"
#include "mmsystem.h"
#include "matrix3d.h"
#include "rendobj.h"
#include "transition.h"
#include "sphere.h"
#include "box3d.h"
#include "cameramgr.h"
#include "filemgr.h"
#include "filelocations.h"
#include "hanim.h"
#include "quat.h"
#include "vector3.h"
#include "obbox.h"
#include "combatchunkid.h"
#include "soldier.h"
#include "editorbuild.h"
#include "mixfiledatabase.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//
// Local constants
//
/////////////////////////////////////////////////////////////////////////////
const int TOOLBAR_HEIGHT = 36;
const int TOOLBAR_V_SPACING = 5;
const int TOOLBAR_V_BORDER = TOOLBAR_V_SPACING * 2;
const int TOOLBAR_H_SPACING = 5;
const int TOOLBAR_H_BORDER = TOOLBAR_H_SPACING * 2;
/////////////////////////////////////////////////////////////////////////////
//
// Local prototypes
//
/////////////////////////////////////////////////////////////////////////////
static void Trackball_Camera (HWND hwnd, CameraClass &camera, const Vector3 &center, POINT point, POINT last_point);
/////////////////////////////////////////////////////////////////////////////
//
// TransitionEditDialogClass
//
/////////////////////////////////////////////////////////////////////////////
TransitionEditDialogClass::TransitionEditDialogClass(CWnd* pParent /*=NULL*/)
: m_LookAtDist (0),
m_Camera (NULL),
m_Scene (NULL),
m_RenderObj (NULL),
m_Transition (NULL),
m_Zone (NULL),
m_CharacterObj (NULL),
m_Animation (NULL),
m_SwapChain (NULL),
m_TimerID (0),
m_CurrFrame (0),
m_LastAnimUpdate (0),
m_IsEditingZone (true),
m_IsEditingChar (true),
m_IsAnimating (false),
m_IsSizingZone (false),
m_IsRotatingChar (false),
CDialog(TransitionEditDialogClass::IDD, pParent)
{
//{{AFX_DATA_INIT(TransitionEditDialogClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::DoDataExchange (CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(TransitionEditDialogClass)
DDX_Control(pDX, IDC_EDIT_ZONE, m_MoveZoneCheck);
DDX_Control(pDX, IDC_EDIT_CHAR, m_MoveCharCheck);
DDX_Control(pDX, IDC_SIZE_ZONE, m_SizeZoneCheck);
DDX_Control(pDX, IDC_ROTATE_CHAR, m_RotateCharCheck);
DDX_Control(pDX, IDC_ANIMATION_LIST, m_AnimationList);
DDX_Control(pDX, IDC_TRIGGER_LIST, m_TriggerList);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(TransitionEditDialogClass, CDialog)
//{{AFX_MSG_MAP(TransitionEditDialogClass)
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_TOP, OnTop)
ON_BN_CLICKED(IDC_FRONT, OnFront)
ON_BN_CLICKED(IDC_LEFT, OnLeft)
ON_BN_CLICKED(IDC_RIGHT, OnRight)
ON_BN_CLICKED(IDC_EDIT_CHAR, OnEditChar)
ON_BN_CLICKED(IDC_EDIT_ZONE, OnEditZone)
ON_CBN_SELCHANGE(IDC_ANIMATION_LIST, OnSelChangeAnimationList)
ON_COMMAND(IDM_ANI_BACK_FRAME, OnAniBackFrame)
ON_COMMAND(IDM_ANI_FIRST_FRAME, OnAniFirstFrame)
ON_COMMAND(IDM_ANI_FWD_FRAME, OnAniFwdFrame)
ON_COMMAND(IDM_ANI_LAST_FRAME, OnAniLastFrame)
ON_COMMAND(IDM_ANI_PAUSE, OnAniPause)
ON_COMMAND(IDM_ANI_PLAY, OnAniPlay)
ON_COMMAND(IDM_ANI_STOP, OnAniStop)
ON_BN_CLICKED(IDC_SIZE_ZONE, OnSizeZone)
ON_BN_CLICKED(IDC_ROTATE_CHAR, OnRotateChar)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL
TransitionEditDialogClass::OnInitDialog (void)
{
CWaitCursor wait_cursor;
CLevelEditView::Allow_Repaint (false);
CDialog::OnInitDialog ();
//
// Subclass the 3D window for mouse-tracking
//
SetWindowLong (::GetDlgItem (m_hWnd, IDC_3D_WINDOW), GWL_WNDPROC, (LONG)fn3DWindow);
::SetProp (::GetDlgItem (m_hWnd, IDC_3D_WINDOW), "TRANSITION_DIALOG", (HANDLE)this);
//
// Setup the toolbar
//
m_Toolbar.CreateEx (this, TBSTYLE_FLAT, WS_BORDER | WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP, CRect(0, 0, 10, 10), 101);
m_Toolbar.SetOwner (this);
m_Toolbar.LoadToolBar (IDR_ANI_TOOLBAR);
m_Toolbar.SetBarStyle (m_Toolbar.GetBarStyle () | CBRS_TOOLTIPS | CBRS_FLYBY);
// Position the toolbar
CRect rect;
CSize size;
m_Toolbar.GetToolBarCtrl ().GetMaxSize (&size);
::GetWindowRect (::GetDlgItem (m_hWnd, IDC_TOOLBAR), &rect);
ScreenToClient (&rect);
m_Toolbar.SetWindowPos (NULL,
rect.left + (rect.Width () >> 1) - (size.cx >> 1),
rect.top + (rect.Height () >> 1) - (size.cy >> 1),
rect.Width (),
rect.Height (),
SWP_SHOWWINDOW);
//
// Get the dimensions of the client area of the window we'll be rendering in
//
::GetClientRect (::GetDlgItem (m_hWnd, IDC_3D_WINDOW), &rect);
int cx = rect.Width ();
int cy = rect.Height ();
//
// Create a swap chain so we can render to this window as well
//
m_SwapChain = DX8Wrapper::Create_Additional_Swap_Chain (::GetDlgItem (m_hWnd, IDC_3D_WINDOW));
//
// Create the scene and camera we will use
//
m_Scene = new SimpleSceneClass;
m_Camera = new CameraClass;
m_Scene->Set_Ambient_Light (Vector3 (1, 1, 1));
m_Camera->Set_Clip_Planes (0.1F, 400.0F);
//
// Configure the camera
//
double hfov = 0;
double vfov = 0;
if (cy > cx) {
vfov = (float)DEG_TO_RAD(45.0f);
hfov = (double)cx / (double)cy * vfov;
} else {
hfov = (float)DEG_TO_RAD(45.0f);
vfov = (double)cy / (double)cx * hfov;
}
m_Camera->Set_View_Plane (hfov, vfov);
//
// Setup the scene
//
Load_Object ();
Insert_Zone ();
Fill_Trigger_List ();
Fill_Animation_List ();
Load_Animation ();
//
// Select the default UI
//
SendDlgItemMessage (IDC_TOP, BM_SETCHECK, (WPARAM)TRUE);
SendDlgItemMessage (IDC_EDIT_ZONE, BM_SETCHECK, (WPARAM)TRUE);
SendDlgItemMessage (IDC_EDIT_CHAR, BM_SETCHECK, (WPARAM)TRUE);
OnTop ();
OnEditZone ();
OnEditChar ();
Update_Status ();
// Kick off a timer that we can use to update
// the display (kinda like a game loop iterator)
m_TimerID = ::timeSetEvent ( 50,
50,
fnUpdateTimer,
(DWORD)m_hWnd,
TIME_PERIODIC);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnOK
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnOK (void)
{
//
// Create a matrix we can use to transform the zone and
// character into 'relative' space.
//
Matrix3D obj_tm = m_RenderObj->Get_Transform ();
Matrix3D obj_inv;
obj_tm.Get_Orthogonal_Inverse (obj_inv);
//
// Pass the new animation name onto the transition object
//
CString name;
m_AnimationList.GetWindowText (name);
CString animation_name = CString ("S_A_HUMAN.") + name;
m_Transition->Set_Animation_Name ((LPCTSTR)animation_name);
//
// Pass the trigger type onto the transition
//
m_Transition->Set_Type ((TransitionDataClass::StyleType)m_TriggerList.GetCurSel ());
//
// Pass the character's ending position onto the transition
//
Matrix3D ending_tm = m_CharacterObj->Get_Transform () * obj_inv;
m_Transition->Set_Ending_TM (ending_tm);
//
// Transform the zone from world space coords to relative coords
//
OBBoxClass zone_box (m_Zone->Get_Transform ().Get_Translation (), m_Zone->Get_Dimensions () * 0.5F);
OBBoxClass rel_zone;
OBBoxClass::Transform (obj_inv, zone_box, &rel_zone);
m_Transition->Set_Zone (rel_zone);
CDialog::OnOK ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnDestroy
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnDestroy (void)
{
// Stop the timer
if (m_TimerID != 0) {
::timeKillEvent (m_TimerID);
m_TimerID = 0;
}
//
// Free our swap chain
//
if (m_SwapChain != NULL) {
m_SwapChain->Release ();
m_SwapChain = NULL;
}
CLevelEditView::Allow_Repaint (true);
//
// Destroy the scene/camera/render-obj
//
m_Scene->Remove_Render_Object (m_RenderObj);
m_Scene->Remove_Render_Object (m_Zone);
m_Scene->Remove_Render_Object (m_CharacterObj);
MEMBER_RELEASE (m_Scene);
MEMBER_RELEASE (m_Camera);
MEMBER_RELEASE (m_RenderObj);
MEMBER_RELEASE (m_CharacterObj);
MEMBER_RELEASE (m_Zone);
MEMBER_RELEASE (m_Animation);
//
// Free all the data we associated with the animation list
//
int count = m_AnimationList.GetCount ();
for (int index = 0; index < count; index ++) {
LPTSTR data = (LPTSTR)m_AnimationList.GetItemData (index);
if (data != NULL) {
::free (data);
}
}
m_AnimationList.ResetContent ();
CDialog::OnDestroy ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Render_View
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Render_View (void)
{
static render_lock = false;
if (!render_lock) {
render_lock = true;
//
// Move the camera if the user is pressing
// the camera-control keys.
//
Handle_Keypress ();
//
// Pick the next animation frame
//
Update_Animation ();
//
// Configure the render target
//
DX8Wrapper::Set_Render_Target (m_SwapChain);
//
// Render the scene
//
WW3D::Begin_Render (true, true, Vector3 (0.4F, 0.4F, 0.4F));
WW3D::Render (m_Scene, m_Camera, FALSE, FALSE);
WW3D::End_Render ();
//
// Blit the frame to the client area of the window
//
m_SwapChain->Present (NULL, NULL, NULL, NULL);
//
// Restore the render target
//
DX8Wrapper::Set_Render_Target ((LPDIRECT3DSURFACE8)NULL);
//
// Cleanup
//
RemoveProp (m_hWnd, "WaitingToProcess");
render_lock = false;
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// fnUpdateTimer
//
/////////////////////////////////////////////////////////////////////////////
void CALLBACK
TransitionEditDialogClass::fnUpdateTimer
(
UINT uID,
UINT uMsg,
DWORD user_data,
DWORD dw1,
DWORD dw2
)
{
HWND hwnd = (HWND)user_data;
if (hwnd != NULL) {
if ((GetProp (hwnd, "WaitingToProcess") == NULL)) {
SetProp (hwnd, "WaitingToProcess", (HANDLE)1);
// Send the message to the view so it will be in the
// same thread (We don't seem to be thread-safe)
::PostMessage (hwnd, WM_USER+101, 0, 0L);
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// WindowProc
//
/////////////////////////////////////////////////////////////////////////////
LRESULT
TransitionEditDialogClass::WindowProc
(
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
if (message == (WM_USER + 101)) {
Render_View ();
} else if (message == WM_KEYDOWN || message == WM_KEYUP) {
//
// Eat the keyboard messages we 'special case'.
//
if (wParam == VK_NUMPAD8 || wParam == VK_NUMPAD2 ||
wParam == VK_NUMPAD4 || wParam == VK_NUMPAD6 ||
wParam == VK_NUMPAD7 || wParam == VK_NUMPAD1)
{
return 0;
}
}
return CDialog::WindowProc (message, wParam, lParam);
}
////////////////////////////////////////////////////////////////////////////
//
// OnTop
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnTop (void)
{
Vector3 pos = m_RenderObj->Get_Position ();
Matrix3D transform (1);
transform.Look_At (pos + Vector3 (0, 0, m_LookAtDist), pos, 3.1415926535F);
m_Camera->Set_Transform (transform);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnFront
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnFront (void)
{
Vector3 pos = m_RenderObj->Get_Position ();
Matrix3D transform (1);
transform.Look_At (pos + Vector3 (m_LookAtDist, 0, 0), pos, 0);
m_Camera->Set_Transform (transform);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnLeft
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnLeft (void)
{
Vector3 pos = m_RenderObj->Get_Position ();
Matrix3D transform (1);
transform.Look_At (pos + Vector3 (0, -m_LookAtDist, 0), pos, 0);
m_Camera->Set_Transform (transform);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnRight
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnRight (void)
{
Vector3 pos = m_RenderObj->Get_Position ();
Matrix3D transform (1);
transform.Look_At (pos + Vector3 (0, m_LookAtDist, 0), pos, 0);
m_Camera->Set_Transform (transform);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Load_Object
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Load_Object (void)
{
//
// Determine how big the object is
//
SphereClass sphere = m_RenderObj->Get_Bounding_Sphere ();
m_LookAtDist = sphere.Radius * 1.5F;
m_LookAtDist = max (m_LookAtDist, 4.0F);
//
// Add the render object to the world at 0, 0, 0
//
m_Scene->Add_Render_Object (m_RenderObj);
m_RenderObj->Set_Transform (Matrix3D(Vector3(0, 0, m_Height)));
//
// Add a grid render object to the world to act as a floor
//
RenderObjClass *floor = ::Create_Render_Obj ("GRID");
if (floor != NULL) {
floor->Set_Transform (Matrix3D(1));
m_Scene->Add_Render_Object (floor);
floor->Release_Ref ();
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Insert_Zone
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Insert_Zone (void)
{
//
// Create the zone and add it to the scene
//
m_Zone = new Box3DClass (Vector3 (1, 1, 1));
m_Zone->Set_Color (Vector3 (0, 0, 0.7F));
//
// Transform the zone from relative to world space coords
//
Matrix3D obj_tm = m_RenderObj->Get_Transform ();
OBBoxClass rel_zone = m_Transition->Get_Zone ();
OBBoxClass zone_box;
OBBoxClass::Transform (obj_tm, rel_zone, &zone_box);
m_Zone->Set_Position (zone_box.Center);
m_Zone->Set_Dimensions (zone_box.Extent * 2.0F);
m_Scene->Add_Render_Object (m_Zone);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Set_Render_Obj
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Set_Render_Obj (RenderObjClass *render_obj)
{
MEMBER_ADD (m_RenderObj, render_obj);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Set_Transition
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Set_Transition (TransitionDataClass *transition)
{
m_Transition = transition;
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Handle_Keypress
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Handle_Keypress (void)
{
//
// Determine which speed modifier to use
//
float speed_mod = 1.0F;
if (::GetAsyncKeyState (VK_CONTROL) < 0) {
speed_mod = 3.0F;
}
//
// Move the camera forward-backward (if necessary)
//
if ((::GetAsyncKeyState (VK_NUMPAD8) < 0) ||
(::GetAsyncKeyState (VK_NUMPAD2) < 0)) {
// Get the camera's current position
Vector3 position = m_Camera->Get_Position ();
float orig_z = position.Z;
//
// Determine how far to move the camera
//
float delta = (::GetAsyncKeyState (VK_NUMPAD8) < 0) ? -0.35F : 0.35F;
delta *= speed_mod;
//
// Scale the position along the direction vector
//
Matrix3D transform = m_Camera->Get_Transform ();
position += (delta * transform.Get_Z_Vector ());
//
// Should we lock the z-position?
//
if (::GetAsyncKeyState (VK_CAPITAL) < 0) {
position.Z = orig_z;
}
// Set the camera's new position
m_Camera->Set_Position (position);
}
//
// Pan the camera left-right (if neccessary)
//
if ((::GetAsyncKeyState (VK_NUMPAD4) < 0) ||
(::GetAsyncKeyState (VK_NUMPAD6) < 0)) {
// Get the camera's current position
Vector3 position = m_Camera->Get_Position ();
//
// Determine how far to move the camera
//
float delta = (::GetAsyncKeyState (VK_NUMPAD4) < 0) ? -0.35F : 0.35F;
delta *= speed_mod;
//
// Scale the position along the x-vector
//
Matrix3D transform = m_Camera->Get_Transform ();
position += (delta * transform.Get_X_Vector ());
// Set the camera's new position
m_Camera->Set_Position (position);
}
//
// Elevate the camera up-down (if neccessary)
//
if ((::GetAsyncKeyState (VK_NUMPAD7) < 0) ||
(::GetAsyncKeyState (VK_NUMPAD1) < 0)) {
// Get the camera's current position
Vector3 position = m_Camera->Get_Position ();
//
// Determine how far to move the camera
//
float delta = (::GetAsyncKeyState (VK_NUMPAD1) < 0) ? -0.35F : 0.35F;
delta *= speed_mod;
//
// Scale the position along the x-vector
//
Matrix3D transform = m_Camera->Get_Transform ();
position += (delta * transform.Get_Y_Vector ());
// Set the camera's new position
m_Camera->Set_Position (position);
}
if ((::GetAsyncKeyState (VK_UP) < 0) ||
(::GetAsyncKeyState (VK_DOWN) < 0) ||
(::GetAsyncKeyState (VK_LEFT) < 0) ||
(::GetAsyncKeyState (VK_RIGHT) < 0))
{
float amount = 0.025F;
if (::GetAsyncKeyState (VK_CONTROL) < 0) {
amount *= 4.0F;
}
Vector3 translation(0,0,0);
if (::GetAsyncKeyState (VK_UP) < 0) {
if (::GetAsyncKeyState (VK_SHIFT) < 0) {
translation.Z += amount;
} else {
translation.X += amount;
}
}
if (::GetAsyncKeyState (VK_DOWN) < 0) {
if (::GetAsyncKeyState (VK_SHIFT) < 0) {
translation.Z -= amount;
} else {
translation.X -= amount;
}
}
if (::GetAsyncKeyState (VK_RIGHT) < 0) {
translation.Y += amount;
}
if (::GetAsyncKeyState (VK_LEFT) < 0) {
translation.Y -= amount;
}
//
// Move the zone
//
if (m_IsEditingZone) {
Matrix3D tm = m_Zone->Get_Transform ();
tm.Translate (translation);
m_Zone->Set_Transform (tm);
}
//
// Size the Zone
//
if (m_IsSizingZone) {
Vector3 size = m_Zone->Get_Dimensions ();
size += translation;
m_Zone->Set_Dimensions (size);
}
//
// Move the character
//
if (m_IsEditingChar) {
Matrix3D tm = m_CharacterObj->Get_Transform ();
tm.Set_Translation (tm.Get_Translation () + translation);
m_CharacterObj->Set_Transform (tm);
}
//
// Rotate the character
//
if ( m_IsRotatingChar &&
((::GetAsyncKeyState (VK_RIGHT) < 0) ||
(::GetAsyncKeyState (VK_LEFT) < 0)) )
{
Matrix3D tm = m_CharacterObj->Get_Transform ();
float deg = (::GetAsyncKeyState (VK_RIGHT) < 0) ? 5.0F : -5.0F;
tm.Rotate_Z (DEG_TO_RAD (deg));
m_CharacterObj->Set_Transform (tm);
}
Update_Status ();
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Status
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Update_Status (void)
{
//
// Update the zone's status
//
Vector3 zone_pos = m_Zone->Get_Transform ().Get_Translation ();
Vector3 zone_size = m_Zone->Get_Dimensions ();
CString status;
status.Format ("Zone Pos (%.2f, %.2f, %.2f)\nZone Size (%.2f, %.2f, %.2f)",
zone_pos.X, zone_pos.Y, zone_pos.Z,
zone_size.X, zone_size.Y, zone_size.Z);
SetDlgItemText (IDC_ZONE_STATUS, status);
//
// Update the character's status
//
Vector3 char_pos = m_CharacterObj->Get_Transform ().Get_Translation ();
float char_rot = m_CharacterObj->Get_Transform ().Get_Z_Rotation ();
status.Format ("Char Pos (%.2f, %.2f, %.2f)\nChar Rot (%.2f)",
char_pos.X, char_pos.Y, char_pos.Z,
RAD_TO_DEG (char_rot));
SetDlgItemText (IDC_CHAR_STATUS, status);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Fill_Trigger_List
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Fill_Trigger_List (void)
{
int type_to_sel = (int)m_Transition->Get_Type ();
int count = TransitionDataClass::Get_Num_Types ();
for (int index = 0; index < count; index ++) {
LPCTSTR name = TransitionDataClass::Get_Type_Name ((TransitionDataClass::StyleType)index);
int item_index = m_TriggerList.AddString (name);
if (index == type_to_sel) {
m_TriggerList.SetCurSel (item_index);
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Fill_Animation_List
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Fill_Animation_List (void)
{
int index = 0;
//
// Generate a list of animation files
//
DynamicVectorClass<StringClass> file_list;
file_list.Set_Growth_Step (500);
#ifdef PUBLIC_EDITOR_VER
MixFileDatabaseClass::Get_Instance ()->Find_Files (file_list, "h_a_*.w3d");
#else
//
// Generate a list of animation files
//
DynamicVectorClass<CString> temp_file_list;
CString path = ::Get_File_Mgr()->Make_Full_Path (CHAR_ANIMS_PATH);
::Get_File_Mgr ()->Find_Files (path, "*.w3d", temp_file_list, true);
for (index = 0; index < temp_file_list.Count (); index ++) {
file_list.Add ((const char *)temp_file_list[index]);
}
#endif //PUBLIC_EDITOR_VER
//
// Populate the combobox
//
bool selected = false;
for (index = 0; index < file_list.Count (); index ++) {
StringClass &filename = file_list[index];
CString animation_name = ::Asset_Name_From_Filename (filename);
//
// Add this entry to the animation combobox
//
int cb_index = m_AnimationList.AddString (animation_name);
if (cb_index != CB_ERR) {
m_AnimationList.SetItemData (cb_index, (ULONG)::_strdup ((LPCTSTR)filename));
//
// Should we select this animation by default?
//
CString name = m_Transition->Get_Animation_Name ();
CString real_name = name;
LPCTSTR suffix = ::strstr (name, ".");
if (suffix != NULL) {
real_name = suffix + 1;
}
if (::lstrcmpi (animation_name, real_name) == 0) {
m_AnimationList.SetCurSel (cb_index);
selected = true;
}
}
}
if (!selected) {
m_AnimationList.SetCurSel (0);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnEditChar
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnEditChar (void)
{
m_IsEditingChar = (SendDlgItemMessage (IDC_EDIT_CHAR, BM_GETCHECK) == 1);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnEditZone
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnEditZone (void)
{
m_IsEditingZone = (SendDlgItemMessage (IDC_EDIT_ZONE, BM_GETCHECK) == 1);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Load_Animation
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Load_Animation (void)
{
//
// Determine which animation file to load
//
int index = m_AnimationList.GetCurSel ();
if (index != CB_ERR) {
LPCTSTR filename = (LPCTSTR)m_AnimationList.GetItemData (index);
//
// Load the animation from the file
//
if (filename != NULL) {
Load_Animation (filename);
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Load_Animation
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Load_Animation (LPCTSTR filename)
{
//
// Create the character if necessary
//
Load_Character ();
MEMBER_RELEASE (m_Animation);
//
// Load the new animation
//
CString path = ::Strip_Filename_From_Path (filename);
CString asset_name = CString ("S_A_HUMAN.") + ::Asset_Name_From_Filename (filename);
::Set_Current_Directory (path);
m_Animation = WW3DAssetManager::Get_Instance ()->Get_HAnim (asset_name);
ASSERT (m_Animation != NULL);
//
// Pass the new animation onto the character
//
m_CurrFrame = 0;
m_CharacterObj->Set_Animation (m_Animation, m_CurrFrame);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Load_Character
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Load_Character (void)
{
if (m_CharacterObj == NULL) {
//
// Create the character's render object
//
SoldierGameObjDef *definition = (SoldierGameObjDef *)DefinitionMgrClass::Find_Typed_Definition ("Commando", CLASSID_GAME_OBJECT_DEF_SOLDIER, false);
if (definition != NULL) {
SoldierGameObj *game_obj = new SoldierGameObj;
game_obj->Init (*definition);
REF_PTR_SET (m_CharacterObj, game_obj->Peek_Model ());
game_obj->Set_Delete_Pending ();
}
//
// Transform the character from relative to world space coords
//
Matrix3D obj_tm = m_RenderObj->Get_Transform ();
Matrix3D char_tm = m_Transition->Get_Ending_TM ();
char_tm = char_tm * obj_tm;
m_CharacterObj->Set_Transform (char_tm);
//
// Add the character to the world
//
m_Scene->Add_Render_Object (m_CharacterObj);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnSelChangeAnimationList
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnSelChangeAnimationList (void)
{
Load_Animation ();
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// fn3DWindow
//
/////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK
TransitionEditDialogClass::fn3DWindow
(
HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam
)
{
if (message == WM_LBUTTONDOWN) {
TransitionEditDialogClass *dialog = NULL;
dialog = (TransitionEditDialogClass *)::GetProp (hwnd, "TRANSITION_DIALOG");
dialog->Handle_LBUTTON_DOWN (wparam, lparam);
} else if (message == WM_LBUTTONUP) {
TransitionEditDialogClass *dialog = NULL;
dialog = (TransitionEditDialogClass *)::GetProp (hwnd, "TRANSITION_DIALOG");
dialog->Handle_LBUTTON_UP (wparam, lparam);
} else if (message == WM_MOUSEMOVE) {
TransitionEditDialogClass *dialog = NULL;
dialog = (TransitionEditDialogClass *)::GetProp (hwnd, "TRANSITION_DIALOG");
dialog->Handle_MOUSEMOVE (wparam, lparam);
}
return ::DefWindowProc (hwnd, message, wparam, lparam);
}
////////////////////////////////////////////////////////////////////////////
//
// Handle_LBUTTON_DOWN
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Handle_LBUTTON_DOWN (WPARAM wparam, LPARAM lparam)
{
::SetCapture (::GetDlgItem (m_hWnd, IDC_3D_WINDOW));
m_LastPoint.x = LOWORD (lparam);
m_LastPoint.y = HIWORD (lparam);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Handle_LBUTTON_UP
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Handle_LBUTTON_UP (WPARAM wparam, LPARAM lparam)
{
::ReleaseCapture ();
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Handle_MOUSEMOVE
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Handle_MOUSEMOVE (WPARAM wparam, LPARAM lparam)
{
POINT point = { LOWORD (lparam), HIWORD (lparam) };
WWASSERT (m_Camera != NULL);
if ((wparam & MK_LBUTTON) && (wparam & MK_RBUTTON)) {
float delta_x = float(m_LastPoint.x - point.x) / 32;
float delta_y = float(point.y - m_LastPoint.y) / 32;
//
// Scale the position along the direction vector
//
Vector3 position = m_Camera->Get_Position ();
Matrix3D transform = m_Camera->Get_Transform ();
position += (delta_x * transform.Get_X_Vector ());
position += (delta_y * transform.Get_Y_Vector ());
// Set the camera's new position
m_Camera->Set_Position (position);
} else if (wparam & MK_LBUTTON) {
//
// Orbit the camera around the object
//
if (::GetCapture () == ::GetDlgItem (m_hWnd, IDC_3D_WINDOW)) {
::Trackball_Camera ( ::GetDlgItem (m_hWnd, IDC_3D_WINDOW),
*m_Camera,
Vector3 (0, 0, 0),
point,
m_LastPoint );
}
} else if (wparam & MK_RBUTTON) {
float delta = float(m_LastPoint.y - point.y) / 12;
//
// Scale the position along the direction vector
//
Vector3 position = m_Camera->Get_Position ();
Matrix3D transform = m_Camera->Get_Transform ();
position += (delta * transform.Get_Z_Vector ());
// Set the camera's new position
m_Camera->Set_Position (position);
}
m_LastPoint = point;
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Trackball_Camera
//
/////////////////////////////////////////////////////////////////////////////
void
Trackball_Camera
(
HWND hwnd,
CameraClass & camera,
const Vector3 & center,
POINT point,
POINT last_point
)
{
RECT rect;
::GetClientRect (hwnd, &rect);
//
// Convert the points to normalized units
//
float mid_point_x = float(rect.right >> 1);
float mid_point_y = float(rect.bottom >> 1);
float last_point_x = ((float)last_point.x - mid_point_x) / mid_point_x;
float last_point_y = (mid_point_y - (float)last_point.y) / mid_point_y;
float point_x = ((float)point.x - mid_point_x) / mid_point_x;
float point_y = (mid_point_y - (float)point.y) / mid_point_y;
//
// Calculate the orbit
//
Quaternion rotation = ::Trackball (last_point_x, last_point_y, point_x, point_y, 0.8F);
//
// Get the transformation matrix for the camera and its inverse
//
Matrix3D transform = camera.Get_Transform ();
Matrix3D inv_tm;
transform.Get_Orthogonal_Inverse (inv_tm);
//
// Translate to the object's center, perform the rotation, then translate back out.
//
Vector3 to_object = inv_tm * center;
transform.Translate (to_object);
Matrix3D::Multiply (transform, Build_Matrix3D (rotation), &transform);
transform.Translate (-to_object);
// Pass the new trnasform onto the camera
camera.Set_Transform (transform);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// PreTranslateMessage
//
/////////////////////////////////////////////////////////////////////////////
BOOL
TransitionEditDialogClass::PreTranslateMessage (MSG *pMsg)
{
if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP) {
if (pMsg->wParam == VK_NUMPAD8 || pMsg->wParam == VK_NUMPAD2 ||
pMsg->wParam == VK_NUMPAD4 || pMsg->wParam == VK_NUMPAD6 ||
pMsg->wParam == VK_NUMPAD7 || pMsg->wParam == VK_NUMPAD1 ||
pMsg->wParam == VK_UP || pMsg->wParam == VK_DOWN ||
pMsg->wParam == VK_LEFT || pMsg->wParam == VK_RIGHT)
{
return 1;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
////////////////////////////////////////////////////////////////////////////
//
// OnAniBackFrame
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnAniBackFrame (void)
{
m_CurrFrame -= 1.0F;
if (m_CurrFrame < 0) {
m_CurrFrame = float(m_Animation->Get_Num_Frames () - 1);
}
m_CharacterObj->Set_Animation (m_Animation, m_CurrFrame);
m_IsAnimating = false;
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnAniFirstFrame
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnAniFirstFrame (void)
{
m_CurrFrame = 0;
m_CharacterObj->Set_Animation (m_Animation, m_CurrFrame);
m_IsAnimating = false;
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnAniFwdFrame
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnAniFwdFrame (void)
{
m_CurrFrame += 1;
if (m_CurrFrame >= float(m_Animation->Get_Num_Frames () - 1)) {
m_CurrFrame = 0;
}
m_CharacterObj->Set_Animation (m_Animation, m_CurrFrame);
m_IsAnimating = false;
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnAniLastFrame
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnAniLastFrame (void)
{
m_CurrFrame = float(m_Animation->Get_Num_Frames () - 1);
m_CharacterObj->Set_Animation (m_Animation, m_CurrFrame);
m_IsAnimating = false;
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnAniPause
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnAniPause (void)
{
m_IsAnimating = false;
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnAniPlay
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnAniPlay (void)
{
m_IsAnimating = true;
m_LastAnimUpdate = ::GetTickCount ();
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnAniStop
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnAniStop (void)
{
m_CurrFrame = 0;
m_CharacterObj->Set_Animation (m_Animation, m_CurrFrame);
m_IsAnimating = false;
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Animation
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::Update_Animation (void)
{
if (m_IsAnimating) {
DWORD curr_ticks = ::GetTickCount ();
float seconds = float((curr_ticks - m_LastAnimUpdate)/1000.0F);
float frame_inc = seconds * m_Animation->Get_Frame_Rate ();
m_CurrFrame += frame_inc;
if (m_CurrFrame > float(m_Animation->Get_Num_Frames ())) {
m_CurrFrame -= float(m_Animation->Get_Num_Frames ());
}
m_CharacterObj->Set_Animation (m_Animation, m_CurrFrame);
m_LastAnimUpdate = curr_ticks;
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnSizeZone
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnSizeZone (void)
{
m_IsSizingZone = (m_SizeZoneCheck.GetCheck () == 1);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_EDIT_ZONE), !m_IsSizingZone);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_EDIT_CHAR), !m_IsSizingZone);
if (m_IsSizingZone) {
m_IsEditingZone = false;
m_IsEditingChar = false;
m_IsRotatingChar = false;
m_RotateCharCheck.SetCheck (false);
} else {
OnEditChar ();
OnEditZone ();
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnRotateChar
//
/////////////////////////////////////////////////////////////////////////////
void
TransitionEditDialogClass::OnRotateChar (void)
{
m_IsRotatingChar = (m_RotateCharCheck.GetCheck () == 1);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_EDIT_ZONE), !m_IsRotatingChar);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_EDIT_CHAR), !m_IsRotatingChar);
if (m_IsRotatingChar) {
m_IsEditingZone = false;
m_IsEditingChar = false;
m_IsSizingZone = false;
m_SizeZoneCheck.SetCheck (false);
} else {
OnEditChar ();
OnEditZone ();
}
return ;
}