REManagedObjects are the basic building blocks of most types in the engine (unless they're native types).
They are returned from methods like:
sdk.call_native_func
sdk.call_object_func
sdk.get_managed_singleton
REManagedObject:call
Example usage:
local scene_manager = sdk.get_native_singleton("via.SceneManager")
local scene_manager_type = sdk.find_type_definition("via.SceneManager")
local scene = sdk.call_native_func(scene_manager, scene_manager_type, "get_CurrentScene")
-- Scene is an REManagedObject
if scene ~= nil then
local current_timescale = scene:call("get_TimeScale")
log.info("Current timescale: " .. tostring(current_timescale))
scene:call("set_TimeScale", 5.0)
end
Custom indexers
self.foo
If foo
is a field or method of the object, returns either the field or REMethodDefinition
if it exists.
self:foo(bar, baz)
If foo
is a method of the object, calls foo
with the supplied arguments.
If the method is an overloaded function, you must instead use self:call(name, args...)
with the correct function prototype, as this does not deduce the correct function based on the passed arguments.
self.foo = bar
If foo
is a field of the object, assigns the value bar
to the field.
This automatically handles the reference counting for the old and new field. Do not use :force_release()
and :add_ref_permanent()
in this case to handle the references.
self[i]
Checks if the object has a get_Item
method and calls it with i
.
self[i] = foo
Checks if the object has a set_Item
method and calls it with i
and foo
as the respective parameters.
Methods
self:call(method_name, args...)
Return value is dependent on the method's return type. Wrapper over sdk.call_object_func
.
Full function prototype can be passed as method_name
if there are multiple functions with the same name but different parameters.
e.g. self:call("foo(System.String, System.Single, System.UInt32, System.Object)", a, b, c, d)
Valid method names can be found in the Object Explorer. Find the type you're looking for, and valid methods will be found under TDB Methods
.
self:get_type_definition()
Returns an RETypeDefinition*
.
self:get_field(name)
Return type is dependent on the field type.
self:set_field(name, value)
self:get_address()
self:get_reference_count()
self:deserialize_native(data, objects)
Experimental API to deserialize data
into self
.
data
is RSZ data, in table
format as an array of bytes.
Will only work on native via
types.
Dangerous Methods
Only use these if necessary!
self:add_ref()
Increments the object's internal reference count.
self:add_ref_permanent()
Increments the object's internal reference count without REFramework managing it. Any objects created with REFramework and also using this method will not be deleted after the Lua state is destroyed.
self:release()
Decrements the object's internal reference count. Destroys the object if it reaches 0. Can only be used on objects managed by Lua.
self:force_release()
Decrements the object's internal reference count. Destroys the object if it reaches 0. Can be used on any REManagedObject. Can crash the game or cause undefined behavior.
When a new Lua reference is created to an REManagedObject
, REFramework automatically increments its reference count internally with self:add_ref()
. This will keep the object alive until you are no longer referencing the object in Lua. self:release()
is automatically called when Lua is no longer referencing the object anywhere.
The only time you will need to manually call self:add_ref()
and self:release()
is when a newly created object is returned by the engine, e.g. an array, or something from sdk.create_instance()
.
A more in-depth explanation can be found in the "FrameGC Algorithm" section of this GDC presentation by Capcom:
https://github.com/kasicass/blog/blob/master/3d-reengine/2021_03_10_achieve_rapid_iteration_re_engine_design.md#framegc-algorithm-17