Fix T100076: OBJ import: new importer doesn't use //relative/image/paths
The Python based importer had logic to immediately turn image paths into relative-to-blender-file paths, if user preference for relative paths is used (which is on by default). The new importer code did not have that. Fixes T100076.
This commit is contained in:
parent
bea5281919
commit
e2be6bc03f
Notes:
blender-bot
2023-02-14 06:00:45 +01:00
Referenced by issue #100076, OBJ import: new importer doesn't use //relative/image/paths
|
@ -394,6 +394,7 @@ static int wm_obj_import_exec(bContext *C, wmOperator *op)
|
|||
import_params.up_axis = RNA_enum_get(op->ptr, "up_axis");
|
||||
import_params.import_vertex_groups = RNA_boolean_get(op->ptr, "import_vertex_groups");
|
||||
import_params.validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes");
|
||||
import_params.relative_paths = ((U.flag & USER_RELPATHS) != 0);
|
||||
|
||||
OBJ_import(C, &import_params);
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ struct OBJImportParams {
|
|||
eIOAxis up_axis;
|
||||
bool import_vertex_groups;
|
||||
bool validate_meshes;
|
||||
bool relative_paths;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,7 +57,7 @@ Object *MeshFromGeometry::create_mesh(Main *bmain,
|
|||
create_uv_verts(mesh);
|
||||
create_normals(mesh);
|
||||
create_colors(mesh);
|
||||
create_materials(bmain, materials, created_materials, obj);
|
||||
create_materials(bmain, materials, created_materials, obj, import_params.relative_paths);
|
||||
|
||||
if (import_params.validate_meshes || mesh_geometry_.has_invalid_polys_) {
|
||||
bool verbose_validate = false;
|
||||
|
@ -277,7 +277,8 @@ void MeshFromGeometry::create_uv_verts(Mesh *mesh)
|
|||
static Material *get_or_create_material(Main *bmain,
|
||||
const std::string &name,
|
||||
Map<std::string, std::unique_ptr<MTLMaterial>> &materials,
|
||||
Map<std::string, Material *> &created_materials)
|
||||
Map<std::string, Material *> &created_materials,
|
||||
bool relative_paths)
|
||||
{
|
||||
/* Have we created this material already? */
|
||||
Material **found_mat = created_materials.lookup_ptr(name);
|
||||
|
@ -291,7 +292,7 @@ static Material *get_or_create_material(Main *bmain,
|
|||
const MTLMaterial &mtl = *materials.lookup_or_add(name, std::make_unique<MTLMaterial>());
|
||||
|
||||
Material *mat = BKE_material_add(bmain, name.c_str());
|
||||
ShaderNodetreeWrap mat_wrap{bmain, mtl, mat};
|
||||
ShaderNodetreeWrap mat_wrap{bmain, mtl, mat, relative_paths};
|
||||
mat->use_nodes = true;
|
||||
mat->nodetree = mat_wrap.get_nodetree();
|
||||
BKE_ntree_update_main_tree(bmain, mat->nodetree, nullptr);
|
||||
|
@ -303,10 +304,12 @@ static Material *get_or_create_material(Main *bmain,
|
|||
void MeshFromGeometry::create_materials(Main *bmain,
|
||||
Map<std::string, std::unique_ptr<MTLMaterial>> &materials,
|
||||
Map<std::string, Material *> &created_materials,
|
||||
Object *obj)
|
||||
Object *obj,
|
||||
bool relative_paths)
|
||||
{
|
||||
for (const std::string &name : mesh_geometry_.material_order_) {
|
||||
Material *mat = get_or_create_material(bmain, name, materials, created_materials);
|
||||
Material *mat = get_or_create_material(
|
||||
bmain, name, materials, created_materials, relative_paths);
|
||||
if (mat == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,8 @@ class MeshFromGeometry : NonMovable, NonCopyable {
|
|||
void create_materials(Main *bmain,
|
||||
Map<std::string, std::unique_ptr<MTLMaterial>> &materials,
|
||||
Map<std::string, Material *> &created_materials,
|
||||
Object *obj);
|
||||
Object *obj,
|
||||
bool relative_paths);
|
||||
void create_normals(Mesh *mesh);
|
||||
void create_colors(Mesh *mesh);
|
||||
void create_vertex_groups(Object *obj);
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
*/
|
||||
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_node.h"
|
||||
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_path_util.h"
|
||||
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
|
@ -63,7 +65,8 @@ static void set_property_of_socket(eNodeSocketDatatype property_type,
|
|||
static bool load_texture_image_at_path(Main *bmain,
|
||||
const tex_map_XX &tex_map,
|
||||
bNode *r_node,
|
||||
const std::string &path)
|
||||
const std::string &path,
|
||||
bool relative_paths)
|
||||
{
|
||||
Image *tex_image = BKE_image_load_exists(bmain, path.c_str());
|
||||
if (!tex_image) {
|
||||
|
@ -71,6 +74,9 @@ static bool load_texture_image_at_path(Main *bmain,
|
|||
return false;
|
||||
}
|
||||
fprintf(stderr, "Loaded image from: '%s'\n", path.c_str());
|
||||
if (relative_paths) {
|
||||
BLI_path_rel(tex_image->filepath, BKE_main_blendfile_path(bmain));
|
||||
}
|
||||
r_node->id = reinterpret_cast<ID *>(tex_image);
|
||||
NodeTexImage *image = static_cast<NodeTexImage *>(r_node->storage);
|
||||
image->projection = tex_map.projection_type;
|
||||
|
@ -81,18 +87,21 @@ static bool load_texture_image_at_path(Main *bmain,
|
|||
* Load image for Image Texture node and set the node properties.
|
||||
* Return success if Image can be loaded successfully.
|
||||
*/
|
||||
static bool load_texture_image(Main *bmain, const tex_map_XX &tex_map, bNode *r_node)
|
||||
static bool load_texture_image(Main *bmain,
|
||||
const tex_map_XX &tex_map,
|
||||
bNode *r_node,
|
||||
bool relative_paths)
|
||||
{
|
||||
BLI_assert(r_node && r_node->type == SH_NODE_TEX_IMAGE);
|
||||
|
||||
/* First try treating texture path as relative. */
|
||||
std::string tex_path{tex_map.mtl_dir_path + tex_map.image_path};
|
||||
if (load_texture_image_at_path(bmain, tex_map, r_node, tex_path)) {
|
||||
if (load_texture_image_at_path(bmain, tex_map, r_node, tex_path, relative_paths)) {
|
||||
return true;
|
||||
}
|
||||
/* Then try using it directly as absolute path. */
|
||||
std::string raw_path{tex_map.image_path};
|
||||
if (load_texture_image_at_path(bmain, tex_map, r_node, raw_path)) {
|
||||
if (load_texture_image_at_path(bmain, tex_map, r_node, raw_path, relative_paths)) {
|
||||
return true;
|
||||
}
|
||||
/* Try removing quotes. */
|
||||
|
@ -100,21 +109,24 @@ static bool load_texture_image(Main *bmain, const tex_map_XX &tex_map, bNode *r_
|
|||
auto end_pos = std::remove(no_quote_path.begin(), no_quote_path.end(), '"');
|
||||
no_quote_path.erase(end_pos, no_quote_path.end());
|
||||
if (no_quote_path != tex_path &&
|
||||
load_texture_image_at_path(bmain, tex_map, r_node, no_quote_path)) {
|
||||
load_texture_image_at_path(bmain, tex_map, r_node, no_quote_path, relative_paths)) {
|
||||
return true;
|
||||
}
|
||||
/* Try replacing underscores with spaces. */
|
||||
std::string no_underscore_path{no_quote_path};
|
||||
std::replace(no_underscore_path.begin(), no_underscore_path.end(), '_', ' ');
|
||||
if (no_underscore_path != no_quote_path && no_underscore_path != tex_path &&
|
||||
load_texture_image_at_path(bmain, tex_map, r_node, no_underscore_path)) {
|
||||
load_texture_image_at_path(bmain, tex_map, r_node, no_underscore_path, relative_paths)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ShaderNodetreeWrap::ShaderNodetreeWrap(Main *bmain, const MTLMaterial &mtl_mat, Material *mat)
|
||||
ShaderNodetreeWrap::ShaderNodetreeWrap(Main *bmain,
|
||||
const MTLMaterial &mtl_mat,
|
||||
Material *mat,
|
||||
bool relative_paths)
|
||||
: mtl_mat_(mtl_mat)
|
||||
{
|
||||
nodetree_.reset(ntreeAddTree(nullptr, "Shader Nodetree", ntreeType_Shader->idname));
|
||||
|
@ -122,7 +134,7 @@ ShaderNodetreeWrap::ShaderNodetreeWrap(Main *bmain, const MTLMaterial &mtl_mat,
|
|||
shader_output_ = add_node_to_tree(SH_NODE_OUTPUT_MATERIAL);
|
||||
|
||||
set_bsdf_socket_values(mat);
|
||||
add_image_textures(bmain, mat);
|
||||
add_image_textures(bmain, mat, relative_paths);
|
||||
link_sockets(bsdf_, "BSDF", shader_output_, "Surface", 4);
|
||||
|
||||
nodeSetActive(nodetree_.get(), shader_output_);
|
||||
|
@ -325,7 +337,7 @@ void ShaderNodetreeWrap::set_bsdf_socket_values(Material *mat)
|
|||
}
|
||||
}
|
||||
|
||||
void ShaderNodetreeWrap::add_image_textures(Main *bmain, Material *mat)
|
||||
void ShaderNodetreeWrap::add_image_textures(Main *bmain, Material *mat, bool relative_paths)
|
||||
{
|
||||
for (const Map<const eMTLSyntaxElement, tex_map_XX>::Item texture_map :
|
||||
mtl_mat_.texture_maps.items()) {
|
||||
|
@ -335,7 +347,7 @@ void ShaderNodetreeWrap::add_image_textures(Main *bmain, Material *mat)
|
|||
}
|
||||
|
||||
bNode *image_texture = add_node_to_tree(SH_NODE_TEX_IMAGE);
|
||||
if (!load_texture_image(bmain, texture_map.value, image_texture)) {
|
||||
if (!load_texture_image(bmain, texture_map.value, image_texture, relative_paths)) {
|
||||
/* Image could not be added, so don't add or link further nodes. */
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ class ShaderNodetreeWrap {
|
|||
* Initializes a nodetree with a p-BSDF node's BSDF socket connected to shader output node's
|
||||
* surface socket.
|
||||
*/
|
||||
ShaderNodetreeWrap(Main *bmain, const MTLMaterial &mtl_mat, Material *mat);
|
||||
ShaderNodetreeWrap(Main *bmain, const MTLMaterial &mtl_mat, Material *mat, bool relative_paths);
|
||||
~ShaderNodetreeWrap();
|
||||
|
||||
/**
|
||||
|
@ -87,7 +87,7 @@ class ShaderNodetreeWrap {
|
|||
* Create image texture, vector and normal mapping nodes from MTL materials and link the
|
||||
* nodes to p-BSDF node.
|
||||
*/
|
||||
void add_image_textures(Main *bmain, Material *mat);
|
||||
void add_image_textures(Main *bmain, Material *mat, bool relative_paths);
|
||||
};
|
||||
|
||||
} // namespace blender::io::obj
|
||||
|
|
|
@ -61,6 +61,7 @@ class obj_importer_test : public BlendfileLoadingBaseTest {
|
|||
params.up_axis = IO_AXIS_Y;
|
||||
params.validate_meshes = true;
|
||||
params.import_vertex_groups = false;
|
||||
params.relative_paths = true;
|
||||
|
||||
std::string obj_path = blender::tests::flags_test_asset_dir() + "/io_tests/obj/" + path;
|
||||
strncpy(params.filepath, obj_path.c_str(), FILE_MAX - 1);
|
||||
|
|
Loading…
Reference in New Issue