mirror of
https://github.com/TangentFoxy/Piefiller.git
synced 2025-07-28 10:42:16 +00:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b433ddc889 | ||
|
9215842cc8 | ||
|
eb128e3ecc | ||
|
8869727321 | ||
|
c0bf02ccc1 | ||
|
5896dd043e |
32
README.md
32
README.md
@@ -4,37 +4,33 @@ Graphical profiler for Love2D >= 0.9.2
|
||||
|
||||
Originally by devfirefly, heavily modified by Guard13007.
|
||||
|
||||
NOTE: This ReadMe does not currently represent the state of the library as I am
|
||||
currently reworking it.
|
||||
Note that a lot of functionality is undocumented right now, and that some functionality doesn't work as originally intended (such as setting the position and scale of the profiler). The default settings should get you going pretty easily, the key thing to maybe change is calling the constructor with a table with its own `scale` value.
|
||||
|
||||
# Usage
|
||||
|
||||
1) Require the file:
|
||||
```lua
|
||||
local piefiller = require("piefiller")
|
||||
local Piefiller = require("piefiller")
|
||||
```
|
||||
2) Make a new instance of piefiller:
|
||||
```lua
|
||||
local Pie = piefiller:new()
|
||||
local pie = Piefiller()
|
||||
```
|
||||
3) Attach the piefiller to the part of your application that you want to monitor (love.update and love.draw typically are good places):
|
||||
```lua
|
||||
function love.update()
|
||||
Pie:attach()
|
||||
pie:attach()
|
||||
-- do something
|
||||
Pie:detach()
|
||||
pie:detach()
|
||||
end
|
||||
```
|
||||
4) Draw the output and pass events to your piefiller:
|
||||
4) Draw the output and pass key events to your piefiller:
|
||||
```lua
|
||||
function love.draw()
|
||||
Pie:draw()
|
||||
pie:draw()
|
||||
end
|
||||
function love.keypressed(key)
|
||||
Pie:keypressed(key)
|
||||
end
|
||||
function love.mousepressed(...)
|
||||
Pie:mousepressed(...)
|
||||
pie:keypressed(key)
|
||||
end
|
||||
```
|
||||
5) With sufficient output, press the `E` key to output to file. Example output:
|
||||
@@ -84,13 +80,13 @@ show_profiler
|
||||
|
||||
To redefine only one of the keys:
|
||||
```lua
|
||||
piefiller:setKey(command, key)
|
||||
pie:setKey(command, key)
|
||||
```
|
||||
|
||||
example:
|
||||
|
||||
```lua
|
||||
piefiller:setKey("increase_depth","up")
|
||||
pie:setKey("increase_depth","up")
|
||||
```
|
||||
|
||||
To redefine all of the keys:
|
||||
@@ -98,12 +94,12 @@ To redefine all of the keys:
|
||||
table = {
|
||||
"increase_depth" = "up"
|
||||
}
|
||||
piefiller:setKey(table)
|
||||
pie:setKey(table)
|
||||
```
|
||||
|
||||
# For your own interpretation
|
||||
|
||||
If you wish to interpret the data on your own use `piefiller:unpack()`.
|
||||
If you wish to interpret the data on your own use `pie:unpack()`.
|
||||
Output is a table as such:
|
||||
|
||||
```lua
|
||||
@@ -134,7 +130,3 @@ The best depth to search in is usually 2 and sometimes 3.
|
||||
When used in large applications the output may be too much to read, however you
|
||||
most likely will only be wanting to optimize the most expensive items. (And you
|
||||
can always output the data to review later.)
|
||||
|
||||
# Planned features
|
||||
|
||||
See my ToDo list, issue #1 on GitHub.
|
||||
|
34
main.lua
34
main.lua
@@ -1,8 +1,7 @@
|
||||
profilerOn = true
|
||||
drawRect = true
|
||||
|
||||
local Profiler = require("piefiller")
|
||||
local profiler = Profiler:new()
|
||||
local profiler = Profiler()
|
||||
|
||||
function iterateSmall()
|
||||
for i=1,1000 do
|
||||
@@ -31,10 +30,17 @@ function love.draw()
|
||||
|
||||
profiler:detach() -- was attached in update function
|
||||
|
||||
if profilerOn then
|
||||
-- profiler:draw({50}) -- did not appear to have a difference in 0.9.2 or 0.10.2
|
||||
profiler:draw()
|
||||
end
|
||||
-- temporary
|
||||
local w, h = love.graphics.getWidth(), love.graphics.getHeight()
|
||||
love.graphics.setColor(255, 255, 255, 255)
|
||||
love.graphics.rectangle("fill", 0, 0, w, h)
|
||||
|
||||
profiler:draw()
|
||||
|
||||
-- temporary
|
||||
love.graphics.setColor(255, 255, 255, 255)
|
||||
love.graphics.line(w/2, 0, w/2, h)
|
||||
love.graphics.line(0, h/2, w, h/2)
|
||||
end
|
||||
|
||||
function love.update(dt)
|
||||
@@ -49,7 +55,7 @@ end
|
||||
|
||||
function love.keypressed(key)
|
||||
if key == "escape" then
|
||||
profilerOn = not profilerOn
|
||||
love.event.quit()
|
||||
elseif key == ";" then
|
||||
drawRect = not drawRect
|
||||
end
|
||||
@@ -57,16 +63,12 @@ function love.keypressed(key)
|
||||
profiler:keypressed(key)
|
||||
end
|
||||
|
||||
function love.mousepressed(...)
|
||||
profiler:mousepressed(...)
|
||||
end
|
||||
|
||||
-- temporarily allowing for old behavior in 0.10.2
|
||||
function love.wheelmoved(x, y)
|
||||
local X, Y = love.mouse.getPosition()
|
||||
if y > 0 then
|
||||
love.mousepressed(X, Y, "wu")
|
||||
if y < 0 then
|
||||
-- up
|
||||
profiler.scale = profiler.scale - 0.1
|
||||
else
|
||||
love.mousepressed(X, Y, "wd")
|
||||
-- down
|
||||
profiler.scale = profiler.scale + 0.1
|
||||
end
|
||||
end
|
||||
|
220
piefiller.lua
220
piefiller.lua
@@ -2,9 +2,8 @@ local path = ...
|
||||
local piefiller = {}
|
||||
|
||||
local function hsvToRgb(h, s, v)
|
||||
local i, f, p, q, t, r, g, b -- was polluting with globals
|
||||
local i, f, p, q, t, r, g, b
|
||||
|
||||
-- local h,s,v = h,1,1 -- was ignoring s/v values entirely
|
||||
h = math.fmod(h, 360)
|
||||
|
||||
if s == 0 then return {v, v, v} end
|
||||
@@ -40,22 +39,24 @@ local function copy(t)
|
||||
return ret
|
||||
end
|
||||
|
||||
local function setColor(...) -- was global
|
||||
local function setColor(...)
|
||||
-- TODO factor this function out?
|
||||
local args = {...}
|
||||
love.graphics.setColor(args[1] or 255, args[2] or 255, args[3] or 255, args[4] or 255)
|
||||
end
|
||||
|
||||
-- TODO verify these do not break if using multiple profilers
|
||||
local color_data = {}
|
||||
local colors = {} -- the pool of available colors is removed from every time a new time is used
|
||||
local colors = {} -- NOTE the pool of available colors is removed from every time a new time is used
|
||||
|
||||
for i=0,300 do
|
||||
table.insert( colors, hsvToRgb(i, 1, 1) )
|
||||
end
|
||||
|
||||
function piefiller:new()
|
||||
function piefiller:new(settings)
|
||||
local self = {}
|
||||
setmetatable( self, {__index = piefiller} )
|
||||
|
||||
self.data = {}
|
||||
self.parsed = {}
|
||||
self.last = 0
|
||||
@@ -64,42 +65,58 @@ function piefiller:new()
|
||||
self.small = false
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
self.scale = 1
|
||||
self.scale = 0.4
|
||||
self.font = love.graphics.newFont(16 / self.scale)
|
||||
self.visible = true
|
||||
self.step = 1
|
||||
self.background = {0, 0, 0, 180}
|
||||
self.keys = {
|
||||
reset = "r",
|
||||
increase_depth = "down",
|
||||
decrease_depth = "up",
|
||||
-- TODO changing step_size should trigger a reset (by default, make it optional), because else the data is invalid
|
||||
increase_step_size = "=", -- changed default to "+" button
|
||||
decrease_step_size = "-", -- changed default to "-" button
|
||||
shorten_names = "z", -- changed default (based on assumption WASD is common control scheme)
|
||||
show_hidden = "h", -- changed default
|
||||
save_to_file = "e", -- changed default -> e for export
|
||||
show_profiler = "p", -- added new control to show/hide the profiler, default p
|
||||
increase_step_size = "=",
|
||||
decrease_step_size = "-",
|
||||
shorten_names = "z",
|
||||
show_hidden = "h",
|
||||
save_to_file = "e",
|
||||
show_profiler = "p",
|
||||
}
|
||||
|
||||
if settings then
|
||||
for k,v in pairs(settings) do
|
||||
if self[k] then
|
||||
self[k] = v
|
||||
end
|
||||
end
|
||||
if not type(self.keys) == "table" then
|
||||
self.keys = {}
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function piefiller:reset()
|
||||
self.data = {}
|
||||
-- why should these be reset? only the data matters
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
self.scale = 1
|
||||
-- self.x = 0
|
||||
-- self.y = 0
|
||||
-- self.scale = 1
|
||||
end
|
||||
|
||||
function piefiller:setKey(table_or_command,key)
|
||||
if type(table_or_command) == "table" then
|
||||
self.keys = table_or_command
|
||||
-- self.keys = table_or_command -- this was stupid and pointless actually, wtf
|
||||
for i,v in pairs(table_or_command) do
|
||||
if self.keys[i] then self.keys[i] = v end
|
||||
end
|
||||
elseif type(table_or_command) == "string" then
|
||||
if not self.keys[table_or_command] then error("Invalid command: "..tostring(table_or_command)) end
|
||||
self.keys[table_or_command] = key
|
||||
elseif not table_or_command then
|
||||
self.keys = {}
|
||||
else
|
||||
error("Expected table or string, got: "..type(table_or_command))
|
||||
error("Expected table, string, false, or nil; got: "..type(table_or_command))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -202,126 +219,115 @@ function piefiller:detach(stop) -- TODO figure out what stop is useful for
|
||||
if not stop then debug.sethook() end
|
||||
end
|
||||
|
||||
local largeFont = love.graphics.newFont(25)
|
||||
function piefiller:getText(v)
|
||||
if self.small then
|
||||
if v.src:sub(1,1) == "@" then
|
||||
return tostring(math.ceil(v.prc)).."% "..tostring(v.src:sub(2))..":"..tostring(v.def)
|
||||
else
|
||||
return tostring(math.ceil(v.prc)).."% "..tostring(v.src)..":"..tostring(v.def)
|
||||
end
|
||||
else
|
||||
if v.src:sub(1,1) == "@" then
|
||||
return tostring(math.ceil(v.prc)).."% "..tostring(v.name)..tostring(v.src)..":"..tostring(v.def)
|
||||
else
|
||||
return tostring(math.ceil(v.prc)).."% "..tostring(v.name).."@"..tostring(v.src)..":"..tostring(v.def)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- local largeFont = love.graphics.newFont(25)
|
||||
|
||||
function piefiller:draw(args)
|
||||
if not self.visible then return end
|
||||
|
||||
local loading
|
||||
local oldFont = love.graphics.getFont()
|
||||
local args = args or {}
|
||||
local rad = args.rad or 200
|
||||
-- these weren't even being used
|
||||
-- local mode = args["mode"] or "simple"
|
||||
-- local ret = args["return"]
|
||||
local oldLineJoin = love.graphics.getLineJoin()
|
||||
local pi = math.pi
|
||||
local arc = love.graphics.arc
|
||||
local w,h = love.graphics.getDimensions()
|
||||
|
||||
local args = args or {}
|
||||
local rad = args.radius or (h * self.scale - 2 / self.scale)
|
||||
local mode = args.mode or "original" -- "original" for the original style
|
||||
|
||||
love.graphics.push()
|
||||
|
||||
love.graphics.translate(self.x,self.y)
|
||||
love.graphics.translate(self.x, self.y)
|
||||
love.graphics.scale(self.scale)
|
||||
love.graphics.setLineJoin("bevel")
|
||||
love.graphics.setFont(self.font)
|
||||
|
||||
local cx = w/2 + (rad*2 - w)/2 + 2 / self.scale
|
||||
local cy = h * self.scale
|
||||
|
||||
local maxLength = 0
|
||||
for i,v in ipairs(self.parsed) do
|
||||
local s = self.font:getWidth(self:getText(v))
|
||||
if s > maxLength then maxLength = s end
|
||||
end
|
||||
setColor(self.background)
|
||||
love.graphics.rectangle("fill", 0, 0, cx * 2 + 2 / self.scale + maxLength, cy * 2)
|
||||
|
||||
if self.parsed and self.totaltime > 0 then
|
||||
local lastangle = 0
|
||||
local font = love.graphics.getFont()
|
||||
|
||||
for i,v in ipairs(self.parsed) do
|
||||
local color = v.color
|
||||
local cx,cy = w/2,h/2
|
||||
local angle = math.rad(3.6*v.prc)
|
||||
setColor(color)
|
||||
arc("fill",cx,cy,rad,lastangle,lastangle + angle)
|
||||
-- setColor(colors.black) -- not defined, actually needs to be white
|
||||
setColor(255, 255, 255, 255)
|
||||
if v.prc > 1 then
|
||||
arc("line",cx,cy,rad,lastangle,lastangle + angle)
|
||||
end
|
||||
lastangle = lastangle + angle
|
||||
setColor()
|
||||
end
|
||||
|
||||
lastangle = 0
|
||||
love.graphics.circle("line", cx, cy, rad) -- make sure there is an outer white border
|
||||
|
||||
local x = cx + rad + 2 / self.scale
|
||||
local y = cy - rad
|
||||
love.graphics.print("Depth: "..self.depth.." Step: "..self.step, x, y)
|
||||
y = y + self.font:getHeight()
|
||||
|
||||
local sorted = {}
|
||||
for i,v in ipairs(self.parsed) do
|
||||
local color = v.color
|
||||
local cx,cy = w/2,h/2
|
||||
local angle = math.rad(3.6*v.prc)
|
||||
local x = cx + rad * math.cos(lastangle + angle/2)
|
||||
local y = cy + rad * math.sin(lastangle + angle/2)
|
||||
if self.small then
|
||||
txt = tostring(v.src).." @: "..tostring(v.name)
|
||||
else
|
||||
txt = tostring(math.ceil(v.prc)).." % "..tostring(v.name).." : "..tostring(v.src).." @: "..tostring(v.def)
|
||||
end
|
||||
local fw = font:getWidth(txt)
|
||||
local sx = 1
|
||||
if cx < x then
|
||||
sx = -1
|
||||
fw = 0
|
||||
end
|
||||
if cy + rad/2 < y then
|
||||
y = y + font:getHeight()
|
||||
elseif cy + rad/2 > y then
|
||||
y = y - font:getHeight()
|
||||
end
|
||||
local ofx
|
||||
love.graphics.print(txt,((x) + (-(fw+20))*sx),y)
|
||||
lastangle = lastangle + angle
|
||||
sorted[i] = {i, v.prc}
|
||||
end
|
||||
table.sort(sorted,function(a,b)
|
||||
return a[2] > b[2]
|
||||
end)
|
||||
|
||||
for _,i in ipairs(sorted) do
|
||||
local v = self.parsed[i[1]]
|
||||
local color = v.color
|
||||
local txt = self:getText(v)
|
||||
setColor(color)
|
||||
love.graphics.print(txt, x, y)
|
||||
y = y + self.font:getHeight()
|
||||
end
|
||||
|
||||
else
|
||||
loading = true
|
||||
-- REFACTOR
|
||||
setColor()
|
||||
local t = "Loading..."
|
||||
local fh = self.font:getHeight()
|
||||
fw = self.font:getWidth(t)
|
||||
love.graphics.print("Loading...", w/2 - fw/2, h/2)
|
||||
-- END
|
||||
end
|
||||
|
||||
-- our timing is handled in draw... why? My guess is because we aren't called in update
|
||||
self.timer = self.timer + love.timer.getDelta()
|
||||
if self.timer > 20 then
|
||||
self.timer = 0
|
||||
end
|
||||
|
||||
love.graphics.setFont(largeFont)
|
||||
local t = "Depth: "..self.depth.." with step: "..self.step
|
||||
local fw = largeFont:getWidth(t)
|
||||
local fh = largeFont:getHeight()
|
||||
love.graphics.print(t,w/2 - fw/2,(fh+5))
|
||||
if loading then
|
||||
t = "Loading..."
|
||||
fw = largeFont:getWidth(t)
|
||||
love.graphics.print("Loading...",w/2 - fw/2,h/2)
|
||||
end
|
||||
|
||||
love.graphics.pop()
|
||||
|
||||
love.graphics.setFont(oldFont)
|
||||
end
|
||||
|
||||
function piefiller:mousepressed(x,y,b)
|
||||
if b == "wu" then
|
||||
local scale = self.scale - math.floor((0.05*self.scale)*1000)/1000
|
||||
if scale > 0 and scale > 0.1 then
|
||||
local lastzoom = self.scale
|
||||
local mouse_x = x - self.x
|
||||
local mouse_y = y - self.y
|
||||
self.scale = scale
|
||||
local newx = mouse_x * (self.scale/lastzoom)
|
||||
local newy = mouse_y * (self.scale/lastzoom)
|
||||
self.x = self.x + (mouse_x-newx)
|
||||
self.y = self.y + (mouse_y-newy)
|
||||
else
|
||||
self.scale = 0.1
|
||||
end
|
||||
elseif b == "wd" then
|
||||
local scale = self.scale + math.floor((0.05*self.scale)*1000)/1000
|
||||
local scalex = self.scale
|
||||
if scale > 0 and scale < 20 then
|
||||
local lastzoom = self.scale
|
||||
local mouse_x = x - self.x
|
||||
local mouse_y = y - self.y
|
||||
self.scale = scale
|
||||
local newx = mouse_x * (self.scale/lastzoom)
|
||||
local newy = mouse_y * (self.scale/lastzoom)
|
||||
self.x = self.x + (mouse_x-newx)
|
||||
self.y = self.y + (mouse_y-newy)
|
||||
else
|
||||
self.scale = 20
|
||||
end
|
||||
end
|
||||
love.graphics.setLineJoin(oldLineJoin)
|
||||
end
|
||||
|
||||
function piefiller:keypressed(key)
|
||||
@@ -340,16 +346,24 @@ function piefiller:keypressed(key)
|
||||
self.depth = self.depth + 1
|
||||
elseif command == "decrease_depth" then
|
||||
self:reset()
|
||||
self.depth = self.depth - 1
|
||||
if self.depth > 1 then
|
||||
self.depth = self.depth - 1
|
||||
end
|
||||
elseif command == "increase_step_size" then
|
||||
self.step = self.step - 1
|
||||
self:reset()
|
||||
self.step = self.step + 1
|
||||
elseif command == "decrease_step_size" then
|
||||
self.step = self.step +1
|
||||
self:reset()
|
||||
if self.step > 0 then
|
||||
self.step = self.step - 1
|
||||
end
|
||||
elseif command == "shorten_names" then
|
||||
self.small = not self.small
|
||||
elseif command == "show_hidden" then
|
||||
self:reset()
|
||||
self.view_children = not self.view_children
|
||||
elseif command == "show_profiler" then
|
||||
self.visible = not self.visible
|
||||
elseif command == "save_to_file" then
|
||||
local parsed = copy(self.parsed)
|
||||
table.sort(parsed,function(a,b)
|
||||
@@ -407,4 +421,6 @@ function piefiller:unpack(fn)
|
||||
return data
|
||||
end
|
||||
|
||||
setmetatable( piefiller, { __call = piefiller.new } )
|
||||
|
||||
return piefiller
|
||||
|
Reference in New Issue
Block a user