mirror of
https://github.com/thug1src/thug.git
synced 2024-11-27 10:36:43 +00:00
1057 lines
28 KiB
C++
1057 lines
28 KiB
C++
|
/*****************************************************************************
|
||
|
** **
|
||
|
** Neversoft Entertainment. **
|
||
|
** **
|
||
|
** Copyright (C) 1999 - All Rights Reserved **
|
||
|
** **
|
||
|
******************************************************************************
|
||
|
** **
|
||
|
** Project: PS2 **
|
||
|
** **
|
||
|
** Module: **
|
||
|
** **
|
||
|
** File name: **
|
||
|
** **
|
||
|
** Created by: rjm, 9/12/2000 **
|
||
|
** **
|
||
|
** Description: **
|
||
|
** **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
// start autoduck documentation
|
||
|
// @DOC frontend
|
||
|
// @module frontend | None
|
||
|
// @subindex Scripting Database
|
||
|
// @index script | frontend
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Includes **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#include <core/defines.h>
|
||
|
#include <core/singleton.h>
|
||
|
#include <core/support.h>
|
||
|
#include <core/task.h>
|
||
|
|
||
|
#include <gfx/gfxman.h>
|
||
|
#include <gfx/camera.h>
|
||
|
|
||
|
#include <gel/inpman.h>
|
||
|
#include <gel/module.h>
|
||
|
#include <gel/music/music.h>
|
||
|
#include <gel/soundfx/soundfx.h>
|
||
|
#include <gel/net/net.h>
|
||
|
#include <gel/net/server/netserv.h>
|
||
|
#include <gel/net/client/netclnt.h>
|
||
|
#include <gel/mainloop.h>
|
||
|
#include <gel/objtrack.h>
|
||
|
#include <gel/object/compositeobjectmanager.h>
|
||
|
|
||
|
#include <modules/FrontEnd/FrontEnd.h>
|
||
|
#include <sk/modules/skate/skate.h>
|
||
|
|
||
|
#include <objects/skaterprofile.h>
|
||
|
|
||
|
#include <gel/scripting/array.h>
|
||
|
#include <gel/scripting/script.h>
|
||
|
#include <gel/scripting/symboltable.h>
|
||
|
#include <scripting/cfuncs.h>
|
||
|
|
||
|
#include <sk/gamenet/gamenet.h>
|
||
|
#include <sys/sio/keyboard.h>
|
||
|
#include <sys/profiler.h>
|
||
|
#include <sys/File/PRE.h>
|
||
|
#include <sys/replay/replay.h>
|
||
|
|
||
|
|
||
|
#include <gfx/2D/ScreenElemMan.h>
|
||
|
|
||
|
#include <sk/objects/skater.h> // just for pausing the skater, and for running the "run me now" script
|
||
|
|
||
|
|
||
|
extern bool run_runmenow;
|
||
|
|
||
|
namespace Mdl
|
||
|
{
|
||
|
DefineSingletonClass( FrontEnd, "Frontend module" );
|
||
|
|
||
|
|
||
|
FrontEnd::FrontEnd()
|
||
|
{
|
||
|
|
||
|
m_logic_task = new Tsk::Task< FrontEnd > ( FrontEnd::s_logic_code, *this, Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_FRONTEND);
|
||
|
m_handle_keyboard_task = new Tsk::Task< FrontEnd > ( FrontEnd::s_handle_keyboard_code, *this, Tsk::BaseTask::Node::vLOGIC_TASK_PRIORITY_HANDLE_KEYBOARD);
|
||
|
|
||
|
for ( int i = 0; i < SIO::vMAX_DEVICES; i++ )
|
||
|
{
|
||
|
mp_input_handlers[i] = new Inp::Handler< FrontEnd > ( i, FrontEnd::s_input_logic_code, *this, Tsk::BaseTask::Node::vHANDLER_PRIORITY_FRONTEND_INPUT_LOGIC0);
|
||
|
m_pad_info[i].mState = NOT_DOWN;
|
||
|
m_pad_info[i].mMode = ACTIVE;
|
||
|
}
|
||
|
m_paused = false;
|
||
|
|
||
|
m_auto_repeat_time[0] = Tmr::vRESOLUTION * 3 / 10;
|
||
|
m_auto_repeat_time[1] = Tmr::vRESOLUTION * 5 / 100;
|
||
|
|
||
|
|
||
|
// m_pad_info[1].mState = NOT_DOWN;
|
||
|
|
||
|
// m_pad_info[1].mMode = INACTIVE;
|
||
|
|
||
|
m_temp_block_pad_input = false;
|
||
|
|
||
|
m_using_auto_input = false;
|
||
|
m_check_for_auto_input = true;
|
||
|
m_auto_input_script_id = 0;
|
||
|
|
||
|
for (int i = 0; i < MAX_BUTTON_EVENT_MAP_ENTRIES; i++)
|
||
|
{
|
||
|
m_digital_button_event_map[i].mEventType = DEAD_ENTRY;
|
||
|
}
|
||
|
|
||
|
for ( int i = 0; i < SIO::vMAX_DEVICES; i++ )
|
||
|
m_device_server_map[i] = i;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
FrontEnd::~FrontEnd()
|
||
|
{
|
||
|
delete m_logic_task;
|
||
|
|
||
|
for ( int i = 0; i < SIO::vMAX_DEVICES; i++ )
|
||
|
{
|
||
|
delete mp_input_handlers[i];
|
||
|
mp_input_handlers[i] = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void FrontEnd::v_start_cb ( void )
|
||
|
{
|
||
|
|
||
|
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());
|
||
|
Mlp::Manager * mlp_manager = Mlp::Manager::Instance();
|
||
|
mlp_manager->AddLogicTask ( *m_logic_task );
|
||
|
Inp::Manager * inp_manager = Inp::Manager::Instance();
|
||
|
|
||
|
for ( int i = 0; i < SIO::vMAX_DEVICES; i++ )
|
||
|
{
|
||
|
Inp::Handler< FrontEnd >* p_handler = GetInputHandler( i );
|
||
|
inp_manager->AddHandler( *p_handler );
|
||
|
}
|
||
|
Mem::Manager::sHandle().PopContext();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void FrontEnd::v_stop_cb ( void )
|
||
|
{
|
||
|
m_logic_task->Remove();
|
||
|
|
||
|
for ( int i = 0; i < SIO::vMAX_DEVICES; i++ )
|
||
|
{
|
||
|
Inp::Handler< FrontEnd >* p_handler = GetInputHandler( i );
|
||
|
p_handler->Remove();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
bool FrontEnd::PadsPluggedIn()
|
||
|
{
|
||
|
for ( int i = 0; i < SIO::vMAX_DEVICES; i++ )
|
||
|
{
|
||
|
Dbg_MsgAssert(mp_input_handlers[i],("NULL mp_input_handlers[%d]",i));
|
||
|
if (mp_input_handlers[i]->m_Device->IsPluggedIn())
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void FrontEnd::AddKeyboardHandler( int max_string_length )
|
||
|
{
|
||
|
Mlp::Manager * mlp_manager = Mlp::Manager::Instance();
|
||
|
|
||
|
m_max_kb_string_length = max_string_length;
|
||
|
mlp_manager->AddLogicTask( *m_handle_keyboard_task );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void FrontEnd::RemoveKeyboardHandler( void )
|
||
|
{
|
||
|
m_handle_keyboard_task->Remove();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void FrontEnd::SetAnalogStickActiveForMenus( bool isActive )
|
||
|
{
|
||
|
Spt::SingletonPtr<Inp::Manager> p_manager;
|
||
|
p_manager->SetAnalogStickOverride(isActive);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////
|
||
|
// (Mick takes responsibility for this)
|
||
|
// This function JUST pauses the game
|
||
|
// this mainly consists of pausing all the tasks (for objects, cars, peds), but
|
||
|
// first it pauses the skate module (for music), and the sio_manager (pad vibration)
|
||
|
//
|
||
|
// The pausing of stuff is fairly comvoluted, here we:
|
||
|
//
|
||
|
// Pause the PCM music
|
||
|
// pause the pad vibration
|
||
|
// pause all messages, but allow future messages to be launched
|
||
|
// pause all spawned scripts, apart from the current one, and future spawned scritps
|
||
|
//
|
||
|
// pause the skater, but still allow the reading of the pad from script
|
||
|
//
|
||
|
// Overall, a rather mixed bag of things, which might be best refactored
|
||
|
// but should do for now.....
|
||
|
//
|
||
|
// Note: is_active == true ... implies the "Front End" is active, and the "game" paused
|
||
|
|
||
|
void FrontEnd::PauseGame(bool paused)
|
||
|
{
|
||
|
|
||
|
// if already in the correct "paused" state, then just return
|
||
|
if (paused == m_paused)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Mdl::Skate * skate_mod = Mdl::Skate::Instance();
|
||
|
if (paused)
|
||
|
{
|
||
|
// make game be paused
|
||
|
skate_mod->Pause( );
|
||
|
|
||
|
// Ken: Pause the controller vibrations.
|
||
|
SIO::Manager * sio_man = SIO::Manager::Instance();
|
||
|
sio_man->Pause();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// make game be unpaused
|
||
|
// Ken: Un-pause the controller vibrations.
|
||
|
SIO::Manager * sio_man = SIO::Manager::Instance();
|
||
|
sio_man->UnPause();
|
||
|
}
|
||
|
|
||
|
// Pause currently spawned scripts (any script with PauseGame in it will unpause itself)
|
||
|
Script::PauseSpawnedScripts(paused);
|
||
|
|
||
|
// Pause or unpause all the skaters
|
||
|
uint32 NumSkaters = skate_mod->GetNumSkaters();
|
||
|
|
||
|
for (uint32 i = 0; i < NumSkaters; ++i)
|
||
|
{
|
||
|
Obj::CSkater *pSkater = skate_mod->GetSkater(i);
|
||
|
if (pSkater) // Hmm, assert instead?
|
||
|
{
|
||
|
if (paused)
|
||
|
{
|
||
|
pSkater->Pause();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pSkater->UnPause();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Pause all composite objects
|
||
|
Obj::CCompositeObjectManager::Instance()->Pause(paused);
|
||
|
|
||
|
|
||
|
// pause (or unpause) any screen elements in process of morphing
|
||
|
Front::CScreenElementManager* p_screen_element_manager = Front::CScreenElementManager::Instance();
|
||
|
p_screen_element_manager->SetPausedState(paused);
|
||
|
|
||
|
m_paused = paused;
|
||
|
|
||
|
|
||
|
if (m_paused)
|
||
|
{
|
||
|
// make game be paused
|
||
|
Mlp::Manager * mlp_manager = Mlp::Manager::Instance();
|
||
|
mlp_manager->SetLogicMask(Mlp::Manager::mGAME_OBJECTS | Mlp::Manager::mGFX_MANAGER);
|
||
|
Tmr::StoreTimerInfo( );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// make game be unpaused
|
||
|
Mlp::Manager * mlp_manager = Mlp::Manager::Instance();
|
||
|
mlp_manager->SetLogicMask(Mlp::Manager::mNONE);
|
||
|
// rw_viewer->DisableMainLogic(false);
|
||
|
// unpause music and soundfx:
|
||
|
Mdl::Skate * skate_mod = Mdl::Skate::Instance();
|
||
|
skate_mod->Pause( false );
|
||
|
Tmr::RecallTimerInfo( );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void FrontEnd::AddEntriesToEventButtonMap(Script::CStruct *pParams)
|
||
|
{
|
||
|
#ifdef __PLAT_XBOX__
|
||
|
const char *p_array_name = "xbox";
|
||
|
#else
|
||
|
#ifdef __PLAT_NGC__
|
||
|
const char *p_array_name = "gamecube";
|
||
|
#else
|
||
|
const char *p_array_name = "ps2";
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
// This seems a very hacky way of doing things.
|
||
|
// Black and white need to be in position 16 and 17, since they are button indices 16 and 17.
|
||
|
#ifdef __PLAT_XBOX__
|
||
|
const char *p_button_names[] =
|
||
|
{
|
||
|
"left_trigger_full",
|
||
|
"right_trigger_full",
|
||
|
"left_trigger_half",
|
||
|
"right_trigger_half",
|
||
|
"y",
|
||
|
"b",
|
||
|
"a",
|
||
|
"x",
|
||
|
"back",
|
||
|
"left_stick_button",
|
||
|
"right_stick_button",
|
||
|
"null",
|
||
|
"null",
|
||
|
"null",
|
||
|
"null",
|
||
|
"null",
|
||
|
"black",
|
||
|
"white"
|
||
|
};
|
||
|
#else
|
||
|
#ifdef __PLAT_NGC__
|
||
|
const char *p_button_names[] =
|
||
|
{
|
||
|
"left_trigger_full",
|
||
|
"right_trigger_full",
|
||
|
"left_trigger_half",
|
||
|
"right_trigger_half",
|
||
|
"y",
|
||
|
"x",
|
||
|
"a",
|
||
|
"b",
|
||
|
"null",
|
||
|
"z_plus_left_trigger",
|
||
|
"z_plus_right_trigger",
|
||
|
"null",
|
||
|
"null",
|
||
|
"null",
|
||
|
"null",
|
||
|
"null",
|
||
|
"null",
|
||
|
"null",
|
||
|
"z"
|
||
|
};
|
||
|
#else
|
||
|
const char *p_button_names[] =
|
||
|
{
|
||
|
"left_trigger2",
|
||
|
"right_trigger2",
|
||
|
"left_trigger1",
|
||
|
"right_trigger1",
|
||
|
"triangle",
|
||
|
"circle",
|
||
|
"x",
|
||
|
"square",
|
||
|
"select",
|
||
|
"left_stick_button",
|
||
|
"right_stick_button"
|
||
|
};
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
// Cleaner way of allowing varying button names array per platform.
|
||
|
int num_mapped_buttons = sizeof( p_button_names ) / sizeof( char* );
|
||
|
|
||
|
uint32 null_crc = Script::GenerateCRC("null");
|
||
|
|
||
|
/*
|
||
|
Indices:
|
||
|
|
||
|
i: into script array
|
||
|
j: into button name array
|
||
|
x: into map array
|
||
|
*/
|
||
|
|
||
|
Script::CArray *p_map;
|
||
|
if (!pParams->GetArray(p_array_name, &p_map))
|
||
|
return;
|
||
|
|
||
|
for (uint i = 0; i < p_map->GetSize(); i++)
|
||
|
{
|
||
|
Script::CArray *p_entry = p_map->GetArray(i);
|
||
|
|
||
|
uint32 button_crc = p_entry->GetChecksum(0);
|
||
|
uint32 event_crc = p_entry->GetChecksum(1);
|
||
|
|
||
|
for (uint j = 0; j < (uint) num_mapped_buttons; j++)
|
||
|
{
|
||
|
if (button_crc == Script::GenerateCRC(p_button_names[j]) || button_crc == null_crc)
|
||
|
{
|
||
|
#ifdef __NOPT_ASSERT__
|
||
|
bool removing_entries = (button_crc == null_crc || event_crc == null_crc);
|
||
|
#endif
|
||
|
int x = 0;
|
||
|
for (; x < MAX_BUTTON_EVENT_MAP_ENTRIES; x++)
|
||
|
{
|
||
|
if (button_crc == null_crc && m_digital_button_event_map[x].mEventType == event_crc)
|
||
|
{
|
||
|
// in this case, I am removing existing entry (or entries)
|
||
|
m_digital_button_event_map[x].mEventType = DEAD_ENTRY;
|
||
|
}
|
||
|
else if (event_crc == null_crc && m_digital_button_event_map[x].mDigitalButtonIndex == j)
|
||
|
{
|
||
|
// in this case, I am removing existing entry (or entries)
|
||
|
m_digital_button_event_map[x].mEventType = DEAD_ENTRY;
|
||
|
}
|
||
|
else if (m_digital_button_event_map[x].mEventType == DEAD_ENTRY)
|
||
|
{
|
||
|
// in this case, I am adding a new entry, so need empty slot
|
||
|
m_digital_button_event_map[x].mDigitalButtonIndex = j;
|
||
|
m_digital_button_event_map[x].mEventType = event_crc;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
Dbg_MsgAssert(x < MAX_BUTTON_EVENT_MAP_ENTRIES || removing_entries, ("out of entries, increase size of MAX_BUTTON_EVENT_MAP_ENTRIES"));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Paul:
|
||
|
|
||
|
'Y' = PS2 'Triangle'.
|
||
|
'X' = PS2 'Circle'.
|
||
|
'A' = PS2 'X'.
|
||
|
'B' = PS2 'Square'.
|
||
|
'Left Trigger pressed down > halfway' = PS2 'L1'.
|
||
|
'Right Trigger pressed down > halfway' = PS2 'R1'.
|
||
|
'Left Trigger' = PS2 'L2'.
|
||
|
'Right Trigger' = PS2 'R2'.
|
||
|
'Z' plus 'L' = PS2 'Left Stick Button'.
|
||
|
'Z' plus 'R' = PS2 'Right Stick Button'
|
||
|
Z button without L & R is PS2 'Select'
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
Dave:
|
||
|
|
||
|
Xbox start = start
|
||
|
Xbox back = select
|
||
|
The 4 xbox color buttons map to the Ps2 buttons in the same location.
|
||
|
Black and white buttons aren't mapped at all.
|
||
|
Triggers as per Ngc.
|
||
|
Left and right stick buttons map directly to Ps2 equivalents
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void FrontEnd::s_input_logic_code ( const Inp::Handler < FrontEnd >& handler )
|
||
|
{
|
||
|
Dbg_AssertType ( &handler, Inp::Handler< FrontEnd > );
|
||
|
|
||
|
FrontEnd& mdl = handler.GetData();
|
||
|
|
||
|
Obj::CTracker* p_tracker = Obj::CTracker::Instance();
|
||
|
p_tracker->LogTick();
|
||
|
|
||
|
for (int count = 0;; count++)
|
||
|
{
|
||
|
uint32 event_type = 0;
|
||
|
|
||
|
if (count == 0)
|
||
|
{
|
||
|
if (mdl.m_check_for_auto_input)
|
||
|
{
|
||
|
mdl.m_using_auto_input = (bool) Script::GetInteger("use_auto_menu_input");
|
||
|
if (mdl.m_using_auto_input)
|
||
|
{
|
||
|
Script::CScript *p_script = Script::SpawnScript("auto_menu_input");
|
||
|
#ifdef __NOPT_ASSERT__
|
||
|
p_script->SetCommentString("Spawned from FrontEnd::s_input_logic_code");
|
||
|
#endif
|
||
|
mdl.m_auto_input_script_id = p_script->GetUniqueId();
|
||
|
}
|
||
|
mdl.m_check_for_auto_input = false;
|
||
|
}
|
||
|
|
||
|
uint32 timed_event_type = mdl.grab_timed_event_type(handler.m_Input->m_Buttons, handler.m_Index);
|
||
|
if (timed_event_type)
|
||
|
event_type = timed_event_type;
|
||
|
}
|
||
|
|
||
|
uint32 mapped_event_type = mdl.turn_mask_into_event_type(handler.m_Input->m_Makes, count, handler.m_Index,handler.m_Input->m_Buttons);
|
||
|
if (mapped_event_type)
|
||
|
event_type = mapped_event_type;
|
||
|
|
||
|
if (event_type && mdl.m_pad_info[handler.m_Index].mMode != INACTIVE && !mdl.m_temp_block_pad_input)
|
||
|
{
|
||
|
Script::CStruct event_data;
|
||
|
int device_num = handler.m_Device->GetPort();
|
||
|
event_data.AddInteger("device_num", device_num );
|
||
|
// printf("device_num = %i\n", device_num);
|
||
|
|
||
|
if (mdl.m_pad_info[handler.m_Index].mMode == ACTIVE)
|
||
|
{
|
||
|
// get the controller this came from
|
||
|
// event_data.AddInteger("controller", handler.m_Index);
|
||
|
event_data.AddInteger("controller", 0);
|
||
|
// event_data.AddInteger( "controller", Mdl::FrontEnd::Instance()->GetInputHandlerMapping( device_num ) );
|
||
|
// printf( "using controller %i\n", Mdl::FrontEnd::Instance()->GetInputHandlerMapping( device_num ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// printf("using 0\n");
|
||
|
event_data.AddInteger("controller", 0);
|
||
|
}
|
||
|
|
||
|
//if (handler.m_Index)
|
||
|
// printf("firing pad event %s\n", Script::FindChecksumName(event_type));
|
||
|
|
||
|
if (p_tracker->LaunchEvent(event_type, Obj::CEvent::vSYSTEM_EVENT, Obj::CEvent::vSYSTEM_EVENT, &event_data))
|
||
|
{
|
||
|
// will get here whenever menu systems responds to one of above occurences
|
||
|
|
||
|
//handler.m_Input->MaskDigitalInput(Inp::Data::mD_ALL);
|
||
|
//handler.m_Input->MaskAnalogInput(Inp::Data::mA_ALL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (event_type == 0)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void FrontEnd::s_logic_code ( const Tsk::Task< FrontEnd >& task )
|
||
|
{
|
||
|
Dbg_AssertType ( &task, Tsk::Task< FrontEnd > );
|
||
|
|
||
|
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());
|
||
|
|
||
|
FrontEnd& mdl = task.GetData();
|
||
|
|
||
|
mdl.update(mdl.m_paused);
|
||
|
|
||
|
|
||
|
# ifdef __USE_PROFILER__
|
||
|
Sys::CPUProfiler->PushContext( 0, 0, 128 ); // blue under green = screen element update
|
||
|
# endif // __USE_PROFILER__
|
||
|
|
||
|
|
||
|
Front::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();
|
||
|
p_screen_elem_man->Update();
|
||
|
|
||
|
|
||
|
|
||
|
# ifdef __USE_PROFILER__
|
||
|
Sys::CPUProfiler->PopContext( );
|
||
|
# endif // __USE_PROFILER__
|
||
|
|
||
|
Mem::Manager::sHandle().PopContext();
|
||
|
}
|
||
|
|
||
|
|
||
|
void FrontEnd::s_handle_keyboard_code( const Tsk::Task< FrontEnd >& task )
|
||
|
{
|
||
|
int i, num_chars;
|
||
|
char makes[256];
|
||
|
FrontEnd& mdl = task.GetData();
|
||
|
|
||
|
num_chars = SIO::KeyboardRead( makes );
|
||
|
|
||
|
for( i = 0; i < num_chars; i++ )
|
||
|
{
|
||
|
if((( makes[i] >= 32 ) && ( makes[i] <= 126 ) ) || ( makes[i] == SIO::vKB_ENTER ) || ( makes[i] == SIO::vKB_BACKSPACE ))
|
||
|
{
|
||
|
Script::CStruct* pParams;
|
||
|
|
||
|
pParams = new Script::CStruct;
|
||
|
if( makes[i] == SIO::vKB_ENTER )
|
||
|
{
|
||
|
pParams->AddChecksum( NONAME, Script::GenerateCRC( "got_enter" ));
|
||
|
}
|
||
|
else if( makes[i] == SIO::vKB_BACKSPACE )
|
||
|
{
|
||
|
pParams->AddChecksum( NONAME, Script::GenerateCRC( "got_backspace" ));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
char text_string[2];
|
||
|
|
||
|
text_string[0] = makes[i];
|
||
|
text_string[1] = '\0';
|
||
|
pParams->AddString( "text", text_string );
|
||
|
}
|
||
|
|
||
|
pParams->AddInteger( "max_length", mdl.m_max_kb_string_length );
|
||
|
Script::RunScript( "handle_keyboard_input", pParams );
|
||
|
delete pParams;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Don't let anyone else handle the keypresses
|
||
|
SIO::KeyboardClear();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*****************************************************************
|
||
|
* This friendly little function gets called every frame. 'game_is_paused'
|
||
|
* is true if the game is paused, or if the player is in the front end.
|
||
|
*
|
||
|
* I will probably move this function to MainMod.cpp or some other more
|
||
|
* logical place later on.
|
||
|
*
|
||
|
******************************************************************/
|
||
|
void FrontEnd::update(bool game_is_paused)
|
||
|
{
|
||
|
/*
|
||
|
===========================================
|
||
|
Non-front end Stuff
|
||
|
===========================================
|
||
|
*/
|
||
|
|
||
|
// Turn Keybard handler on and off
|
||
|
|
||
|
#ifdef __PLAT_NGPS__
|
||
|
if ( game_is_paused // paused
|
||
|
|| GameNet::Manager::Instance()->InNetGame() // or a network game
|
||
|
|| Mdl::Skate::Instance()->m_requested_level == 0x9f2bafb7 // (0x9f2bafb7 === Load_SkateShop) In skateshop
|
||
|
|| m_handle_keyboard_task->InList() // if the keyboard is on-screen
|
||
|
)
|
||
|
{
|
||
|
SIO::SetKeyboardActive(true);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SIO::SetKeyboardActive(false);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
// Call these functions every frame:
|
||
|
Pcm::Update( );
|
||
|
|
||
|
Sfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();
|
||
|
sfx_manager->Update();
|
||
|
|
||
|
if ( !game_is_paused )
|
||
|
{
|
||
|
// Mick: using the default heap here....
|
||
|
// as spawned scripts can fill up the front end heap in an unpredictable manner
|
||
|
// like with the LA earthquake
|
||
|
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());
|
||
|
|
||
|
|
||
|
# ifdef __USE_PROFILER__
|
||
|
Sys::CPUProfiler->PushContext( 128, 0, 0 ); // red under green = Positional Sounds
|
||
|
# endif // __USE_PROFILER__
|
||
|
|
||
|
sfx_manager->UpdatePositionalSounds( );
|
||
|
|
||
|
# ifdef __USE_PROFILER__
|
||
|
Sys::CPUProfiler->PopContext( ); //
|
||
|
# endif // __USE_PROFILER__
|
||
|
|
||
|
Mem::Manager::sHandle().PopContext();
|
||
|
}
|
||
|
|
||
|
|
||
|
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());
|
||
|
|
||
|
# ifdef __USE_PROFILER__
|
||
|
Sys::CPUProfiler->PushContext( 128, 128, 128 ); // gray under green = spawned scripts
|
||
|
# endif // __USE_PROFILER__
|
||
|
|
||
|
// And call these functions every game frame:
|
||
|
Script::UpdateSpawnedScripts();
|
||
|
|
||
|
Mdl::Skate * skate_mod = Mdl::Skate::Instance();
|
||
|
skate_mod->UpdateGameFlow();
|
||
|
|
||
|
// mick: run the special script I use for command line scripting
|
||
|
if (run_runmenow)
|
||
|
{
|
||
|
run_runmenow = false;
|
||
|
Mdl::Skate * skate_mod = Mdl::Skate::Instance();
|
||
|
Obj::CSkater *pSkater = skate_mod->GetLocalSkater();
|
||
|
Script::RunScript("RunMeNow",NULL,pSkater);
|
||
|
}
|
||
|
|
||
|
|
||
|
# ifdef __USE_PROFILER__
|
||
|
Sys::CPUProfiler->PopContext( ); //
|
||
|
# endif // __USE_PROFILER__
|
||
|
|
||
|
Mem::Manager::sHandle().PopContext();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
uint32 FrontEnd::grab_timed_event_type(uint mask, int index)
|
||
|
{
|
||
|
char makes[256];
|
||
|
int i, num_chars;
|
||
|
uint32 event_type = 0;
|
||
|
|
||
|
/*
|
||
|
We check for these types of pad presses first, because of the timing element
|
||
|
*/
|
||
|
if (mask & Inp::Data::mD_LEFT)
|
||
|
event_type = Obj::CEvent::TYPE_PAD_LEFT;
|
||
|
else if (mask & Inp::Data::mD_RIGHT)
|
||
|
event_type = Obj::CEvent::TYPE_PAD_RIGHT;
|
||
|
else if (mask & Inp::Data::mD_UP)
|
||
|
event_type = Obj::CEvent::TYPE_PAD_UP;
|
||
|
else if (mask & Inp::Data::mD_DOWN)
|
||
|
event_type = Obj::CEvent::TYPE_PAD_DOWN;
|
||
|
|
||
|
// Let the pad take precedence over the keyboard
|
||
|
if(( index == 0 ) && ( event_type == 0 ))
|
||
|
{
|
||
|
// First check for keyboard events, if there were any
|
||
|
num_chars = SIO::KeyboardRead( makes );
|
||
|
|
||
|
if( num_chars > 0 )
|
||
|
{
|
||
|
for( i = 0; i < num_chars; i++ )
|
||
|
{
|
||
|
if( makes[i] == SIO::vKB_LEFT )
|
||
|
{
|
||
|
event_type = Obj::CEvent::TYPE_PAD_LEFT;
|
||
|
break;
|
||
|
}
|
||
|
else if( makes[i] == SIO::vKB_RIGHT )
|
||
|
{
|
||
|
event_type = Obj::CEvent::TYPE_PAD_RIGHT;
|
||
|
break;
|
||
|
}
|
||
|
else if( makes[i] == SIO::vKB_UP )
|
||
|
{
|
||
|
event_type = Obj::CEvent::TYPE_PAD_UP;
|
||
|
break;
|
||
|
}
|
||
|
else if( makes[i] == SIO::vKB_DOWN )
|
||
|
{
|
||
|
event_type = Obj::CEvent::TYPE_PAD_DOWN;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (m_pad_info[index].mState == NOT_DOWN)
|
||
|
{
|
||
|
if (event_type)
|
||
|
{
|
||
|
// The directional pad was freshly pressed, so we will send an event.
|
||
|
// Begin next countdown until the pad input "counts" again.
|
||
|
m_pad_info[index].mAutorepeatCountdown = m_auto_repeat_time[0];
|
||
|
m_pad_info[index].mState = SLOW_REPEAT;
|
||
|
}
|
||
|
}
|
||
|
else if (event_type)
|
||
|
{
|
||
|
// The directional pad was held down last frame (and this one)
|
||
|
|
||
|
// update countdown time
|
||
|
Tmr::Time frame_time = (Tmr::Time) (Tmr::FrameLength() * Tmr::vRESOLUTION);
|
||
|
if (frame_time < m_pad_info[index].mAutorepeatCountdown)
|
||
|
m_pad_info[index].mAutorepeatCountdown -= frame_time;
|
||
|
else
|
||
|
m_pad_info[index].mAutorepeatCountdown = 0;
|
||
|
|
||
|
if (m_pad_info[index].mAutorepeatCountdown == 0)
|
||
|
{
|
||
|
// countdown finished, time to fire event, reset countdown time
|
||
|
if (m_pad_info[index].mState == SLOW_REPEAT)
|
||
|
m_pad_info[index].mState = FAST_REPEAT;
|
||
|
m_pad_info[index].mAutorepeatCountdown = m_auto_repeat_time[1];
|
||
|
}
|
||
|
else
|
||
|
// don't fire pad event, countdown hasn't finished
|
||
|
event_type = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pad_info[index].mState = NOT_DOWN;
|
||
|
}
|
||
|
|
||
|
if (m_using_auto_input && index == 0)
|
||
|
{
|
||
|
event_type = 0;
|
||
|
|
||
|
Script::CScript *p_script = Script::GetScriptWithUniqueId(m_auto_input_script_id);
|
||
|
if (p_script)
|
||
|
{
|
||
|
Script::UnpauseSpawnedScript(p_script);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_using_auto_input = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return event_type;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
uint32 FrontEnd::turn_mask_into_event_type(uint mask, int count, int index, uint buttons)
|
||
|
{
|
||
|
for (int i = 0; i < MAX_BUTTON_EVENT_MAP_ENTRIES; i++)
|
||
|
{
|
||
|
if ((mask & (1<<m_digital_button_event_map[i].mDigitalButtonIndex)) &&
|
||
|
m_digital_button_event_map[i].mEventType != DEAD_ENTRY)
|
||
|
{
|
||
|
count--;
|
||
|
if (count < 0)
|
||
|
return m_digital_button_event_map[i].mEventType;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// Mick: Ignore start button as an event if select is pressed and select_shift is true
|
||
|
if( ! (buttons & Inp::Data::mD_SELECT) || ! Script::GetInt(CRCD(0xf3e055e1,"select_shift")))
|
||
|
{
|
||
|
if( (mask & Inp::Data::mD_START) && count == 0 )
|
||
|
return Obj::CEvent::TYPE_PAD_START;
|
||
|
}
|
||
|
|
||
|
if( index == 0 )
|
||
|
{
|
||
|
char makes[256];
|
||
|
int i, num_chars;
|
||
|
uint32 event_type = 0;
|
||
|
|
||
|
// First check for keyboard events, if there were any
|
||
|
num_chars = SIO::KeyboardRead( makes );
|
||
|
|
||
|
if( num_chars > 0 )
|
||
|
{
|
||
|
for( i = 0; i < num_chars; i++ )
|
||
|
{
|
||
|
// If the keyboard menu is showing, don't treat space and enter as X
|
||
|
if( makes[i] == SIO::vKB_ESCAPE )
|
||
|
{
|
||
|
|
||
|
Script::CStruct* pParams;
|
||
|
|
||
|
pParams= new Script::CStruct;
|
||
|
pParams->AddChecksum( Script::GenerateCRC( "id" ), Script::GenerateCRC( "current_menu_anchor" ));
|
||
|
if( Obj::ScriptObjectExists( pParams, NULL ) == false )
|
||
|
{
|
||
|
event_type = Obj::CEvent::TYPE_PAD_START;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
event_type = Obj::CEvent::TYPE_PAD_BACK;
|
||
|
}
|
||
|
|
||
|
SIO::KeyboardClear();
|
||
|
delete pParams;
|
||
|
break;
|
||
|
}
|
||
|
else if(( makes[i] == SIO::vKB_ENTER ) || ( makes[i] == 32 ))
|
||
|
{
|
||
|
Script::CStruct* pParams;
|
||
|
bool menu_up;
|
||
|
|
||
|
menu_up = false;
|
||
|
pParams = new Script::CStruct;
|
||
|
pParams->AddChecksum( Script::GenerateCRC( "id" ), Script::GenerateCRC( "keyboard_anchor" ));
|
||
|
|
||
|
// Enter and space act as "choose" only if you're not currently using the on-screen keyboard
|
||
|
if( Obj::ScriptObjectExists( pParams, NULL ) == false )
|
||
|
{
|
||
|
pParams->Clear();
|
||
|
pParams->AddChecksum( Script::GenerateCRC( "id" ), Script::GenerateCRC( "actions_menu" ));
|
||
|
|
||
|
// only allow enter in actions menu
|
||
|
if( (Obj::ScriptObjectExists( pParams, NULL ) == true) && ( makes[i] == 32 ) )
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pParams->Clear();
|
||
|
pParams->AddChecksum( Script::GenerateCRC( "id" ), Script::GenerateCRC( "current_menu_anchor" ));
|
||
|
if( Obj::ScriptObjectExists( pParams, NULL ))
|
||
|
{
|
||
|
menu_up = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pParams->Clear();
|
||
|
pParams->AddChecksum( Script::GenerateCRC( "id" ), Script::GenerateCRC( "dialog_box_anchor" ));
|
||
|
if( Obj::ScriptObjectExists( pParams, NULL ))
|
||
|
{
|
||
|
menu_up = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( menu_up )
|
||
|
{
|
||
|
event_type = Obj::CEvent::TYPE_PAD_CHOOSE;
|
||
|
SIO::KeyboardClear();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
delete pParams;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return event_type;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void FrontEnd::UpdateInputHandlerMappings()
|
||
|
{
|
||
|
Spt::SingletonPtr< Inp::Manager > inp_man;
|
||
|
|
||
|
for ( int i = 0; i < SIO::vMAX_DEVICES; i++ )
|
||
|
{
|
||
|
printf("m_device_server_map[%i] = %i\n", i, m_device_server_map[i]);
|
||
|
Inp::Handler< FrontEnd >* p_handler = GetInputHandler( i );
|
||
|
if ( p_handler )
|
||
|
{
|
||
|
printf("got a handler\n");
|
||
|
inp_man->ReassignHandler( *p_handler, m_device_server_map[i] );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int FrontEnd::GetInputHandlerMapping( int device_num )
|
||
|
{
|
||
|
return m_device_server_map[device_num];
|
||
|
}
|
||
|
|
||
|
|
||
|
bool ScriptLaunchMenuScreen(Script::CScriptStructure *pParams, Script::CScript *pScript)
|
||
|
{
|
||
|
uint32 which_menu;
|
||
|
if (!pParams->GetChecksum("screen", &which_menu))
|
||
|
Dbg_MsgAssert(0, ("need screen=... with LaunchMenuScreen command"));
|
||
|
|
||
|
// XXX
|
||
|
Ryan("requesting game menu from LaunchMenuScreen\n");
|
||
|
// FrontEnd* frontend = FrontEnd::Instance();
|
||
|
// frontend->RequestMenuScreen(which_menu);
|
||
|
|
||
|
printf ("STUBBED: LaunchMenuScreen\n");
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
bool ScriptSetMenuAutoRepeatTimes(Script::CScriptStructure *pParams, Script::CScript *pScript)
|
||
|
{
|
||
|
Script::CPair times;
|
||
|
pParams->GetPair(NONAME, ×, Script::ASSERT);
|
||
|
|
||
|
FrontEnd* p_front_end = FrontEnd::Instance();
|
||
|
p_front_end->SetAutoRepeatTimes((Tmr::Time) (times.mX * (float) Tmr::vRESOLUTION),
|
||
|
(Tmr::Time) (times.mY * (float) Tmr::vRESOLUTION));
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
bool ScriptSetMenuPadMappings(Script::CScriptStructure *pParams, Script::CScript *pScript)
|
||
|
{
|
||
|
Script::CArray *p_map_array;
|
||
|
pParams->GetArray(NONAME, &p_map_array, true);
|
||
|
|
||
|
FrontEnd* p_front_end = FrontEnd::Instance();
|
||
|
for (int i = 0; i < 2; i++)
|
||
|
{
|
||
|
uint32 flag = p_map_array->GetChecksum(i);
|
||
|
FrontEnd::EControllerMode mode = FrontEnd::INACTIVE;
|
||
|
if (flag == Script::GenerateCRC("inactive"))
|
||
|
mode = FrontEnd::INACTIVE;
|
||
|
else if (flag == Script::GenerateCRC("active"))
|
||
|
mode = FrontEnd::ACTIVE;
|
||
|
else if (flag == Script::GenerateCRC("use_as_first"))
|
||
|
mode = FrontEnd::MAP_TO_FIRST;
|
||
|
else
|
||
|
Dbg_MsgAssert(0, ("unknown controller mode"));
|
||
|
|
||
|
p_front_end->SetControllerMode(i, mode);
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
bool ScriptSetButtonEventMappings(Script::CStruct *pParams, Script::CScript *pScript)
|
||
|
{
|
||
|
FrontEnd* p_front_end = FrontEnd::Instance();
|
||
|
p_front_end->AddEntriesToEventButtonMap(pParams);
|
||
|
|
||
|
if (pParams->ContainsFlag("block_menu_input"))
|
||
|
p_front_end->SetControllerTempBlock(true);
|
||
|
else if (pParams->ContainsFlag("unblock_menu_input"))
|
||
|
p_front_end->SetControllerTempBlock(false);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
// @script bool | SetAnalogStickActiveForMenus | Turn on/off analog simulation of digital buttons,
|
||
|
// so you can turn them off during certain menus that use analog for other things.
|
||
|
// @uparmopt 1 | on or off, 1 or 0
|
||
|
bool ScriptSetAnalogStickActiveForMenus(Script::CStruct *pParams, Script::CScript *pScript)
|
||
|
{
|
||
|
int active = 1;
|
||
|
pParams->GetInteger(NONAME,&active,false);
|
||
|
FrontEnd::Instance()->SetAnalogStickActiveForMenus((bool)active);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
} // namespace FrontEnd
|