diff --git a/addon/bitsquid/__init__.py b/addon/bitsquid/__init__.py
index 4a96ce0..b67647d 100644
--- a/addon/bitsquid/__init__.py
+++ b/addon/bitsquid/__init__.py
@@ -28,8 +28,11 @@ bl_info = {
# Reload sub modules if they are already loaded
if "bpy" in locals():
import importlib
- importlib.reload(unit_export)
- importlib.reload(unit)
+ if "unit_export" in locals():
+ importlib.reload(unit_export)
+ if "material_export" in locals():
+ importlib.reload(material_export)
+
import bpy
from bpy.types import (
@@ -38,17 +41,19 @@ from bpy.types import (
PropertyGroup,
)
from bpy.props import (
- StringProperty,
EnumProperty,
+ BoolProperty,
+ StringProperty,
PointerProperty,
)
from bpy_extras.io_utils import (
ExportHelper,
+ axis_conversion,
orientation_helper,
path_reference_mode,
- axis_conversion,
)
from bitsquid.unit import export as unit_export
+from bitsquid.material import export as material_export
class BitsquidSettings(PropertyGroup):
@@ -65,7 +70,6 @@ class SCENE_PT_bitsquid(Panel):
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
- # bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
@@ -84,6 +88,12 @@ class BitsquidObjectSettings(PropertyGroup):
subtype='DIR_PATH',
)
+ export_materials: BoolProperty(
+ name="Export materials",
+ description="Automatically export all referenced materials",
+ default=True,
+ )
+
class OBJECT_OT_bitsquid_export(Operator):
"""Export this object into a Bitsquid Unit file"""
@@ -91,15 +101,18 @@ class OBJECT_OT_bitsquid_export(Operator):
bl_label = "Export .unit"
bl_options = {'REGISTER'}
- filepath: StringProperty(subtype='DIR_PATH')
-
@classmethod
def poll(cls, context):
- return bpy.data.is_saved and context.active_object is not None
+ object = context.active_object
+ return bpy.data.is_saved and object is not None and object.type == 'MESH'
def execute(self, context):
- print("Export .unit")
- return unit_export.save(self, context, context.object.bitsquid.unit_filepath)
+ object = context.active_object
+ if object.bitsquid.export_materials:
+ for material_slot in object.material_slots.values():
+ material_export.save(self, context, material_slot.material)
+
+ return unit_export.save(self, context, object)
class OBJECT_PT_bitsquid(Panel):
@@ -107,16 +120,67 @@ class OBJECT_PT_bitsquid(Panel):
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
- # bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ object = context.object
+ layout = self.layout
+
+ if object.type != 'MESH':
+ layout.label(text="Only objects of type 'MESH' are supported.")
+ return
+
+ layout.use_property_split = False
+ layout.use_property_decorate = False
+
+ bitsquid = object.bitsquid
+ layout.prop(bitsquid, "unit_filepath", text="Unit File Path")
+ layout.prop(bitsquid, "export_materials", text="Export materials")
+ layout.operator("object.bitsquid_export_unit", text="Export .unit")
+
+
+class BitsquidMaterialSettings(PropertyGroup):
+ material_filepath: StringProperty(
+ name="Material File Path",
+ description="The directory to store the .material file in. Needs to be within the project root.",
+ default="//",
+ subtype='DIR_PATH',
+ )
+
+
+class MATERIAL_OT_bitsquid_export(Operator):
+ """Export this material into a Bitsquid Material file"""
+ bl_idname = "object.bitsquid_export_material"
+ bl_label = "Export .material"
+ bl_options = {'REGISTER'}
+
+ @classmethod
+ def poll(cls, context):
+ return bpy.data.is_saved and context.active_object is not None
+
+ def execute(self, context):
+ material = context.active_material
+ return unit_export.save(self, context, material)
+
+
+class MATERIAL_PT_bitsquid(Panel):
+ bl_label = "Bitsquid"
+ bl_space_type = "PROPERTIES"
+ bl_region_type = "WINDOW"
+ bl_context = "material"
+
+ @classmethod
+ def poll(cls, context):
+ object = context.active_object
+ return len(object.material_slots) > 0
def draw(self, context):
layout = self.layout
layout.use_property_split = False
layout.use_property_decorate = False
- bitsquid = context.object.bitsquid
- layout.prop(bitsquid, "unit_filepath", text="Unit File Path")
- layout.operator("object.bitsquid_export_unit", text="Export .unit")
+ bitsquid = context.material.bitsquid
+ layout.prop(bitsquid, "material_filepath", text="Material File Path")
+ layout.operator("object.bitsquid_export_material", text="Export .material")
# Register
@@ -126,6 +190,9 @@ classes = [
BitsquidObjectSettings,
OBJECT_PT_bitsquid,
OBJECT_OT_bitsquid_export,
+ BitsquidMaterialSettings,
+ MATERIAL_PT_bitsquid,
+ MATERIAL_OT_bitsquid_export,
]
@@ -136,6 +203,7 @@ def register():
bpy.types.Scene.bitsquid = PointerProperty(type=BitsquidSettings)
bpy.types.Object.bitsquid = PointerProperty(type=BitsquidObjectSettings)
+ bpy.types.Material.bitsquid = PointerProperty(type=BitsquidMaterialSettings)
def unregister():
diff --git a/addon/bitsquid/material/export.py b/addon/bitsquid/material/export.py
new file mode 100644
index 0000000..e32276a
--- /dev/null
+++ b/addon/bitsquid/material/export.py
@@ -0,0 +1,101 @@
+# Bitsquid Blender Tools
+# Copyright (C) 2021 Lucas Schwiderski
+#
+# 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 3 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, see .
+
+import os
+import bpy
+from bitsquid import step
+
+
+template = """
+parent_material = "core/stingray_renderer/shader_import/standard"
+
+textures = {}
+
+variables = {
+ base_color = {
+ type = "vector3"
+ value = [
+ 1
+ 0.333333333333333
+ 0
+ ]
+ }
+ emissive = {
+ type = "vector3"
+ value = [
+ 0
+ 0
+ 0
+ ]
+ }
+ emissive_intensity = {
+ type = "scalar"
+ value = 1
+ }
+ metallic = {
+ type = "scalar"
+ value = 0
+ }
+ roughness = {
+ type = "scalar"
+ value = 0.91
+ }
+ use_ao_map = {
+ type = "scalar"
+ value = 0
+ }
+ use_color_map = {
+ type = "scalar"
+ value = 0
+ }
+ use_emissive_map = {
+ type = "scalar"
+ value = 0
+ }
+ use_metallic_map = {
+ type = "scalar"
+ value = 0
+ }
+ use_normal_map = {
+ type = "scalar"
+ value = 0
+ }
+ use_roughness_map = {
+ type = "scalar"
+ value = 0
+ }
+}
+
+"""
+
+
+def build_filepath(material):
+ dir = bpy.path.abspath(material.bitsquid.material_filepath)
+ return os.path.join(dir, "{}.material".format(material.name))
+
+
+def save(self, context, material):
+ filepath = build_filepath(material)
+ self.report({'INFO'}, "Saving material to " + filepath)
+
+ namespace = {
+ 'material': material,
+ }
+ content = step.Template(template).expand(namespace)
+
+ self.report({'INFO'}, content)
+
+ return {'FINISHED'}
diff --git a/addon/bitsquid/unit/export.py b/addon/bitsquid/unit/export.py
index fb4829b..4e9f64f 100644
--- a/addon/bitsquid/unit/export.py
+++ b/addon/bitsquid/unit/export.py
@@ -14,11 +14,57 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+import os
import bpy
+from bpy_extras import io_utils
+from bitsquid import step
+from bitsquid.material import export as material_export
+
+template = """
+%if len(materials) > 0:
+materials = {
+ %for item in materials:
+ {{ item['name'] }} = "{{ item['path'] }}"
+ %endfor
+}
+%endif
+
+renderables = {
+ {{ object.name }} = {
+ always_keep = false
+ culling = "bounding_volume"
+ generate_uv_unwrap = false
+ occluder = false
+ shadow_caster = true
+ surface_queries = false
+ viewport_visible = true
+ }
+}
+"""
-def save(self, context, unit_filepath):
- filepath = bpy.path.abspath(unit_filepath)
+def build_filepath(object):
+ dir = bpy.path.abspath(object.bitsquid.unit_filepath)
+ return os.path.join(dir, "{}.unit".format(object.name))
+
+
+def save(self, context, object):
+ filepath = build_filepath(object)
self.report({'INFO'}, "Saving unit to " + filepath)
+ materials = []
+ for material_slot in object.material_slots.values():
+ materials.append({
+ 'name': material_slot.name,
+ 'path': material_export.build_filepath(material_slot.material),
+ })
+
+ namespace = {
+ 'object': object,
+ 'materials': materials,
+ }
+ content = step.Template(template).expand(namespace)
+
+ self.report({'INFO'}, content)
+
return {'FINISHED'}