'AXIAL.INC
'=========  

  % ExplicitMain
  % ColorCodedPick
  % fontA =  "Arial",FW_SEMIBOLD
  uses OpenglSceneFrame
  uses glo2/ShaderSupport
  uses glo2/shaders
  uses glo2/shapes

  static int slflat 'uniform location for flat coloring
  static float plabel[4]
  '
  procedure picklabel(int c)
  ==========================
  indexbase 1
  if pick
    #noprec plabel[1]= c and 0xff          / 0x100
    #noprec plabel[2]= c and 0xff00   >>8  / 0x100
    #noprec plabel[3]= c and 0xff0000 >>16 / 0x100
    plabel[4]=0xff
    glUniform4fv slFlat, 1, plabel
  endif
  end procedure

  def BeginPick
  =============
  if bLeft+bMid+bWheel+bRight then
    if picking=0
      pick=1
    end if
    picking=1 'inhibit further picks till buttons released
  else
    picking=0
  endif
  RebuildFrame:
  end def

  'static float pickpixf[4]
  '
  def EndPick
  ===========
  if pick
    glReadpixels mposx-lpane, crect.bottom-mposy, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, @pickpix
    picked=pickpix and 0xffffff
    pick=0
    goto RebuildFrame 'FULL RENDER
  end if
  end def

  sub thickness(float th=1)
  =========================
  glHint GL_LINE_SMOOTH_HINT, GL_NICEST
  glEnable GL_LINE_SMOOTH
  glLineWidth th
 end sub

  macro MoveThisWithMouse
  =======================
  scope
  int bl,bm,br
  if mode and 1
    'SWAP LEFT/RIGHT BUTTON FUNCTIONS
    bl=bRight
    br=bLeft
  else
    bl=bLeft
    br=bRight
  end if
  bm=bMid
  if bR
    'assume scale 1/16
    'float f=(2.4142-z*8)/crect.bottom
    float f=(32-z)/crect.bottom
    d.x=f*(mposx-sposx)
    d.y=f*(sposy-mposy)
  else
    x+=d.x
    y+=d.y
    z+=d.z
    d.x=0.0
    d.y=0.0
    d.z=0.0
    if snap 'SNAP TO NEAREST
      x=round(x/snap)*snap
      y=round(y/snap)*snap
    end if
  end if
  '
  if bL
    a.y=aa.y+(mposx-sposx)
    a.x=aa.x+(mposy-sposy)
  else
    aa.x=a.x
    aa.y=a.y
  end if
  '
  'if bWheel
  '  if bWheel>0
  '    z-=2.0
  '  else
  '    z+=2.0
  '  end if
  'end if
  '
  if bM
    'Z MOVEMENT 
    float f=(32-z)/crect.bottom
    f=f*(sposy-mposy)*.1
    z-=f
    '
    ''SCALING
    'f=.01
    's.y=sa.y+f*(sposy-mposy)
    'if mode and 16
    '  s.x=sa.x+f*(mposx-sposx)
    '  s.z=s.x
    'else
    '  s.x=s.y
    '  s.z=s.y
    'end if
  else
    sa.x=s.x
    sa.y=s.y
    sa.z=s.z
  end if
  end scope
  end macro

  macro MoveThisWithKeys(mv,an,k)
  ===============================
  if key[VK_CONTROL]
    if key[37] then a.y-=an : k=2  ' left
    if key[39] then a.y+=an : k=2  ' right
    if key[38] then a.x-=an : k=2  ' up
    if key[40] then a.x+=an : k=2  ' down
    if key[33] then a.z+=an : k=2  ' PgUp
    if key[34] then a.z-=an : k=2  ' PgDn
    if key[36] 
      a.x=0. : a.y=0. : a.z=0. : k=3 'HOME'
    end if
    static float m
    m=1.0+m*.01
    if key[0xbd] then s.x/=m : s.y/=m : s.z/=m : k=1  ' -
    if key[0xbb] then s.x*=m : s.y*=m : s.z*=m : k=1  ' =
  else
    scope
    static float m
    if key[VK_SHIFT] then m=mv*3 else m=mv
    if key[37] then x-=m : k=1  ' left
    if key[39] then x+=m : k=1  ' right
    if key[38] then y+=m : k=1  ' up
    if key[40] then y-=m : k=1  ' down
    if key[33] then z-=m : k=1  ' PgUp
    if key[34] then z+=m : k=1  ' PgDn
    end scope
  end if
  end macro


  class MoveableObject
  ====================
  float  x,y,z  'position
  sys    render 'rendering call
  vector s      'scale
  vector a      'angle
  vector aa     'angle anchor
  vector sa     'scale anchor
  vector d      'mouse drag
  int    id     'identity for picking
  float  snap   'snap to grid resolution
  int    mode   'keyboard and mouse movement modes
  int    locked 'movement locked
  int    n      'count of pp indexes   
  word   pp[32] 'indexes to other objects
  '
  method set(sys ii,rr,float xx,yy,zz)
    id=ii   : render=rr
    x=xx  : y=yy  : z=zz
    s.x=1.  : s.y=1.  : s.z=1.
    sa.x=1. : sa.y=1. : sa.z=1.
  end method
  '
  method act()
    '
    'SUPPORTS RANGE OF 100 NAMED PARTS
    if not locked
      if (picked>=id) and (picked<id+100)
        int k
        if mode and 0x100
          MoveThisWithKeys .05,1,k 'macro
        end if
        if not k
          MoveThisWithMouse      'macro
        end if
      else
        d.x=0 : d.y=0 : d.z=0 'not with picked range
      end if
      glTranslatef x+d.x, y+d.y, z
      if s.x then glScalef s.x,s.y,s.z
      if a.z then glRotatef a.z,0,0,1
      if a.y then glRotatef a.y,0,1,0
      if a.x then glRotatef a.x,1,0,0
    end if
    PickLabel id
    if Render then call Render
  end method
  '
  end class

  class moveableObjects
  =====================
  moveableObject*mo
  int qo
  '
  method constructor(int n)
  @mo=getmemory n*sizeof MoveableObject
  qo=n
  end method
  '
  method destructor
  freememory @mo 
  end method
  '
  method index(int n) as MoveableObject*
    return @mo+n*sizeof MoveableObject
  end method
  '
  end class


  macro Usermovement(a,c,n,  i,k)
  ===============================
  if opening
    #ifndef n
      %n=1 'default single object
    #endif
    static MoveableObject a[n]
    '#recordof a
    '#recordof moveableobject
    scope
      int i=n
      int k=c
      for i=1 to n
        a[i].mode=0x101
        a[i].id=k
        k+=100 'addition to base ID
      next
    end scope
  endif
  #if n=1
    a.act()
  #endif
  end macro

  '#recordof usermovement


  procedure TransformToAxis(float *mt,x1,y1,z1, x2,y2,z2, ay=0)
  =============================================================
  float rd,rr,ax,az
  x2-=x1 : y2-=y1 : z2-=z1
  rr=sqr(x2*x2+y2*y2+z2*z2) 'hypot
  rd=y2
  ax=atan(z2,rd)
  rd=hypot(z2,rd)
  az=-atan(x2,rd) 'negate angle
  '
  'TRANSFORMS (APPLIED IN REVERSE ORDER)
  'from mathutil
  LoadIdentity
  Translatef x1,y1,z1
  Rotatef deg(ax),1,0,0
  Rotatef deg(az),0,0,1
  Rotatef deg(ay),0,1,0
  Scalef 1,rr,1
  SaveMatrix mt
  '
  'using opengl transforms instead
  'gltranslatef x1,y1,z1
  'glrotatef deg(ax),1,0,0 'ax clockwise
  'glrotatef deg(az),0,0,1 'az anticlockwise (neg far)
  'glrotatef deg(ay),0,1,0 'ay clockwise axial
  'glscalef 1.0,rr,1.0
  end procedure

  'types
  '====
  '
  type vert float x,y,z
  type tex  float u,v
  type rgba byte  r,g,b,a
  '
