aboutsummaryrefslogtreecommitdiff
path: root/script.it/script_event/click.ml
blob: b7ffcb6f1a403e7a00c7d22e7277df7857766e45 (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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
module State = Script_state.State
module Selection = Script_state.Selection

(** 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
    begin 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
    end
  (*  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;
    begin 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
        begin 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

        end
    end

  | _ when Elements.Timer.delay timer < 0.3 ->
    state

  | _ ->
    drag point state worker state.mode