mirror of
https://github.com/pound-emu/ballistic.git
synced 2026-06-17 04:16:48 -07:00
This adds luajit-imgui without submodules. Signed-off-by: Ronald Caesar <github43132@proton.me>
256 lines
12 KiB
Lua
256 lines
12 KiB
Lua
--from Flix code
|
|
--Timeline Stuff Here (from: https://github.com/nem0/LumixEngine/blob/timeline_gui/external/imgui/imgui_user.inl)=
|
|
-- Improved with code by @meshula (panzoomer here: https://github.com/ocornut/imgui/issues/76)
|
|
-- removed clipping code to allow using ImGuiListClipper from main
|
|
local function loader(ig)
|
|
local M = {}
|
|
|
|
local ffi = require"ffi"
|
|
local s_max_timeline_value=0;
|
|
local s_ptimeline_offset_and_scale = NULL;
|
|
|
|
|
|
function M.BeginTimeline(str_id, max_value, num_visible_rows, popt_offset_and_scale)
|
|
|
|
-- reset global variables
|
|
s_max_timeline_value=0.;
|
|
s_ptimeline_offset_and_scale = popt_offset_and_scale;
|
|
|
|
if (s_ptimeline_offset_and_scale~=nil) then
|
|
if (s_ptimeline_offset_and_scale.y==0) then s_ptimeline_offset_and_scale.y=1; end
|
|
end
|
|
local row_height = ig.GetTextLineHeightWithSpacing();
|
|
local rv = ig.BeginChild(str_id,ig.ImVec2(0,num_visible_rows>0 and (row_height*(num_visible_rows+1)) or (ig.GetContentRegionAvail().y-row_height*1.2)),false);
|
|
ig.PushStyleColor(ig.lib.ImGuiCol_Separator,ig.GetStyle().Colors[ig.lib.ImGuiCol_Border]);
|
|
ig.Columns(2,str_id);
|
|
local contentRegionWidth = ig.GetContentRegionAvail().x
|
|
if (ig.GetColumnOffset(1)>=contentRegionWidth*0.48) then ig.SetColumnOffset(1,contentRegionWidth*0.15); end
|
|
s_max_timeline_value = max_value>=0 and max_value or (contentRegionWidth*0.85);
|
|
|
|
return rv;
|
|
end
|
|
|
|
function M.TimelineEvent(str_id, values, keep_range_constant)
|
|
|
|
--print(str_id)
|
|
local row_height = ig.GetTextLineHeightWithSpacing();
|
|
local TIMELINE_RADIUS = row_height*0.45;
|
|
local row_height_offset = (row_height-TIMELINE_RADIUS*2)*0.5;
|
|
|
|
|
|
local win = ig.GetCurrentWindow();
|
|
local inactive_color = ig.ColorConvertFloat4ToU32(ig.GetStyle().Colors[ig.lib.ImGuiCol_Button]);
|
|
local active_color = ig.ColorConvertFloat4ToU32(ig.GetStyle().Colors[ig.lib.ImGuiCol_ButtonHovered]);
|
|
local line_color = ig.ColorConvertFloat4ToU32(ig.GetStyle().Colors[ig.lib.ImGuiCol_SeparatorActive]);
|
|
local changed = false;
|
|
local hovered = false;
|
|
local active = false;
|
|
|
|
ig.Text("%s",str_id);
|
|
ig.NextColumn();
|
|
|
|
|
|
local s_timeline_time_offset = s_ptimeline_offset_and_scale~=nil and s_ptimeline_offset_and_scale.x or 0;
|
|
local s_timeline_time_scale = s_ptimeline_offset_and_scale~=nil and s_ptimeline_offset_and_scale.y or 1;
|
|
|
|
local columnOffset = ig.GetColumnOffset(1);
|
|
local columnWidth = ig.GetColumnWidth(1)-ig.GetStyle().ScrollbarSize;
|
|
local columnWidthScaled = columnWidth * s_timeline_time_scale;
|
|
local columnWidthOffsetScaled = columnWidthScaled * s_timeline_time_offset;
|
|
--local cursor_pos = ig.ImVec2(ig.GetWindowContentRegionMin().x + win.Pos.x+columnOffset-TIMELINE_RADIUS,win.DC.CursorPos.y);
|
|
local cursor_pos = ig.ImVec2(ig.GetCursorPos().x + win.Pos.x+columnOffset-TIMELINE_RADIUS,win.DC.CursorPos.y);
|
|
local mustMoveBothEnds=false;
|
|
local isMouseDraggingZero = ig.IsMouseDragging(0);
|
|
local posx = ffi.new("float[?]",2,{0,0});
|
|
|
|
for i=0,1 do
|
|
local pos = ig.ImVec2(cursor_pos);
|
|
pos.x = pos.x + columnWidthScaled * values[i] / s_max_timeline_value - columnWidthOffsetScaled + TIMELINE_RADIUS;
|
|
pos.y = pos.y + row_height_offset+TIMELINE_RADIUS;
|
|
posx[i] = pos.x;
|
|
--if (pos.x+TIMELINE_RADIUS < cursor_pos.x or pos.x-2*TIMELINE_RADIUS > cursor_pos.x+columnWidth) continue; -- culling
|
|
if (pos.x+TIMELINE_RADIUS >= cursor_pos.x and pos.x-2*TIMELINE_RADIUS <= cursor_pos.x+columnWidth) then
|
|
ig.SetCursorScreenPos(pos - ig.ImVec2(TIMELINE_RADIUS, TIMELINE_RADIUS));
|
|
ig.PushID(i);
|
|
ig.InvisibleButton(str_id, ig.ImVec2(2 * TIMELINE_RADIUS, 2 * TIMELINE_RADIUS));
|
|
active = ig.IsItemActive();
|
|
if (active or ig.IsItemHovered()) then
|
|
ig.SetTooltip("%f", values[i]);
|
|
if (not keep_range_constant) then
|
|
-- @meshula:The item hovered line needs to be compensated for vertical scrolling. Thx!
|
|
local a = ig.ImVec2(pos.x, ig.GetCursorPos().y + win.Pos.y + win.Scroll.y);
|
|
local b = ig.ImVec2(pos.x, ig.GetContentRegionAvail().y + ig.GetCursorPos().y + win.Pos.y + win.Scroll.y);
|
|
-- possible aternative:
|
|
--ImVec2 a(pos.x, win->Pos.y);
|
|
--ImVec2 b(pos.x, win->Pos.y+win->Size.y);
|
|
win.DrawList:AddLine(a, b, line_color);
|
|
end
|
|
hovered = true;
|
|
end
|
|
if (active and isMouseDraggingZero) then
|
|
if (not keep_range_constant) then
|
|
values[i] = values[i] + ig.GetIO().MouseDelta.x / columnWidthScaled * s_max_timeline_value;
|
|
if (values[i]<0) then values[i]=0;
|
|
elseif (values[i]>s_max_timeline_value) then values[i]=s_max_timeline_value; end
|
|
else
|
|
mustMoveBothEnds = true;
|
|
end
|
|
changed , hovered = true,true;
|
|
end
|
|
ig.PopID();
|
|
win.DrawList:AddCircleFilled(
|
|
pos, TIMELINE_RADIUS, (ig.IsItemActive() or ig.IsItemHovered()) and active_color or inactive_color,8);
|
|
end
|
|
end
|
|
|
|
local start = ig.ImVec2(posx[0]+TIMELINE_RADIUS*0.5,cursor_pos.y+row_height*0.1)--*0.3);
|
|
local endp = ig.ImVec2(posx[1]-TIMELINE_RADIUS*0.5,start.y+row_height*0.8)--*0.4);
|
|
|
|
if (start.x<cursor_pos.x) then start.x=cursor_pos.x; end
|
|
if (endp.x>cursor_pos.x+columnWidth+TIMELINE_RADIUS) then endp.x=cursor_pos.x+columnWidth+TIMELINE_RADIUS; end
|
|
local isInvisibleButtonCulled = start.x >= cursor_pos.x+columnWidth or endp.x<=cursor_pos.x;
|
|
|
|
local isInvisibleButtonItemActive=false;
|
|
local isInvisibleButtonItemHovered=false;
|
|
if (not isInvisibleButtonCulled) then
|
|
ig.PushID(-1);
|
|
ig.SetCursorScreenPos(start);
|
|
ig.InvisibleButton(str_id, endp - start);
|
|
isInvisibleButtonItemActive = ig.IsItemActive();
|
|
isInvisibleButtonItemHovered = isInvisibleButtonItemActive or ig.IsItemHovered();
|
|
ig.PopID();
|
|
win.DrawList:AddRectFilled(start, endp, (isInvisibleButtonItemActive or isInvisibleButtonItemHovered) and active_color or inactive_color);
|
|
end
|
|
if ((isInvisibleButtonItemActive and isMouseDraggingZero) or mustMoveBothEnds) then
|
|
local deltaX = ig.GetIO().MouseDelta.x / columnWidthScaled * s_max_timeline_value;
|
|
values[0] = values[0] + deltaX;
|
|
values[1] = values[1] + deltaX;
|
|
changed, hovered = true,true;
|
|
elseif (isInvisibleButtonItemHovered) then
|
|
hovered = true;
|
|
end
|
|
|
|
ig.SetCursorScreenPos(cursor_pos + ig.ImVec2(0, row_height));
|
|
ig.Dummy(ig.ImVec2(0,0))
|
|
if (changed) then
|
|
if (values[0]>values[1]) then local tmp=values[0];values[0]=values[1];values[1]=tmp; end
|
|
if (values[1]>s_max_timeline_value) then values[0]= values[0] -(values[1]-s_max_timeline_value);values[1]=s_max_timeline_value; end
|
|
if (values[0]<0) then values[1]=values[1]-values[0];values[0]=0; end
|
|
end
|
|
|
|
if (hovered) then ig.SetMouseCursor(ig.lib.ImGuiMouseCursor_Hand) end
|
|
|
|
ig.NextColumn();
|
|
return changed;
|
|
end
|
|
|
|
|
|
function M.EndTimeline( num_vertical_grid_lines, current_time, timeline_running_color)
|
|
local row_height = ig.GetTextLineHeightWithSpacing();
|
|
|
|
ig.NextColumn();
|
|
|
|
local win = ig.GetCurrentWindow();
|
|
|
|
local columnOffset = ig.GetColumnOffset(1);
|
|
local columnWidth = ig.GetColumnWidth(1)-ig.GetStyle().ScrollbarSize;
|
|
local s_timeline_time_offset = s_ptimeline_offset_and_scale~=nil and s_ptimeline_offset_and_scale.x or 0;
|
|
local s_timeline_time_scale = s_ptimeline_offset_and_scale~=nil and s_ptimeline_offset_and_scale.y or 1;
|
|
local columnWidthScaled = columnWidth*s_timeline_time_scale;
|
|
local columnWidthOffsetScaled = columnWidthScaled * s_timeline_time_offset;
|
|
local horizontal_interval = columnWidth / num_vertical_grid_lines;
|
|
|
|
local color = ig.ColorConvertFloat4ToU32(ig.GetStyle().Colors[ig.lib.ImGuiCol_Button]);
|
|
local line_color = ig.ColorConvertFloat4ToU32(ig.GetStyle().Colors[ig.lib.ImGuiCol_Border]);
|
|
local text_color = ig.ColorConvertFloat4ToU32(ig.GetStyle().Colors[ig.lib.ImGuiCol_Text]);
|
|
local moving_line_color = ig.ColorConvertFloat4ToU32(ig.GetStyle().Colors[ig.lib.ImGuiCol_SeparatorActive]);
|
|
local rounding = ig.GetStyle().ScrollbarRounding;
|
|
local startY = ig.GetWindowHeight() + win.Pos.y;
|
|
|
|
-- Draw black vertical lines (inside scrolling area)
|
|
for i=1,num_vertical_grid_lines do
|
|
local a = ig.GetCursorPos() + win.Pos;
|
|
a.x = a.x + s_timeline_time_scale * i * horizontal_interval + columnOffset - columnWidthOffsetScaled;
|
|
win.DrawList:AddLine(a, ig.ImVec2(a.x,startY), line_color);
|
|
end
|
|
|
|
-- Draw moving vertical line
|
|
if (current_time>0 and current_time<s_max_timeline_value) then
|
|
local a = ig.GetCursorPos() + win.Pos;
|
|
a.x = a.x + columnWidthScaled*(current_time/s_max_timeline_value)+columnOffset-columnWidthOffsetScaled;
|
|
win.DrawList:AddLine(a, ig.ImVec2(a.x,startY), moving_line_color,3);
|
|
end
|
|
|
|
ig.Columns(1);
|
|
ig.PopStyleColor();
|
|
|
|
ig.EndChild();
|
|
local isChildWindowHovered = s_ptimeline_offset_and_scale~=nil and ig.IsItemHovered() or false;
|
|
|
|
-- Draw bottom axis ribbon (outside scrolling region)
|
|
win = ig.GetCurrentWindow();
|
|
local startx = ig.GetCursorScreenPos().x + columnOffset;
|
|
local endy = ig.GetCursorScreenPos().y+row_height;--GetWindowContentRegionMax().y + win->Pos.y;
|
|
local start = ig.ImVec2(startx,ig.GetCursorScreenPos().y);
|
|
local endp = ig.ImVec2(startx+columnWidth,endy);--start.y+row_height);
|
|
local maxx = start.x+columnWidthScaled-columnWidthOffsetScaled;
|
|
if (maxx<endp.x) then endp.x = maxx end
|
|
if (current_time<=0) then win.DrawList:AddRectFilled(start, endp, color, rounding)
|
|
elseif (current_time>s_max_timeline_value) then win.DrawList:AddRectFilled(start, endp, timeline_running_color, rounding);
|
|
else
|
|
local median = ig.ImVec2(start.x+columnWidthScaled*(current_time/s_max_timeline_value)-columnWidthOffsetScaled,endp.y);
|
|
if (median.x<startx) then median.x=startx;
|
|
else
|
|
if (median.x>startx+columnWidth) then median.x=startx+columnWidth; end
|
|
win.DrawList:AddRectFilled(start, median, timeline_running_color, rounding,ig.lib.ImDrawFlags_RoundCornersLeft);
|
|
end
|
|
median.y=start.y;
|
|
if (median.x<startx+columnWidth) then
|
|
win.DrawList:AddRectFilled(median, endp, color, rounding,ig.lib.ImDrawFlags_RoundCornersRight);
|
|
if (median.x>startx) then win.DrawList:AddLine(median, ig.ImVec2(median.x,endp.y), moving_line_color,3); end
|
|
end
|
|
end
|
|
|
|
local tmp = ffi.new("char[?]",256);
|
|
for i = 0,num_vertical_grid_lines-1 do
|
|
local a = ig.ImVec2(start);
|
|
a.x = start.x + s_timeline_time_scale * i * horizontal_interval - columnWidthOffsetScaled;
|
|
--if (a.x < startx or a.x >= startx+columnWidth) continue;
|
|
if (a.x >= startx and a.x < startx+columnWidth) then
|
|
ig.ImFormatString(tmp, ffi.sizeof(tmp), "%.2f", i * s_max_timeline_value / num_vertical_grid_lines);
|
|
win.DrawList:AddText(a, text_color, tmp);
|
|
end
|
|
end
|
|
ig.SetCursorPosY(ig.GetCursorPosY()+row_height);
|
|
ig.Dummy(ig.ImVec2(0,0))
|
|
|
|
-- zoom and pan
|
|
if (s_ptimeline_offset_and_scale~=nil) then
|
|
local iog = ig.GetIO();
|
|
if (isChildWindowHovered and iog.KeyCtrl) then
|
|
if (ig.IsMouseDragging(1)) then
|
|
-- pan
|
|
s_ptimeline_offset_and_scale.x=s_ptimeline_offset_and_scale.x-(iog.MouseDelta.x/columnWidthScaled);
|
|
if (s_ptimeline_offset_and_scale.x>1) then s_ptimeline_offset_and_scale.x=1;
|
|
elseif (s_ptimeline_offset_and_scale.x<0) then s_ptimeline_offset_and_scale.x=0; end
|
|
elseif (iog.MouseReleased[2]) then
|
|
-- reset
|
|
s_ptimeline_offset_and_scale.x=0;
|
|
s_ptimeline_offset_and_scale.y=1;
|
|
end
|
|
if (iog.MouseWheel~=0) then
|
|
-- zoom
|
|
s_ptimeline_offset_and_scale.y=s_ptimeline_offset_and_scale.y*((iog.MouseWheel>0) and 1.05 or 0.95);
|
|
if (s_ptimeline_offset_and_scale.y<0.25) then s_ptimeline_offset_and_scale.y=0.25;
|
|
elseif (s_ptimeline_offset_and_scale.y>4.) then s_ptimeline_offset_and_scale.y=4; end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
return M
|
|
end
|
|
|
|
return loader
|