ksp
premium article

Last modifiedby & filed under Kontakt Scripting (KSP) - Basics, UIs, Tutorials, Scripts and Tools, Kontakt Scripting (KSP) :: Custom Scripts & Functions (Plugins), Kontakt Scripting (KSP) :: UI (Design) & Engine.

this is an update to the v1.0 drag & drop script. You can now set horizontal draggables or vertical draggables like lists (see animation below). For real use cases also see Rearrange FX Slots via Draggables

KSP vertical drag & drop


drag n drop Script v2.0:
Vertical & Horizontal Draggables

  • NKI file: open script tab
  • ksp script files (vanilla ksp)
  • ksp functions (sublime text)
DOWNLOAD


License:

MIT International License.
https://blog.yummybeats.com/license-text-mit/
You may use this script, modify it, build upon it, as you like (also commercially), as long as you keep all credits within the code visible to others. You may put them into an extra open script tab or inside an about section of your instrument. If you would like to remove the credits or publish them somewhere else, please contact us

YOU MAY NOT commercialize, share, distribute, whatsoever the included image files and other media (©2025 all rights reserved).


Related POSTs

Content

preliminary definitions

A few definitions in advance.
In the following there are 2 movement terms used: same and opposite direction

Terms used:

  • same direction refers to all x-movements for the horizontal drag & drop and to all y-movements for vertical drag & drop.
  • opposite direction refers to all y-movements for the horizontal drag & drop and to all x-movements for vertical drag & drop.

Color coding:

  • The pink marker refers to any horizontal movements, the x-axis or or x-positions
  • The purple marker refers to any vertical movements, the y-axis or y-positions

Version History

Vanilla KSP

v2.0 drag & drop code has been refined. Vertical and horizontal cursor movement is possible now

Note: Vanilla is not updated anymore

Sublime KSP

v2.0 drag & drop code has been refined. Vertical and horizontal cursor movement is possible now

v2.1 yb_dd_onclick function added

v2.2 all vars are persistent now. So the latest cursor positions are saved and recalled

DOCS – Global vars & usage

%dd_cursor_index (both vanilla & sublime)

  • holds all positions (key) and current cursor index (val) at the position
  • each key gets updated with the new cursor index after each cursor movement on mouse release

so the array keys represent the fixed position ([0]: 1st pos, [1]: 2nd pos, and so on)
and the value is the current cursor index on that position.

Use this array to to rearrange multiple items at once like anything from FX chains to data lists or samples, you name it.

Also read rearrange FX Slots, the probably most common use case


$dd_this_cursor (both vanilla & sublime)

holds the current selected cursor index

use this to rearrange a single item, or to get/display the current selected cursor index

Also read rearrange FX Slots, the probably most common use case


