Skip to content

Commit

Permalink
add 'Import from a Directory' operation
Browse files Browse the repository at this point in the history
  • Loading branch information
matyalatte committed Jan 19, 2023
1 parent c455f2b commit af537d8
Show file tree
Hide file tree
Showing 12 changed files with 347 additions and 303 deletions.
6 changes: 3 additions & 3 deletions addons/blender_dds_addon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,21 @@ def reload_package_recursive(current_dir, module_dict):
if ".import_dds" in locals():
reload_package(locals())

from .ui import import_dds, export_dds, set_properties, preferences
from .ui import import_dds, export_dds, custom_properties, preferences

def register():
"""Add addon."""
preferences.register()
import_dds.register()
export_dds.register()
set_properties.register()
custom_properties.register()

def unregister():
"""Remove addon."""
preferences.unregister()
import_dds.unregister()
export_dds.unregister()
set_properties.unregister()
custom_properties.unregister()

except ModuleNotFoundError as exc:
print(exc)
Expand Down
8 changes: 6 additions & 2 deletions addons/blender_dds_addon/directx/texconv.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
class Texconv:
"""Texture converter."""
def __init__(self, dll_path=None):
self.load_dll(dll_path=dll_path)

def load_dll(self, dll_path=None):
if dll_path is None:
file_path = os.path.realpath(__file__)
if util.is_windows():
Expand Down Expand Up @@ -96,7 +99,8 @@ def convert_to_tga(self, file, out=None, cubemap_layout="h-cross", invert_normal
args += ['-inverty']

if dds_header.is_cube():
name = ".".join(file.split(".")[:-1] + [fmt])
name = os.path.join(out, os.path.basename(file))
name = ".".join(name.split(".")[:-1] + [fmt])
self.cube_to_image(file, name, args, cubemap_layout=cubemap_layout, verbose=verbose)
else:
out = self.texconv(file, args, out=out, verbose=verbose)
Expand All @@ -111,7 +115,7 @@ def convert_to_dds(self, file, dds_fmt, out=None,
verbose=True, allow_slow_codec=False):
"""Convert texture to dds."""

ext = util.get_ext(file).lower()
ext = util.get_ext(file)

if is_hdr(dds_fmt) and ext != 'hdr':
raise RuntimeError(f'Use .hdr for HDR textures. ({file})')
Expand Down
2 changes: 1 addition & 1 deletion addons/blender_dds_addon/directx/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def mkdir(directory):

def get_ext(file):
"""Get file extension."""
return file.split('.')[-1]
return file.split('.')[-1].lower()


def check(actual, expected, f=None, msg='Parse failed. This is unexpected error.'):
Expand Down
8 changes: 8 additions & 0 deletions addons/blender_dds_addon/ui/bpy_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ def get_image_editor_space(context):
return space


def get_selected_tex(context):
space = get_image_editor_space(context)
tex = space.image
if tex is None:
raise RuntimeError('Select an image on Image Editor.')
return tex


def load_texture(file, name, color_space='Non-Color'):
"""Load a texture file.
Expand Down
186 changes: 186 additions & 0 deletions addons/blender_dds_addon/ui/custom_properties.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import bpy
from bpy.props import BoolProperty, EnumProperty, PointerProperty
from bpy.types import PropertyGroup
from .bpy_util import get_image_editor_space, dds_properties_exist
from ..directx.dxgi_format import DXGI_FORMAT

fmt_list = [fmt.name[12:] for fmt in DXGI_FORMAT]
fmt_list = [fmt for fmt in fmt_list if "BC" in fmt] + [fmt for fmt in fmt_list if "BC" not in fmt]

dic = {
"BC1_UNORM": " (DXT1)",
"BC3_UNORM": " (DXT5)",
"BC4_UNORM": " (ATI1)",
"BC5_UNORM": " (ATI2)",
}


def get_alt_fmt(fmt):
"""Add alt name for the format."""
if fmt in dic:
return fmt + dic[fmt]
return fmt


def is_supported(fmt):
return ('TYPELESS' not in fmt) and ('ASTC' not in fmt) and\
(len(fmt) > 4) and (fmt not in ["UNKNOWN", "420_OPAQUE"])


DDS_FMT_ITEMS = [(fmt, get_alt_fmt(fmt), '') for fmt in fmt_list if is_supported(fmt)]
DDS_FMT_NAMES = [fmt for fmt in fmt_list if is_supported(fmt)]


class DDSOptions(PropertyGroup):
"""Properties for operations."""

dxgi_format: EnumProperty(
name='DDS format',
items=DDS_FMT_ITEMS,
description="DXGI format for DDS",
default='BC1_UNORM'
)

invert_normals: BoolProperty(
name='Invert Normals',
description="Invert G channel for BC5 textures",
default=False,
)

no_mip: BoolProperty(
name='No Mipmaps',
description="Disable mipmap generation",
default=False,
)

allow_slow_codec: BoolProperty(
name='Allow Slow Codec',
description=("Allow to use CPU codec for BC6 and BC7.\n"
"But it'll take a long time for conversion"),
default=False,
)

export_as_cubemap: BoolProperty(
name='Export as Cubemap',
description=("Export a texture as a cubemap.\n"
'Faces should be aligned in a layout defined in "Layout for Cubemap Faces" option'),
default=False,
)

cubemap_layout: EnumProperty(
name='Layout for Cubemap Faces',
items=[
('h-cross', 'Horizontal Cross', 'Align faces in a horizontal cross layout'),
('v-cross', 'Vertical Cross', 'Align faces in a vertical cross layout'),
('h-cross-fnz', 'Horizontal Cross (Flip -Z)',
'Align faces in a vertical cross layout. And Rotate -Z face by 180 degrees'),
('v-cross-fnz', 'Vertical Cross (Flip -Z)',
'Align faces in a vertical cross layout. And Rotate -Z face by 180 degrees'),
('h-strip', 'Horizontal Strip', 'Align faces horizontaly'),
('v-strip', 'Vertical Strip', 'Align faces verticaly'),
],
description=(
'How to align faces of a cubemap.\n'
),
default='h-cross'
)


class DDSCustomProperties(PropertyGroup):
"""Properties for dds info."""

dxgi_format: EnumProperty(
name='DDS format',
items=[('NONE', 'None', 'Skip this image when excuting the export opration.')] + DDS_FMT_ITEMS,
description="DXGI format for DDS",
default='NONE'
)

no_mip: BoolProperty(
name='No Mipmaps',
description="Disable mipmap generation",
default=False,
)

is_cube: BoolProperty(
name='Is Cubemap',
description=("Export this texture as a cubemap.\n"
'Faces should be aligned in a layout defined in "Layout for Cubemap Faces" option'),
default=False,
)

cubemap_layout: EnumProperty(
name='Layout for Cubemap Faces',
items=[
('h-cross', 'Horizontal Cross', 'Align faces in a horizontal cross layout'),
('v-cross', 'Vertical Cross', 'Align faces in a vertical cross layout'),
('h-cross-fnz', 'Horizontal Cross (Flip -Z)',
'Align faces in a vertical cross layout. And Rotate -Z face by 180 degrees'),
('v-cross-fnz', 'Vertical Cross (Flip -Z)',
'Align faces in a vertical cross layout. And Rotate -Z face by 180 degrees'),
('h-strip', 'Horizontal Strip', 'Align faces horizontaly'),
('v-strip', 'Vertical Strip', 'Align faces verticaly'),
],
description=(
'How to align faces of a cubemap.\n'
),
default='h-cross'
)


def add_custom_props_for_dds():
if dds_properties_exist():
return
bpy.types.Image.dds_props = PointerProperty(type=DDSCustomProperties)


def remove_custom_props_for_dds():
if dds_properties_exist():
del bpy.types.Image.dds_props


class DDS_PT_property_panel(bpy.types.Panel):
"""UI panel for custom properties."""
bl_label = "Custom Properties"
bl_idname = 'DDS_PT_property_panel'
bl_space_type = "IMAGE_EDITOR"
bl_region_type = "UI"
bl_category = "DDS"

def draw(self, context):
"""Draw UI panel."""
if not dds_properties_exist():
return
layout = self.layout
tex = get_image_editor_space(context).image
if tex is None:
return
layout.prop(tex.dds_props, "dxgi_format")
if tex.dds_props.dxgi_format != "NONE":
layout.prop(tex.dds_props, "no_mip")
layout.prop(tex.dds_props, "is_cube")
if tex.dds_props.is_cube:
layout.prop(tex.dds_props, "cubemap_layout")


classes = (
DDSOptions,
DDSCustomProperties,
DDS_PT_property_panel,
)


def register():
"""Add UI panel, operator, and properties."""
for c in classes:
bpy.utils.register_class(c)
bpy.types.Scene.dds_options = PointerProperty(type=DDSOptions)
add_custom_props_for_dds()


def unregister():
"""Remove UI panel, operator, and properties."""
for c in classes:
bpy.utils.unregister_class(c)
del bpy.types.Scene.dds_options
remove_custom_props_for_dds()
Loading

0 comments on commit af537d8

Please sign in to comment.