about summary refs log tree commit diff stats
path: root/source_file.lua
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2022-09-05 11:28:03 -0700
committerKartik K. Agaram <vc@akkartik.com>2022-09-05 11:29:39 -0700
commit528c64d690c2d1cb4b3b70c37008b3ba37d904b9 (patch)
tree6a05d6d291276b5a3c63475686e02648f3091da6 /source_file.lua
parent9f94470f9dd56c03c66d98bbeff2fc60995cc0ae (diff)
downloadlines.love-528c64d690c2d1cb4b3b70c37008b3ba37d904b9.tar.gz
support drawings in the source editor
Diffstat (limited to 'source_file.lua')
-rw-r--r--source_file.lua156
1 files changed, 139 insertions, 17 deletions
diff --git a/source_file.lua b/source_file.lua
index 9c0b8a4..6552667 100644
--- a/source_file.lua
+++ b/source_file.lua
@@ -25,17 +25,21 @@ function load_from_file(infile)
     while true do
       local line = infile_next_line()
       if line == nil then break end
-      local line_info = {}
-      if line:find(Fold) then
-        _, _, line_info.data, line_info.dataB = line:find('([^'..Fold..']*)'..Fold..'([^'..Fold..']*)')
+      if line == '```lines' then  -- inflexible with whitespace since these files are always autogenerated
+        table.insert(result, load_drawing(infile_next_line))
       else
-        line_info.data = line
+        local line_info = {mode='text'}
+        if line:find(Fold) then
+          _, _, line_info.data, line_info.dataB = line:find('([^'..Fold..']*)'..Fold..'([^'..Fold..']*)')
+        else
+          line_info.data = line
+        end
+        table.insert(result, line_info)
       end
-      table.insert(result, line_info)
     end
   end
   if #result == 0 then
-    table.insert(result, {data=''})
+    table.insert(result, {mode='text', data=''})
   end
   return result
 end
@@ -46,16 +50,86 @@ function save_to_disk(State)
     error('failed to write to "'..State.filename..'"')
   end
   for _,line in ipairs(State.lines) do
-    outfile:write(line.data)
-    if line.dataB and #line.dataB > 0 then
-      outfile:write(Fold)
-      outfile:write(line.dataB)
+    if line.mode == 'drawing' then
+      store_drawing(outfile, line)
+    else
+      outfile:write(line.data)
+      if line.dataB and #line.dataB > 0 then
+        outfile:write(Fold)
+        outfile:write(line.dataB)
+      end
+      outfile:write('\n')
     end
-    outfile:write('\n')
   end
   outfile:close()
 end
 
+function load_drawing(infile_next_line)
+  local drawing = {mode='drawing', h=256/2, points={}, shapes={}, pending={}}
+  while true do
+    local line = infile_next_line()
+    assert(line)
+    if line == '```' then break end
+    local shape = json.decode(line)
+    if shape.mode == 'freehand' then
+      -- no changes needed
+    elseif shape.mode == 'line' or shape.mode == 'manhattan' then
+      local name = shape.p1.name
+      shape.p1 = Drawing.find_or_insert_point(drawing.points, shape.p1.x, shape.p1.y, --[[large width to minimize overlap]] 1600)
+      drawing.points[shape.p1].name = name
+      name = shape.p2.name
+      shape.p2 = Drawing.find_or_insert_point(drawing.points, shape.p2.x, shape.p2.y, --[[large width to minimize overlap]] 1600)
+      drawing.points[shape.p2].name = name
+    elseif shape.mode == 'polygon' or shape.mode == 'rectangle' or shape.mode == 'square' then
+      for i,p in ipairs(shape.vertices) do
+        local name = p.name
+        shape.vertices[i] = Drawing.find_or_insert_point(drawing.points, p.x,p.y, --[[large width to minimize overlap]] 1600)
+        drawing.points[shape.vertices[i]].name = name
+      end
+    elseif shape.mode == 'circle' or shape.mode == 'arc' then
+      local name = shape.center.name
+      shape.center = Drawing.find_or_insert_point(drawing.points, shape.center.x,shape.center.y, --[[large width to minimize overlap]] 1600)
+      drawing.points[shape.center].name = name
+    elseif shape.mode == 'deleted' then
+      -- ignore
+    else
+      print(shape.mode)
+      assert(false)
+    end
+    table.insert(drawing.shapes, shape)
+  end
+  return drawing
+end
+
+function store_drawing(outfile, drawing)
+  outfile:write('```lines\n')
+  for _,shape in ipairs(drawing.shapes) do
+    if shape.mode == 'freehand' then
+      outfile:write(json.encode(shape), '\n')
+    elseif shape.mode == 'line' or shape.mode == 'manhattan' then
+      local line = json.encode({mode=shape.mode, p1=drawing.points[shape.p1], p2=drawing.points[shape.p2]})
+      outfile:write(line, '\n')
+    elseif shape.mode == 'polygon' or shape.mode == 'rectangle' or shape.mode == 'square' then
+      local obj = {mode=shape.mode, vertices={}}
+      for _,p in ipairs(shape.vertices) do
+        table.insert(obj.vertices, drawing.points[p])
+      end
+      local line = json.encode(obj)
+      outfile:write(line, '\n')
+    elseif shape.mode == 'circle' then
+      outfile:write(json.encode({mode=shape.mode, center=drawing.points[shape.center], radius=shape.radius}), '\n')
+    elseif shape.mode == 'arc' then
+      outfile:write(json.encode({mode=shape.mode, center=drawing.points[shape.center], radius=shape.radius, start_angle=shape.start_angle, end_angle=shape.end_angle}), '\n')
+    elseif shape.mode == 'deleted' then
+      -- ignore
+    else
+      print(shape.mode)
+      assert(false)
+    end
+  end
+  outfile:write('```\n')
+end
+
 -- for tests
 function load_array(a)
   local result = {}
