Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'io_scene_gltf2/__init__.py')
-rwxr-xr-xio_scene_gltf2/__init__.py520
1 files changed, 520 insertions, 0 deletions
diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py
new file mode 100755
index 00000000..0318919a
--- /dev/null
+++ b/io_scene_gltf2/__init__.py
@@ -0,0 +1,520 @@
+# Copyright 2018 The glTF-Blender-IO authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Imports
+#
+
+import os
+import bpy
+from bpy_extras.io_utils import ImportHelper, ExportHelper
+from bpy.types import Operator, AddonPreferences
+
+from .io.com.gltf2_io_debug import Log
+
+from bpy.props import (CollectionProperty,
+ StringProperty,
+ BoolProperty,
+ EnumProperty,
+ FloatProperty,
+ IntProperty)
+
+#
+# Globals
+#
+
+bl_info = {
+ 'name': 'glTF 2.0 format',
+ 'author': 'Julien Duroure, Norbert Nopper, Urs Hanselmann Moritz Becher, Benjamin Schmithüsen',
+ "version": (0, 0, 1),
+ 'blender': (2, 80, 0),
+ 'location': 'File > Import-Export',
+ 'description': 'Import-Export as glTF 2.0',
+ 'warning': '',
+ 'wiki_url': "https://github.com/KhronosGroup/glTF-Blender-IO",
+ 'tracker_url': "https://github.com/KhronosGroup/glTF-Blender-IO/issues/",
+ 'support': 'OFFICIAL',
+ 'category': 'Import-Export'}
+
+
+#
+# Functions / Classes.
+#
+
+
+class ExportGLTF2_Base:
+
+ # TODO: refactor to avoid boilerplate
+
+ bl_options = {'UNDO', 'PRESET'}
+
+ export_format: EnumProperty(
+ name='Format',
+ items=(('GLB', 'glTF Binary (.glb)',
+ 'Exports a single file, with all data packed in binary form. '
+ 'Most efficient and portable, but more difficult to edit later'),
+ ('GLTF_EMBEDDED', 'glTF Embedded (.gltf)',
+ 'Exports a single file, with all data packed in JSON. '
+ 'Less efficient than binary, but easier to edit later'),
+ ('GLTF_SEPARATE', 'glTF Separate (.gltf + .bin + textures)',
+ 'Exports multiple files, with separate JSON, binary and texture data. '
+ 'Easiest to edit later')),
+ description=(
+ 'Output format and embedding options. Binary is most efficient, '
+ 'but JSON (embedded or separate) may be easier to edit later'
+ ),
+ default='GLB'
+ )
+
+ ui_tab: EnumProperty(
+ items=(('GENERAL', "General", "General settings"),
+ ('MESHES', "Meshes", "Mesh settings"),
+ ('OBJECTS', "Objects", "Object settings"),
+ ('MATERIALS', "Materials", "Material settings"),
+ ('ANIMATION', "Animation", "Animation settings")),
+ name="ui_tab",
+ description="Export setting categories",
+ )
+
+ export_copyright: StringProperty(
+ name='Copyright',
+ description='Legal rights and conditions for the model',
+ default=''
+ )
+
+ export_texcoords: BoolProperty(
+ name='UVs',
+ description='Export UVs (texture coordinates) with meshes',
+ default=True
+ )
+
+ export_normals: BoolProperty(
+ name='Normals',
+ description='Export vertex normals with meshes',
+ default=True
+ )
+
+ export_tangents: BoolProperty(
+ name='Tangents',
+ description='Export vertex tangents with meshes',
+ default=False
+ )
+
+ export_materials: BoolProperty(
+ name='Materials',
+ description='Export materials',
+ default=True
+ )
+
+ export_colors: BoolProperty(
+ name='Vertex Colors',
+ description='Export vertex colors with meshes',
+ default=True
+ )
+
+ export_cameras: BoolProperty(
+ name='Cameras',
+ description='Export cameras',
+ default=False
+ )
+
+ export_selected: BoolProperty(
+ name='Selected Objects',
+ description='Export selected objects only',
+ default=False
+ )
+
+ # export_layers: BoolProperty(
+ # name='All layers',
+ # description='Export all layers, rather than just the first',
+ # default=True
+ # )
+
+ export_extras: BoolProperty(
+ name='Custom Properties',
+ description='Export custom properties as glTF extras',
+ default=False
+ )
+
+ export_yup: BoolProperty(
+ name='+Y Up',
+ description='Export using glTF convention, +Y up',
+ default=True
+ )
+
+ export_apply: BoolProperty(
+ name='Apply Modifiers',
+ description='Apply modifiers to mesh objects',
+ default=False
+ )
+
+ export_animations: BoolProperty(
+ name='Animations',
+ description='Exports active actions and NLA tracks as glTF animations',
+ default=True
+ )
+
+ export_frame_range: BoolProperty(
+ name='Limit to Playback Range',
+ description='Clips animations to selected playback range',
+ default=True
+ )
+
+ export_frame_step: IntProperty(
+ name='Sampling Rate',
+ description='How often to evaluate animated values (in frames)',
+ default=1,
+ min=1,
+ max=120
+ )
+
+ export_move_keyframes: BoolProperty(
+ name='Keyframes Start at 0',
+ description='Keyframes start at 0, instead of 1',
+ default=True
+ )
+
+ export_force_sampling: BoolProperty(
+ name='Always Sample Animations',
+ description='Apply sampling to all animations',
+ default=False
+ )
+
+ export_current_frame: BoolProperty(
+ name='Use Current Frame',
+ description='Export the scene in the current animation frame',
+ default=True
+ )
+
+ export_skins: BoolProperty(
+ name='Skinning',
+ description='Export skinning (armature) data',
+ default=True
+ )
+
+ export_bake_skins: BoolProperty(
+ name='Bake Skinning Constraints',
+ description='Apply skinning constraints to armatures',
+ default=False
+ )
+
+ export_all_influences: BoolProperty(
+ name='Include All Bone Influences',
+ description='Allow >4 joint vertex influences. Models may appear incorrectly in many viewers',
+ default=False
+ )
+
+ export_morph: BoolProperty(
+ name='Shape Keys',
+ description='Export shape keys (morph targets)',
+ default=True
+ )
+
+ export_morph_normal: BoolProperty(
+ name='Shape Key Normals',
+ description='Export vertex normals with shape keys (morph targets)',
+ default=True
+ )
+
+ export_morph_tangent: BoolProperty(
+ name='Shape Key Tangents',
+ description='Export vertex tangents with shape keys (morph targets)',
+ default=False
+ )
+
+ export_lights: BoolProperty(
+ name='Punctual Lights',
+ description='Export directional, point, and spot lights. '
+ 'Uses "KHR_lights_punctual" glTF extension',
+ default=False
+ )
+
+ export_texture_transform: BoolProperty(
+ name='Texture Transforms',
+ description='Export texture or UV position, rotation, and scale. '
+ 'Uses "KHR_texture_transform" glTF extension',
+ default=False
+ )
+
+ export_displacement: BoolProperty(
+ name='Displacement Textures (EXPERIMENTAL)',
+ description='EXPERIMENTAL: Export displacement textures. '
+ 'Uses incomplete "KHR_materials_displacement" glTF extension',
+ default=False
+ )
+
+ will_save_settings: BoolProperty(default=False)
+
+ # Custom scene property for saving settings
+ scene_key = "glTF2ExportSettings"
+
+ #
+
+ def invoke(self, context, event):
+ settings = context.scene.get(self.scene_key)
+ self.will_save_settings = False
+ if settings:
+ try:
+ for (k, v) in settings.items():
+ setattr(self, k, v)
+ self.will_save_settings = True
+
+ except (AttributeError, TypeError):
+ self.report({"ERROR"}, "Loading export settings failed. Removed corrupted settings")
+ del context.scene[self.scene_key]
+
+ return ExportHelper.invoke(self, context, event)
+
+ def save_settings(self, context):
+ # find all export_ props
+ all_props = self.properties
+ export_props = {x: getattr(self, x) for x in dir(all_props)
+ if x.startswith("export_") and all_props.get(x) is not None}
+
+ context.scene[self.scene_key] = export_props
+
+ def execute(self, context):
+ import datetime
+ from .blender.exp import gltf2_blender_export
+
+ if self.will_save_settings:
+ self.save_settings(context)
+
+ if self.export_format == 'GLB':
+ self.filename_ext = '.glb'
+ else:
+ self.filename_ext = '.gltf'
+
+ # All custom export settings are stored in this container.
+ export_settings = {}
+
+ export_settings['timestamp'] = datetime.datetime.now()
+
+ export_settings['gltf_filepath'] = bpy.path.ensure_ext(self.filepath, self.filename_ext)
+ export_settings['gltf_filedirectory'] = os.path.dirname(export_settings['gltf_filepath']) + '/'
+
+ export_settings['gltf_format'] = self.export_format
+ export_settings['gltf_copyright'] = self.export_copyright
+ export_settings['gltf_texcoords'] = self.export_texcoords
+ export_settings['gltf_normals'] = self.export_normals
+ export_settings['gltf_tangents'] = self.export_tangents and self.export_normals
+ export_settings['gltf_materials'] = self.export_materials
+ export_settings['gltf_colors'] = self.export_colors
+ export_settings['gltf_cameras'] = self.export_cameras
+ export_settings['gltf_selected'] = self.export_selected
+ export_settings['gltf_layers'] = True #self.export_layers
+ export_settings['gltf_extras'] = self.export_extras
+ export_settings['gltf_yup'] = self.export_yup
+ export_settings['gltf_apply'] = self.export_apply
+ export_settings['gltf_animations'] = self.export_animations
+ if self.export_animations:
+ export_settings['gltf_current_frame'] = False
+ export_settings['gltf_frame_range'] = self.export_frame_range
+ export_settings['gltf_move_keyframes'] = self.export_move_keyframes
+ export_settings['gltf_force_sampling'] = self.export_force_sampling
+ else:
+ export_settings['gltf_current_frame'] = self.export_current_frame
+ export_settings['gltf_frame_range'] = False
+ export_settings['gltf_move_keyframes'] = False
+ export_settings['gltf_force_sampling'] = False
+ export_settings['gltf_skins'] = self.export_skins
+ if self.export_skins:
+ export_settings['gltf_bake_skins'] = self.export_bake_skins
+ export_settings['gltf_all_vertex_influences'] = self.export_all_influences
+ else:
+ export_settings['gltf_bake_skins'] = False
+ export_settings['gltf_all_vertex_influences'] = False
+ export_settings['gltf_frame_step'] = self.export_frame_step
+ export_settings['gltf_morph'] = self.export_morph
+ if self.export_morph:
+ export_settings['gltf_morph_normal'] = self.export_morph_normal
+ else:
+ export_settings['gltf_morph_normal'] = False
+ if self.export_morph and self.export_morph_normal:
+ export_settings['gltf_morph_tangent'] = self.export_morph_tangent
+ else:
+ export_settings['gltf_morph_tangent'] = False
+
+ export_settings['gltf_lights'] = self.export_lights
+ export_settings['gltf_texture_transform'] = self.export_texture_transform
+ export_settings['gltf_displacement'] = self.export_displacement
+
+ export_settings['gltf_binary'] = bytearray()
+ export_settings['gltf_binaryfilename'] = os.path.splitext(os.path.basename(self.filepath))[0] + '.bin'
+
+ return gltf2_blender_export.save(context, export_settings)
+
+ def draw(self, context):
+ self.layout.prop(self, 'ui_tab', expand=True)
+ if self.ui_tab == 'GENERAL':
+ self.draw_general_settings()
+ elif self.ui_tab == 'MESHES':
+ self.draw_mesh_settings()
+ elif self.ui_tab == 'OBJECTS':
+ self.draw_object_settings()
+ elif self.ui_tab == 'MATERIALS':
+ self.draw_material_settings()
+ elif self.ui_tab == 'ANIMATION':
+ self.draw_animation_settings()
+
+ def draw_general_settings(self):
+ col = self.layout.box().column()
+ col.prop(self, 'export_format')
+ col.prop(self, 'export_selected')
+ col.prop(self, 'export_apply')
+ col.prop(self, 'export_yup')
+ col.prop(self, 'export_extras')
+ col.prop(self, 'export_copyright')
+
+ def draw_mesh_settings(self):
+ col = self.layout.box().column()
+ col.prop(self, 'export_texcoords')
+ col.prop(self, 'export_normals')
+ if self.export_normals:
+ col.prop(self, 'export_tangents')
+ col.prop(self, 'export_colors')
+
+ def draw_object_settings(self):
+ col = self.layout.box().column()
+ col.prop(self, 'export_cameras')
+ col.prop(self, 'export_lights')
+
+ def draw_material_settings(self):
+ col = self.layout.box().column()
+ col.prop(self, 'export_materials')
+ col.prop(self, 'export_texture_transform')
+
+ def draw_animation_settings(self):
+ col = self.layout.box().column()
+ col.prop(self, 'export_animations')
+ if self.export_animations:
+ col.prop(self, 'export_frame_range')
+ col.prop(self, 'export_frame_step')
+ col.prop(self, 'export_move_keyframes')
+ col.prop(self, 'export_force_sampling')
+ else:
+ col.prop(self, 'export_current_frame')
+ col.prop(self, 'export_skins')
+ if self.export_skins:
+ col.prop(self, 'export_bake_skins')
+ col.prop(self, 'export_all_influences')
+ col.prop(self, 'export_morph')
+ if self.export_morph:
+ col.prop(self, 'export_morph_normal')
+ if self.export_morph_normal:
+ col.prop(self, 'export_morph_tangent')
+
+
+class ExportGLTF2(bpy.types.Operator, ExportGLTF2_Base, ExportHelper):
+ """Export scene as glTF 2.0 file"""
+ bl_idname = 'export_scene.gltf'
+ bl_label = 'glTF 2.0 (.glb/.gltf)'
+
+ filename_ext = ''
+
+ filter_glob: StringProperty(default='*.glb;*.gltf', options={'HIDDEN'})
+
+
+def menu_func_export(self, context):
+ self.layout.operator(ExportGLTF2.bl_idname, text='glTF 2.0 (.glb/.gltf)')
+
+
+class ImportGLTF2(Operator, ImportHelper):
+ bl_idname = 'import_scene.gltf'
+ bl_label = 'glTF 2.0 (.glb/.gltf)'
+
+ filter_glob: StringProperty(default="*.glb;*.gltf", options={'HIDDEN'})
+
+ loglevel: EnumProperty(
+ items=Log.get_levels(),
+ name="Log Level",
+ description="Set level of log to display",
+ default=Log.default())
+
+ import_pack_images: BoolProperty(
+ name='Pack images',
+ description='Pack all images into .blend file',
+ default=True
+ )
+
+ import_shading: EnumProperty(
+ name="Shading",
+ items=(("NORMALS", "Use Normal Data", ""),
+ ("FLAT", "Flat Shading", ""),
+ ("SMOOTH", "Smooth Shading", "")),
+ description="How normals are computed during import",
+ default="NORMALS")
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.prop(self, 'loglevel')
+ layout.prop(self, 'import_pack_images')
+ layout.prop(self, 'import_shading')
+
+ def execute(self, context):
+ return self.import_gltf2(context)
+
+ def import_gltf2(self, context):
+ from .io.imp.gltf2_io_gltf import glTFImporter
+ from .blender.imp.gltf2_blender_gltf import BlenderGlTF
+
+ import_settings = self.as_keywords()
+
+ self.gltf_importer = glTFImporter(self.filepath, import_settings)
+ success, txt = self.gltf_importer.read()
+ if not success:
+ self.report({'ERROR'}, txt)
+ return {'CANCELLED'}
+ success, txt = self.gltf_importer.checks()
+ if not success:
+ self.report({'ERROR'}, txt)
+ return {'CANCELLED'}
+ self.gltf_importer.log.critical("Data are loaded, start creating Blender stuff")
+ BlenderGlTF.create(self.gltf_importer)
+ self.gltf_importer.log.critical("glTF import is now finished")
+ self.gltf_importer.log.removeHandler(self.gltf_importer.log_handler)
+
+ return {'FINISHED'}
+
+
+def menu_func_import(self, context):
+ self.layout.operator(ImportGLTF2.bl_idname, text=ImportGLTF2.bl_label)
+
+
+classes = (
+ ExportGLTF2,
+ ImportGLTF2
+)
+
+
+def register():
+ for c in classes:
+ bpy.utils.register_class(c)
+ # bpy.utils.register_module(__name__)
+
+ # add to the export / import menu
+ bpy.types.TOPBAR_MT_file_export.append(menu_func_export)
+ bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
+
+
+def unregister():
+ for c in classes:
+ bpy.utils.unregister_class(c)
+ # bpy.utils.unregister_module(__name__)
+
+ # remove from the export / import menu
+ bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
+ bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
+