type mode = | Edit | Selection of Selection.t | Out type worker_event = Worker_messages.from_worker (* The state cant hold functionnal values, and thus cannot be used to store elements like timer *) type state = { mode : mode ; paths : Outline.t list ; current : Path.Path_Builder.t ; width : float ; angle : float ; rendering : Layer.Paths.printer ; mouse_down_position : Gg.v2 } include Application.Make(struct type t = state end) let post : Brr_webworkers.Worker.t -> Worker_messages.to_worker -> unit = Brr_webworkers.Worker.post let insert_or_replace state ((x, y) as p) stamp path = let width = state.width and angle = state.angle in let point = Path.Point.create ~x ~y ~angle ~width ~stamp in match Path.Path_Builder.peek path with | None -> Path.Path_Builder.add_point point path | Some p1 -> let open Gg.V2 in let p1' = Path.Point.get_coord p1 in let dist = (norm (p1' - (of_tuple p))) in if dist < 5. then ( path ) else ( Path.Path_Builder.add_point point path ) (** Select the given segment, and modify angle and width accordingly *) let select_segment _ (_, selected, p0, p1) state dist = let point' = Path.Point.mix dist (Path.Point.get_coord p0) p0 p1 in let angle = (Float.round @@ 10. *. Path.Point.get_angle point') /. 10. and width = (Float.round @@ 10. *. Path.Point.get_width point') /. 10. in let id = Selection.select_path selected in { state with mode = (Selection id) ; angle ; width } let init = { paths = [] ; current = Path.Path_Builder.empty ; mode = Out ; angle = 30. ; width = 10. ; rendering = `Fill ; mouse_down_position = Gg.V2.ox }