1
1
forked from 0ad/0ad

Terrain XML loading, plus mouse/JS portability and some misc stuff to mix it up

This was SVN commit r2412.
This commit is contained in:
Simon Brenner 2005-06-20 15:14:36 +00:00
parent 047e1e8c7f
commit 7577d224a6
22 changed files with 536 additions and 203 deletions

View File

@ -14,6 +14,7 @@
#include "Model.h"
#include "Terrain.h"
#include "TextureManager.h"
#include "TextureEntry.h"
#include "timer.h"
#include "Loader.h"

View File

@ -1,6 +1,8 @@
#include "precompiled.h"
#include "lib/types.h"
#include "lib/res/vfs.h"
#include "MapWriter.h"
#include "MapReader.h"
#include "UnitManager.h"
@ -11,11 +13,11 @@
#include "Terrain.h"
#include "LightEnv.h"
#include "TextureManager.h"
#include "TextureEntry.h"
#include "VFSUtil.h"
#include "Loader.h"
#include "ps/XMLWriter.h"
#include "lib/res/vfs.h"
#include "simulation/Entity.h"
#include "simulation/BaseEntity.h"
#include "simulation/BaseEntityCollection.h"
@ -101,7 +103,7 @@ void CMapWriter::EnumTerrainTextures(CTerrain *pTerrain,
// uh-oh, this shouldn't happen; set texturename to empty string
texturename="";
} else {
texturename=texentry->GetName();
texturename=texentry->GetTag();
}
textures.push_back(texturename);
}

View File

@ -5,6 +5,7 @@ class CModel;
class CSkeletonAnim;
struct SPropPoint;
#include <map>
#include <vector>
#include <map>
#include "CStr.h"

View File

