SUAPI-CppWrapper
C++WrapperforSketchUpCAPI
Entity.cpp
1 //
2 // Entity.cpp
3 //
4 // Sketchup C++ Wrapper for C API
5 // MIT License
6 //
7 // Copyright (c) 2017 Tom Kaneko
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
15 
16 // The above copyright notice and this permission notice shall be included in all
17 // copies or substantial portions of the Software.
18 
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 // SOFTWARE.
26 //
27 
28 // Macro for getting rid of unused variables commonly for assert checking
29 #define _unused(x) ((void)(x))
30 
31 #include "SUAPI-CppWrapper/model/Entity.hpp"
32 
33 #include <algorithm>
34 #include <cassert>
35 #include <stdexcept>
36 #include <algorithm>
37 
38 #include "SUAPI-CppWrapper/model/AttributeDictionary.hpp"
39 #include "SUAPI-CppWrapper/model/Model.hpp"
40 #include "SUAPI-CppWrapper/model/Entities.hpp"
41 
42 
43 namespace CW {
44 
45 /******************************
46 ** Constructors / Destructor **
47 *******************************/
49  m_entity(SU_INVALID),
50  m_attached(false)
51 {}
52 
53 
54 Entity::Entity(SUEntityRef entity, bool attached):
55  m_entity(entity),
56  m_attached(attached)
57 {}
58 
59 
60 Entity::Entity(const Entity& other, SUEntityRef entity_ref):
61  m_entity(entity_ref),
62  m_attached(other.m_attached)
63 {}
64 
65 
67  // Entity objects cannot release themselves.
68 }
69 
70 /*******************
71 ** Public Methods **
72 ********************/
74  m_attached = other.m_attached;
75  if (SUIsInvalid(other.m_entity)) {
76  m_entity = other.m_entity;
77  }
78  else if (!other.m_attached) {
79  this->copy_attributes_from(other);
80  }
81  return (*this);
82 }
83 
84 
85 Entity::operator SUEntityRef() const {
86  return ref();
87 }
88 
89 
90 Entity::operator SUEntityRef*() {
91  return &m_entity;
92 }
93 
94 
95 SUEntityRef Entity::ref() const{
96  return m_entity;
97 }
98 
99 
100 bool Entity::attached() const {
101  return m_attached;
102 }
103 
104 
105 void Entity::attached(bool attach) {
106  m_attached = attach;
107 }
108 
109 
110 std::vector<AttributeDictionary> Entity::attribute_dictionaries() const {
111  if (!(*this)) {
112  throw std::logic_error("CW::Entity::attribute_dictionaries(): Entity is null");
113  }
114  size_t num_dicts = 0;
115  SUResult res = SUEntityGetNumAttributeDictionaries(m_entity, &num_dicts);
116  assert(res == SU_ERROR_NONE);
117  if (num_dicts == 0) {
118  return std::vector<AttributeDictionary>{};
119  }
120  std::vector<SUAttributeDictionaryRef> dicts_ref(num_dicts, SU_INVALID);
121  res = SUEntityGetAttributeDictionaries(m_entity, num_dicts, dicts_ref.data(), &num_dicts);
122  assert(res == SU_ERROR_NONE); _unused(res);
123  std::vector<AttributeDictionary> dicts(num_dicts);
124  std::transform(dicts_ref.begin(), dicts_ref.end(), dicts.begin(),
125  [](const SUAttributeDictionaryRef& value) {
126  return AttributeDictionary(value);
127  });;
128  return dicts;
129 }
130 
131 AttributeDictionary Entity::attribute_dictionary(const std::string& name) const {
132  if (!(*this)) {
133  throw std::logic_error("CW::Entity::attribute_dictionary(): Entity is null");
134  }
135  char const *c_name = name.c_str();
136  SUAttributeDictionaryRef dict_ref = SU_INVALID;
137  SUResult res = SUEntityGetAttributeDictionary(m_entity, &c_name[0], &dict_ref);
138  if (res == SU_ERROR_NONE) {
139  return AttributeDictionary(dict_ref);
140  }
141  // Otherwise return null object
142  return AttributeDictionary();
143 }
144 
145 
147  SUResult res = SUEntityAddAttributeDictionary(m_entity, dict.ref());
148  if (res == SU_ERROR_NONE) {
149  dict.attached(true);
150  return true;
151  }
152  return false;
153 }
154 
155 
157  if (!(*this) || !entity) {
158  throw std::logic_error("CW::Entity::copy_attributes_from(): Entity is null");
159  }
160  std::vector<AttributeDictionary> atts_from = entity.attribute_dictionaries();
161  for (size_t i=0; i < atts_from.size(); i++) {
162  std::vector<std::string> from_keys = atts_from[i].get_keys();
163  for (size_t j=0; j < from_keys.size(); j++) {
164  set_attribute(atts_from[i].get_name(), from_keys[j], atts_from[i].get_value(from_keys[j]));
165  }
166  }
167  // TODO do some checking.
168  return true;
169 }
170 
171 /* TODO: deleting attributes is not possible with the current C API. It could be used, however, to store a list of deleted attributes, so if this object is copied, the deleted attributes are not copied over to the new object.
172 void delete_attribute(AttributeDictionary &dict, std::string key);
173 */
174 
175 bool Entity::is_valid() const {
176  return !!(*this);
177 }
178 
179 
180 bool Entity::operator!() const {
181  return SUIsInvalid(m_entity);
182 }
183 
184 
185 int32_t Entity::entityID() const{
186  if (!(*this)) {
187  throw std::logic_error("CW::Entity::entityID(): Entity is null");
188  }
189  int32_t entity_id = SU_INVALID;
190  SUEntityGetID(m_entity, &entity_id);
191  return entity_id;
192 }
193 
194 
195 TypedValue Entity::get_attribute(const std::string& dict_name, const std::string& key, const TypedValue& default_value) const {
196  if (!(*this)) {
197  throw std::logic_error("CW::Entity::get_attribute(): Entity is null");
198  }
199  AttributeDictionary dict = attribute_dictionary(dict_name);
200  return get_attribute(dict, key, default_value);
201 }
202 
203 
204 TypedValue Entity::get_attribute(const AttributeDictionary& dict, const std::string& key, const TypedValue& default_value) const {
205  if (!(*this)) {
206  throw std::logic_error("CW::Entity::get_attribute(): Entity is null");
207  }
208  return dict.get_attribute(key, default_value);
209 }
210 
211 /*
212 // TODO: C API does not currently allow traversing upwards
213 parent()
214 */
215 
216 
217 bool Entity::set_attribute(const std::string& dict_name, const std::string& key, const TypedValue& value) {
218  if (!(*this)) {
219  throw std::logic_error("CW::Entity::set_attribute(): Entity is null");
220  }
221  AttributeDictionary dict = attribute_dictionary(dict_name);
222  return set_attribute(dict, key, value);
223 }
224 
225 
226 bool Entity::set_attribute(AttributeDictionary& dict, const std::string& key, const TypedValue& value) {
227  if (!(*this)) {
228  throw std::logic_error("CW::Entity::set_attribute(): Entity is null");
229  }
230  return dict.set_attribute(key, value);
231 }
232 
233 
234 enum SURefType Entity::entity_type() const{
235  if (!(*this)) {
236  throw std::logic_error("CW::Entity::entity_type(): Entity is null");
237  }
238  return SUEntityGetType(m_entity);
239 }
240 
242  if (!(*this)) {
243  throw std::logic_error("CW::Entity::parent(): Entity is null");
244  }
245  SUModelRef model = SU_INVALID;
246  SUResult res = SUEntityGetModel(m_entity, &model);
247  assert(res == SU_ERROR_NONE); _unused(res);
248  return Model(model, false);
249 }
250 
252  if (!(*this)) {
253  throw std::logic_error("CW::Entity::parent(): Entity is null");
254  }
255  SUEntitiesRef entities = SU_INVALID;
256  SUResult res = SUEntityGetParentEntities(m_entity, &entities);
257  assert(res == SU_ERROR_NONE); _unused(res);
258  return Entities(entities, this->model().ref());
259 }
260 
261 
262 int64_t Entity::persistent_id() const {
263  int64_t pid;
264  SUResult res = SUEntityGetPersistentID(m_entity, &pid);
265  assert(res == SU_ERROR_NONE); _unused(res);
266  return pid;
267 }
268 
269 
270 /*
271 bool Entity::operator==(const Entity& entity) const {
272  if (m_entity.ptr == entity.m_entity.ptr) {
273  return true;
274  }
275  return false;
276  //return entityID() == entity.entityID();
277 }
278 */
279 
280 bool operator==(const Entity& lhs, const Entity& rhs) {
281  if (!lhs || !rhs) {
282  if (!lhs && !rhs) {
283  return true;
284  }
285  return false;
286  }
287 
288  return lhs.m_entity.ptr == rhs.m_entity.ptr;
289 }
290 
291 bool operator!=(const Entity& lhs, const Entity& rhs) {
292  return !(lhs == rhs);
293 }
294 
295 } /* namespace CW */
bool m_attached
Indicates whether the Entity has been attached to a model.
Definition: Entity.hpp:64
SUAttributeDictionaryRef ref() const
TypedValue get_attribute(const std::string &dict_name, const std::string &key, const TypedValue &default_value=TypedValue()) const
Retrieves the value of an attribute in the entity&#39;s attribute dictionary.
Definition: Entity.cpp:195
Entity()
Constructor representing a null objject.
Definition: Entity.cpp:48
bool attached() const
Returns true if the entity is attached to another object.
Definition: Entity.cpp:100
friend bool operator==(const Entity &lhs, const Entity &rhs)
Equality operator for two entity objects.
Definition: Entity.cpp:280
friend bool operator!=(const Entity &lhs, const Entity &rhs)
Non-equality operator for two entity objects.
Definition: Entity.cpp:291
bool copy_attributes_from(const Entity &entity)
Copies attributes from another Entity object to this one.
Definition: Entity.cpp:156
std::vector< AttributeDictionary > attribute_dictionaries() const
Returns the AttributeDictionaries collection attached to the entity.
Definition: Entity.cpp:110
TypedValue get_attribute(const std::string &key, const TypedValue &default_value) const
enum SURefType entity_type() const
Returns the type of the entity. See enum SURefType.
Definition: Entity.cpp:234
~Entity()
Destructor.
Definition: Entity.cpp:66
Model model() const
Definition: Entity.cpp:241
SUEntityRef m_entity
The C SUEntityRef that this class wraps.
Definition: Entity.hpp:59
int32_t entityID() const
Retrieve a unique ID assigned to an entity.
Definition: Entity.cpp:185
bool is_valid() const
Checks if the entity is valid.
Definition: Entity.cpp:175
bool add_dictionary(AttributeDictionary &dict)
Adds the AttributeDictionary to the Entity.
Definition: Entity.cpp:146
Definition: Color.hpp:34
bool operator!() const
Returns true if this entity is not valid. Alias of !is_valid().
Definition: Entity.cpp:180
int64_t persistent_id() const
Definition: Entity.cpp:262
Entities parent() const
Definition: Entity.cpp:251
bool set_attribute(const std::string &dict_name, const std::string &key, const TypedValue &value)
Sets the value of an attribute in the given AttributeDictionary object.
Definition: Entity.cpp:217
AttributeDictionary attribute_dictionary(const std::string &name) const
Returns an attribute dictionary object with a given name that is attached to an Entity.
Definition: Entity.cpp:131
bool set_attribute(const std::string &key, const TypedValue &value)
Entity & operator=(const Entity &other)
Copy assignment operator.
Definition: Entity.cpp:73