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/PresetsLibForm.cpp

3668 lines
88 KiB
C++
Raw Permalink Normal View History

/*
** 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/>.
*/
// PresetsForm.cpp : implementation file
//
#include "stdafx.h"
#include "leveledit.h"
#include "presetslibform.h"
#include "utils.h"
#include "filemgr.h"
#include "definitionfactorymgr.h"
#include "definitionclassids.h"
#include "definitionfactory.h"
#include "definitionmgr.h"
#include "definition.h"
#include "icons.h"
#include "terraindefinition.h"
#include "preset.h"
#include "presetmgr.h"
#include "sceneeditor.h"
#include "saveload.h"
#include "rawfile.h"
#include "chunkio.h"
#include "filelocations.h"
#include "nodecategories.h"
#include "editorchunkids.h"
#include "regkeys.h"
#include "nodemgr.h"
#include "LevelEditView.h"
#include "PlaySoundDialog.h"
#include "AudibleSound.h"
#include "UpdatePresetDialog.h"
#include "definitionutils.h"
#include "presetlogger.h"
#include "rendobj.h"
#include "phys.h"
#include "textfile.h"
#include "node.h"
#include "ramfile.h"
#include "editorbuild.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
///////////////////////////////////////////////////////////////////////
//
// Helper objects
//
///////////////////////////////////////////////////////////////////////
class SelectionCaptureClass
{
public:
SelectionCaptureClass (PresetsFormClass *preset_form)
{
m_PresetForm = preset_form;
HTREEITEM tree_item = m_PresetForm->m_TreeCtrl.GetSelectedItem ();
PresetClass *preset = m_PresetForm->Get_Item_Preset (tree_item);
DefinitionFactoryClass *factory = m_PresetForm->Get_Item_Factory (tree_item);
if (preset != NULL) {
m_ID = preset->Get_ID ();
m_IsFactory = false;
} else {
m_ID = factory->Get_Class_ID ();
m_IsFactory = true;
}
return ;
}
void Restore (void)
{
m_PresetForm->Reselect_Item (m_ID, m_IsFactory);
return ;
}
private:
PresetsFormClass * m_PresetForm;
int m_ID;
bool m_IsFactory;
};
///////////////////////////////////////////////////////////////////////
//
// Macros
//
///////////////////////////////////////////////////////////////////////
#ifndef TreeView_SetOverlay
#define TreeView_SetOverlay(hwndLV, i, overlay) \
{ \
TVITEMEX item_info = { TVIF_STATE, i, INDEXTOOVERLAYMASK(overlay), TVIS_OVERLAYMASK, 0 }; \
TreeView_SetItem(hwndLV, &item_info); \
}
#endif
///////////////////////////////////////////////////////////////////////
//
// Constants
//
///////////////////////////////////////////////////////////////////////
typedef enum
{
TYPE_FACTORY,
TYPE_PRESET,
} ITEM_TYPE;
typedef struct
{
ITEM_TYPE type;
union
{
DefinitionFactoryClass *factory;
PresetClass *preset;
};
} ITEM_DATA;
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;
/////////////////////////////////////////////////////////////////////////////
//
// PresetsFormClass
//
/////////////////////////////////////////////////////////////////////////////
PresetsFormClass::PresetsFormClass(CWnd *parent_wnd)
: m_DragItem (NULL),
m_IsDragging (false),
m_DragImageList (NULL),
CDialog(PresetsFormClass::IDD)
{
//{{AFX_DATA_INIT(PresetsFormClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
Create (PresetsFormClass::IDD, parent_wnd);
return ;
}
PresetsFormClass::~PresetsFormClass()
{
return ;
}
void PresetsFormClass::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(PresetsFormClass)
DDX_Control(pDX, IDC_PRESETS_TREE, m_TreeCtrl);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(PresetsFormClass, CDialog)
//{{AFX_MSG_MAP(PresetsFormClass)
ON_WM_SIZE()
ON_COMMAND(IDC_ADD, OnAdd)
ON_NOTIFY(TVN_DELETEITEM, IDC_PRESETS_TREE, OnDeleteitemPresetsTree)
ON_COMMAND(IDC_MODIFY, OnModify)
ON_COMMAND(IDC_MAKE, OnMake)
ON_COMMAND(IDC_ADD_TEMP, OnAddTemp)
ON_COMMAND(IDC_DELETE, OnDelete)
ON_NOTIFY(TVN_SELCHANGED, IDC_PRESETS_TREE, OnSelchangedPresetsTree)
ON_COMMAND(IDC_PLAY, OnPlay)
ON_COMMAND(IDC_INFO, OnInfo)
ON_COMMAND(IDC_EXTRA, OnExtra)
ON_UPDATE_COMMAND_UI(IDC_CONVERT, OnUpdateConvert)
ON_UPDATE_COMMAND_UI(IDC_INFO, OnUpdateInfo)
ON_UPDATE_COMMAND_UI(IDC_PLAY, OnUpdatePlay)
ON_UPDATE_COMMAND_UI(IDC_UPDATE_VSS, OnUpdateUpdateVss)
ON_WM_DRAWITEM()
ON_WM_MEASUREITEM()
ON_COMMAND(IDC_CONVERT, OnConvert)
ON_COMMAND(IDC_UPDATE_VSS, OnUpdateVss)
ON_COMMAND(IDM_BATCH_IMPORT_TERRAIN, OnBatchImportTerrain)
ON_COMMAND(IDM_UPDATE_EMBEDDED_NODE_LIST, OnBuildEmbedNodeList)
ON_COMMAND(IDM_CLEAR_EMBEDDED_NODE_LIST, OnClearEmbeddedNodeList)
ON_UPDATE_COMMAND_UI(IDM_BATCH_IMPORT_TERRAIN, OnUpdateBatchImportTerrain)
ON_UPDATE_COMMAND_UI(IDM_UPDATE_EMBEDDED_NODE_LIST, OnUpdateEmbeddedNodeList)
ON_UPDATE_COMMAND_UI(IDM_CLEAR_EMBEDDED_NODE_LIST, OnUpdateClearEmbeddedNodeList)
ON_NOTIFY(TVN_BEGINDRAG, IDC_PRESETS_TREE, OnBegindragPresetsTree)
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// PresetsFormClass diagnostics
#ifdef _DEBUG
void PresetsFormClass::AssertValid() const
{
CDialog::AssertValid();
}
void PresetsFormClass::Dump(CDumpContext& dc) const
{
CDialog::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
//
// OnSize
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnSize
(
UINT nType,
int cx,
int cy
)
{
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 empty 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 ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL
PresetsFormClass::OnInitDialog (void)
{
CDialog::OnInitDialog ();
CRect rect;
GetClientRect (&rect);
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_PRESET_TOOLBAR1);
m_Toolbar.SetBarStyle (m_Toolbar.GetBarStyle () | CBRS_TOOLTIPS | CBRS_FLYBY);
m_Toolbar.GetToolBarCtrl ().SetExtendedStyle (TBSTYLE_EX_DRAWDDARROWS);
TBBUTTONINFO button_info = { sizeof (TBBUTTONINFO), TBIF_STYLE, 0 };
int index = m_Toolbar.CommandToIndex (IDC_EXTRA);
m_Toolbar.GetToolBarCtrl ().GetButtonInfo (IDC_EXTRA, &button_info);
button_info.fsStyle |= TBSTYLE_DROPDOWN;
m_Toolbar.GetToolBarCtrl ().SetButtonInfo (IDC_EXTRA, &button_info);
//
// Get the bounding rectangle of the form window
//
CRect parentrect;
GetWindowRect (&parentrect);
m_Toolbar.SetWindowPos (NULL, 0, 0, parentrect.Width () - TOOLBAR_H_BORDER, TOOLBAR_HEIGHT, SWP_NOZORDER | SWP_NOMOVE);
m_Toolbar.Enable_Button (IDC_ADD, Enable_Button (IDC_ADD));
m_Toolbar.Enable_Button (IDC_DELETE, Enable_Button (IDC_DELETE));
//
// Pass the general use imagelist onto the tree control
//
m_TreeCtrl.SetImageList (::Get_Global_Image_List (), TVSIL_NORMAL);
Reload_Presets ();
//
// Select the first item in the tree control
//
HTREEITEM first_item = m_TreeCtrl.GetNextItem (NULL, TVGN_CHILD);
if (first_item != NULL) {
m_TreeCtrl.SelectItem (first_item);
}
SetProp (m_TreeCtrl, "TRANS_ACCS", (HANDLE)1);
SetProp (m_hWnd, "TRANS_ACCS", (HANDLE)1);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// Reload_Presets
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Reload_Presets (void)
{
m_TreeCtrl.SetRedraw (FALSE);
m_TreeCtrl.SelectItem (NULL);
m_TreeCtrl.DeleteAllItems ();
//
// Loop through and add all the registered definition factories 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) {
//
// Add all presets for this factory into the tree
//
if (factory->Is_Displayed ()) {
Set_Item_Data (tree_item, factory);
Fill_In_Presets (tree_item);
}
} else {
//
// 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 and all its definitions 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);
Set_Item_Data (child_item, factory);
Fill_In_Presets (child_item);
}
}
}
}
Sort_Nodes (TVI_ROOT);
m_TreeCtrl.SetRedraw (TRUE);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Fill_In_Presets
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Fill_In_Presets (HTREEITEM root_item)
{
DefinitionFactoryClass *factory = Get_Item_Factory (root_item);
if (factory != NULL && factory->Is_Displayed ()) {
uint32 class_id = factory->Get_Class_ID ();
//
// Find all the presets that belong to this class
//
PresetClass *preset = NULL;
for ( preset = PresetMgrClass::Get_First (class_id, PresetMgrClass::ID_CLASS);
preset != NULL;
preset = PresetMgrClass::Get_Next (preset, class_id, PresetMgrClass::ID_CLASS))
{
//
// Add this preset to the tree
//
if (preset->Get_Parent () == NULL) {
HTREEITEM tree_item = Insert_Preset (root_item, preset);
if (tree_item != NULL) {
//
// Recursively fill in this definition's 'children'
//
Fill_In_Preset_Children (tree_item, preset->Get_ID ());
}
}
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Fill_In_Preset_Children
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Fill_In_Preset_Children
(
HTREEITEM root_item,
uint32 parent_id
)
{
//
// Lookup the parent preset
//
PresetClass *parent_preset = PresetMgrClass::Find_Preset (parent_id);
if (parent_preset == NULL) {
return ;
}
//
// Loop over all the children of this preset
//
int count = parent_preset->Get_Child_Preset_Count ();
for (int index = 0; index < count; index ++) {
PresetClass *child_preset = parent_preset->Get_Child_Preset (index);
if (child_preset != NULL) {
//
// Check to make sure we have no recursive links
//
PresetClass *parent = child_preset->Get_Parent ();
if (parent == child_preset || parent->Get_ID () == child_preset->Get_ID ()) {
CString message;
message.Format ("Preset '%s' is recursively linked to itself.\r\n", child_preset->Get_Name ());
MessageBox (message, "Preset Error", MB_ICONERROR | MB_OK | MB_SETFOREGROUND);
continue ;
}
//
// Check to make sure the parent is correct
//
if (parent != NULL && child_preset->Get_Class_ID () != parent->Get_Class_ID ()) {
CString message;
message.Format ("Preset '%s' is incorrectly linked as a child of '%s'.\r\n", child_preset->Get_Name (), parent->Get_Name ());
MessageBox (message, "Preset Error", MB_ICONERROR | MB_OK | MB_SETFOREGROUND);
}
//
// Add this preset to the tree
//
HTREEITEM tree_item = Insert_Preset (root_item, child_preset);
if (tree_item != NULL) {
//
// Recursively fill in this definition's 'children'
//
Fill_In_Preset_Children (tree_item, child_preset->Get_ID ());
}
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Find_Preset
//
/////////////////////////////////////////////////////////////////////////////
HTREEITEM
PresetsFormClass::Find_Preset (HTREEITEM root_item, uint32 id)
{
HTREEITEM preset_item = NULL;
//
// Look for the preset in this item's children (recursive)
//
for ( HTREEITEM tree_item = m_TreeCtrl.GetChildItem (root_item);
(tree_item != NULL) && (preset_item == NULL);
tree_item = m_TreeCtrl.GetNextSiblingItem (tree_item))
{
DefinitionClass *definition = Get_Item_Definition (tree_item);
//
// Is this the preset we were looking for?
//
if ((definition != NULL) && (definition->Get_ID () == id)) {
preset_item = tree_item;
} else if (m_TreeCtrl.ItemHasChildren (tree_item)) {
//
// Recursively call this method for all sub-folders in this tree
//
preset_item = Find_Preset (tree_item, id);
}
}
return preset_item;
}
/////////////////////////////////////////////////////////////////////////////
//
// Find_Factory
//
/////////////////////////////////////////////////////////////////////////////
HTREEITEM
PresetsFormClass::Find_Factory (HTREEITEM root_item, uint32 id)
{
HTREEITEM factory_item = NULL;
//
// Look for the preset in this item's children (recursive)
//
for ( HTREEITEM tree_item = m_TreeCtrl.GetChildItem (root_item);
(tree_item != NULL) && (factory_item == NULL);
tree_item = m_TreeCtrl.GetNextSiblingItem (tree_item))
{
DefinitionFactoryClass *factory = Get_Item_Factory (tree_item);
//
// Is this the factory we were looking for?
//
if ((factory != NULL) && (factory->Get_Class_ID () == id)) {
factory_item = tree_item;
} else if (m_TreeCtrl.ItemHasChildren (tree_item)) {
//
// Recursively call this method for all sub-folders in this tree
//
factory_item = Find_Factory (tree_item, id);
}
}
return factory_item;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Selected_Factory
//
/////////////////////////////////////////////////////////////////////////////
DefinitionFactoryClass *
PresetsFormClass::Get_Selected_Factory (void)
{
HTREEITEM curr_item = m_TreeCtrl.GetSelectedItem ();
DefinitionFactoryClass *factory = Get_Item_Factory (curr_item);
// Does this item represent a definition?
if (factory == NULL) {
//
// Find the defintion's factory (if possible)
//
DefinitionClass *definition = Get_Item_Definition (curr_item);
if (definition != NULL) {
uint32 class_id = definition->Get_Class_ID ();
factory = DefinitionFactoryMgrClass::Find_Factory (class_id);
}
}
return factory;
}
/////////////////////////////////////////////////////////////////////////////
//
// Set_Item_Data
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Set_Item_Data (HTREEITEM item, DefinitionFactoryClass *factory)
{
//
// Allocate a new wrapper if we need to
//
ITEM_DATA *item_data = (ITEM_DATA *)m_TreeCtrl.GetItemData (item);
if (item_data == NULL) {
item_data = new ITEM_DATA;
}
//
// Set a flag in the wrapper so we know what kind of data
// this tree item contains.
//
item_data->type = TYPE_FACTORY;
item_data->factory = factory;
m_TreeCtrl.SetItemData (item, (DWORD)item_data);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Set_Item_Data
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Set_Item_Data (HTREEITEM item, PresetClass *preset)
{
//
// Allocate a new wrapper if we need to
//
ITEM_DATA *item_data = (ITEM_DATA *)m_TreeCtrl.GetItemData (item);
if (item_data == NULL) {
item_data = new ITEM_DATA;
}
//
// Set a flag in the wrapper so we know what kind of data
// this tree item contains.
//
item_data->type = TYPE_PRESET;
item_data->preset = preset;
m_TreeCtrl.SetItemData (item, (DWORD)item_data);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Item_Factory
//
/////////////////////////////////////////////////////////////////////////////
DefinitionFactoryClass *
PresetsFormClass::Get_Item_Factory (HTREEITEM item)
{
DefinitionFactoryClass *factory = NULL;
if (item != NULL) {
//
// If this item represents a factory, then return the factory
// pointer to the caller.
//
ITEM_DATA *item_data = (ITEM_DATA *)m_TreeCtrl.GetItemData (item);
if ((item_data != NULL) && (item_data->type == TYPE_FACTORY)) {
factory = item_data->factory;
}
}
return factory;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Item_Definition
//
/////////////////////////////////////////////////////////////////////////////
DefinitionClass *
PresetsFormClass::Get_Item_Definition (HTREEITEM item)
{
DefinitionClass *definition = NULL;
if (item != NULL) {
//
// Get the definition from the preset this item
// represents
//
PresetClass *preset = Get_Item_Preset (item);
if (preset != NULL) {
definition = preset->Get_Definition ();
}
}
return definition;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Item_Preset
//
/////////////////////////////////////////////////////////////////////////////
PresetClass *
PresetsFormClass::Get_Item_Preset (HTREEITEM item)
{
PresetClass *preset = NULL;
if (item != NULL) {
//
// If this item represents a definition, then return the definition
// pointer to the caller.
//
ITEM_DATA *item_data = (ITEM_DATA *)m_TreeCtrl.GetItemData (item);
if ((item_data != NULL) && (item_data->type == TYPE_PRESET)) {
preset = item_data->preset;
}
}
return preset;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Icon
//
/////////////////////////////////////////////////////////////////////////////
int
PresetsFormClass::Get_Icon (PresetClass *preset)
{
int icon = FOLDER_ICON;
DefinitionClass *definition = preset->Get_Definition ();
if (definition != NULL) {
int class_id = definition->Get_Class_ID ();
int superclass_id = ::SuperClassID_From_ClassID (class_id);
switch (superclass_id) {
case CLASSID_TERRAIN:
icon = TERRAIN_ICON;
break;
case CLASSID_TILE:
icon = TILE_ICON;
break;
case CLASSID_GAME_OBJECTS:
case CLASSID_MUNITIONS:
case CLASSID_DUMMY_OBJECTS:
if (class_id == CLASSID_GAME_OBJECT_DEF_BUILDING) {
icon = BUILDING_ICON;
} else {
icon = OBJECT_ICON;
}
break;
case CLASSID_LIGHT:
icon = LIGHT_ICON;
break;
case CLASSID_SOUND:
icon = SOUND_ICON;
break;
case CLASSID_WAYPATH:
icon = WAYPATH_ICON;
break;
case CLASSID_ZONE:
icon = ZONE_ICON;
break;
case CLASSID_TRANSITION:
icon = TRANSITION_ICON;
break;
case CLASSID_TWIDDLERS:
icon = RAND_ICON;
break;
case CLASSID_BUILDINGS:
icon = BUILDING_ICON;
break;
case CLASSID_EDITOR_OBJECTS:
if (class_id == CLASSID_VIS_POINT_DEF) {
icon = VIS_ICON;
} else if (class_id == CLASSID_PATHFIND_START_DEF) {
icon = PATHFIND_ICON;
}
break;
case CLASSID_GLOBAL_SETTINGS:
icon = FILE_ICON;
break;
}
}
if (preset->Get_IsTemporary ()) {
icon = TEMP_ICON;
}
return icon;
}
/////////////////////////////////////////////////////////////////////////////
//
// Insert_Preset
//
/////////////////////////////////////////////////////////////////////////////
HTREEITEM
PresetsFormClass::Insert_Preset
(
HTREEITEM root_item,
PresetClass * preset
)
{
int icon = Get_Icon (preset);
//
// Insert a new node into the tree to represent this item
//
HTREEITEM tree_item = m_TreeCtrl.InsertItem (preset->Get_Name (), icon, icon, root_item);
if (tree_item != NULL) {
Set_Item_Data (tree_item, preset);
bool needs_overlay = (preset->Get_Node_List ().Count () > 0);
TreeView_SetOverlay (m_TreeCtrl, tree_item, needs_overlay);
}
return tree_item;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnDeleteitemPresetsTree
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnDeleteitemPresetsTree
(
NMHDR * pNMHDR,
LRESULT *pResult
)
{
NM_TREEVIEW *pNMTreeView = (NM_TREEVIEW *)pNMHDR;
(*pResult) = 0;
//
// Free the wrapper we installed around this item
//
ITEM_DATA *item_data = (ITEM_DATA *)m_TreeCtrl.GetItemData (pNMTreeView->itemOld.hItem);
SAFE_DELETE (item_data);
m_TreeCtrl.SetItemData (pNMTreeView->itemOld.hItem, 0L);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnModify
//
/////////////////////////////////////////////////////////////////////////////
bool
PresetsFormClass::Modify_Preset (void)
{
bool retval = false;
HTREEITEM current_item = m_TreeCtrl.GetSelectedItem ();
PresetClass *preset = Get_Item_Preset (current_item);
if (preset != NULL) {
StringClass old_name = preset->Get_Name ();
//
// Show the properties dialog for this preset
//
if (preset->Show_Properties ()) {
//
// Check to see if the user has renamed the preset
//
StringClass new_name = preset->Get_Name ();
if (::lstrcmp (old_name, new_name) != 0) {
//
// Rename the item in the tree
//
m_TreeCtrl.SetRedraw (FALSE);
m_TreeCtrl.SetItemText (current_item, preset->Get_Name ());
m_TreeCtrl.SetRedraw (TRUE);
m_TreeCtrl.InvalidateRect (NULL, TRUE);
//
// Log the rename operation
//
if (preset->Get_IsTemporary () == false) {
PresetLoggerClass::Log_Renamed (old_name, new_name);
}
}
retval = true;
}
}
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnModify
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnModify (void)
{
HTREEITEM current_item = m_TreeCtrl.GetSelectedItem ();
PresetClass *preset = Get_Item_Preset (current_item);
if (preset != NULL) {
if (preset->Get_IsTemporary () == false) {
//
// Check out the definition database
//
SelectionCaptureClass sel_capture (this);
bool undo_on_err = false;
uint32 class_id = preset->Get_Class_ID ();
if (PresetMgrClass::Check_Out_Database (class_id, &undo_on_err)) {
sel_capture.Restore ();
//
// Re-get the preset (its pointer has changed, the
// old one is crap).
//
current_item = m_TreeCtrl.GetSelectedItem ();
preset = Get_Item_Preset (current_item);
if (preset != NULL) {
//
// Show the preset settings
//
if (Modify_Preset ()) {
Save_Global_Presets (class_id);
PresetMgrClass::Add_Dirty_Preset (preset->Get_ID ());
} else if (undo_on_err) {
PresetMgrClass::Undo_Database_Check_Out (class_id);
}
}
}
} else {
//
// Show the preset settings
//
if (Modify_Preset ()) {
Save_Temp_Presets ();
}
}
NodeMgrClass::Reload_Nodes (preset);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Load_Databases
//
/////////////////////////////////////////////////////////////////////////////
bool
PresetsFormClass::Load_Databases (void)
{
// Start fresh
PresetMgrClass::Free_Presets ();
DefinitionMgrClass::Free_Definitions ();
bool retval = false;
#ifdef PUBLIC_EDITOR_VER
//
// Reload the presets
//
retval = Old_Load_Presets ();
retval &= Load_Temp_Presets ();
#else
//
// Reload the presets
//
retval = Load_Preset_Libraries ();
retval &= Load_Temp_Presets ();
#endif //PUBLIC_EDITOR_VER
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// Load_Preset_Libraries
//
/////////////////////////////////////////////////////////////////////////////
bool
PresetsFormClass::Load_Preset_Libraries (void)
{
//
// Try to load the library for each factory
//
DefinitionFactoryClass *factory = NULL;
for ( factory = DefinitionFactoryMgrClass::Get_First ();
factory != NULL;
factory = DefinitionFactoryMgrClass::Get_Next (factory))
{
if (factory->Is_Displayed ()) {
Load_Presets (factory->Get_Class_ID ());
}
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
//
// Load_Presets
//
/////////////////////////////////////////////////////////////////////////////
bool
PresetsFormClass::Load_Presets (uint32 class_id)
{
//
// Build a filename for the presets library
//
CString path;
::Get_File_Mgr ()->Get_Preset_Library_Path (class_id, false, path);
//
// Open the file
//
HANDLE file = ::CreateFile ( path,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0L,
NULL);
if (file != INVALID_HANDLE_VALUE) {
//
// Determine how large the file is
//
int file_size = ::GetFileSize (file, NULL);
if (file_size > 0 && file_size < 99999999)
{
//
// Read the file into memory
//
unsigned char *buffer = new unsigned char[file_size];
DWORD bytes_read = 0;
::ReadFile (file, buffer, file_size, &bytes_read, NULL);
//
// Close the file
//
::CloseHandle (file);
file = INVALID_HANDLE_VALUE;
//
// Use a RAM file for the loading
//
RAMFileClass file_obj (buffer, file_size);
file_obj.Open (FileClass::READ);
ChunkLoadClass chunk_load (&file_obj);
//
// Load the file
//
SaveLoadSystemClass::Load (chunk_load);
//
// Free the buffer
//
delete [] buffer;
buffer = NULL;
}
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
//
// Old_Load_Presets
//
/////////////////////////////////////////////////////////////////////////////
bool
PresetsFormClass::Old_Load_Presets (void)
{
CString path = ::Get_File_Mgr ()->Make_Full_Path (OBJECTS_DDB_PATH);
//
// Open the file
//
HANDLE file = ::CreateFile (path,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0L,
NULL);
if (file != INVALID_HANDLE_VALUE) {
//
// Determine how large the file is
//
int file_size = ::GetFileSize (file, NULL);
if (file_size > 0 && file_size < 99999999)
{
//
// Read the file into memory
//
unsigned char *buffer = new unsigned char[file_size];
DWORD bytes_read = 0;
::ReadFile (file, buffer, file_size, &bytes_read, NULL);
//
// Close the file
//
::CloseHandle (file);
file = INVALID_HANDLE_VALUE;
//
// Use a RAM file for the loading
//
RAMFileClass file_obj (buffer, file_size);
file_obj.Open (FileClass::READ);
ChunkLoadClass chunk_load (&file_obj);
//
// Load the file
//
SaveLoadSystemClass::Load (chunk_load);
//
// Free the buffer
//
delete [] buffer;
buffer = NULL;
}
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
//
// Load_Temp_Presets
//
/////////////////////////////////////////////////////////////////////////////
bool
PresetsFormClass::Load_Temp_Presets (void)
{
CString path = ::Get_File_Mgr ()->Make_Full_Path (TEMP_DB_PATH);
//
// Open the file
//
HANDLE hfile = ::CreateFile (path,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0L,
NULL);
if (hfile != INVALID_HANDLE_VALUE) {
RawFileClass file_obj;
file_obj.Attach (hfile);
ChunkLoadClass chunk_load (&file_obj);
//
// Load the file
//
SaveLoadSystemClass::Load (chunk_load);
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
//
// Save_Temp_Presets
//
/////////////////////////////////////////////////////////////////////////////
bool
PresetsFormClass::Save_Temp_Presets (void)
{
Save_Presets (0, true);
return true;
}
/////////////////////////////////////////////////////////////////////////////
//
// Save_Global_Presets
//
/////////////////////////////////////////////////////////////////////////////
bool
PresetsFormClass::Save_Global_Presets (uint32 class_id)
{
#ifndef PUBLIC_EDITOR_VER
Save_Presets (class_id, false);
#endif //PUBLIC_EDITOR_VER
return true;
}
/////////////////////////////////////////////////////////////////////////////
//
// Build_DDB_File_List
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Build_DDB_File_List
(
DynamicVectorClass<CString> & file_list,
HTREEITEM parent_item
)
{
//
// Loop over all the immediate children
//
for ( HTREEITEM child_item = m_TreeCtrl.GetChildItem (parent_item);
child_item != NULL;
child_item = m_TreeCtrl.GetNextSiblingItem (child_item))
{
//
// If this tree item represents a definition factory, then
// we should have a preset library to match
//
DefinitionFactoryClass *factory = Get_Item_Factory (child_item);
if (factory != NULL) {
//
// Build a filename for this preset library
//
CString path;
::Get_File_Mgr ()->Get_Preset_Library_Path (factory->Get_Class_ID (), false, path);
//
// Add this preset library to the list
//
file_list.Add (path);
} else if (m_TreeCtrl.ItemHasChildren (child_item)) {
//
// Recursively call this method for all sub-folders in this tree
//
Build_DDB_File_List (file_list, child_item);
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Save_Preset_Libraries
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Save_Preset_Libraries (HTREEITEM parent_item)
{
#ifdef PUBLIC_EDITOR_VER
//
// Simply save the presets together in one file
//
CString path = ::Get_File_Mgr ()->Make_Full_Path (OBJECTS_DDB_PATH);
Save_Presets (path, 0, false, false);
#else
//
// Loop over all the immediate children
//
for ( HTREEITEM child_item = m_TreeCtrl.GetChildItem (parent_item);
child_item != NULL;
child_item = m_TreeCtrl.GetNextSiblingItem (child_item))
{
//
// If this tree item represents a definition factory, then save
// a preset library for all presets of this class ID
//
DefinitionFactoryClass *factory = Get_Item_Factory (child_item);
if (factory != NULL) {
Save_Global_Presets (factory->Get_Class_ID ());
} else if (m_TreeCtrl.ItemHasChildren (child_item)) {
//
// Recursively call this method for all sub-folders in this tree
//
Save_Preset_Libraries (child_item);
}
}
#endif //PUBLIC_EDITOR_VER
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Save_Presets
//
/////////////////////////////////////////////////////////////////////////////
bool
PresetsFormClass::Save_Presets
(
LPCTSTR path,
uint32 class_id,
bool class_id_matters,
bool temps_only
)
{
///
// Delete the file if it already exists
//
if (::GetFileAttributes (path) != 0xFFFFFFFF) {
DWORD attributes = ::GetFileAttributes (path);
::SetFileAttributes (path, attributes & (~FILE_ATTRIBUTE_READONLY));
::DeleteFile (path);
}
//
// Create the file at the specified location
//
HANDLE file = ::CreateFile ( path,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
0L,
NULL);
ASSERT (file != INVALID_HANDLE_VALUE);
if (file != INVALID_HANDLE_VALUE) {
//
// Now write the presets and definitions out to this file
//
Save_Presets (file, class_id, class_id_matters, temps_only);
} else {
//
// Warn the user
//
DWORD last_error = ::GetLastError ();
CString message;
message.Format ("Unable to create database file.\nPath:%s\nError Code:%d", path, last_error);
::MessageBox (::AfxGetMainWnd ()->m_hWnd, message, "File I/O Error", MB_ICONERROR | MB_OK);
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
//
// Save_Presets
//
/////////////////////////////////////////////////////////////////////////////
bool
PresetsFormClass::Save_Presets (uint32 class_id, bool temps_only)
{
//
// Build a filename for the presets library
//
CString path;
::Get_File_Mgr ()->Get_Preset_Library_Path (class_id, temps_only, path);
//
// Now save the presets to this file
//
return Save_Presets (path, class_id, !temps_only, temps_only);
}
/////////////////////////////////////////////////////////////////////////////
//
// Save_Presets
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Save_Presets (HANDLE file, uint32 class_id, bool class_id_matters, bool temps_only)
{
//
// Create a chunk IO object that we can use to save our subsystems
//
RawFileClass file_obj;
file_obj.Attach (file);
ChunkSaveClass chunk_save (&file_obj);
//
// Remove all the presets that don't match our criteria
//
PRESET_LIST preset_list;
preset_list.Set_Growth_Step (2000);
PresetMgrClass::Remove_Non_Matching_Presets (class_id, class_id_matters, temps_only, preset_list);
//
// Turn saving off for all definitions
//
DefinitionClass *definition = NULL;
for ( definition = DefinitionMgrClass::Get_First ();
definition != NULL;
definition = DefinitionMgrClass::Get_Next (definition))
{
definition->Enable_Save (false);
}
//
// Now turn saving on for all definitions that are needed by
// one of the presets.
//
DEFINITION_LIST defs_to_save;
PresetClass *preset = NULL;
for ( preset = PresetMgrClass::Get_First ();
preset != NULL;
preset = PresetMgrClass::Get_Next (preset))
{
//
// Build a list of definitions this preset depends on
//
DEFINITION_LIST curr_defs;
preset->Collect_Definitions (curr_defs);
//
// Turn saving on for all these definitions
//
for (int index = 0; index < curr_defs.Count (); index ++) {
DefinitionClass *definition = curr_defs[index];
if (definition != NULL) {
definition->Enable_Save (true);
}
}
}
//
// The definition database consists of the definitions (global)
// and the presets (editor only).
//
SaveLoadSystemClass::Save (chunk_save, _TheDefinitionMgr);
SaveLoadSystemClass::Save (chunk_save, _ThePresetMgr);
//
// Turn saving back on for all definitions
//
for ( definition = DefinitionMgrClass::Get_First ();
definition != NULL;
definition = DefinitionMgrClass::Get_Next (definition))
{
definition->Enable_Save (true);
}
//
// Now add back all the presets we removed
//
PresetMgrClass::Put_Presets_Back (preset_list);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Reselect_Item
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Reselect_Item (int id, bool is_factory)
{
HTREEITEM tree_item = NULL;
if (is_factory) {
tree_item = Find_Factory (TVI_ROOT, id);
} else {
tree_item = Find_Preset (TVI_ROOT, id);
}
m_TreeCtrl.Select (tree_item, TVGN_FIRSTVISIBLE);
m_TreeCtrl.SelectItem (tree_item);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnAddTemp
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnAddTemp (void)
{
DefinitionFactoryClass *factory = Get_Selected_Factory ();
if (factory != NULL) {
if (Add_New_Preset (NULL, true) != NULL) {
Save_Temp_Presets ();
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnAdd
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnAdd (void)
{
DefinitionFactoryClass *factory = Get_Selected_Factory ();
if (factory != NULL) {
//
// Check out the definition database
//
SelectionCaptureClass sel_capture (this);
bool undo_check_out = false;
if (PresetMgrClass::Check_Out_Database (factory->Get_Class_ID (), &undo_check_out)) {
sel_capture.Restore ();
//
// Create a new preset
//
PresetClass *preset = Add_New_Preset (NULL);
if (preset != NULL) {
//
// Log creation
//
PresetLoggerClass::Log_Created (preset);
//
// Register this new preset for check-in
//
Save_Global_Presets (factory->Get_Class_ID ());
PresetMgrClass::Add_Dirty_Preset (preset->Get_ID ());
} else if (undo_check_out) {
PresetMgrClass::Undo_Database_Check_Out (factory->Get_Class_ID ());
}
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnMake
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnMake (void)
{
HTREEITEM current_item = m_TreeCtrl.GetSelectedItem ();
PresetClass *preset = Get_Item_Preset (current_item);
if (preset != NULL) {
::Get_Scene_Editor ()->Create_Node (preset);
//
// Repartition the scene if the user placed a terrain
//
if (preset->Get_Class_ID () == CLASSID_TERRAIN) {
::Get_Scene_Editor ()->Re_Partition_Static_Projectors ();
::Get_Scene_Editor ()->Re_Partition_Static_Lights ();
::Get_Scene_Editor ()->Re_Partition_Static_Objects ();
}
::Refresh_Main_View ();
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Add_New_Preset
//
/////////////////////////////////////////////////////////////////////////////
PresetClass *
PresetsFormClass::Add_New_Preset (LPCTSTR name, bool is_temp, bool sel_new)
{
PresetClass *new_preset = NULL;
DefinitionFactoryClass *factory = Get_Selected_Factory ();
if (factory != NULL) {
HTREEITEM current_item = m_TreeCtrl.GetSelectedItem ();
PresetClass *parent_preset = Get_Item_Preset (current_item);
//
// Create a new preset
//
new_preset = PresetMgrClass::Create_Preset (factory->Get_Class_ID (), name, is_temp);
new_preset->Set_Parent (parent_preset);
//
// Give the new preset its parent's values by default
//
if (parent_preset != NULL) {
new_preset->Copy_Properties (*parent_preset);
}
//
// Edit the preset's properties
//
if (name != NULL || new_preset->Show_Properties ()) {
//
// Add this preset to the framework
//
HTREEITEM new_item = Insert_Preset (current_item, new_preset);
PresetMgrClass::Add_Preset (new_preset);
DefinitionMgrClass::Register_Definition (new_preset->Get_Definition ());
if (parent_preset != NULL) {
parent_preset->Add_Child_Preset (new_preset->Get_ID ());
}
//
// Select the new entry
//
if (sel_new) {
m_TreeCtrl.Select (new_item, TVGN_FIRSTVISIBLE);
m_TreeCtrl.SelectItem (new_item);
}
m_TreeCtrl.SortChildren (current_item);
m_TreeCtrl.InvalidateRect (NULL, TRUE);
} else {
DefinitionClass *definition = new_preset->Get_Definition ();
SAFE_DELETE (definition);
SAFE_DELETE (new_preset);
}
}
return new_preset;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnDelete
//
/////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnDelete (void)
{
HTREEITEM current_item = m_TreeCtrl.GetSelectedItem ();
PresetClass *preset = Get_Item_Preset (current_item);
if (preset != NULL) {
//
// Make sure the user really wants to do this
//
if (::Message_Box ( m_hWnd,
IDS_DELETE_PRESET_MSG,
IDS_DELETE_PRESET_TITLE,
MB_ICONQUESTION | MB_YESNO) == IDYES )
{
CWaitCursor wait_cursor;
//
// Check out the definition database (unless its a temp)
//
SelectionCaptureClass sel_capture (this);
bool undo_on_err = false;
bool was_temp = preset->Get_IsTemporary ();;
if (was_temp || PresetMgrClass::Check_Out_Database (preset->Get_Class_ID (), &undo_on_err)) {
sel_capture.Restore ();
//
// Re-get the preset (its pointer has changed, the
// old one is crap).
//
current_item = m_TreeCtrl.GetSelectedItem ();
preset = Get_Item_Preset (current_item);
if (preset != NULL) {
//
// Log the delete operation
//
if (preset->Get_IsTemporary () == false) {
PresetLoggerClass::Log_Deleted (preset->Get_Name ());
}
//
// Build a list of all the sub-items that are affected by this operation
//
DynamicVectorClass<HTREEITEM> tree_item_list;
tree_item_list.Add (current_item);
Build_Child_List (current_item, tree_item_list);
//
// Determine what class-id's these presets belong to (they all belong
// to the same class)
//
uint32 class_id = 0;
DefinitionClass *definition = preset->Get_Definition ();
if (definition != NULL) {
class_id = definition->Get_Class_ID ();
}
//
// Free all the nodes in the scene that use any of these presets.
// Also unregister the preset and its definition
//
bool save_temp_lib = was_temp;
for (int index = 0; index < tree_item_list.Count (); index ++) {
PresetClass *preset = Get_Item_Preset (tree_item_list[index]);
if (preset != NULL) {
::Get_Scene_Editor ()->Delete_Nodes (preset);
PresetMgrClass::Remove_Preset (preset);
//
// Determine if we need to save the temporary preset
// library later or not.
//
if (preset->Get_IsTemporary ()) {
save_temp_lib = true;
}
//
// Unlink the definition
//
preset->Set_Definition (NULL);
//
// Free the definition
//
DefinitionClass *definition = preset->Get_Definition ();
if (definition != NULL) {
DefinitionMgrClass::Unregister_Definition (definition);
preset->Set_Definition (NULL);
SAFE_DELETE (definition);
}
//
// Free the preset
//
SAFE_DELETE (preset);
}
}
//
// Save the temporary presets library if necessary.
//
if (save_temp_lib) {
Save_Temp_Presets ();
}
//
// Save the global presets library if necessary
//
if (was_temp == false) {
Save_Global_Presets (class_id);
if (PresetMgrClass::Get_Immediate_Check_In_Mode ()) {
PresetMgrClass::Check_In_Presets ();
} else {
PresetMgrClass::Set_Presets_Dirty ();
}
}
m_TreeCtrl.DeleteItem (current_item);
::Refresh_Main_View ();
}
}
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Sort_Nodes
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Sort_Nodes (HTREEITEM root_item, bool recursive)
{
for ( HTREEITEM tree_item = m_TreeCtrl.GetChildItem (root_item);
tree_item != NULL;
tree_item = m_TreeCtrl.GetNextSiblingItem (tree_item))
{
//
// Sort the children
//
m_TreeCtrl.SortChildren (tree_item);
//
// Recurse through the hierarchy
//
if (recursive && m_TreeCtrl.ItemHasChildren (tree_item)) {
Sort_Nodes (tree_item);
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Create_Preset
//
////////////////////////////////////////////////////////////////////////////
PresetClass *
PresetsFormClass::Create_Preset (DefinitionFactoryClass *factory, bool is_temp)
{
//
// Create a new definition for the preset
//
DefinitionClass *definition = factory->Create ();
//
// Assign 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 ()));
}
//
// Create the new preset
//
PresetClass *new_preset = new PresetClass;
new_preset->Set_Definition (definition);
new_preset->Set_IsTemporary (is_temp);
return new_preset;
}
////////////////////////////////////////////////////////////////////////////
//
// Build_Child_List
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Build_Child_List
(
HTREEITEM parent_item,
DynamicVectorClass<HTREEITEM> & list
)
{
//
// Loop over all the immediate children
//
for ( HTREEITEM child_item = m_TreeCtrl.GetChildItem (parent_item);
child_item != NULL;
child_item = m_TreeCtrl.GetNextSiblingItem (child_item))
{
list.Add (child_item);
if (m_TreeCtrl.ItemHasChildren (child_item)) {
//
// Recursively call this method for all sub-folders in this tree
//
Build_Child_List (child_item, list);
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Enable_Button
//
////////////////////////////////////////////////////////////////////////////
bool
PresetsFormClass::Enable_Button (int cmd_id)
{
bool retval = false;
HTREEITEM current_item = m_TreeCtrl.GetSelectedItem ();
if (current_item != NULL) {
PresetClass *preset = Get_Item_Preset (current_item);
DefinitionFactoryClass *factory = Get_Item_Factory (current_item);
bool read_only = ::Get_File_Mgr()->Is_VSS_Read_Only ();
bool temp = (preset != NULL && preset->Get_IsTemporary ()) ? true : false;
bool is_proxy_test_folder = false;
//
// Determine if this is the proxy-test folder or not (special rules
// apply to this folder).
//
if (preset != NULL) {
is_proxy_test_folder = preset->Is_A_Parent (PROXY_TESTS_FOLDER);
}
//
// Change the read_only state depending on the user class
//
if (read_only == false && ::Get_File_Mgr ()->Is_Special_User ()) {
read_only = true;
if (preset != NULL) {
if (preset->Is_A_Parent (SPECIAL_USER_FOLDER)) {
read_only = false;
//
// Don't let special users modify the folder itself (just sub-folders)
//
if ( ::lstrcmpi (preset->Get_Name (), SPECIAL_USER_FOLDER) == 0 &&
(cmd_id == IDC_MODIFY || cmd_id == IDC_DELETE))
{
read_only = true;
}
}
}
}
//
// What operation is this?
//
switch (cmd_id)
{
case IDC_ADD:
retval = ((preset || factory) && !read_only && !temp && !is_proxy_test_folder);
break;
case IDC_ADD_TEMP:
retval = (preset || factory);
break;
case IDC_MAKE:
retval = (preset != NULL);
break;
case IDC_MODIFY:
retval = (preset && (!read_only || temp));
break;
case IDC_DELETE:
retval = (preset && (!read_only || temp));
break;
case IDC_PLAY:
retval = (preset != NULL && preset->Is_Valid_Sound_Preset ()) ? true : false;
break;
case IDC_UPDATE_VSS:
retval = ((preset != NULL) && !read_only);
break;
case IDC_INFO:
retval = (preset != NULL);
break;
case IDC_CONVERT:
retval = ((preset != NULL) && temp && !read_only && !is_proxy_test_folder);
if ( preset != NULL &&
preset->Get_Parent () != NULL &&
preset->Get_Parent ()->Get_IsTemporary ())
{
retval = false;
}
break;
case IDM_BATCH_IMPORT_TERRAIN:
{
if (preset != NULL && preset->Get_Class_ID () == CLASSID_TERRAIN) {
retval = true;
}
}
break;
case IDM_CLEAR_EMBEDDED_NODE_LIST:
{
retval = (preset && (!read_only || temp));
if (preset != NULL && preset->Get_Node_List ().Count () == 0) {
retval = false;
}
}
break;
case IDM_UPDATE_EMBEDDED_NODE_LIST:
retval = (preset && (!read_only || temp));
//
// Only allow this option for terrain and tile presets
//
if (preset != NULL) {
if ( preset->Get_Class_ID () != CLASSID_TERRAIN &&
preset->Get_Class_ID () != CLASSID_TILE)
{
retval = false;
}
}
break;
}
}
return retval;
}
////////////////////////////////////////////////////////////////////////////
//
// OnSelchangedPresetsTree
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnSelchangedPresetsTree (NMHDR *pNMHDR, LRESULT *pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
(*pResult) = 0;
//
// Enable/disable the toolbar buttons
//
m_Toolbar.Enable_Button (IDC_ADD, Enable_Button (IDC_ADD));
m_Toolbar.Enable_Button (IDC_ADD_TEMP, Enable_Button (IDC_ADD_TEMP));
m_Toolbar.Enable_Button (IDC_MAKE, Enable_Button (IDC_MAKE));
m_Toolbar.Enable_Button (IDC_MODIFY, Enable_Button (IDC_MODIFY));
m_Toolbar.Enable_Button (IDC_DELETE, Enable_Button (IDC_DELETE));
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Propagate_Changes
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Propagate_Changes
(
HTREEITEM modified_item,
DERIVED_PARAM_LIST & list
)
{
CWaitCursor wait_cursor;
CLevelEditView::Allow_Repaint (false);
PresetClass *preset = Get_Item_Preset (modified_item);
DefinitionClass *definition = preset->Get_Definition ();
//
// Loop over the list of derived parameters that need to
// be updated with the new values.
//
for (int index = 0; index < list.Count (); index ++) {
DERIVED_PARAM_INFO &info = list[index];
//
// Copy all the inherited parameter values from the parent preset
//
int list_count = info.base_param_list.Count ();
for (int list_index = 0; list_index < list_count; list_index ++) {
//int param_index = info.inherited_param_list[list_index];
ParameterClass *parameter = info.base_param_list[list_index];
ParameterClass *curr_parameter = info.derived_param_list[list_index];
ASSERT (parameter != NULL);
ASSERT (curr_parameter != NULL);
//
// Copy the parameter value from the parent.
//
curr_parameter->Copy_Value (*parameter);
//
// Release the parameter pointers
//
//definition->Unlock_Parameter (param_index);
//curr_definition->Unlock_Parameter (param_index);
}
//
// Now reload any nodes in the scene that refer to the
// changed preset.
//
if (info.preset != NULL) {
NodeMgrClass::Reload_Nodes (info.preset);
}
}
//
// Now reload any nodes in the scene that refer to the
// changed preset.
//
NodeMgrClass::Reload_Nodes (preset);
CLevelEditView::Allow_Repaint (true);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Compare_Derived_Parameters
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Compare_Derived_Parameters
(
PresetClass * curr_preset,
DefinitionClass * base_def,
DefinitionClass * derived_def,
DERIVED_PARAM_LIST & list
)
{
DERIVED_PARAM_INFO info;
info.preset = curr_preset;
//
// Compare all the parameters with this derived definition to
// find any that are not overridden.
//
int param_count = base_def->Get_Parameter_Count ();
for (int param_index = 0; param_index < param_count; param_index ++) {
ParameterClass *parameter = base_def->Lock_Parameter (param_index);
ParameterClass *curr_parameter = derived_def->Lock_Parameter (param_index);
ASSERT (parameter != NULL);
ASSERT (curr_parameter != NULL);
//
// If the parameter values are exactly the same, then
// we will assume this parameter is derived and not overridden
//
if (*curr_parameter == *parameter) {
info.base_param_list.Add (parameter);
info.derived_param_list.Add (curr_parameter);
} else if (parameter->Get_Type () == ParameterClass::TYPE_MODELDEFINITIONID) {
//
// Lookup the definitions that these parameters reference
//
int base_id = ((ModelDefParameterClass *)parameter)->Get_Value ();
int derived_id = ((ModelDefParameterClass *)curr_parameter)->Get_Value ();
DefinitionClass *base_model_def = DefinitionMgrClass::Find_Definition (base_id, false);
DefinitionClass *derived_model_def = DefinitionMgrClass::Find_Definition (derived_id, false);
//
// Recursively add parameters from these definitions to the list
//
if ( base_model_def != NULL && derived_model_def != NULL &&
base_model_def->Get_Class_ID () == derived_model_def->Get_Class_ID ())
{
Compare_Derived_Parameters (NULL, base_model_def, derived_model_def, list);
}
}
//
// Release the parameter pointers
//
base_def->Unlock_Parameter (param_index);
derived_def->Unlock_Parameter (param_index);
}
//
// If this preset contains at least one derived (not overridden) value,
// then add it to the list.
//
if (info.base_param_list.Count () > 0) {
list.Add (info);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Build_Inherited_Param_List
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Build_Inherited_Param_List
(
HTREEITEM parent_item,
DERIVED_PARAM_LIST & list
)
{
PresetClass *preset = Get_Item_Preset (parent_item);
DefinitionClass *definition = preset->Get_Definition ();
//
// Build a list of children (derived presets)
//
DynamicVectorClass<HTREEITEM> child_list;
Build_Child_List (parent_item, child_list);
//
// Loop over all the derived presets and build up the list
// of non-overridden parameter values
//
for (int index = 0; index < child_list.Count (); index ++) {
HTREEITEM tree_item = child_list[index];
PresetClass *curr_preset = Get_Item_Preset (tree_item);
DefinitionClass *curr_definition = curr_preset->Get_Definition ();
ASSERT (curr_definition->Get_Class_ID () == definition->Get_Class_ID ());
//
// Build the list of parameters that are the same as the base
//
Compare_Derived_Parameters (curr_preset, definition, curr_definition, list);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnPlay
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnPlay (void)
{
HTREEITEM tree_item = m_TreeCtrl.GetSelectedItem ();
PresetClass *preset = Get_Item_Preset (tree_item);
if (preset != NULL && preset->Get_Definition () != NULL) {
AudibleSoundDefinitionClass *definition = NULL;
definition = (AudibleSoundDefinitionClass *)preset->Get_Definition ();
//
// Make sure we have a local copy of this sound
//
CString filename = definition->Get_Filename ();
if (::Get_File_Mgr ()->Does_File_Exist (filename, true)) {
//
// Pass the sound filename onto the dialog
//
PlaySoundDialogClass dialog (filename, this);
dialog.DoModal ();
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnInfo
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnInfo (void)
{
HTREEITEM current_item = m_TreeCtrl.GetSelectedItem ();
PresetClass *preset = Get_Item_Preset (current_item);
if (preset != NULL) {
//
// Show the (read-only) properties dialog for this preset
//
preset->Show_Properties (true);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnExtra
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnExtra (void)
{
//
// Determine the screen coords of the toolbar button
//
CRect rect;
m_Toolbar.GetItemRect (m_Toolbar.CommandToIndex (IDC_EXTRA), &rect);
m_Toolbar.ClientToScreen (&rect);
//
// Load the menu we want to display
//
HMENU main_menu = ::LoadMenu (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDR_XTRA_POPUP));
HMENU menu = ::GetSubMenu (main_menu, 0);
//
// Make the menu commands owner-draw so we can paint icons next to them
//
::ModifyMenu (menu, IDC_PLAY, MF_BYCOMMAND | MF_OWNERDRAW, IDC_PLAY, NULL);
::ModifyMenu (menu, IDC_CONVERT, MF_BYCOMMAND | MF_OWNERDRAW, IDC_CONVERT, NULL);
::ModifyMenu (menu, IDC_UPDATE_VSS, MF_BYCOMMAND | MF_OWNERDRAW, IDC_UPDATE_VSS, NULL);
::ModifyMenu (menu, IDM_BATCH_IMPORT_TERRAIN, MF_BYCOMMAND | MF_OWNERDRAW, IDM_BATCH_IMPORT_TERRAIN, NULL);
::ModifyMenu (menu, IDM_UPDATE_EMBEDDED_NODE_LIST, MF_BYCOMMAND | MF_OWNERDRAW, IDM_UPDATE_EMBEDDED_NODE_LIST, NULL);
::ModifyMenu (menu, IDM_CLEAR_EMBEDDED_NODE_LIST, MF_BYCOMMAND | MF_OWNERDRAW, IDM_CLEAR_EMBEDDED_NODE_LIST, NULL);
//
// Disable any buttons if necessary
//
if (Enable_Button (IDC_PLAY) == false) {
::EnableMenuItem (menu, IDC_PLAY, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
}
if (Enable_Button (IDC_CONVERT) == false) {
::EnableMenuItem (menu, IDC_CONVERT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
}
if (Enable_Button (IDC_UPDATE_VSS) == false) {
::EnableMenuItem (menu, IDC_UPDATE_VSS, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
}
if (Enable_Button (IDM_BATCH_IMPORT_TERRAIN) == false) {
::EnableMenuItem (menu, IDM_BATCH_IMPORT_TERRAIN, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
}
if (Enable_Button (IDM_UPDATE_EMBEDDED_NODE_LIST) == false) {
::EnableMenuItem (menu, IDM_UPDATE_EMBEDDED_NODE_LIST, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
}
if (Enable_Button (IDM_CLEAR_EMBEDDED_NODE_LIST) == false) {
::EnableMenuItem (menu, IDM_CLEAR_EMBEDDED_NODE_LIST, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
}
//
// Display the menu
//
::TrackPopupMenu (menu, TPM_LEFTALIGN | TPM_TOPALIGN, rect.left, rect.bottom, 0, m_hWnd, NULL);
//
// Cleanup
//
::DestroyMenu (main_menu);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnNotify
//
////////////////////////////////////////////////////////////////////////////
BOOL
PresetsFormClass::OnNotify
(
WPARAM wParam,
LPARAM lParam,
LRESULT* pResult
)
{
if (((NMHDR *)lParam)->code == TBN_DROPDOWN) {
OnExtra ();
(*pResult) = TBDDRET_DEFAULT;
return TRUE;
}
return CDialog::OnNotify(wParam, lParam, pResult);
}
////////////////////////////////////////////////////////////////////////////
//
// OnUpdateConvert
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnUpdateConvert (CCmdUI *pCmdUI)
{
pCmdUI->Enable (Enable_Button (IDC_CONVERT));
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnUpdateInfo
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnUpdateInfo (CCmdUI *pCmdUI)
{
pCmdUI->Enable (Enable_Button (IDC_INFO));
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnUpdatePlay
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnUpdatePlay (CCmdUI *pCmdUI)
{
pCmdUI->Enable (Enable_Button (IDC_PLAY));
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnUpdateUpdateVss
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnUpdateUpdateVss (CCmdUI *pCmdUI)
{
pCmdUI->Enable (Enable_Button (IDC_UPDATE_VSS));
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Menu_Text
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Get_Menu_Text (int menu_id, CString &text)
{
switch (menu_id)
{
case IDC_PLAY:
text = "Play...";
break;
case IDC_CONVERT:
text = "Convert Temp...";
break;
case IDC_UPDATE_VSS:
text = "Update VSS...";
break;
case IDM_BATCH_IMPORT_TERRAIN:
text = "Batch Import Terrain...";
break;
case IDM_CLEAR_EMBEDDED_NODE_LIST:
text = "Clear Embedded Node List";
break;
case IDM_UPDATE_EMBEDDED_NODE_LIST:
text = "Embed Nodes...";
break;
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnDrawItem
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnDrawItem
(
int nIDCtl,
LPDRAWITEMSTRUCT lpDrawItemStruct
)
{
HICON icon = NULL;
CString text;
Get_Menu_Text (lpDrawItemStruct->itemID, text);
switch (lpDrawItemStruct->itemID)
{
case IDC_PLAY:
icon = (HICON)::LoadImage (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_PLAY), IMAGE_ICON, 16, 16, LR_SHARED);
break;
case IDC_CONVERT:
icon = (HICON)::LoadImage (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_CONVERT), IMAGE_ICON, 16, 16, LR_SHARED);
break;
case IDC_UPDATE_VSS:
icon = (HICON)::LoadImage (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_UPDATE), IMAGE_ICON, 16, 16, LR_SHARED);
break;
case IDM_BATCH_IMPORT_TERRAIN:
icon = (HICON)::LoadImage (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_TERRAIN), IMAGE_ICON, 16, 16, LR_SHARED);
break;
case IDM_UPDATE_EMBEDDED_NODE_LIST:
icon = (HICON)::LoadImage (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_OBJECT), IMAGE_ICON, 16, 16, LR_SHARED);
break;
case IDM_CLEAR_EMBEDDED_NODE_LIST:
icon = (HICON)::LoadImage (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_DELETE), IMAGE_ICON, 16, 16, LR_SHARED);
break;
}
CRect rect = lpDrawItemStruct->rcItem;
int dss_state = DSS_NORMAL;
UINT bk_color = 0;
//
// Deteremine what background and text color to use
//
if (lpDrawItemStruct->itemState & ODS_GRAYED) {
bk_color = COLOR_MENU;
::SetBkColor (lpDrawItemStruct->hDC, ::GetSysColor (COLOR_MENU));
::SetTextColor (lpDrawItemStruct->hDC, ::GetSysColor (COLOR_GRAYTEXT));
dss_state = DSS_DISABLED;
} else if (lpDrawItemStruct->itemState & ODS_SELECTED) {
bk_color = COLOR_HIGHLIGHT;
::SetBkColor (lpDrawItemStruct->hDC, ::GetSysColor (COLOR_HIGHLIGHT));
::SetTextColor (lpDrawItemStruct->hDC, ::GetSysColor (COLOR_HIGHLIGHTTEXT));
} else {
bk_color = COLOR_MENU;
::SetBkColor (lpDrawItemStruct->hDC, ::GetSysColor (COLOR_MENU));
::SetTextColor (lpDrawItemStruct->hDC, ::GetSysColor (COLOR_MENUTEXT));
}
//
// Determine the height of the text
//
CSize text_size;
::GetTextExtentPoint32 (lpDrawItemStruct->hDC, text, text.GetLength (), &text_size);
//
// Render the text
//
rect.top += 2;
rect.bottom -= 2;
::FillRect (lpDrawItemStruct->hDC, &rect, (HBRUSH) (bk_color+1));
::SetBkMode (lpDrawItemStruct->hDC, TRANSPARENT);
::DrawState ( lpDrawItemStruct->hDC,
NULL,
NULL,
(LPARAM)(LPCTSTR)text,
0,
rect.left + 24,
rect.top + (rect.Height () >> 1) - (text_size.cy >> 1),
0, 0, DST_TEXT | dss_state);
//
// Draw the associated icon (if necessary)
//
if (icon != NULL) {
::DrawState ( lpDrawItemStruct->hDC, NULL, NULL, (LPARAM)icon, 0, rect.left + 4, rect.top + 4, 16, 16, DST_ICON | dss_state);
}
CDialog::OnDrawItem (nIDCtl, lpDrawItemStruct);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnMeasureItem
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnMeasureItem
(
int nIDCtl,
LPMEASUREITEMSTRUCT lpMeasureItemStruct
)
{
CString text;
Get_Menu_Text (lpMeasureItemStruct->itemID, text);
NONCLIENTMETRICS metrics = { sizeof (NONCLIENTMETRICS), 0 };
::SystemParametersInfo (SPI_GETNONCLIENTMETRICS, 0, &metrics, FALSE);
HDC mem_dc = ::CreateCompatibleDC (NULL);
HFONT font = ::CreateFontIndirect (&metrics.lfMenuFont);
HFONT old_font = (HFONT)::SelectObject (mem_dc, font);
CSize text_size;
::GetTextExtentPoint32 (mem_dc, text, text.GetLength (), &text_size);
::SelectObject (mem_dc, old_font);
::DeleteObject (font);
::DeleteDC (mem_dc);
lpMeasureItemStruct->itemWidth = text_size.cx + 24;
lpMeasureItemStruct->itemHeight = 24;
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnConvert
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnConvert (void)
{
HTREEITEM item = m_TreeCtrl.GetSelectedItem ();
PresetClass *preset = Get_Item_Preset (item);
if (preset != NULL) {
//
// Make sure the user really wants to do this...
//
CString message;
message.Format ("Are you sure you wish to convert '%s' from a temporary preset to a shared preset?", preset->Get_Name ());
if (MessageBox (message, "Preset Convert", MB_ICONQUESTION | MB_YESNO) == IDYES) {
CWaitCursor wait_cursor;
//
// Check out the definition database
//
SelectionCaptureClass sel_capture (this);
bool undo_check_out = false;
uint32 class_id = preset->Get_Class_ID ();
if (PresetMgrClass::Check_Out_Database (class_id, &undo_check_out)) {
sel_capture.Restore ();
item = m_TreeCtrl.GetSelectedItem ();
PresetClass *preset = Get_Item_Preset (item);
if (preset != NULL) {
//
// Change the preset's ID from temp-range to normal-range
//
preset->Set_IsTemporary (false);
preset->Set_ID (DefinitionMgrClass::Get_New_ID (preset->Get_Class_ID ()));
//
// Now change the IDs of any embedded definition objects
//
Fix_Embedded_Definition_IDs (preset->Get_Definition ());
//
// Now save-out the databases (they have both changed)
//
Save_Global_Presets (class_id);
PresetMgrClass::Add_Dirty_Preset (preset->Get_ID ());
Save_Temp_Presets ();
//
// Finally change the preset's icon
//
int icon = Get_Icon (preset);
m_TreeCtrl.SetItemImage (item, icon, icon);
//
// Force a re-paint
//
m_TreeCtrl.SelectItem (item);
m_TreeCtrl.InvalidateRect (NULL, TRUE);
} else if (undo_check_out) {
MessageBox ("Unable to find preset.", "Preset Error", MB_ICONERROR | MB_OK);
PresetMgrClass::Undo_Database_Check_Out (class_id);
}
}
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnUpdateVss
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnUpdateVss (void)
{
HTREEITEM item = m_TreeCtrl.GetSelectedItem ();
PresetClass *preset = Get_Item_Preset (item);
if (preset != NULL) {
//
// Show the update-preset dialog
//
UpdatePresetDialogClass dialog (preset, this);
dialog.DoModal ();
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnClearEmbeddedNodeList
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnClearEmbeddedNodeList (void)
{
CWaitCursor wait_cursor;
//
// Get the currently selected preset
//
HTREEITEM current_item = m_TreeCtrl.GetSelectedItem ();
PresetClass *preset = Get_Item_Preset (current_item);
if (preset != NULL) {
if (preset->Get_IsTemporary () == false) {
//
// Check out the definition database
//
SelectionCaptureClass sel_capture (this);
bool undo_on_err = false;
uint32 class_id = preset->Get_Class_ID ();
if (PresetMgrClass::Check_Out_Database (class_id, &undo_on_err)) {
sel_capture.Restore ();
//
// Re-get the preset (its pointer has changed, the
// old one is crap).
//
current_item = m_TreeCtrl.GetSelectedItem ();
preset = Get_Item_Preset (current_item);
//
// Now, free the embedded nodes
//
if (preset != NULL) {
preset->Free_Node_List ();
Save_Global_Presets (preset->Get_Class_ID ());
PresetMgrClass::Add_Dirty_Preset (preset->Get_ID ());
}
}
} else {
//
// Free the embedded nodes
//
preset->Free_Node_List ();
Save_Temp_Presets ();
}
Reset_Embedded_Node_Instances (preset);
NodeMgrClass::Reload_Nodes (preset);
if (preset != NULL) {
//
// Update the overlay icon on the preset
//
bool needs_overlay = (preset->Get_Node_List ().Count () > 0);
TreeView_SetOverlay (m_TreeCtrl, current_item, needs_overlay);
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Reset_Embedded_Node_Instances
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Reset_Embedded_Node_Instances (PresetClass *preset)
{
if (preset == NULL) {
return ;
}
//
// Loop over all the nodes in the scene
//
for ( NodeClass *node = NodeMgrClass::Get_First ();
node != NULL;
node = NodeMgrClass::Get_Next (node))
{
//
// If this was an embedded node, then convert it to
// a "normal" node.
//
if (node->Get_Container_Preset_ID () == preset->Get_ID ()) {
node->Set_Is_Proxied (false);
node->Set_Needs_Save (true);
node->Set_Container_Preset_ID (0);
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnBuildEmbedNodeList
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnBuildEmbedNodeList (void)
{
//
// Prompt the user
//
if (::MessageBox (m_hWnd,
"This operation will embed a copy of all the nodes in scene into this preset. Are you sure you wish to continue?",
"Embed Nodes", MB_ICONQUESTION | MB_YESNO) == IDNO)
{
return ;
}
CWaitCursor wait_cursor;
//
// Get the currently selected preset
//
HTREEITEM current_item = m_TreeCtrl.GetSelectedItem ();
PresetClass *preset = Get_Item_Preset (current_item);
if (preset != NULL) {
if (preset->Get_IsTemporary () == false) {
//
// Check out the definition database
//
SelectionCaptureClass sel_capture (this);
bool undo_on_err = false;
uint32 class_id = preset->Get_Class_ID ();
if (PresetMgrClass::Check_Out_Database (class_id, &undo_on_err)) {
sel_capture.Restore ();
//
// Re-get the preset (its pointer has changed, the
// old one is crap).
//
current_item = m_TreeCtrl.GetSelectedItem ();
preset = Get_Item_Preset (current_item);
//
// Now, update the embedded node information for this preset
//
if (preset != NULL) {
Update_Embedded_Nodes (preset);
Save_Global_Presets (preset->Get_Class_ID ());
PresetMgrClass::Add_Dirty_Preset (preset->Get_ID ());
}
}
} else {
//
// Update the embedded node information for this preset
//
Update_Embedded_Nodes (preset);
Save_Temp_Presets ();
}
NodeMgrClass::Reload_Nodes (preset);
//
// Update the overlay icon on the preset
//
if (preset != NULL) {
bool needs_overlay = (preset->Get_Node_List ().Count () > 0);
TreeView_SetOverlay (m_TreeCtrl, current_item, needs_overlay);
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Embedded_Nodes
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Update_Embedded_Nodes (PresetClass *preset)
{
Reset_Embedded_Node_Instances (preset);
//
// Loop over all the nodes in the scene
//
for ( NodeClass *node = NodeMgrClass::Get_First ();
node != NULL;
node = NodeMgrClass::Get_Next (node))
{
//
// Just find the first node that came from this preset
//
if (node->Get_Preset () == preset) {
break;
}
}
//
// Generate the node list
//
if (node != NULL) {
preset->Build_Node_List (node);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnBatchImportTerrain
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnBatchImportTerrain (void)
{
CFileDialog dialog ( TRUE,
".w3d",
NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT | OFN_EXPLORER,
"Westwood 3D Files (*.w3d)|*.w3d||",
this);
TCHAR filename_list[MAX_PATH*20] = { 0 };
dialog.m_ofn.lpstrFile = filename_list;
dialog.m_ofn.nMaxFile = sizeof (filename_list);
//
// Ask the user what files they wish to import
//
if (dialog.DoModal () == IDOK) {
//
// Loop through all the selected files
//
POSITION pos = dialog.GetStartPosition ();
while (pos != NULL) {
//
// Add this preset to the tree
//
Add_Terrain_Preset (dialog.GetNextPathName (pos));
}
//
// Save the temp presets lib
//
Save_Temp_Presets ();
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnUpdateClearEmbeddedNodeList
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnUpdateClearEmbeddedNodeList (CCmdUI *pCmdUI)
{
pCmdUI->Enable (Enable_Button (IDM_CLEAR_EMBEDDED_NODE_LIST));
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnUpdateEmbeddedNodeList
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnUpdateEmbeddedNodeList (CCmdUI *pCmdUI)
{
pCmdUI->Enable (Enable_Button (IDM_UPDATE_EMBEDDED_NODE_LIST));
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnUpdateBatchImportTerrain
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnUpdateBatchImportTerrain (CCmdUI *pCmdUI)
{
pCmdUI->Enable (Enable_Button (IDM_BATCH_IMPORT_TERRAIN));
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Add_Terrain_Preset
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Add_Terrain_Preset (LPCTSTR filename)
{
if (::Is_W3D_Filename (filename)) {
//
// Make an asset name from the filename
//
CString preset_name = ::Asset_Name_From_Filename (filename);
if (preset_name.GetLength () > 0) {
//
// Add the new preset
//
PresetClass *preset = Add_New_Preset (preset_name, true, false);
if (preset != NULL && preset->Get_Class_ID () == CLASSID_TERRAIN) {
//
// Configure the preset
//
TerrainDefinitionClass *definition = (TerrainDefinitionClass *)preset->Get_Definition ();
definition->Set_Model_Name (::Get_File_Mgr ()->Make_Relative_Path (filename));
}
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnBegindragPresetsTree
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnBegindragPresetsTree
(
NMHDR * pNMHDR,
LRESULT *pResult
)
{
NM_TREEVIEW *tv_info = (NM_TREEVIEW *)pNMHDR;
(*pResult) = 0;
if (Is_Drag_OK (tv_info->itemNew.hItem)) {
//
// Set-up for our drag operation
//
m_DragItem = tv_info->itemNew.hItem;
if (m_DragItem != NULL) {
m_DragImageList = m_TreeCtrl.CreateDragImage (m_DragItem);
m_DragImageList->BeginDrag (0, CPoint (-20, -20));
m_IsDragging = true;
SetCapture ();
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnLButtonUp
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnLButtonUp (UINT nFlags, CPoint point)
{
if (m_IsDragging) {
//
// Convert the tab mouse-position to the tree's mouse-position
//
CPoint tree_pt = point;
ClientToScreen (&tree_pt);
m_TreeCtrl.ScreenToClient (&tree_pt);
//
// Reset the state of the tree
//
CImageList::EndDrag ();
ReleaseCapture ();
m_TreeCtrl.SelectDropTarget (NULL);
m_TreeCtrl.SelectItem (m_DragItem);
//
// Check to ensure its OK to move the preset
//
UINT flags = TVHT_ONITEM;
HTREEITEM drop_target = m_TreeCtrl.HitTest (tree_pt, &flags);
if (Is_Drop_OK (drop_target)) {
//
// Perform the move operation
//
m_TreeCtrl.SelectItem (drop_target);
Do_Drop (m_DragItem, drop_target);
}
m_DragItem = NULL;
m_IsDragging = false;
}
CDialog::OnLButtonUp (nFlags, point);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnMouseMove
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnMouseMove (UINT nFlags, CPoint point)
{
if (m_IsDragging) {
//
// Convert the tab mouse-position to the tree's mouse-position
//
CPoint tree_pt = point;
ClientToScreen (&tree_pt);
m_TreeCtrl.ScreenToClient (&tree_pt);
//
// Draw the outline of the drag operation
//
CImageList::DragMove (tree_pt);
m_DragImageList->DragLeave (&m_TreeCtrl);
//
// Determine if we should hilight one of the entries in the tree control
//
UINT flags = TVHT_ONITEM;
HTREEITEM drop_target = m_TreeCtrl.HitTest (tree_pt, &flags);
if (drop_target != NULL) {
m_TreeCtrl.SelectDropTarget (drop_target);
}
m_DragImageList->DragEnter (&m_TreeCtrl, tree_pt);
//
// Choose a cursor
//
if (drop_target == NULL || Is_Drop_OK (drop_target) == false) {
SetCursor (::LoadCursor (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDC_NODROP)));
} else {
SetCursor (::LoadCursor (NULL, IDC_ARROW));
}
}
CDialog::OnMouseMove (nFlags, point);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Is_Drag_OK
//
////////////////////////////////////////////////////////////////////////////
bool
PresetsFormClass::Is_Drag_OK (HTREEITEM drag_item)
{
bool retval = false;
PresetClass *preset = Get_Item_Preset (drag_item);
bool read_only = ::Get_File_Mgr()->Is_VSS_Read_Only ();
bool temp = (preset != NULL && preset->Get_IsTemporary ()) ? true : false;
//
// We allow the user to drag a preset if its a temp or they have write
// access to the database.
//
if (preset != NULL && (read_only == false || temp == true)) {
retval = true;
}
return retval;
}
////////////////////////////////////////////////////////////////////////////
//
// Is_Drop_OK
//
////////////////////////////////////////////////////////////////////////////
bool
PresetsFormClass::Is_Drop_OK (HTREEITEM drop_item)
{
bool retval = false;
if (m_DragItem != NULL && drop_item != NULL) {
PresetClass *drag_preset = Get_Item_Preset (m_DragItem);
PresetClass *drop_preset = Get_Item_Preset (drop_item);
DefinitionFactoryClass *factory = Get_Item_Factory (drop_item);
if (drag_preset != NULL && (drop_preset != NULL || factory != NULL)) {
//
// Check to make sure we don't try to move a preset to one of its children
//
if (drop_preset == NULL || drop_preset->Is_A_Parent (drag_preset) == false) {
//
// Get information about what 'type' of presets these are
//
int drag_classid = drag_preset->Get_Class_ID ();
int drop_classid = 0;
if (drop_preset != NULL) {
drop_classid = drop_preset->Get_Class_ID ();
} else {
drop_classid = factory->Get_Class_ID ();
}
//
// Are the preset's factories the same?
//
if (drag_classid == drop_classid) {
bool is_drop_temp = (drop_preset != NULL && drop_preset->Get_IsTemporary ()) ? true : false;
bool is_drag_temp = (drag_preset != NULL && drag_preset->Get_IsTemporary ()) ? true : false;
//
// We allow the drop if the target is a factory, or both the drag and drops are non-temp
//
if (factory != NULL || is_drag_temp || is_drop_temp == false) {
retval = true;
}
}
}
}
}
return retval;
}
////////////////////////////////////////////////////////////////////////////
//
// Do_Drop
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Do_Drop (HTREEITEM drag_item, HTREEITEM drop_item)
{
CWaitCursor wait_cursor;
PresetClass *drag_preset = Get_Item_Preset (drag_item);
bool is_drag_temp = (drag_preset != NULL && drag_preset->Get_IsTemporary ()) ? true : false;
//
// Does this operation affect only shared presets or only temps?
//
if (is_drag_temp == false) {
uint32 drag_preset_id = drag_preset->Get_Definition ()->Get_ID ();
//
// Check out the definition database
//
SelectionCaptureClass sel_capture (this);
bool undo_on_err = false;
uint32 class_id = drag_preset->Get_Class_ID ();
if (PresetMgrClass::Check_Out_Database (class_id, &undo_on_err)) {
sel_capture.Restore ();
//
// Look-up the preset tree items
//
drag_item = Find_Preset (TVI_ROOT, drag_preset_id);
drop_item = m_TreeCtrl.GetSelectedItem ();
drag_preset = Get_Item_Preset (drag_item);
//
// Are the drag and drop locations still valid?
//
if ( drag_preset != NULL &&
drag_preset->Get_Definition ()->Get_ID () == drag_preset_id &&
drag_item != NULL && drop_item != NULL && drag_item != drop_item)
{
//
// Perform the operation and save the presets...
//
Move_Preset (drag_item, drop_item);
Save_Global_Presets (class_id);
PresetMgrClass::Add_Dirty_Preset (drag_preset->Get_ID ());
} else {
//
// Inform the user that something has changed...
//
::MessageBox ( NULL,
"Either the drag source or the drop target no longer exists, please try again.",
"Drag/Drop Error",
MB_OK | MB_ICONERROR);
if (undo_on_err) {
PresetMgrClass::Undo_Database_Check_Out (class_id);
}
}
}
} else {
//
// Simply move the preset and save the temp library
//
Move_Preset (drag_item, drop_item);
if (drag_preset != NULL) {
Save_Temp_Presets ();
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Move_Preset
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Move_Preset (HTREEITEM preset_item, HTREEITEM parent_item)
{
ASSERT (preset_item != NULL);
ASSERT (parent_item != NULL);
PresetClass *preset = Get_Item_Preset (preset_item);
if (preset != NULL) {
//
// Let the preset know who its new parent is
//
PresetClass *parent_preset = Get_Item_Preset (parent_item);
preset->Set_Parent (parent_preset);
if (parent_preset != NULL) {
parent_preset->Add_Child_Preset (preset->Get_ID ());
}
//
// Make a log entry about the new parent
//
if (preset->Get_IsTemporary () == false) {
//
// Get the name of the new parent
//
const char *parent_name = NULL;
if (parent_preset != NULL) {
parent_name = parent_preset->Get_Name ();
}
//
// Log the operation
//
PresetLoggerClass::Log_Moved (preset, parent_name);
}
//
// Move the tree item (and all its children)
//
m_TreeCtrl.SetRedraw (false);
Copy_Preset_Items (preset_item, parent_item);
m_TreeCtrl.DeleteItem (preset_item);
m_TreeCtrl.SetRedraw (true);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Copy_Preset_Items
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Copy_Preset_Items (HTREEITEM preset_item, HTREEITEM parent_item)
{
//
// Copy the preset to its new parent
//
PresetClass *preset = Get_Item_Preset (preset_item);
HTREEITEM new_item = Insert_Preset (parent_item, preset);
//
// Recursive copy all child items
//
for ( HTREEITEM child_item = m_TreeCtrl.GetChildItem (preset_item);
child_item != NULL;
child_item = m_TreeCtrl.GetNextSiblingItem (child_item))
{
Copy_Preset_Items (child_item, new_item);
}
// Ensure the entries are sorted correctly
m_TreeCtrl.SortChildren (parent_item);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// OnDestroy
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::OnDestroy (void)
{
::RemoveProp (m_TreeCtrl, "TRANS_ACCS");
::RemoveProp (m_hWnd, "TRANS_ACCS");
CDialog::OnDestroy ();
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Export_File_Dependencies
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Export_File_Dependencies (const char *filename)
{
//
// Create the file
//
TextFileClass file (filename);
if (file.Open (RawFileClass::WRITE)) {
//
// Build a list of all the entries in the tree
//
DynamicVectorClass<HTREEITEM> entry_list;
Build_Child_List (TVI_ROOT, entry_list);
//
// Loop over all the presets in the list
//
for (int index = 0; index < entry_list.Count (); index ++) {
PresetClass *preset = Get_Item_Preset (entry_list[index]);
if (preset != NULL) {
DefinitionClass *definition = preset->Get_Definition ();
if (definition != NULL) {
//
// Generate the list of file's that this preset is dependent on
//
DynamicVectorClass<StringClass> file_list;
Build_File_Dependencies_For_Definition (file_list, definition);
//
// If the list wasn't empty, then export the filenames to the text file.
//
if (file_list.Count () > 0) {
//
// Start the entry off with the name of the preset
//
StringClass entry;
entry.Format ("%s\t", (const char *)definition->Get_Name ());
//
// Now, spit out the list of files
//
for (int index = 0; index < file_list.Count (); index ++) {
entry += file_list[index];
entry += "\t";
}
//
// Add the entry to the text file
//
file.Write_Line (entry);
}
}
}
}
//
// Close the file
//
file.Close ();
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Build_File_Dependencies_For_Definition
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Build_File_Dependencies_For_Definition
(
DynamicVectorClass<StringClass> & file_list,
DefinitionClass * definition
)
{
//
// Loop over all the parameters of this definition
//
int count = definition->Get_Parameter_Count ();
for (int index = 0; index < count; index ++) {
ParameterClass *parameter = definition->Lock_Parameter (index);
//
// Handle the different file types
//
if (parameter->Is_Type (ParameterClass::TYPE_FILENAME)) {
FilenameParameterClass *filename_param = reinterpret_cast<FilenameParameterClass *> (parameter);
//
// Add the filename to the list if its not empty
//
StringClass filename = filename_param->Get_String ();
if (filename.Get_Length () > 0) {
file_list.Add (filename);
}
} else if (parameter->Get_Type () == ParameterClass::TYPE_MODELDEFINITIONID) {
int def_id = ((ModelDefParameterClass *)parameter)->Get_Value ();
//
// Recurse into the model's definition (if necessary)
//
DefinitionClass *model_definition = DefinitionMgrClass::Find_Definition (def_id, false);
if (model_definition != NULL) {
Build_File_Dependencies_For_Definition (file_list, model_definition);
}
} else if (parameter->Get_Type () == ParameterClass::TYPE_PHYSDEFINITIONID) {
int def_id = ((PhysDefParameterClass *)parameter)->Get_Value ();
//
// Recurse into the physic object's definition (if necessary)
//
DefinitionClass *phys_definition = DefinitionMgrClass::Find_Definition (def_id, false);
if (phys_definition != NULL) {
Build_File_Dependencies_For_Definition (file_list, phys_definition);
}
}
definition->Unlock_Parameter (index);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Add_Preset
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Add_Preset (PresetClass *preset)
{
uint32 class_id = preset->Get_Class_ID ();
//
// Find the root item
//
HTREEITEM root_item = Find_Factory (TVI_ROOT, class_id);
if (root_item != NULL) {
//
// Add the preset to the tree
//
Insert_Preset (root_item, preset);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Sort_Items
//
////////////////////////////////////////////////////////////////////////////
void
PresetsFormClass::Sort_Items (uint32 class_id)
{
//
// Find the root item
//
HTREEITEM root_item = Find_Factory (TVI_ROOT, class_id);
if (root_item != NULL) {
//
// Sort all items under this root
//
m_TreeCtrl.SetRedraw (FALSE);
Sort_Nodes (root_item);
m_TreeCtrl.SetRedraw (TRUE);
}
return ;
}