@ -1,19 +1,35 @@
#include "precompiled.h"
#include <string>
#include "ogl.h"
#include "res/ogl_tex.h"
#include "CLogger.h"
#include "TextureEntry.h"
#include "TextureManager.h"
#include "Texture.h"
#include "CLogger.h"
#include "Renderer.h"
#include "Overlay.h"
#include "Parser.h"
#include "XeroXMB.h"
#include "Xeromyces.h"
using namespace std;
#define LOG_CATEGORY "graphics"
/////////////////////////////////////////////////////////////////////////////////////
// CTextureEntry constructor
CTextureEntry::CTextureEntry(const char* name,int type)
: m_Name(name), m_Bitmap(0), m_Handle(-1), m_BaseColor(0), m_Type(type), m_BaseColorValid(false)
{
}
CTextureEntry::CTextureEntry():
m_pParent(NULL),
m_Bitmap(NULL),
m_Handle(-1),
m_BaseColor(0),
m_BaseColorValid(false)
{}
/////////////////////////////////////////////////////////////////////////////////////
// CTextureEntry destructor
@ -21,23 +37,136 @@ CTextureEntry::~CTextureEntry()
{
if (m_Handle > 0)
tex_free(m_Handle);
GroupVector::iterator it=m_Groups.begin();
for (;it!=m_Groups.end();++it)
(*it)->RemoveTerrain(this);
}
CTextureEntry *CTextureEntry::FromXML(XMBElement node, CXeromyces *pFile)
{
CTextureEntry *thiz=new CTextureEntry();
#define ELMT(x) int elmt_##x = pFile->getElementID(#x)
#define ATTR(x) int attr_##x = pFile->getAttributeID(#x)
ELMT(doodad);
ELMT(passable);
ELMT(event);
// Terrain Attribs
ATTR(tag);
ATTR(skin);
ATTR(parent);
ATTR(mmap);
ATTR(groups);
ATTR(properties);
// Passable Attribs
ATTR(type);
ATTR(speed);
ATTR(effect);
// Doodad Attribs
ATTR(name);
ATTR(max);
// Event attribs
ATTR(on);
#undef ELMT
#undef ATTR
XMBAttributeList attribs = node.getAttributes();
for (int i=0;i<attribs.Count;i++)
{
XMBAttribute attr = attribs.item(i);
if (attr.Name == attr_tag)
thiz->m_Tag = (CStr)attr.Value;
if (attr.Name == attr_parent)
thiz->m_ParentName = (CStr)attr.Value;
else if (attr.Name == attr_skin)
{
thiz->m_TexturePath = (CStr)attr.Value;
}
else if (attr.Name == attr_groups)
{
// Parse a comma-separated list of groups, add the new entry to
// each of them
CParser parser;
CParserLine parserLine;
parser.InputTaskType("GroupList", "<_$value_,>_$value_");
if (!parserLine.ParseString(parser, (CStr)attr.Value))
continue;
for (size_t i=0;i<parserLine.GetArgCount();i++)
{
string value;
if (!parserLine.GetArgString(i, value))
continue;
CTerrainTypeGroup *pType = g_TexMan.FindGroup(value);
thiz->m_Groups.push_back(pType);
pType->AddTerrain(thiz);
}
}
else if (attr.Name == attr_mmap)
{
CColor col;
if (!col.ParseString((CStr)attr.Value, 255))
continue;
// m_BaseColor is RGBA
u8 (&baseColor)[4] = *(u8 (*)[4])&thiz->m_BaseColor;
baseColor[0] = (u8)(col.r*255);
baseColor[1] = (u8)(col.g*255);
baseColor[2] = (u8)(col.b*255);
baseColor[3] = (u8)(col.a*255);
thiz->m_BaseColorValid = true;
}
else if (attr.Name == attr_properties)
{
// TODO Parse a list of properties and store them somewhere
}
}
// TODO Parse information in child nodes and store them somewhere
LOG(NORMAL, LOG_CATEGORY, "CTextureEntry::FromXML(): Terrain type %s (texture %s) loaded", thiz->m_Tag.c_str(), thiz->m_TexturePath.c_str());
return thiz;
}
void CTextureEntry::LoadParent()
{
// Don't do anything at all if we already have a parent, or if we are a root
// entry
if (m_pParent || !m_ParentName.size())
return;
m_pParent = g_TexMan.FindTexture(m_ParentName);
if (!m_pParent)
{
LOG(ERROR, LOG_CATEGORY, "CTextureEntry::LoadParent(): %s: Could not find parent terrain type %s", m_Tag.c_str(), m_ParentName.c_str());
return;
}
m_pParent->LoadParent(); // Make sure we're loaded all the way to our root
}
/////////////////////////////////////////////////////////////////////////////////////
// LoadTexture: actually load the texture resource from file
void CTextureEntry::LoadTexture()
{
CStr pathname("art/textures/terrain/types/");
pathname+=g_TexMan.m_TerrainTextures[m_Type].m_Name;
pathname+='/';
pathname+=m_Name;
CTexture texture;
texture.SetName(pathname);
if (g_Renderer.LoadTexture(&texture,GL_REPEAT)) {
m_Handle=texture.GetHandle();
} else {
m_Handle=0;
if (m_TexturePath.size() == 0)
{
assert(m_pParent);
m_pParent->LoadTexture();
m_Handle = m_pParent->m_Handle;
return;
}
else
{
CTexture texture;
texture.SetName(m_TexturePath);
if (g_Renderer.LoadTexture(&texture,GL_REPEAT)) {
m_Handle=texture.GetHandle();
} else {
m_Handle=0;
}
}
}
@ -46,6 +175,22 @@ void CTextureEntry::LoadTexture()
// in m_BaseColor member
void CTextureEntry::BuildBaseColor()
{
// a) We have an XML override: m_BaseColorValid=true, so we never get here
// b) No XML override, overriden texture: use own texture, calc. BaseColor
// c) No XML override, parent texture: use parent BaseColor
// d) No XML override, but parent has: use parent BaseColor
// cases c&d: We don't have our own texture, use parent base color instead
if (m_TexturePath.size() == 0)
{
assert(m_pParent);
m_BaseColor=m_pParent->GetBaseColor();
m_BaseColorValid=true;
return;
}
// case b: Calculate base color by mipmapping our texture
Handle handle=GetHandle();
g_Renderer.BindTexture(0,tex_id(handle));

View File

@ -4,17 +4,26 @@
#include "res/handle.h"
#include "CStr.h"
#include "TextureManager.h"
class XMBElement;
class CXeromyces;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// CTextureEntry: class wrapping a terrain texture object; contains various other required
// elements - color of minimap, terrain "group" it belongs to, etc
class CTextureEntry
{
public:
CTextureEntry(const char* name,int type);
typedef std::vector<CTerrainTypeGroup *> GroupVector;
~CTextureEntry();
// accessor - return texture name
const char* GetName() const { return (const char*) m_Name; }
CStr GetTag() const
{ return m_Tag; }
CStr GetTexturePath() const
{ return m_TexturePath; }
// accessor - get UI bitmap object
void* GetBitmap() const { return m_Bitmap; }
@ -31,30 +40,44 @@ public:
if (!m_BaseColorValid) BuildBaseColor();
return m_BaseColor;
}
// accessor - return texture type
int GetType() const { return m_Type; }
const GroupVector &GetGroups() const
{ return m_Groups; }
// returns whether this texture-entry has loaded any data yet
bool IsLoaded() { return (m_Handle!=-1); }
static CTextureEntry *FromXML(XMBElement el, CXeromyces *pFile);
// Load all properties from the parent (run on all terrains after loading
// all the xml's or when changes has been made on the parent)
// This will only actually work once per instance (noop on subsequent calls)
void LoadParent();
private:
CTextureEntry();
// load texture from file
void LoadTexture();
// calculate the root color of the texture, used for coloring minimap
void BuildBaseColor();
// filename
CStr m_Name;
// UI bitmap object
void* m_Bitmap;
// handle to GL texture data
Handle m_Handle;
// BGRA color of topmost mipmap level, for coloring minimap
CStr m_Tag;
CStr m_ParentName;
CTextureEntry *m_pParent;
CStr m_TexturePath;
void* m_Bitmap; // UI bitmap object (user data for ScEd)
Handle m_Handle; // handle to GL texture data
// BGRA color of topmost mipmap level, for coloring minimap, or a color
// manually specified in the Terrain XML (or by any parent)
// ..Valid is true if the base color is a cached value or an XML override
u32 m_BaseColor;
// above color valid?
bool m_BaseColorValid;
// "type" of texture - index into TextureManager texturetypes array
int m_Type;
// All terrain type groups we're a member of
GroupVector m_Groups;
};
#endif
#endif

View File

@ -1,53 +1,48 @@
#include "precompiled.h"
#include <algorithm>
#include <vector>
#include "TextureManager.h"
#include "TextureEntry.h"
#include "res/res.h"
#include "ogl.h"
#include "res/ogl_tex.h"
#include "CLogger.h"
#include "ogl.h"
#include "timer.h"
#include "CLogger.h"
#include "Xeromyces.h"
#include "XeroXMB.h"
#define LOG_CATEGORY "graphics"
// filter for vfs_next_dirent
static const char* SupportedTextureFormats[] = { "*.png", "*.dds", "*.tga", "*.bmp" };
using namespace std;
CTextureManager::CTextureManager()
{
m_TerrainTextures.reserve(32);
}
CTextureManager::~CTextureManager()
{
for (size_t i=0;i<m_TerrainTextures.size();i++) {
for (size_t j=0;j<m_TerrainTextures[i].m_Textures.size();j++) {
delete m_TerrainTextures[i].m_Textures[j];
}
for (size_t i=0;i<m_TextureEntries.size();i++) {
delete m_TextureEntries[i];
}
TerrainTypeGroupMap::iterator it=m_TerrainTypeGroups.begin();
while (it != m_TerrainTypeGroups.end())
{
delete it->second;
++it;
}
}
void CTextureManager::AddTextureType(const char* name)
CTextureEntry* CTextureManager::FindTexture(CStr tag)
{
m_TerrainTextures.resize(m_TerrainTextures.size()+1);
STextureType& ttype=m_TerrainTextures.back();
ttype.m_Name=name;
ttype.m_Index=(int)m_TerrainTextures.size()-1;
}
CTextureEntry* CTextureManager::FindTexture(const char* filename)
{
// check if file already loaded
for (uint k=0;k<m_TerrainTextures.size();k++) {
STextureType& ttype=m_TerrainTextures[k];
for (uint i=0;i<ttype.m_Textures.size();i++) {
if (strcmp((const char*) ttype.m_Textures[i]->GetName(),filename)==0) {
return ttype.m_Textures[i];
}
}
for (uint i=0;i<m_TextureEntries.size();i++)
{
if (m_TextureEntries[i]->GetTag() == tag)
return m_TextureEntries[i];
}
return 0;
@ -55,23 +50,77 @@ CTextureEntry* CTextureManager::FindTexture(const char* filename)
CTextureEntry* CTextureManager::FindTexture(Handle handle)
{
for (uint k=0;k<m_TerrainTextures.size();k++) {
STextureType& ttype=m_TerrainTextures[k];
for (uint i=0;i<ttype.m_Textures.size();i++) {
// Don't bother looking at textures that haven't been loaded yet - since
// the caller has given us a Handle to the texture, it must be loaded.
// (This matters because GetHandle would load the texture, even though
// there's no need to.)
if (ttype.m_Textures[i]->IsLoaded() && handle==ttype.m_Textures[i]->GetHandle()) {
return ttype.m_Textures[i];
}
for (uint i=0;i<m_TextureEntries.size();i++)
{
// Don't bother looking at textures that haven't been loaded yet - since
// the caller has given us a Handle to the texture, it must be loaded.
// (This matters because GetHandle would load the texture, even though
// there's no need to.)
if (m_TextureEntries[i]->IsLoaded()
&& handle==m_TextureEntries[i]->GetHandle())
{
return m_TextureEntries[i];
}
}
return 0;
}
CTextureEntry* CTextureManager::AddTexture(const char* filename,int type)
void CTextureManager::LoadTerrainsFromXML(const char *filename)
{
CXeromyces XeroFile;
if (XeroFile.Load(filename) != PSRETURN_OK)
return;
XMBElement root = XeroFile.getRoot();
CStr rootName = XeroFile.getElementString(root.getNodeName());
// Check that we've got the right kind of xml document
if (rootName != "terrains")
{
LOG(ERROR,
LOG_CATEGORY,
"TextureManager: Loading %s: Root node is not terrains (found \"%s\")",
filename,
rootName.c_str());
return;
}
#define ELMT(x) int el_##x = XeroFile.getElementID(#x)
#define ATTR(x) int at_##x = XeroFile.getAttributeID(#x)
ELMT(terrain);
// Load terrains
// Iterate main children
// they should all be <object> or <script> elements
XMBElementList children = root.getChildNodes();
for (int i=0; i<children.Count; ++i)
{
//debug_printf("Object %d\n", i);
XMBElement child = children.item(i);
if (child.getNodeName() == el_terrain)
{
CTextureEntry *pEntry = CTextureEntry::FromXML(child, &XeroFile);
if (pEntry)
m_TextureEntries.push_back(pEntry);
}
else
{
LOG(WARNING, LOG_CATEGORY,
"TextureManager: Loading %s: Unexpected node %s\n",
filename,
XeroFile.getElementString(child.getNodeName()).c_str());
// Keep reading - typos shouldn't be showstoppers
}
}
#undef EL
#undef AT
}
/*CTextureEntry* CTextureManager::AddTexture(const char* filename,int type)
{
assert((uint)type<m_TerrainTextures.size());
@ -82,70 +131,79 @@ CTextureEntry* CTextureManager::AddTexture(const char* filename,int type)
m_TerrainTextures[type].m_Textures.push_back(texentry);
return texentry;
}
}*/
void CTextureManager::DeleteTexture(CTextureEntry* entry)
{
// find entry in list
std::vector<CTextureEntry*>& textures=m_TerrainTextures[entry->GetType()].m_Textures;
typedef std::vector<CTextureEntry*>::iterator Iter;
Iter i=std::find(textures.begin(),textures.end(),entry);
if (i!=textures.end()) {
textures.erase(i);
Iter i=std::find(m_TextureEntries.begin(),m_TextureEntries.end(),entry);
if (i!=m_TextureEntries.end()) {
m_TextureEntries.erase(i);
}
delete entry;
}
void CTextureManager::LoadTerrainTexturesImpl(int terraintype,const char* fileext_filter)
void CTextureManager::RecurseDirectory(CStr path)
{
CStr pathname("art/textures/terrain/types/");
pathname+=m_TerrainTextures[terraintype].m_Name;
pathname+="/";
LOG(NORMAL, LOG_CATEGORY, "CTextureManager::RecurseDirectory(%s)", path.c_str());
Handle dir=vfs_open_dir(pathname.c_str());
vfsDirEnt dent;
if (dir > 0)
{
while (vfs_next_dirent(dir, &dent, fileext_filter) == 0)
{
LOG(NORMAL, LOG_CATEGORY, "CTextureManager::LoadTerrainTextures(): texture %s added to type %s", dent.name, m_TerrainTextures[terraintype].m_Name.c_str());
AddTexture(dent.name, terraintype);
}
vfs_close_dir(dir);
}
}
void CTextureManager::BuildTerrainTypes()
{
Handle dir=vfs_open_dir("art/textures/terrain/types/");
Handle dir=vfs_open_dir(path.c_str());
vfsDirEnt dent;
if (dir > 0)
{
while (vfs_next_dirent(dir, &dent, "/") == 0)
{
AddTextureType(dent.name);
RecurseDirectory(path+dent.name+"/");
}
vfs_close_dir(dir);
}
dir=vfs_open_dir(path.c_str());
if (dir > 0)
{
while (vfs_next_dirent(dir, &dent, "*.xml") == 0)
{
CStr xmlFileName = path+dent.name;
LOG(NORMAL, LOG_CATEGORY, "CTextureManager::LoadTerrainTextures(): loading terrain XML %s", xmlFileName.c_str());
LoadTerrainsFromXML(xmlFileName);
}
vfs_close_dir(dir);
}
}
int CTextureManager::LoadTerrainTextures()
{
// find all the terrain types by directory name
BuildTerrainTypes();
// now iterate through terrain types loading all textures of that type
for (uint i=0;i<m_TerrainTextures.size();i++) {
for (uint j=0;j<ARRAY_SIZE(SupportedTextureFormats);j++) {
LoadTerrainTexturesImpl(i,SupportedTextureFormats[j]);
}
}
RecurseDirectory("art/textures/terrain/types/");
std::vector<CTextureEntry *>::iterator it=m_TextureEntries.begin();
for (;it != m_TextureEntries.end();++it)
(*it)->LoadParent();
return 0;
}
CTerrainTypeGroup *CTextureManager::FindGroup(CStr name)
{
TerrainTypeGroupMap::const_iterator it=m_TerrainTypeGroups.find(name);
if (it != m_TerrainTypeGroups.end())
return it->second;
else
return m_TerrainTypeGroups[name] = new CTerrainTypeGroup(name);
}
void CTerrainTypeGroup::AddTerrain(CTextureEntry *pTerrain)
{
m_Terrains.push_back(pTerrain);
}
void CTerrainTypeGroup::RemoveTerrain(CTextureEntry *pTerrain)
{
vector<CTextureEntry *>::iterator it;
it=find(m_Terrains.begin(), m_Terrains.end(), pTerrain);
if (it != m_Terrains.end())
m_Terrains.erase(it);
}

View File

@ -2,27 +2,53 @@
#define _TEXTUREMANAGER_H
#include <vector>
#include <map>
#include "res/handle.h"
#include "CStr.h"
#include "Singleton.h"
#include "TextureEntry.h"
// access to sole CTextureManager object
#define g_TexMan CTextureManager ::GetSingleton()
class XMBElement;
class CXeromyces;
class CTextureEntry;
class CTerrainTypeGroup
{
// name of this terrain type (as referenced in terrain xmls)
CStr m_Name;
// list of textures of this type (found from the texture directory)
std::vector<CTextureEntry*> m_Terrains;
public:
CTerrainTypeGroup(CStr name):
m_Name(name)
{}
// Add a texture entry to this terrain type
void AddTerrain(CTextureEntry *);
// Remove a texture entry
void RemoveTerrain(CTextureEntry *);
};
///////////////////////////////////////////////////////////////////////////////////////////
// CTextureManager : manager class for all terrain texture objects
class CTextureManager : public Singleton<CTextureManager>
{
public:
struct STextureType
{
// name of this texture type (derived from directory name)
CStr m_Name;
// index in parent array
int m_Index;
// list of textures of this type (found from the texture directory)
std::vector<CTextureEntry*> m_Textures;
};
// All texture entries created by this class, for easy freeing now that
// textures may be in several STextureType's
std::vector<CTextureEntry *> m_TextureEntries;
typedef std::map<CStr, CTerrainTypeGroup *> TerrainTypeGroupMap;
TerrainTypeGroupMap m_TerrainTypeGroups;
// Find all XML's in the directory (with subdirs) and try to load them as
// terrain XML's
void RecurseDirectory(CStr path);
public:
// constructor, destructor
@ -30,21 +56,17 @@ public:
~CTextureManager();
int LoadTerrainTextures();
void LoadTerrainsFromXML(const char *filename);
void AddTextureType(const char* name);
CTextureEntry* FindTexture(const char* filename);
CTextureEntry* FindTexture(CStr tag);
CTextureEntry* FindTexture(Handle handle);
CTextureEntry* AddTexture(const char* filename,int type);
// TODO How do Atlas/ScEd want to create new terrain types?
// CTextureEntry* AddTexture(const char* filename,int type);
void DeleteTexture(CTextureEntry* entry);
std::vector<STextureType> m_TerrainTextures;
private:
void LoadTerrainTexturesImpl(int terraintype,const char* fileext);
void BuildTerrainTypes();
// Find or create a new texture group. All terrain groups are owned by the
// texturemanager (TerrainTypeManager)
CTerrainTypeGroup *FindGroup(CStr name);
};

View File

@ -80,42 +80,14 @@ bool __ParseString<CClientArea>(const CStr& Value, CClientArea &Output)
template <>
bool GUI<int>::ParseColor(const CStr& Value, CColor &Output, float DefaultAlpha)
{
// Use the parser to parse the values
CParser& parser (CParserCache::Get("_[-$arg(_minus)]$value_[-$arg(_minus)]$value_[-$arg(_minus)]$value_[[-$arg(_minus)]$value_]"));
string str = Value;
CParserLine line;
line.ParseString(parser, str);
if (!line.m_ParseOK)
{
// TODO Gee: Parsing failed
return false;
}
float values[4];
values[3] = DefaultAlpha;
for (int i=0; i<(int)line.GetArgCount(); ++i)
{
if (!line.GetArgFloat(i, values[i]))
{
// Parsing failed
return false;
}
}
Output.r = values[0]/255.f;
Output.g = values[1]/255.f;
Output.b = values[2]/255.f;
Output.a = values[3]/255.f;
return true;
return Output.ParseString(Value, DefaultAlpha);
}
template <>
bool __ParseString<CColor>(const CStr& Value, CColor &Output)
{
return GUI<int>::ParseColor(Value, Output, 255.f);
return Output.ParseString(Value, 255.f);
}
template <>

View File

@ -1155,6 +1155,7 @@ fail:
void* realloc_dbg(const void* user_p, size_t user_size, AllocType type, const char* file, int line, const char* func, uint stack_frames)
{
void* ret = 0;
uint old_size = 0;
assert2(type == AT_REALLOC);
@ -1174,7 +1175,7 @@ void* realloc_dbg(const void* user_p, size_t user_size, AllocType type, const ch
if(!a)
{
// you called realloc for a pointer mmgr didn't allocate
assert2(0);
assert2(0 && "realloc was called for a pointer mmgr didn't allocate");
log("[!] realloc: wasn't previously allocated\n");
goto fail;
}
@ -1186,6 +1187,8 @@ void* realloc_dbg(const void* user_p, size_t user_size, AllocType type, const ch
// .. you requested a breakpoint when reallocating this allocation
// (it will continue to be triggered unless you clear a->break_on_realloc)
assert2(!a->break_on_realloc);
old_size = a->size;
}
// else: skip security checks; realloc(0, size) is equivalent to malloc
@ -1194,8 +1197,13 @@ void* realloc_dbg(const void* user_p, size_t user_size, AllocType type, const ch
if(user_size)
ret = alloc_dbg(user_size, type, file,line,func, stack_frames+1);
// old_size should only be non-zero if the Alloc security checks all passed
// If the old buffer was actually zero bytes large, do nothing :P
if (old_size)
memcpy(ret, user_p, old_size);
if(user_p)
free_dbg(user_p, type, file,line,func, stack_frames+1);
free_dbg(user_p, AT_FREE, file,line,func, stack_frames+1);
lock();

View File

@ -26,6 +26,7 @@
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#ifdef _MSC_VER
#pragma comment(lib, "opengl32.lib")

View File

@ -1,5 +1,15 @@
#ifndef _lib_sdl_H
#define _lib_sdl_H
#define SDL_BUTTON_INDEX_COUNT 5
#if defined(_WIN32) && !defined(NO_WSDL)
# include "sysdep/win/wsdl.h"
// The SDL_BUTTON_* enum is zero-based and in the range [0..4] in wsdl.h
#define SDL_BUTTON_TO_INDEX(_but) _but
#define SDL_INDEX_TO_BUTTON(_idx) _idx
#else
# include <SDL/SDL.h>
# include <SDL/SDL_thread.h>
@ -8,4 +18,23 @@
// in static bswap routines. doesn't matter - modern compilers
// will strip them if unused, and this is more convenient than
// another header that toggles between wsdl and SDL_endian.h.
#if SDL_BUTTON_LEFT == 1 && SDL_BUTTON_MIDDLE == 2 && SDL_BUTTON_RIGHT == 3 \
&& SDL_BUTTON_WHEELUP == 4 && SDL_BUTTON_WHEELDOWN == 5
#define SDL_BUTTON_TO_INDEX(_but) ((_but) - 1)
#define SDL_INDEX_TO_BUTTON(_idx) ((_idx) - 1)
#else
/* Add a test like the one above for your set of button constants, and implement
the BUTTON_TO_INDEX macros so that the resulting indices are within the range
[0, SDL_BUTTON_INDEX_COUNT-1]
*/
#error "Platform with unrecognized SDL constants. Update sdl.h"
#endif
#endif
#endif // _lib_sdl_H

View File

@ -116,7 +116,7 @@ ErrorReaction debug_assert_failed(const char* file, int line, const char* expr)
// from an xterm and in full-screen mode)
int c=getchar();
if (c == EOF) // I/O Error
return 2;
return ER_EXIT;
c=tolower(c);
switch (c)
{

View File

@ -193,13 +193,15 @@ SDL_MouseMotionEvent;
// SDL_MouseButtonEvent.button
enum
{
// do not change order
SDL_BUTTON_LEFT,
SDL_BUTTON_RIGHT,
SDL_BUTTON_MIDDLE,
// do not change order or values
// ... but if you do, update lib/sdl.h so that SDL_BUTTON_TO_INDEX still
// yields contiguous values
SDL_BUTTON_LEFT=0,
SDL_BUTTON_RIGHT=1,
SDL_BUTTON_MIDDLE=2,
SDL_BUTTON_WHEELUP,
SDL_BUTTON_WHEELDOWN
SDL_BUTTON_WHEELUP=3,
SDL_BUTTON_WHEELDOWN=4
};
typedef struct

View File

@ -831,6 +831,14 @@ TIMER(InitScripting);
g_ScriptingHost.DefineConstant( "ORDER_ATTACK", CEntityOrder::ORDER_ATTACK_MELEE );
g_ScriptingHost.DefineConstant( "ORDER_GATHER", CEntityOrder::ORDER_GATHER );
#define REG_JS_CONSTANT(_name) g_ScriptingHost.DefineConstant(#_name, _name)
REG_JS_CONSTANT(SDL_BUTTON_LEFT);
REG_JS_CONSTANT(SDL_BUTTON_MIDDLE);
REG_JS_CONSTANT(SDL_BUTTON_RIGHT);
REG_JS_CONSTANT(SDL_BUTTON_WHEELUP);
REG_JS_CONSTANT(SDL_BUTTON_WHEELDOWN);
#undef REG_JS_CONSTANT
CNetMessage::ScriptingInit();
JSI_Camera::init();
@ -1241,8 +1249,10 @@ debug_printf("INIT &argc=%p &argv=%p\n", &argc, &argv);
// enable/disable VSync
// note: "GL_EXT_SWAP_CONTROL" is "historical" according to dox.
#ifdef OS_WIN
if(oglHaveExtension("WGL_EXT_swap_control"))
wglSwapIntervalEXT(g_VSync? 1 : 0);
#endif
MICROLOG(L"init ps");
InitPs();

View File

@ -723,7 +723,8 @@ void CMouseoverEntities::stopBandbox()
void FireWorldClickEvent(uint button, int clicks)
{
debug_printf("FireWorldClickEvent: button %d, clicks %d\n", button, clicks);
//debug_printf("FireWorldClickEvent: button %d, clicks %d\n", button, clicks);
g_JSGameEvents.FireWorldClick(
button,
clicks,
@ -782,12 +783,19 @@ int interactInputHandler( const SDL_Event* ev )
CCamera *pCamera=pView->GetCamera();
CTerrain *pTerrain=g_Game->GetWorld()->GetTerrain();
// One entry for each of five mouse buttons (SDL mouse buttons 1-5, mouse
// buttons over 5 if existant, will be ignored)
static double lastclicktime[5] = {0.0, 0.0, 0.0, 0.0, 0.0};
static HEntity lastclickobject[5];
static u8 clicks[5] = {0, 0, 0, 0, 0};
// One entry for each mouse button
static double lastclicktime[SDL_BUTTON_INDEX_COUNT];
static HEntity lastclickobject[SDL_BUTTON_INDEX_COUNT];
static u8 clicks[SDL_BUTTON_INDEX_COUNT];
ONCE(
for (int i=0;i<SDL_BUTTON_INDEX_COUNT;i++)
{
lastclicktime[i] = 0.0f;
clicks[i] = 0;
});
// These refer to the left mouse button
static u16 button_down_x, button_down_y;
static double button_down_time;
static bool button_down = false;
@ -857,11 +865,10 @@ int interactInputHandler( const SDL_Event* ev )
return( EV_HANDLED );
case SDL_MOUSEBUTTONUP:
{
// Assumes SDL button enums are contiguous
int button = ev->button.button - SDL_BUTTON_LEFT;
int button = SDL_BUTTON_TO_INDEX(ev->button.button);
// Only process buttons within the range for which we have button state
// arrays above.
if (button >= 0 && button < 5)
if (button >= 0 && button < SDL_BUTTON_INDEX_COUNT)
{
double time = get_time();
// Reset clicks counter if too slow or if the cursor's

View File

@ -10,6 +10,7 @@
#include <CStr.h>
#include <CLogger.h>
#include <CConsole.h>
#include <Game.h>
#define LOG_CAT_NET "net"
@ -49,24 +50,28 @@ CNetClient::CNetClient(CGame *pGame, CGameAttributes *pGameAttribs):
CNetClient::~CNetClient()
{
g_ScriptingHost.SetGlobal("g_NetClient", JSVAL_NULL);
SessionMap::iterator it=m_ServerSessions.begin();
while (it != m_ServerSessions.end())
{
delete it->second;
}
}
void CNetClient::ScriptingInit()
{
AddMethod<bool, &CNetClient::JSI_BeginConnect>("beginConnect", 1);
AddProperty(L"onStartGame", &CNetClient::m_OnStartGame);
AddProperty(L"onChat", &CNetClient::m_OnChat);
AddProperty(L"onConnectComplete", &CNetClient::m_OnConnectComplete);
AddProperty(L"onDisconnect", &CNetClient::m_OnDisconnect);
AddProperty(L"onClientConnect", &CNetClient::m_OnClientConnect);
AddProperty(L"onClientDisconnect", &CNetClient::m_OnClientDisconnect);
AddProperty(L"password", &CNetClient::m_Password);
AddProperty<CStrW>(L"playerName", &CNetClient::m_Name);
AddProperty(L"sessionId", &CNetClient::m_SessionID);
AddProperty(L"sessions", &CNetClient::m_JSI_ServerSessions);
CJSMap<SessionMap>::ScriptingInit("NetClient_SessionMap");

View File

@ -5,13 +5,16 @@
#include <Network/Session.h>
#include "TurnManager.h"
#include "Game.h"
#include "simulation/ScriptObject.h"
#include "scripting/ScriptableObject.h"
#include "scripting/JSMap.h"
#include <map>
class CPlayerSlot;
class CPlayer;
class CGame;
class CGameAttributes;
class CNetClient: public CNetSession, protected CTurnManager, public CJSObject<CNetClient>
{

View File

@ -5,26 +5,26 @@
#include "lib.h"
#define Serialize_int_1(_pos, _val) \
STMT( *((_pos)++) = (u8)(_val&0xff); )
STMT( *((_pos)++) = (u8)((_val)&0xff); )
#define Serialize_int_2(_pos, _val) STMT(\
Serialize_int_1(_pos, _val>>8); \
Serialize_int_1(_pos, _val); \
Serialize_int_1(_pos, (_val)>>8); \
Serialize_int_1(_pos, (_val)); \
)
#define Serialize_int_3(_pos, _val) STMT(\
Serialize_int_1(_pos, _val>>16); \
Serialize_int_2(_pos, _val); \
Serialize_int_1(_pos, (_val)>>16); \
Serialize_int_2(_pos, (_val)); \
)
#define Serialize_int_4(_pos, _val) STMT(\
Serialize_int_1(_pos, _val>>24); \
Serialize_int_3(_pos, _val); \
Serialize_int_1(_pos, (_val)>>24); \
Serialize_int_3(_pos, (_val)); \
)
#define Serialize_int_8(_pos, _val) STMT(\
Serialize_int_4(_pos, _val>>32); \
Serialize_int_4(_pos, _val); \
Serialize_int_4(_pos, (_val)>>32); \
Serialize_int_4(_pos, (_val)); \
)
#define __shift_de(_pos, _val) STMT( \

View File

@ -266,7 +266,7 @@ void CNetServer::PlayerSlotAssignmentCallback(void *userdata, CPlayerSlot *pSlot
if (pSlot->GetAssignment() == SLOT_SESSION)
pSlot->GetSession()->SetPlayerSlot(pSlot);
CNetMessage *pMsg=CreatePlayerSlotAssignmentMessage(pSlot);
g_Console->InsertMessage(L"Player Slot Assignment: %ls\n", pMsg->GetString().c_str());
g_Console->InsertMessage(L"Player Slot Assignment: %hs\n", pMsg->GetString().c_str());
pInstance->Broadcast(pMsg);
}
@ -303,7 +303,10 @@ void CNetServer::RemoveSession(CNetServerSession *pSession)
}
else if (m_ServerState == NSS_InGame)
{
LOG(ERROR, LOG_CAT_NET, "CNetServer::RemoveSession(): In-Game Player Disconnection not implemented!");
// TODO Reassign entities to Gaia control
// TODO Set everything up for re-connect and resume
SetClientPipe(pSession->GetPlayerSlot()->GetSlotID(), NULL);
pSession->GetPlayerSlot()->AssignClosed();
}
}

View File

@ -6,7 +6,45 @@ rich@0ad.wildfiregames.com
#include "precompiled.h"
#include <string>
#include "Overlay.h"
#include "Parser.h"
using namespace std;
bool CColor::ParseString(const CStr& Value, float DefaultAlpha)
{
// Use the parser to parse the values
CParser& parser (CParserCache::Get("_[-$arg(_minus)]$value_[-$arg(_minus)]$value_[-$arg(_minus)]$value_[[-$arg(_minus)]$value_]"));
string str = Value;
CParserLine line;
line.ParseString(parser, str);
if (!line.m_ParseOK)
{
// TODO Gee: Parsing failed
return false;
}
float values[4];
values[3] = DefaultAlpha;
for (int i=0; i<(int)line.GetArgCount(); ++i)
{
if (!line.GetArgFloat(i, values[i]))
{
// Parsing failed
return false;
}
}
r = values[0]/255.f;
g = values[1]/255.f;
b = values[2]/255.f;
a = values[3]/255.f;
return true;
}
COverlay::COverlay()
: m_Rect(CRect(0.f,0.f,0.f,0.f)), m_Z(0), m_Color(CColor(0,0,0,0)), m_Texture(""), m_HasBorder(false), m_BorderColor(CColor(0,0,0,0))

View File

@ -13,12 +13,15 @@ by Rich Cross, rich@0ad.wildfiregames.com
#define COVERLAY_H
#include "types.h"
#include <CStr.h>
struct CColor
{
CColor() : r(-1.f), g(-1.f), b(-1.f), a(1.f) {}
CColor(float cr,float cg,float cb,float ca) : r(cr), g(cg), b(cb), a(ca) {}
bool ParseString(const CStr& Value, float DefaultAlpha);
bool operator == (const CColor &color) const;
bool operator != (const CColor &color) const

View File

@ -126,8 +126,8 @@ struct SAuraData
ALLY = 8,
ENEMY = 16,
};
static const size_t DURATION_RADIUS = -1;
static const size_t DURATION_PERMANENT = -2;
static const ssize_t DURATION_RADIUS = -1;
static const ssize_t DURATION_PERMANENT = -2;
SClassSet::ClassSet m_Affects;
Allegiance m_Allegiance;
float m_Radius;