Last active
July 22, 2022 09:54
-
-
Save kurapica/03f244cc96b9bde3671fbd4b0fa80969 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "PLoop" (function(_ENV) | |
-- Declare the namespace | |
_G.Defold = namespace "Defold" | |
-- Register it as global, so can be easily accessed | |
Environment.RegisterGlobalNamespace(Defold) | |
-- Define the base script class | |
__Sealed__() | |
class "Script" (function(_ENV) | |
local go = _G.go | |
-- Define useful methods | |
function Delete(self) go.delete() end | |
function GetPosition(self) return go.get_position() end | |
function SetPosition(self, pos) return go.set_position(pos) end | |
-- Define the abstract method to be override | |
__Abstract__() function OnUpdate(self) end | |
__Abstract__() function OnMessage(self, id, message, sender) end | |
__Abstract__() function OnReload(self) end | |
__Abstract__() function OnFinal(self) end | |
-- A property to hold the script target | |
property "ScriptTarget" {} | |
-- The constructor to hold the script target | |
function __ctor(self, script) | |
self.ScriptTarget = script | |
end | |
end) | |
-- An attribute to declare the class property to be script property | |
__Sealed__() | |
class "__ScriptAttr__" (function(_ENV) | |
extend "IInitAttribute" "IAttachAttribute" | |
-- Modify the property definition so the value will be get/set in the script target | |
function InitDefinition(self, target, targettype, definition, owner, name, stack) | |
if not Class.IsSubType(owner, Script) then | |
error("The __ScriptAttr__ can only be used on sub class of Defold.Script", stack + 1) | |
end | |
-- Modify the propety's get/set | |
definition.get = function(self) | |
return self.ScriptTarget[name] | |
end | |
definition.set = function(self, value) | |
self.ScriptTarget[name] = value | |
end | |
end | |
-- Attach a data so the Script.Install can diff the script property with common property | |
function AttachAttribute(self, target, targettype, owner, name, stack) | |
return true | |
end | |
-- The attribute can only be used on property | |
property "AttributeTarget" { set = false, default = AttributeTargets.Property } | |
end) | |
-- Define the script install script | |
__Static__() | |
function Script.Install(func) | |
-- Gets the call environment | |
local env = getfenv(2) | |
local scriptClass | |
if Class.Validate(func) then | |
scriptClass = func | |
elseif type(func) == "function" or type(func) == "table" then | |
-- Generate the class from the definition | |
local ok | |
ok, scriptClass = pcall(class, func) | |
if not ok then | |
error(scriptClass, 0) | |
end | |
else | |
error("Usage: Defold.Script.Install(script) - the script must be a class or definition", 2) | |
end | |
if not Class.IsSubType(scriptClass, Script) then | |
error("Usage: Defold.Script.Install(script) - the script must be sub class of Defold.Script", 2) | |
end | |
-- Generate the script properties | |
for name, prop in Class.GetFeatures(scriptClass) do | |
if Property.Validate(prop) and Attribute.HasAttachedData(__ScriptAttr__, prop, scriptClass) then | |
env.go.property(name, prop:GetDefault()) | |
end | |
end | |
-- Create the script class in the init | |
env.init = function(self) self.__inner = scriptClass(self) end | |
-- Check if need update, use GetNormalMethod to ignore the abstract method | |
if Class.GetNormalMethod(scriptClass, "OnUpdate") then | |
env.update = function(self, dt) return self.__inner:OnUpdate(dt) end | |
end | |
-- Check if need on_message | |
if Class.GetNormalMethod(scriptClass, "OnMessage") then | |
env.on_message = function(self, id, msg, sender) return self.__inner:OnMessage(id, msg, sender) end | |
end | |
-- Check if need on_reload | |
if Class.GetNormalMethod(scriptClass, "OnReload") then | |
env.on_reload = function(self) return self.__inner:OnReload() end | |
end | |
-- Check if need final | |
if Class.GetNormalMethod(scriptClass, "OnFinal") then | |
env.final = function(self) return self.__inner:OnFinal() end | |
end | |
end | |
end) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The usage