Pass arbitrary arguments to GUI events / SendEventToAll and remove loading screen progess workaround, refs D1716, 6d792365aa, bd3bd084c0, 4b1297b328, db5d4bb5f1.

Differential Revision: https://code.wildfiregames.com/D1754
Reviewed By: Itms
Comments By: leper
This was SVN commit r22515.
This commit is contained in:
elexis 2019-07-19 21:15:04 +00:00
parent 498d58e24d
commit feb88a337a
14 changed files with 99 additions and 37 deletions

View File

@ -58,25 +58,28 @@ function init(data)
} }
Engine.GetGUIObjectByName("progressText").caption = ""; Engine.GetGUIObjectByName("progressText").caption = "";
Engine.GetGUIObjectByName("progressbar").caption = 0;
let progressbar = Engine.GetGUIObjectByName("progressbar");
progressbar.caption = 0;
progressbar.onGameLoadProgress = displayProgress;
Engine.GetGUIObjectByName("quoteText").caption = translate(pickRandom(Engine.ReadFileLines(g_QuotesFile).filter(line => line))); Engine.GetGUIObjectByName("quoteText").caption = translate(pickRandom(Engine.ReadFileLines(g_QuotesFile).filter(line => line)));
} }
function displayProgress() function displayProgress(progression, description)
{ {
// Make the progessbar finish a little early so that the user can actually see it finish // Make the progessbar finish a little early so that the user can actually see it finish
if (g_Progress >= 100) if (progression >= 100)
return; return;
// Show 100 when it is really 99 // Show 100 when it is really 99
let progress = g_Progress + 1; let progress = progression + 1;
Engine.GetGUIObjectByName("progressbar").caption = progress; // display current progress Engine.GetGUIObjectByName("progressbar").caption = progress; // display current progress
Engine.GetGUIObjectByName("progressText").caption = progress + "%"; Engine.GetGUIObjectByName("progressText").caption = progress + "%";
// Displays detailed loading info rather than a percent // Displays detailed loading info rather than a percent
// Engine.GetGUIObjectByName("progressText").caption = g_LoadDescription; // display current progess details // Engine.GetGUIObjectByName("progressText").caption = description;
// Keep curved right edge of progress bar in sync with the rest of the progress bar // Keep curved right edge of progress bar in sync with the rest of the progress bar
let middle = Engine.GetGUIObjectByName("progressbar"); let middle = Engine.GetGUIObjectByName("progressbar");

View File

@ -21,7 +21,6 @@
> >
<object name="progressbar_left" size="-8 0 8 100%" type="image" sprite="LoadingProgressBarLeft"/> <object name="progressbar_left" size="-8 0 8 100%" type="image" sprite="LoadingProgressBarLeft"/>
<object name="progressbar_right" size="8 0 24 100%" type="image" sprite="LoadingProgressBarRight"/> <object name="progressbar_right" size="8 0 24 100%" type="image" sprite="LoadingProgressBarRight"/>
<action on="Progress">displayProgress();</action>
<object name="progressText" size="0 0 100% 100%" type="text" style="LoadingBarText"/> <object name="progressText" size="0 0 100% 100%" type="text" style="LoadingBarText"/>
</object> </object>
</object> </object>

View File

@ -726,11 +726,13 @@ function onNetworkOutOfSync(msg)
); );
} }
function onReplayOutOfSync() function onReplayOutOfSync(turn, hash, expectedHash)
{ {
messageBox( messageBox(
500, 140, 500, 140,
translate("Out-Of-Sync error!") + "\n" + sprintf(translate("Out-Of-Sync error on turn %(turn)s."), {
"turn": turn
}) + "\n" +
// Translation: This is shown if replay is out of sync // Translation: This is shown if replay is out of sync
translateWithContext("Out-Of-Sync", "The current game state is different from the original game state."), translateWithContext("Out-Of-Sync", "The current game state is different from the original game state."),
translate("Out of Sync") translate("Out of Sync")

View File

@ -24,7 +24,7 @@
</action> </action>
<action on="ReplayOutOfSync"> <action on="ReplayOutOfSync">
onReplayOutOfSync(); onReplayOutOfSync(arguments[0], arguments[1], arguments[2]);
</action> </action>
<!-- Hotkeys won't work properly unless outside menu --> <!-- Hotkeys won't work properly unless outside menu -->

View File

@ -274,8 +274,12 @@ void CGUI::SendEventToAll(const CStr& EventName)
// (sending events here) wasn't converting to lower case, // (sending events here) wasn't converting to lower case,
// leading to a similar problem. // leading to a similar problem.
// now fixed; case is irrelevant since all are converted to lower. // now fixed; case is irrelevant since all are converted to lower.
GUI<CStr>::RecurseObject(0, m_BaseObject, GUI<CStr>::RecurseObject(0, m_BaseObject, &IGUIObject::ScriptEvent, EventName.LowerCase());
&IGUIObject::ScriptEvent, EventName.LowerCase()); }
void CGUI::SendEventToAll(const CStr& EventName, JS::HandleValueArray paramData)
{
GUI<CStr>::RecurseObject(0, m_BaseObject, &IGUIObject::ScriptEvent, EventName.LowerCase(), paramData);
} }
CGUI::CGUI(const shared_ptr<ScriptRuntime>& runtime) CGUI::CGUI(const shared_ptr<ScriptRuntime>& runtime)

View File

@ -96,6 +96,14 @@ public:
*/ */
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 paramData JS::HandleValueArray storing the arguments passed to the event handler.
*/
void SendEventToAll(const CStr& EventName, JS::HandleValueArray paramData);
/** /**
* Displays the whole GUI * Displays the whole GUI
*/ */

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2018 Wildfire Games. /* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -357,6 +357,11 @@ void CGUIManager::SendEventToAll(const CStr& eventName) const
top()->SendEventToAll(eventName); top()->SendEventToAll(eventName);
} }
void CGUIManager::SendEventToAll(const CStr& eventName, JS::HandleValueArray paramData) const
{
top()->SendEventToAll(eventName, paramData);
}
void CGUIManager::TickObjects() void CGUIManager::TickObjects()
{ {
PROFILE3("gui tick"); PROFILE3("gui tick");

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2018 Wildfire Games. /* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -111,6 +111,7 @@ public:
* See CGUI::SendEventToAll; applies to the currently active page. * See CGUI::SendEventToAll; applies to the currently active page.
*/ */
void SendEventToAll(const CStr& eventName) const; void SendEventToAll(const CStr& eventName) const;
void SendEventToAll(const CStr& eventName, JS::HandleValueArray paramData) const;
/** /**
* See CGUI::TickObjects; applies to @em all loaded pages. * See CGUI::TickObjects; applies to @em all loaded pages.

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2015 Wildfire Games. /* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -222,6 +222,7 @@ private:
typedef void (IGUIObject::*void_Object_pFunction_argT)(const T& arg); typedef void (IGUIObject::*void_Object_pFunction_argT)(const T& arg);
typedef void (IGUIObject::*void_Object_pFunction_argRefT)(T& arg); typedef void (IGUIObject::*void_Object_pFunction_argRefT)(T& arg);
typedef void (IGUIObject::*void_Object_pFunction)(); typedef void (IGUIObject::*void_Object_pFunction)();
typedef void (IGUIObject::*void_Object_pFunction_argTJS)(const T& arg, JS::HandleValueArray paramData);
/** /**
* If you want to call a IGUIObject-function * If you want to call a IGUIObject-function
@ -279,6 +280,18 @@ private:
RecurseObject(RR, obj, pFunc, Argument); RecurseObject(RR, obj, pFunc, Argument);
} }
static void RecurseObject(int RR, IGUIObject* pObject, void_Object_pFunction_argTJS pFunc, const T& Argument, JS::HandleValueArray paramData)
{
if (CheckIfRestricted(RR, pObject))
return;
(pObject->*pFunc)(Argument, paramData);
// Iterate children
for (IGUIObject* const& obj : *pObject)
RecurseObject(RR, obj, pFunc, Argument, paramData);
}
/** /**
* With no argument. * With no argument.
* *

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2016 Wildfire Games. /* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -450,7 +450,7 @@ InReaction IGUIObject::SendEvent(EGUIMessageType type, const CStr& EventName)
void IGUIObject::ScriptEvent(const CStr& Action) void IGUIObject::ScriptEvent(const CStr& Action)
{ {
std::map<CStr, JS::Heap<JSObject*>>::iterator it = m_ScriptHandlers.find(Action); std::map<CStr, JS::Heap<JSObject*> >::iterator it = m_ScriptHandlers.find(Action);
if (it == m_ScriptHandlers.end()) if (it == m_ScriptHandlers.end())
return; return;
@ -477,24 +477,20 @@ void IGUIObject::ScriptEvent(const CStr& Action)
} }
} }
void IGUIObject::ScriptEvent(const CStr& Action, JS::HandleValue Argument) void IGUIObject::ScriptEvent(const CStr& Action, JS::HandleValueArray paramData)
{ {
std::map<CStr, JS::Heap<JSObject*>>::iterator it = m_ScriptHandlers.find(Action); std::map<CStr, JS::Heap<JSObject*> >::iterator it = m_ScriptHandlers.find(Action);
if (it == m_ScriptHandlers.end()) if (it == m_ScriptHandlers.end())
return; return;
JSContext* cx = m_pGUI->GetScriptInterface()->GetContext(); JSContext* cx = m_pGUI->GetScriptInterface()->GetContext();
JSAutoRequest rq(cx); JSAutoRequest rq(cx);
JS::AutoValueVector paramData(cx);
paramData.append(Argument.get());
JS::RootedObject obj(cx, GetJSObject()); JS::RootedObject obj(cx, GetJSObject());
JS::RootedValue handlerVal(cx, JS::ObjectValue(*it->second)); JS::RootedValue handlerVal(cx, JS::ObjectValue(*it->second));
JS::RootedValue result(cx); JS::RootedValue result(cx);
bool ok = JS_CallFunctionValue(cx, obj, handlerVal, paramData, &result);
if (!ok) 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 action \"%s\"", Action.c_str());
}
} }
JSObject* IGUIObject::GetJSObject() JSObject* IGUIObject::GetJSObject()

View File

@ -400,9 +400,9 @@ protected:
* Does nothing if no script has been registered for that action. * Does nothing if no script has been registered for that action.
* *
* @param Action Name of action * @param Action Name of action
* @param Argument Argument to pass to action * @param paramData JS::HandleValueArray arguments to pass to the event.
*/ */
void ScriptEvent(const CStr& Action, JS::HandleValue Argument); void ScriptEvent(const CStr& Action, JS::HandleValueArray paramData);
void SetScriptHandler(const CStr& Action, JS::HandleObject Function); void SetScriptHandler(const CStr& Action, JS::HandleObject Function);

View File

@ -246,7 +246,11 @@ void CMiniMap::FireWorldClickEvent(int UNUSED(button), int UNUSED(clicks))
g_GUI->GetActiveGUI()->GetScriptInterface()->Eval("({})", &coords); g_GUI->GetActiveGUI()->GetScriptInterface()->Eval("({})", &coords);
g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords, "x", x, false); g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords, "x", x, false);
g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords, "z", z, false); g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords, "z", z, false);
ScriptEvent("worldclick", coords);
JS::AutoValueVector paramData(cx);
paramData.append(coords);
ScriptEvent("worldclick", paramData);
} }
// This sets up and draws the rectangle on the minimap // This sets up and draws the rectangle on the minimap

