001 package com.croftsoft.core.animation.model.seri;
002
003 import java.awt.*;
004 import java.io.*;
005 import java.util.*;
006
007 import com.croftsoft.core.lang.NullArgumentException;
008 import com.croftsoft.core.math.geom.Point2DD;
009 import com.croftsoft.core.math.geom.PointXY;
010 import com.croftsoft.core.math.geom.ShapeLib;
011 import com.croftsoft.core.util.ArrayKeeper;
012 import com.croftsoft.core.util.ArrayLib;
013 import com.croftsoft.core.util.StableArrayKeeper;
014
015 import com.croftsoft.core.animation.model.Impassable;
016 import com.croftsoft.core.animation.model.Model;
017 import com.croftsoft.core.animation.model.ModelAccessor;
018 import com.croftsoft.core.animation.model.World;
019
020 /*********************************************************************
021 * A World implementation.
022 *
023 * @version
024 * 2003-06-18
025 * @since
026 * 2003-04-03
027 * @author
028 * <a href="https://www.croftsoft.com/">David Wallace Croft</a>
029 *********************************************************************/
030
031 public class SeriWorld
032 implements World, Serializable
033 //////////////////////////////////////////////////////////////////////
034 //////////////////////////////////////////////////////////////////////
035 {
036
037 private static final long serialVersionUID = 0L;
038
039 //
040
041 protected final ArrayKeeper modelArrayKeeper;
042
043 //
044
045 private final Point2DD center;
046
047 private final java.util.List modelList;
048
049 //
050
051 private boolean cleared;
052
053 //////////////////////////////////////////////////////////////////////
054 //////////////////////////////////////////////////////////////////////
055
056 public SeriWorld ( )
057 //////////////////////////////////////////////////////////////////////
058 {
059 modelArrayKeeper = new StableArrayKeeper ( new Model [ 0 ] );
060
061 center = new Point2DD ( );
062
063 modelList = new ArrayList ( );
064 }
065
066 //////////////////////////////////////////////////////////////////////
067 //////////////////////////////////////////////////////////////////////
068
069 public void clear ( )
070 //////////////////////////////////////////////////////////////////////
071 {
072 modelArrayKeeper.setArray ( new Model [ 0 ] );
073
074 cleared = true;
075 }
076
077 public void remove ( Model model )
078 //////////////////////////////////////////////////////////////////////
079 {
080 modelArrayKeeper.remove ( model );
081 }
082
083 //////////////////////////////////////////////////////////////////////
084 //////////////////////////////////////////////////////////////////////
085
086 public Impassable [ ] getImpassables ( )
087 //////////////////////////////////////////////////////////////////////
088 {
089 return ( Impassable [ ] )
090 modelArrayKeeper.getArray ( Impassable.class );
091 }
092
093 public Iterator getImpassables (
094 Shape shape,
095 Model model )
096 //////////////////////////////////////////////////////////////////////
097 {
098 modelList.clear ( );
099
100 Impassable [ ] impassables = getImpassables ( );
101
102 for ( int i = 0; i < impassables.length; i++ )
103 {
104 Impassable impassable = impassables [ i ];
105
106 if ( ( impassable != model )
107 && impassable.isActive ( )
108 && ShapeLib.intersects ( shape, impassable.getShape ( ) ) )
109 {
110 modelList.add ( impassable );
111 }
112 }
113
114 return modelList.iterator ( );
115 }
116
117 public Model [ ] getModels ( )
118 //////////////////////////////////////////////////////////////////////
119 {
120 return ( Model [ ] ) modelArrayKeeper.getArray ( );
121 }
122
123 public ModelAccessor [ ] getModelAccessors (
124 ModelAccessor [ ] modelAccessors )
125 //////////////////////////////////////////////////////////////////////
126 {
127 return getModelAccessors ( ( Shape ) null, modelAccessors );
128 }
129
130 public ModelAccessor [ ] getModelAccessors (
131 Shape shape,
132 ModelAccessor [ ] modelAccessors )
133 //////////////////////////////////////////////////////////////////////
134 {
135 Model [ ] allModels = getModels ( );
136
137 if ( shape == null )
138 {
139 return allModels;
140 }
141
142 NullArgumentException.check ( modelAccessors );
143
144 int index = 0;
145
146 for ( int i = 0; i < allModels.length; i++ )
147 {
148 Model model = allModels [ i ];
149
150 if ( ShapeLib.intersects ( shape, model.getShape ( ) ) )
151 {
152 if ( index < modelAccessors.length )
153 {
154 modelAccessors [ index ] = model;
155 }
156 else
157 {
158 modelAccessors = ( ModelAccessor [ ] )
159 ArrayLib.append ( modelAccessors, model );
160 }
161
162 index++;
163 }
164 }
165
166 if ( index < modelAccessors.length )
167 {
168 modelAccessors [ index ] = null;
169 }
170
171 return modelAccessors;
172 }
173
174 public boolean isBlocked (
175 Shape shape,
176 Model model )
177 //////////////////////////////////////////////////////////////////////
178 {
179 Impassable [ ] impassables = getImpassables ( );
180
181 for ( int i = 0; i < impassables.length; i++ )
182 {
183 Impassable impassable = impassables [ i ];
184
185 if ( ( impassable != model )
186 && impassable.isActive ( )
187 && ShapeLib.intersects ( shape, impassable.getShape ( ) ) )
188 {
189 return true;
190 }
191 }
192
193 return false;
194 }
195
196 public boolean isBlocked ( Model model )
197 //////////////////////////////////////////////////////////////////////
198 {
199 return isBlocked ( model.getShape ( ), model );
200 }
201
202 public Model getModel (
203 PointXY pointXY,
204 Class [ ] classes,
205 Model model )
206 //////////////////////////////////////////////////////////////////////
207 {
208 double x = pointXY.getX ( );
209
210 double y = pointXY.getY ( );
211
212 Model [ ] models = getModels ( );
213
214 for ( int i = 0; i < models.length; i++ )
215 {
216 Model otherModel = models [ i ];
217
218 if ( ( otherModel != model )
219 && otherModel.isActive ( )
220 && otherModel.getShape ( ).contains ( x, y ) )
221 {
222 for ( int j = 0; j < classes.length; j++ )
223 {
224 if ( classes [ j ].isInstance ( otherModel ) )
225 {
226 return otherModel;
227 }
228 }
229 }
230 }
231
232 return null;
233 }
234
235 public Model [ ] getModels ( Class c )
236 //////////////////////////////////////////////////////////////////////
237 {
238 if ( c == null )
239 {
240 return ( Model [ ] ) modelArrayKeeper.getArray ( );
241 }
242
243 return ( Model [ ] ) modelArrayKeeper.getArray ( c );
244 }
245
246 public Model [ ] getModels (
247 PointXY pointXY,
248 Model [ ] models,
249 Class c )
250 //////////////////////////////////////////////////////////////////////
251 {
252 Model [ ] allModels = getModels ( c );
253
254 if ( pointXY == null )
255 {
256 return allModels;
257 }
258
259 NullArgumentException.check ( models );
260
261 double x = pointXY.getX ( );
262
263 double y = pointXY.getY ( );
264
265 int index = 0;
266
267 for ( int i = 0; i < allModels.length; i++ )
268 {
269 Model model = allModels [ i ];
270
271 if ( model.isActive ( )
272 && model.getShape ( ).contains ( x, y ) )
273 {
274 if ( index < models.length )
275 {
276 models [ index ] = model;
277 }
278 else
279 {
280 models = ( Model [ ] ) ArrayLib.append ( models, model );
281 }
282
283 index++;
284 }
285 }
286
287 if ( index < models.length )
288 {
289 models [ index ] = null;
290 }
291
292 return models;
293 }
294
295 public Model [ ] getModels (
296 Shape shape,
297 Model [ ] models,
298 Class c )
299 //////////////////////////////////////////////////////////////////////
300 {
301 Model [ ] allModels = getModels ( c );
302
303 if ( shape == null )
304 {
305 return allModels;
306 }
307
308 NullArgumentException.check ( models );
309
310 int index = 0;
311
312 for ( int i = 0; i < allModels.length; i++ )
313 {
314 Model model = allModels [ i ];
315
316 if ( model.isActive ( )
317 && ShapeLib.intersects ( shape, model.getShape ( ) ) )
318 {
319 if ( index < models.length )
320 {
321 models [ index ] = model;
322 }
323 else
324 {
325 models = ( Model [ ] ) ArrayLib.append ( models, model );
326 }
327
328 index++;
329 }
330 }
331
332 if ( index < models.length )
333 {
334 models [ index ] = null;
335 }
336
337 return models;
338 }
339
340 public Model getModelClosest (
341 PointXY pointXY,
342 Class c,
343 Model model )
344 //////////////////////////////////////////////////////////////////////
345 {
346 int index = -1;
347
348 double closestDistance = Double.POSITIVE_INFINITY;
349
350 Model [ ] models = ( Model [ ] ) modelArrayKeeper.getArray ( );
351
352 for ( int i = 0; i < models.length; i++ )
353 {
354 Model otherModel = models [ i ];
355
356 if ( ( otherModel != model )
357 && otherModel.isActive ( )
358 && c.isInstance ( otherModel ) )
359 {
360 double distance = ShapeLib.getCenter (
361 otherModel.getShape ( ), center ).distanceXY ( pointXY );
362
363 if ( distance < closestDistance )
364 {
365 closestDistance = distance;
366
367 index = i;
368 }
369 }
370 }
371
372 if ( index > -1 )
373 {
374 return models [ index ];
375 }
376
377 return null;
378 }
379
380 //////////////////////////////////////////////////////////////////////
381 // mutator methods
382 //////////////////////////////////////////////////////////////////////
383
384 public boolean isCleared ( ) { return cleared; }
385
386 public void prepare ( )
387 //////////////////////////////////////////////////////////////////////
388 {
389 Model [ ] models = getModels ( );
390
391 for ( int i = 0; i < models.length; i++ )
392 {
393 models [ i ].prepare ( );
394 }
395
396 cleared = false;
397 }
398
399 public void update ( double timeDelta )
400 //////////////////////////////////////////////////////////////////////
401 {
402 Model [ ] models = getModels ( );
403
404 for ( int i = 0; i < models.length; i++ )
405 {
406 models [ i ].update ( timeDelta );
407 }
408 }
409
410 //////////////////////////////////////////////////////////////////////
411 //////////////////////////////////////////////////////////////////////
412 }