slabOS/lib/basalt/objects/Image.lua
2025-06-02 10:23:40 +03:00

363 lines
11 KiB
Lua

local images = require("images")
local bimg = require("bimg")
local unpack,sub,max,min = table.unpack,string.sub,math.max,math.min
return function(name, basalt)
-- Image
local base = basalt.getObject("VisualObject")(name, basalt)
local objectType = "Image"
local bimgLibrary = bimg()
local bimgFrame = bimgLibrary.getFrameObject(1)
local originalImage
local image
local activeFrame = 1
local infinitePlay = false
local animTimer
local usePalette = false
local autoSize = true
local xOffset, yOffset = 0, 0
base:setSize(24, 8)
base:setZIndex(2)
local function getPalette(id)
local p = {}
for k,v in pairs(colors)do
if(type(v)=="number")then
p[k] = {term.nativePaletteColor(v)}
end
end
local globalPalette = bimgLibrary.getMetadata("palette")
if(globalPalette~=nil)then
for k,v in pairs(globalPalette)do
p[k] = tonumber(v)
end
end
local localPalette = bimgLibrary.getFrameData("palette")
basalt.log(localPalette)
if(localPalette~=nil)then
for k,v in pairs(localPalette)do
p[k] = tonumber(v)
end
end
return p
end
local function checkAutoSize()
if(autoSize)then
if(bimgLibrary~=nil)then
base:setSize(bimgLibrary.getSize())
end
end
end
local object = {
getType = function(self)
return objectType
end,
isType = function(self, t)
return objectType==t or base.isType~=nil and base.isType(t) or false
end,
setOffset = function(self, _x, _y, rel)
if(rel)then
xOffset = xOffset + _x or 0
yOffset = yOffset + _y or 0
else
xOffset = _x or xOffset
yOffset = _y or yOffset
end
self:updateDraw()
return self
end,
setXOffset = function(self, _x)
return self:setOffset(self, _x, nil)
end,
setYOffset = function(self, _y)
return self:setOffset(self, nil, _y)
end,
setSize = function(self, _x, _y)
base:setSize(_x, _y)
autoSize = false
return self
end,
getOffset = function(self)
return xOffset, yOffset
end,
getXOffset = function(self)
return xOffset
end,
getYOffset = function(self)
return yOffset
end,
selectFrame = function(self, id)
if(bimgLibrary.getFrameObject(id)==nil)then
bimgLibrary.addFrame(id)
end
bimgFrame = bimgLibrary.getFrameObject(id)
image = bimgFrame.getImage(id)
activeFrame = id
self:updateDraw()
end,
addFrame = function(self, id)
bimgLibrary.addFrame(id)
return self
end,
getFrame = function(self, id)
return bimgLibrary.getFrame(id)
end,
getFrameObject = function(self, id)
return bimgLibrary.getFrameObject(id)
end,
removeFrame = function(self, id)
bimgLibrary.removeFrame(id)
return self
end,
moveFrame = function(self, id, dir)
bimgLibrary.moveFrame(id, dir)
return self
end,
getFrames = function(self)
return bimgLibrary.getFrames()
end,
getFrameCount = function(self)
return #bimgLibrary.getFrames()
end,
getActiveFrame = function(self)
return activeFrame
end,
loadImage = function(self, path)
if(fs.exists(path))then
local newBimg = images.loadBIMG(path)
bimgLibrary = bimg(newBimg)
activeFrame = 1
bimgFrame = bimgLibrary.getFrameObject(1)
originalImage = bimgLibrary.createBimg()
image = bimgFrame.getImage()
checkAutoSize()
self:updateDraw()
end
return self
end,
setPath = function(self, path)
return self:loadImage(path)
end,
setImage = function(self, t)
if(type(t)=="table")then
bimgLibrary = bimg(t)
activeFrame = 1
bimgFrame = bimgLibrary.getFrameObject(1)
originalImage = bimgLibrary.createBimg()
image = bimgFrame.getImage()
checkAutoSize()
self:updateDraw()
end
return self
end,
clear = function(self)
bimgLibrary = bimg()
bimgFrame = bimgLibrary.getFrameObject(1)
image = nil
self:updateDraw()
return self
end,
getImage = function(self)
return bimgLibrary.createBimg()
end,
getImageFrame = function(self, id)
return bimgFrame.getImage(id)
end,
usePalette = function(self, use)
usePalette = use~=nil and use or true
return self
end,
getUsePalette = function(self)
return usePalette
end,
setUsePalette = function(self, use)
return self:usePalette(use)
end,
play = function(self, inf)
if(bimgLibrary.getMetadata("animated"))then
local t = bimgLibrary.getMetadata("duration") or bimgLibrary.getMetadata("secondsPerFrame") or 0.2
self:listenEvent("other_event")
animTimer = os.startTimer(t)
infinitePlay = inf or false
end
return self
end,
setPlay = function(self, inf)
return self:play(inf)
end,
stop = function(self)
os.cancelTimer(animTimer)
animTimer = nil
infinitePlay = false
return self
end,
eventHandler = function(self, event, timerId, ...)
base.eventHandler(self, event, timerId, ...)
if(event=="timer")then
if(timerId==animTimer)then
if(bimgLibrary.getFrame(activeFrame+1)~=nil)then
activeFrame = activeFrame + 1
self:selectFrame(activeFrame)
local t = bimgLibrary.getFrameData(activeFrame, "duration") or bimgLibrary.getMetadata("secondsPerFrame") or 0.2
animTimer = os.startTimer(t)
else
if(infinitePlay)then
activeFrame = 1
self:selectFrame(activeFrame)
local t = bimgLibrary.getFrameData(activeFrame, "duration") or bimgLibrary.getMetadata("secondsPerFrame") or 0.2
animTimer = os.startTimer(t)
end
end
self:updateDraw()
end
end
end,
setMetadata = function(self, key, value)
bimgLibrary.setMetadata(key, value)
return self
end,
getMetadata = function(self, key)
return bimgLibrary.getMetadata(key)
end,
getFrameMetadata = function(self, id, key)
return bimgLibrary.getFrameData(id, key)
end,
setFrameMetadata = function(self, id, key, value)
bimgLibrary.setFrameData(id, key, value)
return self
end,
blit = function(self, text, fg, bg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.blit(text, fg, bg, x, y)
image = bimgFrame.getImage()
self:updateDraw()
return self
end,
setText = function(self, text, _x, _y)
x = _x or x
y = _y or y
bimgFrame.text(text, x, y)
image = bimgFrame.getImage()
self:updateDraw()
return self
end,
setBg = function(self, bg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.bg(bg, x, y)
image = bimgFrame.getImage()
self:updateDraw()
return self
end,
setFg = function(self, fg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.fg(fg, x, y)
image = bimgFrame.getImage()
self:updateDraw()
return self
end,
getImageSize = function(self)
return bimgLibrary.getSize()
end,
setImageSize = function(self, w, h)
bimgLibrary.setSize(w, h)
image = bimgFrame.getImage()
self:updateDraw()
return self
end,
resizeImage = function(self, w, h)
local newBimg = images.resizeBIMG(originalImage, w, h)
bimgLibrary = bimg(newBimg)
activeFrame = 1
bimgFrame = bimgLibrary.getFrameObject(1)
image = bimgFrame.getImage()
self:updateDraw()
return self
end,
draw = function(self)
base.draw(self)
self:addDraw("image", function()
local w,h = self:getSize()
local x, y = self:getPosition()
local wParent, hParent = self:getParent():getSize()
local parentXOffset, parentYOffset = self:getParent():getOffset()
if(x - parentXOffset > wParent)or(y - parentYOffset > hParent)or(x - parentXOffset + w < 1)or(y - parentYOffset + h < 1)then
return
end
if(usePalette)then
self:getParent():setPalette(getPalette(activeFrame))
end
if(image~=nil)then
for k,v in pairs(image)do
if(k+yOffset<=h)and(k+yOffset>=1)then
local t,f,b = v[1],v[2],v[3]
local startIdx = max(1 - xOffset, 1)
local endIdx = min(w - xOffset, #t)
t = sub(t, startIdx, endIdx)
f = sub(f, startIdx, endIdx)
b = sub(b, startIdx, endIdx)
self:addBlit(max(1 + xOffset, 1), k + yOffset, t, f, b)
end
end
end
end)
end,
}
object.__index = object
return setmetatable(object, base)
end