|
|
@@ -0,0 +1,174 @@
|
|
|
+local class = require("class")
|
|
|
+local DebugWindow = require("debug_overlay.debugwindow")
|
|
|
+require "imgui"
|
|
|
+
|
|
|
+local commands = require("debug_overlay.console.commands")
|
|
|
+local Console = class(DebugWindow)
|
|
|
+
|
|
|
+local INFO = 1
|
|
|
+local DEBUG = 2
|
|
|
+local LOG = 3
|
|
|
+local WARN = 4
|
|
|
+local ERROR = 5
|
|
|
+
|
|
|
+local function bind(new_self, fun, ...)
|
|
|
+ return function(...)
|
|
|
+ fun(new_self, ...)
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+local function splitArgs(text)
|
|
|
+ local result = {}
|
|
|
+ local e = 0
|
|
|
+ while true do
|
|
|
+ local b = e+1
|
|
|
+ b = text:find("%S",b)
|
|
|
+ if b==nil then break end
|
|
|
+ if text:sub(b,b)=="'" then
|
|
|
+ e = text:find("'",b+1)
|
|
|
+ b = b+1
|
|
|
+ elseif text:sub(b,b)=='"' then
|
|
|
+ e = text:find('"',b+1)
|
|
|
+ b = b+1
|
|
|
+ else
|
|
|
+ e = text:find("%s",b+1)
|
|
|
+ end
|
|
|
+ if e==nil then e=#text+1 end
|
|
|
+ result[#result+1] = text:sub(b,e-1)
|
|
|
+ end
|
|
|
+ return result
|
|
|
+end
|
|
|
+
|
|
|
+function Console:init()
|
|
|
+ self.shortcut = "f12"
|
|
|
+ self.logs = {}
|
|
|
+ self.logs_filter_toggles = {}
|
|
|
+ self.visible = false;
|
|
|
+ self.input_text = "";
|
|
|
+ self.commands = {}
|
|
|
+ self.command_helps = {}
|
|
|
+ self.take_focus = false
|
|
|
+ self.scroll_to_bottom = true
|
|
|
+
|
|
|
+ for i=1,5 do
|
|
|
+ self.logs_filter_toggles[i] = true
|
|
|
+ end
|
|
|
+
|
|
|
+ for i,v in pairs(commands) do
|
|
|
+ self:registerCommand(i, bind(self, commands[i].fun), v.help)
|
|
|
+ end
|
|
|
+
|
|
|
+end
|
|
|
+
|
|
|
+function Console:render()
|
|
|
+ imgui.SetNextWindowPos(0, love.graphics.getHeight() - 200, 1);
|
|
|
+ imgui.SetNextWindowSize(love.graphics.getWidth(), 200);
|
|
|
+
|
|
|
+ imgui.Begin("Console", nil, {"NoCollapse", "NoResize", "NoMove", "NoTitleBar"})
|
|
|
+
|
|
|
+ if imgui.Button("Bottom") then self.scroll_to_bottom = true end
|
|
|
+ for k,v in ipairs({"Info", "Debug", "Log", "Warn", "Error"}) do
|
|
|
+ imgui.SameLine()
|
|
|
+ if imgui.Checkbox(v, self.logs_filter_toggles[k]) then
|
|
|
+ self.logs_filter_toggles[k] = not self.logs_filter_toggles[k]
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+
|
|
|
+ imgui.BeginChild("Console log", 0,-imgui.GetItemsLineHeightWithSpacing())
|
|
|
+
|
|
|
+ for k,l in ipairs(self.logs) do
|
|
|
+ local color = 0xFFFFFF
|
|
|
+ if self.logs_filter_toggles[l.level] then
|
|
|
+ if l.level == 1 then
|
|
|
+ imgui.PushStyleColor("Text", 0.6,0.6,0.6,1)
|
|
|
+ elseif l.level == 2 then
|
|
|
+ imgui.PushStyleColor("Text", 0.4,0.4,0.6,1)
|
|
|
+ elseif l.level == 3 then
|
|
|
+ imgui.PushStyleColor("Text", 1,1,1,1)
|
|
|
+ elseif l.level == 4 then
|
|
|
+ imgui.PushStyleColor("Text", 1,1,0,1)
|
|
|
+ elseif l.level == 5 then
|
|
|
+ imgui.PushStyleColor("Text", 1,0.2,0.2,1)
|
|
|
+ end
|
|
|
+ imgui.TextUnformatted(l.msg)
|
|
|
+ imgui.PopStyleColor(1)
|
|
|
+ end
|
|
|
+ end
|
|
|
+ if self.scroll_to_bottom then
|
|
|
+ imgui.SetScrollHere();
|
|
|
+ self.scroll_to_bottom = false;
|
|
|
+ end
|
|
|
+ imgui.EndChild()
|
|
|
+
|
|
|
+
|
|
|
+ local status = false
|
|
|
+ imgui.PushItemWidth(imgui.GetContentRegionAvailWidth())
|
|
|
+ status, self.input_text = imgui.InputText("", self.input_text, 256, {"EnterReturnsTrue"})
|
|
|
+ imgui.PopItemWidth()
|
|
|
+
|
|
|
+ if self.take_focus then
|
|
|
+ imgui.SetKeyboardFocusHere(0)
|
|
|
+ self.take_focus = false
|
|
|
+ end
|
|
|
+
|
|
|
+ if status then
|
|
|
+ self:enterCommand()
|
|
|
+ end
|
|
|
+ imgui.End()
|
|
|
+end
|
|
|
+
|
|
|
+function Console:enterCommand()
|
|
|
+ if self.input_text == "" then return end
|
|
|
+ local command_line = self.input_text
|
|
|
+ local parts = splitArgs(command_line)
|
|
|
+ local args = {}
|
|
|
+ for i=2,#parts do
|
|
|
+ args[i-1] = parts[i]
|
|
|
+ end
|
|
|
+ self:log("> "..self.input_text, 1)
|
|
|
+ self:processCommand(parts[1]:lower(), args)
|
|
|
+ self.input_text = ""
|
|
|
+ self.take_focus = true
|
|
|
+end
|
|
|
+
|
|
|
+function Console:toggle()
|
|
|
+ DebugWindow.toggle(self)
|
|
|
+ if self.visible then
|
|
|
+ self.take_focus = true
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function Console:log(str, level)
|
|
|
+ self.logs[#self.logs + 1] = {
|
|
|
+ msg = str,
|
|
|
+ level = level or 3
|
|
|
+ }
|
|
|
+ self.scroll_to_bottom = true
|
|
|
+end
|
|
|
+
|
|
|
+function Console:registerCommand(name, fun, help)
|
|
|
+ self.commands[name] = fun
|
|
|
+ if help then
|
|
|
+ self.command_helps[name] = help
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function Console:processCommand(fun_name, args)
|
|
|
+ local command = self.commands[fun_name]
|
|
|
+ if not command then
|
|
|
+ self:log("Command not found : "..fun_name, ERROR)
|
|
|
+ return
|
|
|
+ end
|
|
|
+
|
|
|
+ local processed_commands = {}
|
|
|
+ local f = function()
|
|
|
+ command(unpack(args))
|
|
|
+ end
|
|
|
+ local success, result = xpcall(f, function(err) return debug.traceback(err) end)
|
|
|
+ if not success then
|
|
|
+ self:log(result, ERROR)
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+return Console
|