def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): if item: icon = "ERROR" if not os.path.isdir( _path_utils.repair_path(item.path)) else "NONE" layout.prop(item, "path", text="", emboss=False, icon=icon) else: layout.label(text="", icon_value=icon)
def get_texture(texture_path, texture_type, report_invalid=False): """Creates and setup Texture and Image data on active Material. :param texture_path: Texture path :type texture_path: str :param texture_type: Texture type keyword :type texture_type: str :param report_invalid: flag indicating if invalid texture should be reported in 3d view :type report_invalid: bool """ # CREATE TEXTURE/IMAGE ID NAME teximag_id_name = _path.get_filename(texture_path, with_ext=False) # CREATE ABSOLUTE FILEPATH abs_texture_filepath = _path.get_abs_path(texture_path) # return None on non-existing texture file path if not abs_texture_filepath or not os.path.isfile(abs_texture_filepath): return None if abs_texture_filepath.endswith(".tobj"): abs_texture_filepath = _path.get_texture_path_from_tobj(abs_texture_filepath) # if not existing or none supported file if abs_texture_filepath is None or abs_texture_filepath[-4:] not in (".tga", ".png", ".dds"): if report_invalid: lprint("", report_warnings=-1, report_errors=-1) # take care of none existing paths referenced in tobj texture names if abs_texture_filepath: lprint("W Texture can't be displayed as TOBJ file: %r is referencing non texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) else: lprint("W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file.", (texture_path,)) if report_invalid: lprint("", report_warnings=1, report_errors=1) return None texture = None if abs_texture_filepath and os.path.isfile(abs_texture_filepath): # find existing texture with this image if teximag_id_name in bpy.data.textures: # reuse existing image texture if possible postfix = 0 postfixed_tex = teximag_id_name while postfixed_tex in bpy.data.textures: img_exists = bpy.data.textures[postfixed_tex].image is not None if img_exists and _path.repair_path(bpy.data.textures[postfixed_tex].image.filepath) == _path.repair_path(abs_texture_filepath): texture = bpy.data.textures[postfixed_tex] break postfix += 1 postfixed_tex = teximag_id_name + "." + str(postfix).zfill(3) # if texture wasn't found create new one if not texture: texture = bpy.data.textures.new(teximag_id_name, 'IMAGE') image = None # reuse existing image if possible postfix = 0 postfixed_img = teximag_id_name while postfixed_img in bpy.data.images: if _path.repair_path(bpy.data.images[postfixed_img].filepath) == _path.repair_path(abs_texture_filepath): image = bpy.data.images[postfixed_img] break postfix += 1 postfixed_img = teximag_id_name + "." + str(postfix).zfill(3) # if image wasn't found load it if not image: image = bpy.data.images.load(abs_texture_filepath) image.name = teximag_id_name # try to get relative path to the Blender file and set it to the image if bpy.data.filepath != '': # empty file path means blender file is not saved try: rel_path = _path.relative_path(os.path.dirname(bpy.data.filepath), abs_texture_filepath) except ValueError: # catch different mount paths: "path is on mount 'C:', start on mount 'E:'" rel_path = None if rel_path: image.filepath = rel_path # finally link image to texture texture.image = image image.use_alpha = True # set proper color space depending on texture type if texture_type == "nmap": # For TGA normal maps texture use Non-Color color space as it should be, # but for 16-bits PNG normal maps texture sRGB has to be used # otherwise Blender completely messes up normals calculation if texture.image.filepath.endswith(".tga"): texture.image.colorspace_settings.name = "Non-Color" else: texture.image.colorspace_settings.name = "sRGB" else: texture.image.colorspace_settings.name = "sRGB" # set usage of normal map if texture type is correct texture.use_normal_map = (texture_type == "nmap") if texture is None and texture_path.endswith(".tobj"): if report_invalid: lprint("", report_warnings=-1, report_errors=-1) lprint("W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) if report_invalid: lprint("", report_warnings=1, report_errors=1) return texture
def get_texture(texture_path, texture_type, report_invalid=False): """Creates and setup Texture and Image data on active Material. :param texture_path: Texture path :type texture_path: str :param texture_type: Texture type keyword :type texture_type: str :param report_invalid: flag indicating if invalid texture should be reported in 3d view :type report_invalid: bool """ # CREATE TEXTURE/IMAGE ID NAME teximag_id_name = _path.get_filename(texture_path, with_ext=False) # CREATE ABSOLUTE FILEPATH abs_texture_filepath = _path.get_abs_path(texture_path) # return None on non-existing texture file path if not abs_texture_filepath or not os.path.isfile(abs_texture_filepath): return None if abs_texture_filepath.endswith(".tobj"): abs_texture_filepath = _path.get_texture_path_from_tobj( abs_texture_filepath) # if not existing or none supported file if abs_texture_filepath is None or abs_texture_filepath[-4:] not in ( ".tga", ".png", ".dds"): if report_invalid: lprint("", report_warnings=-1, report_errors=-1) # take care of none existing paths referenced in tobj texture names if abs_texture_filepath: lprint( "W Texture can't be displayed as TOBJ file: %r is referencing non texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) else: lprint( "W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file.", (texture_path, )) if report_invalid: lprint("", report_warnings=1, report_errors=1) return None texture = None if abs_texture_filepath and os.path.isfile(abs_texture_filepath): # find existing texture with this image if teximag_id_name in bpy.data.textures: # reuse existing image texture if possible postfix = 0 postfixed_tex = teximag_id_name while postfixed_tex in bpy.data.textures: img_exists = bpy.data.textures[postfixed_tex].image is not None if img_exists and _path.repair_path( bpy.data.textures[postfixed_tex].image.filepath ) == _path.repair_path(abs_texture_filepath): texture = bpy.data.textures[postfixed_tex] break postfix += 1 postfixed_tex = teximag_id_name + "." + str(postfix).zfill(3) # if texture wasn't found create new one if not texture: texture = bpy.data.textures.new(teximag_id_name, 'IMAGE') image = None # reuse existing image if possible postfix = 0 postfixed_img = teximag_id_name while postfixed_img in bpy.data.images: if _path.repair_path( bpy.data.images[postfixed_img].filepath ) == _path.repair_path(abs_texture_filepath): image = bpy.data.images[postfixed_img] break postfix += 1 postfixed_img = teximag_id_name + "." + str(postfix).zfill(3) # if image wasn't found load it if not image: image = bpy.data.images.load(abs_texture_filepath) image.name = teximag_id_name # try to get relative path to the Blender file and set it to the image if bpy.data.filepath != '': # empty file path means blender file is not saved try: rel_path = _path.relative_path( os.path.dirname(bpy.data.filepath), abs_texture_filepath) except ValueError: # catch different mount paths: "path is on mount 'C:', start on mount 'E:'" rel_path = None if rel_path: image.filepath = rel_path # finally link image to texture texture.image = image image.use_alpha = True # set proper color space depending on texture type if texture_type == "nmap": # For TGA normal maps texture use Non-Color color space as it should be, # but for 16-bits PNG normal maps texture sRGB has to be used # otherwise Blender completely messes up normals calculation if texture.image.filepath.endswith(".tga"): texture.image.colorspace_settings.name = "Non-Color" else: texture.image.colorspace_settings.name = "sRGB" else: texture.image.colorspace_settings.name = "sRGB" # set usage of normal map if texture type is correct texture.use_normal_map = (texture_type == "nmap") if texture is None and texture_path.endswith(".tobj"): if report_invalid: lprint("", report_warnings=-1, report_errors=-1) lprint( "W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) if report_invalid: lprint("", report_warnings=1, report_errors=1) return texture
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): if item: icon = "ERROR" if not os.path.isdir(_path_utils.repair_path(item.path)) else "NONE" layout.prop(item, "path", text="", emboss=False, icon=icon) else: layout.label(text="", icon_value=icon)
def get_texture(texture_path, texture_type): """Creates and setup Texture and Image data on active Material. :param texture_path: Texture path :type texture_path: str :param texture_type: Texture type keyword :type texture_type: str """ # print(' texture_path: %s' % str(texture_path)) # CREATE TEXTURE/IMAGE ID NAME teximag_id_name = _path.get_filename(texture_path, with_ext=False) # CREATE ABSOLUTE FILEPATH abs_texture_filepath = _path.get_abs_path(texture_path) texture = None if abs_texture_filepath and os.path.isfile(abs_texture_filepath): # find existing texture with this image if teximag_id_name in bpy.data.textures: # reuse existing image texture if possible postfix = 0 postfixed_tex = teximag_id_name while postfixed_tex in bpy.data.textures: if _path.repair_path(bpy.data.textures[postfixed_tex].image.filepath) == _path.repair_path(abs_texture_filepath): texture = bpy.data.textures[postfixed_tex] break postfix += 1 postfixed_tex = teximag_id_name + "." + str(postfix).zfill(3) # if texture wasn't found create new one if not texture: texture = bpy.data.textures.new(teximag_id_name, 'IMAGE') image = None # reuse existing image if possible postfix = 0 postfixed_img = teximag_id_name while postfixed_img in bpy.data.images: if _path.repair_path(bpy.data.images[postfixed_img].filepath) == _path.repair_path(abs_texture_filepath): image = bpy.data.images[postfixed_img] break postfix += 1 postfixed_img = teximag_id_name + "." + str(postfix).zfill(3) # if image wasn't found load it if not image: image = bpy.data.images.load(abs_texture_filepath) image.name = teximag_id_name # try to get relative path to the Blender file and set it to the image if bpy.data.filepath != '': # empty file path means blender file is not saved try: rel_path = _path.relative_path(os.path.dirname(bpy.data.filepath), abs_texture_filepath) except ValueError: # catch different mount paths: "path is on mount 'C:', start on mount 'E:'" rel_path = None if rel_path: image.filepath = rel_path # finally link image to texture texture.image = image image.use_alpha = True # normal map related settings if texture_type == "nmap": texture.image.colorspace_settings.name = "Raw" texture.use_normal_map = True else: texture.image.colorspace_settings.name = "sRGB" texture.use_normal_map = False return texture
def get_texture_image(texture_path, texture_type, report_invalid=False): """Creates and returns image for given texture path and type. :param texture_path: Texture path :type texture_path: str :param texture_type: Texture type keyword :type texture_type: str :param report_invalid: flag indicating if invalid texture should be reported in 3d view :type report_invalid: bool :return: loaded image datablock to be used in SCS material :rtype: bpy.types.Image """ # get reflection image texture if texture_path.endswith(".tobj") and texture_type == "reflection": return get_reflection_image(texture_path, report_invalid=report_invalid) # CREATE TEXTURE/IMAGE ID NAME teximag_id_name = _path.get_filename(texture_path, with_ext=False) # CREATE ABSOLUTE FILEPATH abs_texture_filepath = _path.get_abs_path(texture_path) # return None on non-existing texture file path if not abs_texture_filepath or not os.path.isfile(abs_texture_filepath): return None if abs_texture_filepath.endswith(".tobj"): abs_texture_filepath = _path.get_texture_path_from_tobj(abs_texture_filepath) # if not existing or none supported file if abs_texture_filepath is None or abs_texture_filepath[-4:] not in (".tga", ".png", ".dds"): if report_invalid: lprint("", report_warnings=-1, report_errors=-1) # take care of none existing paths referenced in tobj texture names if abs_texture_filepath: lprint("W Texture can't be displayed as TOBJ file: %r is referencing non texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) else: lprint("W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file.", (texture_path,)) if report_invalid: lprint("", report_warnings=1, report_errors=1) return None image = None if abs_texture_filepath and os.path.isfile(abs_texture_filepath): # reuse existing image texture if possible postfix = 0 postfixed_tex = teximag_id_name while postfixed_tex in bpy.data.images: img_exists = postfixed_tex in bpy.data.images if img_exists and _path.repair_path(bpy.data.images[postfixed_tex].filepath) == _path.repair_path(abs_texture_filepath): image = bpy.data.images[postfixed_tex] break postfix += 1 postfixed_tex = teximag_id_name + "." + str(postfix).zfill(3) # if image wasn't found create new one if not image: image = None # reuse existing image if possible postfix = 0 postfixed_img = teximag_id_name while postfixed_img in bpy.data.images: if _path.repair_path(bpy.data.images[postfixed_img].filepath) == _path.repair_path(abs_texture_filepath): image = bpy.data.images[postfixed_img] break postfix += 1 postfixed_img = teximag_id_name + "." + str(postfix).zfill(3) # if image wasn't found load it if not image: image = bpy.data.images.load(abs_texture_filepath) image.name = teximag_id_name image.alpha_mode = 'CHANNEL_PACKED' # try to get relative path to the Blender file and set it to the image if bpy.data.filepath != '': # empty file path means blender file is not saved try: rel_path = _path.relative_path(os.path.dirname(bpy.data.filepath), abs_texture_filepath) except ValueError: # catch different mount paths: "path is on mount 'C:', start on mount 'E:'" rel_path = None if rel_path: image.filepath = rel_path if image is None and texture_path.endswith(".tobj"): if report_invalid: lprint("", report_warnings=-1, report_errors=-1) lprint("W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) if report_invalid: lprint("", report_warnings=1, report_errors=1) return image
def get_reflection_image(texture_path, report_invalid=False): """Gets reflection image for given texture path. 1. gets all textures names and check existance 2. create image objects for all planes 3. setup scene, create planes, create camera projector and assign images 4. render & save image 5. cleanup & scene restoring 6. load temp image and pack it 7. set filepath to TOBJ :param texture_path: Texture path :type texture_path: str :param report_invalid: flag indicating if invalid texture should be reported in 3d view :type report_invalid: bool :return: loaded image datablock to be used in SCS material :rtype: bpy.types.Image """ # CREATE TEXTURE/IMAGE ID NAME teximag_id_name = _path.get_filename(texture_path, with_ext=False) + "_cubemap" # CREATE ABSOLUTE FILEPATH abs_tobj_filepath = _path.get_abs_path(texture_path) # return None on non-existing TOBJ if not abs_tobj_filepath or not os.path.isfile(abs_tobj_filepath): return None # 1. reuse existing image texture if possible, otherwise construct first free slot postfix = 0 postfixed_tex = teximag_id_name while postfixed_tex in bpy.data.images: img_exists = postfixed_tex in bpy.data.images if img_exists and _path.repair_path( bpy.data.images[postfixed_tex].filepath) == _path.repair_path( abs_tobj_filepath): return bpy.data.images[postfixed_tex] postfix += 1 postfixed_tex = teximag_id_name + "." + str(postfix).zfill(3) teximag_id_name = postfixed_tex # 2. get all textures file paths and check their existance abs_texture_filepaths = _path.get_texture_paths_from_tobj( abs_tobj_filepath) # should be a cubemap with six images if not abs_texture_filepaths or len(abs_texture_filepaths) != 6: return None # all six images have to exist for abs_texture_filepath in abs_texture_filepaths: if abs_texture_filepath[-4:] not in (".tga", ".png", ".dds"): # none supported file if report_invalid: lprint("", report_warnings=-1, report_errors=-1) lprint( "W Texture can't be displayed as TOBJ file: %r is referencing non texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) if report_invalid: lprint("", report_warnings=1, report_errors=1) return None elif not os.path.isfile(abs_texture_filepath): # none existing file if report_invalid: lprint("", report_warnings=-1, report_errors=-1) # take care of none existing paths referenced in tobj texture names lprint( "W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) if report_invalid: lprint("", report_warnings=1, report_errors=1) return None # 3. create image objects for all planes images = [] for abs_texture_filepath in abs_texture_filepaths: images.append(bpy.data.images.load(abs_texture_filepath)) # 4. setup scene, create planes, create camera projector and assign images old_scene = bpy.context.window.scene tmp_scene = bpy.data.scenes.new("cubemap") bpy.context.window.scene = tmp_scene meshes = [] materials = [] objects = [] for i, plane in enumerate(("x+", "x-", "y+", "y-", "z+", "z-")): # mesh creation bm = bmesh.new(use_operators=True) bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=1, calc_uvs=True) mesh = bpy.data.meshes.new(plane) bm.to_mesh(mesh) bm.free() mesh.uv_layers.new() meshes.append(mesh) # material creation material = bpy.data.materials.new(plane) material.use_nodes = True material.node_tree.nodes.clear() out_node = material.node_tree.nodes.new("ShaderNodeOutputMaterial") emission_node = material.node_tree.nodes.new("ShaderNodeEmission") tex_node = material.node_tree.nodes.new("ShaderNodeTexImage") tex_node.image = images[i] material.node_tree.links.new(emission_node.inputs['Color'], tex_node.outputs['Color']) material.node_tree.links.new(out_node.inputs['Surface'], emission_node.outputs['Emission']) mesh.materials.append(material) materials.append(material) # object creation obj = bpy.data.objects.new(mesh.name, mesh) obj.location = (0, ) * 3 obj.rotation_euler = (0, ) * 3 if plane == "x+": obj.rotation_euler.x = pi * 0.5 obj.location.y = 1 elif plane == "x-": obj.rotation_euler.x = pi * 0.5 obj.rotation_euler.z = pi obj.location.y = -1 elif plane == "y+": obj.rotation_euler.x = pi obj.rotation_euler.z = pi * 0.5 obj.location.z = 1 elif plane == "y-": obj.rotation_euler.z = pi * 0.5 obj.location.z = -1 elif plane == "z+": obj.rotation_euler.x = pi * 0.5 obj.rotation_euler.z = pi * 0.5 obj.location.x = -1 elif plane == "z-": obj.rotation_euler.x = pi * 0.5 obj.rotation_euler.z = -pi * 0.5 obj.location.x = 1 tmp_scene.collection.objects.link(obj) objects.append(obj) # camera creation camera = bpy.data.cameras.new("projector") camera.type = "PANO" camera.lens = 5 camera.sensor_width = 32 camera.cycles.panorama_type = "EQUIRECTANGULAR" camera.cycles.latitude_min = -pi * 0.5 camera.cycles.latitude_max = pi * 0.5 camera.cycles.longitude_min = pi camera.cycles.longitude_max = -pi cam_obj = bpy.data.objects.new(camera.name, camera) cam_obj.location = (0, ) * 3 cam_obj.rotation_euler = (pi * 0.5, 0, 0) tmp_scene.collection.objects.link(cam_obj) # 5. render & save image final_image_path = os.path.join(tempfile.gettempdir(), teximag_id_name + ".tga") tmp_scene.render.engine = "CYCLES" tmp_scene.cycles.samples = 1 tmp_scene.camera = cam_obj tmp_scene.render.image_settings.file_format = "TARGA" tmp_scene.render.image_settings.color_mode = "RGBA" tmp_scene.render.resolution_percentage = 100 tmp_scene.render.resolution_x = images[0].size[0] * 4 tmp_scene.render.resolution_y = images[0].size[1] * 2 tmp_scene.render.filepath = final_image_path bpy.ops.render.render(write_still=True, scene=tmp_scene.name) # 6. cleanup & scene restoring for obj in objects: bpy.data.objects.remove(obj) for mesh in meshes: bpy.data.meshes.remove(mesh) for material in materials: bpy.data.materials.remove(material) for image in images: bpy.data.images.remove(image) bpy.data.objects.remove(cam_obj) bpy.data.cameras.remove(camera) bpy.context.window.scene = old_scene bpy.data.scenes.remove(tmp_scene) # 7. load temp image and pack it final_image = bpy.data.images.load(final_image_path) final_image.name = teximag_id_name final_image.alpha_mode = 'CHANNEL_PACKED' final_image.pack() # 8. set filepath to original image final_image.filepath = abs_tobj_filepath return final_image