• Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

Question - IDE Macros help

J

Jerek

Guest
I just upgraded to GMS 2 and love it so far. However, I'm a bit confused as to what happened to macros as they are no longer in the resource tree. Any idea where they are or if it's an obsolete feature now?
 

ZeDuval

Member
No, the handling of macros just became way, way, sooo way better(yes, hating the old Macro-window from the bottom of my heart). You can now define macros inline like it was already possible with enums. The syntax:
Code:
#macro Winw window_get_width()
No equal sign and no semicolon at the end. I recommend creating one script like initialize_all_the_things(), to define all macros, enums and global.variables in there and call that before everything else(though this only affects the globals).
 
P

psyke

Guest
I'm pretty sure you don't need to call the script, macros are pre-compiled.
Just make one script and put all your macros there (don't need to call the script).
 

Hyomoto

Member
Huh, I had a suspicion about macros working like that but I assumed you'd still have to call the script. I'll have to test that. I hate to be a non-believer but it raises some questions about what happens if you macro a variable before it is declared. how does it know?
 

mMcFab

Member
Huh, I had a suspicion about macros working like that but I assumed you'd still have to call the script. I'll have to test that. I hate to be a non-believer but it raises some questions about what happens if you macro a variable before it is declared. how does it know?
I can be certain you don't need to call the script, since I have an enum/macro script that I never call and it works fine.
I did a quick test. This code works fine too:
Code:
#macro testMacro test

var test = "Test";

show_debug_message(testMacro);
I assume macros work kind of like a pre-compile find and replace, so it doesn't really matter where they are declared
 

ZeDuval

Member
I can be certain you don't need to call the script, since I have an enum/macro script that I never call and it works fine.
I did a quick test. This code works fine too:
Code:
#macro testMacro test

var test = "Test";

show_debug_message(testMacro);
I assume macros work kind of like a pre-compile find and replace, so it doesn't really matter where they are declared
That's exactly how they work. When not referencing a local var like in your example, but referencing an instance- or an global var, you don't even need to "initialize" it the first time with it's original name, but use the macro right from the start. However, if you reference a var(and not a number, string, expression or function) it needs to be initialized before it's first usage just like with vars using them "normally".

Bonus round:
If you'd want to have all your macros, enums and globals in one place(script) and have it so that you don't need to call it even once in the beginning, do it like this:
Code:
/// initialize_stuff()

// this is where the magic happens
gml_pragma("global","initialize_stuff()");

// init_Enums
enum day{
    monday, tuesday, nextday, otherday
}

// init_Constants
#macro myName global.__myName
#macro releaseYear 2016

// init_Globals
global.__debugMode = true;
myName = "SlimShady";
Credit for discovering this neat, little trick goes to @gnysek
 

mMcFab

Member
That's exactly how they work. When not referencing a local var like in your example, but referencing an instance- or an global var, you don't even need to "initialize" it the first time with it's original name, but use the macro right from the start. However, if you reference a var(and not a number, string, expression or function) it needs to be initialized before it's first usage just like with vars using them "normally".

Bonus round:
If you'd want to have all your macros, enums and globals in one place(script) and have it so that you don't need to call it even once in the beginning, do it like this:
Code:
/// initialize_stuff()

// this is where the magic happens
gml_pragma("global","initialize_stuff()");

// init_Enums
enum day{
    monday, tuesday, nextday, otherday
}

// init_Constants
#macro myName global.__myName
#macro releaseYear 2016

// init_Globals
global.__debugMode = true;
myName = "SlimShady";
Credit for discovering this neat, little trick goes to @gnysek
Oh, wow! That's really neat. I wonder why this pragma functionality wasn't documented! I know I'm saying goodbye to manual init now!
 

ZeDuval

Member
Oh, wow! That's really neat. I wonder why this pragma functionality wasn't documented! I know I'm saying goodbye to manual init now!
Exactly my thoughts! :D As to why it's not documented, I don't know, but it will be in the future in one way or another... ;)
And it doesn't stop at global vars, I think you can also already create datastructures, for example.

