Emscripten: Remove direct blocking prompt calls from Lua
Notable changes: - tpt.{input,throw_error,message_box,confirm} have been superseded by ui.begin{Input,ThrowError,MessageBox,Confirm}, each with an extra callback argument and no blocking behaviour, but otherwise the same semantics as their predecessors. - The "script not responding" error doesn't wait for user confirmation anymore, it fires without asking. Future exercise: maybe let the user configure the timeout. - Remove the confirmPrompt argument of tpt.getscript; this also means it unconditionally fails if the destination file exists.
This commit is contained in:
parent
67e41b6705
commit
4f31f85b6b
@ -8,8 +8,9 @@
|
|||||||
|
|
||||||
#include "graphics/Graphics.h"
|
#include "graphics/Graphics.h"
|
||||||
|
|
||||||
InformationMessage::InformationMessage(String title, String message, bool large):
|
InformationMessage::InformationMessage(String title, String message, bool large, DismissCallback callback_):
|
||||||
ui::Window(ui::Point(-1, -1), ui::Point(200, 35))
|
ui::Window(ui::Point(-1, -1), ui::Point(200, 35)),
|
||||||
|
callback(callback_)
|
||||||
{
|
{
|
||||||
if (large) //Maybe also use this large mode for changelogs eventually, or have it as a customizable size?
|
if (large) //Maybe also use this large mode for changelogs eventually, or have it as a customizable size?
|
||||||
{
|
{
|
||||||
@ -61,6 +62,8 @@ InformationMessage::InformationMessage(String title, String message, bool large)
|
|||||||
okayButton->Appearance.BorderInactive = ui::Colour(200, 200, 200);
|
okayButton->Appearance.BorderInactive = ui::Colour(200, 200, 200);
|
||||||
okayButton->SetActionCallback({ [this] {
|
okayButton->SetActionCallback({ [this] {
|
||||||
CloseActiveWindow();
|
CloseActiveWindow();
|
||||||
|
if (callback.dismiss)
|
||||||
|
callback.dismiss();
|
||||||
SelfDestruct(); //TODO: Fix component disposal
|
SelfDestruct(); //TODO: Fix component disposal
|
||||||
} });
|
} });
|
||||||
AddComponent(okayButton);
|
AddComponent(okayButton);
|
||||||
|
@ -3,8 +3,15 @@
|
|||||||
|
|
||||||
class InformationMessage : public ui::Window
|
class InformationMessage : public ui::Window
|
||||||
{
|
{
|
||||||
|
struct DismissCallback
|
||||||
|
{
|
||||||
|
std::function<void ()> dismiss;
|
||||||
|
};
|
||||||
|
|
||||||
|
DismissCallback callback;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InformationMessage(String title, String message, bool large);
|
InformationMessage(String title, String message, bool large, DismissCallback callback_ = {});
|
||||||
virtual ~InformationMessage() = default;
|
virtual ~InformationMessage() = default;
|
||||||
|
|
||||||
void OnDraw() override;
|
void OnDraw() override;
|
||||||
|
@ -11,10 +11,6 @@
|
|||||||
#include "simulation/gravity/Gravity.h"
|
#include "simulation/gravity/Gravity.h"
|
||||||
#include "simulation/Simulation.h"
|
#include "simulation/Simulation.h"
|
||||||
#include "simulation/SimulationData.h"
|
#include "simulation/SimulationData.h"
|
||||||
#include "gui/dialogues/ConfirmPrompt.h"
|
|
||||||
#include "gui/dialogues/ErrorMessage.h"
|
|
||||||
#include "gui/dialogues/InformationMessage.h"
|
|
||||||
#include "gui/dialogues/TextPrompt.h"
|
|
||||||
#include "gui/game/GameController.h"
|
#include "gui/game/GameController.h"
|
||||||
#include "gui/game/GameModel.h"
|
#include "gui/game/GameModel.h"
|
||||||
#include "gui/interface/Engine.h"
|
#include "gui/interface/Engine.h"
|
||||||
@ -264,8 +260,7 @@ void luacon_hook(lua_State * l, lua_Debug * ar)
|
|||||||
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||||
if (ar->event == LUA_HOOKCOUNT && Platform::GetTime() - luacon_ci->luaExecutionStart > 3000)
|
if (ar->event == LUA_HOOKCOUNT && Platform::GetTime() - luacon_ci->luaExecutionStart > 3000)
|
||||||
{
|
{
|
||||||
if(ConfirmPrompt::Blocking("Script not responding", "The Lua script may have stopped responding. There might be an infinite loop. Press \"Stop\" to stop it", "Stop"))
|
luaL_error(l, "Error: Script not responding");
|
||||||
luaL_error(l, "Error: Script not responding");
|
|
||||||
luacon_ci->luaExecutionStart = Platform::GetTime();
|
luacon_ci->luaExecutionStart = Platform::GetTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,13 +298,6 @@ int luatpt_getelement(lua_State *l)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int luatpt_error(lua_State* l)
|
|
||||||
{
|
|
||||||
String errorMessage = tpt_lua_optString(l, 1, "Error text");
|
|
||||||
ErrorMessage::Blocking("Error", errorMessage);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int luatpt_drawtext(lua_State* l)
|
int luatpt_drawtext(lua_State* l)
|
||||||
{
|
{
|
||||||
int textx, texty, textred, textgreen, textblue, textalpha;
|
int textx, texty, textred, textgreen, textblue, textalpha;
|
||||||
@ -1038,38 +1026,6 @@ int luatpt_delete(lua_State* l)
|
|||||||
return luaL_error(l,"Invalid coordinates or particle ID");
|
return luaL_error(l,"Invalid coordinates or particle ID");
|
||||||
}
|
}
|
||||||
|
|
||||||
int luatpt_input(lua_State* l)
|
|
||||||
{
|
|
||||||
String title = tpt_lua_optString(l, 1, "Title");
|
|
||||||
String prompt = tpt_lua_optString(l, 2, "Enter some text:");
|
|
||||||
String text = tpt_lua_optString(l, 3, "");
|
|
||||||
String shadow = tpt_lua_optString(l, 4, "");
|
|
||||||
|
|
||||||
String result = TextPrompt::Blocking(title, prompt, text, shadow, false);
|
|
||||||
|
|
||||||
tpt_lua_pushString(l, result);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int luatpt_message_box(lua_State* l)
|
|
||||||
{
|
|
||||||
String title = tpt_lua_optString(l, 1, "Title");
|
|
||||||
String message = tpt_lua_optString(l, 2, "Message");
|
|
||||||
int large = lua_toboolean(l, 3);
|
|
||||||
new InformationMessage(title, message, large);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int luatpt_confirm(lua_State *l)
|
|
||||||
{
|
|
||||||
String title = tpt_lua_optString(l, 1, "Title");
|
|
||||||
String message = tpt_lua_optString(l, 2, "Message");
|
|
||||||
String buttonText = tpt_lua_optString(l, 3, "Confirm");
|
|
||||||
bool ret = ConfirmPrompt::Blocking(title, message, buttonText);
|
|
||||||
lua_pushboolean(l, ret ? 1 : 0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int luatpt_get_numOfParts(lua_State* l)
|
int luatpt_get_numOfParts(lua_State* l)
|
||||||
{
|
{
|
||||||
lua_pushinteger(l, luacon_sim->NUM_PARTS);
|
lua_pushinteger(l, luacon_sim->NUM_PARTS);
|
||||||
|
@ -49,7 +49,6 @@ int luacon_transitionwrite(lua_State* l);
|
|||||||
//tpt. api
|
//tpt. api
|
||||||
int luatpt_getelement(lua_State *l);
|
int luatpt_getelement(lua_State *l);
|
||||||
|
|
||||||
int luatpt_error(lua_State* l);
|
|
||||||
int luatpt_drawtext(lua_State* l);
|
int luatpt_drawtext(lua_State* l);
|
||||||
|
|
||||||
int luatpt_create(lua_State* l);
|
int luatpt_create(lua_State* l);
|
||||||
@ -96,9 +95,6 @@ int luatpt_textwidth(lua_State* l);
|
|||||||
int luatpt_get_name(lua_State* l);
|
int luatpt_get_name(lua_State* l);
|
||||||
|
|
||||||
int luatpt_delete(lua_State* l);
|
int luatpt_delete(lua_State* l);
|
||||||
int luatpt_input(lua_State* l);
|
|
||||||
int luatpt_message_box(lua_State* l);
|
|
||||||
int luatpt_confirm(lua_State* l);
|
|
||||||
int luatpt_get_numOfParts(lua_State* l);
|
int luatpt_get_numOfParts(lua_State* l);
|
||||||
int luatpt_start_getPartIndex(lua_State* l);
|
int luatpt_start_getPartIndex(lua_State* l);
|
||||||
int luatpt_next_getPartIndex(lua_State* l);
|
int luatpt_next_getPartIndex(lua_State* l);
|
||||||
|
@ -38,6 +38,10 @@
|
|||||||
#include "simulation/SaveRenderer.h"
|
#include "simulation/SaveRenderer.h"
|
||||||
#include "simulation/Snapshot.h"
|
#include "simulation/Snapshot.h"
|
||||||
|
|
||||||
|
#include "gui/dialogues/ConfirmPrompt.h"
|
||||||
|
#include "gui/dialogues/ErrorMessage.h"
|
||||||
|
#include "gui/dialogues/InformationMessage.h"
|
||||||
|
#include "gui/dialogues/TextPrompt.h"
|
||||||
#include "gui/interface/Window.h"
|
#include "gui/interface/Window.h"
|
||||||
#include "gui/interface/Engine.h"
|
#include "gui/interface/Engine.h"
|
||||||
#include "gui/game/GameView.h"
|
#include "gui/game/GameView.h"
|
||||||
@ -345,9 +349,6 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m):
|
|||||||
{"textwidth", &luatpt_textwidth},
|
{"textwidth", &luatpt_textwidth},
|
||||||
{"get_name", &luatpt_get_name},
|
{"get_name", &luatpt_get_name},
|
||||||
{"delete", &luatpt_delete},
|
{"delete", &luatpt_delete},
|
||||||
{"input", &luatpt_input},
|
|
||||||
{"message_box", &luatpt_message_box},
|
|
||||||
{"confirm", &luatpt_confirm},
|
|
||||||
{"get_numOfParts", &luatpt_get_numOfParts},
|
{"get_numOfParts", &luatpt_get_numOfParts},
|
||||||
{"start_getPartIndex", &luatpt_start_getPartIndex},
|
{"start_getPartIndex", &luatpt_start_getPartIndex},
|
||||||
{"next_getPartIndex", &luatpt_next_getPartIndex},
|
{"next_getPartIndex", &luatpt_next_getPartIndex},
|
||||||
@ -360,7 +361,6 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m):
|
|||||||
{"num_menus", &luatpt_num_menus},
|
{"num_menus", &luatpt_num_menus},
|
||||||
{"decorations_enable", &luatpt_decorations_enable},
|
{"decorations_enable", &luatpt_decorations_enable},
|
||||||
{"display_mode", &luatpt_cmode_set},
|
{"display_mode", &luatpt_cmode_set},
|
||||||
{"throw_error", &luatpt_error},
|
|
||||||
{"heat", &luatpt_heat},
|
{"heat", &luatpt_heat},
|
||||||
{"setfire", &luatpt_setfire},
|
{"setfire", &luatpt_setfire},
|
||||||
{"setdebug", &luatpt_setdebug},
|
{"setdebug", &luatpt_setdebug},
|
||||||
@ -660,7 +660,124 @@ int LuaScriptInterface::tpt_newIndex(lua_State *l)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//// Begin Interface API
|
static int beginMessageBox(lua_State* l)
|
||||||
|
{
|
||||||
|
String title = tpt_lua_optString(l, 1, "Title");
|
||||||
|
String message = tpt_lua_optString(l, 2, "Message");
|
||||||
|
int large = lua_toboolean(l, 3);
|
||||||
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||||
|
auto cb = std::make_shared<LuaSmartRef>(luacon_ci->l); // * Bind to main lua state (might be different from l).
|
||||||
|
cb->Assign(l, 4);
|
||||||
|
new InformationMessage(title, message, large, { [cb]() {
|
||||||
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||||
|
auto l = luacon_ci->l;
|
||||||
|
cb->Push(l);
|
||||||
|
if (lua_isfunction(l, -1))
|
||||||
|
{
|
||||||
|
if (lua_pcall(l, 0, 0, 0))
|
||||||
|
{
|
||||||
|
luacon_ci->Log(CommandInterface::LogError, luacon_geterror());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lua_pop(l, 1);
|
||||||
|
}
|
||||||
|
} });
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int beginThrowError(lua_State* l)
|
||||||
|
{
|
||||||
|
String errorMessage = tpt_lua_optString(l, 1, "Error text");
|
||||||
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||||
|
auto cb = std::make_shared<LuaSmartRef>(luacon_ci->l); // * Bind to main lua state (might be different from l).
|
||||||
|
cb->Assign(l, 2);
|
||||||
|
new ErrorMessage("Error", errorMessage, { [cb]() {
|
||||||
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||||
|
auto l = luacon_ci->l;
|
||||||
|
cb->Push(l);
|
||||||
|
if (lua_isfunction(l, -1))
|
||||||
|
{
|
||||||
|
if (lua_pcall(l, 0, 0, 0))
|
||||||
|
{
|
||||||
|
luacon_ci->Log(CommandInterface::LogError, luacon_geterror());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lua_pop(l, 1);
|
||||||
|
}
|
||||||
|
} });
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int beginInput(lua_State* l)
|
||||||
|
{
|
||||||
|
String title = tpt_lua_optString(l, 1, "Title");
|
||||||
|
String prompt = tpt_lua_optString(l, 2, "Enter some text:");
|
||||||
|
String text = tpt_lua_optString(l, 3, "");
|
||||||
|
String shadow = tpt_lua_optString(l, 4, "");
|
||||||
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||||
|
auto cb = std::make_shared<LuaSmartRef>(luacon_ci->l); // * Bind to main lua state (might be different from l).
|
||||||
|
cb->Assign(l, 5);
|
||||||
|
auto handle = [cb](const String &input) {
|
||||||
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||||
|
auto l = luacon_ci->l;
|
||||||
|
cb->Push(l);
|
||||||
|
if (lua_isfunction(l, -1))
|
||||||
|
{
|
||||||
|
tpt_lua_pushString(l, input);
|
||||||
|
if (lua_pcall(l, 1, 0, 0))
|
||||||
|
{
|
||||||
|
luacon_ci->Log(CommandInterface::LogError, luacon_geterror());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lua_pop(l, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
new TextPrompt(title, prompt, text, shadow, false, { [handle](const String &input) {
|
||||||
|
handle(input);
|
||||||
|
}, [handle]() {
|
||||||
|
handle({}); // * Has always returned empty string >_>
|
||||||
|
} });
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int beginConfirm(lua_State *l)
|
||||||
|
{
|
||||||
|
String title = tpt_lua_optString(l, 1, "Title");
|
||||||
|
String message = tpt_lua_optString(l, 2, "Message");
|
||||||
|
String buttonText = tpt_lua_optString(l, 3, "Confirm");
|
||||||
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||||
|
auto cb = std::make_shared<LuaSmartRef>(luacon_ci->l); // * Bind to main lua state (might be different from l).
|
||||||
|
cb->Assign(l, 4);
|
||||||
|
auto handle = [cb](int result) {
|
||||||
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||||
|
auto l = luacon_ci->l;
|
||||||
|
cb->Push(l);
|
||||||
|
if (lua_isfunction(l, -1))
|
||||||
|
{
|
||||||
|
lua_pushboolean(l, result);
|
||||||
|
if (lua_pcall(l, 1, 0, 0))
|
||||||
|
{
|
||||||
|
luacon_ci->Log(CommandInterface::LogError, luacon_geterror());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lua_pop(l, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
new ConfirmPrompt(title, message, { [handle]() {
|
||||||
|
handle(1);
|
||||||
|
}, [handle]() {
|
||||||
|
handle(0);
|
||||||
|
} }, buttonText);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void LuaScriptInterface::initInterfaceAPI()
|
void LuaScriptInterface::initInterfaceAPI()
|
||||||
{
|
{
|
||||||
@ -672,6 +789,10 @@ void LuaScriptInterface::initInterfaceAPI()
|
|||||||
{"grabTextInput", interface_grabTextInput},
|
{"grabTextInput", interface_grabTextInput},
|
||||||
{"dropTextInput", interface_dropTextInput},
|
{"dropTextInput", interface_dropTextInput},
|
||||||
{"textInputRect", interface_textInputRect},
|
{"textInputRect", interface_textInputRect},
|
||||||
|
{"beginInput", beginInput},
|
||||||
|
{"beginMessageBox", beginMessageBox},
|
||||||
|
{"beginConfirm", beginConfirm},
|
||||||
|
{"beginThrowError", beginThrowError},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
luaL_register(l, "interface", interfaceAPIMethods);
|
luaL_register(l, "interface", interfaceAPIMethods);
|
||||||
@ -4431,8 +4552,9 @@ void LuaScriptInterface::OnTick()
|
|||||||
new ErrorMessage("Script download", ByteString(http::StatusText(ret)).FromUtf8());
|
new ErrorMessage("Script download", ByteString(http::StatusText(ret)).FromUtf8());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Platform::FileExists(scriptDownloadFilename) && scriptDownloadConfirmPrompt && !ConfirmPrompt::Blocking("File already exists, overwrite?", scriptDownloadFilename.FromUtf8(), "Overwrite"))
|
if (Platform::FileExists(scriptDownloadFilename))
|
||||||
{
|
{
|
||||||
|
new ErrorMessage("Script download", "File already exists");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!Platform::WriteFile(std::vector<char>(scriptData.begin(), scriptData.end()), scriptDownloadFilename))
|
if (!Platform::WriteFile(std::vector<char>(scriptData.begin(), scriptData.end()), scriptDownloadFilename))
|
||||||
@ -4885,7 +5007,6 @@ int LuaScriptInterface::luatpt_getscript(lua_State* l)
|
|||||||
int scriptID = luaL_checkinteger(l, 1);
|
int scriptID = luaL_checkinteger(l, 1);
|
||||||
auto filename = tpt_lua_checkByteString(l, 2);
|
auto filename = tpt_lua_checkByteString(l, 2);
|
||||||
bool runScript = luaL_optint(l, 3, 0);
|
bool runScript = luaL_optint(l, 3, 0);
|
||||||
int confirmPrompt = luaL_optint(l, 4, 1);
|
|
||||||
|
|
||||||
if (luacon_ci->scriptDownload)
|
if (luacon_ci->scriptDownload)
|
||||||
{
|
{
|
||||||
@ -4894,16 +5015,11 @@ int LuaScriptInterface::luatpt_getscript(lua_State* l)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ByteString url = ByteString::Build(SCHEME, "starcatcher.us/scripts/main.lua?get=", scriptID);
|
ByteString url = ByteString::Build(SCHEME, "starcatcher.us/scripts/main.lua?get=", scriptID);
|
||||||
if (confirmPrompt && !ConfirmPrompt::Blocking("Do you want to install script?", url.FromUtf8(), "Install"))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
luacon_ci->scriptDownload = std::make_unique<http::Request>(url);
|
luacon_ci->scriptDownload = std::make_unique<http::Request>(url);
|
||||||
luacon_ci->scriptDownload->Start();
|
luacon_ci->scriptDownload->Start();
|
||||||
luacon_ci->scriptDownloadFilename = filename;
|
luacon_ci->scriptDownloadFilename = filename;
|
||||||
luacon_ci->scriptDownloadRunScript = runScript;
|
luacon_ci->scriptDownloadRunScript = runScript;
|
||||||
luacon_ci->scriptDownloadConfirmPrompt = confirmPrompt;
|
|
||||||
|
|
||||||
luacon_controller->HideConsole();
|
luacon_controller->HideConsole();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -31,7 +31,6 @@ class LuaScriptInterface: public TPTScriptInterface
|
|||||||
std::unique_ptr<http::Request> scriptDownload;
|
std::unique_ptr<http::Request> scriptDownload;
|
||||||
ByteString scriptDownloadFilename;
|
ByteString scriptDownloadFilename;
|
||||||
bool scriptDownloadRunScript;
|
bool scriptDownloadRunScript;
|
||||||
bool scriptDownloadConfirmPrompt;
|
|
||||||
|
|
||||||
int luacon_mousex, luacon_mousey, luacon_mousebutton;
|
int luacon_mousex, luacon_mousey, luacon_mousebutton;
|
||||||
ByteString luacon_selectedl, luacon_selectedr, luacon_selectedalt, luacon_selectedreplace;
|
ByteString luacon_selectedl, luacon_selectedr, luacon_selectedalt, luacon_selectedreplace;
|
||||||
|
Reference in New Issue
Block a user