1
0
forked from 0ad/0ad

Stopped ScEd crashing when loading maps. Avoided crashes from invalid animations. Moved game-specific code out of XMLWriter.

This was SVN commit r1920.
This commit is contained in:
Ykkrosh 2005-02-11 12:57:19 +00:00
parent 414015ca57
commit 03a6b6e804
10 changed files with 54 additions and 40 deletions

View File

@ -149,7 +149,10 @@ void CMapReader::ApplyData(CFileUnpacker& unpacker, CTerrain *pTerrain, CUnitMan
}
}
// empty out existing units
// remove all existing entities (by recreating the entity manager)
delete &g_EntityManager;
new CEntityManager();
// delete all remaining non-entity units
pUnitMan->DeleteAll();
// add new objects

View File

@ -279,7 +279,7 @@ void CMapWriter::WriteXML(const char* filename, CUnitManager* pUnitMan)
XML_Setting("Template", entity->m_base->m_Tag);
XML_Setting("Player", entity->GetPlayer());
XML_Setting("Player", entity->GetPlayer()->GetPlayerID());
{
CVector3D position = entity->m_position;

View File

@ -18,6 +18,9 @@
#include "MeshManager.h"
#include "lib/res/ogl_tex.h"
#include "ps/CLogger.h"
#define LOG_CATEGORY "graphics"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Constructor
CModel::CModel()
@ -249,6 +252,8 @@ void CModel::GenerateBoneMatrices()
{
if (!m_Anim || !m_BoneMatrices) return;
assert(m_pModelDef->GetNumBones() == m_Anim->m_AnimDef->GetNumKeys());
m_Anim->m_AnimDef->BuildBoneMatrices(m_AnimTime,m_BoneMatrices);
const CMatrix3D& transform=GetTransform();
@ -282,8 +287,9 @@ void CModel::GenerateBoneMatrices()
// return false on error, else true
bool CModel::SetAnimation(CSkeletonAnim* anim, bool once)
{
m_Anim=anim;
if (m_Anim) {
m_Anim=NULL; // in case something fails
if (anim) {
m_Flags &= ~MODELFLAG_NOLOOPANIMATION;
if( once )
m_Flags |= MODELFLAG_NOLOOPANIMATION;
@ -293,8 +299,10 @@ bool CModel::SetAnimation(CSkeletonAnim* anim, bool once)
return false;
}
if (m_Anim->m_AnimDef->GetNumKeys()!=m_pModelDef->GetNumBones()) {
if (anim->m_AnimDef->GetNumKeys()!=m_pModelDef->GetNumBones()) {
// mismatch between model's skeleton and animation's skeleton
LOG(ERROR, LOG_CATEGORY, "Mismatch between model's skeleton and animation's skeleton (%d model bones != %d animation keys)",
m_pModelDef->GetNumBones(), anim->m_AnimDef->GetNumKeys());
return false;
}
@ -306,6 +314,8 @@ bool CModel::SetAnimation(CSkeletonAnim* anim, bool once)
m_AnimTime=0;
}
m_Anim=anim;
return true;
}

View File

@ -92,7 +92,7 @@ CModelDef* CModelDef::Load(const char* filename)
}
}
}
} catch (...) {
} catch (CFileUnpacker::CFileEOFError) {
delete mdef;
throw CFileUnpacker::CFileEOFError();
}

View File

