Rewrite modules functions as macro

This let us recompile initialize/finalize/update functions during
runtime without having to register them once again.
This commit is contained in:
Renaud Casenave-Péré 2014-11-14 20:29:39 +09:00
parent 6b2c2df3bf
commit 9faa777972
6 changed files with 58 additions and 37 deletions

View file

@ -7,7 +7,9 @@
(defpackage stoe.debug
(:nicknames :debug)
(:use :cl
:utils))
:utils)
(:import-from :modules
:defmodule))
(in-package :stoe.debug)
(defvar *swank-server-port* 4006)
@ -46,6 +48,4 @@ start the swank server to accept remote connection."
(setf time-counter 0.0)
(setf frames-counter 0))))
(modules:register-initialize-fun #'initialize)
(modules:register-finalize-fun #'finalize)
(modules:register-update-fun #'update)
(defmodule debug)

View file

@ -8,7 +8,9 @@
(:use :cl)
(:nicknames :game)
(:export :get-world-origin
:get-current-camera))
:get-current-camera)
(:import-from :modules
:defmodule))
(in-package :stoe.game)
(defconstant +loop-step-time+ 16000.0
@ -51,9 +53,7 @@ Advance the world by `delta-time', +loop-step-time+ at a time."
(decf delta-time +loop-step-time+)))
(setf *last-frame-remaining-time* delta-time))
(modules:register-initialize-fun #'initialize)
(modules:register-finalize-fun #'finalize)
(modules:register-update-fun #'update)
(defmodule game)
(defun get-world-origin () *world-origin*)
(defun get-current-camera () *current-camera*)

View file

@ -14,7 +14,9 @@
:job-result
:push-job
:wait-for-job
:cancel-job))
:cancel-job)
(:import-from :modules
:defmodule))
(in-package :stoe.jobs)
(defstruct job
@ -82,9 +84,7 @@ If a thread is available, assign a new job to it."
(if (not (thread-alive-p (thread-thread thread)))
(finalize-thread thread))))))
(modules:register-initialize-fun #'initialize)
(modules:register-finalize-fun #'finalize)
(modules:register-update-fun #'update)
(defmodule jobs)
(defun push-job (fun args)
"Create a new job using `fun' and `data' and push it into the job-list."

View file

@ -8,8 +8,10 @@
(:nicknames :modules)
(:use :cl
:utils)
(:export :register-initialize-fun :register-finalize-fun :register-update-fun
:initialize :finalize :update))
(:export :initialize :finalize :update
:defmodule)
(:import-from :alexandria
:once-only))
(in-package :stoe.modules)
(defparameter *initialize-hook* nil
@ -25,25 +27,32 @@ the program argv.")
Functions attached to this hook should expect an argument containing the time
since last frame.")
(defun initialize (&optional argv)
(defmacro initialize (&optional argv)
"Perform the engine and subsystems initialization process."
(format t "Initialize...~%")
(run-hook *initialize-hook* argv))
`(progn
(format t "Initialize...~%")
,@(loop for fun in *initialize-hook*
collect (list fun argv))))
(defun finalize ()
(defmacro finalize ()
"Perform the engine and subsystems finalization process."
(format t "Finalize...~%")
(run-hook *finalize-hook*))
`(progn
(format t "Finalize...~%")
,@(loop for fun in *finalize-hook*
collect (list fun))))
(defun update (delta-time)
(defmacro update (delta-time)
"Update the modules each loop."
(run-hook *update-hook* delta-time))
`(progn
,@(loop for fun in *update-hook*
collect (list fun delta-time))))
(defun register-initialize-fun (fun)
(add-hook *initialize-hook* fun 'append))
(defun register-finalize-fun (fun)
(add-hook *finalize-hook* fun))
(defun register-update-fun (fun)
(add-hook *update-hook* fun 'append))
(defmacro defmodule (module)
"Register a new module.
The module is expected to have at least `initialize', `update', and `finalize' functions.
`initialize' accepts an optional `argv' argument,
`update' accepts a delta-time argument."
`(progn
(setf *initialize-hook* (append *initialize-hook* (list (intern "INITIALIZE" ',module))))
(push (intern "FINALIZE" ',module) *finalize-hook*)
(setf *update-hook* (append *update-hook* (list (intern "UPDATE" ',module))))))

View file

@ -8,7 +8,9 @@
(:nicknames :render)
(:use :cl
:utils)
(:export :poll-events))
(:export :poll-events)
(:import-from :modules
:defmodule))
(in-package :stoe.render)
(defvar *window* nil)
@ -60,9 +62,7 @@ Render a frame and swap buffers."
(render-scene (game:get-world-origin))
(glop:swap-buffers *window*))
(modules:register-initialize-fun #'initialize)
(modules:register-finalize-fun #'finalize)
(modules:register-update-fun #'update)
(defmodule render)
(defun poll-events ()
"Poll events from the window manager.

View file

@ -22,7 +22,7 @@ continue unless `unprotected' is t."
(update-current-time)
(update-clock clock (get-delta-time))
(render:poll-events)
(modules:update (clock-delta clock))))))
(update (clock-delta clock))))))
(defun quit ()
"Quit the main loop."
@ -55,11 +55,23 @@ continue unless `unprotected' is t."
(go:attach (go:make-object :mesh (with-input-from-string (s f)
(mesh:make-mesh (read s)))) (game:get-world-origin))))
(defun initialize (&optional argv)
"Initialize all the modules passing the optional argv"
(modules:initialize argv))
(defun finalize ()
"Finalize all the modules"
(modules:finalize))
(defun update (delta-time)
"Update all the modules passing the delta time since the last frame"
(modules:update delta-time))
(defun main (&optional argv)
"Run the program."
(modules:initialize argv)
(initialize argv)
(unwind-protect
(progn
(game-start)
(main-loop))
(modules:finalize)))
(finalize)))