Blender V4.3
DocumentExporter.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <algorithm> /* std::find */
10#include <cmath>
11#include <cstdio>
12#include <cstdlib>
13#include <vector>
14
15#include "COLLADASWAsset.h"
16#include "COLLADASWBaseInputElement.h"
17#include "COLLADASWBindMaterial.h"
18#include "COLLADASWCamera.h"
19#include "COLLADASWColorOrTexture.h"
20#include "COLLADASWConstants.h"
21#include "COLLADASWEffectProfile.h"
22#include "COLLADASWException.h"
23#include "COLLADASWImage.h"
24#include "COLLADASWInputList.h"
25#include "COLLADASWInstanceCamera.h"
26#include "COLLADASWInstanceController.h"
27#include "COLLADASWInstanceGeometry.h"
28#include "COLLADASWInstanceLight.h"
29#include "COLLADASWInstanceNode.h"
30#include "COLLADASWLibraryAnimations.h"
31#include "COLLADASWLibraryControllers.h"
32#include "COLLADASWLibraryEffects.h"
33#include "COLLADASWLibraryImages.h"
34#include "COLLADASWLibraryMaterials.h"
35#include "COLLADASWLibraryVisualScenes.h"
36#include "COLLADASWNode.h"
37#include "COLLADASWParamBase.h"
38#include "COLLADASWParamTemplate.h"
39#include "COLLADASWPrimitves.h"
40#include "COLLADASWSampler.h"
41#include "COLLADASWScene.h"
42#include "COLLADASWSource.h"
43#include "COLLADASWSurfaceInitOption.h"
44#include "COLLADASWTechnique.h"
45#include "COLLADASWTexture.h"
46#include "COLLADASWVertices.h"
47
48#include "MEM_guardedalloc.h"
49
50#include "DNA_action_types.h"
51#include "DNA_anim_types.h"
52#include "DNA_armature_types.h"
54#include "DNA_curve_types.h"
55#include "DNA_image_types.h"
56#include "DNA_material_types.h"
57#include "DNA_mesh_types.h"
58#include "DNA_modifier_types.h"
59#include "DNA_object_types.h"
60#include "DNA_scene_types.h"
61#include "DNA_userdef_types.h"
62
63#include "BLI_fileops.h"
64#include "BLI_listbase.h"
65#include "BLI_path_utils.hh"
66#include "BLI_string.h"
67#include "BLI_utildefines.h"
68
69#include "BKE_action.hh" /* pose functions */
70#include "BKE_animsys.h"
71#include "BKE_appdir.hh"
72#include "BKE_armature.hh"
73#include "BKE_blender_version.h"
74#include "BKE_customdata.hh"
75#include "BKE_fcurve.hh"
76#include "BKE_global.hh"
77#include "BKE_image.hh"
78#include "BKE_main.hh"
79#include "BKE_material.h"
80#include "BKE_object.hh"
81#include "BKE_scene.hh"
82
83#include "ED_keyframing.hh"
84#ifdef WITH_BUILDINFO
85extern "C" char build_commit_date[];
86extern "C" char build_commit_time[];
87extern "C" char build_hash[];
88#endif
89
90#include "RNA_access.hh"
91
92#include "DocumentExporter.h"
93#include "collada_internal.h"
94#include "collada_utils.h"
95
96/* can probably go after refactor is complete */
97#include "InstanceWriter.h"
98#include "TransformWriter.h"
99
100#include "AnimationExporter.h"
101#include "ArmatureExporter.h"
102#include "CameraExporter.h"
103#include "ControllerExporter.h"
104#include "EffectExporter.h"
105#include "GeometryExporter.h"
106#include "ImageExporter.h"
107#include "LightExporter.h"
108#include "MaterialExporter.h"
109#include "SceneExporter.h"
110
111#include <cerrno>
112
113const char *bc_CustomData_get_layer_name(const CustomData *data, const eCustomDataType type, int n)
114{
115 int layer_index = CustomData_get_layer_index(data, type);
116 if (layer_index < 0) {
117 return nullptr;
118 }
119
120 return data->layers[layer_index + n].name;
121}
122
124{
125 /* get the layer index of the active layer of type */
126 int layer_index = CustomData_get_active_layer_index(data, type);
127 if (layer_index < 0) {
128 return nullptr;
129 }
130
131 return data->layers[layer_index].name;
132}
133
134DocumentExporter::DocumentExporter(BlenderContext &blender_context,
135 ExportSettings *export_settings)
136 : blender_context(blender_context),
137 export_settings(BCExportSettings(export_settings, blender_context))
138{
139}
140
141static COLLADABU::NativeString make_temp_filepath(const char *name, const char *extension)
142{
143 char tempfile[FILE_MAX];
144
145 if (name == nullptr) {
146 name = "untitled";
147 }
148
149 BLI_path_join(tempfile, sizeof(tempfile), BKE_tempdir_session(), name);
150
151 if (extension) {
152 BLI_path_extension_ensure(tempfile, FILE_MAX, extension);
153 }
154
155 COLLADABU::NativeString native_filename = COLLADABU::NativeString(
156 tempfile, COLLADABU::NativeString::ENCODING_UTF8);
157 return native_filename;
158}
159
160/* TODO: it would be better to instantiate animations rather than create a new one per object
161 * COLLADA allows this through multiple <channel>s in <animation>.
162 * For this to work, we need to know objects that use a certain action. */
163
165{
166 Scene *sce = blender_context.get_scene();
167 bContext *C = blender_context.get_context();
168
169 PointerRNA unit_settings;
170 PropertyRNA *system; /* unused, *scale; */
171
173
174 COLLADABU::NativeString native_filename = make_temp_filepath(nullptr, ".dae");
175 COLLADASW::StreamWriter *writer;
176 try {
177 writer = new COLLADASW::StreamWriter(native_filename);
178 }
179 catch (COLLADASW::StreamWriterException &e) {
180 e.printMessage();
181 fprintf(stderr, "Collada: No Objects will be exported.\n");
182 return 1;
183 }
184
185 /* open <collada> */
186 writer->startDocument();
187
188 /* <asset> */
189 COLLADASW::Asset asset(writer);
190
191 PointerRNA sceneptr = RNA_id_pointer_create(&sce->id);
192 unit_settings = RNA_pointer_get(&sceneptr, "unit_settings");
193 system = RNA_struct_find_property(&unit_settings, "system");
194 // scale = RNA_struct_find_property(&unit_settings, "scale_length");
195
196 std::string unitname = "meter";
197 float linearmeasure = RNA_float_get(&unit_settings, "scale_length");
198
199 switch (RNA_property_enum_get(&unit_settings, system)) {
200 case USER_UNIT_NONE:
201 case USER_UNIT_METRIC:
202 if (linearmeasure == 0.001f) {
203 unitname = "millimeter";
204 }
205 else if (linearmeasure == 0.01f) {
206 unitname = "centimeter";
207 }
208 else if (linearmeasure == 0.1f) {
209 unitname = "decimeter";
210 }
211 else if (linearmeasure == 1.0f) {
212 unitname = "meter";
213 }
214 else if (linearmeasure == 1000.0f) {
215 unitname = "kilometer";
216 }
217 break;
219 if (linearmeasure == 0.0254f) {
220 unitname = "inch";
221 }
222 else if (linearmeasure == 0.3048f) {
223 unitname = "foot";
224 }
225 else if (linearmeasure == 0.9144f) {
226 unitname = "yard";
227 }
228 break;
229 default:
230 break;
231 }
232
233 asset.setUnit(unitname, linearmeasure);
234 asset.setUpAxisType(COLLADASW::Asset::Z_UP);
235 asset.getContributor().mAuthor = "Blender User";
236 char version_buf[128];
237#ifdef WITH_BUILDINFO
238 SNPRINTF(version_buf,
239 "Blender %s commit date:%s, commit time:%s, hash:%s",
243 build_hash);
244#else
245 SNPRINTF(version_buf, "Blender %s", BKE_blender_version_string());
246#endif
247 asset.getContributor().mAuthoringTool = version_buf;
248 asset.add();
249
250 LinkNode *export_set = this->export_settings.get_export_set();
251 /* <library_cameras> */
252 if (bc_has_object_type(export_set, OB_CAMERA)) {
253 CamerasExporter ce(writer, this->export_settings);
254 ce.exportCameras(sce);
255 }
256
257 /* <library_lights> */
258 if (bc_has_object_type(export_set, OB_LAMP)) {
259 LightsExporter le(writer, this->export_settings);
260 le.exportLights(sce);
261 }
262
263 /* <library_effects> */
264 EffectsExporter ee(writer, this->export_settings, key_image_map);
265 ee.exportEffects(C, sce);
266
267 /* <library_images> */
268 ImagesExporter ie(writer, this->export_settings, key_image_map);
269 ie.exportImages(sce);
270
271 /* <library_materials> */
272 MaterialsExporter me(writer, this->export_settings);
273 me.exportMaterials(sce);
274
275 /* <library_geometries> */
276 if (bc_has_object_type(export_set, OB_MESH)) {
277 GeometryExporter ge(blender_context, writer, this->export_settings);
278 ge.exportGeom();
279 }
280
281 /* <library_controllers> */
282 ArmatureExporter arm_exporter(blender_context, writer, this->export_settings);
283 ControllerExporter controller_exporter(blender_context, writer, this->export_settings);
284 if (bc_has_object_type(export_set, OB_ARMATURE) || this->export_settings.get_include_shapekeys())
285 {
286 controller_exporter.export_controllers();
287 }
288
289 /* <library_visual_scenes> */
290
291 SceneExporter se(blender_context, writer, &arm_exporter, this->export_settings);
292
293 if (this->export_settings.get_include_animations()) {
294 /* <library_animations> */
295 AnimationExporter ae(writer, this->export_settings);
296 ae.exportAnimations();
297 }
298
299 se.exportScene();
300
301 /* <scene> */
302 std::string scene_name(translate_id(id_name(sce)));
303 COLLADASW::Scene scene(writer, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, scene_name));
304 scene.add();
305
306 /* close <Collada> */
307 writer->endDocument();
308 delete writer;
309
310 /* Finally move the created document into place */
311 fprintf(stdout, "Collada export to: %s\n", this->export_settings.get_filepath());
312 int status = BLI_rename_overwrite(native_filename.c_str(), this->export_settings.get_filepath());
313 if (status != 0) {
314 status = BLI_copy(native_filename.c_str(), this->export_settings.get_filepath());
315 BLI_delete(native_filename.c_str(), false, false);
316 }
317 return status;
318}
319
320/*
321 * NOTES:
322 *
323 * AnimationExporter::sample_animation enables all curves on armature, this is undesirable for a
324 * user
325 */
Blender kernel action and pose functionality.
const char * BKE_blender_version_string(void)
Definition blender.cc:139
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_layer_index(const CustomData *data, eCustomDataType type)
int CustomData_get_active_layer_index(const CustomData *data, eCustomDataType type)
General operations, lookup, etc. for materials.
General operations, lookup, etc. for blender objects.
File and directory operations.
int BLI_copy(const char *path_src, const char *path_dst) ATTR_NONNULL()
int BLI_delete(const char *path, bool dir, bool recursive) ATTR_NONNULL()
int BLI_rename_overwrite(const char *from, const char *to) ATTR_NONNULL()
Definition fileops_c.cc:505
#define FILE_MAX
#define BLI_path_join(...)
bool BLI_path_extension_ensure(char *path, size_t path_maxncpy, const char *ext) ATTR_NONNULL(1
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
Object groups, one object can be in many groups at once.
Object is a sort of wrapper for general info.
@ OB_CAMERA
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ USER_UNIT_IMPERIAL
@ USER_UNIT_METRIC
@ USER_UNIT_NONE
static COLLADABU::NativeString make_temp_filepath(const char *name, const char *extension)
const char * bc_CustomData_get_layer_name(const CustomData *data, const eCustomDataType type, int n)
const char * bc_CustomData_get_active_layer_name(const CustomData *data, const eCustomDataType type)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
char build_commit_date[]
Definition bpy_app.cc:66
char build_commit_time[]
Definition bpy_app.cc:67
void exportCameras(Scene *sce)
DocumentExporter(BlenderContext &blender_context, ExportSettings *export_settings)
void exportEffects(bContext *C, Scene *sce)
void exportImages(Scene *sce)
void exportLights(Scene *sce)
void exportMaterials(Scene *sce)
std::string translate_id(const char *idString)
void clear_global_id_map()
std::string id_name(void *id)
bool bc_has_object_type(LinkNode *export_set, short obtype)
char build_hash[16]
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
float RNA_float_get(PointerRNA *ptr, const char *name)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
PointerRNA RNA_id_pointer_create(ID *id)
void * BKE_tempdir_session
Definition stubs.c:38