// File: tomfunkhouser[P]gaps/pkgs/R3Utils/R3SurfelViewer.cpp
// Function: gaps::R3SurfelViewer::MouseButton(int, int, int, int, int, int, int, int)
int R3SurfelViewer::
MouseButton(int x, int y, int button, int state, int shift, int ctrl, int alt, int update_center_point)
{
  // Initialize
  int redraw = 0;

  // Process mouse button event
  if (state == 1) {
    // Button is going down
    mouse_drag_distance_squared = 0;

    // Remember mouse down position 
    mouse_down_position[0] = x;
    mouse_down_position[1] = y;

    // Process thumbwheel
    if ((button == 3) || (button == 4)) {
      R3Point viewing_center_point = center_point;
      const R3Camera& camera = viewer.Camera();
      R3Plane camera_plane(camera.Origin(), camera.Towards());
      RNScalar signed_distance = R3SignedDistance(camera_plane, viewing_center_point);
      if (signed_distance < 0) viewing_center_point -= (signed_distance - 1) * camera.Towards();
      if (button == 3) viewer.ScaleWorld(viewing_center_point, 1.1);
      else if (button == 4) viewer.ScaleWorld(viewing_center_point, 0.9);
      redraw = TRUE;
    }
  }
  else {
    // Check for drag
    RNBoolean drag = (mouse_drag_distance_squared > 10 * 10);

    // Check for double click
    static RNBoolean double_click = FALSE;
    static RNTime last_mouse_down_time;
    double_click = !drag && !double_click && (last_mouse_down_time.Elapsed() < 0.4);
    last_mouse_down_time.Read();

    // Select stuff on left click 
    if (!drag && update_center_point) {
      // Select image
      R3Point pick_position;
      R3SurfelImage *picked_image = PickImage(x, y, &pick_position);
      if (picked_image) {
        if (button == 0) SelectImage(picked_image, FALSE, FALSE);
        SetCenterPoint(pick_position);
        redraw = TRUE;
      }
      else {
        // Select point
        int picked_surfel_index = -1;
        R3SurfelBlock *picked_block = NULL;
        if (PickNode(x, y, &pick_position, &picked_block, &picked_surfel_index)) {
          // Hit
          if ((button == 0) && (picked_surfel_index >= 0)) {
            SelectPoint(picked_block, picked_surfel_index);
            if (selected_point && !image_plane_visibility) {
              R3SurfelImage *image = scene->FindImageByBestView(selected_point->Position(), selected_point->Normal());
              SelectImage(image, FALSE, FALSE);
            }
          }
          SetCenterPoint(pick_position);
          redraw = TRUE;
        }
        else {
          // Miss
          SelectPoint(NULL, -1);
          redraw = TRUE;
        }
      }
    }

    // Redraw if was subsampling
    if (subsampling_multiplier_when_mouse_down > 1) redraw = TRUE;
  }

  // Remember mouse position 
  mouse_position[0] = x;
  mouse_position[1] = y;

  // Remember button state 
  mouse_button[button] = state;
  
  // Remember modifiers 
  shift_down = shift;
  ctrl_down = ctrl;
  alt_down = alt;

  // Return whether need redraw
  return redraw;
}

