wh-engine/wh-engine/scene.lisp

87 lines
2.8 KiB
Common Lisp

;;;; 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-load-form-saving-slots this :environment environment)
(make-generic-load-form this :environment environment))
(defmethod print-object ((this scene) stream)
(print-unreadable-object (this stream :type t :identity t)
(prin1 [this :slot id] stream)
(princ " ")
(prin1 [this :slot name] stream)))
(defmethod add-actor ((this scene) actor)
"Add an actor to this scene."
(when [actor scene]
(error "~S is already in scene ~S" actor [actor scene]))
(push actor [this :slot actors])
(setf [actor :slot scene] (make-weak-pointer this))
actor)
(defmethod remove-actor ((this scene) actor)
"Remove an actor from this scene."
(unless (eq [actor scene] this)
(error "~S is not in scene ~S" actor this))
(setf [this :slot actors] (delete actor [this :slot actors] :count 1))
(setf [actor :slot scene] nil)
actor)
(defmethod get-actor ((this scene) actor-id)
"Get the actor with the specified ID in this scene."
(find-if (lambda (actor) (eq [actor id] actor-id)) [this actors]))
(defmethod get-tagged-actors ((this scene) tags)
"Get all actors tagged with the given set of tags."
(loop for actor in [this actors]
if (subsetp tags [actor tags])
collect actor))
(defmethod update ((this scene))
"Update all actors in this scene."
(loop for actor in [this actors]
unless (or [actor destroyed-p] (not [actor tree-active-p]))
do [actor (update)]))
(defmethod destroy ((this scene))
"Mark this scene for unloading."
(unless [this destroyed-p]
; We're dead, clean up actors
(loop for actor in [this actors]
do [actor (destroy)])
(remove-scene this))
(setf [this :slot destroyed-p] t))
(defmethod resume ((this scene))
"Initialize or restore this scene's state."
; Restore actors
(loop for actor in [this actors]
do [actor (resume)]))
(defmethod suspend ((this scene))
"Prepare this scene for serialization."
; Suspend actors
(loop for actor in [this actors]
do [actor (suspend)]))