SC3的图形化用户界面类
Server.default=s=Server.local;
SC3的GUI类包括量程(Range)和2D滑杆,拖放工具,下拉列表,多滑杆和其它很多很多,,
同时按下shift+cmd+N (Mac机)看看可选的GUI小工具。
GD_ToolboxWindow() // 展示GUI建设的第三方类
在这份教程中,SwingOSC用户(这包括了使用PsyCollider的任何人)将需要在以下所有GUI代码前加上J,或使用另一个可替代文件(5.2b GUI与SwingOSC)
SwingOSC.default.boot;
做一个窗口
// Rect定义初始的萤幕位置和窗口大小 // screenx,screeny, windowwidth, windowheight是其引数 // 原点(0,0)为萤幕左下角 ( var w; w=SCWindow("My Window", Rect(100,500,200,200)); // 一个200*200的窗口出现在萤幕坐标点(100, 500) w.front; // 这行代码显示窗口 )
注意,萤幕的原点坐标(0,0)在萤幕左下角,相对的,窗口坐标点(100,500)也在窗口左下角。
我们为我们的窗口加入控制,定义它们使用的参数。我们在窗口内再次使用一个Rect新建一个控制器,并决定它在窗口内的位置和大小。
( var w, slid; w=SCWindow("My Window", Rect(100,500,200,200)); //一个200*200的窗口出现在萤幕坐标点(100, 500) slid=SCSlider(w,Rect(10,10,150,40)); //一个基础的滑杆对象 // 这是收回(callback)——任何时候当你移动滑杆,这个函数都将被调用 slid.action_({slid.value.postln;}); w.front; )
注意滑杆默认的范围是0.0~1.0。
对此来说,ControlSpec是一个很有帮助的UGen,它可以将默认的范围转变到任何想要的范围。
( var w, slid, cs; w=SCWindow("My Window", Rect(100,500,200,200)); //一个200*200的窗口出现在萤幕坐标点(100, 500) slid=SCSlider(w,Rect(10,10,150,40)); //引数为最小值、最大值、warp(映射函数)、递增量和起始值 cs= ControlSpec(20, 20000, 'exp', 10, 1000); slid.action_({cs.map(slid.value).postln;}); //map to the desired range w.front; )
运用2D滑杆进行声音合成的的小样
( SynthDef(\filterme, {arg freq=1000, rq=0.5; Out.ar(0, Pan2.ar( BPF.ar(Impulse.ar(LFNoise0.kr(15,500,1000),0.1, WhiteNoise.ar(2)),freq,rq) )) }).load(s) ) ( var w, slid2d, syn; w=SCWindow("My Window", Rect(100,300,200,200)); slid2d= SC2DSlider(w,Rect(5,5,175,175)); syn=Synth(\filterme); slid2d.action_({ [slid2d.x, slid2d.y].postln; // 我在这做自己的映射,而不是使用ControlSpec syn.set(\freq,100+(10000*slid2d.y),\rq,0.01+(0.09*slid2d.x)); }); w.front; w.onClose={syn.free;}; )
更进一步的探索:
要尝试拖放和其它UI工具,可以打开SC范例文件夹内的GUI examples文件夹查阅。
( // 创建一个含一些数字盒的GUI窗口 // 你可以在按下cmd键的同时鼠标左键 // 拖动一个数字到另一个数字上以替换后者的值 var w, n, f, s; w = SCWindow("number box test", Rect(128, 64, 260, 80)); w.view.decorator = f = FlowLayout(w.view.bounds); n = SCNumberBox(w, Rect(0,0,80,24)); n.value = 123; n = SCNumberBox(w, Rect(0,0,80,24)); n.value = 456; n = SCDragBoth(w, Rect(0,0,80,24)); n.object = 789; f.nextLine; s = SCSlider(w, Rect(0,0,240,24)); w.front; )
同样的,还有其它一些有趣的GUI对象的帮助文档:
赞许一下——很多更有趣的GUI对象是由Jan Trutzschler引入SuperCollider的。
[SCMultiSliderView]
[SCEnvelopeView]
还有一些媒体预览对象
[SCSoundFileView]
( w = SCWindow.new("soundfile test", Rect(200, 200, 800, 400)); a = SCSoundFileView.new(w, Rect(20,20, 700, 60)); f = SoundFile.new; f.openRead("sounds/a11wlk01.wav"); a.soundfile_(f); a.read(0, f.numFrames); a.gridOn_(false); w.front; )
[SCMovieView]
( z = SCWindow.new.front; z.view.decorator = FlowLayout(z.view.bounds); a=SCMovieView(z,Rect(0,0, 300,300)); //you need to put a path to a video file on your hard drive a.path_("/Volumes/data/video/icmc/klippav-duck_cutup.mov") ) a.stepForward
Pen类可作为一个萤幕绘制工具
( var w, h = 400, v = 400, seed = Date.seed, run = true; w = SCWindow("subdiv", Rect(400, 200, h, v)); w.view.background = Color.rand; w.onClose = { run = false }; w.front; w.drawHook = { var done, nextx, nexty, yellowness, penwidth; nextx=0; nexty=0; yellowness=rrand(0.0,1.0); penwidth=rrand(0.5,1.5); //done=0; Pen.use { 200.do({arg i; var lastx,lasty; lastx=nextx; lasty=nexty; nextx=nextx+rrand(1,20); nexty=nexty+rrand(1,40); if(nextx>=h, {nextx=nextx%h}); if(nexty>=v, {nexty=nexty%v}); penwidth=(penwidth+(0.2.rand2))%8.0; Pen.width= penwidth; yellowness= (yellowness+(0.1.rand2))%2.0; Color.yellow(yellowness).set; Pen.beginPath; Pen.line(Point(lastx,lasty),Point(nextx,nexty)); Pen.rotate(rand(i%40)); Pen.line(Point(lastx,lasty),Point(nextx,nexty)); Pen.rotate(rand(i%40)); Pen.line(Point(lastx,lasty),Point(nextx,nexty)); Pen.rotate(rand(i%40)); Pen.line(Point(lastx,lasty),Point(nextx,nexty)); Pen.stroke; //Pen.fillRect(Rect(h.rand,v.rand,rrand(1,50),rrand(1,50))) }); }; }; //{ while { run } { w.refresh; 3.wait; } }.fork(AppClock) )
你同样可以用它来进行文字处理….
( var linetext, drawletter; var w, h = 800, v = 60, seed = Date.seed, run = true; var time, name, sourcestring; var yellowness, penwidth; //name=[\s,\u,\p,\e,\r,\c,\o,\l,\l,\i,\d,\e,\r]; //sourcestring= "any lower case text"; sourcestring= "welcome to supercollider"; name=Array.fill(sourcestring.size,{arg i; sourcestring[i].asSymbol}); time=0; linetext= ( 'a':[[[0,1],[0.5,0]],[[0.5,0],[1,1]],[[0.25,0.5],[0.75,0.5]]], 'b':[[[0,1],[0,0]],[[0,1],[1,1]],[[0,0],[1,0]],[[0,0.5],[0.75,0.5]],[[0.75,0.5],[1,0.75]],[[0.75,0.5],[1,0.25]],[[1,0.75],[1,1]],[[1,0.25],[1,0]]], 'c':[[[0,1],[0,0]],[[0,0],[1,0]],[[0,1],[1,1]]], 'd':[[[0,1],[0,0]],[[0,0],[0.75,0]],[[0,1],[0.75,1]],[[0.75,1],[1,0.75]],[[0.75,0],[1,0.25]],[[1,0.25],[1,0.75]]], 'e':[[[0,0],[0,1]],[[0,0],[1,0]],[[0,1],[1,1]],[[0,0.5],[1,0.5]]], 'f':[[[0,0],[0,1]],[[0,0],[1,0]],[[0,0.5],[1,0.5]]], 'g':[[[0,1],[0,0]],[[0,0],[1,0]],[[0,1],[1,1]],[[1,1],[1,0.5]],[[0.5,0.5],[1,0.5]]], 'h':[[[0,1],[0,0]],[[0,0.5],[1,0.5]],[[1,1],[1,0]]], 'i':[[[0,0],[1,0]],[[0.5,0],[0.5,1]],[[0,1],[1,1]]], 'j':[[[0,0],[1,0]],[[0.5,0],[0.5,1]],[[0,1],[0.5,1]]], 'k':[[[0,1],[0,0]],[[0,0.5],[1,1]],[[0,0.5],[1,0]]], 'l':[[[0,1],[0,0]],[[0,1],[1,1]]], 'm':[[[0,1],[0,0]],[[0,0],[0.5,0.5]],[[0.5,0.5],[1,0]],[[1,0],[1,1]]], 'n':[[[0,1],[0,0]],[[0,0],[1,1]],[[1,1],[1,0]]], 'o':[[[0,1],[0,0]],[[0,0],[1,0]],[[0,1],[1,1]],[[1,0],[1,1]]], 'p':[[[0,0],[0,1]],[[0,0],[1,0]],[[0,0.5],[1,0.5]],[[1,0],[1,0.5]]], 'q':[[[0,0],[0,0.75]],[[0,0],[0.75,0]],[[0,0.75],[0.75,0.75]],[[0.75,0],[0.75,0.75]],[[0.5,0.5],[1,1]]], 'r':[[[0,0],[0,1]],[[0,0],[1,0]],[[0,0.5],[1,0.5]],[[1,0],[1,0.5]],[[0,0.5],[1,1]]], 's':[[[0,0],[0,0.5]],[[0,0],[1,0]],[[0,1],[1,1]],[[0,0.5],[1,0.5]],[[1,0.5],[1,1]]], 't':[[[0,0],[1,0]],[[0.5,0],[0.5,1]]], 'u':[[[0,1],[0,0]],[[0,1],[1,1]],[[1,0],[1,1]]], 'v':[[[0,0],[0.5,1]],[[0.5,1],[1,0]]], 'w':[[[0,0],[0.25,1]],[[0.25,1],[0.5,0.5]],[[0.5,0.5],[0.75,1]],[[0.75,1],[1,0]]], 'x':[[[0,0],[1,1]],[[0,1],[1,0]]], 'y':[[[0,0],[0.5,0.5]],[[0.5,0.5],[1,0]],[[0.5,0.5],[0.5,1]]], 'z':[[[0,1],[1,0]],[[0,0],[1,0]],[[0,1],[1,1]]], (" ".asSymbol):[[[0,1],[1,1]],[[0,0.8],[0,1]],[[1,0.8],[1,1]]] ); w = SCWindow("welcome", Rect(40, 500, h, v)); w.view.background = Color.blue(0.5); w.onClose = { run = false }; w.front; drawletter={arg which, startx, starty, xscale=100, yscale,prop=1.0; var data; yscale= yscale ? xscale; data= linetext[which]; prop=(round((data.size)*prop).asInteger).max(1); prop.do({arg i; var val=data[i]; Pen.beginPath; Pen.line(Point(startx+(xscale*val[0][0]),starty+(yscale*val[0][1])),Point(startx+(xscale*val[1][0]),starty+(yscale*val[1][1]))); Pen.stroke; }); }; yellowness=rrand(0.7,0.9); penwidth=rrand(2,3); w.drawHook = { Pen.use {var xoscil, xsizoscil,yoscil, todraw, usedtime; Pen.width= penwidth; Color.yellow(yellowness).set; usedtime=time.min(1.0); todraw=(round((name.size)*usedtime).asInteger).max(1); todraw.do({arg j; xoscil= sin(2*pi*time+(j*pi*0.13))*140/(1+(10*time)); yoscil= sin(2*pi*time+(j*pi*0.03))*200/(1+(200*time)); xsizoscil= time*5+5; drawletter.value(name[j],50+(25*j)+(xoscil),10+yoscil,xsizoscil,xsizoscil,usedtime); }); }; }; { while { time<2.0 } { w.refresh; time=(time+0.025); // %2.0; 0.05.wait; } }.fork(AppClock) )