1
2//
3// This source file is part of appleseed.
4// Visit http://appleseedhq.net/ for additional information and resources.
5//
6// This software is released under the MIT license.
7//
8// Copyright (c) 2012-2013 Esteban Tovagliari, Jupiter Jazz Limited
9// Copyright (c) 2014-2017 Esteban Tovagliari, The appleseedhq Organization
10//
11// Permission is hereby granted, free of charge, to any person obtaining a copy
12// of this software and associated documentation files (the "Software"), to deal
13// in the Software without restriction, including without limitation the rights
14// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15// copies of the Software, and to permit persons to whom the Software is
16// furnished to do so, subject to the following conditions:
17//
18// The above copyright notice and this permission notice shall be included in
19// all copies or substantial portions of the Software.
20//
21// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27// THE SOFTWARE.
28//
29
30#ifndef APPLESEED_PYTHON_BINDENTITYCONTAINERS_H
31#define APPLESEED_PYTHON_BINDENTITYCONTAINERS_H
32
33// appleseed.python headers.
34#include "pyseed.h" // has to be first, to avoid redefinition warnings
35#include "dict2dict.h"
36
37// appleseed.renderer headers.
38#include "renderer/modeling/entity/entitymap.h"
39#include "renderer/modeling/entity/entityvector.h"
40
41// appleseed.foundation headers.
42#include "foundation/utility/autoreleaseptr.h"
43
44// Standard headers.
45#include <cstddef>
46#include <string>
47
48namespace detail
49{
50 template <typename T>
51 T* typed_entity_vector_get_item(renderer::TypedEntityVector<T>& vec, const int relative_index)
52 {
53 const size_t index =
54 static_cast<size_t>(
55 relative_index >= 0 ? relative_index : vec.size() + relative_index);
56
57 if (index >= vec.size())
58 {
59 PyErr_SetString(PyExc_IndexError, "Invalid index in appleseed.EntityVector");
60 boost::python::throw_error_already_set();
61 }
62
63 return vec.get_by_index(index);
64 }
65
66 template <typename T>
67 boost::python::object typed_entity_vector_remove(renderer::TypedEntityVector<T>& vec, T* entity)
68 {
69 foundation::auto_release_ptr<T> e = vec.remove(entity);
70 return boost::python::object(e);
71 }
72
73 template <typename T>
74 T* typed_entity_map_get_item(renderer::TypedEntityMap<T>& map, const std::string& key)
75 {
76 return map.get_by_name(key.c_str());
77 }
78
79 template <typename T>
80 boost::python::object typed_entity_map_remove(renderer::TypedEntityMap<T>* map, T* entity)
81 {
82 foundation::auto_release_ptr<T> e = map->remove(entity);
83 return boost::python::object(e);
84 }
85
86 template <typename T>
87 boost::python::object typed_entity_map_remove_by_uid(renderer::TypedEntityMap<T>* map, const foundation::UniqueID id)
88 {
89 foundation::auto_release_ptr<T> e = map->remove(id);
90 return boost::python::object(e);
91 }
92
93 template <typename T>
94 boost::python::object typed_entity_map_get_iter(renderer::TypedEntityMap<T>* map)
95 {
96 boost::python::dict items;
97
98 typedef typename renderer::TypedEntityMap<T>::iterator iterator;
99
100 for (iterator it(map->begin()), e(map->end()); it != e; ++it)
101 items[it->get_name()] = boost::python::ptr(&(*it));
102
103 return items.attr("__iter__")();
104 }
105
106 template <typename T>
107 boost::python::list typed_entity_map_get_keys(renderer::TypedEntityMap<T>* map)
108 {
109 boost::python::list items;
110
111 typedef typename renderer::TypedEntityMap<T>::iterator iterator;
112
113 for (iterator it(map->begin()), e(map->end()); it != e; ++it)
114 items.append(it->get_name());
115
116 return items;
117 }
118
119 template <typename T>
120 boost::python::list typed_entity_map_get_values(renderer::TypedEntityMap<T>* map)
121 {
122 boost::python::list items;
123
124 typedef typename renderer::TypedEntityMap<T>::iterator iterator;
125
126 for (iterator it(map->begin()), e(map->end()); it != e; ++it)
127 items.append(boost::python::ptr(&(*it)));
128
129 return items;
130 }
131}
132
133template <typename T>
134void bind_typed_entity_vector(const char* name)
135{
136 boost::python::class_<renderer::TypedEntityVector<T>, boost::python::bases<renderer::EntityVector>, boost::noncopyable>(name)
137 .def("__getitem__", detail::typed_entity_vector_get_item<T>, boost::python::return_value_policy<boost::python::reference_existing_object>())
138 .def("get_by_uid", &renderer::TypedEntityVector<T>::get_by_uid, boost::python::return_value_policy<boost::python::reference_existing_object>())
139 .def("get_by_name", &renderer::TypedEntityVector<T>::get_by_name, boost::python::return_value_policy<boost::python::reference_existing_object>())
140
141 .def("insert", &renderer::TypedEntityVector<T>::insert)
142 .def("remove", &detail::typed_entity_vector_remove<T>)
143
144 .def("__iter__", boost::python::iterator<renderer::TypedEntityVector<T>, boost::python::return_internal_reference<> >());
145}
146
147template <typename T>
148void bind_typed_entity_map(const char* name)
149{
150 boost::python::class_<renderer::TypedEntityMap<T>, boost::python::bases<renderer::EntityMap>, boost::noncopyable>(name)
151 .def("__getitem__", detail::typed_entity_map_get_item<T>, boost::python::return_value_policy<boost::python::reference_existing_object>())
152 .def("get_by_uid", &renderer::TypedEntityMap<T>::get_by_uid, boost::python::return_value_policy<boost::python::reference_existing_object>())
153 .def("get_by_name", &renderer::TypedEntityMap<T>::get_by_name, boost::python::return_value_policy<boost::python::reference_existing_object>())
154
155 .def("insert", &renderer::TypedEntityMap<T>::insert)
156 .def("remove", &detail::typed_entity_map_remove<T>)
157 .def("remove_by_uid", &detail::typed_entity_map_remove_by_uid<T>)
158
159 .def("__iter__", &detail::typed_entity_map_get_iter<T>)
160
161 .def("keys", &detail::typed_entity_map_get_keys<T>)
162 .def("values", &detail::typed_entity_map_get_values<T>);
163}
164
165#endif // !APPLESEED_PYTHON_BINDENTITYCONTAINERS_H
166