PS: Works with GM1.4 and GM2!
 

Hyomoto

Member
Exactly my thoughts! :D As to why it's not documented, I don't know, but it will be in the future in one way or another... ;)
And it doesn't stop at global vars, I think you can also already create datastructures, for example.

PS: Works with GM1.4 and GM2!
So this gml_pragma script does what exactly? I'm only guessing from your example, and it seems this would be incredibly useful, but is this a way of running a script at game start -without- relying on the room creation code? I mean, that is literally on my wishlist so I'd be psyched to know that exists. That said, what are the arguments? The second one seems self-explanatory, but some of what you have there is confusing. I figured it was for scope, but in your myName example, you macro __myName but declare myName. Is that a typo on your part?
 

ZeDuval

Member
It does exactly what you were wishing for. Having the gml_pragma function with above arguments inside the script tells GM to call the script at gamestart, or even before I think - without relying on the room creation code. However, you cannot create your first object-instance because at that point there's not even a room loaded to put that instance in. That still has to be done in the room creation code, or manually placed inside the room.

I make the macro myName be a reference to the global variable global.__myName, but in order to, for example, draw it to the screen, just like a global variable that's not referenced by a macro, I need to give it a value.

Code:
// make myName a reference to the global variable
#macro myName global.__myName

// assign a value to the global variable
// both following lines are the same
myName = "SlimShady" // using the macro
global.__myName = "SlimShady" // or the variable itself

// without doing this, the following would cause an error when used in some draw event
draw_text(0,0,myName);
 

Hyomoto

Member
Ah, I think I see now. You are setting a macro myName to global.__myName, then you set global.__myName by invoking myName. That makes more sense. Hmm. It looks like I'll be rewriting my engine init code one day to incorporate this.

Still what was the first argument, "global" for?
 

ZeDuval

Member
The basic functionality of gml_pragma() is to give instructions to the compiler and now that we know of one additional usage besides the documented "forceinline" I guess it's safe to say that the first argument defines what instruction should be given while further arguments(if any) are actually arguments for that instruction. Would the function be written in gml like a normal script, it might look somewhat like this:
Code:
/// gml_pragma(instruction,arg,...)
switch argument[0]{
  case "forceinline":
  // embed this script-code directly at every place where the script is used
  exit;
  case "global":
  script_execute(asset_get_index(argument[1]));
  // and do it before the actual game starts
  exit;
}
There could be even more cases for more undocumented instructions, who knows?
 

rwkay

GameMaker Staff
GameMaker Dev.
The gml_pragma functionality is internal, though I suspect we will document this one (there are a few other things that gml_pragma can do) it as you suspected, giving the compiler some extra instructions.

The "global" instruction tells the compiler to execute the string that comes after it before any room is created (so there are no instances, and no instances can/should be created (NOTE: This will not be enforced by the code but if you did create an instance then it would be in limbo and probably crash everything) - the main reason it is not documented is that there are a lot of caveats to what you can and cannot do and we have not reinforced the code to allow anyone loose on what they can do. You should be able to create data structures but basically anything to do with rooms, rendering or instances cannot be done.

This global code will be executed first (though there is no guarantee on the order that the global code will be executed), we added it to support the compatibility scrips, so it only has the functionality that we needed and we do not plan on adding anything else to it.

Russell
 

Juju

Member
I honestly can't see this particular gml_pragma command doing anything better than an initialisation room under normal circumstances (which has been standard practice for years). Perhaps it will find utility in extensions.
 

rwkay

GameMaker Staff
GameMaker Dev.
In most circumstances you are correct it will add very little, even for extension writers the extension init is already executed before the first room is run so this will add nothing - we needed it for compatibility as we had to guarantee that some code was executed before anything else at all (even extensions)

Russell
 
Top