Rotating a View

Trying to wrap my head around UserViews and Pen, which i’m not very good at obviously.
Is it possible to rotate a whole View around its own center in a simple way? For example if you have a parent view for a bunch of UserViews and you just want to tilt everything 30 degrees or something. Wanting to do that seems like such an obvious thing, so i’m probably missing the point (pun intended).

Simple example of how i would want it to work:

(
Window.closeAll;
w = Window("rotate", Rect(400, 400, 400, 400)).alwaysOnTop_(true);
v = View(w, Rect(100, 100, 200, 200));
v.background = Color.green;

w.front;
)

// this is how i would like to do it:
v.bounds = v.bounds.rotate(0.25pi);
// or even better:
v.rotate(0.25pi);

Hello,
.rotate is not a method of the class View.
I think you should use .rotate as follows:

(
Window.closeAll;
w = Window("rotate", Rect(400, 400, 400, 400)).alwaysOnTop_(true);
w.front;
w.drawFunc = {
	Pen.translate(200, 200); // 0@0 is now 200@200
	2.do { |i|
		Pen.fillColor_(Color.green(0.5, 0.1));
		Pen.moveTo(-100@ -100);
		Pen.lineTo(-100@100);
		Pen.lineTo(100@100);
		Pen.lineTo(100@ -100);
		Pen.fill;
		Pen.rotate(0.2pi);
	}
};
)

or as follows:

(
Window.closeAll;
w = Window("rotate", Rect(400, 400, 400, 400)).alwaysOnTop_(true);
w.front;
w.drawFunc = {
	Pen.translate(200, 200); // 0@0 is now 200@200
	2.do { |i|
		Pen.fillColor_(Color.green(0.5, 0.1))
		.moveTo(-100@ -100)
		.lineTo(-100@100)
		.lineTo(100@100)
		.lineTo(100@ -100)
		.fill
		.rotate(0.2pi)
	}
};
)

Thanks. But yes, i know that. And because of that it seems to be quite complex if you have many UserViews as children in a parent view and want to rotate the whole constellation. My question was more in the spirit of “shouldn’t such a method exist?” I guess. But maybe there are good reasons it doesn’t.

1 Like

Sorry for misunderstanding your question.

I remember that I also had shortly thought about why canvas, UserView or window could not be rotated from its centre.

I do not know why there is no method .rotate for UserView. So, I think that we should achieve what we need using the provided methods and classes.

I know the following code block is not what you want, but I think it is a bit similar to your simple code example’s construction. The variable view in the code below could be the variable v in your simple code example. I used it to draw graphics in windows[0], and what I drew in windows[0] is rotating in windows[1] and windows[2] simply using a simple code construction.

What do you think about this construction? By using functions like this example, we can simplify the code structure.

If this is again so far from your question, I will apologise again for my interruption. Could you, however, describe your idea more then?
Your question may differ depending on what is drawn in each UserView and how it is positioned in SuperCollider.
Then, other users may help you, and I may also learn many sophisticated ways.

(
var windows, winWidth, winHeight, centreX, centreY, win, draw, view;

Window.closeAll;

# winWidth, winHeight = [500, 500]; 

windows = 3.collect { |i| 
	var thisWin;
	thisWin = Window("window" + i, Rect(i * 550 + 50, 50, winWidth, winHeight));
	thisWin.alwaysOnTop_(true).front;
	thisWin
};

draw = { |num, radius, x, y, transX=0, transY=0|
	Pen
	.translate(winWidth / 2, winHeight / 2)
	.translate(transX, transY);
	num.do { |i|
		Pen
		.fillColor_(Color.green(0.5, 0.08))
		.moveTo( (-1 * x) @ (-1 * y))
		.lineTo( (-1 * x) @       y )
		.lineTo(       x @       y )
		.lineTo(       x @ (-1 * y))
		.fill
		.rotate(radius)
	};
	Pen
	.rotate(-1 * num * radius)
	.translate(  -1 * transX, -1 * transY   )
	.translate(winWidth / -2, winHeight / -2);
};

view = {
	draw.(4,  10 / 360 * 2pi, 100, 100);
	draw.(3, -10 / 360 * 2pi,  50,  50, -170, -170);
	draw.(2,  45 / 360 * 2pi,  60,  60);
	draw.(5,  -5 / 360 * 2pi,  30,  30,  170, -170)
};

windows[0].drawFunc = { view.() };

{
	inf.do { |i|
		windows[1].refresh;
		windows[1].drawFunc = { 
			Pen.rotate(i % 360 / 360 * 2pi, winWidth / 2, winHeight / 2);
			view.()
		};
		windows[2].refresh;
		windows[2].drawFunc = { 
			Pen.rotate(i % 360 / 360 * 2pi, winWidth / 2, winHeight / 2);
			view.();
			Pen
			.translate(-50, -50)
			.rotate(-1 * i % 360 / 360 * 2pi, winWidth / 2 - 50, winHeight / 2 -50)
			.scale(0.5, 0.5);
			view.()
		};
		(1 / 60).wait;
	};
	2.do { |i| windows[i + 1].refresh }
}.fork(clock: AppClock)
)
1 Like

Thanks for the example! This seems to be a really good approach. I will re-write my clumsy code like this immediately.

1 Like