!S4Callbacks.f95       Group ID: #4   Stereo-3D Simulation Environment Vsn:1.00
!2025.05.24.1840cdt JMS- CallBack referenced routines*, & utilities->OpenGL.

!            Author- Jeffrey M. Setterholm, Lakeville,MN 55044 USA
!         IP Status- Free source code (e.g.: post copyright)
!
!          Computer- "T3"/Dell Precision T3500/Intel i5 E5520/Win10Pro-21H2
!                     ^name ^Mfgr.Id           ^chipset       ^OS 
!                    /Absoft Pro Fortran 21.0.2/GeForce GTX 1050/f90gl~Glut3.7
!                     ^compiler ~Fortran 95     ^graphics card   ^graphics

!    f90gl bindings- public domain; see "https://math.nist.gov/f90gl/"

!Disclaimer:
! ***************************************************************
! **********   Individual cognition is always flawed,  **********
! **********         including yours and mine.         **********
! **********                 - So: -                   **********
! **********       Use this code at your own risk.     **********
! ***************************************************************

!Table of Contents: ...use to search...
!*Subroutine UserView
!*Subroutine Keyboard(Key,xCursor,yCursor)
!*Subroutine SpecialFunctionKeys(Key,xCursor,yCursor)
!*Subroutine MouseButtons(Button,State,iX,iY)
!*Subroutine MouseMotion(iX,iY)
! Subroutine MouseRecUpdate(md)    -used by MouseButtons() & MouseMotion()
!*...directly called by the OpenGL S2Callback subroutine passthroughs.
!---------------------------------------------------------------------------7 9
Subroutine UserView
!2025.04.18.1520cdt JMS- CallBack- User(i.e.your) View generator:
!                      - ThreePhase=3 bypassed & removed.
!--Globals
 use OpenGLRec,only:  &      !Ref: OpenGL GL/GLU/GLUT docs
      glClear,glClearColor,glEnable,glFlush,glLoadIdentity,glMatrixMode &
     ,glMultMatrixd,glOrtho,glutPostRedisplay,GLUTSWAPBUFFERS           &
     ,GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT,GL_DEPTH_TEST             &
     ,GL_MODELVIEW,GL_PROJECTION
!use S2Callback,only:CheckGL !OpenGL CB's, GlutHandoff, & glGetError
 use ioDef     ,only: &      !Files,Units,TimeStamp,Selfies,Flags
      ExeFileOut,ExeFileIn,EnvIni,EnvNml,Uupdate,Ur,Us,Ut,DaTimeLabel &
     ,NowView,Up,NowPrint,iTeapot
 use ScreenDef ,only: &      !screen & colors
      xWindowFull,yWindowFull,xyWindowRatio,vScrnHVD,iScrnColor &
     ,nCharCenX,nCharCenY,nCharMaxY,ForceRGBA,Side,nCharCenXS
 use KeyboardDef,only:&      !Keyboard
      KbdKey,ArrowKey
 use MouseDef   ,only: &     !Mouse
      Mouse,iMouse7DoF,MChanX,MChanY,MouseDirect,MouseDirectPrev,MXYdel
 use ModelDef   ,only: &     !Modelview Projection variables
      nRowOffset,nRowIn,nColOffset,nColIn,Nnutate,NutateAng,Nutate7,Nutateh
 use ViewDef,only: ThreePhase,Key,V,jVG,cVuModeName,cEyeName,cSplitName
 use SimDef     ,only: &     !Simulation F9-F12
      SimMode,dT,RunTimer,Fnew,IterTotal,IterRun
 use HelpDef    ,only: &     !Help text block
      HhHelpView,nHelpLines,BufferHhHelpView
 use AppsDef    ,only: &     !User Apps F1-F8
      Appnumber,AppNumberNew
 use BreakPtDef ,only: BrkOn !BreakPoint & scrolling tracker
