diff --git a/bin/conf/gui.conf.default b/bin/conf/gui.conf.default index 40765ef..08c8afb 100644 --- a/bin/conf/gui.conf.default +++ b/bin/conf/gui.conf.default @@ -8,7 +8,7 @@ // 3: OpenGL // 4: DirectX 8.1 // 5: DirectX 9.0c -driver=5 +driver=3 // resolution and more resx=1024 @@ -28,6 +28,12 @@ depth=32 // 0: No (default) UseSound=1 +// Master Sound Volume. Multiplier that affects all sounds that are played +// 1.0 - max volume +// 0.5 - half sound volume +// 0 - silent +MasterSoundVolume=1.0 + //================================================================================================ // Expert options: Renderer finetuning diff --git a/bin/data/scp/gui_charselect_text.scp b/bin/data/scp/gui_charselect_text.scp new file mode 100644 index 0000000..9166e99 --- /dev/null +++ b/bin/data/scp/gui_charselect_text.scp @@ -0,0 +1,14 @@ +#dbname=gui_charselect_text + +[1] +0=Enter World +1=New Character +2=Delete Character +3=Change Realm +4=Back +5=OK +6=Cancel + +[2] +0=Realmlist + diff --git a/bin/data/scp/gui_login_text.scp b/bin/data/scp/gui_login_text.scp index 46a1663..0d365d2 100644 --- a/bin/data/scp/gui_login_text.scp +++ b/bin/data/scp/gui_login_text.scp @@ -23,3 +23,13 @@ 0=Oh noes! 1=You have to enter account name and password! +// the text box labels +[3] +0=Account: +1=Password: + +// the buttons +[4] +0=Login +1=Quit +2=Community Site diff --git a/bin/scripts/database_loader.def b/bin/scripts/database_loader.def index cb120ce..daf8c81 100644 --- a/bin/scripts/database_loader.def +++ b/bin/scripts/database_loader.def @@ -4,10 +4,10 @@ if ?{not ?{IsHooked _startup}} HookAdd db_loader_load_all HookEnd - // set up paths; ./data/scp and ./cache are set in the core already - // the SCP files placed in this directory are used to override some values - // in already present SCP files or to add custom fields or content - // note: it DOES matter in which order paths are added!! + // Set up paths; ./data/scp and ./cache are set in the core already. + // The SCP files placed in this directory are used to override some values + // in already present SCP files or to add custom fields or content. + // Note: it DOES matter in which order paths are added!! AddDBPath ./data/scp-patches endif @@ -29,11 +29,12 @@ LoadDB creaturemodeldata LoadDB gameobjectdisplayinfo // LoadDB itemdisplayinfo // not yet used // LoadDB charsections // not yet used -// LoadDB sound // not yet used +LoadDB sound // LoadDB npcsound // not yet used // GUI related databases LoadDB gui_login_text +LoadDB gui_charselect_text log ** Databases loaded. diff --git a/src/configure.ac b/configure.ac similarity index 73% rename from src/configure.ac rename to configure.ac index de7c5bc..56a7d6e 100644 --- a/src/configure.ac +++ b/configure.ac @@ -4,8 +4,8 @@ AC_PREREQ(2.61) AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS) AM_INIT_AUTOMAKE(pseuwow, 0.1) -#AC_CONFIG_SRCDIR([shared/ProgressBar.h]) -AM_CONFIG_HEADER([config.h]) +#AC_CONFIG_SRCDIR([src/shared/ProgressBar.h]) +AM_CONFIG_HEADER([src/config.h]) # Checks for programs. AC_PROG_CXX @@ -58,18 +58,18 @@ AC_FUNC_UTIME_NULL AC_FUNC_VPRINTF AC_CHECK_FUNCS([floor ftime ftruncate getcwd gethostbyaddr gethostbyname gethostname gettimeofday memmove memset mkdir pow realpath select socket sqrt strerror strrchr strstr strtol strtoul uname utime]) -#AC_CONFIG_FILES([dep/src/irrlicht/Makefile -# dep/src/zlib/Makefile -# dep/src/zthread/Makefile]) -#AC_CONFIG_SUBDIRS([dep/src/irrlicht/jpeglib -# dep/src/irrlicht/libpng]) -AC_CONFIG_FILES([Makefile - shared/Makefile - shared/Auth/Makefile - shared/Network/Makefile - Client/Makefile - Client/GUI/Makefile - Client/Realm/Makefile - Client/World/Makefile - Client/DefScript/Makefile]) +#AC_CONFIG_FILES([src/dep/src/irrlicht/Makefile +# src/dep/src/zlib/Makefile +# src/dep/src/zthread/Makefile]) +#AC_CONFIG_SUBDIRS([src/dep/src/irrlicht/jpeglib +# src/dep/src/irrlicht/libpng]) +AC_CONFIG_FILES([src/Makefile + src/shared/Makefile + src/shared/Auth/Makefile + src/shared/Network/Makefile + src/Client/Makefile + src/Client/GUI/Makefile + src/Client/Realm/Makefile + src/Client/World/Makefile + src/Client/DefScript/Makefile]) AC_OUTPUT diff --git a/src/Client/DefScriptInterface.cpp b/src/Client/DefScriptInterface.cpp index 8df2751..8f19c4a 100644 --- a/src/Client/DefScriptInterface.cpp +++ b/src/Client/DefScriptInterface.cpp @@ -1019,6 +1019,18 @@ DefReturnResult DefScriptPackage::SCGui(CmdSet &Set) { ins->GetGUI()->SetSceneState(SCENESTATE_LOGINSCREEN); } + else if(ins->GetRSession() && !ins->GetWSession()) + { + ins->GetGUI()->SetSceneState(SCENESTATE_REALMSELECT); + } + else if(ins->GetRSession() && ins->GetWSession()) + { + ins->GetGUI()->SetSceneState(SCENESTATE_CHARSELECT); + } + /*else if(ins->GetWSession() && !ins->GetWSession()->InWorld()) + { + ins->GetGUI()->SetSceneState(SCENESTATE_LOGINSCREEN); + }*/ // TODO: uncomment after implemented else if(ins->GetWSession() && ins->GetWSession()->InWorld()) { ins->GetGUI()->SetSceneState(SCENESTATE_WORLD); diff --git a/src/Client/GUI/GUIEventReceiver.h b/src/Client/GUI/GUIEventReceiver.h new file mode 100644 index 0000000..4abdb41 --- /dev/null +++ b/src/Client/GUI/GUIEventReceiver.h @@ -0,0 +1,88 @@ +#ifndef GUIEVENTRECEIVER_H +#define GUIEVENTRECEIVER_H + + +class GUIEventReceiver : public IEventReceiver +{ +public: + GUIEventReceiver() + { + buttons = 0; + react_to_keys = true; + memset(&guievent, 0 , sizeof(SEvent)); + memset(&keyevent, 0 , sizeof(SEvent)); + memset(&mouseevent, 0 , sizeof(SEvent)); + guievent_proc = false; + mouseevent_proc = false; + keyevent_proc = false; + } + virtual bool OnEvent(const SEvent& event) + { + // copy all 3 event types into different stores for later external use + if(event.EventType == EET_GUI_EVENT) + { + guievent = event; + guievent_proc = false; + } + else if(event.EventType == EET_KEY_INPUT_EVENT) + { + keyevent = event; + keyevent_proc = false; + } + else if(event.EventType == EET_MOUSE_INPUT_EVENT) + { + mouseevent = event; + mouseevent_proc = false; + } + + bool proc = false; + //GUI EVENT + if (event.EventType == EET_GUI_EVENT) + { + s32 id = event.GUIEvent.Caller->getID(); + + printf("event type %u ID %u\n",event.GUIEvent.EventType,id); + + switch(event.GUIEvent.EventType) + { + case EGET_BUTTON_CLICKED: + buttons += id; + proc = true; + break; + + case EGET_MESSAGEBOX_OK: // triggered on enter or ok button click + case EGET_MESSAGEBOX_CANCEL: // triggered on escape + react_to_keys = true; // popup is gone, main window can react to keys again + proc = true; + break; + } + + if(customHandledEvents.find(event.GUIEvent.EventType) != customHandledEvents.end()) + proc = true; + + } + + if(react_to_keys && event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown) + { + std::map::iterator it = keyToButtonMap.find(event.KeyInput.Key); + if( it != keyToButtonMap.end() ) + { + buttons += it->second; + proc = true; + } + } + return proc; + } + + bool react_to_keys; + u32 buttons; + SEvent guievent, mouseevent, keyevent; + bool keyevent_proc, mouseevent_proc, guievent_proc; + std::map keyToButtonMap; // to simulate button press on key input + std::set customHandledEvents; + +}; + +#endif + + diff --git a/src/Client/GUI/PseuGUI.cpp b/src/Client/GUI/PseuGUI.cpp index 0d03865..206a297 100644 --- a/src/Client/GUI/PseuGUI.cpp +++ b/src/Client/GUI/PseuGUI.cpp @@ -121,6 +121,7 @@ void PseuGUI::_Init(void) _smgr = _device->getSceneManager(); _guienv = _device->getGUIEnvironment(); _timer = _device->getTimer(); + _screendimension = _driver->getScreenSize(); //... // disable crappy irrlicht logging @@ -139,7 +140,14 @@ void PseuGUI::_Init(void) { _soundengine = createIrrKlangDevice(); if(_soundengine) + { logdetail("PseuGUI: Sound Driver: %s",_soundengine->getDriverName()); + _soundengine->setSoundVolume(GetInstance()->GetConf()->masterSoundVolume); + // accept only values between 0 and 1 + if(_soundengine->getSoundVolume() < 0.0f || _soundengine->getSoundVolume() >= 1.0f) + _soundengine->setSoundVolume(1.0f); + logdetail("PseuGUI: Master Sound Volume: %.3f",_soundengine->getSoundVolume()); + } else logerror("PseuGUI: Failed to initialize sound engine!"); } @@ -194,7 +202,6 @@ void PseuGUI::Run(void) _lastpasstime = _passtime; _passtime = _timer->getTime(); _passtimediff = _passtime - _lastpasstime; - // _HandleWindowResize(); // not yet used; doesnt work if (!_device->isWindowActive()) { @@ -209,6 +216,18 @@ void PseuGUI::Run(void) continue; } + if(_screendimension != _driver->getScreenSize()) + { + _scene->OnResize(); + _screendimension = _driver->getScreenSize(); + } + + if(_updateScene) + { + _updateScene = false; + _scene->OnManualUpdate(); + } + _scene->OnUpdate(_passtimediff); // custom: process input, set camera, etc _driver->beginScene(true, true, _scene->GetBackgroundColor()); // irr: call driver to start drawing _scene->OnDrawBegin(); // custom: draw everything before irrlicht draws everything by itself @@ -295,6 +314,17 @@ void PseuGUI::_UpdateSceneState(void) case SCENESTATE_GUISTART: _scene = new SceneGuiStart(this); break; case SCENESTATE_LOGINSCREEN: _scene = new SceneLogin(this); break; case SCENESTATE_WORLD: _scene = new SceneWorld(this); break; + case SCENESTATE_REALMSELECT: + _scene = new SceneCharSelection(this); + _scene->SetData(ISCENE_CHARSEL_REALMFIRST, 1); + _scene->OnResize(); + _scenestate_new = SCENESTATE_CHARSELECT; + break; + case SCENESTATE_CHARSELECT: + _scene = new SceneCharSelection(this); + _scene->SetData(ISCENE_CHARSEL_REALMFIRST, 0); + _scene->OnResize(); + break; default: _scene = new Scene(this); // will draw nothing, just yield the gui } _scene->SetState(_scenestate_new); @@ -334,25 +364,3 @@ WorldPosition PseuGUI::GetWorldPosition(void) return WorldPosition(); } -void PseuGUI::_HandleWindowResize(void) -{ - dimension2d scrn = _driver->getScreenSize(); - if(_screendimension.Width != scrn.Width) - { - scrn.Height = s32(scrn.Width * 0.8f); // for now use aspect ratio 5:4 - _screendimension = scrn; - _driver->OnResize(scrn); - DEBUG(logdebug("DEBUG: Width resize handled, Height adjusted")); - - } - else if(_screendimension.Height != scrn.Height) - { - scrn.Width = s32(scrn.Height * 1.25); // 5:4 here too - _screendimension = scrn; - _driver->OnResize(scrn); - DEBUG(logdebug("DEBUG: Height resize handled, Width adjusted")); - - } - // TODO: how to set irrlicht window size ?! - -} diff --git a/src/Client/GUI/PseuGUI.h b/src/Client/GUI/PseuGUI.h index e9e076f..e3c610f 100644 --- a/src/Client/GUI/PseuGUI.h +++ b/src/Client/GUI/PseuGUI.h @@ -17,7 +17,7 @@ enum SceneState SCENESTATE_NULL = 0, SCENESTATE_GUISTART, SCENESTATE_LOGINSCREEN, - SCENESTATE_REALMSELECT, + SCENESTATE_REALMSELECT, // actually both realm and char select will call the same scene, but with slightly different data SCENESTATE_CHARSELECT, SCENESTATE_LOADING, SCENESTATE_WORLD, @@ -73,6 +73,7 @@ class PseuGUI friend class SceneWorld; friend class SceneGuiStart; friend class SceneLogin; + friend class SceneCharSelection; // ... public: @@ -103,6 +104,7 @@ public: void SetSceneState(SceneState); bool SetSceneData(uint32, uint32); uint32 GetSceneState(void); + inline void UpdateScene(void) { _updateScene = true; } // helpers WorldPosition GetWorldPosition(void); @@ -110,7 +112,6 @@ public: private: void _Init(void); void _UpdateSceneState(void); - void _HandleWindowResize(void); uint16 _xres,_yres,_colordepth; bool _windowed,_vsync,_shadows; bool _initialized,_mustdie; @@ -129,6 +130,7 @@ private: uint32 _passtime, _lastpasstime, _passtimediff; irr::core::dimension2d _screendimension; uint32 _throttle;//used for frameratelimiting + bool _updateScene; // manually update scene? }; diff --git a/src/Client/GUI/Scene.cpp b/src/Client/GUI/Scene.cpp index 833ec5d..63bb92e 100644 --- a/src/Client/GUI/Scene.cpp +++ b/src/Client/GUI/Scene.cpp @@ -14,6 +14,7 @@ Scene::Scene(PseuGUI *g) driver = gui->_driver; smgr = gui->_smgr; guienv = gui->_guienv; + rootgui = guienv->getRootGUIElement(); cursor = new CCursorController(device->getCursorControl(), driver); cursor->setOSCursorVisible(true); cursor->setVisible(false); @@ -35,6 +36,15 @@ void Scene::OnUpdate(s32) { } +void Scene::OnManualUpdate(void) +{ + OnResize(); +} + +void Scene::OnResize(void) +{ +} + void Scene::OnDrawBegin(void) { } diff --git a/src/Client/GUI/Scene.h b/src/Client/GUI/Scene.h index a9ee333..d8fabee 100644 --- a/src/Client/GUI/Scene.h +++ b/src/Client/GUI/Scene.h @@ -13,8 +13,24 @@ using namespace gui; using namespace irrklang; +inline core::rect CalcRelativeScreenPos(core::dimension2d dim, f32 x, f32 y, f32 w, f32 h) +{ + core::rect r; + r.UpperLeftCorner.X = dim.Width * x; + r.UpperLeftCorner.Y = dim.Height* y; + r.LowerRightCorner.X = r.UpperLeftCorner.X + (dim.Width * w); + r.LowerRightCorner.Y = r.UpperLeftCorner.Y + (dim.Height * h); + return r; +} + +inline core::rect CalcRelativeScreenPos(video::IVideoDriver* drv, f32 x, f32 y, f32 w, f32 h) +{ + return CalcRelativeScreenPos(drv->getScreenSize(),x,y,w,h); +} + class PseuGUI; class CCursorController; +class GUIEventReceiver; // base class class Scene @@ -27,11 +43,14 @@ public: inline void SetState(SceneState sc) { _scenestate = sc; } inline SceneState GetState(void) { return _scenestate; } virtual void OnUpdate(s32); + virtual void OnManualUpdate(void); virtual void OnDraw(void); virtual void OnDrawBegin(void); virtual void OnDelete(void); + virtual void OnResize(void); virtual video::SColor GetBackgroundColor(void); virtual void SetData(uint32 index, uint32 value) { scenedata[index] = value; } + protected: PseuInstance *instance; PseuGUI *gui; @@ -39,6 +58,7 @@ protected: irr::video::IVideoDriver* driver; irr::scene::ISceneManager* smgr; irr::gui::IGUIEnvironment* guienv; + irr::gui::IGUIElement* rootgui; irrklang::ISoundEngine *soundengine; CCursorController *cursor; SceneState _scenestate; @@ -56,8 +76,6 @@ private: }; -class GUIEventReceiver; - class SceneLogin : public Scene { public: @@ -66,14 +84,33 @@ public: void OnDelete(void); private: - gui::IGUIElement* root; IGUIImage *irrlogo, *background; GUIEventReceiver *eventrecv; - PseuGUI* _gui; gui::IGUIElement *msgbox; + gui::IGUIWindow *popup; uint32 msgbox_textid; }; +class CharSelectGUIEventReceiver; + +class SceneCharSelection : public Scene +{ +public: + SceneCharSelection(PseuGUI *gui); + void OnUpdate(s32); + void OnDelete(void); + void OnResize(void); + +private: + GUIEventReceiver *eventrecv; + IGUIWindow *realmwin; + IGUIListBox *realmlistbox; + IGUIListBox *charlistbox; // temporary until something better found +}; + + + + class ShTlTerrainSceneNode; class MCameraFPS; class MCameraOrbit; @@ -101,7 +138,7 @@ public: void InitTerrain(void); void RelocateCamera(void); void RelocateCameraBehindChar(void); - void UpdateDoodads(void); + void UpdateMapSceneNodes(std::map&); scene::ISceneNode *GetMyCharacterSceneNode(void); video::SColor GetBackgroundColor(void); @@ -112,7 +149,6 @@ private: MCameraFPS *camera; MyEventReceiver *eventrecv; ZThread::FastMutex mutex; - PseuGUI *gui; uint32 map_gridX, map_gridY; WorldSession *wsession; World *world; @@ -120,6 +156,7 @@ private: IGUIStaticText *debugText; bool debugmode; std::map _doodads; + std::map _sound_emitters; scene::ISceneNode *sky; scene::ISceneNode *selectedNode, *oldSelectedNode, *focusedNode, *oldFocusedNode; video::SColor envBasicColor; diff --git a/src/Client/GUI/SceneCharselection.cpp b/src/Client/GUI/SceneCharselection.cpp new file mode 100644 index 0000000..792446f --- /dev/null +++ b/src/Client/GUI/SceneCharselection.cpp @@ -0,0 +1,259 @@ +#include "common.h" +#include "PseuGUI.h" +#include "PseuWoW.h" +#include "Scene.h" +#include "GUIEventReceiver.h" +#include "RealmSession.h" +#include "WorldSession.h" + +enum GuiElementID +{ + BUTTON_ENTER_WORLD = 0x1, + BUTTON_BACK = 0x2, + BUTTON_NEW_CHARACTER = 0x4, + BUTTON_DELETE_CHARACTER = 0x8, + BUTTON_SELECT_REALM = 0x10, + BUTTON_REALMWIN_OK = 0x20, + BUTTON_REALMWIN_CANCEL = 0x40, +}; + + +SceneCharSelection::SceneCharSelection(PseuGUI *gui) : Scene(gui) +{ + textdb = instance->dbmgr.GetDB("gui_charselect_text"); + eventrecv = new GUIEventReceiver(); + device->setEventReceiver(eventrecv); + eventrecv->keyToButtonMap[KEY_ESCAPE] = BUTTON_BACK | BUTTON_REALMWIN_CANCEL; + eventrecv->keyToButtonMap[KEY_RETURN] = BUTTON_ENTER_WORLD | BUTTON_REALMWIN_OK; + eventrecv->customHandledEvents.insert(EGET_LISTBOX_SELECTED_AGAIN); + + dimension2d scrn = driver->getScreenSize(); + + OnResize(); // call this manually to draw all buttons and stuff + + if(soundengine) + { + ISoundSource *main_theme = soundengine->getSoundSource("data/misc/main_theme.ogg"); + if(main_theme && !soundengine->isCurrentlyPlaying(main_theme)) + { + soundengine->play2D(main_theme,true); + } + } +} + +void SceneCharSelection::OnUpdate(s32 timepassed) +{ + if(eventrecv->buttons & BUTTON_ENTER_WORLD && !realmwin) + { + logdebug("GUI: SceneCharSelect: Entering world"); + WorldSession *ws = instance->GetWSession(); + if(ws) + { + u32 selected = charlistbox->getSelected(); + if(selected < ws->GetCharsCount()) + { + ws->EnterWorldWithCharacter(ws->GetCharFromList(selected).p._name); + } + else + logerror("Character selection out of bounds! (%u)",selected); + } + else + logerror("GUI: BUTTON_ENTER_ WORLD pressed, but no WorldSession exists!"); + } + if(eventrecv->buttons & BUTTON_BACK && !realmwin) // cant cancel with realmwin open (important for ESC key handling) + { + logdebug("GUI: SceneCharSelect: Back to Loginscreen"); + gui->SetSceneState(SCENESTATE_LOGINSCREEN); + // disconnect from realm server if connected + if(RealmSession *rs = instance->GetRSession()) + rs->SetMustDie(); + if(WorldSession *ws = instance->GetWSession()) + ws->SetMustDie(); + } + if(eventrecv->buttons & BUTTON_DELETE_CHARACTER) + { + guienv->addMessageBox(L"Not yet implemented!", L"Deleting a character does not yet work!"); + } + if(eventrecv->buttons & BUTTON_NEW_CHARACTER) + { + guienv->addMessageBox(L"Not yet implemented!", L"Creating a new character does not yet work!"); + } + if(eventrecv->buttons & BUTTON_SELECT_REALM) + { + if(instance->GetRSession()) + { + scenedata[ISCENE_CHARSEL_REALMFIRST] = 1; // show realm selection window + OnResize(); // force gui redraw to remove window + // TODO: there should exist a better way without full redraw + } + else + { + guienv->addMessageBox(L"Not yet implemented!", L"This action is not yet supported.\nYou can change the realm only while still connected to the realm server."); + } + } + // treat doubleclick on realmlist as OK button click + if(!eventrecv->guievent_proc) + { + eventrecv->guievent_proc = true; + if(eventrecv->guievent.GUIEvent.EventType == EGET_LISTBOX_SELECTED_AGAIN && eventrecv->guievent.GUIEvent.Caller == realmlistbox) + { + eventrecv->buttons |= BUTTON_REALMWIN_OK; + } + //... + } + + if(eventrecv->buttons & BUTTON_REALMWIN_OK) + { + RealmSession *rs = instance->GetRSession(); + if(rs) + { + u32 selected = realmlistbox->getSelected(); + if(selected < rs->GetRealmCount()) + { + rs->SetRealmAddr(rs->GetRealm(selected).addr_port); + instance->CreateWorldSession(); + eventrecv->buttons |= BUTTON_REALMWIN_CANCEL; // easiest way to close the window without much additional code + } + else + logerror("Realmlist selection out of bounds! (%u)",selected); + } + } + + + // realmlist window + if(eventrecv->buttons & BUTTON_REALMWIN_CANCEL) + { + scenedata[ISCENE_CHARSEL_REALMFIRST] = 0; // do not show realm selection window + OnResize(); // force gui redraw to remove window + // TODO: there should exist a better way without full redraw + } + + eventrecv->buttons = 0; +} + +void SceneCharSelection::OnDelete(void) +{ +} + + +void SceneCharSelection::OnResize(void) +{ + // this seems to be necessary since after a window resize == 0x00000001 for some unknown reason (=CRASH!) + // if anyone knows how to fix that or whats causing it... please do so. + // note: used VC71. also tested it with resizing SceneLogin, there the ptr stays fine. wtf?! + textdb = instance->dbmgr.GetDB("gui_charselect_text"); + + guienv->clear(); // drop all elements and redraw + guienv->addButton(CalcRelativeScreenPos(driver, 0.45f ,0.9f, 0.15f, 0.05f), NULL, BUTTON_ENTER_WORLD, + GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_BUTTON_ENTERWORLD).c_str()); + guienv->addButton(CalcRelativeScreenPos(driver, 0.9f, 0.92f, 0.08f, 0.03f), NULL, BUTTON_BACK, + GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_BUTTON_BACK).c_str()); + guienv->addButton(CalcRelativeScreenPos(driver, 0.85f, 0.05f, 0.12f, 0.04f), NULL, BUTTON_SELECT_REALM, + GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_BUTTON_CHANGEREALM).c_str()); + guienv->addButton(CalcRelativeScreenPos(driver, 0.85f, 0.8f, 0.1f, 0.04f), NULL, BUTTON_NEW_CHARACTER, + GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_BUTTON_NEWCHAR).c_str()); + guienv->addButton(CalcRelativeScreenPos(driver, 0.78f, 0.92f, 0.1f, 0.03f), NULL, BUTTON_DELETE_CHARACTER, + GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_BUTTON_DELCHAR).c_str()); + + realmwin = NULL; + if(scenedata[ISCENE_CHARSEL_REALMFIRST]) + { + dimension2d dim; + rect pos; + realmwin = guienv->addWindow(CalcRelativeScreenPos(driver, 0.2f, 0.2f, 0.6f, 0.6f), true, + GetStringFromDB(ISCENE_CHARSEL_LABELS, DSCENE_CHARSEL_LABEL_REALMWIN).c_str()); + pos = realmwin->getAbsolutePosition(); // get absolute position and trandform to absolute in-window position + dim.Width = pos.LowerRightCorner.X - pos.UpperLeftCorner.X; + dim.Height = pos.LowerRightCorner.Y - pos.UpperLeftCorner.Y; + realmwin->addChild(guienv->addButton(CalcRelativeScreenPos(dim, 0.7f, 0.93f, 0.12f, 0.05f), realmwin, BUTTON_REALMWIN_OK, + GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_REALMWIN_OK).c_str())); + realmwin->addChild(guienv->addButton(CalcRelativeScreenPos(dim, 0.85f, 0.93f, 0.12f, 0.05f), realmwin, BUTTON_REALMWIN_CANCEL, + GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_REALMWIN_CANCEL).c_str())); + + realmlistbox = guienv->addListBox(CalcRelativeScreenPos(dim, 0.1f, 0.1f, 0.8f, 0.8f), realmwin); + realmwin->addChild(realmlistbox); + + RealmSession *rs = instance->GetRSession(); + + for(uint32 i = 0; i < rs->GetRealmCount(); i++) + { + SRealmInfo& r = rs->GetRealm(i); + core::stringw entry; + entry += r.name.c_str(); + entry += L", "; + switch(r.icon) // icon means here RealmType + { + case 0: entry += "Normal"; break; + case 1: entry += "PvP"; break; + case 4: entry += "Normal(4)"; break; + case 6: entry += "RP"; break; + case 8: entry += "RP-PvP"; break; + case 16: entry += "FFA-PvP"; break; // MaNGOS custom realm type + default: entry += "Unknown"; break; + } + entry += L", ("; + entry += r.chars_here; + entry += L") Chars"; + entry += L" ["; + entry += r.addr_port.c_str(); + entry += L"]"; + realmlistbox->addItem(entry.c_str(), -1); + SColor col; + switch(r.color) + { + case 0: col.set(0xFF, 0x00, 0xFF, 0x00); break; + case 1: col.set(0xFF, 0xFF, 0x00, 0x00); break; + case 2: col.set(0xFF, 0x7F, 0x7F, 0x7F); break; + case 3: col.set(0xFF, 0xB0, 0xB0, 0x00); break; + default: col.set(0xFFFFFFFF); + } + realmlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT,col); + realmlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT_HIGHLIGHT,col); + } + if(realmlistbox->getItemCount()) + realmlistbox->setSelected(0); + } + + rect clb_rect = CalcRelativeScreenPos(driver, 0.65f, 0.12f, 0.34f, 0.67f); + charlistbox = guienv->addListBox(clb_rect); + WorldSession *ws = instance->GetWSession(); + if(ws) + { + SCPDatabase *racedb = instance->dbmgr.GetDB("race"); + uint32 ffaction = racedb->GetFieldId("faction"); + for(uint32 i = 0; i < ws->GetCharsCount(); i++) + { + CharacterListExt& c = ws->GetCharFromList(i); + core::stringw entry; + entry += c.p._name.c_str(); + entry += L", "; + entry += L"Level "; + entry += c.p._level; + entry += "L "; + entry += c.race.c_str(); + entry += L" "; + entry += c.class_.c_str(); + entry += L", "; + entry += c.zone.c_str(); + entry += L" ("; + entry += c.map_.c_str(); + entry += L")"; + charlistbox->addItem(entry.c_str()); + + uint32 faction = racedb->GetInt(c.p._race, ffaction); + + SColor col; + switch(faction) + { + case 1: col.set(0xFF, 0xFF, 0x30, 0x30); break; + case 7: col.set(0xFF, 0x30, 0x30, 0xFF); break; + default: col.set(0xFFFFFFFF); + } + charlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT,col); + charlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT_HIGHLIGHT,col); + + } + } + +} + diff --git a/src/Client/GUI/SceneData.h b/src/Client/GUI/SceneData.h index 40e904d..5815a1c 100644 --- a/src/Client/GUI/SceneData.h +++ b/src/Client/GUI/SceneData.h @@ -1,7 +1,7 @@ #ifndef SCENEDATA_H #define SCENEDATA_H -#define SCENEDATA_SIZE 255 +#define SCENEDATA_SIZE 256 // I: index, enums should start with 1 // D: data value @@ -10,8 +10,10 @@ enum SceneLoginDataIndexes { ISCENE_LOGIN_CONN_STATUS = 1, - ISCENE_LOGIN_MSGBOX_DUMMY = 2, - ISCENE_LOGIN_END = 3 + ISCENE_LOGIN_MSGBOX_DUMMY = 2, // text + ISCENE_LOGIN_LABELS = 3, // text + ISCENE_LOGIN_BUTTONS = 4, // text + ISCENE_LOGIN_END }; enum SceneLoginConnStatus @@ -29,6 +31,44 @@ enum SceneLoginConnStatus DSCENE_LOGIN_UNK_ERROR = 10, DSCENE_LOGIN_FILE_TRANSFER = 11, }; + +enum SceneLoginLabels +{ + DSCENE_LOGIN_LABEL_ACC = 0, + DSCENE_LOGIN_LABEL_PASS = 1, +}; + +enum SceneLoginButtons +{ + DSCENE_LOGIN_BUTTON_LOGIN = 0, + DSCENE_LOGIN_BUTTON_QUIT = 1, + DSCENE_LOGIN_BUTTON_SITE = 2, +}; + +enum SceneCharSelectDataIndexes +{ + ISCENE_CHARSEL_BUTTONS = 1, // text + ISCENE_CHARSEL_LABELS = 2, // text + ISCENE_CHARSEL_REALMFIRST = 255, // flag that is set when connecting to a realm wasnt possible and the realm list must be shown first + ISCENE_CHARSEL_END +}; + +enum SceneCharSelectButtons +{ + DSCENE_CHARSEL_BUTTON_ENTERWORLD = 0, + DSCENE_CHARSEL_BUTTON_NEWCHAR = 1, + DSCENE_CHARSEL_BUTTON_DELCHAR = 2, + DSCENE_CHARSEL_BUTTON_CHANGEREALM = 3, + DSCENE_CHARSEL_BUTTON_BACK = 4, + DSCENE_CHARSEL_REALMWIN_OK = 5, + DSCENE_CHARSEL_REALMWIN_CANCEL = 6, +}; + +enum SceneCharSelectLabels +{ + DSCENE_CHARSEL_LABEL_REALMWIN = 0, +}; + #endif diff --git a/src/Client/GUI/SceneLogin.cpp b/src/Client/GUI/SceneLogin.cpp index 9c58071..8dc2c86 100644 --- a/src/Client/GUI/SceneLogin.cpp +++ b/src/Client/GUI/SceneLogin.cpp @@ -3,6 +3,7 @@ #include "PseuWoW.h" #include "Scene.h" #include "RealmSession.h" +#include "GUIEventReceiver.h" enum GuiElementID { @@ -13,37 +14,6 @@ enum GuiElementID BUTTON_LOGON = 0x10, }; -class GUIEventReceiver : public IEventReceiver -{ -public: - GUIEventReceiver() - { - buttons=0; - } - virtual bool OnEvent(const SEvent& event) - { - //GUI EVENT - if (event.EventType == EET_GUI_EVENT) - { - s32 id = event.GUIEvent.Caller->getID(); - - switch(event.GUIEvent.EventType) - { - case EGET_BUTTON_CLICKED: - logdebug("user clicked button %u",id); - buttons+=id; - return true; - break; - } - } - - return false; - } - u32 buttons; -}; - - - //TODO: Reposition elements on resize //the code happens only ones, We need to, in the main loop ( usually while(driver->run()) ) set the //positions of each gui element based on the current screensize ( gotten with driver->getScreenSize(); ) @@ -53,29 +23,39 @@ SceneLogin::SceneLogin(PseuGUI *gui) : Scene(gui) textdb = instance->dbmgr.GetDB("gui_login_text"); msgbox_textid = 0; eventrecv = new GUIEventReceiver(); + eventrecv->keyToButtonMap[KEY_RETURN] = BUTTON_LOGON; + eventrecv->keyToButtonMap[KEY_ESCAPE] = BUTTON_QUIT; device->setEventReceiver(eventrecv); - root = guienv->getRootGUIElement(); dimension2d scrn = driver->getScreenSize(); - irrlogo = guienv->addImage(driver->getTexture("data/misc/irrlichtlogo.png"), core::position2d(5,5),true,root); - background = guienv->addImage(driver->getTexture("data/misc/sky.jpg"), core::position2d(5,5),true,root); + irrlogo = guienv->addImage(driver->getTexture("data/misc/irrlichtlogo.png"), core::position2d(5,5),true,rootgui); + background = guienv->addImage(driver->getTexture("data/misc/sky.jpg"), core::position2d(5,5),true,rootgui); background->setRelativePosition(rect(0,0,scrn.Width,scrn.Height)); irrlogo->setScaleImage(true); - guienv->addStaticText(L"Account:",rect((scrn.Width*0.5f)-90, (scrn.Height*0.3f)-10, (scrn.Width*0.5f)+90, (scrn.Height*0.3f)+10), false, false, 0, 0); - guienv->addStaticText(L"Password:", rect((scrn.Width*0.5f)-90, (scrn.Height*0.3f)+50, (scrn.Width*0.5f)+90, (scrn.Height*0.3f)+70), false, false, 0, 0); - guienv->addEditBox(L"", rect((scrn.Width*0.5f)-90, (scrn.Height*0.3f)+10, (scrn.Width*0.5f)+90, (scrn.Height*0.3f)+30), true, 0, 1); + core::stringw accn; + accn += instance->GetConf()->accname.c_str(); + + guienv->addStaticText(GetStringFromDB(ISCENE_LOGIN_LABELS,DSCENE_LOGIN_LABEL_ACC).c_str(),rect((scrn.Width*0.5f)-90, (scrn.Height*0.3f)-10, (scrn.Width*0.5f)+90, (scrn.Height*0.3f)+10), false, false, 0, 0); + guienv->addStaticText(GetStringFromDB(ISCENE_LOGIN_LABELS,DSCENE_LOGIN_LABEL_PASS).c_str(), rect((scrn.Width*0.5f)-90, (scrn.Height*0.3f)+50, (scrn.Width*0.5f)+90, (scrn.Height*0.3f)+70), false, false, 0, 0); + guienv->addEditBox(accn.c_str(), rect((scrn.Width*0.5f)-90, (scrn.Height*0.3f)+10, (scrn.Width*0.5f)+90, (scrn.Height*0.3f)+30), true, 0, 1); guienv->addEditBox(L"", rect((scrn.Width*0.5f)-90, (scrn.Height*0.3f)+70, (scrn.Width*0.5f)+90, (scrn.Height*0.3f)+90), true, 0, 2)->setPasswordBox(true); - guienv->addButton(rect(scrn.Width-120, scrn.Height-40, scrn.Width-10, scrn.Height-10), 0, 4, L"Quit"); - guienv->addButton(rect(10, scrn.Height-40, 120, scrn.Height-10), 0, 8, L"Community Site"); - guienv->addButton(rect((scrn.Width*0.5f)-60, (scrn.Height*0.3f)+100, (scrn.Width*0.5f)+60, (scrn.Height*0.3f)+130), 0, 16, L"Logon"); + guienv->addButton(rect(scrn.Width-120, scrn.Height-40, scrn.Width-10, scrn.Height-10), 0, 4, GetStringFromDB(ISCENE_LOGIN_BUTTONS,DSCENE_LOGIN_BUTTON_QUIT).c_str()); + guienv->addButton(rect(10, scrn.Height-40, 120, scrn.Height-10), 0, 8, GetStringFromDB(ISCENE_LOGIN_BUTTONS,DSCENE_LOGIN_BUTTON_SITE).c_str()); + guienv->addButton(rect((scrn.Width*0.5f)-60, (scrn.Height*0.3f)+100, (scrn.Width*0.5f)+60, (scrn.Height*0.3f)+130), 0, 16, GetStringFromDB(ISCENE_LOGIN_BUTTONS,DSCENE_LOGIN_BUTTON_LOGIN).c_str()); msgbox = guienv->addStaticText(GetStringFromDB(ISCENE_LOGIN_CONN_STATUS,DSCENE_LOGIN_NOT_CONNECTED).c_str(),rect((scrn.Width*0.5f)-90, (scrn.Height*0.3f)+150, (scrn.Width*0.5f)+90, (scrn.Height*0.3f)+180),true,true); if(soundengine) { - soundengine->play2D("data/misc/main_theme.ogg",true); + ISoundSource *main_theme = soundengine->getSoundSource("data/misc/main_theme.ogg"); + if(main_theme && !soundengine->isCurrentlyPlaying(main_theme)) + { + soundengine->play2D(main_theme,true); + } } + + popup = NULL; } void SceneLogin::OnUpdate(s32 timepassed) @@ -92,12 +72,11 @@ void SceneLogin::OnUpdate(s32 timepassed) } if(eventrecv->buttons & BUTTON_LOGON) { - eventrecv->buttons=0; logdebug("Commencing Logon"); core::stringc tmp; - tmp=root->getElementFromId(TEXTBOX_NAME,true)->getText(); + tmp=rootgui->getElementFromId(TEXTBOX_NAME,true)->getText(); std::string accname =tmp.c_str(); - tmp=root->getElementFromId(TEXTBOX_PASSWORD,true)->getText(); + tmp=rootgui->getElementFromId(TEXTBOX_PASSWORD,true)->getText(); std::string accpass=tmp.c_str(); if(accname.size() && accpass.size()) { @@ -106,14 +85,27 @@ void SceneLogin::OnUpdate(s32 timepassed) // we can safely override the conf settings instance->GetConf()->accname = accname; instance->GetConf()->accpass = accpass; + // ...but do not set the defscript vars; its just not safe instance->CreateRealmSession(); } else { - guienv->addMessageBox(GetStringFromDB(ISCENE_LOGIN_MSGBOX_DUMMY,0).c_str(), - GetStringFromDB(ISCENE_LOGIN_MSGBOX_DUMMY,1).c_str()); + popup = guienv->addMessageBox(GetStringFromDB(ISCENE_LOGIN_MSGBOX_DUMMY,0).c_str(), + GetStringFromDB(ISCENE_LOGIN_MSGBOX_DUMMY,1).c_str()); + eventrecv->react_to_keys = false; // prevent main window from processing key input; it must be processed by the msgbox's event recv! + // our eventrecv will handle msgbox close event by itself and enable input again. } + } + if(eventrecv->buttons & BUTTON_COMMUNITY) + { +#if PLATFORM == PLATFORM_WIN32 + ShellExecute(NULL, "open", "http://www.mangosclient.org", NULL, NULL, SW_SHOWNORMAL); +#elif PLATFORM == PLATFORM_UNIX + // linux code here +#elif PLATFORM == PLATFORM_APPLE + // mac code here +#endif } eventrecv->buttons = 0; } diff --git a/src/Client/GUI/SceneWorld.cpp b/src/Client/GUI/SceneWorld.cpp index a9e044d..e034148 100644 --- a/src/Client/GUI/SceneWorld.cpp +++ b/src/Client/GUI/SceneWorld.cpp @@ -14,6 +14,7 @@ #include "CCursorController.h" #include "MovementMgr.h" #include "DrawObject.h" +#include "irrKlangSceneNode.h" // TODO: replace this by conf value #define MAX_CAM_DISTANCE 70 @@ -35,6 +36,11 @@ SceneWorld::SceneWorld(PseuGUI *g) : Scene(g) _CalcXYMoveVect(mychar->GetO()); old_char_o = mychar->GetO(); + if(soundengine) + { + soundengine->stopAllSounds(); + } + ILightSceneNode* light = smgr->addLightSceneNode(0, core::vector3df(0,0,0), SColorf(255, 255, 255, 255), 1000.0f); SLight ldata = light->getLightData(); ldata.AmbientColor = video::SColorf(0.2f,0.2f,0.2f); @@ -369,7 +375,7 @@ void SceneWorld::OnUpdate(s32 timediff) device->getCursorControl()->setPosition(mouse_pos); // rotate character if right mouse button pressed. - if(mouse_pressed_right) + if(mouse_pressed_right && !_freeCameraMove) { mychar->GetPositionPtr()->o = PI*3/2 - DEG_TO_RAD(camera->getHeading()); // send update to server only if we turned by some amount and not always when we turn @@ -473,6 +479,7 @@ void SceneWorld::OnDelete(void) { DEBUG(logdebug("~SceneWorld()")); _doodads.clear(); + _sound_emitters.clear(); gui->domgr.Clear(); delete camera; delete eventrecv; @@ -543,7 +550,8 @@ void SceneWorld::UpdateTerrain(void) return; } - UpdateDoodads(); // drop doodads on maps not loaded anymore. no maptile pointers are dereferenced here, so it can be done before acquiring the mutex + UpdateMapSceneNodes(_doodads); // drop doodads on maps not loaded anymore. no maptile pointers are dereferenced here, so it can be done before acquiring the mutex + UpdateMapSceneNodes(_sound_emitters); // same with sound emitters mutex.acquire(); // prevent other threads from deleting maptiles @@ -637,6 +645,63 @@ void SceneWorld::UpdateTerrain(void) } } } + // create sound emitters + logdebug("Loading %u sound emitters for tile (%u, %u)", maptile->GetSoundEmitterCount(), tile_real_x, tile_real_y); + uint32 fieldId[10]; // SCP: file1 - file10 (index 0 not used) + char fieldname_t[10]; + SCPDatabase *sounddb = gui->GetInstance()->dbmgr.GetDB("sound"); + if(sounddb) + { + for(uint32 i = 0; i < 10; i++) + { + sprintf(fieldname_t,"file%u",i + 1); // starts with "file1" + fieldId[i] = sounddb->GetFieldId(fieldname_t); + } + + for(uint32 i = 0; i < maptile->GetSoundEmitterCount(); i++) + { + MCSE_chunk *snd = maptile->GetSoundEmitter(i); + if(_sound_emitters.find(snd->soundPointID) == _sound_emitters.end()) + { + CIrrKlangSceneNode *snode = new CIrrKlangSceneNode(soundengine, smgr->getRootSceneNode(), smgr, snd->soundPointID); + snode->drop(); + snode->setPosition(core::vector3df(-snd->x, snd->z, -snd->y)); + snode->getDebugCube()->setPosition(snode->getPosition()); + snode->setMinMaxSoundDistance(snd->minDistance,snd->maxDistance); + bool exists = sounddb->GetRowByIndex(snd->soundNameID); + if(exists) + { + for(uint32 s = 0; s < 10; s++) + { + u32 offs = sounddb->GetInt(snd->soundNameID, fieldId[s]); + if(fieldId[s] != SCP_INVALID_INT && offs && offs != SCP_INVALID_INT) + { + std::string fn = "data/sound/"; + fn += sounddb->GetString(snd->soundNameID, fieldId[s]); + snode->addSoundFileName(fn.c_str()); + } + } + snode->setLoopingStreamMode(); + } + + core::stringw txt; + txt += (exists ? sounddb->GetString(snd->soundNameID, "name") : "[NA SoundEmitter]"); + txt += L" ("; + txt += u32(snd->soundNameID); + txt += L")"; + snode->getDebugText()->setPosition(snode->getPosition()); + snode->getDebugText()->setText(txt.c_str()); + + SceneNodeWithGridPos gp; + gp.gx = mapmgr->GetGridX() + tilex - 1; + gp.gy = mapmgr->GetGridY() + tiley - 1; + gp.scenenode = snode; + _sound_emitters[snd->soundPointID] = gp; + } + + } + } + } else { @@ -679,21 +744,21 @@ void SceneWorld::UpdateTerrain(void) RelocateCameraBehindChar(); } -// drop unneeded doodads from the map -void SceneWorld::UpdateDoodads(void) +// drop unneeded map SceneNodes from the map +void SceneWorld::UpdateMapSceneNodes(std::map& node_map) { - uint32 s = _doodads.size(); + uint32 s = node_map.size(); std::set tmp; // temporary storage for all doodad unique ids // too bad erasing from a map causes pointer invalidation, so first store all unique ids, and then erase - for(std::map::iterator it = _doodads.begin(); it != _doodads.end(); it++ ) + for(std::map::iterator it = node_map.begin(); it != node_map.end(); it++ ) if(!mapmgr->GetTile(it->second.gx, it->second.gy)) tmp.insert(it->first); for(std::set::iterator it = tmp.begin(); it != tmp.end(); it++) { - _doodads[*it].scenenode->remove(); - _doodads.erase(*it); + node_map[*it].scenenode->remove(); + node_map.erase(*it); } - logdebug("SceneWorld: Doodads cleaned up, before: %u, after: %u, dropped: %u", s, _doodads.size(), s - _doodads.size()); + logdebug("SceneWorld: MapSceneNodes cleaned up, before: %u, after: %u, dropped: %u", s, node_map.size(), s - node_map.size()); } diff --git a/src/Client/GUI/irrKlangSceneNode.cpp b/src/Client/GUI/irrKlangSceneNode.cpp index 4b288f4..d9b25bb 100644 --- a/src/Client/GUI/irrKlangSceneNode.cpp +++ b/src/Client/GUI/irrKlangSceneNode.cpp @@ -29,12 +29,17 @@ CIrrKlangSceneNode::CIrrKlangSceneNode(irrklang::ISoundEngine* soundEngine, if (SoundEngine) SoundEngine->grab(); + + cube = mgr->addCubeSceneNode(0.5f); + cube->setMaterialTexture(0,mgr->getVideoDriver()->getTexture("data/misc/square.jpg")); + text = mgr->addTextSceneNode(mgr->getGUIEnvironment()->getBuiltInFont(), L"", video::SColor(0xFF00AF00)); } CIrrKlangSceneNode::~CIrrKlangSceneNode() { stop(); + cube->remove(); if (SoundEngine) SoundEngine->drop(); @@ -52,6 +57,9 @@ void CIrrKlangSceneNode::OnRegisterSceneNode() void CIrrKlangSceneNode::OnAnimate(u32 timeMs) { + if(!SoundFileNames.size()) + return; + ISceneNode::OnAnimate(timeMs); // play the sound @@ -84,7 +92,8 @@ void CIrrKlangSceneNode::OnAnimate(u32 timeMs) else if (!Sound && (!TimeMsDelayFinished || timeMs > TimeMsDelayFinished)) { - // play new sound + // play new sound; select one from the possible files + core::stringc& SoundFileName = SoundFileNames[ rand() % SoundFileNames.size() ]; if (SoundFileName.size()) Sound = SoundEngine->play3D(SoundFileName.c_str(), pos, false, true, true); @@ -105,6 +114,7 @@ void CIrrKlangSceneNode::OnAnimate(u32 timeMs) { if (!Sound) { + core::stringc& SoundFileName = SoundFileNames[ rand() % SoundFileNames.size() ]; if (SoundFileName.size()) Sound = SoundEngine->play3D(SoundFileName.c_str(), pos, true, true, true); @@ -142,6 +152,7 @@ void CIrrKlangSceneNode::OnAnimate(u32 timeMs) else { // start + core::stringc& SoundFileName = SoundFileNames[ rand() % SoundFileNames.size() ]; if (SoundFileName.size()) Sound = SoundEngine->play3D(SoundFileName.c_str(), pos, false, true, true); @@ -234,7 +245,7 @@ void CIrrKlangSceneNode::render() material.Lighting = false; material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; material.MaterialTypeParam = 255; - material.TextureLayer[0].Texture = driver->getTexture("textures/editor_defaults/default_sound.png"); + material.TextureLayer[0].Texture = driver->getTexture("data/misc/square.jpg"); core::matrix4 mat; driver->setTransform(video::ETS_WORLD, mat); @@ -256,122 +267,6 @@ const c8* const IrrKlangPlayModeNames[] = "nothing", "random", "looping", "play_once", 0 }; - -//! Writes attributes of the scene node. -void CIrrKlangSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const -{ - if (!out) - return; - - ISceneNode::serializeAttributes(out, options); - const char** soundNames = 0; - - if ( SoundEngine && options && ( options->Flags & io::EARWF_FOR_EDITOR ) ) - { - // show a list of all loaded sound files in editor - - int count = SoundEngine->getSoundSourceCount(); - soundNames = new const char*[count+3]; - - for (int i=0; igetSoundSource(i)->getName(); - - soundNames[count] = ""; - soundNames[count+1] = "