diff --git a/source/tools/atlas/AtlasUI/ActorEditor/ActorEditor.cpp b/source/tools/atlas/AtlasUI/ActorEditor/ActorEditor.cpp index 613221ee48..2836a4cafc 100644 --- a/source/tools/atlas/AtlasUI/ActorEditor/ActorEditor.cpp +++ b/source/tools/atlas/AtlasUI/ActorEditor/ActorEditor.cpp @@ -4,9 +4,21 @@ #include "ActorEditorListCtrl.h" #include "AtlasObject/AtlasObject.h" +#include "Datafile.h" + +#include "wx/file.h" + +BEGIN_EVENT_TABLE(ActorEditor, AtlasWindow) + EVT_MENU(ID_Custom1, OnCreateEntity) +END_EVENT_TABLE() + + +static AtlasWindow::CustomMenu::CustomMenuItem menuItem1 = { _("Create &entity...") }; +static AtlasWindow::CustomMenu::CustomMenuItem* menuItems[] = { &menuItem1, NULL }; +static AtlasWindow::CustomMenu menu = { _("&Actor"), menuItems }; ActorEditor::ActorEditor(wxWindow* parent) - : AtlasWindow(parent, _("Actor Editor"), wxSize(1024, 450)) + : AtlasWindow(parent, _("Actor Editor"), wxSize(1024, 450), &menu) { wxPanel* mainPanel = new wxPanel(this); @@ -265,3 +277,89 @@ AtObj ActorEditor::ExportData() out.set("actor", actor); return out; } + + +void ActorEditor::OnCreateEntity(wxCommandEvent& WXUNUSED(event)) +{ + // Create a very basic entity for this actor. + + // The output should be an XML file like: + // + // + // + // units/celt_csw_a.xml + // + // + // 'Actor' comes from this actor's filename. + // 'Parent' comes from the filename of a user-selected entity. + // The file will be saved into a user-selected location. + + // Get the entity's expected name + wxFileName currentFilename (GetCurrentFilename()); + if (! currentFilename.IsOk()) + { + wxMessageDialog(this, _("Please save this actor before attempting to create an entity for it."), + _("Gentle reminder"), wxOK | wxICON_INFORMATION).ShowModal(); + return; + } + wxString entityName = currentFilename.GetName(); + + // Work out where the entities are stored + wxFileName entityPath (_T("../data/mods/official/entities/")); + entityPath.MakeAbsolute(Datafile::GetSystemDirectory()); + + // Make sure the user knows what's going on + static bool instructed = false; // only tell them once per session + if (! instructed) + { + instructed = true; + if (wxMessageBox(_("To create an entity, you will first be asked to choose a parent entity, and then asked where save the new entity."), + _("Usage instructions"), wxICON_INFORMATION|wxOK|wxCANCEL, this) != wxOK) + return; // cancelled by user + } + + wxString parentEntityFilename + (wxFileSelector(_("Choose a parent entity"), entityPath.GetPath(), _T(""), + _T("xml"), _("XML files (*.xml)|*.xml|All files (*.*)|*.*"), wxOPEN, this)); + + if (! parentEntityFilename.Length()) + return; // cancelled by user + + // Get the parent's name + wxString parentName (wxFileName(parentEntityFilename).GetName()); + + wxString outputEntityFilename + (wxFileSelector(_("Choose a filename to save as"), entityPath.GetPath(), entityName, + _T("xml"), _("XML files (*.xml)|*.xml|All files (*.*)|*.*"), wxSAVE|wxOVERWRITE_PROMPT, this)); + + if (! outputEntityFilename.Length()) + return; // cancelled by user + + // Get this actor's filename, relative to actors/ + wxFileName actorPath (_T("../data/mods/official/art/actors/")); + actorPath.MakeAbsolute(Datafile::GetSystemDirectory()); + wxFileName actorFilename (currentFilename); + actorFilename.MakeRelativeTo(actorPath.GetFullPath()); + + // Create the XML data to be written + // TODO: Native line endings + wxString xml = + _T("\r\n") + _T("\r\n") + _T("\r\n") + _T("\t") + actorFilename.GetFullPath(wxPATH_UNIX) + _T("\r\n") + _T("\r\n"); + + wxFile file (outputEntityFilename.fn_str(), wxFile::write); + if (! file.IsOpened()) + { + wxLogError(_("Failed to open file")); + return; + } + + if (! file.Write(xml)) + { + wxLogError(_("Failed to write XML data to file")); + return; + } +} \ No newline at end of file diff --git a/source/tools/atlas/AtlasUI/ActorEditor/ActorEditor.h b/source/tools/atlas/AtlasUI/ActorEditor/ActorEditor.h index 563adca974..4c2cde9260 100644 --- a/source/tools/atlas/AtlasUI/ActorEditor/ActorEditor.h +++ b/source/tools/atlas/AtlasUI/ActorEditor/ActorEditor.h @@ -7,6 +7,9 @@ class ActorEditor : public AtlasWindow public: ActorEditor(wxWindow* parent); +private: + void OnCreateEntity(wxCommandEvent& event); + protected: AtObj FreezeData(); void ThawData(AtObj& in); @@ -19,4 +22,6 @@ private: wxCheckBox* m_CastShadows; wxTextCtrl* m_Material; + + DECLARE_EVENT_TABLE(); }; diff --git a/source/tools/atlas/AtlasUI/ActorEditor/ActorEditorListCtrl.cpp b/source/tools/atlas/AtlasUI/ActorEditor/ActorEditorListCtrl.cpp index 7e59939d01..7bfb15797e 100644 --- a/source/tools/atlas/AtlasUI/ActorEditor/ActorEditorListCtrl.cpp +++ b/source/tools/atlas/AtlasUI/ActorEditor/ActorEditorListCtrl.cpp @@ -23,8 +23,8 @@ ActorEditorListCtrl::ActorEditorListCtrl(wxWindow* parent) AddColumnType(_("Variant"), 100, "@name", new FieldEditCtrl_Text()); AddColumnType(_("Freq"), 50, "@frequency", new FieldEditCtrl_Text()); - AddColumnType(_("Model"), 160, "mesh", new FieldEditCtrl_File(_T("art/meshes"), _("Mesh files (*.pmd)|*.pmd|All files (*.*)|*.*"))); - AddColumnType(_("Texture"), 160, "texture", new FieldEditCtrl_File(_T("art/textures/skins"), _("All files (*.*)|*.*"))); // could be dds, or tga, or png, or bmp, etc, so just allow * + AddColumnType(_("Model"), 160, "mesh", new FieldEditCtrl_File(_T("art/meshes/"), _("Mesh files (*.pmd)|*.pmd|All files (*.*)|*.*"))); + AddColumnType(_("Texture"), 160, "texture", new FieldEditCtrl_File(_T("art/textures/skins/"), _("All files (*.*)|*.*"))); // could be dds, or tga, or png, or bmp, etc, so just allow * AddColumnType(_("Animations"), 250, "animations", new FieldEditCtrl_Dialog(_T("AnimListEditor"))); AddColumnType(_("Props"), 250, "props", new FieldEditCtrl_Dialog(_T("PropListEditor"))); } diff --git a/source/tools/atlas/AtlasUI/ActorEditor/AnimListEditor.cpp b/source/tools/atlas/AtlasUI/ActorEditor/AnimListEditor.cpp index 63cb40c7e6..28a5474d03 100644 --- a/source/tools/atlas/AtlasUI/ActorEditor/AnimListEditor.cpp +++ b/source/tools/atlas/AtlasUI/ActorEditor/AnimListEditor.cpp @@ -31,6 +31,16 @@ AtObj AnimListEditor::FreezeData() return m_MainListBox->FreezeData(); } +void AnimListEditor::ImportData(AtObj& in) +{ + m_MainListBox->ImportData(in); +} + +AtObj AnimListEditor::ExportData() +{ + return m_MainListBox->ExportData(); +} + ////////////////////////////////////////////////////////////////////////// AnimListEditorListCtrl::AnimListEditorListCtrl(wxWindow* parent) @@ -38,7 +48,7 @@ AnimListEditorListCtrl::AnimListEditorListCtrl(wxWindow* parent) wxLC_REPORT | wxLC_HRULES | wxLC_VRULES | wxLC_SINGLE_SEL) { AddColumnType(_("Anim name"), 100, "@name", new FieldEditCtrl_List("animations")); - AddColumnType(_("File"), 200, "@file", new FieldEditCtrl_File(_T("art/animation"), _("Animation files (*.psa)|*.psa|All files (*.*)|*.*"))); + AddColumnType(_("File"), 200, "@file", new FieldEditCtrl_File(_T("art/animation/"), _("Animation files (*.psa)|*.psa|All files (*.*)|*.*"))); AddColumnType(_("Speed"), 50, "@speed", new FieldEditCtrl_Text()); } diff --git a/source/tools/atlas/AtlasUI/ActorEditor/AnimListEditor.h b/source/tools/atlas/AtlasUI/ActorEditor/AnimListEditor.h index ac95b3eed6..9bb84b7e92 100644 --- a/source/tools/atlas/AtlasUI/ActorEditor/AnimListEditor.h +++ b/source/tools/atlas/AtlasUI/ActorEditor/AnimListEditor.h @@ -17,6 +17,9 @@ protected: AtObj FreezeData(); void ThawData(AtObj& in); + AtObj ExportData(); + void ImportData(AtObj& in); + private: AnimListEditorListCtrl* m_MainListBox; }; diff --git a/source/tools/atlas/AtlasUI/ActorEditor/PropListEditor.cpp b/source/tools/atlas/AtlasUI/ActorEditor/PropListEditor.cpp index 993f3bd163..ffe83808a1 100644 --- a/source/tools/atlas/AtlasUI/ActorEditor/PropListEditor.cpp +++ b/source/tools/atlas/AtlasUI/ActorEditor/PropListEditor.cpp @@ -31,6 +31,16 @@ AtObj PropListEditor::FreezeData() return m_MainListBox->FreezeData(); } +void PropListEditor::ImportData(AtObj& in) +{ + m_MainListBox->ImportData(in); +} + +AtObj PropListEditor::ExportData() +{ + return m_MainListBox->ExportData(); +} + ////////////////////////////////////////////////////////////////////////// PropListEditorListCtrl::PropListEditorListCtrl(wxWindow* parent) @@ -38,7 +48,7 @@ PropListEditorListCtrl::PropListEditorListCtrl(wxWindow* parent) wxLC_REPORT | wxLC_HRULES | wxLC_VRULES | wxLC_SINGLE_SEL) { AddColumnType(_("Attachment point"), 100, "@attachpoint", new FieldEditCtrl_List("attachpoints")); - AddColumnType(_("Prop model"), 200, "@actor", new FieldEditCtrl_File(_T("art/actors"), _("Actor files (*.xml)|*.xml|All files (*.*)|*.*"))); + AddColumnType(_("Prop model"), 200, "@actor", new FieldEditCtrl_File(_T("art/actors/"), _("Actor files (*.xml)|*.xml|All files (*.*)|*.*"))); } void PropListEditorListCtrl::DoImport(AtObj& in) diff --git a/source/tools/atlas/AtlasUI/ActorEditor/PropListEditor.h b/source/tools/atlas/AtlasUI/ActorEditor/PropListEditor.h index 99d32c5ae8..6307334e9d 100644 --- a/source/tools/atlas/AtlasUI/ActorEditor/PropListEditor.h +++ b/source/tools/atlas/AtlasUI/ActorEditor/PropListEditor.h @@ -17,6 +17,9 @@ protected: AtObj FreezeData(); void ThawData(AtObj& in); + AtObj ExportData(); + void ImportData(AtObj& in); + private: PropListEditorListCtrl* m_MainListBox; }; diff --git a/source/tools/atlas/AtlasUI/AtlasUI.vcproj b/source/tools/atlas/AtlasUI/AtlasUI.vcproj index e9c31628b3..decfe379cc 100644 --- a/source/tools/atlas/AtlasUI/AtlasUI.vcproj +++ b/source/tools/atlas/AtlasUI/AtlasUI.vcproj @@ -124,6 +124,12 @@ + + + + diff --git a/source/tools/atlas/AtlasUI/CustomControls/DraggableListCtrl/DraggableListCtrlCommands.cpp b/source/tools/atlas/AtlasUI/CustomControls/DraggableListCtrl/DraggableListCtrlCommands.cpp index 7996c42f0c..7ebb45f7bd 100644 --- a/source/tools/atlas/AtlasUI/CustomControls/DraggableListCtrl/DraggableListCtrlCommands.cpp +++ b/source/tools/atlas/AtlasUI/CustomControls/DraggableListCtrl/DraggableListCtrlCommands.cpp @@ -31,14 +31,14 @@ bool DragCommand::Do() if (m_Tgt > m_Src) std::copy( - m_Ctrl->m_ListData.begin()+m_Src+1, - m_Ctrl->m_ListData.begin()+m_Tgt+1, - m_Ctrl->m_ListData.begin()+m_Src); + m_Ctrl->m_ListData.begin()+(m_Src+1), + m_Ctrl->m_ListData.begin()+(m_Tgt+1), + m_Ctrl->m_ListData.begin()+ m_Src); else if (m_Tgt < m_Src) std::copy_backward( - m_Ctrl->m_ListData.begin()+m_Tgt, - m_Ctrl->m_ListData.begin()+m_Src, - m_Ctrl->m_ListData.begin()+m_Src+1); + m_Ctrl->m_ListData.begin()+ m_Tgt, + m_Ctrl->m_ListData.begin()+ m_Src, + m_Ctrl->m_ListData.begin()+(m_Src+1)); else // m_Tgt == m_Src ; // do nothing - this item was just dragged onto itself diff --git a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrl.cpp b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrl.cpp index 288e7d9a20..52de393f89 100644 --- a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrl.cpp +++ b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrl.cpp @@ -7,6 +7,7 @@ #include "FieldEditCtrl.h" #include "AtlasObject/AtlasObject.h" #include "AtlasObject/AtlasObjectText.h" +#include "AtlasClipboard.h" const int BlanksAtEnd = 2; @@ -76,6 +77,37 @@ void EditableListCtrl::OnMouseEvent(wxMouseEvent& event) } } +void EditableListCtrl::OnKeyDown(wxKeyEvent& event) +{ + // TODO: Don't use magic key-code numbers + + // Check for Copy + if ((event.GetKeyCode() == 3) || // ctrl+c + (event.GetKeyCode() == WXK_INSERT && event.ControlDown())) // ctrl+insert + { + AtObj row; + long selection = GetSelection(); + if (selection >= 0 && selection < (long)m_ListData.size()) + row = m_ListData[selection]; + AtlasClipboard::SetClipboard(row); + } + + // Check for Paste + else + if ((event.GetKeyCode() == 22) || // ctrl+v + (event.GetKeyCode() == WXK_INSERT && event.ShiftDown())) // shift+insert + { + AtObj row; + if (AtlasClipboard::GetClipboard(row)) + { + long selection = GetSelection(); + AtlasWindowCommandProc* commandProc = AtlasWindowCommandProc::GetFromParentFrame(this); + commandProc->Submit(new PasteCommand(this, selection, row)); + } + } + else + event.Skip(); +} int EditableListCtrl::GetColumnAtPosition(wxPoint& pos) { @@ -235,8 +267,6 @@ wxListItemAttr* EditableListCtrl::OnGetItemAttr(long item) const void EditableListCtrl::ImportData(AtObj& in) { - //AtlasWindowCommandProc* commandProc = AtlasWindowCommandProc::GetFromParentFrame(this); - //commandProc->Submit(new ImportCommand(this, in)); return DoImport(in); } @@ -267,4 +297,5 @@ AtObj EditableListCtrl::FreezeData() BEGIN_EVENT_TABLE(EditableListCtrl, wxListCtrl) EVT_LEFT_DCLICK(EditableListCtrl::OnMouseEvent) EVT_RIGHT_DOWN(EditableListCtrl::OnMouseEvent) + EVT_CHAR(EditableListCtrl::OnKeyDown) END_EVENT_TABLE() diff --git a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrl.h b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrl.h index 01f12cb4f6..434655b7d0 100644 --- a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrl.h +++ b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrl.h @@ -16,6 +16,7 @@ class EditableListCtrl : public wxListCtrl, public IAtlasSerialiser friend class DeleteCommand; friend class DragCommand; friend class ImportCommand; + friend class PasteCommand; public: EditableListCtrl(wxWindow *parent, @@ -28,6 +29,7 @@ public: ~EditableListCtrl(); + void OnKeyDown(wxKeyEvent& event); void OnMouseEvent(wxMouseEvent& event); void MakeSizeAtLeast(int n); diff --git a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrlCommands.cpp b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrlCommands.cpp index 13daccafd8..99691978e0 100644 --- a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrlCommands.cpp +++ b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrlCommands.cpp @@ -6,35 +6,6 @@ ////////////////////////////////////////////////////////////////////////// -IMPLEMENT_CLASS(ImportCommand, AtlasWindowCommand); - -ImportCommand::ImportCommand(EditableListCtrl* ctrl, AtObj& in) - : AtlasWindowCommand(true, _("Import")), m_Ctrl(ctrl), m_In(in) -{ -} - -bool ImportCommand::Do() -{ - m_Ctrl->CloneListData(m_OldData); - - m_Ctrl->DoImport(m_In); - - m_Ctrl->UpdateDisplay(); - - return true; -} - -bool ImportCommand::Undo() -{ - m_Ctrl->SetListData(m_OldData); - - m_Ctrl->UpdateDisplay(); - - return true; -} - -////////////////////////////////////////////////////////////////////////// - IMPLEMENT_CLASS(EditCommand_Dialog, AtlasWindowCommand); EditCommand_Dialog::EditCommand_Dialog(EditableListCtrl* ctrl, long row, int col, AtObj& newData) @@ -98,3 +69,36 @@ bool EditCommand_Text::Undo() return true; } + +////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_CLASS(PasteCommand, AtlasWindowCommand); + +PasteCommand::PasteCommand(EditableListCtrl* ctrl, long row, AtObj& newData) + : AtlasWindowCommand(true, _("Paste")), m_Ctrl(ctrl), m_Row(row), m_NewData(newData) +{ +} + +bool PasteCommand::Do() +{ + m_Ctrl->CloneListData(m_OldData); + + m_Ctrl->MakeSizeAtLeast(m_Row); + + m_Ctrl->m_ListData.insert(m_Ctrl->m_ListData.begin()+m_Row, m_NewData); + + m_Ctrl->UpdateDisplay(); + m_Ctrl->SetSelection(m_Row); + + return true; +} + +bool PasteCommand::Undo() +{ + m_Ctrl->SetListData(m_OldData); + + m_Ctrl->UpdateDisplay(); + m_Ctrl->SetSelection(m_Row); + + return true; +} diff --git a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrlCommands.h b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrlCommands.h index ccae0d0e51..cffa4a2a91 100644 --- a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrlCommands.h +++ b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrlCommands.h @@ -4,23 +4,6 @@ class EditableListCtrl; -class ImportCommand : public AtlasWindowCommand -{ - DECLARE_CLASS(ImportCommand); - -public: - ImportCommand(EditableListCtrl* ctrl, AtObj& in); - bool Do(); - bool Undo(); - -private: - EditableListCtrl* m_Ctrl; - AtObj m_In; - - std::vector m_OldData; -}; - - class EditCommand_Dialog : public AtlasWindowCommand { DECLARE_CLASS(EditCommand_Dialog); @@ -59,3 +42,20 @@ private: std::vector m_OldData; }; + +class PasteCommand : public AtlasWindowCommand +{ + DECLARE_CLASS(PasteCommand); + +public: + PasteCommand(EditableListCtrl* ctrl, long row, AtObj& newData); + bool Do(); + bool Undo(); + +private: + EditableListCtrl* m_Ctrl; + long m_Row; + AtObj m_NewData; + std::vector m_OldData; +}; + diff --git a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/FieldEditCtrl.cpp b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/FieldEditCtrl.cpp index df1c671c23..7e12fb8f7d 100644 --- a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/FieldEditCtrl.cpp +++ b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/FieldEditCtrl.cpp @@ -59,13 +59,13 @@ void FieldEditCtrl_Dialog::StartEdit(wxWindow* parent, wxRect WXUNUSED(rect), lo EditableListCtrl* editCtrl = (EditableListCtrl*)parent; AtObj in (editCtrl->GetCellObject(row, col)); - dialog->ThawData(in); + dialog->ImportData(in); int ret = dialog->ShowModal(); if (ret == wxID_OK) { - AtObj out (dialog->FreezeData()); + AtObj out (dialog->ExportData()); AtlasWindowCommandProc::GetFromParentFrame(parent)->Submit( new EditCommand_Dialog(editCtrl, row, col, out) @@ -80,11 +80,15 @@ void FieldEditCtrl_Dialog::StartEdit(wxWindow* parent, wxRect WXUNUSED(rect), lo FieldEditCtrl_File::FieldEditCtrl_File(const wxString& rootDir, const wxString& fileMask) : m_FileMask(fileMask) { - // Make the path correct, relative to binaries/system - m_RootDir = _T("../data/mods/official/") + rootDir; + // Make the rootDir path absolute (where rootDir is relative to binaries/system): + wxFileName path (_T("../data/mods/official/") + rootDir); + wxASSERT(path.IsOk()); + path.MakeAbsolute(Datafile::GetSystemDirectory()); + wxASSERT(path.IsOk()); + m_RememberedDir = m_RootDir = path.GetPath(); } void FieldEditCtrl_File::StartEdit(wxWindow* parent, wxRect rect, long row, int col) { - new QuickFileCtrl(parent, rect, m_RootDir, m_FileMask, ListCtrlValidator((EditableListCtrl*)parent, row, col)); + new QuickFileCtrl(parent, rect, m_RootDir, m_FileMask, m_RememberedDir, ListCtrlValidator((EditableListCtrl*)parent, row, col)); } \ No newline at end of file diff --git a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/FieldEditCtrl.h b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/FieldEditCtrl.h index d309008e34..25d32f1a8b 100644 --- a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/FieldEditCtrl.h +++ b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/FieldEditCtrl.h @@ -54,6 +54,7 @@ private: class FieldEditCtrl_File : public FieldEditCtrl { public: + // rootDir is relative to mods/official, and must end with a / FieldEditCtrl_File(const wxString& rootDir, const wxString& fileMask); protected: @@ -62,4 +63,5 @@ protected: private: wxString m_RootDir; wxString m_FileMask; + wxString m_RememberedDir; }; diff --git a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/QuickFileCtrl.cpp b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/QuickFileCtrl.cpp index 350dfe0272..4a5099b08a 100644 --- a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/QuickFileCtrl.cpp +++ b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/QuickFileCtrl.cpp @@ -13,6 +13,9 @@ const int verticalPadding = 2; // changes, and compare the focus-recipient to every control inside the group, // to tell whether focus is leaving. // +// (This solution doesn't work very well, and I'd like to find a better +// way of doing it...) +// // So, create some unexciting classes: class FileCtrl_TextCtrl : public wxTextCtrl @@ -86,14 +89,30 @@ public: long style, const wxString& rootDir, const wxString& fileMask) : FileCtrl_Button(parent, wxID_ANY, _("&Browse..."), pos, size, style), m_RootDir(rootDir), m_FileMask(fileMask) - {} + { + } void OnPress(wxCommandEvent& WXUNUSED(event)) { QuickFileCtrl* parent = wxDynamicCast(GetParent(), QuickFileCtrl); wxASSERT(parent); - wxFileDialog dlg(this, _("Choose a file"), m_RootDir, wxEmptyString, m_FileMask, wxOPEN); + wxString defaultDir, defaultFile; + + wxFileName oldFilename (parent->m_TextCtrl->GetValue()); // TODO: use wxPATH_UNIX? + if (oldFilename.IsOk()) + { + oldFilename.MakeAbsolute(m_RootDir); + defaultDir = oldFilename.GetPath(); + defaultFile = oldFilename.GetFullName(); + } + else + { + defaultDir = *parent->m_RememberedDir; + defaultFile = wxEmptyString; + } + + wxFileDialog dlg(this, _("Choose a file"), defaultDir, defaultFile, m_FileMask, wxOPEN); parent->m_DisableKillFocus = true; int ret = dlg.ShowModal(); @@ -103,6 +122,8 @@ public: return; wxFileName filename (dlg.GetPath()); + *parent->m_RememberedDir = filename.GetPath(); + filename.MakeRelativeTo(m_RootDir); wxString filenameRel (filename.GetFullPath(wxPATH_UNIX)); @@ -123,11 +144,12 @@ QuickFileCtrl::QuickFileCtrl(wxWindow* parent, wxRect& location, const wxString& rootDir, const wxString& fileMask, + wxString& rememberedDir, const wxValidator& validator) : wxPanel(parent, wxID_ANY, location.GetPosition()-wxPoint(0,verticalPadding), wxDefaultSize, wxNO_BORDER), - m_DisableKillFocus(false) + m_DisableKillFocus(false), m_RememberedDir(&rememberedDir) { wxBoxSizer* s = new wxBoxSizer(wxVERTICAL); @@ -148,9 +170,12 @@ QuickFileCtrl::QuickFileCtrl(wxWindow* parent, SetSizer(s); s->SetSizeHints(this); + m_DisableKillFocus = true; // yucky m_TextCtrl->GetValidator()->TransferToWindow(); m_TextCtrl->SetFocus(); m_TextCtrl->SetSelection(-1, -1); + m_DisableKillFocus = false; + m_TextCtrl->SetFocus(); } void QuickFileCtrl::OnKillFocus() diff --git a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/QuickFileCtrl.h b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/QuickFileCtrl.h index 75b5ab0cbc..466d0c867e 100644 --- a/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/QuickFileCtrl.h +++ b/source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/QuickFileCtrl.h @@ -8,6 +8,7 @@ public: QuickFileCtrl() {}; QuickFileCtrl(wxWindow* parent, wxRect& location, const wxString& rootDir, const wxString& fileMask, + wxString& rememberedDir, const wxValidator& validator = wxDefaultValidator); void OnKillFocus(); @@ -16,4 +17,6 @@ public: wxTextCtrl* m_TextCtrl; wxButton* m_ButtonBrowse; bool m_DisableKillFocus; + + wxString* m_RememberedDir; // can't be wxString&, because DYNAMIC_CLASSes need default constructors, and there's no suitable string to store in here... }; diff --git a/source/tools/atlas/AtlasUI/CustomControls/Windows/AtlasDialog.h b/source/tools/atlas/AtlasUI/CustomControls/Windows/AtlasDialog.h index 3445d865a9..b5ab334362 100644 --- a/source/tools/atlas/AtlasUI/CustomControls/Windows/AtlasDialog.h +++ b/source/tools/atlas/AtlasUI/CustomControls/Windows/AtlasDialog.h @@ -16,6 +16,7 @@ public: AtlasDialog(wxWindow* parent, const wxString& title); virtual ~AtlasDialog() {} +private: void OnUndo(wxCommandEvent& event); void OnRedo(wxCommandEvent& event); diff --git a/source/tools/atlas/AtlasUI/CustomControls/Windows/AtlasWindow.cpp b/source/tools/atlas/AtlasUI/CustomControls/Windows/AtlasWindow.cpp index c1bd343f8e..7136afd087 100644 --- a/source/tools/atlas/AtlasUI/CustomControls/Windows/AtlasWindow.cpp +++ b/source/tools/atlas/AtlasUI/CustomControls/Windows/AtlasWindow.cpp @@ -54,17 +54,6 @@ END_EVENT_TABLE() IMPLEMENT_CLASS(AtlasWindow, wxFrame); -enum -{ - ID_Quit = 1, - ID_New, -// ID_Import, -// ID_Export, - ID_Open, - ID_Save, - ID_SaveAs -}; - BEGIN_EVENT_TABLE(AtlasWindow, wxFrame) EVT_MENU(ID_New, AtlasWindow::OnNew) // EVT_MENU(ID_Import, AtlasWindow::OnImport) @@ -81,7 +70,7 @@ BEGIN_EVENT_TABLE(AtlasWindow, wxFrame) EVT_CLOSE(AtlasWindow::OnClose) END_EVENT_TABLE() -AtlasWindow::AtlasWindow(wxWindow* parent, const wxString& title, const wxSize& size) +AtlasWindow::AtlasWindow(wxWindow* parent, const wxString& title, const wxSize& size, CustomMenu* menu) : wxFrame(parent, wxID_ANY, _T(""), wxDefaultPosition, size), m_WindowTitle(title), m_FileHistory(9) { @@ -117,6 +106,18 @@ AtlasWindow::AtlasWindow(wxWindow* parent, const wxString& title, const wxSize& m_CommandProc.SetEditMenu(menuEdit); m_CommandProc.Initialize(); + + if (menu) + { + wxMenu* menuCustom = new wxMenu; + menuBar->Append(menuCustom, menu->title); + + int id = ID_Custom1; + for (CustomMenu::CustomMenuItem** item = menu->items; *item; ++item) + menuCustom->Append(id++, (*item)->name); + } + + m_FileHistory.Load(*wxConfigBase::Get()); CreateStatusBar(); diff --git a/source/tools/atlas/AtlasUI/CustomControls/Windows/AtlasWindow.h b/source/tools/atlas/AtlasUI/CustomControls/Windows/AtlasWindow.h index b5285a59bf..d6288e8a28 100644 --- a/source/tools/atlas/AtlasUI/CustomControls/Windows/AtlasWindow.h +++ b/source/tools/atlas/AtlasUI/CustomControls/Windows/AtlasWindow.h @@ -14,8 +14,34 @@ class AtlasWindow : public wxFrame, public IAtlasSerialiser DECLARE_CLASS(AtlasWindow); public: - AtlasWindow(wxWindow* parent, const wxString& title, const wxSize& size); + enum + { + ID_Quit = 1, + ID_New, + // ID_Import, + // ID_Export, + ID_Open, + ID_Save, + ID_SaveAs, + + // IDs for custom window-specific menu items + ID_Custom1, + ID_Custom2, + ID_Custom3 + }; + + // See ActorEditor.cpp for example usage + struct CustomMenu { + const wxChar* title; + struct CustomMenuItem { + const wxChar* name; + }** items; + }; + + AtlasWindow(wxWindow* parent, const wxString& title, const wxSize& size, CustomMenu* menu = NULL); + +private: void OnNew(wxCommandEvent& event); // void OnImport(wxCommandEvent& event); // void OnExport(wxCommandEvent& event); diff --git a/source/tools/atlas/AtlasUI/General/AtlasClipboard.cpp b/source/tools/atlas/AtlasUI/General/AtlasClipboard.cpp new file mode 100644 index 0000000000..2349552d86 --- /dev/null +++ b/source/tools/atlas/AtlasUI/General/AtlasClipboard.cpp @@ -0,0 +1,20 @@ +#include "stdafx.h" + +#include "AtlasClipboard.h" + +// TODO: Do this properly, using the native clipboard. (That probably +// requires AtObj to be serialisable, though... Maybe just use XML?) + +static AtObj g_Clipboard; + +bool AtlasClipboard::SetClipboard(AtObj& in) +{ + g_Clipboard = in; + return true; +} + +bool AtlasClipboard::GetClipboard(AtObj& out) +{ + out = g_Clipboard; + return true; +} \ No newline at end of file diff --git a/source/tools/atlas/AtlasUI/General/AtlasClipboard.h b/source/tools/atlas/AtlasUI/General/AtlasClipboard.h new file mode 100644 index 0000000000..d1134d8b44 --- /dev/null +++ b/source/tools/atlas/AtlasUI/General/AtlasClipboard.h @@ -0,0 +1,9 @@ +#include "AtlasObject/AtlasObject.h" + +class AtlasClipboard +{ +public: + // Return true on success + static bool SetClipboard(AtObj& in); + static bool GetClipboard(AtObj& out); +}; \ No newline at end of file diff --git a/source/tools/atlas/AtlasUI/General/Datafile.h b/source/tools/atlas/AtlasUI/General/Datafile.h index 1947e767fe..72fe12d99d 100644 --- a/source/tools/atlas/AtlasUI/General/Datafile.h +++ b/source/tools/atlas/AtlasUI/General/Datafile.h @@ -11,6 +11,8 @@ public: // relative to the current working directory. static void SetSystemDirectory(const wxString& dir); + static wxString GetSystemDirectory() { return systemDir; } + private: static wxString systemDir; }; \ No newline at end of file diff --git a/source/tools/atlas/AtlasUI/Misc/actored.cpp b/source/tools/atlas/AtlasUI/Misc/actored.cpp index cdfb69a0a6..37f956477e 100644 --- a/source/tools/atlas/AtlasUI/Misc/actored.cpp +++ b/source/tools/atlas/AtlasUI/Misc/actored.cpp @@ -15,6 +15,11 @@ class MyApp: public wxApp // Initialise the global config file wxConfigBase::Set(new wxConfig(_T("Atlas Editor"), _T("Wildfire Games"))); + // Assume that the .exe is located in .../binaries/system. (We can't + // just use the cwd, since that isn't correct when being executed by + // dragging-and-dropping onto the program in Explorer.) + Datafile::SetSystemDirectory(argv[0]); + // Display the Actor Editor window AtlasWindow *frame = new ActorEditor(NULL); frame->Show(); @@ -23,12 +28,6 @@ class MyApp: public wxApp // One argument => argv[1] is a filename to open if (argc > 1) { - // We were probably executed by dragging a file onto the icon. - // The working directory is then different to the exe's directory, - // so we need to set it. (In the normal no-argument case, it should - // be safe to assume that we're being run from the right directory.) - Datafile::SetSystemDirectory(argv[0]); - wxChar* filename = argv[1]; if (wxFile::Exists(filename)) frame->OpenFile(filename); diff --git a/source/tools/atlas/AtlasUI/Misc/stdafx.h b/source/tools/atlas/AtlasUI/Misc/stdafx.h index 2108e81970..967d6277b7 100644 --- a/source/tools/atlas/AtlasUI/Misc/stdafx.h +++ b/source/tools/atlas/AtlasUI/Misc/stdafx.h @@ -17,6 +17,7 @@ #include "wx/dialog.h" #include "wx/filename.h" #include "wx/artprov.h" +#include "wx/file.h" #include #include diff --git a/source/tools/atlas/AtlasUI/TODO.txt b/source/tools/atlas/AtlasUI/TODO.txt index c341f6a7ed..5b789480cd 100644 --- a/source/tools/atlas/AtlasUI/TODO.txt +++ b/source/tools/atlas/AtlasUI/TODO.txt @@ -1,15 +1,13 @@ -* Open from prop-actor selection +* Regression testing + +* Open actors from prop-actor selection * Make import undo work with multi-control windows, and update the title bar === -* 'Create entity' button (take name, parent) - * Better input controls (=> export nicely, support undo, etc) -* Copy and paste - * Help (tooltips, etc) * More efficient Datafile::ReadList (don't read from disk every time) @@ -22,7 +20,8 @@ === -* Correct undo menu entry when selecting 'New' (so it's not 'Import') +* Better copy and paste (e.g. between multiple instances of the program, + and paste XML into other text-editing programs * Save on exit: don't ask if no changes @@ -63,8 +62,11 @@ ====== -Done: +Done: (newest at top) +* Copy and paste +* 'Create entity' button (take name, parent) +* Correct undo menu entry when selecting 'New' (so it's not 'Import') * MRU file list * 'New' menu item * Import/export filter, for validation(?) and for handling attributes