Announcement

Collapse
No announcement yet.

How to Write a MAKI Script

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to Write a MAKI Script

    How to write a MAKI script:

    ive seen alot of new skinners comming into the forums asking about maki. most of the time they are just refered to std.mi. the problem is that unless you know something about programming, it wont get you very far. this will serve as a crash course of sorts through maki programming, and will help you get from a blank page to a fully compiled script...hopefully. so lets begin

    im going to use a script i wrote myself. its pretty simple and should be easy enough to follow. here it is in full:
    code:

    //----------------------------------------------------------------------------------------------------------------
    // wingsanim.m
    //
    // controls animation between layouts
    // be warned...i accedentally messed this script up after compiling, so as is it actually
    // wont compile as is cuz i dont feel like looking for why it wont
    //
    // help by FrisbeeMonkey
    //
    //----------------------------------------------------------------------------------------------------------------

    #include "../../../lib/std.mi"

    Global AnimatedLayer WingAnim;
    Global Group AnimGroup, RetractGroup1, RetractGroup2;
    Global Button Button1, Button2;
    Global Layout NormalLayout, ClosedLayout, AnimationLayout;
    Global Container MainContainer;
    Global Int a;


    System.onScriptLoaded() {

    MainContainer = getContainer("main");
    Layout NormalLayout = MainContainer.getLayout("normal");
    Layout ClosedLayout = MainContainer.getLayout("closed");
    Layout AnimationLayout = MainContainer.getLayout("animation");

    AnimGroup = AnimationLayout.getObject("anim");
    WingAnim = AnimGroup.getObject("wingsanim");
    RetractGroup1 = NormalLayout.getObject("retract");
    Button1 = RetractGroup1.getObject("ret");
    RetractGroup2 = ClosedLayout.getObject("retract2");
    Button2 = RetractGroup2.getObject("ret");

    WingAnim.setSpeed(65);
    a = 0;

    }

    WingAnim.onStop(){
    if(a == 1){
    MainContainer.switchToLayout("closed");
    }
    else if(a == 0){
    MainContainer.switchToLayout("normal");
    }
    }

    Button1.onLeftButtonUp(int x, int y) {
    a = 1;
    WingAnim.setStartFrame(1);
    WingAnim.setEndFrame(8);
    MainContainer.switchToLayout("animation");
    WingAnim.play();
    }
    Button2.onLeftButtonUp(int x, int y) {
    a = 0;
    WingAnim.setStartFrame(8);
    WingAnim.setEndFrame(1);
    MainContainer.switchToLayout("animation");
    WingAnim.play();
    }

    not too complicated, but can be a little intimidating. so lets break it up
    code:

    //----------------------------------------------------------------------------------------------------------------
    // wingsanim.m
    //
    // controls animation between layouts
    // be warned...i accedentally messed this script up after compiling, so as is it actually
    // wont compile as is cuz i dont feel like looking for why it wont
    //
    // help by FrisbeeMonkey
    //
    //----------------------------------------------------------------------------------------------------------------

    this is not required to make your script work, but its nice. just a little intro and credits to your skin. what it does and who made it.
    code:

    #include "../../../lib/std.mi"

    never forget this. it tell the script to look for all the commands youre going to tell it later. make sure it looks just like that and is at the top of your page.
    code:

    Global AnimatedLayer WingAnim;
    Global Group AnimGroup, RetractGroup1, RetractGroup2;
    Global Button Button1, Button2;
    Global Layout NormalLayout, ClosedLayout, AnimationLayout;
    Global Container MainContainer;
    Global Int a;

    in the Globals area we define any variables we use or items we refrence. if you have a button that will, lets say, increase the volume, you should first put it in your xml (im going to asume you know xml for this), and then have something like "Global Button -yourbutton-". what goes in the -yourbutton- spot is up to you, just make sure you remember it for the next part. there are many kinds of Globals, as you can see here. to know which one to use, just look at youre xml. if it looks like this:
    code:

    x="2" y="2"
    w="335" h="403"
    id="wingsanim"
    image="winganim"
    move="0"
    autoplay="0"
    autoreplay="0"
    sysregion="1"
    ghost="1"
    />

    then you want a Global AnimatedLayer (notice the first part of the xml is the type of Global).
    code:

    System.onScriptLoaded() {

    MainContainer = getContainer("main");
    Layout NormalLayout = MainContainer.getLayout("normal");
    Layout ClosedLayout = MainContainer.getLayout("closed");
    Layout AnimationLayout = MainContainer.getLayout("animation");

    AnimGroup = AnimationLayout.getObject("anim");
    WingAnim = AnimGroup.getObject("wingsanim");
    RetractGroup1 = NormalLayout.getObject("retract");
    Button1 = RetractGroup1.getObject("ret");
    RetractGroup2 = ClosedLayout.getObject("retract2");
    Button2 = RetractGroup2.getObject("ret");

    WingAnim.setSpeed(65);
    a = 0;

    }

    this is the stuff that happens the moment winamp loads your script, and doesnt need to be triggered. 'System.onScriptLoaded() {' tells the program this is the stuff to do as i just described it, and you dont need to change it. ok, this can get a little complicated, so ill be as clear as i can. things like 'MainContainer = getContainer("main");' is where you define all the different parts of youre skin, as they appear in your xml. you need to define anything your skin needs to work (buttons, sliders, layers) as well as the continers, layouts, and groups they are in. in this example, everything is in the main container, so its the only one i have. there are three layout that come into play, so they are defined. they are in the main continer, so you get 'Layout NormalLayout = MainContainer.getLayout("normal"); '. only Layouts require 'Layout' at the begining of the line like that. 'MainContainer.' tells you the layout is in the main container, and its called 'normal' in my xml, so thats how its refenced here. get it?

    alright, if youve used Scythe, this will be a little easier. i have two usable layouts, one will the wings opened, the other with them closed, and a third layout which is just the animation. in the three layouts i have ine item i refer to: the buttons in each layout to trigger the animation and the animtion itsself. the reason there are six items defined is that these things all fall into groups, which you have to define as well. if you read this then just stare at the code for a while, you should get it.

    last i set the animation speed (just another command you can find in std.mi) and a varible int a = 0. thats pretty much that...just remember the closing bracket!
    code:

    WingAnim.onStop(){
    if(a == 1){
    MainContainer.switchToLayout("closed");
    }
    else if(a == 0){
    MainContainer.switchToLayout("normal");
    }
    }

    Button1.onLeftButtonUp(int x, int y) {
    a = 1;
    WingAnim.setStartFrame(1);
    WingAnim.setEndFrame(8);
    MainContainer.switchToLayout("animation");
    WingAnim.play();
    }
    Button2.onLeftButtonUp(int x, int y) {
    a = 0;
    WingAnim.setStartFrame(8);
    WingAnim.setEndFrame(1);
    MainContainer.switchToLayout("animation");
    WingAnim.play();
    }

    this is the real stuff right here. this is where button clicking and the like does what it does. tis is actually the easiest part once you know what going on. i will assume you have NO IDEA how to program.
    code:

    WingAnim.onStop(){
    if(a == 1){
    MainContainer.switchToLayout("closed");
    }
    else if(a == 0){
    MainContainer.switchToLayout("normal");
    }
    }

    this tells winamp that when WingAnim (which was defined earlier) stops, it should perform the action that follows. if a==1, it will switch to the closed layout. if a==0, it will switch to the normal layout. how does it know what a is? thats in the next little bit. 'if' and 'else if' are classic programming commands, and are pretty easy to figure out how to use. make sure you have double equal (==) in an if statement, or != if they should be not equal. some other programming stuff to look out for: make sure you end most lines with a ';' unless the line ends in a { or }. make sure every { has a matching }.
    code:

    Button1.onLeftButtonUp(int x, int y) {
    a = 1;
    WingAnim.setStartFrame(1);
    WingAnim.setEndFrame(8);
    MainContainer.switchToLayout("animation");
    WingAnim.play();
    }
    Button2.onLeftButtonUp(int x, int y) {
    a = 0;
    WingAnim.setStartFrame(8);
    WingAnim.setEndFrame(1);
    MainContainer.switchToLayout("animation");
    WingAnim.play();
    }

    this tells winamp that if the user left clicks the button1 i defined earlier (this is the button from normal layout) that it should first set a=1 (this is important so that the onStop() part from above knows which layout to switch to next). it then sets the starting frame of the animation to 1 and the end frame to 8. it is an 8 frame animation. it then switches to the layout that has the animation, and plays it. the only difference between that and the second one is that a will equal 0 (so the animation switching works right) and that is plays the animation backwards.


    does all of that make sense? i hope so
    there are many many other command you can use in your maki script, which can, for 99% of you, be found at C:\Program Files\Winamp3\Lib\std.mi. its only partly documented, but most of what you need is in there. i just hope mostof you will know how to use those commands now. if you need any clarification, ill be happy to...clarify
    Published: OvalAmp | Scythe | Simple Amp(code) | PAD(code) | Classix10k | LayerONE (code)
    WIP: Aeschere | Manta | Winamp 5 SingleGUI
    Need some help? How to write a MAKI script | Custom Vis Script | Add a Notifier to Your Skin

  • #2
    this helps a lot b/c my main problem so far has been maki.
    thanks for making this thread!

    Comment


    • #3
      the reason for this thread was really to help you make your own stuff, to do stuff that wasnt easily done with a premade script (like frisbee monkey's...which are excelent). one thing that is wonderful in its customizability is the drop down list. in this ill show how to creat your very own. if youve ever used Mercury or my skin, you know how neat and functional these can be.

      again ill start with one of my scripts from Scythe...and again it will help if youre familiar. i trimmed it down to isolate what we want to work with and here it is:

      code:

      //----------------------------------------------------------------------------------------------------------------
      // thinger.m
      //
      // controls super cool thinger functions
      //
      // help from rpeterclark's dropdown example
      //
      //----------------------------------------------------------------------------------------------------------------

      #include "../../../lib/std.mi"

      Global Group ToggleGroup;
      Global Button Toggle;
      Global Layout ThingerLayout;
      Global Container ThingerContainer;
      Global PopupMenu ControlPopup;

      System.onScriptLoaded() {

      ThingerContainer = getContainer("thinger");
      Layout ThingerLayout = ThingerContainer.getLayout("normal");

      ToggleGroup = ThingerLayout.getObject("togglebutton");
      Toggle = ToggleGroup.getObject("toggle");

      ControlPopup = new PopupMenu;
      ControlPopup.addCommand("Play", 1,0,0);
      ControlPopup.addCommand("Stop", 2,0,0);
      ControlPopup.addCommand("Pause", 3,0,0);
      ControlPopup.addCommand("Next", 4,0,0);
      ControlPopup.addCommand("Previous", 5,0,0);
      ControlPopup.addCommand("Open Files", 6,0,0);

      }




      Toggle.onRightButtonDown(int a, int b) {
      Int intSelection = ControlPopup.popAtMouse();
      if (intSelection > 0) {
      if (intSelection==1) {
      system.play();
      }
      else if (intSelection==2) {
      system.stop();
      }
      else if (intSelection==3) {
      system.pause();
      }
      else if (intSelection==4) {
      system.next();
      }
      else if (intSelection==5) {
      system.previous();
      }
      else if (intSelection==6) {
      system.eject();
      }
      }
      Complete;
      }

      ill assume youve read the last thing and know what the basics are. if so, this should be a breeze.

      code:

      ControlPopup = new PopupMenu;
      ControlPopup.addCommand("Play", 1,0,0);
      ControlPopup.addCommand("Stop", 2,0,0);
      ControlPopup.addCommand("Pause", 3,0,0);
      ControlPopup.addCommand("Next", 4,0,0);
      ControlPopup.addCommand("Previous", 5,0,0);
      ControlPopup.addCommand("Open Files", 6,0,0);

      this here is where we tell winamp what we want our popup to look like. 'ControlPopup' is what I named the menu, you can make it whatever you like, just make sure it matches your Global definition! to add an option to our menu we use the 'addCommand()' function, and heres what the option inside the () mean: the first is what appears in the menu...easy enough. the second is which number on the list it will be, as well and the interger value its assigned. dont worry too much about what that means, just be ready to refer back to it--generally do it in the orderly way shown here, its easiest. the last two numbers are how it should appear when active/inactive(kinda like how theres a little mark next to the skin your using in the default menu). this can be a bit tricky to get to work right, but fortunately for us it doesnt matter in this case. by setting both to '0', there wont be any marks. this is more important for toggle stuff, which i might explain in more depth later.

      code:

      Toggle.onRightButtonDown(int a, int b) {
      Int intSelection = ControlPopup.popAtMouse();
      if (intSelection > 0) {
      if (intSelection==1) {
      system.play();
      }
      else if (intSelection==2) {
      system.stop();
      }
      else if (intSelection==3) {
      system.pause();
      }
      else if (intSelection==4) {
      system.next();
      }
      else if (intSelection==5) {
      system.previous();
      }
      else if (intSelection==6) {
      system.eject();
      }
      }
      Complete;
      }

      the heart of the code right here. according to this, when someone right clicks on the Toggle button it will cause the pop up to come down. this is pretty much a copy paste job, changing the names that need to be changed in the first part, and adding/subtracting else if statements as needed. for the if/else if statements, heres what they mean: the 'intSelection==x' part refers back to the int assignments i mentioned earlier. "Play" was assigned value 1, so if they select "Play" (or, you could say, 1), then it triggers the system.play() function (look in std.mi for funtions like that). the rest is pretty self explanitory. hope that does it for you.
      Published: OvalAmp | Scythe | Simple Amp(code) | PAD(code) | Classix10k | LayerONE (code)
      WIP: Aeschere | Manta | Winamp 5 SingleGUI
      Need some help? How to write a MAKI script | Custom Vis Script | Add a Notifier to Your Skin

      Comment


      • #4
        thanks, i didnt know how to use menus
        .........?.

        Comment


        • #5
          Now I've got something else to implement into Zechtichoplayer!
          Thx!
          .:SharkWork::Deviantart::Breed:.

          Comment


          • #6
            glad this was all well recieved...any requests?
            Published: OvalAmp | Scythe | Simple Amp(code) | PAD(code) | Classix10k | LayerONE (code)
            WIP: Aeschere | Manta | Winamp 5 SingleGUI
            Need some help? How to write a MAKI script | Custom Vis Script | Add a Notifier to Your Skin

            Comment


            • #7
              GO FOR IT

              hey y dont u check out that one guys idea n make a script that says good bye when u turn it off. just a thought. by he way i love this post n u really can have my children

              Comment


              • #8
                Just wanted to say excellent work here. Nice contribution.

                Comment


                • #9
                  thank DH, stuff like that keeps goin...

                  ok, for the goodbye script. the problem is theres no maki command to close winamp. theres a work around involving setting up a dummy close button button in your xml and having the maki trigger that, but ill go more into that later. heres what i threw together...it works, it just doesnt close after the timer stops, it plays:

                  code:

                  //--------------------------------------------
                  // goodbye.m
                  //
                  // shows "goodbye" before closing
                  //
                  //-------------------------------------------
                  #include "../../../lib/std.mi"

                  Global Container MainContainer;
                  Global Layout NormalLayout;
                  Global Button CloseButton;
                  Global Text Ticker1;
                  Global Group DrawerGroup1, CloseGroup;
                  Global Timer closeTimer;

                  System.onScriptLoaded(){

                  MainContainer = getContainer("main");
                  Layout NormalLayout = MainContainer.getLayout("normal");

                  DrawerGroup1 = System.getContainer("main").getLayout("normal").getObject("tubes");
                  Ticker1 = DrawerGroup1.getObject("SongTicker");
                  CloseGroup = NormalLayout.getobject("fancy");
                  CloseButton = CloseGroup.getObject("close");

                  closeTimer = new Timer;
                  closeTimer.setDelay(5000);
                  }

                  CloseButton.onLeftClick(){
                  Ticker1.setText("Goodbye");
                  closeTimer.start();
                  }

                  closeTimer.onTimer() {
                  system.play();
                  }

                  because i dont want this to become a seond maki cheats skin, im going to explain how it works. id also like to say i hadnt used timers or setText before i wrote this...so you can write new stuff!!

                  code:

                  closeTimer = new Timer;
                  closeTimer.setDelay(5000);

                  there isnt much to explain really. you set up the timer in the onScriptLoad area. first initialize it by setting it equal to 'new Timer', then .setDelay() it for how long you want the timer to go for (its in miliseconds)

                  code:

                  CloseButton.onLeftClick(){
                  Ticker1.setText("Goodbye");
                  closeTimer.start();
                  }

                  closeTimer.onTimer() {
                  system.play();
                  }

                  the CloseButton i used here does NOT have an action defined in the xml. if you set its action to close, youll never get a chance to see the code work. i set my Ticker1 text to "Goodbye" when you click the button, then the timer starts. the 'onTimer' command tells winamp what to do when the timer its attatched to ends, in this case play (until a work around is implemented, which ill work on later i guess). you could also make it more elaborate with multible timers and/or layered tickers to get it to spell out goodbye letter by letter, but ill leave that to you. keep em comming
                  Published: OvalAmp | Scythe | Simple Amp(code) | PAD(code) | Classix10k | LayerONE (code)
                  WIP: Aeschere | Manta | Winamp 5 SingleGUI
                  Need some help? How to write a MAKI script | Custom Vis Script | Add a Notifier to Your Skin

                  Comment


                  • #10
                    To the moderators:

                    Plz, make this sticky! It's a great thread and I'm sure it's worth it !

                    Comment


                    • #11
                      damn right!
                      Published: OvalAmp | Scythe | Simple Amp(code) | PAD(code) | Classix10k | LayerONE (code)
                      WIP: Aeschere | Manta | Winamp 5 SingleGUI
                      Need some help? How to write a MAKI script | Custom Vis Script | Add a Notifier to Your Skin

                      Comment


                      • #12
                        yep,btw,congrats for featuring your Scythe skin , great work!

                        Comment


                        • #13
                          Does this forum really need another sticky? I spose if people find it useful - someone should set up a site with all this maki stuff on.

                          *stuck* (feel free to unstick if you think there's too much stickiness around )
                          For long you live and high you fly, but only if you ride the tide, and balanced on the biggest wave you race towards an early grave.
                          |Musicbrainz|Audioscrobbler|last.fm|

                          Comment


                          • #14
                            hey i for one say congrats iplaywithspoons! it helped the hell out of me but one thing i could never latch on to is drawer scripts. wanna do some good for a person? help me out.

                            Comment


                            • #15
                              drawers drawers drawers

                              heyyyy, stickied...thats pretty cool. now, as requested:

                              these are one of the most used things that requires maki, but need to be customizable enough where a premade script just doesnt work the same. theyre also exceedingly easy to write. in this here ill show you how to setp up some basic drawers, and some other cool stuff you can do too.

                              lets start with a script i just wrote last night, but does something not most drawers dont:

                              code:

                              //----------------------------------------------------------------------
                              // eq.m
                              //
                              // controls drawer sliding and anything else i add later....
                              //
                              //----------------------------------------------------------------------

                              #include "../../../lib/std.mi"

                              Global Container MainContainer;
                              Global Layout NormalLayout;
                              Global Group Equalizer;
                              Global Button Toggle, presets;
                              Global Togglebutton power, auto;
                              Global Layer buttonback;
                              Global Int B;

                              System.onScriptLoaded() {
                              MainContainer = getContainer("main");
                              Layout NormalLayout = System.getContainer("main").getLayout("normal");

                              Equalizer = NormalLayout.getObject("equalizer");
                              Toggle = Equalizer.getobject("toggle");
                              presets = Equalizer.getobject("presets");
                              power = Equalizer.getobject("power");
                              auto = Equalizer.getobject("auto");
                              buttonback = Equalizer.getobject("buttons.back");

                              B = 0;

                              }

                              Toggle.onLeftClick() {
                              if (B == 0) {
                              B = 1;
                              Equalizer.setTargetX(265);
                              Equalizer.setTargetY(13);
                              Equalizer.setTargetSpeed(0.5);
                              Equalizer.gotoTarget();
                              }
                              else if (B == 1) {
                              B = 0;
                              presets.setTargetY(111);
                              presets.setTargetSpeed(0.5);
                              presets.gotoTarget();
                              power.setTargetY(111);
                              power.setTargetSpeed(0.5);
                              power.gotoTarget();
                              auto.setTargetY(111);
                              auto.setTargetSpeed(0.5);
                              auto.gotoTarget();
                              buttonback.setTargetY(90);
                              buttonback.setTargetSpeed(0.5);
                              buttonback.gotoTarget();
                              }
                              }

                              Equalizer.onTargetReached() {
                              if (B == 1) {
                              presets.setTargetY(136);
                              presets.setTargetSpeed(0.5);
                              presets.gotoTarget();
                              power.setTargetY(136);
                              power.setTargetSpeed(0.5);
                              power.gotoTarget();
                              auto.setTargetY(136);
                              auto.setTargetSpeed(0.5);
                              auto.gotoTarget();
                              buttonback.setTargetY(115);
                              buttonback.setTargetSpeed(0.5);
                              buttonback.gotoTarget();
                              }
                              }

                              buttonback.onTargetReached() {
                              if (B == 0) {
                              Equalizer.setTargetX(112);
                              Equalizer.setTargetY(13);
                              Equalizer.setTargetSpeed(0.5);
                              Equalizer.gotoTarget();
                              }
                              }

                              ok, you should all know what the first part of that mess means by now. ive decalred the global int B so i know if the drawer is in or out. i set B = 0; at first, so i know 0 means its closed. you can have your toggle button inside or outside of the drawer group...in this case its inside

                              code:

                              Toggle.onLeftClick() {
                              if (B == 0) {
                              B = 1;
                              Equalizer.setTargetX(265);
                              Equalizer.setTargetY(13);
                              Equalizer.setTargetSpeed(0.5);
                              Equalizer.gotoTarget();
                              }

                              thats the heart of a drawer right there. its pretty self explanitory. when the user clicks the toggle button (which i declared and defined earlier), heres what happens: if B == 0 then the drawer is closed. i set B = 1 so the drawer is now considered open. Equalizer.setTargetY(13); means that the Equalizer group's new Y position will be ay 13 (in pixels) and Equalizer.setTargetX(265); means its new X position will be at 265. Equalizer.setTargetSpeed(0.5); is how fast the drawer will get there, 0 being that fastest, and slower the higher the number. we finish it off with Equalizer.gotoTarget();, telling the drawer to move to the set position at the set speed. that will always follow the most recently set numbers, so its good to keep the clustered. also , if your only moving your Y position, you dont need to setTargetX().


                              code:

                              Equalizer.onTargetReached() {
                              if (B == 1) {
                              presets.setTargetY(136);
                              presets.setTargetSpeed(0.5);
                              presets.gotoTarget();
                              power.setTargetY(136);
                              power.setTargetSpeed(0.5);
                              power.gotoTarget();
                              auto.setTargetY(136);
                              auto.setTargetSpeed(0.5);
                              auto.gotoTarget();
                              buttonback.setTargetY(115);
                              buttonback.setTargetSpeed(0.5);
                              buttonback.gotoTarget();
                              }
                              }

                              now, this is not nescessary to a drawer at all, but it shows a command that can be fun to use. the onTargetReached() command bascically says 'when the group is done moving...do this.". in this case, i have it so when the drawer is finished opening, i have a whole bunch of different things sliding down, without the user having to click or do anything...and it knows to do that only when the drawer is done opeining (and not done closing, because it only happens when B == 1)

                              that pretty much all for making a drawer script. here are some other commands you can use assoctiated with drawers:

                              setTargetW(x) // this can have your objects width change to what you set (in pixels)

                              setTargetH(x) // this can have your objects height change to what you set (in pixels)

                              setTargetA(x) // this can have your objects alpha change to what you set. alpha is transperency, so you can have a drawer fade in or out as it moves. a value between 0 - 255.
                              Published: OvalAmp | Scythe | Simple Amp(code) | PAD(code) | Classix10k | LayerONE (code)
                              WIP: Aeschere | Manta | Winamp 5 SingleGUI
                              Need some help? How to write a MAKI script | Custom Vis Script | Add a Notifier to Your Skin

                              Comment

                              Working...
                              X
                              😀
                              🥰
                              🤢
                              😎
                              😡
                              👍
                              👎