diff --git a/binaries/data/mods/official/entities/template_entity.xml b/binaries/data/mods/official/entities/template_entity.xml
index ef309843ca..6d22ed815a 100755
--- a/binaries/data/mods/official/entities/template_entity.xml
+++ b/binaries/data/mods/official/entities/template_entity.xml
@@ -52,6 +52,11 @@
-1.0
+
+ elite.dds
+ 7.0
+ 7.0
+
6
diff --git a/binaries/data/mods/official/gui/test/functions_page_session_status_commands.js b/binaries/data/mods/official/gui/test/functions_page_session_status_commands.js
index ce68c8a4ce..ccb91036de 100644
--- a/binaries/data/mods/official/gui/test/functions_page_session_status_commands.js
+++ b/binaries/data/mods/official/gui/test/functions_page_session_status_commands.js
@@ -246,10 +246,22 @@ function updateTab (tab, type, cellSheet, attribute, attribute2, arrayCells)
{
case "command":
// An array of actions for the command "tabs" can be triggered by clicking the individual commands. We'll set them here.
- tabObject.onPress = function (event)
+ switch(tab)
{
- }
+ case "rally":
+ tabObject.onPress = function (event)
+ {
+ setCursor("cursor-rally");
+ }
+ break;
+ default:
+ tabObject.onPress = function (event)
+ {
+ }
+ break;
+ }
break;
+
default:
// Set tab function when user moves mouse over tab.
tabObject.onMouseEnter = function (event)
@@ -1090,7 +1102,6 @@ function UpdateListold(listIcon, listCounter)
snStatusPaneCommand[listCounter][createLoop+1].last++;
}
else
- {
guiHide("snStatusPaneCommand" + listCounter + "_" + parseInt(createLoop+1));
}
}
diff --git a/binaries/data/mods/official/gui/test/functions_sim_entity.js b/binaries/data/mods/official/gui/test/functions_sim_entity.js
index be097c3170..bd473c834b 100644
--- a/binaries/data/mods/official/gui/test/functions_sim_entity.js
+++ b/binaries/data/mods/official/gui/test/functions_sim_entity.js
@@ -37,7 +37,15 @@ function worldClickHandler(event)
{
return;
}
-
+
+ //setting rally point
+ if ( getCursorName() == "cursor-rally" )
+ {
+ for ( var i=0; i2
-
-
+
+
diff --git a/source/graphics/MapReader.cpp b/source/graphics/MapReader.cpp
index 2efb8ef3e3..b08b3cd064 100644
--- a/source/graphics/MapReader.cpp
+++ b/source/graphics/MapReader.cpp
@@ -15,6 +15,7 @@
#include "Camera.h"
#include "graphics/Patch.h"
#include "renderer/WaterManager.h"
+#include "renderer/SkyManager.h"
#include "Model.h"
#include "Terrain.h"
@@ -35,8 +36,9 @@ CMapReader::CMapReader()
// LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
-void CMapReader::LoadMap(const char* filename, CTerrain *pTerrain_, CUnitManager *pUnitMan_,
- WaterManager* pWaterMan_, CLightEnv *pLightEnv_, CCamera *pCamera_)
+void CMapReader::LoadMap(const char* filename, CTerrain *pTerrain_,
+ CUnitManager *pUnitMan_, WaterManager* pWaterMan_, SkyManager* pSkyMan_,
+ CLightEnv *pLightEnv_, CCamera *pCamera_)
{
// latch parameters (held until DelayedLoadFinished)
pTerrain = pTerrain_;
@@ -44,6 +46,7 @@ void CMapReader::LoadMap(const char* filename, CTerrain *pTerrain_, CUnitManager
pLightEnv = pLightEnv_;
pCamera = pCamera_;
pWaterMan = pWaterMan_;
+ pSkyMan = pSkyMan_;
// [25ms]
unpacker.Read(filename, "PSMP");
@@ -328,6 +331,7 @@ void CXMLReader::ReadEnvironment(XMBElement parent)
{
#define EL(x) int el_##x = xmb_file.getElementID(#x)
#define AT(x) int at_##x = xmb_file.getAttributeID(#x)
+ EL(skyset);
EL(suncolour);
EL(sunelevation);
EL(sunrotation);
@@ -350,7 +354,12 @@ void CXMLReader::ReadEnvironment(XMBElement parent)
int element_name = element.getNodeName();
XMBAttributeList attrs = element.getAttributes();
- if (element_name == el_suncolour)
+
+ if (element_name == el_skyset)
+ {
+ m_MapReader.pSkyMan->SetSkySet(element.getText());
+ }
+ else if (element_name == el_suncolour)
{
m_MapReader.m_LightEnv.m_SunColor = RGBColor(
CStr(attrs.getNamedItem(at_r)).ToFloat(),
diff --git a/source/graphics/MapReader.h b/source/graphics/MapReader.h
index 208f57239a..3a3701a7e0 100644
--- a/source/graphics/MapReader.h
+++ b/source/graphics/MapReader.h
@@ -11,6 +11,7 @@ class CObjectEntry;
class CTerrain;
class CUnitManager;
class WaterManager;
+class SkyManager;
class CLightEnv;
class CCamera;
@@ -25,7 +26,7 @@ public:
CMapReader();
// LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
void LoadMap(const char* filename, CTerrain *pTerrain, CUnitManager *pUnitMan,
- WaterManager* pWaterMan, CLightEnv *pLightEnv, CCamera *pCamera);
+ WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv *pLightEnv, CCamera *pCamera);
private:
// UnpackTerrain: unpack the terrain from the input stream
@@ -67,6 +68,7 @@ private:
CTerrain* pTerrain;
CUnitManager* pUnitMan;
WaterManager* pWaterMan;
+ SkyManager* pSkyMan;
CLightEnv* pLightEnv;
CCamera* pCamera;
CStr filename_xml;
diff --git a/source/graphics/MapWriter.cpp b/source/graphics/MapWriter.cpp
index 29e69b81bb..a214f5e208 100644
--- a/source/graphics/MapWriter.cpp
+++ b/source/graphics/MapWriter.cpp
@@ -3,29 +3,30 @@
#include "lib/types.h"
#include "lib/res/file/vfs.h"
-#include "MapWriter.h"
-#include "MapReader.h"
-#include "UnitManager.h"
-#include "Unit.h"
-#include "ObjectManager.h"
-#include "ObjectBase.h"
-#include "Model.h"
-#include "Terrain.h"
+#include "Camera.h"
#include "LightEnv.h"
-#include "TextureManager.h"
+#include "MapReader.h"
+#include "MapWriter.h"
+#include "Model.h"
+#include "ObjectBase.h"
+#include "ObjectManager.h"
+#include "Patch.h"
+#include "Terrain.h"
#include "TextureEntry.h"
-#include "ps/VFSUtil.h"
-#include "ps/Loader.h"
-#include "maths/MathUtil.h"
-#include "graphics/Camera.h"
-#include "ps/Player.h"
-#include "graphics/Patch.h"
-#include "renderer/WaterManager.h"
+#include "TextureManager.h"
+#include "Unit.h"
+#include "UnitManager.h"
+#include "maths/MathUtil.h"
+#include "ps/Loader.h"
+#include "ps/Player.h"
+#include "ps/VFSUtil.h"
#include "ps/XML/XMLWriter.h"
-#include "simulation/Entity.h"
+#include "renderer/SkyManager.h"
+#include "renderer/WaterManager.h"
#include "simulation/BaseEntity.h"
#include "simulation/BaseEntityCollection.h"
+#include "simulation/Entity.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
// CMapWriter constructor: nothing to do at the minute
@@ -35,20 +36,21 @@ CMapWriter::CMapWriter()
///////////////////////////////////////////////////////////////////////////////////////////////////
// SaveMap: try to save the current map to the given file
-void CMapWriter::SaveMap(const char* filename, CTerrain* pTerrain, CUnitManager* pUnitMan,
- WaterManager* pWaterMan, CLightEnv* pLightEnv, CCamera* pCamera)
+void CMapWriter::SaveMap(const char* filename, CTerrain* pTerrain,
+ CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan,
+ CLightEnv* pLightEnv, CCamera* pCamera)
{
CFilePacker packer(FILE_VERSION, "PSMP");
// build necessary data
- PackMap(packer, pTerrain, pUnitMan, pLightEnv);
+ PackMap(packer, pTerrain);
// write it out
packer.Write(filename);
CStr filename_xml (filename);
filename_xml = filename_xml.Left(filename_xml.Length()-4) + ".xml";
- WriteXML(filename_xml, pUnitMan, pWaterMan, pLightEnv, pCamera);
+ WriteXML(filename_xml, pUnitMan, pWaterMan, pSkyMan, pLightEnv, pCamera);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -118,8 +120,7 @@ void CMapWriter::EnumTerrainTextures(CTerrain *pTerrain,
///////////////////////////////////////////////////////////////////////////////////////////////////
// PackMap: pack the current world into a raw data stream
-void CMapWriter::PackMap(CFilePacker& packer, CTerrain* pTerrain,
- CUnitManager* UNUSED(pUnitMan), CLightEnv* UNUSED(pLightEnv))
+void CMapWriter::PackMap(CFilePacker& packer, CTerrain* pTerrain)
{
// now pack everything up
PackTerrain(packer, pTerrain);
@@ -158,7 +159,9 @@ void CMapWriter::PackTerrain(CFilePacker& packer, CTerrain* pTerrain)
-void CMapWriter::WriteXML(const char* filename, CUnitManager* pUnitMan, WaterManager* pWaterMan, CLightEnv* pLightEnv, CCamera* pCamera)
+void CMapWriter::WriteXML(const char* filename,
+ CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan,
+ CLightEnv* pLightEnv, CCamera* pCamera)
{
Handle h = vfs_open(filename, FILE_WRITE_TO_TARGET|FILE_NO_AIO);
if (h <= 0)
@@ -175,6 +178,7 @@ void CMapWriter::WriteXML(const char* filename, CUnitManager* pUnitMan, WaterMan
{
XML_Element("Environment");
+ XML_Setting("SkySet", pSkyMan->GetSkySet());
{
XML_Element("SunColour");
XML_Attribute("r", pLightEnv->m_SunColor.X); // yes, it's X/Y/Z...
@@ -326,7 +330,8 @@ void CMapWriter::WriteXML(const char* filename, CUnitManager* pUnitMan, WaterMan
///////////////////////////////////////////////////////////////////////////////////////////////////
// RewriteAllMaps
void CMapWriter::RewriteAllMaps(CTerrain* pTerrain, CUnitManager* pUnitMan,
- WaterManager* pWaterMan, CLightEnv* pLightEnv, CCamera* pCamera)
+ WaterManager* pWaterMan, SkyManager* pSkyMan,
+ CLightEnv* pLightEnv, CCamera* pCamera)
{
VFSUtil::FileList files;
VFSUtil::FindFiles("maps/scenarios", "*.pmp", files);
@@ -335,13 +340,13 @@ void CMapWriter::RewriteAllMaps(CTerrain* pTerrain, CUnitManager* pUnitMan,
{
CMapReader* reader = new CMapReader;
LDR_BeginRegistering();
- reader->LoadMap(*it, pTerrain, pUnitMan, pWaterMan, pLightEnv, pCamera);
+ reader->LoadMap(*it, pTerrain, pUnitMan, pWaterMan, pSkyMan, pLightEnv, pCamera);
LDR_EndRegistering();
LDR_NonprogressiveLoad();
CStr n (*it);
n.Replace("scenarios/", "scenarios/new/");
CMapWriter writer;
- writer.SaveMap(n, pTerrain, pUnitMan, pWaterMan, pLightEnv, pCamera);
+ writer.SaveMap(n, pTerrain, pUnitMan, pWaterMan, pSkyMan, pLightEnv, pCamera);
}
}
diff --git a/source/graphics/MapWriter.h b/source/graphics/MapWriter.h
index f54d61969e..d31597e650 100644
--- a/source/graphics/MapWriter.h
+++ b/source/graphics/MapWriter.h
@@ -11,6 +11,7 @@ class CTerrain;
class CUnitManager;
class CCamera;
class WaterManager;
+class SkyManager;
class CMapWriter : public CMapIO
{
@@ -18,15 +19,15 @@ public:
// constructor
CMapWriter();
// SaveMap: try to save the current map to the given file
- void SaveMap(const char* filename, CTerrain* pTerr, CUnitManager* pUnitMan, WaterManager* pWaterMan, CLightEnv* pLightEnv, CCamera* pCamera);
+ void SaveMap(const char* filename, CTerrain* pTerr, CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera);
// RewriteAllMaps: for use during development: load/save all maps, to
// update them to the newest format.
- static void RewriteAllMaps(CTerrain* pTerrain, CUnitManager* pUnitMan, WaterManager* pWaterMan, CLightEnv* pLightEnv, CCamera* pCamera);
+ static void RewriteAllMaps(CTerrain* pTerrain, CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera);
private:
// PackMap: pack the current world into a raw data stream
- void PackMap(CFilePacker& packer, CTerrain* pTerr, CUnitManager* pUnitMan, CLightEnv* pLightEnv);
+ void PackMap(CFilePacker& packer, CTerrain* pTerrain);
// PackTerrain: pack the terrain onto the end of the data stream
void PackTerrain(CFilePacker& packer, CTerrain* pTerrain);
@@ -36,7 +37,7 @@ private:
std::vector& tileIndices);
// WriteXML: output some other data (entities, etc) in XML format
- void WriteXML(const char* filename, CUnitManager* pUnitMan, WaterManager* pWaterMan, CLightEnv* pLightEnv, CCamera* pCamera);
+ void WriteXML(const char* filename, CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera);
};
#endif
diff --git a/source/lib/res/file/vfs.cpp b/source/lib/res/file/vfs.cpp
index c0145a9b34..a479c5adf7 100644
--- a/source/lib/res/file/vfs.cpp
+++ b/source/lib/res/file/vfs.cpp
@@ -143,7 +143,7 @@ static LibError VDir_to_string(const VDir* vd, char* buf)
// open a directory for reading its entries via vfs_next_dirent.
-// need not end in '/'; we add it if not present.
+// V_dir must end in '/' to indicate it's a directory path.
Handle vfs_dir_open(const char* V_dir_path)
{
// must disallow handle caching because this object is not
diff --git a/source/lib/res/file/vfs.h b/source/lib/res/file/vfs.h
index 280e72a2ee..5b617fd3fd 100644
--- a/source/lib/res/file/vfs.h
+++ b/source/lib/res/file/vfs.h
@@ -292,8 +292,8 @@ extern LibError vfs_set_write_target(const char* P_target_dir);
//
// open the directory for reading its entries via vfs_next_dirent.
-// need not end in '/'; we add it if not present.
-extern Handle vfs_dir_open(const char* dir);
+// V_dir must end in '/' to indicate it's a directory path.
+extern Handle vfs_dir_open(const char* V_dir_path);
// close the handle to a directory.
// all DirEnt.name strings are now invalid.
diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp
index 505e9bc3dd..f3257768be 100644
--- a/source/ps/GameSetup/GameSetup.cpp
+++ b/source/ps/GameSetup/GameSetup.cpp
@@ -379,6 +379,9 @@ void Render()
PROFILE_END( "render health bars" );
glPopAttrib();
+ //Depth test is now enabled
+ g_Selection.renderRallyPoints();
+ g_Mouseover.renderRallyPoints();
}
else
{
diff --git a/source/ps/Interact.cpp b/source/ps/Interact.cpp
index 604c988368..47adf97eaa 100644
--- a/source/ps/Interact.cpp
+++ b/source/ps/Interact.cpp
@@ -247,7 +247,23 @@ void CSelectedEntities::renderOverlays()
glDisable( GL_TEXTURE_2D );
glPopMatrix();
}
+void CSelectedEntities::renderRallyPoints()
+{
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+ glEnable( GL_BLEND );
+ std::vector::iterator it;
+ for( it = m_selected.begin(); it < m_selected.end(); it++ )
+ (*it)->renderRallyPoint();
+
+ if( m_group_highlight != -1 )
+ {
+ std::vector::iterator it;
+ for( it = m_groups[m_group_highlight].begin(); it < m_groups[m_group_highlight].end(); it++ )
+ (*it)->renderRallyPoint();
+ }
+ glDisable( GL_BLEND );
+}
void CSelectedEntities::setSelection( HEntity entity )
{
m_group = -1;
@@ -868,7 +884,17 @@ void CMouseoverEntities::renderBarBorders()
glDisable( GL_BLEND );
}
+void CMouseoverEntities::renderRallyPoints()
+{
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+ glEnable( GL_BLEND );
+ std::vector::iterator it;
+ for( it = m_mouseover.begin(); it < m_mouseover.end(); it++ )
+ it->entity->renderRallyPoint();
+
+ glDisable( GL_BLEND );
+}
// Helper function for CSelectedEntities::loadUnitUITextures
static void LoadUnitUIThunk( const char* path, const DirEnt* UNUSED(ent), void* context )
{
@@ -876,12 +902,7 @@ static void LoadUnitUIThunk( const char* path, const DirEnt* UNUSED(ent), void*
CStr name(path);
if ( !tex_is_known_extension(path) )
- {
- if ( name.BeforeLast(".") == name ) //this is a directory (contains no ".")
- return;
- LOG(ERROR, LOG_CATEGORY, "Unknown rank texture extension (%s)", path);
return;
- }
Handle tmp = ogl_tex_load(path);
if (tmp <= 0)
{
diff --git a/source/ps/Interact.h b/source/ps/Interact.h
index 0cf1207102..431779c9db 100644
--- a/source/ps/Interact.h
+++ b/source/ps/Interact.h
@@ -80,6 +80,7 @@ struct CSelectedEntities : public Singleton
void renderStaminaBars();
void renderRanks();
void renderBarBorders();
+ void renderRallyPoints();
void destroyUnitUITextures();
int loadUnitUITextures();
@@ -136,6 +137,7 @@ struct CMouseoverEntities : public Singleton
void renderStaminaBars();
void renderRanks();
void renderBarBorders();
+ void renderRallyPoints();
bool isBandbox() { return( m_bandbox ); }
void startBandbox( u16 x, u16 y );
diff --git a/source/ps/VFSUtil.h b/source/ps/VFSUtil.h
index 5324c32837..9c3bd10fb7 100644
--- a/source/ps/VFSUtil.h
+++ b/source/ps/VFSUtil.h
@@ -8,7 +8,7 @@ namespace VFSUtil
typedef std::vector FileList;
// Puts the list of files inside 'dirname' matching 'filter' into 'files'.
-// 'dirname' shouldn't end with a slash.
+// 'dirname' must end with a slash.
// 'filter': see vfs_next_dirent
// 'files' is initially cleared, and undefined on failure.
// On failure, logs an error and returns false.
diff --git a/source/ps/World.cpp b/source/ps/World.cpp
index 11e07f6eb2..ec0519153d 100644
--- a/source/ps/World.cpp
+++ b/source/ps/World.cpp
@@ -56,7 +56,7 @@ void CWorld::Initialize(CGameAttributes *pAttribs)
try {
reader = new CMapReader;
reader->LoadMap(mapfilename, m_Terrain, m_UnitManager, g_Renderer.GetWaterManager(),
- &g_LightEnv, m_pGame->GetView()->GetCamera());
+ g_Renderer.GetSkyManager(), &g_LightEnv, m_pGame->GetView()->GetCamera());
// fails immediately, or registers for delay loading
} catch (PSERROR_File&) {
delete reader;
@@ -85,5 +85,6 @@ CWorld::~CWorld()
void CWorld::RewriteMap()
{
CMapWriter::RewriteAllMaps(m_Terrain, m_UnitManager,
- g_Renderer.GetWaterManager(), &g_LightEnv, m_pGame->GetView()->GetCamera());
+ g_Renderer.GetWaterManager(), g_Renderer.GetSkyManager(),
+ &g_LightEnv, m_pGame->GetView()->GetCamera());
}
diff --git a/source/renderer/SkyManager.cpp b/source/renderer/SkyManager.cpp
index f6e0e05dde..319f626e60 100644
--- a/source/renderer/SkyManager.cpp
+++ b/source/renderer/SkyManager.cpp
@@ -19,6 +19,7 @@
#include "ps/CLogger.h"
#include "ps/Loader.h"
+#include "ps/VFSUtil.h"
#include "renderer/SkyManager.h"
#include "renderer/Renderer.h"
@@ -141,6 +142,42 @@ void SkyManager::SetSkySet( CStrW newSet )
}
}
+///////////////////////////////////////////////////////////////////
+// Generate list of available skies
+std::vector SkyManager::GetSkySets() const
+{
+ std::vector skies;
+
+ // Find all subdirectories in art/textures/skies
+
+ const char* dirname = "art/textures/skies/";
+ Handle dir = vfs_dir_open(dirname);
+ if (dir <= 0)
+ {
+ LOG(ERROR, "vfs", "Error opening directory '%s' (%lld)", dirname, dir);
+ return std::vector(1, GetSkySet()); // just return what we currently have
+ }
+
+ const char* filter = "/";
+ int err;
+ DirEnt entry;
+ while ((err = vfs_dir_next_ent(dir, &entry, filter)) == 0)
+ {
+ skies.push_back(CStr(entry.name));
+ }
+
+ if (err != ERR_DIR_END)
+ {
+ LOG(ERROR, "vfs", "Error reading files from directory '%s' (%d)", dirname, err);
+ return std::vector(1, GetSkySet()); // just return what we currently have
+ }
+
+ vfs_dir_close(dir);
+
+ sort(skies.begin(), skies.end());
+
+ return skies;
+}
///////////////////////////////////////////////////////////////////
// Render sky
diff --git a/source/renderer/SkyManager.h b/source/renderer/SkyManager.h
index efa8dbb7aa..a5efd3ed36 100644
--- a/source/renderer/SkyManager.h
+++ b/source/renderer/SkyManager.h
@@ -47,17 +47,23 @@ public:
void RenderSky();
/**
- * GetSkySet(): Return the currently selected sky set name
+ * GetSkySet(): Return the currently selected sky set name.
*/
- inline CStrW GetSkySet() {
+ inline CStrW GetSkySet() const {
return m_SkySet;
}
/**
- * GetSkySet(): Set the sky set name, potentially loading the textures
+ * GetSkySet(): Set the sky set name, potentially loading the textures.
*/
void SetSkySet(CStrW name);
+ /**
+ * Return a sorted list of available sky sets, in a form suitable
+ * for passing to SetSkySet.
+ */
+ std::vector GetSkySets() const;
+
private:
/// Name of current skyset (a directory within art/textures/skies)
CStrW m_SkySet;
diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp
index 6f28645e7c..9bceecfd06 100644
--- a/source/scripting/ScriptGlue.cpp
+++ b/source/scripting/ScriptGlue.cpp
@@ -834,11 +834,14 @@ JSBool vmem( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rva
JSBool setCursor( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval) )
{
REQUIRE_PARAMS(1, setCursor);
-
g_CursorName = g_ScriptingHost.ValueToString(argv[0]);
return JS_TRUE;
}
-
+JSBool getCursorName( JSContext* UNUSED(cx), JSObject*, uint UNUSED(argc), jsval* UNUSED(argv), jsval* rval )
+{
+ *rval = ToJSVal(g_CursorName);
+ return JS_TRUE;
+}
// Trigger a rewrite of all maps.
// params:
@@ -1258,6 +1261,7 @@ JSFunctionSpec ScriptFunctionTable[] =
JS_FUNC(_rewriteMaps, _rewriteMaps, 0)
JS_FUNC(_lodbias, _lodbias, 0)
JS_FUNC(setCursor, setCursor, 1)
+ JS_FUNC(getCursorName, getCursorName, 0)
JS_FUNC(getFPS, getFPS, 0)
// Miscellany
diff --git a/source/simulation/BaseEntity.cpp b/source/simulation/BaseEntity.cpp
index d6b6900430..553aa97703 100644
--- a/source/simulation/BaseEntity.cpp
+++ b/source/simulation/BaseEntity.cpp
@@ -30,8 +30,7 @@ CBaseEntity::CBaseEntity( CPlayer* player )
AddProperty( L"actions.move.run.decay_rate", &m_runDecayRate );
AddProperty( L"actions.move.pass_through_allies", &m_passThroughAllies );
AddProperty( L"actor", &m_actorName );
- AddProperty( L"traits.extant", &m_extant );
- AddProperty( L"traits.corpse", &m_corpse );
+ AddProperty( L"traits.extant", &m_extant );
AddProperty( L"traits.health.curr", &m_healthCurr );
AddProperty( L"traits.health.max", &m_healthMax );
AddProperty( L"traits.health.bar_height", &m_healthBarHeight );
@@ -51,6 +50,9 @@ CBaseEntity::CBaseEntity( CPlayer* player )
AddProperty( L"traits.stamina.border_height", &m_staminaBorderHeight);
AddProperty( L"traits.stamina.border_width", &m_staminaBorderWidth );
AddProperty( L"traits.stamina.border_name", &m_staminaBorderName );
+ AddProperty( L"traits.rally.name", &m_rallyName );
+ AddProperty( L"traits.rally.width", &m_rallyWidth );
+ AddProperty( L"traits.rally.height", &m_rallyHeight );
AddProperty( L"traits.flank_penalty.sectors", &m_sectorDivs );
AddProperty( L"traits.pitch.sectors", &m_pitchDivs );
AddProperty( L"traits.rank.width", &m_rankWidth );
@@ -76,7 +78,6 @@ CBaseEntity::CBaseEntity( CPlayer* player )
// Initialize, make life a little easier on the scriptors
m_speed = m_turningRadius = 0.0f;
m_extant = true;
- m_corpse = CStrW();
m_foundation = CStrW();
m_passThroughAllies = false;
m_sectorDivs = 4;
diff --git a/source/simulation/BaseEntity.h b/source/simulation/BaseEntity.h
index 30c56b1fa9..5d2ce77796 100644
--- a/source/simulation/BaseEntity.h
+++ b/source/simulation/BaseEntity.h
@@ -44,7 +44,6 @@ public:
// Base stats
CBaseEntity* m_base;
- CStrW m_corpse;
bool m_extant;
// The unmodified, no-player version of this template
@@ -93,6 +92,10 @@ public:
float m_rankWidth;
float m_rankHeight;
CStr m_rankName;
+ //Rally name
+ CStr m_rallyName;
+ float m_rallyWidth;
+ float m_rallyHeight;
// Minimap properties
CStrW m_minimapType;
diff --git a/source/simulation/Entity.cpp b/source/simulation/Entity.cpp
index dd4295052b..2e2abb847c 100644
--- a/source/simulation/Entity.cpp
+++ b/source/simulation/Entity.cpp
@@ -25,9 +25,9 @@
#include "simulation/FormationManager.h"
#include "Formation.h"
#include "graphics/GameView.h"
+#include "graphics/Sprite.h"
#include "graphics/UnitManager.h"
-
extern CConsole* g_Console;
extern int g_xres, g_yres;
@@ -61,7 +61,6 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation, cons
AddProperty( L"selected", &m_selected, false, (NotifyFn)&CEntity::checkSelection );
AddProperty( L"group", &m_grouped, false, (NotifyFn)&CEntity::checkGroup );
AddProperty( L"traits.extant", &m_extant );
- AddProperty( L"traits.corpse", &m_corpse );
AddProperty( L"actions.move.turningradius", &m_turningRadius );
AddProperty( L"position", &m_graphics_position, false, (NotifyFn)&CEntity::teleport );
AddProperty( L"orientation", &(m_orientation.Y), false, (NotifyFn)&CEntity::reorient );
@@ -85,6 +84,9 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation, cons
AddProperty( L"traits.stamina.border_height", &m_staminaBorderHeight);
AddProperty( L"traits.stamina.border_width", &m_staminaBorderWidth );
AddProperty( L"traits.stamina.border_name", &m_staminaBorderName );
+ AddProperty( L"traits.rally.name", &m_rallyTexture );
+ AddProperty( L"traits.rally.width", &m_rallyWidth );
+ AddProperty( L"traits.rally.height", &m_rallyHeight );
AddProperty( L"traits.flank_penalty.sectors", &m_sectorDivs);
AddProperty( L"traits.pitch.sectors", &m_pitchDivs );
AddProperty( L"traits.rank.width", &m_rankWidth );
@@ -140,6 +142,7 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation, cons
m_graphics_position = m_position;
m_graphics_orientation = m_orientation;
m_actor_transform_valid = false;
+ m_hasRallyPoint = false;
m_destroyed = false;
@@ -255,7 +258,6 @@ void CEntity::initAttributes(const CEntity* _this)
CEntity::m_AttributeTable["actions.move.run.decay_rate"] = getoffset(m_runDecayRate);
CEntity::m_AttributeTable["actions.move.pass_through_allies"] = getoffset(m_passThroughAllies);
CEntity::m_AttributeTable["traits.extant"] = getoffset(m_extant);
- CEntity::m_AttributeTable["traits.corpse"] = getoffset(m_corpse);
CEntity::m_AttributeTable["actions.move.turningradius"] = getoffset(m_turningRadius);
CEntity::m_AttributeTable["traits.health.curr"] = getoffset(m_healthCurr);
@@ -594,11 +596,6 @@ void CEntity::update( size_t timestep )
m_actor->SetRandomAnimation( "idle" );
}
}
- else if( !m_actor->GetModel()->GetAnimation() )
- {
- m_actor->SetEntitySelection( L"corpse" );
- m_actor->SetRandomAnimation( "corpse" );
- }
}
if( m_lastState != -1 )
@@ -1382,8 +1379,32 @@ void CEntity::renderRank()
glEnd();
}
+void CEntity::renderRallyPoint()
+{
+ if ( !m_hasRallyPoint || g_Selection.m_unitUITextures.find(m_rallyTexture) ==
+ g_Selection.m_unitUITextures.end() )
+ {
+ return;
+ }
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
+ glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
+ CSprite sprite;
+ CTexture tex;
+ tex.SetHandle( g_Selection.m_unitUITextures[m_rallyTexture] );
+ sprite.SetTexture(&tex);
+ CVector3D rally = m_rallyPoint;
+ rally.Y += m_rallyHeight/2.f + .1f;
+ sprite.SetTranslation(rally);
+ sprite.Render();
+}
void CEntity::CalculateRun(float timestep)
{
if( m_staminaMax > 0 )
@@ -1452,6 +1473,9 @@ void CEntity::ScriptingInit()
AddMethod( "getAttackDirections", 0 );
AddMethod("findSector", 4);
AddMethod("getHeight", 0 );
+ AddMethod("hasRallyPoint", 0 );
+ AddMethod("setRallyPoint", 0 );
+ AddMethod("getRallyPoint", 0 );
AddClassProperty( L"template", (CBaseEntity* CEntity::*)&CEntity::m_base, false, (NotifyFn)&CEntity::loadBase );
AddClassProperty( L"traits.id.classes", (GetFn)&CEntity::getClassSet, (SetFn)&CEntity::setClassSet );
@@ -1685,22 +1709,6 @@ bool CEntity::Kill( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(arg
}
m_aurasInfluencingMe.clear();
- // Change this entity's template to the corpse entity - but note
- // we don't fiddle with the actors or bounding information that we
- // usually do when changing templates.
-
- if(m_corpse == L"null")
- {
- kill();
- }
-
- CBaseEntity* corpse = g_EntityTemplateCollection.getTemplate( m_corpse );
- if( corpse )
- {
- m_base = corpse;
- SetBase( m_base );
- }
-
if( m_bounds )
{
delete( m_bounds );
@@ -1723,8 +1731,8 @@ bool CEntity::Kill( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(arg
if( m_actor )
{
- m_actor->SetEntitySelection( L"death" );
- m_actor->SetRandomAnimation( "death", true );
+ m_actor->SetEntitySelection( L"death" );
+ m_actor->SetRandomAnimation( "death", true );
}
return( true );
@@ -2212,3 +2220,17 @@ jsval CEntity::FindSector( JSContext* cx, uintN argc, jsval* argv )
debug_warn("JS - FindSector(): invalid parameters");
return ToJSVal(-1);
}
+jsval CEntity::HasRallyPoint( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
+{
+ return ToJSVal( m_hasRallyPoint );
+}
+jsval CEntity::GetRallyPoint( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
+{
+ return ToJSVal( m_rallyPoint );
+}
+jsval CEntity::SetRallyPoint( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
+{
+ m_hasRallyPoint = true;
+ m_rallyPoint = g_Game->GetView()->GetCamera()->GetWorldCoordinates();
+ return JS_TRUE;
+}
diff --git a/source/simulation/Entity.h b/source/simulation/Entity.h
index 24b8414edb..4ce7b778b2 100644
--- a/source/simulation/Entity.h
+++ b/source/simulation/Entity.h
@@ -67,9 +67,6 @@ public:
//Attributes table: key=attribute, value=variable name
static std::map m_AttributeTable;
- // The entity to switch to when this dies.
- CStrW m_corpse;
-
// The class types this entity has
SClassSet m_classes;
@@ -144,6 +141,10 @@ public:
float m_rankHeight;
float m_rankWidth;
CStr m_rankName;
+ //Rally texture
+ CStr m_rallyTexture;
+ float m_rallyWidth;
+ float m_rallyHeight;
bool m_healthDecay;
@@ -182,6 +183,8 @@ public:
CVector2D m_orientation_unclamped;
+ CVector3D m_rallyPoint;
+ bool m_hasRallyPoint;
// If the actor's current transform data is valid (i.e. the entity hasn't
// moved since it was last calculated, and the terrain hasn't been changed).
@@ -298,6 +301,7 @@ public:
void renderHealthBar();
void renderStaminaBar();
void renderRank();
+ void renderRallyPoint();
CVector2D getScreenCoords( float height );
// After a collision, recalc the path to the next fixed waypoint.
void repath();
@@ -356,6 +360,10 @@ public:
bool Kill( JSContext* cx, uintN argc, jsval* argv );
jsval GetSpawnPoint( JSContext* cx, uintN argc, jsval* argv );
+ inline jsval HasRallyPoint( JSContext* cx, uintN argc, jsval* argv );
+ inline jsval GetRallyPoint( JSContext* cx, uintN argc, jsval* argv );
+ inline jsval SetRallyPoint( JSContext* cx, uintN argc, jsval* argv );
+
jsval AddAura( JSContext* cx, uintN argc, jsval* argv );
jsval RemoveAura( JSContext* cx, uintN argc, jsval* argv );
diff --git a/source/simulation/Technology.cpp b/source/simulation/Technology.cpp
index 1e19124837..e4a03b26cf 100644
--- a/source/simulation/Technology.cpp
+++ b/source/simulation/Technology.cpp
@@ -14,13 +14,15 @@
#define LOG_CATEGORY "Techs"
STL_HASH_SET CTechnology::m_scriptsLoaded;
+bool CTechnology::m_excluded[PS_MAX_PLAYERS+1];
CTechnology::CTechnology()
{
ONCE( ScriptingInit(); );
- m_researched = m_excluded=false;
- m_effectFunction = NULL;
+ m_researched=false;
+ for ( PS_uint i=0; iSetFunction( fn );
+ m_effectFunction.SetFunction( fn );
}
else if ( Inline != CStr() )
- m_effectFunction->Compile( CStrW( filename ) + L"::" + (CStrW)funcName + L" (" + CStrW( element.getLineNumber() ) + L")", Inline );
+ m_effectFunction.Compile( CStrW( filename ) + L"::" + (CStrW)funcName + L" (" + CStrW( element.getLineNumber() ) + L")", Inline );
//(No error needed; scripts are optional)
}
else
@@ -317,7 +319,9 @@ bool CTechnology::loadELEffect( XMBElement effect, CXeromyces& XeroFile, CStr& f
}
bool CTechnology::isTechValid()
{
- if ( m_excluded )
+ if ( !m_player )
+ return false;
+ if ( m_excluded[m_player->GetPlayerID()])
return false;
if ( hasReqEntities() && hasReqTechs() )
return true;
@@ -385,20 +389,19 @@ void CTechnology::ScriptingInit()
jsval CTechnology::ApplyEffects( JSContext* cx, uintN argc, jsval* argv )
{
- if ( !isTechValid() )
- return JS_FALSE;
- else if ( argc < 3 )
+ if ( argc < 3 )
{
JS_ReportError(cx, "too few parameters for CTechnology::ApplyEffects.");
return JS_FALSE;
}
-
m_player = g_Game->GetPlayer( ToPrimitive( argv[0] ) );
- if( m_player == 0 )
+ if( !m_player )
{
JS_ReportError(cx, "invalid player number for CTechnology::ApplyEffects.");
return JS_FALSE;
}
+ if ( !isTechValid() )
+ return JS_FALSE;
bool first = ToPrimitive( argv[1] );
bool invert = ToPrimitive( argv[2] );
@@ -408,24 +411,24 @@ jsval CTechnology::ApplyEffects( JSContext* cx, uintN argc, jsval* argv )
if ( argc == 4 )
varType = ToPrimitive( argv[3] );
- if ( first && m_effectFunction )
+ if ( first )
{
- m_effectFunction->Run( this->GetScript() );
+ m_effectFunction.Run( this->GetScript() );
}
//Disable other templates
for ( std::vector::iterator it=m_Pairs.begin(); it != m_Pairs.end(); it++ )
- g_TechnologyCollection.getTechnology(*it)->setExclusion(true);
-
+ g_TechnologyCollection.getTechnology(*it)->setExclusion(m_player->GetPlayerID(), true);
+ setExclusion(m_player->GetPlayerID(), true);
+
std::vector* entities = m_player->GetControlledEntities();
if ( entities->empty() )
{
delete entities;
return JS_FALSE;
}
-
+
std::vector entitiesAffected;
-
//Find which entities should be affected
for ( size_t i=0; isize(); ++i )
{
@@ -453,7 +456,7 @@ jsval CTechnology::ApplyEffects( JSContext* cx, uintN argc, jsval* argv )
if ( varType == "int" )
*(int*)attribute += (int)modValue;
- if ( varType == "double" )
+ else if ( varType == "double" )
*(double*)attribute += (double)modValue;
else
*(float*)attribute += (float)modValue;
@@ -473,19 +476,18 @@ jsval CTechnology::ApplyEffects( JSContext* cx, uintN argc, jsval* argv )
if ( varType == "int" )
*(int*)attribute = (int)setValue;
- if ( varType == "double" )
+ else if ( varType == "double" )
*(double*)attribute = (double)setValue;
else
*(float*)attribute = (float)setValue;
}
}
- if ( !first && m_effectFunction )
+ if ( !first )
{
- m_effectFunction->Run( this->GetScript() );
+ m_effectFunction.Run( this->GetScript() );
}
delete entities;
- debug_printf("Done! I think\n");
return JS_TRUE;
}
@@ -497,7 +499,7 @@ jsval CTechnology::IsValid( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UN
}
jsval CTechnology::IsExcluded( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
{
- if ( m_excluded )
+ if ( m_excluded[m_player->GetPlayerID()] )
return JS_TRUE;
return JS_FALSE;
}
diff --git a/source/simulation/Technology.h b/source/simulation/Technology.h
index ee50bdb02e..cb51b41396 100644
--- a/source/simulation/Technology.h
+++ b/source/simulation/Technology.h
@@ -7,8 +7,9 @@
#include
#include "scripting/ScriptableObject.h"
+#include "simulation/ScriptObject.h"
+#include "ps/Game.h"
-class CStr;
class XMBElement;
class CXeromyces;
@@ -37,12 +38,11 @@ public:
jsval IsExcluded( JSContext* cx, uintN argc, jsval* argv );
inline jsval GetPlayerID( JSContext* cx, uintN argc, jsval* argv );
-
bool isTechValid();
inline bool isResearched() { return m_researched; }
void setPlayer( CPlayer* player ) { m_player=player; }
- void setExclusion( bool exclude ) { m_excluded=exclude; }
+ void setExclusion( PS_uint player, bool exclude ) { m_excluded[player]=exclude; }
bool loadXML( CStr filename );
bool loadELID( XMBElement ID, CXeromyces& XeroFile );
@@ -72,12 +72,11 @@ private:
std::vector m_Sets;
CPlayer* m_player; //Which player this tech belongs to
- CScriptObject* m_effectFunction;
+ CScriptObject m_effectFunction;
bool m_JSFirst; //Should JS effect function run before C++
- // TODO: Make these per-player
- bool m_excluded;
+ static bool m_excluded[PS_MAX_PLAYERS+1]; //Gaia is not counted in max_players
bool m_researched;
bool hasReqEntities();
diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.cpp
index 5ad976b922..0a4ba73f1b 100644
--- a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.cpp
+++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.cpp
@@ -7,6 +7,8 @@
#include "General/Observable.h"
#include "CustomControls/ColourDialog/ColourDialog.h"
+using AtlasMessage::Shareable;
+
static Observable g_EnvironmentSettings;
//////////////////////////////////////////////////////////////////////////
@@ -15,8 +17,8 @@ class VariableSlider : public wxSlider
{
static const int range = 1024;
public:
- VariableSlider(wxWindow* parent, float& var, float min, float max)
- : wxSlider(parent, -1, 0, 0, range),
+ VariableSlider(wxWindow* parent, Shareable& var, float min, float max)
+ : wxSlider(parent, wxID_ANY, 0, 0, range),
m_Var(var), m_Min(min), m_Max(max)
{
}
@@ -33,7 +35,7 @@ public:
}
private:
- float& m_Var;
+ Shareable& m_Var;
float m_Min, m_Max;
DECLARE_EVENT_TABLE();
@@ -46,7 +48,7 @@ END_EVENT_TABLE()
class VariableSliderBox : public wxStaticBoxSizer
{
public:
- VariableSliderBox(wxWindow* parent, const wxString& label, float& var, float min, float max)
+ VariableSliderBox(wxWindow* parent, const wxString& label, Shareable& var, float min, float max)
: wxStaticBoxSizer(wxVERTICAL, parent, label)
{
m_Slider = new VariableSlider(parent, var, min, max);
@@ -72,11 +74,82 @@ private:
//////////////////////////////////////////////////////////////////////////
+class VariableCombo : public wxComboBox
+{
+ static const int range = 1024;
+public:
+ VariableCombo(wxWindow* parent, Shareable& var)
+ : wxComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxArrayString(), wxCB_READONLY),
+ m_Var(var)
+ {
+ }
+
+ void OnSelect(wxCommandEvent& WXUNUSED(evt))
+ {
+ m_Var = std::wstring(GetValue().c_str());
+ POST_COMMAND(SetEnvironmentSettings, (g_EnvironmentSettings));
+ }
+
+ void UpdateFromVar()
+ {
+ SetValue(m_Var.c_str());
+ }
+
+private:
+ Shareable& m_Var;
+
+ DECLARE_EVENT_TABLE();
+};
+
+BEGIN_EVENT_TABLE(VariableCombo, wxComboBox)
+ EVT_COMBOBOX(wxID_ANY, OnSelect)
+END_EVENT_TABLE()
+
+class VariableListBox : public wxStaticBoxSizer
+{
+public:
+ VariableListBox(wxWindow* parent, const wxString& label, Shareable& var)
+ : wxStaticBoxSizer(wxVERTICAL, parent, label)
+ {
+ m_Combo = new VariableCombo(parent, var);
+ Add(m_Combo);
+
+ m_Conn = g_EnvironmentSettings.RegisterObserver(0, &VariableListBox::OnSettingsChange, this);
+ }
+
+ ~VariableListBox()
+ {
+ m_Conn.disconnect();
+ }
+
+ void SetChoices(const std::vector& choices)
+ {
+ wxArrayString choices_arraystr;
+ for (size_t i = 0; i < choices.size(); ++i)
+ choices_arraystr.Add(choices[i].c_str());
+
+ m_Combo->Clear();
+ m_Combo->Append(choices_arraystr);
+
+ m_Combo->UpdateFromVar();
+ }
+
+ void OnSettingsChange(const AtlasMessage::sEnvironmentSettings& WXUNUSED(env))
+ {
+ m_Combo->UpdateFromVar();
+ }
+
+private:
+ ObservableConnection m_Conn;
+ VariableCombo* m_Combo;
+};
+
+//////////////////////////////////////////////////////////////////////////
class VariableColourButton : public wxButton
{
public:
- VariableColourButton(wxWindow* parent, AtlasMessage::Colour& colour)
- : wxButton(parent, -1), m_Colour(colour)
+ VariableColourButton(wxWindow* parent, Shareable& colour)
+ : wxButton(parent, wxID_ANY), m_Colour(colour)
{
UpdateDisplay();
}
@@ -84,7 +157,7 @@ public:
void OnClick(wxCommandEvent& WXUNUSED(evt))
{
ColourDialog dlg (NULL, _T("Scenario Editor/LightingColour"),
- wxColour(m_Colour.r, m_Colour.g, m_Colour.b));
+ wxColour(m_Colour->r, m_Colour->g, m_Colour->b));
if (dlg.ShowModal() == wxID_OK)
{
@@ -98,10 +171,10 @@ public:
void UpdateDisplay()
{
- SetBackgroundColour(wxColour(m_Colour.r, m_Colour.g, m_Colour.b));
- SetLabel(wxString::Format(_T("%02X %02X %02X"), m_Colour.r, m_Colour.g, m_Colour.b));
+ SetBackgroundColour(wxColour(m_Colour->r, m_Colour->g, m_Colour->b));
+ SetLabel(wxString::Format(_T("%02X %02X %02X"), m_Colour->r, m_Colour->g, m_Colour->b));
- int y = 3*m_Colour.r + 6*m_Colour.g + 1*m_Colour.b;
+ int y = 3*m_Colour->r + 6*m_Colour->g + 1*m_Colour->b;
if (y > 1280)
SetForegroundColour(wxColour(0, 0, 0));
else
@@ -109,7 +182,7 @@ public:
}
private:
- AtlasMessage::Colour& m_Colour;
+ Shareable& m_Colour;
DECLARE_EVENT_TABLE();
};
@@ -121,7 +194,7 @@ END_EVENT_TABLE()
class VariableColourBox : public wxStaticBoxSizer
{
public:
- VariableColourBox(wxWindow* parent, const wxString& label, AtlasMessage::Colour& colour)
+ VariableColourBox(wxWindow* parent, const wxString& label, Shareable& colour)
: wxStaticBoxSizer(wxVERTICAL, parent, label)
{
m_Button = new VariableColourButton(parent, colour);
@@ -155,6 +228,7 @@ EnvironmentSidebar::EnvironmentSidebar(wxWindow* sidebarContainer, wxWindow* bot
m_MainSizer->Add(new VariableSliderBox(this, _("Water waviness"), g_EnvironmentSettings.waterwaviness, 0, 10.f));
m_MainSizer->Add(new VariableSliderBox(this, _("Sun rotation"), g_EnvironmentSettings.sunrotation, 0, 2*M_PI));
m_MainSizer->Add(new VariableSliderBox(this, _("Sun elevation"), g_EnvironmentSettings.sunelevation, -M_PI/2, M_PI/2));
+ m_MainSizer->Add(m_SkyList = new VariableListBox(this, _("Sky set"), g_EnvironmentSettings.skyset));
m_MainSizer->Add(new VariableColourBox(this, _("Sun colour"), g_EnvironmentSettings.suncolour));
m_MainSizer->Add(new VariableColourBox(this, _("Terrain ambient colour"), g_EnvironmentSettings.terraincolour));
m_MainSizer->Add(new VariableColourBox(this, _("Object ambient colour"), g_EnvironmentSettings.unitcolour));
@@ -162,9 +236,15 @@ EnvironmentSidebar::EnvironmentSidebar(wxWindow* sidebarContainer, wxWindow* bot
void EnvironmentSidebar::OnFirstDisplay()
{
- AtlasMessage::qGetEnvironmentSettings qry;
- qry.Post();
- g_EnvironmentSettings = qry.settings;
+ // Load the list of skies. (Can only be done now rather than in the constructor,
+ // after the game has been initialised.)
+ AtlasMessage::qGetSkySets qry_skysets;
+ qry_skysets.Post();
+ m_SkyList->SetChoices(*qry_skysets.skysets);
+
+ AtlasMessage::qGetEnvironmentSettings qry_env;
+ qry_env.Post();
+ g_EnvironmentSettings = qry_env.settings;
g_EnvironmentSettings.NotifyObservers();
// TODO: reupdate everything when loading a new map...
diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.h b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.h
index 7930828f74..1144ac8094 100644
--- a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.h
+++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.h
@@ -1,5 +1,7 @@
#include "../Common/Sidebar.h"
+class VariableListBox;
+
class EnvironmentSidebar : public Sidebar
{
public:
@@ -7,4 +9,7 @@ public:
protected:
virtual void OnFirstDisplay();
+
+private:
+ VariableListBox* m_SkyList;
};
diff --git a/source/tools/atlas/GameInterface/CommandProc.h b/source/tools/atlas/GameInterface/CommandProc.h
index 0f254f0496..3d197279a0 100644
--- a/source/tools/atlas/GameInterface/CommandProc.h
+++ b/source/tools/atlas/GameInterface/CommandProc.h
@@ -47,29 +47,118 @@ extern cmdHandlers& GetCmdHandlers();
CommandProc& GetCommandProc();
-struct DataCommand : public Command // so commands can optionally override (De|Con)struct
-{
- void Destruct() {};
- void Construct() {};
- // MergeIntoPrevious should be overridden by commands, and implemented
- // to update 'prev' to include the effects of 'this'
- void MergeIntoPrevious(void*) { debug_warn("MergeIntoPrevious unimplemented in some command"); }
-};
+/*
+We want the command handler implementations to be as pretty as possible - so let people write
+
+ BEGIN_COMMAND(CommandName)
+ {
+ int member;
+ cCommandName() { ... } // } both are optional; neither may
+ ~cCommandName() { ... } // } make use of this->msg
+
+ void Do() { ... interact with this->msg ... }
+ void Undo() { ... }
+ void Redo() { ... }
+
+ void MergeIntoPrevious(cCommandName* prev) { ... } // iff this command is a mergeable one
+ };
+ END_COMMAND(CommandName)
+
+which looks almost exactly like a class definition, and is about the simplest
+system I can find.
+
+
+The following macros convert that into:
+
+ class cCommandName_base : public Command
+ {
+ protected:
+ // Storage for data passed into this command
+ dCommandName* msg;
+ public:
+ // Ensure msg is initialised to something 'safe'
+ cCommandName_base : msg(NULL) {}
+
+ // MergeIntoPrevious should be overridden by mergeable commands, and implemented
+ // to update 'prev' to include the effects of 'this'. (A subclass overriding
+ // any function named 'MergeIntoPrevious' will hide this function, even if
+ // the types differ.)
+ void MergeIntoPrevious(void*) { ...error - needs to be overridden... }
+ };
+
+ // Use 'struct' for automatic publicness - we want users to write as little as possible
+ struct cCommandName : public cCommandName_base
+ {
+ // (user's command code - mostly overriding virtual methods from Command)
+ }
+
+ // Subclass the command to add things which require knowledge of the
+ // complete class definition
+ class cCommandName_sub : public cCommandName
+ {
+ public:
+ cCommandName_sub(dCommandName *data) { ...set msg... }
+ ~cCommandName_sub() { ...clear msg... }
+
+ // Implement the relevant virtual methods from the Command base class,
+ // with automatic casting to the correct types and stuff
+ virtual void Merge(Command* prev) { ...call MergeIntoPrevious... }
+ virtual const char* GetType() const { return "CommandName"; }
+
+ // Factory method for creating an instance of this class, casting the
+ // data pointer into the right form (to avoid forcing the generic
+ // command-handling support code to worry about the types)
+ static Command* Create(const void* data) { ...return new cCommandName_sub... }
+ };
+
+ // Register.cpp wants to get that Create method, but it doesn't want to
+ // load all the class definitions; so define a simple method that just
+ // returns the address of Create
+ cmdHandler cCommandName_create()
+ {
+ return &cCommandName_sub::Create;
+ }
+
+// (TODO: make sure this stays in sync with the code below)
+
+*/
#define BEGIN_COMMAND(t) \
- class c##t : public DataCommand \
+ class c##t##_base : public Command \
{ \
+ protected: \
d##t* msg; \
public: \
- c##t(d##t* data) : msg(data) { Construct(); } \
- ~c##t() { Destruct(); AtlasMessage::ShareableDelete(msg); /* msg was allocated by mDoCommand() */ } \
- static Command* Create(const void* data) { return new c##t ((d##t*)data); } \
- virtual void Merge(Command* prev) { MergeIntoPrevious((c##t*)prev); } \
- virtual const char* GetType() const { return #t; }
+ c##t##_base() : msg(NULL) {} \
+ void MergeIntoPrevious(void*) { debug_warn("MergeIntoPrevious unimplemented in command " #t); } \
+ }; \
+ struct c##t : public c##t##_base
#define END_COMMAND(t) \
+ class c##t##_sub : public c##t \
+ { \
+ public: \
+ c##t##_sub(d##t* data) \
+ { \
+ msg = data; \
+ } \
+ ~c##t##_sub() \
+ { \
+ /* (msg was allocated in mDoCommand(), using SHAREABLE_NEW) */ \
+ AtlasMessage::ShareableDelete(msg); \
+ msg = NULL; \
+ } \
+ virtual void Merge(Command* prev) { MergeIntoPrevious(static_cast(prev)); } \
+ virtual const char* GetType() const { return #t; } \
+ static Command* Create(const void* data) \
+ { \
+ return new c##t##_sub (reinterpret_cast(const_cast(data))); \
+ } \
}; \
- cmdHandler c##t##__create() { \
- return &c##t ::Create; \
+ cmdHandler c##t##_create() \
+ { \
+ return &c##t##_sub ::Create; \
}
+
+
}
diff --git a/source/tools/atlas/GameInterface/Handlers/ElevationHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/ElevationHandlers.cpp
index 0c42b0d574..4f376f3fb6 100644
--- a/source/tools/atlas/GameInterface/Handlers/ElevationHandlers.cpp
+++ b/source/tools/atlas/GameInterface/Handlers/ElevationHandlers.cpp
@@ -79,16 +79,13 @@ protected:
BEGIN_COMMAND(AlterElevation)
-
+{
TerrainArray m_TerrainDelta;
- void Construct()
+ cAlterElevation()
{
m_TerrainDelta.Init();
}
- void Destruct()
- {
- }
void Do()
{
@@ -142,22 +139,19 @@ BEGIN_COMMAND(AlterElevation)
{
prev->m_TerrainDelta.OverlayWith(m_TerrainDelta);
}
-
+};
END_COMMAND(AlterElevation)
//////////////////////////////////////////////////////////////////////////
BEGIN_COMMAND(FlattenElevation)
-
+{
TerrainArray m_TerrainDelta;
- void Construct()
+ cFlattenElevation()
{
m_TerrainDelta.Init();
}
- void Destruct()
- {
- }
void Do()
{
@@ -204,7 +198,7 @@ BEGIN_COMMAND(FlattenElevation)
{
prev->m_TerrainDelta.OverlayWith(m_TerrainDelta);
}
-
+};
END_COMMAND(FlattenElevation)
}
diff --git a/source/tools/atlas/GameInterface/Handlers/EnvironmentHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/EnvironmentHandlers.cpp
index e005bdc4f9..5d27d8e8de 100644
--- a/source/tools/atlas/GameInterface/Handlers/EnvironmentHandlers.cpp
+++ b/source/tools/atlas/GameInterface/Handlers/EnvironmentHandlers.cpp
@@ -8,6 +8,7 @@
#include "graphics/Terrain.h"
#include "ps/World.h"
#include "renderer/Renderer.h"
+#include "renderer/SkyManager.h"
#include "renderer/WaterManager.h"
namespace AtlasMessage {
@@ -24,6 +25,8 @@ sEnvironmentSettings GetSettings()
s.sunrotation = g_LightEnv.GetRotation();
s.sunelevation = g_LightEnv.GetElevation();
+ s.skyset = g_Renderer.GetSkyManager()->GetSkySet();
+
#define COLOUR(A, B) A = Colour(B.X*255, B.Y*255, B.Z*255)
COLOUR(s.suncolour, g_LightEnv.m_SunColor);
COLOUR(s.terraincolour, g_LightEnv.m_TerrainAmbientColor);
@@ -43,7 +46,9 @@ void SetSettings(const sEnvironmentSettings& s)
g_LightEnv.SetRotation(s.sunrotation);
g_LightEnv.SetElevation(s.sunelevation);
-#define COLOUR(A, B) B = RGBColor(A.r/255.f, A.g/255.f, A.b/255.f)
+ g_Renderer.GetSkyManager()->SetSkySet(*s.skyset);
+
+#define COLOUR(A, B) B = RGBColor(A->r/255.f, A->g/255.f, A->b/255.f)
COLOUR(s.suncolour, g_LightEnv.m_SunColor);
COLOUR(s.terraincolour, g_LightEnv.m_TerrainAmbientColor);
COLOUR(s.unitcolour, g_LightEnv.m_UnitsAmbientColor);
@@ -51,7 +56,7 @@ void SetSettings(const sEnvironmentSettings& s)
}
BEGIN_COMMAND(SetEnvironmentSettings)
-
+{
sEnvironmentSettings m_OldSettings, m_NewSettings;
void Do()
@@ -75,7 +80,7 @@ BEGIN_COMMAND(SetEnvironmentSettings)
{
prev->m_NewSettings = m_NewSettings;
}
-
+};
END_COMMAND(SetEnvironmentSettings)
QUERYHANDLER(GetEnvironmentSettings)
@@ -83,4 +88,10 @@ QUERYHANDLER(GetEnvironmentSettings)
msg->settings = GetSettings();
}
+QUERYHANDLER(GetSkySets)
+{
+ std::vector skies = g_Renderer.GetSkyManager()->GetSkySets();
+ msg->skysets = std::vector(skies.begin(), skies.end());
+}
+
}
diff --git a/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp
index b009f46f60..c7971c28b2 100644
--- a/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp
+++ b/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp
@@ -109,7 +109,8 @@ MESSAGEHANDLER(SaveMap)
CMapWriter writer;
writer.SaveMap(CStr(L"maps/scenarios/" + *msg->filename),
g_Game->GetWorld()->GetTerrain(), g_Game->GetWorld()->GetUnitManager(),
- g_Renderer.GetWaterManager(), &g_LightEnv, g_Game->GetView()->GetCamera());
+ g_Renderer.GetWaterManager(), g_Renderer.GetSkyManager(),
+ &g_LightEnv, g_Game->GetView()->GetCamera());
}
}
diff --git a/source/tools/atlas/GameInterface/Handlers/MessageHandler.h b/source/tools/atlas/GameInterface/Handlers/MessageHandler.h
index c43ae09110..d07bd1db58 100644
--- a/source/tools/atlas/GameInterface/Handlers/MessageHandler.h
+++ b/source/tools/atlas/GameInterface/Handlers/MessageHandler.h
@@ -12,7 +12,7 @@ extern msgHandlers& GetMsgHandlers();
#define THINGHANDLER(prefix, expectedtype, t) \
void f##t(prefix##t*); \
- void f##t##__wrapper(IMessage* msg) { \
+ void f##t##_wrapper(IMessage* msg) { \
debug_assert(msg->GetType() == IMessage::expectedtype); \
f##t (static_cast(msg)); \
} \
diff --git a/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp
index 72e2bccc25..c3b929a72e 100644
--- a/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp
+++ b/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp
@@ -154,7 +154,7 @@ QUERYHANDLER(GetObjectSettings)
}
BEGIN_COMMAND(SetObjectSettings)
-
+{
int m_PlayerOld, m_PlayerNew;
std::set m_SelectionsOld, m_SelectionsNew;
@@ -194,7 +194,7 @@ BEGIN_COMMAND(SetObjectSettings)
unit->SetPlayerID(m_PlayerOld);
unit->SetActorSelections(m_SelectionsOld);
}
-
+};
END_COMMAND(SetObjectSettings);
//////////////////////////////////////////////////////////////////////////
@@ -320,7 +320,7 @@ MESSAGEHANDLER(ObjectPreview)
}
BEGIN_COMMAND(CreateObject)
-
+{
CVector3D m_Pos;
float m_Angle;
int m_ID;
@@ -430,7 +430,7 @@ BEGIN_COMMAND(CreateObject)
}
}
}
-
+};
END_COMMAND(CreateObject)
@@ -471,7 +471,7 @@ QUERYHANDLER(PickObject)
BEGIN_COMMAND(MoveObject)
-
+{
CVector3D m_PosOld, m_PosNew;
void Do()
@@ -527,12 +527,12 @@ BEGIN_COMMAND(MoveObject)
debug_assert(prev->msg->id == msg->id);
prev->m_PosNew = m_PosNew;
}
-
+};
END_COMMAND(MoveObject)
BEGIN_COMMAND(RotateObject)
-
+{
float m_AngleOld, m_AngleNew;
CMatrix3D m_TransformOld, m_TransformNew;
@@ -620,20 +620,20 @@ BEGIN_COMMAND(RotateObject)
prev->m_AngleNew = m_AngleNew;
prev->m_TransformNew = m_TransformNew;
}
-
+};
END_COMMAND(RotateObject)
BEGIN_COMMAND(DeleteObject)
-
+{
CUnit* m_UnitInLimbo;
- void Construct()
+ cDeleteObject()
{
m_UnitInLimbo = NULL;
}
- void Destruct()
+ ~cDeleteObject()
{
if (m_UnitInLimbo)
{
@@ -672,7 +672,7 @@ BEGIN_COMMAND(DeleteObject)
g_UnitMan.AddUnit(m_UnitInLimbo);
m_UnitInLimbo = NULL;
}
-
+};
END_COMMAND(DeleteObject)
diff --git a/source/tools/atlas/GameInterface/Handlers/TerrainHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/TerrainHandlers.cpp
index 8458c6a118..48c4854e56 100644
--- a/source/tools/atlas/GameInterface/Handlers/TerrainHandlers.cpp
+++ b/source/tools/atlas/GameInterface/Handlers/TerrainHandlers.cpp
@@ -99,7 +99,7 @@ QUERYHANDLER(GetTerrainGroupPreviews)
//////////////////////////////////////////////////////////////////////////
BEGIN_COMMAND(PaintTerrain)
-
+{
struct TerrainTile
{
TerrainTile(Handle t, int p) : tex(t), priority(p) {}
@@ -155,13 +155,10 @@ BEGIN_COMMAND(PaintTerrain)
TerrainArray m_TerrainDelta;
- void Construct()
+ cPaintTerrain()
{
m_TerrainDelta.Init();
}
- void Destruct()
- {
- }
void Do()
{
@@ -205,7 +202,7 @@ BEGIN_COMMAND(PaintTerrain)
{
prev->m_TerrainDelta.OverlayWith(m_TerrainDelta);
}
-
+};
END_COMMAND(PaintTerrain)
diff --git a/source/tools/atlas/GameInterface/Messages.h b/source/tools/atlas/GameInterface/Messages.h
index 59cd5fbe92..b3f6f426f3 100644
--- a/source/tools/atlas/GameInterface/Messages.h
+++ b/source/tools/atlas/GameInterface/Messages.h
@@ -172,19 +172,18 @@ MESSAGE(RotateAround,
struct sEnvironmentSettings
{
- float waterheight; // range 0..1 corresponds to min..max terrain height; out-of-bounds values allowed
- float watershininess;
- float waterwaviness;
+ Shareable waterheight; // range 0..1 corresponds to min..max terrain height; out-of-bounds values allowed
+ Shareable watershininess;
+ Shareable waterwaviness;
- float sunrotation; // range 0..2pi
- float sunelevation; // range -pi/2 .. +pi/2
+ Shareable sunrotation; // range 0..2pi
+ Shareable sunelevation; // range -pi/2 .. +pi/2
- Colour suncolour;
- Colour terraincolour;
- Colour unitcolour;
+ Shareable skyset;
- // (Note: None of these are declared as Shareable<> - they're all sufficiently
- // primitive types, and this makes it easier to manipulate them)
+ Shareable suncolour;
+ Shareable terraincolour;
+ Shareable unitcolour;
};
SHAREABLE_STRUCT(sEnvironmentSettings);
@@ -198,6 +197,13 @@ COMMAND(SetEnvironmentSettings, MERGE,
((sEnvironmentSettings, settings))
);
+QUERY(GetSkySets,
+ // no inputs
+ ,
+ ((std::vector, skysets))
+ );
+
+
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
diff --git a/source/tools/atlas/GameInterface/Register.cpp b/source/tools/atlas/GameInterface/Register.cpp
index 5dd71e9384..107692401f 100644
--- a/source/tools/atlas/GameInterface/Register.cpp
+++ b/source/tools/atlas/GameInterface/Register.cpp
@@ -23,16 +23,16 @@ typedef std::map cmdHandlers;
extern cmdHandlers& GetCmdHandlers();
#define MESSAGE(name, vals) \
- extern void f##name##__wrapper(AtlasMessage::IMessage*); \
- AtlasMessage::GetMsgHandlers().insert(std::pair(#name, &f##name##__wrapper));
+ extern void f##name##_wrapper(AtlasMessage::IMessage*); \
+ AtlasMessage::GetMsgHandlers().insert(std::pair(#name, &f##name##_wrapper));
#define QUERY(name, in_vals, out_vals) \
- extern void f##name##__wrapper(AtlasMessage::IMessage*); \
- AtlasMessage::GetMsgHandlers().insert(std::pair(#name, &f##name##__wrapper));
+ extern void f##name##_wrapper(AtlasMessage::IMessage*); \
+ AtlasMessage::GetMsgHandlers().insert(std::pair(#name, &f##name##_wrapper));
#define COMMAND(name, merge, vals) \
- extern cmdHandler c##name##__create(); \
- GetCmdHandlers().insert(std::pair("c"#name, c##name##__create()));
+ extern cmdHandler c##name##_create(); \
+ GetCmdHandlers().insert(std::pair("c"#name, c##name##_create()));
#define FUNCTION(def)
@@ -53,4 +53,3 @@ void RegisterHandlers()
}
}
-