1 /*
2 * Entreri, an entity-component framework in Java
3 *
4 * Copyright (c) 2013, Michael Ludwig
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without modification,
8 * are permitted provided that the following conditions are met:
9 *
10 * Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package com.lhkbob.entreri.property;
28
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 import java.util.Arrays;
32
33 /**
34 * BooleanProperty is an implementation of Property that stores a single boolean
35 * property.
36 *
37 * @author Michael Ludwig
38 */
39 @Factory(BooleanProperty.Factory.class)
40 public final class BooleanProperty implements Property {
41 private boolean[] data;
42
43 /**
44 * Create a BooleanProperty.
45 */
46 public BooleanProperty() {
47 data = new boolean[1];
48 }
49
50 /**
51 * Return the backing boolean array of this property's IndexedDataStore. The array may
52 * be longer than necessary for the number of components in the system. Data can be
53 * accessed for a component directly using the component's index.
54 *
55 * @return The boolean data for all packed properties that this property has been
56 * packed with
57 */
58 public boolean[] getIndexedData() {
59 return data;
60 }
61
62 /**
63 * Get the value stored in this property for the given component index.
64 *
65 * @param componentIndex The component's index
66 *
67 * @return The object at the given offset for the given component
68 *
69 * @throws ArrayIndexOutOfBoundsException if the componentIndex is invalid
70 */
71 public boolean get(int componentIndex) {
72 return data[componentIndex];
73 }
74
75 /**
76 * Store <var>val</var> in this property for the given component index.
77 *
78 * @param componentIndex The index of the component being modified
79 * @param val The value to store
80 *
81 * @throws ArrayIndexOutOfBoundsException if the componentIndex is invalid
82 */
83 public void set(int componentIndex, boolean val) {
84 data[componentIndex] = val;
85 }
86
87 @Override
88 public void swap(int a, int b) {
89 boolean t = data[a];
90 data[a] = data[b];
91 data[b] = t;
92 }
93
94 @Override
95 public int getCapacity() {
96 return data.length;
97 }
98
99 @Override
100 public void setCapacity(int size) {
101 data = Arrays.copyOf(data, size);
102 }
103
104 /**
105 * Factory to create BooleanProperties. Properties annotated with DefaultBoolean will
106 * use that value as the default for all components.
107 *
108 * @author Michael Ludwig
109 */
110 public static class Factory implements PropertyFactory<BooleanProperty> {
111 private final boolean defaultValue;
112 private final Clone.Policy policy;
113
114 public Factory(Attributes attrs) {
115 defaultValue = attrs.hasAttribute(DefaultBoolean.class) &&
116 attrs.getAttribute(DefaultBoolean.class).value();
117 policy = attrs.hasAttribute(Clone.class) ? attrs.getAttribute(Clone.class)
118 .value()
119 : Clone.Policy.JAVA_DEFAULT;
120 }
121
122 public Factory(boolean defaultValue) {
123 this.defaultValue = defaultValue;
124 policy = Clone.Policy.JAVA_DEFAULT;
125 }
126
127 @Override
128 public BooleanProperty create() {
129 return new BooleanProperty();
130 }
131
132 @Override
133 public void setDefaultValue(BooleanProperty property, int index) {
134 property.set(index, defaultValue);
135 }
136
137 @Override
138 public void clone(BooleanProperty src, int srcIndex, BooleanProperty dst,
139 int dstIndex) {
140 switch (policy) {
141 case DISABLE:
142 // assign default value
143 setDefaultValue(dst, dstIndex);
144 break;
145 case INVOKE_CLONE:
146 // fall through, since default implementation of INVOKE_CLONE is to
147 // just function like JAVA_DEFAULT
148 case JAVA_DEFAULT:
149 dst.set(dstIndex, src.get(srcIndex));
150 break;
151 default:
152 throw new UnsupportedOperationException(
153 "Enum value not supported: " + policy);
154 }
155 }
156 }
157
158 /**
159 * Default boolean attribute for properties.
160 *
161 * @author Michael Ludwig
162 */
163 @Attribute
164 @Retention(RetentionPolicy.RUNTIME)
165 public static @interface DefaultBoolean {
166 boolean value();
167 }
168 }