1 /********************************************************************************
2 * ReactPhysics3D physics library, http://www.reactphysics3d.com *
3 * Copyright (c) 2010-2020 Daniel Chappuis *
4 *********************************************************************************
5 * *
6 * This software is provided 'as-is', without any express or implied warranty. *
7 * In no event will the authors be held liable for any damages arising from the *
8 * use of this software. *
9 * *
10 * Permission is granted to anyone to use this software for any purpose, *
11 * including commercial applications, and to alter it and redistribute it *
12 * freely, subject to the following restrictions: *
13 * *
14 * 1. The origin of this software must not be misrepresented; you must not claim *
15 * that you wrote the original software. If you use this software in a *
16 * product, an acknowledgment in the product documentation would be *
17 * appreciated but is not required. *
18 * *
19 * 2. Altered source versions must be plainly marked as such, and must not be *
20 * misrepresented as being the original software. *
21 * *
22 * 3. This notice may not be removed or altered from any source distribution. *
23 * *
24 ********************************************************************************/
25
26 // Libraries
27 #include <reactphysics3d/components/Components.h>
28 #include <cassert>
29
30 // We want to use the ReactPhysics3D namespace
31 using namespace reactphysics3d;
32
33 // Constructor
Components(MemoryAllocator & allocator,size_t componentDataSize)34 Components::Components(MemoryAllocator& allocator, size_t componentDataSize)
35 : mMemoryAllocator(allocator), mNbComponents(0), mComponentDataSize(componentDataSize),
36 mNbAllocatedComponents(0), mBuffer(nullptr), mMapEntityToComponentIndex(allocator),
37 mDisabledStartIndex(0) {
38
39 }
40
~Components()41 Components::~Components() {
42
43 // If there are allocated components
44 if (mNbAllocatedComponents > 0) {
45
46 // Destroy all the remaining components
47 for (uint32 i = 0; i < mNbComponents; i++) {
48
49 destroyComponent(i);
50 }
51
52 // Size for the data of a single component (in bytes)
53 const size_t totalSizeBytes = mNbAllocatedComponents * mComponentDataSize;
54
55 // Release the allocated memory
56 mMemoryAllocator.release(mBuffer, totalSizeBytes);
57 }
58 }
59
60 // Compute the index where we need to insert the new component
prepareAddComponent(bool isSleeping)61 uint32 Components::prepareAddComponent(bool isSleeping) {
62
63 // If we need to allocate more components
64 if (mNbComponents == mNbAllocatedComponents) {
65 allocate(mNbAllocatedComponents * 2);
66 }
67
68 uint32 index;
69
70 // If the component to add is part of a disabled entity or there are no disabled entity
71 if (isSleeping) {
72
73 // Add the component at the end of the array
74 index = mNbComponents;
75 }
76 // If the component to add is not part of a disabled entity
77 else {
78
79 // If there already are disabled components
80 if (mDisabledStartIndex != mNbComponents) {
81
82 // Move the first disabled component to the end of the array
83 moveComponentToIndex(mDisabledStartIndex, mNbComponents);
84 }
85
86 index = mDisabledStartIndex;
87
88 mDisabledStartIndex++;
89 }
90
91 return index;
92 }
93
94 // Destroy a component at a given index
destroyComponent(uint32 index)95 void Components::destroyComponent(uint32 index) {
96
97 assert(index < mNbComponents);
98 }
99
100 // Remove a component at a given index
removeComponent(Entity entity)101 void Components::removeComponent(Entity entity) {
102
103 assert(mMapEntityToComponentIndex.containsKey(entity));
104
105 uint index = mMapEntityToComponentIndex[entity];
106
107 assert(index < mNbComponents);
108
109 // We want to keep the arrays tightly packed. Therefore, when a component is removed,
110 // we replace it with the last element of the array. But we need to make sure that enabled
111 // and disabled components stay grouped together.
112
113 // Destroy the component
114 destroyComponent(index);
115
116 // If the component to remove is disabled
117 if (index >= mDisabledStartIndex) {
118
119 // If the component is not the last one
120 if (index != mNbComponents - 1) {
121
122 // We replace it by the last disabled component
123 moveComponentToIndex(mNbComponents - 1, index);
124 }
125 }
126 else { // If the component to remove is enabled
127
128 // If it not the last enabled component
129 if (index != mDisabledStartIndex - 1) {
130
131 // We replace it by the last enabled component
132 moveComponentToIndex(mDisabledStartIndex - 1, index);
133 }
134
135 // If there are disabled components at the end
136 if (mDisabledStartIndex != mNbComponents) {
137
138 // We replace the last enabled component by the last disabled component
139 moveComponentToIndex(mNbComponents - 1, mDisabledStartIndex - 1);
140 }
141
142 mDisabledStartIndex--;
143 }
144
145 mNbComponents--;
146
147 assert(mDisabledStartIndex <= mNbComponents);
148 assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
149 }
150
151 // Notify if a given entity is disabled (sleeping) or not
setIsEntityDisabled(Entity entity,bool isDisabled)152 void Components::setIsEntityDisabled(Entity entity, bool isDisabled) {
153
154 const uint32 index = mMapEntityToComponentIndex[entity];
155
156 // If the component was disabled and is not disabled anymore
157 if (!isDisabled && index >= mDisabledStartIndex) {
158
159 assert(mDisabledStartIndex < mNbComponents);
160
161 // If the disabled component is not the first disabled component
162 if (mDisabledStartIndex != index) {
163
164 // Swap the first disabled component with the one we need to enable it
165 swapComponents(index, mDisabledStartIndex);
166 }
167
168 mDisabledStartIndex++;
169 }
170 // If the component was enabled and must now be disabled
171 else if (isDisabled && index < mDisabledStartIndex) {
172
173 assert(mDisabledStartIndex > 0);
174
175 // If the enabled component is not the only enabled component
176 if (index != mDisabledStartIndex - 1) {
177
178 // Swap the last enabled component with the one we need to disable
179 swapComponents(index, mDisabledStartIndex - 1);
180 }
181
182 mDisabledStartIndex--;
183 }
184
185 assert(mDisabledStartIndex <= mNbComponents);
186 assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
187 }
188