!--End Globals
 implicit none
 !--Internals
  !--EndDefs-----------------------------------------------
  Up=0
  !--Increment the total iteration counter & update RunSecs (.nnn)
   IterTotal=IterTotal+1;                      call RunSeconds
  !--Screen color selection
   if((KbdKey==67).or.(KbdKey==99)) then
     iScrnColor=16-iScrnColor; KbdKey=0   ! toggle screen color
   endif !KbdKey='C'or'c'
   if(iScrnColor==15) call glClearColor(0.,0.,0.,0.) ! toggle->black
   if(iScrnColor== 1) call glClearColor(1.,1.,1.,0.) ! toggle->white
   call glMatrixMode(GL_PROJECTION) ;call glLoadIdentity
   call glMatrixMode(GL_MODELVIEW)  ;call glLoadIdentity
   call glClear(ior(GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT))
   call glEnable(GL_DEPTH_TEST)                                   ;call glFlush

  !-- Define the coefficients of an orthographic screen, vertical [-1.:1.]:
   vScrnHVD(1,1)=-xyWindowRatio; vScrnHVD(2,1)=-vScrnHVD(1,1) !X Left -to-right
   vScrnHVD(1,2)=-1.000;         ; vScrnHVD(2,2)= 1.000       !Y bottom-to-top
   vScrnHVD(1,3)=-1.000;         ; vScrnHVD(2,3)=+1.000       !Z far  -to-near
                                                              !(right handed)
  !--The projection matrix will be (re)defined while calling the apps.
  ! (PrntOrtho uses its own Identity projection matrix.)

  !F1-F12 Function Key useages (Apps access + simulation controls):
   if(SimMode< 1) SimMode=0
   if((ArrowKey> 0).and.(ArrowKey< 13)) then
     Fnew=ArrowKey; ArrowKey=0
   endif !ArrowKey >0 & <13
       AppNumberNew=  0
   if((Fnew> 0).and.(Fnew< 9)) then !F1-F8 App selection):
       AppNumber   =Fnew
       AppNumberNew=Fnew; Fnew =0
   endif !Fnew >0 & <9
  !--Simulation mode switching:
   select case(Fnew) !----------------------
    case( 9); SimMode=1      ; Fnew=0;                     !F9 Reset
     write(Us,"(   a18,' Reset(F 9) dT   =',f8.3)" )  &
                      DaTimeLabel,dT
    case(10); SimMode=2      ; Fnew=0                      !F10 Hold
     write(Us,"(13x,a5,' Hold( F10) Timer=',f8.3)" )  &
                      DaTimeLabel(14:18),RunTimer
    case(11); SimMode=3      ; Fnew=0                      !F11  Run
     write(Us,"(13x,a5,' Run(  F11) Timer=',f8.3)" )  &
                      DaTimeLabel(14:18),RunTimer
    case(12); SimMode=4      ; Fnew=0                      !F12 Stop
     write(Us,"(13x,a5,' Stop( F12) Timer=',f8.3,i10,' iterations.')" ) &
                      DaTimeLabel(14:18),RunTimer,IterRun
   end select !Fnew -----------------------^

  !--'Real Time' Simulation mode control: 
   select case(SimMode) !----------------------
    case( 1); RunTimer=0.d0                                !F9 Reset
              IterRun =0
    case( 2);                                              !F10 Hold
    case( 3); RunTimer=RunTimer+dT                         !f11  Run
              IterRun =IterRun +  1
    case( 4);                                              !F12 Stop
   end select !S.SimMode -----------------------^

  !--KbdKey controls:
   select case(KbdKey) !-----------------------
   !--Eye configuration. =-1:Right|Left, =0:Full-screen,+1:Left|Right
    case( 69); KbdKey   =0; Key%SplitScreen =Key%SplitScreen +1      !'E'
           if(Key%SplitScreen> 1) Key%SplitScreen =          -1
   !--Orthographic|Projective control. =0:orthographic,=1:persp,=2:3D
    case(101); KbdKey   =0; Key%VuMode=Key%VuMode+1                  !'e'
          if(Key%VuMode> 2) Key%VuMode=           0

   !--Breakpoint scrolling control toggle:
    case(66,98); KbdKey=0; BrkOn=1-BrkOn                             !'Bb'

   !--Mouse output redirect toggle (when==2):
    case(  77); KbdKey=0; if(iMouse7Dof <2) then; iMouse7DoF=2       !'M'
                                            else; iMouse7DoF=0
                          endif!iMouse7Dof <2
   !--PoI / 6DoF toggle (when==1):
    case( 109); KbdKey=0; if(iMouse7Dof==0) then; iMouse7DoF=1       !'m'
                                            else; iMouse7DoF=0
                          endif!iMouse7Dof==0
   !--Help screen toggle:                                changed 2024.04.02
    case( 72); KbdKey=0                                              !'H':2
                  if(HhHelpView/=2) then; HhHelpView=2
                                    else; HhHelpView=0
                  endif !HhHelpView=0
    case(104); KbdKey=0                                              !'h':1
                  if(HhHelpView/=1) then; HhHelpView=1
                                    else; HhHelpView=0
                  endif !HhHelpView=0

    case(78    ); KbdKey=0 !Linear nutation                          !'N '
                  if(Nnutate==0) then; Nnutate=2
                                 else; Nnutate=0
                  endif !Nnutate=0
                  
    case(   110); KbdKey=0  !Rotational nutation                    !' n'
                  if(Nnutate==0) then; Nnutate=1
                                 else; Nnutate=0
                  endif !Nnutate=0

