FBX: Add material name collision mode
Introduces the Material Name Collision option, similar to how USD / OBJ importers have it. Pull Request: https://projects.blender.org/blender/blender/pulls/144375
This commit is contained in:
committed by
Aras Pranckevicius
parent
da46eed108
commit
b1d9a91647
@@ -198,6 +198,15 @@ class ImportFBX(bpy.types.Operator, ImportHelper):
|
||||
description="Use pre/post rotation from FBX transform (you may have to disable that in some cases)",
|
||||
default=True,
|
||||
)
|
||||
mtl_name_collision_mode: EnumProperty(
|
||||
name="Material Name Collision",
|
||||
items=(("MAKE_UNIQUE", "Make Unique", "Import each FBX material as a unique Blender material"),
|
||||
("REFERENCE_EXISTING", "Reference Existing",
|
||||
"If a material with the same name already exists, reference that instead of importing"),
|
||||
),
|
||||
default='MAKE_UNIQUE',
|
||||
description="Behavior when the name of an imported material conflicts with an existing material",
|
||||
)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -206,6 +215,7 @@ class ImportFBX(bpy.types.Operator, ImportHelper):
|
||||
|
||||
import_panel_include(layout, self)
|
||||
import_panel_transform(layout, self)
|
||||
import_panel_materials(layout, self)
|
||||
import_panel_animation(layout, self)
|
||||
import_panel_armature(layout, self)
|
||||
|
||||
@@ -267,6 +277,11 @@ def import_panel_transform_orientation(layout, operator):
|
||||
body.prop(operator, "axis_forward")
|
||||
body.prop(operator, "axis_up")
|
||||
|
||||
def import_panel_materials(layout, operator):
|
||||
header, body = layout.panel("FBX_import_material", default_closed=True)
|
||||
header.label(text="Materials")
|
||||
if body:
|
||||
body.prop(operator, "mtl_name_collision_mode")
|
||||
|
||||
def import_panel_animation(layout, operator):
|
||||
header, body = layout.panel("FBX_import_animation", default_closed=True)
|
||||
@@ -290,7 +305,6 @@ def import_panel_armature(layout, operator):
|
||||
sub.prop(operator, "primary_bone_axis")
|
||||
sub.prop(operator, "secondary_bone_axis")
|
||||
|
||||
|
||||
@orientation_helper(axis_forward='-Z', axis_up='Y')
|
||||
class ExportFBX(bpy.types.Operator, ExportHelper):
|
||||
"""Write a FBX file"""
|
||||
|
||||
@@ -1927,5 +1927,5 @@ FBXImportSettings = namedtuple("FBXImportSettings", (
|
||||
"use_custom_props", "use_custom_props_enum_as_string",
|
||||
"nodal_material_wrap_map", "image_cache",
|
||||
"ignore_leaf_bones", "force_connect_children", "automatic_bone_orientation", "bone_correction_matrix",
|
||||
"use_prepost_rot", "colors_type",
|
||||
"use_prepost_rot", "colors_type", "mtl_name_collision_mode",
|
||||
))
|
||||
|
||||
@@ -2050,6 +2050,10 @@ def blen_read_material(fbx_tmpl, fbx_obj, settings):
|
||||
|
||||
elem_name_utf8 = elem_name_ensure_class(fbx_obj, b'Material')
|
||||
|
||||
if settings.mtl_name_collision_mode == "REFERENCE_EXISTING":
|
||||
if (ma := bpy.data.materials.get(elem_name_utf8)):
|
||||
return ma
|
||||
|
||||
nodal_material_wrap_map = settings.nodal_material_wrap_map
|
||||
ma = bpy.data.materials.new(name=elem_name_utf8)
|
||||
|
||||
@@ -3043,7 +3047,8 @@ def load(operator, context, filepath="",
|
||||
primary_bone_axis='Y',
|
||||
secondary_bone_axis='X',
|
||||
use_prepost_rot=True,
|
||||
colors_type='SRGB'):
|
||||
colors_type='SRGB',
|
||||
mtl_name_collision_mode="MAKE_UNIQUE"):
|
||||
|
||||
global fbx_elem_nil
|
||||
fbx_elem_nil = FBXElem('', (), (), ())
|
||||
@@ -3182,7 +3187,7 @@ def load(operator, context, filepath="",
|
||||
use_custom_props, use_custom_props_enum_as_string,
|
||||
nodal_material_wrap_map, image_cache,
|
||||
ignore_leaf_bones, force_connect_children, automatic_bone_orientation, bone_correction_matrix,
|
||||
use_prepost_rot, colors_type,
|
||||
use_prepost_rot, colors_type, mtl_name_collision_mode,
|
||||
)
|
||||
|
||||
# #### And now, the "real" data.
|
||||
|
||||
@@ -33,6 +33,20 @@
|
||||
# include "io_fbx_ops.hh"
|
||||
# include "io_utils.hh"
|
||||
|
||||
const EnumPropertyItem rna_enum_fbx_mtl_name_collision_mode_items[] = {
|
||||
{int(eFBXMtlNameCollisionMode::MakeUnique),
|
||||
"MAKE_UNIQUE",
|
||||
0,
|
||||
"Make Unique",
|
||||
"Import each FBX material as a unique Blender material"},
|
||||
{int(eFBXMtlNameCollisionMode::ReferenceExisting),
|
||||
"REFERENCE_EXISTING",
|
||||
0,
|
||||
"Reference Existing",
|
||||
"If a material with the same name already exists, reference that instead of importing"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem fbx_vertex_colors_mode[] = {
|
||||
{int(eFBXVertexColorMode::None), "NONE", 0, "None", "Do not import color attributes"},
|
||||
{int(eFBXVertexColorMode::sRGB),
|
||||
@@ -60,6 +74,8 @@ static wmOperatorStatus wm_fbx_import_exec(bContext *C, wmOperator *op)
|
||||
params.use_anim = RNA_boolean_get(op->ptr, "use_anim");
|
||||
params.anim_offset = RNA_float_get(op->ptr, "anim_offset");
|
||||
params.vertex_colors = eFBXVertexColorMode(RNA_enum_get(op->ptr, "import_colors"));
|
||||
params.mtl_name_collision_mode = eFBXMtlNameCollisionMode(
|
||||
RNA_enum_get(op->ptr, "mtl_name_collision_mode"));
|
||||
|
||||
params.reports = op->reports;
|
||||
|
||||
@@ -110,6 +126,11 @@ static void ui_fbx_import_settings(const bContext *C, uiLayout *layout, PointerR
|
||||
col->prop(ptr, "validate_meshes", UI_ITEM_NONE, std::nullopt, ICON_NONE);
|
||||
}
|
||||
|
||||
if (uiLayout *panel = layout->panel(C, "FBX_import_material", true, IFACE_("Materials"))) {
|
||||
uiLayout *col = &panel->column(false);
|
||||
col->prop(ptr, "mtl_name_collision_mode", UI_ITEM_NONE, std::nullopt, ICON_NONE);
|
||||
}
|
||||
|
||||
{
|
||||
PanelLayout panel = layout->panel(C, "FBX_import_anim", true);
|
||||
panel.header->use_property_split_set(false);
|
||||
@@ -157,6 +178,14 @@ void WM_OT_fbx_import(wmOperatorType *ot)
|
||||
FILE_SORT_DEFAULT);
|
||||
|
||||
RNA_def_float(ot->srna, "global_scale", 1.0f, 1e-6f, 1e6f, "Scale", "", 0.001f, 1000.0f);
|
||||
|
||||
RNA_def_enum(
|
||||
ot->srna,
|
||||
"mtl_name_collision_mode",
|
||||
rna_enum_fbx_mtl_name_collision_mode_items,
|
||||
int(eFBXMtlNameCollisionMode::MakeUnique),
|
||||
"Material Name Collision",
|
||||
"Behavior when the name of an imported material conflicts with an existing material");
|
||||
RNA_def_enum(ot->srna,
|
||||
"import_colors",
|
||||
fbx_vertex_colors_mode,
|
||||
|
||||
@@ -18,6 +18,15 @@ struct Mesh;
|
||||
struct bContext;
|
||||
struct ReportList;
|
||||
|
||||
/**
|
||||
* Behavior when the name of an imported material
|
||||
* conflicts with an existing material.
|
||||
*/
|
||||
enum class eFBXMtlNameCollisionMode {
|
||||
MakeUnique = 0,
|
||||
ReferenceExisting = 1,
|
||||
};
|
||||
|
||||
enum class eFBXVertexColorMode {
|
||||
None = 0,
|
||||
sRGB = 1,
|
||||
@@ -27,6 +36,7 @@ enum class eFBXVertexColorMode {
|
||||
struct FBXImportParams {
|
||||
char filepath[FILE_MAX] = "";
|
||||
float global_scale = 1.0f;
|
||||
eFBXMtlNameCollisionMode mtl_name_collision_mode = eFBXMtlNameCollisionMode::MakeUnique;
|
||||
eFBXVertexColorMode vertex_colors = eFBXVertexColorMode::sRGB;
|
||||
bool validate_meshes = true;
|
||||
bool use_custom_normals = true;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_light.h"
|
||||
#include "BKE_object.hh"
|
||||
#include "BKE_report.hh"
|
||||
@@ -98,9 +99,17 @@ void FbxImportContext::import_globals(Scene *scene) const
|
||||
void FbxImportContext::import_materials()
|
||||
{
|
||||
for (const ufbx_material *fmat : this->fbx.materials) {
|
||||
Material *mat = io::fbx::import_material(this->bmain, this->base_dir, *fmat);
|
||||
if (this->params.use_custom_props) {
|
||||
read_custom_properties(fmat->props, mat->id, this->params.props_enum_as_string);
|
||||
Material *mat = nullptr;
|
||||
/* Check if a material with this name already exists in the main database */
|
||||
if (this->params.mtl_name_collision_mode == eFBXMtlNameCollisionMode::ReferenceExisting) {
|
||||
mat = (Material *)BKE_libblock_find_name(this->bmain, ID_MA, fmat->name.data);
|
||||
}
|
||||
|
||||
if (mat == nullptr) {
|
||||
mat = io::fbx::import_material(this->bmain, this->base_dir, *fmat);
|
||||
if (this->params.use_custom_props) {
|
||||
read_custom_properties(fmat->props, mat->id, this->params.props_enum_as_string);
|
||||
}
|
||||
}
|
||||
this->mapping.mat_to_material.add(fmat, mat);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user