Add variables with a getter / setter block

FossilOrigin-Name: cd2ac12a141a97a05449c82fbacc67cd3b6a172e66b7fb68bfd785b31d9776c0
This commit is contained in:
Jonathan Schleifer 2025-03-29 22:29:22 +00:00
parent a838f496b1
commit cc73f6ed78
12 changed files with 241 additions and 118 deletions

View file

@ -8,8 +8,15 @@
OF_APPLICATION_DELEGATE(Cube)
VARF(gamespeed, 10, 100, 1000, if (multiplayer()) gamespeed = 100);
VARP(minmillis, 0, 5, 1000);
static int gamespeed = 100;
VARB(gamespeed, 10, 1000, ^ { return gamespeed; }, ^ (int value) {
if (multiplayer())
gamespeed = 100;
else
gamespeed = value;
})
VARP(minmillis, 0, 5, 1000)
@implementation Cube
{

View file

@ -35,7 +35,11 @@ static int nextmonster, spawnremain, numkilled, monstertotal, mtimestart;
move: move];
}
VARF(skill, 1, 3, 10, conoutf(@"skill is now %d", skill));
static int skill = 3;
VARB(skill, 1, 10, ^ { return skill; }, ^ (int value) {
skill = value;
conoutf(@"skill is now %d", skill);
})
// for savegames
+ (void)restoreAll

View file

@ -2,4 +2,6 @@
@interface OFColor (Cube)
- (void)cube_setAsGLColor;
- (void)cube_setAsGLClearColor;
- (void)cube_setAsGLFogColor;
@end

View file

@ -6,7 +6,30 @@
- (void)cube_setAsGLColor
{
float red, green, blue, alpha;
[self getRed: &red green: &green blue: &blue alpha: &alpha];
glColor4f(red, green, blue, alpha);
}
- (void)cube_setAsGLClearColor
{
float red, green, blue, alpha;
[self getRed: &red green: &green blue: &blue alpha: &alpha];
glClearColor(red, green, blue, alpha);
}
- (void)cube_setAsGLFogColor
{
float color[4];
[self getRed: &color[0]
green: &color[1]
blue: &color[2]
alpha: &color[3]];
glFogfv(GL_FOG_COLOR, color);
}
@end

View file

