add engine pause mode
This commit is contained in:
@@ -168,6 +168,15 @@ bool DebuggingServer::performCommand(
|
|||||||
void DebuggingServer::onHitBreakpoint(dv::value&& stackTrace) {
|
void DebuggingServer::onHitBreakpoint(dv::value&& stackTrace) {
|
||||||
logger.info() << "hit breakpoint:\n"
|
logger.info() << "hit breakpoint:\n"
|
||||||
<< json::stringify(stackTrace, true, " ");
|
<< json::stringify(stackTrace, true, " ");
|
||||||
|
if (connection == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
connection->send(dv::object({
|
||||||
|
{"type", std::string("hit-breakpoint")},
|
||||||
|
{"stack", std::move(stackTrace)}
|
||||||
|
}));
|
||||||
|
|
||||||
|
engine.startPauseLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebuggingServer::setClient(u64id_t client) {
|
void DebuggingServer::setClient(u64id_t client) {
|
||||||
|
|||||||
@@ -309,6 +309,30 @@ void Engine::nextFrame() {
|
|||||||
input->pollEvents();
|
input->pollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::startPauseLoop() {
|
||||||
|
bool initialCursorLocked = false;
|
||||||
|
if (!isHeadless()) {
|
||||||
|
initialCursorLocked = input->isCursorLocked();
|
||||||
|
if (initialCursorLocked) {
|
||||||
|
input->toggleCursor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!isQuitSignal()) {
|
||||||
|
if (!debuggingServer->update()) {
|
||||||
|
debuggingServer.reset();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (isHeadless()) {
|
||||||
|
platform::sleep(1.0 / params.tps * 1000);
|
||||||
|
} else {
|
||||||
|
nextFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (initialCursorLocked) {
|
||||||
|
input->toggleCursor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Engine::renderFrame() {
|
void Engine::renderFrame() {
|
||||||
screen->draw(time.getDelta());
|
screen->draw(time.getDelta());
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ public:
|
|||||||
void updateFrontend();
|
void updateFrontend();
|
||||||
void renderFrame();
|
void renderFrame();
|
||||||
void nextFrame();
|
void nextFrame();
|
||||||
|
void startPauseLoop();
|
||||||
|
|
||||||
/// @brief Set screen (scene).
|
/// @brief Set screen (scene).
|
||||||
/// nullptr may be used to delete previous screen before creating new one,
|
/// nullptr may be used to delete previous screen before creating new one,
|
||||||
|
|||||||
@@ -164,7 +164,85 @@ static int l_math_normal_random(lua::State* L) {
|
|||||||
|
|
||||||
constexpr inline int MAX_SHORT_STRING_LEN = 50;
|
constexpr inline int MAX_SHORT_STRING_LEN = 50;
|
||||||
|
|
||||||
static dv::value create_stack_trace(lua_State* L, int initFrame = 2) {
|
static dv::value collect_locals(lua::State* L, lua_Debug& frame) {
|
||||||
|
auto locals = dv::object();
|
||||||
|
|
||||||
|
int localIndex = 1;
|
||||||
|
const char* name;
|
||||||
|
while ((name = lua_getlocal(L, &frame, localIndex++))) {
|
||||||
|
if (name[0] == '(') {
|
||||||
|
lua::pop(L);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto local = dv::object();
|
||||||
|
|
||||||
|
int type = lua::type(L, -1);
|
||||||
|
switch (type) {
|
||||||
|
case LUA_TNIL:
|
||||||
|
local["short"] = "nil";
|
||||||
|
local["type"] = "nil";
|
||||||
|
break;
|
||||||
|
case LUA_TBOOLEAN:
|
||||||
|
local["short"] = lua::toboolean(L, -1) ? "true" : "false";
|
||||||
|
local["type"] = "boolean";
|
||||||
|
break;
|
||||||
|
case LUA_TNUMBER: {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << lua::tonumber(L, -1);
|
||||||
|
local["short"] = ss.str();
|
||||||
|
local["type"] = "number";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LUA_TSTRING: {
|
||||||
|
const char* str = lua::tostring(L, -1);
|
||||||
|
if (strlen(str) > MAX_SHORT_STRING_LEN) {
|
||||||
|
local["short"] = std::string(str, MAX_SHORT_STRING_LEN);
|
||||||
|
} else {
|
||||||
|
local["short"] = str;
|
||||||
|
}
|
||||||
|
local["type"] = "string";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LUA_TTABLE:
|
||||||
|
local["short"] = "{...}";
|
||||||
|
local["type"] = "table";
|
||||||
|
break;
|
||||||
|
case LUA_TFUNCTION: {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "function: 0x" << std::hex << lua::topointer(L, -1);
|
||||||
|
local["short"] = ss.str();
|
||||||
|
local["type"] = "function";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LUA_TUSERDATA: {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "userdata: 0x" << std::hex << lua::topointer(L, -1);
|
||||||
|
local["short"] = ss.str();
|
||||||
|
local["type"] = "userdata";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LUA_TTHREAD: {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "thread: 0x" << std::hex << lua::topointer(L, -1);
|
||||||
|
local["short"] = ss.str();
|
||||||
|
local["type"] = "thread";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "cdata: 0x" << std::hex << lua::topointer(L, -1);
|
||||||
|
local["short"] = ss.str();
|
||||||
|
local["type"] = "cdata";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
locals[name] = std::move(local);
|
||||||
|
lua::pop(L);
|
||||||
|
}
|
||||||
|
return locals;
|
||||||
|
}
|
||||||
|
|
||||||
|
static dv::value create_stack_trace(lua::State* L, int initFrame = 2) {
|
||||||
auto entriesList = dv::list();
|
auto entriesList = dv::list();
|
||||||
|
|
||||||
lua_Debug frame;
|
lua_Debug frame;
|
||||||
@@ -187,82 +265,7 @@ static dv::value create_stack_trace(lua_State* L, int initFrame = 2) {
|
|||||||
entry["line"] = frame.currentline;
|
entry["line"] = frame.currentline;
|
||||||
}
|
}
|
||||||
entry["what"] = frame.what;
|
entry["what"] = frame.what;
|
||||||
|
entry["locals"] = collect_locals(L, frame);
|
||||||
auto locals = dv::object();
|
|
||||||
|
|
||||||
int localIndex = 1;
|
|
||||||
const char* name;
|
|
||||||
while ((name = lua_getlocal(L, &frame, localIndex++))) {
|
|
||||||
if (name[0] == '(') {
|
|
||||||
lua::pop(L);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto local = dv::object();
|
|
||||||
|
|
||||||
int type = lua::type(L, -1);
|
|
||||||
switch (type) {
|
|
||||||
case LUA_TNIL:
|
|
||||||
local["short"] = "nil";
|
|
||||||
local["type"] = "nil";
|
|
||||||
break;
|
|
||||||
case LUA_TBOOLEAN:
|
|
||||||
local["short"] = lua::toboolean(L, -1) ? "true" : "false";
|
|
||||||
local["type"] = "boolean";
|
|
||||||
break;
|
|
||||||
case LUA_TNUMBER: {
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << lua::tonumber(L, -1);
|
|
||||||
local["short"] = ss.str();
|
|
||||||
local["type"] = "number";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LUA_TSTRING: {
|
|
||||||
const char* str = lua::tostring(L, -1);
|
|
||||||
if (strlen(str) > MAX_SHORT_STRING_LEN) {
|
|
||||||
local["short"] = std::string(str, MAX_SHORT_STRING_LEN);
|
|
||||||
} else {
|
|
||||||
local["short"] = str;
|
|
||||||
}
|
|
||||||
local["type"] = "string";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LUA_TTABLE:
|
|
||||||
local["short"] = "{...}";
|
|
||||||
local["type"] = "table";
|
|
||||||
break;
|
|
||||||
case LUA_TFUNCTION: {
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << "function: 0x" << std::hex << lua::topointer(L, -1);
|
|
||||||
local["short"] = ss.str();
|
|
||||||
local["type"] = "function";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LUA_TUSERDATA: {
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << "userdata: 0x" << std::hex << lua::topointer(L, -1);
|
|
||||||
local["short"] = ss.str();
|
|
||||||
local["type"] = "userdata";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LUA_TTHREAD: {
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << "thread: 0x" << std::hex << lua::topointer(L, -1);
|
|
||||||
local["short"] = ss.str();
|
|
||||||
local["type"] = "thread";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << "cdata: 0x" << std::hex << lua::topointer(L, -1);
|
|
||||||
local["short"] = ss.str();
|
|
||||||
local["type"] = "cdata";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
locals[name] = std::move(local);
|
|
||||||
lua::pop(L);
|
|
||||||
}
|
|
||||||
entry["locals"] = std::move(locals);
|
|
||||||
entriesList.add(std::move(entry));
|
entriesList.add(std::move(entry));
|
||||||
level++;
|
level++;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user