$dd_pos (both vanilla & sublime

holds the current selected cursor’s position

use this to rearrange a single item, or to get/display the current position

Also read rearrange FX Slots, the probably most common use case


[sublime only]

function yb_dd_rearrange(index,pos,index_all)

This function is always called on every mouse release after dragging  an element to a new position.

use this function to rearrange anything by simply adding your code into this function or by calling other functions within this function. Use the function’s local arguments (which are nice & short) to pass all necessary parameters:

index equivalent to $dd_this_cursor, is passing the current selected cursor index

pos equivalent to $dd_pos, is passing the current selected cursor’s position

index_all equivalent to %dd_cursor_index, is passing the complete array with all positions and indices


function yb_dd_onclick(index,pos,index_all)

This function is called when clicking on a cursor. You can use it for example to open a specific fx dialog.

index is holding the current selected cursor index

pos is holding the current position of the clicked cursor

index_all is holding the complete array of all cursors whereas the key represents the cursor position and the value the cursor’s index currently residing on that position.

installing the script (vanilla ksp)

  1. copy the whole code from inside the on init into your on init. It is best to place the code somewhere below yours.
    But don’t copy the “on init” “end on” again
  2. copy the whole code from below the on init somewhere below your on init.
  3. Put the copyright notice in a visible location (e.g. into an extra open script tab or into an about section of your instrument).
on init
  {### YOUR CODE ###}

  {YUMMYBEAT'S KSP DRAG & DROP SCRIPT}
end on

{### YOUR CODE ### }

{YUMMYBEAT'S KSP DRAG & DROP SCRIPT}
on ui_control (?dd_area)
  {.....}
end on

setup: defining the Drag & Drop Area

{SET DRAG & DROP AREA}
declare const $DD_NUM_CURSOR := 8 {set the amount of total cursors; max = 16}
declare const $DD_AREA_WIDTH := 400 {set the drop down area width}
declare const $DD_AREA_HEIGHT := 148 {set the drop down area height (this should equal the cursor image height)}
declare const $DD_AREA_JUSTIFY := 1 {justify the drag & drop area: 1 = center; 0 = left}
declare const $DD_AREA_POS_X := 0 {left indent; set to 0 when align = center}
declare const $DD_AREA_POS_Y := 100 {position the drag & drop area vertically}
declare const $DD_DIRECTION := 1 {0:= horizontal; 1 = vertical} 
$DD_MOUSE_X := 0 {set mouse behavior X: default = 0; min = 1; max = 1000}
$DD_MOUSE_Y := 0 {set mouse behavior Y: default = 0; min = 1; max = 1000}

 

$DD_DIRECTION [NEW]

switch between 0 = horizontal list vs 1 = vertical list


$DD_MOUSE_X; $DD_MOUSE_Y [NEW]

sets custom drag movement speed.
leave 0 for default / automatic setting
Max speed is 1000; Lowest speed is 1 (almost no movement)

$DD_MOUSE_X: horizontally

$DD_MOUSE_Y: vertically

Note:

  • setting a custom value for both directions will create a completely free omnidirectional cursor movement while still having the sorting function feature, just try it yourself.
  • If only same direction values are set, the movement speed can only be slowed down (since the default setting, is already max speed), resulting in a unidirectional movement (default behavior)
  • If only opposite direction values are set, the movement speed can only be increased (since the default setting is already lowest speed), resulting in the above mentioned bidirectional cursor movements (since the same direction’s default setting is max already)

Cases:

$DD_DIRECTION = 0: $DD_MOUSE_X = same movement
$DD_DIRECTION = 0: $DD_MOUSE_Y = opposite movement speed

$DD_DIRECTION = 1: $DD_MOUSE_X = opposite movement
$DD_DIRECTION = 1: $DD_MOUSE_Y = same movement

Examples:

1. Horizontal Drag & Drop: One Direction, Cursor movement default but slowed down

$DD_DIRECTION = 0, $DD_MOUSE_X = 100
$DD_DIRECTION = 0: $DD_MOUSE_Y = 0

2.Horizontal Drag & Drop: Omnidirectional, Cursor movement max

$DD_DIRECTION = 0, $DD_MOUSE_X = 1000
$DD_DIRECTION = 0: $DD_MOUSE_Y = 1000

3. Vertical Drag & Drop: One Direction, Cursor movement default but slowed down

$DD_DIRECTION = 1: $DD_MOUSE_X = 1
$DD_DIRECTION = 1: $DD_MOUSE_Y = 100

4. Vertical Drag & Drop: Omnidirectional, same direction max <=> opposite direction slow

$DD_DIRECTION = 1: $DD_MOUSE_X = 100
$DD_DIRECTION = 1: $DD_MOUSE_Y = 0


$DD_NUM_CURSOR

defines the number of cursors (max 16)


$DD_AREA_WIDTH

sets the total width of the drag & drop area in pixels


$DD_AREA_HEIGHT

defines the total height of the drag & drop area in pixels


$DD_AREA_JUSTIFY

defines the horizontal alignment of the the whole drag & drop area within your UI.
0 = Left
1 = centered


$DD_AREA_POS_X

positions the drag&drop area accross the x-axis in pixels depending on the $DD_AREA_ALIGN settings. Negative values are allowed but only have effect at centered alignment.
If $DD_AREA_ALIGN the origin is the very left.
if $DD_AREA_ALIGN = 1 the origin is the center of your UI


$DD_AREA_POS_Y

positions the drag&drop area across the y-axis in pixels. Negative values have no effect.

installing the script (sublime text)

  1.  put this in the top of the on init (before calling any functions):
    declare !cursor_img[] := ("cursor_list_0","cursor_list_1","cursor_list_2","cursor_list_3","cursor_list_4","cursor_list_5","cursor_list_6","cursor_list_7")
    declare const DD_CURSOR_COUNT := cursor_img.SIZE
  2. in the KSP folder open “ksp_draggables_v2-1_xy (sublime).ksp” and copy all the required functions somewhere into your script. Preferably under the “on init”:
    REQUIRED FUNCTIONS: yb_init_ddarea, yb_dragndrop_colision, yb_justify_content, yb_dd_rearrange,yb_dd_onclick
    OPTIONAL FUNCTIONS: yb_set_ui
  3. Call the yb_init_ddarea function without the “call” expression anywhere inside the on init and pass all arguments. Read the little SETUP box below
  4. Add an on ui_control for ?dd_area and call the yb_dd_oncontrol like so:
    on ui_control (?dd_area)
      yb_dd_oncontrol
    end on
  5. please copy the credits & copyright notice (from inside the script) somewhere clearly visible e.g. into another open script tab or into an about section of your instrument.
    If you would like to completely remove the copyright notice, shorten it or place it somewhere else, please get in touch @ https://yummybeats.com/contact

SETUP: defining the Drag & Drop Area

declare !cursor_img[] := ("cursor_list_0","cursor_list_1","cursor_list_2",...)
//
  • add custom cursor images. Simply replace all values with your filenames without file extension (.png)
  • The images should be formatted like a button with 6 states, learn more (don’t forget to add the txt file)
  • To use more than 8 cursors simply extend the array. Up to 16 cursors allowed. A max cursor count would looks like this:
    declare !cursor_img[] := (“cursor_0”, “cursor_1”, “cursor_2”, “cursor_3”, “cursor_4”, “cursor_5”, “cursor_6”, “cursor_7”, “cursor_8”, “cursor_9”, “cursor_10”, “cursor_11”, “cursor_12”, “cursor_13”, “cursor_14”, “cursor_15”)

 

Passing the Arguments & defining the DD area

yb_init_ddarea(ui_width,ui_height,dd_width,dd_height,dd_justify,dd_posx,dd_posy,dd_direction,dd_mouse_x,dd_mouse_y,dd_array_cursorimg)
//
  • ui_width pass the total width of your UI in pixels e.g. 800
  • ui_height pass the height of your UI in pixels e.g. 400
  • dd_width pass the width of the drag n drop area
  • dd_height pass the height of the drag n drop area
  • dd_justify justify the dd_area along the x-axis … 0=left/start, 1=center, 2= right/end
  • dd_align align the dd_area along the y-axis … 0=top; 1=center;  2=bottom
  • dd_posx move the dd_area across the x-axis depending on the justification (negatives values = left; positive values = right)
  • dd_posy move the dd_area across the y-axis depending on the alignment (negatives values = up; positive values = down)
  • dd_direction 0=horizontal cursor movement; 1=vertical cursor movement
  • dd_mouse_x drag speed across the x-axis 0=default; 1000=max (note: both values above 0 means free cursor movement in 2D space) (read vanilla for detailed explanation)
  • dd_mouse_y drag speed across the y-axis 0=default; 1000=max (note: both values above 0 means free cursor movement in 2D space) (read vanilla for detailed explanation)
  • dd_array_cursorimg used to pass the cursor image array, so always keep it set to “cursor_img” unless you are using a custom array for the images

example

on init
  //declare const $UI_WIDTH := 800 //NOT REQUIRED BUT RECOMMENDED TO SIMPLIFY REPEATING UI SETTINGS
  //declare const $UI_HEIGHT := 400 //NOT REQUIRED BUT RECOMMENDED TO SIMPLIFY REPEATING UI SETTINGS

  // PUT THIS BEFORE CALLING yb_init_ddarea
    declare !cursor_img[] := ("cursor_list_0","cursor_list_1","cursor_list_2","cursor_list_3","cursor_list_4","cursor_list_5","cursor_list_6","cursor_list_7")
    declare const DD_CURSOR_COUNT := cursor_img.SIZE

  // CALL THE FUNCTION(S)
    yb_init_ddarea(800,400,228,224,1,0,100,1,0,0,cursor_img)
    yb_set_ui (800,400,"wp2","yb_ico")
    yb_decalre_display(800,400,160,28,-6,"",1,2)

  message("")
end on

on ui_control (?dd_area)
  yb_dd_oncontrol
end on

function yb_init_ddarea(ui_width,ui_height,dd_width,dd_height,dd_justify,dd_posx,dd_posy,dd_direction,dd_mouse_x,dd_mouse_y,dd_array_cursorimg)
end function

function yb_dd_oncontrol
end function

function yb_dd_rearrange(index,pos,index_all)
end function

function yb_justify_content(id,ui_width,type,width,pos)
end function

function yb_align_item(id,ui_height,type,height,pos)
end function

function yb_set_ui(width,height,wallpaper,icon)
end function

function yb_decalre_display(ui_width,ui_height,width,height,pos,picture,justify,align)
end function

DOCS v2.0: All changes explained (vanilla ksp)

The following explains all new features that have been added to v1.0
To delve deeper for a better understanding please also read the main v1.0 docs

premium content

How useful was this article?

something you didn't like? Please tell us before you rate!

Average rating / 5. Vote count:

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

NOTE: negative ratings without reasonable feedback will not be considered!

Tell us how we can improve this post?

14 Responses to “Kontakt Scripting (KSP) :: SCRIPTS :: Vertical & Horizontal Drag n Drop v2”

  1. HarryG

    Hi again, I want to show a panel containing sliders related on the selected fx, when the user clicks on one of the cursor. I declared an Array containing all my panels, and then put this line of code in the yb_dd_onclick function : set_control_par(%fxPanel_uID[index], $CONTROL_PAR_HIDE, $HIDE_PART_NOTHING). I can't make it work, how am I supposed to do in order to show the panel related to the cursor when the user clicks on it ? Thanks

    • YummyBeats

      Hey, are your FX static or can the user swap the fx? Because the latter is unfortunately way too complex for the comments

      But if your FX are always linked to a specific cursor, make sure that your %fxPanel_uID array keys represent the cursor indices (not the cursor positions). So let's assume that the compressor fx is always linked to cursor index 3, %fxPanel_uID[3] would always be your compressor panel.

      Then first store the compressor panel ui_id to key 3 like so: %fxPanel_uID[3] := get_ui_id($panel_comp)

      Now just show the panel like you did. Within onclick or the rearrange function set_control_par(%fxPanel_uID[index] should already work. Otherwise use set_control_par(%fxPanel_uID[$dd_cursor_idx], $CONTROL_PAR_HIDE, $HIDE_PART_NOTHING)

      If it is not working you may have other issues e.g. not set the z_layers correctly so that the panel is covered by another panel?!

      • HarryG

        Thanks everything works, now I'm trying to make a "radio button" function that hides every panels except the one of the cursor that is selected. Because now, let's say I click on cursor 2, the cursor2panel shows up, but if I click on cursor 3, the cursor3panel shows up too but the cursor 2 panel is still visible, so they are overriding. I only want a single panel to be shown at a time. I thought of a flag function with 8 cases for every selected cursor but is there a more efficient way to achieve that ? Thank you

        • YummyBeats

          Great!

          I see, the best way to achieve this would be to add a function which hides all panels first, then just show the one panel of the related cursor with another function.
          To hide all panels first just iterate through the whole %fxPanel_uID like so:

          function hideAll 
              declare i
              for i := 0 to num_elements(%fxPanel_uID)-1
                  %fxPanel_uID[i] -> hide := $HIDE_WHOLE_CONTROL
              end for
          end function
          

          Then you can call the following function and pass the index of the panel you want to show again.
          E.g. in a button's on ui_control callback or inside the onclick function or anywhere you want

          function openPanel(idx)
              hideAll
              %fxPanel_uID[idx] -> hide := $HIDE_PART_NOTHING
          end function
          

          • HarryG

            Works perfectly thank you ! I just had to delete the (idx) of the openPanel function and replace it with "$dd_this_cursor" for it to work with the onclick function, otherwise I would conflicts. Now, i'm trying to add a Bypass button for each cursor that would be on the cursor's image, and would follow the cursor when I drag it to another position. I assume i would have to incorporate a switch array into the yb_init_ddarea right ?

          • YummyBeats

            Hmm, actually it should also work without conflicts if you pass index within the onclick function like so:
            function yb_dd_onclick(index,pos,index_all)
                openPanel(index)
            end function
            

            But yeah, openPanel($dd_this_cursor) is also perfectly fine. If it works it works :)

            Regarding the moving bypass button, well to be honest I don't think this is possible. At least it sounds very complicated since it requires cursor movement tracking etc. I can't help you on this one, sorry. I would drop this idea anyway and just add the bypass button to the fx panel. And then swap the cursor's pictures to indicate a bypassed status. It just sounds far too time-consuming for the small added value you get with this concept, if it works at all (you know 2 separate movements not really synced to each other..very sketchy).

  2. HarryG

    Hi, I'm having a hard time installing the script with sublime. When I copy the "declare !cursor_img" and the "declare const DD_CURSOR_COUNT" at the very top of the on init, and compile the code, sublime tells me this : Syntax error (line 8) declare !cursor_img[] := ("cursor_list_0","cursor_list_1","cursor_list_2","cursor_list_3","cursor_list_4","cursor_list_5","cursor_list_6","cursor_list_7"). What am I doing wrong ? I've completed the installation process for sublime and the sublime error remains. Sublime is fully updated. Thanks

    • YummyBeats

      Hi,
      That's weird. Have you tried to compile the included ksp script as is (just for testing if it works). Because I can confirm that this file works without any issues on my side.
      If it doesn't work on your side you probably still need to update your ksp plugin. Some older plugin versions may not be able to handle the "one-line-array" syntax
      If it does work on your side you probably really have some syntax issues somewhere in your code, so double check every line. Or you didn't add all the dependent functions, maybe?!

      If this all doesn't help try to use vanilla KSP for declaring the !array and use the $ with the constant.

      • HarryG

        Hi again, I made it work ! Thank you, now I have a problem making the cursors persistent when I reload kontakt... In the rearrange fx dlc you make persistent (?last_cursor_val), (%cursor_index) and (?cursor_val). I tried that but it doesn't work, maybe it has changed with the V2 DD ? But how to make the new dd cursors persistent ? Thank you.

        • YummyBeats

          Hey, that's great to hear!
          make_persistent only works when saving your whole nki patch or when saving/loading a snapshot. Since your users most likely won't overwrite the nki you should encourage them to use snapshots.
          That being said in the yb_init_ddarea function simply add pers to all variable declarations including the dd_area. I will also update the script

          Like so:

          declare global pers %id[]			  
          declare global pers ?last_cursor_val[]
          declare global pers %dd_cursor_index[]
          ...
          

          • HarryG

            I wanted the curors to recall the way they were left by the user after closing and reopening a project in a daw. The nki or snapshot isn't saved by the user but the project where kontakt is opened in would ! In this case the make persistent would work right ?

          • YummyBeats

            Yes true this case also should work with persistent vars. I have just updated the script can you try version 2.2?
            I have not tested it in a DAW though but it should work.

Leave a Reply

use <pre> </pre> to wrap code blocks

use <code> </code> to wrap small code snippets

use basic html to style your comment

Your email address will not be published. Required fields are marked *