0.0.0.0:80 juere-engine / master ui / ui.factor
master

Tree @master (Download .tar.gz)

ui.factor @masterraw · history · blame

USING: accessors arrays calendar combinators kernel literals 
math math.vectors memoize sequences threads ui ui.gadgets 
ui.gadgets.worlds ui.gestures ui.pens ui.pixel-formats unicode
classes generic namespaces math.functions generalizations
   juere-engine.utils
   juere-engine.stage
   juere-engine.physics
   juere-engine.level-editor
   juere-engine.shooting-gallery
   juere-engine.rendering ;
IN: juere-engine

CONSTANT: mouse-sens { 0.002 0.002 }

CONSTANT: camv 0.1
CONSTANT: -camv -0.1

! == Control Processing 
TUPLE: control-state
   cam-Xv cam-Yv cam-Zv
   player-Xv player-Zv 
   click-state ;

: <controls> ( -- control-state )
   0 0 0 f f f control-state boa ;

: add-action ( stage-gt quot -- )
   [ add-action* ] curry change-stage drop ;

: move-tangible ( yaw xv xz -- action )
   [ or ] [ [ [ 0 ] unless* ] bi@
            2array xz>angle nip - 
            '[ 0 _ footfall ] 
   ] [ 3drop [ drop ] ] 2if ;

: move-intangible ( yaw xv xz -- action )
   [ [ 0 ] unless* ] bi@ [ -1 * ] dip
   rot rot-vector 2array -1 v*n
   '[ 0 _ move-entity ] ;

: apply-control-state ( stage-gt -- stage-gt )
   dup control-state>>
      [ cam-Xv>> ] [ cam-Yv>> ] [ cam-Zv>> ] tri 3array
      dupd [ move-camera ] curry add-action

   dup control-state>> click-state>>
      [ dupd [ set-crosshair ] curry add-action ] when*

   dup [ stage>> camera-yaw>> ] [ control-state>> ] bi
       [ player-Xv>> ] [ player-Zv>> ] bi
     [ move-tangible dupd add-action ] 3keep
     move-intangible over stage>> physical?
     [ drop ] [ dupd add-action ] if ;

! == Stage Gadget ==

! Declared in .rendering:
! TUPLE: stage-gadget < gadget
!   stage yaw pitch camera-xyz 
!   control-state stop? ;

SINGLETON: stage-pen
M: stage-pen draw-interior ( gadget pen -- )
   drop dup [ draw-stage ] curry with-3dgl ;

M: stage-gadget pref-dim* drop ${ 600 600 } ;
: <stage-gadget> ( stage -- gadget )
   stage-gadget new
        swap >>stage
   stage-pen >>interior
           t >>clipped?
          45 >>fov
  <controls> >>control-state ;

! == Threads ==

CONSTANT: ticktime 25

: update-thread ( gadget -- )
   dup stop?>> [ drop ] 
   [ ticktime milliseconds sleep
     apply-control-state
     dup stage>> do-actions
     dup relayout-1
     update-thread
   ] if ;

M: stage-gadget graft* ( gadget -- ) 
   ! How do we get tracebacks and errors out from a thread?
   f >>stop? [ update-thread ] curry in-thread ;

M: stage-gadget ungraft* ( gadget -- ) 
   t >>stop? drop ;

! == Keyboard Processing ==

: k-toggle ( stage-gt gesture accessor states -- ? )
   rot key-down? [ first ] [ second ] if 
   swap curry change-control-state ; inline

: if-down ( gesture quot -- ? )
   [ key-down? ] dip [ drop ] if t ; inline

: do-keys ( stage-gt gesture -- ? ) 
! Factor out into lv-edit/phys/etc.
   dup sym>> >lower { 
   { "w" [ [ >>cam-Zv ] { -0.1 0 } k-toggle ] }
   { "s" [ [ >>cam-Zv ] { 0.1 0 } k-toggle ] }
   { "a" [ [ >>cam-Xv ] { -0.1 0 } k-toggle ] }
   { "d" [ [ >>cam-Xv ] { 0.1 0 } k-toggle ] }
   { " " [ [ >>cam-Yv ] { -0.1 0 } k-toggle ] }
   { "tab" [ [ >>cam-Yv ] { 0.1 0 } k-toggle ] }

   { "up"    [ [ >>player-Zv ] { 0.1 f } k-toggle ] }
   { "down"  [ [ >>player-Zv ] { -0.1 f } k-toggle ] }
   { "left"  [ [ >>player-Xv ] { -0.1 f } k-toggle ] }
   { "right" [ [ >>player-Xv ] { 0.1 f } k-toggle ] }
   
   { "z" [ [ [ 0.05 raise@cursor ] add-action ] if-down ] }
   { "x" [ [ [ -0.05 raise@cursor ] add-action ] if-down ] }
   { "c" [ [ [ 0 jump ] add-action ] if-down ] }
   { "delete" [ [ [ del@cursor ] add-action ] if-down ] }

   { "b" [ [ [  1 next-mat ] add-action ] if-down ] }
   { "n" [ [ [ -1 next-mat ] add-action ] if-down ] }
   { "m" [ [ [ push-tile@cursor ] add-action ] if-down ] }

   [ 3drop f ]
   } case ;

: do-drag ( stage-gt gesture -- ? )
   drop drag-loc mouse-sens v* first2
   [ rotate-camera ] 2curry add-action t ;

: click-axis ( stage-gt -- d-yaw d-pitch )
   [ fov>> ] [ dim>> ] bi hand-click-loc get-global
   swap [ v/ 0.5 v-n ] keep first2 / '{ _ -1 } v*
   swap v*n first2 neg ;

:: pt@angles ( yaw pitch length -- point )
    pitch deg>rad cos length * yaw -90 + angle>xyz
    pitch neg deg>rad sin length * '{ 0 _ 0 } v+ ;

: clicked ( stage-gt length -- point )
   [ dup stage>> [ camera-xyz>> ] [ camera-yaw>> ] 
                 [ camera-pitch>> ] tri 
     4 nrot click-axis swapd [ + ] 2bi@ 
   ] dip pt@angles v+ ;

M: stage-gadget handle-gesture ( gesture gadget -- ? ) 
   swap 
   { { [ dup key-gesture? ] [ do-keys ] }
     { [ dup drag? ] [ do-drag ] }
     { [ dup button-down? ] 
         [ dupd drop 10 clicked [ >>click-state ] 
           curry change-control-state
           request-focus t ] } 
     [ 2drop f ]
   } cond ;

M: stage-gadget handles-gesture? 2drop t ;

! == Windows ==

MEMO: w-attributes ( -- pixel-format-attributes )
 T{ world-attributes 
   { pixel-format-attributes { 
      windowed
      double-buffered
      T{ depth-bits { value 16 } }
     } }
   { title "Juere Engine" }
 } ;

: run-juere ( gadget -- gadget )
   \ (load-texture) reset-memoized
   [ w-attributes open-window ] dupd curry with-ui ;

: juere-engine* ( -- gadget )
   test-stage <stage-gadget> run-juere ;