Atlas: Simple undo system
This was SVN commit r2627.
This commit is contained in:
parent
a10082d69b
commit
5d62c3f3f7
@ -1,8 +1,5 @@
|
||||
dofile("../functions.lua")
|
||||
|
||||
atlas = 0 -- temporarily disabled, until the whole of Atlas
|
||||
-- can be integrated into this build process
|
||||
|
||||
-- Set up the Project
|
||||
project.name = "pyrogenesis"
|
||||
project.bindir = "../../../binaries/system"
|
||||
@ -20,7 +17,6 @@ function setuppackage (projectname)
|
||||
exename = "sced"
|
||||
objdirprefix = "obj/ScEd_"
|
||||
package.build = 0 -- Don't build Sced by default
|
||||
atlas = 0 -- Don't build Atlas into ScEd
|
||||
else
|
||||
package.name = "pyrogenesis"
|
||||
exename = "ps"
|
||||
@ -72,7 +68,10 @@ function setuppackage (projectname)
|
||||
"terrain",
|
||||
"sound",
|
||||
"scripting",
|
||||
"i18n"
|
||||
"i18n",
|
||||
|
||||
"tools/atlas/GameInterface",
|
||||
"tools/atlas/GameInterface/Handlers"
|
||||
}
|
||||
|
||||
if (projectname ~= "sced") then tconcat(source_dirs, {
|
||||
@ -80,11 +79,6 @@ function setuppackage (projectname)
|
||||
"gui/scripting"
|
||||
}) end
|
||||
|
||||
if (atlas == 1) then tconcat(source_dirs, {
|
||||
"tools/atlas/GameInterface",
|
||||
"tools/atlas/GameInterface/Handlers"
|
||||
}) end
|
||||
|
||||
if (projectname == "sced") then tconcat(source_dirs, {
|
||||
"tools/sced",
|
||||
"tools/sced/ui"
|
||||
@ -145,10 +139,6 @@ function setuppackage (projectname)
|
||||
tinsert(package.defines, "NO_MAIN_REDIRECT")
|
||||
end
|
||||
|
||||
if (atlas == 1) then
|
||||
tinsert(package.defines, "ATLAS")
|
||||
end
|
||||
|
||||
-- Platform Specifics
|
||||
if (OS == "windows") then
|
||||
|
||||
|
@ -323,7 +323,7 @@ int main(int argc, char* argv[])
|
||||
ATLAS_RunIfOnCmdLine(argc, argv);
|
||||
|
||||
// ELSE
|
||||
Init(argc, argv, true);
|
||||
Init(argc, argv, true, true);
|
||||
MainControllerInit();
|
||||
|
||||
while(!quit)
|
||||
@ -341,7 +341,7 @@ int main(int argc, char* argv[])
|
||||
void Init_(int argc, char** argv, bool setup_gfx)
|
||||
{
|
||||
g_Quickstart = true;
|
||||
Init(argc, argv, setup_gfx);
|
||||
Init(argc, argv, setup_gfx, false);
|
||||
}
|
||||
void Shutdown_()
|
||||
{
|
||||
|
@ -74,9 +74,13 @@ static void ATLAS_Run(int argc, char* argv[], int flags = 0)
|
||||
return;
|
||||
}
|
||||
|
||||
void(*pStartWindow)(int argc, char* argv[]);
|
||||
*(void**)&pStartWindow = dlsym(atlas_so_handle, "_StartWindow");
|
||||
pStartWindow(argc, argv);
|
||||
// TODO (make nicer)
|
||||
extern bool BeginAtlas(int argc, char* argv[], void* dll);
|
||||
if (!BeginAtlas(argc, argv, atlas_so_handle))
|
||||
{
|
||||
debug_warn("Atlas loading failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -431,7 +431,7 @@ static void InitVfs(const char* argv0)
|
||||
}
|
||||
|
||||
|
||||
static void InitPs()
|
||||
static void InitPs(bool setup_gui)
|
||||
{
|
||||
// console
|
||||
{
|
||||
@ -458,7 +458,8 @@ static void InitPs()
|
||||
}
|
||||
|
||||
// GUI uses VFS, so this must come after VFS init.
|
||||
GUI_Init();
|
||||
if (setup_gui)
|
||||
GUI_Init();
|
||||
}
|
||||
|
||||
|
||||
@ -584,8 +585,6 @@ void Shutdown()
|
||||
{
|
||||
MICROLOG(L"Shutdown");
|
||||
|
||||
ATLAS_Shutdown();
|
||||
|
||||
ShutdownPs(); // Must delete g_GUI before g_ScriptingHost
|
||||
|
||||
if (g_Game)
|
||||
@ -652,7 +651,7 @@ void Shutdown()
|
||||
# pragma optimize("", off)
|
||||
#endif
|
||||
|
||||
void Init(int argc, char* argv[], bool setup_gfx = true)
|
||||
void Init(int argc, char* argv[], bool setup_gfx, bool setup_gui)
|
||||
{
|
||||
debug_printf("INIT &argc=%p &argv=%p\n", &argc, &argv);
|
||||
|
||||
@ -700,10 +699,6 @@ void Init(int argc, char* argv[], bool setup_gfx = true)
|
||||
MICROLOG(L"init i18n");
|
||||
I18n::LoadLanguage(NULL);
|
||||
|
||||
// should be done before the bulk of GUI init because it prevents
|
||||
// most loads from happening (since ATLAS_IsRunning will return true).
|
||||
ATLAS_RunIfOnCmdLine(argc, argv);
|
||||
|
||||
// Set up the console early, so that debugging
|
||||
// messages can be logged to it. (The console's size
|
||||
// and fonts are set later in InitPs())
|
||||
@ -749,7 +744,7 @@ void Init(int argc, char* argv[], bool setup_gfx = true)
|
||||
if(!g_Quickstart)
|
||||
{
|
||||
WriteSystemInfo();
|
||||
vfs_display();
|
||||
// vfs_display(); // disabled to decrease startup time
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -781,7 +776,7 @@ void Init(int argc, char* argv[], bool setup_gfx = true)
|
||||
#endif
|
||||
|
||||
MICROLOG(L"init ps");
|
||||
InitPs();
|
||||
InitPs(setup_gui);
|
||||
|
||||
oglCheck();
|
||||
InitRenderer();
|
||||
|
@ -19,4 +19,4 @@ extern void Render();
|
||||
|
||||
extern void Shutdown();
|
||||
|
||||
extern void Init(int argc, char* argv[], bool setup_gfx = true);
|
||||
extern void Init(int argc, char* argv[], bool setup_gfx, bool setup_gui);
|
||||
|
@ -20,6 +20,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ColourTester", "AtlasFronte
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pyrogenesis", "..\..\..\build\workspaces\vc2003\pyrogenesis.vcproj", "{CDA14ADB-57CA-DB49-A474-E7605D7922BD}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{E99BA969-D540-4F23-822E-37C499E8F704} = {E99BA969-D540-4F23-822E-37C499E8F704}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
|
@ -1,7 +1,7 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#define ATLASDLLIMPEXP __declspec(dllimport)
|
||||
#define ATLASDLLIMPEXP extern "C" __declspec(dllimport)
|
||||
|
||||
#include "AtlasUI/Misc/DLLInterface.h"
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#define ATLASDLLIMPEXP __declspec(dllimport)
|
||||
#define ATLASDLLIMPEXP extern "C" __declspec(dllimport)
|
||||
|
||||
#include "AtlasUI/Misc/DLLInterface.h"
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#define ATLASDLLIMPEXP __declspec(dllimport)
|
||||
#define ATLASDLLIMPEXP extern "C" __declspec(dllimport)
|
||||
|
||||
#include "AtlasUI/Misc/DLLInterface.h"
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
Version="7.10"
|
||||
Name="AtlasUI"
|
||||
ProjectGUID="{E99BA969-D540-4F23-822E-37C499E8F704}"
|
||||
RootNamespace="AtlasUI"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
|
@ -13,15 +13,18 @@ class AtlasWindowCommand : public wxCommand
|
||||
|
||||
public:
|
||||
AtlasWindowCommand(bool canUndoIt, const wxString& name)
|
||||
: wxCommand(canUndoIt, name), m_Finalized(false) {}
|
||||
: wxCommand(canUndoIt, name), m_Finalized(false)
|
||||
{ }
|
||||
|
||||
virtual bool Redo() { return Do(); }
|
||||
|
||||
private:
|
||||
// Control merging of this command with a future one (so they
|
||||
// can be undone in a single step). The function should try to merge
|
||||
// with the previous command, by altering that previous command and then
|
||||
// returning true. If it can't, return false.
|
||||
virtual bool Merge(AtlasWindowCommand* WXUNUSED(previousCommand)) { return false; }
|
||||
|
||||
private:
|
||||
bool m_Finalized;
|
||||
};
|
||||
|
||||
|
@ -41,4 +41,4 @@
|
||||
#endif
|
||||
|
||||
|
||||
#define ATLASDLLIMPEXP __declspec(dllexport)
|
||||
#define ATLASDLLIMPEXP extern "C" __declspec(dllexport)
|
||||
|
@ -111,15 +111,70 @@ END_EVENT_TABLE()
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum
|
||||
{
|
||||
ID_Quit = 1,
|
||||
// ID_New,
|
||||
// // ID_Import,
|
||||
// // ID_Export,
|
||||
// ID_Open,
|
||||
// ID_Save,
|
||||
// ID_SaveAs,
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(ScenarioEditor, wxFrame)
|
||||
EVT_CLOSE(ScenarioEditor::OnClose)
|
||||
EVT_TIMER(wxID_ANY, ScenarioEditor::OnTimer)
|
||||
|
||||
EVT_MENU(ID_Quit, ScenarioEditor::OnQuit)
|
||||
EVT_MENU(wxID_UNDO, ScenarioEditor::OnUndo)
|
||||
EVT_MENU(wxID_REDO, ScenarioEditor::OnRedo)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
static AtlasWindowCommandProc g_CommandProc;
|
||||
AtlasWindowCommandProc& ScenarioEditor::GetCommandProc() { return g_CommandProc; }
|
||||
|
||||
ScenarioEditor::ScenarioEditor()
|
||||
: wxFrame(NULL, wxID_ANY, _("Atlas - Scenario Editor"), wxDefaultPosition, wxSize(1024, 768))
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Menu
|
||||
|
||||
wxMenuBar* menuBar = new wxMenuBar;
|
||||
SetMenuBar(menuBar);
|
||||
|
||||
wxMenu *menuFile = new wxMenu;
|
||||
menuBar->Append(menuFile, _("&File"));
|
||||
{
|
||||
// menuFile->Append(ID_New, _("&New"));
|
||||
// // menuFile->Append(ID_Import, _("&Import..."));
|
||||
// // menuFile->Append(ID_Export, _("&Export..."));
|
||||
// menuFile->Append(ID_Open, _("&Open..."));
|
||||
// menuFile->Append(ID_Save, _("&Save"));
|
||||
// menuFile->Append(ID_SaveAs, _("Save &As..."));
|
||||
// menuFile->AppendSeparator();//-----------
|
||||
menuFile->Append(ID_Quit, _("E&xit"));
|
||||
// m_FileHistory.UseMenu(menuFile);//-------
|
||||
// m_FileHistory.AddFilesToMenu();
|
||||
}
|
||||
|
||||
// m_menuItem_Save = menuFile->FindItem(ID_Save); // remember this item, to let it be greyed out
|
||||
// wxASSERT(m_menuItem_Save);
|
||||
|
||||
wxMenu *menuEdit = new wxMenu;
|
||||
menuBar->Append(menuEdit, _("&Edit"));
|
||||
{
|
||||
menuEdit->Append(wxID_UNDO, _("&Undo"));
|
||||
menuEdit->Append(wxID_REDO, _("&Redo"));
|
||||
}
|
||||
|
||||
GetCommandProc().SetEditMenu(menuEdit);
|
||||
GetCommandProc().Initialize();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Main window
|
||||
|
||||
SnapSplitterWindow* splitter = new SnapSplitterWindow(this);
|
||||
|
||||
// Set up GL canvas:
|
||||
@ -187,6 +242,21 @@ void ScenarioEditor::OnTimer(wxTimerEvent&)
|
||||
last = time;
|
||||
}
|
||||
|
||||
void ScenarioEditor::OnQuit(wxCommandEvent&)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void ScenarioEditor::OnUndo(wxCommandEvent&)
|
||||
{
|
||||
GetCommandProc().Undo();
|
||||
}
|
||||
|
||||
void ScenarioEditor::OnRedo(wxCommandEvent&)
|
||||
{
|
||||
GetCommandProc().Redo();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AtlasMessage::Position::Position(const wxPoint& pt)
|
||||
|
@ -1,12 +1,25 @@
|
||||
#ifndef SCENARIOEDITOR_H__
|
||||
#define SCENARIOEDITOR_H__
|
||||
|
||||
#include "General/AtlasWindowCommandProc.h"
|
||||
|
||||
class ScenarioEditor : public wxFrame
|
||||
{
|
||||
public:
|
||||
ScenarioEditor();
|
||||
void OnClose(wxCloseEvent& evt);
|
||||
void OnTimer(wxTimerEvent& evt);
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void OnTimer(wxTimerEvent& event);
|
||||
|
||||
void OnQuit(wxCommandEvent& event);
|
||||
void OnUndo(wxCommandEvent& event);
|
||||
void OnRedo(wxCommandEvent& event);
|
||||
|
||||
static AtlasWindowCommandProc& GetCommandProc();
|
||||
|
||||
private:
|
||||
wxTimer m_Timer;
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
#endif // SCENARIOEDITOR_H__
|
||||
|
@ -44,7 +44,7 @@ public:
|
||||
{
|
||||
if (m_IsActive)
|
||||
{
|
||||
ADD_COMMAND(AlterElevation(m_Pos, dt*4.096f));
|
||||
ADD_WORLDCOMMAND(AlterElevation, (m_Pos, dt*4.096f));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "Tools.h"
|
||||
#include "GameInterface/Messages.h"
|
||||
|
||||
class DummyTool : public ITool
|
||||
{
|
||||
@ -21,3 +22,35 @@ void SetCurrentTool(ITool* tool)
|
||||
else
|
||||
g_CurrentTool = tool;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPLEMENT_CLASS(WorldCommand, AtlasWindowCommand);
|
||||
|
||||
WorldCommand::WorldCommand(AtlasMessage::mWorldCommand* command)
|
||||
: AtlasWindowCommand(true, _("???")), m_Command(command)
|
||||
{
|
||||
}
|
||||
|
||||
WorldCommand::~WorldCommand()
|
||||
{
|
||||
delete m_Command;
|
||||
}
|
||||
|
||||
bool WorldCommand::Do()
|
||||
{
|
||||
ADD_COMMAND(DoCommand(m_Command));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldCommand::Undo()
|
||||
{
|
||||
ADD_COMMAND(UndoCommand());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldCommand::Redo()
|
||||
{
|
||||
ADD_COMMAND(RedoCommand());
|
||||
return true;
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
#ifndef TOOLS_H__
|
||||
#define TOOLS_H__
|
||||
|
||||
#include "ScenarioEditor/ScenarioEditor.h"
|
||||
#include "general/AtlasWindowCommand.h"
|
||||
|
||||
class wxMouseEvent;
|
||||
class wxKeyEvent;
|
||||
|
||||
@ -22,4 +25,23 @@ public:
|
||||
extern ITool* g_CurrentTool;
|
||||
extern void SetCurrentTool(ITool*); // for internal use only
|
||||
|
||||
namespace AtlasMessage { struct mWorldCommand; }
|
||||
class WorldCommand : public AtlasWindowCommand
|
||||
{
|
||||
DECLARE_CLASS(WorldCommand);
|
||||
|
||||
public:
|
||||
WorldCommand(AtlasMessage::mWorldCommand* command);
|
||||
~WorldCommand();
|
||||
bool Do();
|
||||
bool Undo();
|
||||
bool Redo();
|
||||
|
||||
private:
|
||||
AtlasMessage::mWorldCommand* m_Command;
|
||||
};
|
||||
|
||||
#define ADD_WORLDCOMMAND(type, data) ScenarioEditor::GetCommandProc().Submit(new WorldCommand(new AtlasMessage::m##type(AtlasMessage::d##type data)))
|
||||
|
||||
|
||||
#endif // TOOLS_H__
|
||||
|
@ -1,7 +1,5 @@
|
||||
Colour tester:
|
||||
|
||||
* Display DDS info (compression, size)
|
||||
|
||||
==============================
|
||||
|
||||
Actor editor:
|
||||
@ -81,6 +79,7 @@ General and/or unsorted miscellany:
|
||||
|
||||
Done: (newest at top)
|
||||
|
||||
* Display DDS info (compression, size)
|
||||
* Copy and paste
|
||||
* 'Create entity' button (take name, parent)
|
||||
* Correct undo menu entry when selecting 'New' (so it's not 'Import')
|
||||
|
73
source/tools/atlas/GameInterface/CommandProc.cpp
Normal file
73
source/tools/atlas/GameInterface/CommandProc.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "CommandProc.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T> T next(T x) { T t = x; return ++t; }
|
||||
|
||||
template<typename T, typename I> void delete_erase(T list, I first, I last)
|
||||
{
|
||||
while (first != last)
|
||||
{
|
||||
delete *first;
|
||||
first = list.erase(first);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
using namespace AtlasMessage;
|
||||
|
||||
namespace AtlasMessage {
|
||||
static CommandProc g_CommandProc;
|
||||
|
||||
CommandProc& GetCommandProc() { return g_CommandProc; }
|
||||
|
||||
cmdHandlers& GetCmdHandlers()
|
||||
{
|
||||
static cmdHandlers h;
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CommandProc::CommandProc()
|
||||
{
|
||||
// Start the list with a NULL, so m_CurrentCommand can point at
|
||||
// something even when the command stack is empty
|
||||
m_Commands.push_back(NULL);
|
||||
|
||||
m_CurrentCommand = m_Commands.begin();
|
||||
}
|
||||
|
||||
CommandProc::~CommandProc()
|
||||
{
|
||||
delete_erase(m_Commands, m_Commands.begin(), m_Commands.end());
|
||||
}
|
||||
|
||||
void CommandProc::Submit(Command* cmd)
|
||||
{
|
||||
delete_erase(m_Commands, next(m_CurrentCommand), m_Commands.end());
|
||||
m_CurrentCommand = m_Commands.insert(next(m_CurrentCommand), cmd);
|
||||
|
||||
(*m_CurrentCommand)->Do();
|
||||
}
|
||||
|
||||
void CommandProc::Undo()
|
||||
{
|
||||
if (m_CurrentCommand != m_Commands.begin())
|
||||
{
|
||||
(*m_CurrentCommand)->Undo();
|
||||
--m_CurrentCommand;
|
||||
}
|
||||
}
|
||||
|
||||
void CommandProc::Redo()
|
||||
{
|
||||
if (next(m_CurrentCommand) != m_Commands.end())
|
||||
{
|
||||
++m_CurrentCommand;
|
||||
(*m_CurrentCommand)->Redo();
|
||||
}
|
||||
}
|
59
source/tools/atlas/GameInterface/CommandProc.h
Normal file
59
source/tools/atlas/GameInterface/CommandProc.h
Normal file
@ -0,0 +1,59 @@
|
||||
#include <list>
|
||||
|
||||
namespace AtlasMessage
|
||||
{
|
||||
|
||||
struct Command
|
||||
{
|
||||
virtual ~Command() {}
|
||||
virtual void Do() = 0;
|
||||
virtual void Undo() = 0;
|
||||
virtual void Redo() = 0;
|
||||
// virtual void Merge(Command* prev) = 0;
|
||||
};
|
||||
|
||||
class CommandProc
|
||||
{
|
||||
public:
|
||||
CommandProc();
|
||||
~CommandProc();
|
||||
|
||||
void Submit(Command* cmd);
|
||||
|
||||
void Undo();
|
||||
void Redo();
|
||||
|
||||
private:
|
||||
std::list<Command*> m_Commands;
|
||||
std::list<Command*>::iterator m_CurrentCommand;
|
||||
};
|
||||
|
||||
typedef Command* (*cmdHandler)(const void*);
|
||||
typedef std::map<std::string, cmdHandler> cmdHandlers;
|
||||
extern cmdHandlers& GetCmdHandlers();
|
||||
|
||||
CommandProc& GetCommandProc();
|
||||
|
||||
class DataCommand : public Command // so commands can optionally override (De|Con)struct
|
||||
{
|
||||
void Destruct() {};
|
||||
void Construct() {};
|
||||
};
|
||||
|
||||
#define BEGIN_COMMAND(t) \
|
||||
class c##t : public DataCommand \
|
||||
{ \
|
||||
d##t* d; \
|
||||
public: \
|
||||
c##t(d##t* data) : d(data) { Construct(); } \
|
||||
~c##t() { Destruct(); delete d; } \
|
||||
static Command* Create(const void* data) { return new c##t((d##t*)data); }
|
||||
|
||||
#define END_COMMAND(t) \
|
||||
}; \
|
||||
namespace CAT2(hndlr_, __LINE__) { struct init { init() { \
|
||||
bool notAlreadyRegisted = GetCmdHandlers().insert(std::pair<std::string, cmdHandler>("c"#t, &c##t##::Create)).second; \
|
||||
assert(notAlreadyRegisted); \
|
||||
} } init; };
|
||||
|
||||
}
|
@ -21,9 +21,6 @@
|
||||
|
||||
using namespace AtlasMessage;
|
||||
|
||||
extern __declspec(dllimport) void Atlas_StartWindow(wchar_t* type);
|
||||
extern __declspec(dllimport) void Atlas_SetMessagePasser(MessagePasser<mCommand>*, MessagePasser<mInput>*);
|
||||
|
||||
extern void Render_();
|
||||
|
||||
extern "C" { __declspec(dllimport) int __stdcall SwapBuffers(void*); }
|
||||
@ -31,7 +28,9 @@ extern "C" { __declspec(dllimport) int __stdcall SwapBuffers(void*); }
|
||||
//
|
||||
// (Er, actually that's what most of this file is. Oh well.)
|
||||
|
||||
|
||||
// Loaded from DLL:
|
||||
void (*Atlas_StartWindow)(wchar_t* type);
|
||||
void (*Atlas_SetMessagePasser)(MessagePasser<mCommand>*, MessagePasser<mInput>*);
|
||||
|
||||
static MessagePasserImpl<mCommand> msgPasser_Command;
|
||||
static MessagePasserImpl<mInput> msgPasser_Input;
|
||||
@ -49,8 +48,14 @@ static void* LaunchWindow(void*)
|
||||
}
|
||||
|
||||
|
||||
void BeginAtlas(int argc, char** argv)
|
||||
bool BeginAtlas(int argc, char* argv[], void* dll)
|
||||
{
|
||||
*(void**)&Atlas_StartWindow = dlsym(dll, "Atlas_StartWindow");
|
||||
*(void**)&Atlas_SetMessagePasser = dlsym(dll, "Atlas_SetMessagePasser");
|
||||
|
||||
if (!Atlas_StartWindow || !Atlas_SetMessagePasser)
|
||||
return false;
|
||||
|
||||
// Pass our message handler to Atlas
|
||||
Atlas_SetMessagePasser(&msgPasser_Command, &msgPasser_Input);
|
||||
|
||||
@ -92,7 +97,7 @@ void BeginAtlas(int argc, char** argv)
|
||||
// if (!(in interactive-tool mode))
|
||||
{
|
||||
mCommand* msg;
|
||||
while (msg = msgPasser_Command.Retrieve())
|
||||
while ((msg = msgPasser_Command.Retrieve()) != NULL)
|
||||
{
|
||||
recent_activity = true;
|
||||
|
||||
@ -110,8 +115,8 @@ void BeginAtlas(int argc, char** argv)
|
||||
// that it's slightly dangerous - we have to just assume that
|
||||
// GetType is correct, since we can't use proper RTTI
|
||||
}
|
||||
handlers::const_iterator it = GetHandlers().find(name);
|
||||
if (it != GetHandlers().end())
|
||||
msgHandlers::const_iterator it = GetMsgHandlers().find(name);
|
||||
if (it != GetMsgHandlers().end())
|
||||
{
|
||||
it->second(msg);
|
||||
}
|
||||
@ -133,13 +138,13 @@ void BeginAtlas(int argc, char** argv)
|
||||
// Now do the same (roughly), for input events:
|
||||
{
|
||||
mInput* msg;
|
||||
while (msg = msgPasser_Input.Retrieve())
|
||||
while ((msg = msgPasser_Input.Retrieve()) != NULL)
|
||||
{
|
||||
recent_activity = true;
|
||||
|
||||
std::string name (msg->GetType());
|
||||
handlers::const_iterator it = GetHandlers().find(name);
|
||||
if (it != GetHandlers().end())
|
||||
msgHandlers::const_iterator it = GetMsgHandlers().find(name);
|
||||
if (it != GetMsgHandlers().end())
|
||||
{
|
||||
it->second(msg);
|
||||
}
|
||||
@ -175,4 +180,6 @@ void BeginAtlas(int argc, char** argv)
|
||||
// TODO: delete all remaining messages, to avoid memory leak warnings
|
||||
|
||||
pthread_join(gameThread, NULL);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
44
source/tools/atlas/GameInterface/Handlers/Command.cpp
Normal file
44
source/tools/atlas/GameInterface/Handlers/Command.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "MessageHandler.h"
|
||||
|
||||
#include "../CommandProc.h"
|
||||
|
||||
namespace AtlasMessage {
|
||||
|
||||
|
||||
void fDoCommand(IMessage* msg)
|
||||
{
|
||||
mDoCommand* cmd = static_cast<mDoCommand*>(msg);
|
||||
|
||||
Command* c = NULL;
|
||||
cmdHandlers::const_iterator it = GetCmdHandlers().find("c" + cmd->name);
|
||||
if (it != GetCmdHandlers().end())
|
||||
{
|
||||
c = (it->second)(cmd->data);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_warn("Unrecognised command");
|
||||
return;
|
||||
}
|
||||
|
||||
GetCommandProc().Submit(c);
|
||||
}
|
||||
REGISTER(DoCommand);
|
||||
|
||||
|
||||
void fUndoCommand(IMessage*)
|
||||
{
|
||||
GetCommandProc().Undo();
|
||||
}
|
||||
REGISTER(UndoCommand);
|
||||
|
||||
|
||||
void fRedoCommand(IMessage*)
|
||||
{
|
||||
GetCommandProc().Redo();
|
||||
}
|
||||
REGISTER(RedoCommand);
|
||||
|
||||
}
|
@ -2,34 +2,64 @@
|
||||
|
||||
#include "MessageHandler.h"
|
||||
|
||||
#include "../CommandProc.h"
|
||||
|
||||
#include "graphics/Terrain.h"
|
||||
#include "ps/Game.h"
|
||||
|
||||
namespace AtlasMessage {
|
||||
|
||||
BEGIN_COMMAND(AlterElevation)
|
||||
|
||||
void fAlterElevation(IMessage* msg)
|
||||
{
|
||||
mAlterElevation* cmd = static_cast<mAlterElevation*>(msg);
|
||||
// TODO: much more efficient version of this, and without the memory leaks
|
||||
u16* OldTerrain;
|
||||
u16* NewTerrain;
|
||||
|
||||
// TODO:
|
||||
// Create something like the AtlasCommandProcessor, so that undo is
|
||||
// possible: Push an AlterElevationCommand onto the command stack,
|
||||
// which has Do and Undo methods, and also has Merge (so multiple
|
||||
// consecutive elevation-altering moments can be combined into a single
|
||||
// brush stroke, to conserve memory and also so 'undo' undoes the entire
|
||||
// stroke at once).
|
||||
void Construct()
|
||||
{
|
||||
OldTerrain = NewTerrain = NULL;
|
||||
}
|
||||
void Destruct()
|
||||
{
|
||||
delete OldTerrain;
|
||||
delete NewTerrain;
|
||||
}
|
||||
|
||||
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
||||
void Do() {
|
||||
|
||||
u16* heightmap = terrain->GetHeightMap();
|
||||
int size = terrain->GetVerticesPerSide();
|
||||
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
||||
|
||||
int x = (int)cmd->pos.x;
|
||||
int z = (int)cmd->pos.z;
|
||||
terrain->RaiseVertex(x, z, (int)cmd->amount);
|
||||
terrain->MakeDirty(x, z, x, z);
|
||||
}
|
||||
REGISTER(AlterElevation);
|
||||
int verts = terrain->GetVerticesPerSide()*terrain->GetVerticesPerSide();
|
||||
OldTerrain = new u16[verts];
|
||||
memcpy(OldTerrain, terrain->GetHeightMap(), verts*sizeof(u16));
|
||||
|
||||
int x = (int)d->pos.x;
|
||||
int z = (int)d->pos.z;
|
||||
terrain->RaiseVertex(x, z, (int)d->amount);
|
||||
terrain->MakeDirty(x, z, x, z);
|
||||
|
||||
}
|
||||
|
||||
void Undo() {
|
||||
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
||||
if (! NewTerrain)
|
||||
{
|
||||
int verts = terrain->GetVerticesPerSide()*terrain->GetVerticesPerSide();
|
||||
NewTerrain = new u16[verts];
|
||||
memcpy(NewTerrain, terrain->GetHeightMap(), verts*sizeof(u16));
|
||||
}
|
||||
terrain->SetHeightMap(OldTerrain); // CTerrain duplicates the data
|
||||
}
|
||||
|
||||
void Redo() {
|
||||
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
||||
terrain->SetHeightMap(NewTerrain); // CTerrain duplicates the data
|
||||
}
|
||||
|
||||
void MergeWithSelf(cAlterElevation* prev) {
|
||||
debug_warn("TODO");
|
||||
}
|
||||
|
||||
END_COMMAND(AlterElevation);
|
||||
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ REGISTER(CommandString_init);
|
||||
void fCommandString_shutdown(IMessage*)
|
||||
{
|
||||
Shutdown_();
|
||||
g_GameLoop->rendering = false;
|
||||
}
|
||||
REGISTER(CommandString_shutdown);
|
||||
|
||||
|
@ -5,13 +5,13 @@
|
||||
namespace AtlasMessage
|
||||
{
|
||||
|
||||
handlers& GetHandlers()
|
||||
msgHandlers& GetMsgHandlers()
|
||||
{
|
||||
// Make sure this is initialised when it's first required, rather than
|
||||
// hoping to be lucky with static initialisation order.
|
||||
// (TODO: But is it safe to be sticking things into STL containers during
|
||||
// static initialisation?)
|
||||
static handlers h;
|
||||
static msgHandlers h;
|
||||
return h;
|
||||
}
|
||||
|
||||
|
@ -6,15 +6,15 @@ namespace AtlasMessage
|
||||
// (Random note: Be careful not to give handler .cpp files the same name
|
||||
// as any other file in the project, because it makes everything very confused)
|
||||
|
||||
typedef void (*handler)(IMessage*);
|
||||
typedef std::map<std::string, handler> handlers;
|
||||
extern handlers& GetHandlers();
|
||||
typedef void (*msgHandler)(IMessage*);
|
||||
typedef std::map<std::string, msgHandler> msgHandlers;
|
||||
extern msgHandlers& GetMsgHandlers();
|
||||
|
||||
#define CAT1(a,b) a##b
|
||||
#define CAT2(a,b) CAT1(a,b)
|
||||
|
||||
#define REGISTER(t) namespace CAT2(hndlr_, __LINE__) { struct init { init() { \
|
||||
bool notAlreadyRegisted = GetHandlers().insert(std::pair<std::string, handler>(#t, &f##t)).second; \
|
||||
bool notAlreadyRegisted = GetMsgHandlers().insert(std::pair<std::string, msgHandler>(#t, &f##t)).second; \
|
||||
assert(notAlreadyRegisted); \
|
||||
} } init; };
|
||||
|
||||
|
@ -2,10 +2,22 @@
|
||||
|
||||
#include "MessagePasserImpl.h"
|
||||
|
||||
#define MESSAGE_TRACE 0
|
||||
|
||||
#if MESSAGE_TRACE
|
||||
#include "Messages.h" // for mCommand implementation
|
||||
#endif
|
||||
|
||||
using namespace AtlasMessage;
|
||||
|
||||
|
||||
template<typename T> void MessagePasserImpl<T>::Add(T* msg)
|
||||
{
|
||||
debug_assert(msg);
|
||||
|
||||
#if MESSAGE_TRACE
|
||||
debug_printf("Add %s\n", msg->GetType());
|
||||
#endif
|
||||
m_Mutex.Lock();
|
||||
|
||||
m_Queue.push(msg);
|
||||
@ -30,6 +42,10 @@ template <typename T> T* MessagePasserImpl<T>::Retrieve()
|
||||
|
||||
m_Mutex.Unlock();
|
||||
|
||||
#if MESSAGE_TRACE
|
||||
if (msg) debug_printf("Retrieved %s\n", msg->GetType());
|
||||
#endif
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
@ -46,4 +62,4 @@ MessagePasser<mInput>* g_MessagePasser_Input = NULL;
|
||||
|
||||
// Explicit instantiation:
|
||||
template MessagePasserImpl<mCommand>;
|
||||
template MessagePasserImpl<mInput>;
|
||||
template MessagePasserImpl<mInput>;
|
||||
|
@ -31,8 +31,8 @@ struct IMessage
|
||||
struct mCommand : public IMessage {};
|
||||
struct mInput : public IMessage {};
|
||||
|
||||
#define COMMAND(t) struct m##t : public mCommand { const char* GetType() const { return #t; }
|
||||
#define INPUT(t) struct m##t : public mInput { const char* GetType() const { return #t; }
|
||||
#define COMMAND(t) struct m##t : public mCommand { const char* GetType() const { return #t; } private: const m##t& operator=(const m##t&); public:
|
||||
#define INPUT(t) struct m##t : public mInput { const char* GetType() const { return #t; } private: const m##t& operator=(const m##t&); public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -84,11 +84,51 @@ mToolEnd() {}
|
||||
};
|
||||
*/
|
||||
|
||||
/*
|
||||
COMMAND(AlterElevation)
|
||||
mAlterElevation(Position pos_, float amount_) : pos(pos_), amount(amount_) {}
|
||||
const Position pos;
|
||||
const float amount;
|
||||
};
|
||||
*/
|
||||
|
||||
COMMAND(WorldCommand)
|
||||
mWorldCommand() {}
|
||||
virtual void* CloneData() const = 0;
|
||||
};
|
||||
|
||||
COMMAND(DoCommand)
|
||||
mDoCommand(mWorldCommand* c) : name(c->GetType()), data(c->CloneData()) {}
|
||||
const std::string name;
|
||||
const void* data;
|
||||
};
|
||||
|
||||
COMMAND(UndoCommand)
|
||||
};
|
||||
|
||||
COMMAND(RedoCommand)
|
||||
};
|
||||
|
||||
|
||||
#define WORLDCOMMAND(t, merge) struct m##t : public mWorldCommand, public d##t { \
|
||||
m##t(const d##t& d) : d##t(d) {} \
|
||||
const char* GetType() const { return #t; } \
|
||||
bool IsMergeable() { return merge; } \
|
||||
void* CloneData() const { return new d##t(*this); } \
|
||||
private: \
|
||||
const m##t& operator=(const m##t&);\
|
||||
};
|
||||
|
||||
struct dAlterElevation {
|
||||
dAlterElevation(Position pos_, float amount_) : pos(pos_), amount(amount_) {}
|
||||
const Position pos;
|
||||
const float amount;
|
||||
private:
|
||||
const dAlterElevation& operator=(const dAlterElevation&);
|
||||
};
|
||||
WORLDCOMMAND(AlterElevation, true)
|
||||
|
||||
#undef WORLDCOMMAND
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user