@ -2,22 +2,6 @@
OF_ASSUME_NONNULL_BEGIN
#define VARP(name, min_, cur, max_) \
int name = cur; \
\
OF_CONSTRUCTOR() \
{ \
enqueueInit(^ { \
Variable *variable = [Variable \
variableWithName: @#name \
min: min_ \
max: max_ \
storage: &name \
function: NULL \
persisted: true]; \
Identifier.identifiers[@#name] = variable; \
}); \
}
#define VAR(name, min_, cur, max_) \
int name = cur; \
\
@ -29,14 +13,14 @@ OF_ASSUME_NONNULL_BEGIN
min: min_ \
max: max_ \
storage: &name \
function: NULL \
persisted: false]; \
persisted: false \
getter: NULL \
setter: NULL]; \
Identifier.identifiers[@#name] = variable; \
}); \
}
#define VARF(name, min_, cur, max_, body) \
static void var_##name(void); \
static int name = cur; \
#define VARP(name, min_, cur, max_) \
int name = cur; \
\
OF_CONSTRUCTOR() \
{ \
@ -46,21 +30,13 @@ OF_ASSUME_NONNULL_BEGIN
min: min_ \
max: max_ \
storage: &name \
function: var_##name \
persisted: false]; \
persisted: true \
getter: NULL \
setter: NULL]; \
Identifier.identifiers[@#name] = variable; \
}); \
} \
\
static void \
var_##name(void) \
{ \
body; \
}
#define VARFP(name, min_, cur, max_, body) \
static void var_##name(void); \
static int name = cur; \
\
#define VARB(name, min_, max_, getter_, setter_) \
OF_CONSTRUCTOR() \
{ \
enqueueInit(^ { \
@ -68,41 +44,53 @@ OF_ASSUME_NONNULL_BEGIN
variableWithName: @#name \
min: min_ \
max: max_ \
storage: &name \
function: var_##name \
persisted: true]; \
storage: NULL \
persisted: false \
getter: getter_ \
setter: setter_]; \
Identifier.identifiers[@#name] = variable; \
}); \
} \
\
static void \
var_##name(void) \
}
#define VARBP(name, min_, max_, getter_, setter_) \
OF_CONSTRUCTOR() \
{ \
body; \
enqueueInit(^ { \
Variable *variable = [Variable \
variableWithName: @#name \
min: min_ \
max: max_ \
storage: NULL \
persisted: true \
getter: getter_ \
setter: setter_]; \
Identifier.identifiers[@#name] = variable; \
}); \
}
@interface Variable: Identifier
@property (direct, readonly, nonatomic) int min, max;
@property (direct, readonly, nonatomic) int *storage;
@property (direct, readonly, nullable, nonatomic) void (*function)();
@property (readonly, nonatomic) bool persisted;
@property (direct, readonly, nullable, nonatomic) int (^getter)(void);
@property (direct, readonly, nullable, nonatomic) void (^setter)(int);
@property (direct, nonatomic) int value;
+ (instancetype)variableWithName: (OFString *)name
min: (int)min
max: (int)max
storage: (int *)storage
function: (void (*_Nullable)())function
persisted: (bool)persisted OF_DIRECT;
storage: (nullable int *)storage
persisted: (bool)persisted
getter: (int (^_Nullable)(void))getter
setter: (void (^_Nullable)(int))setter OF_DIRECT;
- (instancetype)initWithName: (OFString *)name OF_UNAVAILABLE;
- (instancetype)initWithName: (OFString *)name
min: (int)min
max: (int)max
storage: (int *)storage
function: (void (*_Nullable)())function
persisted: (bool)persisted OF_DESIGNATED_INITIALIZER
OF_DIRECT;
storage: (nullable int *)storage
persisted: (bool)persisted
getter: (int (^_Nullable)(void))getter
setter: (void (^_Nullable)(int))setter
OF_DESIGNATED_INITIALIZER OF_DIRECT;
- (void)printValue OF_DIRECT;
- (void)setValue: (int)value OF_DIRECT;
@end
OF_ASSUME_NONNULL_END

View file

@ -3,42 +3,50 @@
#include "cube.h"
@implementation Variable
{
int *_storage;
}
+ (instancetype)variableWithName: (OFString *)name
min: (int)min
max: (int)max
storage: (int *)storage
function: (void (*__cdecl)())function
persisted: (bool)persisted
getter: (int (^)(void))getter
setter: (void (^)(int))setter
{
return [[self alloc] initWithName: name
min: min
max: max
storage: storage
function: function
persisted: persisted];
persisted: persisted
getter: getter
setter: setter];
}
- (instancetype)initWithName: (OFString *)name
min: (int)min
max: (int)max
storage: (int *)storage
function: (void (*__cdecl)())function
persisted: (bool)persisted
getter: (int (^)(void))getter
setter: (void (^)(int))setter
{
self = [super initWithName: name];
_min = min;
_max = max;
_storage = storage;
_function = function;
_persisted = persisted;
_getter = [getter copy];
_setter = [setter copy];
return self;
}
- (void)printValue
{
conoutf(@"%@ = %d", self.name, *_storage);
conoutf(@"%@ = %d", self.name, self.value);
}
- (void)setValue: (int)value
@ -60,13 +68,22 @@
outOfRange = true;
}
if (outOfRange)
if (outOfRange) {
conoutf(@"valid range for %@ is %d..%d", self.name, _min, _max);
return;
}
if (_setter != NULL)
_setter(value);
else
*_storage = value;
}
if (_function != NULL)
// call trigger function if available
_function();
- (int)value
{
if (_getter != NULL)
return _getter();
else
return *_storage;
}
@end

View file

