1
0
forked from 0ad/0ad

Restoring SVN repository:

Greek basket texture

# New Greek vases

# housekeeping
documentation fix: trailing / in directory names is mandatory

# Atlas: Sky texture selection; save with maps

Atlas code tidying: Slightly nicer syntax for defining command handlers,
and some explanation of how it works

Automated build.

This was SVN commit r4008.
This commit is contained in:
Ykkrosh 2006-06-21 22:37:31 +00:00
parent 823c93ce47
commit 92b9c07f95
38 changed files with 546 additions and 207 deletions

View File

@ -52,6 +52,11 @@
<Height>-1.0</Height>
<Name></Name>
</Rank>
<Rally>
<Name>elite.dds</Name>
<Height>7.0</Height>
<Width>7.0</Width>
</Rally>
<Flank_Penalty>
<Sectors>6</Sectors>

View File

@ -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));
}
}

View File

@ -37,7 +37,15 @@ function worldClickHandler(event)
{
return;
}
//setting rally point
if ( getCursorName() == "cursor-rally" )
{
for ( var i=0; i<selection.length; i++ )
selection[i].setRallyPoint();
setCursor("arrow-default");
return;
}
switch (cmd)
{
// location target commands
@ -103,7 +111,6 @@ function worldClickHandler(event)
default:
console.write("worldClickHandler: Unknown order: "+cmd);
return;
break;
}
if (event.clicks == 2)

View File

@ -459,7 +459,7 @@ function performAttackRanged( evt )
dmg.crush += dmg.crush * elevationBonus;
dmg.hack += dmg.hack * elevationBonus;
dmg.pierce += dmg.pierce * elevationBonus;
console.write( dmg.crush + "|" + dmg.hack );
if(evt.target.traits.flank_penalty)
{
var flank = (evt.target.getAttackDirections()-1)*evt.target.traits.flank_penalty.value;
@ -948,7 +948,13 @@ function entityEventTargetChanged( evt )
// If we can gather, and the target supplies, gather. If it's our enemy, and we're armed, attack.
// If all else fails, move (or run on a right-click).
if ( getCursorName() == "cursor-rally" )
{
evt.defaultCursor = "cursor-rally";
evt.defaultOrder = -1;
return;
}
evt.defaultOrder = NMT_Goto;
evt.defaultCursor = "arrow-default";
evt.defaultAction = ACTION_NONE;
@ -1289,6 +1295,8 @@ function entityFinishProduction( evt )
if( created )
{
console.write( "Created: ", template.tag );
var rally = this.getRallyPoint();
created.order( ORDER_GOTO, rally.x, rally.z );
}
}
}

View File

@ -41,8 +41,8 @@
<Value>2</Value>
</Modifier>
<Script File="" />
<Function Name="" />
<Script File="scripts/tech_functions.js" />
<Function Name="techExample" />
</Effect>
</Tech>

View File

@ -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(),

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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<STileDesc>& 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

View File

@ -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.
// <v_dir> 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

View File

@ -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.
// <v_dir> 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.

View File

@ -379,6 +379,9 @@ void Render()
PROFILE_END( "render health bars" );
glPopAttrib();
//Depth test is now enabled
g_Selection.renderRallyPoints();
g_Mouseover.renderRallyPoints();
}
else
{

View File

@ -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<HEntity>::iterator it;
for( it = m_selected.begin(); it < m_selected.end(); it++ )
(*it)->renderRallyPoint();
if( m_group_highlight != -1 )
{
std::vector<HEntity>::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<SMouseoverFader>::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)
{

View File

@ -80,6 +80,7 @@ struct CSelectedEntities : public Singleton<CSelectedEntities>
void renderStaminaBars();
void renderRanks();
void renderBarBorders();
void renderRallyPoints();
void destroyUnitUITextures();
int loadUnitUITextures();
@ -136,6 +137,7 @@ struct CMouseoverEntities : public Singleton<CMouseoverEntities>
void renderStaminaBars();
void renderRanks();
void renderBarBorders();
void renderRallyPoints();
bool isBandbox() { return( m_bandbox ); }
void startBandbox( u16 x, u16 y );

View File

@ -8,7 +8,7 @@ namespace VFSUtil
typedef std::vector<CStr> 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.

View File

@ -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());
}

View File

@ -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<CStrW> SkyManager::GetSkySets() const
{
std::vector<CStrW> 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<CStrW>(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<CStrW>(1, GetSkySet()); // just return what we currently have
}
vfs_dir_close(dir);
sort(skies.begin(), skies.end());
return skies;
}
///////////////////////////////////////////////////////////////////
// Render sky

View File

@ -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<CStrW> GetSkySets() const;
private:
/// Name of current skyset (a directory within art/textures/skies)
CStrW m_SkySet;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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<jsval, &CEntity::GetAttackDirections>( "getAttackDirections", 0 );
AddMethod<jsval, &CEntity::FindSector>("findSector", 4);
AddMethod<jsval, &CEntity::GetHeight>("getHeight", 0 );
AddMethod<jsval, &CEntity::HasRallyPoint>("hasRallyPoint", 0 );
AddMethod<jsval, &CEntity::SetRallyPoint>("setRallyPoint", 0 );
AddMethod<jsval, &CEntity::GetRallyPoint>("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;
}

View File

@ -67,9 +67,6 @@ public:
//Attributes table: key=attribute, value=variable name
static std::map<CStr, size_t> 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 );

View File

