Files
GTASource/game/system/MappingManager.h

408 lines
13 KiB
C
Raw Normal View History

2025-02-23 17:40:52 +08:00
//
// system/MappingManager.h
//
// Copyright (C) 1999-2014 Rockstar Games. All Rights Reserved.
//
#ifndef SYSTEM_MAPPINGMANAGER_H
#define SYSTEM_MAPPINGMANAGER_H
// Rage Headers.
#include "input/mapper.h"
#if ENABLE_INPUT_COMBOS
// Game Headers.
#include "system/MappingManagerData.h"
#include "system/control_mapping.h"
namespace rage
{
RAGE_DECLARE_CHANNEL(MappingManager)
#define mapmgrAssert(cond) RAGE_ASSERT(MappingManager,cond)
#define mapmgrAssertf(cond,fmt,...) RAGE_ASSERTF(MappingManager,cond,fmt,##__VA_ARGS__)
#define mapmgrFatalAssertf(cond,fmt,...) RAGE_FATALASSERTF(MappingManager,cond,fmt,##__VA_ARGS__)
#define mapmgrVerify(cond) RAGE_VERIFY(MappingManager,cond)
#define mapmgrVerifyf(cond,fmt,...) RAGE_VERIFYF(MappingManager,cond,fmt,##__VA_ARGS__)
#define mapmgrErrorf(fmt,...) RAGE_ERRORF(MappingManager,fmt,##__VA_ARGS__)
#define mapmgrWarningf(fmt,...) RAGE_WARNINGF(MappingManager,fmt,##__VA_ARGS__)
#define mapmgrDisplayf(fmt,...) RAGE_DISPLAYF(MappingManager,fmt,##__VA_ARGS__)
#define mapmgrDebugf1(fmt,...) RAGE_DEBUGF1(MappingManager,fmt,##__VA_ARGS__)
#define mapmgrDebugf2(fmt,...) RAGE_DEBUGF2(MappingManager,fmt,##__VA_ARGS__)
#define mapmgrDebugf3(fmt,...) RAGE_DEBUGF3(MappingManager,fmt,##__VA_ARGS__)
#define mapmgrLogf(severity,fmt,...) RAGE_LOGF(MappingManager,severity,fmt,##__VA_ARGS__)
class CMappingManager : public datBase
{
public:
// PURPOSE: Constructor.
CMappingManager();
// PURPOSE: Destructor.
virtual ~CMappingManager();
// PURPOSE: Loads a mapping file.
// PARAMS: path - the path of the file to load.
void LoadMappingFile(const char* path);
// PURPOSE: Unloads a mapping file.
// PARAMS: path - the path of the file to be unloaded.
// NOTES: This is identical to RemoveMappingFile() except this function updates the bank
// widgets. This is generally what you want unless the bank widgets are going to
// be updated later.
void UnloadMappingFile(const char* path);
// PURPOSE: Update mappings.
// PARAMS: timeMS - the time in MS.
// NOTES: This needs to be called once per frame.
void Update(u32 timeMS);
// PURPOSE: Retrieves an input's name as a c-string.
// PARAMS: input - the input to get the name for.
// RETURNS: the string name of the input (this is the same as the enum name).
static const char* GetInputName(InputType input);
#if RSG_BANK
// PURPOSE: Initializes the bank widgets.
// NOTES: This function keeps a pointer to bank to update as files are loaded and unloaded.
void InitWidgets(bkBank& bank);
#endif // RSG_BANK
private:
// PURPOSE: All the information regarding a combo track.
// NOTES: A combo track is what one input source (such as a specific pad button) is doing
// during the combo.
struct ComboTrack
{
// PURPOSE: The state a step test can be in.
enum TestState
{
// PURPOSE: The test has not been started yet.
// NOTES: An example of this use is if we are looking for a press but the button was
// already down when we started.
NOT_STARTED,
// PURPOSE: The test has started.
STARTED,
// PURPOSE: The test is an ongoing test and it is in progress.
// NOTES: An example of its use is looking for a key to remain up. Whilst it is up the
// state is in progress. If it goes down then we fail the test. At the end of a
// step IN_PROGRESS is treated as PASSED.
IN_PROGRESS,
// PURPOSE: The test was passed.
PASSED,
// PURPOSE: The test was failed.
FAILED,
};
// PURPOSE: Constructor.
ComboTrack();
// PURPOSE: Updates a combo track state.
// PARAMS: The step the track should use.
void Update(u32 step);
// PURPOSE: The input source.
ioSource m_Source;
// PURPOSE: The step state.
TestState m_StepState;
// PURPOSE: The steps of the combo.
atArray<ControlInput::Trigger> m_Steps;
#if RSG_BANK
// PURPOSE: Get the test state color.
// PARAMS: state - the state to get the color for.
// RETURNS: the requested color.
static Color32 GetTestStateColor(TestState state);
// PURPOSE: Gets the test state c-string.
// PARAMS: state - the state to get the string for.
// RETURNS: the requested c-string.
static const char* GetTestStateStr(TestState state);
#endif // RSG_BANK
};
// PURPOSE: All the information for a combo mapping.
struct ComboMapping
{
// PURPOSE: Constructor.
ComboMapping();
// PURPOSE: Represents an invalid track id.
const static u32 INVALID_TRACK_ID = 0xffffffff;
// PURPOSE: Updates the mapping.
// NOTES: Must be called once per frame.
void Update();
// PURPOSE: Restarts the combo.
void Restart();
// PURPOSE: Progress the combo onto the next step.
// NOTES: At the end of the combo, this will mark the combo as completed.
void ProgressStep();
// PURPOSE: Loads the combo information.
// PARAMS: mapping - the parser structure containing the mapping information.
void Load(const ControlInput::ComboMapping &mapping);
// PURPOSE: The combo running states.
enum RunningState
{
// PURPOSE: The combo has stopped as it was failed It is waiting to be restarted.
FAILED_WAITING,
// PURPOSE: The combo is running.
RUNNING,
// PURPOSE: The combo was completed successfully. It is waiting to be restarted.
SUCCESS_WAITING,
};
#if RSG_BANK
// PURPOSE: Gets a string representing a combo running state.
// NOTES: state - the state to get a string name of.
static const char* GetRunningStateStr(RunningState state);
// PURPOSE: Gets a color representing the combo running state.
// NOTES: state - the state to get a color for.
static Color32 GetRunningStateColor(RunningState state);
#endif // RSG_BANK
// PURPOSE: The input this combo is mapped to.
InputType m_Input;
// PURPOSE: The current step this combo is on.
u32 m_CurrentStep;
// PURPOSE: The time the step was started.
u32 m_StepStartTime;
// PURPOSE: The duration of the combo steps.
u32 m_TimeDelta;
// PURPOSE: The combo mapping running state.
RunningState m_RunningState;
// PURPOSE: The tracks of the combo.
// NOTES: A combo track is what one input source (such as a specific pad button) is
// doing during the combo.
atArray<ComboTrack> m_Tracks;
};
// PURPOSE: A combo group.
// NOTES: A combo group contains a group of mutually exclusive combo mappings. Only one
// combo in the group can fire/succeed at a time. This is based on the order of the
// mappings with the mappings at the top taking priority. If a combo passes, it will
// wait if there are any higher combos running. If no higher combos are running
// then the combo mapping will trigger the input. The whole sequence is then restarted.
class ComboGroup
{
public:
// PURPOSE: Constructor.
ComboGroup();
// PURPOSE: Represents an invalid combo mapping id.
const static u32 INVALID_COMBO_MAPPING_ID = 0xffffffff;
// PURPOSE: Retrieves the group ID.
atHashWithStringNotFinal GetId() const;
// PURPOSE: Updates a mapping group.
// RETURNS: The mapping id that has completed or INVALID_COMBO_MAPPING_ID if not combo has completed.
u32 Update();
// PURPOSE: Restarts a group.
void Restart();
// PURPOSE: Retrieves an input associated with a combo id.
// PARAMS: comboId - the combo id to retrieve the input from.
// RETURNS: the mapped input or UNDEFINED_INPUT if comboId is not valid.
InputType GetComboInput(u32 comboId) const;
// PURPOSE: Tries to retrieve a source for a combo id.
// PARAMS: comboId - the combo id to try and retrieve the source from.
// RETURNS: the source input or ioSource::UNKNOWN_SOURCE if it could not be extracted.
// NOTES: A source can only be retrieved if the combo only uses one source or only one
// source is used (down/pressed) for the final step of the combo.
ioSource GetComboSource(u32 comboId) const;
// PURPOSE: Loads a mapping group.
// PARAMS: id - the id of the group.
// mappingData - the parser group mapping data to be loaded.
void Load(atHashWithStringNotFinal id, const ControlInput::MappingData& mappingData);
// PURPOSE: Unloads the group data.
void Unload();
#if RSG_BANK
// PURPOSE: Initializes the bank widgets.
void InitWidgets(bkBank& bank);
// PURPOSE: Updates debug info.
void UpdateDebugInfo();
// PURPOSE: Draws a combo progress to the screen.
// PARAMS: comboId - the comboId to draw.
void DebugDrawCombo(u32 comboId) const;
// PURPOSE: Draws the state of the whole group to the screen.
void DebugDrawComboList() const;
#endif // RSG_BANK
private:
// These is used to track down if a combo waits too long as the result of higher priority combos
// cycling in progress.
#if RSG_ASSERT
// PURPOSE: The time a combo is passed as started waiting (PASSED_WAITING).
u32 m_WaitStartTime;
// PURPOSE: The duration the passed combo (PASSED_WAITING) should wait for before asserting.
u32 m_WaitDuration;
#endif // RSG_ASSERT
#if RSG_BANK
// PURPOSE: The id of the mapping to display debug info for.
// NOTES: 0 represents all mappings (show the whole group). As a result, this id is offset by 1.
int m_DebugMapping;
#endif // RSG_BANK
// PURPOSE: The id of the group.
atHashWithStringNotFinal m_Id;
// PURPOSE: The combo's in the group.
atArray<ComboMapping> m_ComboMappings;
};
// PURPOSE: Represents an invalid groups id.
const static u32 INVALID_GROUP_ID = 0;
// PURPOSE: Internal function to remove a mapping.
// PARAMS: path - the path of the mapping to be removed.
// NOTES: UnloadMappingFile() calls this but UnloadMappingFile() also updates the bank widgets whereas this function
// does not. Only call this if they are going to be updated later.
void RemoveMappingFile(const char* path);
// PURPOSE: Converts a parser InputSource to an rage ioSource.
// NOTES: inputSource - the source to be converted.
// RETURNS: The converted ioSource if possible or ioSource::UNKNOWN_SOURCE if it could not be converted.
static ioSource ConvertSource(const ControlInput::InputSource& inputSource);
// PURPOSE: Converts a file path to an id.
// PARAMS: path - the path to be converted.
// RETURNS: The path as an id.
// NOTES: This function does some path cleaning (such as changing \ to /). This function was created as the parser
// adds the path strings to the hash string table but it also cleans up the path. This causes the two strings
// 'x:\test.meta' and 'x:/test.meta' to have the same hash but different strings causing an assert.
//
// This function calls the same function that the parser does to do this even though its not really necessary.
static atHashWithStringNotFinal GetPathHash(const char* path);
// PURPOSE: The inputs that are used for the mappings.
atRangeArray<ioValue, MAX_INPUTS> m_Inputs;
// PURPOSE: Update id.
u8 m_UpdateId;
// PURPOSE: The different mapping groups.
// NOTES: Only one mapping in a mapping group can trigger at a time.
atArray<ComboGroup> m_MappingGroups;
#if RSG_BANK
// PURPOSE: Updates the debug display.
void UpdateDebugDisplay();
// PURPOSE: Rag callback to load a mapping file.
void DebugLoadMappingfile();
// PURPOSE: Rebuilds the rag widgets.
void RebuildWidgets();
// PURPOSE: Gets a Trigger as a c-string.
// PARAMS: trigger - the trigger to get the c-string name of.
// RETURNS: the requested c-string.
// NOTES: The string returned is the enum as a string.
static const char* GetTriggerName(ControlInput::Trigger trigger);
// PURPOSE: On screen debugging enabled state.
bool m_EnableDebugging;
// PURPOSE: The group to be display debug info for.
int m_DebugGroup;
// PURPOSE: A pointer to the bank group created containing all the debug widgets.
// NOTES: This is kept so we can remove it when the mappings are updated.
bkGroup* m_BankGroup;
// PURPOSE: A pointer to the parent bank which we use to add the rag widgets to.
// NOTES: This is kept so we can update the widgets.
bkBank* m_BankParent;
// PURPOSE: A path to a file to be loaded from the bank widget.
char m_FilePath[RAGE_MAX_PATH];
#endif // RSG_BANK
};
inline CMappingManager::CMappingManager()
: m_UpdateId(0)
#if RSG_BANK
, m_EnableDebugging(false)
, m_DebugGroup(0)
, m_BankGroup(NULL)
, m_BankParent(NULL)
#endif // RSG_BANK
{
BANK_ONLY(m_FilePath[0] = '\0');
}
inline CMappingManager::~CMappingManager()
{}
inline void CMappingManager::UnloadMappingFile(const char* path)
{
RemoveMappingFile(path);
BANK_ONLY(RebuildWidgets());
}
inline CMappingManager::ComboTrack::ComboTrack()
: m_Source()
, m_StepState(NOT_STARTED)
{
}
inline CMappingManager::ComboMapping::ComboMapping()
: m_Input(UNDEFINED_INPUT)
, m_TimeDelta(0u)
{
Restart();
}
inline CMappingManager::ComboGroup::ComboGroup()
: m_Id(0u)
#if RSG_ASSERT
, m_WaitStartTime(0u)
, m_WaitDuration(0u)
#endif // RSG_ASSERT
#if RSG_BANK
, m_DebugMapping(0)
#endif // RSG_BANK
{
}
inline atHashWithStringNotFinal CMappingManager::ComboGroup::GetId() const
{
return m_Id;
}
}
#endif // ENABLE_INPUT_COMBOS
#endif // SYSTEM_MAPPINGMANAGER_H