-
Notifications
You must be signed in to change notification settings - Fork 13
API changes in v4
Caution
All of the content below is subject to change until v4.0.0 is merged into the stable
branch.
Note
The following article assumes that your mod was made for YYToolkit v3.
If this is not the case, information below may not be entirely relevant.
The methods for accessing RValues have been reworked in order to encourage their usage instead of code that directly accesses the member variables.
Please refer to the table below for more information:
C++ Type | SDK v3.x.x | SDK v4.x.x |
---|---|---|
bool |
AsBool() |
ToBoolean() |
int32_t |
m_i32 |
ToInt32() |
int64_t |
m_i64 |
ToInt64() |
double |
AsReal() |
ToDouble() |
const char* |
N/A | ToCString() |
std::string |
AsString() |
ToString() |
std::u8string |
N/A | ToUTF8String() |
YYObjectBase* |
N/A | ToObject() |
CInstance* |
m_Object |
ToInstance() |
Behavior of the methods listed below has changed as well:
This method now evaluates "truthyness" according to the table below:
RValue Type | SDK v3.x.x | SDK v4.x.x |
---|---|---|
VALUE_REAL VALUE_BOOL
|
True if m_Real > 0.5 |
True if m_Real > 0.5 |
VALUE_STRING |
Console error, always false | True if string is "true" True if string contains numerical value > 0.5 |
VALUE_INT64 |
True if m_i64 > 0 |
True if m_i64 > 0 |
VALUE_OBJECT VALUE_PTR
|
True if m_Pointer != nullptr
|
True if m_Pointer != nullptr
|
VALUE_INT32 VALUE_REF
|
True if m_i32 > 0 |
True if m_i32 > 0 |
VALUE_ARRAY |
Console error, always false | Error: bool argument is array
|
VALUE_UNDEFINED |
Always false | Always false |
VALUE_UNSET |
Console error, always false | Error: bool argument is unset
|
This method's behavior has only changed for a few types:
RValue Type | SDK v3.x.x | SDK v4.x.x |
---|---|---|
VALUE_STRING |
Console error | Tries to get string numerical value If this fails, an error is thrown: unable to convert string to number
|
VALUE_OBJECT |
Console error | If instance: gets the instance ID If JS object: Tries to call valueOf
|
VALUE_UNSET |
Console error, always false | Error: REAL argument is unset
|
Invalid types | Console error, always false | Error: REAL argument incorrect type
|
Structs can now be created without the need for manually calling runner interface functions.
They can also be constructed from a std::map<std::string, RValue>
, where the key is the member name.
Instead of using the runner interface, the syntax is as follows:
RValue value = {
{ "real_value", 1.234 },
{ "string_value", "test" },
{ "array_value", { 1, "second element", 3.14 }}
};
To retrieve values from a struct, you can either use the GetInstanceMember function, the value["member_name"]
syntax, or the new ToMap
/ ToRefMap
functions.
Using the value["member_name"]
syntax is recommended for ease of reading. If a status code is required, use GetInstanceMember.
For looking up all members of a struct in one fell swoop, consider using the ToRefMap
function. If you wish to get copies of the variables, use the ToMap
function.
Warning
The ToRefMap
and ToMap
functions call EnumInstanceMembers behind the scenes, which can be slow for large structs.
See the Remarks section of EnumInstanceMembers for more information.
The kind assigned upon initialization of an RValue may differ from v3 to v4. This is due to numerous fixes being implemented to prevent type confusion from happening within the runner.
Please refer to the table below for more information:
Initialization | Kind (SDK v3.x.x) | Kind (SDK v4.x.x) |
---|---|---|
Default constructor | VALUE_UNDEFINED |
VALUE_UNDEFINED |
std::initializer_list<RValue> |
VALUE_ARRAY |
VALUE_ARRAY |
bool |
VALUE_BOOL |
VALUE_BOOL |
double float
|
VALUE_REAL |
VALUE_REAL |
Any other floating point type ( long double ) |
Error | VALUE_REAL |
CInstance* |
VALUE_OBJECT |
VALUE_OBJECT |
Any object that inherits from CInstanceBase ( YYObjectBase, CScriptRef, ... ) |
VALUE_BOOL |
VALUE_OBJECT |
Any other pointer type | VALUE_BOOL |
VALUE_PTR |
std::vector<RValue> |
Error | VALUE_ARRAY |
Array accesses can now be made via a vector. You can take a snapshot of the array (where all values are copied instead of being referenced) using the ToVector
function. If you wish to get pointers to the actual C++ array, use the ToArray
function (only possible on non-const instances of RValue
).
For example:
// Creates an array of [1, 2, 3, 4]
RValue my_array = { 1, 2, 3, 4 };
// Get the reference to the first element using the index operator.
RValue& first_element = my_array[0];
// Get the reference to the second element using the reference vector WITH bounds checking.
RValue& second_element = *my_array.ToRefVector().at(1);
// Get the reference to the third element using the raw array.
RValue& third_element = my_array.ToArray()[2];
// Get a COPY of the fourth element using the non-reference vector WITHOUT bounds checking.
RValue fourth_element_copy = my_array.ToVector()[3];
Implicit conversions to and from RValues have been improved to support easier conversion to and from C++ types.
In v3.4.3, the following code does not compile:
// Assign integral value to the RValue. Initialized as VALUE_INT32.
RValue my_rvalue = 5;
// Error: No suitable conversion from RValue to int32_t.
int32_t integer_value = my_rvalue;
// Error: No suitable conversion from std::string_view to std::string
std::string string_value = my_rvalue.AsString();
// All lines error. No suitable conversion exists for any of these types.
float float_value = my_rvalue;
double double_value = my_rvalue;
long double long_double_value = my_rvalue;
// All lines error. No suitable conversion exists for any of these types.
int int_value = my_rvalue;
long long_value = my_rvalue;
long long_long_value = my_rvalue;
In v4.0.0, the code compiles, but the RValue initialization behavior is a little different:
// Assign integral value to the RValue. Initialized as VALUE_INT64.
RValue my_rvalue = 5;
// OK. RValues can be casted to int32_t.
// The result is the same as when calling .ToInt32().
int32_t integer_value = my_rvalue;
// OK. ToString returns an std::string.
std::string string_value = my_rvalue.ToString();
// OK. All the floating-point types can be implicitely converted-to from an RValue.
float float_value = my_rvalue;
double double_value = my_rvalue;
long double long_double_value = my_rvalue;
// OK. All the integral types can be implicitely converted-to from an RValue.
int int_value = my_rvalue;
long long_value = my_rvalue;
long long_long_value = my_rvalue;
Many conversions are now able to be done without the need for calling a .ToXXX()
function.
For example, std::string
and std::u8string
can now be constructed directly from RValues.
In v3.4.3, one would encounter the following errors:
// Initialize a string RValue with "This is a C-style string!".
RValue string_rvalue = "This is a C-style string!";
// Error: Strings cannot be created implicitely.
std::string cpp_string_implicit = string_rvalue;
// Error: No constructor of std::string accepts an RValue.
std::string cpp_string_constructed = std::string(string_rvalue);
// Error: No explicit conversion exists from an RValue to a std::string.
std::string cpp_string_casted = static_cast<std::string>(string_rvalue);
On the other hand, v4.0.0 allows all but one of these ways of creating strings:
// Initialize a string RValue with "This is a C-style string!".
RValue string_rvalue = "This is a C-style string!";
// Error: Strings cannot be created implicitely.
std::string cpp_string_implicit = string_rvalue;
// OK. Strings can be constructed from an RValue.
std::string cpp_string_constructed = std::string(string_rvalue);
// OK. An RValue can be explicitely casted to a string.
std::string cpp_string_casted = static_cast<std::string>(string_rvalue);
The at
and operator[]
methods have been removed from CInstance
.
New methods can be used for a similar purpose as per the table below:
Old method name | New method name |
---|---|
operator[] |
GetRefMember |
at |
GetRefMember |
Further-more, a static method is now added to aid getting pointers to CInstance
objects from a GameMaker instance ID.
The syntax for that is as follows:
int32_t instance_id = 103'545; // Assume this is an ID found at runtime
CInstance* object = CInstance::FromInstanceID(instance_id);
All of the newly added methods, together with their compatibility with ISA, can be seen below:
Old method name | New method name | Requires ISA | const-compatible |
---|---|---|---|
GetMembers |
GetMembers |
✅ | ❌ |
operator[] |
GetMember GetRefMember
|
❌ | ✅ |
at |
GetMember GetRefMember
|
❌ | ✅ |
N/A | GetMemberCount |
❌ | ✅ |
N/A | FromInstanceID |
❌ | N/A |