From aa63fc56f4af4376f28709eb63d584201317009c Mon Sep 17 00:00:00 2001 From: false_genesis Date: Mon, 31 Mar 2008 16:57:28 +0000 Subject: [PATCH] * fixed many gui-related possible crashes * the DrawObject system should be stable enough now to do more serious things with it. * added some object drawing code (cute cubes) - thx shlainn!! --- src/Client/DefScriptInterface.cpp | 5 +- src/Client/GUI/DrawObjMgr.cpp | 17 +++++- src/Client/GUI/DrawObjMgr.h | 2 + src/Client/GUI/DrawObject.cpp | 91 +++++++++++++++++++++++++++++-- src/Client/GUI/DrawObject.h | 8 ++- src/Client/GUI/PseuGUI.cpp | 3 + src/Client/GUI/PseuGUI.h | 2 +- 7 files changed, 120 insertions(+), 8 deletions(-) diff --git a/src/Client/DefScriptInterface.cpp b/src/Client/DefScriptInterface.cpp index ab02421..8ecdc13 100644 --- a/src/Client/DefScriptInterface.cpp +++ b/src/Client/DefScriptInterface.cpp @@ -1011,9 +1011,11 @@ DefReturnResult DefScriptPackage::SCGui(CmdSet &Set) logerror("SCGui: failed"); return false; } - while(!ins->GetGUI() && !ins->GetGUI()->IsInitialized()) + while(!ins->GetGUI() || !ins->GetGUI()->IsInitialized()) ins->GetRunnable()->sleep(1); + ZThread::FastMutex mut; + mut.acquire(); // TODO: not sure if this piece of code will work as intended, needs some testing if(ins->GetWSession() && ins->GetWSession()->InWorld()) { @@ -1022,6 +1024,7 @@ DefReturnResult DefScriptPackage::SCGui(CmdSet &Set) } else ins->GetGUI()->SetSceneState(SCENESTATE_GUISTART); + mut.release(); return true; } diff --git a/src/Client/GUI/DrawObjMgr.cpp b/src/Client/GUI/DrawObjMgr.cpp index 05cce72..1b96688 100644 --- a/src/Client/GUI/DrawObjMgr.cpp +++ b/src/Client/GUI/DrawObjMgr.cpp @@ -10,12 +10,18 @@ DrawObjMgr::DrawObjMgr() DrawObjMgr::~DrawObjMgr() { - DEBUG( logdebug("~DrawObjMgr(), deleting %u DrawObjects...", _storage.size() ) ); + Clear(); +} + +void DrawObjMgr::Clear(void) +{ + DEBUG( logdebug("DrawObjMgr::Clear(), deleting %u DrawObjects...", _storage.size() ) ); for(DrawObjStorage::iterator i = _storage.begin(); i != _storage.end(); i++) { DEBUG( logdebug("del for guid "I64FMT, i->first) ); delete i->second; // this can be done safely, since the object ptrs are not accessed } + _storage.clear(); while(_add.size()) { @@ -33,6 +39,15 @@ void DrawObjMgr::Delete(uint64 guid) _del.add(guid); } +void DrawObjMgr::UnlinkAll(void) +{ + DEBUG( logdebug("DrawObjMgr::UnlinkAll(), %u DrawObjects...", _storage.size() ) ); + for(DrawObjStorage::iterator i = _storage.begin(); i != _storage.end(); i++) + { + i->second->Unlink(); + } +} + void DrawObjMgr::Update(void) { ZThread::FastMutex mut; diff --git a/src/Client/GUI/DrawObjMgr.h b/src/Client/GUI/DrawObjMgr.h index 2ae9182..0bb15ad 100644 --- a/src/Client/GUI/DrawObjMgr.h +++ b/src/Client/GUI/DrawObjMgr.h @@ -14,8 +14,10 @@ public: ~DrawObjMgr(); void Add(uint64,DrawObject*); void Delete(uint64); + void Clear(void); void Update(void); // Threadsafe! delete code must be called from here! uint32 StorageSize(void) { return _storage.size(); } + void UnlinkAll(void); private: DrawObjStorage _storage; diff --git a/src/Client/GUI/DrawObject.cpp b/src/Client/GUI/DrawObject.cpp index bb24843..3cab2a8 100644 --- a/src/Client/GUI/DrawObject.cpp +++ b/src/Client/GUI/DrawObject.cpp @@ -2,20 +2,103 @@ #include "PseuGUI.h" #include "DrawObject.h" #include "PseuWoW.h" +#include "Object.h" -DrawObject::DrawObject(irr::scene::ISceneManager *smgr, Object *obj) +DrawObject::DrawObject(irr::IrrlichtDevice *device, Object *obj) { - _smgr = smgr; + _initialized = false; + Unlink(); + _smgr = device->getSceneManager(); + _guienv = device->getGUIEnvironment(); _obj = obj; - DEBUG( logdebug("create DrawObject() this=%X obj=%X smgr=%X",this,_obj,_smgr) ); + DEBUG( logdebug("create DrawObject() this=%X obj=%X name='%s' smgr=%X",this,_obj,_obj->GetName().c_str(),_smgr) ); } DrawObject::~DrawObject() { - DEBUG( logdebug("~DrawObject() this=%X obj=%X smgr=%X",this,_obj,_smgr) ); + DEBUG( logdebug("~DrawObject() this=0x%X obj=0x%X smgr=%X",this,_obj,_smgr) ); + if(cube) + { + text->remove(); + cube->remove(); + } +} + +void DrawObject::Unlink(void) +{ + cube = NULL; + text = NULL; +} + +void DrawObject::_Init(void) +{ + if(!cube && _obj->IsWorldObject()) // only world objects have coords and can be drawn + { + cube = _smgr->addCubeSceneNode(10); + cube->setName("CUBE"); + //cube->setPosition(irr::core::vector3di(100,100,100)); + cube->setRotation(irr::core::vector3df(0,0,0)); + + if(_obj->IsPlayer()) + { + cube->getMaterial(0).DiffuseColor.set(255,255,0,0); + } + else if(_obj->IsCreature()) + { + cube->getMaterial(0).DiffuseColor.set(255,0,255,0); + } + text=_smgr->addTextSceneNode(_guienv->getBuiltInFont(), L"TestText" , irr::video::SColor(255,255,255,255),cube, irr::core::vector3df(0,5,0)); + } + DEBUG(logdebug("initialize DrawObject 0x%X obj: 0x%X "I64FMT,this,_obj,_obj->GetGUID())) + + _initialized = true; } void DrawObject::Draw(void) { + if(!_initialized) + _Init(); + //printf("DRAW() for pObj 0x%X name '%s' guid "I64FMT"\n", _obj, _obj->GetName().c_str(), _obj->GetGUID()); + if(cube) + { + WorldPosition pos = ((WorldObject*)_obj)->GetPosition(); + // TODO: these formulas are horribly wrong! FIXME ASAP! + // they work best for ".tele dunmorogh" + float dx=pos.x * -5.0f - 26830.0f; + float dy=pos.z; + float dz=pos.y * -3.5f - 566.0f; + + cube->setPosition(irr::core::vector3df(dx,dy,dz)); + if(_obj->IsPlayer()) + { + cube->getMaterial(0).DiffuseColor.set(255,255,0,0); + text->setTextColor(irr::video::SColor(255,255,0,0)); + } + else if(_obj->IsCreature()) + { + cube->getMaterial(0).DiffuseColor.set(255,0,0,255); + text->setTextColor(irr::video::SColor(255,0,0,255)); + } + + float s = _obj->GetFloatValue(OBJECT_FIELD_SCALE_X); + if(s <= 0) + s = 1; + cube->setScale(irr::core::vector3df(s,s,s)); + + //cube->setRotation(irr::core::vector3df(0,RAD_TO_DEG(((WorldObject*)_obj)->GetO()),0)); + irr::core::stringw tmp = L""; + if(_obj->GetName().empty()) + { + tmp += L"unk<"; + tmp += _obj->GetTypeId(); + tmp += L">"; + } + else + { + tmp += _obj->GetName().c_str(); + } + text->setText(tmp.c_str()); + } } + diff --git a/src/Client/GUI/DrawObject.h b/src/Client/GUI/DrawObject.h index d2f2cbd..4960976 100644 --- a/src/Client/GUI/DrawObject.h +++ b/src/Client/GUI/DrawObject.h @@ -9,14 +9,20 @@ class Object; class DrawObject { public: - DrawObject(irr::scene::ISceneManager*, Object*); + DrawObject(irr::IrrlichtDevice *device, Object*); ~DrawObject(); void Draw(void); // call only in threadsafe environment!! (ensure the obj ptr is still valid!) + void Unlink(void); // additionally, we dont use a GetObject() func - that would fuck things up if the object was already deleted. private: + void _Init(void); Object *_obj; + bool _initialized : 1; irr::scene::ISceneManager *_smgr; + irr::gui::IGUIEnvironment* _guienv; + irr::scene::ISceneNode* cube; + irr::scene::ITextSceneNode *text; }; diff --git a/src/Client/GUI/PseuGUI.cpp b/src/Client/GUI/PseuGUI.cpp index f25b33f..e54e910 100644 --- a/src/Client/GUI/PseuGUI.cpp +++ b/src/Client/GUI/PseuGUI.cpp @@ -48,6 +48,7 @@ PseuGUI::PseuGUI() PseuGUI::~PseuGUI() { + domgr.Clear(); this->Cancel(); _instance->DeleteGUI(); // this makes the instance set its gui ptr to NULL logdebug("PseuGUI::~PseuGUI()"); @@ -213,6 +214,8 @@ void PseuGUI::Run(void) } } + domgr.UnlinkAll(); // At this point the irr::device is probably closed and deleted already, which means it deleted + // all SceneNodes and everything. the ptrs are still stored in the DrawObjects, means they need to be unlinked now not to cause a crash. DEBUG(logdebug("PseuGUI::Run() finished")); Cancel(); // already got shut down somehow, we can now safely cancel and drop the device } diff --git a/src/Client/GUI/PseuGUI.h b/src/Client/GUI/PseuGUI.h index a02bdff..133b07b 100644 --- a/src/Client/GUI/PseuGUI.h +++ b/src/Client/GUI/PseuGUI.h @@ -74,7 +74,7 @@ public: void UseShadows(bool); void Cancel(void); void Shutdown(void); - inline bool IsInitialized(void) { return _initialized; } + inline bool IsInitialized(void) { return _initialized && _device; } inline bool MustDie(void) { return _mustdie; }