Files
itgmania212121/stepmania/src/LightsManager.cpp
T

497 lines
12 KiB
C++
Raw Normal View History

2003-11-16 04:45:12 +00:00
#include "global.h"
#include "LightsManager.h"
#include "GameState.h"
#include "RageTimer.h"
#include "arch/Lights/LightsDriver.h"
#include "RageUtil.h"
2003-11-16 06:27:52 +00:00
#include "GameInput.h" // for GameController
#include "InputMapper.h"
2004-07-25 17:07:32 +00:00
#include "Game.h"
#include "PrefsManager.h"
2005-04-29 00:26:48 +00:00
#include "Actor.h"
2005-05-04 20:28:50 +00:00
#include "Preference.h"
#include "Foreach.h"
#include "GameManager.h"
#include "CommonMetrics.h"
#include "Style.h"
2003-11-16 04:45:12 +00:00
#include "arch/arch.h"
2003-11-16 04:45:12 +00:00
Preference<float> g_fLightsFalloffSeconds( "LightsFalloffSeconds", 0.1f );
Preference<float> g_fLightsAheadSeconds( "LightsAheadSeconds", 0.05f );
2005-05-04 20:28:50 +00:00
static const CString CabinetLightNames[] = {
2004-03-29 09:44:00 +00:00
"MarqueeUpLeft",
"MarqueeUpRight",
"MarqueeLrLeft",
"MarqueeLrRight",
"ButtonsLeft",
"ButtonsRight",
"BassLeft",
"BassRight",
};
2005-03-05 21:50:33 +00:00
XToString( CabinetLight, NUM_CABINET_LIGHTS );
2005-04-28 11:13:53 +00:00
StringToX( CabinetLight );
2004-03-29 09:44:00 +00:00
static const CString LightsModeNames[] = {
"Attract",
"Joining",
"Menu",
"Demonstration",
"Gameplay",
"Stage",
"Cleared",
2005-04-21 19:54:11 +00:00
"TestAutoCycle",
"TestManualCycle",
};
2005-03-05 21:50:33 +00:00
XToString( LightsMode, NUM_LIGHTS_MODES );
static void GetUsedGameInputs( vector<GameInput> &vGameInputsOut )
{
vGameInputsOut.clear();
set<GameInput> vGIs;
vector<const Style*> vStyles;
GAMEMAN->GetStylesForGame( GAMESTATE->m_pCurGame, vStyles );
FOREACH( const Style*, vStyles, style )
{
bool bFound = find( STEPS_TYPES_TO_SHOW.GetValue().begin(), STEPS_TYPES_TO_SHOW.GetValue().end(), (*style)->m_StepsType ) != STEPS_TYPES_TO_SHOW.GetValue().end();
if( !bFound )
continue;
FOREACH_PlayerNumber( pn )
{
for( int i=0; i<(*style)->m_iColsPerPlayer; i++ )
{
StyleInput si( pn, i );
GameInput gi = (*style)->StyleInputToGameInput( si );
if( gi.IsValid() )
{
vGIs.insert( gi );
}
}
}
}
FOREACHS_CONST( GameInput, vGIs, gi )
vGameInputsOut.push_back( *gi );
}
2004-03-29 09:44:00 +00:00
2003-11-16 04:45:12 +00:00
LightsManager* LIGHTSMAN = NULL; // global and accessable from anywhere in our program
LightsManager::LightsManager(CString sDriver)
{
ZERO( m_fSecsLeftInCabinetLightBlink );
ZERO( m_fSecsLeftInGameButtonBlink );
2005-04-29 02:06:51 +00:00
ZERO( m_fActorLights );
ZERO( m_fSecsLeftInActorLightBlink );
m_LightsMode = LIGHTSMODE_JOINING;
MakeLightsDrivers( sDriver, m_vpDrivers );
m_fTestAutoCycleCurrentIndex = 0;
m_clTestManualCycleCurrent = LIGHT_INVALID;
m_iControllerTestManualCycleCurrent = -1;
2003-11-16 04:45:12 +00:00
}
LightsManager::~LightsManager()
{
FOREACH( LightsDriver*, m_vpDrivers, iter )
SAFE_DELETE( *iter );
m_vpDrivers.clear();
2003-11-16 04:45:12 +00:00
}
2005-04-29 00:26:48 +00:00
// XXX: make themable
static const float g_fLightEffectRiseSeconds = 0.075f;
static const float g_fLightEffectFalloffSeconds = 0.35f;
2005-04-29 02:02:27 +00:00
void LightsManager::BlinkActorLight( CabinetLight cl )
{
2005-04-29 02:08:45 +00:00
m_fSecsLeftInActorLightBlink[cl] = g_fLightEffectRiseSeconds;
2005-04-29 02:02:27 +00:00
}
2005-04-29 00:26:48 +00:00
float LightsManager::GetActorLightLatencySeconds() const
{
return g_fLightEffectRiseSeconds;
}
2003-11-16 04:45:12 +00:00
void LightsManager::Update( float fDeltaTime )
{
2005-04-29 00:26:48 +00:00
//
// Update actor effect lights.
//
FOREACH_CabinetLight( cl )
{
float fTime = fDeltaTime;
2005-04-29 02:08:45 +00:00
float &fDuration = m_fSecsLeftInActorLightBlink[cl];
2005-04-29 00:26:48 +00:00
if( fDuration > 0 )
{
/* The light has power left. Brighten it. */
float fSeconds = min( fDuration, fTime );
fDuration -= fSeconds;
fTime -= fSeconds;
2005-04-29 02:09:56 +00:00
fapproach( m_fActorLights[cl], 1, fSeconds / g_fLightEffectRiseSeconds );
2005-04-29 00:26:48 +00:00
}
if( fTime > 0 )
{
/* The light is out of power. Dim it. */
2005-04-29 02:09:56 +00:00
fapproach( m_fActorLights[cl], 0, fTime / g_fLightEffectFalloffSeconds );
2005-04-29 00:26:48 +00:00
}
2005-04-29 02:09:56 +00:00
Actor::SetBGMLight( cl, m_fActorLights[cl] );
2005-04-29 00:26:48 +00:00
}
if( !IsEnabled() )
return;
2004-04-20 02:35:30 +00:00
// update lights falloff
{
FOREACH_CabinetLight( cl )
fapproach( m_fSecsLeftInCabinetLightBlink[cl], 0, fDeltaTime );
FOREACH_GameController( gc )
FOREACH_GameButton( gb )
fapproach( m_fSecsLeftInGameButtonBlink[gc][gb], 0, fDeltaTime );
2004-04-20 02:35:30 +00:00
}
2004-03-30 07:44:29 +00:00
2003-11-16 06:27:52 +00:00
//
2004-04-20 02:35:30 +00:00
// Set new lights state cabinet lights
2003-11-16 06:27:52 +00:00
//
2004-04-20 02:35:30 +00:00
{
ZERO( m_LightsState.m_bCabinetLights );
ZERO( m_LightsState.m_bGameButtonLights );
2004-04-20 02:35:30 +00:00
}
2004-03-30 07:44:29 +00:00
2005-04-21 19:54:11 +00:00
if( m_LightsMode == LIGHTSMODE_TEST_AUTO_CYCLE )
{
m_fTestAutoCycleCurrentIndex += fDeltaTime;
m_fTestAutoCycleCurrentIndex = fmodf( m_fTestAutoCycleCurrentIndex, NUM_CABINET_LIGHTS*100 );
2005-04-21 19:54:11 +00:00
}
2004-03-23 06:11:10 +00:00
switch( m_LightsMode )
2003-11-16 04:45:12 +00:00
{
2004-03-23 06:11:10 +00:00
case LIGHTSMODE_JOINING:
2003-11-16 04:45:12 +00:00
{
2005-05-04 20:37:41 +00:00
// int iBeat = (int)(GAMESTATE->m_fLightSongBeat);
2004-04-02 00:19:01 +00:00
// bool bBlinkOn = (iBeat%2)==0;
2004-03-30 07:44:29 +00:00
FOREACH_PlayerNumber( pn )
2003-11-16 04:45:12 +00:00
{
2004-03-30 07:44:29 +00:00
if( GAMESTATE->m_bSideIsJoined[pn] )
2003-11-16 04:45:12 +00:00
{
2004-03-30 07:44:29 +00:00
m_LightsState.m_bCabinetLights[LIGHT_MARQUEE_UP_LEFT+pn] = true;
m_LightsState.m_bCabinetLights[LIGHT_MARQUEE_LR_LEFT+pn] = true;
m_LightsState.m_bCabinetLights[LIGHT_BUTTONS_LEFT+pn] = true;
m_LightsState.m_bCabinetLights[LIGHT_BASS_LEFT+pn] = true;
2003-11-16 04:45:12 +00:00
}
}
}
break;
2004-03-23 06:11:10 +00:00
case LIGHTSMODE_ATTRACT:
2003-11-16 04:45:12 +00:00
{
int iSec = (int)RageTimer::GetTimeSinceStartFast();
2004-03-30 07:44:29 +00:00
int iTopIndex = iSec % 4;
switch( iTopIndex )
2003-11-16 04:45:12 +00:00
{
2004-03-30 07:44:29 +00:00
case 0: m_LightsState.m_bCabinetLights[LIGHT_MARQUEE_UP_LEFT] = true; break;
case 1: m_LightsState.m_bCabinetLights[LIGHT_MARQUEE_LR_RIGHT] = true; break;
case 2: m_LightsState.m_bCabinetLights[LIGHT_MARQUEE_UP_RIGHT] = true; break;
case 3: m_LightsState.m_bCabinetLights[LIGHT_MARQUEE_LR_LEFT] = true; break;
default: ASSERT(0);
2003-11-16 04:45:12 +00:00
}
2004-03-30 07:44:29 +00:00
bool bOn = (iSec%4)==0;
m_LightsState.m_bCabinetLights[LIGHT_BASS_LEFT] = bOn;
m_LightsState.m_bCabinetLights[LIGHT_BASS_RIGHT] = bOn;
2003-11-16 04:45:12 +00:00
}
break;
2004-03-23 06:11:10 +00:00
case LIGHTSMODE_MENU:
2003-11-16 04:45:12 +00:00
{
2004-03-30 07:44:29 +00:00
FOREACH_CabinetLight( cl )
m_LightsState.m_bCabinetLights[cl] = false;
2005-05-04 20:37:41 +00:00
int iBeat = (int)(GAMESTATE->m_fLightSongBeat);
int iTopIndex = iBeat;
wrap( iTopIndex, 4 );
2004-03-30 07:44:29 +00:00
switch( iTopIndex )
2003-11-16 04:45:12 +00:00
{
2004-03-30 07:44:29 +00:00
case 0: m_LightsState.m_bCabinetLights[LIGHT_MARQUEE_UP_LEFT] = true; break;
case 1: m_LightsState.m_bCabinetLights[LIGHT_MARQUEE_LR_RIGHT] = true; break;
case 2: m_LightsState.m_bCabinetLights[LIGHT_MARQUEE_UP_RIGHT] = true; break;
case 3: m_LightsState.m_bCabinetLights[LIGHT_MARQUEE_LR_LEFT] = true; break;
default: ASSERT(0);
2003-11-16 04:45:12 +00:00
}
2004-03-30 07:44:29 +00:00
2005-05-04 20:28:50 +00:00
/* Flash the button lights for active players. */
2004-03-30 07:44:29 +00:00
bool bBlinkOn = (iBeat%2)==0;
FOREACH_PlayerNumber( pn )
2003-11-16 04:45:12 +00:00
{
2004-03-30 07:44:29 +00:00
if( GAMESTATE->m_bSideIsJoined[pn] )
{
m_LightsState.m_bCabinetLights[LIGHT_BUTTONS_LEFT+pn] = bBlinkOn;
}
2003-11-16 04:45:12 +00:00
}
}
break;
2004-03-23 06:11:10 +00:00
case LIGHTSMODE_DEMONSTRATION:
case LIGHTSMODE_GAMEPLAY:
2004-05-20 19:05:37 +00:00
FOREACH_CabinetLight( cl )
m_LightsState.m_bCabinetLights[cl] = m_fSecsLeftInCabinetLightBlink[cl] > 0;
2003-11-16 04:45:12 +00:00
break;
2004-03-23 06:11:10 +00:00
case LIGHTSMODE_STAGE:
case LIGHTSMODE_ALL_CLEARED:
2003-11-16 04:45:12 +00:00
{
2004-03-23 06:11:10 +00:00
FOREACH_CabinetLight( cl )
2005-06-02 20:38:30 +00:00
{
bool b = true;
switch( cl )
{
case LIGHT_BUTTONS_LEFT:
case LIGHT_BUTTONS_RIGHT:
b = false;
break;
default:
b = true;
break;
}
m_LightsState.m_bCabinetLights[cl] = b;
}
2003-11-16 04:45:12 +00:00
}
break;
2005-04-21 19:54:11 +00:00
case LIGHTSMODE_TEST_AUTO_CYCLE:
2004-03-23 06:33:01 +00:00
{
int iSec = GetTestAutoCycleCurrentIndex();
2004-03-23 06:33:01 +00:00
FOREACH_CabinetLight( cl )
{
bool bOn = (iSec%NUM_CABINET_LIGHTS) == cl;
m_LightsState.m_bCabinetLights[cl] = bOn;
}
}
break;
case LIGHTSMODE_TEST_MANUAL_CYCLE:
{
FOREACH_CabinetLight( cl )
{
bool bOn = cl == m_clTestManualCycleCurrent;
m_LightsState.m_bCabinetLights[cl] = bOn;
}
}
break;
2003-11-16 04:45:12 +00:00
default:
ASSERT(0);
}
2003-11-16 06:27:52 +00:00
2004-03-30 08:03:00 +00:00
// If not joined, has enough credits, and not too late to join, then
// blink the menu buttons rapidly so they'll press Start
{
2005-05-04 20:37:41 +00:00
int iBeat = (int)(GAMESTATE->m_fLightSongBeat*4);
2004-03-30 08:03:00 +00:00
bool bBlinkOn = (iBeat%2)==0;
FOREACH_PlayerNumber( pn )
{
if( !GAMESTATE->m_bSideIsJoined[pn] && GAMESTATE->PlayersCanJoin() && GAMESTATE->EnoughCreditsToJoin() )
{
m_LightsState.m_bCabinetLights[LIGHT_BUTTONS_LEFT+pn] = bBlinkOn;
}
}
}
2003-11-16 06:27:52 +00:00
//
// Update game controller lights
//
// FIXME: Works only with Game==dance
// FIXME: lights pads for players who aren't playing
2004-03-23 06:11:10 +00:00
switch( m_LightsMode )
2003-11-16 06:27:52 +00:00
{
2004-03-23 06:11:10 +00:00
case LIGHTSMODE_ATTRACT:
case LIGHTSMODE_DEMONSTRATION:
2003-11-16 06:27:52 +00:00
{
2004-03-23 06:11:10 +00:00
ZERO( m_LightsState.m_bGameButtonLights );
2003-11-16 06:27:52 +00:00
}
break;
2004-03-23 06:11:10 +00:00
case LIGHTSMODE_ALL_CLEARED:
case LIGHTSMODE_STAGE:
case LIGHTSMODE_JOINING:
2003-11-16 06:27:52 +00:00
{
2004-03-23 06:11:10 +00:00
FOREACH_GameController( gc )
2003-11-16 06:27:52 +00:00
{
2004-03-23 06:11:10 +00:00
bool bOn = GAMESTATE->m_bSideIsJoined[gc];
2003-11-16 06:27:52 +00:00
2004-03-23 06:11:10 +00:00
FOREACH_GameButton( gb )
m_LightsState.m_bGameButtonLights[gc][gb] = bOn;
2003-11-16 06:27:52 +00:00
}
}
break;
case LIGHTSMODE_MENU:
case LIGHTSMODE_GAMEPLAY:
2003-11-16 06:27:52 +00:00
{
if( m_LightsMode == LIGHTSMODE_GAMEPLAY && PREFSMAN->m_bBlinkGameplayButtonLightsOnNote )
2003-11-16 06:27:52 +00:00
{
//
// Blink on notes.
//
FOREACH_GameController( gc )
2003-11-16 06:27:52 +00:00
{
FOREACH_GameButton( gb )
{
m_LightsState.m_bGameButtonLights[gc][gb] = m_fSecsLeftInGameButtonBlink[gc][gb] > 0 ;
}
}
}
else
{
//
// Blink on button pressess.
//
FOREACH_GameController( gc )
{
// don't blink unjoined sides
if( !GAMESTATE->m_bSideIsJoined[gc] )
continue;
FOREACH_GameButton( gb )
{
bool bOn = INPUTMAPPER->IsButtonDown( GameInput(gc,gb) );
m_LightsState.m_bGameButtonLights[gc][gb] = bOn;
}
2003-11-16 06:27:52 +00:00
}
}
}
break;
2005-04-21 19:54:11 +00:00
case LIGHTSMODE_TEST_AUTO_CYCLE:
2004-03-23 06:33:01 +00:00
{
int index = GetTestAutoCycleCurrentIndex();
vector<GameInput> vGI;
GetUsedGameInputs( vGI );
wrap( index, vGI.size() );
2004-04-07 02:27:11 +00:00
ZERO( m_LightsState.m_bGameButtonLights );
GameController gc = vGI[index].controller;
GameButton gb = vGI[index].button;
m_LightsState.m_bGameButtonLights[gc][gb] = true;
}
break;
case LIGHTSMODE_TEST_MANUAL_CYCLE:
{
ZERO( m_LightsState.m_bGameButtonLights );
vector<GameInput> vGI;
GetUsedGameInputs( vGI );
if( m_iControllerTestManualCycleCurrent != -1 )
2004-03-23 06:33:01 +00:00
{
GameController gc = vGI[m_iControllerTestManualCycleCurrent].controller;
GameButton gb = vGI[m_iControllerTestManualCycleCurrent].button;
m_LightsState.m_bGameButtonLights[gc][gb] = true;
2004-03-23 06:33:01 +00:00
}
}
break;
2003-11-16 06:27:52 +00:00
default:
ASSERT(0);
}
2003-11-16 07:43:39 +00:00
// apply new light values we set above
FOREACH( LightsDriver*, m_vpDrivers, iter )
(*iter)->Set( &m_LightsState );
2003-11-16 04:45:12 +00:00
}
void LightsManager::BlinkCabinetLight( CabinetLight cl )
{
2005-05-04 20:28:50 +00:00
m_fSecsLeftInCabinetLightBlink[cl] = g_fLightsFalloffSeconds;
}
void LightsManager::BlinkGameButton( GameInput gi )
2004-03-30 07:44:29 +00:00
{
2005-05-04 20:28:50 +00:00
m_fSecsLeftInGameButtonBlink[gi.controller][gi.button] = g_fLightsFalloffSeconds;
2004-03-30 07:44:29 +00:00
}
2004-03-23 06:11:10 +00:00
void LightsManager::SetLightsMode( LightsMode lm )
2003-11-16 04:45:12 +00:00
{
2004-03-23 06:11:10 +00:00
m_LightsMode = lm;
2003-11-20 11:55:45 +00:00
}
LightsMode LightsManager::GetLightsMode()
{
return m_LightsMode;
}
2004-06-08 01:24:17 +00:00
void LightsManager::ChangeTestCabinetLight( int iDir )
2005-04-21 19:54:11 +00:00
{
m_iControllerTestManualCycleCurrent = -1;
m_clTestManualCycleCurrent = (CabinetLight)(m_clTestManualCycleCurrent+iDir);
wrap( (int&)m_clTestManualCycleCurrent, NUM_CABINET_LIGHTS );
2005-04-21 19:54:11 +00:00
}
void LightsManager::ChangeTestGameButtonLight( int iDir )
2005-04-21 19:54:11 +00:00
{
m_clTestManualCycleCurrent = LIGHT_INVALID;
vector<GameInput> vGI;
GetUsedGameInputs( vGI );
2005-04-21 19:54:11 +00:00
m_iControllerTestManualCycleCurrent += iDir;
wrap( m_iControllerTestManualCycleCurrent, vGI.size() );
}
2005-04-21 19:54:11 +00:00
CabinetLight LightsManager::GetFirstLitCabinetLight()
2005-04-21 19:54:11 +00:00
{
FOREACH_CabinetLight( cl )
{
if( m_LightsState.m_bCabinetLights[cl] )
return cl;
}
return LIGHT_INVALID;
2005-04-21 19:54:11 +00:00
}
void LightsManager::GetFirstLitGameButtonLight( GameController &gcOut, GameButton &gbOut )
{
FOREACH_GameController( gc )
{
FOREACH_GameButton( gb )
{
if( m_LightsState.m_bGameButtonLights[gc][gb] )
{
gcOut = gc;
gbOut = gb;
return;
}
}
}
gcOut = GAME_CONTROLLER_INVALID;
gbOut = GAME_BUTTON_INVALID;
2005-04-21 19:54:11 +00:00
}
bool LightsManager::IsEnabled() const
{
return m_vpDrivers.size() > 1 || PREFSMAN->m_bDebugLights;
}
2004-06-08 01:24:17 +00:00
/*
* (c) 2003-2004 Chris Danford
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/