split into modules a lil

This commit is contained in:
Jill 2023-05-04 17:29:26 +03:00
parent db7d0db7ec
commit 57225d526c
Signed by: oat
GPG Key ID: 33489AA58A955108
3 changed files with 603 additions and 599 deletions

533
uranium/actors.lua Normal file
View File

@ -0,0 +1,533 @@
oat._actorsInitialized = false -- if true, no new actors can be created
oat._actorsInitializing = false -- the above but a bit more explicit
local drawfunctionArguments = {}
local specialActorFrames = {} -- ones defined specifically; here for drawfunction jank
function setDrawFunction(frame, func)
--if not frame.__raw then error('uranium: cannot set actorframe drawfunction during module loadtime! put this in uranium.init or actor:addcommand(\'Init\', ...)', 2) end
if not frame.SetDrawFunction then error('uranium: expected an actorframe but got something that doesn\'t even bother to implement SetDrawFunction', 2) end
if type(func) ~= 'function' then error('uranium: tried to set a drawfunction to a.. ' .. type(func) .. '?? the hell', 2) end
frame:SetDrawFunction(function()
for i = 1, frame:GetNumChildren() do
local a = frame:GetChildAt(i - 1)
if specialActorFrames[a] == false then
a:Draw()
end
end
local args = drawfunctionArguments[frame]
if args then
func(unpack(args))
else
func()
end
end)
end
function setShader(actor, shader)
if not shader.__raw then
function uranium.init() setShader(actor, shader) end
else
actor:SetShader(shader.__raw)
end
end
function setShaderfuck(shader)
if not shader.__raw then
function uranium.init() setShaderfuck(shader) end
else
DISPLAY:ShaderFuck(shader.__raw)
end
end
function clearShaderfuck()
DISPLAY:ClearShaderFuck()
end
oat._actorAssociationTable = {}
function getChildren(frame)
local c = oat._actorAssociationTable[frame]
if c then
return c
else
error('uranium: actorframe doesn\'t exist (or isn\'t an actorframe)', 2)
end
end
local patchedFunctions = {}
function oat._patchFunction(f, obj)
if not patchedFunctions[f] then patchedFunctions[f] = {} end
if not patchedFunctions[f][obj] then
patchedFunctions[f][obj] = function(...)
arg[1] = obj
local results
local status, result = pcall(function()
-- doing it this way instead of returning because lua
-- offers no way of grabbing everything BUT the first
-- argument out of pcall
results = {f(unpack(arg))}
end)
if not status then
error(result, 2)
else
return unpack(results)
end
end
end
return patchedFunctions[f][obj]
end
oat._globalQueue = {} -- for resetting
function reset(actor)
if not actorsInitialized then error('uranium: cannot reset an actor during initialization', 2) end
for _, q in ipairs(oat._globalQueue) do
local queueActor = q[1]
if queueActor == actor.__raw then
local v = q[2]
local func = queueActor[v[1]]
if not func then
-- uhmmm ??? hm. what do we do??
else
oat._patchFunction(func, queueActor)(unpack(v[2]))
end
end
end
end
resetActor = reset
oat._actorQueue = {}
oat._actorAssociationQueue = {}
oat._actorTree = {}
oat._currentPath = nil
oat._pastPaths = {}
oat._currentActor = nil
local function findFirstActor(path)
for i, v in ipairs(path) do
if v.type or v.file then
return v, i
end
end
end
local function findFirstActorFrame(path)
for i, v in ipairs(path) do
if not v.type and not v.file then
return v, i
end
end
end
oat._actor = {}
local function nextActor()
local new, idx = findFirstActor(oat._currentPath)
if not new then
oat._currentActor = nil
else
oat._currentActor = new
table.remove(oat._currentPath, idx)
end
end
function oat._actor.recurse(forceActor)
local newFrame, idx = findFirstActorFrame(oat._currentPath)
local newActor = findFirstActor(oat._currentPath)
if newFrame and not (newActor and forceActor) then
table.insert(oat._pastPaths, oat._currentPath)
oat._currentPath = oat._currentPath[idx]
table.remove(oat._pastPaths[#oat._pastPaths], idx)
return true
elseif newActor then
table.insert(oat._pastPaths, oat._currentPath)
return true
else
return false
end
end
function oat._actor.recurseLast()
return oat._actor.recurse(true)
end
function oat._actor.endRecurse()
oat._currentPath = table.remove(oat._pastPaths, #oat._pastPaths)
end
function oat._actor.cond()
return oat._currentActor ~= nil
end
function oat._actor.hasShader()
return oat._actor.cond() and (oat._currentActor.frag ~= nil or oat._currentActor.vert ~= nil)
end
function oat._actor.noShader()
nextActor()
return oat._actor.cond() and not oat._actor.hasShader()
end
function oat._actor.type()
return oat._currentActor.type
end
function oat._actor.file()
return oat._currentActor.file
end
function oat._actor.frag()
return oat._currentActor.frag or 'nop.frag'
end
function oat._actor.vert()
return oat._currentActor.vert or 'nop.vert'
end
function oat._actor.font()
return oat._currentActor.font
end
function oat._actor.init(self)
oat._currentActor.init(self)
self:removecommand('Init')
oat._currentActor = nil -- to prevent any weirdness
end
function oat._actor.initFrame(self)
self:removecommand('Init')
self:SetDrawFunction(function()
for i = 1, self:GetNumChildren() do
local a = self:GetChildAt(i - 1)
if specialActorFrames[a] == false then
a:Draw()
end
end
end)
if oat._currentPath.init then
oat._currentPath.init(self)
oat._currentPath.init = nil
specialActorFrames[self] = true
else
specialActorFrames[self] = false
end
end
local actorMethodOverrides = {
Draw = function(self, ...)
drawfunctionArguments[self] = arg
self.__raw:Draw()
end
}
local function createProxyActor(name)
local queue = {}
local initCommands = {}
local lockedActor
local queueRepresentation
return setmetatable({}, {
__index = function(self, key)
if key == '__raw' then
return lockedActor
end
if lockedActor then
if actorMethodOverrides[key] then
return actorMethodOverrides[key]
else
local val = lockedActor[key]
if type(val) == 'function' then
return oat._patchFunction(val, lockedActor)
end
return val
end
end
if key == '__queue' then
return queueRepresentation
end
if key == '__queueRepresentation' then
return function(q)
queueRepresentation = q
end
end
if key == '__lock' then
return function(actor)
if lockedActor then return end
for _, v in ipairs(queue) do
local func = actor[v[1]]
if not func then
error(
'uranium: error on \'' .. name .. '\' initialization on ' .. v[3].short_src .. ':' .. v[3].currentline .. ':\n' ..
'you\'re calling a function \'' .. v[1] .. '\' on a ' .. name .. ' which doesn\'t exist!:\n'
)
else
local success, result = pcall(function()
oat._patchFunction(func, actor)(unpack(v[2]))
end)
if not success then
error(
'uranium: error on \'' .. name .. '\' initialization on ' .. v[3].short_src .. ':' .. v[3].currentline .. ':\n' ..
result
)
end
end
end
-- now that we know there's no poisonous methods in queue, let's offload them
for _, v in ipairs(queue) do
table.insert(oat._globalQueue, {actor, v})
end
-- let's also properly route everything from the proxied actor to the actual actor
lockedActor = actor
-- and now let's run the initcommands
for _, c in ipairs(initCommands) do
local func = c[1]
local success, result = pcall(function()
func(actor)
end)
if not success then
error(
'uranium: error on \'' .. name .. '\' InitCommand defined on ' .. v[3].short_src .. ':' .. v[3].currentline .. ':\n' ..
result
)
end
end
-- to make mr. Garbage Collector's job easier
initCommands = {}
queueRepresentation = nil
queue = {}
end
else
return function(...)
if oat._actorsInitialized then return end
if key == 'addcommand' and arg[2] == 'Init' then
table.insert(initCommands, {arg[3], debug.getinfo(2, 'Sl')})
else
table.insert(queue, {key, arg, debug.getinfo(2, 'Sl')})
end
end
end
end,
__newindex = function()
error('uranium: cannot set properties on actors!', 2)
end,
__tostring = function() return 'Proxy of ' .. name end,
__name = name
})
end
local function createGenericFunc(type)
return function()
if oat._actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if oat._actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
local actor = createProxyActor(type)
table.insert(oat._actorQueue, {
type = type,
init = function(a)
actor.__lock(a)
end
})
actor.__queueRepresentation(oat._actorQueue[#oat._actorQueue])
return actor
end
end
Quad = createGenericFunc('Quad')
ActorProxy = createGenericFunc('ActorProxy')
Polygon = createGenericFunc('Polygon')
ActorFrameTexture = createGenericFunc('ActorFrameTexture')
function Sprite(file)
if oat._actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if oat._actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
--if not file then error('uranium: cannot create a Sprite without a file', 2) end
local actor = createProxyActor('Sprite')
local type = nil
if not file then type = 'Sprite' end
table.insert(oat._actorQueue, {
type = type,
file = file and oat.dir .. file,
init = function(a)
actor.__lock(a)
end
})
actor.__queueRepresentation(oat._actorQueue[#oat._actorQueue])
return actor
end
function ActorFrame()
if oat._actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if oat._actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
local actor = createProxyActor('ActorFrame')
table.insert(oat._actorQueue, {
type = 'ActorFrame',
init = function(a)
actor.__lock(a)
end
})
actor.__queueRepresentation(oat._actorQueue[#oat._actorQueue])
oat._actorAssociationTable[actor] = {}
return actor
end
local function isShaderCode(str)
return string.find(str or '', '\n')
end
function Shader(frag, vert)
if oat._actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if oat._actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
local actor = createProxyActor('RageShaderProgram')
local fragFile = frag
local vertFile = vert
local isFragShaderCode = isShaderCode(frag)
local isVertShaderCode = isShaderCode(vert)
if isFragShaderCode then fragFile = nil end
if isVertShaderCode then vertFile = nil end
if (frag and vert) and ((isFragShaderCode and not isVertShaderCode) or (not isFragShaderCode and isVertShaderCode)) then
error('uranium: cannot create a shader with 1 shader file and 1 shader code block', 2)
end
table.insert(oat._actorQueue, {
type = 'Sprite',
frag = fragFile and ('../' .. fragFile) or 'nop.frag',
vert = vertFile and ('../' .. vertFile) or 'nop.vert',
init = function(a)
a:hidden(1)
actor.__lock(a:GetShader())
-- shader code stuff
if isFragShaderCode or isVertShaderCode then
a:GetShader():compile(vert or '', frag or '')
end
end
})
actor.__queueRepresentation(oat._actorQueue[#oat._actorQueue])
return actor
end
function Texture(file)
if oat._actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if oat._actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
if not file then error('uranium: cannot create a texture without a file', 2) end
local actor = createProxyActor('RageTexture')
table.insert(oat._actorQueue, {
file = file and oat.dir .. file,
init = function(a)
a:hidden(1)
actor.__lock(a:GetTexture())
end
})
actor.__queueRepresentation(oat._actorQueue[#oat._actorQueue])
return actor
end
function Model(file)
if oat._actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if oat._actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
if not file then error('uranium: cannot create a Model without a file', 2) end
local actor = createProxyActor('Model')
table.insert(oat._actorQueue, {
type = nil,
file = file and oat.dir .. file,
init = function(a)
actor.__lock(a)
end
})
actor.__queueRepresentation(oat._actorQueue[#oat._actorQueue])
return actor
end
function BitmapText(font, text)
if oat._actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if oat._actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
local actor = createProxyActor('BitmapText')
table.insert(oat._actorQueue, {
type = 'BitmapText',
font = font or 'common',
init = function(a)
if text then a:settext(text) end
actor.__lock(a)
end
})
actor.__queueRepresentation(oat._actorQueue[#oat._actorQueue])
return actor
end
function ActorSound(file)
if oat._actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if oat._actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
if not file then error('uranium: cannot create an ActorSound without a file', 2) end
local actor = createProxyActor('ActorSound')
table.insert(oat._actorQueue, {
type = 'ActorSound',
file = oat.dir .. file,
init = function(a)
actor.__lock(a)
end
})
actor.__queueRepresentation(oat._actorQueue[#oat._actorQueue])
return actor
end
function addChild(frame, actor)
if not frame or not actor then
error('uranium: frame and actor must both Exist', 2)
end
if oat._actorsInitializing then
error('uranium: cannot create frame-child associations during actor initialization', 2)
end
if oat._actorsInitialized then
error('uranium: cannot create frame-child associations after actors have been initialized', 2)
end
if not frame.__lock then
error('uranium: ActorFrame passed into addChild must be one instantiated with ActorFrame()!', 2)
end
if not actor.__lock then
error('uranium: trying to add a child to an ActorFrame that isn\'t an actor; please read the first half of \'ActorFrame\'', 2)
end
oat._actorAssociationQueue[actor.__queue] = frame.__queue
table.insert(oat._actorAssociationTable[frame], actor)
end
function oat._transformQueueToTree()
local tree = {}
local paths = {}
local iter = 0
while #oat._actorQueue > 0 do
iter = iter + 1
if iter > 99999 then
error('uranium: failed to transform queue to tree: reached maximum iteration limit! is there an actor with an invalid actorframe?')
end
for i = #oat._actorQueue, 1, -1 do
v = oat._actorQueue[i]
local insertInto
if not oat._actorAssociationQueue[v] then
insertInto = tree
else
if paths[oat._actorAssociationQueue[v]] then
insertInto = paths[oat._actorAssociationQueue[v]]
end
end
if insertInto then
if v.type == 'ActorFrame' then
table.insert(insertInto, {init = v.init})
table.remove(oat._actorQueue, i)
paths[v] = insertInto[#insertInto]
else
table.insert(insertInto, v)
table.remove(oat._actorQueue, i)
end
end
end
end
oat._actorTree = tree
end

44
uranium/events.lua Normal file
View File

@ -0,0 +1,44 @@
useProfiler = false
profilerInfo = {}
local uraniumFunc = {}
local debugCache = {}
function uraniumFunc:call(event, ...)
if self._callbacks[event] then
profilerInfo[event] = {}
for _, callback in ipairs(self._callbacks[event]) do
local start = os.clock()
local res = callback(unpack(arg))
local dur = os.clock() - start
if oat.useProfiler then
if not debugCache[callback] then
debugCache[callback] = debug.getinfo(callback, 'Sl') -- cached cus debug.getinfo is EXPENSIVE
end
local finfo = debugCache[callback]
table.insert(profilerInfo[event], {
src = finfo.short_src .. ':' .. finfo.linedefined,
t = dur
})
end
if res ~= nil then return res end
end
end
end
local uraniumMeta = {}
function uraniumMeta:__newindex(key, value)
if self._callbacks[key] then
table.insert(self._callbacks[key], value)
else
self._callbacks[key] = {value}
end
end
uraniumMeta.__index = uraniumFunc
uranium = setmetatable({_callbacks = {}}, uraniumMeta)

View File

@ -25,62 +25,12 @@ sh = SCREEN_HEIGHT
dw = DISPLAY:GetDisplayWidth()
dh = DISPLAY:GetDisplayHeight()
useProfiler = false
profilerInfo = {}
local resetOnFrameStartCfg = false
local resetOnFrameStartActors = {}
local uraniumFunc = {}
uranium = {}
local debugCache = {}
function uraniumFunc:call(event, ...)
if self._callbacks[event] then
profilerInfo[event] = {}
for _, callback in ipairs(self._callbacks[event]) do
local start = os.clock()
local res = callback(unpack(arg))
local dur = os.clock() - start
if oat.useProfiler then
if not debugCache[callback] then
debugCache[callback] = debug.getinfo(callback, 'Sl') -- cached cus debug.getinfo is EXPENSIVE
end
local finfo = debugCache[callback]
table.insert(profilerInfo[event], {
src = finfo.short_src .. ':' .. finfo.linedefined,
t = dur
})
end
if res ~= nil then return res end
end
end
end
local uraniumMeta = {}
function uraniumMeta:__newindex(key, value)
if self._callbacks[key] then
table.insert(self._callbacks[key], value)
else
self._callbacks[key] = {value}
end
end
uraniumMeta.__index = uraniumFunc
uranium = setmetatable({_callbacks = {}}, uraniumMeta)
function backToSongWheel(message)
if message then
SCREENMAN:SystemMessage(message)
print(message)
end
GAMESTATE:FinishSong()
-- disable update_command
_main:hidden(1)
end
require 'uranium.events'
local hasExited = false
local function exit()
@ -95,39 +45,22 @@ local function exit()
collectgarbage()
end
local actorsInitialized = false -- if true, no new actors can be created
local actorsInitializing = false -- the above but a bit more explicit
function backToSongWheel(message)
if message then
SCREENMAN:SystemMessage(message)
print(message)
end
exit()
GAMESTATE:FinishSong()
-- disable update_command
_main:hidden(1)
end
local luaobj
local globalQueue = {} -- for resetting
local patchedFunctions = {}
local function patchFunction(f, obj)
if not patchedFunctions[f] then patchedFunctions[f] = {} end
if not patchedFunctions[f][obj] then
patchedFunctions[f][obj] = function(...)
arg[1] = obj
local results
local status, result = pcall(function()
-- doing it this way instead of returning because lua
-- offers no way of grabbing everything BUT the first
-- argument out of pcall
results = {f(unpack(arg))}
end)
if not status then
error(result, 2)
else
return unpack(results)
end
end
end
return patchedFunctions[f][obj]
end
local function onCommand(self)
actorsInitialized = true
actorsInitializing = false
oat._actorsInitialized = true
oat._actorsInitializing = false
local resetOnFrameStartActors_ = {}
for k,v in pairs(resetOnFrameStartActors) do
resetOnFrameStartActors_[k.__raw] = v
@ -136,24 +69,6 @@ local function onCommand(self)
uranium:call('init')
end
function reset(actor)
if not actorsInitialized then error('uranium: cannot reset an actor during initialization', 2) end
for _, q in ipairs(globalQueue) do
local queueActor = q[1]
if queueActor == actor.__raw then
local v = q[2]
local func = queueActor[v[1]]
if not func then
-- uhmmm ??? hm. what do we do??
else
patchFunction(func, queueActor)(unpack(v[2]))
end
end
end
end
resetActor = reset
-- runs once during ScreenReadyCommand, before the user code is loaded
-- hides various actors that are placed by the theme
local function hideThemeActors()
@ -174,49 +89,6 @@ end
GAMESTATE:ApplyModifiers('clearall')
local drawfunctionArguments = {}
local specialActorFrames = {} -- ones defined specifically; here for drawfunction jank
function setDrawFunction(frame, func)
--if not frame.__raw then error('uranium: cannot set actorframe drawfunction during module loadtime! put this in uranium.init or actor:addcommand(\'Init\', ...)', 2) end
if not frame.SetDrawFunction then error('uranium: expected an actorframe but got something that doesn\'t even bother to implement SetDrawFunction', 2) end
if type(func) ~= 'function' then error('uranium: tried to set a drawfunction to a.. ' .. type(func) .. '?? the hell', 2) end
frame:SetDrawFunction(function()
for i = 1, frame:GetNumChildren() do
local a = frame:GetChildAt(i - 1)
if specialActorFrames[a] == false then
a:Draw()
end
end
local args = drawfunctionArguments[frame]
if args then
func(unpack(args))
else
func()
end
end)
end
function setShader(actor, shader)
if not shader.__raw then
function uranium.init() setShader(actor, shader) end
else
actor:SetShader(shader.__raw)
end
end
function setShaderfuck(shader)
if not shader.__raw then
function uranium.init() setShaderfuck(shader) end
else
DISPLAY:ShaderFuck(shader.__raw)
end
end
function clearShaderfuck()
DISPLAY:ClearShaderFuck()
end
function resetOnFrameStart(bool)
resetOnFrameStartCfg = bool
end
@ -226,452 +98,7 @@ function resetActorOnFrameStart(actor, bool)
resetOnFrameStartActors[actor.__raw or actor] = bool
end
local actorAssociationTable = {}
function getChildren(frame)
local c = actorAssociationTable[frame]
if c then
return c
else
error('uranium: actorframe doesn\'t exist (or isn\'t an actorframe)', 2)
end
end
-- actors
local actorQueue = {}
local actorAssociationQueue = {}
local actorTree = {}
local currentPath
local pastPaths = {}
local currentActor = nil
local function findFirstActor(path)
for i, v in ipairs(path) do
if v.type or v.file then
return v, i
end
end
end
local function findFirstActorFrame(path)
for i, v in ipairs(path) do
if not v.type and not v.file then
return v, i
end
end
end
oat._actor = {}
local function nextActor()
local new, idx = findFirstActor(currentPath)
if not new then
currentActor = nil
else
currentActor = new
table.remove(currentPath, idx)
end
end
function oat._actor.recurse(forceActor)
local newFrame, idx = findFirstActorFrame(currentPath)
local newActor = findFirstActor(currentPath)
if newFrame and not (newActor and forceActor) then
table.insert(pastPaths, currentPath)
currentPath = currentPath[idx]
table.remove(pastPaths[#pastPaths], idx)
return true
elseif newActor then
table.insert(pastPaths, currentPath)
return true
else
return false
end
end
function oat._actor.recurseLast()
return oat._actor.recurse(true)
end
function oat._actor.endRecurse()
currentPath = table.remove(pastPaths, #pastPaths)
end
function oat._actor.cond()
return currentActor ~= nil
end
function oat._actor.hasShader()
return oat._actor.cond() and (currentActor.frag ~= nil or currentActor.vert ~= nil)
end
function oat._actor.noShader()
nextActor()
return oat._actor.cond() and not oat._actor.hasShader()
end
function oat._actor.type()
return currentActor.type
end
function oat._actor.file()
return currentActor.file
end
function oat._actor.frag()
return currentActor.frag or 'nop.frag'
end
function oat._actor.vert()
return currentActor.vert or 'nop.vert'
end
function oat._actor.font()
return currentActor.font
end
function oat._actor.init(self)
currentActor.init(self)
self:removecommand('Init')
currentActor = nil -- to prevent any weirdness
end
function oat._actor.initFrame(self)
self:removecommand('Init')
self:SetDrawFunction(function()
for i = 1, self:GetNumChildren() do
local a = self:GetChildAt(i - 1)
if specialActorFrames[a] == false then
a:Draw()
end
end
end)
if currentPath.init then
currentPath.init(self)
currentPath.init = nil
specialActorFrames[self] = true
else
specialActorFrames[self] = false
end
end
local actorMethodOverrides = {
Draw = function(self, ...)
drawfunctionArguments[self] = arg
self.__raw:Draw()
end
}
local function createProxyActor(name)
local queue = {}
local initCommands = {}
local lockedActor
local queueRepresentation
return setmetatable({}, {
__index = function(self, key)
if key == '__raw' then
return lockedActor
end
if lockedActor then
if actorMethodOverrides[key] then
return actorMethodOverrides[key]
else
local val = lockedActor[key]
if type(val) == 'function' then
return patchFunction(val, lockedActor)
end
return val
end
end
if key == '__queue' then
return queueRepresentation
end
if key == '__queueRepresentation' then
return function(q)
queueRepresentation = q
end
end
if key == '__lock' then
return function(actor)
if lockedActor then return end
for _, v in ipairs(queue) do
local func = actor[v[1]]
if not func then
error(
'uranium: error on \'' .. name .. '\' initialization on ' .. v[3].short_src .. ':' .. v[3].currentline .. ':\n' ..
'you\'re calling a function \'' .. v[1] .. '\' on a ' .. name .. ' which doesn\'t exist!:\n'
)
else
local success, result = pcall(function()
patchFunction(func, actor)(unpack(v[2]))
end)
if not success then
error(
'uranium: error on \'' .. name .. '\' initialization on ' .. v[3].short_src .. ':' .. v[3].currentline .. ':\n' ..
result
)
end
end
end
-- now that we know there's no poisonous methods in queue, let's offload them
for _, v in ipairs(queue) do
table.insert(globalQueue, {actor, v})
end
-- let's also properly route everything from the proxied actor to the actual actor
lockedActor = actor
-- and now let's run the initcommands
for _, c in ipairs(initCommands) do
local func = c[1]
local success, result = pcall(function()
func(actor)
end)
if not success then
error(
'uranium: error on \'' .. name .. '\' InitCommand defined on ' .. v[3].short_src .. ':' .. v[3].currentline .. ':\n' ..
result
)
end
end
-- to make mr. Garbage Collector's job easier
initCommands = {}
queueRepresentation = nil
queue = {}
end
else
return function(...)
if actorsInitialized then return end
if key == 'addcommand' and arg[2] == 'Init' then
table.insert(initCommands, {arg[3], debug.getinfo(2, 'Sl')})
else
table.insert(queue, {key, arg, debug.getinfo(2, 'Sl')})
end
end
end
end,
__newindex = function()
error('uranium: cannot set properties on actors!', 2)
end,
__tostring = function() return 'Proxy of ' .. name end,
__name = name
})
end
local function createGenericFunc(type)
return function()
if actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
local actor = createProxyActor(type)
table.insert(actorQueue, {
type = type,
init = function(a)
actor.__lock(a)
end
})
actor.__queueRepresentation(actorQueue[#actorQueue])
actorAssociationTable[actor] = {}
return actor
end
end
Quad = createGenericFunc('Quad')
ActorProxy = createGenericFunc('ActorProxy')
Polygon = createGenericFunc('Polygon')
ActorFrameTexture = createGenericFunc('ActorFrameTexture')
function Sprite(file)
if actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
--if not file then error('uranium: cannot create a Sprite without a file', 2) end
local actor = createProxyActor('Sprite')
local type = nil
if not file then type = 'Sprite' end
table.insert(actorQueue, {
type = type,
file = file and oat.dir .. file,
init = function(a)
actor.__lock(a)
end
})
actor.__queueRepresentation(actorQueue[#actorQueue])
return actor
end
function ActorFrame()
if actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
local actor = createProxyActor('ActorFrame')
table.insert(actorQueue, {
type = 'ActorFrame',
init = function(a)
actor.__lock(a)
end
})
actor.__queueRepresentation(actorQueue[#actorQueue])
return actor
end
local function isShaderCode(str)
return string.find(str or '', '\n')
end
function Shader(frag, vert)
if actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
local actor = createProxyActor('RageShaderProgram')
local fragFile = frag
local vertFile = vert
local isFragShaderCode = isShaderCode(frag)
local isVertShaderCode = isShaderCode(vert)
if isFragShaderCode then fragFile = nil end
if isVertShaderCode then vertFile = nil end
if (frag and vert) and ((isFragShaderCode and not isVertShaderCode) or (not isFragShaderCode and isVertShaderCode)) then
error('uranium: cannot create a shader with 1 shader file and 1 shader code block', 2)
end
table.insert(actorQueue, {
type = 'Sprite',
frag = fragFile and ('../' .. fragFile) or 'nop.frag',
vert = vertFile and ('../' .. vertFile) or 'nop.vert',
init = function(a)
a:hidden(1)
actor.__lock(a:GetShader())
-- shader code stuff
if isFragShaderCode or isVertShaderCode then
a:GetShader():compile(vert or '', frag or '')
end
end
})
actor.__queueRepresentation(actorQueue[#actorQueue])
return actor
end
function Texture(file)
if actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
if not file then error('uranium: cannot create a texture without a file', 2) end
local actor = createProxyActor('RageTexture')
table.insert(actorQueue, {
file = file and oat.dir .. file,
init = function(a)
a:hidden(1)
actor.__lock(a:GetTexture())
end
})
actor.__queueRepresentation(actorQueue[#actorQueue])
return actor
end
function Model(file)
if actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
if not file then error('uranium: cannot create a Model without a file', 2) end
local actor = createProxyActor('Model')
table.insert(actorQueue, {
type = nil,
file = file and oat.dir .. file,
init = function(a)
actor.__lock(a)
end
})
actor.__queueRepresentation(actorQueue[#actorQueue])
return actor
end
function BitmapText(font, text)
if actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
local actor = createProxyActor('BitmapText')
table.insert(actorQueue, {
type = 'BitmapText',
font = font or 'common',
init = function(a)
if text then a:settext(text) end
actor.__lock(a)
end
})
actor.__queueRepresentation(actorQueue[#actorQueue])
return actor
end
function ActorSound(file)
if actorsInitializing then error('uranium: cannot create an actor during actor initialization!!', 2) end
if actorsInitialized then error('uranium: cannot create an actor during runtime!!', 2) end
if not file then error('uranium: cannot create an ActorSound without a file', 2) end
local actor = createProxyActor('ActorSound')
table.insert(actorQueue, {
type = 'ActorSound',
file = oat.dir .. file,
init = function(a)
actor.__lock(a)
end
})
actor.__queueRepresentation(actorQueue[#actorQueue])
return actor
end
function addChild(frame, actor)
if not frame or not actor then
error('uranium: frame and actor must both Exist', 2)
end
if actorsInitializing then
error('uranium: cannot create frame-child associations during actor initialization', 2)
end
if actorsInitialized then
error('uranium: cannot create frame-child associations after actors have been initialized', 2)
end
if not frame.__lock then
error('uranium: ActorFrame passed into addChild must be one instantiated with ActorFrame()!', 2)
end
if not actor.__lock then
error('uranium: trying to add a child to an ActorFrame that isn\'t an actor; please read the first half of \'ActorFrame\'', 2)
end
actorAssociationQueue[actor.__queue] = frame.__queue
table.insert(actorAssociationTable[frame], actor)
end
local function transformQueueToTree()
local tree = {}
local paths = {}
local iter = 0
while #actorQueue > 0 do
iter = iter + 1
if iter > 99999 then
error('uranium: failed to transform queue to tree: reached maximum iteration limit! is there an actor with an invalid actorframe?')
end
for i = #actorQueue, 1, -1 do
v = actorQueue[i]
local insertInto
if not actorAssociationQueue[v] then
insertInto = tree
else
if paths[actorAssociationQueue[v]] then
insertInto = paths[actorAssociationQueue[v]]
end
end
if insertInto then
if v.type == 'ActorFrame' then
table.insert(insertInto, {init = v.init})
table.remove(actorQueue, i)
paths[v] = insertInto[#insertInto]
else
table.insert(insertInto, v)
table.remove(actorQueue, i)
end
end
end
end
actorTree = tree
end
require 'uranium.actors'
local lastt = GAMESTATE:GetSongTime()
local function screenReadyCommand(self)
@ -679,13 +106,13 @@ local function screenReadyCommand(self)
self:hidden(0)
oat._actor = {}
actorQueue = {}
actorAssociationQueue = {}
oat._actorQueue = {}
oat._actorAssociationQueue = {}
actorTree = {}
currentPath = nil
pastPaths = {}
currentActor = nil
oat._actorTree = {}
oat._currentPath = nil
oat._pastPaths = {}
oat._currentActor = nil
collectgarbage()
@ -719,7 +146,7 @@ local function screenReadyCommand(self)
drawfunctionArguments = {}
for _, q in ipairs(globalQueue) do
for _, q in ipairs(oat._globalQueue) do
local enabled = resetOnFrameStartCfg
local actor = q[1]
@ -733,7 +160,7 @@ local function screenReadyCommand(self)
if not func then
-- uhmmm ??? hm. what do we do??
else
patchFunction(func, actor)(unpack(v[2]))
oat._patchFunction(func, actor)(unpack(v[2]))
end
end
end
@ -763,9 +190,9 @@ if success then
print('---')
actorsInitializing = true
transformQueueToTree()
--Trace(fullDump(actorTree))
currentPath = actorTree
oat._transformQueueToTree()
--Trace(fullDump(oat._actorTree))
oat._currentPath = oat._actorTree
_main:addcommand('On', onCommand)
_main:addcommand('Ready', screenReadyCommand)