forked from nandryshak/ECS
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsystem.lisp
80 lines (67 loc) · 2.71 KB
/
system.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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
(in-package :cl-ecs)
(defstruct (system (:conc-name nil))
required
grouping
entities)
(defmacro defsys (name (required grouping) &body body)
"Define a new system."
(let ((entities (gensym)))
`(progn
(setf (gethash ',name (ecs-systems *ecs*))
(make-system :required ',required
:grouping ',grouping))
(cache-system-entities)
(defmethod %do-entities ((system (eql ',name)) &rest ,entities)
(block ,name
(destructuring-bind ,grouping ,entities
,@body))))))
(defgeneric %do-entities (system &rest entities))
(defun all-systems ()
"Get a list of all defined systems."
(hash-table-keys (ecs-systems *ecs*)))
(defun required-components (system)
"Get a list of the specified system's required components."
(required (gethash system (ecs-systems *ecs*))))
(defun (setf required-components) (value system)
"Assign a list of required components to the specified system."
(setf (required (gethash system (ecs-systems *ecs*))) value))
(defun system-grouping (system)
"Get the list of grouping information for the specified system."
(grouping (gethash system (ecs-systems *ecs*))))
(defun collect-system-entities (system)
"Create a list of all of a system's entities."
(loop :with r = (required-components system)
:for (id . e) :in (hash-table-alist (ecs-entities *ecs*))
:for c = (components e)
:when (or (not r)
(and (listp r) (all r c))
(and (eq r :none) (not c))
(and (eq r :any) c))
:collect id))
(defun system-entities (system)
"Get a list of all of a system's entities."
(entities (gethash system (ecs-systems *ecs*))))
(defun (setf system-entities) (value system)
"Assign a list of entities to the specified system."
(setf (entities (gethash system (ecs-systems *ecs*))) value))
(defun cache-system-entities ()
"Update the the list of entities for all systems."
(loop :for system :in (all-systems)
:do (setf (system-entities system) (collect-system-entities system))))
(defmethod do-system (system)
"Execute the specified system. The system definition's grouping determines
parallel processing of entities."
(let ((grouping (length (system-grouping system)))
(entities (system-entities system))
(result))
(when (>= (length entities) grouping)
(if (= (length entities) 1)
(setf result (apply #'%do-entities system entities))
(map-combinations
(lambda (x) (setf result (apply #'%do-entities system x)))
entities :length grouping))
result)))
(defun cycle-systems ()
"Cycle through all defined systems."
(dolist (system (all-systems))
(do-system system)))