Преглед изворни кода

- Thanks to SIapran for the new FFIClass
- Trying a FFI struct based component storage
- Resturctured the debug menu for future modular implementation (ability to register more easily whole menus for specific things)

Eiyeron Fulmincendii пре 8 година
родитељ
комит
6f88aa2fd9
5 измењених фајлова са 116 додато и 49 уклоњено
  1. 52 0
      class/fficlass.lua
  2. 31 22
      debug_overlay/init.lua
  3. 0 19
      ecs/Component.lua
  4. 22 2
      ecs/ECS.lua
  5. 11 6
      main.lua

+ 52 - 0
class/fficlass.lua

@@ -0,0 +1,52 @@
+local class = require("class")
+local ffi = require("ffi")
+local rawget = rawget
+
+local c_id = 0
+local function make_C_identifier( )
+    local res = "id" .. c_id
+    c_id = c_id + 1
+    return res
+end
+
+local function ffi_make_meta( self )
+    local c_id = make_C_identifier()
+    ffi.cdef("typedef struct {" .. self.__cdef .. "} " .. c_id ..";")
+    self.__ctype = ffi.metatype(c_id, self)
+    self.__c_id = c_id
+end
+
+local function ffi_new(self, ...)
+    if not rawget(self, "__ctype") then
+        ffi_make_meta(self)
+    end
+    local res = self.__ctype()
+    if self.init then
+        res:init(...)
+    end
+    return res
+end
+
+local function ffi_new_array(self, nb_elem, ...)
+    if not rawget(self, "__ctype") then
+        ffi_make_meta(self)
+    end
+    local res = ffi.new(self.__c_id .. "[?]", nb_elem)
+    if self.init then
+        for i = 0, nb_elem - 1 do
+            res[i]:init(...)
+        end
+    end
+    return res
+end
+
+local function make_ffi_class(structdef, ...)
+    local res = class(...)
+    res.new = ffi_new
+    res.new_array = ffi_new_array
+    res.__cdef = structdef
+    res.is_ffi_class = true
+    return res
+end
+
+return make_ffi_class

+ 31 - 22
debug_overlay/init.lua

@@ -9,42 +9,51 @@ require("imgui")
 local Debug = class(object)
 
 function Debug:init()
-    self.debug_windows = {
-        Console = Console:new(),
-        Graphs = Graphs:new(),
-        Watch = Watch:new(),
-        ECS = ECSDebug:new(),
+    self.debug_menus = {
+        Debug = {
+            Console = Console:new(),
+            Watch = Watch:new(),
+            Graphs = Graphs:new(),
+        },
+        ECS = {
+            ECS = ECSDebug:new()
+        }
     }
-    self.console = self.debug_windows.Console
-    self.watch = self.debug_windows.Watch
+    self.console = self.debug_menus.Debug.Console
+    self.watch = self.debug_menus.Debug.Watch
 end
 
 function Debug:render()
-    self.debug_windows.Graphs:update()
-    -- Menu
+    self.debug_menus.Debug.Graphs:update()
     if imgui.BeginMainMenuBar() then
-        if imgui.BeginMenu("Debug") then
-            for k,v in pairs(self.debug_windows) do
-                if imgui.MenuItem(k, v.shortcut, v.visible) then
-                    v:toggle()
+        for menu,windows in pairs(self.debug_menus) do
+        -- Menu
+            if imgui.BeginMenu(menu) then
+                for k,v in pairs(windows) do
+                    if imgui.MenuItem(k, v.shortcut, v.visible) then
+                        v:toggle()
+                    end
                 end
+                imgui.EndMenu()
             end
-            imgui.EndMenu()
         end
         imgui.EndMainMenuBar()
-    end
-    for k,v in pairs(self.debug_windows) do
-        if v.visible then
-            v:render()
+        for menu,windows in pairs(self.debug_menus) do
+            for k, window in pairs(windows) do
+                if window.visible then
+                    window:render()
+                end
+            end
         end
     end
-
 end
 
 function Debug:keypressed(key)
-    for k,v in pairs(self.debug_windows) do
-        if v.shortcut and key == v.shortcut then
-            v:toggle()
+    for _, windows in pairs(self.debug_menus) do
+        for __, window in pairs(windows) do
+            if window.shortcut and key == window.shortcut then
+                window:toggle()
+            end
         end
     end
 end

+ 0 - 19
ecs/Component.lua

@@ -1,19 +0,0 @@
-local ffi = require("ffi")
-local class, object =  require("class"), require("class.object")
-require("ecs")
-
-local Component = class(object)
-
-local function make_component(name, struct)
-    if type(struct) == "string" then
-        -- Assuming FFI cdef
-        -- TODO : find a way to merge class and userdata
-        local ct = ffi.cdef("typdef struct {"..struct.."} "..name..";")
-        return ffi.metatype(ct, class(Component))
-    elseif struct.instanceof and struct:instanceof(Component) then
-        -- Assuming parent class
-        return class(struct)
-    else
-        return class(Component)
-    end
-end

+ 22 - 2
ecs/ECS.lua

@@ -1,14 +1,34 @@
 local ffi = require("ffi")
 local class, object =  require("class"), require("class.object")
+local fficlass =  require("class.fficlass")
 require("ecs")
 
 local ECS = class(object)
 ECS.N_ENTITIES = 100
 function ECS:init()
     self.entities = ffi.new("entity_t[?]", ECS.N_ENTITIES)
+    -- Making sure that everything is set
+    for i=0,ECS.N_ENTITIES-1 do
+        self.entities[i] = false
+    end
+
+
     self.components = {}
-    self.components["test_t"] = ffi.new("test_t[?]", ECS.N_ENTITIES)
-    self.n_components = 1
+    self.components_classes = {}
+    self.n_components = 0
+end
+
+function ECS:create_component(name, structdef)
+    assert(not self.components_classes[name])
+    local new_component = fficlass("bool _alive;"..structdef)
+    self.components_classes[name] = new_component
+    self.components[name] = new_component:new_array(ECS.N_ENTITIES)
+    self.n_components = self.n_components + 1
+    return new_component
+end
+
+function ECS:get_component(name, id)
+    return self.components[name][id]
 end
 
 return ECS

+ 11 - 6
main.lua

@@ -6,6 +6,12 @@ local inspect = require 'inspect'
 debug_overlay = Debug:new()
 local ecs = ECS:new()
 local a = {b = 42}
+local Position = ecs:create_component("Position", [[
+    int32_t x;
+    int32_t y;
+]])
+local p = ecs:get_component("Position", 42)
+
 _G.debug_overlay = debug_overlay
 _G.ecs = ecs
 
@@ -13,13 +19,12 @@ _G.ecs = ecs
 -- LOVE callbacks
 --
 function love.load(arg)
-    for i=0,100-1 do
-        ecs.entities[i] = false
-    end
-    ecs.entities[0] = true
-    ecs.components.test_t[0]._alive = true
-
 
+    p = Position:new()
+    p.x = 2
+    p.y = 5
+    debug_overlay.watch:add(p, "x")
+    debug_overlay.watch:add(p, "y")
 end
 
 function love.update(dt)