forked from mirrors/0ad
Entities: Removed Tag attribute; it is taken from the filename instead. Made entity XML files be loaded on demand. Probably stopped crash when maps contain non-existent entities. Fixed a few bugs in entity definitions.
Maps: Stored non-entity objects in XML instead of PMP, for easier manual editing. Updated existing maps to newest format, so that they can still work. Added undocumented _rewriteMaps() JS function. Also renamed _mem to vmem, and reclassified its undocumentedness as unintentional, since it's reasonably useful. Loader: added NonprogressiveLoad function, for ScEd/_rewriteMaps/etc which don't care about progressiveness. main.cpp: re-enabled vfs_display, since it doesn't crash now Vector3D: stopped warning This was SVN commit r2078.
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include "BaseEntity.h"
|
||||
#include "BaseEntityCollection.h"
|
||||
#include "EntityManager.h"
|
||||
#include "CLogger.h"
|
||||
|
||||
#include "Model.h"
|
||||
#include "Terrain.h"
|
||||
@@ -18,6 +19,8 @@
|
||||
#include "Loader.h"
|
||||
#include "LoaderThunks.h"
|
||||
|
||||
#define LOG_CATEGORY "graphics"
|
||||
|
||||
// CMapReader constructor: nothing to do at the minute
|
||||
CMapReader::CMapReader()
|
||||
{
|
||||
@@ -167,21 +170,25 @@ void CMapReader::ApplyData()
|
||||
for (u32 i=0;i<m_Objects.size();i++) {
|
||||
|
||||
if (unpacker.GetVersion() < 3) {
|
||||
|
||||
// Hijack the standard actor instantiation for actors that correspond to entities.
|
||||
// Not an ideal solution; we'll have to figure out a map format that can define entities separately or somesuch.
|
||||
|
||||
CBaseEntity* templateObject = g_EntityTemplateCollection.getTemplateByActor(m_ObjectTypes.at(m_Objects[i].m_ObjectIndex));
|
||||
|
||||
if (templateObject)
|
||||
{
|
||||
CVector3D orient = ((CMatrix3D*)m_Objects[i].m_Transform)->GetIn();
|
||||
CVector3D position = ((CMatrix3D*)m_Objects[i].m_Transform)->GetTranslation();
|
||||
debug_warn("Old unsupported map version - objects will be missing");
|
||||
// (getTemplateByActor doesn't work, since entity templates are now
|
||||
// loaded on demand)
|
||||
|
||||
g_EntityManager.create(templateObject, position, atan2(-orient.X, -orient.Z));
|
||||
|
||||
continue;
|
||||
}
|
||||
// // Hijack the standard actor instantiation for actors that correspond to entities.
|
||||
// // Not an ideal solution; we'll have to figure out a map format that can define entities separately or somesuch.
|
||||
//
|
||||
// CBaseEntity* templateObject = g_EntityTemplateCollection.getTemplateByActor(m_ObjectTypes.at(m_Objects[i].m_ObjectIndex));
|
||||
//
|
||||
// if (templateObject)
|
||||
// {
|
||||
// CVector3D orient = ((CMatrix3D*)m_Objects[i].m_Transform)->GetIn();
|
||||
// CVector3D position = ((CMatrix3D*)m_Objects[i].m_Transform)->GetTranslation();
|
||||
//
|
||||
// g_EntityManager.create(templateObject, position, atan2(-orient.X, -orient.Z));
|
||||
//
|
||||
// continue;
|
||||
// }
|
||||
}
|
||||
|
||||
CUnit* unit = g_UnitMan.CreateUnit(m_ObjectTypes.at(m_Objects[i].m_ObjectIndex), NULL);
|
||||
@@ -226,6 +233,9 @@ void CMapReader::ReadXML()
|
||||
EL(player);
|
||||
EL(position);
|
||||
EL(orientation);
|
||||
EL(nonentities);
|
||||
EL(nonentity);
|
||||
EL(actor);
|
||||
AT(x);
|
||||
AT(y);
|
||||
AT(z);
|
||||
@@ -266,28 +276,22 @@ void CMapReader::ReadXML()
|
||||
int element_name = child.getNodeName();
|
||||
|
||||
if (element_name == el_template)
|
||||
{
|
||||
// <template>
|
||||
{ // <template>
|
||||
TemplateName = child.getText();
|
||||
}
|
||||
else if (element_name == el_player)
|
||||
{
|
||||
// <player>
|
||||
{ // <player>
|
||||
PlayerID = CStr(child.getText()).ToInt();
|
||||
}
|
||||
else if (element_name == el_position)
|
||||
{
|
||||
// <position>
|
||||
{ // <position>
|
||||
XMBAttributeList attrs = child.getAttributes();
|
||||
Position = CVector3D(
|
||||
CStr(attrs.getNamedItem(at_x)).ToFloat(),
|
||||
CStr(attrs.getNamedItem(at_y)).ToFloat(),
|
||||
CStr(attrs.getNamedItem(at_z)).ToFloat()
|
||||
);
|
||||
Position = CVector3D(CStr(attrs.getNamedItem(at_x)).ToFloat(),
|
||||
CStr(attrs.getNamedItem(at_y)).ToFloat(),
|
||||
CStr(attrs.getNamedItem(at_z)).ToFloat());
|
||||
}
|
||||
else if (element_name == el_orientation)
|
||||
{
|
||||
// <orientation>
|
||||
{ // <orientation>
|
||||
XMBAttributeList attrs = child.getAttributes();
|
||||
Orientation = CStr(attrs.getNamedItem(at_angle)).ToFloat();
|
||||
}
|
||||
@@ -296,8 +300,67 @@ void CMapReader::ReadXML()
|
||||
}
|
||||
|
||||
HEntity ent = g_EntityManager.create(g_EntityTemplateCollection.getTemplate(TemplateName), Position, Orientation);
|
||||
if (! ent)
|
||||
LOG(ERROR, LOG_CATEGORY, "Failed to create entity '%ls'", TemplateName.c_str());
|
||||
else
|
||||
ent->SetPlayer(g_Game->GetPlayer(PlayerID));
|
||||
}
|
||||
}
|
||||
else if (child.getNodeName() == el_nonentities)
|
||||
{
|
||||
// <nonentities>
|
||||
|
||||
ent->SetPlayer(g_Game->GetPlayer(PlayerID));
|
||||
XMBElementList children = child.getChildNodes();
|
||||
for (int i = 0; i < children.Count; ++i)
|
||||
{
|
||||
XMBElement child = children.item(i);
|
||||
assert(child.getNodeName() == el_nonentity);
|
||||
|
||||
// <nonentity>
|
||||
|
||||
CStr ActorName;
|
||||
CVector3D Position;
|
||||
float Orientation;
|
||||
|
||||
XMBElementList children = child.getChildNodes();
|
||||
for (int i = 0; i < children.Count; ++i)
|
||||
{
|
||||
XMBElement child = children.item(i);
|
||||
int element_name = child.getNodeName();
|
||||
|
||||
if (element_name == el_actor)
|
||||
{ // <actor>
|
||||
ActorName = child.getText();
|
||||
}
|
||||
else if (element_name == el_position)
|
||||
{ // <position>
|
||||
XMBAttributeList attrs = child.getAttributes();
|
||||
Position = CVector3D(CStr(attrs.getNamedItem(at_x)).ToFloat(),
|
||||
CStr(attrs.getNamedItem(at_y)).ToFloat(),
|
||||
CStr(attrs.getNamedItem(at_z)).ToFloat());
|
||||
}
|
||||
else if (element_name == el_orientation)
|
||||
{ // <orientation>
|
||||
XMBAttributeList attrs = child.getAttributes();
|
||||
Orientation = CStr(attrs.getNamedItem(at_angle)).ToFloat();
|
||||
}
|
||||
else
|
||||
debug_warn("Invalid XML data - DTD shouldn't allow this");
|
||||
}
|
||||
|
||||
CUnit* unit = g_UnitMan.CreateUnit(ActorName, NULL);
|
||||
if (unit && unit->GetModel())
|
||||
{
|
||||
// Copied from CEntity::updateActorTransforms():
|
||||
float s = sin( Orientation );
|
||||
float c = cos( Orientation );
|
||||
CMatrix3D m;
|
||||
m._11 = -c; m._12 = 0.0f; m._13 = -s; m._14 = Position.X;
|
||||
m._21 = 0.0f; m._22 = 1.0f; m._23 = 0.0f; m._24 = Position.Y;
|
||||
m._31 = s; m._32 = 0.0f; m._33 = -c; m._34 = Position.Z;
|
||||
m._41 = 0.0f; m._42 = 0.0f; m._43 = 0.0f; m._44 = 1.0f;
|
||||
unit->GetModel()->SetTransform(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "lib/types.h"
|
||||
#include "MapWriter.h"
|
||||
#include "MapReader.h"
|
||||
#include "UnitManager.h"
|
||||
#include "Unit.h"
|
||||
#include "ObjectManager.h"
|
||||
@@ -10,6 +11,8 @@
|
||||
#include "Terrain.h"
|
||||
#include "LightEnv.h"
|
||||
#include "TextureManager.h"
|
||||
#include "VFSUtil.h"
|
||||
#include "Loader.h"
|
||||
|
||||
#include "ps/XMLWriter.h"
|
||||
#include "lib/res/vfs.h"
|
||||
@@ -54,20 +57,6 @@ static u16 GetHandleIndex(const Handle handle,const std::vector<Handle>& handles
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GetObjectIndex: return the index of the given object in the given list; or 0xffff if
|
||||
// object isn't in list
|
||||
static u16 GetObjectIndex(const CObjectEntry* object,const std::vector<CObjectEntry*>& objects)
|
||||
{
|
||||
for (uint i=0;i<(uint)objects.size();i++) {
|
||||
if (objects[i]==object) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// EnumTerrainTextures: build lists of textures used by map, and tile descriptions for
|
||||
// each tile on the terrain
|
||||
@@ -118,48 +107,6 @@ void CMapWriter::EnumTerrainTextures(CTerrain *pTerrain,
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// EnumObjects: build lists of object types used by map, and object descriptions for
|
||||
// each object in the world
|
||||
void CMapWriter::EnumObjects(CUnitManager *pUnitMan,
|
||||
std::vector<CStr>& objectTypes, std::vector<SObjectDesc>& objects)
|
||||
{
|
||||
// the list of all object entries in use
|
||||
std::vector<CObjectEntry*> objectsInUse;
|
||||
|
||||
// resize object array to required size
|
||||
const std::vector<CUnit*>& units=pUnitMan->GetUnits();
|
||||
objects.clear();
|
||||
objects.reserve(units.size()); // slightly larger than necessary (if there are some entities)
|
||||
|
||||
// now iterate through all the units
|
||||
for (size_t j=0;j<units.size();j++) {
|
||||
|
||||
CUnit* unit=units[j];
|
||||
|
||||
// Ignore entities, since they're outputted to XML instead
|
||||
if (unit->GetEntity())
|
||||
continue;
|
||||
|
||||
u16 index=u16(GetObjectIndex(unit->GetObject(),objectsInUse));
|
||||
if (index==0xffff) {
|
||||
index=(u16)objectsInUse.size();
|
||||
objectsInUse.push_back(unit->GetObject());
|
||||
}
|
||||
|
||||
SObjectDesc obj;
|
||||
obj.m_ObjectIndex=index;
|
||||
memcpy(obj.m_Transform,&unit->GetModel()->GetTransform()._11,sizeof(float)*16);
|
||||
|
||||
objects.push_back(obj);
|
||||
}
|
||||
|
||||
// now build outgoing objectTypes array
|
||||
for (uint i=0;i<(uint)objectsInUse.size();i++) {
|
||||
objectTypes.push_back(objectsInUse[i]->m_Base->m_Name);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PackMap: pack the current world into a raw data stream
|
||||
void CMapWriter::PackMap(CFilePacker& packer, CTerrain *pTerrain, CLightEnv *pLightEnv, CUnitManager *pUnitMan)
|
||||
@@ -186,25 +133,10 @@ void CMapWriter::PackLightEnv(CFilePacker& packer, CLightEnv *pLightEnv)
|
||||
// - data: list of objects types used by map, list of object descriptions
|
||||
void CMapWriter::PackObjects(CFilePacker& packer, CUnitManager *pUnitMan)
|
||||
{
|
||||
// the list of object types used by map
|
||||
std::vector<CStr> objectTypes;
|
||||
// descriptions of each object
|
||||
std::vector<SObjectDesc> objects;
|
||||
|
||||
// build lists by scanning through the world
|
||||
EnumObjects(pUnitMan, objectTypes, objects);
|
||||
|
||||
// pack object types
|
||||
u32 numObjTypes=(u32)objectTypes.size();
|
||||
packer.PackRaw(&numObjTypes,sizeof(numObjTypes));
|
||||
for (uint i=0;i<numObjTypes;i++) {
|
||||
packer.PackString(objectTypes[i]);
|
||||
}
|
||||
|
||||
// pack object data
|
||||
u32 numObjects=(u32)objects.size();
|
||||
packer.PackRaw(&numObjects,sizeof(numObjects));
|
||||
packer.PackRaw(&objects[0],sizeof(SObjectDesc)*numObjects);
|
||||
// (These are now handled by XML, so this function is fairly uninteresting)
|
||||
u32 zero = 0;
|
||||
packer.PackRaw(&zero,sizeof(zero)); // numObjTypes
|
||||
packer.PackRaw(&zero,sizeof(zero)); // numObjects
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -294,6 +226,38 @@ void CMapWriter::WriteXML(const char* filename, CUnitManager* pUnitMan)
|
||||
{
|
||||
float angle = entity->m_orientation;
|
||||
|
||||
XML_Element("Orientation");
|
||||
XML_Attribute("angle", angle);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
XML_Element("Nonentities");
|
||||
|
||||
const std::vector<CUnit*>& units = pUnitMan->GetUnits();
|
||||
for (std::vector<CUnit*>::const_iterator unit = units.begin(); unit != units.end(); ++unit) {
|
||||
|
||||
// Ignore objects that are entities
|
||||
if ((*unit)->GetEntity())
|
||||
continue;
|
||||
|
||||
XML_Element("Nonentity");
|
||||
|
||||
XML_Setting("Actor", (*unit)->GetObject()->m_Base->m_Name);
|
||||
|
||||
{
|
||||
CVector3D position = (*unit)->GetModel()->GetTransform().GetTranslation();
|
||||
|
||||
XML_Element("Position");
|
||||
XML_Attribute("x", position.X);
|
||||
XML_Attribute("y", position.Y);
|
||||
XML_Attribute("z", position.Z);
|
||||
}
|
||||
|
||||
{
|
||||
CVector3D orient = (*unit)->GetModel()->GetTransform().GetIn();
|
||||
float angle = atan2(-orient.X, -orient.Z);
|
||||
|
||||
XML_Element("Orientation");
|
||||
XML_Attribute("angle", angle);
|
||||
}
|
||||
@@ -314,3 +278,25 @@ void CMapWriter::WriteXML(const char* filename, CUnitManager* pUnitMan)
|
||||
vfs_close(h);
|
||||
#endif
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RewriteAllMaps
|
||||
void CMapWriter::RewriteAllMaps(CTerrain *pTerrain, CUnitManager *pUnitMan, CLightEnv *pLightEnv)
|
||||
{
|
||||
VFSUtil::FileList files;
|
||||
VFSUtil::FindFiles("maps/scenarios", "*.pmp", files);
|
||||
|
||||
for (VFSUtil::FileList::iterator it = files.begin(); it != files.end(); ++it)
|
||||
{
|
||||
CMapReader* reader = new CMapReader;
|
||||
LDR_BeginRegistering();
|
||||
reader->LoadMap(*it, pTerrain, pUnitMan, pLightEnv);
|
||||
LDR_EndRegistering();
|
||||
LDR_NonprogressiveLoad();
|
||||
|
||||
CStr n (*it);
|
||||
n.Replace("scenarios/", "scenarios/new/");
|
||||
CMapWriter writer;
|
||||
writer.SaveMap(n, pTerrain, pLightEnv, pUnitMan);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ public:
|
||||
// SaveMap: try to save the current map to the given file
|
||||
void SaveMap(const char* filename, CTerrain *pTerr, CLightEnv *pLightEnv, CUnitManager *pUnitMan);
|
||||
|
||||
// RewriteAllMaps: for use during development: load/save all maps, to
|
||||
// update them to the newest format.
|
||||
static void RewriteAllMaps(CTerrain *pTerrain, CUnitManager *pUnitMan, CLightEnv *pLightEnv);
|
||||
|
||||
private:
|
||||
// PackMap: pack the current world into a raw data stream
|
||||
void PackMap(CFilePacker& packer, CTerrain *pTerr, CLightEnv *pLightEnv, CUnitManager *pUnitMan);
|
||||
@@ -33,11 +37,6 @@ private:
|
||||
void EnumTerrainTextures(CTerrain *pTerrain, std::vector<CStr>& textures,
|
||||
std::vector<STileDesc>& tileIndices);
|
||||
|
||||
// EnumObjects: build lists of object types used by map, and object descriptions for
|
||||
// each object in the world
|
||||
void EnumObjects(CUnitManager *pUnitMan, std::vector<CStr>& objectTypes,
|
||||
std::vector<SObjectDesc>& objects);
|
||||
|
||||
// WriteXML: output some other data (entities, etc) in XML format
|
||||
void WriteXML(const char* filename, CUnitManager* pUnitMan);
|
||||
};
|
||||
|
||||
@@ -17,11 +17,14 @@ bool CObjectBase::Load(const char* filename)
|
||||
{
|
||||
m_Variants.clear();
|
||||
|
||||
CStr filePath ("art/actors/");
|
||||
filePath += filename;
|
||||
|
||||
CXeromyces XeroFile;
|
||||
if (XeroFile.Load(filename) != PSRETURN_OK)
|
||||
if (XeroFile.Load(filePath) != PSRETURN_OK)
|
||||
return false;
|
||||
|
||||
m_FileName = filename;
|
||||
m_Name = filename;
|
||||
|
||||
XMBElement root = XeroFile.getRoot();
|
||||
|
||||
@@ -59,7 +62,7 @@ bool CObjectBase::Load(const char* filename)
|
||||
CStr element_value (child.getText());
|
||||
|
||||
if (element_name == el_name)
|
||||
m_Name = element_value;
|
||||
m_ShortName = element_value;
|
||||
|
||||
else if (element_name == el_modelname)
|
||||
m_Variants.back().back().m_ModelFilename = element_value;
|
||||
@@ -136,7 +139,7 @@ bool CObjectBase::Load(const char* filename)
|
||||
//// New-format actor file ////
|
||||
|
||||
// Use the filename for the model's name
|
||||
m_Name = CStr(filename).AfterLast("/").BeforeLast(".xml");
|
||||
m_ShortName = CStr(filename).AfterLast("/").BeforeLast(".xml");
|
||||
|
||||
// Define all the elements used in the XML file
|
||||
#define EL(x) int el_##x = XeroFile.getElementID(#x)
|
||||
|
||||
@@ -57,8 +57,8 @@ public:
|
||||
// object name
|
||||
CStr m_Name;
|
||||
|
||||
// file name
|
||||
CStr m_FileName;
|
||||
// short human-readable name
|
||||
CStr m_ShortName;
|
||||
|
||||
struct {
|
||||
// automatically flatten terrain when applying object
|
||||
|
||||
@@ -124,7 +124,7 @@ bool CObjectEntry::BuildModel()
|
||||
m_Model->AddProp(proppoint,propmodel);
|
||||
if (oe->m_WalkAnim) propmodel->SetAnimation(oe->m_WalkAnim);
|
||||
} else {
|
||||
LOG(ERROR, LOG_CATEGORY, "Failed to build prop model \"%s\" on actor \"%s\"", (const char*)prop.m_ModelName, (const char*)m_Base->m_Name);
|
||||
LOG(ERROR, LOG_CATEGORY, "Failed to build prop model \"%s\" on actor \"%s\"", (const char*)prop.m_ModelName, (const char*)m_Base->m_ShortName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -61,14 +61,11 @@ CObjectBase* CObjectManager::FindObjectBase(const char* objectname)
|
||||
|
||||
// Not already loaded, so try to load it:
|
||||
|
||||
for (uint k = 0; k < m_ObjectTypes.size(); k++) {
|
||||
|
||||
CStr filename ("art/actors/");
|
||||
filename += objectname;
|
||||
|
||||
for (uint k = 0; k < m_ObjectTypes.size(); k++)
|
||||
{
|
||||
CObjectBase* obj = new CObjectBase();
|
||||
|
||||
if (obj->Load(filename))
|
||||
if (obj->Load(objectname))
|
||||
{
|
||||
m_ObjectTypes[k].m_ObjectBases[objectname] = obj;
|
||||
return obj;
|
||||
@@ -151,25 +148,6 @@ void CObjectManager::DeleteObject(CObjectEntry* entry)
|
||||
}
|
||||
|
||||
|
||||
void CObjectManager::AddObjectBase(CObjectBase* base)
|
||||
{
|
||||
m_ObjectTypes[0].m_ObjectBases.insert(make_pair(base->m_FileName, base));
|
||||
}
|
||||
|
||||
void CObjectManager::DeleteObjectBase(CObjectBase* base)
|
||||
{
|
||||
std::map<CStr, CObjectBase*>& objects = m_ObjectTypes[0].m_ObjectBases;
|
||||
|
||||
for (std::map<CStr, CObjectBase*>::iterator it = objects.begin(); it != objects.end(); )
|
||||
if (it->second == base)
|
||||
objects.erase(it++);
|
||||
else
|
||||
++it;
|
||||
|
||||
delete base;
|
||||
}
|
||||
|
||||
|
||||
void CObjectManager::LoadObjects()
|
||||
{
|
||||
AddObjectType("");
|
||||
|
||||
@@ -54,8 +54,6 @@ public:
|
||||
void DeleteObject(CObjectEntry* entry);
|
||||
|
||||
CObjectBase* FindObjectBase(const char* objname);
|
||||
void AddObjectBase(CObjectBase* base);
|
||||
void DeleteObjectBase(CObjectBase* base);
|
||||
|
||||
CBaseEntity* m_SelectedEntity;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user