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// appleseed.python headers.
31#include "pyseed.h" // has to be first, to avoid redefinition warnings
32#include "bindentitycontainers.h"
33#include "dict2dict.h"
34#include "metadata.h"
35#include "unalignedtransform.h"
36
37// appleseed.renderer headers.
38#include "renderer/api/scene.h"
39#include "renderer/api/texture.h"
40
41// appleseed.foundation headers.
42#include "foundation/utility/searchpaths.h"
43
44namespace bpy = boost::python;
45using namespace foundation;
46using namespace renderer;
47using namespace std;
48
49// Work around a regression in Visual Studio 2015 Update 3.
50#if defined(_MSC_VER) && _MSC_VER == 1900
51namespace boost
52{
53 template <> Texture const volatile* get_pointer<Texture const volatile>(Texture const volatile* p) { return p; }
54 template <> TextureInstance const volatile* get_pointer<TextureInstance const volatile>(TextureInstance const volatile* p) { return p; }
55}
56#endif
57
58namespace
59{
60 auto_release_ptr<Texture> create_texture(
61 const string& model,
62 const string& name,
63 const bpy::dict& params,
64 const bpy::list& search_paths)
65 {
66 TextureFactoryRegistrar factories;
67 const ITextureFactory* factory = factories.lookup(model.c_str());
68
69 if (factory)
70 {
71 SearchPaths paths;
72
73 for (bpy::ssize_t i = 0, e = bpy::len(search_paths); i < e; ++i)
74 {
75 bpy::extract<const char*> extractor(search_paths[i]);
76 if (extractor.check())
77 paths.push_back(extractor());
78 else
79 {
80 PyErr_SetString(PyExc_TypeError, "Incompatible type. Only strings accepted.");
81 bpy::throw_error_already_set();
82 }
83 }
84
85 return factory->create(name.c_str(), bpy_dict_to_param_array(params), paths);
86 }
87 else
88 {
89 PyErr_SetString(PyExc_RuntimeError, "Texture model not found");
90 bpy::throw_error_already_set();
91 }
92
93 return auto_release_ptr<Texture>();
94 }
95
96 auto_release_ptr<TextureInstance> create_texture_instance(
97 const string& name,
98 const bpy::dict& params,
99 const string& texture_name,
100 const UnalignedTransformf& transform)
101 {
102 return
103 TextureInstanceFactory::create(
104 name.c_str(),
105 bpy_dict_to_param_array(params),
106 texture_name.c_str(),
107 transform.as_foundation_transform());
108 }
109
110 UnalignedTransformf texture_inst_get_transform(const TextureInstance* tx)
111 {
112 return UnalignedTransformf(tx->get_transform());
113 }
114
115 string texture_inst_get_texture_name(const TextureInstance* tx)
116 {
117 return tx->get_texture_name();
118 }
119}
120
121void bind_texture()
122{
123 bpy::enum_<TextureAddressingMode>("TextureAddressingMode")
124 .value("Clamp", TextureAddressingClamp)
125 .value("Wrap", TextureAddressingWrap)
126 ;
127
128 bpy::enum_<TextureFilteringMode>("TextureFilteringMode")
129 .value("Nearest", TextureFilteringNearest)
130 .value("Bilinear", TextureFilteringBilinear)
131 .value("Bicubic", TextureFilteringBicubic)
132 .value("Feline", TextureFilteringFeline)
133 .value("EWA", TextureFilteringEWA)
134 ;
135
136 bpy::enum_<TextureAlphaMode>("TextureAlphaMode")
137 .value("AlphaChannel", TextureAlphaModeAlphaChannel)
138 .value("Luminance", TextureAlphaModeLuminance)
139 .value("Detect", TextureAlphaModeDetect)
140 ;
141
142 bpy::class_<Texture, auto_release_ptr<Texture>, bpy::bases<Entity>, boost::noncopyable>("Texture", bpy::no_init)
143 .def("get_model_metadata", &detail::get_entity_model_metadata<TextureFactoryRegistrar>).staticmethod("get_model_metadata")
144 .def("get_input_metadata", &detail::get_entity_input_metadata<TextureFactoryRegistrar>).staticmethod("get_input_metadata")
145 .def("__init__", bpy::make_constructor(create_texture))
146 .def("get_model", &Texture::get_model)
147 .def("get_color_space", &Texture::get_color_space)
148 ;
149
150 bind_typed_entity_vector<Texture>("TextureContainer");
151
152 bpy::class_<TextureInstance, auto_release_ptr<TextureInstance>, bpy::bases<Entity>, boost::noncopyable>("TextureInstance", bpy::no_init)
153 .def("__init__", bpy::make_constructor(create_texture_instance))
154 .def("get_addressing_mode", &TextureInstance::get_addressing_mode)
155 .def("get_alpha_mode", &TextureInstance::get_alpha_mode)
156 .def("get_filtering_mode", &TextureInstance::get_filtering_mode)
157 .def("get_transform", &texture_inst_get_transform)
158 .def("get_texture_name", &texture_inst_get_texture_name)
159 .def("find_texture", &TextureInstance::find_texture, bpy::return_value_policy<bpy::reference_existing_object>())
160 ;
161
162 bind_typed_entity_vector<TextureInstance>("TextureInstanceContainer");
163}
164