@ -14,13 +14,15 @@
#define LOG_CATEGORY "Techs"
STL_HASH_SET<CStr, CStr_hash_compare> 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; i<PS_MAX_PLAYERS; ++i )
m_excluded[i] = false;
m_JSFirst = false;
}
bool CTechnology::loadXML( CStr filename )
@ -300,10 +302,10 @@ bool CTechnology::loadELEffect( XMBElement effect, CXeromyces& XeroFile, CStr& f
LOG( ERROR, LOG_CATEGORY, "CTechnology::LoadXML: Function does not exist for %hs in file %s. Load failed.", funcName.c_str(), filename.c_str() );
return false;
}
m_effectFunction->SetFunction( 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<PS_uint>( 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<bool>( argv[1] );
bool invert = ToPrimitive<bool>( argv[2] );
@ -408,24 +411,24 @@ jsval CTechnology::ApplyEffects( JSContext* cx, uintN argc, jsval* argv )
if ( argc == 4 )
varType = ToPrimitive<CStr>( argv[3] );
if ( first && m_effectFunction )
if ( first )
{
m_effectFunction->Run( this->GetScript() );
m_effectFunction.Run( this->GetScript() );
}
//Disable other templates
for ( std::vector<CStr>::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<HEntity>* entities = m_player->GetControlledEntities();
if ( entities->empty() )
{
delete entities;
return JS_FALSE;
}
std::vector<HEntity> entitiesAffected;
//Find which entities should be affected
for ( size_t i=0; i<entities->size(); ++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;
}

View File

@ -7,8 +7,9 @@
#include <vector>
#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<Modifier> 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();

View File

@ -7,6 +7,8 @@
#include "General/Observable.h"
#include "CustomControls/ColourDialog/ColourDialog.h"
using AtlasMessage::Shareable;
static Observable<AtlasMessage::sEnvironmentSettings> 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<float>& 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<float>& 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<float>& 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<std::wstring>& 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<std::wstring>& 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<std::wstring>& 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<std::wstring>& 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<AtlasMessage::Colour>& 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<AtlasMessage::Colour>& 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<AtlasMessage::Colour>& 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...

View File

@ -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;
};

View File

@ -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<c##t##_sub*>(prev)); } \
virtual const char* GetType() const { return #t; } \
static Command* Create(const void* data) \
{ \
return new c##t##_sub (reinterpret_cast<d##t*>(const_cast<void*>(data))); \
} \
}; \
cmdHandler c##t##__create() { \
return &c##t ::Create; \
cmdHandler c##t##_create() \
{ \
return &c##t##_sub ::Create; \
}
}

View File

@ -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)
}

View File

@ -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<CStrW> skies = g_Renderer.GetSkyManager()->GetSkySets();
msg->skysets = std::vector<std::wstring>(skies.begin(), skies.end());
}
}

View File

@ -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());
}
}

View File

@ -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<prefix##t*>(msg)); \
} \

View File

@ -154,7 +154,7 @@ QUERYHANDLER(GetObjectSettings)
}
BEGIN_COMMAND(SetObjectSettings)
{
int m_PlayerOld, m_PlayerNew;
std::set<CStrW> 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)

View File

@ -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)

View File

@ -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<float> waterheight; // range 0..1 corresponds to min..max terrain height; out-of-bounds values allowed
Shareable<float> watershininess;
Shareable<float> waterwaviness;
float sunrotation; // range 0..2pi
float sunelevation; // range -pi/2 .. +pi/2
Shareable<float> sunrotation; // range 0..2pi
Shareable<float> sunelevation; // range -pi/2 .. +pi/2
Colour suncolour;
Colour terraincolour;
Colour unitcolour;
Shareable<std::wstring> skyset;
// (Note: None of these are declared as Shareable<> - they're all sufficiently
// primitive types, and this makes it easier to manipulate them)
Shareable<Colour> suncolour;
Shareable<Colour> terraincolour;
Shareable<Colour> unitcolour;
};
SHAREABLE_STRUCT(sEnvironmentSettings);
@ -198,6 +197,13 @@ COMMAND(SetEnvironmentSettings, MERGE,
((sEnvironmentSettings, settings))
);
QUERY(GetSkySets,
// no inputs
,
((std::vector<std::wstring>, skysets))
);
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

View File

@ -23,16 +23,16 @@ typedef std::map<std::string, cmdHandler> cmdHandlers;
extern cmdHandlers& GetCmdHandlers();
#define MESSAGE(name, vals) \
extern void f##name##__wrapper(AtlasMessage::IMessage*); \
AtlasMessage::GetMsgHandlers().insert(std::pair<std::string, AtlasMessage::msgHandler>(#name, &f##name##__wrapper));
extern void f##name##_wrapper(AtlasMessage::IMessage*); \
AtlasMessage::GetMsgHandlers().insert(std::pair<std::string, AtlasMessage::msgHandler>(#name, &f##name##_wrapper));
#define QUERY(name, in_vals, out_vals) \
extern void f##name##__wrapper(AtlasMessage::IMessage*); \
AtlasMessage::GetMsgHandlers().insert(std::pair<std::string, AtlasMessage::msgHandler>(#name, &f##name##__wrapper));
extern void f##name##_wrapper(AtlasMessage::IMessage*); \
AtlasMessage::GetMsgHandlers().insert(std::pair<std::string, AtlasMessage::msgHandler>(#name, &f##name##_wrapper));
#define COMMAND(name, merge, vals) \
extern cmdHandler c##name##__create(); \
GetCmdHandlers().insert(std::pair<std::string, cmdHandler>("c"#name, c##name##__create()));
extern cmdHandler c##name##_create(); \
GetCmdHandlers().insert(std::pair<std::string, cmdHandler>("c"#name, c##name##_create()));
#define FUNCTION(def)
@ -53,4 +53,3 @@ void RegisterHandlers()
}
}