Skip to content

Using #import magic

Vadim Dyachenko edited this page Jul 12, 2018 · 4 revisions

General idea

GML assets and functions are globally accessible and generally expected to be named in snake_case. This is generally okay thing to do, but means that either of two things happen:

  1. Names are descriptive but potentially long.
  2. Names are shortened or abbreviated, loosening any outsider's ability to tell what's going on in your code.

Usually this specific kind of problem is resolved by introducing namespace support to the language so that items can be given shorter names without clashing with each other. As of writing this GML does not feature built-in namespace support, but you can probably suspect where this is going.

Since most of the longer built-in and user-defined names follow category_subcategory_name format, that alone is enough to reliably categorize them (based on prefix).

Therefore the idea is to give the ability to specify rules for shortening names for editing while storing the full names in files.

The feature can be disabled in preferences.

Various way of use follow,

#import com.pkg.some as alias

Makes the specified item available under alias.

Periods (.) in "path" are interchangeable with underscores (_) and purely cosmetic. That is, doing

#import audio.sound.set_track_position as seek

would allow you to use seek(au, 0) instead of audio_sound_set_track_position(au, 0) inside of script in question.

You can also use in instead of as if you prefer.

#import com.pkg.some

Same as above, but auto-decides short alias based on the part of identifier after the last period (.) in the name. That is, doing

#import steam.ugc_query.set_return_long_description

would allow you to use set_return_long_description instead of steam_ugc_query_set_return_long_description.

#import com.pkg.* as alias

Makes all items starting with com_pkg_ available as alias.name, namespace style. That is, doing

#import physics_particle_group.* as pg

would allow you to use pg.get_angle instead of physics_particle_group_get_angle.

If you are using this for camel-cased names, you can omit the final dot. That is, doing

#import scrHyperCrystal* as HC

would allow you to use HC.Spawn() instead of scrHyperCrystalSpawn()

#import com.pkg.some as ns.alias

Much like the regular #import path as alias but adds it to the namespace.

Useful for adding items from multiple sources to the same namespace for type magic - for example,

#import string.* in String
#import sha1_string_utf8 in String.sha1

#import com.pkg.*

A mix of above two, auto-decides short alias for each item starting with specified prefix. That is, if you do

#import physics.particle.*

would allow you to use group_begin instead of physics_particle_group_begin

Note that you should be careful with this as it makes it easier to override something by accident.

#import "name"

Reads #import rules from the specified file. Files are read from #import subdirectory in project directory. You can navigate to declaration of file (middle click or F12) to open it for editing.

Import files can also #import other files, which allows for flexible reuse of rules between different parts of game code.

global.gml

As an exception from usual rules, you can have a "global" import file by creating a "global.gml" file in #import subdirectory (type #import "global" and middle-click "global" to quickly open it).

Any rules defined in this file will be automatically applied to all code in the project.

Needless to say, you should be careful with this so that you don't override your own code.

Additional notes

  • #import only affects the scope (script/event/moment) that it's declared in.

  • #import can be applied to any "global" identifier - functions, constants, assets, macros, global variables, even keywords (that said, be careful).

  • #import rules take priority over "normal" items with same name (plain some or dot-separated pkg.some).

  • #import are applied in order of declaration and can override each other. That is, if you do

    #import steam.ugc.* as ugc
    #import steam.ugc.query.* as query

    then steam_ugc_query_set_search_text will be shortened to query.set_search_text rather than ugc.query_set_search_text.

"Allow undo-ing #import" option

Normally, when you add/remove #import lines and this causes code to be reformatted as per new rules, the undo history is cleared in process.

This is because GMEdit does not store import rule snapshots in undo history, thus undo-ing the reformat but saving at a point where pre-reformat rules were already erased can cause identifiers to not be expanded back correctly.

If you have a good grasp at how things work and need this specific functionality, you can enable the option at your own risk.

It is regardless suggested that you use version control to be safe.