Fix issue with (process-load-forms) overwriting slot values, error checking on (referize) and (pointerize) (for #3)
This commit is contained in:
parent
01b787e7bf
commit
67d6fe13b2
5 changed files with 102 additions and 60 deletions
|
@ -72,6 +72,9 @@
|
||||||
:initform (meye 3)))
|
:initform (meye 3)))
|
||||||
(:documentation "Base class for entities in the game."))
|
(:documentation "Base class for entities in the game."))
|
||||||
|
|
||||||
|
(defmethod make-load-form ((this actor) &optional environment)
|
||||||
|
(make-load-form-saving-slots this :environment environment))
|
||||||
|
|
||||||
(defmethod scene ((this actor))
|
(defmethod scene ((this actor))
|
||||||
"The scene containing this actor."
|
"The scene containing this actor."
|
||||||
(deref-pointer [this :slot scene]))
|
(deref-pointer [this :slot scene]))
|
||||||
|
@ -185,11 +188,11 @@
|
||||||
(defmethod resume ((this actor))
|
(defmethod resume ((this actor))
|
||||||
"Initialize or restore this actor's state."
|
"Initialize or restore this actor's state."
|
||||||
; Restore self
|
; Restore self
|
||||||
(resume-setf [this :slot scene])
|
(pointerize-setf [this :slot scene])
|
||||||
(resume-setf [this :slot parent])
|
(pointerize-setf [this :slot parent])
|
||||||
(loop for entry on [this :slot children]
|
(loop for entry on [this :slot children]
|
||||||
when (typep (car entry) 'id-ref)
|
when (typep (car entry) 'id-ref)
|
||||||
do (rplaca entry (resume-ptr (car entry))))
|
do (rplaca entry (pointerize (car entry))))
|
||||||
; Restore components
|
; Restore components
|
||||||
(loop for component in [this components]
|
(loop for component in [this components]
|
||||||
do [component (resume)]))
|
do [component (resume)]))
|
||||||
|
@ -202,9 +205,9 @@
|
||||||
; Suspend self
|
; Suspend self
|
||||||
(loop for entry on [this :slot children]
|
(loop for entry on [this :slot children]
|
||||||
when (typep (car entry) 'weak-pointer)
|
when (typep (car entry) 'weak-pointer)
|
||||||
do (rplaca entry (suspend-ptr (car entry))))
|
do (rplaca entry (referize (car entry))))
|
||||||
(suspend-setf [this :slot scene])
|
(referize-setf [this :slot scene])
|
||||||
(suspend-setf [this :slot parent]))
|
(referize-setf [this :slot parent]))
|
||||||
|
|
||||||
(defmethod update ((this actor))
|
(defmethod update ((this actor))
|
||||||
"Update this actor's components."
|
"Update this actor's components."
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
:initform nil))
|
:initform nil))
|
||||||
(:documentation "Base class for components attached to game entities."))
|
(:documentation "Base class for components attached to game entities."))
|
||||||
|
|
||||||
|
(defmethod make-load-form ((this component) &optional environment)
|
||||||
|
(make-load-form-saving-slots this :environment environment))
|
||||||
|
|
||||||
(defmethod actor ((this component))
|
(defmethod actor ((this component))
|
||||||
"The actor this component belongs to."
|
"The actor this component belongs to."
|
||||||
(deref-pointer [this :slot actor]))
|
(deref-pointer [this :slot actor]))
|
||||||
|
@ -61,8 +64,8 @@
|
||||||
when (and (eq (sb-mop:slot-definition-allocation slot) :instance)
|
when (and (eq (sb-mop:slot-definition-allocation slot) :instance)
|
||||||
(slot-boundp this slot-name))
|
(slot-boundp this slot-name))
|
||||||
do (let ((value (slot-value this slot-name)))
|
do (let ((value (slot-value this slot-name)))
|
||||||
(when (typep value id-ref)
|
(when (typep value 'id-ref)
|
||||||
(setf (slot-value this slot-name) (resume-ptr value))))
|
(setf (slot-value this slot-name) (pointerize value))))
|
||||||
))
|
))
|
||||||
|
|
||||||
(defmethod suspend ((this component))
|
(defmethod suspend ((this component))
|
||||||
|
@ -71,8 +74,8 @@
|
||||||
for slot-name = (sb-mop:slot-definition-name slot)
|
for slot-name = (sb-mop:slot-definition-name slot)
|
||||||
when (slot-boundp this slot-name)
|
when (slot-boundp this slot-name)
|
||||||
do (let ((value (slot-value this slot-name)))
|
do (let ((value (slot-value this slot-name)))
|
||||||
(when (typep value weak-pointer)
|
(when (typep value 'weak-pointer)
|
||||||
(setf (slot-value this slot-name) (suspend-ptr value))))
|
(setf (slot-value this slot-name) (referize value))))
|
||||||
))
|
))
|
||||||
|
|
||||||
(defmethod start ((this component))
|
(defmethod start ((this component))
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
;; serialization.lisp
|
;; serialization.lisp
|
||||||
id-ref make-id-ref
|
id-ref make-id-ref
|
||||||
pointer
|
pointer
|
||||||
suspend-ptr resume-ptr
|
referize pointerize
|
||||||
suspend-setf resume-setf
|
referize-setf pointerize-setf
|
||||||
generate-load-forms
|
generate-load-forms
|
||||||
|
|
||||||
;; actor.lisp
|
;; actor.lisp
|
||||||
|
@ -70,6 +70,7 @@
|
||||||
get-actor get-tagged-actors
|
get-actor get-tagged-actors
|
||||||
update
|
update
|
||||||
destroy
|
destroy
|
||||||
|
resume suspend
|
||||||
|
|
||||||
;; render/drawable.lisp
|
;; render/drawable.lisp
|
||||||
drawable
|
drawable
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
:initform nil))
|
:initform nil))
|
||||||
(:documentation "A scene containing game entities."))
|
(: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)
|
(defmethod print-object ((this scene) stream)
|
||||||
(print-unreadable-object (this stream :type t :identity t)
|
(print-unreadable-object (this stream :type t :identity t)
|
||||||
(prin1 [this :slot id] stream)
|
(prin1 [this :slot id] stream)
|
||||||
|
@ -68,3 +71,15 @@
|
||||||
do [actor (destroy)])
|
do [actor (destroy)])
|
||||||
(remove-scene this))
|
(remove-scene this))
|
||||||
(setf [this :slot destroyed-p] t))
|
(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)]))
|
||||||
|
|
|
@ -8,34 +8,47 @@
|
||||||
|
|
||||||
(deftype pointer () '(or id-ref weak-pointer null))
|
(deftype pointer () '(or id-ref weak-pointer null))
|
||||||
|
|
||||||
(defun suspend-ptr (ptr)
|
(defun referize (ptr)
|
||||||
"Convert weak-pointer ptr to an id-ref."
|
"Convert weak-pointer ptr into an id-ref."
|
||||||
(declare (type weak-pointer ptr))
|
(declare (type weak-pointer ptr))
|
||||||
|
|
||||||
(let (target (weak-pointer-value ptr))
|
(let ((target (weak-pointer-value ptr)))
|
||||||
(cond
|
(cond
|
||||||
((typep target 'scene)
|
((typep target 'scene)
|
||||||
(make-id-ref :scene [target id]))
|
(make-id-ref :scene [target id]))
|
||||||
((typep target 'actor)
|
((typep target 'actor)
|
||||||
(make-id-ref :scene [target scene id]
|
(make-id-ref :scene [target scene id]
|
||||||
:actor [target id]))
|
:actor [target id]))
|
||||||
((typep target 'component)
|
((typep target 'component)
|
||||||
(make-id-ref :scene [target scene id]
|
(make-id-ref :scene [target scene id]
|
||||||
:actor [target actor id]
|
:actor [target actor id]
|
||||||
:component (class-name (class-of target))))
|
:component (class-name (class-of target))))
|
||||||
(t ptr))))
|
(t (error "can't referize ~S (not an actor, component, or scene)" ptr)))))
|
||||||
|
|
||||||
(defun resume-ptr (ref)
|
(defun pointerize (ref)
|
||||||
"Convert id-ref ref to a weak-pointer."
|
"Convert id-ref ref into a weak-pointer."
|
||||||
(declare (type id-ref ref))
|
(declare (type id-ref ref))
|
||||||
|
|
||||||
(let ((scene (get-scene (id-ref-scene ref))) actor component)
|
(let ((scene (get-scene (id-ref-scene ref))) actor component)
|
||||||
(if (setf actor [scene (get-actor (id-ref-actor ref))])
|
(unless scene
|
||||||
(if (setf component [actor (get-component (find-class (id-ref-component ref)))])
|
(error "can't pointerize ~S (scene not found)" ref))
|
||||||
(make-weak-pointer component)
|
(if (id-ref-actor ref)
|
||||||
(make-weak-pointer actor))
|
(if (setf actor [scene (get-actor (id-ref-actor ref))])
|
||||||
|
(if (id-ref-component ref)
|
||||||
|
(if (setf component [actor (get-component (find-class (id-ref-component ref)))])
|
||||||
|
(make-weak-pointer component)
|
||||||
|
(error "can't pointerize ~S (component not found)" ref))
|
||||||
|
(make-weak-pointer actor))
|
||||||
|
(error "can't pointerize ~S (actor not found)" ref))
|
||||||
(make-weak-pointer scene))))
|
(make-weak-pointer scene))))
|
||||||
|
|
||||||
|
(defmacro referize-setf (place)
|
||||||
|
`(when (typep ,place 'weak-pointer)
|
||||||
|
(setf ,place (referize ,place))))
|
||||||
|
(defmacro pointerize-setf (place)
|
||||||
|
`(when (typep ,place 'id-ref)
|
||||||
|
(setf ,place (pointerize ,place))))
|
||||||
|
|
||||||
(defun replace-in-tree (tree atom-fun)
|
(defun replace-in-tree (tree atom-fun)
|
||||||
(if (consp (car tree))
|
(if (consp (car tree))
|
||||||
(replace-in-tree (car tree) atom-fun)
|
(replace-in-tree (car tree) atom-fun)
|
||||||
|
@ -45,29 +58,48 @@
|
||||||
(rplacd tree (funcall atom-fun (cdr tree))))
|
(rplacd tree (funcall atom-fun (cdr tree))))
|
||||||
tree)
|
tree)
|
||||||
|
|
||||||
|
(defun copy-replace-tree (tree atom-fun)
|
||||||
|
(when tree
|
||||||
|
(let ((new-car (car tree)) (new-cdr (cdr tree)))
|
||||||
|
(if (consp new-car)
|
||||||
|
(setf new-car (copy-replace-tree new-car atom-fun))
|
||||||
|
(setf new-car (funcall atom-fun new-car)))
|
||||||
|
(if (consp new-cdr)
|
||||||
|
(setf new-cdr (copy-replace-tree new-cdr atom-fun))
|
||||||
|
(setf new-cdr (funcall atom-fun new-cdr)))
|
||||||
|
(cons new-car new-cdr))))
|
||||||
|
|
||||||
(defun process-load-forms (obj table)
|
(defun process-load-forms (obj table)
|
||||||
(multiple-value-bind (cons-form init-form)
|
(multiple-value-bind (cons-form init-form)
|
||||||
(make-load-form obj)
|
(make-load-form obj)
|
||||||
(let ((sym (gensym))
|
(let ((sym (gensym))
|
||||||
(output-cons-forms ())
|
(output-cons-forms ())
|
||||||
(output-init-forms ()))
|
(output-init-forms ()))
|
||||||
(setf (gethash obj table) (cons sym cons-form))
|
(setf (gethash obj table) sym)
|
||||||
(replace-in-tree init-form (lambda (x)
|
(setf init-form
|
||||||
(cond
|
(copy-replace-tree init-form
|
||||||
; x has already been processed
|
(lambda (x)
|
||||||
((gethash x table)
|
(cond
|
||||||
(car (gethash x table)))
|
;; x has already been processed
|
||||||
; x needs to be run through process-load-forms
|
((gethash x table))
|
||||||
((typep x '(or standard-object structure-object condition class))
|
;; x is an id-ref, just serialize it like this
|
||||||
(multiple-value-bind (x-cons-forms x-init-forms x-sym)
|
((typep x 'id-ref)
|
||||||
(process-load-forms x table)
|
`(make-id-ref :scene ,(id-ref-scene x)
|
||||||
(setf output-cons-forms (nconc output-cons-forms x-cons-forms))
|
:actor ,(id-ref-actor x)
|
||||||
(setf output-init-forms (nconc output-init-forms x-init-forms))
|
:component ,(id-ref-component x)))
|
||||||
x-sym))
|
;; x needs to be run through process-load-forms
|
||||||
; x is a type that doesn't need processing
|
((typep x '(or standard-object structure-object condition class))
|
||||||
(t x))))
|
(multiple-value-bind (x-cons-forms x-init-forms x-sym)
|
||||||
|
(process-load-forms x table)
|
||||||
|
(setf output-cons-forms (nconc output-cons-forms x-cons-forms))
|
||||||
|
(when x-init-forms
|
||||||
|
(setf output-init-forms (nconc output-init-forms x-init-forms)))
|
||||||
|
x-sym))
|
||||||
|
;; x doesn't need processing
|
||||||
|
(t x)))))
|
||||||
(setf output-cons-forms (nconc output-cons-forms `((,sym ,cons-form))))
|
(setf output-cons-forms (nconc output-cons-forms `((,sym ,cons-form))))
|
||||||
(setf output-init-forms (nconc output-init-forms `(,init-form)))
|
(when init-form
|
||||||
|
(setf output-init-forms (nconc output-init-forms `(,init-form))))
|
||||||
(values output-cons-forms output-init-forms sym))))
|
(values output-cons-forms output-init-forms sym))))
|
||||||
|
|
||||||
(defun generate-load-forms (obj)
|
(defun generate-load-forms (obj)
|
||||||
|
@ -77,15 +109,3 @@
|
||||||
,@init-forms
|
,@init-forms
|
||||||
,sym)))
|
,sym)))
|
||||||
|
|
||||||
(defun serialize-instance (obj)
|
|
||||||
"Serialize obj into a Lisp expression that evaluates back to it."
|
|
||||||
(let ((obj-sym (gensym)) forms)
|
|
||||||
(setf forms `(let ((,obj-sym (make-instance ',(class-name (class-of obj)))))))
|
|
||||||
))
|
|
||||||
|
|
||||||
(defmacro suspend-setf (place)
|
|
||||||
`(when (typep ,place 'weak-pointer)
|
|
||||||
(setf ,place (suspend-ptr ,place))))
|
|
||||||
(defmacro resume-setf (place)
|
|
||||||
`(when (typep ,place 'id-ref)
|
|
||||||
(setf ,place (resume-ptr ,place))))
|
|
||||||
|
|
Loading…
Reference in a new issue