

  #case capital
  def NULL null
  '=============
  'Opengl Window
  '=============

  'MS Child Windows
  'http://msdn.microsoft.com/en-us/library/ms632598(VS.85).aspx

  '15:20 14/09/2012
  '08:16 15/03/2017
  '15:28 13/01/2018
  '17:34 19/04/2018
  '10:48 20/06/2021
  '07:31 04/06/2022
  '15:45 30/11/2023
  '13:37 27/04/2026


  'Charles E V Pegge
  '
  #fpnprecision single 'no prototype float numbers

  uses ogl

  % TRUE  1
  % FALSE 0

  % SelectBufSize 1024

  type vector
    float x,y,z
  end type

  type ColorType
    float r,g,b,a
  end type

  type      StateType
    float rf,gf,bf,af 'forground color
    float rb,gb,bb,ab 'background color
    float xs,ys,zs    'scale
    float xd,yd,zd    'distance
  end type
  
  =================
  'GLOBAL VARIABLES
  =================

  % nmax 0x100
  sys    hchw[nmax],gwnd
  dword  SelectBuf[SelectBufSize]
  int    texn[nmax],texe 'for texture index
  int    lisn[nmax*4],lisi 'for compiled lists
  int    lpane=0,rpane=0
  int    FrameCount
  double aspect
  string filedrop
  vector*FrameScale
  '
  def       stkmax   32
  StateType StateStack[stkmax] 'stack for color & positionstates
  sys       gwnd
  int       stko 'stack offset
  int       stke=stkmax*sizeof StateType 'stack offset limit

  string    tab=chr(9)
  string    cr=chr(13,10)

  int       sphere,cylinder,cube

  ColorType bcolor at (@StateStack.rb) 
  ColorType fcolor at (@StateStack.rf)
 
  stke = stkmax*sizeof StateType
  bcolor = {0.20, 0.20, 0.40, 1.0}  'background color
  fcolor = {0.00, 0.70, 0.70, 1.0}  'forground and text color



  sys  timer
  sys  timercall
  quad tickcount
  '
  sub timetick (sys lpParameter,TimerOrWaitFired) callback
  ========================================================
  tickcount+=1
  if timercall then call timercall
  end sub

  '
  'FRAME ACTION MODES
  '==================
  'act=0 'general
  'act=1 mouse or keyboard event
  'act=2 timer event
  'act=3 window move event
  'act=4 window size event
  'act=5 window closing

  macro ActOpengl
  ===============
  'itr multithread issue
  'if not closing
  FrameCount++
  if pausing
    if act
      scene hwnd
    endif
  else
    scene hwnd
  end if
  swapBuffers hdc
  opening=0
  act=0
  if key[bkey] then
    act=1
  end if
  'endif
  end macro

  ! scene(sys hwnd)


  % GuiSharedMem "Local\WinGuiState"
  uses winutil
  uses imgwin
  uses chaos
  uses timeutil

  #ifndef opengles
    uses Glo2\OpenglSceneUtil
  #endif

  #ifdef shaders
    uses glo2\ShaderSupport
  #endif
  '
  #ifdef MidiSound
    use minmidi
    sys hmo,ermo
  #endif



  function KeyState(int k) as int
  ===============================
  return GetAsyncKeyState(k) and 0x8000 'key down
  end function


  def SetFun '(name)
  ==================
  @%1=wglGetProcAddress "%1"
  if @%1=0 then print "%1?"
  end def

  sub CloseScene()
  ================
    SendMessage hWndMain,WM_CLOSE,0,0
  end sub
  '
  sub WaitForEvent(int n=1)
  =========================
  pausing=n
  end sub
  '
 
  macro NewFrame()
  ================
  glClear GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT
  glEnable GL_DEPTH_TEST
  glEnable GL_NORMALIZE
  glEnable GL_BLEND
  glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
  glPolygonMode GL_FRONT_AND_BACK, GL_FILL
  #ifndef opengles
    glLoadIdentity
  #endif
  end macro

  macro TimeFrame
  ===============
  static int   countn
  static float FramePeriod,stepn
  scope
  static quad   t1,t2
  stepn=1
  t1=t2
  TimeMark t2
  if t1
    FramePeriod=TimeDiff t2,t1
    if FramePeriod>.02              'quantum 60Hz 0.0166
      stepn=round(FramePeriod*60.0) 'moment scale
      countn+=stepn-1               'count missed frames
    end if
  end if
  end scope
  end macro

  macro ActiveFrame()
  ===================
  'TimeFrame
  SnapShots(hwnd) 'if Ctrl-P then take snapshot
  NewFrame
  end macro
  '
  macro LazyFrame()
  =================
  if act>2
  elseif bleft+bmid+bWheel+bright+bkey+mmove+actn
    SnapShots(hwnd) 'Ctrl-P take snapshot
    mmove=0
    if actn then actn--
  else
    sleep 100
  end if
  NewFrame
  end macro
  '
  macro DozyFrame()
  =================
  scope
  static int done
  if act>2
  elseif bleft+bmid+bWheel+bright+bkey+mmove+actn
    SnapShots(hwnd) 'Ctrl-P take snapshot
    mmove=0
    if actn then actn--
    done=0
  elseif not done
    done=1
  else
    sleep 100
    'exit sub
  end if
  NewFrame
  end scope
  end macro
  '
  macro StillFrame()
  =================
  scope
  static int done
  if done>=2
    if bkey
      SnapShots(hwnd) 'Ctrl-P take snapshot
    end if
    if act<2
      sleep 100
      'exit sub
    end if
  else
    done=1
  end if
  NewFrame
  end scope
  end macro



  function limit(float mn,v,mx) as float
  ======================================
  if v<mn then v=mn
  if v>mx then v=mx
  return v
  end function

  macro DotProduct(u,v)
  =====================
  u.x*v.x + u.y*v.y + u.z*v.z
  end macro

  macro VectorUnity(v)
  ====================
  'adjusts x,y,z to give scalar value of 1.0
  scope
  double r
  r=1/sqr(v.x*v.x + v.y*v.y + v.z*v.z)
  v.x*=r : v.y*=r : v.z*=r
  end scope
  end macro

  macro VectorDiff(pr,pt,pd)
  ==========================
  pr.x=pt.x-pd.x
  pr.y=pt.y-pd.y
  pr.z=pt.z-pd.z
  end macro

  sub SurfaceNormal(vector *n,*p1,*p2,*p3)
  ========================================
  'assumes triangle points are defined anticlockwise
  vector u,v
  VectorDiff(u,p2,p1)
  VectorDiff(v,p3,p1)
  n.x=(u.y*v.z)-(u.z*v.y)
  n.y=(u.z*v.x)-(u.x*v.z)
  n.z=(u.x*v.y)-(u.y*v.x)
  end sub



 '
  type Pixel4
    dword color
    =
    byte r,g,b,a
  end type


  'CREATE OPENGL TEXTURE
  '=====================

  Sub MakeTexture(sys pPixelArray, int xSize, ySize, TexNum )
  ===========================================================
  '
  glBindTexture GL_TEXTURE_2D, TexNum
  '
  'GL_NEAREST
  'GL_LINEAR
  glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
  '
  'GL_NEAREST
  'GL_LINEAR
  'GL_NEAREST_MIPMAP_NEAREST         0x2700
  'GL_LINEAR_MIPMAP_NEAREST          0x2701
  'GL_NEAREST_MIPMAP_LINEAR          0x2702
  'GL_LINEAR_MIPMAP_LINEAR           0x2703
  glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR

  #define GL_MIRRORED_REPEAT                0x8370
  #define GL_CLAMP_TO_EDGE                  0x812F

  'glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE
  'glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE

  glTexImage2D GL_TEXTURE_2D, 0, 4, xSize, ySize, 0, GL_RGBA, GL_UNSIGNED_BYTE, pPixelArray
  '
  End Sub

  sub MinTexture(int n,f,h,b)
  ===========================
  long v[16]
  'b background
  'h half
  'f forground
  v<=
  b,b,b,b,
  b,f,h,b,
  b,h,f,b,
  b,b,b,b
  MakeTexture @v, 4, 4, n
  End sub

  macro GenTextures(n)
  ====================
  glGenTextures n,texn
  end macro
  '
  macro DeleteTextures(n)
  =======================
  glDeleteTextures n,texn
  end macro



  sub LoadTexture(optional string fi, int n,res,*wi,*ht,*pflip)
  ===========================================================
  int flip
  if not fi then exit sub
  'if n>32 then exit sub
  if not n then texe++ : n=texe
  string imgs=""
  if @pflip then flip=pflip else flip=6
  LoadPixImage fi,res,imgs, wi, ht, flip
  If not res then
    MakeTexture strptr imgs,wi,ht,texn[n]
  else
    MakeTexture strptr imgs,res,res,texn[n]
  end if
  end sub

  sub texture(int n)
  ==================
  if n<=0
    glDisable GL_TEXTURE_2D
  else
    if not pick then 
      glEnable GL_TEXTURE_2D
      glBindTexture GL_TEXTURE_2D, texn[n]
    end if
  end if
  end sub

  macro NewTexture(n)
  ===================
  static int n = ++ texe
  end macro


  function GetTexture(int *n, string fi, int res=0, *wi=null, *ht=null) as int
  ============================================================================
  'static int texe=20 'image counter max 0xff
  if n=0 then
    texe++
    n=texe
    'res=0 'use wi and ht of image
    LoadTexture fi,n,res,wi,ht
  end if
  texture n
  return n
  end function

  macro CreateTexture(n,f)
  ========================
  static int n,n##wi,n##ht
  GetTexture n,f,0,n##wi,n##ht
  end macro

  sub DynSynthTexture(int *n, any*v, int c)
  =========================================
  int w=sqr(c/4)
  MakeTexture @v, w, w, texn[n]
  end sub

  macro CreateSynthTexture(n,v,c)
  ===============================
  NewTexture n
  #ifdef c
    DynSynthtexture n,v,c
  #else
    DynSynthtexture n,v,bytesof(v)
  #endif
  end macro

  sub snapshots(sys hwnd)
  =======================
  static int photo
  int g,tr
  if key[80] and key[VK_CONTROL] and photo=0
    if key[VK_SHIFT]
      tr=1 'transparent background
    end if
    if not GDIplus 2 then GDIplus 1 : g=1
    if tr
      TakeSnapShot hwnd,"tim75.png","image/png",75,tr,1
    else
      TakeSnapShot hwnd,"tim50.jpg","image/jpeg",50,0,1
      'SaveClientImage hwnd
    end if
    if g then GDIplus 0
    photo=1
  elseif key[80]=0
    photo=0
  end if
  end sub


  sub placetop(int n,*ord,c)
  ==========================
  int b,i
  for i=1 to c
    if ord[i]=n then b=i : exit for
  next
  if (b=0)or(b=c) then return
  for i=b to < c
    ord[i]=ord[i+1] 'SHUNT THE REST, USING THE VACANT POSITION
  next
  ord[c]=n 'FRONT POSITION
  end sub

  
   sub color(float r=0.5,g=0.5,b=0.5,a=1.0)
  ========================================
  if pick then exit sub
  fcolor={r,g,b,a}
  glColor4fv fcolor.r
  '
  'SPLIT BETWEEN DIFFUSE AND AMBIENT
  float d
  d=0.75
  colortype c
  c={r*d, g*d, b*d, a}
  glMaterialfv GL_FRONT,  GL_DIFFUSE, c.r
  d=0.25
  c={r*d, g*d, b*d, a}
  glMaterialfv GL_FRONT, GL_AMBIENT, c.r
  end sub

  sub PushState
  =============
  int n=sizeof StateType
  if stko<stke
    glPushMatrix
    stko+=n
    StateType s at @StateStack+stko
    copy @s, @s-n, n
    @bcolor+=n
    @fcolor+=n
  end if
  end sub

  sub PopState
  ============
  if stko>0
    int n=sizeof StateType
    StateType s at @StateStack+stko
    @bColor-=n
    @fColor-=n
    color fcolor.r, fcolor.g, fcolor.b, fcolor.a
    stko-=n
    glPopMatrix
  end if
  end sub

 sub move(optional float x,y,z)
  ==============================
  glTranslatef x,y,z
  StateType s at @StateStack+stko
  s.xd+=x
  s.yd+=y
  s.zd+=z
  end sub

  sub scale(optional float x,y,z)
  ===============================
  if not x then x=1.0
  if not y then y=x
  if not z then z=x
  glScalef x,y,z
  StateType s at @StateStack+stko
  s.xs*=x
  s.ys*=y
  s.zs*=z
  end sub

  sub Rotate(optional float a,x,y,z)
  ==================================
  if not a then exit sub
  glRotatef a,x,y,z
  end sub

  sub RotateX(optional float a)
  ==============================
  if not a then exit sub
  glRotatef a,1.,0.,0.
  end sub

  sub RotateY(optional float a)
  ==============================
  if not a then exit sub
  glRotatef a,0.,1.,0.
  end sub

  sub RotateZ(optional float a)
  ==============================
  if not a then exit sub
  glRotatef a,0.,0.,1.
  end sub

  sub PointSize(optional float ps)
  ================================
  glHint GL_POINT_SMOOTH_HINT, GL_NICEST
  glEnable GL_POINT_SMOOTH
  glPointSize ps
  end sub

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

  sub point(optional float x,y,z)
  ==============================
  glBegin GL_POINTS
  glVertex3fv   x
  glEnd
  end sub

  sub line(optional float x,y,z)
  ==============================
  glBegin GL_LINES
  vector a
  glVertex3fv a.x
  glVertex3fv   x 'from param stack
  glEnd
  end sub



 macro Navigation()
  ==================
  '
  'VIEW CONTROL WITH KEYBOARD KEYS
  '
  static float cmmx,cmmy,cmmz,cmax,cmay,cmaz,ns
  glrotatef    cmax,1,0,0 'rotate yz : pitch
  glrotatef    cmay,0,1,0 'rotate xz : yaw
  glrotatef    cmaz,0,0,1 'rotate xy : roll
  glTranslatef cmmx,cmmy,cmmz
  '
  if not key[VK_CONTROL]
    'MOVE
    ns=0.02
    if key[VK_SHIFT] then ns=0.1
    if key[37] then cmmx+=ns*cos(rad(cmay)) : cmmz+=ns*sin(rad(cmay)) 'left
    if key[39] then cmmx-=ns*cos(rad(cmay)) : cmmz-=ns*sin(rad(cmay)) 'right
    if key[38] then cmmx-=ns*sin(rad(cmay)) : cmmz+=ns*cos(rad(cmay)) 'up
    if key[40] then cmmx+=ns*sin(rad(cmay)) : cmmz-=ns*cos(rad(cmay)) 'dpwn
    if key[33] then cmmy-=ns 'pgup
    if key[34] then cmmy+=ns 'pgdn
  else
    'ROTATE
    ns=.4
    if key[VK_SHIFT] then ns=1.0
    if key[37] then cmay-=ns 'left
    if key[39] then cmay+=ns 'right
    if key[38] then cmax-=ns 'up 
    if key[40] then cmax+=ns 'down
    if key[33] then cmaz+=ns 'pgup
    if key[34] then cmaz-=ns 'pgdn
    if key[36] 
      cmax=0. : cmay=0. : cmaz=0. 'HOME'
    end if
  end if
  end macro
  '
  '
  '
  macro MoveObjectWithMouse(vv)
  =============================
  static float dx,dy,dz,df
  if picked then
    if bleft then
      'df=-1.05*vv.z/crect.right
      df=-vv.z*0.785/crect.bottom
      dx=df*(mposx-sposx)
      dy=df*(sposy-mposy)
    else
      vv.x+=dx
      vv.y+=dy
      vv.z+=dz
      dx=0.0
      dy=0.0
      dz=0.0
    end if
  end if
  end macro

  macro MoveObjectWithKeys(vv,mv,an)
  ==================================
  if picked
    if key[VK_CONTROL]
      if key[37] then vv.a.y-=an  ' left
      if key[39] then vv.a.y+=an  ' right
      if key[38] then vv.a.x-=an  ' up
      if key[40] then vv.a.x+=an  ' down
      if key[33] then vv.a.z+=an  ' PgUp
      if key[34] then vv.a.z-=an  ' PgDn
      if key[36] 
        vv.a.x=0. : vv.a.y=0. : vv.a.z=0. 'HOME'
      end if
    else
      scope
      static float m
      if key[VK_SHIFT] then m=mv*3 else m=mv
      if key[37] then vv.x-=m  ' left
      if key[39] then vv.x+=m  ' right
      if key[38] then vv.y+=m  ' up
      if key[40] then vv.y-=m  ' down
      if key[33] then vv.z-=m  ' PgUp
      if key[34] then vv.z+=m  ' PgDn
      end scope
    end if
  end if
  end macro

  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
    if @FrameScale
      f/=FrameScale.y
    endif
    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
  char   name[32] 'name
  float  snap     'snap to grid resolution
  int    mode     'keyboard and mouse movement modes
  int    locked   'movement & scaling 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
      move x+d.x, y+d.y, z
      if s.x then scale s.x,s.y,s.z
      if a.z then rotateZ a.z
      if a.y then rotateY a.y
      if a.x then rotateX a.x
    end if
    PickLabel id
    if Render then call Render
  end method
  '
  end class 'moveable object

  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 'moveable objects

  sub TouchZone(optional float v)
  ===============================
  if not pick then exit sub
  if not v then v=1.0
  glBegin GL_QUADS
  float z=-.0001
  glVertex3f -v,-v, z
  glVertex3f  v,-v, z
  glVertex3f  v, v, z
  glVertex3f -v, v, z
  'itr 3d
  glEnd
  end sub

  macro Usermovement(a,c,n,nm,  i,k)
  ==================================
  if opening
    #ifndef n
      %n=1 'default single object
    #endif
    #ifndef nm
      %nm=""
    #endif
    static MoveableObject a[n] 'n moveable objects
    '#recordof a
    '#recordof moveableobject
    scope
      int k=c
      int i
      for i=1 to n             'number of objects
        a[i].mode=0x101        'key and mouse mode
        a[i].s={1.0,1.0,1.0} 'default scales
        a[i].id=k              'id of object
        a[i].name=nm
        k+=100 'addition to base ID
      next
    end scope
  endif
  #if n=1
    a.act()
  #endif
  end macro

  '#recordof usermovement



  'CONDITIONAL/DEFAULT EQUATES
  '
  %% title  "OpenGl Scene"
  '
  'STANDARD CHILD WINDOWS STYLES
  '=============================
  '
  'Button	The class for a button.
  'ComboBox	The class for a combo box.
  'Edit	        The class for an edit control.
  'ListBox	The class for a list box.
  'MDIClient	The class for an MDI client window.
  'ScrollBar	The class for a scroll bar.
  'Static	The class for a static control.

  sys WndProcExtra 'callback for customised windows message processing

  ! Initialize(sys hWnd)
  ! Release(sys hWnd)
  !*wglSwapIntervalEXT(int b) extern
  
