Editors also have some padding within their borders.
6C3UZDESM2HPFIHAW5YIPUV6VXO4YV5DIEY574HUGP2DGOQNUVOAC
ZV5ZL57L2M3Y4PQCAZDS44YMTASLVJZYDTEFSIMBQE5R7PJR2LHAC
AZS44H5MHGCREAQDHLCKHLN7CATGCGO2V4SZ6ZNLXEGYGIFUKDMQC
YFQRJ4EYPIIUN26G4XKLAXK4YHJ54IKUDI272U4UT6BP2JEXWK6QC
UGWH4VEHN5G6REWZU6BCXZ57AFU7PGK4MULMMHMJCMEMVVEDH2KAC
R5QXEHUIZLELJGGCZAE7ATNS3CLRJ7JFRENMGH4XXH24C5WABZDQC
O5GJ6PNNBYHH4X3DU4XOB7IDJ4QEW5KXFETIDUJESBUKJYXBSYYAC
7TQAF4BYIK75EEYCCK7VEUSZHNCWMWIA3HZGQKIILYESUZ5ZZRVQC
AKQBXWCVTZ5LEG76QW54B7MHXYFA7GD2Y2GSEN7RUXO5CHMYCZKAC
JIBCE66ZTWM5WEHEHNKKTRWBJQSQWBDDWPMOJIJR5Q676OSHYCNAC
SUPHTPXYKS4JBDPASHAYA5OBVJ45QT7ZV2HYNTF7OJYOKKS6DW5QC
BF7TW3EKRIDYC6J2Q2J4YOBAVQF55Y3H6KGZIHNXMH4N72MR6GXQC
TBPJ5WSRM5IKQH7FTAVYTWWUBWW7G2CLT5M6FN7CMPLD6Y77YIWQC
OLCKKDVSDTIBX5U3IRCLRL6KQMG2RDWKGDN4OTPI3WMN4FSX6ROQC
FBDRJ53NJ5BWDQGU2GWZ6NEYHKCCRD7RODMIG7QQZBRFUB4HR7OAC
ZANGJNNX6EITFBOF6NWCF2EM5BDQDEIOD4UPWMF5I6SKAURRTIHAC
X7HYGAL2QVKG7M5EMZ2VSH37UYWGE3EPUXYQBJOVL6IGJFZ2I5AAC
JE6PEYCDKZAOTTEWA35OZ2YGAEAWNHMAPCRPDI4ZV5H3NAVQVCSQC
XCEP7G5GRX6WQGCROJDNZRTLSITGAETL7EFCFTR74S36VXK32HBQC
DXFOMHQIWZ6EAUIDZQLY3ZRRDWJRB2VQHJXHBBNXQYCYCABIMJ5QC
initialize_global_viewport = function()
local minx, miny, maxx, maxy = surface_bounds(Definitions)
-- ensure 1px of white background all around
-- just in case the viewport ever goes
-- outside canvas bounds while animating
minx,miny, maxx,maxy = minx-1,miny-1, maxx+2,maxy+1
local zoomx = App.screen.width/(maxx-minx)
local zoomy = App.screen.height/(maxy-miny)
local zoom, cw, ch
if zoomx < zoomy then
zoom = zoomx
cw = maxx-minx
ch = cw*App.screen.height/App.screen.width
else
zoom = zoomy
ch = maxy-miny
cw = ch*App.screen.width/App.screen.height
end
Global_viewport = {x=minx, y=miny, w=cw, h=ch, zoom=zoom}
end
survey_animation = function()
---[[ '--' at start to disable animation, '---' to enable
local minx, miny, maxx, maxy = surface_bounds(Definitions)
-- ensure 1px of white background all around
-- just in case the viewport ever goes
-- outside canvas bounds while animating
minx,miny, maxx,maxy = minx-1,miny-1, maxx+2,maxy+1
local zoomx = App.screen.width/(maxx-minx)
local zoomy = App.screen.height/(maxy-miny)
local zoom, cw, ch
if zoomx < zoomy then
zoom = zoomx
cw = maxx-minx
ch = cw*App.screen.height/App.screen.width
else
zoom = zoomy
ch = maxy-miny
cw = ch*App.screen.width/App.screen.height
end
Global_viewport = {x=minx, y=miny, w=cw, h=ch, zoom=zoom}
snapshot_canvas()
-- initialize animation
Animating = {
copy_viewport(Global_viewport),
copy_viewport(Viewport),
}
Viewport.x = -App.screen.width/2
Viewport.y = -App.screen.height/2
Viewport.w = App.screen.width
Viewport.h = App.screen.height
Viewport.zoom = 1.0 --]]
end
on.code_submit = function(editor)
if not editor.load_time_error then
Manifest_navigator.reload = true
end
-- update definition backgrounds of failing tests
for name,node in pairs(Definitions) do
-- ignore temporary definitions with numeric indices; they haven't been saved yet
if type(name) == 'string' and starts_with(name, 'test_') then
if Client_app_test_failures[name] then
node.bg = Failing_test_definition_background_color
else
node.bg = Test_definition_background_color
end
end
end
A()
end
node.editor.load_time_error = nil
node.editor.load_time_error = Client_app_test_failures[name]
zoom_in = function(x,y)
-- precondition: Zoomed_out
-- precondition: Viewport == Global_viewport
-- precondition: Save_viewport exists
-- center Viewport on x,y at zoom level Saved_viewport.zoom
snapshot_canvas()
Animating = {
{
x=sx(x)-App.screen.width/Save_viewport.zoom/2,
y=sy(y)-App.screen.height/Save_viewport.zoom/2,
w=App.screen.width/Save_viewport.zoom,
h=App.screen.height/Save_viewport.zoom,
zoom=Save_viewport.zoom,
},
}
Zoomed_out = nil
Save_viewport = nil
end
animate_next_frame = function(state, dt)
if state.initial == nil then
state.initial = from_viewport(state)
-- once we've checked keys, pollute the keyspace
state.step = 0
state.frame_time = 0
return
end
state.frame_time = state.frame_time + dt
if state.frame_time > 0.01 then
state.frame_time = state.frame_time - 0.01
state.step = state.step+1
interpolate_viewport(state.initial, state, state.step)
B()
end
end
animate_next = function(dt)
if Animating[1].step and Animating[1].step >= Num_animation_frames then
table.remove(Animating, 1)
if #Animating == 0 then
Animating = nil
Canvas = nil
A()
return
end
end
animate_next_frame(Animating[1], dt)
end
snapshot_canvas = function()
-- Render the canvas at pixel perfect resolution.
local winw,winh = App.screen.width, App.screen.height
App.screen.width,App.screen.height = Global_viewport.w, Global_viewport.h
local saved_viewport = Viewport
Viewport = copy_viewport(Global_viewport)
Viewport.zoom = 1.0
A()
Canvas = love.graphics.newCanvas(Global_viewport.w, Global_viewport.h)
love.graphics.setCanvas(Canvas)
App.fake_key_press = true -- Hack; disable drawing the menu and ticks
on.draw()
App.fake_key_press = nil
love.graphics.setCanvas()
Viewport = saved_viewport
App.screen.width,App.screen.height = winw,winh
end
zoom_out = function()
Save_viewport = copy_viewport(Viewport)
snapshot_canvas()
Animating = {
copy_viewport(Global_viewport),
}
Zoomed_out = true
end
initialize_global_viewport()
interpolate_viewport = function(initial, final, step)
for k,v in pairs(initial) do
Viewport[k] = (initial[k]*(Num_animation_frames - step) + final[k]*step) / Num_animation_frames
end
end
Animating = nil -- set this to enable animation
-- When enabled, animation should consist of a series of viewport states that we animate into.
-- Each viewport state will be attained in Num_animation_frames frames, each of 0.01 ms or 1 Love frame.
-- Each state will specify the final state of various viewport keys. Keys not mentioned will remain unchanged.
draw_manifest_navigator = function()
App.color(Menu_command_color)
local filter_text = to_hud_text(Manifest_navigator.filter)
App.screen.draw(filter_text, 5, 5)
draw_cursor(5 + filter_text:getWidth(), 5)
App.color(Menu_background_color)
love.graphics.rectangle('fill', 0,Menu_bar_height, App.screen.width, Manifest_navigator.num_lines * (HUD_line_height + --[[highlight padding]]5))
local x,y = 5, Menu_bar_height
for i,definition in ipairs(Manifest_navigator.candidates) do
x,y = add_def_to_menu(x,y, definition, i == Manifest_navigator.index)
if Menu_cursor >= App.screen.width - 5 then
break
end
end
Manifest_navigator.bottom_y = y + HUD_line_height + --[[highlight padding]] 5
end
on_handle = function(x,y)
for _,node in ipairs(Surface) do
if node.type == 'text' then
if x >= vx(node.x) and node.w and x < vx(node.x + node.w/2-5) then
if y >= vy(node.y-30) and node.h and y < vy(node.y-10) then
return node
end
end
end
end
end
maybe_update_key_in_definitions = function(old_definition_name, definition_name, Cursor_node)
--print(old_definition_name, definition_name)
if old_definition_name ~= definition_name then
if old_definition_name == nil or Definitions[old_definition_name] ~= Cursor_node then
local pos = array.find(Definitions, Cursor_node)
--print('found at index', pos)
assert(pos)
table.remove(Definitions, pos)
elseif Definitions[old_definition_name] == Cursor_node then
--print('found at key', old_definition_name)
Definitions[old_definition_name] = nil
end
if definition_name and Definitions[definition_name] == nil then
--print('moving to key', definition_name)
Definitions[definition_name] = Cursor_node
elseif definition_name == nil or Definitions[definition_name] then
-- temporary collision; try again later
-- deleting and reinserting is inefficient, but hopefully rare
--print('moving to index', #Definitions+1)
table.insert(Definitions, Cursor_node)
end
--print('-- definition keys')
--for k in pairs(Definitions) do
--print(k)
--end
end
end
if Manifest_navigator.show then
draw_manifest_navigator()
return
end
if Zoomed_out == nil then
add_hotkey_to_menu('ctrl+g: zoom out')
else
add_hotkey_to_menu('ctrl+g: undo zoom out')
end
add_hotkey_to_menu('ctrl+l: load definition')
add_hotkey_to_menu('ctrl+n: new definition')
add_hotkey_to_menu('ctrl+d: delete definition')
if Animating then
local q = love.graphics.newQuad((Viewport.x-Global_viewport.x)*Viewport.zoom,(Viewport.y-Global_viewport.y)*Viewport.zoom, App.screen.width, App.screen.height, Global_viewport.w*Viewport.zoom, Global_viewport.h*Viewport.zoom)
App.color{r=1,g=1,b=1}
love.graphics.draw(Canvas, q, 0,0)
return
end
love.graphics.rectangle(obj.drawmode or 'fill', vx(obj.x),vy(obj.y), scale(obj.w),scale(obj.h), scale(obj.rx or 2), scale(obj.ry or 2))
love.graphics.rectangle(obj.drawmode or 'fill', vx(obj.x),vy(obj.y), scale(obj.w),scale(obj.h), scale(obj.rx or 5), scale(obj.ry or 5))
elseif chord == 'C-n' then
new_definition()
A()
elseif chord == 'C-l' then
Manifest_navigator.show = true
Manifest_navigator.for_delete = false
initialize_manifest_navigator()
elseif chord == 'C-d' then
Manifest_navigator.show = true
Manifest_navigator.for_delete = true
initialize_manifest_navigator()
node_to_render = {type='rectangle', drawmode='line', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, key=node.key}
node_to_render = {type='rectangle', drawmode='line', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x-5, y=node.y-5, key=node.key}
local node = on_handle(x,y)
if node then
-- move node
Move = {xoff=App.mouse_x()-vx(node.x), yoff=App.mouse_y()-vy(node.y), node=node}
return
end