View Javadoc

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   * IntProperty is an implementation of Property that stores a single int value.
35   *
36   * @author Michael Ludwig
37   */
38  @Factory(IntProperty.Factory.class)
39  public final class IntProperty implements Property {
40      private int[] data;
41  
42      /**
43       * Create an IntProperty.
44       */
45      public IntProperty() {
46          data = new int[1];
47      }
48  
49      /**
50       * Return the backing int array of this property's IndexedDataStore. The array may be
51       * longer than necessary for the number of components in the system. Data can be
52       * accessed for a component directly using the component's index.
53       *
54       * @return The int data for all packed properties that this property has been packed
55       *         with
56       */
57      public int[] getIndexedData() {
58          return data;
59      }
60  
61      /**
62       * Get the value stored in this property for the given component index.
63       *
64       * @param componentIndex The component's index
65       *
66       * @return The object at the given offset for the given component
67       *
68       * @throws ArrayIndexOutOfBoundsException if the componentIndex is invalid
69       */
70      public int get(int componentIndex) {
71          return data[componentIndex];
72      }
73  
74      /**
75       * Store <var>val</var> in this property for the given component index.
76       *
77       * @param componentIndex The index of the component being modified
78       * @param val            The value to store, can be null
79       *
80       * @throws ArrayIndexOutOfBoundsException if the componentIndex is invalid
81       */
82      public void set(int componentIndex, int val) {
83          data[componentIndex] = val;
84      }
85  
86      @Override
87      public void swap(int a, int b) {
88          int t = data[a];
89          data[a] = data[b];
90          data[b] = t;
91      }
92  
93      @Override
94      public int getCapacity() {
95          return data.length;
96      }
97  
98      @Override
99      public void setCapacity(int size) {
100         data = Arrays.copyOf(data, size);
101     }
102 
103     /**
104      * Factory to create IntProperties. Properties annotated with DefaultInt will use that
105      * value as the default for all components.
106      *
107      * @author Michael Ludwig
108      */
109     public static class Factory implements PropertyFactory<IntProperty> {
110         private final int defaultValue;
111         private final Clone.Policy policy;
112 
113         public Factory(Attributes attrs) {
114             defaultValue = attrs.hasAttribute(DefaultInt.class) ? attrs
115                     .getAttribute(DefaultInt.class).value() : 0;
116             policy = attrs.hasAttribute(Clone.class) ? attrs.getAttribute(Clone.class)
117                                                             .value()
118                                                      : Clone.Policy.JAVA_DEFAULT;
119         }
120 
121         public Factory(int defaultValue) {
122             this.defaultValue = defaultValue;
123             policy = Clone.Policy.JAVA_DEFAULT;
124         }
125 
126         @Override
127         public IntProperty create() {
128             return new IntProperty();
129         }
130 
131         @Override
132         public void setDefaultValue(IntProperty property, int index) {
133             property.set(index, defaultValue);
134         }
135 
136         @Override
137         public void clone(IntProperty src, int srcIndex, IntProperty dst, int dstIndex) {
138             switch (policy) {
139             case DISABLE:
140                 // assign default value
141                 setDefaultValue(dst, dstIndex);
142                 break;
143             case INVOKE_CLONE:
144                 // fall through, since default implementation of INVOKE_CLONE is to
145                 // just function like JAVA_DEFAULT
146             case JAVA_DEFAULT:
147                 dst.set(dstIndex, src.get(srcIndex));
148                 break;
149             default:
150                 throw new UnsupportedOperationException(
151                         "Enum value not supported: " + policy);
152             }
153         }
154     }
155 
156     /**
157      * Default int attribute for properties.
158      *
159      * @author Michael Ludwig
160      */
161     @Attribute
162     @Retention(RetentionPolicy.RUNTIME)
163     public static @interface DefaultInt {
164         int value();
165     }
166 }