From eafd44cfc5cab659c850951279e2f78598d37521 Mon Sep 17 00:00:00 2001 From: elexis Date: Wed, 15 Jan 2020 16:00:37 +0000 Subject: [PATCH] Remove counterproductive lowercasing of GUI ScriptEvent names, refs #127. a8f48ff7e0 introduced XeroXMB lowercasing of element and attribute names as a feature. cf9d8b9797, 4d390f501c, dda6268466 added bugfixes and TODOs because of that. f76d0ffdc6, 44fe226dd2 removed the XeroXMB lowercase feature. This patch removes the lowercasing GUI bugfixes that don't fix any bug anymore while increasing code complexity and lowering performance (string copies). Do not send mouse coordinates objects for events that do not relate to the mouse. Store event names in static const members to: (1) improve performance, ensuring that the CStr is not reconstructed every call, (2) obtain compile errors when misspelling event names, (3) allow reuse of the strings in inherited and friend classes. Differential Revision: https://code.wildfiregames.com/D2445 Comments by Matei, Philip on 2006-03-11-QuakeNet-#wfg-Meeting-0126.log and 2006-06-24-QuakeNet-#wfg-Meeting-0139.log This was SVN commit r23403. --- .../public/gui/replaymenu/replay_menu.xml | 2 +- .../data/mods/public/gui/session/session.js | 6 +- source/gui/CGUI.cpp | 65 ++++++++-------- source/gui/CGUI.h | 26 ++++++- source/gui/GUIManager.cpp | 4 +- source/gui/GUIManager.h | 2 + source/gui/ObjectBases/IGUIButtonBehavior.cpp | 13 +++- source/gui/ObjectBases/IGUIButtonBehavior.h | 5 ++ source/gui/ObjectBases/IGUIObject.cpp | 77 +++++++++++-------- source/gui/ObjectBases/IGUIObject.h | 29 ++++--- source/gui/ObjectTypes/CInput.cpp | 26 ++++--- source/gui/ObjectTypes/CInput.h | 4 + source/gui/ObjectTypes/CList.cpp | 16 ++-- source/gui/ObjectTypes/CList.h | 5 ++ source/gui/ObjectTypes/CMiniMap.cpp | 4 +- source/gui/ObjectTypes/CMiniMap.h | 2 + source/gui/ObjectTypes/COList.cpp | 4 +- source/gui/ObjectTypes/COList.h | 2 + source/gui/ObjectTypes/CSlider.cpp | 4 +- source/gui/ObjectTypes/CSlider.h | 1 + .../gui/Scripting/JSInterface_IGUIObject.cpp | 8 +- source/ps/Game.cpp | 6 +- source/ps/Game.h | 4 +- source/ps/GameSetup/GameSetup.cpp | 4 +- source/ps/XML/XeroXMB.h | 9 +-- .../simulation2/system/ReplayTurnManager.cpp | 11 ++- source/simulation2/system/ReplayTurnManager.h | 5 +- source/simulation2/system/TurnManager.cpp | 6 +- source/simulation2/system/TurnManager.h | 13 ++-- 29 files changed, 226 insertions(+), 137 deletions(-) diff --git a/binaries/data/mods/public/gui/replaymenu/replay_menu.xml b/binaries/data/mods/public/gui/replaymenu/replay_menu.xml index b6d31a7e27..dc3f256b98 100644 --- a/binaries/data/mods/public/gui/replaymenu/replay_menu.xml +++ b/binaries/data/mods/public/gui/replaymenu/replay_menu.xml @@ -62,7 +62,7 @@ displayReplayDetails(); displayReplayList(); - startReplay(); + startReplay(); diff --git a/binaries/data/mods/public/gui/session/session.js b/binaries/data/mods/public/gui/session/session.js index bc3bb5e2fa..362889a72b 100644 --- a/binaries/data/mods/public/gui/session/session.js +++ b/binaries/data/mods/public/gui/session/session.js @@ -688,9 +688,9 @@ function updateGroups() let button = Engine.GetGUIObjectByName("unitGroupButton[" + i + "]"); button.hidden = g_Groups.groups[i].getTotalCount() == 0; - button.onpress = (function(i) { return function() { performGroup((Engine.HotkeyIsPressed("selection.add") ? "add" : "select"), i); }; })(i); - button.ondoublepress = (function(i) { return function() { performGroup("snap", i); }; })(i); - button.onpressright = (function(i) { return function() { performGroup("breakUp", i); }; })(i); + button.onPress = (function(i) { return function() { performGroup((Engine.HotkeyIsPressed("selection.add") ? "add" : "select"), i); }; })(i); + button.onDoublePress = (function(i) { return function() { performGroup("snap", i); }; })(i); + button.onPressRight = (function(i) { return function() { performGroup("breakUp", i); }; })(i); // Choose the icon of the most common template (or the most costly if it's not unique) if (g_Groups.groups[i].getTotalCount() > 0) diff --git a/source/gui/CGUI.cpp b/source/gui/CGUI.cpp index 847baac84b..d4a45bb400 100644 --- a/source/gui/CGUI.cpp +++ b/source/gui/CGUI.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -47,6 +47,19 @@ extern int g_yres; const double SELECT_DBLCLICK_RATE = 0.5; const u32 MAX_OBJECT_DEPTH = 100; // Max number of nesting for GUI includes. Used to detect recursive inclusion +const CStr CGUI::EventNameLoad = "Load"; +const CStr CGUI::EventNameTick = "Tick"; +const CStr CGUI::EventNamePress = "Press"; +const CStr CGUI::EventNameRelease = "Release"; +const CStr CGUI::EventNameMouseRightPress = "MouseRightPress"; +const CStr CGUI::EventNameMouseLeftPress = "MouseLeftPress"; +const CStr CGUI::EventNameMouseWheelDown = "MouseWheelDown"; +const CStr CGUI::EventNameMouseWheelUp = "MouseWheelUp"; +const CStr CGUI::EventNameMouseLeftDoubleClick = "MouseLeftDoubleClick"; +const CStr CGUI::EventNameMouseLeftRelease = "MouseLeftRelease"; +const CStr CGUI::EventNameMouseRightDoubleClick = "MouseRightDoubleClick"; +const CStr CGUI::EventNameMouseRightRelease = "MouseRightRelease"; + CGUI::CGUI(const shared_ptr& runtime) : m_BaseObject(*this), m_FocusedObject(nullptr), @@ -93,9 +106,9 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev) for (IGUIObject* const& obj : it->second) { if (ev->ev.type == SDL_HOTKEYDOWN) - ret = obj->SendEvent(GUIM_PRESSED, "press"); + ret = obj->SendEvent(GUIM_PRESSED, EventNamePress); else - ret = obj->SendEvent(GUIM_RELEASED, "release"); + ret = obj->SendEvent(GUIM_RELEASED, EventNameRelease); } } @@ -158,12 +171,12 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev) SetFocusedObject(pNearest); if (pNearest) - ret = pNearest->SendEvent(GUIM_MOUSE_PRESS_LEFT, "mouseleftpress"); + ret = pNearest->SendMouseEvent(GUIM_MOUSE_PRESS_LEFT, EventNameMouseLeftPress); break; case SDL_BUTTON_RIGHT: if (pNearest) - ret = pNearest->SendEvent(GUIM_MOUSE_PRESS_RIGHT, "mouserightpress"); + ret = pNearest->SendMouseEvent(GUIM_MOUSE_PRESS_RIGHT, EventNameMouseRightPress); break; default: @@ -173,9 +186,9 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev) else if (ev->ev.type == SDL_MOUSEWHEEL && pNearest) { if (ev->ev.wheel.y < 0) - ret = pNearest->SendEvent(GUIM_MOUSE_WHEEL_DOWN, "mousewheeldown"); + ret = pNearest->SendMouseEvent(GUIM_MOUSE_WHEEL_DOWN, EventNameMouseWheelDown); else if (ev->ev.wheel.y > 0) - ret = pNearest->SendEvent(GUIM_MOUSE_WHEEL_UP, "mousewheelup"); + ret = pNearest->SendMouseEvent(GUIM_MOUSE_WHEEL_UP, EventNameMouseWheelUp); } else if (ev->ev.type == SDL_MOUSEBUTTONUP) { @@ -186,11 +199,10 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev) { double timeElapsed = timer_Time() - pNearest->m_LastClickTime[SDL_BUTTON_LEFT]; pNearest->m_LastClickTime[SDL_BUTTON_LEFT] = timer_Time(); - if (timeElapsed < SELECT_DBLCLICK_RATE) - ret = pNearest->SendEvent(GUIM_MOUSE_DBLCLICK_LEFT, "mouseleftdoubleclick"); + ret = pNearest->SendMouseEvent(GUIM_MOUSE_DBLCLICK_LEFT, EventNameMouseLeftDoubleClick); else - ret = pNearest->SendEvent(GUIM_MOUSE_RELEASE_LEFT, "mouseleftrelease"); + ret = pNearest->SendMouseEvent(GUIM_MOUSE_RELEASE_LEFT, EventNameMouseLeftRelease); } break; case SDL_BUTTON_RIGHT: @@ -198,11 +210,10 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev) { double timeElapsed = timer_Time() - pNearest->m_LastClickTime[SDL_BUTTON_RIGHT]; pNearest->m_LastClickTime[SDL_BUTTON_RIGHT] = timer_Time(); - if (timeElapsed < SELECT_DBLCLICK_RATE) - ret = pNearest->SendEvent(GUIM_MOUSE_DBLCLICK_RIGHT, "mouserightdoubleclick"); + ret = pNearest->SendMouseEvent(GUIM_MOUSE_DBLCLICK_RIGHT, EventNameMouseRightDoubleClick); else - ret = pNearest->SendEvent(GUIM_MOUSE_RELEASE_RIGHT, "mouserightrelease"); + ret = pNearest->SendMouseEvent(GUIM_MOUSE_RELEASE_RIGHT, EventNameMouseRightRelease); } break; } @@ -257,29 +268,18 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev) void CGUI::TickObjects() { - const CStr action = "tick"; - m_BaseObject.RecurseObject(nullptr, &IGUIObject::ScriptEvent, action); - + SendEventToAll(EventNameTick); m_Tooltip.Update(FindObjectUnderMouse(), m_MousePos, *this); } -void CGUI::SendEventToAll(const CStr& EventName) +void CGUI::SendEventToAll(const CStr& eventName) { - // janwas 2006-03-03: spoke with Ykkrosh about EventName case. - // when registering, case is converted to lower - this avoids surprise - // if someone were to get the case wrong and then not notice their - // handler is never called. however, until now, the other end - // (sending events here) wasn't converting to lower case, - // leading to a similar problem. - // now fixed; case is irrelevant since all are converted to lower. - const CStr EventNameLower = EventName.LowerCase(); - m_BaseObject.RecurseObject(nullptr, &IGUIObject::ScriptEvent, EventNameLower); + m_BaseObject.RecurseObject(nullptr, &IGUIObject::ScriptEvent, eventName); } -void CGUI::SendEventToAll(const CStr& EventName, const JS::HandleValueArray& paramData) +void CGUI::SendEventToAll(const CStr& eventName, const JS::HandleValueArray& paramData) { - const CStr EventNameLower = EventName.LowerCase(); - m_BaseObject.RecurseObject(nullptr, &IGUIObject::ScriptEvent, EventNameLower, paramData); + m_BaseObject.RecurseObject(nullptr, &IGUIObject::ScriptEvent, eventName, paramData); } void CGUI::Draw() @@ -468,7 +468,7 @@ void CGUI::LoadedXmlFiles() SGUIMessage msg(GUIM_LOAD); m_BaseObject.RecurseObject(nullptr, &IGUIObject::HandleMessage, msg); - SendEventToAll("load"); + SendEventToAll(EventNameLoad); } //=================================================================== @@ -677,9 +677,8 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec // Read the inline code (concatenating to the file code, if both are specified) code += CStr(child.GetText()); - CStr action = CStr(child.GetAttributes().GetNamedItem(attr_on)); - - object->RegisterScriptHandler(action.LowerCase(), code, *this); + CStr eventName = child.GetAttributes().GetNamedItem(attr_on); + object->RegisterScriptHandler(eventName, code, *this); } else if (element_name == elmt_repeat) { diff --git a/source/gui/CGUI.h b/source/gui/CGUI.h index e88898d094..795beeaa04 100644 --- a/source/gui/CGUI.h +++ b/source/gui/CGUI.h @@ -74,17 +74,17 @@ public: /** * Sends a specified script event to every object * - * @param EventName String representation of event name + * @param eventName String representation of event name */ - void SendEventToAll(const CStr& EventName); + void SendEventToAll(const CStr& eventName); /** * Sends a specified script event to every object * - * @param EventName String representation of event name + * @param eventName String representation of event name * @param paramData JS::HandleValueArray storing the arguments passed to the event handler. */ - void SendEventToAll(const CStr& EventName, const JS::HandleValueArray& paramData); + void SendEventToAll(const CStr& eventName, const JS::HandleValueArray& paramData); /** * Displays the whole GUI @@ -611,6 +611,24 @@ private: */ std::map m_GlobalHotkeys; + /** + * XML and JS can subscribe handlers to events identified by these names. + * Store in static const members to avoid string copies, gain compile errors when misspelling and + * to allow reuse in other classes. + */ + static const CStr EventNameLoad; + static const CStr EventNameTick; + static const CStr EventNamePress; + static const CStr EventNameRelease; + static const CStr EventNameMouseRightPress; + static const CStr EventNameMouseLeftPress; + static const CStr EventNameMouseWheelDown; + static const CStr EventNameMouseWheelUp; + static const CStr EventNameMouseLeftDoubleClick; + static const CStr EventNameMouseLeftRelease; + static const CStr EventNameMouseRightDoubleClick; + static const CStr EventNameMouseRightRelease; + //-------------------------------------------------------- // Databases // These are loaded from XML files and marked as noncopyable and const to diff --git a/source/gui/GUIManager.cpp b/source/gui/GUIManager.cpp index 59ac90b655..8877dfa0de 100644 --- a/source/gui/GUIManager.cpp +++ b/source/gui/GUIManager.cpp @@ -31,6 +31,8 @@ CGUIManager* g_GUI = nullptr; +const CStr CGUIManager::EventNameWindowResized = "WindowResized"; + // General TODOs: // @@ -377,7 +379,7 @@ void CGUIManager::UpdateResolution() for (const SGUIPage& p : pageStack) { p.gui->UpdateResolution(); - p.gui->SendEventToAll("WindowResized"); + p.gui->SendEventToAll(EventNameWindowResized); } } diff --git a/source/gui/GUIManager.h b/source/gui/GUIManager.h index f3d315427d..80f2e32593 100644 --- a/source/gui/GUIManager.h +++ b/source/gui/GUIManager.h @@ -161,6 +161,8 @@ private: shared_ptr callbackFunction; }; + const static CStr EventNameWindowResized; + shared_ptr top() const; shared_ptr m_ScriptRuntime; diff --git a/source/gui/ObjectBases/IGUIButtonBehavior.cpp b/source/gui/ObjectBases/IGUIButtonBehavior.cpp index f7f0f5e9a2..4ed7eeba13 100644 --- a/source/gui/ObjectBases/IGUIButtonBehavior.cpp +++ b/source/gui/ObjectBases/IGUIButtonBehavior.cpp @@ -21,6 +21,11 @@ #include "gui/CGUISprite.h" +const CStr IGUIButtonBehavior::EventNamePress = "Press"; +const CStr IGUIButtonBehavior::EventNamePressRight = "PressRight"; +const CStr IGUIButtonBehavior::EventNameDoublePress = "DoublePress"; +const CStr IGUIButtonBehavior::EventNameDoublePressRight = "DoublePressRight"; + IGUIButtonBehavior::IGUIButtonBehavior(IGUIObject& pObject) : m_pObject(pObject), m_Pressed(), @@ -69,7 +74,7 @@ void IGUIButtonBehavior::HandleMessage(SGUIMessage& Message) // Since GUIM_MOUSE_PRESS_LEFT also gets called twice in a // doubleclick event, we let it handle playing sounds. - m_pObject.SendEvent(GUIM_DOUBLE_PRESSED, "doublepress"); + m_pObject.SendEvent(GUIM_DOUBLE_PRESSED, EventNameDoublePress); break; case GUIM_MOUSE_PRESS_LEFT: @@ -80,7 +85,7 @@ void IGUIButtonBehavior::HandleMessage(SGUIMessage& Message) } m_pObject.PlaySound(m_SoundPressed); - m_pObject.SendEvent(GUIM_PRESSED, "press"); + m_pObject.SendEvent(GUIM_PRESSED, EventNamePress); m_Pressed = true; break; @@ -90,7 +95,7 @@ void IGUIButtonBehavior::HandleMessage(SGUIMessage& Message) // Since GUIM_MOUSE_PRESS_RIGHT also gets called twice in a // doubleclick event, we let it handle playing sounds. - m_pObject.SendEvent(GUIM_DOUBLE_PRESSED_MOUSE_RIGHT, "doublepressright"); + m_pObject.SendEvent(GUIM_DOUBLE_PRESSED_MOUSE_RIGHT, EventNameDoublePressRight); break; case GUIM_MOUSE_PRESS_RIGHT: @@ -102,7 +107,7 @@ void IGUIButtonBehavior::HandleMessage(SGUIMessage& Message) // Button was right-clicked m_pObject.PlaySound(m_SoundPressed); - m_pObject.SendEvent(GUIM_PRESSED_MOUSE_RIGHT, "pressright"); + m_pObject.SendEvent(GUIM_PRESSED_MOUSE_RIGHT, EventNamePressRight); m_PressedRight = true; break; diff --git a/source/gui/ObjectBases/IGUIButtonBehavior.h b/source/gui/ObjectBases/IGUIButtonBehavior.h index 6ff2bdb38e..cb4a1c5026 100644 --- a/source/gui/ObjectBases/IGUIButtonBehavior.h +++ b/source/gui/ObjectBases/IGUIButtonBehavior.h @@ -60,6 +60,11 @@ public: const CGUISpriteInstance& GetButtonSprite(const CGUISpriteInstance& sprite, const CGUISpriteInstance& sprite_over, const CGUISpriteInstance& sprite_pressed, const CGUISpriteInstance& sprite_disabled) const; protected: + static const CStr EventNamePress; + static const CStr EventNamePressRight; + static const CStr EventNameDoublePress; + static const CStr EventNameDoublePressRight; + /** * @see IGUIObject#ResetStates() */ diff --git a/source/gui/ObjectBases/IGUIObject.cpp b/source/gui/ObjectBases/IGUIObject.cpp index 52232ee88f..4b81b73e9e 100644 --- a/source/gui/ObjectBases/IGUIObject.cpp +++ b/source/gui/ObjectBases/IGUIObject.cpp @@ -27,6 +27,10 @@ #include "scriptinterface/ScriptInterface.h" #include "soundmanager/ISoundManager.h" +const CStr IGUIObject::EventNameMouseEnter = "MouseEnter"; +const CStr IGUIObject::EventNameMouseMove = "MouseMove"; +const CStr IGUIObject::EventNameMouseLeave = "MouseLeave"; + IGUIObject::IGUIObject(CGUI& pGUI) : m_pGUI(pGUI), m_pParent(), @@ -178,18 +182,18 @@ void IGUIObject::UpdateMouseOver(IGUIObject* const& pMouseOver) if (pMouseOver == this) { if (!m_MouseHovering) - SendEvent(GUIM_MOUSE_ENTER, "mouseenter"); + SendMouseEvent(GUIM_MOUSE_ENTER,EventNameMouseEnter); m_MouseHovering = true; - SendEvent(GUIM_MOUSE_OVER, "mousemove"); + SendMouseEvent(GUIM_MOUSE_OVER, EventNameMouseMove); } else { if (m_MouseHovering) { m_MouseHovering = false; - SendEvent(GUIM_MOUSE_LEAVE, "mouseleave"); + SendMouseEvent(GUIM_MOUSE_LEAVE, EventNameMouseLeave); } } } @@ -292,7 +296,7 @@ float IGUIObject::GetBufferedZ() const return m_Z; } -void IGUIObject::RegisterScriptHandler(const CStr& Action, const CStr& Code, CGUI& pGUI) +void IGUIObject::RegisterScriptHandler(const CStr& eventName, const CStr& Code, CGUI& pGUI) { JSContext* cx = pGUI.GetScriptInterface()->GetContext(); JSAutoRequest rq(cx); @@ -303,12 +307,12 @@ void IGUIObject::RegisterScriptHandler(const CStr& Action, const CStr& Code, CGU const char* paramNames[paramCount] = { "mouse" }; // Location to report errors from - CStr CodeName = GetName()+" "+Action; + CStr CodeName = GetName() + " " + eventName; // Generate a unique name static int x = 0; char buf[64]; - sprintf_s(buf, ARRAY_SIZE(buf), "__eventhandler%d (%s)", x++, Action.c_str()); + sprintf_s(buf, ARRAY_SIZE(buf), "__eventhandler%d (%s)", x++, eventName.c_str()); JS::CompileOptions options(cx); options.setFileAndLine(CodeName.c_str(), 0); @@ -318,25 +322,25 @@ void IGUIObject::RegisterScriptHandler(const CStr& Action, const CStr& Code, CGU JS::AutoObjectVector emptyScopeChain(cx); if (!JS::CompileFunction(cx, emptyScopeChain, options, buf, paramCount, paramNames, Code.c_str(), Code.length(), &func)) { - LOGERROR("RegisterScriptHandler: Failed to compile the script for %s", Action.c_str()); + LOGERROR("RegisterScriptHandler: Failed to compile the script for %s", eventName.c_str()); return; } JS::RootedObject funcObj(cx, JS_GetFunctionObject(func)); - SetScriptHandler(Action, funcObj); + SetScriptHandler(eventName, funcObj); } -void IGUIObject::SetScriptHandler(const CStr& Action, JS::HandleObject Function) +void IGUIObject::SetScriptHandler(const CStr& eventName, JS::HandleObject Function) { if (m_ScriptHandlers.empty()) JS_AddExtraGCRootsTracer(m_pGUI.GetScriptInterface()->GetJSRuntime(), Trace, this); - m_ScriptHandlers[Action] = JS::Heap(Function); + m_ScriptHandlers[eventName] = JS::Heap(Function); } -void IGUIObject::UnsetScriptHandler(const CStr& Action) +void IGUIObject::UnsetScriptHandler(const CStr& eventName) { - std::map >::iterator it = m_ScriptHandlers.find(Action); + std::map >::iterator it = m_ScriptHandlers.find(eventName); if (it == m_ScriptHandlers.end()) return; @@ -347,25 +351,28 @@ void IGUIObject::UnsetScriptHandler(const CStr& Action) JS_RemoveExtraGCRootsTracer(m_pGUI.GetScriptInterface()->GetJSRuntime(), Trace, this); } -InReaction IGUIObject::SendEvent(EGUIMessageType type, const CStr& EventName) +InReaction IGUIObject::SendEvent(EGUIMessageType type, const CStr& eventName) { PROFILE2_EVENT("gui event"); - PROFILE2_ATTR("type: %s", EventName.c_str()); + PROFILE2_ATTR("type: %s", eventName.c_str()); PROFILE2_ATTR("object: %s", m_Name.c_str()); SGUIMessage msg(type); HandleMessage(msg); - ScriptEvent(EventName); + ScriptEvent(eventName); - return (msg.skipped ? IN_PASS : IN_HANDLED); + return msg.skipped ? IN_PASS : IN_HANDLED; } -void IGUIObject::ScriptEvent(const CStr& Action) +InReaction IGUIObject::SendMouseEvent(EGUIMessageType type, const CStr& eventName) { - std::map >::iterator it = m_ScriptHandlers.find(Action); - if (it == m_ScriptHandlers.end()) - return; + PROFILE2_EVENT("gui mouse event"); + PROFILE2_ATTR("type: %s", eventName.c_str()); + PROFILE2_ATTR("object: %s", m_Name.c_str()); + + SGUIMessage msg(type); + HandleMessage(msg); JSContext* cx = m_pGUI.GetScriptInterface()->GetContext(); JSAutoRequest rq(cx); @@ -381,23 +388,27 @@ void IGUIObject::ScriptEvent(const CStr& Action) "x", mousePos.x, "y", mousePos.y, "buttons", m_pGUI.GetMouseButtons()); - JS::AutoValueVector paramData(cx); paramData.append(mouse); - JS::RootedObject obj(cx, GetJSObject()); - JS::RootedValue handlerVal(cx, JS::ObjectValue(*it->second)); - JS::RootedValue result(cx); - bool ok = JS_CallFunctionValue(cx, obj, handlerVal, paramData, &result); - if (!ok) - { - // We have no way to propagate the script exception, so just ignore it - // and hope the caller checks JS_IsExceptionPending - } + ScriptEvent(eventName, paramData); + + return msg.skipped ? IN_PASS : IN_HANDLED; } -void IGUIObject::ScriptEvent(const CStr& Action, const JS::HandleValueArray& paramData) +void IGUIObject::ScriptEvent(const CStr& eventName) { - std::map >::iterator it = m_ScriptHandlers.find(Action); + if (m_ScriptHandlers.find(eventName) == m_ScriptHandlers.end()) + return; + + JSContext* cx = m_pGUI.GetScriptInterface()->GetContext(); + JSAutoRequest rq(cx); + JS::AutoValueVector paramData(cx); + ScriptEvent(eventName, paramData); +} + +void IGUIObject::ScriptEvent(const CStr& eventName, const JS::HandleValueArray& paramData) +{ + std::map >::iterator it = m_ScriptHandlers.find(eventName); if (it == m_ScriptHandlers.end()) return; @@ -408,7 +419,7 @@ void IGUIObject::ScriptEvent(const CStr& Action, const JS::HandleValueArray& par JS::RootedValue result(cx); if (!JS_CallFunctionValue(cx, obj, handlerVal, paramData, &result)) - JS_ReportError(cx, "Errors executing script action \"%s\"", Action.c_str()); + JS_ReportError(cx, "Errors executing script event \"%s\"", eventName.c_str()); } void IGUIObject::CreateJSObject() diff --git a/source/gui/ObjectBases/IGUIObject.h b/source/gui/ObjectBases/IGUIObject.h index faad41cf73..5810da5584 100644 --- a/source/gui/ObjectBases/IGUIObject.h +++ b/source/gui/ObjectBases/IGUIObject.h @@ -199,10 +199,15 @@ public: * Send event to this GUI object (HandleMessage and ScriptEvent) * * @param type Type of GUI message to be handled - * @param EventName String representation of event name + * @param eventName String representation of event name * @return IN_HANDLED if event was handled, or IN_PASS if skipped */ - InReaction SendEvent(EGUIMessageType type, const CStr& EventName); + InReaction SendEvent(EGUIMessageType type, const CStr& eventName); + + /** + * Same as SendEvent, but passes mouse coordinates and button state as an argument. + */ + InReaction SendMouseEvent(EGUIMessageType type, const CStr& eventName); /** * All sizes are relative to resolution, and the calculation @@ -219,11 +224,11 @@ public: /** * Set the script handler for a particular object-specific action * - * @param Action Name of action + * @param eventName Name of action * @param Code Javascript code to execute when the action occurs * @param pGUI GUI instance to associate the script with */ - void RegisterScriptHandler(const CStr& Action, const CStr& Code, CGUI& pGUI); + void RegisterScriptHandler(const CStr& eventName, const CStr& Code, CGUI& pGUI); /** * Inheriting classes may append JS functions to the JS object representing this class. @@ -373,28 +378,28 @@ protected: * Does nothing if no script has been registered for that action. * The mouse coordinates will be passed as the first argument. * - * @param Action Name of action + * @param eventName Name of action */ - void ScriptEvent(const CStr& Action); + void ScriptEvent(const CStr& eventName); /** * Execute the script for a particular action. * Does nothing if no script has been registered for that action. * - * @param Action Name of action + * @param eventName Name of action * @param paramData JS::HandleValueArray arguments to pass to the event. */ - void ScriptEvent(const CStr& Action, const JS::HandleValueArray& paramData); + void ScriptEvent(const CStr& eventName, const JS::HandleValueArray& paramData); /** * Assigns a JS function to the event name. */ - void SetScriptHandler(const CStr& Action, JS::HandleObject Function); + void SetScriptHandler(const CStr& eventName, JS::HandleObject Function); /** * Deletes an event handler assigned to the given name, if such a handler exists. */ - void UnsetScriptHandler(const CStr& Action); + void UnsetScriptHandler(const CStr& eventName); /** * Inputes the object that is currently hovered, this function @@ -456,6 +461,10 @@ private: // Variables protected: + static const CStr EventNameMouseEnter; + static const CStr EventNameMouseMove; + static const CStr EventNameMouseLeave; + // Name of object CStr m_Name; diff --git a/source/gui/ObjectTypes/CInput.cpp b/source/gui/ObjectTypes/CInput.cpp index 4ccf5477fd..7dfabd62df 100644 --- a/source/gui/ObjectTypes/CInput.cpp +++ b/source/gui/ObjectTypes/CInput.cpp @@ -37,6 +37,10 @@ extern int g_yres; +const CStr CInput::EventNameTextEdit = "TextEdit"; +const CStr CInput::EventNamePress = "Press"; +const CStr CInput::EventNameTab = "Tab"; + CInput::CInput(CGUI& pGUI) : IGUIObject(pGUI), @@ -157,7 +161,7 @@ InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) m_iBufferPos_Tail = -1; UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); return IN_HANDLED; } @@ -206,7 +210,7 @@ InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1); UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); return IN_HANDLED; } @@ -244,7 +248,7 @@ void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode) { case SDLK_TAB: { - SendEvent(GUIM_TAB, "tab"); + SendEvent(GUIM_TAB, EventNameTab); // Don't send a textedit event, because it should only // be sent if the GUI control changes the text break; @@ -275,7 +279,7 @@ void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode) } UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); break; } case SDLK_DELETE: @@ -297,7 +301,7 @@ void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode) } UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); break; } case SDLK_KP_ENTER: @@ -307,7 +311,7 @@ void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode) // otherwise a '\n' character will be added. if (!m_MultiLine) { - SendEvent(GUIM_PRESSED, "press"); + SendEvent(GUIM_PRESSED, EventNamePress); break; } @@ -343,7 +347,7 @@ void CInput::ManuallyMutableHandleKeyDownEvent(const SDL_Keycode keyCode) ++m_iBufferPos; UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); break; } } @@ -617,7 +621,7 @@ InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) sys_clipboard_free(text); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); } return IN_HANDLED; @@ -653,7 +657,7 @@ InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) { DeleteCurSelection(); UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); } } @@ -700,7 +704,7 @@ InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) UpdateBufferPositionSetting(); DeleteCurSelection(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); } UpdateAutoScroll(); return IN_HANDLED; @@ -739,7 +743,7 @@ InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) DeleteCurSelection(); } UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); return IN_HANDLED; } else if (hotkey == "text.move.left") diff --git a/source/gui/ObjectTypes/CInput.h b/source/gui/ObjectTypes/CInput.h index 724b5fe25a..9fb621641a 100644 --- a/source/gui/ObjectTypes/CInput.h +++ b/source/gui/ObjectTypes/CInput.h @@ -190,6 +190,10 @@ protected: /// If the cursor should be drawn or not. bool m_CursorVisState; + static const CStr EventNameTextEdit; + static const CStr EventNamePress; + static const CStr EventNameTab; + // Settings i32 m_BufferPosition; float m_BufferZone; diff --git a/source/gui/ObjectTypes/CList.cpp b/source/gui/ObjectTypes/CList.cpp index fcaa5f5bf9..e5dce02791 100644 --- a/source/gui/ObjectTypes/CList.cpp +++ b/source/gui/ObjectTypes/CList.cpp @@ -26,6 +26,11 @@ #include "lib/external_libraries/libsdl.h" #include "lib/timer.h" +const CStr CList::EventNameSelectionChange = "SelectionChange"; +const CStr CList::EventNameHoverChange = "HoverChange"; +const CStr CList::EventNameMouseLeftClickItem = "MouseLeftClickItem"; +const CStr CList::EventNameMouseLeftDoubleClickItem = "MouseLeftDoubleClickItem"; + CList::CList(CGUI& pGUI) : IGUIObject(pGUI), IGUITextOwner(*static_cast(this)), @@ -172,8 +177,7 @@ void CList::HandleMessage(SGUIMessage& Message) if (m_AutoScroll) UpdateAutoScroll(); - // TODO only works if lower-case, shouldn't it be made case sensitive instead? - ScriptEvent("selectionchange"); + ScriptEvent(EventNameSelectionChange); } if (Message.value == "scrollbar") @@ -204,9 +208,9 @@ void CList::HandleMessage(SGUIMessage& Message) PlaySound(m_SoundSelected); if (timer_Time() - m_LastItemClickTime < SELECT_DBLCLICK_RATE && hovered == m_PrevSelectedItem) - this->SendEvent(GUIM_MOUSE_DBLCLICK_LEFT_ITEM, "mouseleftdoubleclickitem"); + this->SendMouseEvent(GUIM_MOUSE_DBLCLICK_LEFT_ITEM, EventNameMouseLeftDoubleClickItem); else - this->SendEvent(GUIM_MOUSE_PRESS_LEFT_ITEM, "mouseleftclickitem"); + this->SendMouseEvent(GUIM_MOUSE_PRESS_LEFT_ITEM, EventNameMouseLeftClickItem); m_LastItemClickTime = timer_Time(); m_PrevSelectedItem = hovered; @@ -219,7 +223,7 @@ void CList::HandleMessage(SGUIMessage& Message) break; SetSetting("hovered", -1, true); - ScriptEvent("hoverchange"); + ScriptEvent(EventNameHoverChange); break; } @@ -230,7 +234,7 @@ void CList::HandleMessage(SGUIMessage& Message) break; SetSetting("hovered", hovered, true); - ScriptEvent("hoverchange"); + ScriptEvent(EventNameHoverChange); break; } diff --git a/source/gui/ObjectTypes/CList.h b/source/gui/ObjectTypes/CList.h index 3bcfbedd3d..731a1a6858 100644 --- a/source/gui/ObjectTypes/CList.h +++ b/source/gui/ObjectTypes/CList.h @@ -138,6 +138,11 @@ protected: CGUIList m_ListData; private: + static const CStr EventNameSelectionChange; + static const CStr EventNameHoverChange; + static const CStr EventNameMouseLeftClickItem; + static const CStr EventNameMouseLeftDoubleClickItem; + // Whether the list's items have been modified since last handling a message. bool m_Modified; diff --git a/source/gui/ObjectTypes/CMiniMap.cpp b/source/gui/ObjectTypes/CMiniMap.cpp index d2f0e8669a..3808df4052 100644 --- a/source/gui/ObjectTypes/CMiniMap.cpp +++ b/source/gui/ObjectTypes/CMiniMap.cpp @@ -64,6 +64,8 @@ static unsigned int ScaleColor(unsigned int color, float x) return (0xff000000 | b | g<<8 | r<<16); } +const CStr CMiniMap::EventNameWorldClick = "WorldClick"; + CMiniMap::CMiniMap(CGUI& pGUI) : IGUIObject(pGUI), m_TerrainTexture(0), m_TerrainData(0), m_MapSize(0), m_Terrain(0), m_TerrainDirty(true), m_MapScale(1.f), @@ -249,7 +251,7 @@ void CMiniMap::FireWorldClickEvent(int UNUSED(button), int UNUSED(clicks)) JS::AutoValueVector paramData(cx); paramData.append(coords); - ScriptEvent("worldclick", paramData); + ScriptEvent(EventNameWorldClick, paramData); } // This sets up and draws the rectangle on the minimap diff --git a/source/gui/ObjectTypes/CMiniMap.h b/source/gui/ObjectTypes/CMiniMap.h index 7278e43262..4b90e4e090 100644 --- a/source/gui/ObjectTypes/CMiniMap.h +++ b/source/gui/ObjectTypes/CMiniMap.h @@ -58,6 +58,8 @@ protected: void FireWorldClickEvent(int button, int clicks); + static const CStr EventNameWorldClick; + // the terrain we are mini-mapping const CTerrain* m_Terrain; diff --git a/source/gui/ObjectTypes/COList.cpp b/source/gui/ObjectTypes/COList.cpp index cdf4401e84..cab8cc51e9 100644 --- a/source/gui/ObjectTypes/COList.cpp +++ b/source/gui/ObjectTypes/COList.cpp @@ -29,6 +29,8 @@ const float SORT_SPRITE_DIM = 16.0f; const CPos COLUMN_SHIFT = CPos(0, 4); +const CStr COList::EventNameSelectionColumnChange = "SelectionColumnChange"; + COList::COList(CGUI& pGUI) : CList(pGUI), m_SpriteHeading(), @@ -165,7 +167,7 @@ void COList::HandleMessage(SGUIMessage& Message) else SetSetting("selected_column_order", -m_SelectedColumnOrder, true); - ScriptEvent("selectioncolumnchange"); + ScriptEvent(EventNameSelectionColumnChange); PlaySound(m_SoundSelected); return; } diff --git a/source/gui/ObjectTypes/COList.h b/source/gui/ObjectTypes/COList.h index d1412862c6..a27f919627 100644 --- a/source/gui/ObjectTypes/COList.h +++ b/source/gui/ObjectTypes/COList.h @@ -83,6 +83,8 @@ protected: CGUISpriteInstance m_SpriteNotSorted; private: + static const CStr EventNameSelectionColumnChange; + // Width of space available for columns float m_TotalAvailableColumnWidth; float m_HeadingHeight; diff --git a/source/gui/ObjectTypes/CSlider.cpp b/source/gui/ObjectTypes/CSlider.cpp index 1c39d4465c..02636f8439 100644 --- a/source/gui/ObjectTypes/CSlider.cpp +++ b/source/gui/ObjectTypes/CSlider.cpp @@ -22,6 +22,8 @@ #include "gui/CGUI.h" #include "maths/MathUtil.h" +const CStr CSlider::EventNameValueChange = "ValueChange"; + CSlider::CSlider(CGUI& pGUI) : IGUIObject(pGUI), m_IsPressed(), @@ -127,7 +129,7 @@ void CSlider::Draw() void CSlider::UpdateValue() { SetSetting("value", m_Value, true); - ScriptEvent("valuechange"); + ScriptEvent(EventNameValueChange); } CRect CSlider::GetButtonRect() const diff --git a/source/gui/ObjectTypes/CSlider.h b/source/gui/ObjectTypes/CSlider.h index 6ed68da247..750bd28e2d 100644 --- a/source/gui/ObjectTypes/CSlider.h +++ b/source/gui/ObjectTypes/CSlider.h @@ -30,6 +30,7 @@ public: virtual ~CSlider(); protected: + static const CStr EventNameValueChange; /** * @see IGUIObject#HandleMessage() diff --git a/source/gui/Scripting/JSInterface_IGUIObject.cpp b/source/gui/Scripting/JSInterface_IGUIObject.cpp index 7876dcb038..1ee82d216b 100644 --- a/source/gui/Scripting/JSInterface_IGUIObject.cpp +++ b/source/gui/Scripting/JSInterface_IGUIObject.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -82,7 +82,7 @@ bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Handle // Use onWhatever to access event handlers if (propName.substr(0, 2) == "on") { - CStr eventName(CStr(propName.substr(2)).LowerCase()); + CStr eventName(propName.substr(2)); std::map>::iterator it = e->m_ScriptHandlers.find(eventName); if (it == e->m_ScriptHandlers.end()) vp.setNull(); @@ -163,7 +163,7 @@ bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Handle return result.fail(JSMSG_NOT_FUNCTION); } - CStr eventName(CStr(propName.substr(2)).LowerCase()); + CStr eventName(propName.substr(2)); e->SetScriptHandler(eventName, vpObj); return result.succeed(); @@ -194,7 +194,7 @@ bool JSI_IGUIObject::deleteProperty(JSContext* cx, JS::HandleObject obj, JS::Han // event handlers if (propName.substr(0, 2) == "on") { - CStr eventName(CStr(propName.substr(2)).LowerCase()); + CStr eventName(propName.substr(2)); e->UnsetScriptHandler(eventName); return result.succeed(); } diff --git a/source/ps/Game.cpp b/source/ps/Game.cpp index b0f713a9db..670e6da687 100644 --- a/source/ps/Game.cpp +++ b/source/ps/Game.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -59,6 +59,8 @@ extern GameLoopState* g_AtlasGameLoop; **/ CGame *g_Game=NULL; +const CStr CGame::EventNameSimulationUpdate = "SimulationUpdate"; + /** * Constructor * @@ -401,7 +403,7 @@ void CGame::Update(const double deltaRealTime, bool doInterpolate) { { PROFILE3("gui sim update"); - g_GUI->SendEventToAll("SimulationUpdate"); + g_GUI->SendEventToAll(EventNameSimulationUpdate); } GetView()->GetLOSTexture().MakeDirty(); diff --git a/source/ps/Game.h b/source/ps/Game.h index c11e3e1026..c5e04d737a 100644 --- a/source/ps/Game.h +++ b/source/ps/Game.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -203,6 +203,8 @@ public: { return *m_ReplayLogger; } private: + static const CStr EventNameSimulationUpdate; + void RegisterInit(const JS::HandleValue attribs, const std::string& savedState); IReplayLogger* m_ReplayLogger; diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index 60e6e0a34c..5ebc08f1d9 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -113,6 +113,8 @@ shared_ptr g_ScriptRuntime; static const int SANE_TEX_QUALITY_DEFAULT = 5; // keep in sync with code +static const CStr g_EventNameGameLoadProgress = "GameLoadProgress"; + bool g_InDevelopmentCopy; bool g_CheckedIfInDevelopmentCopy = false; @@ -193,7 +195,7 @@ void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task) scriptInterface.ToJSVal(cx, &valPendingTask, pending_task); paramData.append(valPendingTask); - g_GUI->SendEventToAll("GameLoadProgress", paramData); + g_GUI->SendEventToAll(g_EventNameGameLoadProgress, paramData); } bool ShouldRender() diff --git a/source/ps/XML/XeroXMB.h b/source/ps/XML/XeroXMB.h index d0c9ac0a02..7ecee9b5b8 100644 --- a/source/ps/XML/XeroXMB.h +++ b/source/ps/XML/XeroXMB.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -17,9 +17,6 @@ /* Xeromyces - XMB reading library -*/ - -/* Brief outline: @@ -33,10 +30,6 @@ Main limitations: considered identical. * Tries to avoid using strings - you usually have to load the numeric IDs and use them instead. - * Case-sensitive (but converts all element/attribute names in - the XML file to lowercase, so you only have to be careful in - the code) - Theoretical file structure: diff --git a/source/simulation2/system/ReplayTurnManager.cpp b/source/simulation2/system/ReplayTurnManager.cpp index d5a7884fd8..82b621b621 100644 --- a/source/simulation2/system/ReplayTurnManager.cpp +++ b/source/simulation2/system/ReplayTurnManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -24,6 +24,9 @@ #include "ps/Util.h" #include "simulation2/Simulation2.h" +const CStr CReplayTurnManager::EventNameReplayFinished = "ReplayFinished"; +const CStr CReplayTurnManager::EventNameReplayOutOfSync = "ReplayOutOfSync"; + CReplayTurnManager::CReplayTurnManager(CSimulation2& simulation, IReplayLogger& replay) : CLocalTurnManager(simulation, replay) { @@ -57,7 +60,7 @@ void CReplayTurnManager::StoreFinalReplayTurn(u32 turn) void CReplayTurnManager::NotifyFinishedUpdate(u32 turn) { if (turn == 1 && m_FinalTurn == 0) - g_GUI->SendEventToAll("ReplayFinished"); + g_GUI->SendEventToAll(EventNameReplayFinished); if (turn > m_FinalTurn) return; @@ -99,7 +102,7 @@ void CReplayTurnManager::NotifyFinishedUpdate(u32 turn) scriptInterface.ToJSVal(cx, &expectedHashVal, expectedHash); paramData.append(expectedHashVal); - g_GUI->SendEventToAll("ReplayOutOfSync", paramData); + g_GUI->SendEventToAll(EventNameReplayOutOfSync, paramData); } void CReplayTurnManager::DoTurn(u32 turn) @@ -120,5 +123,5 @@ void CReplayTurnManager::DoTurn(u32 turn) } if (turn == m_FinalTurn) - g_GUI->SendEventToAll("ReplayFinished"); + g_GUI->SendEventToAll(EventNameReplayFinished); } diff --git a/source/simulation2/system/ReplayTurnManager.h b/source/simulation2/system/ReplayTurnManager.h index 1c3fd74fef..d1b1ce394e 100644 --- a/source/simulation2/system/ReplayTurnManager.h +++ b/source/simulation2/system/ReplayTurnManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -41,6 +41,9 @@ private: void DoTurn(u32 turn); + static const CStr EventNameReplayFinished; + static const CStr EventNameReplayOutOfSync; + // Contains the commands of every player on each turn std::map>> m_ReplayCommands; diff --git a/source/simulation2/system/TurnManager.cpp b/source/simulation2/system/TurnManager.cpp index 9f7527b905..3327a98fad 100644 --- a/source/simulation2/system/TurnManager.cpp +++ b/source/simulation2/system/TurnManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -40,6 +40,8 @@ const int COMMAND_DELAY = 2; #define NETTURN_LOG(...) #endif +const CStr CTurnManager::EventNameSavegameLoaded = "SavegameLoaded"; + CTurnManager::CTurnManager(CSimulation2& simulation, u32 defaultTurnLength, int clientId, IReplayLogger& replay) : m_Simulation2(simulation), m_CurrentTurn(0), m_ReadyTurn(1), m_TurnLength(defaultTurnLength), m_PlayerId(-1), m_ClientId(clientId), m_DeltaSimTime(0), m_HasSyncError(false), m_Replay(replay), @@ -357,7 +359,7 @@ void CTurnManager::QuickLoad() JS::AutoValueArray<1> paramData(cx); paramData[0].set(quickSaveMetadataClone); - g_GUI->SendEventToAll("SavegameLoaded", paramData); + g_GUI->SendEventToAll(EventNameSavegameLoaded, paramData); LOGMESSAGERENDER("Quickloaded game"); } diff --git a/source/simulation2/system/TurnManager.h b/source/simulation2/system/TurnManager.h index 10bf4372cd..102e3cbab0 100644 --- a/source/simulation2/system/TurnManager.h +++ b/source/simulation2/system/TurnManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -18,21 +18,22 @@ #ifndef INCLUDED_TURNMANAGER #define INCLUDED_TURNMANAGER +#include "ps/CStr.h" #include "simulation2/helpers/SimulationCommand.h" #include #include #include +class CSimulationMessage; +class CSimulation2; +class IReplayLogger; + extern const u32 DEFAULT_TURN_LENGTH_SP; extern const u32 DEFAULT_TURN_LENGTH_MP; extern const int COMMAND_DELAY; -class CSimulationMessage; -class CSimulation2; -class IReplayLogger; - /** * This file defines the base class of the turn managers for clients, local games and replays. * The basic idea of our turn managing system across a network is as in this article: @@ -186,6 +187,8 @@ protected: u32 m_FinalTurn; private: + static const CStr EventNameSavegameLoaded; + size_t m_TimeWarpNumTurns; // 0 if disabled std::list m_TimeWarpStates; std::string m_QuickSaveState; // TODO: should implement a proper disk-based quicksave system