@ -73,28 +73,28 @@ bool CObjectEntry::BuildModel()
m_Model->CalcObjectBounds();
// load animations
for( uint t = 0; t < m_Animations.size(); t++ )
for (uint t = 0; t < m_Animations.size(); t++)
{
if( m_Animations[t].m_FileName.Length() > 0 )
if (m_Animations[t].m_FileName.Length() > 0)
{
const char* animfilename = m_Animations[t].m_FileName.c_str();
m_Animations[t].m_AnimData = m_Model->BuildAnimation(animfilename,m_Animations[t].m_Speed);
CStr AnimNameLC = m_Animations[t].m_AnimName.LowerCase();
if( AnimNameLC == "idle" )
if (AnimNameLC == "idle")
m_IdleAnim = m_Animations[t].m_AnimData;
else
if( AnimNameLC == "walk" )
if (AnimNameLC == "walk")
m_WalkAnim = m_Animations[t].m_AnimData;
else
if( AnimNameLC == "attack" )
if (AnimNameLC == "attack")
m_MeleeAnim = m_Animations[t].m_AnimData;
else
if( AnimNameLC == "death" )
if (AnimNameLC == "death")
m_DeathAnim = m_Animations[t].m_AnimData;
else
if( AnimNameLC == "decay" )
if (AnimNameLC == "decay")
m_CorpseAnim = m_Animations[t].m_AnimData;
//else
// debug_out("Invalid animation name '%s'\n", (const char*)AnimNameLC);
@ -106,7 +106,8 @@ bool CObjectEntry::BuildModel()
}
}
// start up idling
m_Model->SetAnimation( m_IdleAnim );
if (! m_Model->SetAnimation(m_IdleAnim))
LOG(ERROR, LOG_CATEGORY, "Failed to set idle animation in model \"%s\"", modelfilename);
// build props - TODO, RC - need to fix up bounds here
for (uint p=0;p<m_Props.size();p++) {

View File

@ -25,7 +25,7 @@ protected:
public:
/*
Note: This constructer takes over ownership of the passed pipe end. It
Note: This constructor takes over ownership of the passed pipe end. It
should not be freed by the caller, and should be heap-allocated.
*/
inline CNetSession(MessageHandler *pMsgHandler=NULL):

View File

@ -20,16 +20,20 @@ void CWorld::Initialize(CGameAttributes *pAttribs)
{
g_EntityTemplateCollection.loadTemplates();
CStr mapfilename("maps/scenarios/");
// Load the map, if one was specified
if (pAttribs->m_MapFile.Length())
{
CStr mapfilename("maps/scenarios/");
mapfilename += (CStr)pAttribs->m_MapFile;
mapfilename += (CStr)pAttribs->m_MapFile;
try {
CMapReader reader;
reader.LoadMap(mapfilename, &m_Terrain, &m_UnitManager, &g_LightEnv);
} catch (...) {
LOG(ERROR, LOG_CATEGORY, "Failed to load map %s", mapfilename.c_str());
throw PSERROR_Game_World_MapLoadFailed();
try {
CMapReader reader;
reader.LoadMap(mapfilename, &m_Terrain, &m_UnitManager, &g_LightEnv);
} catch (...) {
LOG(ERROR, LOG_CATEGORY, "Failed to load map %s", mapfilename.c_str());
throw PSERROR_Game_World_MapLoadFailed();
}
}
}

View File

@ -2,13 +2,10 @@
#include "XMLWriter.h"
// TODO: (MT) Someone who knows what this is supposed to do, please take a look at CPlayer and make sure it's doing what it's supposed to.
#include "Player.h"
#include "ps/CLogger.h"
#include "lib/res/vfs.h"
// TODO: Write to the VFS handle all the time frequently, instead of buffering
// TODO (maybe): Write to the VFS handle frequently, instead of buffering
// the entire file, so that large files get written faster.
enum { EL_ATTR, EL_TEXT, EL_SUBEL };
@ -145,7 +142,11 @@ template <> void XMLWriter_File::ElementAttribute<CStr>(const char* name, const
}
}
// Attribute/setting value-to-string template specialisations:
// Attribute/setting value-to-string template specialisations.
//
// These only deal with basic types. Anything more complicated should
// be converted into a basic type by whatever is making use of XMLWriter,
// to keep game-related logic out of the not-directly-game-related code here.
// Use CStr's conversion for most types:
#define TYPE2(ID_T, ARG_T) \
@ -163,12 +164,10 @@ TYPE(double)
// Weird - I know ;-)
TYPE2(const char *, char const* const&)
// Encode Unicode strings as UTF-8 (though that will only be correct if
// the encoding was set to "utf-8"; it'll look a little odd if you store
// Unicode strings in an iso-8859-1 file, so please don't do that)
template <> void XMLWriter_File::ElementAttribute<CStrW>(const char* name, const CStrW& value, bool newelement)
{
ElementAttribute(name, value.utf8(), newelement);
}
template <> void XMLWriter_File::ElementAttribute<CPlayer*>(const char* name, CPlayer*const & value, bool newelement)
{
ElementAttribute(name, value->GetPlayerID(), newelement);
}

View File

@ -161,6 +161,9 @@ static bool saveTGA(const char* filename,int width,int height,unsigned char* dat
// Init: perform one time initialisation of the editor
bool CEditorData::Init()
{
// Set attributes for the game
g_GameAttributes.m_MapFile = L""; // start without a map
// Set up the actual game
g_Game = new CGame();
PSRETURN ret = g_Game->StartGame(&g_GameAttributes);

View File

@ -75,11 +75,7 @@ void CSelectObjectTool::SelectObject(unsigned int flags,int px,int py)
// RenderUnitBounds: render a bounding box round given unit
void CSelectObjectTool::RenderUnitBounds(CUnit* unit)
{
glPushMatrix();
const CMatrix3D& transform=unit->GetModel()->GetTransform();
glMultMatrixf(&transform._11);
const CBound& bounds=unit->GetModel()->GetObjectBounds();
const CBound& bounds=unit->GetModel()->GetBounds();
glBegin(GL_LINE_LOOP);
glVertex3f(bounds[0].X,bounds[0].Y,bounds[0].Z);
@ -108,8 +104,6 @@ void CSelectObjectTool::RenderUnitBounds(CUnit* unit)
glVertex3f(bounds[1].X,bounds[1].Y,bounds[1].Z);
glVertex3f(bounds[1].X,bounds[1].Y,bounds[0].Z);
glEnd();
glPopMatrix();
}