forked from 0ad/0ad
Adds AI control to Atlas player panel
Adds camera control to Atlas player panel Changes map reader to handle per-player starting camera position. See #55 Adds entity name filter to Atlas object panel Fixes bug in Atlas map settings (caused crash when object panel was not loaded) This was SVN commit r9617.
This commit is contained in:
parent
7e1cbf6ece
commit
3e4d74480d
@ -25,6 +25,7 @@ Player.prototype.Init = function()
|
||||
this.diplomacy = []; // array of diplomatic stances for this player with respect to other players (including self)
|
||||
this.conquestCriticalEntitiesCount = 0; // number of owned units with ConquestCritical class
|
||||
this.phase = "village";
|
||||
this.startCam = undefined;
|
||||
};
|
||||
|
||||
Player.prototype.SetPlayerID = function(id)
|
||||
@ -225,6 +226,21 @@ Player.prototype.SetPhase = function(p)
|
||||
this.phase = p;
|
||||
};
|
||||
|
||||
Player.prototype.GetStartingCamera = function()
|
||||
{
|
||||
return this.startCam;
|
||||
}
|
||||
|
||||
Player.prototype.SetStartingCamera = function(pos)
|
||||
{
|
||||
this.startCam = pos;
|
||||
}
|
||||
|
||||
Player.prototype.HasStartingCamera = function()
|
||||
{
|
||||
return (this.startCam !== undefined);
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep track of population effects of all entities that
|
||||
* become owned or unowned by this player
|
||||
|
@ -128,6 +128,11 @@ function LoadPlayerSettings(settings)
|
||||
{ //Set default
|
||||
player.SetDiplomacy(diplomacy);
|
||||
}
|
||||
|
||||
if (getSetting(pData, pDefs, "StartingCamera") !== undefined)
|
||||
{
|
||||
player.SetStartingCamera(getSetting(pData, pDefs, "StartingCamera"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Copy gaia data from defaults
|
||||
|
@ -74,8 +74,7 @@ void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
|
||||
pTrigMan = pTrigMan_;
|
||||
pSimulation2 = pSimulation2_;
|
||||
m_PlayerID = playerID_;
|
||||
|
||||
m_CameraStartupTarget = INVALID_ENTITY;
|
||||
m_StartingCameraTarget = INVALID_ENTITY;
|
||||
|
||||
filename_xml = pathname.ChangeExtension(L".xml");
|
||||
|
||||
@ -146,8 +145,7 @@ void CMapReader::LoadRandomMap(const CStrW& scriptFile, const CScriptValRooted&
|
||||
pTrigMan = pTrigMan_;
|
||||
pSimulation2 = pSimulation2_;
|
||||
m_PlayerID = playerID_;
|
||||
|
||||
m_CameraStartupTarget = INVALID_ENTITY;
|
||||
m_StartingCameraTarget = INVALID_ENTITY;
|
||||
|
||||
// delete all existing entities
|
||||
if (pSimulation2)
|
||||
@ -284,13 +282,24 @@ int CMapReader::ApplyData()
|
||||
if (pLightEnv)
|
||||
*pLightEnv = m_LightEnv;
|
||||
|
||||
if (pGameView)
|
||||
CmpPtr<ICmpPlayerManager> cmpPlayerManager(*pSimulation2, SYSTEM_ENTITY);
|
||||
|
||||
if (pGameView && !cmpPlayerManager.null())
|
||||
{
|
||||
// Default to global camera (with constraints)
|
||||
pGameView->ResetCameraTarget(pGameView->GetCamera()->GetFocus());
|
||||
|
||||
if (m_CameraStartupTarget != INVALID_ENTITY)
|
||||
CmpPtr<ICmpPlayer> cmpPlayer(*pSimulation2, cmpPlayerManager->GetPlayerByID(m_PlayerID));
|
||||
if (!cmpPlayer.null() && cmpPlayer->HasStartingCamera())
|
||||
{
|
||||
CmpPtr<ICmpPosition> cmpPosition(*pSimulation2, m_CameraStartupTarget);
|
||||
// Use player starting camera
|
||||
CFixedVector3D pos = cmpPlayer->GetStartingCamera();
|
||||
pGameView->ResetCameraTarget(CVector3D(pos.X.ToFloat(), pos.Y.ToFloat(), pos.Z.ToFloat()));
|
||||
}
|
||||
else if (m_StartingCameraTarget != INVALID_ENTITY)
|
||||
{
|
||||
// Point camera at entity
|
||||
CmpPtr<ICmpPosition> cmpPosition(*pSimulation2, m_StartingCameraTarget);
|
||||
if (!cmpPosition.null())
|
||||
{
|
||||
CFixedVector3D pos = cmpPosition->GetPosition();
|
||||
@ -678,6 +687,7 @@ void CXMLReader::ReadEnvironment(XMBElement parent)
|
||||
|
||||
void CXMLReader::ReadCamera(XMBElement parent)
|
||||
{
|
||||
// defaults if we don't find player starting camera
|
||||
#define EL(x) int el_##x = xmb_file.GetElementID(#x)
|
||||
#define AT(x) int at_##x = xmb_file.GetAttributeID(#x)
|
||||
EL(declination);
|
||||
@ -849,7 +859,7 @@ int CXMLReader::ReadEntities(XMBElement parent, double end_time)
|
||||
XMBElementList entities = parent.GetChildNodes();
|
||||
|
||||
CSimulation2& sim = *m_MapReader.pSimulation2;
|
||||
CmpPtr<ICmpPlayerManager> cmpPlayerManager(sim.GetSimContext(), SYSTEM_ENTITY);
|
||||
CmpPtr<ICmpPlayerManager> cmpPlayerManager(sim, SYSTEM_ENTITY);
|
||||
|
||||
while (entity_idx < entities.Count)
|
||||
{
|
||||
@ -907,14 +917,13 @@ int CXMLReader::ReadEntities(XMBElement parent, double end_time)
|
||||
}
|
||||
|
||||
entity_id_t ent = sim.AddEntity(TemplateName, EntityUid);
|
||||
if (ent == INVALID_ENTITY)
|
||||
{
|
||||
entity_id_t player = cmpPlayerManager->GetPlayerByID(PlayerID);
|
||||
if (ent == INVALID_ENTITY || player == INVALID_ENTITY)
|
||||
{ // Don't add entities with invalid player IDs
|
||||
LOGERROR(L"Failed to load entity template '%ls'", TemplateName.c_str());
|
||||
}
|
||||
else if (cmpPlayerManager->GetPlayerByID(PlayerID) != INVALID_ENTITY)
|
||||
{ // Don't add entities with invalid player IDs
|
||||
// TODO: Is a warning OK or should it just silently fail?
|
||||
|
||||
else
|
||||
{
|
||||
CmpPtr<ICmpPosition> cmpPosition(sim, ent);
|
||||
if (!cmpPosition.null())
|
||||
{
|
||||
@ -927,13 +936,10 @@ int CXMLReader::ReadEntities(XMBElement parent, double end_time)
|
||||
if (!cmpOwner.null())
|
||||
cmpOwner->SetOwner(PlayerID);
|
||||
|
||||
if (boost::algorithm::ends_with(TemplateName, L"civil_centre"))
|
||||
if (PlayerID == m_MapReader.m_PlayerID && (boost::algorithm::ends_with(TemplateName, L"civil_centre") || m_MapReader.m_StartingCameraTarget == INVALID_ENTITY))
|
||||
{
|
||||
// HACK: we special-case civil centre files to initialise the camera.
|
||||
// This ought to be based on a more generic mechanism for indicating
|
||||
// per-player camera start locations.
|
||||
if (m_MapReader.m_CameraStartupTarget == INVALID_ENTITY && PlayerID == m_MapReader.m_PlayerID && !cmpPosition.null())
|
||||
m_MapReader.m_CameraStartupTarget = ent;
|
||||
// Focus on civil centre or first entity owned by player
|
||||
m_MapReader.m_StartingCameraTarget = ent;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1201,6 +1207,9 @@ int CMapReader::ParseEntities()
|
||||
if (!pSimulation2->GetScriptInterface().GetProperty(m_MapData.get(), "entities", entities))
|
||||
LOGWARNING(L"CMapReader::ParseEntities() failed to get 'entities' property");
|
||||
|
||||
CSimulation2& sim = *pSimulation2;
|
||||
CmpPtr<ICmpPlayerManager> cmpPlayerManager(sim, SYSTEM_ENTITY);
|
||||
|
||||
size_t entity_idx = 0;
|
||||
size_t num_entities = entities.size();
|
||||
|
||||
@ -1212,33 +1221,33 @@ int CMapReader::ParseEntities()
|
||||
currEnt = entities[entity_idx];
|
||||
|
||||
entity_id_t ent = pSimulation2->AddEntity(currEnt.templateName, currEnt.entityID);
|
||||
// Check that entity was added
|
||||
if (ent == INVALID_ENTITY)
|
||||
{
|
||||
entity_id_t player = cmpPlayerManager->GetPlayerByID(currEnt.playerID);
|
||||
if (ent == INVALID_ENTITY || player == INVALID_ENTITY)
|
||||
{ // Don't add entities with invalid player IDs
|
||||
LOGERROR(L"Failed to load entity template '%ls'", currEnt.templateName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
CmpPtr<ICmpPosition> cmpPosition(*pSimulation2, ent);
|
||||
CFixedVector3D Position;
|
||||
Position.X = fixed::FromFloat(currEnt.positionX);
|
||||
Position.Z = fixed::FromFloat(currEnt.positionZ);
|
||||
|
||||
CmpPtr<ICmpPosition> cmpPosition(sim, ent);
|
||||
if (!cmpPosition.null())
|
||||
{
|
||||
cmpPosition->JumpTo(entity_pos_t::FromFloat(currEnt.positionX), entity_pos_t::FromFloat(currEnt.positionZ));
|
||||
cmpPosition->JumpTo(Position.X, Position.Z);
|
||||
cmpPosition->SetYRotation(entity_angle_t::FromFloat(currEnt.orientationY));
|
||||
// TODO: other parts of the position
|
||||
}
|
||||
|
||||
CmpPtr<ICmpOwnership> cmpOwner(*pSimulation2, ent);
|
||||
CmpPtr<ICmpOwnership> cmpOwner(sim, ent);
|
||||
if (!cmpOwner.null())
|
||||
cmpOwner->SetOwner(currEnt.playerID);
|
||||
|
||||
if (boost::algorithm::ends_with(currEnt.templateName, L"civil_centre"))
|
||||
if (currEnt.playerID == m_PlayerID && (boost::algorithm::ends_with(currEnt.templateName, L"civil_centre") || m_StartingCameraTarget == INVALID_ENTITY))
|
||||
{
|
||||
// HACK: we special-case civil centre files to initialise the camera.
|
||||
// This ought to be based on a more generic mechanism for indicating
|
||||
// per-player camera start locations.
|
||||
if (m_CameraStartupTarget == INVALID_ENTITY && currEnt.playerID == m_PlayerID && !cmpPosition.null())
|
||||
m_CameraStartupTarget = ent;
|
||||
|
||||
// Focus on civil centre or first entity owned by player
|
||||
m_StartingCameraTarget = currEnt.entityID;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1327,7 +1336,7 @@ int CMapReader::ParseEnvironment()
|
||||
int CMapReader::ParseCamera()
|
||||
{
|
||||
// parse camera settings from map data
|
||||
// defaults if we don't find camera
|
||||
// defaults if we don't find player starting camera
|
||||
float declination = DEGTORAD(30.f), rotation = DEGTORAD(-45.f);
|
||||
CVector3D translation = CVector3D(100, 150, -100);
|
||||
|
||||
|
@ -137,7 +137,8 @@ private:
|
||||
VfsPath filename_xml;
|
||||
bool only_xml;
|
||||
u32 file_format_version;
|
||||
entity_id_t m_CameraStartupTarget;
|
||||
entity_id_t m_StartingCameraTarget;
|
||||
CVector3D m_StartingCamera;
|
||||
|
||||
// UnpackTerrain generator state
|
||||
size_t cur_terrain_tex;
|
||||
|
@ -625,3 +625,16 @@ std::string CSimulation2::ReadJSON(VfsPath path)
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string CSimulation2::GetAIData()
|
||||
{
|
||||
ScriptInterface& scriptInterface = GetScriptInterface();
|
||||
std::vector<CScriptValRooted> aiData = ICmpAIManager::GetAIs(scriptInterface);
|
||||
|
||||
// Build single JSON string with array of AI data
|
||||
CScriptValRooted ais;
|
||||
if (!scriptInterface.Eval("({})", ais) || !scriptInterface.SetProperty(ais.get(), "AIData", aiData))
|
||||
return std::string();
|
||||
|
||||
return scriptInterface.StringifyJSON(ais.get());
|
||||
}
|
||||
|
@ -233,6 +233,13 @@ public:
|
||||
*/
|
||||
std::string GetMapSizes();
|
||||
|
||||
/**
|
||||
* Get AI data
|
||||
*
|
||||
* @return string containing JSON format data
|
||||
*/
|
||||
std::string GetAIData();
|
||||
|
||||
private:
|
||||
CSimulation2Impl* m;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
#include "ICmpPlayer.h"
|
||||
|
||||
#include "maths/FixedVector3D.h"
|
||||
#include "simulation2/system/InterfaceScripted.h"
|
||||
#include "simulation2/scripting/ScriptComponent.h"
|
||||
|
||||
@ -51,6 +52,16 @@ public:
|
||||
{
|
||||
return m_Script.Call<CColor>("GetColour");
|
||||
}
|
||||
|
||||
virtual CFixedVector3D GetStartingCamera()
|
||||
{
|
||||
return m_Script.Call<CFixedVector3D>("GetStartingCamera");
|
||||
}
|
||||
|
||||
virtual bool HasStartingCamera()
|
||||
{
|
||||
return m_Script.Call<bool>("HasStartingCamera");
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_COMPONENT_SCRIPT_WRAPPER(PlayerScripted)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -21,6 +21,7 @@
|
||||
#include "simulation2/system/Interface.h"
|
||||
|
||||
struct CColor;
|
||||
class CFixedVector3D;
|
||||
|
||||
/**
|
||||
* Player data.
|
||||
@ -35,6 +36,9 @@ public:
|
||||
virtual void SetColour(u8 r, u8 g, u8 b) = 0;
|
||||
|
||||
virtual CColor GetColour() = 0;
|
||||
virtual CFixedVector3D GetStartingCamera() = 0;
|
||||
|
||||
virtual bool HasStartingCamera() = 0;
|
||||
|
||||
DECLARE_INTERFACE_TYPE(Player)
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -153,6 +153,7 @@ public:
|
||||
void set(const char* key, const wchar_t* value);
|
||||
void set(const char* key, AtObj& data);
|
||||
void setBool(const char* key, bool value);
|
||||
void setDouble(const char* key, double value);
|
||||
void setInt(const char* key, int value);
|
||||
void setString(const wchar_t* value);
|
||||
void addOverlay(AtObj& data);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -175,6 +175,19 @@ void AtObj::setBool(const char* key, bool value)
|
||||
p = p->setChild(key, AtNode::Ptr(o));
|
||||
}
|
||||
|
||||
void AtObj::setDouble(const char* key, double value)
|
||||
{
|
||||
std::wstringstream str;
|
||||
str << value;
|
||||
AtNode* o = new AtNode(str.str().c_str());
|
||||
o->children.insert(AtNode::child_pairtype("@number", AtNode::Ptr(new AtNode())));
|
||||
|
||||
if (!p)
|
||||
p = new AtNode();
|
||||
|
||||
p = p->setChild(key, AtNode::Ptr(o));
|
||||
}
|
||||
|
||||
void AtObj::setInt(const char* key, int value)
|
||||
{
|
||||
std::wstringstream str;
|
||||
|
@ -448,15 +448,9 @@ void MapSidebar::OnRandomGenerate(wxCommandEvent& WXUNUSED(evt))
|
||||
wxChoice* sizeChoice = wxDynamicCast(FindWindow(ID_RandomSize), wxChoice);
|
||||
wxString size;
|
||||
size << (intptr_t)sizeChoice->GetClientData(sizeChoice->GetSelection());
|
||||
AtObj sizeObj;
|
||||
sizeObj.setString(size);
|
||||
sizeObj.set("@number", L"");
|
||||
settings.set("Size", sizeObj);
|
||||
settings.setInt("Size", wxAtoi(size));
|
||||
|
||||
AtObj seedObj;
|
||||
seedObj.setString(wxDynamicCast(FindWindow(ID_RandomSeed), wxTextCtrl)->GetValue());
|
||||
seedObj.set("@number", L"");
|
||||
settings.set("Seed", seedObj);
|
||||
settings.setInt("Seed", wxAtoi(wxDynamicCast(FindWindow(ID_RandomSeed), wxTextCtrl)->GetValue()));
|
||||
|
||||
std::string json = AtlasObject::SaveToJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), settings);
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
enum
|
||||
{
|
||||
ID_ObjectType = 1,
|
||||
ID_ObjectFilter,
|
||||
ID_PlayerSelect,
|
||||
ID_SelectObject,
|
||||
ID_ToggleViewer,
|
||||
@ -110,6 +111,12 @@ struct ObjectSidebarImpl
|
||||
ObjectSidebar::ObjectSidebar(ScenarioEditor& scenarioEditor, wxWindow* sidebarContainer, wxWindow* bottomBarContainer)
|
||||
: Sidebar(scenarioEditor, sidebarContainer, bottomBarContainer), p(new ObjectSidebarImpl())
|
||||
{
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(new wxStaticText(this, wxID_ANY, _("Filter")), wxSizerFlags().Align(wxALIGN_CENTER));
|
||||
wxTextCtrl* objectFilter = new wxTextCtrl(this, ID_ObjectFilter);
|
||||
sizer->Add(objectFilter, wxSizerFlags().Expand().Proportion(1));
|
||||
m_MainSizer->Add(sizer, wxSizerFlags().Expand());
|
||||
|
||||
wxArrayString strings;
|
||||
strings.Add(_("Entities"));
|
||||
strings.Add(_("Actors (all)"));
|
||||
@ -158,20 +165,27 @@ void ObjectSidebar::OnFirstDisplay()
|
||||
qry.Post();
|
||||
p->m_Objects = *qry.objects;
|
||||
// Display first group of objects
|
||||
SetObjectFilter(0);
|
||||
FilterObjects();
|
||||
}
|
||||
|
||||
void ObjectSidebar::SetObjectFilter(int type)
|
||||
void ObjectSidebar::FilterObjects()
|
||||
{
|
||||
int filterType = wxDynamicCast(FindWindow(ID_ObjectType), wxChoice)->GetSelection();
|
||||
wxString filterName = wxDynamicCast(FindWindow(ID_ObjectFilter), wxTextCtrl)->GetValue();
|
||||
|
||||
p->m_ObjectListBox->Freeze();
|
||||
p->m_ObjectListBox->Clear();
|
||||
for (std::vector<AtlasMessage::sObjectsListItem>::iterator it = p->m_Objects.begin(); it != p->m_Objects.end(); ++it)
|
||||
{
|
||||
if (it->type == type)
|
||||
if (it->type == filterType)
|
||||
{
|
||||
wxString id = it->id.c_str();
|
||||
wxString name = it->name.c_str();
|
||||
p->m_ObjectListBox->Append(name, new wxStringClientData(id));
|
||||
|
||||
if (name.Lower().Find(filterName.Lower()) != wxNOT_FOUND)
|
||||
{
|
||||
p->m_ObjectListBox->Append(name, new wxStringClientData(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
p->m_ObjectListBox->Thaw();
|
||||
@ -185,10 +199,9 @@ void ObjectSidebar::ToggleViewer(wxCommandEvent& WXUNUSED(evt))
|
||||
m_ScenarioEditor.GetToolManager().SetCurrentTool(_T("ActorViewerTool"), NULL);
|
||||
}
|
||||
|
||||
void ObjectSidebar::OnSelectType(wxCommandEvent& evt)
|
||||
void ObjectSidebar::OnSelectType(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
// Switch between displayed lists of objects (e.g. entities vs actors)
|
||||
SetObjectFilter(evt.GetSelection());
|
||||
FilterObjects();
|
||||
}
|
||||
|
||||
void ObjectSidebar::OnSelectObject(wxCommandEvent& evt)
|
||||
@ -213,8 +226,14 @@ void ObjectSidebar::OnSelectObject(wxCommandEvent& evt)
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectSidebar::OnSelectFilter(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
FilterObjects();
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(ObjectSidebar, Sidebar)
|
||||
EVT_CHOICE(ID_ObjectType, ObjectSidebar::OnSelectType)
|
||||
EVT_TEXT(ID_ObjectFilter, ObjectSidebar::OnSelectFilter)
|
||||
EVT_LISTBOX(ID_SelectObject, ObjectSidebar::OnSelectObject)
|
||||
EVT_BUTTON(ID_ToggleViewer, ObjectSidebar::ToggleViewer)
|
||||
END_EVENT_TABLE();
|
||||
@ -256,7 +275,7 @@ private:
|
||||
// Adjust displayed number of players
|
||||
Clear();
|
||||
size_t numPlayers = settings["PlayerData"]["item"].count();
|
||||
for (size_t i = 0; i <= numPlayers; ++i)
|
||||
for (size_t i = 0; i <= numPlayers && i < m_Players.Count(); ++i)
|
||||
{
|
||||
Append(m_Players[i]);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class ObjectSidebar : public Sidebar
|
||||
public:
|
||||
ObjectSidebar(ScenarioEditor& scenarioEditor, wxWindow* sidebarContainer, wxWindow* bottomBarContainer);
|
||||
~ObjectSidebar();
|
||||
void SetObjectFilter(int type);
|
||||
void FilterObjects();
|
||||
|
||||
protected:
|
||||
virtual void OnFirstDisplay();
|
||||
@ -35,6 +35,7 @@ private:
|
||||
|
||||
void ToggleViewer(wxCommandEvent& evt);
|
||||
void OnSelectType(wxCommandEvent& evt);
|
||||
void OnSelectFilter(wxCommandEvent& evt);
|
||||
void OnSelectObject(wxCommandEvent& evt);
|
||||
|
||||
ObjectSidebarImpl* p;
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#include "AtlasObject/AtlasObject.h"
|
||||
#include "AtlasScript/ScriptInterface.h"
|
||||
#include "GameInterface/Messages.h"
|
||||
#include "ScenarioEditor/ScenarioEditor.h"
|
||||
|
||||
#include "wx/choicebk.h"
|
||||
@ -34,21 +33,12 @@ enum
|
||||
ID_PlayerMetal,
|
||||
ID_PlayerStone,
|
||||
ID_PlayerPop,
|
||||
ID_PlayerColour
|
||||
};
|
||||
|
||||
// Controls present on each player page
|
||||
struct PlayerPageControls
|
||||
{
|
||||
wxTextCtrl* name;
|
||||
wxChoice* civ;
|
||||
wxButton* colour;
|
||||
wxSpinCtrl* food;
|
||||
wxSpinCtrl* wood;
|
||||
wxSpinCtrl* stone;
|
||||
wxSpinCtrl* metal;
|
||||
wxSpinCtrl* pop;
|
||||
wxChoice* team;
|
||||
ID_PlayerColour,
|
||||
ID_PlayerHuman,
|
||||
ID_PlayerAI,
|
||||
ID_CameraSet,
|
||||
ID_CameraView,
|
||||
ID_CameraClear
|
||||
};
|
||||
|
||||
// TODO: Some of these helper things should be moved out of this file
|
||||
@ -71,6 +61,8 @@ public:
|
||||
: wxPanel(parent, wxID_ANY), m_ScenarioEditor(scenarioEditor), m_Name(name), m_PlayerID(playerID)
|
||||
{
|
||||
|
||||
m_Controls.page = this;
|
||||
|
||||
Freeze();
|
||||
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||
@ -93,6 +85,10 @@ public:
|
||||
wxButton* colourButton = new wxButton(this, ID_PlayerColour);
|
||||
gridSizer->Add(Tooltipped(colourButton, _("Set player colour")), wxSizerFlags(1).Expand().Align(wxALIGN_RIGHT));
|
||||
m_Controls.colour = colourButton;
|
||||
gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Default AI")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
|
||||
wxChoice* aiChoice = new wxChoice(this, wxID_ANY);
|
||||
gridSizer->Add(Tooltipped(aiChoice, _("Select default AI")), wxSizerFlags(1).Expand().Align(wxALIGN_RIGHT));
|
||||
m_Controls.ai = aiChoice;
|
||||
|
||||
playerInfoSizer->Add(gridSizer, wxSizerFlags(1).Expand());
|
||||
sizer->Add(playerInfoSizer, wxSizerFlags().Expand());
|
||||
@ -142,7 +138,6 @@ public:
|
||||
diplomacySizer->Add(boxSizer, wxSizerFlags(1).Expand());
|
||||
|
||||
// TODO: possibly have advanced panel where each player's diplomacy can be set?
|
||||
|
||||
// Advanced panel
|
||||
/*wxCollapsiblePane* advPane = new wxCollapsiblePane(this, wxID_ANY, _("Advanced"));
|
||||
wxWindow* pane = advPane->GetPane();
|
||||
@ -150,6 +145,20 @@ public:
|
||||
|
||||
sizer->Add(diplomacySizer, wxSizerFlags().Expand());
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Camera
|
||||
wxStaticBoxSizer* cameraSizer = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Starting Camera"));
|
||||
wxButton* cameraSet = new wxButton(this, ID_CameraSet, _("Set"));
|
||||
cameraSizer->Add(Tooltipped(cameraSet, _("Set player camera to this view")), wxSizerFlags(1));
|
||||
wxButton* cameraView = new wxButton(this, ID_CameraView, _("View"));
|
||||
cameraView->Enable(false);
|
||||
cameraSizer->Add(Tooltipped(cameraView, _("View the player camera")), wxSizerFlags(1));
|
||||
wxButton* cameraClear = new wxButton(this, ID_CameraClear, _("Clear"));
|
||||
cameraClear->Enable(false);
|
||||
cameraSizer->Add(Tooltipped(cameraClear, _("Clear player camera")), wxSizerFlags(1));
|
||||
|
||||
sizer->Add(cameraSizer, wxSizerFlags().Expand());
|
||||
|
||||
Layout();
|
||||
Thaw();
|
||||
|
||||
@ -174,6 +183,26 @@ public:
|
||||
return m_PlayerID;
|
||||
}
|
||||
|
||||
bool IsCameraDefined()
|
||||
{
|
||||
return m_CameraDefined;
|
||||
}
|
||||
|
||||
sCameraInfo GetCamera()
|
||||
{
|
||||
return m_Camera;
|
||||
}
|
||||
|
||||
void SetCamera(sCameraInfo info, bool isDefined = true)
|
||||
{
|
||||
m_Camera = info;
|
||||
m_CameraDefined = isDefined;
|
||||
|
||||
// Enable/disable controls
|
||||
wxDynamicCast(FindWindow(ID_CameraView), wxButton)->Enable(isDefined);
|
||||
wxDynamicCast(FindWindow(ID_CameraClear), wxButton)->Enable(isDefined);
|
||||
}
|
||||
|
||||
private:
|
||||
void OnColour(wxCommandEvent& evt)
|
||||
{
|
||||
@ -193,9 +222,34 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
ScenarioEditor& m_ScenarioEditor;
|
||||
void OnCameraSet(wxCommandEvent& evt)
|
||||
{
|
||||
AtlasMessage::qGetView qryView;
|
||||
qryView.Post();
|
||||
SetCamera(qryView.info, true);
|
||||
|
||||
// Pass event on to next handler
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void OnCameraView(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
POST_MESSAGE(SetView, (m_Camera));
|
||||
}
|
||||
|
||||
void OnCameraClear(wxCommandEvent& evt)
|
||||
{
|
||||
SetCamera(sCameraInfo(), false);
|
||||
|
||||
// Pass event on to next handler
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
sCameraInfo m_Camera;
|
||||
bool m_CameraDefined;
|
||||
wxString m_Name;
|
||||
size_t m_PlayerID;
|
||||
ScenarioEditor& m_ScenarioEditor;
|
||||
|
||||
PlayerPageControls m_Controls;
|
||||
|
||||
@ -204,6 +258,9 @@ private:
|
||||
|
||||
BEGIN_EVENT_TABLE(PlayerNotebookPage, wxPanel)
|
||||
EVT_BUTTON(ID_PlayerColour, PlayerNotebookPage::OnColour)
|
||||
EVT_BUTTON(ID_CameraSet, PlayerNotebookPage::OnCameraSet)
|
||||
EVT_BUTTON(ID_CameraView, PlayerNotebookPage::OnCameraView)
|
||||
EVT_BUTTON(ID_CameraClear, PlayerNotebookPage::OnCameraClear)
|
||||
END_EVENT_TABLE();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -331,6 +388,8 @@ private:
|
||||
|
||||
BEGIN_EVENT_TABLE(PlayerSettingsControl, wxPanel)
|
||||
EVT_BUTTON(ID_PlayerColour, PlayerSettingsControl::OnEdit)
|
||||
EVT_BUTTON(ID_CameraSet, PlayerSettingsControl::OnEdit)
|
||||
EVT_BUTTON(ID_CameraClear, PlayerSettingsControl::OnEdit)
|
||||
EVT_CHOICE(wxID_ANY, PlayerSettingsControl::OnEdit)
|
||||
EVT_TEXT(wxID_ANY, PlayerSettingsControl::OnEdit)
|
||||
EVT_SPINCTRL(ID_NumPlayers, PlayerSettingsControl::OnNumPlayersChanged)
|
||||
@ -382,6 +441,16 @@ void PlayerSettingsControl::CreateWidgets()
|
||||
civCodes.Add(wxString(civ["Code"]));
|
||||
}
|
||||
|
||||
// Load AI data
|
||||
ArrayOfAIData ais(AIData::CompareAIData);
|
||||
AtlasMessage::qGetAIData qryAI;
|
||||
qryAI.Post();
|
||||
AtObj aiData = AtlasObject::LoadFromJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), *qryAI.data);
|
||||
for (AtIter a = aiData["AIData"]["item"]; a.defined(); ++a)
|
||||
{
|
||||
ais.Add(new AIData(wxString(a["id"]), wxString(a["data"]["name"])));
|
||||
}
|
||||
|
||||
// Create player pages
|
||||
AtIter player = m_PlayerDefaults["item"];
|
||||
++player; // Skip gaia
|
||||
@ -395,6 +464,14 @@ void PlayerSettingsControl::CreateWidgets()
|
||||
wxChoice* civChoice = controls.civ;
|
||||
for (size_t j = 0; j < civNames.Count(); ++j)
|
||||
civChoice->Append(civNames[j], new wxStringClientData(civCodes[j]));
|
||||
civChoice->SetSelection(0);
|
||||
|
||||
// Populate ai choice box
|
||||
wxChoice* aiChoice = controls.ai;
|
||||
aiChoice->Append(_("<None>"), new wxStringClientData());
|
||||
for (size_t j = 0; j < ais.Count(); ++j)
|
||||
aiChoice->Append(ais[j]->GetName(), new wxStringClientData(ais[j]->GetID()));
|
||||
aiChoice->SetSelection(0);
|
||||
}
|
||||
|
||||
m_InGUIUpdate = false;
|
||||
@ -418,6 +495,10 @@ void PlayerSettingsControl::ReadFromEngine()
|
||||
// Prevent error if there's no map settings to parse
|
||||
m_MapSettings = AtlasObject::LoadFromJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), *qry.settings);
|
||||
}
|
||||
else
|
||||
{ // Use blank object, it will be created next
|
||||
m_MapSettings = AtObj();
|
||||
}
|
||||
|
||||
AtIter player = m_MapSettings["PlayerData"]["item"];
|
||||
size_t numPlayers = player.count();
|
||||
@ -480,6 +561,31 @@ void PlayerSettingsControl::ReadFromEngine()
|
||||
}
|
||||
controls.colour->SetBackgroundColour(colour);
|
||||
|
||||
// player type
|
||||
wxString aiID;
|
||||
if (player["AI"].defined())
|
||||
aiID = wxString(player["AI"]);
|
||||
else
|
||||
aiID = wxString(playerDefs["AI"]);
|
||||
|
||||
choice = controls.ai;
|
||||
if (!aiID.empty())
|
||||
{ // AI
|
||||
for (size_t j = 0; j < choice->GetCount(); ++j)
|
||||
{
|
||||
wxStringClientData* str = dynamic_cast<wxStringClientData*>(choice->GetClientObject(j));
|
||||
if (str->GetData() == aiID)
|
||||
{
|
||||
choice->SetSelection(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Human
|
||||
choice->SetSelection(0);
|
||||
}
|
||||
|
||||
// resources
|
||||
AtObj resObj = *player["Resources"];
|
||||
if (resObj.defined() && resObj["food"].defined())
|
||||
@ -514,6 +620,20 @@ void PlayerSettingsControl::ReadFromEngine()
|
||||
else
|
||||
controls.team->SetSelection(0);
|
||||
|
||||
// camera
|
||||
if (player["StartingCamera"].defined())
|
||||
{
|
||||
AtObj cam = *player["StartingCamera"];
|
||||
sCameraInfo info;
|
||||
info.pX = wxAtof(*cam["x"]);
|
||||
info.pY = wxAtof(*cam["y"]);
|
||||
info.pZ = wxAtof(*cam["z"]);
|
||||
|
||||
controls.page->SetCamera(info, true);
|
||||
}
|
||||
else
|
||||
controls.page->SetCamera(sCameraInfo(), false);
|
||||
|
||||
}
|
||||
|
||||
m_InGUIUpdate = false;
|
||||
@ -556,6 +676,18 @@ AtObj PlayerSettingsControl::UpdateSettingsObject()
|
||||
clrObj.setInt("b", (int)colour.Blue());
|
||||
player.set("Colour", clrObj);
|
||||
|
||||
// player type
|
||||
choice = controls.ai;
|
||||
if (choice->GetSelection() > 0)
|
||||
{ // ai - get id
|
||||
wxStringClientData* str = dynamic_cast<wxStringClientData*>(choice->GetClientObject(choice->GetSelection()));
|
||||
player.set("AI", str->GetData());
|
||||
}
|
||||
else
|
||||
{ // human
|
||||
player.set("AI", _T(""));
|
||||
}
|
||||
|
||||
// resources
|
||||
AtObj resObj;
|
||||
if (controls.food->GetValue() > 0)
|
||||
@ -581,6 +713,17 @@ AtObj PlayerSettingsControl::UpdateSettingsObject()
|
||||
player.setInt("Team", choice->GetSelection() - 1);
|
||||
}
|
||||
|
||||
// camera
|
||||
if (controls.page->IsCameraDefined())
|
||||
{
|
||||
sCameraInfo cam = controls.page->GetCamera();
|
||||
AtObj camObj;
|
||||
camObj.setDouble("x", cam.pX);
|
||||
camObj.setDouble("y", cam.pY);
|
||||
camObj.setDouble("z", cam.pZ);
|
||||
player.set("StartingCamera", camObj);
|
||||
}
|
||||
|
||||
players.add("item", player);
|
||||
if (oldPlayer.defined())
|
||||
++oldPlayer;
|
||||
|
@ -17,8 +17,13 @@
|
||||
|
||||
#include "../Common/Sidebar.h"
|
||||
|
||||
#include "GameInterface/Messages.h"
|
||||
|
||||
#include "wx/collpane.h"
|
||||
|
||||
using namespace AtlasMessage;
|
||||
|
||||
class PlayerNotebookPage;
|
||||
class PlayerSettingsControl;
|
||||
|
||||
class PlayerSidebar : public Sidebar
|
||||
@ -40,3 +45,50 @@ private:
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
// Controls present on each player page
|
||||
struct PlayerPageControls
|
||||
{
|
||||
PlayerNotebookPage* page;
|
||||
|
||||
wxTextCtrl* name;
|
||||
wxChoice* civ;
|
||||
wxButton* colour;
|
||||
wxSpinCtrl* food;
|
||||
wxSpinCtrl* wood;
|
||||
wxSpinCtrl* stone;
|
||||
wxSpinCtrl* metal;
|
||||
wxSpinCtrl* pop;
|
||||
wxChoice* team;
|
||||
wxChoice* ai;
|
||||
};
|
||||
|
||||
// Definitions for keeping AI data sorted
|
||||
class AIData
|
||||
{
|
||||
public:
|
||||
AIData(const wxString& id, const wxString& name)
|
||||
: m_ID(id), m_Name(name)
|
||||
{
|
||||
}
|
||||
|
||||
wxString& GetID()
|
||||
{
|
||||
return m_ID;
|
||||
}
|
||||
|
||||
wxString& GetName()
|
||||
{
|
||||
return m_Name;
|
||||
}
|
||||
|
||||
static int CompareAIData(AIData* ai1, AIData* ai2)
|
||||
{
|
||||
return ai1->m_Name.Cmp(ai2->m_Name);
|
||||
}
|
||||
|
||||
private:
|
||||
wxString m_ID;
|
||||
wxString m_Name;
|
||||
};
|
||||
WX_DEFINE_SORTED_ARRAY(AIData*, ArrayOfAIData);
|
||||
|
@ -219,5 +219,32 @@ MESSAGEHANDLER(LookAt)
|
||||
camera.UpdateFrustum();
|
||||
}
|
||||
|
||||
QUERYHANDLER(GetView)
|
||||
{
|
||||
CVector3D focus = g_Game->GetView()->GetCamera()->GetFocus();
|
||||
|
||||
sCameraInfo info;
|
||||
|
||||
info.pX = focus.X;
|
||||
info.pY = focus.Y;
|
||||
info.pZ = focus.Z;
|
||||
|
||||
// TODO: Rotation
|
||||
|
||||
msg->info = info;
|
||||
}
|
||||
|
||||
MESSAGEHANDLER(SetView)
|
||||
{
|
||||
if (g_Game->GetView()->GetCinema()->IsPlaying())
|
||||
return;
|
||||
|
||||
CGameView* view = g_Game->GetView();
|
||||
view->ResetCameraTarget(view->GetCamera()->GetFocus());
|
||||
|
||||
sCameraInfo cam = msg->info;
|
||||
|
||||
view->ResetCameraTarget(CVector3D(cam.pX, cam.pY, cam.pZ));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -35,4 +35,9 @@ QUERYHANDLER(GetPlayerDefaults)
|
||||
msg->defaults = g_Game->GetSimulation2()->GetPlayerDefaults();
|
||||
}
|
||||
|
||||
QUERYHANDLER(GetAIData)
|
||||
{
|
||||
msg->data = g_Game->GetSimulation2()->GetAIData();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -183,6 +183,11 @@ QUERY(GetPlayerDefaults,
|
||||
((std::string, defaults))
|
||||
);
|
||||
|
||||
QUERY(GetAIData,
|
||||
,
|
||||
((std::string, data))
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MESSAGE(RenderStyle,
|
||||
@ -362,6 +367,15 @@ MESSAGE(LookAt,
|
||||
|
||||
MESSAGE(CameraReset, );
|
||||
|
||||
QUERY(GetView,
|
||||
,
|
||||
((sCameraInfo, info))
|
||||
);
|
||||
|
||||
MESSAGE(SetView,
|
||||
((sCameraInfo, info))
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MESSAGES_SKIP_STRUCTS
|
||||
|
Loading…
Reference in New Issue
Block a user