@ -1,6 +1,7 @@
# pragma once
# include "olcPixelGameEngine.h"
# include "SMX.h"
# include <assert.h>
using namespace olc ;
@ -15,15 +16,17 @@ public:
//LEFT is 0x08
//Add these bytes together to get the combination (all 4 held down is 0xAA
HWButton GetPanel ( Key k , int pad = 0 ) const {
return panelState [ k - UP ] ;
return panelState [ k - UP ] [ pad ] ;
} ;
void EnableLogMessages ( bool enabled ) {
logMessages = enabled ;
}
private :
static bool logMessages ;
HWButton internal_panelState [ 4 ] ;
HWButton panelState [ 4 ] ; //We store the 4 main panel states, similar to how PGE does.
HWButton internal_panelState [ 4 ] [ 2 ] ;
HWButton panelState [ 4 ] [ 2 ] ; //We store the 4 main panel states, similar to how PGE does.
double totalElapsedTime { 0. } ;
double nextLightUpdate { 0. } ;
//SMX "screen" is 12x21
//Each panel is 4x7
static void SMXStateChangedCallback ( int pad , SMXUpdateCallbackReason reason , void * pUser )
@ -44,31 +47,57 @@ private:
{
if ( logMessages ) {
printf ( " Device %i state changed: %04x \n " , pad , SMX_GetInputState ( pad ) ) ;
printf ( " Device %i state changed: %04x \n " , 1 , SMX_GetInputState ( 1 ) ) ;
}
int16_t state ( SMX_GetInputState ( pad ) ) ;
if ( state & 0x2 & & ! internal_panelState [ UP - UP ] . bPressed ) {
internal_panelState [ UP - UP ] = { true , false , true } ;
int16_t state ( SMX_GetInputState ( 0 ) ) ;
if ( state & 0x2 & & ! internal_panelState [ UP - UP ] [ 0 ] . bPressed ) {
internal_panelState [ UP - UP ] [ 0 ] = { true , false , true } ;
} else
if ( ! ( state & 0x2 ) & & ! internal_panelState [ UP - UP ] . bReleased ) {
internal_panelState [ UP - UP ] = { false , true , false } ;
if ( ! ( state & 0x2 ) & & ! internal_panelState [ UP - UP ] [ 0 ] . bReleased ) {
internal_panelState [ UP - UP ] [ 0 ] = { false , true , false } ;
}
if ( state & 0x20 & & ! internal_panelState [ RIGHT - UP ] . bPressed ) {
internal_panelState [ RIGHT - UP ] = { true , false , true } ;
if ( state & 0x20 & & ! internal_panelState [ RIGHT - UP ] [ 0 ] . bPressed ) {
internal_panelState [ RIGHT - UP ] [ 0 ] = { true , false , true } ;
} else
if ( ! ( state & 0x20 ) & & ! internal_panelState [ RIGHT - UP ] . bReleased ) {
internal_panelState [ RIGHT - UP ] = { false , true , false } ;
if ( ! ( state & 0x20 ) & & ! internal_panelState [ RIGHT - UP ] [ 0 ] . bReleased ) {
internal_panelState [ RIGHT - UP ] [ 0 ] = { false , true , false } ;
}
if ( state & 0x80 & & ! internal_panelState [ DOWN - UP ] . bPressed ) {
internal_panelState [ DOWN - UP ] = { true , false , true } ;
if ( state & 0x80 & & ! internal_panelState [ DOWN - UP ] [ 0 ] . bPressed ) {
internal_panelState [ DOWN - UP ] [ 0 ] = { true , false , true } ;
} else
if ( ! ( state & 0x80 ) & & ! internal_panelState [ DOWN - UP ] . bReleased ) {
internal_panelState [ DOWN - UP ] = { false , true , false } ;
if ( ! ( state & 0x80 ) & & ! internal_panelState [ DOWN - UP ] [ 0 ] . bReleased ) {
internal_panelState [ DOWN - UP ] [ 0 ] = { false , true , false } ;
}
if ( state & 0x8 & & ! internal_panelState [ LEFT - UP ] . bPressed ) {
internal_panelState [ LEFT - UP ] = { true , false , true } ;
if ( state & 0x8 & & ! internal_panelState [ LEFT - UP ] [ 0 ] . bPressed ) {
internal_panelState [ LEFT - UP ] [ 0 ] = { true , false , true } ;
} else
if ( ! ( state & 0x8 ) & & ! internal_panelState [ LEFT - UP ] . bReleased ) {
internal_panelState [ LEFT - UP ] = { false , true , false } ;
if ( ! ( state & 0x8 ) & & ! internal_panelState [ LEFT - UP ] [ 0 ] . bReleased ) {
internal_panelState [ LEFT - UP ] [ 0 ] = { false , true , false } ;
}
state = SMX_GetInputState ( 1 ) ;
if ( state & 0x2 & & ! internal_panelState [ UP - UP ] [ 1 ] . bPressed ) {
internal_panelState [ UP - UP ] [ 1 ] = { true , false , true } ;
} else
if ( ! ( state & 0x2 ) & & ! internal_panelState [ UP - UP ] [ 1 ] . bReleased ) {
internal_panelState [ UP - UP ] [ 1 ] = { false , true , false } ;
}
if ( state & 0x20 & & ! internal_panelState [ RIGHT - UP ] [ 1 ] . bPressed ) {
internal_panelState [ RIGHT - UP ] [ 1 ] = { true , false , true } ;
} else
if ( ! ( state & 0x20 ) & & ! internal_panelState [ RIGHT - UP ] [ 1 ] . bReleased ) {
internal_panelState [ RIGHT - UP ] [ 1 ] = { false , true , false } ;
}
if ( state & 0x80 & & ! internal_panelState [ DOWN - UP ] [ 1 ] . bPressed ) {
internal_panelState [ DOWN - UP ] [ 1 ] = { true , false , true } ;
} else
if ( ! ( state & 0x80 ) & & ! internal_panelState [ DOWN - UP ] [ 1 ] . bReleased ) {
internal_panelState [ DOWN - UP ] [ 1 ] = { false , true , false } ;
}
if ( state & 0x8 & & ! internal_panelState [ LEFT - UP ] [ 1 ] . bPressed ) {
internal_panelState [ LEFT - UP ] [ 1 ] = { true , false , true } ;
} else
if ( ! ( state & 0x8 ) & & ! internal_panelState [ LEFT - UP ] [ 1 ] . bReleased ) {
internal_panelState [ LEFT - UP ] [ 1 ] = { false , true , false } ;
}
}
@ -79,18 +108,29 @@ private:
virtual bool OnBeforeUserUpdate ( float & fElapsedTime ) {
//We don't want the panel states changing in the middle of a frame, since the input polling is on a separate thread.
//Copy over the internal button states to the current panel state.
for ( int i = 0 ; i < 4 ; i + + ) {
panelState [ i ] = internal_panelState [ i ] ;
internal_panelState [ i ] . bPressed = false ;
internal_panelState [ i ] . bReleased = false ;
for ( int pad = 0 ; pad < 2 ; pad + + ) {
for ( int i = 0 ; i < 4 ; i + + ) {
panelState [ i ] [ pad ] = internal_panelState [ i ] [ pad ] ;
internal_panelState [ i ] [ pad ] . bPressed = false ;
internal_panelState [ i ] [ pad ] . bReleased = false ;
}
}
return false ;
}
virtual void OnAfterUserUpdate ( float fElapsedTime ) override {
for ( int i = 0 ; i < 4 ; i + + ) {
panelState [ i ] . bPressed = false ;
panelState [ i ] . bReleased = false ;
double previousTotalElapsedTime { totalElapsedTime } ;
totalElapsedTime = fmod ( totalElapsedTime + fElapsedTime , 10000. ) ;
if ( previousTotalElapsedTime > totalElapsedTime ) {
//We are in the past, so reset lastLightUpdate to keep lights running.
nextLightUpdate = totalElapsedTime ;
}
if ( nextLightUpdate > totalElapsedTime ) return ; //Ignore light updates if not enough time has passed. We can only send light updates at 30 FPS.
for ( int pad = 0 ; pad < 2 ; pad + + ) {
for ( int i = 0 ; i < 4 ; i + + ) {
panelState [ i ] [ pad ] . bPressed = false ;
panelState [ i ] [ pad ] . bReleased = false ;
}
}
std : : string lightData ;
//The light data for an SMX dance pad is outlined in the docs but the code used to transform the PGE's pixels to SMX pad's lights will be annotated here.
@ -105,7 +145,7 @@ private:
col + + ;
continue ;
}
Pixel p ( pge - > GetDrawTarget ( ) - > GetPixel ( x , y ) ) ;
Pixel p ( pge - > GetDrawTarget ( ) - > GetPixel ( x + 12 * pad , y ) ) ;
lightData . append ( 1 , p . r ) ;
lightData . append ( 1 , p . g ) ;
lightData . append ( 1 , p . b ) ;
@ -121,7 +161,7 @@ private:
col + + ;
continue ;
}
Pixel p ( pge - > GetDrawTarget ( ) - > GetPixel ( x , y ) ) ;
Pixel p ( pge - > GetDrawTarget ( ) - > GetPixel ( x + 12 * pad , y ) ) ;
lightData . append ( 1 , p . r ) ;
lightData . append ( 1 , p . g ) ;
lightData . append ( 1 , p . b ) ;
@ -131,6 +171,8 @@ private:
}
}
}
if ( lightData . size ( ) ! = 1350 ) throw ;
nextLightUpdate = totalElapsedTime + 1 / 30.f ;
SMX_SetLights2 ( lightData . data ( ) , lightData . size ( ) ) ;
}
} ;