Changeset View
Changeset View
Standalone View
Standalone View
source/gui/GUIManager.cpp
Show First 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | if (m_PageStack.size() < 2) | ||||
return; | return; | ||||
} | } | ||||
m_PageStack.pop_back(); | m_PageStack.pop_back(); | ||||
m_PageStack.back().PerformCallbackFunction(args); | m_PageStack.back().PerformCallbackFunction(args); | ||||
} | } | ||||
CGUIManager::SGUIPage::SGUIPage(const CStrW& pageName, const ScriptInterface::StructuredClone initData) | CGUIManager::SGUIPage::SGUIPage(const CStrW& pageName, const ScriptInterface::StructuredClone initData) | ||||
: name(pageName), initData(initData), inputs(), gui(), callbackFunction() | : m_Name(pageName), initData(initData), inputs(), gui(), callbackFunction() | ||||
{ | { | ||||
} | } | ||||
void CGUIManager::SGUIPage::LoadPage(shared_ptr<ScriptContext> scriptContext) | void CGUIManager::SGUIPage::LoadPage(shared_ptr<ScriptContext> scriptContext) | ||||
{ | { | ||||
// If we're hotloading then try to grab some data from the previous page | // If we're hotloading then try to grab some data from the previous page | ||||
ScriptInterface::StructuredClone hotloadData; | ScriptInterface::StructuredClone hotloadData; | ||||
if (gui) | if (gui) | ||||
{ | { | ||||
shared_ptr<ScriptInterface> scriptInterface = gui->GetScriptInterface(); | shared_ptr<ScriptInterface> scriptInterface = gui->GetScriptInterface(); | ||||
ScriptRequest rq(scriptInterface); | ScriptRequest rq(scriptInterface); | ||||
JS::RootedValue global(rq.cx, rq.globalValue()); | JS::RootedValue global(rq.cx, rq.globalValue()); | ||||
JS::RootedValue hotloadDataVal(rq.cx); | JS::RootedValue hotloadDataVal(rq.cx); | ||||
scriptInterface->CallFunction(global, "getHotloadData", &hotloadDataVal); | scriptInterface->CallFunction(global, "getHotloadData", &hotloadDataVal); | ||||
hotloadData = scriptInterface->WriteStructuredClone(hotloadDataVal, true); | hotloadData = scriptInterface->WriteStructuredClone(hotloadDataVal, true); | ||||
} | } | ||||
g_CursorName = g_DefaultCursor; | g_CursorName = g_DefaultCursor; | ||||
inputs.clear(); | inputs.clear(); | ||||
gui.reset(new CGUI(scriptContext)); | gui.reset(new CGUI(scriptContext)); | ||||
gui->AddObjectTypes(); | gui->AddObjectTypes(); | ||||
VfsPath path = VfsPath("gui") / name; | VfsPath path = VfsPath("gui") / m_Name; | ||||
inputs.insert(path); | inputs.insert(path); | ||||
CXeromyces xero; | CXeromyces xero; | ||||
if (xero.Load(g_VFS, path, "gui_page") != PSRETURN_OK) | if (xero.Load(g_VFS, path, "gui_page") != PSRETURN_OK) | ||||
// Fail silently (Xeromyces reported the error) | // Fail silently (Xeromyces reported the error) | ||||
return; | return; | ||||
int elmt_page = xero.GetElementID("page"); | int elmt_page = xero.GetElementID("page"); | ||||
int elmt_include = xero.GetElementID("include"); | int elmt_include = xero.GetElementID("include"); | ||||
XMBElement root = xero.GetRoot(); | XMBElement root = xero.GetRoot(); | ||||
if (root.GetNodeName() != elmt_page) | if (root.GetNodeName() != elmt_page) | ||||
{ | { | ||||
LOGERROR("GUI page '%s' must have root element <page>", utf8_from_wstring(name)); | LOGERROR("GUI page '%s' must have root element <page>", utf8_from_wstring(m_Name)); | ||||
return; | return; | ||||
} | } | ||||
XERO_ITER_EL(root, node) | XERO_ITER_EL(root, node) | ||||
{ | { | ||||
if (node.GetNodeName() != elmt_include) | if (node.GetNodeName() != elmt_include) | ||||
{ | { | ||||
LOGERROR("GUI page '%s' must only have <include> elements inside <page>", utf8_from_wstring(name)); | LOGERROR("GUI page '%s' must only have <include> elements inside <page>", utf8_from_wstring(m_Name)); | ||||
continue; | continue; | ||||
} | } | ||||
std::string name = node.GetText(); | CStr8 name = node.GetText(); | ||||
CStrW nameW (node.GetText().FromUTF8()); | CStrW nameW = node.GetText().FromUTF8(); | ||||
PROFILE2("load gui xml"); | PROFILE2("load gui xml"); | ||||
PROFILE2_ATTR("name: %s", name.c_str()); | PROFILE2_ATTR("name: %s", name.c_str()); | ||||
TIMER(nameW.c_str()); | TIMER(nameW.c_str()); | ||||
if (name.back() == '/') | if (name.back() == '/') | ||||
{ | { | ||||
VfsPath directory = VfsPath("gui") / nameW; | VfsPath currentDirectory = VfsPath("gui") / nameW; | ||||
VfsPaths pathnames; | VfsPaths directories; | ||||
vfs::GetPathnames(g_VFS, directory, L"*.xml", pathnames); | vfs::GetPathnames(g_VFS, currentDirectory, L"*.xml", directories); | ||||
for (const VfsPath& path : pathnames) | for (const VfsPath& directory : directories) | ||||
gui->LoadXmlFile(path, inputs); | gui->LoadXmlFile(directory, inputs); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
VfsPath path = VfsPath("gui") / nameW; | VfsPath directory = VfsPath("gui") / nameW; | ||||
gui->LoadXmlFile(path, inputs); | gui->LoadXmlFile(directory, inputs); | ||||
} | } | ||||
} | } | ||||
gui->LoadedXmlFiles(); | gui->LoadedXmlFiles(); | ||||
shared_ptr<ScriptInterface> scriptInterface = gui->GetScriptInterface(); | shared_ptr<ScriptInterface> scriptInterface = gui->GetScriptInterface(); | ||||
ScriptRequest rq(scriptInterface); | ScriptRequest rq(scriptInterface); | ||||
JS::RootedValue initDataVal(rq.cx); | JS::RootedValue initDataVal(rq.cx); | ||||
JS::RootedValue hotloadDataVal(rq.cx); | JS::RootedValue hotloadDataVal(rq.cx); | ||||
JS::RootedValue global(rq.cx, rq.globalValue()); | JS::RootedValue global(rq.cx, rq.globalValue()); | ||||
if (initData) | if (initData) | ||||
scriptInterface->ReadStructuredClone(initData, &initDataVal); | scriptInterface->ReadStructuredClone(initData, &initDataVal); | ||||
if (hotloadData) | if (hotloadData) | ||||
scriptInterface->ReadStructuredClone(hotloadData, &hotloadDataVal); | scriptInterface->ReadStructuredClone(hotloadData, &hotloadDataVal); | ||||
if (scriptInterface->HasProperty(global, "init") && | if (scriptInterface->HasProperty(global, "init") && | ||||
!scriptInterface->CallFunctionVoid(global, "init", initDataVal, hotloadDataVal)) | !scriptInterface->CallFunctionVoid(global, "init", initDataVal, hotloadDataVal)) | ||||
LOGERROR("GUI page '%s': Failed to call init() function", utf8_from_wstring(name)); | LOGERROR("GUI page '%s': Failed to call init() function", utf8_from_wstring(m_Name)); | ||||
} | } | ||||
void CGUIManager::SGUIPage::SetCallbackFunction(ScriptInterface& scriptInterface, JS::HandleValue callbackFunc) | void CGUIManager::SGUIPage::SetCallbackFunction(ScriptInterface& scriptInterface, JS::HandleValue callbackFunc) | ||||
{ | { | ||||
if (!callbackFunc.isObject()) | if (!callbackFunc.isObject()) | ||||
{ | { | ||||
LOGERROR("Given callback handler is not an object!"); | LOGERROR("Given callback handler is not an object!"); | ||||
return; | return; | ||||
Show All 38 Lines | if(!JS_CallFunctionValue(rq.cx, globalObj, funcVal, paramData, &result)) | ||||
ScriptException::CatchPending(rq); | ScriptException::CatchPending(rq); | ||||
} | } | ||||
Status CGUIManager::ReloadChangedFile(const VfsPath& path) | Status CGUIManager::ReloadChangedFile(const VfsPath& path) | ||||
{ | { | ||||
for (SGUIPage& p : m_PageStack) | for (SGUIPage& p : m_PageStack) | ||||
if (p.inputs.find(path) != p.inputs.end()) | if (p.inputs.find(path) != p.inputs.end()) | ||||
{ | { | ||||
LOGMESSAGE("GUI file '%s' changed - reloading page '%s'", path.string8(), utf8_from_wstring(p.name)); | LOGMESSAGE("GUI file '%s' changed - reloading page '%s'", path.string8(), utf8_from_wstring(p.m_Name)); | ||||
p.LoadPage(m_ScriptContext); | p.LoadPage(m_ScriptContext); | ||||
// TODO: this can crash if LoadPage runs an init script which modifies the page stack and breaks our iterators | // TODO: this can crash if LoadPage runs an init script which modifies the page stack and breaks our iterators | ||||
} | } | ||||
return INFO::OK; | return INFO::OK; | ||||
} | } | ||||
Status CGUIManager::ReloadAllPages() | Status CGUIManager::ReloadAllPages() | ||||
▲ Show 20 Lines • Show All 126 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator