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         }