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 * A game component that can swap other components in and out of its parent game object.  The
21 * purpose of the ChangeComponentsComponent is to allow game objects to have different "modes"
22 * defined by different combinations of GameComponents.  ChangeComponentsComponent manages the
23 * switching in and out of those modes by activating and deactivating specific game components.
24 */
25public class ChangeComponentsComponent extends GameComponent {
26    private final static int MAX_COMPONENT_SWAPS = 16;
27    private FixedSizeArray<GameComponent> mComponentsToInsert;
28    private FixedSizeArray<GameComponent> mComponentsToRemove;
29    private boolean mPingPong;
30    private boolean mActivated;
31    private boolean mCurrentlySwapped;
32    private GameObject.ActionType mSwapOnAction;
33    private GameObject.ActionType mLastAction;
34
35    public ChangeComponentsComponent() {
36        super();
37
38        mComponentsToInsert = new FixedSizeArray<GameComponent>(MAX_COMPONENT_SWAPS);
39        mComponentsToRemove = new FixedSizeArray<GameComponent>(MAX_COMPONENT_SWAPS);
40
41        reset();
42    }
43
44    @Override
45    public void reset() {
46
47        GameObjectFactory factory = sSystemRegistry.gameObjectFactory;
48        // GameComponents hanging out in the mComponentsToInsert list are not part of the object
49        // hierarchy, so we need to manually release them.
50        if (factory != null) {
51            FixedSizeArray<GameComponent> unrelasedComponents = mComponentsToInsert;
52            if (mActivated) {
53                if (!mPingPong) {
54                    // if we've activated and are not set to ping pong, the contents of
55                    // mComponentsToInsert have already been inserted into the object and
56                    // will be cleaned up with all the other of the object's components.
57                    // In that case, mComponentsToRemove contains objects that need manual
58                    // clean up.
59                    unrelasedComponents = mComponentsToRemove;
60                }
61            }
62            final int inactiveComponentCount = unrelasedComponents.getCount();
63            for (int x = 0; x < inactiveComponentCount; x++) {
64                GameComponent component = unrelasedComponents.get(x);
65                if (!component.shared) {
66                    factory.releaseComponent(component);
67                }
68            }
69        }
70        mComponentsToInsert.clear();
71        mComponentsToRemove.clear();
72        mPingPong = false;
73        mActivated = false;
74        mCurrentlySwapped = false;
75        mSwapOnAction = GameObject.ActionType.INVALID;
76        mLastAction = GameObject.ActionType.INVALID;
77    }
78
79
80
81    @Override
82	public void update(float timeDelta, BaseObject parent) {
83		if (mSwapOnAction != GameObject.ActionType.INVALID) {
84			GameObject parentObject = (GameObject)parent;
85			GameObject.ActionType currentAction = parentObject.getCurrentAction();
86			if (currentAction != mLastAction) {
87				mLastAction = currentAction;
88				if (currentAction == mSwapOnAction) {
89					activate(parentObject);
90				}
91			}
92		}
93	}
94
95	public void addSwapInComponent(GameComponent component) {
96        mComponentsToInsert.add(component);
97    }
98
99    public void addSwapOutComponent(GameComponent component) {
100        mComponentsToRemove.add(component);
101    }
102
103    public void setPingPongBehavior(boolean pingPong) {
104        mPingPong = pingPong;
105    }
106
107    public void setSwapAction(GameObject.ActionType action) {
108    	mSwapOnAction = action;
109    }
110
111    /** Inserts and removes components added to the swap-in and swap-out list, respectively.
112     * Unless mPingPong is set, this may only be called once.
113     * @param parent  The parent object to swap components on.
114     */
115    public void activate(GameObject parent) {
116        if (!mActivated || mPingPong) {
117            final int removeCount = mComponentsToRemove.getCount();
118            for (int x = 0; x < removeCount; x++) {
119                parent.remove(mComponentsToRemove.get(x));
120            }
121
122            final int addCount = mComponentsToInsert.getCount();
123            for (int x = 0; x < addCount; x++) {
124                parent.add(mComponentsToInsert.get(x));
125            }
126
127            mActivated = true;
128            mCurrentlySwapped = !mCurrentlySwapped;
129            if (mPingPong) {
130                FixedSizeArray<GameComponent> swap = mComponentsToInsert;
131                mComponentsToInsert = mComponentsToRemove;
132                mComponentsToRemove = swap;
133            }
134        }
135    }
136
137    public boolean getCurrentlySwapped() {
138        return mCurrentlySwapped;
139    }
140}
141