Displacement Map Visualizer.lua 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. -- Displacement Map Visualizer
  2. --
  3. -- This script will create a little preview window that will test a displacement map.
  4. --
  5. -- TODO: Handling of sizes != 127 doesn't work properly and rounds differently from the real shader. Ah well.
  6. local scale = 4
  7. -- This script requires UI
  8. if not app.isUIAvailable then
  9. return
  10. end
  11. local getOffsetPixel = function(x, y, image, rect)
  12. local posX = x - rect.x
  13. local posY = y - rect.y
  14. if posX < 0 or posX >= image.width or posY < 0 or posY >= image.height then
  15. return image.spec.transparentColor
  16. end
  17. return image:getPixel(posX, posY)
  18. end
  19. local pixelValueToColor = function(sprite, value)
  20. return Color(value)
  21. end
  22. local applyDisplacementMap = function(width, height, size, displacement, displacementRect, target, targetRect)
  23. -- print(Color(displacement:getPixel(17, 15)).red)
  24. local image = target:clone()
  25. image:resize(width, height)
  26. image:clear()
  27. for x = 0, width - 1 do
  28. for y = 0, height - 1 do
  29. local value = getOffsetPixel(x, y, displacement, displacementRect)
  30. local color = pixelValueToColor(sprite, value)
  31. if color.alpha ~= 0 then
  32. local offset_x = (color.red - 128) / 127 * size
  33. local offset_y = (color.green - 128) / 127 * size
  34. local colorValue = getOffsetPixel(x + offset_x, y + offset_y, target, targetRect)
  35. image:drawPixel(x, y, colorValue)
  36. end
  37. end
  38. end
  39. return image
  40. end
  41. local dialog = nil
  42. local sprite = app.editor.sprite
  43. local spriteChanged = sprite.events:on("change",
  44. function(ev)
  45. dialog:repaint()
  46. end)
  47. local layers = {}
  48. for i,layer in ipairs(sprite.layers) do
  49. table.insert(layers, 1, layer.name)
  50. end
  51. local findLayer = function(sprite, name)
  52. for i, layer in ipairs(sprite.layers) do
  53. if layer.name == name then
  54. return layer
  55. end
  56. end
  57. return nil
  58. end
  59. dialog = Dialog{
  60. title = "Displacement map preview",
  61. onclose = function(ev)
  62. sprite.events:off(spriteChanged)
  63. end}
  64. dialog:canvas{
  65. id = "canvas",
  66. width = sprite.width * scale,
  67. height = sprite.height * scale,
  68. onpaint = function(ev)
  69. local context = ev.context
  70. local layerDisplacement = findLayer(sprite, dialog.data["displacement-select"])
  71. local layerTarget = findLayer(sprite, dialog.data["reference-select"])
  72. local layerBackground = findLayer(sprite, dialog.data["background-select"])
  73. -- print(layerDisplacement.name)
  74. -- print(layerTarget.name)
  75. local celDisplacement = layerDisplacement:cel(1)
  76. local celTarget = layerTarget:cel(1)
  77. local celBackground = layerBackground:cel(1)
  78. -- Draw background
  79. context:drawImage(
  80. -- srcImage
  81. celBackground.image,
  82. -- srcPos
  83. 0, 0,
  84. -- srcSize
  85. celBackground.image.width, celBackground.image.height,
  86. -- dstPos
  87. celBackground.position.x * scale, celBackground.position.y * scale,
  88. -- dstSize
  89. celBackground.image.width * scale, celBackground.image.height * scale)
  90. -- Apply displacement map and draw
  91. local image = applyDisplacementMap(
  92. sprite.width, sprite.height,
  93. dialog.data["size"],
  94. celDisplacement.image, celDisplacement.bounds,
  95. celTarget.image, celTarget.bounds)
  96. context:drawImage(
  97. -- srcImage
  98. image,
  99. -- srcPos
  100. 0, 0,
  101. -- srcSize
  102. image.width, image.height,
  103. -- dstPos
  104. 0, 0,
  105. -- dstSize
  106. image.width * scale, image.height * scale)
  107. end
  108. }
  109. dialog:combobox{
  110. id = "displacement-select",
  111. label = "displacement layer",
  112. options = layers,
  113. onchange = function(ev)
  114. dialog:repaint()
  115. end
  116. }
  117. dialog:combobox{
  118. id = "reference-select",
  119. label = "reference layer",
  120. options = layers,
  121. onchange = function(ev)
  122. dialog:repaint()
  123. end
  124. }
  125. dialog:combobox{
  126. id = "background-select",
  127. label = "background layer",
  128. options = layers,
  129. onchange = function(ev)
  130. dialog:repaint()
  131. end
  132. }
  133. dialog:slider{
  134. id = "size",
  135. label = "displacement size",
  136. min = 1,
  137. max = 127,
  138. value = 127,
  139. onchange = function(ev)
  140. dialog:repaint()
  141. end
  142. }
  143. dialog:show{wait = false}