//////////////////////////////////////////////
//////////////////////////////////////////////
// SuperCollider Pen Tutorial
// rhoadley.net
// v0.1
//////////////////////////////////////////////
//////////////////////////////////////////////

(
var w = Window("Simple line drawing", Rect(100, 200, 300, 300)).front;
var r= 15;
w.drawHook = { |v|	
	Pen.strokeColor = Color.black;
	Pen.moveTo(150@150);
	Pen.lineTo(250@250);
	Pen.fillStroke;
};
)

(
var w = Window("Simple line drawing", Rect(100, 200, 300, 300)).front;
var r= 15;
w.drawHook = { |v|	
	Pen.strokeColor = Color.red;
	Pen.line(150@150, 250@50);
	Pen.fillStroke;
};
)

(
var w = Window("Simple oval drawing", Rect(100, 200, 300, 300)).front;
var r= 15;
w.drawHook = { |v|	
	Pen.fillColor = Color.blue;
	Pen.strokeColor = Color.red;
	Pen.moveTo(50@50);
	Pen.curveTo(150@150, 250@10, 350@350);
	Pen.fillStroke;
};
)

(
var w = Window("Simple oval drawing", Rect(100, 200, 300, 300)).front;
var r= 15;
w.drawHook = { |v|	
	Pen.fillColor = Color.new255(255, 0, 255);
	Pen.strokeColor = Color.new255(255, 255, 0);
	Pen.moveTo(50@50);
	Pen.curveTo(150@150, 250@10, 350@350);
	Pen.fillStroke;
};
)

(
// also see Color help file
var w = Window("Tutorial 1", Rect(100, 200, 300, 300)).front;

var a1 = 450.rand;
var b1 = 450.rand;
var c1 = 450.rand;
var d1 = 450.rand;
var e1 = 450.rand;
var f1 = 450.rand;

w.drawHook = { |v|	
	Pen.fillColor = Color.new255(255.rand, 255.rand, 255.rand);
	Pen.strokeColor = Color.new255(255.rand, 255.rand, 255.rand);
	Pen.moveTo(0@0);
	Pen.curveTo(a1@b1, c1@d1, e1@f1);
	Pen.fillStroke;
};
)

// Animation
(
var w, run = true;
w = Window("SCPen Animation Tutorial", Rect(128, 64, 800, 500));
w.view.background = Color.white;
w.onClose = { run = false; };
w.front;
w.drawHook = {
	Pen.use {
		Pen.width = 2;
		20.do {
			Pen.width = rrand(0,4) + 0.5;
			Pen.beginPath;
			Pen.moveTo(Point(800.rand, 500.rand));
			Pen.lineTo(Point(800.rand, 500.rand));
			Pen.stroke;
		};
	};
};

{ while { run } { w.refresh; 1.0.rand.wait } }.fork(AppClock)

)

(
var w, run = true;
w = Window("SCPen Animation Tutorial", Rect(128, 64, 800, 500));
w.view.background = Color.white;
w.onClose = { run = false; };
w.front;
w.drawHook = {
	Pen.use {
		Pen.width = 2;
		2.do {
 			var r;
			Pen.width = rrand(0,4) + 0.5;
			Pen.beginPath;

			r = Rect(100.rand, 100.rand, 160.rand, 80.rand);
			Pen.strokeColor = Color.black.alpha_(0.8);
			Pen.strokeOval(r);
		};
	};
};

{ while { run } { w.refresh; 0.1.wait } }.fork(AppClock)

)

(
var w, run = true;
w = Window("SCPen Animation Tutorial", Rect(128, 64, 800, 500));
w.view.background = Color.white;
w.onClose = { run = false; };
w.front;
w.drawHook = {
	Pen.use {
		Pen.width = 2;
		2.do {
 			var r;
			Pen.width = rrand(0,4) + 0.5;
			Pen.beginPath;

			r = Rect(200.rand, 200.rand, 260.rand, 800.rand);
			Pen.strokeColor = Color.new255(255.rand, 255.rand, 255.rand);
			Pen.strokeOval(r);
			Pen.fillColor = Color.new255(255.rand, 255.rand, 255.rand);
			Pen.fillOval(r);
		};
	};
};

{ while { run } { w.refresh; 0.1.wait } }.fork(AppClock)

)

(
var w, run = true;
var a1 = 200.rand, b1 = 200.rand, c1 = 200.rand, d1 = 200.rand;
var myMove=1;
w = Window("SCPen Animation Tutorial Oval Moving", Rect(128, 64, 400, 500));
w.view.background = Color.white;
w.onClose = { run = false; };
w.front;
w.drawHook = {
	Pen.use {
		Pen.width = 2;
		1.do {
 			var r;
			Pen.width = rrand(0,4) + 0.5;
			Pen.beginPath;

			r = Rect(a1, b1, c1, d1);
			Pen.strokeColor = Color.new255(255.rand, 255.rand, 255.rand);
			Pen.strokeOval(r);
			Pen.fillColor = Color.new255(255.rand, 255.rand, 255.rand);
			Pen.fillOval(r);
			
			myMove = 10.rand;
			
			if ( 0.5.coin, { a1 = a1 + myMove }, { a1 = a1 - myMove } );
			if ( 0.5.coin, { b1 = b1 + myMove }, { b1 = b1 - myMove } );
			if ( 0.5.coin, { c1 = c1 + myMove }, { c1 = c1 - myMove } );
			if ( 0.5.coin, { d1 = d1 + myMove }, { d1 = d1 - myMove } );
		};
	};
};

{ while { run } { w.refresh; 0.1.wait } }.fork(AppClock)

)