#ifndef CustomWndProc 'default

  function WndProc(sys hwnd, uMsg, wParam, lParam) as sys callback
  ================================================================
  static   int a
  'globals sys hDC,hRC
  '
  if WndProcExtra
    a=call WndProcExtra(hwnd,uMsg,wParam,lParam)
    if a then exit function
  end if
  '
  select umsg 
  '
  MouseMessages()
  KeyboardMessages()
  '
  case WM_TIMER

  act=2

  case WM_MOVE

  act=3

  case WM_SIZE 
  '
  act=4

  'finit 'intitialise fpu
  GetClientRect  hWnd,cRect
  crect.right=crect.right-lpane-rpane
  'MoveWindow hchw , lpane , 0 , crect.right , crect.bottom , TRUE
  glViewport lpane, 0, crect.right, crect.bottom
  aspect=crect.right/crect.bottom 'WIDTH/HEIGHT
  #ifndef opengles
    setPerspective
  #endif
  ActOpengl 'CONTINUOUS REFRESH

  case WM_ERASEBKGND
  '
  'actopengl 'REFRESH
  return 1

  case WM_DROPFILES
  '
  filedrop = rtrim GetDropFiles(wparam)
  DragFinish(wparam)
  act=4
  pick=1
  picking=1
  ActOpenGl 'exec pick cycle
  '
  case WM_CLOSE

  SendMessage hwnd, WM_DESTROY, 0, 0
  '
  case WM_CREATE

  'SETUP DEVICE CONTEXT AND RENDER CONTEXT
  '
  if minCreate
    return DefWindowProc(hwnd, uMsg, wParam, lParam) 'unprocessed messages
  endif
  'int style=WS_CHILD | WS_VISIBLE
  int style=WS_POPUP | WS_BORDER
  % ID_FIRSTCHILD  100
  int id=ID_FIRSTCHILD
  hchw=hwnd
  'hchw=CreateWindowEx(0,"static", null, style, 0,0,100,100, hwnd, id, hInst, null)
  hDC=GetDC hchw
  SelectPixelformat(hDC)
  opening=1
  hRC = wglCreateContext hDC
  wglMakeCurrent hDC, hRC

  #ifndef opengles
    def BuildFontM BuildFont (hWnd, hDC, hRC, %1, %!2)
    #ifdef fontA
      'FW_NORMAL 400
      'BuildFont hWnd, hDC, hRC, 1024,"Arial",FW_NORMAL,0
      BuildFontM 1024 fontA
    #endif
    #ifdef fontB
      'BuildFont hWnd, hDC, hRC ,1280, "Courier New",600,1
      BuildFontM 1280 fontB
    #endif
  #endif
  '
  'SYNC FRAME RATE - 60HZ
  'sys p=wglgetprocaddress "wglSwapIntervalEXT" : call p 1
  SetFun wglSwapIntervalEXT
  if @wglSwapIntervalEXT then wglSwapIntervalEXT 1
  '
  FrameCount=0
  Initialize hWnd
  SetWindowText hwnd,title
  'SET PRECISE CLIENT AREA
  RECT rc
  GetClientRect hwnd,rc
  MoveWindow hWnd,hpos,vpos, width*2-rc.right, height*2-rc.bottom,1
  
  case WM_DESTROY
  '
  if minCreate then exit function
  if not running then exit function 'PREVENT RECURSION
  'final frame      
  act=5
  closing=1
  scene hWnd
  'swapBuffers hdc
  Release hWnd 'cleanup
  #ifndef opengles
    #ifdef fontA
      glDeleteLists 1024, 256
    #endif
    #ifdef fontB
      glDeleteLists 1280, 256
    #endif
  #endif
  wglMakeCurrent hDC, null
  wglDeleteContext hRC
  ReleaseDC hchw,hDC
  running=0
  act=0
  opening=0
  closing=0
  pausing=0
  DestroyWindow hWnd 'SELF DESTRUCT
  return 1

  case else
  '
  return DefWindowProc(hwnd, uMsg, wParam, lParam) 'unprocessed messages 
  '
  end select
  '
  end function

#endif 'CustomWndProc


  macro StepAngle(a,i)
  ====================
  static float a
  if not pick then
    a+=i
    if a>360 then a-=360
  end if
  end macro


  macro fader(startf,endf,inout,action)
  =====================================
  scope
  if not picking then
    if FrameCount<startf
      '
    elseif FrameCount>=endf
      #ifdef action
        action
      #endif
    else 
      int Opacity,t,d,f,i
      d=endf-startf
      f=FrameCount-startf
      i=inout
      if d<1 then d=1
      t=f*255/d 'SCALE FADER
      if t>255 then t=255
      if i<0 then
        Opacity=255-t 'FADE OUT
      else
        Opacity=t 'FADE IN
      end if
      'Set WS_EX_LAYERED on this window 
      SetWindowLongPtr(hwnd, GWL_EXSTYLE,
      GetWindowLongPtr(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED)
      SetLayeredWindowAttributes(hwnd, 0, Opacity, LWA_ALPHA);
    end if
  end if
  end scope
  end macro

  #ifndef ExplicitMain
  MainWindow(width,height,WS_OVERLAPPEDWINDOW,2)
  #endif