// Assembly:
subq $0x168, %rsp            # imm = 0x168
movl 0x180(%rsp), %eax
movl 0x178(%rsp), %eax
movl 0x170(%rsp), %eax
movq %rdi, 0x160(%rsp)
movl %esi, 0x15c(%rsp)
movl %edx, 0x158(%rsp)
movl %ecx, 0x154(%rsp)
movl %r8d, 0x150(%rsp)
movl %r9d, 0x14c(%rsp)
movq 0x160(%rsp), %rax
movq %rax, 0x30(%rsp)
movl $0x0, 0x148(%rsp)
cmpl $0x1, 0x150(%rsp)
jne 0x36af0
movq 0x30(%rsp), %rax
movl $0x0, 0x4b8(%rax)
movl 0x15c(%rsp), %ecx
movl %ecx, 0x4b0(%rax)
movl 0x158(%rsp), %ecx
movl %ecx, 0x4b4(%rax)
cmpl $0x3, 0x154(%rsp)
je 0x36990
cmpl $0x4, 0x154(%rsp)
jne 0x36aeb
movq 0x30(%rsp), %rsi
addq $0x2b0, %rsi            # imm = 0x2B0
leaq 0x130(%rsp), %rdi
callq 0x162300
movq 0x30(%rsp), %rdi
addq $0x78, %rdi
callq 0x2f6d0
movq %rax, 0x128(%rsp)
movq 0x128(%rsp), %rdi
callq 0x2ee60
movq %rax, 0x28(%rsp)
movq 0x128(%rsp), %rsi
leaq 0xf0(%rsp), %rdi
callq 0x2eea0
movq 0x28(%rsp), %rsi
leaq 0x108(%rsp), %rdi
leaq 0xf0(%rsp), %rdx
callq 0x15fa20
leaq 0x108(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0xf1220
movsd %xmm0, 0xe8(%rsp)
xorps %xmm0, %xmm0
ucomisd 0xe8(%rsp), %xmm0
jbe 0x36a8c
movsd 0xe8(%rsp), %xmm0
movsd 0x20a5d3(%rip), %xmm1   # 0x241010
subsd %xmm1, %xmm0
movsd %xmm0, 0x20(%rsp)
movq 0x128(%rsp), %rsi
leaq 0xb8(%rsp), %rdi
callq 0x2eea0
movsd 0x20(%rsp), %xmm0
leaq 0xd0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x2f4b0
leaq 0x130(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x163000
cmpl $0x3, 0x154(%rsp)
jne 0x36ab6
movq 0x30(%rsp), %rdi
addq $0x78, %rdi
leaq 0x130(%rsp), %rsi
movsd 0x20aaa9(%rip), %xmm0   # 0x241558
callq 0xcd830
jmp 0x36ae0
cmpl $0x4, 0x154(%rsp)
jne 0x36ade
movq 0x30(%rsp), %rdi
addq $0x78, %rdi
leaq 0x130(%rsp), %rsi
movsd 0x20aa17(%rip), %xmm0   # 0x2414f0
callq 0xcd830
jmp 0x36ae0
movl $0x1, 0x148(%rsp)
jmp 0x36dd7
movq 0x30(%rsp), %rax
cmpl $0x64, 0x4b8(%rax)
setg %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0xb4(%rsp)
cmpb $0x0, 0x29ba0e(%rip)    # 0x2d2520
jne 0x36b3f
leaq 0x29ba05(%rip), %rdi    # 0x2d2520
callq 0x29360
cmpl $0x0, %eax
je 0x36b3f
leaq 0x29b9e4(%rip), %rdi    # 0x2d2510
callq 0x1a20c0
jmp 0x36b33
leaq 0x29b9e6(%rip), %rdi    # 0x2d2520
callq 0x286a0
xorl %eax, %eax
cmpl $0x0, 0xb4(%rsp)
movb %al, 0x1f(%rsp)
jne 0x36b80
xorl %eax, %eax
cmpl $0x0, 0x29b9b0(%rip)    # 0x2d2508
movb %al, 0x1f(%rsp)
jne 0x36b80
leaq 0x29b9ab(%rip), %rdi    # 0x2d2510
callq 0x1a2180
movaps %xmm0, %xmm1
movsd 0x20a4ab(%rip), %xmm0   # 0x241020
ucomisd %xmm1, %xmm0
seta %al
movb %al, 0x1f(%rsp)
movb 0x1f(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x29b979(%rip)    # 0x2d2508
leaq 0x29b97a(%rip), %rdi    # 0x2d2510
callq 0x2ef40
cmpl $0x0, 0xb4(%rsp)
jne 0x36dbc
cmpl $0x0, 0x180(%rsp)
je 0x36dbc
leaq 0x88(%rsp), %rdi
callq 0x1622b0
movq 0x30(%rsp), %rdi
movl 0x15c(%rsp), %esi
movl 0x158(%rsp), %edx
movq (%rdi), %rax
leaq 0x88(%rsp), %rcx
callq *0x1e8(%rax)
movq %rax, 0x80(%rsp)
cmpq $0x0, 0x80(%rsp)
je 0x36c6c
cmpl $0x0, 0x154(%rsp)
jne 0x36c46
movq 0x30(%rsp), %rdi
movq 0x80(%rsp), %rsi
movq (%rdi), %rax
xorl %ecx, %ecx
movl %ecx, %edx
callq *0x1c0(%rax)
jmp 0x36c46
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xa8(%rsp)
movl %eax, 0xa4(%rsp)
leaq 0x29b8e4(%rip), %rdi    # 0x2d2520
callq 0x28680
jmp 0x36e42
movq 0x30(%rsp), %rdi
movq (%rdi), %rax
leaq 0x88(%rsp), %rsi
callq *0x80(%rax)
movl $0x1, 0x148(%rsp)
jmp 0x36dba
movq 0x30(%rsp), %rdi
movl $0xffffffff, 0x7c(%rsp) # imm = 0xFFFFFFFF
movq $0x0, 0x70(%rsp)
movl 0x15c(%rsp), %esi
movl 0x158(%rsp), %edx
movq (%rdi), %rax
leaq 0x88(%rsp), %rcx
leaq 0x70(%rsp), %r8
leaq 0x7c(%rsp), %r9
xorl %r10d, %r10d
movl $0x0, (%rsp)
callq *0x1f8(%rax)
cmpq $0x0, %rax
je 0x36d96
cmpl $0x0, 0x154(%rsp)
jne 0x36d73
cmpl $0x0, 0x7c(%rsp)
jl 0x36d73
movq 0x30(%rsp), %rdi
movq 0x70(%rsp), %rsi
movl 0x7c(%rsp), %edx
movq (%rdi), %rax
callq *0x1b8(%rax)
movq 0x30(%rsp), %rax
cmpq $0x0, 0x2c8(%rax)
je 0x36d71
movq 0x30(%rsp), %rax
cmpl $0x0, 0x328(%rax)
jne 0x36d71
movq 0x30(%rsp), %rax
movq 0x8(%rax), %rcx
movq %rcx, 0x10(%rsp)
movq 0x2c8(%rax), %rsi
leaq 0x50(%rsp), %rdi
callq 0x3e1d0
movq 0x30(%rsp), %rax
movq 0x2c8(%rax), %rsi
leaq 0x38(%rsp), %rdi
callq 0x3e6c0
movq 0x10(%rsp), %rdi
leaq 0x50(%rsp), %rsi
leaq 0x38(%rsp), %rdx
callq 0x6a6b0
movq 0x30(%rsp), %rdi
movq %rax, 0x68(%rsp)
movq 0x68(%rsp), %rsi
movq (%rdi), %rax
xorl %ecx, %ecx
movl %ecx, %edx
callq *0x1c0(%rax)
jmp 0x36d73
movq 0x30(%rsp), %rdi
movq (%rdi), %rax
leaq 0x88(%rsp), %rsi
callq *0x80(%rax)
movl $0x1, 0x148(%rsp)
jmp 0x36db8
movq 0x30(%rsp), %rdi
movq (%rdi), %rax
xorl %ecx, %ecx
movl %ecx, %esi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq *0x1b8(%rax)
movl $0x1, 0x148(%rsp)
jmp 0x36dba
jmp 0x36dbc
movq 0x30(%rsp), %rax
cmpl $0x1, 0x490(%rax)
jle 0x36dd5
movl $0x1, 0x148(%rsp)
jmp 0x36dd7
movq 0x30(%rsp), %rax
movl 0x15c(%rsp), %ecx
movl %ecx, 0x4a8(%rax)
movl 0x158(%rsp), %ecx
movl %ecx, 0x4ac(%rax)
movl 0x150(%rsp), %edx
movslq 0x154(%rsp), %rcx
movl %edx, 0x49c(%rax,%rcx,4)
movl 0x14c(%rsp), %ecx
movl %ecx, 0x4bc(%rax)
movl 0x170(%rsp), %ecx
movl %ecx, 0x4c0(%rax)
movl 0x178(%rsp), %ecx
movl %ecx, 0x4c4(%rax)
movl 0x148(%rsp), %eax
addq $0x168, %rsp            # imm = 0x168
retq
movq 0xa8(%rsp), %rdi
callq 0x292e0
nop