System addition/removal. I'm not doing topo sort (today)

This commit is contained in:
BirDt_ 2026-03-28 18:52:48 +08:00
parent 9be97de885
commit 04a6555cbd
2 changed files with 119 additions and 6 deletions

View file

@ -23,16 +23,14 @@ Components are SRFI-99 records which store data associated for a particular enti
** Systems
Systems are functions which modify state and draw to the screen.
Systems are stored in the ~systems~ list as a record containing a name (symbol), rendering (a symbol), a priority (integer), dependencies (list of symbols), entity criteria (list of symbols), and the function itself.
Systems are stored in the ~systems~ list as a record containing a name (symbol), rendering (a symbol), a priority (integer), entity criteria (list of symbols), and the function itself.
Each system specifies the components an entity (the entity criteria) must have for it to be processed by that system. The entities are then selected for the system from the ~component-sets~.
Each system is applied to all entities which match its entity criteria.
Systems have a priority which defaults to 0. Lower priority systems will be executed before higher priority systems. Systems within the same priority execute in order of addition to the ~systems~ list.
Systems can depend on other systems, which moves them to execute after the system specified.
If a system defines a rendering symbol of 3D, it will be wrapped in ~with-mode-3d~. If a system defines a rendering symbol of 2D, it will be wrapped in ~with-mode-2d~. All systems run in render loop, wrapped in ~with-drawing~, and can draw non-2D and non-3D elements arbitrarily. In this way ~with-mode-3d~ and ~with-mode-2d~ can be avoided in system function bodies, and non-3D/2D systems can draw in screen space.
The ~systems~ list is sorted on each addition and removal of a system.
Removal of a system which has dependent systems results in an error.
Addition of a system which creates a circular dependency loop results in an error.
Like entities, the addition of systems is queued for the beginning of each frame. This prevents the system list from being sorted multiple times per frame.
Systems can access resources via free variables or by being formed as closures. Systems only ever take an entity (a component list) as input.

View file

@ -1,7 +1,7 @@
(module (engine core)
(add-entity add-named-entity remove-entity)
(module (engine core) ()
(import scheme
(chicken base)
(chicken module)
;; raylib
(srfi 1)
(srfi 69)
@ -89,6 +89,14 @@
del-entity-queue)
(set! del-entity-queue '()))
;; Resolve all queued entity changes
(define (resolve-entity-queue)
(remove-queued-entities)
(add-queued-entities))
;; Entity creation/removal interface
(export add-named-entity add-entity remove-entity)
;; Create an entity in the world and return it's ID
(define (add-named-entity id . components)
(assert (symbol? id))
@ -105,4 +113,111 @@
(assert (symbol? id))
(queue-del-entity id)
id)
;; System record interface
(export make-system system? system-name system-rendering
system-priority set-system-priority! system-criteria
set-system-criteria! system-process set-system-process!)
;; The system record
(define-record-type <system>
(internal-make-system name rendering priority criteria process)
system?
(name system-name)
(rendering system-rendering)
(priority system-priority internal-set-system-priority!)
(criteria system-criteria internal-set-system-criteria!)
(process system-process internal-set-system-process!))
;; Type-checked system constructor wrapper
(define (make-system name rendering priority criteria process)
(assert (symbol? name))
(assert (and (symbol? rendering) (member rendering '(3d 2d screen none))))
(assert (integer? priority))
(assert (every symbol? criteria))
(assert (procedure? process))
(internal-make-system name rendering priority criteria process))
;; Type-checked system priority mutator
(define (set-system-priority! system priority)
(assert (system? system))
(assert (integer? priority))
(internal-set-system-priority! system priority))
;; Type-checked system criteria mutator
(define (set-system-criteria! system criteria)
(assert (system? system))
(assert (every symbol? criteria))
(internal-set-system-criteria! system criteria))
;; Type-checked system process mutator
(define (set-system-process! system process)
(assert (system? system))
(assert (procedure? process))
(internal-set-system-process! system process))
;; The systems list
(define systems '())
;; Immediately add a new system
(define (add-system-now system)
(set! systems
(append systems (list system))))
;; Immediately remove a new system
(define (remove-system-now name)
(set! systems
(delete name systems
(lambda (n el)
(eqv? n (system-name el))))))
;; System addition/deletion queues
(define add-system-queue '())
(define del-system-queue '())
;; Add a system to the incoming queue
(define (queue-add-system system)
(set! add-system-queue
(append add-system-queue (list system))))
;; Add a system to the deletion queue
(define (queue-del-system name)
(set! del-system-queue
(append del-system-queue (list name))))
;; Resolve all new system creations
(define (add-queued-systems)
(for-each
(lambda (system)
(add-system-now system))
add-system-queue)
(set! add-system-queue '()))
;; Resolve all queued system deletions
(define (remove-queued-systems)
(for-each
(lambda (system-name)
(remove-system-now system-name))
del-system-queue)
(set! del-system-queue '()))
;; Resolve all queued system changes
(define (resolve-system-queue)
(remove-queued-systems)
(add-queued-systems))
;; System creation/removal interface
(export add-system remove-system)
;; Add a system to the state processing and return its name
(define (add-system system)
(assert (system? system))
(queue-add-system system)
(system-name system))
;; Remove a system from process
(define (remove-system name)
(assert (symbol? name))
(queue-del-system name)
name)
)