Asset - Extension GMLive.gml - livecoding for GMS1 & GMS2! [live shader reloading soon!]

Discussion in 'Marketplace' started by YellowAfterlife, Nov 17, 2017.

  1. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,475
    banner.png
    Links: blog post · itch.io · marketplace
    Price: USD 29.95 (itch) / USD 39.99 (marketplace)
    GIFs: livecoding a visual effect in GMS1 · tweaking things in GMS2 · initial teaser
    Modules (GMS2): all
    Modules (GMS1): all but HTML5 (bug wasn't resolved before EoL)
    Versions: GMS1, GMS2

    GMLive is an extension that introduces livecoding / interactive programming into GameMaker: Studio and GameMaker Studio 2 (incl. Mac IDE).

    That is, it allows to reload chosen scripts or events mid-game when they are changed from the editor - without having to recompile and restart the game.

    This allows to save tremendous amounts of time during development, especially for projects and platforms with longer compile time.

    For those familiar, this was in the works for a little while now (since June!) and I'm proud to finally have it finished and released.

    If there are any questions, do ask. Have fun!
     
    Last edited: Jan 12, 2020
    fireday2, chirpy, Bart and 14 others like this.
  2. Felipe Rybakovas

    Felipe Rybakovas Member

    Joined:
    Apr 12, 2017
    Posts:
    267
    Just wanna say that this is great!

    Really... Thanks.


    And just another thing... a had an issue with the macros... I had to import my Default to All configuration to be located.


    But again, thanks, this is great.
     
    YellowAfterlife likes this.
  3. 7bones

    7bones Member

    Joined:
    Jun 22, 2016
    Posts:
    44
    How with performance in big projects? Will it cost a lot of FPS while testing?
     
  4. rIKmAN

    rIKmAN Member

    Joined:
    Sep 6, 2016
    Posts:
    4,912
    This looks very cool - great job as always @YellowAfterlife.

    Is there any difference between the itch version and the marketplace version?
    I ask as I notice there is a ~$10 price difference.
     
  5. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    145

    [​IMG]
     
  6. rIKmAN

    rIKmAN Member

    Joined:
    Sep 6, 2016
    Posts:
    4,912
    Literally just finished reading the blog entry and was about to edit my post , but you saved me a job, thanks.
     
  7. hippyman

    hippyman Member

    Joined:
    Jun 20, 2016
    Posts:
    565
    For crying out loud YYG, hire this man!
     
    Dogarooski, Samuel Venable and rIKmAN like this.
  8. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,299
    Agreed. I can't imagine all the good he could do for GameMaker as an official developer of it. I mean look at him now, he's already doing so much! I think @YellowAfterlife and @zbox are probably the two most experieced extension makers in the community.

    @YellowAfterlife This looks really interesting. I have no direct need for it, but I can't imagine how much work this must have been to create.
     
    zbox likes this.
  9. Felipe Rybakovas

    Felipe Rybakovas Member

    Joined:
    Apr 12, 2017
    Posts:
    267
    @YellowAfterlife , Im having a issue using arrays during live code.

    [live][01:32:19] Runtime error: gml_Script_draw_tooltip_container[29:24] Row index (11) is out of bounds (0..5 excl.)

    The code :
    colorOut= magic_arr[i,11];

    Array creation:
    //MAGIC BAR ARRAY
    magic_arr[0,11] = 0; //PRIMARY ATK / MOUSE L - ZR
    magic_arr[1,11] = 0; //SKILL ATK / MOUSE R - R
    magic_arr[2,11] = 0; //SKILL ATK / E - L
    magic_arr[3,11] = 0; //SKILL ATK / Q - ZL
    magic_arr[4,11] = 0; //ULTIMATE ATK / SPACE - B


    Can advice please ?
    Thank you!
     
  10. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,475
    Oh, I can probably fix that - I forgot that per-configuration macros are stored separately in GMS1.

    Only the scripts containing live_call are interpreted, so project size has no effect on performance.
    That's an equivalent of a normal GML error - you are trying to read something outside the array on line 29, column 24; "row" is the first of two indexes.
     
    Last edited: Nov 18, 2017
  11. Lukan

    Lukan Gay Wizard Freak

    Joined:
    Jun 20, 2016
    Posts:
    409
    @Mike @rwkay HIRE THIS INDIVIDUAL!
    It would be awesome if this ended up as part of gms2
     
  12. Felipe Rybakovas

    Felipe Rybakovas Member

    Joined:
    Apr 12, 2017
    Posts:
    267
    So that is the issue.

    The game compiles normally... without errors. The error happens with the GMLive compiler...

    to apply the changes I need to close and run it again..
    Im 100% sure that I´m accessing it right.
     
  13. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,475
    If the project isn't overly big/secret, please PM me a GMZ so that I can debug what's different.
    If it is, try reproducing the error on a blank project by copying related bits of code over to it.
     
    Felipe Rybakovas likes this.
  14. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,475
    New version is now live (update log), fixing various small oddities that people found so far.
     
    rIKmAN likes this.
  15. rIKmAN

    rIKmAN Member

    Joined:
    Sep 6, 2016
    Posts:
    4,912
    @YellowAfterlife
    Looking at the visual effect video it seems that you can add draw calls and have them live update - would this also work for actually changing the sprite completely (ie. live reloading a whole new sprite)

    Also would live reloading work with Spine sprites?
    Things such as changing the actual sprite / skeleton used (as above) and live updating slots/attachments, using the skeleton_* functions to manipulate the skeleton data in realtime and changing animations etc?

    Sorry if these are silly questions, but I know the Spine stuff is handled differently by GMS on the backend (texture pages and such) so I thought it was worth asking before I make the purchase.

    Thanks.
     
    Last edited: Nov 20, 2017
  16. Arconious

    Arconious Member

    Joined:
    Jun 20, 2016
    Posts:
    38
    Hey YellowAfterLife,

    Thanks much for making this! I very much appreciate the extensions you've thus created.

    In trying to integrate this with my current project, I've run into a few snafus:

    1) live_call_ext() / live_defcall() do not seem to be included with my package/extension. (I am using GMS2, bought from Yoyo Marketplace). [​IMG]Image for reference.

    2) I make heavy use of your TJSON extension, but it appears I have to make sure any of those tj_get/set function calls are nested within individual scripts themselves, otherwise GMLive reports 'tj_get is not a function or a script'. This applies to other extensions as well, per your documentation. Is my understanding here correct?

    3) I kept getting a "Not a constant expression" error on scripts/events that included the 'live_call' function, including the base obj_gmlive object:
    Code:
    [live][12:09:07 AM] Ready!
    [live][12:09:07 AM] Error in obj_gmlive:Draw_0:
    [live][12:09:07 AM] Not a constant expression
    [live][12:09:07 AM] Error in ActorStateAttack:
    [live][12:09:07 AM] Not a constant expression
    This one I am at a loss for, and I accept that it is highly likely it is just my ineptitude in some fashion here. 'ActorStateAttack' was the only script I placed the live_call functionality in thus far, and the script does not take any arguments directly. It does call a series of other scripts, but do each of those need to the live_call functionality within them in order to properly function?

    For reference:
    Code:
    ///ActorStateAttack()
    if ((stateMethod & STATE_METHOD_START) == STATE_METHOD_START)
    {
        AbilityActivate(actorCurrentAbility);
        var _abilityAttributeList = actorCurrentAbility[abilitySlot.abilityAttributeList];
        var inputAnimation = actorCurrentAbility[abilitySlot.animation];
        var inputDuration = actorCurrentAbility[abilitySlot.durationMax];
    
        AnimationObjectsSetAnimation(id, animationObjects, inputAnimation);
        AnimationObjectsSetDuration(animationObjects, inputDuration);
     
        if (isWeaponEquipped)
        {
            drawWeaponEnabled = true;
        }
       
        actorAbilityDirection = actorCurrentAbility[abilitySlot.direction];
        velocity[vec2.x] = 2 * actorAbilityDirection;
        actorMoveDirection = sign(velocity[vec2.x]);
     
        stateMethod = stateMethod ^ STATE_METHOD_START; //Reset toggle to off
    }
    
    
    if ((stateMethod & STATE_METHOD_STEP) == STATE_METHOD_STEP)
    {
        ActorApplyFriction(velocity, actorMoveFriction);
        if (!isOnGround)
            ActorApplyGravity(velocity, actorMoveGravity);
        //ActorCallStateMethod(actorStates.move, STATE_METHOD_STEP);
        MovementUpdate();
    }
    
    
    if ((stateMethod & STATE_METHOD_DRAW) == STATE_METHOD_DRAW)
    {
        //Draw Setup
        image_xscale = actorAbilityDirection;
        AnimationObjectsUpdate(id, animationObjects);
    }
    
     
    Last edited: Nov 20, 2017
  17. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,475
    Just published a new version that fixes that mishap.
    Should also be fixed in new version. Depending on factors, may need to change "tj_true" and alike macros in extension from just "g_tj_true" to "global.g_tj_true" because that was relying on globalvar declaration in another file but I did not derive the exact globalvar<->macro relationship/compilation order in GML yet.
    This is most likely it not being able to figure what value something is in an enum somewhere, but this particular error was missing position information. New version should show the actual file-row-column of what it's upset about.
    GMLive only handles code updates for the time being. Texture information (and specifically Spine data) is largely unexposed in GM so it is not possible to modify these things at runtime without substantial reverse engineering (and violation of GMS and Spine licenses in process).
     
    Arconious and rIKmAN like this.
  18. rIKmAN

    rIKmAN Member

    Joined:
    Sep 6, 2016
    Posts:
    4,912
    Ah I see, thanks for clearing that up regarding Spine.
     
  19. Arconious

    Arconious Member

    Joined:
    Jun 20, 2016
    Posts:
    38
    Thanks for the fast update!

    I hate to be a bother, but unfortunately I'm still having difficulty getting my project to comply with having only the obj_gmlive containing any live_call functionality. After you pointed out the meaning behind the error (and with the handy line references you added), I was able to determine that GMLive does not appreciate storing script references in enums and an enum that had a staggered index count that used macros of which are just integer amounts. Whenever it hit an enum it did not appreciate, it would error out with:
    Code:
    [live][10:35:41 PM] Ready!
    [live][10:35:41 PM] Error in obj_gmlive:Draw_0:
    [live][10:35:41 PM] enum items [L3,c13] Not a constant expression
    ERROR!!! :: ############################################################################################
    FATAL ERROR in
    action number 1
    of Draw Event
    for object obj_gmlive:
    
    
    trying to index a variable which is not an array
     at gml_Script_live_call (line 20) -             var l_name=l_pg[13];
    ############################################################################################
    --------------------------------------------------------------------------------------------
    stack frame is
    gml_Script_live_call (line 20)
    called from - gml_Object_obj_gmlive_Draw_0 (line 2) - if (live_call()) return live_result;
    
    Code:
    [live][10:35:41 PM] Ready!
    [live][10:35:41 PM] Error in obj_gmlive:Draw_0:
    [live][10:35:41 PM] enum items [L3,c13] Not a constant expression
    ERROR!!! :: ############################################################################################
    FATAL ERROR in
    action number 1
    of Draw Event
    for object obj_gmlive:
    
    
    trying to index a variable which is not an array
     at gml_Script_live_call (line 20) -             var l_name=l_pg[13];
    ############################################################################################
    --------------------------------------------------------------------------------------------
    stack frame is
    gml_Script_live_call (line 20)
    called from - gml_Object_obj_gmlive_Draw_0 (line 2) - if (live_call()) return live_result;
    

    For reference, the enum's I had it error out on were:
    Code:
    #macro BASE_HELM_ITEM_INDEX        10000
    #macro BASE_ARMOR_ITEM_INDEX    20000
    #macro BASE_RING_ITEM_INDEX        30000
    #macro BASE_WEAPON_ITEM_INDEX    40000
    
    enum items {
        noItem,
        ironHelm    =    BASE_HELM_ITEM_INDEX,
        steelHelm,
        jellyHelm,
        hoodedHelm,
        _countHelm,
        armor1        =    BASE_ARMOR_ITEM_INDEX,
        armor2,
        _countArmor,
        ring1        =    BASE_RING_ITEM_INDEX,
        ring2,
        _countRing,
        woodsword1    =    BASE_WEAPON_ITEM_INDEX,
        silversword1,
        woodhammer1,
        etc...
        _countWeapon
    }
    
    enum actorStates {
        idle            =    ActorStateIdle,
        move            =    ActorStateMove,
        jump            =    ActorStateJump,
            etc
    }

    I recognize this may just be a symptom of funky/improper enum use, so feel free to tell me as such.
     
  20. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,475
    I uploaded a hotfix (1.0.5) shortly after 1.0.4 yesterday to fix that (only occurred if the original script wouldn't compile).
    That's not entirely wrong (in fact, that's first time I see someone use asset IDs as enum values), but I uploaded a new version (1.0.7) that should be more more forgiving to such use cases.
     
  21. kburkhart84

    kburkhart84 Firehammer Games

    Joined:
    Jun 26, 2016
    Posts:
    470
    Quick question(considering purchase)...is there not a nice automatic way to remove this stuff for exports/builds? I notice you state in the documentation to to change a certain macro, which makes the scripts all simply return default values instead of actually executing...but if you do this you still have any and all of those script calls, which can reduce performance. Or would simply removing the object you put in the first room and any calls to the live* scripts be enough to restore full performance? I miss "live coding" from Unity's system in GMS2, but I wouldn't want to sacrifice performance to achieve it.
     
  22. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,475
    GameMaker evaluates constant expessions compile-time, so
    Code:
    if (1) trace("yes"); else trace("no");
    becomes trace("yes"), and
    Code:
    if (0) trace("oh");
    simply vanishes.

    All of the extension's scripts are structured like
    Code:
    if (live_enabled) {
    // script code
    }
    so flipping that macro strips out all of the extension code entirely, and calling a completely empty script doesn't take very long at all.

    Still, you can have if (!live_enabled) instance_destroy() in obj_gmlive and have your "live" lines like
    Code:
    if (live_enabled && live_call()) return live_result;
    but the later are usually commented out once you are done messing with the given bit of code, and calling a single empty script per game frame isn't much of a concern.
     
  23. kburkhart84

    kburkhart84 Firehammer Games

    Joined:
    Jun 26, 2016
    Posts:
    470
    So the trick is to add the live_call() line to only a few scripts at a time anyway for performance according to the documentation. Once done working with that set of scripts you can comment the line out of course. And your persistent object(the one you add to the first room), it does nothing if no live_call() scripts are called?

    I'm wondering if you set that macro could it instead simply destroy itself? I'm sure you would run into issues if someone tries to use the system in those cases(though that problem is created by the user). Is that just a decision you made for that reason?
     
  24. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,475
    if live_enabled is 0, it does nothing. If live_enabled is 1, it'll still try to ping the live-server because the game itself has no way of knowing what code it contains and if any of it uses live_call.

    At this time you can safely destroy the object yourself without any consequences if live_enabled == 0, or have it self-destruct if the server doesn't respond to the first ping (recently asked), or on any other condition - it's role is to run initialization on game start and then send/receive HTTP requests from the local server, none of which happen if live_enabled is false. The code can also be surrounded by if (live_enabled) { } and moved to any custom persistent controller if potentially wasting ~1 microsecond per game frame is an issue.
     
  25. kburkhart84

    kburkhart84 Firehammer Games

    Joined:
    Jun 26, 2016
    Posts:
    470
    I'm probably overly picky about this kind of thing...so I'd likely just have the object destroy itself if the macro is flipped. It would be my risk as far as making sure I deleted the code enabling live edit on scripts. I don't mind the little bit of performance hit during testing, as it would get me Unity-like live code editing, quite useful for many things. Consider me a customer, since it provides a quite useful feature and the slight drawbacks won't affect the final products.

    EDIT****

    I added $5 to the purchase price. This is one of those things that I see being extremely useful. You are welcome :)
     
  26. kburkhart84

    kburkhart84 Firehammer Games

    Joined:
    Jun 26, 2016
    Posts:
    470
    I just had a thought(new info, new post). I wonder how good of an idea it would be to use macros for this. You can have macros be defined differently for different configurations, so if I have one for debug, one not, I should be able to make things automatic. One macro would be quick code to create in code the controller object, and if not in debug mode it would be blank(or a comment). Another macro would be similar, but for the live_edit() script. Instead of placing the controller in the room editor, I would create it in my first controller objects code(or even in the room init code event) using that macro so it doesn't actually happen if not in debug mode.

    As a suggestion, I think you could make this a method of use automatically included in your extension(for GMS2 at the least). Macros can be defined in any script, so you could easily put it in your scripts somewhere. It would have to simply be an alternative way to do things though, especially since GMS1 can't do it the exact same way(not with extensions I mean, and macros not being created in scripts).
     
  27. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,475
    GMS2 version has the macro defined in obj_gmlive itself. I don't think you can define configuration-specific code in extensions? Even if that seemed like a good idea (given that everyone can name configurations as they please)
    While I appreciate everyone's enthusiasm about macros in GMS2, I don't think "put this magic text" is an easier to understand concept than "put an instance of this object" (which does reasonably imply that you can also create or not create it with code).

    Having macros for if (live_call(...)) lines makes a bit more sense, but, unless something changed in the recent update, GMS2 doesn't allow to use argument#/argument[] in a macro.
     
  28. kburkhart84

    kburkhart84 Firehammer Games

    Joined:
    Jun 26, 2016
    Posts:
    470
    Good points about configs and macros...I forgot about the fact that people name their configs as they please.

    However, the example for macros in the manual specifically states you can put a function call there, with arguments. Maybe I missed exactly what you meant, but for sure you can put functions as part of macros, and it will actually call that function each time you reference the macro(according to the manual). The example uses the following macro.
    Code:
    #macro col make_colour_hsv(irandom(255, 255, 255)
    
    It then says that using that code would return a different color each time. So for the purposes of the live_call() function, it makes good sense, and I'd say at least on a personal level my other suggestion makes sense, although maybe not for something you can add to your extension...maybe something you document as simply a possible way to use it?!
     
  29. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,475
    New update is now out!

    This is a big one, adding support for live updating sprites as well.
    You call sprite_set_live, and then you can edit the images/origin/collision mask from GMS1/GMS2/external software, and it'll show up in-game as soon as the file is saved.
    yep-2.gif
    yep-3.gif
     
    kagamma likes this.
  30. kagamma

    kagamma Member

    Joined:
    Sep 18, 2017
    Posts:
    13
    Thanks for the update! I just test the new version and I can access deactivated instances and call return without errors now.

    About hexadecimal prefix issue I still get "Expected a statement, got gml_node_Ident" error.
     
  31. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,475
    Fixed this for sure now.

    Also released a new update with support for room reloading, which more or less completes the set of features that I like for rapid prototyping.
    yep4.gif yep-physics.gif
     
    kagamma and Rukola like this.
  32. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,475
    Apparently I forgot to update this thread for a little bit, but since my last post here I have made GMLive compatible with GMS2 HTML5 module, and am currently working on shader live reloading!
    gmlive-shaders-12.gif
    For the initial release I'm targeting Windows with this, but may later be able to expand the functionality to support HTML5, and, possibly, Mac/Linux;
    Since the helper extension for this introduces a literal shader_replace function, it may also prove handy for other purposes (much like live_execute_string does).
     
  33. JaimitoEs

    JaimitoEs Member

    Joined:
    Aug 9, 2016
    Posts:
    217
    Pretty sweet!:):):)
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice