1 ! Copyright (C) 2008 Eduardo Cavazos.
2 ! Copyright (C) 2011 Anton Gorenko.
3 ! See http://factorcode.org/license.txt for BSD license.
5 USING: accessors arrays boids.simulation calendar classes colors
6 kernel literals locals math math.functions math.trig models
7 namespaces opengl opengl.demo-support opengl.gl sequences
8 threads ui ui.commands ui.gadgets ui.gadgets.borders
9 ui.gadgets.buttons ui.gadgets.frames ui.gadgets.grids
10 ui.gadgets.labeled ui.gadgets.labels ui.gadgets.packs
11 ui.gadgets.sliders ui.gadgets.tracks ui.gadgets.worlds ui.render
14 QUALIFIED-WITH: models.range mr
17 TUPLE: boids-gadget < gadget paused boids behaviours dt ;
19 CONSTANT: initial-population 100
20 CONSTANT: initial-dt 5
22 : initial-behaviours ( -- seq )
23 1.0 75 -0.1 <cohesion>
24 1.0 40 -0.5 <alignment>
25 1.0 25 -1.0 <separation>
28 : <boids-gadget> ( -- gadget )
31 ${ WIDTH HEIGHT } >>pref-dim
32 initial-population random-boids >>boids
33 initial-behaviours >>behaviours
36 M: boids-gadget ungraft*
39 : vec>deg ( vec -- deg )
40 first2 rect> arg rad>deg ; inline
42 : draw-boid ( boid -- )
44 vel>> vec>deg 0 0 1 glRotated
52 : draw-boids ( boids -- )
53 0.0 0.0 0.0 0.5 glColor4f
56 M: boids-gadget draw-gadget* ( boids-gadget -- )
59 : iterate-system ( boids-gadget -- )
60 dup [ boids>> ] [ behaviours>> ] [ dt>> ] tri
61 simulate >>boids drop ;
63 :: start-boids-thread ( gadget -- )
73 TUPLE: range-observer quot ;
75 M: range-observer model-changed
76 [ range-value ] dip quot>> call( value -- ) ;
78 : connect ( range-model quot -- )
79 range-observer boa swap add-connection ;
81 :: behavior-panel ( behavior -- gadget )
82 2 3 <frame> white-interior { 2 4 } >>gap { 0 0 } >>filled-cell
84 "weight" <label> { 0 0 } grid-add
85 behavior weight>> 100 * >fixnum 0 0 200 1 mr:<range>
86 dup [ 100.0 / behavior weight<< ] connect
87 horizontal <slider> { 1 0 } grid-add
89 "radius" <label> { 0 1 } grid-add
90 behavior radius>> 0 0 100 1 mr:<range>
91 dup [ behavior radius<< ] connect
92 horizontal <slider> { 1 1 } grid-add
94 "angle" <label> { 0 2 } grid-add
95 behavior angle-cos>> acos rad>deg >fixnum 0 0 180 1 mr:<range>
96 dup [ deg>rad cos behavior angle-cos<< ] connect
97 horizontal <slider> { 1 2 } grid-add
99 { 5 5 } <border> white-interior
101 behavior class-of name>> COLOR: gray <framed-labeled-gadget> ;
103 :: set-population ( n boids-gadget -- )
105 dup length n - dup 0 >
107 [ neg random-boids append ] if
108 ] change-boids drop ;
111 : find-boids-gadget ( gadget -- boids-gadget )
112 dup boids-gadget? [ children>> [ boids-gadget? ] find nip ] unless ;
115 : com-pause ( boids-gadget -- )
117 dup paused>> not [ >>paused ] keep
118 [ drop ] [ start-boids-thread ] if ;
120 : com-randomize ( boids-gadget -- )
122 [ length random-boids ] change-boids relayout-1 ;
124 :: simulation-panel ( boids-gadget -- gadget )
125 <pile> white-interior
127 2 2 <frame> { 2 4 } >>gap { 0 0 } >>filled-cell
129 "population" <label> { 0 0 } grid-add
130 initial-population 0 0 200 10 mr:<range>
131 dup [ boids-gadget set-population ] connect
132 horizontal <slider> { 1 0 } grid-add
134 "speed" <label> { 0 1 } grid-add
135 boids-gadget dt>> 0 1 10 1 mr:<range>
136 dup [ boids-gadget dt<< ] connect
137 horizontal <slider> { 1 1 } grid-add
139 { 5 5 } <border> add-gadget
141 <shelf> { 2 2 } >>gap
142 "pause" [ drop boids-gadget com-pause ]
143 <border-button> add-gadget
144 "randomize" [ drop boids-gadget com-randomize ]
145 <border-button> add-gadget
147 { 5 5 } <border> add-gadget
149 "simulation" COLOR: gray <framed-labeled-gadget> ;
151 TUPLE: boids-frame < pack ;
153 :: <boids-frame> ( -- boids-frame )
154 boids-frame new horizontal >>orientation
155 <boids-gadget> :> boids-gadget
156 boids-gadget [ start-boids-thread ] keep
159 <pile> { 5 5 } >>gap 1.0 >>fill
161 boids-gadget simulation-panel
164 boids-gadget behaviours>>
165 [ behavior-panel add-gadget ] each
167 { 5 5 } <border> add-gadget ;
169 boids-frame "touchbar" f {
174 MAIN-WINDOW: boids { { title "Boids" } }
175 <boids-frame> >>gadgets ;