I was in need of a visual representation of nodes on the server and a way to rearranged these by mouse-dragging. I could not find any extensions doing this so I cooked up some code for that purpose. It works quite well on my system (Mac M1, OSX, SC in Rosetta mode) but the drawback is that it requires the server to be on for the MouseX ugen. Is there a way to poll the position of the mouse in sclang? Also, are there any better/alternative ways of achieving a similar result, maybe even a quark that does this already?
(
s.waitForBoot{
b = Bus.control(s); // for MouseX values
{ Out.kr(b, MouseX.kr()) }.play;
~screenWidth = Window.screenBounds.width;
~mouseResponsiveness = 0.8; // user can change
~size = 100; // user can change
~spacing = 10; // user can change
~numViews = 5; // user can change
v = ~numViews.collect{|i| View().fixedSize_((~size - ~spacing)@(~size - ~spacing))
.layout_(HLayout(StaticText().string_(i).align_(\center))).background_(Color.rand)
};
w = View().layout_(VLayout(HLayout(*v), StaticText().string_("Drag squares to rearrange")).spacing_(~spacing).margins_(~spacing)).front;
~order = (0..v.size - 1);
v.collect{|view, i|
view.mouseDownAction_{
~r.reset;
~r.play;
~curIndex = i;
};
view.mouseUpAction_{
~r.stop;
v[~curIndex].moveTo(~order.indexOfEqual(~curIndex) * ~size + ~spacing, ~spacing)
};
};
~swap = {|i, type = 1|
var me = ~order.indexOfEqual(i);
var target = (~order[me + type]);
if (target.notNil)
{
var targetPos = ((~order.indexOfEqual(target) * ~size) + (type * -1 * ~size) + ~spacing);
v[target].moveTo(targetPos, ~spacing);
~order.swap(me, ~order.indexOfEqual(target)).debug(\order);
}
};
~r = Routine{
var initX = b.getSynchronous;
var flag = false;
var offset = ( ~order.indexOfEqual(~curIndex) * ~size);
s.sync;
0.1.wait;
loop{
var mouseX = b.getSynchronous;
var pos = ~screenWidth * ( (mouseX - initX) * ~mouseResponsiveness) + offset;
var relativePos = pos%~size;
var upperEdge = ~size * 0.8;
var lowerEdge = ~size * 0.2;
v[~curIndex].front;
{ v[~curIndex].moveTo(pos, ~spacing) }.defer;
case
{ (relativePos > upperEdge) && flag }
{
flag = false;
{ ~swap.(~curIndex, 1) }.defer
}
{ (relativePos < lowerEdge) && flag }
{
flag = false;
{ ~swap.(~curIndex, -1) }.defer
}
{ ( ( (relativePos < upperEdge) && (relativePos > lowerEdge)) ) && flag.not }
{ flag = true };
0.05.wait
}
}
}
)