forked from nandryshak/ECS
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcomponent.lisp
51 lines (44 loc) · 1.95 KB
/
component.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
(in-package :cl-ecs)
(defstruct (component (:conc-name nil))
fields)
(defmacro defcomponent (name &body (fields))
"Define a new component with the specified fields.
Also defines accessors for each field to be used on an entity."
(let ((field-list (mapcar (lambda (x)
(intern (format nil "~A/~A" name x)))
fields)))
`(progn
(setf (gethash ',name (ecs-components *ecs*))
(make-component :fields ',field-list))
,@(loop :for field :in field-list
:for key = (make-keyword field)
:collect `(defun ,field (id)
(entity-attr id ,key))
:collect `(defun (setf ,field) (value id)
(setf (entity-attr id ,key) value)))
',name)))
(defun all-components ()
"Get a list of all defined components."
(hash-table-keys (ecs-components *ecs*)))
(defun component-fields (component)
"Get a list of fields for the specified component."
(fields (gethash component (ecs-components *ecs*))))
(defun (setf component-fields) (value component)
"Assign a list of fields to the specified component."
(setf (fields (gethash component (ecs-components *ecs*))) value))
(defun add-component (id component attrs)
"Add a new component to the specified entity."
(when (member component (all-components))
(pushnew component (entity-components id)))
(cache-system-entities)
(loop :for (field . value) :in (plist-alist attrs)
:for fields = (mapcar #'make-keyword (component-fields component))
:when (member field fields)
:do (setf (entity-attr id field) value)))
(defun remove-component (id component)
"Remove a component from the specified entity."
(deletef (entity-components id) component)
(cache-system-entities)
(loop :for field :in (mapcar #'make-keyword (component-fields component))
:when (entity-attr id field)
:do (remove-entity-attr id field)))