1/*
2 * Copyright (C) 2011 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.android.scenegraph;
18
19import java.lang.Math;
20import java.util.ArrayList;
21
22import com.android.scenegraph.SceneManager;
23
24import android.renderscript.*;
25import android.renderscript.Float3;
26import android.renderscript.Matrix4f;
27import android.util.Log;
28
29/**
30 * @hide
31 */
32public class CompoundTransform extends Transform {
33
34    public static abstract class Component {
35        String mName;
36        CompoundTransform mParent;
37        int mParentIndex;
38        protected ScriptField_TransformComponent_s.Item mData;
39
40        Component(int type, String name) {
41            mData = new ScriptField_TransformComponent_s.Item();
42            mData.type = type;
43            mName = name;
44        }
45
46        void setNameAlloc() {
47            RenderScriptGL rs = SceneManager.getRS();
48            if (mData.name != null)  {
49                return;
50            }
51            mData.name = SceneManager.getCachedAlloc(getName());
52            if (mData.name == null) {
53                mData.name = SceneManager.getStringAsAllocation(rs, getName());
54                SceneManager.cacheAlloc(getName(), mData.name);
55            }
56        }
57
58        ScriptField_TransformComponent_s.Item getRSData() {
59            setNameAlloc();
60            return mData;
61        }
62
63        protected void update() {
64            if (mParent != null) {
65                mParent.updateRSComponent(this);
66            }
67        }
68
69        public String getName() {
70            return mName;
71        }
72    }
73
74    public static class TranslateComponent extends Component {
75        public TranslateComponent(String name, Float3 translate) {
76            super(ScriptC_export.const_Transform_TRANSLATE, name);
77            setValue(translate);
78        }
79        public Float3 getValue() {
80            return new Float3(mData.value.x, mData.value.y, mData.value.z);
81        }
82        public void setValue(Float3 val) {
83            mData.value.x = val.x;
84            mData.value.y = val.y;
85            mData.value.z = val.z;
86            update();
87        }
88    }
89
90    public static class RotateComponent extends Component {
91        public RotateComponent(String name, Float3 axis, float angle) {
92            super(ScriptC_export.const_Transform_ROTATE, name);
93            setAxis(axis);
94            setAngle(angle);
95        }
96        public Float3 getAxis() {
97            return new Float3(mData.value.x, mData.value.y, mData.value.z);
98        }
99        public float getAngle() {
100            return mData.value.w;
101        }
102        public void setAxis(Float3 val) {
103            mData.value.x = val.x;
104            mData.value.y = val.y;
105            mData.value.z = val.z;
106            update();
107        }
108        public void setAngle(float val) {
109            mData.value.w = val;
110            update();
111        }
112    }
113
114    public static class ScaleComponent extends Component {
115        public ScaleComponent(String name, Float3 scale) {
116            super(ScriptC_export.const_Transform_SCALE, name);
117            setValue(scale);
118        }
119        public Float3 getValue() {
120            return new Float3(mData.value.x, mData.value.y, mData.value.z);
121        }
122        public void setValue(Float3 val) {
123            mData.value.x = val.x;
124            mData.value.y = val.y;
125            mData.value.z = val.z;
126            update();
127        }
128    }
129
130    ScriptField_TransformComponent_s mComponentField;
131    public ArrayList<Component> mTransformComponents;
132
133    public CompoundTransform() {
134        mTransformComponents = new ArrayList<Component>();
135    }
136
137    public TranslateComponent addTranslate(String name, Float3 translate) {
138        TranslateComponent c = new TranslateComponent(name, translate);
139        addComponent(c);
140        return c;
141    }
142
143    public RotateComponent addRotate(String name, Float3 axis, float angle) {
144        RotateComponent c = new RotateComponent(name, axis, angle);
145        addComponent(c);
146        return c;
147    }
148
149    public ScaleComponent addScale(String name, Float3 scale) {
150        ScaleComponent c = new ScaleComponent(name, scale);
151        addComponent(c);
152        return c;
153    }
154
155    public void addComponent(Component c) {
156        if (c.mParent != null) {
157            throw new IllegalArgumentException("Transform components may not be shared");
158        }
159        c.mParent = this;
160        c.mParentIndex = mTransformComponents.size();
161        mTransformComponents.add(c);
162        updateRSComponentAllocation();
163    }
164
165    public void setComponent(int index, Component c) {
166        if (c.mParent != null) {
167            throw new IllegalArgumentException("Transform components may not be shared");
168        }
169        if (index >= mTransformComponents.size()) {
170            throw new IllegalArgumentException("Invalid component index");
171        }
172        c.mParent = this;
173        c.mParentIndex = index;
174        mTransformComponents.set(index, c);
175        updateRSComponent(c);
176    }
177
178    void updateRSComponent(Component c) {
179        if (mField == null || mComponentField == null) {
180            return;
181        }
182        mComponentField.set(c.getRSData(), c.mParentIndex, true);
183        mField.set_isDirty(0, 1, true);
184    }
185
186    void updateRSComponentAllocation() {
187        if (mField == null) {
188            return;
189        }
190        initLocalData();
191
192        mField.set_components(0, mTransformData.components, false);
193        mField.set_isDirty(0, 1, true);
194    }
195
196    void initLocalData() {
197        RenderScriptGL rs = SceneManager.getRS();
198        int numComponenets = mTransformComponents.size();
199        if (numComponenets > 0) {
200            mComponentField = new ScriptField_TransformComponent_s(rs, numComponenets);
201            for (int i = 0; i < numComponenets; i ++) {
202                Component ith = mTransformComponents.get(i);
203                mComponentField.set(ith.getRSData(), i, false);
204            }
205            mComponentField.copyAll();
206
207            mTransformData.components = mComponentField.getAllocation();
208        }
209    }
210}
211
212
213
214
215
216