diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3948621 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +*.yy linguist-language=Game Maker Language +*.h linguist-language=C++ +*.html linguist-vendored +*.yy linguist-vendored +*/extensions/*/autogen.gml linguist-vendored diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bb1fdfe --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +.vs/ +*/#backups/* +*/Configs/*/* + +*/datafiles/snippets.html + +*/Debug/ +*/Release/ +Debug/ +Release/ +export/*.gmz +export/*.gmez +export/*.yyz +export/*.yymp +export/*.yymps +export/*.png +export/*.zip + +*.sdf +help.rtf \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c8614f0 --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +# Snippet API (working title) +**Quick links:** [documentation](https://yal-gamemaker.github.io/gmk-snippets/)\ +**Supported versions:** GameMaker 8.1\[1] + +A collection of Cool Tricks for dynamically loading scripts in GameMaker 8.1¹. + +Based on my own findings and techniques of yesteryear. + +Features: +- Can load and call "scripts" (snippets) + Snippets can call each other, + support arguments, and generally act like scripts. +- Can load objects from a GMEdit-like single-file format +- A little syntactic sugar for snippet code +- A few helper functions + +\[1] Technically any version that has `argument[]`/`argument_count` and `execute_string`/`object_event_add`, +which is most likely versions between GM8.1 (incl.) and GM:HTML5 (incl.). + +## Technical +The extension consists of a DLL and a bunch of GML scripts. + +The DLL does code preprocessing and other operations that were deemed too slow to do in GM8.1. + +The scripts use `object_event_add` + `event_perform_object` to store and call the final code without parsing penalties that would occur with `execute_string`. + +## Intended use cases +
+ +![shrug](./misc/shrug.png)\ +~~What use cases?~~ + +
+ +You could use it for dynamic content loading if you are making a game in GM8.1. + +Myself I wanted something that could run snippets of GM8.1 code without opening GM8.1, +which is convenient timing given that GM8.1 +[doesn't open at the time of writing](https://forum.gamemaker.io/index.php?threads/gamemaker-8-1-unable-to-validate-license.113289/#post-675237). + +## snippet-tester +This is an example project that has snippets setup and does +```gml +snippet_init(); +snippet_load_listfile("startup.gmk-snips"); +``` +on game start. + +If you compile a [GMEdit](https://github.com/YellowAfterlife/GMEdit/) version from git, you can open `.gmk-snips` files in it for a slightly-better code editing experience. + +## TODOs + +- Wildcard support in listfiles?\ + (`folder/*.gml`) +- Arguments for `snippet_execute_string`?\ + (needs an "argument count waterfall") + +## Meta + +**Author:** [YellowAfterlife](https://github.com/YellowAfterlife) +**License:** MIT? \ No newline at end of file diff --git a/docs/index.dmd b/docs/index.dmd new file mode 100644 index 0000000..7dd1e18 --- /dev/null +++ b/docs/index.dmd @@ -0,0 +1,326 @@ +```set template default.html``` +```set title snippet_* cheat sheet``` +```set autoapi ext``` +```gmlapi fnames2``` +```setmd intro +This is a "cheat sheet" for the "snippets" extension by YellowAfterlife. +The extension can be found +[on GitHub](https://github.com/YAL-GameMaker/gmk-snippets) +``` + +#[Setting up](setup) { + --{ + - Import `snippets.gml` to your project.\ + This should add a folder of scripts. + - Add `events.gml`, `fnames`, and `snippets.dll` to your project folder + (_or_ Included Files) + - Call `snippets_init` before using the functions + } +} +#[Preprocessing](+preproc) { + Snippet code undergoes the following transformations: + #[argument / argument_count](.arg) { + Arguments cannot be passed to `event_perform_object`, + so instead [snippet_call] will store them in global variables + and argument-related variables will be replaced with reads/writes of these. + } + #[var, globalvar](.var) { + For purposes of offering baseline convenience, + ```gml + var v = 1; + globalvar g = 2; + ``` + will be translated to + ```gml + var v; v = 1; + globalvar g; g = 2; + ``` + Note that multiple declarations (`var a = 1, b = 2`) are not supported. + } + #[function calls](.call) { + Calls to unknown functions will be replaced by [snippet_call], so + ```gml + result = mystery_func(1, 2, 3); + ``` + becomes + ```gml + result = snippet_call("mystery_func", 1, 2, 3); + ``` + Functions can be [registered](signatures) to be called by snippets. + } + #[function overrides](.hook) { + A defined snippet takes precedence over the known functions + for the subsequently compiled snippets (but not the ones that were compiled with it in one call). + + This allows to "hook" a built-in function or project script if necessary. + For example, + ```gml + snippet_define("cool_hooks", ' + #define game_end + if (show_question("Really quit?")) { + game_end(); // calls the real game_end + } + ') + snippet_execute_string(' + game_end(); // calls the game_end "hook" + ') + ``` + } +} +#[General functions](general) { + #[snippet_init()]() { + Loads up the DLL and initializes the global variables. + + This will also do the equivalent of the following: + ```gml + snippet_parse_api_file("fnames"); + snippet_parse_event_file("events.gml"); + ``` + and a `snippet_function_add` for each script in the project. + } + #[snippet_execute_string(gml_code)->]() { + Like regular `execute_string`, but uses the snippet preprocessor + (e.g. can call snippets using `func()`). + } +} +#[Snippets](snippets) { + #[snippet_define(name, gml_code)]() { + Creates/overwrites a snippet. + + If the code contains `#define` sections, multiple snippets can be defined in one call. + + For example, the following would define snippets `test` and `add`: + ```gml + snippet_define("test", ' + return add(1, 2); + #define add + return argument0 + argument1; + ') + ``` + } + #[snippet_define_raw(name, gml_code)]() { + Like above, but does _not_ use the snippet preprocessor. + + This is mostly useful if you know what you're doing or to "clone" + a snippet using [snippet_get_code]. + } + State: + #[snippet_exists(name)->]() { + Returns whether a snippet with the given name exists + } + #[snippet_get_code(name)->]() { + Returns the [preprocessed](preproc) code of a snippet. + } + Calls: + #[snippet_call(name, ...arguments)->]() { + Calls a snippet with the given name and returns the result, not unlike `script_execute`. + } +} +#[Objects](objects) { + #[snippet_define_object(name, gml_code)->]() { + Creates/overwrites an object. + + Returns the object index. + + Events are defined using [GMEdit](https://yellowafterlife.itch.io/gmedit)-inspired syntax: + ```gml + snippet_define_object("obj_test", ' + #event create + points = 0; + + #event step + points += 1 + + #event draw + draw_text(5, 5, string(points)); + ') + ``` + (also see [event types](event_types)) + --- + If there is code before the first event, + it is considered to be one-time "properties" setup + and may define the following variables + ```gml + visible -> object_set_visible + depth -> object_set_depth + persistent -> object_set_persistent + parent_index -> object_set_parent + sprite_index -> object_set_sprite + mask_index -> object_set_mask + solid -> object_set_solid + ``` + You may also use this opportunity to load the resources that the object uses. + --- + If the object name is a valid variable name, a `globalvar` will be automatically set up + for it so that it can be referenced in other code without extra effort. + } + #[snippet_prepare_object(name)->]() { + Creates an object if that doesn't exist yet. + + Returns the object index. + } + --- + #[snippet_object_get_name(ind)->]() { + Like the regular `object_get_name`, but also knows what you've called the objects + that were created using [snippet_define_object]. + } + #[snippet_object_get_index(ind)->]() { + Returns the index of an object with the given name, + including ones that were created using [snippet_define_object]. + + Returns `-1` if there's no object with a name like that. + } +} +#[List files](+listfile) { + #[snippet_load_list(list, directory)]() { + Loads one or more files from the `directory` + (use `""` for current directory) + based on the instructions in the `list`. + + Each item is a string, which can be formatted like one of the following: --{ + - `test.gml`\ + Just some script(s) (calls [snippet_define]). + - `test.object.gml`\ + An object definition file (calls [snippet_define_object]).\ + If the line ends with a `>`, an instance of the object is automatically created at 0,0. + - `test.global.gml`\ + One-time code (calls [snippet_execute_string]). + - `>code`\ + A single-line snippet for [snippet_execute_string], + in case you don't want to make a file just for that. + } + } + #[snippet_load_listfile(path)]() { + This function calls the above, + but also adds support for comments (as `# comment`). + + An example file might be called `test.gmk-snips` and contain the following: + ``` + functions.gml + obj_control.object.gml> + obj_player.object.gml + > instance_create(100, 100, obj_player) + ``` + This would: --{ + - Load scripts from `functions.gml` + - Load an object from `obj_control.object.gml` and make an instance of it + - Load an object from `obj_player.object.gml` + - Create an instance of `obj_player` at 100, 100 + } + } +} +#[Event types](+event_types) { + #[Intro](.) { + For [snippet_define_object], + the extension supports named events in a few formats. + + You can find the supported event names in `events.gml` (and/or add your own). + + The extension also supports segmented (`type:number`) names.\ + For these, the following types are supported: --{ + - `create` + - `destroy` + - `alarm` + - `step` + - `collision` + - `keyboard` + - `mouse` + - `other` + - `draw` + - `keypress` + - `keyrelease` + } + "collision" event supports object names (per [snippet_object_get_index]), + such as `collision:obj_test`. + + The three keyboard event types recognize 0-9, A-Z, and `vk_` constants, + so `keyboard:vk_left` and `keypress:E` both work. + + You can dynamically register additional events/types using + [snippet_event_register] and [snippet_event_register_type]. + } + --- + #[snippet_event_get_type(name)->]() { + Parses an event name and returns its `event_type`. + + An event is invalid if [snippet_event_get_number] is `-1`. + } + #[snippet_event_get_number(name)->]() { + Parses an event name and returns its `event_number`. + + If an event is invalid, returns `-1`. + + If it's an event that uses an object name as an argument, + returns `-2` (the named can be retrieved using [snippet_event_get_number_object]). + } + #[snippet_event_get_number_object()->]() { + If the last [snippet_event_get_number] call returned `-2`, + this returns the object name. + } + --- + #[snippet_event_register(name, type, number)]() { + Registers a named event. + } + #[snippet_event_register_type(name, type, arg_kind)]() { + Registers a named event type (for `type:arg`). + + `arg_kind` can be: --{ + - `0`: just numbers + - `1`: object name + - `2`: key code + } + } + #[snippet_parse_event_file(path)]() { + Loads event definitions (like with `events.gml`) from a file. + } +} +#[Signatures](signatures) { + #[snippet_parse_api_file(path)]() { + Parses contents of an `fnames`-styled API definitions file. + } + #[snippet_parse_api_entry(line)]() { + Parses a single-line definition in the aforementioned format. + } + --- + #[snippet_function_add(name)]() { + Registers a known function name. + + Known function calls will not be replaced by the [preprocessor](preproc.call). + } + #[snippet_function_remove(name)]() { + Removes a known function registration. + + Calls to it in subsequently compiled snippet will be the [preprocessor](preproc.call). + } +} +#[Other stuff](other) { + File functions: + #[sniptools_file_get_contents(path)->]() { + Returns the contents of a file as a string (`""` if a file is missing). + } + String functions: + #[sniptools_string_trim(str)->]() { + Returns a string with spaces trimmed from the beginning and end of it. + } + #[sniptools_string_trim_start(str)->]() { + Returns a string with spaces trimmed from the beginning of it. + } + #[sniptools_string_trim_end(str)->]() { + Returns a string with spaces trimmed from the end of it. + } + --- + #[sniptools_string_split_start(str, delimiter)->]() { + Split a string and returns the number of sections in it. + + Can be used like so: + ```gml + repeat (sniptools_string_split_start("a;bb;ccc", ";")) { + show_message(sniptools_string_split_next()); + } + ``` + (which would show `a`, `bb`, `ccc`) + } + #[sniptools_string_split_next()->]() { + Returns the next item from the string list made by [sniptools_string_split_start]. + } +} \ No newline at end of file diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..c4b1939 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,797 @@ + + +snippet_* cheat sheet + + + + + + + + + + + + + + + +
+ +
+
+This is a "cheat sheet" for the "snippets" extension by YellowAfterlife.
+The extension can be found +on GitHub +
+
+Click on sections to expand/collapse them.
Quick display controls: +CategoriesSectionsEverything
+
+

+ + + + + + + + +

Setting up
    +
  • Import snippets.gml to your project.
    + This should add a folder of scripts. +
  • Add events.gml, fnames, and snippets.dll to your project folder + (_or_ Included Files) +
  • Call snippets_init before using the functions +
Preprocessing
Preprocessing

+ Snippet code undergoes the following transformations: +

argument / argument_count

+ Arguments cannot be passed to event_perform_object, + so instead snippet_call will store them in global variables + and argument-related variables will be replaced with reads/writes of these. +

var, globalvar

+ For purposes of offering baseline convenience, +

+var v = 1;
+globalvar g = 2;
+

+ will be translated to +

+var v; v = 1;
+globalvar g; g = 2;
+

+ Note that multiple declarations (var a = 1, b = 2) are not supported. +

function calls

+ Calls to unknown functions will be replaced by snippet_call, so +

+result = mystery_func(1, 2, 3);
+

+ becomes +

+result = snippet_call("mystery_func", 1, 2, 3);
+

+ Functions can be registered to be called by snippets. +

function overrides

+ A defined snippet takes precedence over the known functions + for the subsequently compiled snippets (but not the ones that were compiled with it in one call). +

+ This allows to "hook" a built-in function or project script if necessary. + For example, +

+snippet_define("cool_hooks", '
+#define game_end
+if (show_question("Really quit?")) {
+    game_end(); // calls the real game_end
+}
+')
+snippet_execute_string('
+game_end(); // calls the game_end "hook"
+')
+
General functions
Snippets
Snippets
snippet_define(name, gml_code)

+ Creates/overwrites a snippet. +

+ If the code contains #define sections, multiple snippets can be defined in one call. +

+ For example, the following would define snippets test and add: +

+snippet_define("test", '
+return add(1, 2);
+#define add
+return argument0 + argument1;
+')
+
snippet_define_raw(name, gml_code)

+ Like above, but does not use the snippet preprocessor. +

+ This is mostly useful if you know what you're doing or to "clone" + a snippet using snippet_get_code. +

+ State: +

snippet_exists(name)​

+ Returns whether a snippet with the given name exists +

snippet_get_code(name)​

+ Calls: +

snippet_call(name, ...arguments)​

+ Calls a snippet with the given name and returns the result, not unlike script_execute. +

Objects
Objects
snippet_define_object(name, gml_code)​

+ Creates/overwrites an object. +

+ Returns the object index. +

+ Events are defined using GMEdit-inspired syntax: +

+snippet_define_object("obj_test", '
+#event create
+points = 0;
+
+#event step
+points += 1
+
+#event draw
+draw_text(5, 5, string(points));
+')
+

+ (also see event types) +


+ If there is code before the first event, + it is considered to be one-time "properties" setup + and may define the following variables +

+visible -> object_set_visible
+depth -> object_set_depth
+persistent -> object_set_persistent
+parent_index -> object_set_parent
+sprite_index -> object_set_sprite
+mask_index -> object_set_mask
+solid -> object_set_solid
+

+ You may also use this opportunity to load the resources that the object uses. +


+ If the object name is a valid variable name, a globalvar will be automatically set up + for it so that it can be referenced in other code without extra effort. +

snippet_prepare_object(name)​

+ Creates an object if that doesn't exist yet. +

+ Returns the object index. +


snippet_object_get_name(ind)​

+ Like the regular object_get_name, but also knows what you've called the objects + that were created using snippet_define_object. +

snippet_object_get_index(ind)​

+ Returns the index of an object with the given name, + including ones that were created using snippet_define_object. +

+ Returns -1 if there's no object with a name like that. +

List files
List files
snippet_load_list(list, directory)

+ Loads one or more files from the directory + (use "" for current directory) + based on the instructions in the list. +

+ Each item is a string, which can be formatted like one of the following:

    +
  • test.gml
    + Just some script(s) (calls snippet_define). +
  • test.object.gml
    + An object definition file (calls snippet_define_object).
    + If the line ends with a >, an instance of the object is automatically created at 0,0. +
  • test.global.gml
    + One-time code (calls snippet_execute_string). +
  • >code
    + A single-line snippet for snippet_execute_string, + in case you don't want to make a file just for that. +
snippet_load_listfile(path)

+ This function calls the above, + but also adds support for comments (as # comment). +

+ An example file might be called test.gmk-snips and contain the following: +

+functions.gml
+obj_control.object.gml>
+obj_player.object.gml
+> instance_create(100, 100, obj_player)
+

+ This would:

    +
  • Load scripts from functions.gml +
  • Load an object from obj_control.object.gml and make an instance of it +
  • Load an object from obj_player.object.gml +
  • Create an instance of obj_player at 100, 100 +
Event types
Event types
Intro

+ For snippet_define_object, + the extension supports named events in a few formats. +

+ You can find the supported event names in events.gml (and/or add your own). +

+ The extension also supports segmented (type:number) names.
+ For these, the following types are supported:

    +
  • create +
  • destroy +
  • alarm +
  • step +
  • collision +
  • keyboard +
  • mouse +
  • other +
  • draw +
  • keypress +
  • keyrelease +

+ "collision" event supports object names (per snippet_object_get_index), + such as collision:obj_test. +

+ The three keyboard event types recognize 0-9, A-Z, and vk_ constants, + so keyboard:vk_left and keypress:E both work. +

+ You can dynamically register additional events/types using + snippet_event_register and snippet_event_register_type. +


snippet_event_get_type(name)​
snippet_event_get_number(name)​

+ Parses an event name and returns its event_number. +

+ If an event is invalid, returns -1. +

+ If it's an event that uses an object name as an argument, + returns -2 (the named can be retrieved using snippet_event_get_number_object). +

snippet_event_get_number_object()​

snippet_event_register(name, type, number)

+ Registers a named event. +

snippet_event_register_type(name, type, arg_kind)

+ Registers a named event type (for type:arg). +

+ arg_kind can be:

    +
  • 0: just numbers +
  • 1: object name +
  • 2: key code +
snippet_parse_event_file(path)

+ Loads event definitions (like with events.gml) from a file. +

Signatures
Other stuff
Other stuff

+ File functions: +

sniptools_file_get_contents(path)​

+ Returns the contents of a file as a string ("" if a file is missing). +

+ String functions: +

sniptools_string_trim(str)​

+ Returns a string with spaces trimmed from the beginning and end of it. +

sniptools_string_trim_start(str)​

+ Returns a string with spaces trimmed from the beginning of it. +

sniptools_string_trim_end(str)​

+ Returns a string with spaces trimmed from the end of it. +


sniptools_string_split_start(str, delimiter)​
sniptools_string_split_next()​

+
+ + diff --git a/misc/shrug.png b/misc/shrug.png new file mode 100644 index 0000000..ba22181 Binary files /dev/null and b/misc/shrug.png differ diff --git a/snippets.sln b/snippets.sln new file mode 100644 index 0000000..ea374a5 --- /dev/null +++ b/snippets.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29424.173 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "snippets", "snippets\snippets.vcxproj", "{EA16C6EF-C7F3-42BC-A4AC-EBEE2E84C450}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EA16C6EF-C7F3-42BC-A4AC-EBEE2E84C450}.Debug|x86.ActiveCfg = Debug|Win32 + {EA16C6EF-C7F3-42BC-A4AC-EBEE2E84C450}.Debug|x86.Build.0 = Debug|Win32 + {EA16C6EF-C7F3-42BC-A4AC-EBEE2E84C450}.Release|x86.ActiveCfg = Release|Win32 + {EA16C6EF-C7F3-42BC-A4AC-EBEE2E84C450}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8FCBDF72-1C64-42B3-B970-F6A254875BD6} + EndGlobalSection +EndGlobal diff --git a/snippets/CharTools.h b/snippets/CharTools.h new file mode 100644 index 0000000..8cea18b --- /dev/null +++ b/snippets/CharTools.h @@ -0,0 +1,16 @@ +#pragma once + +namespace CharTools { + inline bool isSpace(char c) { + switch (c) { + case ' ': case '\t': case '\r': case '\n': return true; + default: return false; + } + } + inline bool isIdentStart(char c) { + return c == '_' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'; + } + inline bool isIdent(char c) { + return c == '_' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9'; + } +} \ No newline at end of file diff --git a/snippets/autogen.cpp b/snippets/autogen.cpp new file mode 100644 index 0000000..a4a3bf3 --- /dev/null +++ b/snippets/autogen.cpp @@ -0,0 +1,2 @@ +#include "gml_ext.h" +gmk_buffer gmk_buffer_args; diff --git a/snippets/dllmain.cpp b/snippets/dllmain.cpp new file mode 100644 index 0000000..69b5891 --- /dev/null +++ b/snippets/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : Defines the entry point for the DLL application. +#include "stdafx.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/snippets/gml_ext.h b/snippets/gml_ext.h new file mode 100644 index 0000000..49d4dd2 --- /dev/null +++ b/snippets/gml_ext.h @@ -0,0 +1,306 @@ +#pragma once +#include "stdafx.h" +#define gml_ext_h +#include +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +#include +#endif +#include +#include +#include +using namespace std; + +#define dllg /* tag */ +#define dllgm /* tag;mangled */ + +#if defined(_WINDOWS) +#define dllx extern "C" __declspec(dllexport) +#define dllm __declspec(dllexport) +#elif defined(GNUC) +#define dllx extern "C" __attribute__ ((visibility("default"))) +#define dllm __attribute__ ((visibility("default"))) +#else +#define dllx extern "C" +#define dllm /* */ +#endif + +#ifdef _WINDEF_ +/// auto-generates a window_handle() on GML side +typedef HWND GAME_HWND; +#endif + +/// auto-generates an asset_get_index("argument_name") on GML side +typedef int gml_asset_index_of; +/// Wraps a C++ pointer for GML. +template using gml_ptr = T*; +/// Same as gml_ptr, but replaces the GML-side pointer by a nullptr after passing it to C++ +template using gml_ptr_destroy = T*; +/// Wraps any ID (or anything that casts to int64, really) for GML. +template using gml_id = T; +/// Same as gml_id, but replaces the GML-side ID by a 0 after passing it to C++ +template using gml_id_destroy = T; + +class gml_buffer { +private: + uint8_t* _data; + int32_t _size; + int32_t _tell; +public: + gml_buffer() : _data(nullptr), _tell(0), _size(0) {} + gml_buffer(uint8_t* data, int32_t size, int32_t tell) : _data(data), _size(size), _tell(tell) {} + + inline uint8_t* data() { return _data; } + inline int32_t tell() { return _tell; } + inline int32_t size() { return _size; } +}; + +class gml_istream { + uint8_t* pos; + uint8_t* start; +public: + gml_istream(void* origin) : pos((uint8_t*)origin), start((uint8_t*)origin) {} + + template T read() { + static_assert(std::is_trivially_copyable_v, "T must be trivially copyable to be read"); + T result{}; + std::memcpy(&result, pos, sizeof(T)); + pos += sizeof(T); + return result; + } + + char* read_string() { + char* r = (char*)pos; + while (*pos != 0) pos++; + pos++; + return r; + } + + template std::vector read_vector() { + static_assert(std::is_trivially_copyable_v, "T must be trivially copyable to be read"); + auto n = read(); + std::vector vec(n); + std::memcpy(vec.data(), pos, sizeof(T) * n); + pos += sizeof(T) * n; + return vec; + } + #ifdef tiny_array_h + template tiny_const_array read_tiny_const_array() { + static_assert(std::is_trivially_copyable_v, "T must be trivially copyable to be read"); + auto n = read(); + tiny_const_array arr((T*)pos, sizeof(T)); + pos += sizeof(T) * n; + return arr; + } + #endif + + std::vector read_string_vector() { + auto n = read(); + std::vector vec(n); + for (auto i = 0u; i < n; i++) { + vec[i] = read_string(); + } + return vec; + } + + gml_buffer read_gml_buffer() { + auto _data = (uint8_t*)read(); + auto _size = read(); + auto _tell = read(); + return gml_buffer(_data, _size, _tell); + } + + #ifdef tiny_optional_h + template tiny_optional read_tiny_optional() { + if (read()) { + return read; + } else return {}; + } + #endif + + #pragma region Tuples + #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) + template + std::tuple read_tuple() { + std::tuple tup; + std::apply([this](auto&&... arg) { + (( + arg = this->read>() + ), ...); + }, tup); + return tup; + } + + template optional read_optional() { + if (read()) { + return read; + } else return {}; + } + #else + template std::tuple read_tuple() { + A a = read(); + B b = read(); + return std::tuple(a, b); + } + + template std::tuple read_tuple() { + A a = read(); + B b = read(); + C c = read(); + return std::tuple(a, b, c); + } + + template std::tuple read_tuple() { + A a = read(); + B b = read(); + C c = read(); + D d = read(); + return std::tuple(a, b, c, d); + } + #endif +}; + +class gml_ostream { + uint8_t* pos; + uint8_t* start; +public: + gml_ostream(void* origin) : pos((uint8_t*)origin), start((uint8_t*)origin) {} + + template void write(T val) { + static_assert(std::is_trivially_copyable_v, "T must be trivially copyable to be write"); + memcpy(pos, &val, sizeof(T)); + pos += sizeof(T); + } + + void write_string(const char* s) { + for (int i = 0; s[i] != 0; i++) write(s[i]); + write(0); + } + + template void write_vector(std::vector& vec) { + static_assert(std::is_trivially_copyable_v, "T must be trivially copyable to be write"); + auto n = vec.size(); + write((uint32_t)n); + memcpy(pos, vec.data(), n * sizeof(T)); + pos += n * sizeof(T); + } + + #ifdef tiny_array_h + template void write_tiny_array(tiny_array& arr) { + static_assert(std::is_trivially_copyable_v, "T must be trivially copyable to be write"); + auto n = arr.size(); + write(n); + memcpy(pos, arr.data(), n * sizeof(T)); + pos += n * sizeof(T); + } + template void write_tiny_const_array(tiny_const_array& arr) { + static_assert(std::is_trivially_copyable_v, "T must be trivially copyable to be write"); + auto n = arr.size(); + write(n); + memcpy(pos, arr.data(), n * sizeof(T)); + pos += n * sizeof(T); + } + #endif + + void write_string_vector(std::vector vec) { + auto n = vec.size(); + write((uint32_t)n); + for (auto i = 0u; i < n; i++) { + write_string(vec[i]); + } + } + + #ifdef tiny_optional_h + template void write_tiny_optional(tiny_optional& val) { + auto hasValue = val.has_value(); + write(hasValue); + if (hasValue) write(val.value()); + } + #endif + + #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) + template + void write_tuple(std::tuple tup) { + std::apply([this](auto&&... arg) { + (this->write(arg), ...); + }, tup); + } + + template void write_optional(optional& val) { + auto hasValue = val.has_value(); + write(hasValue); + if (hasValue) write(val.value()); + } + #else + template void write_tuple(std::tuple& tup) { + write(std::get<0>(tup)); + write(std::get<1>(tup)); + } + template void write_tuple(std::tuple& tup) { + write(std::get<0>(tup)); + write(std::get<1>(tup)); + write(std::get<2>(tup)); + } + template void write_tuple(std::tuple& tup) { + write(std::get<0>(tup)); + write(std::get<1>(tup)); + write(std::get<2>(tup)); + write(std::get<3>(tup)); + } + #endif +}; + +class gmk_buffer { + uint8_t* buf = 0; + int pos = 0; + int len = 0; +public: + gmk_buffer() {} + uint8_t* prepare(int size) { + if (len < size) { + auto nb = (uint8_t*)realloc(buf, size); + if (nb == nullptr) { + show_error("Failed to reallocate %u bytes in gmk_buffer::prepare", size); + return nullptr; + } + len = size; + buf = nb; + if (buf == 0) MessageBoxA(0, "It would app", "", 0); + } + pos = 0; + return buf; + } + void init() { + buf = 0; + pos = 0; + len = 0; + } + void rewind() { pos = 0; } + inline uint8_t* data() { return buf; } + // + template void write(T val) { + static_assert(std::is_trivially_copyable_v, "T must be trivially copyable to be write"); + int next = pos + sizeof(T); + if (next > len) { + auto nl = len; + while (nl < next) nl *= 2; + auto nb = (uint8_t*)realloc(buf, nl); + if (nb == nullptr) { + show_error("Failed to reallocate %u bytes in gmk_buffer::write", nl); + return; + } + len = nl; + buf = nb; + } + memcpy(buf + pos, &val, sizeof(T)); + pos = next; + } + template T read() { + static_assert(std::is_trivially_copyable_v, "T must be trivially copyable to be read"); + int next = pos + sizeof(T); + T result{}; + if (next > len) return result; + memcpy(&result, buf + pos, sizeof(T)); + pos = next; + return result; + } +}; diff --git a/snippets/named_events.cpp b/snippets/named_events.cpp new file mode 100644 index 0000000..acb1dcc --- /dev/null +++ b/snippets/named_events.cpp @@ -0,0 +1,195 @@ +#include "stdafx.h" +#include +#include +#include + +struct gml_event_pair { + int type, number; + gml_event_pair() : type(-1), number(-1) {} + gml_event_pair(int _type, int _number) : type(_type), number(_number) {} +}; +std::unordered_map gml_named_events{ + {"properties", gml_event_pair(-1, 0)} +}; + +enum class gml_event_type_arg : int { + index, + object, + key, +}; +struct gml_event_type_pair { + int type; + gml_event_type_arg arg; + gml_event_type_pair() : type(-1), arg(gml_event_type_arg::index) {} + gml_event_type_pair(int _type) : type(_type), arg(gml_event_type_arg::index) {} + gml_event_type_pair(int _type, gml_event_type_arg _number) : type(_type), arg(_number) {} +}; +std::unordered_map gml_named_event_types{ + {"create", gml_event_type_pair(0)}, + {"destroy", gml_event_type_pair(1)}, + {"alarm", gml_event_type_pair(2)}, + {"step", gml_event_type_pair(3)}, + {"collision", gml_event_type_pair(4, gml_event_type_arg::object)}, + {"keyboard", gml_event_type_pair(5, gml_event_type_arg::key)}, + {"mouse", gml_event_type_pair(6)}, + {"other", gml_event_type_pair(7)}, + {"draw", gml_event_type_pair(8)}, + {"keypress", gml_event_type_pair(9, gml_event_type_arg::key)}, + {"keyrelease", gml_event_type_pair(10, gml_event_type_arg::key)}, +}; + +std::unordered_map gml_keycodes_init() { + std::unordered_map map{ + {"vk_nokey", 0}, + {"vk_anykey", 1}, + {"vk_backspace", 8}, + {"vk_tab", 9}, + {"vk_return", 13}, + {"vk_enter", 13}, + {"vk_shift", 16}, + {"vk_control", 17}, + {"vk_alt", 18}, + {"vk_pause", 19}, + {"vk_escape", 27}, + {"vk_space", 32}, + {"vk_pageup", 33}, + {"vk_pagedown", 34}, + {"vk_end", 35}, + {"vk_home", 36}, + {"vk_left", 37}, + {"vk_up", 38}, + {"vk_right", 39}, + {"vk_down", 40}, + {"vk_printscreen", 44}, + {"vk_insert", 45}, + {"vk_delete", 46}, + {"vk_numpad0", 96}, + {"vk_numpad1", 97}, + {"vk_numpad2", 98}, + {"vk_numpad3", 99}, + {"vk_numpad4", 100}, + {"vk_numpad5", 101}, + {"vk_numpad6", 102}, + {"vk_numpad7", 103}, + {"vk_numpad8", 104}, + {"vk_numpad9", 105}, + {"vk_multiply", 106}, + {"vk_add", 107}, + {"vk_subtract", 109}, + {"vk_decimal", 110}, + {"vk_divide", 111}, + {"vk_lshift", 160}, + {"vk_rshift", 161}, + {"vk_lcontrol", 162}, + {"vk_rcontrol", 163}, + {"vk_lalt", 164}, + {"vk_ralt", 165}, + }; + for (int c = 'A'; c <= 'Z'; c++) map[std::string(1, c)] = c; + for (int c = '0'; c <= '9'; c++) map[std::string(1, c)] = c; + for (int i = 1; i <= 24; i++) { + map["vk_f" + std::to_string(i)] = 111 + i; + } + return map; +} +std::unordered_map gml_keycodes = gml_keycodes_init(); + +/// +dllx double snippet_event_get_type(const char* name) { + static std::string str{}; + str.assign(name); + auto pos = str.find(':'); + if (pos != std::string::npos) { + auto pair = gml_named_event_types.find(str.substr(0, pos)); + if (pair == gml_named_event_types.end()) return -1; + return pair->second.type; + } else { + auto pair = gml_named_events.find(name); + if (pair == gml_named_events.end()) return -1; + return pair->second.type; + } +} + +static std::string snippet_event_object; +/// +dllx double snippet_event_get_number(const char* name) { + static std::string str{}; + str.assign(name); + auto pos = str.find(':'); + if (pos != std::string::npos) { + auto pair = gml_named_event_types.find(str.substr(0, pos)); + if (pair == gml_named_event_types.end()) return -1; + switch (pair->second.arg) { + case gml_event_type_arg::index: { + int numb = 0; + if (std::sscanf(str.c_str() + pos + 1, "%d", &numb)) { + if (numb < 0) numb = -1; + return numb; + } + return -1; + }; + case gml_event_type_arg::object: + snippet_event_object = str.substr(pos + 1); + return -2; + case gml_event_type_arg::key: { + auto key = str.substr(pos + 1); + auto kp = gml_keycodes.find(key); + if (kp != gml_keycodes.end()) kp->second; + + int numb = 0; + if (std::sscanf(key.c_str(), "%d", &numb)) { + if (numb < 0) numb = -1; + return numb; + } + + return -1; + }; + default: return -1; + } + } else { + auto pair = gml_named_events.find(name); + if (pair == gml_named_events.end()) return -1; + return pair->second.number; + } +} +/// +dllx const char* snippet_event_get_number_object() { + return snippet_event_object.c_str(); +} + +/// +dllx double snippet_event_register(const char* name, double type, double number) { + gml_event_pair pair{}; + pair.type = (int)type; + pair.number = (int)number; + gml_named_events[name] = pair; + return 1; +} + +/// +dllx double snippet_event_register_type(const char* name, double type, double arg_type) { + gml_event_type_pair pair{}; + pair.type = (int)type; + pair.arg = (gml_event_type_arg)arg_type; + gml_named_event_types[name] = pair; + return 1; +} + +/// +dllx double snippet_parse_event_file(const char* path) { + std::ifstream fs(path); + std::string line{}; + char ename[33]{}; + int n = 0; + while (std::getline(fs, line)) { + if (line.length() == 0) continue; + int type = 0, number = 0; + if (std::sscanf(line.c_str(), "%d:%d %32s", &type, &number, ename) > 0) { + snippet_event_register(ename, type, number); + //std::string m = std::string("type: ") + std::to_string(type) + " n:" + std::to_string(number) + " s:" + ename; + //MessageBoxA(0, m.c_str(), "", 0); + n += 1; + } + } + return n; +} diff --git a/snippets/postBuild.bat b/snippets/postBuild.bat new file mode 100644 index 0000000..e134f0f --- /dev/null +++ b/snippets/postBuild.bat @@ -0,0 +1,39 @@ +@echo off +set dllPath=%~1 +set solutionDir=%~2 +set projectDir=%~3 +set arch=%~4 +set config=%~5 + +echo Running post-build for %config% + +set extName=snippets +set dllName=snippets +set dllRel=%dllName%.dll +set cppRel=%dllName%.cpp +set outDir=%solutionDir%snippets_gml +set cppPath=%outDir%\%cppRel% + +echo Combining the source files... +type "%projectDir%*.h" "%projectDir%*.cpp" >"%cppPath%" 2>nul + +where /q gmxgen +if %ERRORLEVEL% EQU 0 ( +gmxgen "%outDir%\%extName%.gmxgen81" ^ + --copy "%dllPath%" "%dllRel%:%arch%" ^ + --copy "%outDir%/snippets_core.gml" "snippets_core_gm81.gml"^ + --gmk-loader snippet_init_dll + +) else ( + + copy /Y "%dllPath%" "%outDir%\%dllRel%" + + echo postBuild.bat: Warning N/A: Could not find GmxGen - extensions will not be updated automatically. See https://github.com/YAL-GameMaker-Tools/GmxGen for setup. +) +:: copy the DLL to the test project too: +copy /Y "%outDir%\%dllRel%" "%outDir%\tester\%dllRel%" + +:: clean up the mess that we made: +del /Q "%outDir%\snippets_core_gm81.gml" +del /Q "%outDir%\snippets_discard.gml" +del /Q "%outDir%\snippets_autogen.gml" diff --git a/snippets/preBuild.bat b/snippets/preBuild.bat new file mode 100644 index 0000000..c53dc20 --- /dev/null +++ b/snippets/preBuild.bat @@ -0,0 +1,19 @@ +@echo off +set dllPath=%~1 +set solutionDir=%~2 +set projectDir=%~3 +set arch=%~4 +set config=%~5 + +echo Running pre-build for %config% + +where /q GmlCppExtFuncs +if %ERRORLEVEL% EQU 0 ( + echo Running GmlCppExtFuncs... + GmlCppExtFuncs ^ + --prefix snippets^ + --cpp "%projectDir%autogen.cpp"^ + --gml "%solutionDir%snippets_gml/snippets_discard.gml"^ + --gmk "%solutionDir%snippets_gml/snippets_autogen.gml"^ + %projectDir%snippets.cpp +) \ No newline at end of file diff --git a/snippets/resource1.h b/snippets/resource1.h new file mode 100644 index 0000000..6825f47 --- /dev/null +++ b/snippets/resource1.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by snippets.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/snippets/snippets.aps b/snippets/snippets.aps new file mode 100644 index 0000000..849b65d Binary files /dev/null and b/snippets/snippets.aps differ diff --git a/snippets/snippets.cpp b/snippets/snippets.cpp new file mode 100644 index 0000000..fed4243 --- /dev/null +++ b/snippets/snippets.cpp @@ -0,0 +1,342 @@ +/// @author YellowAfterlife + +#include "stdafx.h" +#include +#include +#include +#include +#include +#include +#include +#include "CharTools.h" + +const char* rets(std::string& s) { + static std::string _str{}; + _str = s; + return _str.c_str(); +} + +#define set_contains(set, thing) (set.find(thing) != set.end()) + +static std::unordered_set gml_keywords{ + "if", "then", "else", "begin", "end", "for", "while", "do", "until", "repeat", + "switch", "case", "default", "break", "continue", "with", "exit", "return", + "self", "other", "noone", "all", "global", "local", + "mod", "div", "not", "and", "or", "xor", +}; +static bool is_gml_keyword(std::string& s) { + return set_contains(gml_keywords, s); +} + +static std::unordered_set gml_functions{}; + +class snippet_preproc_t { +public: + std::stringstream out{}; + std::string out_name{}; + std::queue names{}; + std::queue codes{}; + /// (including the ones that were empty and weren't added to output) + int found = 0; + int pos = 0; + int len = 0; + int start = 0; + const char* str = nullptr; + snippet_preproc_t() {} + + void skipSpaces() { + while (pos < len) { + auto c = str[pos]; + if (CharTools::isSpace(c)) pos += 1; else break; + } + } + void skipLine() { + while (pos < len) { + if (str[pos++] == '\n') break; + } + } + std::string slice(int start, int end) { + return std::string(str + start, end - start); + } + std::string readIdent(bool afterFirst = true) { + auto identStart = pos; + if (afterFirst) identStart -= 1; + while (pos < len) { + auto c = str[pos]; + if (CharTools::isIdent(c)) pos += 1; else break; + } + return std::string(str + identStart, pos - identStart); + } + void flush(int till) { + if (till > start) out.write(str + start, till - start); + } + void flushPart(int till, bool last) { + auto first = found == 0; + found += 1; + + // #define right at the start? + if (till == 0 && !last) return; + + flush(till); + auto code = out.str(); + + // if the snip is 100% spaces, we'd like it trimmed: + int len = (int)code.length(); + int pos = 0; + while (pos < len) { + if (CharTools::isSpace(code[pos])) { + pos += 1; + } else break; + } + if (pos >= len) code = ""; + + // and we don't want to add a spaces-only first section unless that's also the last section + if (!first || last || !code.empty()) { + names.push(out_name); + codes.push(code); + } + out = std::stringstream(); + } + int run(const char* first_name, const char* code, const char* splitter) { + str = code; + pos = 0; + start = 0; + found = 0; + len = strlen(code); + out = std::stringstream(); + out_name = first_name; + while (!names.empty()) names.pop(); + while (!codes.empty()) codes.pop(); + + bool is_script = std::string(splitter) == "define"; + + while (pos < len) { + auto c = str[pos++]; + if (CharTools::isSpace(c)) continue; + + switch (c) { + case '/': + switch (str[pos]) { + case '/': + skipLine(); + continue; + case '*': + while (pos < len) { + c = str[pos]; + if (c == '/' && str[pos - 1] == '*') break; + if (c == '#' && str[pos - 1] == '\n') { + auto beforeWord = pos++; + auto word = readIdent(false); + if (word == splitter) { + pos = beforeWord; + break; + } + } + pos += 1; + } + continue; + } + continue; + case '"': case '\'': + while (pos < len) { + if (str[pos++] == c) break; + } + continue; + } + if (CharTools::isIdentStart(c)) { + auto before_pos = pos - 1; + auto word = readIdent(); + auto wlen = word.size(); + + if (is_script && word == "return") { // `return X` -> `for ({}; true; exit) global.__snippet_result = X` + flush(before_pos); + out << "for ({}; true; exit) global.__snippet__result ="; + start = pos; + continue; + } + + if (word == "var" || word == "globalvar") { // `var i = 1` -> `var i; i = 1` + skipSpaces(); + auto before_vname = pos; + auto vname = readIdent(false); + if (is_gml_keyword(vname)) { // `var var name` + pos = before_vname; + continue; + } + auto before_equ = pos; + skipSpaces(); + if (str[pos] == '=' || str[pos] == ':' && str[pos + 1] == '=') { + flush(before_pos); + out << word << " " << vname << "; " << vname; + start = before_equ; + } + continue; + } + + if (is_script && word == "argument_count") { + flush(before_pos); + out << "global.__snippet__argument_count"; + start = pos; + continue; + } + + // `argument[#]` / `argument#` -> `global.__snippet__argument[#]` + const auto argn = sizeof("argument") - 1; + if (is_script && wlen >= argn && wlen <= argn + 2 && strncmp(word.c_str(), "argument", argn) == 0) do { + int argi; + if (wlen == argn) { + argi = -1; + } else { + argi = word[argn] - '0'; + if (argi < 0 || argi > 9) break; + if (wlen > argn + 1) { + argi = word[argn + 1] - '0'; + if (argi < 0 || argi > 5) break; + argi += 10; + } + } + flush(before_pos); + out << "global.__snippet__argument"; + if (argi >= 0) { + out << "[" << std::to_string(argi) << "]"; + } + start = pos; + continue; + } while (false); + + if (word == splitter && before_pos > 0 && str[before_pos - 1] == '#' + && (before_pos == 1 || str[before_pos - 2] == '\n') + ) { // #define + skipSpaces(); + auto name_start = pos; + while (pos < len) { // name spans till eol/space/`(` + c = str[pos]; + if (c == '(') break; + if (CharTools::isSpace(c)) break; + pos += 1; + } + auto name = slice(name_start, pos); + flushPart(before_pos - 1, false); + out_name = name; + skipLine(); + start = pos; + continue; + } + + if (!is_gml_keyword(word) && word != "snippet_call" && !set_contains(gml_functions, word)) { // `func(` -> + auto peek = pos; + bool isCall = false; + while (peek < len) { + auto c1 = str[peek++]; + if (!CharTools::isSpace(c1)) { + isCall = c1 == '('; + break; + } + } + if (isCall) { + flush(before_pos); + pos = peek; + // it's okay! Trailing commas are allowed in argument lists in GML + out << "snippet_call(\"" << word << "\","; + start = pos; + } + } + } + } + flushPart(pos, true); + return names.size(); + } +} snippet_preproc; +/// #gmki +dllx double snippet_preproc_run(const char* name, const char* code, const char* splitter) { + return snippet_preproc.run(name, code, splitter); +} +/// #gmki +dllx const char* snippet_preproc_pop_name() { + static std::string s{}; + s = snippet_preproc.names.front(); + snippet_preproc.names.pop(); + return s.c_str(); +} +/// #gmki +dllx const char* snippet_preproc_pop_code() { + static std::string s{}; + s = snippet_preproc.codes.front(); + snippet_preproc.codes.pop(); + return s.c_str(); +} +/// #gmki +dllx const char* snippet_preproc_concat_names() { + static std::queue tmp{}; + tmp = snippet_preproc.names; + std::stringstream out{}; + auto sep = false; + while (!tmp.empty()) { + if (sep) out << "\n"; else sep = true; + out << tmp.front(); + tmp.pop(); + } + static std::string result{}; + result = out.str(); + return result.c_str(); +} + +bool snippet_def_parse_impl(const char* def) { + int pos = 0; + int len = strlen(def); + + // spaces at line start: + while (pos < len) { + if (CharTools::isSpace(def[pos])) pos += 1; else break; + } + + // read name: + int name_start = pos; + if (!CharTools::isIdentStart(def[pos])) return false; + while (pos < len) { + if (CharTools::isIdent(def[pos])) pos += 1; else break; + } + auto name = std::string(def + name_start, pos - name_start); + + // more spaces? + while (pos < len) { + if (CharTools::isSpace(def[pos])) pos += 1; else break; + } + + if (def[pos] == '(') { // a function! + if (!set_contains(gml_functions, name)) gml_functions.insert(name); + return true; + } + + return false; +} + +/// +dllx double snippet_function_add(const char* name) { + if (set_contains(gml_functions, name)) return -1; + gml_functions.insert(name); + return true; +} +/// +dllx double snippet_function_remove(const char* name) { + auto item = gml_functions.find(name); + if (item == gml_functions.end()) return -1; + gml_functions.erase(item); + return 1; +} + +/// +dllx double snippet_parse_api_entry(const char* line) { + return snippet_def_parse_impl(line); +} +/// +dllx double snippet_parse_api_file(const char* path) { + std::ifstream fs(path); + std::string line{}; + int n = 0; + while (std::getline(fs, line)) { + if (snippet_def_parse_impl(line.c_str())) n += 1; + } + return n; +} + diff --git a/snippets/snippets.rc b/snippets/snippets.rc new file mode 100644 index 0000000..9546b6d Binary files /dev/null and b/snippets/snippets.rc differ diff --git a/snippets/snippets.vcxproj b/snippets/snippets.vcxproj new file mode 100644 index 0000000..28494fd --- /dev/null +++ b/snippets/snippets.vcxproj @@ -0,0 +1,211 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {EA16C6EF-C7F3-42BC-A4AC-EBEE2E84C450} + Win32Proj + snippets + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;snippets_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + + + cmd /C postBuild.bat "$(TargetPath)" "$(SolutionDir)" "$(ProjectDir)" "$(PlatformTarget)" "$(ConfigurationName)" + + + cmd /C preBuild.bat "$(TargetPath)" "$(SolutionDir)" "$(ProjectDir)" "$(PlatformTarget)" "$(ConfigurationName)" + + + + + + + Level3 + Disabled + _DEBUG;_WINDOWS;_USRDLL;snippets_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + + + cmd /C postBuild.bat "$(TargetPath)" "$(SolutionDir)" "$(ProjectDir)" "$(PlatformTarget)" "$(ConfigurationName)" + + + cmd /C preBuild.bat "$(TargetPath)" "$(SolutionDir)" "$(ProjectDir)" "$(PlatformTarget)" "$(ConfigurationName)" + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;snippets_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + None + + + Windows + true + true + No + + + cmd /C postBuild.bat "$(TargetPath)" "$(SolutionDir)" "$(ProjectDir)" "$(PlatformTarget)" "$(ConfigurationName)" + + + cmd /C preBuild.bat "$(TargetPath)" "$(SolutionDir)" "$(ProjectDir)" "$(PlatformTarget)" "$(ConfigurationName)" + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_WINDOWS;_USRDLL;snippets_EXPORTS;%(PreprocessorDefinitions) + None + MultiThreaded + + + Windows + true + true + false + + + cmd /C postBuild.bat "$(TargetPath)" "$(SolutionDir)" "$(ProjectDir)" "$(PlatformTarget)" "$(ConfigurationName)" + + + cmd /C preBuild.bat "$(TargetPath)" "$(SolutionDir)" "$(ProjectDir)" "$(PlatformTarget)" "$(ConfigurationName)" + + + + + + + + + + + + + false + + + false + + + false + + + false + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/snippets/snippets.vcxproj.filters b/snippets/snippets.vcxproj.filters new file mode 100644 index 0000000..647eeb6 --- /dev/null +++ b/snippets/snippets.vcxproj.filters @@ -0,0 +1,73 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {9a9fbe1a-e106-412a-839c-4a270587c3d1} + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Source Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + + + Build scripts + + + Build scripts + + + Build scripts + + + \ No newline at end of file diff --git a/snippets/snippets.vcxproj.user b/snippets/snippets.vcxproj.user new file mode 100644 index 0000000..89c6d0b --- /dev/null +++ b/snippets/snippets.vcxproj.user @@ -0,0 +1,22 @@ + + + + + Default + + + Default + $(NintendoTargetSerialNumber) + $(NintendoTargetName) + + + Default + $(NintendoTargetSerialNumber) + $(NintendoTargetName) + + + Default + $(NintendoTargetSerialNumber) + $(NintendoTargetName) + + \ No newline at end of file diff --git a/snippets/sniptools.cpp b/snippets/sniptools.cpp new file mode 100644 index 0000000..961979d --- /dev/null +++ b/snippets/sniptools.cpp @@ -0,0 +1,80 @@ +#include "stdafx.h" +#include +#include +#include "CharTools.h" + +/// +dllx const char* sniptools_file_get_contents(const char* path) { + std::ifstream fs(path); + std::ostringstream out{}; + out << fs.rdbuf(); + static std::string result{}; + result.assign(out.str()); + return result.c_str(); +} +/// +dllx const char* sniptools_string_trim(const char* str) { + static std::string s; + s = str; + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { + return !std::isspace(ch); + })); + s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { + return !std::isspace(ch); + }).base(), s.end()); + return s.c_str(); +} +/// +dllx const char* sniptools_string_trim_start(const char* str) { + static std::string s; + s = str; + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { + return !std::isspace(ch); + })); + return s.c_str(); +} +/// +dllx const char* sniptools_string_trim_end(const char* str) { + static std::string s; + s = str; + s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { + return !std::isspace(ch); + }).base(), s.end()); + return s.c_str(); +} +/// +dllx double sniptools_string_is_ident(const char* str) { + int n = strlen(str); + if (n == 0 || !CharTools::isIdentStart(str[0])) return false; + for (int i = 1; i < n; i++) { + if (!CharTools::isIdent(str[i])) return false; + } + return true; +} + +static std::queue sniptools_string_split_parts{}; +/// +dllx double sniptools_string_split_start(const char* str, const char* sep) { + static std::string tmp{}; + tmp = str; + + sniptools_string_split_parts = std::queue(); + size_t pos = 0; + size_t start = 0; + while ((pos = tmp.find(sep, start)) != std::string::npos) { + std::string part = tmp.substr(start, pos - start); + sniptools_string_split_parts.push(part); + start = pos + 1; + } + std::string part = tmp.substr(start); + sniptools_string_split_parts.push(part); + return sniptools_string_split_parts.size(); +} +/// +dllx const char* sniptools_string_split_next() { + if (sniptools_string_split_parts.empty()) return ""; + static std::string result{}; + result = sniptools_string_split_parts.front(); + sniptools_string_split_parts.pop(); + return result.c_str(); +} \ No newline at end of file diff --git a/snippets/stdafx.cpp b/snippets/stdafx.cpp new file mode 100644 index 0000000..c301026 --- /dev/null +++ b/snippets/stdafx.cpp @@ -0,0 +1,23 @@ +// stdafx.cpp : source file that includes just the standard includes +// snippets.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file + +#ifdef _WINDOWS +// https://yal.cc/printf-without-standard-library/ +void show_error(const char* pszFormat, ...) { + char buf[1024]; + va_list argList; + va_start(argList, pszFormat); + wvsprintfA(buf, pszFormat, argList); + va_end(argList); + auto len = strlen(buf); + buf[len] = '\n'; + buf[++len] = 0; + MessageBoxA(0, buf, gm_extension_name, MB_OK | MB_ICONERROR); +} +#endif diff --git a/snippets/stdafx.h b/snippets/stdafx.h new file mode 100644 index 0000000..a84bc8e --- /dev/null +++ b/snippets/stdafx.h @@ -0,0 +1,32 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once +#define gm_extension_name "snippets" + +#ifdef _WINDOWS + #include "targetver.h" + + #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + #include +#endif + +#if defined(WIN32) +#define dllx extern "C" __declspec(dllexport) +#elif defined(GNUC) +#define dllx extern "C" __attribute__ ((visibility("default"))) +#else +#define dllx extern "C" +#endif + +#define trace(...) { printf("[" gm_extension_name ":%d] ", __LINE__); printf(__VA_ARGS__); printf("\n"); fflush(stdout); } + +void show_error(const char* format, ...); + +#include "gml_ext.h" +#include +#include + +// TODO: reference additional headers your program requires here \ No newline at end of file diff --git a/snippets/targetver.h b/snippets/targetver.h new file mode 100644 index 0000000..87c0086 --- /dev/null +++ b/snippets/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/snippets_gml/.gitignore b/snippets_gml/.gitignore new file mode 100644 index 0000000..12c5023 --- /dev/null +++ b/snippets_gml/.gitignore @@ -0,0 +1,5 @@ +snippets.cpp +/snippets.dll +*.gb1 +*.zip +tester/*.exe \ No newline at end of file diff --git a/snippets_gml/extension.gmk-snips b/snippets_gml/extension.gmk-snips new file mode 100644 index 0000000..c6a570b --- /dev/null +++ b/snippets_gml/extension.gmk-snips @@ -0,0 +1,3 @@ +# comment +snippets.gml +snippets_core.gml \ No newline at end of file diff --git a/snippets_gml/pack.bat b/snippets_gml/pack.bat new file mode 100644 index 0000000..40f4eb7 --- /dev/null +++ b/snippets_gml/pack.bat @@ -0,0 +1,11 @@ +del /Q snippets-ext.zip +del /Q snippets-tester.zip + +cmd /C 7z a snippets-ext.zip snippets.gml snippets.dll +cd tester +cmd /C 7z a ..\snippets-ext.zip fnames events.gml + +cmd /C 7z a ..\snippets-tester.zip * +cmd /C 7z d ..\snippets-tester.zip snippet_tester.gb1 + +pause \ No newline at end of file diff --git a/snippets_gml/snippets.gml b/snippets_gml/snippets.gml new file mode 100644 index 0000000..e67c3ee --- /dev/null +++ b/snippets_gml/snippets.gml @@ -0,0 +1,518 @@ +#define snippet_init_dll +/// snippet_init_dll() +var _path, _dir; + +_dir = ""; +_path = _dir + "snippets.dll"; +global.f_snippet_event_get_type = external_define(_path, "snippet_event_get_type", dll_cdecl, ty_real, 1, ty_string); +global.f_snippet_event_get_number = external_define(_path, "snippet_event_get_number", dll_cdecl, ty_real, 1, ty_string); +global.f_snippet_event_get_number_object = external_define(_path, "snippet_event_get_number_object", dll_cdecl, ty_string, 0); +global.f_snippet_event_register = external_define(_path, "snippet_event_register", dll_cdecl, ty_real, 3, ty_string, ty_real, ty_real); +global.f_snippet_event_register_type = external_define(_path, "snippet_event_register_type", dll_cdecl, ty_real, 3, ty_string, ty_real, ty_real); +global.f_snippet_parse_event_file = external_define(_path, "snippet_parse_event_file", dll_cdecl, ty_real, 1, ty_string); +global.f_snippet_function_add = external_define(_path, "snippet_function_add", dll_cdecl, ty_real, 1, ty_string); +global.f_snippet_function_remove = external_define(_path, "snippet_function_remove", dll_cdecl, ty_real, 1, ty_string); +global.f_snippet_parse_api_entry = external_define(_path, "snippet_parse_api_entry", dll_cdecl, ty_real, 1, ty_string); +global.f_snippet_parse_api_file = external_define(_path, "snippet_parse_api_file", dll_cdecl, ty_real, 1, ty_string); +global.f_sniptools_file_get_contents = external_define(_path, "sniptools_file_get_contents", dll_cdecl, ty_string, 1, ty_string); +global.f_sniptools_string_trim = external_define(_path, "sniptools_string_trim", dll_cdecl, ty_string, 1, ty_string); +global.f_sniptools_string_trim_start = external_define(_path, "sniptools_string_trim_start", dll_cdecl, ty_string, 1, ty_string); +global.f_sniptools_string_trim_end = external_define(_path, "sniptools_string_trim_end", dll_cdecl, ty_string, 1, ty_string); +global.f_sniptools_string_is_ident = external_define(_path, "sniptools_string_is_ident", dll_cdecl, ty_real, 1, ty_string); +global.f_sniptools_string_split_start = external_define(_path, "sniptools_string_split_start", dll_cdecl, ty_real, 2, ty_string, ty_string); +global.f_sniptools_string_split_next = external_define(_path, "sniptools_string_split_next", dll_cdecl, ty_string, 0); +global.f_snippet_preproc_run = external_define(_path, "snippet_preproc_run", dll_cdecl, ty_real, 3, ty_string, ty_string, ty_string); +global.f_snippet_preproc_pop_name = external_define(_path, "snippet_preproc_pop_name", dll_cdecl, ty_string, 0); +global.f_snippet_preproc_pop_code = external_define(_path, "snippet_preproc_pop_code", dll_cdecl, ty_string, 0); +global.f_snippet_preproc_concat_names = external_define(_path, "snippet_preproc_concat_names", dll_cdecl, ty_string, 0); + + +#define snippet_init +/// () +snippet_init_dll(); +var i; i = 0; +global.__snippet__argument[0] = 0; +global.__snippet__argument_count = 0; +global.__snippet__result = 0; +global.__snippet__map = ds_map_create(); // name -> ID +global.__snippet__code_map = ds_map_create(); +global.__snippet__next = 100; + +// blank object is used to count objects and as a properties drop-in +global.__snippet__blank_object = object_add(); + +// populate object names<->ids +global.__snippet__object_names = ds_map_create(); +global.__snippet__object_ids = ds_map_create(); +for (i = 0; i < global.__snippet__blank_object; i += 1) if (object_exists(i)) { + var _name; _name = object_get_name(i); + ds_map_add(global.__snippet__object_ids, _name, i); +} + +// contains things like "create\nstep" in case we need to delete events later +global.__snippet__object_events = ds_map_create(); + +snippet_parse_api_file("fnames"); +snippet_parse_event_file("events.gml"); + +// collect scripts: +var _max_gap; _max_gap = 1024; +var _gap; _gap = _max_gap; +var _seen_snippet_init; _seen_snippet_init = false; +while (_gap < _max_gap || !_seen_snippet_init) { + if (script_exists(i)) { + _gap = 0; + var _name; _name = script_get_name(i); + if (!_seen_snippet_init && _name == "snippet_init") _seen_snippet_init = true; + snippet_function_add(_name); + } + i += 1; + _gap += 1; +} +//var _script_time = current_time - _time; + +/*show_message( + "Parse time: " + string(_fnames_time) + + "#Script time: " + string(_script_time) +);*/ + +#define snippet_execute_string +/// (gml_code) +var n; n = external_call(global.f_snippet_preproc_run, "", argument0, "define"); +var _result; _result = 0; +repeat (n) { + var _name; _name = external_call(global.f_snippet_preproc_pop_name); + var _code; _code = external_call(global.f_snippet_preproc_pop_code); + _result = execute_string(_code); +} +return _result; + +#define snippet_define +/// (name, gml_code) +var n; n = external_call(global.f_snippet_preproc_run, argument0, argument1, "define"); +repeat (n) { + var _name; _name = external_call(global.f_snippet_preproc_pop_name); + var _code; _code = external_call(global.f_snippet_preproc_pop_code); + snippet_define_raw(_name, _code); +} + +#define snippet_define_raw +/// (name, raw_gml_code) +var _name; _name = argument0; +var _code; _code = argument1; +// show_message(_name + ":" + chr(10) + _gml); + +// unregister name so that subsequent snippets call the snippet and not the built-in: +snippet_function_remove(_name); + +// one event per snippet: +var _enumb; +if (ds_map_exists(global.__snippet__map, _name)) { + _enumb = ds_map_find_value(global.__snippet__map, _name); + object_event_clear(obj_snippets, ev_alarm, _enumb); + ds_map_replace(global.__snippet__code_map, _name, _code); +} else { + _enumb = global.__snippet__next; + global.__snippet__next += 1; + + ds_map_add(global.__snippet__map, _name, _enumb); + ds_map_add(global.__snippet__code_map, _name, _code); +} +object_event_add(obj_snippets, ev_alarm, _enumb, _code); + +/* one object per snippet: +var _obj; +if (ds_map_exists(global.__snippet__map, _name)) { + _obj = ds_map_find_value(global.__snippet__map, _name); + object_event_clear(_obj, ev_other, 257); +} else { + _obj = object_add(); + ds_map_add(global.__snippet__map, _name, _obj); +} +object_event_add(_obj, ev_other, 257, _code);*/ + +#define snippet_exists +/// (name)-> +return ds_map_exists(global.__snippet__map, argument0); + +#define snippet_get_code +/// (name)-> +if (ds_map_exists(global.__snippet__code_map, argument0)) { + return ds_map_find_value(global.__snippet__code_map, argument0); +} else return ""; + +#define snippet_call +/// (name, ...args) +var _name; _name = argument0; + +// store old arguments: +var _old_argc; _old_argc = global.__snippet__argument_count; +var _old_args; _old_args = global.__snippet__argument; +var i; i = 1; +repeat (_old_argc - 1) { + _old_args[i] = global.__snippet__argument[i]; + i += 1; +} + +// copy new arguments: +var _argc; _argc = argument_count - 1; +global.__snippet__argument_count = _argc; +i = 0; +repeat (_argc) { + global.__snippet__argument[i] = argument[i + 1]; + i += 1; +} + +// clear "extra" arguments: +repeat (_old_argc - _argc) { + global.__snippet__argument[i] = 0; + i += 1; +} + +if (ds_map_exists(global.__snippet__map, _name)) { + // one snippet per event: + var _enumb; _enumb = ds_map_find_value(global.__snippet__map, _name); + event_perform_object(obj_snippets, ev_alarm, _enumb); + //*/ + + /* one snippet per object: + var _obj; _obj = ds_map_find_value(global.__snippet__map, _name); + event_perform_object(_obj, ev_other, 257); + //*/ +} else { + show_error('Snippet "' + _name + '" does not exist!', true); +} + +// restore previous arguments: +global.__snippet__argument_count = _old_argc; +i = 0; +repeat (_old_argc) { + global.__snippet__argument[i] = _old_args[i]; + i += 1; +} + +// clear the extra arguments (the other way around!): +repeat (_argc - _old_argc) { + global.__snippet__argument[i] = 0; + i += 1; +} + +return global.__snippet__result; + +#define snippet_prepare_object +/// (name) +var _name; _name = argument0; +if (ds_map_exists(global.__snippet__object_ids, _name)) { + return ds_map_find_value(global.__snippet__object_ids, _name); +} else { + var _obj; _obj = object_add(); + ds_map_add(global.__snippet__object_ids, _name, _obj); + ds_map_add(global.__snippet__object_names, _obj, _name); + if (sniptools_string_is_ident(_name)) { + // register so that it's globally accessible in code + execute_string('globalvar ' + _name + ';' + _name + ' = argument0', _obj); + } + return _obj; +} + +#define snippet_define_object +/// (name, gml_code) +var _name; _name = argument0; +var n; n = external_call(global.f_snippet_preproc_run, "properties", argument1, "event"); +var _obj; _obj = snippet_prepare_object(_name); + +// clear old events: +var _events; _events = external_call(global.f_snippet_preproc_concat_names); +if (ds_map_exists(global.__snippet__object_events, _obj)) { + var _old_events; _old_events = ds_map_find_value(global.__snippet__object_events, _obj); + repeat (sniptools_string_split_start(_old_events, chr(10))) { + var _ename; _ename = sniptools_string_split_next(); + var _type; _type = snippet_event_get_type(_ename); + var _numb; _numb = snippet_event_get_number(_ename); + if (_type == -1) { + if (_numb != 0) continue; + // revert properties! + object_set_visible(_obj, true); + object_set_depth(_obj, 0); + object_set_persistent(_obj, false); + object_set_parent(_obj, -1); + object_set_sprite(_obj, -1); + object_set_mask(_obj, -1); + object_set_solid(_obj, false); + continue; + } + if (_numb == -1) continue; + if (_numb == -2) { // object + _numb = snippet_object_get_index(snippet_event_get_number_object()); + if (_numb == -1) continue; + } + object_event_clear(_obj, _type, _numb); + } + ds_map_replace(global.__snippet__object_events, _obj, _events); +} else { + ds_map_add(global.__snippet__object_events, _obj, _events); +} + +repeat (n) { + var _ename; _ename = external_call(global.f_snippet_preproc_pop_name); + var _code; _code = external_call(global.f_snippet_preproc_pop_code); + var _type; _type = snippet_event_get_type(_ename); + var _numb; _numb = snippet_event_get_number(_ename); + if (_type == -1) { + if (_numb != 0) { + show_error('"' + _ename + '" is not a known event type!', false); + continue; + } + // properties! + with (instance_create(0, 0, global.__snippet__blank_object)) { + visible = object_get_visible(_obj); + depth = object_get_depth(_obj); + persistent = object_get_persistent(_obj); + parent_index = object_get_parent(_obj); + sprite_index = object_get_sprite(_obj); + mask_index = object_get_mask(_obj); + solid = object_get_solid(_obj); + // + execute_string(_code); + // + object_set_visible(_obj, visible); + object_set_depth(_obj, depth); + object_set_persistent(_obj, persistent); + object_set_parent(_obj, parent_index); + object_set_sprite(_obj, sprite_index); + object_set_mask(_obj, mask_index); + object_set_solid(_obj, solid); + // + instance_destroy(); + } + continue; + } + if (_numb == -1) { + show_error('"' + _ename + '" is not a known event (sub-)type!', false); + continue; + } + if (_numb == -2) { + var _cobj_name; _cobj_name = snippet_event_get_number_object(); + var _cobj; _cobj = snippet_object_get_index(_cobj_name); + if (_cobj == -1) { + show_error('"' + _cobj_name + '" in "' + _ename + '" is not a known object!', false); + continue; + } + _numb = _cobj; + } + object_event_add(_obj, _type, _numb, _code); + /*show_message(_name + + chr(10) + _ename + " -> (" + string(_type) + ", " + string(_numb) + ")" + + chr(10) + _code + );*/ +} +return _obj; + +#define snippet_object_get_name +/// (object_index)-> +if (ds_map_exists(global.__snippet__object_names, argument0)) { + return ds_map_find_value(global.__snippet__object_names, argument0); +} else { + return object_get_name(argument0); +} + +#define snippet_object_get_index +/// (object_name)-> +if (ds_map_exists(global.__snippet__object_ids, argument0)) { + return ds_map_find_value(global.__snippet__object_ids, argument0); +} else { + return -1; +} + +#define snippet_load_list +/// (path_list, dir) +var _files; _files = argument0; +var _pre; _pre = argument1; +if (_pre != "") switch (string_char_at(_pre, string_length(_pre))) { + case '/': case '\': break; + default: _pre += '\'; +} +var i; +var n; n = ds_list_size(_files); +var _grid; _grid = ds_grid_create(n, 4); // [kind, path, name, meta] + +// figure out what to do with each thing: +for (i = 0; i < n; i += 1) { + var _file; _file = ds_list_find_value(_files, i); + if (string_char_at(_file, 1) == '>') { + ds_grid_set(_grid, i, 0, "inline"); + ds_grid_set(_grid, i, 1, sniptools_string_trim_start(string_delete(_file, 1, 1))); + continue; + } + + var _meta; _meta = 0; + var _sep; _sep = string_pos('>', _file); + if (_sep != 0) { + _meta = sniptools_string_trim_start(string_delete(_file, 1, _sep)); + _file = sniptools_string_trim_end(string_copy(_file, 1, _sep - 1)); + } + + var _kind; _kind = ""; + + var _name; _name = filename_name(_file); + repeat (2) { + if (filename_ext(_name) == "") break; + _name = filename_change_ext(_name, ""); + } + + var _ext; _ext = string_lower(filename_ext(_file)); + if (_ext == ".gml") { + var _noext; _noext = filename_change_ext(_file, ""); + var _ext2; _ext2 = string_lower(filename_ext(_noext)); + switch (_ext2) { + case "": _kind = "script"; break; + case ".object": _kind = "object"; break; + case ".global": _kind = "global"; break; + default: + show_error('"' + _noext + '" is not a recognized sub-extension (for "' + _file + '")', false); + } + } else { + show_error('No idea how to load "' + _ext + '" files (for "' + _file + '")', false); + } + ds_grid_set(_grid, i, 0, _kind); + ds_grid_set(_grid, i, 1, _file); + ds_grid_set(_grid, i, 2, _name); + ds_grid_set(_grid, i, 3, _meta); +} + +// should we create objects beforehand? It's okay so long as children appear after parents +/*for (i = 0; i < n; i += 1) { + if (ds_grid_get(_grid, i, 0) == "object") { + snippet_prepare_object(ds_grid_get(_grid, i, 2)); + } +}*/ + +// load the code bits: +for (i = 0; i < n; i += 1) { + var _kind; _kind = ds_grid_get(_grid, i, 0); + var _file; _file = ds_grid_get(_grid, i, 1); + var _name; _name = ds_grid_get(_grid, i, 2); + var _meta; _meta = ds_grid_get(_grid, i, 3); + switch (_kind) { + case "script": case "object": + var _gml; _gml = sniptools_file_get_contents(_pre + _file); + //show_message(_name + ":" + chr(10) + _gml); + if (_gml == "") { + show_error('"' + _file + '" is missing or empty!', false); + } else if (_kind == "object") { + var _obj; _obj = snippet_define_object(_name, _gml); + if (is_string(_meta)) { + if (_meta == "") { + execute_string('instance_create(0, 0, argument0)', _obj); + } else { + show_error('Unsupported meta "' + _meta + '" for "' + _file + '"', false); + } + _meta = 0; + } + } else { + snippet_define(_name, _gml); + } + break; + case "global": + var _gml; _gml = sniptools_file_get_contents(_pre + _file); + if (_gml == "") { + show_error('"' + _file + '" is missing or empty!', false); + } else { + snippet_execute_string(_gml); + } + break; + case "inline": + snippet_execute_string(_file); + break; + } + if (is_string(_meta)) { + show_error('">' + _meta + '" was specified for "' + _file + '" but is not supported for the file type.', false) + } +} +ds_grid_destroy(_grid); + +#define snippet_load_listfile +/// (path) +var _path; _path = argument0; +var _tf; _tf = file_text_open_read(_path); +var _todo; _todo = ds_list_create(); +var _pre; _pre = filename_path(_path); +while (!file_text_eof(_tf)) { + var _line; _line = file_text_read_string(_tf); + file_text_readln(_tf); + + if (sniptools_string_trim_end(_line) == "") continue; + if (string_char_at(_line, 1) == "#") continue; + + ds_list_add(_todo, _line); +} +file_text_close(_tf); +snippet_load_list(_todo, _pre); +ds_list_destroy(_todo); +#define snippet_event_get_type +/// snippet_event_get_type(name) +return external_call(global.f_snippet_event_get_type, argument0); + +#define snippet_event_get_number +/// snippet_event_get_number(name) +return external_call(global.f_snippet_event_get_number, argument0); + +#define snippet_event_get_number_object +/// snippet_event_get_number_object() +return external_call(global.f_snippet_event_get_number_object); + +#define snippet_event_register +/// snippet_event_register(name, type, number) +return external_call(global.f_snippet_event_register, argument0, argument1, argument2); + +#define snippet_event_register_type +/// snippet_event_register_type(name, type, arg_type) +return external_call(global.f_snippet_event_register_type, argument0, argument1, argument2); + +#define snippet_parse_event_file +/// snippet_parse_event_file(path) +return external_call(global.f_snippet_parse_event_file, argument0); + +#define snippet_function_add +/// snippet_function_add(name) +return external_call(global.f_snippet_function_add, argument0); + +#define snippet_function_remove +/// snippet_function_remove(name) +return external_call(global.f_snippet_function_remove, argument0); + +#define snippet_parse_api_entry +/// snippet_parse_api_entry(line) +return external_call(global.f_snippet_parse_api_entry, argument0); + +#define snippet_parse_api_file +/// snippet_parse_api_file(path) +return external_call(global.f_snippet_parse_api_file, argument0); + +#define sniptools_file_get_contents +/// sniptools_file_get_contents(path) +return external_call(global.f_sniptools_file_get_contents, argument0); + +#define sniptools_string_trim +/// sniptools_string_trim(str) +return external_call(global.f_sniptools_string_trim, argument0); + +#define sniptools_string_trim_start +/// sniptools_string_trim_start(str) +return external_call(global.f_sniptools_string_trim_start, argument0); + +#define sniptools_string_trim_end +/// sniptools_string_trim_end(str) +return external_call(global.f_sniptools_string_trim_end, argument0); + +#define sniptools_string_is_ident +/// sniptools_string_is_ident(str) +return external_call(global.f_sniptools_string_is_ident, argument0); + +#define sniptools_string_split_start +/// sniptools_string_split_start(str, sep) +return external_call(global.f_sniptools_string_split_start, argument0, argument1); + +#define sniptools_string_split_next +/// sniptools_string_split_next() +return external_call(global.f_sniptools_string_split_next); diff --git a/snippets_gml/snippets.gmxgen81 b/snippets_gml/snippets.gmxgen81 new file mode 100644 index 0000000..8534f10 --- /dev/null +++ b/snippets_gml/snippets.gmxgen81 @@ -0,0 +1,4 @@ +>snippets.gml +snippets_autogen.gml +snippets_core_gm81.gml +snippets.dll \ No newline at end of file diff --git a/snippets_gml/snippets_core.gml b/snippets_gml/snippets_core.gml new file mode 100644 index 0000000..71e828b --- /dev/null +++ b/snippets_gml/snippets_core.gml @@ -0,0 +1,422 @@ +#define snippet_init +/// () +snippet_init_dll(); +var i = 0; +global.__snippet__argument[0] = 0; +global.__snippet__argument_count = 0; +global.__snippet__result = 0; +global.__snippet__map = ds_map_create(); // name -> ID +global.__snippet__code_map = ds_map_create(); +global.__snippet__next = 100; + +// blank object is used to count objects and as a properties drop-in +global.__snippet__blank_object = object_add(); + +// populate object names<->ids +global.__snippet__object_names = ds_map_create(); +global.__snippet__object_ids = ds_map_create(); +for (i = 0; i < global.__snippet__blank_object; i += 1) if (object_exists(i)) { + var _name = object_get_name(i); + ds_map_add(global.__snippet__object_ids, _name, i); +} + +// contains things like "create\nstep" in case we need to delete events later +global.__snippet__object_events = ds_map_create(); + +snippet_parse_api_file("fnames"); +snippet_parse_event_file("events.gml"); + +// collect scripts: +var _max_gap = 1024; +var _gap = _max_gap; +var _seen_snippet_init = false; +while (_gap < _max_gap || !_seen_snippet_init) { + if (script_exists(i)) { + _gap = 0; + var _name = script_get_name(i); + if (!_seen_snippet_init && _name == "snippet_init") _seen_snippet_init = true; + snippet_function_add(_name); + } + i += 1; + _gap += 1; +} +//var _script_time = current_time - _time; + +/*show_message( + "Parse time: " + string(_fnames_time) + + "#Script time: " + string(_script_time) +);*/ + +#define snippet_execute_string +/// (gml_code) +var n = external_call(global.f_snippet_preproc_run, "", argument0, "define"); +var _result = 0; +repeat (n) { + var _name = external_call(global.f_snippet_preproc_pop_name); + var _code = external_call(global.f_snippet_preproc_pop_code); + _result = execute_string(_code); +} +return _result; + +#define snippet_define +/// (name, gml_code) +var n = external_call(global.f_snippet_preproc_run, argument0, argument1, "define"); +repeat (n) { + var _name = external_call(global.f_snippet_preproc_pop_name); + var _code = external_call(global.f_snippet_preproc_pop_code); + snippet_define_raw(_name, _code); +} + +#define snippet_define_raw +/// (name, raw_gml_code) +var _name = argument0; +var _code = argument1; +// show_message(_name + ":" + chr(10) + _gml); + +// unregister name so that subsequent snippets call the snippet and not the built-in: +snippet_function_remove(_name); + +// one event per snippet: +var _enumb; +if (ds_map_exists(global.__snippet__map, _name)) { + _enumb = ds_map_find_value(global.__snippet__map, _name); + object_event_clear(obj_snippets, ev_alarm, _enumb); + ds_map_replace(global.__snippet__code_map, _name, _code); +} else { + _enumb = global.__snippet__next; + global.__snippet__next += 1; + + ds_map_add(global.__snippet__map, _name, _enumb); + ds_map_add(global.__snippet__code_map, _name, _code); +} +object_event_add(obj_snippets, ev_alarm, _enumb, _code); + +/* one object per snippet: +var _obj; +if (ds_map_exists(global.__snippet__map, _name)) { + _obj = ds_map_find_value(global.__snippet__map, _name); + object_event_clear(_obj, ev_other, 257); +} else { + _obj = object_add(); + ds_map_add(global.__snippet__map, _name, _obj); +} +object_event_add(_obj, ev_other, 257, _code);*/ + +#define snippet_exists +/// (name)-> +return ds_map_exists(global.__snippet__map, argument0); + +#define snippet_get_code +/// (name)-> +if (ds_map_exists(global.__snippet__code_map, argument0)) { + return ds_map_find_value(global.__snippet__code_map, argument0); +} else return ""; + +#define snippet_call +/// (name, ...args) +var _name = argument0; + +// store old arguments: +var _old_argc = global.__snippet__argument_count; +var _old_args = global.__snippet__argument; +var i = 1; +repeat (_old_argc - 1) { + _old_args[i] = global.__snippet__argument[i]; + i += 1; +} + +// copy new arguments: +var _argc = argument_count - 1; +global.__snippet__argument_count = _argc; +i = 0; +repeat (_argc) { + global.__snippet__argument[i] = argument[i + 1]; + i += 1; +} + +// clear "extra" arguments: +repeat (_old_argc - _argc) { + global.__snippet__argument[i] = 0; + i += 1; +} + +if (ds_map_exists(global.__snippet__map, _name)) { + // one snippet per event: + var _enumb = ds_map_find_value(global.__snippet__map, _name); + event_perform_object(obj_snippets, ev_alarm, _enumb); + //*/ + + /* one snippet per object: + var _obj = ds_map_find_value(global.__snippet__map, _name); + event_perform_object(_obj, ev_other, 257); + //*/ +} else { + show_error('Snippet "' + _name + '" does not exist!', true); +} + +// restore previous arguments: +global.__snippet__argument_count = _old_argc; +i = 0; +repeat (_old_argc) { + global.__snippet__argument[i] = _old_args[i]; + i += 1; +} + +// clear the extra arguments (the other way around!): +repeat (_argc - _old_argc) { + global.__snippet__argument[i] = 0; + i += 1; +} + +return global.__snippet__result; + +#define snippet_prepare_object +/// (name) +var _name = argument0; +if (ds_map_exists(global.__snippet__object_ids, _name)) { + return ds_map_find_value(global.__snippet__object_ids, _name); +} else { + var _obj = object_add(); + ds_map_add(global.__snippet__object_ids, _name, _obj); + ds_map_add(global.__snippet__object_names, _obj, _name); + if (sniptools_string_is_ident(_name)) { + // register so that it's globally accessible in code + execute_string('globalvar ' + _name + ';' + _name + ' = argument0', _obj); + } + return _obj; +} + +#define snippet_define_object +/// (name, gml_code) +var _name = argument0; +var n = external_call(global.f_snippet_preproc_run, "properties", argument1, "event"); +var _obj = snippet_prepare_object(_name); + +// clear old events: +var _events = external_call(global.f_snippet_preproc_concat_names); +if (ds_map_exists(global.__snippet__object_events, _obj)) { + var _old_events = ds_map_find_value(global.__snippet__object_events, _obj); + repeat (sniptools_string_split_start(_old_events, chr(10))) { + var _ename = sniptools_string_split_next(); + var _type = snippet_event_get_type(_ename); + var _numb = snippet_event_get_number(_ename); + if (_type == -1) { + if (_numb != 0) continue; + // revert properties! + object_set_visible(_obj, true); + object_set_depth(_obj, 0); + object_set_persistent(_obj, false); + object_set_parent(_obj, -1); + object_set_sprite(_obj, -1); + object_set_mask(_obj, -1); + object_set_solid(_obj, false); + continue; + } + if (_numb == -1) continue; + if (_numb == -2) { // object + _numb = snippet_object_get_index(snippet_event_get_number_object()); + if (_numb == -1) continue; + } + object_event_clear(_obj, _type, _numb); + } + ds_map_replace(global.__snippet__object_events, _obj, _events); +} else { + ds_map_add(global.__snippet__object_events, _obj, _events); +} + +repeat (n) { + var _ename = external_call(global.f_snippet_preproc_pop_name); + var _code = external_call(global.f_snippet_preproc_pop_code); + var _type = snippet_event_get_type(_ename); + var _numb = snippet_event_get_number(_ename); + if (_type == -1) { + if (_numb != 0) { + show_error('"' + _ename + '" is not a known event type!', false); + continue; + } + // properties! + with (instance_create(0, 0, global.__snippet__blank_object)) { + visible = object_get_visible(_obj); + depth = object_get_depth(_obj); + persistent = object_get_persistent(_obj); + parent_index = object_get_parent(_obj); + sprite_index = object_get_sprite(_obj); + mask_index = object_get_mask(_obj); + solid = object_get_solid(_obj); + // + execute_string(_code); + // + object_set_visible(_obj, visible); + object_set_depth(_obj, depth); + object_set_persistent(_obj, persistent); + object_set_parent(_obj, parent_index); + object_set_sprite(_obj, sprite_index); + object_set_mask(_obj, mask_index); + object_set_solid(_obj, solid); + // + instance_destroy(); + } + continue; + } + if (_numb == -1) { + show_error('"' + _ename + '" is not a known event (sub-)type!', false); + continue; + } + if (_numb == -2) { + var _cobj_name = snippet_event_get_number_object(); + var _cobj = snippet_object_get_index(_cobj_name); + if (_cobj == -1) { + show_error('"' + _cobj_name + '" in "' + _ename + '" is not a known object!', false); + continue; + } + _numb = _cobj; + } + object_event_add(_obj, _type, _numb, _code); + /*show_message(_name + + chr(10) + _ename + " -> (" + string(_type) + ", " + string(_numb) + ")" + + chr(10) + _code + );*/ +} +return _obj; + +#define snippet_object_get_name +/// (object_index)-> +if (ds_map_exists(global.__snippet__object_names, argument0)) { + return ds_map_find_value(global.__snippet__object_names, argument0); +} else { + return object_get_name(argument0); +} + +#define snippet_object_get_index +/// (object_name)-> +if (ds_map_exists(global.__snippet__object_ids, argument0)) { + return ds_map_find_value(global.__snippet__object_ids, argument0); +} else { + return -1; +} + +#define snippet_load_list +/// (path_list, dir) +var _files = argument0; +var _pre = argument1; +if (_pre != "") switch (string_char_at(_pre, string_length(_pre))) { + case '/': case '\': break; + default: _pre += '\'; +} +var i; +var n = ds_list_size(_files); +var _grid = ds_grid_create(n, 4); // [kind, path, name, meta] + +// figure out what to do with each thing: +for (i = 0; i < n; i += 1) { + var _file = ds_list_find_value(_files, i); + if (string_char_at(_file, 1) == '>') { + ds_grid_set(_grid, i, 0, "inline"); + ds_grid_set(_grid, i, 1, sniptools_string_trim_start(string_delete(_file, 1, 1))); + continue; + } + + var _meta = 0; + var _sep = string_pos('>', _file); + if (_sep != 0) { + _meta = sniptools_string_trim_start(string_delete(_file, 1, _sep)); + _file = sniptools_string_trim_end(string_copy(_file, 1, _sep - 1)); + } + + var _kind = ""; + + var _name = filename_name(_file); + repeat (2) { + if (filename_ext(_name) == "") break; + _name = filename_change_ext(_name, ""); + } + + var _ext = string_lower(filename_ext(_file)); + if (_ext == ".gml") { + var _noext = filename_change_ext(_file, ""); + var _ext2 = string_lower(filename_ext(_noext)); + switch (_ext2) { + case "": _kind = "script"; break; + case ".object": _kind = "object"; break; + case ".global": _kind = "global"; break; + default: + show_error('"' + _noext + '" is not a recognized sub-extension (for "' + _file + '")', false); + } + } else { + show_error('No idea how to load "' + _ext + '" files (for "' + _file + '")', false); + } + ds_grid_set(_grid, i, 0, _kind); + ds_grid_set(_grid, i, 1, _file); + ds_grid_set(_grid, i, 2, _name); + ds_grid_set(_grid, i, 3, _meta); +} + +// should we create objects beforehand? It's okay so long as children appear after parents +/*for (i = 0; i < n; i += 1) { + if (ds_grid_get(_grid, i, 0) == "object") { + snippet_prepare_object(ds_grid_get(_grid, i, 2)); + } +}*/ + +// load the code bits: +for (i = 0; i < n; i += 1) { + var _kind = ds_grid_get(_grid, i, 0); + var _file = ds_grid_get(_grid, i, 1); + var _name = ds_grid_get(_grid, i, 2); + var _meta = ds_grid_get(_grid, i, 3); + switch (_kind) { + case "script": case "object": + var _gml = sniptools_file_get_contents(_pre + _file); + //show_message(_name + ":" + chr(10) + _gml); + if (_gml == "") { + show_error('"' + _file + '" is missing or empty!', false); + } else if (_kind == "object") { + var _obj = snippet_define_object(_name, _gml); + if (is_string(_meta)) { + if (_meta == "") { + execute_string('instance_create(0, 0, argument0)', _obj); + } else { + show_error('Unsupported meta "' + _meta + '" for "' + _file + '"', false); + } + _meta = 0; + } + } else { + snippet_define(_name, _gml); + } + break; + case "global": + var _gml = sniptools_file_get_contents(_pre + _file); + if (_gml == "") { + show_error('"' + _file + '" is missing or empty!', false); + } else { + snippet_execute_string(_gml); + } + break; + case "inline": + snippet_execute_string(_file); + break; + } + if (is_string(_meta)) { + show_error('">' + _meta + '" was specified for "' + _file + '" but is not supported for the file type.', false) + } +} +ds_grid_destroy(_grid); + +#define snippet_load_listfile +/// (path) +var _path = argument0; +var _tf = file_text_open_read(_path); +var _todo = ds_list_create(); +var _pre = filename_path(_path); +while (!file_text_eof(_tf)) { + var _line = file_text_read_string(_tf); + file_text_readln(_tf); + + if (sniptools_string_trim_end(_line) == "") continue; + if (string_char_at(_line, 1) == "#") continue; + + ds_list_add(_todo, _line); +} +file_text_close(_tf); +snippet_load_list(_todo, _pre); +ds_list_destroy(_todo); \ No newline at end of file diff --git a/snippets_gml/tester/events.gml b/snippets_gml/tester/events.gml new file mode 100644 index 0000000..47a7a6d --- /dev/null +++ b/snippets_gml/tester/events.gml @@ -0,0 +1,128 @@ +-1:0 properties +0:0 create +1:0 destroy + +2:0 alarm0 +2:1 alarm1 +2:2 alarm2 +2:3 alarm3 +2:4 alarm4 +2:5 alarm5 +2:6 alarm6 +2:7 alarm7 +2:8 alarm8 +2:9 alarm9 +2:10 alarm10 +2:11 alarm11 + +3:0 step +3:1 step_begin +3:2 step_end + +6:0 mouse_left_button +6:4 mouse_left_press +6:7 mouse_left_release +6:2 mouse_middle_button +6:6 mouse_middle_press +6:9 mouse_middle_release +6:1 mouse_right_button +6:5 mouse_right_press +6:8 mouse_right_release +6:10 mouse_enter +6:11 mouse_leave +6:60 mouse_wheel_up +6:61 mouse_wheel_down +6:50 mouse_global_left_button +6:53 mouse_global_left_press +6:56 mouse_global_left_release +6:52 mouse_global_middle_button +6:55 mouse_global_middle_press +6:58 mouse_global_middle_release +6:51 mouse_global_right_button +6:54 mouse_global_right_press +6:57 mouse_global_right_release +6:3 mouse_no_button + +7:9 other_no_more_health +7:6 other_no_more_lives +7:7 other_animation_end +7:1 other_boundary +7:3 other_game_end +7:2 other_game_start +7:0 other_outside +7:4 other_room_start +7:5 other_room_end +7:8 other_end_of_path +7:30 other_close_button +7:10 other_user0 +7:11 other_user1 +7:12 other_user2 +7:13 other_user3 +7:14 other_user4 +7:15 other_user5 +7:16 other_user6 +7:17 other_user7 +7:18 other_user8 +7:19 other_user9 +7:20 other_user10 +7:21 other_user11 +7:22 other_user12 +7:23 other_user13 +7:24 other_user14 +7:25 other_user15 +7:40 other_outside_view0 +7:41 other_outside_view1 +7:42 other_outside_view2 +7:43 other_outside_view3 +7:44 other_outside_view4 +7:45 other_outside_view5 +7:46 other_outside_view6 +7:47 other_outside_view7 +7:50 other_boundary_view0 +7:51 other_boundary_view1 +7:52 other_boundary_view2 +7:53 other_boundary_view3 +7:54 other_boundary_view4 +7:55 other_boundary_view5 +7:56 other_boundary_view6 +7:57 other_boundary_view7 +7:59 other_animation_event +7:60 async_image +7:62 async_http +7:63 async_dialog +7:66 async_iap +7:67 async_cloud +7:68 async_network +7:69 async_steam +7:70 async_social +7:71 async_push_notification +7:72 async_save_load +7:73 async_audio_recording +7:74 async_audio_playback +7:75 async_system +7:76 other_broadcast_message + +8:0 draw +8:65 draw_resize +8:72 draw_begin +8:73 draw_end +8:77 draw_post +8:76 draw_pre +8:64 draw_gui +8:74 draw_gui_begin +8:75 draw_gui_end + +12:0 cleanup +13:1 gesture_double_tap +13:4 gesture_drag_end +13:2 gesture_drag_start +13:3 gesture_dragging +13:5 gesture_flick +13:9 gesture_pinch_end +13:7 gesture_pinch_in +13:8 gesture_pinch_out +13:6 gesture_pinch_start +13:12 gesture_rotate_end +13:10 gesture_rotate_start +13:11 gesture_rotating +13:0 gesture_tap \ No newline at end of file diff --git a/snippets_gml/tester/fnames b/snippets_gml/tester/fnames new file mode 100644 index 0000000..fca0f8f --- /dev/null +++ b/snippets_gml/tester/fnames @@ -0,0 +1,1885 @@ +////////////// +// Chapter 401 +////////////// + +// # = constant +// * = readonly + +argument_relative* +argument +argument0 +argument1 +argument2 +argument3 +argument4 +argument5 +argument6 +argument7 +argument8 +argument9 +argument10 +argument11 +argument12 +argument13 +argument14 +argument15 +argument_count +self# +other# +all# +noone# +global# +local# +////////////// +// Chapter 402 +////////////// + +// section 2.1 + +true# +false# +pi# + +// section 2.2 + +is_real(val) +is_string(val) +random(x) +random_range(x1,x2) +irandom(x) +irandom_range(x1,x2) +random_set_seed(seed) +random_get_seed() +randomize() +choose(x1,x2,x3,...) +abs(x) +round(x) +floor(x) +ceil(x) +sign(x) +frac(x) +sqrt(x) +sqr(x) +exp(x) +ln(x) +log2(x) +log10(x) +sin(x) +cos(x) +tan(x) +arcsin(x) +arccos(x) +arctan(x) +arctan2(y,x) +degtorad(x) +radtodeg(x) +power(x,n) +logn(n,x) +min(x1,x2,x3,...) +max(x1,x2,x3,...) +mean(x1,x2,x3,...) +median(x1,x2,x3,...) +clamp(val,min,max) +lerp(val1,val2,amount) +dot_product(x1,y1,x2,y2) +dot_product_3d(x1,y1,z1,x2,y2,z2) +point_distance_3d(x1,y1,z1,x2,y2,z2) +point_distance(x1,y1,x2,y2) +point_direction(x1,y1,x2,y2) +lengthdir_x(len,dir) +lengthdir_y(len,dir) + +// section 2.3 + +real(str) +string(val) +string_format(val,total,dec) +chr(val) +ansi_char(val) +ord(char) +string_length(str) +string_pos(substr,str) +string_copy(str,index,count) +string_char_at(str,index) +string_delete(str,index,count) +string_insert(substr,str,index) +string_lower(str) +string_upper(str) +string_repeat(str,count) +string_letters(str) +string_digits(str) +string_lettersdigits(str) +string_replace(str,substr,newstr) +string_replace_all(str,substr,newstr) +string_count(substr,str) +clipboard_has_text() +clipboard_set_text(str) +clipboard_get_text() + +// section 2.4 + +date_current_datetime() +date_current_date() +date_current_time() +date_create_datetime(year,month,day,hour,minute,second) +date_create_date(year,month,day) +date_create_time(hour,minute,second) +date_valid_datetime(year,month,day,hour,minute,second) +date_valid_date(year,month,day) +date_valid_time(hour,minute,second) +date_inc_year(date,amount) +date_inc_month(date,amount) +date_inc_week(date,amount) +date_inc_day(date,amount) +date_inc_hour(date,amount) +date_inc_minute(date,amount) +date_inc_second(date,amount) +date_get_year(date) +date_get_month(date) +date_get_week(date) +date_get_day(date) +date_get_hour(date) +date_get_minute(date) +date_get_second(date) +date_get_weekday(date) +date_get_day_of_year(date) +date_get_hour_of_year(date) +date_get_minute_of_year(date) +date_get_second_of_year(date) +date_year_span(date1,date2) +date_month_span(date1,date2) +date_week_span(date1,date2) +date_day_span(date1,date2) +date_hour_span(date1,date2) +date_minute_span(date1,date2) +date_second_span(date1,date2) +date_compare_datetime(date1,date2) +date_compare_date(date1,date2) +date_compare_time(date1,date2) +date_date_of(date) +date_time_of(date) +date_datetime_string(date) +date_date_string(date) +date_time_string(date) +date_days_in_month(date) +date_days_in_year(date) +date_leap_year(date) +date_is_today(date) +////////////// +// Chapter 403 +////////////// + +// section 3.1 + +x +y +xprevious +yprevious +xstart +ystart +hspeed +vspeed +direction +speed +friction +gravity +gravity_direction +motion_set(dir,speed) +motion_add(dir,speed) +place_free(x,y) +place_empty(x,y) +place_meeting(x,y,obj) +place_snapped(hsnap,vsnap) +move_random(hsnap,vsnap) +move_snap(hsnap,vsnap) +move_towards_point(x,y,sp) +move_contact_solid(dir,maxdist) +move_contact_all(dir,maxdist) +move_outside_solid(dir,maxdist) +move_outside_all(dir,maxdist) +move_bounce_solid(advanced) +move_bounce_all(advanced) +move_wrap(hor,vert,margin) +distance_to_point(x,y) +distance_to_object(obj) +position_empty(x,y) +position_meeting(x,y,obj) + +// section 3.2 + +path_start(path,speed,endaction,absolute) +path_end() +path_index* +path_position +path_positionprevious +path_speed +path_scale +path_orientation +path_endaction + +// section 3.3 + +mp_linear_step(x,y,speed,checkall) +mp_potential_step(x,y,speed,checkall) +mp_linear_step_object(x,y,speed,obj) +mp_potential_step_object(x,y,speed,obj) +mp_potential_settings(maxrot,rotstep,ahead,onspot) +mp_linear_path(path,xg,yg,stepsize,checkall) +mp_potential_path(path,xg,yg,stepsize,factor,checkall) +mp_linear_path_object(path,xg,yg,stepsize,obj) +mp_potential_path_object(path,xg,yg,stepsize,factor,obj) +mp_grid_create(left,top,hcells,vcells,cellwidth,cellheight) +mp_grid_destroy(id) +mp_grid_clear_all(id) +mp_grid_clear_cell(id,h,v) +mp_grid_clear_rectangle(id,left,top,right,bottom) +mp_grid_add_cell(id,h,v) +mp_grid_add_rectangle(id,left,top,right,bottom) +mp_grid_add_instances(id,obj,prec) +mp_grid_path(id,path,xstart,ystart,xgoal,ygoal,allowdiag) +mp_grid_draw(id) + +// section 3.4 + +collision_point(x,y,obj,prec,notme) +collision_rectangle(x1,y1,x2,y2,obj,prec,notme) +collision_circle(x1,y1,radius,obj,prec,notme) +collision_ellipse(x1,y1,x2,y2,obj,prec,notme) +collision_line(x1,y1,x2,y2,obj,prec,notme) + +// section 3.5 + +object_index* +id* +solid +persistent +mask_index +instance_count* +instance_id* +instance_find(obj,n) +instance_exists(obj) +instance_number(obj) +instance_position(x,y,obj) +instance_nearest(x,y,obj) +instance_furthest(x,y,obj) +instance_place(x,y,obj) +instance_create(x,y,obj) +instance_copy(performevent) +instance_change(obj,performevents) +instance_destroy() +position_destroy(x,y) +position_change(x,y,obj,performevents) + +// section 3.6 + +instance_deactivate_all(notme) +instance_deactivate_object(obj) +instance_deactivate_region(left,top,width,height,inside,notme) +instance_activate_all() +instance_activate_object(obj) +instance_activate_region(left,top,width,height,inside) + +// section 3.7 + +room_speed +fps* +current_time* +current_year* +current_month* +current_day* +current_weekday* +current_hour* +current_minute* +current_second* +sleep(millisec) +alarm[0..11] +timeline_index +timeline_position +timeline_speed +timeline_running +timeline_loop + +// section 3.8 + +room +room_first* +room_last* +room_width* +room_height* +room_caption +room_persistent +room_goto(numb) +room_goto_previous() +room_goto_next() +room_previous(numb) +room_next(numb) +room_restart() +game_end() +game_restart() +game_load(filename) +game_save(filename) + +transition_kind +transition_steps +transition_color +transition_define(kind,name) +transition_exists(kind) + +// section 3.9 + +score +lives +health +show_score +show_lives +show_health +caption_score +caption_lives +caption_health + +// section 3.10 + +event_perform(type,numb) +event_user(numb) +event_perform_object(obj,type,numb) +event_inherited() +event_type* +event_number* +event_object* +event_action* +ev_create# +ev_destroy# +ev_step# +ev_alarm# +ev_keyboard# +ev_mouse# +ev_collision# +ev_other# +ev_draw# +ev_keypress# +ev_keyrelease# +ev_trigger# +ev_left_button# +ev_right_button# +ev_middle_button# +ev_no_button# +ev_left_press# +ev_right_press# +ev_middle_press# +ev_left_release# +ev_right_release# +ev_middle_release# +ev_mouse_enter# +ev_mouse_leave# +ev_mouse_wheel_up# +ev_mouse_wheel_down# +ev_global_left_button# +ev_global_right_button# +ev_global_middle_button# +ev_global_left_press# +ev_global_right_press# +ev_global_middle_press# +ev_global_left_release# +ev_global_right_release# +ev_global_middle_release# +ev_joystick1_left# +ev_joystick1_right# +ev_joystick1_up# +ev_joystick1_down# +ev_joystick1_button1# +ev_joystick1_button2# +ev_joystick1_button3# +ev_joystick1_button4# +ev_joystick1_button5# +ev_joystick1_button6# +ev_joystick1_button7# +ev_joystick1_button8# +ev_joystick2_left# +ev_joystick2_right# +ev_joystick2_up# +ev_joystick2_down# +ev_joystick2_button1# +ev_joystick2_button2# +ev_joystick2_button3# +ev_joystick2_button4# +ev_joystick2_button5# +ev_joystick2_button6# +ev_joystick2_button7# +ev_joystick2_button8# +ev_outside# +ev_boundary# +ev_game_start# +ev_game_end# +ev_room_start# +ev_room_end# +ev_no_more_lives# +ev_animation_end# +ev_end_of_path# +ev_no_more_health# +ev_close_button# +ev_user0# +ev_user1# +ev_user2# +ev_user3# +ev_user4# +ev_user5# +ev_user6# +ev_user7# +ev_user8# +ev_user9# +ev_user10# +ev_user11# +ev_user12# +ev_user13# +ev_user14# +ev_user15# +ev_step_normal# +ev_step_begin# +ev_step_end# + +// section 3.11 + +gamemaker_pro* +gamemaker_registered* +gamemaker_version* +error_occurred +error_last +show_debug_message(str) +debug_mode* +variable_global_exists(name) +variable_global_get(name) +variable_global_array_get(name,ind) +variable_global_array2_get(name,ind1,ind2) +variable_global_set(name,value) +variable_global_array_set(name,ind,value) +variable_global_array2_set(name,ind1,ind2,value) +variable_local_exists(name) +variable_local_get(name) +variable_local_array_get(name,ind) +variable_local_array2_get(name,ind1,ind2) +variable_local_set(name,value) +variable_local_array_set(name,ind,value) +variable_local_array2_set(name,ind1,ind2,value) +set_program_priority(priority) +set_application_title(title) + + +////////////// +// Chapter 404 +////////////// + +// section 4.1 + +keyboard_key +keyboard_lastkey +keyboard_lastchar +keyboard_string +keyboard_set_map(key1,key2) +keyboard_get_map(key) +keyboard_unset_map() +keyboard_check(key) +keyboard_check_pressed(key) +keyboard_check_released(key) +keyboard_check_direct(key) +keyboard_get_numlock() +keyboard_set_numlock(on) +keyboard_key_press(key) +keyboard_key_release(key) +vk_nokey# +vk_anykey# +vk_enter# +vk_return# +vk_shift# +vk_control# +vk_alt# +vk_escape# +vk_space# +vk_backspace# +vk_tab# +vk_pause# +vk_printscreen# +vk_left# +vk_right# +vk_up# +vk_down# +vk_home# +vk_end# +vk_delete# +vk_insert# +vk_pageup# +vk_pagedown# +vk_f1# +vk_f2# +vk_f3# +vk_f4# +vk_f5# +vk_f6# +vk_f7# +vk_f8# +vk_f9# +vk_f10# +vk_f11# +vk_f12# +vk_numpad0# +vk_numpad1# +vk_numpad2# +vk_numpad3# +vk_numpad4# +vk_numpad5# +vk_numpad6# +vk_numpad7# +vk_numpad8# +vk_numpad9# +vk_divide# +vk_multiply# +vk_subtract# +vk_add# +vk_decimal# +vk_lshift# +vk_lcontrol# +vk_lalt# +vk_rshift# +vk_rcontrol# +vk_ralt# +keyboard_clear(key) +io_clear() +io_handle() +keyboard_wait() + +// section 4.2 + +mouse_x* +mouse_y* +mouse_button +mouse_lastbutton +mb_any# +mb_none# +mb_left# +mb_right# +mb_middle# +mouse_check_button(button) +mouse_check_button_pressed(button) +mouse_check_button_released(button) +mouse_wheel_up() +mouse_wheel_down() +mouse_clear(button) +mouse_wait() +cursor_sprite + +// section 4.3 + +joystick_exists(id) +joystick_direction(id) +joystick_name(id) +joystick_axes(id) +joystick_buttons(id) +joystick_has_pov(id) +joystick_check_button(id,button) +joystick_xpos(id) +joystick_ypos(id) +joystick_zpos(id) +joystick_rpos(id) +joystick_upos(id) +joystick_vpos(id) +joystick_pov(id) + + +////////////// +// Chapter 405 +////////////// + +// section 5.1 + +visible +sprite_index +sprite_width* +sprite_height* +sprite_xoffset* +sprite_yoffset* +image_number* +image_index +image_speed +depth +image_xscale +image_yscale +image_angle +image_alpha +image_blend +bbox_left* +bbox_right* +bbox_top* +bbox_bottom* + +// section 5.2 + +background_color +background_showcolor +background_visible[0..7] +background_foreground[0..7] +background_index[0..7] +background_x[0..7] +background_y[0...7] +background_width[0...7]* +background_height[0...7]* +background_htiled[0..7] +background_vtiled[0..7] +background_xscale[0..7] +background_yscale[0..7] +background_hspeed[0..7] +background_vspeed[0..7] +background_blend[0..7] +background_alpha[0..7] + +// section 5.3 + +draw_self() +YoYo_GetPlatform() +YoYo_EnableAlphaBlend(enable) +draw_sprite(sprite,subimg,x,y) +draw_sprite_pos(sprite,subimg,x1,y1,x2,y2,x3,y3,x4,y4,alpha) +draw_sprite_ext(sprite,subimg,x,y,xscale,yscale,rot,color,alpha) +draw_sprite_stretched(sprite,subimg,x,y,w,h) +draw_sprite_stretched_ext(sprite,subimg,x,y,w,h,color,alpha) +draw_sprite_tiled(sprite,subimg,x,y) +draw_sprite_tiled_ext(sprite,subimg,x,y,xscale,yscale,color,alpha) +draw_sprite_part(sprite,subimg,left,top,width,height,x,y) +draw_sprite_part_ext(sprite,subimg,left,top,width,height,x,y,xscale,yscale,color,alpha) +draw_sprite_general(sprite,subimg,left,top,width,height,x,y,xscale,yscale,rot,c1,c2,c3,c4,alpha) +draw_background(back,x,y) +draw_background_ext(back,x,y,xscale,yscale,rot,color,alpha) +draw_background_stretched(back,x,y,w,h) +draw_background_stretched_ext(back,x,y,w,h,color,alpha) +draw_background_tiled(back,x,y) +draw_background_tiled_ext(back,x,y,xscale,yscale,color,alpha) +draw_background_part(back,left,top,width,height,x,y) +draw_background_part_ext(back,left,top,width,height,x,y,xscale,yscale,color,alpha) +draw_background_general(back,left,top,width,height,x,y,xscale,yscale,rot,c1,c2,c3,c4,alpha) + +// section 5.4 + +draw_clear(col) +draw_clear_alpha(col,alpha) +draw_point(x,y) +draw_line(x1,y1,x2,y2) +draw_line_width(x1,y1,x2,y2,w) +draw_rectangle(x1,y1,x2,y2,outline) +draw_roundrect(x1,y1,x2,y2,outline) +draw_triangle(x1,y1,x2,y2,x3,y3,outline) +draw_circle(x,y,r,outline) +draw_ellipse(x1,y1,x2,y2,outline) +draw_set_circle_precision(precision) +draw_arrow(x1,y1,x2,y2,size) +draw_button(x1,y1,x2,y2,up) +draw_path(path,x,y,absolute) +draw_healthbar(x1,y1,x2,y2,amount,backcol,mincol,maxcol,direction,showback,showborder) +draw_getpixel(x,y) +draw_set_color(col) +draw_set_alpha(alpha) +draw_get_color() +draw_get_alpha() +c_aqua# +c_black# +c_blue# +c_dkgray# +c_fuchsia# +c_gray# +c_green# +c_lime# +c_ltgray# +c_maroon# +c_navy# +c_olive# +c_purple# +c_red# +c_silver# +c_teal# +c_white# +c_yellow# +c_orange# +make_color_rgb(red,green,blue) +make_color_hsv(hue,saturation,value) +color_get_red(col) +color_get_green(col) +color_get_blue(col) +color_get_hue(col) +color_get_saturation(col) +color_get_value(col) +merge_color(col1,col2,amount) +screen_save(fname) +screen_save_part(fname,x,y,w,h) + +// section 5.5 + +draw_set_font(font) +draw_set_halign(halign) +fa_left# +fa_center# +fa_right# +draw_set_valign(valign) +fa_top# +fa_middle# +fa_bottom# +draw_text(x,y,string) +draw_text_ext(x,y,string,sep,w) +string_width(string) +string_height(string) +string_width_ext(string,sep,w) +string_height_ext(string,sep,w) +draw_text_transformed(x,y,string,xscale,yscale,angle) +draw_text_ext_transformed(x,y,string,sep,w,xscale,yscale,angle) +draw_text_color(x,y,string,c1,c2,c3,c4,alpha) +draw_text_ext_color(x,y,string,sep,w,c1,c2,c3,c4,alpha) +draw_text_transformed_color(x,y,string,xscale,yscale,angle,c1,c2,c3,c4,alpha) +draw_text_ext_transformed_color(x,y,string,sep,w,xscale,yscale,angle,c1,c2,c3,c4,alpha) + +// section 5.6 + +draw_point_color(x,y,col1) +draw_line_color(x1,y1,x2,y2,col1,col2) +draw_line_width_color(x1,y1,x2,y2,w,col1,col2) +draw_rectangle_color(x1,y1,x2,y2,col1,col2,col3,col4,outline) +draw_roundrect_color(x1,y1,x2,y2,col1,col2,outline) +draw_triangle_color(x1,y1,x2,y2,x3,y3,col1,col2,col3,outline) +draw_circle_color(x,y,r,col1,col2,outline) +draw_ellipse_color(x1,y1,x2,y2,col1,col2,outline) +pr_pointlist# +pr_linelist# +pr_linestrip# +pr_trianglelist# +pr_trianglestrip# +pr_trianglefan# +draw_primitive_begin(kind) +draw_vertex(x,y) +draw_vertex_color(x,y,col,alpha) +draw_primitive_end() +sprite_get_texture(spr,subimg) +background_get_texture(back) +texture_preload(texid) +texture_set_priority(texid,prio) +texture_get_width(texid) +texture_get_height(texid) +draw_primitive_begin_texture(kind,texid) +draw_vertex_texture(x,y,xtex,ytex) +draw_vertex_texture_color(x,y,xtex,ytex,col,alpha) +texture_set_interpolation(linear) +texture_set_blending(blend) +texture_set_repeat(repeat) +draw_set_blend_mode(mode) +draw_set_blend_mode_ext(src,dest) +bm_normal# +bm_add# +bm_max# +bm_subtract# +bm_zero# +bm_one# +bm_src_color# +bm_inv_src_color# +bm_src_alpha# +bm_inv_src_alpha# +bm_dest_alpha# +bm_inv_dest_alpha# +bm_dest_color# +bm_inv_dest_color# +bm_src_alpha_sat# + +// section 5.7_1 + +surface_create(w,h) +surface_free(id) +surface_exists(id) +surface_get_width(id) +surface_get_height(id) +surface_get_texture(id) +surface_set_target(id) +surface_reset_target() +draw_surface(id,x,y) +draw_surface_stretched(id,x,y,w,h) +draw_surface_tiled(id,x,y) +draw_surface_part(id,left,top,width,height,x,y) +draw_surface_ext(id,x,y,xscale,yscale,rot,color,alpha) +draw_surface_stretched_ext(id,x,y,w,h,color,alpha) +draw_surface_tiled_ext(id,x,y,xscale,yscale,color,alpha) +draw_surface_part_ext(id,left,top,width,height,x,y,xscale,yscale,color,alpha) +draw_surface_general(id,left,top,width,height,x,y,xscale,yscale,rot,c1,c2,c3,c4,alpha) +surface_getpixel(id,x,y) +surface_save(id,fname) +surface_save_part(id,fname,x,y,w,h) +surface_copy(destination,x,y,source) +surface_copy_part(destination,x,y,source,xs,ys,ws,hs) + +// section 5.7 + +tile_add(background,left,top,width,height,x,y,depth) +tile_delete(id) +tile_exists(id) +tile_get_x(id) +tile_get_y(id) +tile_get_left(id) +tile_get_top(id) +tile_get_width(id) +tile_get_height(id) +tile_get_depth(id) +tile_get_visible(id) +tile_get_xscale(id) +tile_get_yscale(id) +tile_get_background(id) +tile_get_blend(id) +tile_get_alpha(id) +tile_set_position(id,x,y) +tile_set_region(id,left,top,width,height) +tile_set_background(id,background) +tile_set_visible(id,visible) +tile_set_depth(id,depth) +tile_set_scale(id,xscale,yscale) +tile_set_blend(id,color) +tile_set_alpha(id,alpha) +tile_layer_hide(depth) +tile_layer_show(depth) +tile_layer_delete(depth) +tile_layer_shift(depth,x,y) +tile_layer_find(depth,x,y) +tile_layer_delete_at(depth,x,y) +tile_layer_depth(depth,newdepth) + +// section 5.8 + +display_get_width() +display_get_height() +display_get_colordepth() +display_get_frequency() +display_set_size(w,h) +display_set_colordepth(coldepth) +display_set_frequency(frequency) +display_set_all(w,h,frequency,coldepth) +display_test_all(w,h,frequency,coldepth) +display_reset(aa_level) +display_mouse_get_x() +display_mouse_get_y() +display_mouse_set(x,y) + +// section 5.9 + +window_set_visible(visible) +window_get_visible() +window_set_fullscreen(full) +window_get_fullscreen() +window_set_showborder(show) +window_get_showborder() +window_set_showicons(show) +window_get_showicons() +window_set_stayontop(stay) +window_get_stayontop() +window_set_sizeable(sizeable) +window_get_sizeable() +window_set_caption(caption) +window_get_caption() +window_set_cursor(curs) +cr_default# +cr_none# +cr_arrow# +cr_cross# +cr_beam# +cr_size_nesw# +cr_size_ns# +cr_size_nwse# +cr_size_we# +cr_uparrow# +cr_hourglass# +cr_drag# +cr_nodrop# +cr_hsplit# +cr_vsplit# +cr_multidrag# +cr_sqlwait# +cr_no# +cr_appstart# +cr_help# +cr_handpoint# +cr_size_all# +window_get_cursor() +window_set_color(color) +window_get_color() +window_set_region_scale(scale,adaptwindow) +window_get_region_scale() +window_set_position(x,y) +window_set_size(w,h) +window_set_rectangle(x,y,w,h) +window_center() +window_default() +window_get_x() +window_get_y() +window_get_width() +window_get_height() +window_mouse_get_x() +window_mouse_get_y() +window_mouse_set(x,y) + +// section 5.10 + +view_enabled +view_current* +view_visible[0..7] +view_xview[0..7] +view_yview[0..7] +view_wview[0..7] +view_hview[0..7] +view_xport[0..7] +view_yport[0..7] +view_wport[0..7] +view_hport[0..7] +view_angle[0..7] +view_hborder[0..7] +view_vborder[0..7] +view_hspeed[0..7] +view_vspeed[0..7] +view_object[0..7] +window_set_region_size(w,h,adaptwindow) +window_get_region_width() +window_get_region_height() +window_view_mouse_get_x(id) +window_view_mouse_get_y(id) +window_view_mouse_set(id,x,y) +window_views_mouse_get_x() +window_views_mouse_get_y() +window_views_mouse_set(x,y) + +// section 5.11 + +screen_redraw() +screen_refresh() +screen_wait_vsync() +set_automatic_draw(value) +set_synchronization(value) + + +////////////// +// Chapter 406 +////////////// + +// section 6.1 + +sound_play(index) +sound_loop(index) +sound_stop(index) +sound_stop_all() +sound_isplaying(index) +sound_volume(index,value) +sound_global_volume(value) +sound_fade(index,value,time) +sound_pan(index,value) +sound_background_tempo(factor) +sound_set_search_directory(dir) + +// section 6.2 + +se_none# +se_chorus# +se_echo# +se_flanger# +se_gargle# +se_reverb# +se_compressor# +se_equalizer# +sound_effect_set(snd,effect) +sound_effect_chorus(snd,wetdry,depth,feedback,frequency,wave,delay,phase) +sound_effect_echo(snd,wetdry,feedback,leftdelay,rightdelay,pandelay) +sound_effect_flanger(snd,wetdry,depth,feedback,frequency,wave,delay,phase) +sound_effect_gargle(snd,rate,wave) +sound_effect_reverb(snd,gain,mix,time,ratio) +sound_effect_compressor(snd,gain,attack,release,threshold,ratio,delay) +sound_effect_equalizer(snd,center,bandwidth,gain) + +// section 6.3 + +sound_3d_set_sound_position(snd,x,y,z) +sound_3d_set_sound_velocity(snd,x,y,z) +sound_3d_set_sound_distance(snd,mindist,maxdist) +sound_3d_set_sound_cone(snd,x,y,z,anglein,angleout,voloutside) +//sound_3d_set_distance_factor(snd,factor) +//sound_3d_set_rolloff_factor(snd,factor) +//sound_3d_set_doppler_factor(snd,factor) +//sound_3d_set_listener_position(snd,x,y,z) +//sound_3d_set_listener_velocity(snd,x,y,z) +//sound_3d_set_listener_orientation(snd,xf,yf,zf,xt,yt,zt) + +// section 6.4 + +cd_init() +cd_present() +cd_number() +cd_playing() +cd_paused() +cd_track() +cd_length() +cd_track_length(n) +cd_position() +cd_track_position() +cd_play(first,last) +cd_stop() +cd_pause() +cd_resume() +cd_set_position(pos) +cd_set_track_position(pos) +cd_open_door() +cd_close_door() +MCI_command(str) + + +////////////// +// Chapter 407 +////////////// + +// section 7.1 + +splash_show_video(fname,loop) +splash_show_text(fname,delay) +splash_show_web(url,delay) +splash_show_image(fname,delay) +splash_set_caption(cap) +splash_set_fullscreen(full) +splash_set_border(border) +splash_set_size(w,h) +splash_set_position(x,y) +splash_set_adapt(adapt) +splash_set_top(top) +splash_set_color(col) +splash_set_main(main) +splash_set_scale(scale) +splash_set_cursor(vis) +splash_set_interrupt(interrupt) +splash_set_stop_key(stop) +splash_set_stop_mouse(stop) +splash_set_close_button(show) +show_info() +load_info(fname) + +// section 7.2 + +show_message(str) +show_message_ext(str,but1,but2,but3) +show_question(str) +get_integer(str,def) +get_string(str,def) +message_background(back) +message_button(sprite) +message_alpha(alpha) +message_text_font(name,size,color,style) +message_button_font(name,size,color,style) +message_input_font(name,size,color,style) +message_text_charset(type, charset_id) +message_mouse_color(col) +message_input_color(col) +message_position(x,y) +message_size(w,h) +message_caption(show,str) +show_menu(str,def) +show_menu_pos(x,y,str,def) +get_color(defcol) +get_open_filename(filter,fname) +get_save_filename(filter,fname) +get_directory(dname) +get_directory_alt(capt,root) +show_error(str,abort) + +// section 7.3 + +highscore_show_ext(numb,back,border,col1,col2,name,size) +highscore_show(numb) +highscore_set_background(back); +highscore_set_border(show); +highscore_set_font(name,size,style); +highscore_set_strings(caption,nobody,escape); +highscore_set_colors(back,new,other); +highscore_clear() +highscore_add(str,numb) +highscore_add_current() +highscore_value(place) +highscore_name(place) +draw_highscore(x1,y1,x2,y2) + + +////////////// +// Chapter 408 +////////////// + +// section 8.1 + +sprite_exists(ind) +sprite_get_name(ind) +sprite_get_number(ind) +sprite_get_width(ind) +sprite_get_height(ind) +sprite_get_xoffset(ind) +sprite_get_yoffset(ind) +sprite_get_bbox_left(ind) +sprite_get_bbox_right(ind) +sprite_get_bbox_top(ind) +sprite_get_bbox_bottom(ind) + +sprite_save(ind,subimg,fname) +sprite_save_strip(ind,fname) + +// section 8.2 + +sound_exists(ind) +sound_get_name(ind) +sound_get_kind(ind) +sound_get_preload(ind) +sound_discard(ind) +sound_restore(ind) + +// section 8.3 + +background_exists(ind) +background_get_name(ind) +background_get_width(ind) +background_get_height(ind) + +background_save(ind,fname) + + +// section 8.4 + +font_exists(ind) +font_get_name(ind) +font_get_fontname(ind) +font_get_bold(ind) +font_get_italic(ind) +font_get_first(ind) +font_get_last(ind) + +// section 8.5 + +path_exists(ind) +path_get_name(ind) +path_get_length(ind) +path_get_kind(ind) +path_get_closed(ind) +path_get_precision(ind) +path_get_number(ind) +path_get_point_x(ind,n) +path_get_point_y(ind,n) +path_get_point_speed(ind,n) +path_get_x(ind,pos) +path_get_y(ind,pos) +path_get_speed(ind,pos) + +// section 8.6 + +script_exists(ind) +script_get_name(ind) +script_get_text(ind) + +// section 8.7 + +timeline_exists(ind) +timeline_get_name(ind) + +// section 8.8 + +object_exists(ind) +object_get_name(ind) +object_get_sprite(ind) +object_get_solid(ind) +object_get_visible(ind) +object_get_depth(ind) +object_get_persistent(ind) +object_get_mask(ind) +object_get_parent(ind) +object_is_ancestor(ind1,ind2) + +// section 8.9 + +room_exists(ind) +room_get_name(ind) + +////////////// +// Chapter 409 +////////////// + +// section 9.1 + +sprite_set_offset(ind,xoff,yoff) +sprite_duplicate(ind) +sprite_assign(ind,source) +sprite_merge(ind1,ind2) +sprite_add(fname,imgnumb,removeback,smooth,xorig,yorig) +sprite_replace(ind,fname,imgnumb,removeback,smooth,xorig,yorig) +sprite_add_sprite(fname) +sprite_replace_sprite(ind,fname) +sprite_create_from_screen(x,y,w,h,removeback,smooth,xorig,yorig) +sprite_add_from_screen(ind,x,y,w,h,removeback,smooth) +sprite_create_from_surface(id,x,y,w,h,removeback,smooth,xorig,yorig) +sprite_add_from_surface(ind,id,x,y,w,h,removeback,smooth) +sprite_delete(ind) +sprite_set_alpha_from_sprite(ind,spr) +sprite_collision_mask(ind,sepmasks,bboxmode,bbleft,bbright,bbtop,bbbottom,kind,tolerance) + +// section 9.2 + +sound_add(fname,kind,preload) +sound_replace(ind,fname,kind,preload) +sound_delete(ind) + +// section 9.3 + +background_duplicate(ind) +background_assign(ind,source) +background_add(fname,removeback,smooth) +background_replace(ind,fname,removeback,smooth) +background_add_background(fname) +background_replace_background(ind,fname) +background_create_color(w,h,col) +background_create_gradient(w,h,col1,col2,kind) +background_create_from_screen(x,y,w,h,removeback,smooth) +background_create_from_surface(id,x,y,w,h,removeback,smooth) +background_delete(ind) +background_set_alpha_from_background(ind,back) + +// section 9.4 + +font_add(name,size,bold,italic,first,last) +font_add_sprite(spr,first,prop,sep) +font_replace(ind,name,size,bold,italic,first,last) +font_replace_sprite(ind,spr,first,prop,sep) +font_delete(ind) + +// section 9.5 + +path_set_kind(ind,kind) +path_set_closed(ind,closed) +path_set_precision(ind,prec) +path_add() +path_assign(ind,path) +path_duplicate(ind) +path_append(ind,path) +path_delete(ind) +path_add_point(ind,x,y,speed) +path_insert_point(ind,n,x,y,speed) +path_change_point(ind,n,x,y,speed) +path_delete_point(ind,n) +path_clear_points(ind) +path_reverse(ind) +path_mirror(ind) +path_flip(ind) +path_rotate(ind,angle) +path_scale(ind,xscale,yscale) +path_shift(ind,xshift,yshift) + +// section 9.6 + +execute_string(str,arg0,arg1,...) +execute_file(fname,arg0,arg1,...) +script_execute(ind,arg0,arg1,...) + +// section 9.7 + +timeline_add() +timeline_delete(ind) +timeline_clear(ind) +timeline_moment_clear(ind,step) +timeline_moment_add(ind,step,codestr) + +// section 9.8 + +object_set_sprite(ind,spr) +object_set_solid(ind,solid) +object_set_visible(ind,vis) +object_set_depth(ind,depth) +object_set_persistent(ind,pers) +object_set_mask(ind,spr) +object_set_parent(ind,obj) +object_add() +object_delete(ind) +object_event_clear(ind,evtype,evnumb) +object_event_add(ind,evtype,evnumb,codestr) + +// section 9.9 + +room_set_width(ind,w) +room_set_height(ind,h) +room_set_caption(ind,str) +room_set_persistent(ind,pers) +room_set_code(ind,codestr) +room_set_background_color(ind,col,show) +room_set_background(ind,bind,vis,fore,back,x,y,htiled,vtiled,hspeed,vspeed,alpha) +room_set_view(ind,vind,vis,xview,yview,wview,hview,xport,yport,wport,hport,hborder,vborder,hspeed,vspeed,obj) +room_set_view_enabled(ind,val) +room_add() +room_duplicate(ind) +room_assign(ind,source) +room_instance_add(ind,x,y,obj) +room_instance_clear(ind) +room_tile_add(ind,back,left,top,width,height,x,y,depth) +room_tile_add_ext(ind,back,left,top,width,height,x,y,depth,xscale,yscale,alpha) +room_tile_clear(ind) + + + +////////////// +// Chapter 410 +////////////// + +// section 10.1 + +file_text_open_read(fname) +file_text_open_write(fname) +file_text_open_append(fname) +file_text_close(file) +file_text_write_string(file,str) +file_text_write_real(file,val) +file_text_writeln(file) +file_text_read_string(file) +file_text_read_real(file) +file_text_readln(file) +file_text_eof(file) +file_text_eoln(file) +file_exists(fname) +file_delete(fname) +file_rename(oldname,newname) +file_copy(fname,newname) +directory_exists(dname) +directory_create(dname) +file_find_first(mask,attr) +file_find_next() +file_find_close() +file_attributes(fname,attr) +filename_name(fname) +filename_path(fname) +filename_dir(fname) +filename_drive(fname) +filename_ext(fname) +filename_change_ext(fname,newext) +file_bin_open(fname,mode) +file_bin_rewrite(file) +file_bin_close(file) +file_bin_position(file) +file_bin_size(file) +file_bin_seek(file,pos) +file_bin_write_byte(file,byte) +file_bin_read_byte(file) +export_include_file(fname) +export_include_file_location(fname,location) +discard_include_file(fname) +parameter_count() +parameter_string(n) +environment_get_variable(name) +fa_readonly# +fa_hidden# +fa_sysfile# +fa_volumeid# +fa_directory# +fa_archive# +game_id* +working_directory* +temp_directory* +program_directory* +disk_free(drive) +disk_size(drive) + +// section 10.2 + +registry_write_string(name,str) +registry_write_real(name,value) +registry_read_string(name) +registry_read_real(name) +registry_exists(name) +registry_write_string_ext(key,name,str) +registry_write_real_ext(key,name,value) +registry_read_string_ext(key,name) +registry_read_real_ext(key,name) +registry_exists_ext(key,name) +registry_set_root(root) + +// section 10.3 + +ini_open(fname) +ini_close() +ini_read_string(section,key,default) +ini_read_real(section,key,default) +ini_write_string(section,key,str) +ini_write_real(section,key,value) +ini_key_exists(section,key) +ini_section_exists(section) +ini_key_delete(section,key) +ini_section_delete(section) + +// section 10.4 + +execute_program(prog,arg,wait) +execute_shell(prog,arg) +secure_mode* + + + + +////////////// +// Chapter 411 +////////////// + +// section 11.0 + +ds_set_precision(prec) + +// section 11.1 + +ds_stack_create() +ds_stack_destroy(id) +ds_stack_clear(id) +ds_stack_copy(id,source) +ds_stack_size(id) +ds_stack_empty(id) +ds_stack_push(id,value) +ds_stack_pop(id) +ds_stack_top(id) +ds_stack_write(id) +ds_stack_read(id,str) + +// section 11.2 + +ds_queue_create() +ds_queue_destroy(id) +ds_queue_clear(id) +ds_queue_copy(id,source) +ds_queue_size(id) +ds_queue_empty(id) +ds_queue_enqueue(id,value) +ds_queue_dequeue(id) +ds_queue_head(id) +ds_queue_tail(id) +ds_queue_write(id) +ds_queue_read(id,str) + +// section 11.3 + +ds_list_create() +ds_list_destroy(id) +ds_list_clear(id) +ds_list_copy(id,source) +ds_list_size(id) +ds_list_empty(id) +ds_list_add(id,value) +ds_list_insert(id,pos,value) +ds_list_replace(id,pos,value) +ds_list_delete(id,pos) +ds_list_find_index(id,value) +ds_list_find_value(id,pos) +ds_list_sort(id,ascending) +ds_list_shuffle(id) +ds_list_write(id) +ds_list_read(id,str) + +// section 11.4 + +ds_map_create() +ds_map_destroy(id) +ds_map_clear(id) +ds_map_copy(id,source) +ds_map_size(id) +ds_map_empty(id) +ds_map_add(id,key,value) +ds_map_replace(id,key,value) +ds_map_delete(id,key) +ds_map_exists(id,key) +ds_map_find_value(id,key) +ds_map_find_previous(id,key) +ds_map_find_next(id,key) +ds_map_find_first(id) +ds_map_find_last(id) +ds_map_write(id) +ds_map_read(id,str) + +// section 11.5 + +ds_priority_create() +ds_priority_destroy(id) +ds_priority_clear(id) +ds_priority_copy(id,source) +ds_priority_size(id) +ds_priority_empty(id) +ds_priority_add(id,value,priority) +ds_priority_change_priority(id,value,priority) +ds_priority_find_priority(id,value) +ds_priority_delete_value(id,value) +ds_priority_delete_min(id) +ds_priority_find_min(id) +ds_priority_delete_max(id) +ds_priority_find_max(id) +ds_priority_write(id) +ds_priority_read(id,str) + +// section 11.6 + +ds_grid_create(w,h) +ds_grid_destroy(id) +ds_grid_copy(id,source) +ds_grid_resize(id,w,h) +ds_grid_width(id) +ds_grid_height(id) +ds_grid_clear(id,val) +ds_grid_set(id,x,y,val) +ds_grid_add(id,x,y,val) +ds_grid_multiply(id,x,y,val) +ds_grid_set_region(id,x1,y1,x2,y2,val) +ds_grid_add_region(id,x1,y1,x2,y2,val) +ds_grid_multiply_region(id,x1,y1,x2,y2,val) +ds_grid_set_disk(id,xm,ym,r,val) +ds_grid_add_disk(id,xm,ym,r,val) +ds_grid_multiply_disk(id,xm,ym,r,val) +ds_grid_set_grid_region(id,source,x1,y1,x2,y2,xpos,ypos) +ds_grid_add_grid_region(id,source,x1,y1,x2,y2,xpos,ypos) +ds_grid_multiply_grid_region(id,source,x1,y1,x2,y2,xpos,ypos) +ds_grid_get(id,x,y) +ds_grid_get_sum(id,x1,y1,x2,y2) +ds_grid_get_max(id,x1,y1,x2,y2) +ds_grid_get_min(id,x1,y1,x2,y2) +ds_grid_get_mean(id,x1,y1,x2,y2) +ds_grid_get_disk_sum(id,xm,ym,r) +ds_grid_get_disk_min(id,xm,ym,r) +ds_grid_get_disk_max(id,xm,ym,r) +ds_grid_get_disk_mean(id,xm,ym,r) +ds_grid_value_exists(id,x1,y1,x2,y2,val) +ds_grid_value_x(id,x1,y1,x2,y2,val) +ds_grid_value_y(id,x1,y1,x2,y2,val) +ds_grid_value_disk_exists(id,xm,ym,r,val) +ds_grid_value_disk_x(id,xm,ym,r,val) +ds_grid_value_disk_y(id,xm,ym,r,val) +ds_grid_shuffle(id) +ds_grid_write(id) +ds_grid_read(id,str) + +////////////// +// Chapter 412 +////////////// + +// section 12.1a + +effect_create_below(kind,x,y,size,color) +effect_create_above(kind,x,y,size,color) +effect_clear() +ef_explosion# +ef_ring# +ef_ellipse# +ef_firework# +ef_smoke# +ef_smokeup# +ef_star# +ef_spark# +ef_flare# +ef_cloud# +ef_rain# +ef_snow# + +// section 12.1 + +part_type_create() +part_type_destroy(ind) +part_type_exists(ind) +part_type_clear(ind) +part_type_shape(ind,shape) +part_type_sprite(ind,sprite,animat,stretch,random) +part_type_size(ind,size_min,size_max,size_incr,size_wiggle) +part_type_scale(ind,xscale,yscale) +part_type_orientation(ind,ang_min,ang_max,ang_incr,ang_wiggle,ang_relative) +part_type_life(ind,life_min,life_max) +part_type_step(ind,step_number,step_type) +part_type_death(ind,death_number,death_type) +part_type_speed(ind,speed_min,speed_max,speed_incr,speed_wiggle) +part_type_direction(ind,dir_min,dir_max,dir_incr,dir_wiggle) +part_type_gravity(ind,grav_amount,grav_dir) +part_type_color1(ind,color1) +part_type_color2(ind,color1,color2) +part_type_color3(ind,color1,color2,color3) +part_type_color_mix(ind,color1,color2) +part_type_color_rgb(ind,rmin,rmax,gmin,gmax,bmin,bmax) +part_type_color_hsv(ind,hmin,hmax,smin,smax,vmin,vmax) +part_type_alpha1(ind,alpha1) +part_type_alpha2(ind,alpha1,alpha2) +part_type_alpha3(ind,alpha1,alpha2,alpha3) +part_type_blend(ind,additive) +pt_shape_pixel# +pt_shape_disk# +pt_shape_square# +pt_shape_line# +pt_shape_star# +pt_shape_circle# +pt_shape_ring# +pt_shape_sphere# +pt_shape_flare# +pt_shape_spark# +pt_shape_explosion# +pt_shape_cloud# +pt_shape_smoke# +pt_shape_snow# + +// section 12.2 + +part_system_create() +part_system_destroy(ind) +part_system_exists(ind) +part_system_clear(ind) +part_system_draw_order(ind,oldtonew) +part_system_depth(ind,depth) +part_system_position(ind,x,y) +part_system_automatic_update(ind,automatic) +part_system_automatic_draw(ind,draw) +part_system_update(ind) +part_system_drawit(ind) + +part_particles_create(ind,x,y,parttype,number) +part_particles_create_color(ind,x,y,parttype,color,number) +part_particles_clear(ind) +part_particles_count(ind) + +// section 12.3 + +part_emitter_create(ps) +part_emitter_destroy(ps,ind) +part_emitter_destroy_all(ps) +part_emitter_exists(ps,ind) +part_emitter_clear(ps,ind) +part_emitter_region(ps,ind,xmin,xmax,ymin,ymax,shape,distribution) +part_emitter_burst(ps,ind,parttype,number) +part_emitter_stream(ps,ind,parttype,number) +ps_distr_linear# +ps_distr_gaussian# +ps_distr_invgaussian# +ps_shape_rectangle# +ps_shape_ellipse# +ps_shape_diamond# +ps_shape_line# + +// section 12.4 + +part_attractor_create(ps) +part_attractor_destroy(ps,ind) +part_attractor_destroy_all(ps) +part_attractor_exists(ps,ind) +part_attractor_clear(ps,ind) +part_attractor_position(ps,ind,x,y) +part_attractor_force(ps,ind,force,dist,kind,additive) +ps_force_constant# +ps_force_linear# +ps_force_quadratic# + +// section 12.5 + +part_destroyer_create(ps) +part_destroyer_destroy(ps,ind) +part_destroyer_destroy_all(ps) +part_destroyer_exists(ps,ind) +part_destroyer_clear(ps,ind) +part_destroyer_region(ps,ind,xmin,xmax,ymin,ymax,shape) + +// section 12.6 + +part_deflector_create(ps) +part_deflector_destroy(ps,ind) +part_deflector_destroy_all(ps) +part_deflector_exists(ps,ind) +part_deflector_clear(ps,ind) +part_deflector_region(ps,ind,xmin,xmax,ymin,ymax) +part_deflector_kind(ps,ind,kind) +part_deflector_friction(ps,ind,amount) +ps_deflect_vertical# +ps_deflect_horizontal# + +// section 12.7 + +part_changer_create(ps) +part_changer_destroy(ps,ind) +part_changer_destroy_all(ps) +part_changer_exists(ps,ind) +part_changer_clear(ps,ind) +part_changer_region(ps,ind,xmin,xmax,ymin,ymax,shape) +part_changer_kind(ps,ind,kind) +part_changer_types(ps,ind,parttype1,parttype2) +ps_change_all# +ps_change_shape# +ps_change_motion# + +////////////// +// Chapter 413 +////////////// + +// section 13.1 + +mplay_init_ipx() +mplay_init_tcpip(addrstring) +mplay_init_modem(initstr,phonenr) +mplay_init_serial(portno,baudrate,stopbits,parity,flow) +mplay_connect_status() +mplay_end() +mplay_ipaddress() + +// section 13.2 + +mplay_session_mode(move) +mplay_session_create(sesname,playnumb,playername) +mplay_session_find() +mplay_session_name(numb) +mplay_session_join(numb,playername) +mplay_session_status() +mplay_session_end() + +// section 13.3 + +mplay_player_find() +mplay_player_name(numb) +mplay_player_id(numb) + +// section 13.4 + +mplay_data_write(ind,value) +mplay_data_read(ind) +mplay_data_mode(guaranteed) + +// section 13.5 + +mplay_message_send(player,id,val) +mplay_message_send_guaranteed(player,id,val) +mplay_message_receive(player) +mplay_message_id() +mplay_message_value() +mplay_message_player() +mplay_message_name() +mplay_message_count(player) +mplay_message_clear(player) +////////////// +// Chapter 414 +////////////// + +external_call(id,arg1,arg2,...) +external_define(dll,name,calltype,restype,argnumb,arg1type,arg2type,...) +external_free(dllname) +get_function_address(function_name) +window_handle() +ty_real# +ty_string# +dll_cdecl# +dll_stdcall# +////////////// +// Chapter 415 +////////////// + +d3d_start() +d3d_end() +d3d_set_hidden(enable) +d3d_set_perspective(enable) +d3d_set_depth(depth) +d3d_set_zwriteenable(on_off) +d3d_primitive_begin(kind) +d3d_vertex(x,y,z) +d3d_vertex_color(x,y,z,col,alpha) +d3d_primitive_end() +d3d_primitive_begin_texture(kind,texid) +d3d_vertex_texture(x,y,z,xtex,ytex) +d3d_vertex_texture_color(x,y,z,xtex,ytex,col,alpha) +d3d_draw_block(x1,y1,z1,x2,y2,z2,texid,hrepeat,vrepeat) +d3d_draw_cylinder(x1,y1,z1,x2,y2,z2,texid,hrepeat,vrepeat,closed,steps) +d3d_draw_cone(x1,y1,z1,x2,y2,z2,texid,hrepeat,vrepeat,closed,steps) +d3d_draw_ellipsoid(x1,y1,z1,x2,y2,z2,texid,hrepeat,vrepeat,steps) +d3d_draw_wall(x1,y1,z1,x2,y2,z2,texid,hrepeat,vrepeat) +d3d_draw_floor(x1,y1,z1,x2,y2,z2,texid,hrepeat,vrepeat) +d3d_set_projection(xfrom,yfrom,zfrom,xto,yto,zto,xup,yup,zup) +d3d_set_projection_ext(xfrom,yfrom,zfrom,xto,yto,zto,xup,yup,zup,angle,aspect,znear,zfar) +d3d_set_projection_ortho(x,y,w,h,angle) +d3d_set_projection_perspective(x,y,w,h,angle) +d3d_transform_set_identity() +d3d_transform_set_translation(xt,yt,zt) +d3d_transform_set_scaling(xs,ys,zs) +d3d_transform_set_rotation_x(angle) +d3d_transform_set_rotation_y(angle) +d3d_transform_set_rotation_z(angle) +d3d_transform_set_rotation_axis(xa,ya,za,angle) +d3d_transform_add_translation(xt,yt,zt) +d3d_transform_add_scaling(xs,ys,zs) +d3d_transform_add_rotation_x(angle) +d3d_transform_add_rotation_y(angle) +d3d_transform_add_rotation_z(angle) +d3d_transform_add_rotation_axis(xa,ya,za,angle) +d3d_transform_stack_clear() +d3d_transform_stack_empty() +d3d_transform_stack_push() +d3d_transform_stack_pop() +d3d_transform_stack_top() +d3d_transform_stack_discard() +d3d_set_fog(enable,color,start,end) +d3d_set_lighting(enable) +d3d_set_shading(smooth) +d3d_set_culling(cull) +d3d_light_define_ambient( col ) +d3d_light_define_direction(ind,dx,dy,dz,col) +d3d_light_define_point(ind,x,y,z,range,col) +d3d_light_enable(ind,enable) +d3d_vertex_normal(x,y,z,nx,ny,nz) +d3d_vertex_normal_color(x,y,z,nx,ny,nz,col,alpha) +d3d_vertex_normal_texture(x,y,z,nx,ny,nz,xtex,ytex) +d3d_vertex_normal_texture_color(x,y,z,nx,ny,nz,xtex,ytex,col,alpha) + +d3d_model_create() +d3d_model_destroy(ind) +d3d_model_clear(ind) +d3d_model_save(ind,fname) +d3d_model_load(ind,fname) +d3d_model_draw(ind,x,y,z,texid) + +d3d_model_primitive_begin(ind,kind) +d3d_model_vertex(ind,x,y,z) +d3d_model_vertex_color(ind,x,y,z,col,alpha) +d3d_model_vertex_texture(ind,x,y,z,xtex,ytex) +d3d_model_vertex_texture_color(ind,x,y,z,xtex,ytex,col,alpha) +d3d_model_vertex_normal(ind,x,y,z,nx,ny,nz) +d3d_model_vertex_normal_color(ind,x,y,z,nx,ny,nz,col,alpha) +d3d_model_vertex_normal_texture(ind,x,y,z,nx,ny,nz,xtex,ytex) +d3d_model_vertex_normal_texture_color(ind,x,y,z,nx,ny,nz,xtex,ytex,col,alpha) +d3d_model_primitive_end(ind) + +d3d_model_block(ind,x1,y1,z1,x2,y2,z2,hrepeat,vrepeat) +d3d_model_cylinder(ind,x1,y1,z1,x2,y2,z2,hrepeat,vrepeat,closed,steps) +d3d_model_cone(ind,x1,y1,z1,x2,y2,z2,hrepeat,vrepeat,closed,steps) +d3d_model_ellipsoid(ind,x1,y1,z1,x2,y2,z2,hrepeat,vrepeat,steps) +d3d_model_wall(ind,x1,y1,z1,x2,y2,z2,hrepeat,vrepeat) +d3d_model_floor(ind,x1,y1,z1,x2,y2,z2,hrepeat,vrepeat) + + +// YoYo extension stuff +os_win32# +os_win64# +os_macosx# +os_psp# +os_ios# +os_android# + +device_ios_iphone# +device_ios_iphone_retina# +device_ios_ipad# + +os_type* +os_device* +display_aa* + +text_type# +button_type# +input_type# + +ANSI_CHARSET# +DEFAULT_CHARSET# +EASTEUROPE_CHARSET# +RUSSIAN_CHARSET# +SYMBOL_CHARSET# +SHIFTJIS_CHARSET# +HANGEUL_CHARSET# +GB2312_CHARSET# +CHINESEBIG5_CHARSET# +JOHAB_CHARSET# +HEBREW_CHARSET# +ARABIC_CHARSET# +GREEK_CHARSET# +TURKISH_CHARSET# +VIETNAMESE_CHARSET# +THAI_CHARSET# +MAC_CHARSET# +BALTIC_CHARSET# +OEM_CHARSET# + diff --git a/snippets_gml/tester/obj_control.object.gml b/snippets_gml/tester/obj_control.object.gml new file mode 100644 index 0000000..64220e4 --- /dev/null +++ b/snippets_gml/tester/obj_control.object.gml @@ -0,0 +1,12 @@ +#event create +start_time = current_time; + +#event keypress:vk_escape +if (keyboard_check(vk_shift)) { + game_end_direct() +} else { + game_end(); +} + +#event draw +draw_text(5, 5, string((current_time - start_time) div 1000)) \ No newline at end of file diff --git a/snippets_gml/tester/obj_player.object.gml b/snippets_gml/tester/obj_player.object.gml new file mode 100644 index 0000000..783174b --- /dev/null +++ b/snippets_gml/tester/obj_player.object.gml @@ -0,0 +1,11 @@ +sprite_index = sprite_add("spr_test.png", 1, false, false, 24, 24); + +#event step +//x += 4 * (keyboard_check(vk_right) - keyboard_check(vk_left)); +y += 4 * (keyboard_check(vk_down) - keyboard_check(vk_up)); + +#event keyboard:vk_left +x -= 4; + +#event keyboard:vk_right +x += 4; \ No newline at end of file diff --git a/snippets_gml/tester/overrides.gml b/snippets_gml/tester/overrides.gml new file mode 100644 index 0000000..254a04c --- /dev/null +++ b/snippets_gml/tester/overrides.gml @@ -0,0 +1,5 @@ +#define game_end +if (show_question("Really quit?")) game_end(); + +#define game_end_direct +game_end(); \ No newline at end of file diff --git a/snippets_gml/tester/snippet_tester.gm81 b/snippets_gml/tester/snippet_tester.gm81 new file mode 100644 index 0000000..91472d7 Binary files /dev/null and b/snippets_gml/tester/snippet_tester.gm81 differ diff --git a/snippets_gml/tester/snippets.dll b/snippets_gml/tester/snippets.dll new file mode 100644 index 0000000..33878d1 Binary files /dev/null and b/snippets_gml/tester/snippets.dll differ diff --git a/snippets_gml/tester/spr_test.png b/snippets_gml/tester/spr_test.png new file mode 100644 index 0000000..ca40990 Binary files /dev/null and b/snippets_gml/tester/spr_test.png differ diff --git a/snippets_gml/tester/startup.gmk-snips b/snippets_gml/tester/startup.gmk-snips new file mode 100644 index 0000000..16f9a59 --- /dev/null +++ b/snippets_gml/tester/startup.gmk-snips @@ -0,0 +1,4 @@ +overrides.gml +obj_control.object.gml> +obj_player.object.gml +> instance_create(100, 100, obj_player) \ No newline at end of file