1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.replica.replicaisland;
18
19/**
20 * ObjectManagers are "group nodes" in the game graph.  They contain child objects, and updating
21 * an object manager invokes update on its children.  ObjectManagers themselves are derived from
22 * BaseObject, so they may be strung together into a hierarchy of objects.  ObjectManager may
23 * be specialized to implement special types of traversals (e.g. PhasedObjectManager sorts its
24 * children).
25 */
26public class ObjectManager extends BaseObject {
27    protected static final int DEFAULT_ARRAY_SIZE = 64;
28
29    private FixedSizeArray<BaseObject> mObjects;
30    private FixedSizeArray<BaseObject> mPendingAdditions;
31    private FixedSizeArray<BaseObject> mPendingRemovals;
32
33    public ObjectManager() {
34        super();
35        mObjects = new FixedSizeArray<BaseObject>(DEFAULT_ARRAY_SIZE);
36        mPendingAdditions = new FixedSizeArray<BaseObject>(DEFAULT_ARRAY_SIZE);
37        mPendingRemovals = new FixedSizeArray<BaseObject>(DEFAULT_ARRAY_SIZE);
38    }
39
40    public ObjectManager(int arraySize) {
41        super();
42        mObjects = new FixedSizeArray<BaseObject>(arraySize);
43        mPendingAdditions = new FixedSizeArray<BaseObject>(arraySize);
44        mPendingRemovals = new FixedSizeArray<BaseObject>(arraySize);
45    }
46
47    @Override
48    public void reset() {
49        commitUpdates();
50        final int count = mObjects.getCount();
51        for (int i = 0; i < count; i++) {
52            BaseObject object = mObjects.get(i);
53            object.reset();
54        }
55    }
56
57    public void commitUpdates() {
58        final int additionCount = mPendingAdditions.getCount();
59        if (additionCount > 0) {
60            final Object[] additionsArray = mPendingAdditions.getArray();
61            for (int i = 0; i < additionCount; i++) {
62                BaseObject object = (BaseObject)additionsArray[i];
63                mObjects.add(object);
64            }
65            mPendingAdditions.clear();
66        }
67
68        final int removalCount = mPendingRemovals.getCount();
69        if (removalCount > 0) {
70            final Object[] removalsArray = mPendingRemovals.getArray();
71
72            for (int i = 0; i < removalCount; i++) {
73                BaseObject object = (BaseObject)removalsArray[i];
74                mObjects.remove(object, true);
75            }
76            mPendingRemovals.clear();
77        }
78    }
79
80    @Override
81    public void update(float timeDelta, BaseObject parent) {
82        commitUpdates();
83        final int count = mObjects.getCount();
84        if (count > 0) {
85            final Object[] objectArray = mObjects.getArray();
86            for (int i = 0; i < count; i++) {
87                BaseObject object = (BaseObject)objectArray[i];
88                object.update(timeDelta, this);
89            }
90        }
91    }
92
93    public final FixedSizeArray<BaseObject> getObjects() {
94        return mObjects;
95    }
96
97    public final int getCount() {
98        return mObjects.getCount();
99    }
100
101    /** Returns the count after the next commitUpdates() is called. */
102    public final int getConcreteCount() {
103        return mObjects.getCount() + mPendingAdditions.getCount() - mPendingRemovals.getCount();
104    }
105
106    public final BaseObject get(int index) {
107        return mObjects.get(index);
108    }
109
110    public void add(BaseObject object) {
111        mPendingAdditions.add(object);
112    }
113
114    public void remove(BaseObject object) {
115        mPendingRemovals.add(object);
116    }
117
118    public void removeAll() {
119        final int count = mObjects.getCount();
120        final Object[] objectArray = mObjects.getArray();
121        for (int i = 0; i < count; i++) {
122            mPendingRemovals.add((BaseObject)objectArray[i]);
123        }
124        mPendingAdditions.clear();
125    }
126
127    /**
128     * Finds a child object by its type.  Note that this may invoke the class loader and therefore
129     * may be slow.
130     * @param classObject The class type to search for (e.g. BaseObject.class).
131     * @return
132     */
133    public <T> T findByClass(Class<T> classObject) {
134        T object = null;
135        final int count = mObjects.getCount();
136        for (int i = 0; i < count; i++) {
137            BaseObject currentObject = mObjects.get(i);
138            if (currentObject.getClass() == classObject) {
139                object = classObject.cast(currentObject);
140                break;
141            }
142        }
143        return object;
144    }
145
146    protected FixedSizeArray<BaseObject> getPendingObjects() {
147        return mPendingAdditions;
148    }
149
150}
151