!  !--NowView: Toggles 'viewing' details on the screen using "v" or "V"
    case(86)    ; KbdKey=0                                           !'V' uc
     if(     NowView<=0) then; Nowview=2
      elseif(NowView==1) then; Nowview=2
      else                   ; Nowview=0
     endif  !NowView==0
    case(118)   ; KbdKey=0                                           !'v' lc
     if(     NowView<=0) then; Nowview=1
      elseif(NowView==2) then; Nowview=1
      else                   ; Nowview=0
     endif  !NowView==0

   !--NowPrint: One cycle Printout controlled by "p" or "P" (beeps)
    case( 80);   Up=  Ut; NowPrint=2; KbdKey=0 !to your .txt file     'P' uc
                                              call DaTime18
      write(Up,"(/a18,' Hardcopy: `P` ',46('-'))") DaTimeLabel
    case(112);   Up=  Us; NowPrint=1; KbdKey=0 !to your screen        'p' lc
                                                call DaTime18
      write(Us,"(/a18,' DOS screen: `p` ',44('-'))") DaTimeLabel

    !--GLUT Teapot viewing control by the "T" key: 
    case(20);     KbdKey=0;  iTeapot=          0                    !'ctl-t'->0
    case(84,116); KbdKey=0;  iTeapot=iTeapot+1                      !'Tt'
            if(iTeapot>7) iTeapot=             0
   end select !KbdKey ------------------------^

  !--Update model nutation:
   if(Nnutate==0) then; NutateAng=0.d0
    else 
          if(Nnutate==1)       NutateAng = NutateAng+1.d0
          if(Nnutate==2)       NutateAng = NutateAng+2.d0
          if(NutateAng>359.d0) NutateAng = 0.d0
          if(Nnutate==1) & !Rotational nutation
          Nutate7=(/0.d0,0.d0,0.d0,0.d0, 5.d0*dcosd(NutateAng)     &
                                       ,10.d0*dsind(NutateAng),1.d0 /)                                     
          if(Nnutate/=1) & !Translational nutation
          Nutate7=(/ 0.d0,dcosd(NutateAng)*.5d0,0.d0,0.d0,0.d0,0.d0,1.d0 /)                 
          call hFS7Gen(Nutateh,Nutate7,0)
   endif!Nnutate>0

  !--Visualization- 14DoF ///////////////////////
   call View

   if(NowView==2) call ShowProjectAndModel(-19,2,12,'S4Callbacks: @L202')
                                                   !^ a20           !2021.10.04

  !-- Results -> screen:
100 continue                                  !<-HhHelpView==1.'s goto (above).
   side=0
   call glutSwapBuffers; call glutPostRedisplay; call glFlush

  !--Use "~" Tilda key to dump the full screen to SelfieN.bmp N=[0,1,...9]
   if(KbdKey==126) then
     call ScreenSelfie
      KbdKey=0
   endif !=126
  !-- Use "`" key to toggle the screen depth selfie:
 !!if(KbdKey== 96) then; DepthSelfie=1-DepthSelfie; KbdKey=0; endif
  !-- Clear the one-cycle 'NowPrint':
!  if(NowPrint>0)   Up =0
      NowPrint=0
!  MXYdel=0
   return
End Subroutine UserView
!---------------------------------------------------------------------------7 9

Subroutine Keyboard(aKey,xCursor,yCursor)
!2020.06.03.1545cdt JMS-- CallBack- keyboard:
!--Globals
 use OpenGLRec,only:  & !Ref: OpenGL GL/GLU/GLUT docs
      glubyte,glcint,glutFullScreen,glFlush,glutReshapeWindow,glutGetModifiers
 use ioDef   ,only:   & !Files,Units,TimeStamp,Selfies,Flags
      Us,Ut,DaTimeLabel
 use ScreenDef ,only: & !screen & colors
      xWindowFull,yWindowFull,iFullScreen,iScrnColor,WinId,ctlKbd
 use KeyboardDef,only:& !Keyboard
      KbdKeyIn,KbdKey,ArrowKey,iKeyMods,nKpress,KeyHist
 use SimDef    ,only: & !Simulation F9-F12
      IterTotal
