forked from 0ad/0ad
# Atlas updates: better unit ownership control; fixed bottom-bar display; fixed iterator problem in undo; renamed 'd' to 'msg' for consistency
This was SVN commit r3836.
This commit is contained in:
parent
37663d86fb
commit
9e74e3a077
@ -51,6 +51,9 @@ public:
|
|||||||
// Set player ID of this unit
|
// Set player ID of this unit
|
||||||
void SetPlayerID(int id);
|
void SetPlayerID(int id);
|
||||||
|
|
||||||
|
// Get player ID of this unit
|
||||||
|
int GetPlayerID() { return m_PlayerID; }
|
||||||
|
|
||||||
int GetID() const { return m_ID; }
|
int GetID() const { return m_ID; }
|
||||||
void SetID(int id) { m_ID = id; }
|
void SetID(int id) { m_ID = id; }
|
||||||
|
|
||||||
|
28
source/tools/atlas/AtlasUI/General/Observable.h
Normal file
28
source/tools/atlas/AtlasUI/General/Observable.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef OBSERVABLE_H__
|
||||||
|
#define OBSERVABLE_H__
|
||||||
|
|
||||||
|
#include <boost/signals.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
|
typedef boost::signals::connection ObservableConnection;
|
||||||
|
|
||||||
|
template <typename T> class Observable : public T
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template<typename C> ObservableConnection RegisterObserver(int order, void (C::*callback) (const T&), C* obj)
|
||||||
|
{
|
||||||
|
return m_Signal.connect(order, boost::bind(std::mem_fun(callback), obj, _1));
|
||||||
|
}
|
||||||
|
void RemoveObserver(ObservableConnection handle)
|
||||||
|
{
|
||||||
|
handle.disconnect();
|
||||||
|
}
|
||||||
|
void NotifyObservers()
|
||||||
|
{
|
||||||
|
m_Signal(*this);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
boost::signal<void (const T&)> m_Signal;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OBSERVABLE_H__
|
@ -34,6 +34,8 @@
|
|||||||
#include <boost/preprocessor/seq/for_each_i.hpp>
|
#include <boost/preprocessor/seq/for_each_i.hpp>
|
||||||
#include <boost/preprocessor/tuple/elem.hpp>
|
#include <boost/preprocessor/tuple/elem.hpp>
|
||||||
#include <boost/preprocessor/punctuation/comma_if.hpp>
|
#include <boost/preprocessor/punctuation/comma_if.hpp>
|
||||||
|
#include <boost/signals.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
// Nicer memory-leak detection:
|
// Nicer memory-leak detection:
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
@ -36,13 +36,16 @@ protected:
|
|||||||
if (event.GetSelection() != -1)
|
if (event.GetSelection() != -1)
|
||||||
newPage = wxDynamicCast(GetPage(event.GetSelection()), Sidebar);
|
newPage = wxDynamicCast(GetPage(event.GetSelection()), Sidebar);
|
||||||
|
|
||||||
|
if (oldPage)
|
||||||
|
oldPage->OnSwitchAway();
|
||||||
|
|
||||||
if (newPage)
|
if (newPage)
|
||||||
newPage->OnSwitchTo();
|
newPage->OnSwitchTo();
|
||||||
|
|
||||||
if (m_Splitter->IsSplit())
|
if (m_Splitter->IsSplit())
|
||||||
{
|
{
|
||||||
wxWindow* bottom;
|
wxWindow* bottom;
|
||||||
if (newPage && NULL != (bottom = newPage->GetBottomBar(m_Splitter)))
|
if (newPage && NULL != (bottom = newPage->GetBottomBar()))
|
||||||
{
|
{
|
||||||
m_Splitter->ReplaceWindow(m_Splitter->GetWindow2(), bottom);
|
m_Splitter->ReplaceWindow(m_Splitter->GetWindow2(), bottom);
|
||||||
}
|
}
|
||||||
@ -54,7 +57,7 @@ protected:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
wxWindow* bottom;
|
wxWindow* bottom;
|
||||||
if (newPage && NULL != (bottom = newPage->GetBottomBar(m_Splitter)))
|
if (newPage && NULL != (bottom = newPage->GetBottomBar()))
|
||||||
{
|
{
|
||||||
m_Splitter->SplitHorizontally(m_Splitter->GetWindow1(), bottom);
|
m_Splitter->SplitHorizontally(m_Splitter->GetWindow1(), bottom);
|
||||||
}
|
}
|
||||||
@ -104,14 +107,24 @@ void SectionLayout::Build()
|
|||||||
{
|
{
|
||||||
// TODO: wxWidgets bug (http://sourceforge.net/tracker/index.php?func=detail&aid=1298803&group_id=9863&atid=109863)
|
// TODO: wxWidgets bug (http://sourceforge.net/tracker/index.php?func=detail&aid=1298803&group_id=9863&atid=109863)
|
||||||
// - pressing menu keys (e.g. alt+f) with notebook tab focussed causes application to freeze
|
// - pressing menu keys (e.g. alt+f) with notebook tab focussed causes application to freeze
|
||||||
wxNotebook* sidebar = new SidebarNotebook(m_HorizSplitter, m_VertSplitter);
|
SidebarNotebook* sidebarBook = new SidebarNotebook(m_HorizSplitter, m_VertSplitter);
|
||||||
sidebar->AddPage(new MapSidebar(sidebar), _("Map"), false);
|
Sidebar* sidebar;
|
||||||
sidebar->AddPage(new TerrainSidebar(sidebar), _("Terrain"), false);
|
|
||||||
sidebar->AddPage(new ObjectSidebar(sidebar), _("Object"), false);
|
#define ADD_SIDEBAR(classname, label) \
|
||||||
|
sidebar = new classname(sidebarBook, m_VertSplitter); \
|
||||||
|
if (sidebar->GetBottomBar()) \
|
||||||
|
sidebar->GetBottomBar()->Show(false); \
|
||||||
|
sidebarBook->AddPage(sidebar, _(label));
|
||||||
|
|
||||||
|
ADD_SIDEBAR(MapSidebar, "Map");
|
||||||
|
ADD_SIDEBAR(TerrainSidebar, "Terrain");
|
||||||
|
ADD_SIDEBAR(ObjectSidebar, "Object");
|
||||||
|
|
||||||
|
#undef ADD_SIDEBAR
|
||||||
|
|
||||||
m_VertSplitter->SetDefaultSashPosition(-165);
|
m_VertSplitter->SetDefaultSashPosition(-165);
|
||||||
m_VertSplitter->Initialize(m_Canvas);
|
m_VertSplitter->Initialize(m_Canvas);
|
||||||
|
|
||||||
m_HorizSplitter->SetDefaultSashPosition(200);
|
m_HorizSplitter->SetDefaultSashPosition(200);
|
||||||
m_HorizSplitter->SplitVertically(sidebar, m_VertSplitter);
|
m_HorizSplitter->SplitVertically(sidebarBook, m_VertSplitter);
|
||||||
}
|
}
|
||||||
|
@ -4,23 +4,27 @@
|
|||||||
|
|
||||||
IMPLEMENT_DYNAMIC_CLASS(Sidebar, wxPanel)
|
IMPLEMENT_DYNAMIC_CLASS(Sidebar, wxPanel)
|
||||||
|
|
||||||
Sidebar::Sidebar(wxWindow* parent)
|
Sidebar::Sidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer)
|
||||||
: wxPanel(parent), m_AlreadyDisplayed(false)
|
: wxPanel(sidebarContainer), m_BottomBar(NULL), m_AlreadyDisplayed(false)
|
||||||
{
|
{
|
||||||
m_MainSizer = new wxBoxSizer(wxVERTICAL);
|
m_MainSizer = new wxBoxSizer(wxVERTICAL);
|
||||||
SetSizer(m_MainSizer);
|
SetSizer(m_MainSizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxWindow* Sidebar::GetBottomBar(wxWindow* WXUNUSED(parent))
|
void Sidebar::OnSwitchAway()
|
||||||
{
|
{
|
||||||
return NULL;
|
if (m_BottomBar)
|
||||||
|
m_BottomBar->Show(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sidebar::OnSwitchTo()
|
void Sidebar::OnSwitchTo()
|
||||||
{
|
{
|
||||||
if (m_AlreadyDisplayed)
|
if (! m_AlreadyDisplayed)
|
||||||
return;
|
{
|
||||||
|
|
||||||
m_AlreadyDisplayed = true;
|
m_AlreadyDisplayed = true;
|
||||||
OnFirstDisplay();
|
OnFirstDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_BottomBar)
|
||||||
|
m_BottomBar->Show(true);
|
||||||
|
}
|
||||||
|
@ -7,20 +7,21 @@ class Sidebar : public wxPanel
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Sidebar() {}
|
Sidebar() {}
|
||||||
Sidebar(wxWindow* parent);
|
Sidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer);
|
||||||
|
|
||||||
|
void OnSwitchAway();
|
||||||
void OnSwitchTo();
|
void OnSwitchTo();
|
||||||
|
|
||||||
virtual wxWindow* GetBottomBar(wxWindow* parent);
|
wxWindow* GetBottomBar() { return m_BottomBar; }
|
||||||
// called whenever the bottom bar is made visible; should usually be
|
|
||||||
// lazily constructed, then cached forever (to maximise responsiveness)
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxSizer* m_MainSizer; // vertical box sizer, used by most sidebars
|
wxSizer* m_MainSizer; // vertical box sizer, used by most sidebars
|
||||||
|
|
||||||
|
wxWindow* m_BottomBar; // window that goes at the bottom of the screen; may be NULL
|
||||||
|
|
||||||
virtual void OnFirstDisplay() {}
|
virtual void OnFirstDisplay() {}
|
||||||
// should be overridden when sidebars need to do expensive construction,
|
// should be overridden when sidebars need to do expensive construction,
|
||||||
// so it can be delayed until it is required
|
// so it can be delayed until it is required;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_AlreadyDisplayed;
|
bool m_AlreadyDisplayed;
|
||||||
|
@ -69,8 +69,8 @@ static void GenerateRMS(void* data)
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
MapSidebar::MapSidebar(wxWindow* parent)
|
MapSidebar::MapSidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer)
|
||||||
: Sidebar(parent)
|
: Sidebar(sidebarContainer, bottomBarContainer)
|
||||||
{
|
{
|
||||||
// TODO: Less ugliness
|
// TODO: Less ugliness
|
||||||
// TODO: Intercept arrow keys and send them to the GL window
|
// TODO: Intercept arrow keys and send them to the GL window
|
||||||
|
@ -3,5 +3,5 @@
|
|||||||
class MapSidebar : public Sidebar
|
class MapSidebar : public Sidebar
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MapSidebar(wxWindow* parent);
|
MapSidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer);
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
#include "Buttons/ActionButton.h"
|
#include "Buttons/ActionButton.h"
|
||||||
#include "Buttons/ToolButton.h"
|
#include "Buttons/ToolButton.h"
|
||||||
#include "ScenarioEditor/Tools/Common/Tools.h"
|
#include "ScenarioEditor/Tools/Common/Tools.h"
|
||||||
#include "ScenarioEditor/Tools/Common/UnitSettings.h"
|
#include "ScenarioEditor/Tools/Common/ObjectSettings.h"
|
||||||
|
#include "ScenarioEditor/Tools/Common/MiscState.h"
|
||||||
|
|
||||||
#include "GameInterface/Messages.h"
|
#include "GameInterface/Messages.h"
|
||||||
|
|
||||||
@ -62,8 +63,8 @@ struct ObjectSidebarImpl
|
|||||||
std::vector<AtlasMessage::sObjectsListItem> m_Objects;
|
std::vector<AtlasMessage::sObjectsListItem> m_Objects;
|
||||||
};
|
};
|
||||||
|
|
||||||
ObjectSidebar::ObjectSidebar(wxWindow* parent)
|
ObjectSidebar::ObjectSidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer)
|
||||||
: Sidebar(parent), p(new ObjectSidebarImpl())
|
: Sidebar(sidebarContainer, bottomBarContainer), p(new ObjectSidebarImpl())
|
||||||
{
|
{
|
||||||
wxArrayString strings;
|
wxArrayString strings;
|
||||||
strings.Add(_("Entities"));
|
strings.Add(_("Entities"));
|
||||||
@ -72,6 +73,8 @@ ObjectSidebar::ObjectSidebar(wxWindow* parent)
|
|||||||
|
|
||||||
p->m_ObjectListBox = new ObjectSelectListBox(this);
|
p->m_ObjectListBox = new ObjectSelectListBox(this);
|
||||||
m_MainSizer->Add(p->m_ObjectListBox, wxSizerFlags().Proportion(1).Expand());
|
m_MainSizer->Add(p->m_ObjectListBox, wxSizerFlags().Proportion(1).Expand());
|
||||||
|
|
||||||
|
m_BottomBar = new ObjectBottomBar(bottomBarContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectSidebar::~ObjectSidebar()
|
ObjectSidebar::~ObjectSidebar()
|
||||||
@ -79,15 +82,6 @@ ObjectSidebar::~ObjectSidebar()
|
|||||||
delete p;
|
delete p;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxWindow* ObjectSidebar::GetBottomBar(wxWindow* parent)
|
|
||||||
{
|
|
||||||
if (p->m_BottomBar)
|
|
||||||
return p->m_BottomBar;
|
|
||||||
|
|
||||||
p->m_BottomBar = new ObjectBottomBar(parent);
|
|
||||||
return p->m_BottomBar;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectSidebar::OnFirstDisplay()
|
void ObjectSidebar::OnFirstDisplay()
|
||||||
{
|
{
|
||||||
AtlasMessage::qGetObjectsList qry;
|
AtlasMessage::qGetObjectsList qry;
|
||||||
@ -118,15 +112,27 @@ class PlayerComboBox : public wxComboBox
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PlayerComboBox(wxWindow* parent, wxArrayString& choices)
|
PlayerComboBox(wxWindow* parent, wxArrayString& choices)
|
||||||
: wxComboBox(parent, -1, choices[g_UnitSettings.GetPlayerID()], wxDefaultPosition, wxDefaultSize, choices, wxCB_READONLY)
|
: wxComboBox(parent, -1, choices[g_ObjectSettings.GetPlayerID()], wxDefaultPosition, wxDefaultSize, choices, wxCB_READONLY)
|
||||||
{
|
{
|
||||||
|
m_Conn = g_SelectedObjects.RegisterObserver(1, &PlayerComboBox::OnSelectionChange, this);
|
||||||
|
}
|
||||||
|
~PlayerComboBox()
|
||||||
|
{
|
||||||
|
g_SelectedObjects.RemoveObserver(m_Conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
ObservableConnection m_Conn;
|
||||||
|
|
||||||
|
void OnSelectionChange(const std::vector<AtlasMessage::ObjectID>& selection)
|
||||||
|
{
|
||||||
|
SetSelection(g_ObjectSettings.GetPlayerID());
|
||||||
|
}
|
||||||
|
|
||||||
void OnSelect(wxCommandEvent& evt)
|
void OnSelect(wxCommandEvent& evt)
|
||||||
{
|
{
|
||||||
g_UnitSettings.SetPlayerID(evt.GetInt());
|
g_ObjectSettings.SetPlayerID(evt.GetInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE();
|
DECLARE_EVENT_TABLE();
|
||||||
@ -135,6 +141,7 @@ BEGIN_EVENT_TABLE(PlayerComboBox, wxComboBox)
|
|||||||
EVT_COMBOBOX(wxID_ANY, OnSelect)
|
EVT_COMBOBOX(wxID_ANY, OnSelect)
|
||||||
END_EVENT_TABLE();
|
END_EVENT_TABLE();
|
||||||
|
|
||||||
|
|
||||||
ObjectBottomBar::ObjectBottomBar(wxWindow* parent)
|
ObjectBottomBar::ObjectBottomBar(wxWindow* parent)
|
||||||
: wxPanel(parent, wxID_ANY)
|
: wxPanel(parent, wxID_ANY)
|
||||||
{
|
{
|
||||||
@ -153,5 +160,6 @@ ObjectBottomBar::ObjectBottomBar(wxWindow* parent)
|
|||||||
players.Add(_("Player 8"));
|
players.Add(_("Player 8"));
|
||||||
wxComboBox* playerSelect = new PlayerComboBox(this, players);
|
wxComboBox* playerSelect = new PlayerComboBox(this, players);
|
||||||
|
|
||||||
|
sizer->Add(playerSelect);
|
||||||
SetSizer(sizer);
|
SetSizer(sizer);
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,8 @@ struct ObjectSidebarImpl;
|
|||||||
class ObjectSidebar : public Sidebar
|
class ObjectSidebar : public Sidebar
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ObjectSidebar(wxWindow* parent);
|
ObjectSidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer);
|
||||||
~ObjectSidebar();
|
~ObjectSidebar();
|
||||||
wxWindow* GetBottomBar(wxWindow* parent);
|
|
||||||
void SetObjectFilter(int type);
|
void SetObjectFilter(int type);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -13,8 +13,20 @@
|
|||||||
|
|
||||||
#include "wx/spinctrl.h"
|
#include "wx/spinctrl.h"
|
||||||
|
|
||||||
TerrainSidebar::TerrainSidebar(wxWindow* parent)
|
class TextureNotebook;
|
||||||
: Sidebar(parent), m_BottomBar(NULL)
|
|
||||||
|
class TerrainBottomBar : public wxPanel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TerrainBottomBar(wxWindow* parent);
|
||||||
|
void LoadTerrain();
|
||||||
|
private:
|
||||||
|
TextureNotebook* m_Textures;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
TerrainSidebar::TerrainSidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer)
|
||||||
|
: Sidebar(sidebarContainer, bottomBarContainer)
|
||||||
{
|
{
|
||||||
// TODO: Less ugliness
|
// TODO: Less ugliness
|
||||||
|
|
||||||
@ -36,15 +48,12 @@ TerrainSidebar::TerrainSidebar(wxWindow* parent)
|
|||||||
m_MainSizer->Add(sizer);
|
m_MainSizer->Add(sizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_BottomBar = new TerrainBottomBar(bottomBarContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxWindow* TerrainSidebar::GetBottomBar(wxWindow* parent)
|
void TerrainSidebar::OnFirstDisplay()
|
||||||
{
|
{
|
||||||
if (m_BottomBar)
|
static_cast<TerrainBottomBar*>(m_BottomBar)->LoadTerrain();
|
||||||
return m_BottomBar;
|
|
||||||
|
|
||||||
m_BottomBar = new TerrainBottomBar(parent);
|
|
||||||
return m_BottomBar;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -145,6 +154,13 @@ public:
|
|||||||
TextureNotebook(wxWindow *parent)
|
TextureNotebook(wxWindow *parent)
|
||||||
: wxNotebook(parent, wxID_ANY/*, wxDefaultPosition, wxDefaultSize, wxNB_FIXEDWIDTH*/)
|
: wxNotebook(parent, wxID_ANY/*, wxDefaultPosition, wxDefaultSize, wxNB_FIXEDWIDTH*/)
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadTerrain()
|
||||||
|
{
|
||||||
|
DeleteAllPages();
|
||||||
|
m_TerrainGroups.Clear();
|
||||||
|
|
||||||
// Get the list of terrain groups from the engine
|
// Get the list of terrain groups from the engine
|
||||||
AtlasMessage::qGetTerrainGroups qry;
|
AtlasMessage::qGetTerrainGroups qry;
|
||||||
qry.Post();
|
qry.Post();
|
||||||
@ -164,7 +180,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void OnPageChanged(wxNotebookEvent& event)
|
void OnPageChanged(wxNotebookEvent& event)
|
||||||
{
|
{
|
||||||
if (event.GetSelection() != -1)
|
if (event.GetSelection() >= 0 && event.GetSelection() < (int)GetPageCount())
|
||||||
{
|
{
|
||||||
static_cast<TextureNotebookPage*>(GetPage(event.GetSelection()))->OnDisplay();
|
static_cast<TextureNotebookPage*>(GetPage(event.GetSelection()))->OnDisplay();
|
||||||
}
|
}
|
||||||
@ -186,7 +202,12 @@ TerrainBottomBar::TerrainBottomBar(wxWindow* parent)
|
|||||||
: wxPanel(parent, wxID_ANY)
|
: wxPanel(parent, wxID_ANY)
|
||||||
{
|
{
|
||||||
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
wxNotebook* notebook = new TextureNotebook(this);
|
m_Textures = new TextureNotebook(this);
|
||||||
sizer->Add(notebook, wxSizerFlags().Expand().Proportion(1));
|
sizer->Add(m_Textures, wxSizerFlags().Expand().Proportion(1));
|
||||||
SetSizer(sizer);
|
SetSizer(sizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TerrainBottomBar::LoadTerrain()
|
||||||
|
{
|
||||||
|
m_Textures->LoadTerrain();
|
||||||
|
}
|
@ -3,16 +3,8 @@
|
|||||||
class TerrainSidebar : public Sidebar
|
class TerrainSidebar : public Sidebar
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TerrainSidebar(wxWindow* parent);
|
TerrainSidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer);
|
||||||
wxWindow* GetBottomBar(wxWindow* parent);
|
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
wxWindow* m_BottomBar;
|
virtual void OnFirstDisplay();
|
||||||
};
|
|
||||||
|
|
||||||
class TerrainBottomBar : public wxPanel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TerrainBottomBar(wxWindow* parent);
|
|
||||||
private:
|
|
||||||
};
|
};
|
||||||
|
@ -3,3 +3,5 @@
|
|||||||
#include "MiscState.h"
|
#include "MiscState.h"
|
||||||
|
|
||||||
wxString g_SelectedTexture = _T("grass1_spring");
|
wxString g_SelectedTexture = _T("grass1_spring");
|
||||||
|
|
||||||
|
Observable<std::vector<AtlasMessage::ObjectID> > g_SelectedObjects;
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
#ifndef MISCSTATE_H__
|
#ifndef MISCSTATE_H__
|
||||||
#define MISCSTATE_H__
|
#define MISCSTATE_H__
|
||||||
|
|
||||||
|
#include "General/Observable.h"
|
||||||
|
|
||||||
|
namespace AtlasMessage
|
||||||
|
{
|
||||||
|
typedef int ObjectID;
|
||||||
|
}
|
||||||
|
|
||||||
extern wxString g_SelectedTexture;
|
extern wxString g_SelectedTexture;
|
||||||
|
|
||||||
|
// Observer order:
|
||||||
|
// 0 = g_UnitSettings
|
||||||
|
// 1 = things that want to access g_UnitSettings
|
||||||
|
extern Observable<std::vector<AtlasMessage::ObjectID> > g_SelectedObjects;
|
||||||
|
|
||||||
#endif // MISCSTATE_H__
|
#endif // MISCSTATE_H__
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "ObjectSettings.h"
|
||||||
|
|
||||||
|
#include "GameInterface/Messages.h"
|
||||||
|
#include "ScenarioEditor/Tools/Common/Tools.h"
|
||||||
|
|
||||||
|
ObjectSettings g_ObjectSettings;
|
||||||
|
|
||||||
|
ObjectSettings::ObjectSettings()
|
||||||
|
: m_PlayerID(0)
|
||||||
|
{
|
||||||
|
m_Conn = g_SelectedObjects.RegisterObserver(0, &ObjectSettings::OnSelectionChange, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectSettings::~ObjectSettings()
|
||||||
|
{
|
||||||
|
m_Conn.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ObjectSettings::GetPlayerID()
|
||||||
|
{
|
||||||
|
return m_PlayerID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectSettings::SetPlayerID(int playerID)
|
||||||
|
{
|
||||||
|
m_PlayerID = playerID;
|
||||||
|
PostToGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectSettings::SetActorSelections(const std::set<wxString>& selections)
|
||||||
|
{
|
||||||
|
m_ActorSelections = selections;
|
||||||
|
PostToGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
AtlasMessage::sObjectSettings ObjectSettings::GetSettings() const
|
||||||
|
{
|
||||||
|
AtlasMessage::sObjectSettings settings;
|
||||||
|
|
||||||
|
settings.player = m_PlayerID;
|
||||||
|
|
||||||
|
std::vector<std::wstring> selections;
|
||||||
|
for (std::set<wxString>::const_iterator it = m_ActorSelections.begin(); it != m_ActorSelections.end(); ++it)
|
||||||
|
selections.push_back(it->c_str());
|
||||||
|
settings.selections = selections;
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectSettings::OnSelectionChange(const std::vector<AtlasMessage::ObjectID>& selection)
|
||||||
|
{
|
||||||
|
// TODO: what would be the sensible action if nothing's selected?
|
||||||
|
// and if multiple objects are selected?
|
||||||
|
|
||||||
|
if (selection.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
AtlasMessage::qGetObjectSettings qry (selection[0]);
|
||||||
|
qry.Post();
|
||||||
|
|
||||||
|
m_PlayerID = qry.settings->player;
|
||||||
|
std::vector<std::wstring> selections = *qry.settings->selections;
|
||||||
|
|
||||||
|
m_ActorSelections.clear();
|
||||||
|
for (std::vector<std::wstring>::iterator it = selections.begin(); it != selections.end(); ++it)
|
||||||
|
m_ActorSelections.insert(it->c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectSettings::PostToGame()
|
||||||
|
{
|
||||||
|
if (g_SelectedObjects.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
POST_COMMAND(SetObjectSettings, (g_SelectedObjects[0], GetSettings()));
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
#ifndef ObjectSettings_H__
|
||||||
|
#define ObjectSettings_H__
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "ScenarioEditor/Tools/Common/MiscState.h"
|
||||||
|
|
||||||
|
namespace AtlasMessage
|
||||||
|
{
|
||||||
|
struct sObjectSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Various settings to be applied to newly created units, or to the currently
|
||||||
|
// selected unit. If a unit is selected or being previewed, it should match
|
||||||
|
// these settings.
|
||||||
|
class ObjectSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ObjectSettings();
|
||||||
|
~ObjectSettings();
|
||||||
|
|
||||||
|
int GetPlayerID();
|
||||||
|
void SetPlayerID(int playerID);
|
||||||
|
void SetActorSelections(const std::set<wxString>& selections);
|
||||||
|
|
||||||
|
AtlasMessage::sObjectSettings GetSettings() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// 0 = gaia, 1..inf = normal players
|
||||||
|
int m_PlayerID;
|
||||||
|
|
||||||
|
// Set of user-chosen actor selections, potentially a superset of any single
|
||||||
|
// actor's possible variants (since it doesn't get reset if you select
|
||||||
|
// a new actor, and will accumulate variant names)
|
||||||
|
std::set<wxString> m_ActorSelections;
|
||||||
|
|
||||||
|
// Observe changes to unit selection
|
||||||
|
ObservableConnection m_Conn;
|
||||||
|
void OnSelectionChange(const std::vector<AtlasMessage::ObjectID>& selection);
|
||||||
|
|
||||||
|
// Transfer current settings to the currently selected unit (if any)
|
||||||
|
void PostToGame();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ObjectSettings g_ObjectSettings;
|
||||||
|
|
||||||
|
#endif // ObjectSettings_H__
|
@ -3,7 +3,7 @@
|
|||||||
#include "Common/Tools.h"
|
#include "Common/Tools.h"
|
||||||
#include "Common/Brushes.h"
|
#include "Common/Brushes.h"
|
||||||
#include "Common/MiscState.h"
|
#include "Common/MiscState.h"
|
||||||
#include "Common/UnitSettings.h"
|
#include "Common/ObjectSettings.h"
|
||||||
#include "GameInterface/Messages.h"
|
#include "GameInterface/Messages.h"
|
||||||
|
|
||||||
using AtlasMessage::Position;
|
using AtlasMessage::Position;
|
||||||
@ -30,9 +30,9 @@ public:
|
|||||||
+ (m_ScreenPos.type1.y-m_Target.type1.y)*(m_ScreenPos.type1.y-m_Target.type1.y);
|
+ (m_ScreenPos.type1.y-m_Target.type1.y)*(m_ScreenPos.type1.y-m_Target.type1.y);
|
||||||
bool useTarget = (dragDistSq >= 16*16);
|
bool useTarget = (dragDistSq >= 16*16);
|
||||||
if (preview)
|
if (preview)
|
||||||
POST_MESSAGE(ObjectPreview, (m_ObjectID.c_str(), g_UnitSettings.GetSettings(), m_ObjPos, useTarget, m_Target, g_DefaultAngle));
|
POST_MESSAGE(ObjectPreview, (m_ObjectID.c_str(), g_ObjectSettings.GetSettings(), m_ObjPos, useTarget, m_Target, g_DefaultAngle));
|
||||||
else
|
else
|
||||||
POST_COMMAND(CreateObject, (m_ObjectID.c_str(), g_UnitSettings.GetSettings(), m_ObjPos, useTarget, m_Target, g_DefaultAngle));
|
POST_COMMAND(CreateObject, (m_ObjectID.c_str(), g_ObjectSettings.GetSettings(), m_ObjPos, useTarget, m_Target, g_DefaultAngle));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Init(void* initData)
|
virtual void Init(void* initData)
|
||||||
|
@ -11,7 +11,6 @@ class TransformObject : public StateDrivenTool<TransformObject>
|
|||||||
{
|
{
|
||||||
DECLARE_DYNAMIC_CLASS(TransformObject);
|
DECLARE_DYNAMIC_CLASS(TransformObject);
|
||||||
|
|
||||||
std::vector<AtlasMessage::ObjectID> m_Selection;
|
|
||||||
int m_dx, m_dy;
|
int m_dx, m_dy;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -22,8 +21,9 @@ public:
|
|||||||
|
|
||||||
void OnDisable()
|
void OnDisable()
|
||||||
{
|
{
|
||||||
m_Selection.clear();
|
g_SelectedObjects.clear();
|
||||||
POST_MESSAGE(SetSelectionPreview, (m_Selection));
|
g_SelectedObjects.NotifyObservers();
|
||||||
|
POST_MESSAGE(SetSelectionPreview, (g_SelectedObjects));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -36,25 +36,26 @@ public:
|
|||||||
if (evt.LeftDown())
|
if (evt.LeftDown())
|
||||||
{
|
{
|
||||||
// TODO: multiple selection
|
// TODO: multiple selection
|
||||||
AtlasMessage::qSelectObject qry(Position(evt.GetPosition()));
|
AtlasMessage::qPickObject qry(Position(evt.GetPosition()));
|
||||||
qry.Post();
|
qry.Post();
|
||||||
obj->m_Selection.clear();
|
g_SelectedObjects.clear();
|
||||||
if (AtlasMessage::ObjectIDIsValid(qry.id))
|
if (AtlasMessage::ObjectIDIsValid(qry.id))
|
||||||
{
|
{
|
||||||
obj->m_Selection.push_back(qry.id);
|
g_SelectedObjects.push_back(qry.id);
|
||||||
obj->m_dx = qry.offsetx;
|
obj->m_dx = qry.offsetx;
|
||||||
obj->m_dy = qry.offsety;
|
obj->m_dy = qry.offsety;
|
||||||
SET_STATE(Dragging);
|
SET_STATE(Dragging);
|
||||||
}
|
}
|
||||||
POST_MESSAGE(SetSelectionPreview, (obj->m_Selection));
|
g_SelectedObjects.NotifyObservers();
|
||||||
|
POST_MESSAGE(SetSelectionPreview, (g_SelectedObjects));
|
||||||
ScenarioEditor::GetCommandProc().FinaliseLastCommand();
|
ScenarioEditor::GetCommandProc().FinaliseLastCommand();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (evt.Dragging() && evt.RightIsDown() || evt.RightDown())
|
else if (evt.Dragging() && evt.RightIsDown() || evt.RightDown())
|
||||||
{
|
{
|
||||||
Position pos (evt.GetPosition());
|
Position pos (evt.GetPosition());
|
||||||
for (size_t i = 0; i < obj->m_Selection.size(); ++i)
|
for (size_t i = 0; i < g_SelectedObjects.size(); ++i)
|
||||||
POST_COMMAND(RotateObject, (obj->m_Selection[i], true, pos, 0.f));
|
POST_COMMAND(RotateObject, (g_SelectedObjects[i], true, pos, 0.f));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -65,10 +66,11 @@ public:
|
|||||||
{
|
{
|
||||||
if (type == KEY_CHAR && evt.GetKeyCode() == WXK_DELETE)
|
if (type == KEY_CHAR && evt.GetKeyCode() == WXK_DELETE)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < obj->m_Selection.size(); ++i)
|
for (size_t i = 0; i < g_SelectedObjects.size(); ++i)
|
||||||
POST_COMMAND(DeleteObject, (obj->m_Selection[i]));
|
POST_COMMAND(DeleteObject, (g_SelectedObjects[i]));
|
||||||
obj->m_Selection.clear();
|
g_SelectedObjects.clear();
|
||||||
POST_MESSAGE(SetSelectionPreview, (obj->m_Selection));
|
g_SelectedObjects.NotifyObservers();
|
||||||
|
POST_MESSAGE(SetSelectionPreview, (g_SelectedObjects));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -89,8 +91,8 @@ public:
|
|||||||
else if (evt.Dragging())
|
else if (evt.Dragging())
|
||||||
{
|
{
|
||||||
Position pos (evt.GetPosition() + wxPoint(obj->m_dx, obj->m_dy));
|
Position pos (evt.GetPosition() + wxPoint(obj->m_dx, obj->m_dy));
|
||||||
for (size_t i = 0; i < obj->m_Selection.size(); ++i)
|
for (size_t i = 0; i < g_SelectedObjects.size(); ++i)
|
||||||
POST_COMMAND(MoveObject, (obj->m_Selection[i], pos));
|
POST_COMMAND(MoveObject, (g_SelectedObjects[i], pos));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -8,15 +8,6 @@
|
|||||||
|
|
||||||
template<typename T> T next(T x) { T t = x; return ++t; }
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> void delete_fn(T* v) { delete v; }
|
template<typename T> void delete_fn(T* v) { delete v; }
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -63,7 +54,12 @@ void CommandProc::Destroy()
|
|||||||
|
|
||||||
void CommandProc::Submit(Command* cmd)
|
void CommandProc::Submit(Command* cmd)
|
||||||
{
|
{
|
||||||
delete_erase(m_Commands, next(m_CurrentCommand), m_Commands.end());
|
// If some commands have been undone at the time we insert this new one,
|
||||||
|
// delete and remove them all.
|
||||||
|
std::for_each(next(m_CurrentCommand), m_Commands.end(), delete_fn<Command>);
|
||||||
|
m_Commands.erase(next(m_CurrentCommand), m_Commands.end());
|
||||||
|
assert(next(m_CurrentCommand) == m_Commands.end());
|
||||||
|
|
||||||
m_CurrentCommand = m_Commands.insert(next(m_CurrentCommand), cmd);
|
m_CurrentCommand = m_Commands.insert(next(m_CurrentCommand), cmd);
|
||||||
|
|
||||||
(*m_CurrentCommand)->Do();
|
(*m_CurrentCommand)->Do();
|
||||||
|
@ -36,6 +36,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::list<Command*> m_Commands;
|
std::list<Command*> m_Commands;
|
||||||
typedef std::list<Command*>::iterator cmdIt;
|
typedef std::list<Command*>::iterator cmdIt;
|
||||||
|
// The 'current' command is the latest one which has been executed
|
||||||
|
// (ignoring any that have been undone)
|
||||||
cmdIt m_CurrentCommand;
|
cmdIt m_CurrentCommand;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -49,7 +51,7 @@ struct DataCommand : public Command // so commands can optionally override (De|C
|
|||||||
{
|
{
|
||||||
void Destruct() {};
|
void Destruct() {};
|
||||||
void Construct() {};
|
void Construct() {};
|
||||||
// MergeWithSelf should be overriden by commands, and implemented
|
// MergeWithSelf should be overridden by commands, and implemented
|
||||||
// to update 'prev' to include the effects of 'this'
|
// to update 'prev' to include the effects of 'this'
|
||||||
void MergeWithSelf(void*) { debug_warn("MergeWithSelf unimplemented in some command"); }
|
void MergeWithSelf(void*) { debug_warn("MergeWithSelf unimplemented in some command"); }
|
||||||
};
|
};
|
||||||
@ -57,10 +59,10 @@ struct DataCommand : public Command // so commands can optionally override (De|C
|
|||||||
#define BEGIN_COMMAND(t) \
|
#define BEGIN_COMMAND(t) \
|
||||||
class c##t : public DataCommand \
|
class c##t : public DataCommand \
|
||||||
{ \
|
{ \
|
||||||
d##t* d; \
|
d##t* msg; \
|
||||||
public: \
|
public: \
|
||||||
c##t(d##t* data) : d(data) { Construct(); } \
|
c##t(d##t* data) : msg(data) { Construct(); } \
|
||||||
~c##t() { Destruct(); AtlasMessage::ShareableDelete(d); /* d was allocated by mDoCommand() */ } \
|
~c##t() { Destruct(); AtlasMessage::ShareableDelete(msg); /* msg was allocated by mDoCommand() */ } \
|
||||||
static Command* Create(const void* data) { return new c##t ((d##t*)data); } \
|
static Command* Create(const void* data) { return new c##t ((d##t*)data); } \
|
||||||
virtual void Merge(Command* prev) { MergeWithSelf((c##t*)prev); } \
|
virtual void Merge(Command* prev) { MergeWithSelf((c##t*)prev); } \
|
||||||
virtual const char* GetType() const { return #t; }
|
virtual const char* GetType() const { return #t; }
|
||||||
|
@ -91,12 +91,12 @@ BEGIN_COMMAND(AlterElevation)
|
|||||||
|
|
||||||
void Do()
|
void Do()
|
||||||
{
|
{
|
||||||
int amount = (int)d->amount;
|
int amount = (int)msg->amount;
|
||||||
|
|
||||||
// If the framerate is very high, 'amount' is often very
|
// If the framerate is very high, 'amount' is often very
|
||||||
// small (even zero) so the integer truncation is significant
|
// small (even zero) so the integer truncation is significant
|
||||||
static float roundingError = 0.0;
|
static float roundingError = 0.0;
|
||||||
roundingError += d->amount - (float)amount;
|
roundingError += msg->amount - (float)amount;
|
||||||
if (roundingError >= 1.f)
|
if (roundingError >= 1.f)
|
||||||
{
|
{
|
||||||
amount += (int)roundingError;
|
amount += (int)roundingError;
|
||||||
@ -104,7 +104,7 @@ BEGIN_COMMAND(AlterElevation)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CVector3D previousPosition;
|
static CVector3D previousPosition;
|
||||||
d->pos->GetWorldSpace(g_CurrentBrush.m_Centre, previousPosition);
|
msg->pos->GetWorldSpace(g_CurrentBrush.m_Centre, previousPosition);
|
||||||
previousPosition = g_CurrentBrush.m_Centre;
|
previousPosition = g_CurrentBrush.m_Centre;
|
||||||
|
|
||||||
int x0, y0;
|
int x0, y0;
|
||||||
@ -160,10 +160,10 @@ BEGIN_COMMAND(FlattenElevation)
|
|||||||
|
|
||||||
void Do()
|
void Do()
|
||||||
{
|
{
|
||||||
int amount = (int)d->amount;
|
int amount = (int)msg->amount;
|
||||||
|
|
||||||
static CVector3D previousPosition;
|
static CVector3D previousPosition;
|
||||||
d->pos->GetWorldSpace(g_CurrentBrush.m_Centre, previousPosition);
|
msg->pos->GetWorldSpace(g_CurrentBrush.m_Centre, previousPosition);
|
||||||
previousPosition = g_CurrentBrush.m_Centre;
|
previousPosition = g_CurrentBrush.m_Centre;
|
||||||
|
|
||||||
int xc, yc;
|
int xc, yc;
|
||||||
|
@ -103,6 +103,54 @@ MESSAGEHANDLER(SetSelectionPreview)
|
|||||||
g_Selection = *msg->ids;
|
g_Selection = *msg->ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QUERYHANDLER(GetObjectSettings)
|
||||||
|
{
|
||||||
|
CUnit* unit = g_UnitMan.FindByID(msg->id);
|
||||||
|
if (! unit) return;
|
||||||
|
|
||||||
|
sObjectSettings settings;
|
||||||
|
settings.player = unit->GetPlayerID();
|
||||||
|
// TODO: actor variation
|
||||||
|
|
||||||
|
msg->settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN_COMMAND(SetObjectSettings)
|
||||||
|
|
||||||
|
int m_PlayerOld, m_PlayerNew;
|
||||||
|
|
||||||
|
void Do()
|
||||||
|
{
|
||||||
|
CUnit* unit = g_UnitMan.FindByID(msg->id);
|
||||||
|
if (! unit) return;
|
||||||
|
|
||||||
|
sObjectSettings settings = msg->settings;
|
||||||
|
|
||||||
|
m_PlayerOld = unit->GetPlayerID();
|
||||||
|
m_PlayerNew = settings.player;
|
||||||
|
// TODO: actor variations
|
||||||
|
|
||||||
|
Redo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Redo()
|
||||||
|
{
|
||||||
|
CUnit* unit = g_UnitMan.FindByID(msg->id);
|
||||||
|
if (! unit) return;
|
||||||
|
|
||||||
|
unit->SetPlayerID(m_PlayerNew);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Undo()
|
||||||
|
{
|
||||||
|
CUnit* unit = g_UnitMan.FindByID(msg->id);
|
||||||
|
if (! unit) return;
|
||||||
|
|
||||||
|
unit->SetPlayerID(m_PlayerOld);
|
||||||
|
}
|
||||||
|
|
||||||
|
END_COMMAND(SetObjectSettings);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
@ -234,21 +282,27 @@ BEGIN_COMMAND(CreateObject)
|
|||||||
|
|
||||||
void Do()
|
void Do()
|
||||||
{
|
{
|
||||||
m_Pos = GetUnitPos(d->pos);
|
// Calculate the position/orientation to create this unit with
|
||||||
m_Player = d->settings->player;
|
|
||||||
|
|
||||||
if (d->usetarget)
|
m_Pos = GetUnitPos(msg->pos);
|
||||||
|
|
||||||
|
if (msg->usetarget)
|
||||||
{
|
{
|
||||||
|
// Aim from m_Pos towards msg->target
|
||||||
CVector3D target;
|
CVector3D target;
|
||||||
d->target->GetWorldSpace(target, m_Pos.Y);
|
msg->target->GetWorldSpace(target, m_Pos.Y);
|
||||||
CVector2D dir(target.X-m_Pos.X, target.Z-m_Pos.Z);
|
CVector2D dir(target.X-m_Pos.X, target.Z-m_Pos.Z);
|
||||||
m_Angle = atan2(dir.x, dir.y);
|
m_Angle = atan2(dir.x, dir.y);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_Angle = d->angle;
|
m_Angle = msg->angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: variations too
|
||||||
|
m_Player = msg->settings->player;
|
||||||
|
|
||||||
|
// Get a new ID, for future reference to this unit
|
||||||
m_ID = g_UnitMan.GetNewID();
|
m_ID = g_UnitMan.GetNewID();
|
||||||
|
|
||||||
Redo();
|
Redo();
|
||||||
@ -258,7 +312,7 @@ BEGIN_COMMAND(CreateObject)
|
|||||||
{
|
{
|
||||||
bool isEntity;
|
bool isEntity;
|
||||||
CStrW name;
|
CStrW name;
|
||||||
if (ParseObjectName(*d->id, isEntity, name))
|
if (ParseObjectName(*msg->id, isEntity, name))
|
||||||
{
|
{
|
||||||
std::set<CStrW> selections;
|
std::set<CStrW> selections;
|
||||||
|
|
||||||
@ -309,6 +363,8 @@ BEGIN_COMMAND(CreateObject)
|
|||||||
m._31 = s; m._32 = 0.0f; m._33 = -c; m._34 = m_Pos.Z;
|
m._31 = s; m._32 = 0.0f; m._33 = -c; m._34 = m_Pos.Z;
|
||||||
m._41 = 0.0f; m._42 = 0.0f; m._43 = 0.0f; m._44 = 1.0f;
|
m._41 = 0.0f; m._42 = 0.0f; m._43 = 0.0f; m._44 = 1.0f;
|
||||||
unit->GetModel()->SetTransform(m);
|
unit->GetModel()->SetTransform(m);
|
||||||
|
|
||||||
|
unit->SetPlayerID(m_Player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -332,7 +388,7 @@ BEGIN_COMMAND(CreateObject)
|
|||||||
END_COMMAND(CreateObject)
|
END_COMMAND(CreateObject)
|
||||||
|
|
||||||
|
|
||||||
QUERYHANDLER(SelectObject)
|
QUERYHANDLER(PickObject)
|
||||||
{
|
{
|
||||||
float x, y;
|
float x, y;
|
||||||
msg->pos->GetScreenSpace(x, y);
|
msg->pos->GetScreenSpace(x, y);
|
||||||
@ -369,7 +425,7 @@ BEGIN_COMMAND(MoveObject)
|
|||||||
|
|
||||||
void Do()
|
void Do()
|
||||||
{
|
{
|
||||||
CUnit* unit = g_UnitMan.FindByID(d->id);
|
CUnit* unit = g_UnitMan.FindByID(msg->id);
|
||||||
if (! unit) return;
|
if (! unit) return;
|
||||||
|
|
||||||
if (unit->GetEntity())
|
if (unit->GetEntity())
|
||||||
@ -382,14 +438,14 @@ BEGIN_COMMAND(MoveObject)
|
|||||||
m_PosOld = m.GetTranslation();
|
m_PosOld = m.GetTranslation();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_PosNew = GetUnitPos(d->pos);
|
m_PosNew = GetUnitPos(msg->pos);
|
||||||
|
|
||||||
SetPos(m_PosNew);
|
SetPos(m_PosNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPos(CVector3D& pos)
|
void SetPos(CVector3D& pos)
|
||||||
{
|
{
|
||||||
CUnit* unit = g_UnitMan.FindByID(d->id);
|
CUnit* unit = g_UnitMan.FindByID(msg->id);
|
||||||
if (! unit) return;
|
if (! unit) return;
|
||||||
|
|
||||||
if (unit->GetEntity())
|
if (unit->GetEntity())
|
||||||
@ -430,23 +486,23 @@ BEGIN_COMMAND(RotateObject)
|
|||||||
|
|
||||||
void Do()
|
void Do()
|
||||||
{
|
{
|
||||||
CUnit* unit = g_UnitMan.FindByID(d->id);
|
CUnit* unit = g_UnitMan.FindByID(msg->id);
|
||||||
if (! unit) return;
|
if (! unit) return;
|
||||||
|
|
||||||
if (unit->GetEntity())
|
if (unit->GetEntity())
|
||||||
{
|
{
|
||||||
m_AngleOld = unit->GetEntity()->m_orientation;
|
m_AngleOld = unit->GetEntity()->m_orientation;
|
||||||
if (d->usetarget)
|
if (msg->usetarget)
|
||||||
{
|
{
|
||||||
CVector3D& pos = unit->GetEntity()->m_position;
|
CVector3D& pos = unit->GetEntity()->m_position;
|
||||||
CVector3D target;
|
CVector3D target;
|
||||||
d->target->GetWorldSpace(target, pos.Y);
|
msg->target->GetWorldSpace(target, pos.Y);
|
||||||
CVector2D dir(target.X-pos.X, target.Z-pos.Z);
|
CVector2D dir(target.X-pos.X, target.Z-pos.Z);
|
||||||
m_AngleNew = atan2(dir.x, dir.y);
|
m_AngleNew = atan2(dir.x, dir.y);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_AngleNew = d->angle;
|
m_AngleNew = msg->angle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -456,10 +512,10 @@ BEGIN_COMMAND(RotateObject)
|
|||||||
CVector3D pos = unit->GetModel()->GetTransform().GetTranslation();
|
CVector3D pos = unit->GetModel()->GetTransform().GetTranslation();
|
||||||
|
|
||||||
float s, c;
|
float s, c;
|
||||||
if (d->usetarget)
|
if (msg->usetarget)
|
||||||
{
|
{
|
||||||
CVector3D target;
|
CVector3D target;
|
||||||
d->target->GetWorldSpace(target, pos.Y);
|
msg->target->GetWorldSpace(target, pos.Y);
|
||||||
CVector2D dir(target.X-pos.X, target.Z-pos.Z);
|
CVector2D dir(target.X-pos.X, target.Z-pos.Z);
|
||||||
dir = dir.normalize();
|
dir = dir.normalize();
|
||||||
s = dir.x;
|
s = dir.x;
|
||||||
@ -467,8 +523,8 @@ BEGIN_COMMAND(RotateObject)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s = sinf(d->angle);
|
s = sinf(msg->angle);
|
||||||
c = cosf(d->angle);
|
c = cosf(msg->angle);
|
||||||
}
|
}
|
||||||
CMatrix3D& m = m_TransformNew;
|
CMatrix3D& m = m_TransformNew;
|
||||||
m._11 = -c; m._12 = 0.0f; m._13 = -s; m._14 = pos.X;
|
m._11 = -c; m._12 = 0.0f; m._13 = -s; m._14 = pos.X;
|
||||||
@ -482,7 +538,7 @@ BEGIN_COMMAND(RotateObject)
|
|||||||
|
|
||||||
void SetAngle(float angle, CMatrix3D& transform)
|
void SetAngle(float angle, CMatrix3D& transform)
|
||||||
{
|
{
|
||||||
CUnit* unit = g_UnitMan.FindByID(d->id);
|
CUnit* unit = g_UnitMan.FindByID(msg->id);
|
||||||
if (! unit) return;
|
if (! unit) return;
|
||||||
|
|
||||||
if (unit->GetEntity())
|
if (unit->GetEntity())
|
||||||
@ -542,7 +598,7 @@ BEGIN_COMMAND(DeleteObject)
|
|||||||
|
|
||||||
void Redo()
|
void Redo()
|
||||||
{
|
{
|
||||||
CUnit* unit = g_UnitMan.FindByID(d->id);
|
CUnit* unit = g_UnitMan.FindByID(msg->id);
|
||||||
if (! unit) return;
|
if (! unit) return;
|
||||||
|
|
||||||
if (unit->GetEntity())
|
if (unit->GetEntity())
|
||||||
|
@ -165,12 +165,12 @@ BEGIN_COMMAND(PaintTerrain)
|
|||||||
void Do()
|
void Do()
|
||||||
{
|
{
|
||||||
|
|
||||||
d->pos->GetWorldSpace(g_CurrentBrush.m_Centre);
|
msg->pos->GetWorldSpace(g_CurrentBrush.m_Centre);
|
||||||
|
|
||||||
int x0, y0;
|
int x0, y0;
|
||||||
g_CurrentBrush.GetBottomLeft(x0, y0);
|
g_CurrentBrush.GetBottomLeft(x0, y0);
|
||||||
|
|
||||||
CTextureEntry* texentry = g_TexMan.FindTexture(CStrW(*d->texture));
|
CTextureEntry* texentry = g_TexMan.FindTexture(CStrW(*msg->texture));
|
||||||
if (! texentry)
|
if (! texentry)
|
||||||
{
|
{
|
||||||
debug_warn("Can't find texentry"); // TODO: nicer error handling
|
debug_warn("Can't find texentry"); // TODO: nicer error handling
|
||||||
@ -182,7 +182,7 @@ BEGIN_COMMAND(PaintTerrain)
|
|||||||
for (int dx = 0; dx < g_CurrentBrush.m_W; ++dx)
|
for (int dx = 0; dx < g_CurrentBrush.m_W; ++dx)
|
||||||
{
|
{
|
||||||
if (g_CurrentBrush.Get(dx, dy) > 0.5f) // TODO: proper solid brushes
|
if (g_CurrentBrush.Get(dx, dy) > 0.5f) // TODO: proper solid brushes
|
||||||
m_TerrainDelta.PaintTile(x0+dx, y0+dy, texture, d->priority);
|
m_TerrainDelta.PaintTile(x0+dx, y0+dy, texture, msg->priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Game->GetWorld()->GetTerrain()->MakeDirty(x0, y0, x0+g_CurrentBrush.m_W, y0+g_CurrentBrush.m_H, RENDERDATA_UPDATE_INDICES);
|
g_Game->GetWorld()->GetTerrain()->MakeDirty(x0, y0, x0+g_CurrentBrush.m_W, y0+g_CurrentBrush.m_H, RENDERDATA_UPDATE_INDICES);
|
||||||
|
@ -102,16 +102,16 @@ QUERY(GetObjectsList,
|
|||||||
((std::vector<sObjectsListItem>, objects))
|
((std::vector<sObjectsListItem>, objects))
|
||||||
);
|
);
|
||||||
|
|
||||||
struct sUnitSettings
|
struct sObjectSettings
|
||||||
{
|
{
|
||||||
Shareable<int> player;
|
Shareable<int> player;
|
||||||
Shareable<std::vector<std::wstring> > selections;
|
Shareable<std::vector<std::wstring> > selections;
|
||||||
};
|
};
|
||||||
SHAREABLE_STRUCT(sUnitSettings);
|
SHAREABLE_STRUCT(sObjectSettings);
|
||||||
|
|
||||||
MESSAGE(ObjectPreview,
|
MESSAGE(ObjectPreview,
|
||||||
((std::wstring, id)) // or empty string => disable
|
((std::wstring, id)) // or empty string => disable
|
||||||
((sUnitSettings, settings))
|
((sObjectSettings, settings))
|
||||||
((Position, pos))
|
((Position, pos))
|
||||||
((bool, usetarget)) // true => use 'target' for orientation; false => use 'angle'
|
((bool, usetarget)) // true => use 'target' for orientation; false => use 'angle'
|
||||||
((Position, target))
|
((Position, target))
|
||||||
@ -120,7 +120,7 @@ MESSAGE(ObjectPreview,
|
|||||||
|
|
||||||
COMMAND(CreateObject, NOMERGE,
|
COMMAND(CreateObject, NOMERGE,
|
||||||
((std::wstring, id))
|
((std::wstring, id))
|
||||||
((sUnitSettings, settings))
|
((sObjectSettings, settings))
|
||||||
((Position, pos))
|
((Position, pos))
|
||||||
((bool, usetarget)) // true => use 'target' for orientation; false => use 'angle'
|
((bool, usetarget)) // true => use 'target' for orientation; false => use 'angle'
|
||||||
((Position, target))
|
((Position, target))
|
||||||
@ -183,7 +183,7 @@ COMMAND(PaintTerrain, MERGE,
|
|||||||
typedef int ObjectID;
|
typedef int ObjectID;
|
||||||
inline bool ObjectIDIsValid(ObjectID id) { return (id >= 0); }
|
inline bool ObjectIDIsValid(ObjectID id) { return (id >= 0); }
|
||||||
|
|
||||||
QUERY(SelectObject,
|
QUERY(PickObject,
|
||||||
((Position, pos))
|
((Position, pos))
|
||||||
,
|
,
|
||||||
((ObjectID, id))
|
((ObjectID, id))
|
||||||
@ -211,6 +211,18 @@ MESSAGE(SetSelectionPreview,
|
|||||||
((std::vector<ObjectID>, ids))
|
((std::vector<ObjectID>, ids))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
QUERY(GetObjectSettings,
|
||||||
|
((ObjectID, id))
|
||||||
|
,
|
||||||
|
((sObjectSettings, settings))
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMAND(SetObjectSettings, NOMERGE,
|
||||||
|
((ObjectID, id))
|
||||||
|
((sObjectSettings, settings))
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "MessagesSetup.h"
|
#include "MessagesSetup.h"
|
||||||
|
Loading…
Reference in New Issue
Block a user