let display_singleton = (object(self)
inherit display_singleton_type
val mutable renderer = null_renderer
val event_dispatcher = new event_dispatcher
val mutable gl_initialized = false
val mutable next_tick = 0
val mutable antialiasing_passes = 1
method set_antialiasing passes =
assert (passes > 0) ;
antialiasing_passes <- passes
method set_renderer new_renderer = renderer <- new_renderer
| (** Sets the video mode. *) |
method set_video_mode ~width ~height =
Init.init_sdl_once () ;
let _ = Sdlvideo.set_video_mode ~w:width ~h:height [`OPENGL] in
if not gl_initialized then begin
self#init_gl ;
gl_initialized <- true
end else () ;
renderer#set_viewport ~x:0 ~y:0 ~width ~height
method event_dispatcher = event_dispatcher
method render =
GlClear.clear [`color ; `depth ] ;
(*let antialias_passes = 1 in*)
Antialias.accumulate renderer#render antialiasing_passes;
(* Sort of like an Apply button on the OpenGL " :-) *)
Sdlgl.swap_buffers () ;
()
(**
Blocks forever, processing events from SDL.
Events can be detected (and simulated) using
Application.display_singleton.event_dispatcher.
Raises Exit when the user wishes to exit
(for example, by closing the window). Event
listeners may also raise Exit with the same
effect.
*) |
method event_loop =
let rec loop () =
(* This function evaluates all pending events.
Raises Done when the program should terminate. *)
let rec handle_events evt_opt =
match evt_opt with
Some evt ->
begin match evt with
(Sdlevent.KEYDOWN key_evt) ->
event_dispatcher#key#pressed key_evt
| (Sdlevent.KEYUP key_evt) ->
event_dispatcher#key#released key_evt
| (Sdlevent.MOUSEBUTTONDOWN e) ->
event_dispatcher#mouse#pressed e
| (Sdlevent.MOUSEBUTTONUP e) ->
event_dispatcher#mouse#released e
| (Sdlevent.MOUSEMOTION e) ->
if e.Sdlevent.mme_state = [] then
event_dispatcher#mouse#moved e
else
event_dispatcher#mouse#dragged e
| Sdlevent.QUIT ->
raise Exit
| _ -> ignore ()
end ;
handle_events (Sdlevent.poll ())
| None -> ()
in
let donenow = try
handle_events (Sdlevent.poll ()) ; false
with Done -> true
in
match donenow with
false ->
begin let now = Sdltimer.get_ticks () in
match now >= next_tick with
true ->
next_tick <- now + 30 ;
event_dispatcher#ticker#do_tick
| false -> ()
end ;
Sdltimer.delay 1 ;
loop ()
| true ->
print_endline "exiting main loop."
in loop ()
(* interesting: when listeners are added to affectors
(using affector#affect listener) they are appended
to the front of the list of listeners. This means
the first listener added is the last listener executed.
Since the first listener we add to event_dispatcher#tick
is this render function.
Result: Any other tick_listeners we add to the event
dispatcher will be evalutated /before/ the render step. *)
method render_synchronously =
let sync_renderer = object
method do_tick = self#render
end
in event_dispatcher#ticker#affect sync_renderer
method private init_gl =
let blending = true in
print_string "OpenGL Version: " ;
print_endline (GlMisc.get_string `version) ;
(*print_string " ;
print_endline (GlMisc.get_string `extensions) ;*)
(*print_string " ;
print_endline (GlMisc.get_string `renderer) ;
print_string " ;
print_endline (GlMisc.get_string `vendor) ;*)
GlDraw.shade_model `smooth ;
GlClear.color (0.0, 0.0, 0.0) ;
GlClear.depth 1.0 ;
GlMisc.hint `perspective_correction `nicest ;
if false then begin
GlLight.light 0 (`ambient (0.5,0.5,0.5,1.0)) ;
GlLight.light 0 (`diffuse (0.5,0.5,0.5,1.0)) ;
GlLight.light 0 (`position (2.0, 0.0, 2.0, 1.0)) ;
Gl.enable(`lighting) ;
Gl.enable(`light0)
end else () ;
Gl.enable `depth_test ;
GlFunc.depth_func `lequal ;
()
end :> display_singleton_type)