// Now with audio
// Here's a synth
(
SynthDef(\simpleModSynth, { 
	arg toneLength=2.0, freq=440, modFreq=880, indexVal=1.0, amp=0.05, outBus = 0;
				
	var source;

	source = EnvGen.ar(Env.linen(toneLength/20, toneLength/2, toneLength/4), doneAction: 2) * PMOsc.ar(freq, modFreq, indexVal, 0, amp);
		
	Out.ar(outBus, source);
}).send(s);
);

// test
~mySynth = Synth("simpleModSynth", [ \toneLength, 2, \freq, (400.rand)+100, \modFreq, ( [ 400, 400*1.5, 400*2, 400*3, 400*10 ].choose * [ 1.0, 400 ].choose ),  \indexVal, 1.0 ]);

(
var w, run = true;
var myPointX1=0, myPointY1=0;
var myPointX2=0, myPointY2=0;

w = Window("SCPen Animation Tutorial with audio", Rect(128, 64, 800, 500));
w.view.background = Color.white;
w.onClose = { run = false; };
w.front;
w.drawHook = {
	Pen.use {
		myPointX1 = 800.rand;
		myPointY1 = 500.rand;
		myPointX2 = 800.rand;
		myPointY2 = 500.rand;
		Pen.width = 2;
		Pen.width = rrand(0,4) + 0.5;
		Pen.beginPath;
		Pen.moveTo(Point(myPointX1, myPointY1));
		Pen.lineTo(Point(myPointX2, myPointY2));
		Pen.stroke;
		
		~mySynth = Synth("simpleModSynth", [ \toneLength, 2, \freq, myPointX1, \modFreq, ( [ 400, 400*1.5, 400*2, 400*3, 400*10 ].choose * [ 1.0, 400 ].choose ),  \indexVal, 2.0.rand ]);
	};
};

{ while { run } { w.refresh; 1.0.rand.wait } }.fork(AppClock)

)

(
var w, run = true;
var a1 = 400.rand, b1 = 400.rand, c1 = 400.rand, d1 = 400.rand;
var myMove=1;
var myIndex=1.0;
w = Window("SCPen Animation Tutorial Oval Moving with Audio", Rect(128, 64, 400, 500));
w.view.background = Color.white;
w.onClose = { run = false; };
w.front;
w.drawHook = {
	Pen.use {
	 	var r;
	 	
		Pen.width = 2;
		Pen.beginPath;

		r = Rect(a1, b1, c1, d1);
		Pen.strokeColor = Color.new255(100, 100, 100);
		Pen.strokeOval(r);
		Pen.fillColor = Color.new255(200, 200, 200);
		Pen.fillOval(r);
		
		myMove = 20.0.rand;
		
		if ( 0.5.coin, { a1 = a1 + myMove }, { a1 = a1 - myMove } );
		if ( 0.5.coin, { b1 = b1 + myMove }, { b1 = b1 - myMove } );
		if ( 0.5.coin, { c1 = c1 + myMove }, { c1 = c1 - myMove } );
		if ( 0.5.coin, { d1 = d1 + myMove }, { d1 = d1 - myMove } );
		
		if (0.01.coin, { a1 = 400.rand; b1 = 400.rand; c1 = 400.rand; d1 = 400.rand; myIndex=10.0.rand; } );
		
		~mySynth = Synth("simpleModSynth", [ \toneLength, 0.5, \freq, a1, \modFreq, ( [ 400, 400*1.5, 400*2, 400*3, 400*10 ].choose * [ 1.0, 400 ].choose ),  \indexVal, myIndex ]);
	};
};

{ while { run } { w.refresh; 0.01.wait } }.fork(AppClock)

)

(
// By James McCartney
var w, h = 700, v = 700, seed, run = true, phase = 0;
w = Window("wedge", Rect(40, 40, h, v), false);
w.view.background = Color.rand(0,0.3);
w.onClose = { run = false }; // stop the thread on close
w.front;
// store an initial seed value for the random generator
seed = Date.seed;
w.drawHook = {
	Pen.width = 2;
	Pen.use {
		// reset this thread's seed for a moment
		thisThread.randSeed = Date.seed;
		// now a slight chance of a new seed or background color
		if (0.006.coin) { seed = Date.seed; };
		if (0.02.coin) { w.view.background = Color.rand(0,0.3); };
		// either revert to the stored seed or set the new one
		thisThread.randSeed = seed;
		// the random values below will be the same each time if the seed has not changed
		// only the phase value has advanced
		Pen.translate(h/2, v/2);
		// rotate the whole image
		// negative random values rotate one direction, positive the other
		Pen.rotate(phase * 1.0.rand2);
		// scale the rotated y axis in a sine pattern
		Pen.scale(1, 0.3 * sin(phase * 1.0.rand2 + 2pi.rand) + 0.5 );
		// create a random number of annular wedges
		rrand(6,24).do {
			Pen.color = Color.rand(0.0,1.0).alpha_(rrand(0.1,0.7));
			Pen.beginPath;
			Pen.addAnnularWedge(Point(0,0), a = rrand(60,300), a + 50.rand2, 2pi.rand 
				+ (phase * 2.0.rand2), 2pi.rand);
			if (0.5.coin) {Pen.stroke}{Pen.fill};
		};
	};
};

// fork a thread to update 20 times a second, and advance the phase each time
{ while { run } { w.refresh; 0.05.wait; phase = phase + 0.01pi;} }.fork(AppClock)

)