!--End Globals
 implicit none
 !--Arguments
  character(kind=glubyte),intent(inout)::akey
  integer(kind=glcint)   ,intent(inout)::xCursor
  integer(kind=glcint)   ,intent(inout)::yCursor
  integer(4)::xScreen,yScreen
  !--EndDefs-----------------------------------------------
   iKeyMods=glutGetModifiers()
   if(ichar(aKey)> 0) KbdKeyIn=ichar(aKey)!Persistent/not erased when used
   if(ichar(aKey)> 0) KbdKey  =ichar(aKey)!Zeroed after use
  !--Update Keypress history:
   nKpress=nKpress+1; KeyHist(1:3,3)=KeyHist(1:3,2)
                      KeyHist(1:3,2)=KeyHist(1:3,1)
                      KeyHist(1:3,1)=(/ichar(aKey),1,iKeyMods/)
  !--ctl-Q hard quit:
   if(KbdKey==17) then; if(Ut>9) close(Ut); stop 'ctl-Q.'//char(7) ;endif
  !--ctl-K Keyboard redirection toggle:
   if(KbdKey==11) then
        ctlKbd =1-ctlKbd; KbdKey  =0
     if(ctlKbd==1)          ArrowKey=0
   endif!ctlKbd>0
   if(ctlKbd>0) then !Silence KbdKey and ArrowKey
      KbdKey=0                                                        ;return
   endif!KbdKey==11

   select case(KbdKey) !----------------------------
    case(17); KbdKey=0; stop 'ctl-Q.'                          !'ctl-Q'
    case(27); KbdKey=0                          ;call DaTime18 !escape
     select case(iFullScreen) !-----------                     !screen toggle
      case(0); call glutFullScreen; call glFlush                 !fullscreen
               write(Us,"(a18,' DOS screen: escape-end')") DaTimeLabel
               iFullScreen=1                                          ;return
      case(1)!;xScreen=400           ; yScreen=200
               xScreen=xWindowFull*.95; yScreen=yWindowFull*.95
               call glutReshapeWindow(xScreen,yScreen); call glFlush
                                                                !small window
               write(Us,"(/a18,' DOS screen: escape')") DaTimeLabel
               iFullScreen=0                                          ;return
     end select !iFullScreen

    case(81,113); KbdKey=0                      ;call DaTime18 !'Q,q'
     if(Ut>Us) then
!       Closing message to output file:
         write(Ut,"(/a18,' Quit(Q/q)',14x,i15,' cbUserView iterations')")  &
                      DaTimeLabel   ,IterTotal
     !!if(RunTimer> 0.d0) &
     !!  write(Ut,"(57x,'Timer=',f8.3,' seconds')") RunTimer
     !!  write(Ut,"(58a1:)") (ExeBanner(i:i),i=1,len_trim(ExeBanner))
         write(Ut,"(70x,' ...done.')")
       close(Ut)
     endif !Ut>6
!       Closing message to screen:
         write(Us,"(/a18,' Quit(Q/q)',14x,i15,' cbUserView iterations')")  &
                      DaTimeLabel   ,IterTotal
     !!if(RunTimer> 0.d0) &
     !!  write(Us,"(57x,'Timer=',f8.3,' seconds')") RunTimer
     !!  write(Us,"(58a1:)") (ExeBanner(i:i),i=1,len_trim(ExeBanner))
         write(Us,"(70x,' ...done.')")
!   Pause the DOS window from vanishing immediately at run's end:
     if(iFullScreen==0) &
     pause 'Left-click on the DOS window & press `enter` to exit.'
     stop
   end select !key
   return
End Subroutine Keyboard
!---------------------------------------------------------------------------7 9

Subroutine SpecialFunctionKeys(Key,xCursor,yCursor)
!2020.06.03.1545cdt JMS- CallBack- special function keys (F1-F12, arrows, etc.)
!                      - F9...F12 -> Reset,Hold,Operate,& Stop the timer.
!--Globals
 use OpenGLRec  ,only:glcint,glutGetModifiers !Ref: OpenGL GL/GLU/GLUT Docs.
 use KeyboardDef,only:ArrowKey,ArrowKeyIn,iKeyMods,nKpress,KeyHist !Keyboard
 use ScreenDef  ,only:ctlKbd                !screen & colors