@ -42,26 +42,43 @@ allowedittoggle()
return allow;
}
VARF(rate, 0, 0, 25000,
static int rate = 0;
VARB(rate, 0, 25000, ^ { return rate; }, ^ (int value) {
rate = value;
if (clienthost && (!rate || rate > 1000))
enet_host_bandwidth_limit(clienthost, rate, rate));
enet_host_bandwidth_limit(clienthost, rate, rate);
})
void throttle();
static int throttle_interval = 5;
static int throttle_accel = 2;
static int throttle_decel = 2;
VARF(throttle_interval, 0, 5, 30, throttle());
VARF(throttle_accel, 0, 2, 32, throttle());
VARF(throttle_decel, 0, 2, 32, throttle());
void
throttle()
static void
throttle(void)
{
if (!clienthost || connecting)
return;
assert(ENET_PEER_PACKET_THROTTLE_SCALE == 32);
enet_peer_throttle_configure(clienthost->peers,
throttle_interval * 1000, throttle_accel, throttle_decel);
}
VARB(throttle_interval, 0, 30, ^ { return throttle_interval; }, ^ (int value) {
throttle_interval = value;
throttle();
})
VARB(throttle_accel, 0, 32, ^ { return throttle_accel; }, ^ (int value) {
throttle_accel = value;
throttle();
})
VARB(throttle_decel, 0, 32, ^ { return throttle_decel; }, ^ (int value) {
throttle_decel = value;
throttle();
})
static void
newname(OFString *name)
{

View file

@ -43,7 +43,7 @@ setvar(OFString *name, int i)
Variable *variable = Identifier.identifiers[name];
if ([variable isKindOfClass: Variable.class])
*variable.storage = i;
variable.value = i;
}
int
@ -52,7 +52,7 @@ getvar(OFString *name)
Variable *variable = Identifier.identifiers[name];
if ([variable isKindOfClass: Variable.class])
return *variable.storage;
return variable.value;
return 0;
}
@ -144,7 +144,7 @@ lookup(OFString *n)
if ([identifier isKindOfClass: Variable.class]) {
return [OFString stringWithFormat:
@"%d", *[identifier storage]];
@"%d", [identifier value]];
} else if ([identifier isKindOfClass: Alias.class])
return [identifier action];
@ -350,13 +350,12 @@ writecfg()
[stream writeString: @"\n"];
[Identifier.identifiers enumerateKeysAndObjectsUsingBlock:
^ (OFString *name, __kindof Identifier *identifier, bool *stop) {
if (![identifier isKindOfClass: Variable.class] ||
![identifier persisted])
^ (OFString *name, Variable *variable, bool *stop) {
if (![variable isKindOfClass: Variable.class] ||
!variable.persisted)
return;
[stream writeFormat:
@"%@ %d\n", identifier.name, *[identifier storage]];
[stream writeFormat: @"%@ %d\n", variable.name, variable.value];
}];
[stream writeString: @"\n"];

View file

@ -24,8 +24,12 @@ OF_CONSTRUCTOR()
static const struct {
OFString *name;
int *storage;
} vars[4] = { { @"selx", &sel.x }, { @"sely", &sel.y },
{ @"selxs", &sel.xs }, { @"selys", &sel.ys } };
} vars[4] = {
{ @"selx", &sel.x },
{ @"sely", &sel.y },
{ @"selxs", &sel.xs },
{ @"selys", &sel.ys }
};
for (size_t i = 0; i < 4; i++) {
Variable *variable = [Variable
@ -33,8 +37,9 @@ OF_CONSTRUCTOR()
min: 0
max: 4096
storage: vars[i].storage
function: NULL
persisted: false];
persisted: false
getter: NULL
setter: NULL];
Identifier.identifiers[vars[i].name] = variable;
}
});
@ -634,13 +639,16 @@ COMMAND(perlin, ARG_3INT, ^ (int scale, int seed, int psize) {
sel.ys--;
})
VARF(
fullbright, 0, 0, 1, if (fullbright) {
static int fullbright = 0;
VARB(fullbright, 0, 1, ^ { return fullbright; }, ^ (int value) {
if (fullbright) {
if (noteditmode())
return;
for (int i = 0; i < mipsize; i++)
world[i].r = world[i].g = world[i].b = 176;
});
}
});
COMMAND(edittag, ARG_1INT, ^ (int tag) {
EDITSELMP;

View file

@ -320,8 +320,11 @@ render_square(int wtex, float floor1, float floor2, float ceil1, float ceil2,
int wx1, wy1, wx2, wy2;
VAR(watersubdiv, 1, 4, 64);
VARF(waterlevel, -128, -128, 127,
if (!noteditmode()) hdr.waterlevel = waterlevel);
VARB(waterlevel, -128, 127, ^ { return hdr.waterlevel; }, ^ (int value) {
if (!noteditmode())
hdr.waterlevel = value;
})
static inline void
vertw(int v1, float v2, int v3, struct sqr *c, float t1, float t2, float t)

View file

@ -327,14 +327,17 @@ addstrip(int tex, int start, int n)
#undef gamma
VARFP(gamma, 30, 100, 300, {
float f = gamma / 100.0f;
static int gamma = 100;
VARBP(gamma, 30, 300, ^ { return gamma; }, ^ (int value) {
float f = value / 100.0f;
Uint16 ramp[256];
SDL_CalculateGammaRamp(f, ramp);
if (SDL_SetWindowGammaRamp(Cube.sharedInstance.window,
ramp, ramp, ramp) == -1) {
ramp, ramp, ramp) != -1)
gamma = value;
else {
conoutf(
@"Could not set gamma (card/driver doesn't support it?)");
conoutf(@"sdl: %s", SDL_GetError());
@ -362,7 +365,29 @@ VARP(fov, 10, 105, 120);
int xtraverts;
VAR(fog, 64, 180, 1024);
VAR(fogcolour, 0, 0x8099B3, 0xFFFFFF);
static OFColor *fogColor;
VARB(fogcolour, 0, 0xFFFFFF, (^ {
float red, green, blue;
if (fogColor == nil)
return 0x8099B3;
[fogColor getRed: &red green: &green blue: &blue alpha: NULL];
return ((unsigned char)(red * 255.0f) << 16) |
((unsigned char)(green * 255.0f) << 8) |
(unsigned char)(blue * 255.0f);
}), ^ (int value) {
unsigned char red = (value >> 16) & 0xFF;
unsigned char green = (value >> 8) & 0xFF;
unsigned char blue = value & 0xFF;
fogColor = [OFColor colorWithRed: red / 255.0f
green: green / 255.0f
blue: blue / 255.0f
alpha: 1.f];
})
VARP(hudgun, 0, 1, 1);
@ -422,11 +447,8 @@ gl_drawframe(int w, int h, float curfps)
glFogi(GL_FOG_START, (fog + 64) / 8);
glFogi(GL_FOG_END, fog);
float fogc[4] = { (fogcolour >> 16) / 256.0f,
((fogcolour >> 8) & 255) / 256.0f, (fogcolour & 255) / 256.0f,
1.0f };
glFogfv(GL_FOG_COLOR, fogc);
glClearColor(fogc[0], fogc[1], fogc[2], 1.0f);
[fogColor cube_setAsGLFogColor];
[fogColor cube_setAsGLClearColor];
if (underwater) {
fovy += (float)sin(lastmillis / 1000.0) * 2.0f;

View file

@ -2,6 +2,7 @@
#include "cube.h"
#import "OFColor+Cube.h"
#import "Player.h"
#import "Variable.h"
@ -66,19 +67,51 @@ render_particles(int time)
glDisable(GL_FOG);
struct parttype {
float r, g, b;
OFColor *color;
int gr, tex;
float sz;
} parttypes[] = {
{ 0.7f, 0.6f, 0.3f, 2, 3, 0.06f }, // yellow: sparks
{ 0.5f, 0.5f, 0.5f, 20, 7, 0.15f }, // grey: small smoke
{ 0.2f, 0.2f, 1.0f, 20, 3, 0.08f }, // blue: edit mode entities
{ 1.0f, 0.1f, 0.1f, 1, 7, 0.06f }, // red: blood spats
{ 1.0f, 0.8f, 0.8f, 20, 6, 1.2f }, // yellow: fireball1
{ 0.5f, 0.5f, 0.5f, 20, 7, 0.6f }, // grey: big smoke
{ 1.0f, 1.0f, 1.0f, 20, 8, 1.2f }, // blue: fireball2
{ 1.0f, 1.0f, 1.0f, 20, 9, 1.2f }, // green: fireball3
{ 1.0f, 0.1f, 0.1f, 0, 7, 0.2f }, // red: demotrack
/*
* Note: Some comments don't match the color. This was already
* the case in the original.
*/
// yellow: sparks
{ [OFColor colorWithRed: 0.7f
green: 0.6f
blue: 0.3f
alpha: 1.0f], 2, 3, 0.06f },
// grey: small smoke
{ OFColor.gray, 20, 7, 0.15f },
// blue: edit mode entities
{ [OFColor colorWithRed: 0.2f
green: 0.2f
blue: 1.0f
alpha: 1.0f], 20, 3, 0.08f },
// red: blood spats
{ [OFColor colorWithRed: 1.0f
green: 0.1f
blue: 0.1f
alpha: 1.0f], 1, 7, 0.06f },
// yellow: fireball1
{ [OFColor colorWithRed: 1.0f
green: 0.8f
blue: 0.8f
alpha: 1.0f], 20, 6, 1.2f },
// grey: big smoke
{ [OFColor colorWithRed: 0.5f
green: 0.5f
blue: 0.5f
alpha: 1.0f], 20, 7, 0.6f },
// blue: fireball2
{ OFColor.white, 20, 8, 1.2f },
// green: fireball3
{ OFColor.white, 20, 9, 1.2f },
// red: demotrack
{ [OFColor colorWithRed: 1.0f
green: 0.1f
blue: 0.1f
alpha: 1.0f], 0, 7, 0.2f }
};
int numrender = 0;
@ -89,7 +122,7 @@ render_particles(int time)
glBindTexture(GL_TEXTURE_2D, pt->tex);
glBegin(GL_QUADS);
glColor3d(pt->r, pt->g, pt->b);
[pt->color cube_setAsGLColor];
float sz = pt->sz * particlesize / 100.0f;
// perf varray?
glTexCoord2f(0.0, 1.0);