View File

@ -183,9 +183,19 @@ retry:
// display progress / description in loading screen // display progress / description in loading screen
void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task) void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task)
{ {
g_GUI->GetActiveGUI()->GetScriptInterface()->SetGlobal("g_Progress", percent, true, false, true); const ScriptInterface& scriptInterface = *(g_GUI->GetActiveGUI()->GetScriptInterface());
g_GUI->GetActiveGUI()->GetScriptInterface()->SetGlobal("g_LoadDescription", pending_task, true, false, true); JSContext* cx = scriptInterface.GetContext();
g_GUI->GetActiveGUI()->SendEventToAll("progress"); JSAutoRequest rq(cx);
JS::AutoValueVector paramData(cx);
paramData.append(JS::NumberValue(percent));
JS::RootedValue valPendingTask(cx);
scriptInterface.ToJSVal(cx, &valPendingTask, pending_task);
paramData.append(valPendingTask);
g_GUI->GetActiveGUI()->SendEventToAll("GameLoadProgress", paramData);
} }
void SwapBuffers() void SwapBuffers()

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Wildfire Games. /* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -76,12 +76,29 @@ void CReplayTurnManager::NotifyFinishedUpdate(u32 turn)
ENSURE(m_Simulation2.ComputeStateHash(hash, quickHash)); ENSURE(m_Simulation2.ComputeStateHash(hash, quickHash));
hash = Hexify(hash); hash = Hexify(hash);
if (hash != expectedHash) if (hash == expectedHash)
{ return;
m_HasSyncError = true;
LOGERROR("Replay out of sync on turn %d", turn); m_HasSyncError = true;
g_GUI->SendEventToAll("ReplayOutOfSync"); LOGERROR("Replay out of sync on turn %d", turn);
}
const ScriptInterface& scriptInterface = m_Simulation2.GetScriptInterface();
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::AutoValueVector paramData(cx);
paramData.append(JS::NumberValue(turn));
JS::RootedValue hashVal(cx);
scriptInterface.ToJSVal(cx, &hashVal, hash);
paramData.append(hashVal);
JS::RootedValue expectedHashVal(cx);
scriptInterface.ToJSVal(cx, &expectedHashVal, expectedHash);
paramData.append(expectedHashVal);
g_GUI->SendEventToAll("ReplayOutOfSync", paramData);
} }
void CReplayTurnManager::DoTurn(u32 turn) void CReplayTurnManager::DoTurn(u32 turn)