!--End Globals
 implicit none
 !--Arguments
  integer(glcint),intent(inout)::Key,xCursor,yCursor
  !--EndDefs-----------------------------------------------
   iKeyMods=glutGetModifiers()
   if(Key   > 0) ArrowKeyIn = Key!Persistent/not erased when used
   if(Key   > 0) ArrowKey   = Key!Zeroed after use
  !--Update Keypress history:
   nKpress=nKpress+1; KeyHist(1:3,3)=KeyHist(1:3,2)
                      KeyHist(1:3,2)=KeyHist(1:3,1)
                      KeyHist(1:3,1)=(/Key,2,iKeyMods/)
  !--ctk-K silences KbdKey and ArrowKey
   if(ctlKbd> 0) ArrowKey  =  0                                         ;return
End Subroutine SpecialFunctionKeys
!---------------------------------------------------------------------------7 9

Subroutine MouseButtons(Button,State,iX,iY)
!2020.06.19.1100cdt JMS- CallBack- mouse button(s) press/release.

!Mouse buttons                   <- Persists after most recent button press.
!  #define GLUT_LEFT_BUTTON   0                               Reference: glut.h
!  #define GLUT_MIDDLE_BUTTON 1
!  #define GLUT_RIGHT_BUTTON  2
!Mouse button  state             <- Either button controls this
!  #define GLUT_DOWN          0
!  #define GLUT_UP            1
!--Globals
 use OpenGLRec,only:  &          !Ref: OpenGL GL/GLU/GLUT docs
                     glcint,glutWarpPointer,glutSetCursor &
                    ,GLUT_CURSOR_CROSSHAIR        &  ! +
                    ,GLUT_CURSOR_CYCLE            &  !~not
                    ,GLUT_CURSOR_FULL_CROSSHAIR   &
                    ,GLUT_CURSOR_INFO             &  ! crossed arrows
                    ,GLUT_CURSOR_NONE             &
                    ,GLUT_CURSOR_TOP_RIGHT_CORNER &
                    ,GLUT_CURSOR_UP_DOWN          &  ! both ways
                    ,GLUT_CURSOR_WAIT                ! hourglass
 use ioDef      ,only: Us                  !Print unit#
 use MouseDef   ,only: &                   !Mouse
      iMouseButton,iMouseState,MouseDirect,Mouse,MouseDirectPrev,iMouse7DoF &
     ,MouseU,MChan,MChanX,MChanY,nMpress,mdHist,MXY,MXYdel
 use simdef     ,only: IterTotal
!--End Globals
 implicit none
 !--Arguments
  integer(kind=glcint),intent(inOut)::Button,State,iX,iY
 !--Internals
  integer(4)   ::md
  !--EndDefs-----------------------------------------------
                        iMouseButton = Button
                        iMouseState  = State
                     MouseDirectPrev =   MouseDirect
                     MouseDirect     =2*iMouseButton-iMouseState+2
   if(iMouse7Dof==2) MouseDirect     =6 +MouseDirect
                md = MouseDirect
  !--Update the mouse button use history:
   nMpress=nMpress+1
   mdHist( 3)=  mDHist( 2); mdHist( 2)=mDHist( 1); mdHist( 1)=md
   MXY(1:4,3)=  MXY(1:4,2); MXY(1:4,2)=MXY(1:4,1)
   MXY(1:4,1)= (/ iX,iY,MouseDirect,IterTotal /)
   MXYdel    =  0

  !--Mouse mode switching is done with the 'M' key.
   if(iMouse7Dof==2) then  !Reposition the cursor at its previous location
     call glutWarpPointer(Mouse(md)%iX   , Mouse(md)%iY   )
                     else  !Use the present mouse position:
           md        = MouseDirect
     Mouse(md)%iX    = iX
     Mouse(md)%iY    = iY
   endif!iMouse7Dof==2

  !--Process mouse motion:

   call MouseRecUpdate(md) 
   MouseU = Mouse(md)
   MChanX = MChan(MouseU%mcx)
   MChanY = MChan(MouseU%mcy)

   if(0>1) then
  !--Change the mouse's screen cursor:
   select case(md)
    case(1); call glutSetCursor(GLUT_CURSOR_CYCLE)            !Lup
    case(2); call glutSetCursor(GLUT_CURSOR_UP_DOWN)          !Ldown
    case(3); call glutSetCursor(GLUT_CURSOR_WAIT)             !Mup
    case(4); call glutSetCursor(GLUT_CURSOR_WAIT)             !Mdown
    case(5); call glutSetCursor(GLUT_CURSOR_INFO)             !Rup
    case(6); call glutSetCursor(GLUT_CURSOR_TOP_RIGHT_CORNER) !Rdown
    case(7); call glutSetCursor(GLUT_CURSOR_WAIT)             !TBDup
    case(8); call glutSetCursor(GLUT_CURSOR_WAIT)             !TBDdown
   end select!im
   endif!0>1 ////////////////////////////////////
