// File: tomfunkhouser[P]gaps/apps/gapsview/gapsview.cpp
// Function: GLUTMouse(int, int, int, int)
static void
GLUTMouse(int button, int state, int x, int y)
{
  // Invert y coordinate
  y = GLUTwindow_height - y;
  
  // Process mouse button event
  if (state == GLUT_DOWN) {
    // Button is going down
    GLUTmouse_drag_distance_squared = 0;

    // Process thumbwheel
    if ((button == 3) || (button == 4)) {
      R3Point viewing_center_point = world_origin;
      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);
    }
  }
  else { // Button is going up
    // Check for drag
    RNBoolean drag = (GLUTmouse_drag_distance_squared > 10 * 10);
    GLUTmouse_drag_distance_squared = 0;

    // Process button 
    if (button == GLUT_LEFT) {
      // Check for double click  
      // static RNBoolean double_click = FALSE;
      // static RNTime last_mouse_down_time;
      // double_click = (!double_click) && (last_mouse_down_time.Elapsed() < 0.4);
      // last_mouse_down_time.Read();

      // Select position
      if (!drag) {
        int e;
        R3Point p;
        if (Pick(x, y, &p, NULL, &e)) {
          world_origin = p;
          if ((e != GSV_CAMERA_ELEMENT_TYPE) && (e != SFL_CAMERA_ELEMENT_TYPE)) {
            selected_position = p;
          }
        }
      }
    }
  }
  
  // Remember button state 
  int b = (button == GLUT_LEFT_BUTTON) ? 0 : ((button == GLUT_MIDDLE_BUTTON) ? 1 : 2);
  GLUTbutton[b] = (state == GLUT_DOWN) ? 1 : 0;

  // Remember modifiers 
  GLUTmodifiers = glutGetModifiers();

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

  // Redraw
  glutPostRedisplay();
}

// Assembly:
subq $0xe8, %rsp
movl %edi, 0xe4(%rsp)
movl %esi, 0xe0(%rsp)
movl %edx, 0xdc(%rsp)
movl %ecx, 0xd8(%rsp)
movl 0x2bf16b(%rip), %eax    # 0x2efaf4
subl 0xd8(%rsp), %eax
movl %eax, 0xd8(%rsp)
cmpl $0x0, 0xe0(%rsp)
jne 0x30afe
movl $0x0, 0x2ce565(%rip)    # 0x2fef14
cmpl $0x3, 0xe4(%rsp)
je 0x309c7
cmpl $0x4, 0xe4(%rsp)
jne 0x30af9
leaq 0xc0(%rsp), %rdi
leaq 0x2cde9a(%rip), %rsi    # 0x2fe870
callq 0x17fdd0
movq 0x2ce2ce(%rip), %rdi    # 0x2fecb0
callq 0x38d50
movq %rax, 0xb8(%rsp)
movq 0xb8(%rsp), %rdi
callq 0x38c00
movq %rax, 0x18(%rsp)
movq 0xb8(%rsp), %rsi
leaq 0x80(%rsp), %rdi
callq 0x38c30
movq 0x18(%rsp), %rsi
leaq 0x98(%rsp), %rdi
leaq 0x80(%rsp), %rdx
callq 0x17d4f0
leaq 0x98(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x10e2d0
movsd %xmm0, 0x78(%rsp)
xorps %xmm0, %xmm0
ucomisd 0x78(%rsp), %xmm0
jbe 0x30aa7
movsd 0x78(%rsp), %xmm0
movsd 0x2355ac(%rip), %xmm1   # 0x266010
subsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rsp)
movq 0xb8(%rsp), %rsi
leaq 0x48(%rsp), %rdi
callq 0x38c30
movsd 0x10(%rsp), %xmm0
leaq 0x60(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x38f20
leaq 0xc0(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0x180ad0
cmpl $0x3, 0xe4(%rsp)
jne 0x30acf
movq 0x2ce1f8(%rip), %rdi    # 0x2fecb0
leaq 0xc0(%rsp), %rsi
movsd 0x2355b0(%rip), %xmm0   # 0x266078
callq 0xeaa40
jmp 0x30af7
cmpl $0x4, 0xe4(%rsp)
jne 0x30af5
movq 0x2ce1d0(%rip), %rdi    # 0x2fecb0
leaq 0xc0(%rsp), %rsi
movsd 0x235580(%rip), %xmm0   # 0x266070
callq 0xeaa40
jmp 0x30af7
jmp 0x30af9
jmp 0x30b9b
cmpl $0x64, 0x2ce40f(%rip)   # 0x2fef14
setg %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x44(%rsp)
movl $0x0, 0x2ce3f9(%rip)    # 0x2fef14
cmpl $0x0, 0xe4(%rsp)
jne 0x30b99
cmpl $0x0, 0x44(%rsp)
jne 0x30b97
leaq 0x28(%rsp), %rdi
callq 0x17fd80
cvtsi2sdl 0xdc(%rsp), %xmm0
cvtsi2sdl 0xd8(%rsp), %xmm1
leaq 0x28(%rsp), %rdi
xorl %eax, %eax
movl %eax, %ecx
leaq 0x40(%rsp), %rdx
movq %rcx, %rsi
callq 0x36550
cmpl $0x0, %eax
je 0x30b95
leaq 0x2cdd06(%rip), %rdi    # 0x2fe870
leaq 0x28(%rsp), %rsi
callq 0x180420
cmpl $0xa, 0x40(%rsp)
je 0x30b93
cmpl $0x8, 0x40(%rsp)
je 0x30b93
leaq 0x2cdcff(%rip), %rdi    # 0x2fe888
leaq 0x28(%rsp), %rsi
callq 0x180420
jmp 0x30b95
jmp 0x30b97
jmp 0x30b99
jmp 0x30b9b
cmpl $0x0, 0xe4(%rsp)
jne 0x30bad
xorl %eax, %eax
movl %eax, 0xc(%rsp)
jmp 0x30bc8
movl 0xe4(%rsp), %edx
movl $0x2, %eax
movl $0x1, %ecx
cmpl $0x1, %edx
cmovel %ecx, %eax
movl %eax, 0xc(%rsp)
movl 0xc(%rsp), %eax
movl %eax, 0x24(%rsp)
movl 0xe0(%rsp), %ecx
xorl %edx, %edx
movl $0x1, %eax
cmpl $0x0, %ecx
cmovel %eax, %edx
movslq 0x24(%rsp), %rcx
leaq 0x2ce328(%rip), %rax    # 0x2fef18
movl %edx, (%rax,%rcx,4)
callq 0x1fc3c0
movl %eax, 0x2ce312(%rip)    # 0x2fef10
movl 0xdc(%rsp), %eax
movl %eax, 0x2ce2fd(%rip)    # 0x2fef08
movl 0xd8(%rsp), %eax
movl %eax, 0x2ce2f4(%rip)    # 0x2fef0c
callq 0x1f4190
addq $0xe8, %rsp
retq
nopw %cs:(%rax,%rax)