Joint.cpp
Go to the documentation of this file.
1 /*
2  * Original work Copyright (c) 2006-2007 Erin Catto http://www.box2d.org
3  * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 
38 #include <PlayRho/Defines.hpp>
39 
40 #include <algorithm>
41 
42 namespace playrho {
43 namespace d2 {
44 
45 Joint* Joint::Create(const JointConf& def)
46 {
47  switch (def.type)
48  {
50  return Create<DistanceJoint>(static_cast<const DistanceJointConf&>(def));
51  case JointType::Target:
52  return Create<TargetJoint>(static_cast<const TargetJointConf&>(def));
54  return Create<PrismaticJoint>(static_cast<const PrismaticJointConf&>(def));
56  return Create<RevoluteJoint>(static_cast<const RevoluteJointConf&>(def));
57  case JointType::Pulley:
58  return Create<PulleyJoint>(static_cast<const PulleyJointConf&>(def));
59  case JointType::Gear:
60  return Create<GearJoint>(static_cast<const GearJointConf&>(def));
61  case JointType::Wheel:
62  return Create<WheelJoint>(static_cast<const WheelJointConf&>(def));
63  case JointType::Weld:
64  return Create<WeldJoint>(static_cast<const WeldJointConf&>(def));
66  return Create<FrictionJoint>(static_cast<const FrictionJointConf&>(def));
67  case JointType::Rope:
68  return Create<RopeJoint>(static_cast<const RopeJointConf&>(def));
69  case JointType::Motor:
70  return Create<MotorJoint>(static_cast<const MotorJointConf&>(def));
71  case JointType::Unknown:
72  break;
73  }
74  throw InvalidArgument("Joint::Create: Unknown joint type");
75 }
76 
77 Joint::FlagsType Joint::GetFlags(const JointConf& def) noexcept
78 {
79  auto flags = Joint::FlagsType{0};
80  if (def.collideConnected)
81  {
82  flags |= e_collideConnectedFlag;
83  }
84  return flags;
85 }
86 
87 Joint::Joint(const JointConf& def):
88  m_bodyA{def.bodyA}, m_bodyB{def.bodyB}, m_userData{def.userData}, m_flags{GetFlags(def)}
89 {
90  // Intentionally empty.
91 }
92 
93 void Joint::Destroy(const Joint* joint) noexcept
94 {
95  delete joint;
96 }
97 
98 bool Joint::IsOkay(const JointConf& def) noexcept
99 {
100  return def.bodyA != def.bodyB;
101 }
102 
103 // Free functions...
104 
105 bool IsEnabled(const Joint& j) noexcept
106 {
107  const auto bA = j.GetBodyA();
108  const auto bB = j.GetBodyB();
109  return (!bA || bA->IsEnabled()) && (!bB || bB->IsEnabled());
110 }
111 
112 void SetAwake(Joint& j) noexcept
113 {
114  const auto bA = j.GetBodyA();
115  const auto bB = j.GetBodyB();
116  if (bA)
117  {
118  bA->SetAwake();
119  }
120  if (bB)
121  {
122  bB->SetAwake();
123  }
124 }
125 
127 {
128  if (joint)
129  {
130  const auto bA = joint->GetBodyA();
131  const auto bB = joint->GetBodyB();
132  const auto world = bA? bA->GetWorld():
133  bB? bB->GetWorld(): static_cast<const World*>(nullptr);
134  if (world)
135  {
136  auto i = JointCounter{0};
137  const auto joints = world->GetJoints();
138  const auto it = std::find_if(cbegin(joints), cend(joints), [&](const Joint *j) {
139  return (j == joint) || ((void) ++i, false);
140  });
141  if (it != end(joints))
142  {
143  return i;
144  }
145  }
146  }
147  return JointCounter(-1);
148 }
149 
150 #ifdef PLAYRHO_PROVIDE_VECTOR_AT
151 BodyConstraintPtr& At(std::vector<BodyConstraintPair>& container, const Body* key)
152 {
153  auto last = end(container);
154  auto first = begin(container);
155  first = std::lower_bound(first, last, key, [](const BodyConstraintPair &a, const Body* b){
156  return std::get<const Body*>(a) < b;
157  });
158  if ((first == last) || (key != std::get<const Body*>(*first)))
159  {
160  throw std::out_of_range{"invalid key"};
161  }
162  return std::get<BodyConstraintPtr>(*first);
163 }
164 #endif
165 
166 BodyConstraintPtr& At(std::unordered_map<const Body*, BodyConstraint*>& container,
167  const Body* key)
168 {
169  return container.at(key);
170 }
171 
172 const char* ToString(Joint::LimitState val) noexcept
173 {
174  switch (val)
175  {
176  case Joint::e_atLowerLimit: return "at lower";
177  case Joint::e_atUpperLimit: return "at upper";
178  case Joint::e_equalLimits: return "equal";
179  case Joint::e_inactiveLimit: break;
180  }
181  assert(val == Joint::e_inactiveLimit);
182  return "inactive";
183 }
184 
185 } // namespace d2
186 } // namespace playrho