!            call glutSetCursor(GLUT_CURSOR_NONE)
  !--Middle Button: beep!
   if((md==3).or.(md==4)) write(Us,"(a1)") char(7)                      ;return
End Subroutine MouseButtons
!---------------------------------------------------------------------------7 9

Subroutine MouseMotion(iX,iY)
!2020.06.19.1100cdt JMS- CallBack- mouse motion:
!--Globals
 use OpenGLRec,only:  &          !Ref: OpenGL GL/GLU/GLUT docs
      glReadPixels,glutWarpPointer,glutSetCursor        &
     ,GL_FLOAT,GL_DEPTH_COMPONENT,glcint,GLint,GLsizei
 use ScreenDef  ,only: &               !screen & colors
      xWindowFull,yWindowFull
 use MouseDef   ,only: &               !Mouse         ///Consolidate///
      MouseDirect,Mouse,mbID,MouseU,MChan,MChanX,MChanY,MouseDirectPrev &
     ,MouseInit,MouseScreenh,mdTot,MXY,MXYdel
 use simdef     ,only: IterTotal
!--End Globals
 implicit none
 !--Arguments
  integer(kind=glcint ),intent(inout)::iX,iY
  integer(kind=GLint  )              ::iXLoc,iYLoc
  integer(kind=GLsizei)              ::JustOne=1
 !--Internals
  integer(4)::md !,iDoF
  real(4) PixelDepth(1)
  !--EndDefs-----------------------------------------------

  !--Mouse initialization, called from GlutHandoff:
   if(MouseInit==0) then
    !--Screen-enter the cursor positions:
     do md=1,mdTot; Mouse(md)%iX  =xWindowFull/2
                    Mouse(md)%iY  =yWindowFull/2
                    Mouse(md)%md  =md
                    Mouse(md)%mcx =2*md-1
                    Mouse(md)%mcy =2*md
                    Mouse(md)%ID  =mbID(md)
                    call MouseRecUpdate(md)
     enddo!md
    !--Position the cursor at Mouse(1):
     MouseDirect    =1
     call glutWarpPointer(Mouse(1)%iX   , Mouse(1)%iY   )
     MouseInit      =1                                                  ;return
   endif !MouseInit==0

  !--Update the mouse motion history:
   MXY(1:4,3)=MXY(1:4,2); MXY(1:4,2)=MXY(1:4,1)
   MXY(1:4,1)=(/iX,iY,MouseDirect,IterTotal/)
  !--Compute this iteration's mouse motion change:
                            MXYdel    =MXY(1:4,1)-MXY(1:4,2)
   if(MXYdel(3)== 0)        MXYdel(3) =MouseDirect
   if(MXYdel(4)<=120) then; MXYdel(4) =IterTotal !...within 120 iter. ~2. sec
                      else; MXYdel    =(/0,0,MouseDirect,0/)
   endif!MXYdel(4)==1

  !--Process mouse motion:
   md=MouseDirect
   Mouse(md)%iX=iX; Mouse(md)%iY=iY
   call MouseRecUpdate(md)

  !--Simplify read-only access to the two active mouse channels:
   MouseU = Mouse(md)
   MChanX = MChan(MouseU%mcx)
   MChanY = MChan(MouseU%mcy)

  !--Screen depth of the single pixel under the active mouse cursor:
  !Ref: Wright&Sweet P.384                                           2016.04.28
  !WINGDIAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width
  !        , GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
   iXLoc=               MouseU%iX
   iYLoc= yWindowFull-1-MouseU%iY
   call glReadPixels( iXLoc,iYLoc,JustOne,JustOne  &
                     ,GL_DEPTH_COMPONENT,GL_FLOAT,PixelDepth)
   MouseScreenh(1)= (2.*iXLoc-xWindowFull)/xWindowFull
   MouseScreenh(2)= (2.*iYLoc-yWindowFull)/yWindowFull
   MouseScreenh(3)= PixelDepth(1)*2.-1.                             !2020.05.25
   MouseScreenh(4)=            1.0
