I have been looking through a module for dynamic smoke, and I understand most of it but have gotten stuck with this:
export type VoxelModel<T> = {
CreateVoxel: (self: VoxelModel<T>, Position: Vector3, Distance: number, CheckPosition: boolean) -> Voxel?,
ExpandVoxel: (self: VoxelModel<T>, Voxel: Voxel) -> (),
ShootVoxels: (self: VoxelModel<T>, StartPoint: Vector3, EndPoint: Vector3, Thickness: number) -> (),
Clear: (self: VoxelModel<T>) -> (),
Radius: number,
LifeTime: Vector2,
BurstSpeed: Vector2,
Resolution: number,
Model: Model,
Voxels: {}
}
local VoxelModel = {}
VoxelModel.__index = VoxelModel
local function CreateVoxels<T>(Radius: number, Resolution: number, LifeTime: Vector2, BurstSpeed: Vector2):VoxelModel<T>
local self:VoxelModel<T> = (setmetatable({}, VoxelModel) :: unknown) :: VoxelModel<T>
self.Radius = Radius
self.Resolution = Resolution
self.LifeTime = LifeTime
self.BurstSpeed = BurstSpeed
self.Voxels = {}
local Model = Instance.new("Model", workspace)
self.Model = Model
return self
end
local VoxelModel:CreateVoxel()
--stuff here
end
--other functions also here
I am sort of confused at what exactly is happening, but have a general idea. The local VoxelModel is used to define functions that are somehow used by the VoxelModel type, im just confused about how they got there Any clarification on this would be great.
That is just a common way to write OOP-style code in Lua.
The function stored inside VoxelModel are the methods for the objects. Because the VoxelModel table is a metatable for them, the created objects will automatically inherit those methods.
In the example below, the entire class t is also the metatable for any objects of t class. This means those objects will inherit the foo() function and it becomes accessible from the objects themselves, allowing you to call foo by doing object.foo(object) or object:foo()
local t = {}
t.__index = t --t is a metatable and also the class table
t.foo = function(self) --this is a method for the object
print(self.value)
end
local object = setmetatable({}, t) --create a new object as {}, and then use the class table as the metatable
object.value = 123
object:foo() --> this will print 123
--you can verify that foo() is indeed inherited by printing the function
print(object.foo)
--and then compare the memory address with the one inside the metatable:
print(t.foo)
--they should be the same!
You can learn more specifically about that in many other threads:
And then here’s a guide on the type annotations which the module also has: