utils.lua 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. -- Some utility functions that shouldn't be exposed.
  2. local utils = {}
  3. -- https://github.com/stevedonovan/Penlight/blob/master/lua/pl/path.lua#L286
  4. function utils.format_path(path)
  5. local np_gen1,np_gen2 = '[^SEP]+SEP%.%.SEP?','SEP+%.?SEP'
  6. local np_pat1, np_pat2 = np_gen1:gsub('SEP','/'), np_gen2:gsub('SEP','/')
  7. local k
  8. repeat -- /./ -> /
  9. path,k = path:gsub(np_pat2,'/',1)
  10. until k == 0
  11. repeat -- A/../ -> (empty)
  12. path,k = path:gsub(np_pat1,'',1)
  13. until k == 0
  14. if path == '' then path = '.' end
  15. return path
  16. end
  17. -- Compensation for scale/rotation shift
  18. function utils.compensate(tile, tileX, tileY, tileW, tileH)
  19. local compx = 0
  20. local compy = 0
  21. if tile.sx < 0 then compx = tileW end
  22. if tile.sy < 0 then compy = tileH end
  23. if tile.r > 0 then
  24. tileX = tileX + tileH - compy
  25. tileY = tileY + tileH + compx - tileW
  26. elseif tile.r < 0 then
  27. tileX = tileX + compy
  28. tileY = tileY - compx + tileH
  29. else
  30. tileX = tileX + compx
  31. tileY = tileY + compy
  32. end
  33. return tileX, tileY
  34. end
  35. -- Cache images in main STI module
  36. function utils.cache_image(sti, path, image)
  37. image = image or love.graphics.newImage(path)
  38. image:setFilter("nearest", "nearest")
  39. sti.cache[path] = image
  40. end
  41. -- We just don't know.
  42. function utils.get_tiles(imageW, tileW, margin, spacing)
  43. imageW = imageW - margin
  44. local n = 0
  45. while imageW >= tileW do
  46. imageW = imageW - tileW
  47. if n ~= 0 then imageW = imageW - spacing end
  48. if imageW >= 0 then n = n + 1 end
  49. end
  50. return n
  51. end
  52. -- Decompress tile layer data
  53. function utils.get_decompressed_data(data)
  54. local ffi = require "ffi"
  55. local d = {}
  56. local decoded = ffi.cast("uint32_t*", data)
  57. for i = 0, data:len() / ffi.sizeof("uint32_t") do
  58. table.insert(d, tonumber(decoded[i]))
  59. end
  60. return d
  61. end
  62. -- Convert a Tiled ellipse object to a LOVE polygon
  63. function utils.convert_ellipse_to_polygon(x, y, w, h, max_segments)
  64. local ceil = math.ceil
  65. local cos = math.cos
  66. local sin = math.sin
  67. local function calc_segments(segments)
  68. local function vdist(a, b)
  69. local c = {
  70. x = a.x - b.x,
  71. y = a.y - b.y,
  72. }
  73. return c.x * c.x + c.y * c.y
  74. end
  75. segments = segments or 64
  76. local vertices = {}
  77. local v = { 1, 2, ceil(segments/4-1), ceil(segments/4) }
  78. local m
  79. if love and love.physics then
  80. m = love.physics.getMeter()
  81. else
  82. m = 32
  83. end
  84. for _, i in ipairs(v) do
  85. local angle = (i / segments) * math.pi * 2
  86. local px = x + w / 2 + cos(angle) * w / 2
  87. local py = y + h / 2 + sin(angle) * h / 2
  88. table.insert(vertices, { x = px / m, y = py / m })
  89. end
  90. local dist1 = vdist(vertices[1], vertices[2])
  91. local dist2 = vdist(vertices[3], vertices[4])
  92. -- Box2D threshold
  93. if dist1 < 0.0025 or dist2 < 0.0025 then
  94. return calc_segments(segments-2)
  95. end
  96. return segments
  97. end
  98. local segments = calc_segments(max_segments)
  99. local vertices = {}
  100. table.insert(vertices, { x = x + w / 2, y = y + h / 2 })
  101. for i = 0, segments do
  102. local angle = (i / segments) * math.pi * 2
  103. local px = x + w / 2 + cos(angle) * w / 2
  104. local py = y + h / 2 + sin(angle) * h / 2
  105. table.insert(vertices, { x = px, y = py })
  106. end
  107. return vertices
  108. end
  109. function utils.rotate_vertex(map, vertex, x, y, cos, sin, oy)
  110. if map.orientation == "isometric" then
  111. x, y = utils.convert_isometric_to_screen(map, x, y)
  112. vertex.x, vertex.y = utils.convert_isometric_to_screen(map, vertex.x, vertex.y)
  113. end
  114. vertex.x = vertex.x - x
  115. vertex.y = vertex.y - y
  116. return
  117. x + cos * vertex.x - sin * vertex.y,
  118. y + sin * vertex.x + cos * vertex.y - (oy or 0)
  119. end
  120. --- Project isometric position to cartesian position
  121. function utils.convert_isometric_to_screen(map, x, y)
  122. local mapW = map.width
  123. local tileW = map.tilewidth
  124. local tileH = map.tileheight
  125. local tileX = x / tileH
  126. local tileY = y / tileH
  127. local offsetX = mapW * tileW / 2
  128. return
  129. (tileX - tileY) * tileW / 2 + offsetX,
  130. (tileX + tileY) * tileH / 2
  131. end
  132. function utils.hex_to_color(hex)
  133. if hex:sub(1, 1) == "#" then
  134. hex = hex:sub(2)
  135. end
  136. return {
  137. r = tonumber(hex:sub(1, 2), 16) / 255,
  138. g = tonumber(hex:sub(3, 4), 16) / 255,
  139. b = tonumber(hex:sub(5, 6), 16) / 255
  140. }
  141. end
  142. function utils.pixel_function(_, _, r, g, b, a)
  143. local mask = utils._TC
  144. if r == mask.r and
  145. g == mask.g and
  146. b == mask.b then
  147. return r, g, b, 0
  148. end
  149. return r, g, b, a
  150. end
  151. function utils.fix_transparent_color(tileset, path)
  152. local image_data = love.image.newImageData(path)
  153. tileset.image = love.graphics.newImage(image_data)
  154. if tileset.transparentcolor then
  155. utils._TC = utils.hex_to_color(tileset.transparentcolor)
  156. image_data:mapPixel(utils.pixel_function)
  157. tileset.image = love.graphics.newImage(image_data)
  158. end
  159. end
  160. function utils.deepCopy(t)
  161. local copy = {}
  162. for k,v in pairs(t) do
  163. if type(v) == "table" then
  164. v = utils.deepCopy(v)
  165. end
  166. copy[k] = v
  167. end
  168. return copy
  169. end
  170. return utils