Giter Club home page Giter Club logo

Comments (10)

SamWindell avatar SamWindell commented on August 30, 2024

This is an interesting idea, and wouldn't be too difficult to implement. I guess it's use would be dealing with UI controls. But I must admit, I'm not immediately sold on it!

Macros aren't usually a good idea unless Kontakt is forcing you to use them, for example with add_menu_item() or set_table_steps_shown() or for making ui_control callbacks. In your example, wouldn't it be easier and more efficient to make an array containing the UI IDs of the controls, then turn the macro into a function/taskfunc and iterate over it?

For cases where we are forced to use macros, I suppose this new functionality might be handy. I've personally never felt the need for it. Do you specific example where this would be useful?

from sublimeksp.

eitherys avatar eitherys commented on August 30, 2024

Sure!

For example, if you were to create a select of controls and callbacks associated with some kind of "system", or "object".

To be concrete, I may want to create a bunch of controls associated with different articulations. I want one "system" for SUSTAIN, one for STACCATO, etc. Furthermore, this system may have macro calls in a couple different places. One macro in the ICB, one macro for callbacks, one macro for listener behavior and so on.

Normally I simply do this as:

macro initBehavior(#artic#)
    ...
end macro
macro listenerBehavior(#artic#)
    ...
end macro
macro callbackBehavior(#artic#)
    ...
end macro

on init
    initBehavior(SUSTAIN)
    initBehavior(STACCATO)
    ...
end on

on listener
    listenerBehavior(SUSTAIN)
    listenerBehavior(STACCATO)
    ...
end on

callbackBehavior(SUSTAIN)
callbackBehavior(STACCATO)
...

This is an overly simplistic example, but it illustrates the maintainability issue of the code; when we want to edit, remove, or add an articulation, we have to find its occurrence in multiple places. This is kind of simple in this example, but for the work I do, code can be split across several files and be thousands of lines of moving parts, it becomes time consuming to try and make the code flexible by hunting down every instance of a system or object generation associated with these common literal names.

What makes more sense to me from my experience outside of KSP is this:

declare literals articulations := (SUSTAIN, STACCATO, TREMOLO, TENUTO, MARCATO, PIZZICATO, SPICCATO, PORTATO, CRESCENDO, DIMINUENDO, RIP, FALL)

on init
    literate_macro(initBehavior) on articulations
end on

on listener
    literate_macro(listenerBehavior) on articulations
end on

literate_macro(callbackBehavior) on articulations

from sublimeksp.

eitherys avatar eitherys commented on August 30, 2024

You'll notice now that maintenance has been reduced from a lot of potentially buggy moving parts to a simple code generation task abstracted AWAY from the developer by simply editing a nice master list.

Single point of (unlikely) failure.

Additionally, this grants us modularity and code independence. I can write macro code-generation systems that depend on this "articulations" literal list and not have to care what the articulations actually are. Sublime will take care of actually filling them in when I hit "compile". I can then re-use the macros for different sample libraries with different articulations but not actually have to edit anything EXCEPT for the "articulations" list itself per library.

from sublimeksp.

eitherys avatar eitherys commented on August 30, 2024

To provide a side point, this basically accomplishes what your current iterate_macro() already does; it simply is not limited to a set of iterable numbers and instead is extended to allow iteration over any collection of literal names. From an efficiency standpoint, I have nothing to gain by instead doing this with the current iterate_macro(), with numbers associated with those articulations since it's the same code with just different names, and I have the added disadvantage of incomprehensible code on top of that. It's a lose-lose!

from sublimeksp.

andreasOL16 avatar andreasOL16 commented on August 30, 2024

I second this request. I work the same, often having macros for ICB to declare and initialize ui components and macros to generate callbacks belonging to these ui objects. Problem is not so much the deletion of instances (if you remove code from the ICB which results in objects not being declared you're going to get compile error if the callbacks are still generated) but the other way round: An object is added in the ICB but one forgets to add the callbacks so nothing happens on ui interaction.

from sublimeksp.

SamWindell avatar SamWindell commented on August 30, 2024

I see what you mean, I used to use this method as well. However, it's no longer necessary to use macros in this way. Your idea for literate_macro() would absolutely improve using macros like this, however the best thing to do is just avoid macros as much as possible! By simply using the new UI arrays instead of macros for making controls, we can have a much nicer system. These UI arrays are of UI IDs, so rather than just duplicating code, we are actually using arrays and loops.

This also increases readability and robustness of you code:

  • The program is faster because we are actually using loops and arrays rather than duplicating the same code.
  • You no longer need to make macros for every circumstance (init, callback, listener).
  • You can write better functions that just take integer arguments rather than duplicating functions just to receive different names.
  • Much less nasty # symbols in the code.
  • Your UI and data is actually organised in data structures, like arrays. While before you have to be thinking about how the code will function as just a long list of stuff.

There are still some situations where we are forced to use UI control names, rather than IDs (making callbacks for example). And this is where we can use iterate_macro().

If for example this is your code:

macro initBehavior(#artic#)
    declare ui_slider #artic#Slider (0, 100)
    declare ui_switch #artic#Switch
    declare #artic#Variable
    #artic#Slider -> picture := "graphic"
    #artic#Slider -> mouse_behaviour := -500
    set_bounds(#artic#Slider, 0, 10)
end macro

macro callbackBehavior(#artic#)
    on ui_control(#artic#Slider)
        // do something
    end on
    on ui_control(#artic#Switch)
        // do something
    end on
end macro

on init
    initBehavior(SUSTAIN)
    initBehavior(STACCATO)
end on

callbackBehavior(SUSTAIN)
callbackBehavior(STACCATO)

It would be much better written like this:

on init
    define NUM_ARTICULATIONS := 2 // All we have to do is change this number to add/remove more articulations.
    declare ui_slider articSlider[NUM_ARTICULATIONS] (0, 100)
    declare ui_switch articSwitch[NUM_ARTICULATIONS]
    declare articVariable[NUM_ARTICULATIONS]
    declare i
    for i := 0 to NUM_ARTICULATIONS - 1
        articSlider[i] -> picture := "graphic"
        articSlider[i] -> mouse_behaviour := -500
        set_bounds(articSlider[i], 0, 10)
    end for
end on

macro arcticCallbacks(#n#)
    on ui_control(articSlider#n#)
        message(articSlider[#n#] -> value)
    end on
    on ui_control(articSwitch#n#)
        message(articSwitch[#n#] -> value)
    end on
end macro
iterate_macro(articCallbacks) := 0 to NUM_ARTICULATIONS - 1

from sublimeksp.

eitherys avatar eitherys commented on August 30, 2024

Sam,

I am an experienced software developer and have carefully considered efficiency techniques using KSP. Your assumptions about the efficiency and maintainability of certain techniques (including your own proposed technique), as well as those of how I write my code (such as assuming I don't already organize ui controls into an array-based system) aren't correct at all, but I don't wish to drag out a debate here. The fact of the matter is these situations do arise in my work.

If you don't see the use for it, I will reserve time to implement it myself in the future, hopefully you will at least approve the pull request.

from sublimeksp.

SamWindell avatar SamWindell commented on August 30, 2024

I don't mean to shoot your idea down, just sharing my opinion :) In my example I perhaps should have used 'one' rather than 'you' or 'your', I wasn't trying to insinuate that your code was bad!

Anyways, yes it will do no harm having this feature. Take a look at file preprocessor_plugins file, I'm sure you will find it no trouble adding in this functionality.

from sublimeksp.

eitherys avatar eitherys commented on August 30, 2024

Sam,

I apologize if I seemed aggressive. Thank you for the consideration, and I will!

from sublimeksp.

eitherys avatar eitherys commented on August 30, 2024

As a side note, your technique DOES have a great potential for some other applications/systems. So thank you for sharing! I likely will implement it for something it works well with, and thank you for taking the time to enhance SublimeKSP to allow for it.

from sublimeksp.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.