aboutsummaryrefslogtreecommitdiff
path: root/script.it/script_event/click.ml
blob: d1fd2e2d9ddb9f0d9a8d9730c573f7092685a3e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
module State = Script_state.State
module Selection = Script_state.Selection
module Path = Script_path

(** Handle a click outside of the selection *)

type t =
  { point : float * float
  ; timer : Elements.Timer.t
  ; worker : Brr_webworkers.Worker.t
  }

(** The drag function is incorrectly named, as we dont't care if we are
    selecting an element or not.

    But, in the case we are (point, path…), we effectively move the element with the mouse. *)
let drag mouse_coord state worker = function
  | State.Selection t ->
      let mouse_v2 = Gg.V2.of_tuple mouse_coord in
      ( match Selection.find_selection t state.State.paths with
      | None -> state
      | Some (Point (path, point)) ->
          let point' = Path.Point.copy point mouse_v2 in
          State.post worker (`TranslatePoint (point', path));
          (* Just replace the position of the selected point *)
          { state with mode = Selection (Point (path.id, point')) }
      | Some (Path path) ->
          let delta = Gg.V2.(mouse_v2 - state.State.mouse_down_position) in
          State.post worker (`TranslatePath (path, delta));
          state )
  (*  TODO Long click in out mode should translate the whole slate *)
  | _ -> state


let process { point; timer; worker } state =
  match state.State.mode with
  | Edit ->
      let stamp = Elements.Timer.delay timer in
      Elements.Timer.stop timer;
      ( match Path.Path_Builder.peek2 state.current with
      (* If there is at last two points selected, handle this as a curve
          creation. And we add the new point in the current path *)
      | Some _ ->
          let current =
            State.insert_or_replace state point stamp state.current
          in
          let path = Path.Fixed.to_fixed (module Path.Path_Builder) current in

          (* Create a copy from the path with all the interior points *)
          let back =
            Path.Fixed.map path (fun pt ->
                Path.Point.copy pt @@ Path.Point.get_coord' pt )
          in

          let last = Outline.{ path; back; id = Outline.get_id () } in

          (* Send to the worker for a full review *)
          let () = State.post worker (`Complete last) in

          let state =
            { state with
              mode = Out
            ; paths = last :: state.paths
            ; current = Path.Path_Builder.empty
            }
          in
          state
      (* Else, check if there is a curve under the cursor, and remove it *)
      | None ->
          let current = Path.Path_Builder.empty in
          ( match Selection.get_from_paths point state.paths with
          | _, None -> { state with mode = Out; current }
          | dist, Some selection ->
              State.select_segment point selection { state with current } dist
          ) )
  | _ when Elements.Timer.delay timer < 0.3 -> state
  | _ -> drag point state worker state.mode