open Caml_xss let dims = ref (180, 80) let mk_color (r, g, b) = (r * 257, g * 257, b * 257) let _color_bg = mk_color (0, 0, 0) let _color0 = mk_color (255, 255, 255) let _color1 = mk_color (120, 80, 255) let _color2 = mk_color (255, 160, 26) let _color3 = mk_color (20, 250, 62) type shape = | Losange of (int * int) (* (x, y) *) | Square of ((int * int) * int) (* ((x, y), size) *) | Circle of ((int * int) * int) (* ((x, y), radius) *) let coords_losange (x, y) = [ (10 + x, 0 + y, 16 + x, 10 + y); (16 + x, 10 + y, 10 + x, 20 + y); (10 + x, 20 + y, 4 + x, 10 + y); ( 4 + x, 10 + y, 10 + x, 0 + y); ] module UserSaver = struct type _state = { colormap: Caml_xss.colormap; color_bg: pixel; color0: pixel; color1: pixel; color2: pixel; color3: pixel; shapes: shape list; } type state = _state ref let bounded_square (w, h) ((x, y), s) = if x > w then ((0 - s, y), s) else ((x, y), s) let bounded_circle (w, h) ((x, y), r) = if (x) > w then (((0 - r), y), r) else ((x, y), r) let move_shapes shapes = List.map (fun shape -> match shape with | Losange (x, y) -> Losange (x, y) | Square ((x, y), s) -> Square ((x + 1, y), s) | Circle ((x, y), r) -> Circle ((x + 1, y), r) ) shapes let bounded_shapes dims shapes = List.map (fun shape -> match shape with | Losange (x, y) -> Losange (x, y) | Square square -> Square (bounded_square dims square) | Circle circle -> Circle (bounded_circle dims circle) ) shapes let update_shapes dims shapes = move_shapes shapes |> bounded_shapes dims let update_state dims state = { state with shapes = update_shapes dims state.shapes } type user_calls = { saver_init: x_elems -> state; saver_draw: x_elems -> state -> int; saver_reshape: x_elems -> state -> int -> int -> unit; saver_free: x_elems -> state -> unit; } let new_square (w, h) = Square ((Random.int w, Random.int h), 20) let new_circle (w, h) = Circle ((Random.int w, Random.int h), 20) let init_shapes n dims = List.init n (fun _ -> if Random.float 1.0 > 0.6 then new_circle dims else new_square dims ) let saver_init = (fun xelms -> Random.self_init (); let colormap = X.default_colormap xelms in let color_bg = X.alloc_color xelms colormap _color_bg in let color0 = X.alloc_color xelms colormap _color0 in let color1 = X.alloc_color xelms colormap _color1 in let color2 = X.alloc_color xelms colormap _color2 in let color3 = X.alloc_color xelms colormap _color3 in ref { colormap; color_bg; color0; color1; color2; color3; shapes = []; (* shapes = [ (* Losange (20, 30); Losange (36, 32); Square ((60, 50), 10); Square ((80, 60), 10); *) Square ((100, 80), 20); Circle ((100, 80), 20) ]; *) } ) let saver_reshape = (fun xelms _state w h -> dims := (w, h); let state = !_state in let shapes = if state.shapes = [] then init_shapes 12 (w, h) else state.shapes in _state := { state with shapes }; ) let saver_free = (fun xelms state -> print_newline ()) let saver_draw = (fun xelms _state -> let state = !_state in _state := update_state (!dims) state; let w, h = !dims in X.set_foreground xelms state.color_bg; X.fill_rectangle xelms (0, 0, w, h); (* X.set_foreground xelms state.color0; List.iter (X.draw_point xelms) [ (20, 20); (22, 20); (24, 20); (26, 20)]; *) let draw_circle ((x, y), r) = X.set_foreground xelms state.color3; X.draw_arc xelms (x, y, r, r, 0, 360*64); in begin List.iter (fun shape -> match shape with | Losange (x, y) -> X.set_foreground xelms state.color1; let losange_coords = coords_losange (x, y) in List.iter (X.draw_line xelms) losange_coords; | Square ((x, y), s) -> X.set_foreground xelms state.color2; List.iter (X.draw_rectangle xelms) [(x, y, s, s)]; List.iter (X.draw_point xelms) [(x + s, y + s)]; | Circle circle -> draw_circle circle ) state.shapes; end; (* X.set_foreground xelms state.color3; X.draw_arc xelms (40, 60, 20, 20, 0, 360*64); X.draw_arc xelms (0, 0, 30, 30, 0, 360*64); *) (* (40_000) *) (80_000) ) let user_saver = { saver_init; saver_reshape; saver_free; saver_draw; } end module SomeSaver = MakeSaver(UserSaver)