86 lines
2.7 KiB
Common Lisp
86 lines
2.7 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))
|
|
|
|
(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)]))
|