Files
tbd-station-14/Tools/SS14 Aseprite Plugins/Displacement Map Visualizer.lua
Ed e6180da35c Displacement Map Visualizer update (#35952)
Update Displacement Map Visualizer.lua
2025-04-05 15:51:59 +03:00

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}