231 lines
5.9 KiB
Lua
231 lines
5.9 KiB
Lua
-- Displacement Map Visualizer
|
|
--
|
|
-- This script will create a little preview window that will test a displacement map.
|
|
--
|
|
-- TODO: Handling of sizes != 127 doesn't work properly and rounds differently from the real shader. Ah well.
|
|
|
|
local scale = 4
|
|
|
|
-- This script requires UI
|
|
if not app.isUIAvailable then
|
|
return
|
|
end
|
|
|
|
local getOffsetPixel = function(x, y, image, rect)
|
|
local posX = x - rect.x
|
|
local posY = y - rect.y
|
|
|
|
if posX < 0 or posX >= image.width or posY < 0 or posY >= image.height then
|
|
return image.spec.transparentColor
|
|
end
|
|
|
|
return image:getPixel(posX, posY)
|
|
end
|
|
|
|
local pixelValueToColor = function(sprite, value)
|
|
return Color(value)
|
|
end
|
|
|
|
local applyDisplacementMap = function(width, height, size, displacement, displacementRect, target, targetRect)
|
|
-- print(Color(displacement:getPixel(17, 15)).red)
|
|
local image = target:clone()
|
|
image:resize(width, height)
|
|
image:clear()
|
|
|
|
for x = 0, width - 1 do
|
|
for y = 0, height - 1 do
|
|
local value = getOffsetPixel(x, y, displacement, displacementRect)
|
|
local color = pixelValueToColor(sprite, value)
|
|
|
|
if color.alpha ~= 0 then
|
|
local offset_x = (color.red - 128) / 127 * size
|
|
local offset_y = (color.green - 128) / 127 * size
|
|
|
|
local colorValue = getOffsetPixel(x + offset_x, y + offset_y, target, targetRect)
|
|
image:drawPixel(x, y, colorValue)
|
|
end
|
|
end
|
|
end
|
|
|
|
return image
|
|
end
|
|
|
|
local dialog = nil
|
|
|
|
local sprite = app.editor.sprite
|
|
local spriteChanged = sprite.events:on("change",
|
|
function(ev)
|
|
dialog:repaint()
|
|
end)
|
|
|
|
local layers = {}
|
|
for i,layer in ipairs(sprite.layers) do
|
|
table.insert(layers, 1, layer.name)
|
|
end
|
|
|
|
local findLayer = function(sprite, name)
|
|
for i, layer in ipairs(sprite.layers) do
|
|
if layer.name == name then
|
|
return layer
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
local applyOffset = function(dx, dy)
|
|
local cel = app.cel
|
|
local image = cel.image:clone()
|
|
local sprite = app.editor.sprite
|
|
local selection = sprite.selection
|
|
|
|
for x = selection.bounds.x, selection.bounds.x + selection.bounds.width - 1 do
|
|
for y = selection.bounds.y, selection.bounds.y + selection.bounds.height - 1 do
|
|
local xImg = x - cel.position.x
|
|
local yImg = y - cel.position.y
|
|
if xImg >= 0 and xImg < image.width and yImg >= 0 and yImg < image.height then
|
|
local pixelValue = image:getPixel(xImg, yImg)
|
|
local color = Color(pixelValue)
|
|
|
|
-- Offset R and G channel
|
|
color.red = math.min(255, math.max(0, color.red + dx))
|
|
color.green = math.min(255, math.max(0, color.green + dy))
|
|
|
|
image:drawPixel(xImg, yImg, app.pixelColor.rgba(color.red, color.green, color.blue, color.alpha))
|
|
end
|
|
end
|
|
end
|
|
|
|
cel.image = image
|
|
dialog:repaint()
|
|
end
|
|
|
|
dialog = Dialog{
|
|
title = "Displacement map preview",
|
|
onclose = function(ev)
|
|
sprite.events:off(spriteChanged)
|
|
end}
|
|
|
|
dialog:canvas{
|
|
id = "canvas",
|
|
width = sprite.width * scale,
|
|
height = sprite.height * scale,
|
|
onpaint = function(ev)
|
|
local context = ev.context
|
|
|
|
local layerDisplacement = findLayer(sprite, dialog.data["displacement-select"])
|
|
local layerTarget = findLayer(sprite, dialog.data["reference-select"])
|
|
local layerBackground = findLayer(sprite, dialog.data["background-select"])
|
|
-- print(layerDisplacement.name)
|
|
-- print(layerTarget.name)
|
|
|
|
local celDisplacement = layerDisplacement:cel(1)
|
|
local celTarget = layerTarget:cel(1)
|
|
local celBackground = layerBackground:cel(1)
|
|
|
|
-- Draw background
|
|
context:drawImage(
|
|
-- srcImage
|
|
celBackground.image,
|
|
-- srcPos
|
|
0, 0,
|
|
-- srcSize
|
|
celBackground.image.width, celBackground.image.height,
|
|
-- dstPos
|
|
celBackground.position.x * scale, celBackground.position.y * scale,
|
|
-- dstSize
|
|
celBackground.image.width * scale, celBackground.image.height * scale)
|
|
|
|
-- Apply displacement map and draw
|
|
local image = applyDisplacementMap(
|
|
sprite.width, sprite.height,
|
|
dialog.data["size"],
|
|
celDisplacement.image, celDisplacement.bounds,
|
|
celTarget.image, celTarget.bounds)
|
|
|
|
context:drawImage(
|
|
-- srcImage
|
|
image,
|
|
-- srcPos
|
|
0, 0,
|
|
-- srcSize
|
|
image.width, image.height,
|
|
-- dstPos
|
|
0, 0,
|
|
-- dstSize
|
|
image.width * scale, image.height * scale)
|
|
end
|
|
}
|
|
|
|
dialog:combobox{
|
|
id = "displacement-select",
|
|
label = "displacement layer",
|
|
options = layers,
|
|
onchange = function(ev)
|
|
dialog:repaint()
|
|
end
|
|
}
|
|
|
|
dialog:combobox{
|
|
id = "reference-select",
|
|
label = "reference layer",
|
|
options = layers,
|
|
onchange = function(ev)
|
|
dialog:repaint()
|
|
end
|
|
}
|
|
|
|
dialog:combobox{
|
|
id = "background-select",
|
|
label = "background layer",
|
|
options = layers,
|
|
onchange = function(ev)
|
|
dialog:repaint()
|
|
end
|
|
}
|
|
|
|
dialog:slider{
|
|
id = "size",
|
|
label = "displacement size",
|
|
min = 127, --We dont support non 127 atm
|
|
max = 127,
|
|
value = 127,
|
|
onchange = function(ev)
|
|
dialog:repaint()
|
|
end
|
|
}
|
|
|
|
dialog:button{
|
|
id = "moveDown",
|
|
text = "Down",
|
|
onclick = function(ev)
|
|
applyOffset(0, -1)
|
|
end
|
|
}
|
|
|
|
dialog:button{
|
|
id = "moveUp",
|
|
text = "Up",
|
|
onclick = function(ev)
|
|
applyOffset(0, 1)
|
|
end
|
|
}
|
|
|
|
dialog:button{
|
|
id = "moveLeft",
|
|
text = "Left",
|
|
onclick = function(ev)
|
|
applyOffset(1, 0)
|
|
end
|
|
}
|
|
|
|
dialog:button{
|
|
id = "moveRight",
|
|
text = "Right",
|
|
onclick = function(ev)
|
|
applyOffset(-1, 0)
|
|
end
|
|
}
|
|
|
|
dialog:show{wait = false}
|