mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-09-19 18:20:06 +02:00
905 lines
26 KiB
Python
905 lines
26 KiB
Python
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||
|
#
|
||
|
# This program is free software; you can redistribute it and/or
|
||
|
# modify it under the terms of the GNU General Public License
|
||
|
# as published by the Free Software Foundation; either version 2
|
||
|
# of the License, or (at your option) any later version.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU General Public License for more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU General Public License
|
||
|
# along with this program; if not, write to the Free Software Foundation,
|
||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
#
|
||
|
# ##### END GPL LICENSE BLOCK #####
|
||
|
|
||
|
import os
|
||
|
import json
|
||
|
import logging
|
||
|
|
||
|
import bpy
|
||
|
from bpy_extras.io_utils import ExportHelper
|
||
|
from bpy.props import (
|
||
|
EnumProperty,
|
||
|
BoolProperty,
|
||
|
FloatProperty,
|
||
|
IntProperty,
|
||
|
StringProperty
|
||
|
)
|
||
|
|
||
|
from . import constants
|
||
|
|
||
|
logging.basicConfig(
|
||
|
format='%(levelname)s:THREE:%(message)s',
|
||
|
level=logging.DEBUG)
|
||
|
|
||
|
bl_info = {
|
||
|
'name': "Three.js Format",
|
||
|
'author': "repsac, mrdoob, yomotsu, mpk, jpweeks, rkusa",
|
||
|
'version': (1, 4, 0),
|
||
|
'blender': (2, 7, 3),
|
||
|
'location': "File > Export",
|
||
|
'description': "Export Three.js formatted JSON files.",
|
||
|
'warning': "Importer not included.",
|
||
|
'wiki_url': "https://github.com/mrdoob/three.js/tree/"\
|
||
|
"master/utils/exporters/blender",
|
||
|
'tracker_url': "https://github.com/mrdoob/three.js/issues",
|
||
|
'category': 'Import-Export'
|
||
|
}
|
||
|
|
||
|
|
||
|
def _geometry_types():
|
||
|
"""The valid geometry types that are supported by Three.js
|
||
|
|
||
|
:return: list of tuples
|
||
|
|
||
|
"""
|
||
|
keys = (constants.GLOBAL,
|
||
|
constants.GEOMETRY,
|
||
|
constants.BUFFER_GEOMETRY)
|
||
|
types = []
|
||
|
for key in keys:
|
||
|
types.append((key, key.title(), key))
|
||
|
|
||
|
return types
|
||
|
|
||
|
bpy.types.Mesh.THREE_geometry_type = EnumProperty(
|
||
|
name="Geometry type",
|
||
|
description="Geometry type",
|
||
|
items=_geometry_types(),
|
||
|
default=constants.GLOBAL)
|
||
|
|
||
|
class ThreeMesh(bpy.types.Panel):
|
||
|
"""Creates custom properties on a mesh node"""
|
||
|
|
||
|
bl_label = 'THREE'
|
||
|
bl_space_type = 'PROPERTIES'
|
||
|
bl_region_type = 'WINDOW'
|
||
|
bl_context = 'data'
|
||
|
|
||
|
def draw(self, context):
|
||
|
"""
|
||
|
|
||
|
:param context:
|
||
|
|
||
|
"""
|
||
|
row = self.layout.row()
|
||
|
if context.mesh:
|
||
|
row.prop(context.mesh,
|
||
|
'THREE_geometry_type',
|
||
|
text="Type")
|
||
|
|
||
|
def _blending_types(index):
|
||
|
"""Supported blending types for Three.js
|
||
|
|
||
|
:param index:
|
||
|
:type index: int
|
||
|
:returns: tuple if types (str, str, str)
|
||
|
|
||
|
"""
|
||
|
types = (constants.BLENDING_TYPES.NONE,
|
||
|
constants.BLENDING_TYPES.NORMAL,
|
||
|
constants.BLENDING_TYPES.ADDITIVE,
|
||
|
constants.BLENDING_TYPES.SUBTRACTIVE,
|
||
|
constants.BLENDING_TYPES.MULTIPLY,
|
||
|
constants.BLENDING_TYPES.CUSTOM)
|
||
|
return (types[index], types[index], types[index])
|
||
|
|
||
|
bpy.types.Material.THREE_blending_type = EnumProperty(
|
||
|
name="Blending type",
|
||
|
description="Blending type",
|
||
|
items=[_blending_types(x) for x in range(5)],
|
||
|
default=constants.BLENDING_TYPES.NORMAL)
|
||
|
|
||
|
bpy.types.Material.THREE_depth_write = BoolProperty(default=True)
|
||
|
bpy.types.Material.THREE_depth_test = BoolProperty(default=True)
|
||
|
|
||
|
class ThreeMaterial(bpy.types.Panel):
|
||
|
"""Adds custom properties to the Materials of an object"""
|
||
|
|
||
|
bl_label = 'THREE'
|
||
|
bl_space_type = 'PROPERTIES'
|
||
|
bl_region_type = 'WINDOW'
|
||
|
bl_context = 'material'
|
||
|
|
||
|
def draw(self, context):
|
||
|
"""
|
||
|
|
||
|
:param context:
|
||
|
|
||
|
"""
|
||
|
layout = self.layout
|
||
|
mat = context.material
|
||
|
|
||
|
if mat is not None:
|
||
|
row = layout.row()
|
||
|
row.label(text="Selected material: %s" % mat.name)
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(mat, 'THREE_blending_type',
|
||
|
text="Blending type")
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(mat, 'THREE_depth_write',
|
||
|
text="Enable depth writing")
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(mat, 'THREE_depth_test',
|
||
|
text="Enable depth testing")
|
||
|
|
||
|
def _mag_filters(index):
|
||
|
"""Three.js mag filters
|
||
|
|
||
|
:param index:
|
||
|
:type index: int
|
||
|
:returns: tuple with the filter values
|
||
|
|
||
|
"""
|
||
|
types = (constants.LINEAR_FILTERS.LINEAR,
|
||
|
constants.NEAREST_FILTERS.NEAREST)
|
||
|
return (types[index], types[index], types[index])
|
||
|
|
||
|
bpy.types.Texture.THREE_mag_filter = EnumProperty(
|
||
|
name="Mag Filter",
|
||
|
items=[_mag_filters(x) for x in range(2)],
|
||
|
default=constants.LINEAR_FILTERS.LINEAR)
|
||
|
|
||
|
def _min_filters(index):
|
||
|
"""Three.js min filters
|
||
|
|
||
|
:param index:
|
||
|
:type index: int
|
||
|
:returns: tuple with the filter values
|
||
|
|
||
|
"""
|
||
|
types = (constants.LINEAR_FILTERS.LINEAR,
|
||
|
constants.LINEAR_FILTERS.MIP_MAP_NEAREST,
|
||
|
constants.LINEAR_FILTERS.MIP_MAP_LINEAR,
|
||
|
constants.NEAREST_FILTERS.NEAREST,
|
||
|
constants.NEAREST_FILTERS.MIP_MAP_NEAREST,
|
||
|
constants.NEAREST_FILTERS.MIP_MAP_LINEAR)
|
||
|
return (types[index], types[index], types[index])
|
||
|
|
||
|
bpy.types.Texture.THREE_min_filter = EnumProperty(
|
||
|
name="Min Filter",
|
||
|
items=[_min_filters(x) for x in range(6)],
|
||
|
default=constants.LINEAR_FILTERS.MIP_MAP_LINEAR)
|
||
|
|
||
|
def _mapping(index):
|
||
|
"""Three.js texture mappings types
|
||
|
|
||
|
:param index:
|
||
|
:type index: int
|
||
|
:returns: tuple with the mapping values
|
||
|
|
||
|
"""
|
||
|
types = (constants.MAPPING_TYPES.UV,
|
||
|
constants.MAPPING_TYPES.CUBE_REFLECTION,
|
||
|
constants.MAPPING_TYPES.CUBE_REFRACTION,
|
||
|
constants.MAPPING_TYPES.SPHERICAL_REFLECTION)
|
||
|
return (types[index], types[index], types[index])
|
||
|
|
||
|
bpy.types.Texture.THREE_mapping = EnumProperty(
|
||
|
name="Mapping",
|
||
|
items=[_mapping(x) for x in range(4)],
|
||
|
default=constants.MAPPING_TYPES.UV)
|
||
|
|
||
|
class ThreeTexture(bpy.types.Panel):
|
||
|
"""Adds custom properties to a texture"""
|
||
|
bl_label = 'THREE'
|
||
|
bl_space_type = 'PROPERTIES'
|
||
|
bl_region_type = 'WINDOW'
|
||
|
bl_context = 'texture'
|
||
|
|
||
|
#@TODO: possible to make cycles compatible?
|
||
|
def draw(self, context):
|
||
|
"""
|
||
|
|
||
|
:param context:
|
||
|
|
||
|
"""
|
||
|
layout = self.layout
|
||
|
tex = context.texture
|
||
|
|
||
|
if tex is not None:
|
||
|
row = layout.row()
|
||
|
row.prop(tex, 'THREE_mapping', text="Mapping")
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(tex, 'THREE_mag_filter', text="Mag Filter")
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(tex, 'THREE_min_filter', text="Min Filter")
|
||
|
|
||
|
bpy.types.Object.THREE_export = bpy.props.BoolProperty(default=True)
|
||
|
|
||
|
class ThreeObject(bpy.types.Panel):
|
||
|
"""Adds custom properties to an object"""
|
||
|
bl_label = 'THREE'
|
||
|
bl_space_type = 'PROPERTIES'
|
||
|
bl_region_type = 'WINDOW'
|
||
|
bl_context = 'object'
|
||
|
|
||
|
def draw(self, context):
|
||
|
"""
|
||
|
|
||
|
:param context:
|
||
|
|
||
|
"""
|
||
|
layout = self.layout
|
||
|
obj = context.object
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(obj, 'THREE_export', text='Export')
|
||
|
|
||
|
class ThreeExportSettings(bpy.types.Operator):
|
||
|
"""Save the current export settings (gets saved in .blend)"""
|
||
|
bl_label = "Save Settings"
|
||
|
bl_idname = "scene.three_export_settings_set"
|
||
|
|
||
|
def execute(self, context):
|
||
|
cycles = context.scene.cycles
|
||
|
cycles.use_samples_final = True
|
||
|
|
||
|
context.scene[constants.EXPORT_SETTINGS_KEY] = set_settings(context.active_operator.properties)
|
||
|
|
||
|
self.report({"INFO"}, "Three Export Settings Saved")
|
||
|
|
||
|
return {"FINISHED"}
|
||
|
|
||
|
def restore_export_settings(properties, settings):
|
||
|
"""Restore the settings
|
||
|
|
||
|
:param properties:
|
||
|
|
||
|
"""
|
||
|
|
||
|
## Geometry {
|
||
|
properties.option_vertices = settings.get(
|
||
|
constants.VERTICES,
|
||
|
constants.EXPORT_OPTIONS[constants.VERTICES])
|
||
|
|
||
|
properties.option_faces = settings.get(
|
||
|
constants.FACES,
|
||
|
constants.EXPORT_OPTIONS[constants.FACES])
|
||
|
properties.option_normals = settings.get(
|
||
|
constants.NORMALS,
|
||
|
constants.EXPORT_OPTIONS[constants.NORMALS])
|
||
|
|
||
|
properties.option_skinning = settings.get(
|
||
|
constants.SKINNING,
|
||
|
constants.EXPORT_OPTIONS[constants.SKINNING])
|
||
|
|
||
|
properties.option_bones = settings.get(
|
||
|
constants.BONES,
|
||
|
constants.EXPORT_OPTIONS[constants.BONES])
|
||
|
|
||
|
properties.option_influences = settings.get(
|
||
|
constants.INFLUENCES_PER_VERTEX,
|
||
|
constants.EXPORT_OPTIONS[constants.INFLUENCES_PER_VERTEX])
|
||
|
|
||
|
properties.option_geometry_type = settings.get(
|
||
|
constants.GEOMETRY_TYPE,
|
||
|
constants.EXPORT_OPTIONS[constants.GEOMETRY_TYPE])
|
||
|
## }
|
||
|
|
||
|
## Materials {
|
||
|
properties.option_materials = settings.get(
|
||
|
constants.MATERIALS,
|
||
|
constants.EXPORT_OPTIONS[constants.MATERIALS])
|
||
|
|
||
|
properties.option_uv_coords = settings.get(
|
||
|
constants.UVS,
|
||
|
constants.EXPORT_OPTIONS[constants.UVS])
|
||
|
|
||
|
properties.option_face_materials = settings.get(
|
||
|
constants.FACE_MATERIALS,
|
||
|
constants.EXPORT_OPTIONS[constants.FACE_MATERIALS])
|
||
|
|
||
|
properties.option_maps = settings.get(
|
||
|
constants.MAPS,
|
||
|
constants.EXPORT_OPTIONS[constants.MAPS])
|
||
|
|
||
|
properties.option_colors = settings.get(
|
||
|
constants.COLORS,
|
||
|
constants.EXPORT_OPTIONS[constants.COLORS])
|
||
|
|
||
|
properties.option_mix_colors = settings.get(
|
||
|
constants.MIX_COLORS,
|
||
|
constants.EXPORT_OPTIONS[constants.MIX_COLORS])
|
||
|
## }
|
||
|
|
||
|
## Settings {
|
||
|
properties.option_scale = settings.get(
|
||
|
constants.SCALE,
|
||
|
constants.EXPORT_OPTIONS[constants.SCALE])
|
||
|
|
||
|
properties.option_round_off = settings.get(
|
||
|
constants.ENABLE_PRECISION,
|
||
|
constants.EXPORT_OPTIONS[constants.ENABLE_PRECISION])
|
||
|
|
||
|
properties.option_round_value = settings.get(
|
||
|
constants.PRECISION,
|
||
|
constants.EXPORT_OPTIONS[constants.PRECISION])
|
||
|
|
||
|
properties.option_logging = settings.get(
|
||
|
constants.LOGGING,
|
||
|
constants.EXPORT_OPTIONS[constants.LOGGING])
|
||
|
|
||
|
properties.option_compression = settings.get(
|
||
|
constants.COMPRESSION,
|
||
|
constants.NONE)
|
||
|
|
||
|
properties.option_indent = settings.get(
|
||
|
constants.INDENT,
|
||
|
constants.EXPORT_OPTIONS[constants.INDENT])
|
||
|
|
||
|
properties.option_copy_textures = settings.get(
|
||
|
constants.COPY_TEXTURES,
|
||
|
constants.EXPORT_OPTIONS[constants.COPY_TEXTURES])
|
||
|
|
||
|
properties.option_texture_folder = settings.get(
|
||
|
constants.TEXTURE_FOLDER,
|
||
|
constants.EXPORT_OPTIONS[constants.TEXTURE_FOLDER])
|
||
|
|
||
|
properties.option_embed_animation = settings.get(
|
||
|
constants.EMBED_ANIMATION,
|
||
|
constants.EXPORT_OPTIONS[constants.EMBED_ANIMATION])
|
||
|
## }
|
||
|
|
||
|
## Scene {
|
||
|
properties.option_export_scene = settings.get(
|
||
|
constants.SCENE,
|
||
|
constants.EXPORT_OPTIONS[constants.SCENE])
|
||
|
|
||
|
#properties.option_embed_geometry = settings.get(
|
||
|
# constants.EMBED_GEOMETRY,
|
||
|
# constants.EXPORT_OPTIONS[constants.EMBED_GEOMETRY])
|
||
|
|
||
|
properties.option_lights = settings.get(
|
||
|
constants.LIGHTS,
|
||
|
constants.EXPORT_OPTIONS[constants.LIGHTS])
|
||
|
|
||
|
properties.option_cameras = settings.get(
|
||
|
constants.CAMERAS,
|
||
|
constants.EXPORT_OPTIONS[constants.CAMERAS])
|
||
|
|
||
|
properties.option_hierarchy = settings.get(
|
||
|
constants.HIERARCHY,
|
||
|
constants.EXPORT_OPTIONS[constants.HIERARCHY])
|
||
|
## }
|
||
|
|
||
|
## Animation {
|
||
|
properties.option_animation_morph = settings.get(
|
||
|
constants.MORPH_TARGETS,
|
||
|
constants.EXPORT_OPTIONS[constants.MORPH_TARGETS])
|
||
|
|
||
|
properties.option_animation_skeletal = settings.get(
|
||
|
constants.ANIMATION,
|
||
|
constants.EXPORT_OPTIONS[constants.ANIMATION])
|
||
|
|
||
|
properties.option_frame_step = settings.get(
|
||
|
constants.FRAME_STEP,
|
||
|
constants.EXPORT_OPTIONS[constants.FRAME_STEP])
|
||
|
|
||
|
properties.option_frame_index_as_time = settings.get(
|
||
|
constants.FRAME_INDEX_AS_TIME,
|
||
|
constants.EXPORT_OPTIONS[constants.FRAME_INDEX_AS_TIME])
|
||
|
## }
|
||
|
|
||
|
def set_settings(properties):
|
||
|
"""Set the export settings to the correct keys.
|
||
|
|
||
|
:param properties:
|
||
|
:returns: settings
|
||
|
:rtype: dict
|
||
|
|
||
|
"""
|
||
|
settings = {
|
||
|
constants.VERTICES: properties.option_vertices,
|
||
|
constants.FACES: properties.option_faces,
|
||
|
constants.NORMALS: properties.option_normals,
|
||
|
constants.SKINNING: properties.option_skinning,
|
||
|
constants.BONES: properties.option_bones,
|
||
|
constants.GEOMETRY_TYPE: properties.option_geometry_type,
|
||
|
|
||
|
constants.MATERIALS: properties.option_materials,
|
||
|
constants.UVS: properties.option_uv_coords,
|
||
|
constants.FACE_MATERIALS: properties.option_face_materials,
|
||
|
constants.MAPS: properties.option_maps,
|
||
|
constants.COLORS: properties.option_colors,
|
||
|
constants.MIX_COLORS: properties.option_mix_colors,
|
||
|
|
||
|
constants.SCALE: properties.option_scale,
|
||
|
constants.ENABLE_PRECISION: properties.option_round_off,
|
||
|
constants.PRECISION: properties.option_round_value,
|
||
|
constants.LOGGING: properties.option_logging,
|
||
|
constants.COMPRESSION: properties.option_compression,
|
||
|
constants.INDENT: properties.option_indent,
|
||
|
constants.COPY_TEXTURES: properties.option_copy_textures,
|
||
|
constants.TEXTURE_FOLDER: properties.option_texture_folder,
|
||
|
|
||
|
constants.SCENE: properties.option_export_scene,
|
||
|
#constants.EMBED_GEOMETRY: properties.option_embed_geometry,
|
||
|
constants.EMBED_ANIMATION: properties.option_embed_animation,
|
||
|
constants.LIGHTS: properties.option_lights,
|
||
|
constants.CAMERAS: properties.option_cameras,
|
||
|
constants.HIERARCHY: properties.option_hierarchy,
|
||
|
|
||
|
constants.MORPH_TARGETS: properties.option_animation_morph,
|
||
|
constants.ANIMATION: properties.option_animation_skeletal,
|
||
|
constants.FRAME_STEP: properties.option_frame_step,
|
||
|
constants.FRAME_INDEX_AS_TIME: properties.option_frame_index_as_time,
|
||
|
constants.INFLUENCES_PER_VERTEX: properties.option_influences
|
||
|
}
|
||
|
|
||
|
return settings
|
||
|
|
||
|
|
||
|
def compression_types():
|
||
|
"""Supported compression formats
|
||
|
|
||
|
:rtype: tuple
|
||
|
|
||
|
"""
|
||
|
types = [(constants.NONE, constants.NONE, constants.NONE)]
|
||
|
|
||
|
try:
|
||
|
import msgpack
|
||
|
types.append((constants.MSGPACK, constants.MSGPACK,
|
||
|
constants.MSGPACK))
|
||
|
except ImportError:
|
||
|
pass
|
||
|
|
||
|
return types
|
||
|
|
||
|
|
||
|
def animation_options():
|
||
|
"""The supported skeletal animation types
|
||
|
|
||
|
:returns: list of tuples
|
||
|
|
||
|
"""
|
||
|
anim = [
|
||
|
(constants.OFF, constants.OFF.title(), constants.OFF),
|
||
|
(constants.POSE, constants.POSE.title(), constants.POSE),
|
||
|
(constants.REST, constants.REST.title(), constants.REST)
|
||
|
]
|
||
|
|
||
|
return anim
|
||
|
|
||
|
class ExportThree(bpy.types.Operator, ExportHelper):
|
||
|
"""Class that handles the export properties"""
|
||
|
|
||
|
bl_idname = 'export.three'
|
||
|
bl_label = 'Export THREE'
|
||
|
bl_options = {'PRESET'}
|
||
|
|
||
|
filename_ext = constants.EXTENSION
|
||
|
|
||
|
option_vertices = BoolProperty(
|
||
|
name="Vertices",
|
||
|
description="Export vertices",
|
||
|
default=constants.EXPORT_OPTIONS[constants.VERTICES])
|
||
|
|
||
|
option_faces = BoolProperty(
|
||
|
name="Faces",
|
||
|
description="Export faces",
|
||
|
default=constants.EXPORT_OPTIONS[constants.FACES])
|
||
|
|
||
|
option_normals = BoolProperty(
|
||
|
name="Normals",
|
||
|
description="Export normals",
|
||
|
default=constants.EXPORT_OPTIONS[constants.NORMALS])
|
||
|
|
||
|
option_colors = BoolProperty(
|
||
|
name="Vertex Colors",
|
||
|
description="Export vertex colors",
|
||
|
default=constants.EXPORT_OPTIONS[constants.COLORS])
|
||
|
|
||
|
option_mix_colors = BoolProperty(
|
||
|
name="Mix Colors",
|
||
|
description="Mix material and vertex colors",
|
||
|
default=constants.EXPORT_OPTIONS[constants.MIX_COLORS])
|
||
|
|
||
|
option_uv_coords = BoolProperty(
|
||
|
name="UVs",
|
||
|
description="Export texture coordinates",
|
||
|
default=constants.EXPORT_OPTIONS[constants.UVS])
|
||
|
|
||
|
option_materials = BoolProperty(
|
||
|
name="Materials",
|
||
|
description="Export materials",
|
||
|
default=constants.EXPORT_OPTIONS[constants.MATERIALS])
|
||
|
|
||
|
option_face_materials = BoolProperty(
|
||
|
name="Face Materials",
|
||
|
description="Face mapping materials",
|
||
|
default=constants.EXPORT_OPTIONS[constants.FACE_MATERIALS])
|
||
|
|
||
|
option_maps = BoolProperty(
|
||
|
name="Textures",
|
||
|
description="Include texture maps",
|
||
|
default=constants.EXPORT_OPTIONS[constants.MAPS])
|
||
|
|
||
|
option_skinning = BoolProperty(
|
||
|
name="Skinning",
|
||
|
description="Export skin data",
|
||
|
default=constants.EXPORT_OPTIONS[constants.SKINNING])
|
||
|
|
||
|
option_bones = BoolProperty(
|
||
|
name="Bones",
|
||
|
description="Export bones",
|
||
|
default=constants.EXPORT_OPTIONS[constants.BONES])
|
||
|
|
||
|
option_scale = FloatProperty(
|
||
|
name="Scale",
|
||
|
description="Scale vertices",
|
||
|
min=0.01,
|
||
|
max=1000.0,
|
||
|
soft_min=0.01,
|
||
|
soft_max=1000.0,
|
||
|
default=constants.EXPORT_OPTIONS[constants.SCALE])
|
||
|
|
||
|
option_round_off = BoolProperty(
|
||
|
name="Enable Precision",
|
||
|
description="Round off floating point values",
|
||
|
default=constants.EXPORT_OPTIONS[constants.ENABLE_PRECISION])
|
||
|
|
||
|
option_round_value = IntProperty(
|
||
|
name="Precision",
|
||
|
min=0,
|
||
|
max=16,
|
||
|
description="Floating point precision",
|
||
|
default=constants.EXPORT_OPTIONS[constants.PRECISION])
|
||
|
|
||
|
logging_types = [
|
||
|
(constants.DEBUG, constants.DEBUG, constants.DEBUG),
|
||
|
(constants.INFO, constants.INFO, constants.INFO),
|
||
|
(constants.WARNING, constants.WARNING, constants.WARNING),
|
||
|
(constants.ERROR, constants.ERROR, constants.ERROR),
|
||
|
(constants.CRITICAL, constants.CRITICAL, constants.CRITICAL)]
|
||
|
|
||
|
option_logging = EnumProperty(
|
||
|
name="",
|
||
|
description="Logging verbosity level",
|
||
|
items=logging_types,
|
||
|
default=constants.DEBUG)
|
||
|
|
||
|
option_geometry_type = EnumProperty(
|
||
|
name="Type",
|
||
|
description="Geometry type",
|
||
|
items=_geometry_types()[1:],
|
||
|
default=constants.GEOMETRY)
|
||
|
|
||
|
option_export_scene = BoolProperty(
|
||
|
name="Scene",
|
||
|
description="Export scene",
|
||
|
default=constants.EXPORT_OPTIONS[constants.SCENE])
|
||
|
|
||
|
#@TODO: removing this option since the ObjectLoader doesn't have
|
||
|
# support for handling external geometry data
|
||
|
#option_embed_geometry = BoolProperty(
|
||
|
# name="Embed geometry",
|
||
|
# description="Embed geometry",
|
||
|
# default=constants.EXPORT_OPTIONS[constants.EMBED_GEOMETRY])
|
||
|
|
||
|
option_embed_animation = BoolProperty(
|
||
|
name="Embed animation",
|
||
|
description="Embed animation data with the geometry data",
|
||
|
default=constants.EXPORT_OPTIONS[constants.EMBED_ANIMATION])
|
||
|
|
||
|
option_copy_textures = BoolProperty(
|
||
|
name="Copy textures",
|
||
|
description="Copy textures",
|
||
|
default=constants.EXPORT_OPTIONS[constants.COPY_TEXTURES])
|
||
|
|
||
|
option_texture_folder = StringProperty(
|
||
|
name="Texture folder",
|
||
|
description="add this folder to textures path",
|
||
|
default=constants.EXPORT_OPTIONS[constants.TEXTURE_FOLDER])
|
||
|
|
||
|
option_lights = BoolProperty(
|
||
|
name="Lights",
|
||
|
description="Export default scene lights",
|
||
|
default=False)
|
||
|
|
||
|
option_cameras = BoolProperty(
|
||
|
name="Cameras",
|
||
|
description="Export default scene cameras",
|
||
|
default=False)
|
||
|
|
||
|
option_hierarchy = BoolProperty(
|
||
|
name="Hierarchy",
|
||
|
description="Export object hierarchy",
|
||
|
default=False)
|
||
|
|
||
|
option_animation_morph = BoolProperty(
|
||
|
name="Morph animation",
|
||
|
description="Export animation (morphs)",
|
||
|
default=constants.EXPORT_OPTIONS[constants.MORPH_TARGETS])
|
||
|
|
||
|
option_animation_skeletal = EnumProperty(
|
||
|
name="",
|
||
|
description="Export animation (skeletal)",
|
||
|
items=animation_options(),
|
||
|
default=constants.OFF)
|
||
|
|
||
|
option_frame_index_as_time = BoolProperty(
|
||
|
name="Frame index as time",
|
||
|
description="Use (original) frame index as frame time",
|
||
|
default=constants.EXPORT_OPTIONS[constants.FRAME_INDEX_AS_TIME])
|
||
|
|
||
|
option_frame_step = IntProperty(
|
||
|
name="Frame step",
|
||
|
description="Animation frame step",
|
||
|
min=1,
|
||
|
max=1000,
|
||
|
soft_min=1,
|
||
|
soft_max=1000,
|
||
|
default=1)
|
||
|
|
||
|
option_indent = BoolProperty(
|
||
|
name="Indent JSON",
|
||
|
description="Disable this to reduce the file size",
|
||
|
default=constants.EXPORT_OPTIONS[constants.INDENT])
|
||
|
|
||
|
option_compression = EnumProperty(
|
||
|
name="",
|
||
|
description="Compression options",
|
||
|
items=compression_types(),
|
||
|
default=constants.NONE)
|
||
|
|
||
|
option_influences = IntProperty(
|
||
|
name="Influences",
|
||
|
description="Maximum number of bone influences",
|
||
|
min=1,
|
||
|
max=4,
|
||
|
default=2)
|
||
|
|
||
|
def invoke(self, context, event):
|
||
|
settings = context.scene.get(constants.EXPORT_SETTINGS_KEY)
|
||
|
if settings:
|
||
|
try:
|
||
|
restore_export_settings(self.properties, settings)
|
||
|
except AttributeError as e:
|
||
|
logging.error("Loading export settings failed:")
|
||
|
logging.exception(e)
|
||
|
logging.debug("Removed corrupted settings")
|
||
|
|
||
|
del context.scene[constants.EXPORT_SETTINGS_KEY]
|
||
|
|
||
|
return ExportHelper.invoke(self, context, event)
|
||
|
|
||
|
@classmethod
|
||
|
def poll(cls, context):
|
||
|
"""
|
||
|
|
||
|
:param context:
|
||
|
|
||
|
"""
|
||
|
return context.active_object is not None
|
||
|
|
||
|
def execute(self, context):
|
||
|
"""
|
||
|
|
||
|
:param context:
|
||
|
|
||
|
"""
|
||
|
if not self.properties.filepath:
|
||
|
raise Exception("filename not set")
|
||
|
|
||
|
settings = set_settings(self.properties)
|
||
|
settings['addon_version'] = bl_info['version']
|
||
|
|
||
|
filepath = self.filepath
|
||
|
if settings[constants.COMPRESSION] == constants.MSGPACK:
|
||
|
filepath = "%s%s" % (filepath[:-4], constants.PACK)
|
||
|
|
||
|
from io_three import exporter
|
||
|
if settings[constants.SCENE]:
|
||
|
exporter.export_scene(filepath, settings)
|
||
|
else:
|
||
|
exporter.export_geometry(filepath, settings)
|
||
|
|
||
|
return {'FINISHED'}
|
||
|
|
||
|
def draw(self, context):
|
||
|
"""
|
||
|
|
||
|
:param context:
|
||
|
|
||
|
"""
|
||
|
layout = self.layout
|
||
|
|
||
|
## Geometry {
|
||
|
row = layout.row()
|
||
|
row.label(text="GEOMETRY:")
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_vertices')
|
||
|
row.prop(self.properties, 'option_faces')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_normals')
|
||
|
row.prop(self.properties, 'option_uv_coords')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_bones')
|
||
|
row.prop(self.properties, 'option_skinning')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_geometry_type')
|
||
|
|
||
|
## }
|
||
|
|
||
|
layout.separator()
|
||
|
|
||
|
## Materials {
|
||
|
row = layout.row()
|
||
|
row.label(text="- Shading:")
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_face_materials')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_colors')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_mix_colors')
|
||
|
## }
|
||
|
|
||
|
layout.separator()
|
||
|
|
||
|
## Animation {
|
||
|
row = layout.row()
|
||
|
row.label(text="- Animation:")
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_animation_morph')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.label(text="Skeletal animations:")
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_animation_skeletal')
|
||
|
|
||
|
layout.row()
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_influences')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_frame_step')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_frame_index_as_time')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_embed_animation')
|
||
|
|
||
|
## }
|
||
|
|
||
|
layout.separator()
|
||
|
|
||
|
## Scene {
|
||
|
row = layout.row()
|
||
|
row.label(text="SCENE:")
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_export_scene')
|
||
|
row.prop(self.properties, 'option_materials')
|
||
|
|
||
|
#row = layout.row()
|
||
|
#row.prop(self.properties, 'option_embed_geometry')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_lights')
|
||
|
row.prop(self.properties, 'option_cameras')
|
||
|
## }
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_hierarchy')
|
||
|
|
||
|
layout.separator()
|
||
|
|
||
|
## Settings {
|
||
|
row = layout.row()
|
||
|
row.label(text="SETTINGS:")
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_maps')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_copy_textures')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_texture_folder')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_scale')
|
||
|
|
||
|
layout.row()
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_round_off')
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_round_value')
|
||
|
|
||
|
layout.row()
|
||
|
row = layout.row()
|
||
|
row.label(text="Logging verbosity:")
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_logging')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.label(text="File compression format:")
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_compression')
|
||
|
|
||
|
row = layout.row()
|
||
|
row.prop(self.properties, 'option_indent')
|
||
|
## }
|
||
|
|
||
|
## Operators {
|
||
|
has_settings = context.scene.get(constants.EXPORT_SETTINGS_KEY, False)
|
||
|
row = layout.row()
|
||
|
row.operator(
|
||
|
ThreeExportSettings.bl_idname,
|
||
|
ThreeExportSettings.bl_label,
|
||
|
icon="%s" % "PINNED" if has_settings else "UNPINNED")
|
||
|
## }
|
||
|
|
||
|
|
||
|
|
||
|
def menu_func_export(self, context):
|
||
|
"""
|
||
|
|
||
|
:param self:
|
||
|
:param context:
|
||
|
|
||
|
"""
|
||
|
default_path = bpy.data.filepath.replace('.blend', constants.EXTENSION)
|
||
|
text = "Three.js (%s)" % constants.EXTENSION
|
||
|
operator = self.layout.operator(ExportThree.bl_idname, text=text)
|
||
|
operator.filepath = default_path
|
||
|
|
||
|
|
||
|
def register():
|
||
|
"""Registers the addon (Blender boilerplate)"""
|
||
|
bpy.utils.register_module(__name__)
|
||
|
bpy.types.INFO_MT_file_export.append(menu_func_export)
|
||
|
|
||
|
|
||
|
def unregister():
|
||
|
"""Unregisters the addon (Blender boilerplate)"""
|
||
|
bpy.utils.unregister_module(__name__)
|
||
|
bpy.types.INFO_MT_file_export.remove(menu_func_export)
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
register()
|