BodyAtty.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho
3  *
4  * This software is provided 'as-is', without any express or implied
5  * warranty. In no event will the authors be held liable for any damages
6  * arising from the use of this software.
7  *
8  * Permission is granted to anyone to use this software for any purpose,
9  * including commercial applications, and to alter it and redistribute it
10  * freely, subject to the following restrictions:
11  *
12  * 1. The origin of this software must not be misrepresented; you must not
13  * claim that you wrote the original software. If you use this software
14  * in a product, an acknowledgment in the product documentation would be
15  * appreciated but is not required.
16  * 2. Altered source versions must be plainly marked as such, and must not be
17  * misrepresented as being the original software.
18  * 3. This notice may not be removed or altered from any source distribution.
19  */
20 
21 #ifndef PLAYRHO_DYNAMICS_BODYATTY_HPP
22 #define PLAYRHO_DYNAMICS_BODYATTY_HPP
23 
26 
31 
32 #include <algorithm>
33 #include <utility>
34 
35 namespace playrho {
36 namespace d2 {
37 
49 class BodyAtty
50 {
51 private:
52 
54  static Body* CreateBody(World* world, const BodyConf& bd)
55  {
56  return new Body(world, bd);
57  }
58 
60  static void Delete(Body* b)
61  {
62  delete b;
63  }
64 
66  static void AddFixture(Body& b, Fixture *fixture)
67  {
68  b.m_fixtures.push_back(fixture);
69  }
70 
72  static bool RemoveFixture(Body& b, Fixture* fixture)
73  {
74  const auto begIter = begin(b.m_fixtures);
75  const auto endIter = end(b.m_fixtures);
76  const auto it = std::find_if(begIter, endIter, [fixture](Body::Fixtures::value_type& f) {
77  return GetPtr(f) == fixture;
78  });
79  if (it != endIter)
80  {
81  b.m_fixtures.erase(it);
82  return true;
83  }
84  return false;
85  }
86 
88  static void ClearFixtures(Body& b, std::function<void(Fixture&)> callback)
89  {
90  const auto begIter = begin(b.m_fixtures);
91  const auto endIter = end(b.m_fixtures);
92  std::for_each(begIter, endIter, [&](Body::Fixtures::value_type& f) {
93  callback(GetRef(f));
94  });
95  b.m_fixtures.clear();
96  }
97 
99  static void SetTypeFlags(Body& b, BodyType type) noexcept
100  {
102  b.m_flags |= Body::GetFlags(type);
103 
104  switch (type)
105  {
106  case BodyType::Dynamic:
107  break;
108  case BodyType::Kinematic:
109  break;
110  case BodyType::Static:
111  b.UnsetAwakeFlag();
112  b.m_underActiveTime = 0;
113  b.m_velocity = Velocity{LinearVelocity2{}, 0_rpm};
114  b.m_sweep.pos0 = b.m_sweep.pos1;
115  break;
116  }
117  }
118 
120  static void SetAwakeFlag(Body& b) noexcept
121  {
122  b.SetAwakeFlag();
123  }
124 
126  static void SetMassDataDirty(Body& b) noexcept
127  {
128  b.SetMassDataDirty();
129  }
130 
132  static bool Erase(Body& b, const Contact* value)
133  {
134  return b.Erase(value);
135  }
136 
138  static bool Erase(Body& b, const Joint* value)
139  {
140  return b.Erase(value);
141  }
142 
144  static void ClearContacts(Body &b)
145  {
146  b.ClearContacts();
147  }
148 
150  static void ClearJoints(Body &b)
151  {
152  b.ClearJoints();
153  }
154 
156  static bool Insert(Body& b, Joint* value)
157  {
158  return b.Insert(value);
159  }
160 
162  static bool Insert(Body* b, Joint* value)
163  {
164  if (b)
165  {
166  return Insert(*b, value);
167  }
168  return false;
169  }
170 
172  static bool Insert(Body& b, ContactKey key, Contact* value)
173  {
174  return b.Insert(key, value);
175  }
176 
178  static void SetPosition0(Body& b, const Position value) noexcept
179  {
180  assert(b.IsSpeedable() || b.m_sweep.pos0 == value);
181  b.m_sweep.pos0 = value;
182  }
183 
187  static void SetPosition1(Body& b, const Position value) noexcept
188  {
189  assert(b.IsSpeedable() || b.m_sweep.pos1 == value);
190  b.m_sweep.pos1 = value;
191  }
192 
194  static void ResetAlpha0(Body& b) noexcept
195  {
196  b.m_sweep.ResetAlpha0();
197  }
198 
200  static void SetSweep(Body& b, const Sweep value) noexcept
201  {
202  assert(b.IsSpeedable() || value.pos0 == value.pos1);
203  b.m_sweep = value;
204  }
205 
209  static void SetTransformation(Body& b, const Transformation value) noexcept
210  {
211  b.SetTransformation(value);
212  }
213 
217  static void SetVelocity(Body& b, Velocity value) noexcept
218  {
219  b.m_velocity = value;
220  }
221 
224  static void Advance0(Body& b, Real value) noexcept
225  {
226  // Note: Static bodies must **never** have different sweep position values.
227 
228  // Confirm bodies don't have different sweep positions to begin with...
229  assert(b.IsSpeedable() || b.m_sweep.pos1 == b.m_sweep.pos0);
230 
231  b.m_sweep.Advance0(value);
232 
233  // Confirm bodies don't have different sweep positions to end with...
234  assert(b.IsSpeedable() || b.m_sweep.pos1 == b.m_sweep.pos0);
235  }
236 
238  static void Advance(Body& b, Real toi) noexcept
239  {
240  b.Advance(toi);
241  }
242 
244  static void Restore(Body& b, const Sweep value) noexcept
245  {
246  BodyAtty::SetSweep(b, value);
247  BodyAtty::SetTransformation(b, GetTransform1(value));
248  }
249 
251  static void ClearJoints(Body& b, std::function<void(Joint&)> callback)
252  {
253  auto joints = std::move(b.m_joints);
254  assert(empty(b.m_joints));
255  std::for_each(cbegin(joints), cend(joints), [&](Body::KeyedJointPtr j) {
256  callback(*(std::get<Joint*>(j)));
257  });
258  }
259 
261  static void EraseContacts(Body& b, const std::function<bool(Contact&)>& callback)
262  {
263  auto last = end(b.m_contacts);
264  auto iter = begin(b.m_contacts);
265  auto index = Body::Contacts::difference_type{0};
266  while (iter != last)
267  {
268  const auto contact = GetContactPtr(*iter);
269  if (callback(*contact))
270  {
271  b.m_contacts.erase(iter);
272  iter = begin(b.m_contacts) + index;
273  last = end(b.m_contacts);
274  }
275  else
276  {
277  iter = std::next(iter);
278  ++index;
279  }
280  }
281  }
282 
284  static bool IsIslanded(const Body& b) noexcept
285  {
286  return b.IsIslanded();
287  }
288 
290  static void SetIslanded(Body& b) noexcept
291  {
292  b.SetIslandedFlag();
293  }
294 
296  static void UnsetIslanded(Body& b) noexcept
297  {
298  b.UnsetIslandedFlag();
299  }
300 
301  friend class World;
302 };
303 
304 } // namespace d2
305 } // namespace playrho
306 
307 #endif // PLAYRHO_DYNAMICS_BODYATTY_HPP