123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692 |
- # ##### 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 bpy
- from bpy_extras.io_utils import ExportHelper
- from bpy.props import (
- EnumProperty,
- BoolProperty,
- FloatProperty,
- IntProperty
- )
- from . import constants
- SETTINGS_FILE_EXPORT = 'three_settings_export.js'
- bl_info = {
- 'name': 'Three.js Format',
- 'author': 'Ed Caspersen (repsac)',
- 'version': (1, 0, 0),
- 'blender': (2, 7, 2),
- 'location': 'File > Import-Export',
- 'description': 'Export Three.js formatted JSON files.',
- 'warning': '',
- '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():
- types = [
- (constants.GLOBAL, constants.GLOBAL.title(),
- constants.GLOBAL),
- (constants.GEOMETRY, constants.GEOMETRY.title(),
- constants.GEOMETRY),
- (constants.BUFFER_GEOMETRY, constants.BUFFER_GEOMETRY,
- constants.BUFFER_GEOMETRY),
- ]
- return types
- bpy.types.Mesh.THREE_geometry_type = EnumProperty(
- name='Geometry type',
- description='Geometry type',
- items=_geometry_types(),
- default=constants.GLOBAL)
- class MESH_PT_hello(bpy.types.Panel):
- bl_label = 'THREE'
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = 'data'
-
- def draw(self, context):
- row = self.layout.row()
- if context.mesh:
- row.prop(context.mesh, 'THREE_geometry_type', text='Type')
- def _blending_types(index):
- 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 MATERIAL_PT_hello(bpy.types.Panel):
- bl_label = 'THREE'
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = 'material'
-
- def draw(self, 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):
- 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):
- 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):
- 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 TEXTURE_PT_hello(bpy.types.Panel):
- bl_label = 'THREE'
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = 'texture'
- #@TODO: possible to make cycles compatible?
- def draw(self, 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 OBJECT_PT_hello(bpy.types.Panel):
- bl_label = 'THREE'
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = 'object'
- def draw(self, context):
- layout = self.layout
- obj = context.object
- row = layout.row()
- row.prop(obj, 'THREE_export', text='Export')
- def get_settings_fullpath():
- return os.path.join(bpy.app.tempdir, SETTINGS_FILE_EXPORT)
- def save_settings_export(properties):
- 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.COPY_TEXTURES: properties.option_copy_textures,
- 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.MORPH_TARGETS: properties.option_animation_morph,
- constants.ANIMATION: properties.option_animation_skeletal,
- constants.FRAME_STEP: properties.option_frame_step,
- constants.INFLUENCES_PER_VERTEX: properties.option_influences
- }
- fname = get_settings_fullpath()
- with open(fname, 'w') as stream:
- json.dump(settings, stream)
- return settings
- def restore_settings_export(properties):
- settings = {}
- fname = get_settings_fullpath()
- if os.path.exists(fname) and os.access(fname, os.R_OK):
- f = open(fname, 'r')
- settings = json.load(f)
- ## 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_copy_textures = settings.get(
- constants.COPY_TEXTURES,
- constants.EXPORT_OPTIONS[constants.COPY_TEXTURES])
- 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])
- ## }
- ## 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])
- ## }
- def compression_types():
- types = [(constants.NONE, constants.NONE, constants.NONE)]
- try:
- import msgpack
- types.append((constants.MSGPACK, constants.MSGPACK,
- constants.MSGPACK))
- except ImportError:
- pass
- return types
- class ExportThree(bpy.types.Operator, ExportHelper):
- bl_idname='export.three'
- bl_label = 'Export THREE'
- 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='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='Logging',
- 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])
- 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_lights = BoolProperty(
- name='Lights',
- description='Export default scene lights',
- default=False)
- option_cameras = BoolProperty(
- name='Cameras',
- description='Export default scene cameras',
- default=False)
- option_animation_morph = BoolProperty(
- name='Morph animation',
- description='Export animation (morphs)',
- default=constants.EXPORT_OPTIONS[constants.MORPH_TARGETS])
- option_animation_skeletal = BoolProperty(
- name='Skeletal animation',
- description='Export animation (skeletal)',
- default=constants.EXPORT_OPTIONS[constants.ANIMATION])
- option_frame_step = IntProperty(
- name='Frame step',
- description='Animation frame step',
- min=1,
- max=1000,
- soft_min=1,
- soft_max=1000,
- default=1)
-
- option_compression = EnumProperty(
- name='Compression',
- 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):
- restore_settings_export(self.properties)
- return ExportHelper.invoke(self, context, event)
- @classmethod
- def poll(cls, context):
- return context.active_object is not None
- def execute(self, context):
- if not self.properties.filepath:
- raise Exception('filename not set')
- settings = save_settings_export(self.properties)
- 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):
- 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 = layout.row()
- row.prop(self.properties, 'option_bones')
- row.prop(self.properties, 'option_skinning')
- row = layout.row()
- row.prop(self.properties, 'option_geometry_type')
- row = layout.row()
- row.prop(self.properties, 'option_influences')
- ## }
- layout.separator()
- ## Materials {
- row = layout.row()
- row.label(text='Materials:')
- row = layout.row()
- row.prop(self.properties, 'option_materials')
- row.prop(self.properties, 'option_uv_coords')
- row = layout.row()
- row.prop(self.properties, 'option_face_materials')
- row.prop(self.properties, 'option_maps')
- row = layout.row()
- row.prop(self.properties, 'option_colors')
- row.prop(self.properties, 'option_mix_colors')
- ## }
-
- layout.separator()
- ## Settings {
- row = layout.row()
- row.label(text='Settings:')
- row = layout.row()
- row.prop(self.properties, 'option_scale')
-
- row = layout.row()
- row.prop(self.properties, 'option_round_off')
- row.prop(self.properties, 'option_round_value')
- row = layout.row()
- row.prop(self.properties, 'option_logging')
- row = layout.row()
- row.prop(self.properties, 'option_compression')
- row = layout.row()
- row.prop(self.properties, 'option_copy_textures')
- 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 = layout.row()
- row.prop(self.properties, 'option_embed_geometry')
- row = layout.row()
- row.prop(self.properties, 'option_lights')
- row.prop(self.properties, 'option_cameras')
- ## }
- layout.separator()
- ## Animation {
- row = layout.row()
- row.label(text='Animation:')
- row = layout.row()
- row.prop(self.properties, 'option_animation_morph')
- row = layout.row()
- row.prop(self.properties, 'option_animation_skeletal')
- row = layout.row()
- row.prop(self.properties, 'option_frame_step')
- ## }
- def menu_func_export(self, context):
- default_path = bpy.data.filepath.replace('.blend', constants.EXTENSION)
- text = 'Three (%s)' % constants.EXTENSION
- operator = self.layout.operator(ExportThree.bl_idname, text=text)
- operator.filepath = default_path
- def register():
- bpy.utils.register_module(__name__)
- bpy.types.INFO_MT_file_export.append(menu_func_export)
- def unregister():
- bpy.utils.unregister_module(__name__)
- bpy.types.INFO_MT_file_export.remove(menu_func_export)
- if __name__ == '__main__':
- register()
|