I got a faster sine function that I want to use in AGS (gotta keep up the speed wherever I can), that I've already used internally in my plugin elsewhere, but I don't seem to be able to get AGS to recognize the floating point number as a floating point number. Here's the relevant code:
const char *ourScriptHeader =
"struct PALInternal {\r\n"
"///Polynomial Sine Approximation.\r\n"
"import static float FastSin (float x);// $AUTOCOMPLETESTATICONLY$\r\n"
"///Polynomial Cosine Approximation.\r\n"
"import static float FastCos (float x);// $AUTOCOMPLETESTATICONLY$\r\n"
"int dummy; //$AUTOCOMPLETEIGNORE$\r\n"
"};\r\n";
float FastSin(float x)
{
// wrap x within [0, TWO_PI)
const float a = x * twopi_inv;
x -= static_cast<int>(a) * twopi;
if (x < 0.0f)
x += twopi;
// 4 pieces of hills
if (x < halfpi)
return Hill(halfpi - x);
else if (x < PI)
return Hill(x - halfpi);
else if (x < 3.0f * halfpi)
return -Hill(3.0f * halfpi - x);
else
return -Hill(x - 3.0f * halfpi);
}
float FastCos(float x)
{
return FastSin(x + halfpi);
}
//later on....
engine->RegisterScriptFunction ("PALInternal::FastSin^1", FastSin);
engine->RegisterScriptFunction ("PALInternal::FastCos^1", FastCos);
I dunno what I have to return to get AGS to recognize this float as a float. I read through AGS' source code a bit earlier, and it... looked like floats might not actually be literally floats? What do I have to cast the result as in order for AGS to recognize it as a float? I've seen a couple of other plugins returning floats (like the AGSSteam stub), so it's gotta be possible somehow, but I'm not sure how. The code for the AGS float type is a bit intimidating.
(Also I learned today that you can declare enums in a plugin, so that's amazing)
EDIT: Whoops, sorry, I delved further into the code and managed to come up with a solution. Hopefully this can help other people as well:
//Add this at the top
#define SCRIPT_FLOAT(x) signed int __script_float##x
#define INIT_SCRIPT_FLOAT(x) float x; memcpy(&x, &__script_float##x, sizeof(float))
#define FLOAT_RETURN_TYPE signed int
#define RETURN_FLOAT(x) signed int __ret##x; memcpy(&__ret##x, &x, sizeof(float)); return __ret##x
//Wrap functions so that they return a "float".
FLOAT_RETURN_TYPE AGSFastSin (SCRIPT_FLOAT(x))
{
INIT_SCRIPT_FLOAT (x);
x = FastSin (x);
RETURN_FLOAT (x);
}
FLOAT_RETURN_TYPE AGSFastCos (SCRIPT_FLOAT(x))
{
INIT_SCRIPT_FLOAT (x);
x = FastSin (x+halfpi);
RETURN_FLOAT (x);
}
This is how I've done it in the past:
#define RETURN_AGS_FLOAT(x) return *((int32 *) &(x))
#define AGS_FLOAT(x) (*((float *) &(x)))
// Somewhere else:
int32 AGSFastSin(int32 x)
{
RETURN_ARGS_FLOAT(FastSin(AGS_FLOAT(x)));
}
There are however a few caveats. Note that int32 is defined in the plugin header as long; in AGS script all primitives are passed as longs. This assumes that a float takes up 32 bits on a 32-bit system; this will cause problems on 64-bit system probably so this is something to think about. It is hard to advise something here since it will depend on the target platform.
Btw, it might be a better idea to use static casts in de macros for C++, or not use macros at all ;).
Quote from: Wyz on Mon 21/12/2015 16:20:22
There are however a few caveats. Note that int32 is defined in the plugin header as long; in AGS script all primitives are passed as longs. This assumes that a float takes up 32 bits on a 32-bit system; this will cause problems on 64-bit system probably so this is something to think about. It is hard to advise something here since it will depend on the target platform.
Btw, it might be a better idea to use static casts in de macros for C++, or not use macros at all ;).
"Long" is 32-bit on all Windows systems, but has varied size on Linux systems.
Better change it to
typedef int32 int;
The script engine only lets 32-bit values through anyway.
The presence of "long" in the code is an old mistake, and we removed most of longs from engine code long (pun) ago.
Hmm I see; well that is not really a problem then on windows systems. It might be a good idea to switch to int32_t at some point actually if it must be 32-bit; support is about there these days. I'll keep this in mind for my plugins in the future. :)
I wasn't aware that this was an issue! 8-0
I will no go ahead and replace all of the floats in the AGSteam, AGSteamStub, and AGSGalaxy plugins. ;)
EDIT: Done! (This AGS2Client interface is making this process so much easier!)
Btw, you also should never use bool in any function you are registering with RegisterScriptFunction. I learned that the hard way.