wh-engine/wh-engine/scene.lisp

101 lines
3.2 KiB
Common Lisp
Raw Normal View History

2021-11-25 22:28:50 +00:00
;;;; wh-engine/scene.lisp
(in-package wh-engine)
(defclass scene ()
((id :documentation "This scene's unique ID."
:reader id
:type fixnum
:initarg :id
:initform 0)
(name :documentation "This scene's human-readable name."
:accessor name
:type string
:initarg :name
:initform "")
(actors :documentation "A list containing all actors in the scene."
:reader actors
:type (proper-list actor)
:initform nil)
(destroyed-p :documentation "If true, this scene will be unloaded."
:reader destroyed-p
:type boolean
:initform nil))
(:documentation "A scene containing game entities."))
(defmethod make-load-form ((this scene) &optional environment)
(make-generic-load-form this :environment environment))
2021-11-25 22:28:50 +00:00
(defmethod print-object ((this scene) stream)
(print-unreadable-object (this stream :type t :identity t)
2022-02-22 17:16:02 +00:00
(format stream "~D ~S"
(o! this :slot id) (o! this :slot name))))
2021-11-25 22:28:50 +00:00
(defmethod add-actor ((this scene) actor)
"Add an actor to this scene."
(when (o! actor scene)
(error "~S is already in scene ~S" actor (o! actor scene)))
2022-02-22 17:16:02 +00:00
(pushnew actor (o! this :slot actors))
(setf (o! actor :slot scene) (make-weak-pointer this))
2021-11-25 22:28:50 +00:00
actor)
(defmethod remove-actor ((this scene) actor)
"Remove an actor from this scene."
(unless (eq (o! actor scene) this)
2021-11-25 22:28:50 +00:00
(error "~S is not in scene ~S" actor this))
(setf (o! this :slot actors) (delete actor (o! this :slot actors) :count 1))
(setf (o! actor :slot scene) nil)
2021-11-25 22:28:50 +00:00
actor)
(defmethod get-actor ((this scene) actor-id)
"Get the actor with the specified ID in this scene."
(find-if (lambda (actor) (eql (o! actor id) actor-id)) (o! this actors)))
2021-11-25 22:28:50 +00:00
(defmethod get-tagged-actors ((this scene) tags)
"Get all actors tagged with the given set of tags."
(loop for actor in (o! this actors)
if (subsetp tags (o! actor tags))
2021-11-25 22:28:50 +00:00
collect actor))
(defmethod update ((this scene))
"Update all actors in this scene."
(loop for actor in (o! this actors)
unless (or (o! actor destroyed-p) (not (o! actor tree-active-p)))
do (o! actor (update))))
2021-11-25 22:28:50 +00:00
(defmethod destroy ((this scene))
"Mark this scene for unloading."
(unless (o! this destroyed-p)
;; We're dead, clean up actors
(loop for actor in (o! this actors)
do (o! actor (destroy)))
2021-11-25 22:28:50 +00:00
(remove-scene this))
(setf (o! this :slot destroyed-p) t))
(defmethod resume ((this scene))
"Initialize or restore this scene's state."
2022-02-22 17:16:02 +00:00
;; Restore actors
(loop for actor in (o! this actors)
2022-02-22 17:16:02 +00:00
unless (o! actor :slot parent)
do (o! actor (resume))))
(defmethod suspend ((this scene))
"Prepare this scene for serialization."
2022-02-22 17:16:02 +00:00
;; Suspend actors
(loop for actor in (o! this actors)
2022-02-22 17:16:02 +00:00
unless (o! actor :slot parent)
do (o! actor (suspend))))
2022-02-25 00:39:53 +00:00
(defun add-scene (scene)
"Add a scene to the list of running scenes."
(declare (type scene scene))
(push scene *world*)
scene)
(defun remove-scene (scene)
"Remove a scene from the list of running scenes."
(declare (type scene scene))
(setf *world* (remove scene *world*))
scene)