1
0
forked from mirrors/0ad

Start Atlas by closing the root page

Theere is now an  `Engine.startAtlas` property that will start Atlas
when it's returned from the root page. The `Engine.RestartInAtlas`
function is removed.
This commit is contained in:
phosit
2025-03-12 14:05:27 +01:00
committed by phosit
parent c2d3595777
commit 2d206708cd
9 changed files with 64 additions and 26 deletions
@@ -0,0 +1,4 @@
async function init(arg)
{
return arg ? Engine.startAtlas : undefined;
}
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<objects>
<script file="gui/Result/Result.js"/>
</objects>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<page>
<include>Result/Result.xml</include>
</page>
@@ -275,7 +275,7 @@ var g_MainMenuItems = [
{ {
"caption": translate("Scenario Editor"), "caption": translate("Scenario Editor"),
"tooltip": translate('Open the Atlas Scenario Editor in a new window. You can run this more reliably by starting the game with the command-line argument "-editor".'), "tooltip": translate('Open the Atlas Scenario Editor in a new window. You can run this more reliably by starting the game with the command-line argument "-editor".'),
"onPress": async() => { "onPress": async(closePageCallback) => {
if (!Engine.AtlasIsAvailable()) if (!Engine.AtlasIsAvailable())
{ {
messageBox( messageBox(
@@ -292,7 +292,7 @@ var g_MainMenuItems = [
[translate("No"), translate("Yes")]); [translate("No"), translate("Yes")]);
if (buttonIndex === 1) if (buttonIndex === 1)
Engine.RestartInAtlas(); closePageCallback(Engine.startAtlas);
} }
}, },
{ {
+31 -6
View File
@@ -35,11 +35,14 @@
#include "scriptinterface/ScriptInterface.h" #include "scriptinterface/ScriptInterface.h"
#include "scriptinterface/StructuredClone.h" #include "scriptinterface/StructuredClone.h"
#include "js/Equality.h"
namespace namespace
{ {
const CStr EVENT_NAME_GAME_LOAD_PROGRESS = "GameLoadProgress"; const CStr EVENT_NAME_GAME_LOAD_PROGRESS = "GameLoadProgress";
const CStr EVENT_NAME_WINDOW_RESIZED = "WindowResized"; const CStr EVENT_NAME_WINDOW_RESIZED = "WindowResized";
constexpr const char* START_ATLAS{"startAtlas"};
} // anonymous namespace } // anonymous namespace
@@ -165,6 +168,12 @@ void CGUIManager::SGUIPage::LoadPage(ScriptContext& scriptContext)
sendingPromise = std::make_shared<JS::PersistentRootedObject>(rq.cx, sendingPromise = std::make_shared<JS::PersistentRootedObject>(rq.cx,
JS::NewPromiseObject(rq.cx, nullptr)); JS::NewPromiseObject(rq.cx, nullptr));
{
JS::RootedString jsName{rq.cx, JS_NewStringCopyZ(rq.cx, START_ATLAS)};
JS::RootedValue symbol{rq.cx, JS::SymbolValue(JS::NewSymbol(rq.cx, jsName))};
JS::RootedValue nativeScope{rq.cx, JS::ObjectValue(*rq.nativeScope)};
Script::SetProperty(rq, nativeScope, START_ATLAS, symbol, true);
}
gui->AddObjectTypes(); gui->AddObjectTypes();
VfsPath path = VfsPath("gui") / m_Name; VfsPath path = VfsPath("gui") / m_Name;
@@ -257,7 +266,7 @@ JS::Value CGUIManager::SGUIPage::ReplacePromise(ScriptInterface& scriptInterface
return JS::ObjectValue(**receivingPromise); return JS::ObjectValue(**receivingPromise);
} }
std::optional<CGUIManager::SGUIPage::CloseResult> CGUIManager::SGUIPage::MaybeClose() std::optional<CGUIManager::SGUIPage::CloseResult> CGUIManager::SGUIPage::MaybeClose(const bool topmostPage)
{ {
if (JS::GetPromiseState(*sendingPromise) == JS::PromiseState::Pending) if (JS::GetPromiseState(*sendingPromise) == JS::PromiseState::Pending)
return std::nullopt; return std::nullopt;
@@ -267,8 +276,20 @@ std::optional<CGUIManager::SGUIPage::CloseResult> CGUIManager::SGUIPage::MaybeCl
const ScriptRequest rq{gui->GetScriptInterface()}; const ScriptRequest rq{gui->GetScriptInterface()};
JS::RootedValue arg{rq.cx, JS::GetPromiseResult(*sendingPromise)}; JS::RootedValue arg{rq.cx, JS::GetPromiseResult(*sendingPromise)};
return CGUIManager::SGUIPage::CloseResult{Script::WriteStructuredClone(rq, arg), const bool rejected{JS::GetPromiseState(*sendingPromise) == JS::PromiseState::Rejected};
JS::GetPromiseState(*sendingPromise) == JS::PromiseState::Rejected}; if (topmostPage)
{
JS::RootedValue nativeScope{rq.cx, JS::ObjectValue(*rq.nativeScope)};
JS::RootedValue symbol{rq.cx};
Script::GetProperty(rq, nativeScope, START_ATLAS, &symbol);
bool equals;
if (!JS::StrictlyEqual(rq.cx, arg, symbol, &equals))
throw std::runtime_error{"Error while comparing return value to a symbol."};
if (equals)
return CGUIManager::SGUIPage::CloseResult{nullptr, rejected};
}
return CGUIManager::SGUIPage::CloseResult{Script::WriteStructuredClone(rq, arg), rejected};
} }
void CGUIManager::SGUIPage::Refocus(const CloseResult& result) void CGUIManager::SGUIPage::Refocus(const CloseResult& result)
@@ -375,7 +396,7 @@ void CGUIManager::SendEventToAll(const CStr& eventName, JS::HandleValueArray par
p.gui->SendEventToAll(eventName, paramData); p.gui->SendEventToAll(eventName, paramData);
} }
void CGUIManager::TickObjects() std::optional<bool> CGUIManager::TickObjects()
{ {
PROFILE3("gui tick"); PROFILE3("gui tick");
@@ -394,16 +415,20 @@ void CGUIManager::TickObjects()
while (!m_PageStack.empty()) while (!m_PageStack.empty())
{ {
const size_t stackSize{m_PageStack.size()}; const size_t stackSize{m_PageStack.size()};
const std::optional<SGUIPage::CloseResult> result{m_PageStack.back().MaybeClose()}; const std::optional<SGUIPage::CloseResult> result{
m_PageStack.back().MaybeClose(stackSize == 1)};
if (!result.has_value()) if (!result.has_value())
break; break;
ENSURE(m_PageStack.size() == stackSize); ENSURE(m_PageStack.size() == stackSize);
m_PageStack.pop_back(); m_PageStack.pop_back();
if (!m_PageStack.empty()) if (m_PageStack.empty())
return !result.value().arg;
else
m_PageStack.back().Refocus(result.value()); m_PageStack.back().Refocus(result.value());
m_ScriptContext.RunJobs(); m_ScriptContext.RunJobs();
} }
return std::nullopt;
} }
void CGUIManager::Draw(CCanvas2D& canvas) const void CGUIManager::Draw(CCanvas2D& canvas) const
+4 -2
View File
@@ -96,8 +96,10 @@ public:
/** /**
* See CGUI::TickObjects; applies to @em all loaded pages. * See CGUI::TickObjects; applies to @em all loaded pages.
* When the root page is closed it's returned wheter Atlas should be
* started.
*/ */
void TickObjects(); std::optional<bool> TickObjects();
/** /**
* See CGUI::Draw; applies to @em all loaded pages. * See CGUI::Draw; applies to @em all loaded pages.
@@ -156,7 +158,7 @@ private:
* returns the result of the @c init function. * returns the result of the @c init function.
* If this page wasn't closed an empty optional is returned. * If this page wasn't closed an empty optional is returned.
*/ */
std::optional<CloseResult> MaybeClose(); std::optional<CloseResult> MaybeClose(const bool topmostPage);
/** /**
* This function should be called when a child page got closed. The * This function should be called when a child page got closed. The
+12
View File
@@ -284,4 +284,16 @@ public:
CloseTopmostPage(); CloseTopmostPage();
TS_ASSERT_EQUALS(g_GUI->GetPageCount(), 0); TS_ASSERT_EQUALS(g_GUI->GetPageCount(), 0);
} }
void test_Result()
{
const ScriptRequest rq{g_GUI->GetScriptInterface()};
g_GUI->OpenChildPage(L"Result/page_Result.xml",
Script::WriteStructuredClone(rq, JS::FalseHandleValue));
TS_ASSERT(!g_GUI->TickObjects().value());
g_GUI->OpenChildPage(L"Result/page_Result.xml",
Script::WriteStructuredClone(rq, JS::TrueHandleValue));
TS_ASSERT(g_GUI->TickObjects().value());
}
}; };
+3 -8
View File
@@ -172,11 +172,6 @@ void RestartEngine()
g_Shutdown = ShutdownType::Restart; g_Shutdown = ShutdownType::Restart;
} }
void StartAtlas()
{
g_Shutdown = ShutdownType::RestartAsAtlas;
}
// main app message handler // main app message handler
static InReaction MainInputHandler(const SDL_Event_* ev) static InReaction MainInputHandler(const SDL_Event_* ev)
{ {
@@ -430,9 +425,9 @@ static void Frame(RL::Interface* rlInterface)
if (g_NetClient) if (g_NetClient)
g_NetClient->Poll(); g_NetClient->Poll();
g_GUI->TickObjects(); std::optional<bool> completionCommand{g_GUI->TickObjects()};
if (g_GUI->GetPageCount() == 0) if (completionCommand.has_value())
QuitEngine(); g_Shutdown = completionCommand.value() ? ShutdownType::RestartAsAtlas : ShutdownType::Quit;
if (rlInterface) if (rlInterface)
rlInterface->TryApplyMessage(); rlInterface->TryApplyMessage();
-8
View File
@@ -34,15 +34,8 @@
#include "scriptinterface/FunctionWrapper.h" #include "scriptinterface/FunctionWrapper.h"
#include "tools/atlas/GameInterface/GameLoop.h" #include "tools/atlas/GameInterface/GameLoop.h"
extern void StartAtlas();
namespace JSI_Main namespace JSI_Main
{ {
void StartAtlas()
{
::StartAtlas();
}
bool AtlasIsAvailable() bool AtlasIsAvailable()
{ {
return ATLAS_IsAvailable(); return ATLAS_IsAvailable();
@@ -120,7 +113,6 @@ std::string CalculateMD5(const std::string& input)
void RegisterScriptFunctions(const ScriptRequest& rq) void RegisterScriptFunctions(const ScriptRequest& rq)
{ {
ScriptFunction::Register<&StartAtlas>(rq, "RestartInAtlas");
ScriptFunction::Register<&AtlasIsAvailable>(rq, "AtlasIsAvailable"); ScriptFunction::Register<&AtlasIsAvailable>(rq, "AtlasIsAvailable");
ScriptFunction::Register<&IsAtlasRunning>(rq, "IsAtlasRunning"); ScriptFunction::Register<&IsAtlasRunning>(rq, "IsAtlasRunning");
ScriptFunction::Register<&OpenURL>(rq, "OpenURL"); ScriptFunction::Register<&OpenURL>(rq, "OpenURL");