Index: ps/trunk/binaries/data/mods/public/gui/replaymenu/replay_menu.xml =================================================================== --- ps/trunk/binaries/data/mods/public/gui/replaymenu/replay_menu.xml +++ ps/trunk/binaries/data/mods/public/gui/replaymenu/replay_menu.xml @@ -62,7 +62,7 @@ displayReplayDetails(); displayReplayList(); - startReplay(); + startReplay(); Index: ps/trunk/binaries/data/mods/public/gui/session/session.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/session/session.js +++ ps/trunk/binaries/data/mods/public/gui/session/session.js @@ -688,9 +688,9 @@ 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) Index: ps/trunk/source/gui/CGUI.h =================================================================== --- ps/trunk/source/gui/CGUI.h +++ ps/trunk/source/gui/CGUI.h @@ -74,17 +74,17 @@ /** * 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 @@ */ 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 Index: ps/trunk/source/gui/CGUI.cpp =================================================================== --- ps/trunk/source/gui/CGUI.cpp +++ ps/trunk/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 @@ 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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ { 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 @@ 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 @@ SGUIMessage msg(GUIM_LOAD); m_BaseObject.RecurseObject(nullptr, &IGUIObject::HandleMessage, msg); - SendEventToAll("load"); + SendEventToAll(EventNameLoad); } //=================================================================== @@ -677,9 +677,8 @@ // 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) { Index: ps/trunk/source/gui/GUIManager.h =================================================================== --- ps/trunk/source/gui/GUIManager.h +++ ps/trunk/source/gui/GUIManager.h @@ -161,6 +161,8 @@ shared_ptr callbackFunction; }; + const static CStr EventNameWindowResized; + shared_ptr top() const; shared_ptr m_ScriptRuntime; Index: ps/trunk/source/gui/GUIManager.cpp =================================================================== --- ps/trunk/source/gui/GUIManager.cpp +++ ps/trunk/source/gui/GUIManager.cpp @@ -31,6 +31,8 @@ CGUIManager* g_GUI = nullptr; +const CStr CGUIManager::EventNameWindowResized = "WindowResized"; + // General TODOs: // @@ -377,7 +379,7 @@ for (const SGUIPage& p : pageStack) { p.gui->UpdateResolution(); - p.gui->SendEventToAll("WindowResized"); + p.gui->SendEventToAll(EventNameWindowResized); } } Index: ps/trunk/source/gui/ObjectBases/IGUIButtonBehavior.h =================================================================== --- ps/trunk/source/gui/ObjectBases/IGUIButtonBehavior.h +++ ps/trunk/source/gui/ObjectBases/IGUIButtonBehavior.h @@ -60,6 +60,11 @@ 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() */ Index: ps/trunk/source/gui/ObjectBases/IGUIButtonBehavior.cpp =================================================================== --- ps/trunk/source/gui/ObjectBases/IGUIButtonBehavior.cpp +++ ps/trunk/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 @@ // 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 @@ } 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 @@ // 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 @@ // 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; Index: ps/trunk/source/gui/ObjectBases/IGUIObject.h =================================================================== --- ps/trunk/source/gui/ObjectBases/IGUIObject.h +++ ps/trunk/source/gui/ObjectBases/IGUIObject.h @@ -199,10 +199,15 @@ * 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 @@ /** * 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 @@ * 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 @@ // Variables protected: + static const CStr EventNameMouseEnter; + static const CStr EventNameMouseMove; + static const CStr EventNameMouseLeave; + // Name of object CStr m_Name; Index: ps/trunk/source/gui/ObjectBases/IGUIObject.cpp =================================================================== --- ps/trunk/source/gui/ObjectBases/IGUIObject.cpp +++ ps/trunk/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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ "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& eventName) +{ + 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& Action, const JS::HandleValueArray& paramData) +void IGUIObject::ScriptEvent(const CStr& eventName, const JS::HandleValueArray& paramData) { - std::map >::iterator it = m_ScriptHandlers.find(Action); + std::map >::iterator it = m_ScriptHandlers.find(eventName); if (it == m_ScriptHandlers.end()) return; @@ -408,7 +419,7 @@ 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() Index: ps/trunk/source/gui/ObjectTypes/CInput.h =================================================================== --- ps/trunk/source/gui/ObjectTypes/CInput.h +++ ps/trunk/source/gui/ObjectTypes/CInput.h @@ -190,6 +190,10 @@ /// 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; Index: ps/trunk/source/gui/ObjectTypes/CInput.cpp =================================================================== --- ps/trunk/source/gui/ObjectTypes/CInput.cpp +++ ps/trunk/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 @@ m_iBufferPos_Tail = -1; UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); return IN_HANDLED; } @@ -206,7 +210,7 @@ UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1); UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); return IN_HANDLED; } @@ -244,7 +248,7 @@ { 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 @@ } UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); break; } case SDLK_DELETE: @@ -297,7 +301,7 @@ } UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); break; } case SDLK_KP_ENTER: @@ -307,7 +311,7 @@ // otherwise a '\n' character will be added. if (!m_MultiLine) { - SendEvent(GUIM_PRESSED, "press"); + SendEvent(GUIM_PRESSED, EventNamePress); break; } @@ -343,7 +347,7 @@ ++m_iBufferPos; UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); break; } } @@ -617,7 +621,7 @@ sys_clipboard_free(text); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); } return IN_HANDLED; @@ -653,7 +657,7 @@ { DeleteCurSelection(); UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); } } @@ -700,7 +704,7 @@ UpdateBufferPositionSetting(); DeleteCurSelection(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); } UpdateAutoScroll(); return IN_HANDLED; @@ -739,7 +743,7 @@ DeleteCurSelection(); } UpdateAutoScroll(); - SendEvent(GUIM_TEXTEDIT, "textedit"); + SendEvent(GUIM_TEXTEDIT, EventNameTextEdit); return IN_HANDLED; } else if (hotkey == "text.move.left") Index: ps/trunk/source/gui/ObjectTypes/CList.h =================================================================== --- ps/trunk/source/gui/ObjectTypes/CList.h +++ ps/trunk/source/gui/ObjectTypes/CList.h @@ -138,6 +138,11 @@ 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; Index: ps/trunk/source/gui/ObjectTypes/CList.cpp =================================================================== --- ps/trunk/source/gui/ObjectTypes/CList.cpp +++ ps/trunk/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 @@ 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 @@ 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 @@ break; SetSetting("hovered", -1, true); - ScriptEvent("hoverchange"); + ScriptEvent(EventNameHoverChange); break; } @@ -230,7 +234,7 @@ break; SetSetting("hovered", hovered, true); - ScriptEvent("hoverchange"); + ScriptEvent(EventNameHoverChange); break; } Index: ps/trunk/source/gui/ObjectTypes/CMiniMap.h =================================================================== --- ps/trunk/source/gui/ObjectTypes/CMiniMap.h +++ ps/trunk/source/gui/ObjectTypes/CMiniMap.h @@ -58,6 +58,8 @@ void FireWorldClickEvent(int button, int clicks); + static const CStr EventNameWorldClick; + // the terrain we are mini-mapping const CTerrain* m_Terrain; Index: ps/trunk/source/gui/ObjectTypes/CMiniMap.cpp =================================================================== --- ps/trunk/source/gui/ObjectTypes/CMiniMap.cpp +++ ps/trunk/source/gui/ObjectTypes/CMiniMap.cpp @@ -64,6 +64,8 @@ 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 @@ JS::AutoValueVector paramData(cx); paramData.append(coords); - ScriptEvent("worldclick", paramData); + ScriptEvent(EventNameWorldClick, paramData); } // This sets up and draws the rectangle on the minimap Index: ps/trunk/source/gui/ObjectTypes/COList.h =================================================================== --- ps/trunk/source/gui/ObjectTypes/COList.h +++ ps/trunk/source/gui/ObjectTypes/COList.h @@ -83,6 +83,8 @@ CGUISpriteInstance m_SpriteNotSorted; private: + static const CStr EventNameSelectionColumnChange; + // Width of space available for columns float m_TotalAvailableColumnWidth; float m_HeadingHeight; Index: ps/trunk/source/gui/ObjectTypes/COList.cpp =================================================================== --- ps/trunk/source/gui/ObjectTypes/COList.cpp +++ ps/trunk/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 @@ else SetSetting("selected_column_order", -m_SelectedColumnOrder, true); - ScriptEvent("selectioncolumnchange"); + ScriptEvent(EventNameSelectionColumnChange); PlaySound(m_SoundSelected); return; } Index: ps/trunk/source/gui/ObjectTypes/CSlider.h =================================================================== --- ps/trunk/source/gui/ObjectTypes/CSlider.h +++ ps/trunk/source/gui/ObjectTypes/CSlider.h @@ -30,6 +30,7 @@ virtual ~CSlider(); protected: + static const CStr EventNameValueChange; /** * @see IGUIObject#HandleMessage() Index: ps/trunk/source/gui/ObjectTypes/CSlider.cpp =================================================================== --- ps/trunk/source/gui/ObjectTypes/CSlider.cpp +++ ps/trunk/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::UpdateValue() { SetSetting("value", m_Value, true); - ScriptEvent("valuechange"); + ScriptEvent(EventNameValueChange); } CRect CSlider::GetButtonRect() const Index: ps/trunk/source/gui/Scripting/JSInterface_IGUIObject.cpp =================================================================== --- ps/trunk/source/gui/Scripting/JSInterface_IGUIObject.cpp +++ ps/trunk/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 @@ // 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 @@ 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 @@ // 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(); } Index: ps/trunk/source/ps/Game.h =================================================================== --- ps/trunk/source/ps/Game.h +++ ps/trunk/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 @@ { return *m_ReplayLogger; } private: + static const CStr EventNameSimulationUpdate; + void RegisterInit(const JS::HandleValue attribs, const std::string& savedState); IReplayLogger* m_ReplayLogger; Index: ps/trunk/source/ps/Game.cpp =================================================================== --- ps/trunk/source/ps/Game.cpp +++ ps/trunk/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 @@ **/ CGame *g_Game=NULL; +const CStr CGame::EventNameSimulationUpdate = "SimulationUpdate"; + /** * Constructor * @@ -401,7 +403,7 @@ { { PROFILE3("gui sim update"); - g_GUI->SendEventToAll("SimulationUpdate"); + g_GUI->SendEventToAll(EventNameSimulationUpdate); } GetView()->GetLOSTexture().MakeDirty(); Index: ps/trunk/source/ps/GameSetup/GameSetup.cpp =================================================================== --- ps/trunk/source/ps/GameSetup/GameSetup.cpp +++ ps/trunk/source/ps/GameSetup/GameSetup.cpp @@ -113,6 +113,8 @@ 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 @@ scriptInterface.ToJSVal(cx, &valPendingTask, pending_task); paramData.append(valPendingTask); - g_GUI->SendEventToAll("GameLoadProgress", paramData); + g_GUI->SendEventToAll(g_EventNameGameLoadProgress, paramData); } bool ShouldRender() Index: ps/trunk/source/ps/XML/XeroXMB.h =================================================================== --- ps/trunk/source/ps/XML/XeroXMB.h +++ ps/trunk/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 @@ 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: Index: ps/trunk/source/simulation2/system/ReplayTurnManager.h =================================================================== --- ps/trunk/source/simulation2/system/ReplayTurnManager.h +++ ps/trunk/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 @@ 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; Index: ps/trunk/source/simulation2/system/ReplayTurnManager.cpp =================================================================== --- ps/trunk/source/simulation2/system/ReplayTurnManager.cpp +++ ps/trunk/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::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 @@ 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 @@ } if (turn == m_FinalTurn) - g_GUI->SendEventToAll("ReplayFinished"); + g_GUI->SendEventToAll(EventNameReplayFinished); } Index: ps/trunk/source/simulation2/system/TurnManager.h =================================================================== --- ps/trunk/source/simulation2/system/TurnManager.h +++ ps/trunk/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 @@ 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 Index: ps/trunk/source/simulation2/system/TurnManager.cpp =================================================================== --- ps/trunk/source/simulation2/system/TurnManager.cpp +++ ps/trunk/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 @@ #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 @@ JS::AutoValueArray<1> paramData(cx); paramData[0].set(quickSaveMetadataClone); - g_GUI->SendEventToAll("SavegameLoaded", paramData); + g_GUI->SendEventToAll(EventNameSavegameLoaded, paramData); LOGMESSAGERENDER("Quickloaded game"); }