@@ -64,16 +138,64 @@ function load_array(a)
   while true do
     i,line = next_line(a, i)
     if i == nil then break end
-    local line_info = {}
-    if line:find(Fold) then
-      _, _, line_info.data, line_info.dataB = line:find('([^'..Fold..']*)'..Fold..'([^'..Fold..']*)')
+--?     print(line)
+    if line == '```lines' then  -- inflexible with whitespace since these files are always autogenerated
+--?       print('inserting drawing')
+      i, drawing = load_drawing_from_array(next_line, a, i)
+--?       print('i now', i)
+      table.insert(result, drawing)
     else
-      line_info.data = line
+--?       print('inserting text')
+      local line_info = {mode='text'}
+      if line:find(Fold) then
+        _, _, line_info.data, line_info.dataB = line:find('([^'..Fold..']*)'..Fold..'([^'..Fold..']*)')
+      else
+        line_info.data = line
+      end
+      table.insert(result, line_info)
     end
-    table.insert(result, line_info)
   end
   if #result == 0 then
-    table.insert(result, {data=''})
+    table.insert(result, {mode='text', data=''})
   end
   return result
 end
+
+function load_drawing_from_array(iter, a, i)
+  local drawing = {mode='drawing', h=256/2, points={}, shapes={}, pending={}}
+  local line
+  while true do
+    i, line = iter(a, i)
+    assert(i)
+--?     print(i)
+    if line == '```' then break end
+    local shape = json.decode(line)
+    if shape.mode == 'freehand' then
+      -- no changes needed
+    elseif shape.mode == 'line' or shape.mode == 'manhattan' then
+      local name = shape.p1.name
+      shape.p1 = Drawing.find_or_insert_point(drawing.points, shape.p1.x, shape.p1.y, --[[large width to minimize overlap]] 1600)
+      drawing.points[shape.p1].name = name
+      name = shape.p2.name
+      shape.p2 = Drawing.find_or_insert_point(drawing.points, shape.p2.x, shape.p2.y, --[[large width to minimize overlap]] 1600)
+      drawing.points[shape.p2].name = name
+    elseif shape.mode == 'polygon' or shape.mode == 'rectangle' or shape.mode == 'square' then
+      for i,p in ipairs(shape.vertices) do
+        local name = p.name
+        shape.vertices[i] = Drawing.find_or_insert_point(drawing.points, p.x,p.y, --[[large width to minimize overlap]] 1600)
+        drawing.points[shape.vertices[i]].name = name
+      end
+    elseif shape.mode == 'circle' or shape.mode == 'arc' then
+      local name = shape.center.name
+      shape.center = Drawing.find_or_insert_point(drawing.points, shape.center.x,shape.center.y, --[[large width to minimize overlap]] 1600)
+      drawing.points[shape.center].name = name
+    elseif shape.mode == 'deleted' then
+      -- ignore
+    else
+      print(shape.mode)
+      assert(false)
+    end
+    table.insert(drawing.shapes, shape)
+  end
+  return i, drawing
+end