!  call glutSetCursor(GLUT_CURSOR_CROSSHAIR)
   return
End Subroutine MouseMotion
!---------------------------------------------------------------------------7 9

Subroutine MouseRecUpdate(md)
!2020.06.18.0925cdt JMS- Mouse(iMD) -> MChan(iMD*2-1) & MChan(iMD*2)
!--Globals
 use ScreenDef,only: xWindowFull,yWindowFull,vScrnHVD & !screen & colors
                    ,lCharX,lCharY
 use MouseDef ,only: Mouse,MChan,PpX,PpY !Mouse 
 use SimDef   ,only: IterTotal,RunSecs   !Simulation control,F9-F12
!--End Globals
 implicit none
 !--Arguments
  integer(4)   ::md      !Mouse() raw data to use.                         [1:6]
 !--Internals
  integer(4)   ::ic1,ic2 !MChan() rescaled outputs.                       [1:12]

  !--EndDefs-----------------------------------------------
   if((md<1).or.(md>12))         stop'MouseRecUpdate: md outside [1:12]. Halt.'
          ic1    = 2*md-1                !Channel index    - X
          ic2    = 2*md                  !                 - Y
   PpX           = MChan(ic1)%Pp         !Channel          - X
   PpY           = MChan(ic2)%Pp         !                 - Y
   PpX(2)        = PpX(1)                !Previous<-Present- X
   PpY(2)        = PpY(1)                !                 - Y
   PpX(1)%iPix   = Mouse(md)%iX          ![0:ScreenPix]    - X
   PpY(1)%iPix   = Mouse(md)%iY          !                 - y
   PpX(1)%nChar  = PpX(1)%iPix/lCharX+1  !Screen character - column
   PpY(1)%nChar  = PpY(1)%iPix/lCharY+1  !                 - row
   PpX(1)%iUsed  = PpX(1)%iUsed+1        !Iteration duration
   PpY(1)%iUsed  = PpY(1)%iUsed+1
   PpX(1)%Iter   = IterTotal             !@iteration#_
   PpY(1)%Iter   = IterTotal
   PpX(1)%RunSecs= RunSecs               !@runtime_
   PpY(1)%RunSecs= RunSecs
   MChan(ic1)%mc   = ic1
   MChan(ic2)%mc   = ic2
   MChan(ic1)%Pp   = PpX; MChan(ic1)%mdParent=md; MChan(ic1)%iX1Y2=1
   MChan(ic2)%Pp   = PpY; MChan(ic2)%mdParent=md; MChan(ic2)%iX1Y2=2
   MChan(ic1)%r01  = Mouse(md)%iX/dble(xWindowFull)      !x          [0.:1.]
   MChan(ic2)%r01  = Mouse(md)%iY/dble(yWindowFull)      !y
   MChan(ic1)%rm11 =MChan(ic1)%r01*2.d0-1.d0             !x         [-1.:1.]
   MChan(ic2)%rm11 =MChan(ic2)%r01*2.d0-1.d0             !y
   MChan(ic1)%v    =(1.d0-MChan(ic1)%r01)*vScrnHVD(1,1) &!x  e.g.:[-1.6:1.6]
                         +MChan(ic1)%r01 *vScrnHVD(2,1)
   MChan(ic2)%v    =(1.d0-MChan(ic2)%r01)*vScrnHVD(1,2) &!y typical:[-1.:1.]
                         +MChan(ic2)%r01 *vScrnHVD(2,2)

   if(PpX(1)%RunSecs-PpX(2)%RunSecs<3.d0) then 
    !--Less than 3 seconds elapsed, apply the mouse motion:
     MChan(ic1)%iDeltaPix=PpX(1)%iPix-PpX(2)%iPix
     MChan(ic2)%iDeltaPix=PpY(1)%iPix-PpY(2)%iPix
    else
     MChan(ic1)%iDeltaPix=0
     MChan(ic2)%iDeltaPix=0
   endif !PpX(1)%RunSecs-PpX(2)%RunSecs<3.
   return
End Subroutine MouseRecUpdate
!---------------------------------------------------------------------------7 9

