Skip to content

Instantly share code, notes, and snippets.

@julhe
Created June 25, 2023 22:17
Show Gist options
  • Save julhe/c532546aac290f67e3d34265bae5b95a to your computer and use it in GitHub Desktop.
Save julhe/c532546aac290f67e3d34265bae5b95a to your computer and use it in GitHub Desktop.
Example tweakable_value in raylib. Requieres stb_ds.h Doesn't work out of the box, needs a function that gets the current frame.
//TODO: support multiple files!
#include "raylib.h"
#include <string.h>
#include <stdlib.h>
#include "stb_ds.h"
static char* _MainFile_text;
static long _MainFile_lastModTime;
static unsigned long _MainFile_lastModTimeChecked; // Getting the mod time multiple times per frame is SLOW, so use the frame count to check if we did that already.
typedef struct {
int key;
float value;
} CachedFloatValue;
static CachedFloatValue* cachedFloatValues_HM = NULL;
static float TweakableValue_Float_findAndAdd(int tweakedValueLineIndex, float defaultValue) {
const char macroBeginString[] = "TWEAK_FLOAT(";
const size_t macroBeginLength = strlen(macroBeginString);
if (_MainFile_text != NULL) {
//NOTE: this is inefficient, since we scan the file EACH TIME for each value. The file should be scanned ONCE, but thats more work, and this is a one-time thing, so performance should be ok.
char* cursor = _MainFile_text;
size_t lineCount = 0;
while ((*cursor) != '\0') {
cursor++;
if (*cursor == '\n') {
lineCount++;
}
if (tweakedValueLineIndex - 1 == lineCount) {
char* macroBeginInFile = strstr(cursor, macroBeginString);
if (macroBeginInFile != NULL) {
char* valueBegin = &macroBeginInFile[macroBeginLength]; //advance by the length of macroBeginString, since we need the pure value to parse.
float parsedFloat = strtof(valueBegin, NULL); // parse string to float.
CachedFloatValue cfv = {
.value = parsedFloat,
.key = tweakedValueLineIndex };
hmputs(cachedFloatValues_HM, cfv);
return parsedFloat;
}
else {
TraceLog(LOG_ERROR, "Line was found, but macro coudn't be located. Maybe the line number changed?");
return defaultValue;
}
}
}
}
TraceLog(LOG_ERROR, "Unable to find line %d to parse tweak", tweakedValueLineIndex);
return defaultValue;
}
float TweakableValue_Float(const char* filePath, int tweakedValueLineIndex, float defaultValue) {
const unsigned long currentFrameCount = ; // <------------------ IMPORTANT: insert your custom framecounter here!
if (_MainFile_lastModTimeChecked != currentFrameCount || _MainFile_lastModTimeChecked == 0) {
_MainFile_lastModTimeChecked = currentFrameCount;
if (GetFileModTime(filePath) != _MainFile_lastModTime) {
if (_MainFile_text != NULL) {
MemFree(_MainFile_text);
_MainFile_text = NULL;
}
_MainFile_text = LoadFileText(filePath);
_MainFile_lastModTime = GetFileModTime(filePath);
if (cachedFloatValues_HM != NULL) {
hmfree(cachedFloatValues_HM); // reset the cached values.
}
}
}
CachedFloatValue* cachedFloatValue = hmgetp_null(cachedFloatValues_HM, tweakedValueLineIndex);
if (cachedFloatValue != NULL) {
return cachedFloatValue->value;
}
// value wasn't found, so lets parse!
return TweakableValue_Float_findAndAdd(tweakedValueLineIndex, defaultValue);
}
#ifndef TWEAKABLE_VALUE_H
#define TWEAKABLE_VALUE_H
inline float TweakableValue_Float(const char* filePath, size_t key, float defaultValue);
#ifdef LIVE_TWEAKING_DISABLED
#define TWEAK_FLOAT(defaultValue) (defaultValue)
#else
#define TWEAK_FLOAT(defaultValue) (TweakableValue_Float(__FILE__, __LINE__, defaultValue))
#endif
#endif // !TWEAKABLE_VALUE_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment