require("imgui") local class = require("class") local DebugWindow = require("debug_overlay.debugwindow") 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 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) local fun_name = parts[1]:lower() local command = self.commands[fun_name] if not command then self:log("Command not found : "..fun_name, ERROR) else 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 self.input_text = "" self.take_focus = true end imgui.End() 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:info(str) self:log(str, INFO) end function Console:warn(str) self:log(str, WARN) end function Console:debug(str) self:log(str, DEBUG) end function Console:error(str) self:log(str, ERROR) end function Console:registerCommand(name, fun, help) self.commands[name] = fun if help then self.command_helps[name] = help end end return Console