In this tutorial we will add a dragging function to a point. It will change the size of two squares when dragging in the x direction. Their colour will change when dragging in the y direction. This is inspired by the Processing Mouse1D example.
Download drag_func_example.sb here!
Here is an example of what we will be making! The white arrows represent what direction the point is being dragged with the mouse:
Create a new file in Antimony and add a script node.
First add our inputs and shapes:
import fab title('Script') width = 5 height = width/2 input('x', float) input('y', float) input('_s1', float) input('_s2', float) input('_c1', float) input('_c2', float) rectangle_left = fab.shapes.rectangle(x-_s1, x, y-_s1/2, y+_s1/2) rectangle_right = fab.shapes.rectangle(x, x+_s2, y-_s2/2, y+_s2/2)
_s1 and _s2 are scales for the squares. By having an underscore (_) in front of the input name, it hides it as an input from the node.
_c1 and _c2 will be used for the colour of the squares.
The two squares are next to each other on x, and centered on y/2. This will make more sense when the bounding box is created in the next step.
Now add two points and a wireframe:
fab.ui.point(x, y, color=(0,255,0)) fab.ui.wireframe([(x-width/2, y-height/2, 0), (x+width/2, y-height/2, 0), (x+width/2, y+height/2, 0), (x-width/2, y+height/2, 0)], close=True, color=fab.color.orange) fab.ui.point(x-width/2, y-height/2, color=(128,0,128))
The first point (green) is in the middle of the bounding box.
The bounding box is a wireframe in orange.
The second point (purple) is at the lower left corner
We want the purple point to be able to move the x & y coordinates- effectively moving the position of everything.
Add a drag function to the purple point:
fab.ui.point(x-width/2, y-height/2, drag=(x,y,None), color=(128,0,128))
It’s an inline drag function- so when we move the point in the x direction, it will change the x input. Same for y. We don’t have a z point, so it’s set to None.
Dragging the green point should be able to change the size and colour of the squares. This is a bit more involved than using an inline function.
Add a call to a drag function for the green point:
fab.ui.point(x, y, drag=drag_middle, relative=True, color=(0,255,0))
drag=drag_middle is passing what function we want to handle the action
relative=True means that the coordinates in the function will be relative to that point.
Add the drag_middle function above the UI lines:
def drag_middle(this,x,y,z): if x > 0: this._s1 -= x this._s2 += x if y > 0: this._c2 += y elif y < 0: this._c2 -= math.fabs(y) elif x < 0: this._s1 += math.fabs(x) this._s2 -= math.fabs(x) if y > 0: this._c1 += y elif y < 0: this._c1 -= math.fabs(y)
The drag function parameters are itself the node, and the coordinates of the mouse.
Input variables are able to be set by using this._s1 (for whatever input).
What is happening here is it's asking if the drag is to the left or the right of the point. Depending on whichever, it adds the x value to _s1 or _s2 (taking the absolute value if x is negative). Similar for y and _c1 and _c2.
Time to output the squares. Add this above drag_middle:
val1 = int(_c1) val2 = int(_c2) output('left', fab.shapes.set_color(rectangle_left, val1, 0, 200)) output('right', fab.shapes.set_color(rectangle_right, val2, 0, 200))
Right now when the mouse is dragging the green point, the squares can extend beyond the bounding box.
Add this to the bottom of drag_middle:
if this._s1 < width/8: this._s1 = width/8 elif this._s1 > width/2: this._s1 = width/2 if this._s2 < width/8: this._s2 = width/8 elif this._s2 > width/2: this._s2 = width/2
It is setting the maximum and minimum values for the scale.
We can do the same thing for the colours too:
if this._c1 > height/2: this._c1 = height/2 elif this._c1 < -height/2: this._c1 = -height/2 if this._c2 > height/2: this._c2 = height/2 elif this._c2 < -height/2: this._c2 = -height/2
Next up the values of _c1 and _c2 have to be mapped from 0-255 instead of -height/2 to height/2.
Replace the val1 and val2 with this:
def map_nums(val, from_nums, to_nums): return to_nums[0] + (to_nums[1] - to_nums[0]) * ((val - from_nums[0]) / (from_nums[1] - from_nums[0])) val1 = int(map_nums(_c1, [-height/2, height/2], [0, 255])) val2 = int(map_nums(_c2, [-height/2, height/2], [0, 255]))
Now when you move the green point in the x direction, the squares change size.
If you’re on the left or right side of the green point and move in the y direction, the square will change its colour.
The colour change is just the red value being more or less, which lets the blue ‘mix in’.
By having two of the scale (_s1 and _s2) and the colour (_c1 and _c2), you can make fun adjustments for each shape. For example, try multiplying _s2 by 2 in the drag_middle function and see what happens.
This is just the start- lots of cool things you can do with dragging functions and points!