Better haptics_debug output

This commit is contained in:
Marcus Minhorst 2025-09-07 21:44:06 -04:00 committed by Rachael Alexanderson
commit 449e34cc9e
2 changed files with 199 additions and 91 deletions

View file

@ -55,6 +55,17 @@
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
inline void _Rumble(const int);
inline void _RumbleDirect(int, int, double, double, double, double);
const FName * Joy_GetMapping(const FName);
const FName * Joy_GuessMapping(const FName);
const struct Haptics * Joy_GetRumble(FName);
void Joy_Rumble(const FName, const struct Haptics, double);
void RumbleDump();
void RumblePrint(const FName, const FName *, const struct Haptics *, double);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern bool AppActive;
@ -88,7 +99,8 @@ const FName HapticIntense = "INTENSE",
HapticMedium = "MEDIUM",
HapticLight = "LIGHT",
HapticSubtle = "SUBTLE",
HapticNone = "NONE";
HapticNone = "NONE",
HapticDirect = "DIRECT"; // except for this one
// PUBLIC DATA DEFINITIONS -------------------------------------------------
@ -206,7 +218,8 @@ const FName * Joy_GetMapping(const FName identifier)
auto id = soundEngine->FindSoundTentative(identifier.GetChars());
// loop a couple layers deep, trying to find a candidate
for (auto i = 0; i < MAX_TRY_DEPTH; i++) {
for (auto i = 0; i < MAX_TRY_DEPTH; i++)
{
if (!id.isvalid()) break;
actual = soundEngine->GetSoundName(id);
@ -243,7 +256,8 @@ const FName * Joy_GetMapping(const FName identifier)
bool replaced = actual != identifier && actual.IsValidName();
auto warn = [&identifier]() {
auto warn = [&identifier]()
{
if (RumbleMissed.Contains(identifier)) return;
RumbleMissed.Push(identifier);
Printf(DMSG_WARNING|PRINT_NONOTIFY, "Unknown rumble mapping '%s'\n", identifier.GetChars());
@ -293,7 +307,8 @@ const struct Haptics * Joy_GetRumble(FName identifier)
{
struct Haptics * rumble = RumbleDefinition.CheckKey(identifier);
if (!rumble && !RumbleMissed.Contains(identifier)) {
if (!rumble && !RumbleMissed.Contains(identifier))
{
RumbleMissed.Push(identifier);
Printf(DMSG_ERROR, TEXTCOLOR_RED "Rumble mapping not found! '%s'\n", identifier.GetChars());
return nullptr;
@ -312,6 +327,11 @@ const struct Haptics * Joy_GetRumble(FName identifier)
void Joy_AddRumbleType(const FName identifier, const struct Haptics data)
{
if (haptics_debug)
{
if (data.ticks == 0) Printf("rumble disabled %s\n", identifier.GetChars());
else Printf("rumble add %s T%d H%.1g L%.1g\n", identifier.GetChars(), data.ticks, data.high_frequency, data.low_frequency);
}
RumbleDefinition.Insert(identifier, data);
}
@ -326,6 +346,7 @@ void Joy_AddRumbleType(const FName identifier, const struct Haptics data)
void Joy_AddRumbleAlias(const FName alias, const FName actual)
{
if (haptics_debug) Printf("rumble alias %s -> %s\n", alias.GetChars(), actual.GetChars());
RumbleAlias.Insert(alias, actual);
}
@ -339,6 +360,7 @@ void Joy_AddRumbleAlias(const FName alias, const FName actual)
void Joy_MapRumbleType(const FName sound, const FName identifier)
{
if (haptics_debug) Printf("rumble map %s -> %s\n", sound.GetChars(), identifier.GetChars());
RumbleMapping.Insert(sound, identifier);
}
@ -352,6 +374,7 @@ void Joy_MapRumbleType(const FName sound, const FName identifier)
void Joy_ResetRumbleMapping()
{
if (haptics_debug) Printf("rumble reset\n");
RumbleMapping.Clear();
RumbleAlias.Clear();
RumbleMissed.Clear();
@ -373,6 +396,7 @@ void Joy_ResetRumbleMapping()
void Joy_ReadyRumbleMapping()
{
if (haptics_debug) Printf("rumble ready\n");
TArray<FName> found;
TMapIterator<FName, FName> it(RumbleAlias);
TMap<FName, FName>::Pair* pair;
@ -405,11 +429,13 @@ void Joy_ReadyRumbleMapping()
break;
}
while (found.size() > 0) {
while (found.size() > 0)
{
RumbleAlias.Remove(found.Last());
found.Pop();
}
}
if (haptics_debug) RumbleDump();
}
//==========================================================================
@ -420,7 +446,8 @@ void Joy_ReadyRumbleMapping()
//
//==========================================================================
void Joy_RumbleTick() {
void Joy_RumbleTick()
{
if (!Haptics.enabled) return;
// pause detection
@ -507,14 +534,6 @@ void Joy_RumbleTick() {
Haptics.dirty = false;
}
//==========================================================================
//
// Joy_Rumble
//
// Requests haptic feedback. Attenuation of >=1 results in no-op.
//
//==========================================================================
void Joy_Rumble(const FName source, const struct Haptics data, double attenuation)
{
if (!Haptics.enabled) return;
@ -523,9 +542,6 @@ void Joy_Rumble(const FName source, const struct Haptics data, double attenuatio
float strength = 1 - (attenuation < 0? 0: attenuation);
if (haptics_debug)
Printf("r %s * %g\n", source.GetChars(), strength);
// this will overwrite stuff from same source mapping (weapons/pistol not W_BULLET)
Haptics.channels.Insert(source, {
Haptics.tic + data.ticks + 1,
@ -538,6 +554,31 @@ void Joy_Rumble(const FName source, const struct Haptics data, double attenuatio
Haptics.dirty = true;
}
//==========================================================================
//
// Joy_Rumble
//
// Requests haptic feedback based on provided data. Attenuation of >=1 results in no-op.
//
//==========================================================================
void Joy_Rumble(
const FName source,
int tic_count,
double high_frequency,
double low_frequency,
double left_trigger,
double right_trigger,
double attenuation
)
{
const struct Haptics rumble {tic_count, high_frequency, low_frequency, left_trigger, right_trigger};
if (haptics_debug) RumblePrint(source, &HapticDirect, &rumble, attenuation);
Joy_Rumble(source, rumble, attenuation);
}
//==========================================================================
//
// Joy_Rumble
@ -548,15 +589,16 @@ void Joy_Rumble(const FName source, const struct Haptics data, double attenuatio
void Joy_Rumble(const FName identifier, double attenuation)
{
const FName * mapping = Joy_GetMapping(identifier);
const FName * mapping;
const struct Haptics * rumble;
if (mapping == nullptr) return;
rumble = (nullptr != (mapping = Joy_GetMapping(identifier)))
? Joy_GetRumble(*mapping)
: nullptr;
const struct Haptics * rumble = Joy_GetRumble(*mapping);
if (haptics_debug) RumblePrint(identifier, mapping, rumble, attenuation);
if (rumble == nullptr) return;
Joy_Rumble(identifier, * rumble, attenuation);
if (rumble) Joy_Rumble(identifier, * rumble, attenuation);
}
//==========================================================================
@ -573,69 +615,12 @@ CCMD (rumble)
int ticks;
double high_freq, low_freq, left_trig, right_trig;
switch (count) {
switch (count)
{
case 0: {
TArray<FString> unused, used;
{
TMapIterator<FName, struct Haptics> it(RumbleDefinition);
TMap<FName, struct Haptics>::Pair* pair;
while (it.NextPair(pair)) unused.AddUnique(pair->Key.GetChars());
}
{
TMapIterator<FName, FName> it(RumbleAlias);
TMap<FName, FName>::Pair* pair;
while (it.NextPair(pair)) unused.AddUnique(pair->Key.GetChars());
}
{
TMapIterator<FName, FName> it(RumbleAlias);
TMap<FName, FName>::Pair* pair;
while (it.NextPair(pair))
{
if (unused.Contains(pair->Value.GetChars()))
unused.Delete(unused.Find(pair->Value.GetChars()));
}
}
{
TMapIterator<FName, FName> it(RumbleMapping);
TMap<FName, FName>::Pair* pair;
Printf("Mappings:\n");
while (it.NextPair(pair)) {
used.AddUnique(pair->Value.GetChars());
if (unused.Contains(pair->Value.GetChars()))
unused.Delete(unused.Find(pair->Value.GetChars()));
auto mapping = Joy_GetRumble(pair->Value);
FString key = pair->Key.GetChars();
FString val = pair->Value.GetChars();
key.ToLower();
val.ToUpper();
FString a = FStringf("'%s'\t->\t'%s'", key.GetChars(), val.GetChars());
FString b = mapping
? FStringf(
"{ %d %g %g %g %g }",
mapping->ticks,
mapping->high_frequency,
mapping->low_frequency,
mapping->left_trigger,
mapping->right_trigger
) : "[undefined]";
Printf("\t%s\t->\t%s\n", a.GetChars(), b.GetChars());
}
}
if (unused.Size() > 0)
{
Printf("Unused:\n");
for (auto i:unused)
{
FString s = i.GetChars();
s.ToUpper();
Printf("\t'%s'\n", s.GetChars());
}
}
RumbleDump();
Printf("Testing rumble for 5s\n");
Joy_Rumble("", {5 * TICRATE, 1.0, 1.0, 1.0, 1.0});
Joy_Rumble("", 5 * TICRATE, 1.0, 1.0, 1.0, 1.0);
}
break;
case 1:
@ -643,18 +628,20 @@ CCMD (rumble)
Joy_Rumble(argv[1]);
break;
case 5:
try {
try
{
ticks = std::stoi(argv[1], nullptr, 10);
high_freq = static_cast <double> (std::stof(argv[2], nullptr));
low_freq = static_cast <double> (std::stof(argv[3], nullptr));
left_trig = static_cast <double> (std::stof(argv[4], nullptr));
right_trig = static_cast <double> (std::stof(argv[5], nullptr));
} catch (...) {
} catch (...)
{
Printf("Failed to parse args\n");
return;
}
Printf("testing rumble with params (%d, %f, %f, %f, %f)\n", ticks, high_freq, low_freq, left_trig, right_trig);
Joy_Rumble("", {ticks, high_freq, low_freq, left_trig, right_trig});
Joy_Rumble("", ticks, high_freq, low_freq, left_trig, right_trig);
break;
default:
Printf(
@ -675,7 +662,8 @@ CCMD (rumble)
//
//==========================================================================
void _Rumble(const int identifier) {
inline void _Rumble(const int identifier)
{
Joy_Rumble(ENamedName(identifier));
}
@ -703,8 +691,23 @@ DEFINE_ACTION_FUNCTION_NATIVE(DHaptics, Rumble, _Rumble)
//
//==========================================================================
void _RumbleDirect(int source, int tic_count, double high_frequency, double low_frequency, double left_trigger, double right_trigger) {
Joy_Rumble(ENamedName(source), {tic_count, high_frequency, low_frequency, left_trigger, right_trigger});
inline void _RumbleDirect(
int source,
int tic_count,
double high_frequency,
double low_frequency,
double left_trigger,
double right_trigger
)
{
Joy_Rumble(
ENamedName(source),
tic_count,
high_frequency,
low_frequency,
left_trigger,
right_trigger
);
}
//==========================================================================
@ -727,3 +730,103 @@ DEFINE_ACTION_FUNCTION_NATIVE(DHaptics, RumbleDirect, _RumbleDirect)
_RumbleDirect(source, tic_count, high_frequency, low_frequency, left_trigger, right_trigger);
return 0;
}
//==========================================================================
//
// RumblePrint
//
// Debug printout
//
//==========================================================================
void RumblePrint(const FName identifier, const FName * mapping, const struct Haptics * rumble, double attenuation)
{
const char * color;
FString text = FStringf("r '%s'", identifier.GetChars());
if (!mapping)
{ color = TEXTCOLOR_ORANGE; text.AppendFormat(" -"); }
else
{
text.AppendFormat(" %s", mapping->GetChars());
if (!rumble)
{ color = TEXTCOLOR_RED; text.AppendFormat(" -"); }
else if (rumble->ticks == 0)
{ color = TEXTCOLOR_BLACK; text.AppendFormat(" 0"); }
else
{ color = TEXTCOLOR_CYAN; text.AppendFormat(" T%d H%.1g L%.1g A%.1g",
rumble->ticks, rumble->high_frequency, rumble->low_frequency, attenuation); }
}
Printf("%s%s\n", color, text.GetChars());
}
//==========================================================================
//
// RumbleDump
//
// Debug printout
//
//==========================================================================
void RumbleDump()
{
TArray<FString> unused, used;
{
TMapIterator<FName, struct Haptics> it(RumbleDefinition);
TMap<FName, struct Haptics>::Pair* pair;
while (it.NextPair(pair)) unused.AddUnique(pair->Key.GetChars());
}
{
TMapIterator<FName, FName> it(RumbleAlias);
TMap<FName, FName>::Pair* pair;
while (it.NextPair(pair)) unused.AddUnique(pair->Key.GetChars());
}
{
TMapIterator<FName, FName> it(RumbleAlias);
TMap<FName, FName>::Pair* pair;
while (it.NextPair(pair))
{
if (unused.Contains(pair->Value.GetChars()))
unused.Delete(unused.Find(pair->Value.GetChars()));
}
}
{
TMapIterator<FName, FName> it(RumbleMapping);
TMap<FName, FName>::Pair* pair;
Printf("Mappings:\n");
while (it.NextPair(pair))
{
used.AddUnique(pair->Value.GetChars());
if (unused.Contains(pair->Value.GetChars()))
unused.Delete(unused.Find(pair->Value.GetChars()));
auto mapping = Joy_GetRumble(pair->Value);
FString key = pair->Key.GetChars();
FString val = pair->Value.GetChars();
key.ToLower();
val.ToUpper();
FString a = FStringf("'%s'\t->\t'%s'", key.GetChars(), val.GetChars());
FString b = mapping
? FStringf(
"{ %d %g %g %g %g }",
mapping->ticks,
mapping->high_frequency,
mapping->low_frequency,
mapping->left_trigger,
mapping->right_trigger
) : "[undefined]";
Printf("\t%s\t->\t%s\n", a.GetChars(), b.GetChars());
}
}
if (unused.Size() > 0)
{
Printf("Unused:\n");
for (auto i:unused)
{
FString s = i.GetChars();
s.ToUpper();
Printf("\t'%s'\n", s.GetChars());
}
}
}