MacOS: Enable support for EDR rendering #105662
|
@ -155,12 +155,15 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals kg,
|
||||||
sd->Ng = Ng;
|
sd->Ng = Ng;
|
||||||
sd->wi = I;
|
sd->wi = I;
|
||||||
sd->shader = shader;
|
sd->shader = shader;
|
||||||
if (prim != PRIM_NONE)
|
if (lamp != LAMP_NONE) {
|
||||||
sd->type = PRIMITIVE_TRIANGLE;
|
|
||||||
else if (lamp != LAMP_NONE)
|
|
||||||
sd->type = PRIMITIVE_LAMP;
|
sd->type = PRIMITIVE_LAMP;
|
||||||
else
|
}
|
||||||
|
else if (prim != PRIM_NONE) {
|
||||||
|
sd->type = PRIMITIVE_TRIANGLE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
sd->type = PRIMITIVE_NONE;
|
sd->type = PRIMITIVE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
/* primitive */
|
/* primitive */
|
||||||
sd->object = object;
|
sd->object = object;
|
||||||
|
|
|
@ -215,6 +215,7 @@ class GHOST_DeviceVK {
|
||||||
device_features.geometryShader = VK_TRUE;
|
device_features.geometryShader = VK_TRUE;
|
||||||
device_features.dualSrcBlend = VK_TRUE;
|
device_features.dualSrcBlend = VK_TRUE;
|
||||||
device_features.logicOp = VK_TRUE;
|
device_features.logicOp = VK_TRUE;
|
||||||
|
device_features.imageCubeArray = VK_TRUE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VkDeviceCreateInfo device_create_info = {};
|
VkDeviceCreateInfo device_create_info = {};
|
||||||
|
@ -309,7 +310,7 @@ static GHOST_TSuccess ensure_vulkan_device(VkInstance vk_instance,
|
||||||
|
|
||||||
#if STRICT_REQUIREMENTS
|
#if STRICT_REQUIREMENTS
|
||||||
if (!device_vk.features.geometryShader || !device_vk.features.dualSrcBlend ||
|
if (!device_vk.features.geometryShader || !device_vk.features.dualSrcBlend ||
|
||||||
!device_vk.features.logicOp)
|
!device_vk.features.logicOp || !device_vk.features.imageCubeArray)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -571,8 +571,6 @@ class KeyframesCo:
|
||||||
keyframe_points.foreach_set("co", co_buffer)
|
keyframe_points.foreach_set("co", co_buffer)
|
||||||
keyframe_points.foreach_set("interpolation", ipo_buffer)
|
keyframe_points.foreach_set("interpolation", ipo_buffer)
|
||||||
|
|
||||||
# TODO: in Blender 4.0 the next lines can be replaced with one call to `fcurve.update()`.
|
# This also deduplicates keys where baked keys were inserted on the
|
||||||
# See https://projects.blender.org/blender/blender/issues/107126 for more info.
|
# same frame as existing ones.
|
||||||
keyframe_points.sort()
|
fcurve.update()
|
||||||
keyframe_points.deduplicate()
|
|
||||||
keyframe_points.handles_recalc()
|
|
||||||
|
|
|
@ -44,8 +44,8 @@ def geometry_modifier_poll(context):
|
||||||
|
|
||||||
|
|
||||||
def get_context_modifier(context):
|
def get_context_modifier(context):
|
||||||
area = context.area
|
# Context only has a 'modifier' attribute in the modifier extra operators dropdown.
|
||||||
if (area is not None) and (area.type == 'PROPERTIES'):
|
if hasattr(context, 'modifier'):
|
||||||
modifier = context.modifier
|
modifier = context.modifier
|
||||||
else:
|
else:
|
||||||
ob = context.object
|
ob = context.object
|
||||||
|
|
|
@ -109,17 +109,6 @@ class MESH_UL_vgroups(UIList):
|
||||||
layout.label(text="", icon_value=icon)
|
layout.label(text="", icon_value=icon)
|
||||||
|
|
||||||
|
|
||||||
class MESH_UL_fmaps(UIList):
|
|
||||||
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
|
|
||||||
# assert(isinstance(item, bpy.types.FaceMap))
|
|
||||||
fmap = item
|
|
||||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
|
||||||
layout.prop(fmap, "name", text="", emboss=False, icon='FACE_MAPS')
|
|
||||||
elif self.layout_type == 'GRID':
|
|
||||||
layout.alignment = 'CENTER'
|
|
||||||
layout.label(text="", icon_value=icon)
|
|
||||||
|
|
||||||
|
|
||||||
class MESH_UL_shape_keys(UIList):
|
class MESH_UL_shape_keys(UIList):
|
||||||
def draw_item(self, _context, layout, _data, item, icon, active_data, _active_propname, index):
|
def draw_item(self, _context, layout, _data, item, icon, active_data, _active_propname, index):
|
||||||
# assert(isinstance(item, bpy.types.ShapeKey))
|
# assert(isinstance(item, bpy.types.ShapeKey))
|
||||||
|
@ -285,50 +274,6 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
|
||||||
layout.prop(context.tool_settings, "vertex_group_weight", text="Weight")
|
layout.prop(context.tool_settings, "vertex_group_weight", text="Weight")
|
||||||
|
|
||||||
|
|
||||||
class DATA_PT_face_maps(MeshButtonsPanel, Panel):
|
|
||||||
bl_label = "Face Maps"
|
|
||||||
bl_options = {'DEFAULT_CLOSED'}
|
|
||||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
obj = context.object
|
|
||||||
return (obj and obj.type == 'MESH')
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
|
|
||||||
ob = context.object
|
|
||||||
facemap = ob.face_maps.active
|
|
||||||
|
|
||||||
rows = 2
|
|
||||||
if facemap:
|
|
||||||
rows = 4
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.template_list("MESH_UL_fmaps", "", ob, "face_maps", ob.face_maps, "active_index", rows=rows)
|
|
||||||
|
|
||||||
col = row.column(align=True)
|
|
||||||
col.operator("object.face_map_add", icon='ADD', text="")
|
|
||||||
col.operator("object.face_map_remove", icon='REMOVE', text="")
|
|
||||||
|
|
||||||
if facemap:
|
|
||||||
col.separator()
|
|
||||||
col.operator("object.face_map_move", icon='TRIA_UP', text="").direction = 'UP'
|
|
||||||
col.operator("object.face_map_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
|
|
||||||
|
|
||||||
if ob.face_maps and (ob.mode == 'EDIT' and ob.type == 'MESH'):
|
|
||||||
row = layout.row()
|
|
||||||
|
|
||||||
sub = row.row(align=True)
|
|
||||||
sub.operator("object.face_map_assign", text="Assign")
|
|
||||||
sub.operator("object.face_map_remove_from", text="Remove")
|
|
||||||
|
|
||||||
sub = row.row(align=True)
|
|
||||||
sub.operator("object.face_map_select", text="Select")
|
|
||||||
sub.operator("object.face_map_deselect", text="Deselect")
|
|
||||||
|
|
||||||
|
|
||||||
class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
|
class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
|
||||||
bl_label = "Shape Keys"
|
bl_label = "Shape Keys"
|
||||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}
|
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}
|
||||||
|
@ -717,7 +662,6 @@ classes = (
|
||||||
MESH_MT_color_attribute_context_menu,
|
MESH_MT_color_attribute_context_menu,
|
||||||
MESH_MT_attribute_context_menu,
|
MESH_MT_attribute_context_menu,
|
||||||
MESH_UL_vgroups,
|
MESH_UL_vgroups,
|
||||||
MESH_UL_fmaps,
|
|
||||||
MESH_UL_shape_keys,
|
MESH_UL_shape_keys,
|
||||||
MESH_UL_uvmaps,
|
MESH_UL_uvmaps,
|
||||||
MESH_UL_attributes,
|
MESH_UL_attributes,
|
||||||
|
@ -726,7 +670,6 @@ classes = (
|
||||||
DATA_PT_shape_keys,
|
DATA_PT_shape_keys,
|
||||||
DATA_PT_uv_texture,
|
DATA_PT_uv_texture,
|
||||||
DATA_PT_vertex_colors,
|
DATA_PT_vertex_colors,
|
||||||
DATA_PT_face_maps,
|
|
||||||
DATA_PT_mesh_attributes,
|
DATA_PT_mesh_attributes,
|
||||||
DATA_PT_normals,
|
DATA_PT_normals,
|
||||||
DATA_PT_texture_space,
|
DATA_PT_texture_space,
|
||||||
|
|
|
@ -1221,7 +1221,7 @@ class IMAGE_PT_tools_brush_display(Panel, BrushButtonsPanel, DisplayPanel):
|
||||||
bl_context = ".paint_common_2d"
|
bl_context = ".paint_common_2d"
|
||||||
bl_parent_id = "IMAGE_PT_paint_settings"
|
bl_parent_id = "IMAGE_PT_paint_settings"
|
||||||
bl_category = "Tool"
|
bl_category = "Tool"
|
||||||
bl_label = "Brush Tip"
|
bl_label = "Cursor"
|
||||||
bl_options = {'DEFAULT_CLOSED'}
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
bl_ui_units_x = 15
|
bl_ui_units_x = 15
|
||||||
|
|
||||||
|
|
|
@ -2103,7 +2103,7 @@ class VIEW3D_MT_select_edit_curves(Menu):
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
|
||||||
layout.operator("curves.select_random", text="Random")
|
layout.operator("curves.select_random", text="Random")
|
||||||
layout.operator("curves.select_end", text="Endpoints")
|
layout.operator("curves.select_ends", text="Endpoints")
|
||||||
layout.operator("curves.select_linked", text="Linked")
|
layout.operator("curves.select_linked", text="Linked")
|
||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
@ -2121,7 +2121,7 @@ class VIEW3D_MT_select_sculpt_curves(Menu):
|
||||||
layout.operator("curves.select_all", text="None").action = 'DESELECT'
|
layout.operator("curves.select_all", text="None").action = 'DESELECT'
|
||||||
layout.operator("curves.select_all", text="Invert").action = 'INVERT'
|
layout.operator("curves.select_all", text="Invert").action = 'INVERT'
|
||||||
layout.operator("sculpt_curves.select_random", text="Random")
|
layout.operator("sculpt_curves.select_random", text="Random")
|
||||||
layout.operator("curves.select_end", text="Endpoints")
|
layout.operator("curves.select_ends", text="Endpoints")
|
||||||
layout.operator("sculpt_curves.select_grow", text="Grow")
|
layout.operator("sculpt_curves.select_grow", text="Grow")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,7 @@ class AssetLibrary {
|
||||||
*/
|
*/
|
||||||
AssetRepresentation &add_external_asset(StringRef relative_asset_path,
|
AssetRepresentation &add_external_asset(StringRef relative_asset_path,
|
||||||
StringRef name,
|
StringRef name,
|
||||||
|
int id_type,
|
||||||
std::unique_ptr<AssetMetaData> metadata);
|
std::unique_ptr<AssetMetaData> metadata);
|
||||||
/** See #AssetLibrary::add_external_asset(). */
|
/** See #AssetLibrary::add_external_asset(). */
|
||||||
AssetRepresentation &add_local_id_asset(StringRef relative_asset_path, ID &id);
|
AssetRepresentation &add_local_id_asset(StringRef relative_asset_path, ID &id);
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
#include "BLI_compiler_attrs.h"
|
#include "BLI_compiler_attrs.h"
|
||||||
|
|
||||||
|
#include "DNA_ID_enums.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -22,6 +24,8 @@ typedef struct AssetRepresentation AssetRepresentation;
|
||||||
|
|
||||||
const char *AS_asset_representation_name_get(const AssetRepresentation *asset)
|
const char *AS_asset_representation_name_get(const AssetRepresentation *asset)
|
||||||
ATTR_WARN_UNUSED_RESULT;
|
ATTR_WARN_UNUSED_RESULT;
|
||||||
|
ID_Type AS_asset_representation_id_type_get(const AssetRepresentation *asset)
|
||||||
|
ATTR_WARN_UNUSED_RESULT;
|
||||||
AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset)
|
AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset)
|
||||||
ATTR_WARN_UNUSED_RESULT;
|
ATTR_WARN_UNUSED_RESULT;
|
||||||
struct ID *AS_asset_representation_local_id_get(const AssetRepresentation *asset)
|
struct ID *AS_asset_representation_local_id_get(const AssetRepresentation *asset)
|
||||||
|
@ -30,6 +34,9 @@ bool AS_asset_representation_is_local_id(const AssetRepresentation *asset) ATTR_
|
||||||
bool AS_asset_representation_is_never_link(const AssetRepresentation *asset)
|
bool AS_asset_representation_is_never_link(const AssetRepresentation *asset)
|
||||||
ATTR_WARN_UNUSED_RESULT;
|
ATTR_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
bool AS_asset_representation_may_override_import_method(const AssetRepresentation *asset);
|
||||||
|
bool AS_asset_representation_use_relative_path_get(const AssetRepresentation *asset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C version of #AssetRepresentation::make_weak_reference. Returned pointer needs freeing with
|
* C version of #AssetRepresentation::make_weak_reference. Returned pointer needs freeing with
|
||||||
* #MEM_delete() or #BKE_asset_weak_reference_free().
|
* #MEM_delete() or #BKE_asset_weak_reference_free().
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "BLI_string_ref.hh"
|
#include "BLI_string_ref.hh"
|
||||||
|
|
||||||
|
#include "DNA_ID_enums.h"
|
||||||
#include "DNA_asset_types.h"
|
#include "DNA_asset_types.h"
|
||||||
|
|
||||||
#include "AS_asset_identifier.hh"
|
#include "AS_asset_identifier.hh"
|
||||||
|
@ -42,6 +43,7 @@ class AssetRepresentation {
|
||||||
|
|
||||||
struct ExternalAsset {
|
struct ExternalAsset {
|
||||||
std::string name;
|
std::string name;
|
||||||
|
int id_type = 0;
|
||||||
std::unique_ptr<AssetMetaData> metadata_ = nullptr;
|
std::unique_ptr<AssetMetaData> metadata_ = nullptr;
|
||||||
};
|
};
|
||||||
union {
|
union {
|
||||||
|
@ -55,6 +57,7 @@ class AssetRepresentation {
|
||||||
/** Constructs an asset representation for an external ID. The asset will not be editable. */
|
/** Constructs an asset representation for an external ID. The asset will not be editable. */
|
||||||
AssetRepresentation(AssetIdentifier &&identifier,
|
AssetRepresentation(AssetIdentifier &&identifier,
|
||||||
StringRef name,
|
StringRef name,
|
||||||
|
int id_type,
|
||||||
std::unique_ptr<AssetMetaData> metadata,
|
std::unique_ptr<AssetMetaData> metadata,
|
||||||
const AssetLibrary &owner_asset_library);
|
const AssetLibrary &owner_asset_library);
|
||||||
/**
|
/**
|
||||||
|
@ -85,6 +88,7 @@ class AssetRepresentation {
|
||||||
std::unique_ptr<AssetWeakReference> make_weak_reference() const;
|
std::unique_ptr<AssetWeakReference> make_weak_reference() const;
|
||||||
|
|
||||||
StringRefNull get_name() const;
|
StringRefNull get_name() const;
|
||||||
|
ID_Type get_id_type() const;
|
||||||
AssetMetaData &get_metadata() const;
|
AssetMetaData &get_metadata() const;
|
||||||
/**
|
/**
|
||||||
* Get the import method to use for this asset. A different one may be used if
|
* Get the import method to use for this asset. A different one may be used if
|
||||||
|
@ -114,6 +118,9 @@ class AssetRepresentation {
|
||||||
/* C-Handle */
|
/* C-Handle */
|
||||||
struct AssetRepresentation;
|
struct AssetRepresentation;
|
||||||
|
|
||||||
|
const blender::StringRefNull AS_asset_representation_library_relative_identifier_get(
|
||||||
|
const AssetRepresentation *asset_handle);
|
||||||
|
|
||||||
std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *asset);
|
std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *asset);
|
||||||
/**
|
/**
|
||||||
* Get the absolute path to the .blend file containing the given asset. String will be empty if
|
* Get the absolute path to the .blend file containing the given asset. String will be empty if
|
||||||
|
@ -123,5 +130,3 @@ std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *a
|
||||||
std::string AS_asset_representation_full_library_path_get(const ::AssetRepresentation *asset);
|
std::string AS_asset_representation_full_library_path_get(const ::AssetRepresentation *asset);
|
||||||
std::optional<eAssetImportMethod> AS_asset_representation_import_method_get(
|
std::optional<eAssetImportMethod> AS_asset_representation_import_method_get(
|
||||||
const ::AssetRepresentation *asset_handle);
|
const ::AssetRepresentation *asset_handle);
|
||||||
bool AS_asset_representation_may_override_import_method(const ::AssetRepresentation *asset_handle);
|
|
||||||
bool AS_asset_representation_use_relative_path_get(const ::AssetRepresentation *asset_handle);
|
|
||||||
|
|
|
@ -230,11 +230,12 @@ void AssetLibrary::refresh()
|
||||||
|
|
||||||
AssetRepresentation &AssetLibrary::add_external_asset(StringRef relative_asset_path,
|
AssetRepresentation &AssetLibrary::add_external_asset(StringRef relative_asset_path,
|
||||||
StringRef name,
|
StringRef name,
|
||||||
|
const int id_type,
|
||||||
std::unique_ptr<AssetMetaData> metadata)
|
std::unique_ptr<AssetMetaData> metadata)
|
||||||
{
|
{
|
||||||
AssetIdentifier identifier = asset_identifier_from_library(relative_asset_path);
|
AssetIdentifier identifier = asset_identifier_from_library(relative_asset_path);
|
||||||
return asset_storage_->add_external_asset(
|
return asset_storage_->add_external_asset(
|
||||||
std::move(identifier), name, std::move(metadata), *this);
|
std::move(identifier), name, id_type, std::move(metadata), *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetRepresentation &AssetLibrary::add_local_id_asset(StringRef relative_asset_path, ID &id)
|
AssetRepresentation &AssetLibrary::add_local_id_asset(StringRef relative_asset_path, ID &id)
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace blender::asset_system {
|
||||||
|
|
||||||
AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
|
AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
|
||||||
StringRef name,
|
StringRef name,
|
||||||
|
const int id_type,
|
||||||
std::unique_ptr<AssetMetaData> metadata,
|
std::unique_ptr<AssetMetaData> metadata,
|
||||||
const AssetLibrary &owner_asset_library)
|
const AssetLibrary &owner_asset_library)
|
||||||
: identifier_(identifier),
|
: identifier_(identifier),
|
||||||
|
@ -29,6 +30,7 @@ AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
|
||||||
external_asset_()
|
external_asset_()
|
||||||
{
|
{
|
||||||
external_asset_.name = name;
|
external_asset_.name = name;
|
||||||
|
external_asset_.id_type = id_type;
|
||||||
external_asset_.metadata_ = std::move(metadata);
|
external_asset_.metadata_ = std::move(metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +89,15 @@ StringRefNull AssetRepresentation::get_name() const
|
||||||
return external_asset_.name;
|
return external_asset_.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ID_Type AssetRepresentation::get_id_type() const
|
||||||
|
{
|
||||||
|
if (is_local_id_) {
|
||||||
|
return GS(local_asset_id_->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ID_Type(external_asset_.id_type);
|
||||||
|
}
|
||||||
|
|
||||||
AssetMetaData &AssetRepresentation::get_metadata() const
|
AssetMetaData &AssetRepresentation::get_metadata() const
|
||||||
{
|
{
|
||||||
return is_local_id_ ? *local_asset_id_->asset_data : *external_asset_.metadata_;
|
return is_local_id_ ? *local_asset_id_->asset_data : *external_asset_.metadata_;
|
||||||
|
@ -135,6 +146,15 @@ const AssetLibrary &AssetRepresentation::owner_asset_library() const
|
||||||
|
|
||||||
using namespace blender;
|
using namespace blender;
|
||||||
|
|
||||||
|
const StringRefNull AS_asset_representation_library_relative_identifier_get(
|
||||||
|
const AssetRepresentation *asset_handle)
|
||||||
|
{
|
||||||
|
const asset_system::AssetRepresentation *asset =
|
||||||
|
reinterpret_cast<const asset_system::AssetRepresentation *>(asset_handle);
|
||||||
|
const asset_system::AssetIdentifier &identifier = asset->get_identifier();
|
||||||
|
return identifier.library_relative_identifier();
|
||||||
|
}
|
||||||
|
|
||||||
std::string AS_asset_representation_full_path_get(const AssetRepresentation *asset_handle)
|
std::string AS_asset_representation_full_path_get(const AssetRepresentation *asset_handle)
|
||||||
{
|
{
|
||||||
const asset_system::AssetRepresentation *asset =
|
const asset_system::AssetRepresentation *asset =
|
||||||
|
@ -183,6 +203,13 @@ const char *AS_asset_representation_name_get(const AssetRepresentation *asset_ha
|
||||||
return asset->get_name().c_str();
|
return asset->get_name().c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ID_Type AS_asset_representation_id_type_get(const AssetRepresentation *asset_handle)
|
||||||
|
{
|
||||||
|
const asset_system::AssetRepresentation *asset =
|
||||||
|
reinterpret_cast<const asset_system::AssetRepresentation *>(asset_handle);
|
||||||
|
return asset->get_id_type();
|
||||||
|
}
|
||||||
|
|
||||||
AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset_handle)
|
AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset_handle)
|
||||||
{
|
{
|
||||||
const asset_system::AssetRepresentation *asset =
|
const asset_system::AssetRepresentation *asset =
|
||||||
|
|
|
@ -27,11 +27,12 @@ AssetRepresentation &AssetStorage::add_local_id_asset(AssetIdentifier &&identifi
|
||||||
|
|
||||||
AssetRepresentation &AssetStorage::add_external_asset(AssetIdentifier &&identifier,
|
AssetRepresentation &AssetStorage::add_external_asset(AssetIdentifier &&identifier,
|
||||||
StringRef name,
|
StringRef name,
|
||||||
|
const int id_type,
|
||||||
std::unique_ptr<AssetMetaData> metadata,
|
std::unique_ptr<AssetMetaData> metadata,
|
||||||
const AssetLibrary &owner_asset_library)
|
const AssetLibrary &owner_asset_library)
|
||||||
{
|
{
|
||||||
return *external_assets_.lookup_key_or_add(std::make_unique<AssetRepresentation>(
|
return *external_assets_.lookup_key_or_add(std::make_unique<AssetRepresentation>(
|
||||||
std::move(identifier), name, std::move(metadata), owner_asset_library));
|
std::move(identifier), name, id_type, std::move(metadata), owner_asset_library));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssetStorage::remove_asset(AssetRepresentation &asset)
|
bool AssetStorage::remove_asset(AssetRepresentation &asset)
|
||||||
|
|
|
@ -37,6 +37,7 @@ class AssetStorage {
|
||||||
/** See #AssetLibrary::add_external_asset(). */
|
/** See #AssetLibrary::add_external_asset(). */
|
||||||
AssetRepresentation &add_external_asset(AssetIdentifier &&identifier,
|
AssetRepresentation &add_external_asset(AssetIdentifier &&identifier,
|
||||||
StringRef name,
|
StringRef name,
|
||||||
|
int id_type,
|
||||||
std::unique_ptr<AssetMetaData> metadata,
|
std::unique_ptr<AssetMetaData> metadata,
|
||||||
const AssetLibrary &owner_asset_library);
|
const AssetLibrary &owner_asset_library);
|
||||||
/** See #AssetLibrary::add_external_asset(). */
|
/** See #AssetLibrary::add_external_asset(). */
|
||||||
|
|
|
@ -32,7 +32,8 @@ class AssetRepresentationTest : public AssetLibraryTestBase {
|
||||||
AssetRepresentation &add_dummy_asset(AssetLibrary &library, StringRef relative_path)
|
AssetRepresentation &add_dummy_asset(AssetLibrary &library, StringRef relative_path)
|
||||||
{
|
{
|
||||||
std::unique_ptr<AssetMetaData> dummy_metadata = std::make_unique<AssetMetaData>();
|
std::unique_ptr<AssetMetaData> dummy_metadata = std::make_unique<AssetMetaData>();
|
||||||
return library.add_external_asset(relative_path, "Some asset name", std::move(dummy_metadata));
|
return library.add_external_asset(
|
||||||
|
relative_path, "Some asset name", 0, std::move(dummy_metadata));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,13 +27,13 @@ extern "C" {
|
||||||
|
|
||||||
/* Blender file format version. */
|
/* Blender file format version. */
|
||||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||||
#define BLENDER_FILE_SUBVERSION 5
|
#define BLENDER_FILE_SUBVERSION 6
|
||||||
|
|
||||||
/* Minimum Blender version that supports reading file written with the current
|
/* Minimum Blender version that supports reading file written with the current
|
||||||
* version. Older Blender versions will test this and show a warning if the file
|
* version. Older Blender versions will test this and show a warning if the file
|
||||||
* was written with too new a version. */
|
* was written with too new a version. */
|
||||||
#define BLENDER_FILE_MIN_VERSION 400
|
#define BLENDER_FILE_MIN_VERSION 400
|
||||||
#define BLENDER_FILE_MIN_SUBVERSION 2
|
#define BLENDER_FILE_MIN_SUBVERSION 3
|
||||||
|
|
||||||
/** User readable version string. */
|
/** User readable version string. */
|
||||||
const char *BKE_blender_version_string(void);
|
const char *BKE_blender_version_string(void);
|
||||||
|
|
|
@ -733,7 +733,7 @@ enum {
|
||||||
typedef struct CustomDataTransferLayerMap {
|
typedef struct CustomDataTransferLayerMap {
|
||||||
struct CustomDataTransferLayerMap *next, *prev;
|
struct CustomDataTransferLayerMap *next, *prev;
|
||||||
|
|
||||||
eCustomDataType data_type;
|
int data_type;
|
||||||
int mix_mode;
|
int mix_mode;
|
||||||
float mix_factor;
|
float mix_factor;
|
||||||
/** If non-NULL, array of weights, one for each dest item, replaces mix_factor. */
|
/** If non-NULL, array of weights, one for each dest item, replaces mix_factor. */
|
||||||
|
|
|
@ -180,9 +180,6 @@ struct Mesh *BKE_mesh_new_nomain_from_curve_displist(const struct Object *ob,
|
||||||
|
|
||||||
bool BKE_mesh_attribute_required(const char *name);
|
bool BKE_mesh_attribute_required(const char *name);
|
||||||
|
|
||||||
bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me);
|
|
||||||
bool BKE_mesh_clear_facemap_customdata(struct Mesh *me);
|
|
||||||
|
|
||||||
float (*BKE_mesh_orco_verts_get(struct Object *ob))[3];
|
float (*BKE_mesh_orco_verts_get(struct Object *ob))[3];
|
||||||
void BKE_mesh_orco_verts_transform(struct Mesh *me, float (*orco)[3], int totvert, int invert);
|
void BKE_mesh_orco_verts_transform(struct Mesh *me, float (*orco)[3], int totvert, int invert);
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ struct CornerNormalSpaceArray {
|
||||||
*/
|
*/
|
||||||
Array<Array<int>> corners_by_space;
|
Array<Array<int>> corners_by_space;
|
||||||
/** Whether to create the above map when calculating normals. */
|
/** Whether to create the above map when calculating normals. */
|
||||||
bool create_corners_by_space;
|
bool create_corners_by_space = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
void lnor_space_custom_normal_to_data(const CornerNormalSpace *lnor_space,
|
void lnor_space_custom_normal_to_data(const CornerNormalSpace *lnor_space,
|
||||||
|
|
|
@ -84,6 +84,8 @@ void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh);
|
||||||
|
|
||||||
void BKE_mesh_legacy_convert_loops_to_corners(struct Mesh *mesh);
|
void BKE_mesh_legacy_convert_loops_to_corners(struct Mesh *mesh);
|
||||||
|
|
||||||
|
void BKE_mesh_legacy_face_map_to_generic(struct Mesh *mesh);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \ingroup bke
|
|
||||||
* \brief Functions for dealing with object face-maps.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct ListBase;
|
|
||||||
struct Object;
|
|
||||||
struct bFaceMap;
|
|
||||||
|
|
||||||
struct bFaceMap *BKE_object_facemap_add(struct Object *ob);
|
|
||||||
struct bFaceMap *BKE_object_facemap_add_name(struct Object *ob, const char *name);
|
|
||||||
void BKE_object_facemap_remove(struct Object *ob, struct bFaceMap *fmap);
|
|
||||||
void BKE_object_facemap_clear(struct Object *ob);
|
|
||||||
|
|
||||||
int BKE_object_facemap_name_index(struct Object *ob, const char *name);
|
|
||||||
void BKE_object_facemap_unique_name(struct Object *ob, struct bFaceMap *fmap);
|
|
||||||
struct bFaceMap *BKE_object_facemap_find_name(struct Object *ob, const char *name);
|
|
||||||
void BKE_object_facemap_copy_list(struct ListBase *outbase, const struct ListBase *inbase);
|
|
||||||
|
|
||||||
int *BKE_object_facemap_index_map_create(struct Object *ob_src,
|
|
||||||
struct Object *ob_dst,
|
|
||||||
int *r_map_len);
|
|
||||||
void BKE_object_facemap_index_map_apply(int *fmap, int fmap_len, const int *map, int map_len);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -255,7 +255,7 @@ typedef struct PanelType {
|
||||||
|
|
||||||
char idname[BKE_ST_MAXNAME]; /* unique name */
|
char idname[BKE_ST_MAXNAME]; /* unique name */
|
||||||
char label[BKE_ST_MAXNAME]; /* for panel header */
|
char label[BKE_ST_MAXNAME]; /* for panel header */
|
||||||
char *description; /* for panel tooltip */
|
const char *description; /* for panel tooltip */
|
||||||
char translation_context[BKE_ST_MAXNAME];
|
char translation_context[BKE_ST_MAXNAME];
|
||||||
char context[BKE_ST_MAXNAME]; /* for buttons window */
|
char context[BKE_ST_MAXNAME]; /* for buttons window */
|
||||||
char category[BKE_ST_MAXNAME]; /* for category tabs */
|
char category[BKE_ST_MAXNAME]; /* for category tabs */
|
||||||
|
|
|
@ -241,7 +241,6 @@ set(SRC
|
||||||
intern/object.cc
|
intern/object.cc
|
||||||
intern/object_deform.c
|
intern/object_deform.c
|
||||||
intern/object_dupli.cc
|
intern/object_dupli.cc
|
||||||
intern/object_facemap.c
|
|
||||||
intern/object_update.cc
|
intern/object_update.cc
|
||||||
intern/ocean.c
|
intern/ocean.c
|
||||||
intern/ocean_spectrum.c
|
intern/ocean_spectrum.c
|
||||||
|
@ -457,7 +456,6 @@ set(SRC
|
||||||
BKE_node_tree_zones.hh
|
BKE_node_tree_zones.hh
|
||||||
BKE_object.h
|
BKE_object.h
|
||||||
BKE_object_deform.h
|
BKE_object_deform.h
|
||||||
BKE_object_facemap.h
|
|
||||||
BKE_ocean.h
|
BKE_ocean.h
|
||||||
BKE_outliner_treehash.hh
|
BKE_outliner_treehash.hh
|
||||||
BKE_packedFile.h
|
BKE_packedFile.h
|
||||||
|
|
|
@ -1257,20 +1257,6 @@ static void layerSwap_flnor(void *data, const int *corner_indices)
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
|
||||||
/** \name Callbacks for (`int`, #CD_FACEMAP)
|
|
||||||
* \{ */
|
|
||||||
|
|
||||||
static void layerDefault_fmap(void *data, const int count)
|
|
||||||
{
|
|
||||||
int *fmap_num = (int *)data;
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
fmap_num[i] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \} */
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name Callbacks for (#MPropCol, #CD_PROP_COLOR)
|
/** \name Callbacks for (#MPropCol, #CD_PROP_COLOR)
|
||||||
* \{ */
|
* \{ */
|
||||||
|
@ -1628,8 +1614,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
layerCopyValue_normal},
|
layerCopyValue_normal},
|
||||||
/* 9: CD_FACEMAP */
|
/* 9: CD_FACEMAP */ /* DEPRECATED */
|
||||||
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, layerDefault_fmap, nullptr},
|
{sizeof(int), ""},
|
||||||
/* 10: CD_PROP_FLOAT */
|
/* 10: CD_PROP_FLOAT */
|
||||||
{sizeof(MFloatProperty),
|
{sizeof(MFloatProperty),
|
||||||
"MFloatProperty",
|
"MFloatProperty",
|
||||||
|
@ -1865,7 +1851,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
||||||
/* 41: CD_CUSTOMLOOPNORMAL */
|
/* 41: CD_CUSTOMLOOPNORMAL */
|
||||||
{sizeof(short[2]), "vec2s", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
{sizeof(short[2]), "vec2s", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||||
/* 42: CD_SCULPT_FACE_SETS */ /* DEPRECATED */
|
/* 42: CD_SCULPT_FACE_SETS */ /* DEPRECATED */
|
||||||
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
{sizeof(int), ""},
|
||||||
/* 43: CD_LOCATION */
|
/* 43: CD_LOCATION */
|
||||||
{sizeof(float[3]), "vec3f", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
{sizeof(float[3]), "vec3f", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||||
/* 44: CD_RADIUS */
|
/* 44: CD_RADIUS */
|
||||||
|
@ -2010,14 +1996,14 @@ const CustomData_MeshMasks CD_MASK_BAREMESH = {
|
||||||
/*vmask*/ CD_MASK_PROP_FLOAT3,
|
/*vmask*/ CD_MASK_PROP_FLOAT3,
|
||||||
/*emask*/ CD_MASK_PROP_INT32_2D,
|
/*emask*/ CD_MASK_PROP_INT32_2D,
|
||||||
/*fmask*/ 0,
|
/*fmask*/ 0,
|
||||||
/*pmask*/ CD_MASK_FACEMAP,
|
/*pmask*/ 0,
|
||||||
/*lmask*/ CD_MASK_PROP_INT32,
|
/*lmask*/ CD_MASK_PROP_INT32,
|
||||||
};
|
};
|
||||||
const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = {
|
const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = {
|
||||||
/*vmask*/ CD_MASK_PROP_FLOAT3 | CD_MASK_ORIGINDEX,
|
/*vmask*/ CD_MASK_PROP_FLOAT3 | CD_MASK_ORIGINDEX,
|
||||||
/*emask*/ CD_MASK_PROP_INT32_2D | CD_MASK_ORIGINDEX,
|
/*emask*/ CD_MASK_PROP_INT32_2D | CD_MASK_ORIGINDEX,
|
||||||
/*fmask*/ 0,
|
/*fmask*/ 0,
|
||||||
/*pmask*/ CD_MASK_FACEMAP | CD_MASK_ORIGINDEX,
|
/*pmask*/ CD_MASK_ORIGINDEX,
|
||||||
/*lmask*/ CD_MASK_PROP_INT32,
|
/*lmask*/ CD_MASK_PROP_INT32,
|
||||||
};
|
};
|
||||||
const CustomData_MeshMasks CD_MASK_MESH = {
|
const CustomData_MeshMasks CD_MASK_MESH = {
|
||||||
|
@ -2027,7 +2013,7 @@ const CustomData_MeshMasks CD_MASK_MESH = {
|
||||||
(CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_CREASE),
|
(CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_CREASE),
|
||||||
/*fmask*/ 0,
|
/*fmask*/ 0,
|
||||||
/*pmask*/
|
/*pmask*/
|
||||||
(CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
|
(CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
|
||||||
/*lmask*/
|
/*lmask*/
|
||||||
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
|
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
|
||||||
};
|
};
|
||||||
|
@ -2039,7 +2025,7 @@ const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
|
||||||
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_CREASE),
|
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_CREASE),
|
||||||
/*fmask*/ (CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_PREVIEW_MCOL | CD_MASK_TANGENT),
|
/*fmask*/ (CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_PREVIEW_MCOL | CD_MASK_TANGENT),
|
||||||
/*pmask*/
|
/*pmask*/
|
||||||
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL),
|
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
|
||||||
/*lmask*/
|
/*lmask*/
|
||||||
(CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
|
(CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
|
||||||
CD_MASK_PROP_ALL), /* XXX: MISSING #CD_MASK_MLOOPTANGENT ? */
|
CD_MASK_PROP_ALL), /* XXX: MISSING #CD_MASK_MLOOPTANGENT ? */
|
||||||
|
@ -2050,7 +2036,7 @@ const CustomData_MeshMasks CD_MASK_BMESH = {
|
||||||
/*emask*/ (CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
|
/*emask*/ (CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
|
||||||
/*fmask*/ 0,
|
/*fmask*/ 0,
|
||||||
/*pmask*/
|
/*pmask*/
|
||||||
(CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL),
|
(CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
|
||||||
/*lmask*/
|
/*lmask*/
|
||||||
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
|
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
|
||||||
};
|
};
|
||||||
|
@ -2066,8 +2052,7 @@ const CustomData_MeshMasks CD_MASK_EVERYTHING = {
|
||||||
CD_MASK_ORIGSPACE | CD_MASK_TANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_PREVIEW_MCOL |
|
CD_MASK_ORIGSPACE | CD_MASK_TANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_PREVIEW_MCOL |
|
||||||
CD_MASK_PROP_ALL),
|
CD_MASK_PROP_ALL),
|
||||||
/*pmask*/
|
/*pmask*/
|
||||||
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE |
|
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
|
||||||
CD_MASK_PROP_ALL),
|
|
||||||
/*lmask*/
|
/*lmask*/
|
||||||
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL |
|
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL |
|
||||||
CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
|
CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
|
||||||
|
@ -4880,7 +4865,7 @@ static void customdata_data_transfer_interp_generic(const CustomDataTransferLaye
|
||||||
* more than 0.5 of weight. */
|
* more than 0.5 of weight. */
|
||||||
int best_src_idx = 0;
|
int best_src_idx = 0;
|
||||||
|
|
||||||
const eCustomDataType data_type = laymap->data_type;
|
const int data_type = laymap->data_type;
|
||||||
const int mix_mode = laymap->mix_mode;
|
const int mix_mode = laymap->mix_mode;
|
||||||
|
|
||||||
size_t data_size;
|
size_t data_size;
|
||||||
|
@ -4898,7 +4883,7 @@ static void customdata_data_transfer_interp_generic(const CustomDataTransferLaye
|
||||||
data_size = laymap->data_size;
|
data_size = laymap->data_size;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const LayerTypeInfo *type_info = layerType_getInfo(data_type);
|
const LayerTypeInfo *type_info = layerType_getInfo(eCustomDataType(data_type));
|
||||||
|
|
||||||
data_size = size_t(type_info->size);
|
data_size = size_t(type_info->size);
|
||||||
interp_cd = type_info->interp;
|
interp_cd = type_info->interp;
|
||||||
|
@ -4967,7 +4952,7 @@ static void customdata_data_transfer_interp_generic(const CustomDataTransferLaye
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!(int(data_type) & CD_FAKE)) {
|
else if (!(int(data_type) & CD_FAKE)) {
|
||||||
CustomData_data_mix_value(data_type, tmp_dst, data_dst, mix_mode, mix_factor);
|
CustomData_data_mix_value(eCustomDataType(data_type), tmp_dst, data_dst, mix_mode, mix_factor);
|
||||||
}
|
}
|
||||||
/* Else we can do nothing by default, needs custom interp func!
|
/* Else we can do nothing by default, needs custom interp func!
|
||||||
* Note this is here only for sake of consistency, not expected to be used much actually? */
|
* Note this is here only for sake of consistency, not expected to be used much actually? */
|
||||||
|
@ -4990,7 +4975,8 @@ void customdata_data_transfer_interp_normal_normals(const CustomDataTransferLaye
|
||||||
BLI_assert(weights != nullptr);
|
BLI_assert(weights != nullptr);
|
||||||
BLI_assert(count > 0);
|
BLI_assert(count > 0);
|
||||||
|
|
||||||
const eCustomDataType data_type = laymap->data_type;
|
const eCustomDataType data_type = eCustomDataType(laymap->data_type);
|
||||||
|
BLI_assert(data_type == CD_NORMAL);
|
||||||
const int mix_mode = laymap->mix_mode;
|
const int mix_mode = laymap->mix_mode;
|
||||||
|
|
||||||
SpaceTransform *space_transform = static_cast<SpaceTransform *>(laymap->interp_data);
|
SpaceTransform *space_transform = static_cast<SpaceTransform *>(laymap->interp_data);
|
||||||
|
@ -5000,8 +4986,6 @@ void customdata_data_transfer_interp_normal_normals(const CustomDataTransferLaye
|
||||||
|
|
||||||
float tmp_dst[3];
|
float tmp_dst[3];
|
||||||
|
|
||||||
BLI_assert(data_type == CD_NORMAL);
|
|
||||||
|
|
||||||
if (!sources) {
|
if (!sources) {
|
||||||
/* Not supported here, abort. */
|
/* Not supported here, abort. */
|
||||||
return;
|
return;
|
||||||
|
@ -5022,7 +5006,7 @@ void CustomData_data_transfer(const MeshPairRemap *me_remap,
|
||||||
MeshPairRemapItem *mapit = me_remap->items;
|
MeshPairRemapItem *mapit = me_remap->items;
|
||||||
const int totelem = me_remap->items_num;
|
const int totelem = me_remap->items_num;
|
||||||
|
|
||||||
const eCustomDataType data_type = laymap->data_type;
|
const int data_type = laymap->data_type;
|
||||||
const void *data_src = laymap->data_src;
|
const void *data_src = laymap->data_src;
|
||||||
void *data_dst = laymap->data_dst;
|
void *data_dst = laymap->data_dst;
|
||||||
|
|
||||||
|
@ -5051,7 +5035,7 @@ void CustomData_data_transfer(const MeshPairRemap *me_remap,
|
||||||
data_offset = laymap->data_offset;
|
data_offset = laymap->data_offset;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const LayerTypeInfo *type_info = layerType_getInfo(data_type);
|
const LayerTypeInfo *type_info = layerType_getInfo(eCustomDataType(data_type));
|
||||||
|
|
||||||
/* NOTE: we can use 'fake' CDLayers for crease :/. */
|
/* NOTE: we can use 'fake' CDLayers for crease :/. */
|
||||||
data_size = size_t(type_info->size);
|
data_size = size_t(type_info->size);
|
||||||
|
@ -5169,9 +5153,6 @@ void CustomData_blend_write(BlendWriter *writer,
|
||||||
case CD_GRID_PAINT_MASK:
|
case CD_GRID_PAINT_MASK:
|
||||||
write_grid_paint_mask(writer, count, static_cast<const GridPaintMask *>(layer.data));
|
write_grid_paint_mask(writer, count, static_cast<const GridPaintMask *>(layer.data));
|
||||||
break;
|
break;
|
||||||
case CD_FACEMAP:
|
|
||||||
BLO_write_raw(writer, sizeof(int) * count, static_cast<const int *>(layer.data));
|
|
||||||
break;
|
|
||||||
case CD_PROP_BOOL:
|
case CD_PROP_BOOL:
|
||||||
BLO_write_raw(writer, sizeof(bool) * count, static_cast<const bool *>(layer.data));
|
BLO_write_raw(writer, sizeof(bool) * count, static_cast<const bool *>(layer.data));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -808,44 +808,6 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BKE_mesh_ensure_facemap_customdata(Mesh *me)
|
|
||||||
{
|
|
||||||
BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr;
|
|
||||||
bool changed = false;
|
|
||||||
if (bm) {
|
|
||||||
if (!CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
|
|
||||||
BM_data_layer_add(bm, &bm->pdata, CD_FACEMAP);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
|
|
||||||
CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_SET_DEFAULT, me->totpoly);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BKE_mesh_clear_facemap_customdata(Mesh *me)
|
|
||||||
{
|
|
||||||
BMesh *bm = me->edit_mesh ? me->edit_mesh->bm : nullptr;
|
|
||||||
bool changed = false;
|
|
||||||
if (bm) {
|
|
||||||
if (CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
|
|
||||||
BM_data_layer_free(bm, &bm->pdata, CD_FACEMAP);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
|
|
||||||
CustomData_free_layers(&me->pdata, CD_FACEMAP, me->totpoly);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BKE_mesh_has_custom_loop_normals(Mesh *me)
|
bool BKE_mesh_has_custom_loop_normals(Mesh *me)
|
||||||
{
|
{
|
||||||
if (me->edit_mesh) {
|
if (me->edit_mesh) {
|
||||||
|
|
|
@ -1305,6 +1305,40 @@ void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Face Map Conversion
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
void BKE_mesh_legacy_face_map_to_generic(Mesh *mesh)
|
||||||
|
{
|
||||||
|
using namespace blender;
|
||||||
|
if (mesh->attributes().contains("face_maps")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void *data = nullptr;
|
||||||
|
const ImplicitSharingInfo *sharing_info = nullptr;
|
||||||
|
for (const int i : IndexRange(mesh->pdata.totlayer)) {
|
||||||
|
CustomDataLayer &layer = mesh->pdata.layers[i];
|
||||||
|
if (layer.type == CD_FACEMAP) {
|
||||||
|
data = layer.data;
|
||||||
|
sharing_info = layer.sharing_info;
|
||||||
|
layer.data = nullptr;
|
||||||
|
layer.sharing_info = nullptr;
|
||||||
|
CustomData_free_layer(&mesh->pdata, CD_FACEMAP, mesh->totpoly, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data != nullptr) {
|
||||||
|
CustomData_add_layer_named_with_data(
|
||||||
|
&mesh->pdata, CD_PROP_INT32, data, mesh->totpoly, "face_maps", sharing_info);
|
||||||
|
}
|
||||||
|
if (sharing_info != nullptr) {
|
||||||
|
sharing_info->remove_user_and_delete_if_last();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name Bevel Weight Conversion
|
/** \name Bevel Weight Conversion
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
|
@ -628,7 +628,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
|
||||||
|
|
||||||
if (mesh_remap_bvhtree_query_nearest(
|
if (mesh_remap_bvhtree_query_nearest(
|
||||||
&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
|
&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
|
||||||
const int poly_index = looptri_polys[rayhit.index];
|
const int poly_index = looptri_polys[nearest.index];
|
||||||
|
|
||||||
if (mode == MREMAP_MODE_VERT_POLY_NEAREST) {
|
if (mode == MREMAP_MODE_VERT_POLY_NEAREST) {
|
||||||
int index;
|
int index;
|
||||||
|
@ -886,7 +886,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
|
||||||
|
|
||||||
if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist))
|
if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist))
|
||||||
{
|
{
|
||||||
const int poly_index = looptri_polys[rayhit.index];
|
const int poly_index = looptri_polys[nearest.index];
|
||||||
const blender::IndexRange poly_src = polys_src[poly_index];
|
const blender::IndexRange poly_src = polys_src[poly_index];
|
||||||
const int *corner_edge_src = &corner_edges_src[poly_src.start()];
|
const int *corner_edge_src = &corner_edges_src[poly_src.start()];
|
||||||
int nloops = int(poly_src.size());
|
int nloops = int(poly_src.size());
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
#include "BLI_array.hh"
|
#include "BLI_array.hh"
|
||||||
|
#include "BLI_array_utils.hh"
|
||||||
#include "BLI_index_range.hh"
|
#include "BLI_index_range.hh"
|
||||||
#include "BLI_math_vector.h"
|
#include "BLI_math_vector.h"
|
||||||
#include "BLI_math_vector_types.hh"
|
|
||||||
#include "BLI_span.hh"
|
#include "BLI_span.hh"
|
||||||
#include "BLI_task.hh"
|
#include "BLI_task.hh"
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "BKE_attribute.h"
|
#include "BKE_attribute.h"
|
||||||
#include "BKE_attribute.hh"
|
#include "BKE_attribute.hh"
|
||||||
|
#include "BKE_attribute_math.hh"
|
||||||
#include "BKE_bvhutils.h"
|
#include "BKE_bvhutils.h"
|
||||||
#include "BKE_customdata.h"
|
#include "BKE_customdata.h"
|
||||||
#include "BKE_editmesh.h"
|
#include "BKE_editmesh.h"
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
#include "BKE_mesh_mapping.h"
|
#include "BKE_mesh_mapping.h"
|
||||||
#include "BKE_mesh_remesh_voxel.h" /* own include */
|
#include "BKE_mesh_remesh_voxel.h" /* own include */
|
||||||
#include "BKE_mesh_runtime.h"
|
#include "BKE_mesh_runtime.h"
|
||||||
|
#include "BKE_mesh_sample.hh"
|
||||||
|
|
||||||
#include "bmesh_tools.h"
|
#include "bmesh_tools.h"
|
||||||
|
|
||||||
|
@ -360,116 +362,104 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
|
||||||
|
|
||||||
void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
|
void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
|
||||||
{
|
{
|
||||||
BVHTreeFromMesh bvhtree = {nullptr};
|
using namespace blender;
|
||||||
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2);
|
using namespace blender::bke;
|
||||||
|
const AttributeAccessor src_attributes = source->attributes();
|
||||||
|
MutableAttributeAccessor dst_attributes = target->attributes_for_write();
|
||||||
|
|
||||||
int i = 0;
|
Vector<AttributeIDRef> point_ids;
|
||||||
const CustomDataLayer *layer;
|
Vector<AttributeIDRef> corner_ids;
|
||||||
|
source->attributes().for_all([&](const AttributeIDRef &id, const AttributeMetaData &meta_data) {
|
||||||
|
if (CD_TYPE_AS_MASK(meta_data.data_type) & CD_MASK_COLOR_ALL) {
|
||||||
|
if (meta_data.domain == ATTR_DOMAIN_POINT) {
|
||||||
|
point_ids.append(id);
|
||||||
|
}
|
||||||
|
else if (meta_data.domain == ATTR_DOMAIN_CORNER) {
|
||||||
|
corner_ids.append(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (point_ids.is_empty() && corner_ids.is_empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Array<int> source_vert_to_loop_offsets;
|
Array<int> source_vert_to_loop_offsets;
|
||||||
Array<int> source_vert_to_loop_indices;
|
Array<int> source_vert_to_loop_indices;
|
||||||
blender::GroupedSpan<int> source_lmap;
|
GroupedSpan<int> source_lmap;
|
||||||
|
|
||||||
Array<int> target_vert_to_loop_offsets;
|
Array<int> target_vert_to_loop_offsets;
|
||||||
Array<int> target_vert_to_loop_indices;
|
Array<int> target_vert_to_loop_indices;
|
||||||
blender::GroupedSpan<int> target_lmap;
|
GroupedSpan<int> target_lmap;
|
||||||
|
BVHTreeFromMesh bvhtree = {nullptr};
|
||||||
|
threading::parallel_invoke(
|
||||||
|
[&]() { BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2); },
|
||||||
|
[&]() {
|
||||||
|
source_lmap = mesh::build_vert_to_loop_map(source->corner_verts(),
|
||||||
|
source->totvert,
|
||||||
|
source_vert_to_loop_offsets,
|
||||||
|
source_vert_to_loop_indices);
|
||||||
|
},
|
||||||
|
[&]() {
|
||||||
|
target_lmap = mesh::build_vert_to_loop_map(target->corner_verts(),
|
||||||
|
target->totvert,
|
||||||
|
target_vert_to_loop_offsets,
|
||||||
|
target_vert_to_loop_indices);
|
||||||
|
});
|
||||||
|
|
||||||
while ((layer = BKE_id_attribute_from_index(
|
const Span<float3> target_positions = target->vert_positions();
|
||||||
const_cast<ID *>(&source->id), i++, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL)))
|
Array<int> nearest_src_verts(target_positions.size());
|
||||||
{
|
threading::parallel_for(target_positions.index_range(), 1024, [&](const IndexRange range) {
|
||||||
eAttrDomain domain = BKE_id_attribute_domain(&source->id, layer);
|
for (const int i : range) {
|
||||||
const eCustomDataType type = eCustomDataType(layer->type);
|
BVHTreeNearest nearest;
|
||||||
|
nearest.index = -1;
|
||||||
CustomData *target_cdata = domain == ATTR_DOMAIN_POINT ? &target->vdata : &target->ldata;
|
nearest.dist_sq = FLT_MAX;
|
||||||
const CustomData *source_cdata = domain == ATTR_DOMAIN_POINT ? &source->vdata : &source->ldata;
|
BLI_bvhtree_find_nearest(
|
||||||
|
bvhtree.tree, target_positions[i], &nearest, bvhtree.nearest_callback, &bvhtree);
|
||||||
/* Check attribute exists in target. */
|
nearest_src_verts[i] = nearest.index;
|
||||||
int layer_i = CustomData_get_named_layer_index(target_cdata, type, layer->name);
|
|
||||||
if (layer_i == -1) {
|
|
||||||
int elem_num = domain == ATTR_DOMAIN_POINT ? target->totvert : target->totloop;
|
|
||||||
|
|
||||||
CustomData_add_layer_named(target_cdata, type, CD_SET_DEFAULT, elem_num, layer->name);
|
|
||||||
layer_i = CustomData_get_named_layer_index(target_cdata, type, layer->name);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
size_t data_size = CustomData_sizeof(type);
|
for (const AttributeIDRef &id : point_ids) {
|
||||||
void *target_data = target_cdata->layers[layer_i].data;
|
const GVArraySpan src = *src_attributes.lookup(id, ATTR_DOMAIN_POINT);
|
||||||
void *source_data = layer->data;
|
GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
|
||||||
const Span<float3> target_positions = target->vert_positions();
|
id, ATTR_DOMAIN_POINT, cpp_type_to_custom_data_type(src.type()));
|
||||||
|
attribute_math::gather(src, nearest_src_verts, dst.span);
|
||||||
|
dst.finish();
|
||||||
|
}
|
||||||
|
|
||||||
if (domain == ATTR_DOMAIN_POINT) {
|
if (!corner_ids.is_empty()) {
|
||||||
blender::threading::parallel_for(
|
for (const AttributeIDRef &id : corner_ids) {
|
||||||
IndexRange(target->totvert), 4096, [&](const IndexRange range) {
|
const GVArraySpan src = *src_attributes.lookup(id, ATTR_DOMAIN_CORNER);
|
||||||
for (const int i : range) {
|
GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
|
||||||
BVHTreeNearest nearest;
|
id, ATTR_DOMAIN_CORNER, cpp_type_to_custom_data_type(src.type()));
|
||||||
nearest.index = -1;
|
|
||||||
nearest.dist_sq = FLT_MAX;
|
threading::parallel_for(target_positions.index_range(), 1024, [&](const IndexRange range) {
|
||||||
BLI_bvhtree_find_nearest(
|
src.type().to_static_type_tag<ColorGeometry4b, ColorGeometry4f>([&](auto type_tag) {
|
||||||
bvhtree.tree, target_positions[i], &nearest, bvhtree.nearest_callback, &bvhtree);
|
using T = typename decltype(type_tag)::type;
|
||||||
if (nearest.index != -1) {
|
if constexpr (std::is_void_v<T>) {
|
||||||
memcpy(POINTER_OFFSET(target_data, size_t(i) * data_size),
|
BLI_assert_unreachable();
|
||||||
POINTER_OFFSET(source_data, size_t(nearest.index) * data_size),
|
}
|
||||||
data_size);
|
else {
|
||||||
|
const Span<T> src_typed = src.typed<T>();
|
||||||
|
MutableSpan<T> dst_typed = dst.span.typed<T>();
|
||||||
|
for (const int dst_vert : range) {
|
||||||
|
/* Find the average value at the corners of the closest vertex on the
|
||||||
|
* source mesh. */
|
||||||
|
const int src_vert = nearest_src_verts[dst_vert];
|
||||||
|
T value;
|
||||||
|
typename blender::bke::attribute_math::DefaultMixer<T> mixer({&value, 1});
|
||||||
|
for (const int corner : source_lmap[src_vert]) {
|
||||||
|
mixer.mix_in(0, src_typed[corner]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dst_typed.fill_indices(target_lmap[dst_vert], value);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
else {
|
});
|
||||||
/* Lazily init vertex -> loop maps. */
|
|
||||||
if (source_lmap.is_empty()) {
|
|
||||||
source_lmap = blender::bke::mesh::build_vert_to_loop_map(source->corner_verts(),
|
|
||||||
source->totvert,
|
|
||||||
source_vert_to_loop_offsets,
|
|
||||||
source_vert_to_loop_indices);
|
|
||||||
target_lmap = blender::bke::mesh::build_vert_to_loop_map(target->corner_verts(),
|
|
||||||
target->totvert,
|
|
||||||
target_vert_to_loop_offsets,
|
|
||||||
target_vert_to_loop_indices);
|
|
||||||
}
|
|
||||||
|
|
||||||
blender::threading::parallel_for(
|
dst.finish();
|
||||||
IndexRange(target->totvert), 2048, [&](const IndexRange range) {
|
|
||||||
for (const int i : range) {
|
|
||||||
BVHTreeNearest nearest;
|
|
||||||
nearest.index = -1;
|
|
||||||
nearest.dist_sq = FLT_MAX;
|
|
||||||
BLI_bvhtree_find_nearest(
|
|
||||||
bvhtree.tree, target_positions[i], &nearest, bvhtree.nearest_callback, &bvhtree);
|
|
||||||
|
|
||||||
if (nearest.index == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Span<int> source_loops = source_lmap[nearest.index];
|
|
||||||
const Span<int> target_loops = target_lmap[i];
|
|
||||||
|
|
||||||
if (target_loops.size() == 0 || source_loops.size() == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Average color data for loops around the source vertex into
|
|
||||||
* the first target loop around the target vertex
|
|
||||||
*/
|
|
||||||
|
|
||||||
CustomData_interp(source_cdata,
|
|
||||||
target_cdata,
|
|
||||||
source_loops.data(),
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
source_loops.size(),
|
|
||||||
target_loops[0]);
|
|
||||||
|
|
||||||
void *elem = POINTER_OFFSET(target_data, size_t(target_loops[0]) * data_size);
|
|
||||||
|
|
||||||
/* Copy to rest of target loops. */
|
|
||||||
for (int j = 1; j < target_loops.size(); j++) {
|
|
||||||
memcpy(POINTER_OFFSET(target_data, size_t(target_loops[j]) * data_size),
|
|
||||||
elem,
|
|
||||||
data_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,15 +70,8 @@ bool multiresModifier_reshapeFromObject(Depsgraph *depsgraph,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int num_deformed_verts;
|
return multiresModifier_reshapeFromVertcos(
|
||||||
float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(src_mesh_eval, &num_deformed_verts);
|
depsgraph, dst, mmd, BKE_mesh_vert_positions(src_mesh_eval), src_mesh_eval->totvert);
|
||||||
|
|
||||||
const bool result = multiresModifier_reshapeFromVertcos(
|
|
||||||
depsgraph, dst, mmd, deformed_verts, num_deformed_verts);
|
|
||||||
|
|
||||||
MEM_freeN(deformed_verts);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
|
@ -759,6 +759,10 @@ class NodeTreeMainUpdater {
|
||||||
|
|
||||||
LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
|
LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
|
||||||
link->flag |= NODE_LINK_VALID;
|
link->flag |= NODE_LINK_VALID;
|
||||||
|
if (!link->fromsock->is_available() || !link->tosock->is_available()) {
|
||||||
|
link->flag &= ~NODE_LINK_VALID;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const bNode &from_node = *link->fromnode;
|
const bNode &from_node = *link->fromnode;
|
||||||
const bNode &to_node = *link->tonode;
|
const bNode &to_node = *link->tonode;
|
||||||
if (toposort_indices[from_node.index()] > toposort_indices[to_node.index()]) {
|
if (toposort_indices[from_node.index()] > toposort_indices[to_node.index()]) {
|
||||||
|
|
|
@ -114,7 +114,6 @@
|
||||||
#include "BKE_multires.h"
|
#include "BKE_multires.h"
|
||||||
#include "BKE_node.hh"
|
#include "BKE_node.hh"
|
||||||
#include "BKE_object.h"
|
#include "BKE_object.h"
|
||||||
#include "BKE_object_facemap.h"
|
|
||||||
#include "BKE_paint.h"
|
#include "BKE_paint.h"
|
||||||
#include "BKE_particle.h"
|
#include "BKE_particle.h"
|
||||||
#include "BKE_pbvh.h"
|
#include "BKE_pbvh.h"
|
||||||
|
@ -233,7 +232,6 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BKE_object_facemap_copy_list(&ob_dst->fmaps, &ob_src->fmaps);
|
|
||||||
BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true);
|
BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true);
|
||||||
|
|
||||||
ob_dst->mode = ob_dst->type != OB_GPENCIL_LEGACY ? OB_MODE_OBJECT : ob_dst->mode;
|
ob_dst->mode = ob_dst->type != OB_GPENCIL_LEGACY ? OB_MODE_OBJECT : ob_dst->mode;
|
||||||
|
@ -302,7 +300,6 @@ static void object_free_data(ID *id)
|
||||||
MEM_SAFE_FREE(ob->iuser);
|
MEM_SAFE_FREE(ob->iuser);
|
||||||
MEM_SAFE_FREE(ob->runtime.bb);
|
MEM_SAFE_FREE(ob->runtime.bb);
|
||||||
|
|
||||||
BLI_freelistN(&ob->fmaps);
|
|
||||||
if (ob->pose) {
|
if (ob->pose) {
|
||||||
BKE_pose_free_ex(ob->pose, false);
|
BKE_pose_free_ex(ob->pose, false);
|
||||||
ob->pose = nullptr;
|
ob->pose = nullptr;
|
||||||
|
@ -546,13 +543,6 @@ static void object_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_fmaps(BlendWriter *writer, ListBase *fbase)
|
|
||||||
{
|
|
||||||
LISTBASE_FOREACH (bFaceMap *, fmap, fbase) {
|
|
||||||
BLO_write_struct(writer, bFaceMap, fmap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void object_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
static void object_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||||
{
|
{
|
||||||
Object *ob = (Object *)id;
|
Object *ob = (Object *)id;
|
||||||
|
@ -586,7 +576,6 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre
|
||||||
}
|
}
|
||||||
|
|
||||||
BKE_pose_blend_write(writer, ob->pose, arm);
|
BKE_pose_blend_write(writer, ob->pose, arm);
|
||||||
write_fmaps(writer, &ob->fmaps);
|
|
||||||
BKE_constraint_blend_write(writer, &ob->constraints);
|
BKE_constraint_blend_write(writer, &ob->constraints);
|
||||||
animviz_motionpath_blend_write(writer, ob->mpath);
|
animviz_motionpath_blend_write(writer, ob->mpath);
|
||||||
|
|
||||||
|
@ -682,7 +671,6 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
|
||||||
/* Only for versioning, vertex group names are now stored on object data. */
|
/* Only for versioning, vertex group names are now stored on object data. */
|
||||||
BLO_read_list(reader, &ob->defbase);
|
BLO_read_list(reader, &ob->defbase);
|
||||||
|
|
||||||
BLO_read_list(reader, &ob->fmaps);
|
|
||||||
/* XXX deprecated - old animation system <<< */
|
/* XXX deprecated - old animation system <<< */
|
||||||
direct_link_nlastrips(reader, &ob->nlastrips);
|
direct_link_nlastrips(reader, &ob->nlastrips);
|
||||||
BLO_read_list(reader, &ob->constraintChannels);
|
BLO_read_list(reader, &ob->constraintChannels);
|
||||||
|
|
|
@ -1,286 +0,0 @@
|
||||||
/* SPDX-FileCopyrightText: 2008 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \ingroup bke
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "DNA_mesh_types.h"
|
|
||||||
#include "DNA_object_types.h"
|
|
||||||
|
|
||||||
#include "BLI_listbase.h"
|
|
||||||
#include "BLI_string.h"
|
|
||||||
#include "BLI_string_utils.h"
|
|
||||||
#include "BLI_utildefines.h"
|
|
||||||
|
|
||||||
#include "BKE_customdata.h"
|
|
||||||
#include "BKE_editmesh.h"
|
|
||||||
#include "BKE_object.h"
|
|
||||||
#include "BKE_object_deform.h"
|
|
||||||
#include "BKE_object_facemap.h" /* own include */
|
|
||||||
|
|
||||||
#include "BLT_translation.h"
|
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
|
||||||
|
|
||||||
#include "RNA_access.h"
|
|
||||||
#include "RNA_define.h"
|
|
||||||
|
|
||||||
static bool fmap_unique_check(void *arg, const char *name)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
Object *ob;
|
|
||||||
void *fm;
|
|
||||||
} *data = arg;
|
|
||||||
|
|
||||||
bFaceMap *fmap;
|
|
||||||
|
|
||||||
for (fmap = data->ob->fmaps.first; fmap; fmap = fmap->next) {
|
|
||||||
if (data->fm != fmap) {
|
|
||||||
if (STREQ(fmap->name, name)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bFaceMap *fmap_duplicate(bFaceMap *infmap)
|
|
||||||
{
|
|
||||||
bFaceMap *outfmap;
|
|
||||||
|
|
||||||
if (!infmap) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
outfmap = MEM_callocN(sizeof(bFaceMap), "copy facemap");
|
|
||||||
|
|
||||||
/* For now, just copy everything over. */
|
|
||||||
memcpy(outfmap, infmap, sizeof(bFaceMap));
|
|
||||||
|
|
||||||
outfmap->next = outfmap->prev = NULL;
|
|
||||||
|
|
||||||
return outfmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BKE_object_facemap_copy_list(ListBase *outbase, const ListBase *inbase)
|
|
||||||
{
|
|
||||||
bFaceMap *fmap, *fmapn;
|
|
||||||
|
|
||||||
BLI_listbase_clear(outbase);
|
|
||||||
|
|
||||||
for (fmap = inbase->first; fmap; fmap = fmap->next) {
|
|
||||||
fmapn = fmap_duplicate(fmap);
|
|
||||||
BLI_addtail(outbase, fmapn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BKE_object_facemap_unique_name(Object *ob, bFaceMap *fmap)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
Object *ob;
|
|
||||||
void *fmap;
|
|
||||||
} data;
|
|
||||||
data.ob = ob;
|
|
||||||
data.fmap = fmap;
|
|
||||||
|
|
||||||
BLI_uniquename_cb(fmap_unique_check, &data, DATA_("Group"), '.', fmap->name, sizeof(fmap->name));
|
|
||||||
}
|
|
||||||
|
|
||||||
bFaceMap *BKE_object_facemap_add_name(Object *ob, const char *name)
|
|
||||||
{
|
|
||||||
bFaceMap *fmap;
|
|
||||||
|
|
||||||
if (!ob || ob->type != OB_MESH) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fmap = MEM_callocN(sizeof(bFaceMap), __func__);
|
|
||||||
|
|
||||||
STRNCPY(fmap->name, name);
|
|
||||||
|
|
||||||
BLI_addtail(&ob->fmaps, fmap);
|
|
||||||
|
|
||||||
ob->actfmap = BLI_listbase_count(&ob->fmaps);
|
|
||||||
|
|
||||||
BKE_object_facemap_unique_name(ob, fmap);
|
|
||||||
|
|
||||||
return fmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
bFaceMap *BKE_object_facemap_add(Object *ob)
|
|
||||||
{
|
|
||||||
return BKE_object_facemap_add_name(ob, DATA_("FaceMap"));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void object_fmap_remove_edit_mode(Object *ob, bFaceMap *fmap, bool do_selected, bool purge)
|
|
||||||
{
|
|
||||||
const int fmap_nr = BLI_findindex(&ob->fmaps, fmap);
|
|
||||||
|
|
||||||
if (ob->type == OB_MESH) {
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
|
|
||||||
if (me->edit_mesh) {
|
|
||||||
BMEditMesh *em = me->edit_mesh;
|
|
||||||
const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
|
|
||||||
|
|
||||||
if (cd_fmap_offset != -1) {
|
|
||||||
BMFace *efa;
|
|
||||||
BMIter iter;
|
|
||||||
int *map;
|
|
||||||
|
|
||||||
if (purge) {
|
|
||||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
|
||||||
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
|
|
||||||
|
|
||||||
if (map) {
|
|
||||||
if (*map == fmap_nr) {
|
|
||||||
*map = -1;
|
|
||||||
}
|
|
||||||
else if (*map > fmap_nr) {
|
|
||||||
*map -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
|
||||||
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
|
|
||||||
|
|
||||||
if (map && *map == fmap_nr && (!do_selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)))
|
|
||||||
{
|
|
||||||
*map = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ob->actfmap == BLI_listbase_count(&ob->fmaps)) {
|
|
||||||
ob->actfmap--;
|
|
||||||
}
|
|
||||||
|
|
||||||
BLI_remlink(&ob->fmaps, fmap);
|
|
||||||
MEM_freeN(fmap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void object_fmap_remove_object_mode(Object *ob, bFaceMap *fmap, bool purge)
|
|
||||||
{
|
|
||||||
const int fmap_nr = BLI_findindex(&ob->fmaps, fmap);
|
|
||||||
|
|
||||||
if (ob->type == OB_MESH) {
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
|
|
||||||
if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
|
|
||||||
int *map = CustomData_get_layer_for_write(&me->pdata, CD_FACEMAP, me->totpoly);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (map) {
|
|
||||||
for (i = 0; i < me->totpoly; i++) {
|
|
||||||
if (map[i] == fmap_nr) {
|
|
||||||
map[i] = -1;
|
|
||||||
}
|
|
||||||
else if (purge && map[i] > fmap_nr) {
|
|
||||||
map[i]--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ob->actfmap == BLI_listbase_count(&ob->fmaps)) {
|
|
||||||
ob->actfmap--;
|
|
||||||
}
|
|
||||||
|
|
||||||
BLI_remlink(&ob->fmaps, fmap);
|
|
||||||
MEM_freeN(fmap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fmap_remove_exec(Object *ob, bFaceMap *fmap, const bool is_edit_mode, const bool purge)
|
|
||||||
{
|
|
||||||
if (is_edit_mode) {
|
|
||||||
object_fmap_remove_edit_mode(ob, fmap, false, purge);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
object_fmap_remove_object_mode(ob, fmap, purge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BKE_object_facemap_remove(Object *ob, bFaceMap *fmap)
|
|
||||||
{
|
|
||||||
fmap_remove_exec(ob, fmap, BKE_object_is_in_editmode(ob), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BKE_object_facemap_clear(Object *ob)
|
|
||||||
{
|
|
||||||
bFaceMap *fmap = (bFaceMap *)ob->fmaps.first;
|
|
||||||
|
|
||||||
if (fmap) {
|
|
||||||
const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
|
|
||||||
|
|
||||||
while (fmap) {
|
|
||||||
bFaceMap *next_fmap = fmap->next;
|
|
||||||
fmap_remove_exec(ob, fmap, edit_mode, false);
|
|
||||||
fmap = next_fmap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* remove all face-maps */
|
|
||||||
if (ob->type == OB_MESH) {
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
CustomData_free_layer(&me->pdata, CD_FACEMAP, me->totpoly, 0);
|
|
||||||
}
|
|
||||||
ob->actfmap = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int BKE_object_facemap_name_index(Object *ob, const char *name)
|
|
||||||
{
|
|
||||||
return (name) ? BLI_findstringindex(&ob->fmaps, name, offsetof(bFaceMap, name)) : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bFaceMap *BKE_object_facemap_find_name(Object *ob, const char *name)
|
|
||||||
{
|
|
||||||
return BLI_findstring(&ob->fmaps, name, offsetof(bFaceMap, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
int *BKE_object_facemap_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
|
|
||||||
{
|
|
||||||
/* Build src to merged mapping of facemap indices. */
|
|
||||||
if (BLI_listbase_is_empty(&ob_src->fmaps) || BLI_listbase_is_empty(&ob_dst->fmaps)) {
|
|
||||||
*r_map_len = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
*r_map_len = BLI_listbase_count(&ob_src->fmaps);
|
|
||||||
int *fmap_index_map = MEM_malloc_arrayN(
|
|
||||||
*r_map_len, sizeof(*fmap_index_map), "defgroup index map create");
|
|
||||||
bool is_fmap_remap_needed = false;
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (bFaceMap *fmap_src = ob_src->fmaps.first; fmap_src; fmap_src = fmap_src->next, i++) {
|
|
||||||
fmap_index_map[i] = BKE_object_facemap_name_index(ob_dst, fmap_src->name);
|
|
||||||
is_fmap_remap_needed = is_fmap_remap_needed || (fmap_index_map[i] != i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_fmap_remap_needed) {
|
|
||||||
MEM_freeN(fmap_index_map);
|
|
||||||
fmap_index_map = NULL;
|
|
||||||
*r_map_len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmap_index_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BKE_object_facemap_index_map_apply(int *fmap, int fmap_len, const int *map, int map_len)
|
|
||||||
{
|
|
||||||
if (map == NULL || map_len == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < fmap_len; i++, fmap++) {
|
|
||||||
*fmap = (*fmap < map_len && *fmap != -1) ? map[*fmap] : -1;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3449,7 +3449,6 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
|
||||||
EffectorWeights *clmd_effweights;
|
EffectorWeights *clmd_effweights;
|
||||||
int totpoint;
|
int totpoint;
|
||||||
int totedge;
|
int totedge;
|
||||||
float(*deformedVerts)[3];
|
|
||||||
bool realloc_roots;
|
bool realloc_roots;
|
||||||
|
|
||||||
if (!psys->clmd) {
|
if (!psys->clmd) {
|
||||||
|
@ -3505,12 +3504,14 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
|
||||||
psys->clmd->sim_parms->effector_weights = psys->part->effector_weights;
|
psys->clmd->sim_parms->effector_weights = psys->part->effector_weights;
|
||||||
|
|
||||||
BKE_id_copy_ex(NULL, &psys->hair_in_mesh->id, (ID **)&psys->hair_out_mesh, LIB_ID_COPY_LOCALIZE);
|
BKE_id_copy_ex(NULL, &psys->hair_in_mesh->id, (ID **)&psys->hair_out_mesh, LIB_ID_COPY_LOCALIZE);
|
||||||
deformedVerts = BKE_mesh_vert_coords_alloc(psys->hair_out_mesh, NULL);
|
|
||||||
clothModifier_do(
|
|
||||||
psys->clmd, sim->depsgraph, sim->scene, sim->ob, psys->hair_in_mesh, deformedVerts);
|
|
||||||
BKE_mesh_vert_coords_apply(psys->hair_out_mesh, deformedVerts);
|
|
||||||
|
|
||||||
MEM_freeN(deformedVerts);
|
clothModifier_do(psys->clmd,
|
||||||
|
sim->depsgraph,
|
||||||
|
sim->scene,
|
||||||
|
sim->ob,
|
||||||
|
psys->hair_in_mesh,
|
||||||
|
BKE_mesh_vert_positions_for_write(psys->hair_out_mesh));
|
||||||
|
BKE_mesh_tag_positions_changed(psys->hair_out_mesh);
|
||||||
|
|
||||||
/* restore cloth effector weights */
|
/* restore cloth effector weights */
|
||||||
psys->clmd->sim_parms->effector_weights = clmd_effweights;
|
psys->clmd->sim_parms->effector_weights = clmd_effweights;
|
||||||
|
@ -5005,6 +5006,8 @@ static void particlesystem_modifiersForeachIDLink(void *user_data,
|
||||||
void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata)
|
void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata)
|
||||||
{
|
{
|
||||||
ParticleTarget *pt;
|
ParticleTarget *pt;
|
||||||
|
LibraryForeachIDData *foreachid_data = userdata;
|
||||||
|
const int foreachid_data_flags = BKE_lib_query_foreachid_process_flags_get(foreachid_data);
|
||||||
|
|
||||||
func(psys, (ID **)&psys->part, userdata, IDWALK_CB_USER | IDWALK_CB_NEVER_NULL);
|
func(psys, (ID **)&psys->part, userdata, IDWALK_CB_USER | IDWALK_CB_NEVER_NULL);
|
||||||
func(psys, (ID **)&psys->target_ob, userdata, IDWALK_CB_NOP);
|
func(psys, (ID **)&psys->target_ob, userdata, IDWALK_CB_NOP);
|
||||||
|
@ -5024,14 +5027,19 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func,
|
||||||
func(psys, (ID **)&pt->ob, userdata, IDWALK_CB_NOP);
|
func(psys, (ID **)&pt->ob, userdata, IDWALK_CB_NOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Even though psys->part should never be NULL, this can happen as an exception during deletion.
|
/* In case `psys->part` is NULL (See ID_REMAP_SKIP/FORCE/FLAG_NEVER_NULL_USAGE in
|
||||||
* See ID_REMAP_SKIP/FORCE/FLAG_NEVER_NULL_USAGE in BKE_library_remap. */
|
* #BKE_library_remap), or accessing it is forbidden, always handle particles for potential boids
|
||||||
if (psys->part && psys->part->phystype == PART_PHYS_BOIDS) {
|
* data. Unfortunate, but for now there is no other proper way to do this. */
|
||||||
|
if (!(psys->part && (foreachid_data_flags & IDWALK_NO_ORIG_POINTERS_ACCESS) == 0) ||
|
||||||
|
psys->part->phystype == PART_PHYS_BOIDS)
|
||||||
|
{
|
||||||
ParticleData *pa;
|
ParticleData *pa;
|
||||||
int p;
|
int p;
|
||||||
|
|
||||||
for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) {
|
for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) {
|
||||||
func(psys, (ID **)&pa->boid->ground, userdata, IDWALK_CB_NOP);
|
if (pa->boid != NULL) {
|
||||||
|
func(psys, (ID **)&pa->boid->ground, userdata, IDWALK_CB_NOP);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -513,7 +513,7 @@ static void shrinkwrap_calc_normal_projection_cb_ex(void *__restrict userdata,
|
||||||
|
|
||||||
const float proj_limit_squared = calc->smd->projLimit * calc->smd->projLimit;
|
const float proj_limit_squared = calc->smd->projLimit * calc->smd->projLimit;
|
||||||
float *co = calc->vertexCos[i];
|
float *co = calc->vertexCos[i];
|
||||||
float tmp_co[3], tmp_no[3];
|
const float *tmp_co, *tmp_no;
|
||||||
float weight = BKE_defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup);
|
float weight = BKE_defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup);
|
||||||
|
|
||||||
if (calc->invert_vgroup) {
|
if (calc->invert_vgroup) {
|
||||||
|
@ -530,12 +530,12 @@ static void shrinkwrap_calc_normal_projection_cb_ex(void *__restrict userdata,
|
||||||
/* These coordinates are deformed by vertexCos only for normal projection
|
/* These coordinates are deformed by vertexCos only for normal projection
|
||||||
* (to get correct normals) for other cases calc->verts contains undeformed coordinates and
|
* (to get correct normals) for other cases calc->verts contains undeformed coordinates and
|
||||||
* vertexCos should be used */
|
* vertexCos should be used */
|
||||||
copy_v3_v3(tmp_co, calc->vert_positions[i]);
|
tmp_co = calc->vert_positions[i];
|
||||||
copy_v3_v3(tmp_no, calc->vert_normals[i]);
|
tmp_no = calc->vert_normals[i];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
copy_v3_v3(tmp_co, co);
|
tmp_co = co;
|
||||||
copy_v3_v3(tmp_no, proj_axis);
|
tmp_no = proj_axis;
|
||||||
}
|
}
|
||||||
|
|
||||||
hit->index = -1;
|
hit->index = -1;
|
||||||
|
@ -1568,7 +1568,6 @@ void BKE_shrinkwrap_mesh_nearest_surface_deform(bContext *C, Object *ob_source,
|
||||||
void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object *ob_target)
|
void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object *ob_target)
|
||||||
{
|
{
|
||||||
ShrinkwrapModifierData ssmd = {{nullptr}};
|
ShrinkwrapModifierData ssmd = {{nullptr}};
|
||||||
int totvert;
|
|
||||||
|
|
||||||
ssmd.target = ob_target;
|
ssmd.target = ob_target;
|
||||||
ssmd.shrinkType = MOD_SHRINKWRAP_PROJECT;
|
ssmd.shrinkType = MOD_SHRINKWRAP_PROJECT;
|
||||||
|
@ -1581,13 +1580,11 @@ void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object
|
||||||
const float projLimitTolerance = 5.0f;
|
const float projLimitTolerance = 5.0f;
|
||||||
ssmd.projLimit = target_me->remesh_voxel_size * projLimitTolerance;
|
ssmd.projLimit = target_me->remesh_voxel_size * projLimitTolerance;
|
||||||
|
|
||||||
float(*vertexCos)[3] = BKE_mesh_vert_coords_alloc(src_me, &totvert);
|
|
||||||
|
|
||||||
ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
|
ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
|
||||||
|
|
||||||
calc.smd = &ssmd;
|
calc.smd = &ssmd;
|
||||||
calc.numVerts = src_me->totvert;
|
calc.numVerts = src_me->totvert;
|
||||||
calc.vertexCos = vertexCos;
|
calc.vertexCos = BKE_mesh_vert_positions_for_write(src_me);
|
||||||
calc.vert_normals = src_me->vert_normals();
|
calc.vert_normals = src_me->vert_normals();
|
||||||
calc.vgroup = -1;
|
calc.vgroup = -1;
|
||||||
calc.target = target_me;
|
calc.target = target_me;
|
||||||
|
@ -1602,7 +1599,5 @@ void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object
|
||||||
BKE_shrinkwrap_free_tree(&tree);
|
BKE_shrinkwrap_free_tree(&tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
BKE_mesh_vert_coords_apply(src_me, vertexCos);
|
BKE_mesh_tag_positions_changed(src_me);
|
||||||
|
|
||||||
MEM_freeN(vertexCos);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1569,7 +1569,6 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
|
||||||
loopindex2);
|
loopindex2);
|
||||||
loopindex2++;
|
loopindex2++;
|
||||||
|
|
||||||
/* Copy over poly data, e.g. #CD_FACEMAP. */
|
|
||||||
CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1);
|
CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1);
|
||||||
|
|
||||||
if (polyOrigIndex) {
|
if (polyOrigIndex) {
|
||||||
|
|
|
@ -179,94 +179,98 @@ static void libmv_frame_to_normalized_relative(const float frame_coord[2],
|
||||||
/** \name Conversion of markers between Blender's DNA and Libmv.
|
/** \name Conversion of markers between Blender's DNA and Libmv.
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
|
static libmv_Marker dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack &track,
|
||||||
const MovieTrackingMarker *marker,
|
const MovieTrackingMarker &marker,
|
||||||
int clip,
|
const int clip,
|
||||||
int track_index,
|
const int track_index,
|
||||||
int frame_width,
|
const int frame_width,
|
||||||
int frame_height,
|
const int frame_height,
|
||||||
bool backwards,
|
const bool backwards)
|
||||||
libmv_Marker *libmv_marker)
|
|
||||||
{
|
{
|
||||||
const int frame_dimensions[2] = {frame_width, frame_height};
|
libmv_Marker libmv_marker{};
|
||||||
libmv_marker->clip = clip;
|
|
||||||
libmv_marker->frame = marker->framenr;
|
|
||||||
libmv_marker->track = track_index;
|
|
||||||
|
|
||||||
normalized_to_libmv_frame(marker->pos, frame_dimensions, libmv_marker->center);
|
const int frame_dimensions[2] = {frame_width, frame_height};
|
||||||
|
libmv_marker.clip = clip;
|
||||||
|
libmv_marker.frame = marker.framenr;
|
||||||
|
libmv_marker.track = track_index;
|
||||||
|
|
||||||
|
normalized_to_libmv_frame(marker.pos, frame_dimensions, libmv_marker.center);
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
normalized_relative_to_libmv_frame(
|
normalized_relative_to_libmv_frame(
|
||||||
marker->pattern_corners[i], marker->pos, frame_dimensions, libmv_marker->patch[i]);
|
marker.pattern_corners[i], marker.pos, frame_dimensions, libmv_marker.patch[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
normalized_relative_to_libmv_frame(
|
normalized_relative_to_libmv_frame(
|
||||||
marker->search_min, marker->pos, frame_dimensions, libmv_marker->search_region_min);
|
marker.search_min, marker.pos, frame_dimensions, libmv_marker.search_region_min);
|
||||||
|
|
||||||
normalized_relative_to_libmv_frame(
|
normalized_relative_to_libmv_frame(
|
||||||
marker->search_max, marker->pos, frame_dimensions, libmv_marker->search_region_max);
|
marker.search_max, marker.pos, frame_dimensions, libmv_marker.search_region_max);
|
||||||
|
|
||||||
/* NOTE: All the markers does have 1.0 weight.
|
/* NOTE: All the markers does have 1.0 weight.
|
||||||
* Might support in the future, but will require more elaborated process which will involve
|
* Might support in the future, but will require more elaborated process which will involve
|
||||||
* F-Curve evaluation. */
|
* F-Curve evaluation. */
|
||||||
libmv_marker->weight = 1.0f;
|
libmv_marker.weight = 1.0f;
|
||||||
|
|
||||||
if (marker->flag & MARKER_TRACKED) {
|
if (marker.flag & MARKER_TRACKED) {
|
||||||
libmv_marker->source = LIBMV_MARKER_SOURCE_TRACKED;
|
libmv_marker.source = LIBMV_MARKER_SOURCE_TRACKED;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
libmv_marker->source = LIBMV_MARKER_SOURCE_MANUAL;
|
libmv_marker.source = LIBMV_MARKER_SOURCE_MANUAL;
|
||||||
}
|
}
|
||||||
libmv_marker->status = LIBMV_MARKER_STATUS_UNKNOWN;
|
libmv_marker.status = LIBMV_MARKER_STATUS_UNKNOWN;
|
||||||
libmv_marker->model_type = LIBMV_MARKER_MODEL_TYPE_POINT;
|
libmv_marker.model_type = LIBMV_MARKER_MODEL_TYPE_POINT;
|
||||||
libmv_marker->model_id = 0;
|
libmv_marker.model_id = 0;
|
||||||
|
|
||||||
/* NOTE: We currently don't support reference marker from different clip. */
|
/* NOTE: We currently don't support reference marker from different clip. */
|
||||||
libmv_marker->reference_clip = clip;
|
libmv_marker.reference_clip = clip;
|
||||||
|
|
||||||
if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
|
if (track.pattern_match == TRACK_MATCH_KEYFRAME) {
|
||||||
const MovieTrackingMarker *keyframe_marker = tracking_get_keyframed_marker(
|
const MovieTrackingMarker *keyframe_marker = tracking_get_keyframed_marker(
|
||||||
track, marker->framenr, backwards);
|
&track, marker.framenr, backwards);
|
||||||
libmv_marker->reference_frame = keyframe_marker->framenr;
|
libmv_marker.reference_frame = keyframe_marker->framenr;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
libmv_marker->reference_frame = backwards ? marker->framenr - 1 : marker->framenr;
|
libmv_marker.reference_frame = backwards ? marker.framenr - 1 : marker.framenr;
|
||||||
}
|
}
|
||||||
|
|
||||||
libmv_marker->disabled_channels =
|
libmv_marker.disabled_channels =
|
||||||
((track->flag & TRACK_DISABLE_RED) ? LIBMV_MARKER_CHANNEL_R : 0) |
|
((track.flag & TRACK_DISABLE_RED) ? LIBMV_MARKER_CHANNEL_R : 0) |
|
||||||
((track->flag & TRACK_DISABLE_GREEN) ? LIBMV_MARKER_CHANNEL_G : 0) |
|
((track.flag & TRACK_DISABLE_GREEN) ? LIBMV_MARKER_CHANNEL_G : 0) |
|
||||||
((track->flag & TRACK_DISABLE_BLUE) ? LIBMV_MARKER_CHANNEL_B : 0);
|
((track.flag & TRACK_DISABLE_BLUE) ? LIBMV_MARKER_CHANNEL_B : 0);
|
||||||
|
|
||||||
|
return libmv_marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,
|
static MovieTrackingMarker libmv_marker_to_dna_marker(const libmv_Marker &libmv_marker,
|
||||||
int frame_width,
|
const int frame_width,
|
||||||
int frame_height,
|
const int frame_height)
|
||||||
MovieTrackingMarker *marker)
|
|
||||||
{
|
{
|
||||||
const int frame_dimensions[2] = {frame_width, frame_height};
|
MovieTrackingMarker marker{};
|
||||||
marker->framenr = libmv_marker->frame;
|
|
||||||
|
|
||||||
libmv_frame_to_normalized(libmv_marker->center, frame_dimensions, marker->pos);
|
const int frame_dimensions[2] = {frame_width, frame_height};
|
||||||
|
marker.framenr = libmv_marker.frame;
|
||||||
|
|
||||||
|
libmv_frame_to_normalized(libmv_marker.center, frame_dimensions, marker.pos);
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
libmv_frame_to_normalized_relative(libmv_marker->patch[i],
|
libmv_frame_to_normalized_relative(
|
||||||
libmv_marker->center,
|
libmv_marker.patch[i], libmv_marker.center, frame_dimensions, marker.pattern_corners[i]);
|
||||||
frame_dimensions,
|
|
||||||
marker->pattern_corners[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
libmv_frame_to_normalized_relative(
|
libmv_frame_to_normalized_relative(
|
||||||
libmv_marker->search_region_min, libmv_marker->center, frame_dimensions, marker->search_min);
|
libmv_marker.search_region_min, libmv_marker.center, frame_dimensions, marker.search_min);
|
||||||
|
|
||||||
libmv_frame_to_normalized_relative(
|
libmv_frame_to_normalized_relative(
|
||||||
libmv_marker->search_region_max, libmv_marker->center, frame_dimensions, marker->search_max);
|
libmv_marker.search_region_max, libmv_marker.center, frame_dimensions, marker.search_max);
|
||||||
|
|
||||||
marker->flag = 0;
|
marker.flag = 0;
|
||||||
if (libmv_marker->source == LIBMV_MARKER_SOURCE_TRACKED) {
|
if (libmv_marker.source == LIBMV_MARKER_SOURCE_TRACKED) {
|
||||||
marker->flag |= MARKER_TRACKED;
|
marker.flag |= MARKER_TRACKED;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
marker->flag &= ~MARKER_TRACKED;
|
marker.flag &= ~MARKER_TRACKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
@ -279,29 +283,28 @@ static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
/* Returns false if marker crossed margin area from frame bounds. */
|
/* Returns false if marker crossed margin area from frame bounds. */
|
||||||
static bool tracking_check_marker_margin(const libmv_Marker *libmv_marker,
|
static bool tracking_check_marker_margin(const libmv_Marker &libmv_marker,
|
||||||
int margin,
|
const int margin,
|
||||||
int frame_width,
|
const int frame_width,
|
||||||
int frame_height)
|
const int frame_height)
|
||||||
{
|
{
|
||||||
float patch_min[2], patch_max[2];
|
float patch_min[2], patch_max[2];
|
||||||
float margin_left, margin_top, margin_right, margin_bottom;
|
float margin_left, margin_top, margin_right, margin_bottom;
|
||||||
|
|
||||||
INIT_MINMAX2(patch_min, patch_max);
|
INIT_MINMAX2(patch_min, patch_max);
|
||||||
minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[0]);
|
minmax_v2v2_v2(patch_min, patch_max, libmv_marker.patch[0]);
|
||||||
minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[1]);
|
minmax_v2v2_v2(patch_min, patch_max, libmv_marker.patch[1]);
|
||||||
minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[2]);
|
minmax_v2v2_v2(patch_min, patch_max, libmv_marker.patch[2]);
|
||||||
minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[3]);
|
minmax_v2v2_v2(patch_min, patch_max, libmv_marker.patch[3]);
|
||||||
|
|
||||||
margin_left = max_ff(libmv_marker->center[0] - patch_min[0], margin);
|
margin_left = max_ff(libmv_marker.center[0] - patch_min[0], margin);
|
||||||
margin_top = max_ff(patch_max[1] - libmv_marker->center[1], margin);
|
margin_top = max_ff(patch_max[1] - libmv_marker.center[1], margin);
|
||||||
margin_right = max_ff(patch_max[0] - libmv_marker->center[0], margin);
|
margin_right = max_ff(patch_max[0] - libmv_marker.center[0], margin);
|
||||||
margin_bottom = max_ff(libmv_marker->center[1] - patch_min[1], margin);
|
margin_bottom = max_ff(libmv_marker.center[1] - patch_min[1], margin);
|
||||||
|
|
||||||
if (libmv_marker->center[0] < margin_left ||
|
if (libmv_marker.center[0] < margin_left ||
|
||||||
libmv_marker->center[0] > frame_width - margin_right ||
|
libmv_marker.center[0] > frame_width - margin_right ||
|
||||||
libmv_marker->center[1] < margin_bottom ||
|
libmv_marker.center[1] < margin_bottom || libmv_marker.center[1] > frame_height - margin_top)
|
||||||
libmv_marker->center[1] > frame_height - margin_top)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -315,9 +318,9 @@ static bool tracking_check_marker_margin(const libmv_Marker *libmv_marker,
|
||||||
/** \name Auto-Track Context Initialization
|
/** \name Auto-Track Context Initialization
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
static bool autotrack_is_marker_usable(const MovieTrackingMarker *marker)
|
static bool autotrack_is_marker_usable(const MovieTrackingMarker &marker)
|
||||||
{
|
{
|
||||||
if (marker->flag & MARKER_DISABLED) {
|
if (marker.flag & MARKER_DISABLED) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -334,7 +337,7 @@ static bool autotrack_is_track_trackable(const AutoTrackContext *context,
|
||||||
clip, context->start_scene_frame);
|
clip, context->start_scene_frame);
|
||||||
|
|
||||||
const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame_number);
|
const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame_number);
|
||||||
return autotrack_is_marker_usable(marker);
|
return autotrack_is_marker_usable(*marker);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -430,7 +433,7 @@ static size_t autotrack_count_all_usable_markers(AutoTrackContext *context)
|
||||||
for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
|
for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
|
||||||
const MovieTrackingTrack *track = context->all_autotrack_tracks[track_index].track;
|
const MovieTrackingTrack *track = context->all_autotrack_tracks[track_index].track;
|
||||||
for (int marker_index = 0; marker_index < track->markersnr; ++marker_index) {
|
for (int marker_index = 0; marker_index < track->markersnr; ++marker_index) {
|
||||||
const MovieTrackingMarker *marker = &track->markers[marker_index];
|
const MovieTrackingMarker &marker = track->markers[marker_index];
|
||||||
if (!autotrack_is_marker_usable(marker)) {
|
if (!autotrack_is_marker_usable(marker)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -475,21 +478,21 @@ static void autotrack_context_init_autotrack(AutoTrackContext *context)
|
||||||
int num_filled_libmv_markers = 0;
|
int num_filled_libmv_markers = 0;
|
||||||
for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
|
for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
|
||||||
const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
|
const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
|
||||||
/*const*/ MovieTrackingTrack *track = autotrack_track->track;
|
/*const*/ MovieTrackingTrack &track = *autotrack_track->track;
|
||||||
for (int marker_index = 0; marker_index < track->markersnr; ++marker_index) {
|
for (int marker_index = 0; marker_index < track.markersnr; ++marker_index) {
|
||||||
/*const*/ MovieTrackingMarker *marker = &track->markers[marker_index];
|
/*const*/ MovieTrackingMarker &marker = track.markers[marker_index];
|
||||||
if (!autotrack_is_marker_usable(marker)) {
|
if (!autotrack_is_marker_usable(marker)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const AutoTrackClip *autotrack_clip = &context->autotrack_clips[autotrack_track->clip_index];
|
const AutoTrackClip *autotrack_clip = &context->autotrack_clips[autotrack_track->clip_index];
|
||||||
dna_marker_to_libmv_marker(track,
|
libmv_markers[num_filled_libmv_markers++] = dna_marker_to_libmv_marker(
|
||||||
marker,
|
track,
|
||||||
autotrack_track->clip_index,
|
marker,
|
||||||
track_index,
|
autotrack_track->clip_index,
|
||||||
autotrack_clip->width,
|
track_index,
|
||||||
autotrack_clip->height,
|
autotrack_clip->width,
|
||||||
context->is_backwards,
|
autotrack_clip->height,
|
||||||
&libmv_markers[num_filled_libmv_markers++]);
|
context->is_backwards);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,18 +528,17 @@ static void autotrack_context_init_markers(AutoTrackContext *context)
|
||||||
const int clip_frame_number = BKE_movieclip_remap_scene_to_clip_frame(
|
const int clip_frame_number = BKE_movieclip_remap_scene_to_clip_frame(
|
||||||
clip, context->start_scene_frame);
|
clip, context->start_scene_frame);
|
||||||
|
|
||||||
/*const*/ MovieTrackingTrack *track = context->all_autotrack_tracks[track_index].track;
|
/*const*/ MovieTrackingTrack &track = *context->all_autotrack_tracks[track_index].track;
|
||||||
const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame_number);
|
const MovieTrackingMarker &marker = *BKE_tracking_marker_get(&track, clip_frame_number);
|
||||||
|
|
||||||
AutoTrackMarker *autotrack_marker = &context->autotrack_markers[autotrack_marker_index++];
|
AutoTrackMarker *autotrack_marker = &context->autotrack_markers[autotrack_marker_index++];
|
||||||
dna_marker_to_libmv_marker(track,
|
autotrack_marker->libmv_marker = dna_marker_to_libmv_marker(track,
|
||||||
marker,
|
marker,
|
||||||
autotrack_track->clip_index,
|
autotrack_track->clip_index,
|
||||||
track_index,
|
track_index,
|
||||||
autotrack_clip->width,
|
autotrack_clip->width,
|
||||||
autotrack_clip->height,
|
autotrack_clip->height,
|
||||||
context->is_backwards,
|
context->is_backwards);
|
||||||
&autotrack_marker->libmv_marker);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,35 +635,35 @@ static void autotrack_context_step_cb(void *__restrict userdata,
|
||||||
AutoTrackContext *context = static_cast<AutoTrackContext *>(userdata);
|
AutoTrackContext *context = static_cast<AutoTrackContext *>(userdata);
|
||||||
AutoTrackTLS *autotrack_tls = (AutoTrackTLS *)tls->userdata_chunk;
|
AutoTrackTLS *autotrack_tls = (AutoTrackTLS *)tls->userdata_chunk;
|
||||||
|
|
||||||
const AutoTrackMarker *autotrack_marker = &context->autotrack_markers[marker_index];
|
const AutoTrackMarker &autotrack_marker = context->autotrack_markers[marker_index];
|
||||||
const libmv_Marker *libmv_current_marker = &autotrack_marker->libmv_marker;
|
const libmv_Marker &libmv_current_marker = autotrack_marker.libmv_marker;
|
||||||
|
|
||||||
const int frame_delta = context->is_backwards ? -1 : 1;
|
const int frame_delta = context->is_backwards ? -1 : 1;
|
||||||
const int clip_index = libmv_current_marker->clip;
|
const int clip_index = libmv_current_marker.clip;
|
||||||
const int track_index = libmv_current_marker->track;
|
const int track_index = libmv_current_marker.track;
|
||||||
|
|
||||||
const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
|
const AutoTrackClip &autotrack_clip = context->autotrack_clips[clip_index];
|
||||||
const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
|
const AutoTrackTrack &autotrack_track = context->all_autotrack_tracks[track_index];
|
||||||
const MovieTrackingTrack *track = autotrack_track->track;
|
const MovieTrackingTrack &track = *autotrack_track.track;
|
||||||
|
|
||||||
/* Check whether marker is going outside of allowed frame margin. */
|
/* Check whether marker is going outside of allowed frame margin. */
|
||||||
if (!tracking_check_marker_margin(
|
if (!tracking_check_marker_margin(
|
||||||
libmv_current_marker, track->margin, autotrack_clip->width, autotrack_clip->height))
|
libmv_current_marker, track.margin, autotrack_clip.width, autotrack_clip.height))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int new_marker_frame = libmv_current_marker->frame + frame_delta;
|
const int new_marker_frame = libmv_current_marker.frame + frame_delta;
|
||||||
|
|
||||||
AutoTrackTrackingResult *autotrack_result = MEM_cnew<AutoTrackTrackingResult>(
|
AutoTrackTrackingResult *autotrack_result = MEM_cnew<AutoTrackTrackingResult>(
|
||||||
"autotrack result");
|
"autotrack result");
|
||||||
autotrack_result->libmv_marker = *libmv_current_marker;
|
autotrack_result->libmv_marker = libmv_current_marker;
|
||||||
autotrack_result->libmv_marker.frame = new_marker_frame;
|
autotrack_result->libmv_marker.frame = new_marker_frame;
|
||||||
|
|
||||||
/* Update reference frame. */
|
/* Update reference frame. */
|
||||||
libmv_Marker libmv_reference_marker;
|
libmv_Marker libmv_reference_marker;
|
||||||
if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
|
if (track.pattern_match == TRACK_MATCH_KEYFRAME) {
|
||||||
autotrack_result->libmv_marker.reference_frame = libmv_current_marker->reference_frame;
|
autotrack_result->libmv_marker.reference_frame = libmv_current_marker.reference_frame;
|
||||||
libmv_autoTrackGetMarker(context->autotrack,
|
libmv_autoTrackGetMarker(context->autotrack,
|
||||||
clip_index,
|
clip_index,
|
||||||
autotrack_result->libmv_marker.reference_frame,
|
autotrack_result->libmv_marker.reference_frame,
|
||||||
|
@ -669,14 +671,14 @@ static void autotrack_context_step_cb(void *__restrict userdata,
|
||||||
&libmv_reference_marker);
|
&libmv_reference_marker);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BLI_assert(track->pattern_match == TRACK_MATCH_PREVIOUS_FRAME);
|
BLI_assert(track.pattern_match == TRACK_MATCH_PREVIOUS_FRAME);
|
||||||
autotrack_result->libmv_marker.reference_frame = libmv_current_marker->frame;
|
autotrack_result->libmv_marker.reference_frame = libmv_current_marker.frame;
|
||||||
libmv_reference_marker = *libmv_current_marker;
|
libmv_reference_marker = libmv_current_marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform actual tracking. */
|
/* Perform actual tracking. */
|
||||||
autotrack_result->success = libmv_autoTrackMarker(context->autotrack,
|
autotrack_result->success = libmv_autoTrackMarker(context->autotrack,
|
||||||
&autotrack_track->track_region_options,
|
&autotrack_track.track_region_options,
|
||||||
&autotrack_result->libmv_marker,
|
&autotrack_result->libmv_marker,
|
||||||
&autotrack_result->libmv_result);
|
&autotrack_result->libmv_result);
|
||||||
|
|
||||||
|
@ -684,7 +686,7 @@ static void autotrack_context_step_cb(void *__restrict userdata,
|
||||||
* This is how Blender side is currently expecting failed track to be handled. Without this the
|
* This is how Blender side is currently expecting failed track to be handled. Without this the
|
||||||
* marker is left in an arbitrary position which did not provide good correlation. */
|
* marker is left in an arbitrary position which did not provide good correlation. */
|
||||||
if (!autotrack_result->success) {
|
if (!autotrack_result->success) {
|
||||||
autotrack_result->libmv_marker = *libmv_current_marker;
|
autotrack_result->libmv_marker = libmv_current_marker;
|
||||||
autotrack_result->libmv_marker.frame = new_marker_frame;
|
autotrack_result->libmv_marker.frame = new_marker_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -768,22 +770,21 @@ void BKE_autotrack_context_sync(AutoTrackContext *context)
|
||||||
BLI_spin_unlock(&context->spin_lock);
|
BLI_spin_unlock(&context->spin_lock);
|
||||||
|
|
||||||
LISTBASE_FOREACH_MUTABLE (AutoTrackTrackingResult *, autotrack_result, &results_to_sync) {
|
LISTBASE_FOREACH_MUTABLE (AutoTrackTrackingResult *, autotrack_result, &results_to_sync) {
|
||||||
const libmv_Marker *libmv_marker = &autotrack_result->libmv_marker;
|
const libmv_Marker &libmv_marker = autotrack_result->libmv_marker;
|
||||||
const int clip_index = libmv_marker->clip;
|
const int clip_index = libmv_marker.clip;
|
||||||
const int track_index = libmv_marker->track;
|
const int track_index = libmv_marker.track;
|
||||||
const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
|
const AutoTrackClip &autotrack_clip = context->autotrack_clips[clip_index];
|
||||||
const MovieClip *clip = autotrack_clip->clip;
|
const MovieClip *clip = autotrack_clip.clip;
|
||||||
const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
|
const AutoTrackTrack &autotrack_track = context->all_autotrack_tracks[track_index];
|
||||||
MovieTrackingTrack *track = autotrack_track->track;
|
MovieTrackingTrack *track = autotrack_track.track;
|
||||||
|
|
||||||
const int start_clip_frame = BKE_movieclip_remap_scene_to_clip_frame(
|
const int start_clip_frame = BKE_movieclip_remap_scene_to_clip_frame(
|
||||||
clip, context->start_scene_frame);
|
clip, context->start_scene_frame);
|
||||||
const int first_result_frame = start_clip_frame + frame_delta;
|
const int first_result_frame = start_clip_frame + frame_delta;
|
||||||
|
|
||||||
/* Insert marker which corresponds to the tracking result. */
|
/* Insert marker which corresponds to the tracking result. */
|
||||||
MovieTrackingMarker marker;
|
MovieTrackingMarker marker = libmv_marker_to_dna_marker(
|
||||||
libmv_marker_to_dna_marker(
|
autotrack_result->libmv_marker, autotrack_clip.width, autotrack_clip.height);
|
||||||
&autotrack_result->libmv_marker, autotrack_clip->width, autotrack_clip->height, &marker);
|
|
||||||
if (!autotrack_result->success) {
|
if (!autotrack_result->success) {
|
||||||
marker.flag |= MARKER_DISABLED;
|
marker.flag |= MARKER_DISABLED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,7 +186,7 @@ bool BLI_is_file(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||||
*/
|
*/
|
||||||
bool BLI_dir_create_recursive(const char *dir) ATTR_NONNULL();
|
bool BLI_dir_create_recursive(const char *dir) ATTR_NONNULL();
|
||||||
/**
|
/**
|
||||||
* Returns the number of free bytes on the volume containing the specified pathname.
|
* Returns the number of free bytes on the volume containing the specified path.
|
||||||
*
|
*
|
||||||
* \note Not actually used anywhere.
|
* \note Not actually used anywhere.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -74,12 +74,6 @@ template<typename T> struct AngleRadianBase {
|
||||||
|
|
||||||
/** Methods. */
|
/** Methods. */
|
||||||
|
|
||||||
/* 'mod_inline(-3, 4)= 1', 'fmod(-3, 4)= -3' */
|
|
||||||
static float mod_inline(float a, float b)
|
|
||||||
{
|
|
||||||
return a - (b * floorf(a / b));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the angle wrapped inside [-pi..pi] interval. Basically `(angle + pi) % 2pi - pi`.
|
* Return the angle wrapped inside [-pi..pi] interval. Basically `(angle + pi) % 2pi - pi`.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -171,6 +171,11 @@ template<typename T> inline T pow(const T &x, const T &power)
|
||||||
return std::pow(x, power);
|
return std::pow(x, power);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T> inline T exp(const T &x)
|
||||||
|
{
|
||||||
|
return std::exp(x);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T> inline T safe_acos(const T &a)
|
template<typename T> inline T safe_acos(const T &a)
|
||||||
{
|
{
|
||||||
if (UNLIKELY(a <= T(-1))) {
|
if (UNLIKELY(a <= T(-1))) {
|
||||||
|
|
|
@ -680,7 +680,7 @@ template<typename T> QuaternionBase<T> QuaternionBase<T>::expmap(const VecBase<T
|
||||||
T angle;
|
T angle;
|
||||||
const VecBase<T, 3> axis = normalize_and_get_length(expmap, angle);
|
const VecBase<T, 3> axis = normalize_and_get_length(expmap, angle);
|
||||||
if (LIKELY(angle != T(0))) {
|
if (LIKELY(angle != T(0))) {
|
||||||
return to_quaternion(AxisAngleT(axis, angle_wrap_rad(angle)));
|
return to_quaternion(AxisAngleT(axis, AngleRadianBase<T>(angle).wrapped()));
|
||||||
}
|
}
|
||||||
return QuaternionBase<T>::identity();
|
return QuaternionBase<T>::identity();
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,6 +162,11 @@ template<typename T> struct QuaternionBase {
|
||||||
return (a.w == b.w) && (a.x == b.x) && (a.y == b.y) && (a.z == b.z);
|
return (a.w == b.w) && (a.x == b.x) && (a.y == b.y) && (a.z == b.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t hash() const
|
||||||
|
{
|
||||||
|
return VecBase<T, 4>(*this).hash();
|
||||||
|
}
|
||||||
|
|
||||||
friend std::ostream &operator<<(std::ostream &stream, const QuaternionBase &rot)
|
friend std::ostream &operator<<(std::ostream &stream, const QuaternionBase &rot)
|
||||||
{
|
{
|
||||||
return stream << "Quaternion" << static_cast<VecBase<T, 4>>(rot);
|
return stream << "Quaternion" << static_cast<VecBase<T, 4>>(rot);
|
||||||
|
|
|
@ -206,6 +206,16 @@ template<typename T, int Size>
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Per-element exponent. */
|
||||||
|
template<typename T, int Size> [[nodiscard]] inline VecBase<T, Size> exp(const VecBase<T, Size> &x)
|
||||||
|
{
|
||||||
|
VecBase<T, Size> result;
|
||||||
|
for (int i = 0; i < Size; i++) {
|
||||||
|
result[i] = math::exp(x[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns \a a if it is a multiple of \a b or the next multiple or \a b after \b a .
|
* Returns \a a if it is a multiple of \a b or the next multiple or \a b after \b a .
|
||||||
* In other words, it is equivalent to `divide_ceil(a, b) * b`.
|
* In other words, it is equivalent to `divide_ceil(a, b) * b`.
|
||||||
|
|
|
@ -34,7 +34,7 @@ extern "C" {
|
||||||
#define BLI_STR_FORMAT_INT32_INTEGER_UNIT_SIZE 5
|
#define BLI_STR_FORMAT_INT32_INTEGER_UNIT_SIZE 5
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Duplicates the first \a len bytes of cstring \a str
|
* Duplicates the first \a len bytes of the C-string \a str
|
||||||
* into a newly mallocN'd string and returns it. \a str
|
* into a newly mallocN'd string and returns it. \a str
|
||||||
* is assumed to be at least len bytes long.
|
* is assumed to be at least len bytes long.
|
||||||
*
|
*
|
||||||
|
@ -45,7 +45,7 @@ extern "C" {
|
||||||
char *BLI_strdupn(const char *str, size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
|
char *BLI_strdupn(const char *str, size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Duplicates the cstring \a str into a newly mallocN'd
|
* Duplicates the C-string \a str into a newly mallocN'd
|
||||||
* string and returns it.
|
* string and returns it.
|
||||||
*
|
*
|
||||||
* \param str: The string to be duplicated
|
* \param str: The string to be duplicated
|
||||||
|
|
|
@ -172,4 +172,13 @@ TEST(math_vector, safe_rcp)
|
||||||
EXPECT_NEAR(result.z, 0.25f, 1e-6f);
|
EXPECT_NEAR(result.z, 0.25f, 1e-6f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(math_vector, exp)
|
||||||
|
{
|
||||||
|
const float3 a(1.0f, 2.0f, 3.0f);
|
||||||
|
const float3 result = math::exp(a);
|
||||||
|
EXPECT_NEAR(result.x, 2.718281828459045f, 1e-6f);
|
||||||
|
EXPECT_NEAR(result.y, 7.38905609893065f, 1e-6f);
|
||||||
|
EXPECT_NEAR(result.z, 20.085536923187668f, 1e-6f);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::tests
|
} // namespace blender::tests
|
||||||
|
|
|
@ -76,7 +76,10 @@ typedef struct BlendFileReadWMSetupData {
|
||||||
/** The existing WM when filereading process is started. */
|
/** The existing WM when filereading process is started. */
|
||||||
struct wmWindowManager *old_wm;
|
struct wmWindowManager *old_wm;
|
||||||
|
|
||||||
|
/** The startup file is being read. */
|
||||||
bool is_read_homefile;
|
bool is_read_homefile;
|
||||||
|
/** The factory startup file is being read. */
|
||||||
|
bool is_factory_startup;
|
||||||
} BlendFileReadWMSetupData;
|
} BlendFileReadWMSetupData;
|
||||||
|
|
||||||
struct BlendFileReadParams {
|
struct BlendFileReadParams {
|
||||||
|
|
|
@ -182,14 +182,30 @@ void blo_do_versions_400(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
|
||||||
|
|
||||||
if (!MAIN_VERSION_ATLEAST(bmain, 400, 5)) {
|
if (!MAIN_VERSION_ATLEAST(bmain, 400, 5)) {
|
||||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||||
|
ToolSettings *ts = scene->toolsettings;
|
||||||
|
if (ts->snap_mode_tools != SCE_SNAP_MODE_NONE) {
|
||||||
|
ts->snap_mode_tools = SCE_SNAP_MODE_GEOM;
|
||||||
|
}
|
||||||
|
|
||||||
#define SCE_SNAP_PROJECT (1 << 3)
|
#define SCE_SNAP_PROJECT (1 << 3)
|
||||||
if (scene->toolsettings->snap_flag & SCE_SNAP_PROJECT) {
|
if (ts->snap_flag & SCE_SNAP_PROJECT) {
|
||||||
scene->toolsettings->snap_mode |= SCE_SNAP_MODE_FACE_RAYCAST;
|
ts->snap_mode |= SCE_SNAP_MODE_FACE_RAYCAST;
|
||||||
}
|
}
|
||||||
#undef SCE_SNAP_PROJECT
|
#undef SCE_SNAP_PROJECT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!MAIN_VERSION_ATLEAST(bmain, 400, 6)) {
|
||||||
|
LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
|
||||||
|
BKE_mesh_legacy_face_map_to_generic(mesh);
|
||||||
|
}
|
||||||
|
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||||
|
versioning_replace_legacy_glossy_node(ntree);
|
||||||
|
versioning_remove_microfacet_sharp_distribution(ntree);
|
||||||
|
}
|
||||||
|
FOREACH_NODETREE_END;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Versioning code until next subversion bump goes here.
|
* Versioning code until next subversion bump goes here.
|
||||||
*
|
*
|
||||||
|
@ -204,11 +220,6 @@ void blo_do_versions_400(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
/* Convert anisotropic BSDF node to glossy BSDF. */
|
/* Convert anisotropic BSDF node to glossy BSDF. */
|
||||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
|
||||||
versioning_replace_legacy_glossy_node(ntree);
|
|
||||||
versioning_remove_microfacet_sharp_distribution(ntree);
|
|
||||||
}
|
|
||||||
FOREACH_NODETREE_END;
|
|
||||||
|
|
||||||
/* Keep this block, even when empty. */
|
/* Keep this block, even when empty. */
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ set(SRC
|
||||||
intern/bmesh_edgeloop.c
|
intern/bmesh_edgeloop.c
|
||||||
intern/bmesh_edgeloop.h
|
intern/bmesh_edgeloop.h
|
||||||
intern/bmesh_inline.h
|
intern/bmesh_inline.h
|
||||||
intern/bmesh_interp.c
|
intern/bmesh_interp.cc
|
||||||
intern/bmesh_interp.h
|
intern/bmesh_interp.h
|
||||||
intern/bmesh_iterators.cc
|
intern/bmesh_iterators.cc
|
||||||
intern/bmesh_iterators.h
|
intern/bmesh_iterators.h
|
||||||
|
|
|
@ -35,7 +35,7 @@ typedef struct BMEdgeLoopStore {
|
||||||
#define EDGELOOP_EPS 1e-10f
|
#define EDGELOOP_EPS 1e-10f
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* BM_mesh_edgeloops_find & Util Functions. */
|
/* BM_mesh_edgeloops_find & Utility Functions. */
|
||||||
|
|
||||||
static int bm_vert_other_tag(BMVert *v, BMVert *v_prev, BMEdge **r_e)
|
static int bm_vert_other_tag(BMVert *v, BMVert *v_prev, BMEdge **r_e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,7 +63,7 @@ static void bm_data_interp_from_elem(CustomData *data_layer,
|
||||||
src[1] = ele_src_2->head.data;
|
src[1] = ele_src_2->head.data;
|
||||||
w[0] = 1.0f - fac;
|
w[0] = 1.0f - fac;
|
||||||
w[1] = fac;
|
w[1] = fac;
|
||||||
CustomData_bmesh_interp(data_layer, src, w, NULL, 2, ele_dst->head.data);
|
CustomData_bmesh_interp(data_layer, src, w, nullptr, 2, ele_dst->head.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,21 +88,21 @@ void BM_data_interp_from_edges(
|
||||||
* Sets all the customdata (e.g. vert, loop) associated with a vert
|
* Sets all the customdata (e.g. vert, loop) associated with a vert
|
||||||
* to the average of the face regions surrounding it.
|
* to the average of the face regions surrounding it.
|
||||||
*/
|
*/
|
||||||
static void UNUSED_FUNCTION(BM_Data_Vert_Average)(BMesh *UNUSED(bm), BMFace *UNUSED(f))
|
static void UNUSED_FUNCTION(BM_Data_Vert_Average)(BMesh * /*bm*/, BMFace * /*f*/)
|
||||||
{
|
{
|
||||||
// BMIter iter;
|
// BMIter iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BM_data_interp_face_vert_edge(BMesh *bm,
|
void BM_data_interp_face_vert_edge(BMesh *bm,
|
||||||
const BMVert *v_src_1,
|
const BMVert *v_src_1,
|
||||||
const BMVert *UNUSED(v_src_2),
|
const BMVert * /*v_src_2*/,
|
||||||
BMVert *v,
|
BMVert *v,
|
||||||
BMEdge *e,
|
BMEdge *e,
|
||||||
const float fac)
|
const float fac)
|
||||||
{
|
{
|
||||||
float w[2];
|
float w[2];
|
||||||
BMLoop *l_v1 = NULL, *l_v = NULL, *l_v2 = NULL;
|
BMLoop *l_v1 = nullptr, *l_v = nullptr, *l_v2 = nullptr;
|
||||||
BMLoop *l_iter = NULL;
|
BMLoop *l_iter = nullptr;
|
||||||
|
|
||||||
if (!e->l) {
|
if (!e->l) {
|
||||||
return;
|
return;
|
||||||
|
@ -132,7 +132,7 @@ void BM_data_interp_face_vert_edge(BMesh *bm,
|
||||||
src[0] = l_v1->head.data;
|
src[0] = l_v1->head.data;
|
||||||
src[1] = l_v2->head.data;
|
src[1] = l_v2->head.data;
|
||||||
|
|
||||||
CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_v->head.data);
|
CustomData_bmesh_interp(&bm->ldata, src, w, nullptr, 2, l_v->head.data);
|
||||||
} while ((l_iter = l_iter->radial_next) != e->l);
|
} while ((l_iter = l_iter->radial_next) != e->l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ void BM_face_interp_from_face_ex(BMesh *bm,
|
||||||
BMLoop *l_iter;
|
BMLoop *l_iter;
|
||||||
BMLoop *l_first;
|
BMLoop *l_first;
|
||||||
|
|
||||||
float *w = BLI_array_alloca(w, f_src->len);
|
float *w = static_cast<float *>(BLI_array_alloca(w, f_src->len));
|
||||||
float co[2];
|
float co[2];
|
||||||
|
|
||||||
if (f_src != f_dst) {
|
if (f_src != f_dst) {
|
||||||
|
@ -160,9 +160,9 @@ void BM_face_interp_from_face_ex(BMesh *bm,
|
||||||
do {
|
do {
|
||||||
mul_v2_m3v3(co, axis_mat, l_iter->v->co);
|
mul_v2_m3v3(co, axis_mat, l_iter->v->co);
|
||||||
interp_weights_poly_v2(w, cos_2d, f_src->len, co);
|
interp_weights_poly_v2(w, cos_2d, f_src->len, co);
|
||||||
CustomData_bmesh_interp(&bm->ldata, blocks_l, w, NULL, f_src->len, l_iter->head.data);
|
CustomData_bmesh_interp(&bm->ldata, blocks_l, w, nullptr, f_src->len, l_iter->head.data);
|
||||||
if (do_vertex) {
|
if (do_vertex) {
|
||||||
CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, f_src->len, l_iter->v->head.data);
|
CustomData_bmesh_interp(&bm->vdata, blocks_v, w, nullptr, f_src->len, l_iter->v->head.data);
|
||||||
}
|
}
|
||||||
} while ((l_iter = l_iter->next) != l_first);
|
} while ((l_iter = l_iter->next) != l_first);
|
||||||
}
|
}
|
||||||
|
@ -172,9 +172,11 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, con
|
||||||
BMLoop *l_iter;
|
BMLoop *l_iter;
|
||||||
BMLoop *l_first;
|
BMLoop *l_first;
|
||||||
|
|
||||||
const void **blocks_l = BLI_array_alloca(blocks_l, f_src->len);
|
const void **blocks_l = static_cast<const void **>(BLI_array_alloca(blocks_l, f_src->len));
|
||||||
const void **blocks_v = do_vertex ? BLI_array_alloca(blocks_v, f_src->len) : NULL;
|
const void **blocks_v = do_vertex ?
|
||||||
float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
|
static_cast<const void **>(BLI_array_alloca(blocks_v, f_src->len)) :
|
||||||
|
nullptr;
|
||||||
|
float(*cos_2d)[2] = static_cast<float(*)[2]>(BLI_array_alloca(cos_2d, f_src->len));
|
||||||
float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
|
float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -287,7 +289,7 @@ static bool quad_co(const float v1[3],
|
||||||
|
|
||||||
static void mdisp_axis_from_quad(const float v1[3],
|
static void mdisp_axis_from_quad(const float v1[3],
|
||||||
const float v2[3],
|
const float v2[3],
|
||||||
float UNUSED(v3[3]),
|
float[3] /*v3[3]*/,
|
||||||
const float v4[3],
|
const float v4[3],
|
||||||
float r_axis_x[3],
|
float r_axis_x[3],
|
||||||
float r_axis_y[3])
|
float r_axis_y[3])
|
||||||
|
@ -421,9 +423,9 @@ typedef struct BMLoopInterpMultiresData {
|
||||||
|
|
||||||
static void loop_interp_multires_cb(void *__restrict userdata,
|
static void loop_interp_multires_cb(void *__restrict userdata,
|
||||||
const int ix,
|
const int ix,
|
||||||
const TaskParallelTLS *__restrict UNUSED(tls))
|
const TaskParallelTLS *__restrict /*tls*/)
|
||||||
{
|
{
|
||||||
BMLoopInterpMultiresData *data = userdata;
|
BMLoopInterpMultiresData *data = static_cast<BMLoopInterpMultiresData *>(userdata);
|
||||||
|
|
||||||
BMLoop *l_first = data->l_src_first;
|
BMLoop *l_first = data->l_src_first;
|
||||||
BMLoop *l_dst = data->l_dst;
|
BMLoop *l_dst = data->l_dst;
|
||||||
|
@ -458,7 +460,7 @@ static void loop_interp_multires_cb(void *__restrict userdata,
|
||||||
float src_axis_x[3], src_axis_y[3];
|
float src_axis_x[3], src_axis_y[3];
|
||||||
float uv[2];
|
float uv[2];
|
||||||
|
|
||||||
md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset);
|
md_src = static_cast<MDisps *>(BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset));
|
||||||
|
|
||||||
if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) {
|
if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) {
|
||||||
old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]);
|
old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]);
|
||||||
|
@ -470,7 +472,7 @@ static void loop_interp_multires_cb(void *__restrict userdata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BM_loop_interp_multires_ex(BMesh *UNUSED(bm),
|
void BM_loop_interp_multires_ex(BMesh * /*bm*/,
|
||||||
BMLoop *l_dst,
|
BMLoop *l_dst,
|
||||||
const BMFace *f_src,
|
const BMFace *f_src,
|
||||||
const float f_dst_center[3],
|
const float f_dst_center[3],
|
||||||
|
@ -486,17 +488,19 @@ void BM_loop_interp_multires_ex(BMesh *UNUSED(bm),
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
md_dst = BM_ELEM_CD_GET_VOID_P(l_dst, cd_loop_mdisp_offset);
|
md_dst = static_cast<MDisps *>(BM_ELEM_CD_GET_VOID_P(l_dst, cd_loop_mdisp_offset));
|
||||||
compute_mdisp_quad(l_dst, f_dst_center, v1, v2, v3, v4, e1, e2);
|
compute_mdisp_quad(l_dst, f_dst_center, v1, v2, v3, v4, e1, e2);
|
||||||
|
|
||||||
/* if no disps data allocate a new grid, the size of the first grid in f_src. */
|
/* if no disps data allocate a new grid, the size of the first grid in f_src. */
|
||||||
if (!md_dst->totdisp) {
|
if (!md_dst->totdisp) {
|
||||||
const MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset);
|
const MDisps *md_src = static_cast<const MDisps *>(
|
||||||
|
BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset));
|
||||||
|
|
||||||
md_dst->totdisp = md_src->totdisp;
|
md_dst->totdisp = md_src->totdisp;
|
||||||
md_dst->level = md_src->level;
|
md_dst->level = md_src->level;
|
||||||
if (md_dst->totdisp) {
|
if (md_dst->totdisp) {
|
||||||
md_dst->disps = MEM_callocN(sizeof(float[3]) * md_dst->totdisp, __func__);
|
md_dst->disps = static_cast<float(*)[3]>(
|
||||||
|
MEM_callocN(sizeof(float[3]) * md_dst->totdisp, __func__));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
|
@ -506,21 +510,21 @@ void BM_loop_interp_multires_ex(BMesh *UNUSED(bm),
|
||||||
mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y);
|
mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y);
|
||||||
|
|
||||||
const int res = (int)sqrt(md_dst->totdisp);
|
const int res = (int)sqrt(md_dst->totdisp);
|
||||||
BMLoopInterpMultiresData data = {
|
BMLoopInterpMultiresData data = {};
|
||||||
.l_dst = l_dst,
|
data.l_dst = l_dst;
|
||||||
.l_src_first = BM_FACE_FIRST_LOOP(f_src),
|
data.l_src_first = BM_FACE_FIRST_LOOP(f_src);
|
||||||
.cd_loop_mdisp_offset = cd_loop_mdisp_offset,
|
data.cd_loop_mdisp_offset = cd_loop_mdisp_offset;
|
||||||
.md_dst = md_dst,
|
data.md_dst = md_dst;
|
||||||
.f_src_center = f_src_center,
|
data.f_src_center = f_src_center;
|
||||||
.axis_x = axis_x,
|
data.axis_x = axis_x;
|
||||||
.axis_y = axis_y,
|
data.axis_y = axis_y;
|
||||||
.v1 = v1,
|
data.v1 = v1;
|
||||||
.v4 = v4,
|
data.v4 = v4;
|
||||||
.e1 = e1,
|
data.e1 = e1;
|
||||||
.e2 = e2,
|
data.e2 = e2;
|
||||||
.res = res,
|
data.res = res;
|
||||||
.d = 1.0f / (float)(res - 1),
|
data.d = 1.0f / (float)(res - 1);
|
||||||
};
|
|
||||||
TaskParallelSettings settings;
|
TaskParallelSettings settings;
|
||||||
BLI_parallel_range_settings_defaults(&settings);
|
BLI_parallel_range_settings_defaults(&settings);
|
||||||
settings.use_threading = (res > 5);
|
settings.use_threading = (res > 5);
|
||||||
|
@ -583,9 +587,9 @@ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
|
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
|
||||||
MDisps *mdp = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_mdisp_offset);
|
MDisps *mdp = static_cast<MDisps *>(BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_mdisp_offset));
|
||||||
MDisps *mdl = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset);
|
MDisps *mdl = static_cast<MDisps *>(BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset));
|
||||||
MDisps *mdn = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_mdisp_offset);
|
MDisps *mdn = static_cast<MDisps *>(BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_mdisp_offset));
|
||||||
float co1[3];
|
float co1[3];
|
||||||
int sides;
|
int sides;
|
||||||
int y;
|
int y;
|
||||||
|
@ -615,7 +619,7 @@ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
|
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
|
||||||
MDisps *mdl1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset);
|
MDisps *mdl1 = static_cast<MDisps *>(BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset));
|
||||||
MDisps *mdl2;
|
MDisps *mdl2;
|
||||||
float co1[3], co2[3], co[3];
|
float co1[3], co2[3], co[3];
|
||||||
int sides;
|
int sides;
|
||||||
|
@ -641,10 +645,11 @@ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l->radial_next->v == l->v) {
|
if (l->radial_next->v == l->v) {
|
||||||
mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next, cd_loop_mdisp_offset);
|
mdl2 = static_cast<MDisps *>(BM_ELEM_CD_GET_VOID_P(l->radial_next, cd_loop_mdisp_offset));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next->next, cd_loop_mdisp_offset);
|
mdl2 = static_cast<MDisps *>(
|
||||||
|
BM_ELEM_CD_GET_VOID_P(l->radial_next->next, cd_loop_mdisp_offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
sides = (int)sqrt(mdl1->totdisp);
|
sides = (int)sqrt(mdl1->totdisp);
|
||||||
|
@ -685,10 +690,12 @@ void BM_loop_interp_from_face(
|
||||||
{
|
{
|
||||||
BMLoop *l_iter;
|
BMLoop *l_iter;
|
||||||
BMLoop *l_first;
|
BMLoop *l_first;
|
||||||
const void **vblocks = do_vertex ? BLI_array_alloca(vblocks, f_src->len) : NULL;
|
const void **vblocks = do_vertex ?
|
||||||
const void **blocks = BLI_array_alloca(blocks, f_src->len);
|
static_cast<const void **>(BLI_array_alloca(vblocks, f_src->len)) :
|
||||||
float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
|
nullptr;
|
||||||
float *w = BLI_array_alloca(w, f_src->len);
|
const void **blocks = static_cast<const void **>(BLI_array_alloca(blocks, f_src->len));
|
||||||
|
float(*cos_2d)[2] = static_cast<float(*)[2]>(BLI_array_alloca(cos_2d, f_src->len));
|
||||||
|
float *w = static_cast<float *>(BLI_array_alloca(w, f_src->len));
|
||||||
float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
|
float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
|
||||||
float co[2];
|
float co[2];
|
||||||
|
|
||||||
|
@ -723,9 +730,9 @@ void BM_loop_interp_from_face(
|
||||||
|
|
||||||
/* interpolate */
|
/* interpolate */
|
||||||
interp_weights_poly_v2(w, cos_2d, f_src->len, co);
|
interp_weights_poly_v2(w, cos_2d, f_src->len, co);
|
||||||
CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, f_src->len, l_dst->head.data);
|
CustomData_bmesh_interp(&bm->ldata, blocks, w, nullptr, f_src->len, l_dst->head.data);
|
||||||
if (do_vertex) {
|
if (do_vertex) {
|
||||||
CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, f_src->len, l_dst->v->head.data);
|
CustomData_bmesh_interp(&bm->vdata, vblocks, w, nullptr, f_src->len, l_dst->v->head.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_multires) {
|
if (do_multires) {
|
||||||
|
@ -737,9 +744,9 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src)
|
||||||
{
|
{
|
||||||
BMLoop *l_iter;
|
BMLoop *l_iter;
|
||||||
BMLoop *l_first;
|
BMLoop *l_first;
|
||||||
const void **blocks = BLI_array_alloca(blocks, f_src->len);
|
const void **blocks = static_cast<const void **>(BLI_array_alloca(blocks, f_src->len));
|
||||||
float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
|
float(*cos_2d)[2] = static_cast<float(*)[2]>(BLI_array_alloca(cos_2d, f_src->len));
|
||||||
float *w = BLI_array_alloca(w, f_src->len);
|
float *w = static_cast<float *>(BLI_array_alloca(w, f_src->len));
|
||||||
float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
|
float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
|
||||||
float co[2];
|
float co[2];
|
||||||
|
|
||||||
|
@ -758,7 +765,7 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src)
|
||||||
|
|
||||||
/* interpolate */
|
/* interpolate */
|
||||||
interp_weights_poly_v2(w, cos_2d, f_src->len, co);
|
interp_weights_poly_v2(w, cos_2d, f_src->len, co);
|
||||||
CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, f_src->len, v_dst->head.data);
|
CustomData_bmesh_interp(&bm->vdata, blocks, w, nullptr, f_src->len, v_dst->head.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
||||||
|
@ -773,7 +780,7 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
||||||
CustomData_bmesh_init_pool(data, bm->totvert, BM_VERT);
|
CustomData_bmesh_init_pool(data, bm->totvert, BM_VERT);
|
||||||
|
|
||||||
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
|
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
|
||||||
block = NULL;
|
block = nullptr;
|
||||||
CustomData_bmesh_set_default(data, &block);
|
CustomData_bmesh_set_default(data, &block);
|
||||||
CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block);
|
CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block);
|
||||||
CustomData_bmesh_free_block(olddata, &eve->head.data);
|
CustomData_bmesh_free_block(olddata, &eve->head.data);
|
||||||
|
@ -786,7 +793,7 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
||||||
CustomData_bmesh_init_pool(data, bm->totedge, BM_EDGE);
|
CustomData_bmesh_init_pool(data, bm->totedge, BM_EDGE);
|
||||||
|
|
||||||
BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
|
BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
|
||||||
block = NULL;
|
block = nullptr;
|
||||||
CustomData_bmesh_set_default(data, &block);
|
CustomData_bmesh_set_default(data, &block);
|
||||||
CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block);
|
CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block);
|
||||||
CustomData_bmesh_free_block(olddata, &eed->head.data);
|
CustomData_bmesh_free_block(olddata, &eed->head.data);
|
||||||
|
@ -801,7 +808,7 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
||||||
CustomData_bmesh_init_pool(data, bm->totloop, BM_LOOP);
|
CustomData_bmesh_init_pool(data, bm->totloop, BM_LOOP);
|
||||||
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
|
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
|
||||||
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
||||||
block = NULL;
|
block = nullptr;
|
||||||
CustomData_bmesh_set_default(data, &block);
|
CustomData_bmesh_set_default(data, &block);
|
||||||
CustomData_bmesh_copy_data(olddata, data, l->head.data, &block);
|
CustomData_bmesh_copy_data(olddata, data, l->head.data, &block);
|
||||||
CustomData_bmesh_free_block(olddata, &l->head.data);
|
CustomData_bmesh_free_block(olddata, &l->head.data);
|
||||||
|
@ -815,7 +822,7 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
||||||
CustomData_bmesh_init_pool(data, bm->totface, BM_FACE);
|
CustomData_bmesh_init_pool(data, bm->totface, BM_FACE);
|
||||||
|
|
||||||
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
|
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
|
||||||
block = NULL;
|
block = nullptr;
|
||||||
CustomData_bmesh_set_default(data, &block);
|
CustomData_bmesh_set_default(data, &block);
|
||||||
CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block);
|
CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block);
|
||||||
CustomData_bmesh_free_block(olddata, &efa->head.data);
|
CustomData_bmesh_free_block(olddata, &efa->head.data);
|
||||||
|
@ -838,11 +845,13 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
||||||
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
|
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
|
||||||
{
|
{
|
||||||
CustomData olddata = *data;
|
CustomData olddata = *data;
|
||||||
olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
|
olddata.layers = (olddata.layers) ?
|
||||||
|
static_cast<CustomDataLayer *>(MEM_dupallocN(olddata.layers)) :
|
||||||
|
nullptr;
|
||||||
/* The pool is now owned by `olddata` and must not be shared. */
|
/* The pool is now owned by `olddata` and must not be shared. */
|
||||||
data->pool = NULL;
|
data->pool = nullptr;
|
||||||
|
|
||||||
CustomData_add_layer(data, type, CD_SET_DEFAULT, 0);
|
CustomData_add_layer(data, eCustomDataType(type), CD_SET_DEFAULT, 0);
|
||||||
|
|
||||||
update_data_blocks(bm, &olddata, data);
|
update_data_blocks(bm, &olddata, data);
|
||||||
if (olddata.layers) {
|
if (olddata.layers) {
|
||||||
|
@ -853,11 +862,13 @@ void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
|
||||||
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
|
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
|
||||||
{
|
{
|
||||||
CustomData olddata = *data;
|
CustomData olddata = *data;
|
||||||
olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
|
olddata.layers = (olddata.layers) ?
|
||||||
|
static_cast<CustomDataLayer *>(MEM_dupallocN(olddata.layers)) :
|
||||||
|
nullptr;
|
||||||
/* The pool is now owned by `olddata` and must not be shared. */
|
/* The pool is now owned by `olddata` and must not be shared. */
|
||||||
data->pool = NULL;
|
data->pool = nullptr;
|
||||||
|
|
||||||
CustomData_add_layer_named(data, type, CD_SET_DEFAULT, 0, name);
|
CustomData_add_layer_named(data, eCustomDataType(type), CD_SET_DEFAULT, 0, name);
|
||||||
|
|
||||||
update_data_blocks(bm, &olddata, data);
|
update_data_blocks(bm, &olddata, data);
|
||||||
if (olddata.layers) {
|
if (olddata.layers) {
|
||||||
|
@ -867,7 +878,7 @@ void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *
|
||||||
|
|
||||||
void BM_data_layer_ensure_named(BMesh *bm, CustomData *data, int type, const char *name)
|
void BM_data_layer_ensure_named(BMesh *bm, CustomData *data, int type, const char *name)
|
||||||
{
|
{
|
||||||
if (CustomData_get_named_layer_index(data, type, name) == -1) {
|
if (CustomData_get_named_layer_index(data, eCustomDataType(type), name) == -1) {
|
||||||
BM_data_layer_add_named(bm, data, type, name);
|
BM_data_layer_add_named(bm, data, type, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -923,11 +934,13 @@ void BM_uv_map_ensure_pin_attr(BMesh *bm, const char *uv_map_name)
|
||||||
void BM_data_layer_free(BMesh *bm, CustomData *data, int type)
|
void BM_data_layer_free(BMesh *bm, CustomData *data, int type)
|
||||||
{
|
{
|
||||||
CustomData olddata = *data;
|
CustomData olddata = *data;
|
||||||
olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
|
olddata.layers = (olddata.layers) ?
|
||||||
|
static_cast<CustomDataLayer *>(MEM_dupallocN(olddata.layers)) :
|
||||||
|
nullptr;
|
||||||
/* The pool is now owned by `olddata` and must not be shared. */
|
/* The pool is now owned by `olddata` and must not be shared. */
|
||||||
data->pool = NULL;
|
data->pool = nullptr;
|
||||||
|
|
||||||
const bool had_layer = CustomData_free_layer_active(data, type, 0);
|
const bool had_layer = CustomData_free_layer_active(data, eCustomDataType(type), 0);
|
||||||
/* Assert because its expensive to realloc - better not do if layer isn't present. */
|
/* Assert because its expensive to realloc - better not do if layer isn't present. */
|
||||||
BLI_assert(had_layer != false);
|
BLI_assert(had_layer != false);
|
||||||
UNUSED_VARS_NDEBUG(had_layer);
|
UNUSED_VARS_NDEBUG(had_layer);
|
||||||
|
@ -941,9 +954,11 @@ void BM_data_layer_free(BMesh *bm, CustomData *data, int type)
|
||||||
bool BM_data_layer_free_named(BMesh *bm, CustomData *data, const char *name)
|
bool BM_data_layer_free_named(BMesh *bm, CustomData *data, const char *name)
|
||||||
{
|
{
|
||||||
CustomData olddata = *data;
|
CustomData olddata = *data;
|
||||||
olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
|
olddata.layers = (olddata.layers) ?
|
||||||
|
static_cast<CustomDataLayer *>(MEM_dupallocN(olddata.layers)) :
|
||||||
|
nullptr;
|
||||||
/* The pool is now owned by `olddata` and must not be shared. */
|
/* The pool is now owned by `olddata` and must not be shared. */
|
||||||
data->pool = NULL;
|
data->pool = nullptr;
|
||||||
|
|
||||||
const bool had_layer = CustomData_free_layer_named(data, name, 0);
|
const bool had_layer = CustomData_free_layer_named(data, name, 0);
|
||||||
|
|
||||||
|
@ -965,12 +980,17 @@ bool BM_data_layer_free_named(BMesh *bm, CustomData *data, const char *name)
|
||||||
void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n)
|
void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n)
|
||||||
{
|
{
|
||||||
CustomData olddata = *data;
|
CustomData olddata = *data;
|
||||||
olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
|
olddata.layers = (olddata.layers) ?
|
||||||
|
static_cast<CustomDataLayer *>(MEM_dupallocN(olddata.layers)) :
|
||||||
|
nullptr;
|
||||||
/* The pool is now owned by `olddata` and must not be shared. */
|
/* The pool is now owned by `olddata` and must not be shared. */
|
||||||
data->pool = NULL;
|
data->pool = nullptr;
|
||||||
|
|
||||||
const bool had_layer = CustomData_free_layer(
|
const bool had_layer = CustomData_free_layer(
|
||||||
data, type, 0, CustomData_get_layer_index_n(data, type, n));
|
data,
|
||||||
|
eCustomDataType(type),
|
||||||
|
0,
|
||||||
|
CustomData_get_layer_index_n(data, eCustomDataType(type), n));
|
||||||
/* Assert because its expensive to realloc - better not do if layer isn't present. */
|
/* Assert because its expensive to realloc - better not do if layer isn't present. */
|
||||||
BLI_assert(had_layer != false);
|
BLI_assert(had_layer != false);
|
||||||
UNUSED_VARS_NDEBUG(had_layer);
|
UNUSED_VARS_NDEBUG(had_layer);
|
||||||
|
@ -989,24 +1009,24 @@ void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int ds
|
||||||
BMVert *eve;
|
BMVert *eve;
|
||||||
|
|
||||||
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
|
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
|
||||||
void *ptr = CustomData_bmesh_get_n(data, eve->head.data, type, src_n);
|
void *ptr = CustomData_bmesh_get_n(data, eve->head.data, eCustomDataType(type), src_n);
|
||||||
CustomData_bmesh_set_n(data, eve->head.data, type, dst_n, ptr);
|
CustomData_bmesh_set_n(data, eve->head.data, eCustomDataType(type), dst_n, ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (&bm->edata == data) {
|
else if (&bm->edata == data) {
|
||||||
BMEdge *eed;
|
BMEdge *eed;
|
||||||
|
|
||||||
BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
|
BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
|
||||||
void *ptr = CustomData_bmesh_get_n(data, eed->head.data, type, src_n);
|
void *ptr = CustomData_bmesh_get_n(data, eed->head.data, eCustomDataType(type), src_n);
|
||||||
CustomData_bmesh_set_n(data, eed->head.data, type, dst_n, ptr);
|
CustomData_bmesh_set_n(data, eed->head.data, eCustomDataType(type), dst_n, ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (&bm->pdata == data) {
|
else if (&bm->pdata == data) {
|
||||||
BMFace *efa;
|
BMFace *efa;
|
||||||
|
|
||||||
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
|
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
|
||||||
void *ptr = CustomData_bmesh_get_n(data, efa->head.data, type, src_n);
|
void *ptr = CustomData_bmesh_get_n(data, efa->head.data, eCustomDataType(type), src_n);
|
||||||
CustomData_bmesh_set_n(data, efa->head.data, type, dst_n, ptr);
|
CustomData_bmesh_set_n(data, efa->head.data, eCustomDataType(type), dst_n, ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (&bm->ldata == data) {
|
else if (&bm->ldata == data) {
|
||||||
|
@ -1016,8 +1036,8 @@ void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int ds
|
||||||
|
|
||||||
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
|
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
|
||||||
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
||||||
void *ptr = CustomData_bmesh_get_n(data, l->head.data, type, src_n);
|
void *ptr = CustomData_bmesh_get_n(data, l->head.data, eCustomDataType(type), src_n);
|
||||||
CustomData_bmesh_set_n(data, l->head.data, type, dst_n, ptr);
|
CustomData_bmesh_set_n(data, l->head.data, eCustomDataType(type), dst_n, ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1029,13 +1049,15 @@ void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int ds
|
||||||
|
|
||||||
float BM_elem_float_data_get(CustomData *cd, void *element, int type)
|
float BM_elem_float_data_get(CustomData *cd, void *element, int type)
|
||||||
{
|
{
|
||||||
const float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
|
const float *f = static_cast<const float *>(
|
||||||
|
CustomData_bmesh_get(cd, ((BMHeader *)element)->data, eCustomDataType(type)));
|
||||||
return f ? *f : 0.0f;
|
return f ? *f : 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val)
|
void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val)
|
||||||
{
|
{
|
||||||
float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
|
float *f = static_cast<float *>(
|
||||||
|
CustomData_bmesh_get(cd, ((BMHeader *)element)->data, eCustomDataType(type)));
|
||||||
if (f) {
|
if (f) {
|
||||||
*f = val;
|
*f = val;
|
||||||
}
|
}
|
||||||
|
@ -1117,8 +1139,9 @@ static void bm_loop_walk_data(struct LoopWalkCtx *lwc, BMLoop *l_walk)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
BLI_assert(CustomData_data_equals(
|
BLI_assert(CustomData_data_equals(eCustomDataType(lwc->type),
|
||||||
lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_walk, lwc->cd_layer_offset)));
|
lwc->data_ref,
|
||||||
|
BM_ELEM_CD_GET_VOID_P(l_walk, lwc->cd_layer_offset)));
|
||||||
BLI_assert(BM_elem_flag_test(l_walk, BM_ELEM_INTERNAL_TAG));
|
BLI_assert(BM_elem_flag_test(l_walk, BM_ELEM_INTERNAL_TAG));
|
||||||
|
|
||||||
bm_loop_walk_add(lwc, l_walk);
|
bm_loop_walk_add(lwc, l_walk);
|
||||||
|
@ -1132,8 +1155,9 @@ static void bm_loop_walk_data(struct LoopWalkCtx *lwc, BMLoop *l_walk)
|
||||||
}
|
}
|
||||||
BLI_assert(l_other->v == l_walk->v);
|
BLI_assert(l_other->v == l_walk->v);
|
||||||
if (BM_elem_flag_test(l_other, BM_ELEM_INTERNAL_TAG)) {
|
if (BM_elem_flag_test(l_other, BM_ELEM_INTERNAL_TAG)) {
|
||||||
if (CustomData_data_equals(
|
if (CustomData_data_equals(eCustomDataType(lwc->type),
|
||||||
lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_other, lwc->cd_layer_offset)))
|
lwc->data_ref,
|
||||||
|
BM_ELEM_CD_GET_VOID_P(l_other, lwc->cd_layer_offset)))
|
||||||
{
|
{
|
||||||
bm_loop_walk_data(lwc, l_other);
|
bm_loop_walk_data(lwc, l_other);
|
||||||
}
|
}
|
||||||
|
@ -1146,7 +1170,7 @@ LinkNode *BM_vert_loop_groups_data_layer_create(
|
||||||
BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, MemArena *arena)
|
BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, MemArena *arena)
|
||||||
{
|
{
|
||||||
struct LoopWalkCtx lwc;
|
struct LoopWalkCtx lwc;
|
||||||
LinkNode *groups = NULL;
|
LinkNode *groups = nullptr;
|
||||||
BMLoop *l;
|
BMLoop *l;
|
||||||
BMIter liter;
|
BMIter liter;
|
||||||
int loop_num;
|
int loop_num;
|
||||||
|
@ -1166,13 +1190,14 @@ LinkNode *BM_vert_loop_groups_data_layer_create(
|
||||||
bm->elem_index_dirty |= BM_LOOP;
|
bm->elem_index_dirty |= BM_LOOP;
|
||||||
|
|
||||||
lwc.data_len = 0;
|
lwc.data_len = 0;
|
||||||
lwc.data_array = BLI_memarena_alloc(lwc.arena, sizeof(void *) * loop_num);
|
lwc.data_array = static_cast<void **>(BLI_memarena_alloc(lwc.arena, sizeof(void *) * loop_num));
|
||||||
lwc.data_index_array = BLI_memarena_alloc(lwc.arena, sizeof(int) * loop_num);
|
lwc.data_index_array = static_cast<int *>(BLI_memarena_alloc(lwc.arena, sizeof(int) * loop_num));
|
||||||
lwc.weight_array = BLI_memarena_alloc(lwc.arena, sizeof(float) * loop_num);
|
lwc.weight_array = static_cast<float *>(BLI_memarena_alloc(lwc.arena, sizeof(float) * loop_num));
|
||||||
|
|
||||||
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
|
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
|
||||||
if (BM_elem_flag_test(l, BM_ELEM_INTERNAL_TAG)) {
|
if (BM_elem_flag_test(l, BM_ELEM_INTERNAL_TAG)) {
|
||||||
struct LoopGroupCD *lf = BLI_memarena_alloc(lwc.arena, sizeof(*lf));
|
struct LoopGroupCD *lf = static_cast<LoopGroupCD *>(
|
||||||
|
BLI_memarena_alloc(lwc.arena, sizeof(*lf)));
|
||||||
int len_prev = lwc.data_len;
|
int len_prev = lwc.data_len;
|
||||||
|
|
||||||
lwc.data_ref = BM_ELEM_CD_GET_VOID_P(l, lwc.cd_layer_offset);
|
lwc.data_ref = BM_ELEM_CD_GET_VOID_P(l, lwc.cd_layer_offset);
|
||||||
|
@ -1208,7 +1233,7 @@ static void bm_vert_loop_groups_data_layer_merge__single(BMesh *bm,
|
||||||
int layer_n,
|
int layer_n,
|
||||||
void *data_tmp)
|
void *data_tmp)
|
||||||
{
|
{
|
||||||
struct LoopGroupCD *lf = lf_p;
|
struct LoopGroupCD *lf = static_cast<LoopGroupCD *>(lf_p);
|
||||||
const int type = bm->ldata.layers[layer_n].type;
|
const int type = bm->ldata.layers[layer_n].type;
|
||||||
int i;
|
int i;
|
||||||
const float *data_weights;
|
const float *data_weights;
|
||||||
|
@ -1216,23 +1241,23 @@ static void bm_vert_loop_groups_data_layer_merge__single(BMesh *bm,
|
||||||
data_weights = lf->data_weights;
|
data_weights = lf->data_weights;
|
||||||
|
|
||||||
CustomData_bmesh_interp_n(
|
CustomData_bmesh_interp_n(
|
||||||
&bm->ldata, (const void **)lf->data, data_weights, NULL, lf->data_len, data_tmp, layer_n);
|
&bm->ldata, (const void **)lf->data, data_weights, nullptr, lf->data_len, data_tmp, layer_n);
|
||||||
|
|
||||||
for (i = 0; i < lf->data_len; i++) {
|
for (i = 0; i < lf->data_len; i++) {
|
||||||
CustomData_copy_elements(type, data_tmp, lf->data[i], 1);
|
CustomData_copy_elements(eCustomDataType(type), data_tmp, lf->data[i], 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bm_vert_loop_groups_data_layer_merge_weights__single(
|
static void bm_vert_loop_groups_data_layer_merge_weights__single(
|
||||||
BMesh *bm, void *lf_p, const int layer_n, void *data_tmp, const float *loop_weights)
|
BMesh *bm, void *lf_p, const int layer_n, void *data_tmp, const float *loop_weights)
|
||||||
{
|
{
|
||||||
struct LoopGroupCD *lf = lf_p;
|
struct LoopGroupCD *lf = static_cast<LoopGroupCD *>(lf_p);
|
||||||
const int type = bm->ldata.layers[layer_n].type;
|
const int type = bm->ldata.layers[layer_n].type;
|
||||||
int i;
|
int i;
|
||||||
const float *data_weights;
|
const float *data_weights;
|
||||||
|
|
||||||
/* re-weight */
|
/* re-weight */
|
||||||
float *temp_weights = BLI_array_alloca(temp_weights, lf->data_len);
|
float *temp_weights = static_cast<float *>(BLI_array_alloca(temp_weights, lf->data_len));
|
||||||
float weight_accum = 0.0f;
|
float weight_accum = 0.0f;
|
||||||
|
|
||||||
for (i = 0; i < lf->data_len; i++) {
|
for (i = 0; i < lf->data_len; i++) {
|
||||||
|
@ -1250,17 +1275,17 @@ static void bm_vert_loop_groups_data_layer_merge_weights__single(
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomData_bmesh_interp_n(
|
CustomData_bmesh_interp_n(
|
||||||
&bm->ldata, (const void **)lf->data, data_weights, NULL, lf->data_len, data_tmp, layer_n);
|
&bm->ldata, (const void **)lf->data, data_weights, nullptr, lf->data_len, data_tmp, layer_n);
|
||||||
|
|
||||||
for (i = 0; i < lf->data_len; i++) {
|
for (i = 0; i < lf->data_len; i++) {
|
||||||
CustomData_copy_elements(type, data_tmp, lf->data[i], 1);
|
CustomData_copy_elements(eCustomDataType(type), data_tmp, lf->data[i], 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BM_vert_loop_groups_data_layer_merge(BMesh *bm, LinkNode *groups, const int layer_n)
|
void BM_vert_loop_groups_data_layer_merge(BMesh *bm, LinkNode *groups, const int layer_n)
|
||||||
{
|
{
|
||||||
const int type = bm->ldata.layers[layer_n].type;
|
const int type = bm->ldata.layers[layer_n].type;
|
||||||
const int size = CustomData_sizeof(type);
|
const int size = CustomData_sizeof(eCustomDataType(type));
|
||||||
void *data_tmp = alloca(size);
|
void *data_tmp = alloca(size);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -1274,7 +1299,7 @@ void BM_vert_loop_groups_data_layer_merge_weights(BMesh *bm,
|
||||||
const float *loop_weights)
|
const float *loop_weights)
|
||||||
{
|
{
|
||||||
const int type = bm->ldata.layers[layer_n].type;
|
const int type = bm->ldata.layers[layer_n].type;
|
||||||
const int size = CustomData_sizeof(type);
|
const int size = CustomData_sizeof(eCustomDataType(type));
|
||||||
void *data_tmp = alloca(size);
|
void *data_tmp = alloca(size);
|
||||||
|
|
||||||
do {
|
do {
|
|
@ -62,7 +62,6 @@ enum {
|
||||||
SIMFACE_NORMAL,
|
SIMFACE_NORMAL,
|
||||||
SIMFACE_COPLANAR,
|
SIMFACE_COPLANAR,
|
||||||
SIMFACE_SMOOTH,
|
SIMFACE_SMOOTH,
|
||||||
SIMFACE_FACEMAP,
|
|
||||||
SIMFACE_FREESTYLE,
|
SIMFACE_FREESTYLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ typedef struct PathLinkState {
|
||||||
} PathLinkState;
|
} PathLinkState;
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name Min Dist Dir Util
|
/** \name Min Dist Dir Utilities
|
||||||
*
|
*
|
||||||
* Simply getting the closest intersecting vert/edge is _not_ good enough. see #43792
|
* Simply getting the closest intersecting vert/edge is _not_ good enough. see #43792
|
||||||
* we need to get the closest in both directions since the absolute closest may be a dead-end.
|
* we need to get the closest in both directions since the absolute closest may be a dead-end.
|
||||||
|
|
|
@ -766,7 +766,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
|
||||||
vert_coords = BLI_ghash_ptr_new(__func__);
|
vert_coords = BLI_ghash_ptr_new(__func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* util macros */
|
/* Utility macros. */
|
||||||
#define VERT_ORIG_STORE(_v) \
|
#define VERT_ORIG_STORE(_v) \
|
||||||
{ \
|
{ \
|
||||||
float *_co = BLI_memarena_alloc(vert_coords_orig, sizeof(float[3])); \
|
float *_co = BLI_memarena_alloc(vert_coords_orig, sizeof(float[3])); \
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "COM_KuwaharaNode.h"
|
#include "COM_KuwaharaNode.h"
|
||||||
|
|
||||||
|
#include "COM_ConvolutionFilterOperation.h"
|
||||||
#include "COM_FastGaussianBlurOperation.h"
|
#include "COM_FastGaussianBlurOperation.h"
|
||||||
#include "COM_KuwaharaAnisotropicOperation.h"
|
#include "COM_KuwaharaAnisotropicOperation.h"
|
||||||
#include "COM_KuwaharaClassicOperation.h"
|
#include "COM_KuwaharaClassicOperation.h"
|
||||||
|
|
|
@ -104,7 +104,7 @@ void KuwaharaAnisotropicOperation::execute_pixel_sampled(float output[4],
|
||||||
int dx2 = int(sx * (cos(theta) * dx - sin(theta) * dy));
|
int dx2 = int(sx * (cos(theta) * dx - sin(theta) * dy));
|
||||||
int dy2 = int(sy * (sin(theta) * dx + cos(theta) * dy));
|
int dy2 = int(sy * (sin(theta) * dx + cos(theta) * dy));
|
||||||
|
|
||||||
/* Clamp image to avoid artefacts at borders. */
|
/* Clamp image to avoid artifacts at borders. */
|
||||||
const int xx = math::clamp(int(x) + dx2, 0, width - 1);
|
const int xx = math::clamp(int(x) + dx2, 0, width - 1);
|
||||||
const int yy = math::clamp(int(y) + dy2, 0, height - 1);
|
const int yy = math::clamp(int(y) + dy2, 0, height - 1);
|
||||||
|
|
||||||
|
@ -117,9 +117,9 @@ void KuwaharaAnisotropicOperation::execute_pixel_sampled(float output[4],
|
||||||
float color[4];
|
float color[4];
|
||||||
image_reader_->read(color, xx, yy, nullptr);
|
image_reader_->read(color, xx, yy, nullptr);
|
||||||
const double v = color[ch];
|
const double v = color[ch];
|
||||||
/* todo(zazizizou): only compute lum once per region */
|
/* TODO(@zazizizou): only compute lum once per region */
|
||||||
const float lum = IMB_colormanagement_get_luminance(color);
|
const float lum = IMB_colormanagement_get_luminance(color);
|
||||||
/* todo(zazizizou): only compute mean for the selected region */
|
/* TODO(@zazizizou): only compute mean for the selected region */
|
||||||
mean[t] += g * v;
|
mean[t] += g * v;
|
||||||
sum[t] += g * lum;
|
sum[t] += g * lum;
|
||||||
var[t] += g * lum * lum;
|
var[t] += g * lum * lum;
|
||||||
|
@ -155,7 +155,7 @@ void KuwaharaAnisotropicOperation::execute_pixel_sampled(float output[4],
|
||||||
void KuwaharaAnisotropicOperation::set_kernel_size(int kernel_size)
|
void KuwaharaAnisotropicOperation::set_kernel_size(int kernel_size)
|
||||||
{
|
{
|
||||||
/* Filter will be split into n_div.
|
/* Filter will be split into n_div.
|
||||||
* Add n_div / 2 to avoid artefacts such as random black pixels in image. */
|
* Add n_div / 2 to avoid artifacts such as random black pixels in image. */
|
||||||
kernel_size_ = kernel_size + n_div_ / 2;
|
kernel_size_ = kernel_size + n_div_ / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ void KuwaharaAnisotropicOperation::update_memory_buffer_partial(MemoryBuffer *ou
|
||||||
int dx2 = int(sx * (cos(theta) * dx - sin(theta) * dy));
|
int dx2 = int(sx * (cos(theta) * dx - sin(theta) * dy));
|
||||||
int dy2 = int(sy * (sin(theta) * dx + cos(theta) * dy));
|
int dy2 = int(sy * (sin(theta) * dx + cos(theta) * dy));
|
||||||
|
|
||||||
/* Clamp image to avoid artefacts at borders. */
|
/* Clamp image to avoid artifacts at borders. */
|
||||||
const int xx = math::clamp(x + dx2, 0, width - 1);
|
const int xx = math::clamp(x + dx2, 0, width - 1);
|
||||||
const int yy = math::clamp(y + dy2, 0, height - 1);
|
const int yy = math::clamp(y + dy2, 0, height - 1);
|
||||||
|
|
||||||
|
@ -257,9 +257,9 @@ void KuwaharaAnisotropicOperation::update_memory_buffer_partial(MemoryBuffer *ou
|
||||||
const double v = image->get_value(xx, yy, ch);
|
const double v = image->get_value(xx, yy, ch);
|
||||||
float color[4];
|
float color[4];
|
||||||
image->read_elem(xx, yy, color);
|
image->read_elem(xx, yy, color);
|
||||||
/* TODO(zazizizou): only compute lum once per region. */
|
/* TODO(@zazizizou): only compute lum once per region. */
|
||||||
const float lum = IMB_colormanagement_get_luminance(color);
|
const float lum = IMB_colormanagement_get_luminance(color);
|
||||||
/* TODO(zazizizou): only compute mean for the selected region. */
|
/* TODO(@zazizizou): only compute mean for the selected region. */
|
||||||
mean[t] += g * v;
|
mean[t] += g * v;
|
||||||
sum[t] += g * lum;
|
sum[t] += g * lum;
|
||||||
var[t] += g * lum * lum;
|
var[t] += g * lum * lum;
|
||||||
|
|
|
@ -101,6 +101,11 @@ void KuwaharaClassicOperation::execute_pixel_sampled(float output[4],
|
||||||
}
|
}
|
||||||
output[ch] = mean[min_index];
|
output[ch] = mean[min_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* No changes for alpha channel. */
|
||||||
|
float tmp[4];
|
||||||
|
image_reader_->read_sampled(tmp, x, y, sampler);
|
||||||
|
output[3] = tmp[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
void KuwaharaClassicOperation::set_kernel_size(int kernel_size)
|
void KuwaharaClassicOperation::set_kernel_size(int kernel_size)
|
||||||
|
|
|
@ -45,9 +45,14 @@ class Context {
|
||||||
/* Get the node tree used for compositing. */
|
/* Get the node tree used for compositing. */
|
||||||
virtual const bNodeTree &get_node_tree() const = 0;
|
virtual const bNodeTree &get_node_tree() const = 0;
|
||||||
|
|
||||||
/* True if compositor should do write file outputs, false if only running for viewing. */
|
/* True if the compositor should write file outputs, false otherwise. */
|
||||||
virtual bool use_file_output() const = 0;
|
virtual bool use_file_output() const = 0;
|
||||||
|
|
||||||
|
/* True if the compositor should write the composite output, otherwise, the compositor is assumed
|
||||||
|
* to not support the composite output and just displays its viewer output. In that case, the
|
||||||
|
* composite output will be used as a fallback viewer if no other viewer exists */
|
||||||
|
virtual bool use_composite_output() const = 0;
|
||||||
|
|
||||||
/* True if color management should be used for texture evaluation. */
|
/* True if color management should be used for texture evaluation. */
|
||||||
virtual bool use_texture_color_management() const = 0;
|
virtual bool use_texture_color_management() const = 0;
|
||||||
|
|
||||||
|
@ -66,10 +71,14 @@ class Context {
|
||||||
* region. */
|
* region. */
|
||||||
virtual rcti get_compositing_region() const = 0;
|
virtual rcti get_compositing_region() const = 0;
|
||||||
|
|
||||||
/* Get the texture representing the output where the result of the compositor should be
|
/* Get the texture where the result of the compositor should be written. This should be called by
|
||||||
* written. This should be called by output nodes to get their target texture. */
|
* the composite output node to get its target texture. */
|
||||||
virtual GPUTexture *get_output_texture() = 0;
|
virtual GPUTexture *get_output_texture() = 0;
|
||||||
|
|
||||||
|
/* Get the texture where the result of the compositor viewer should be written. This should be
|
||||||
|
* called by viewer output nodes to get their target texture. */
|
||||||
|
virtual GPUTexture *get_viewer_output_texture() = 0;
|
||||||
|
|
||||||
/* Get the texture where the given render pass is stored. This should be called by the Render
|
/* Get the texture where the given render pass is stored. This should be called by the Render
|
||||||
* Layer node to populate its outputs. */
|
* Layer node to populate its outputs. */
|
||||||
virtual GPUTexture *get_input_texture(int view_layer, const char *pass_name) = 0;
|
virtual GPUTexture *get_input_texture(int view_layer, const char *pass_name) = 0;
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#include "NOD_derived_node_tree.hh"
|
#include "NOD_derived_node_tree.hh"
|
||||||
|
|
||||||
|
#include "COM_context.hh"
|
||||||
|
|
||||||
namespace blender::realtime_compositor {
|
namespace blender::realtime_compositor {
|
||||||
|
|
||||||
using namespace nodes::derived_node_tree_types;
|
using namespace nodes::derived_node_tree_types;
|
||||||
|
@ -18,6 +20,6 @@ using Schedule = VectorSet<DNode>;
|
||||||
/* Computes the execution schedule of the node tree. This is essentially a post-order depth first
|
/* Computes the execution schedule of the node tree. This is essentially a post-order depth first
|
||||||
* traversal of the node tree from the output node to the leaf input nodes, with informed order of
|
* traversal of the node tree from the output node to the leaf input nodes, with informed order of
|
||||||
* traversal of dependencies based on a heuristic estimation of the number of needed buffers. */
|
* traversal of dependencies based on a heuristic estimation of the number of needed buffers. */
|
||||||
Schedule compute_schedule(const DerivedNodeTree &tree);
|
Schedule compute_schedule(const Context &context, const DerivedNodeTree &tree);
|
||||||
|
|
||||||
} // namespace blender::realtime_compositor
|
} // namespace blender::realtime_compositor
|
||||||
|
|
|
@ -72,7 +72,7 @@ void Evaluator::compile_and_evaluate()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Schedule schedule = compute_schedule(*derived_node_tree_);
|
const Schedule schedule = compute_schedule(context_, *derived_node_tree_);
|
||||||
|
|
||||||
CompileState compile_state(schedule);
|
CompileState compile_state(schedule);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "BKE_node.hh"
|
#include "BKE_node.hh"
|
||||||
#include "BKE_node_runtime.hh"
|
#include "BKE_node_runtime.hh"
|
||||||
|
|
||||||
|
#include "COM_context.hh"
|
||||||
#include "COM_scheduler.hh"
|
#include "COM_scheduler.hh"
|
||||||
#include "COM_utilities.hh"
|
#include "COM_utilities.hh"
|
||||||
|
|
||||||
|
@ -72,55 +73,88 @@ static const DTreeContext *find_active_context(const DerivedNodeTree &tree)
|
||||||
return find_active_context_recursive(&tree.root_context(), NODE_INSTANCE_KEY_BASE);
|
return find_active_context_recursive(&tree.root_context(), NODE_INSTANCE_KEY_BASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the output node which is marked as NODE_DO_OUTPUT. If multiple types of output nodes are
|
/* Add the viewer node which is marked as NODE_DO_OUTPUT in the given context to the given stack.
|
||||||
* marked, then the preference will be CMP_NODE_VIEWER > CMP_NODE_SPLITVIEWER > CMP_NODE_COMPOSITE.
|
* If multiple types of viewer nodes are marked, then the preference will be CMP_NODE_VIEWER >
|
||||||
* If no output node exists, a null node will be returned. */
|
* CMP_NODE_SPLITVIEWER. If no viewer nodes were found, composite nodes can be added as a fallback
|
||||||
static DNode find_output_in_context(const DTreeContext *context)
|
* viewer node. */
|
||||||
|
static bool add_viewer_nodes_in_context(const DTreeContext *context, Stack<DNode> &node_stack)
|
||||||
{
|
{
|
||||||
const bNodeTree &tree = context->btree();
|
for (const bNode *node : context->btree().nodes_by_type("CompositorNodeViewer")) {
|
||||||
|
|
||||||
for (const bNode *node : tree.nodes_by_type("CompositorNodeViewer")) {
|
|
||||||
if (node->flag & NODE_DO_OUTPUT) {
|
if (node->flag & NODE_DO_OUTPUT) {
|
||||||
return DNode(context, node);
|
node_stack.push(DNode(context, node));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const bNode *node : tree.nodes_by_type("CompositorNodeSplitViewer")) {
|
for (const bNode *node : context->btree().nodes_by_type("CompositorNodeSplitViewer")) {
|
||||||
if (node->flag & NODE_DO_OUTPUT) {
|
if (node->flag & NODE_DO_OUTPUT) {
|
||||||
return DNode(context, node);
|
node_stack.push(DNode(context, node));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const bNode *node : tree.nodes_by_type("CompositorNodeComposite")) {
|
/* The active Composite node was already added, no need to add it again, see the next block. */
|
||||||
|
if (!node_stack.is_empty() && node_stack.peek()->type == CMP_NODE_COMPOSITE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No active viewers exist in this context, try to add the Composite node as a fallback viewer if
|
||||||
|
* it was not already added. */
|
||||||
|
for (const bNode *node : context->btree().nodes_by_type("CompositorNodeComposite")) {
|
||||||
if (node->flag & NODE_DO_OUTPUT) {
|
if (node->flag & NODE_DO_OUTPUT) {
|
||||||
return DNode(context, node);
|
node_stack.push(DNode(context, node));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return DNode();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute the output node whose result should be computed. This node is the output node that
|
/* Add the output nodes whose result should be computed to the given stack. This includes File
|
||||||
* satisfies the requirements in the find_output_in_context function. First, the active context is
|
* Output, Composite, and Viewer nodes. Viewer nodes are a special case, as only the nodes that
|
||||||
* searched for an output node, if non was found, the root context is search. For more information
|
* satisfies the requirements in the add_viewer_nodes_in_context function are added. First, the
|
||||||
* on what contexts mean here, see the find_active_context function. */
|
* active context is searched for viewer nodes, if non were found, the root context is searched.
|
||||||
static DNode compute_output_node(const DerivedNodeTree &tree)
|
* For more information on what contexts mean here, see the find_active_context function. */
|
||||||
|
static void add_output_nodes(const Context &context,
|
||||||
|
const DerivedNodeTree &tree,
|
||||||
|
Stack<DNode> &node_stack)
|
||||||
{
|
{
|
||||||
|
const DTreeContext &root_context = tree.root_context();
|
||||||
|
|
||||||
|
/* Only add File Output nodes if the context supports them. */
|
||||||
|
if (context.use_file_output()) {
|
||||||
|
for (const bNode *node : root_context.btree().nodes_by_type("CompositorNodeOutputFile")) {
|
||||||
|
node_stack.push(DNode(&root_context, node));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only add the Composite output node if the context supports composite outputs. The active
|
||||||
|
* Composite node may still be added as a fallback viewer output below. */
|
||||||
|
if (context.use_composite_output()) {
|
||||||
|
for (const bNode *node : root_context.btree().nodes_by_type("CompositorNodeComposite")) {
|
||||||
|
if (node->flag & NODE_DO_OUTPUT) {
|
||||||
|
node_stack.push(DNode(&root_context, node));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const DTreeContext *active_context = find_active_context(tree);
|
const DTreeContext *active_context = find_active_context(tree);
|
||||||
|
const bool viewer_was_added = add_viewer_nodes_in_context(active_context, node_stack);
|
||||||
|
|
||||||
const DNode node = find_output_in_context(active_context);
|
/* An active viewer was added, no need to search further. */
|
||||||
if (node) {
|
if (viewer_was_added) {
|
||||||
return node;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the active context is the root one and no output node was found, we consider this node tree
|
/* If the active context is the root one and no viewer nodes were found, we consider this node
|
||||||
* to have no output node, even if one of the non-active descendants have an output node. */
|
* tree to have no viewer nodes, even if one of the non-active descendants have viewer nodes. */
|
||||||
if (active_context->is_root()) {
|
if (active_context->is_root()) {
|
||||||
return DNode();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The active context doesn't have an output node, search in the root context as a fallback. */
|
/* The active context doesn't have a viewer node, search in the root context as a fallback. */
|
||||||
return find_output_in_context(&tree.root_context());
|
add_viewer_nodes_in_context(&tree.root_context(), node_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A type representing a mapping that associates each node with a heuristic estimation of the
|
/* A type representing a mapping that associates each node with a heuristic estimation of the
|
||||||
|
@ -177,12 +211,12 @@ using NeededBuffers = Map<DNode, int>;
|
||||||
* implementation because it rarely affects the output and is done by very few nodes.
|
* implementation because it rarely affects the output and is done by very few nodes.
|
||||||
* - The compiler may decide to compiler the schedule differently depending on runtime information
|
* - The compiler may decide to compiler the schedule differently depending on runtime information
|
||||||
* which we can merely speculate at scheduling-time as described above. */
|
* which we can merely speculate at scheduling-time as described above. */
|
||||||
static NeededBuffers compute_number_of_needed_buffers(DNode output_node)
|
static NeededBuffers compute_number_of_needed_buffers(Stack<DNode> &output_nodes)
|
||||||
{
|
{
|
||||||
NeededBuffers needed_buffers;
|
NeededBuffers needed_buffers;
|
||||||
|
|
||||||
/* A stack of nodes used to traverse the node tree starting from the output node. */
|
/* A stack of nodes used to traverse the node tree starting from the output nodes. */
|
||||||
Stack<DNode> node_stack = {output_node};
|
Stack<DNode> node_stack = output_nodes;
|
||||||
|
|
||||||
/* Traverse the node tree in a post order depth first manner and compute the number of needed
|
/* Traverse the node tree in a post order depth first manner and compute the number of needed
|
||||||
* buffers for each node. Post order traversal guarantee that all the node dependencies of each
|
* buffers for each node. Post order traversal guarantee that all the node dependencies of each
|
||||||
|
@ -301,23 +335,23 @@ static NeededBuffers compute_number_of_needed_buffers(DNode output_node)
|
||||||
* doesn't always guarantee an optimal evaluation order, as the optimal evaluation order is very
|
* doesn't always guarantee an optimal evaluation order, as the optimal evaluation order is very
|
||||||
* difficult to compute, however, this method works well in most cases. Moreover it assumes that
|
* difficult to compute, however, this method works well in most cases. Moreover it assumes that
|
||||||
* all buffers will have roughly the same size, which may not always be the case. */
|
* all buffers will have roughly the same size, which may not always be the case. */
|
||||||
Schedule compute_schedule(const DerivedNodeTree &tree)
|
Schedule compute_schedule(const Context &context, const DerivedNodeTree &tree)
|
||||||
{
|
{
|
||||||
Schedule schedule;
|
Schedule schedule;
|
||||||
|
|
||||||
/* Compute the output node whose result should be computed. */
|
/* A stack of nodes used to traverse the node tree starting from the output nodes. */
|
||||||
const DNode output_node = compute_output_node(tree);
|
Stack<DNode> node_stack;
|
||||||
|
|
||||||
/* No output node, the node tree has no effect, return an empty schedule. */
|
/* Add the output nodes whose result should be computed to the stack. */
|
||||||
if (!output_node) {
|
add_output_nodes(context, tree, node_stack);
|
||||||
|
|
||||||
|
/* No output nodes, the node tree has no effect, return an empty schedule. */
|
||||||
|
if (node_stack.is_empty()) {
|
||||||
return schedule;
|
return schedule;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute the number of buffers needed by each node connected to the output. */
|
/* Compute the number of buffers needed by each node connected to the outputs. */
|
||||||
const NeededBuffers needed_buffers = compute_number_of_needed_buffers(output_node);
|
const NeededBuffers needed_buffers = compute_number_of_needed_buffers(node_stack);
|
||||||
|
|
||||||
/* A stack of nodes used to traverse the node tree starting from the output node. */
|
|
||||||
Stack<DNode> node_stack = {output_node};
|
|
||||||
|
|
||||||
/* Traverse the node tree in a post order depth first manner, scheduling the nodes in an order
|
/* Traverse the node tree in a post order depth first manner, scheduling the nodes in an order
|
||||||
* informed by the number of buffers needed by each node. Post order traversal guarantee that all
|
* informed by the number of buffers needed by each node. Post order traversal guarantee that all
|
||||||
|
|
|
@ -10,7 +10,19 @@ GPU_SHADER_CREATE_INFO(compositor_read_pass_shared)
|
||||||
.sampler(0, ImageType::FLOAT_2D, "input_tx")
|
.sampler(0, ImageType::FLOAT_2D, "input_tx")
|
||||||
.compute_source("compositor_read_pass.glsl");
|
.compute_source("compositor_read_pass.glsl");
|
||||||
|
|
||||||
GPU_SHADER_CREATE_INFO(compositor_read_pass)
|
GPU_SHADER_CREATE_INFO(compositor_read_pass_float)
|
||||||
|
.additional_info("compositor_read_pass_shared")
|
||||||
|
.image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||||
|
.define("READ_EXPRESSION(pass_color)", "vec4(pass_color.r, vec3(0.0))")
|
||||||
|
.do_static_compilation(true);
|
||||||
|
|
||||||
|
GPU_SHADER_CREATE_INFO(compositor_read_pass_vector)
|
||||||
|
.additional_info("compositor_read_pass_shared")
|
||||||
|
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||||
|
.define("READ_EXPRESSION(pass_color)", "pass_color")
|
||||||
|
.do_static_compilation(true);
|
||||||
|
|
||||||
|
GPU_SHADER_CREATE_INFO(compositor_read_pass_color)
|
||||||
.additional_info("compositor_read_pass_shared")
|
.additional_info("compositor_read_pass_shared")
|
||||||
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||||
.define("READ_EXPRESSION(pass_color)", "pass_color")
|
.define("READ_EXPRESSION(pass_color)", "pass_color")
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
#include "BKE_action.h"
|
#include "BKE_action.h"
|
||||||
|
#include "BKE_collection.h"
|
||||||
|
|
||||||
#include "RNA_prototypes.h"
|
#include "RNA_prototypes.h"
|
||||||
|
|
||||||
|
@ -183,6 +184,14 @@ void deg_graph_build_finalize(Main *bmain, Depsgraph *graph)
|
||||||
flag |= ID_RECALC_NTREE_OUTPUT;
|
flag |= ID_RECALC_NTREE_OUTPUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
/* Collection content might have changed (children collection might have been added or
|
||||||
|
* removed from the graph based on their inclusion and visibility flags). */
|
||||||
|
const ID_Type id_type = GS(id_node->id_cow->name);
|
||||||
|
if (id_type == ID_GR) {
|
||||||
|
BKE_collection_object_cache_free(reinterpret_cast<Collection *>(id_node->id_cow));
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Restore recalc flags from original ID, which could possibly contain recalc flags set by
|
/* Restore recalc flags from original ID, which could possibly contain recalc flags set by
|
||||||
* an operator and then were carried on by the undo system. */
|
* an operator and then were carried on by the undo system. */
|
||||||
flag |= id_orig->recalc;
|
flag |= id_orig->recalc;
|
||||||
|
|
|
@ -68,6 +68,14 @@ class Context : public realtime_compositor::Context {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The viewport compositor doesn't really support the composite output, it only displays the
|
||||||
|
* viewer output in the viewport. Settings this to false will make the compositor use the
|
||||||
|
* composite output as fallback viewer if no other viewer exists. */
|
||||||
|
bool use_composite_output() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool use_texture_color_management() const override
|
bool use_texture_color_management() const override
|
||||||
{
|
{
|
||||||
return BKE_scene_check_color_management_enabled(DRW_context_state_get()->scene);
|
return BKE_scene_check_color_management_enabled(DRW_context_state_get()->scene);
|
||||||
|
@ -145,6 +153,11 @@ class Context : public realtime_compositor::Context {
|
||||||
return DRW_viewport_texture_list_get()->color;
|
return DRW_viewport_texture_list_get()->color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GPUTexture *get_viewer_output_texture() override
|
||||||
|
{
|
||||||
|
return DRW_viewport_texture_list_get()->color;
|
||||||
|
}
|
||||||
|
|
||||||
GPUTexture *get_input_texture(int view_layer, const char *pass_name) override
|
GPUTexture *get_input_texture(int view_layer, const char *pass_name) override
|
||||||
{
|
{
|
||||||
if (view_layer == 0 && STREQ(pass_name, RE_PASSNAME_COMBINED)) {
|
if (view_layer == 0 && STREQ(pass_name, RE_PASSNAME_COMBINED)) {
|
||||||
|
|
|
@ -184,7 +184,7 @@ static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
|
||||||
/* Happens on first uniform or if chunk is full. */
|
/* Happens on first uniform or if chunk is full. */
|
||||||
if (!unichunk || unichunk->uniform_used == unichunk->uniform_len) {
|
if (!unichunk || unichunk->uniform_used == unichunk->uniform_len) {
|
||||||
unichunk = static_cast<DRWUniformChunk *>(BLI_memblock_alloc(DST.vmempool->uniforms));
|
unichunk = static_cast<DRWUniformChunk *>(BLI_memblock_alloc(DST.vmempool->uniforms));
|
||||||
unichunk->uniform_len = ARRAY_SIZE(shgroup->uniforms->uniforms);
|
unichunk->uniform_len = BOUNDED_ARRAY_TYPE_SIZE<decltype(shgroup->uniforms->uniforms)>();
|
||||||
unichunk->uniform_used = 0;
|
unichunk->uniform_used = 0;
|
||||||
BLI_LINKS_PREPEND(shgroup->uniforms, unichunk);
|
BLI_LINKS_PREPEND(shgroup->uniforms, unichunk);
|
||||||
}
|
}
|
||||||
|
|
|
@ -566,13 +566,14 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
|
||||||
((filter_mode & ANIMFILTER_SEL) && test_func) || \
|
((filter_mode & ANIMFILTER_SEL) && test_func) || \
|
||||||
((filter_mode & ANIMFILTER_UNSEL) && test_func == 0))
|
((filter_mode & ANIMFILTER_UNSEL) && test_func == 0))
|
||||||
|
|
||||||
/* quick macro to test if an anim-channel (F-Curve) is selected ok for editing purposes
|
/**
|
||||||
* - _SELEDIT means that only selected curves will have visible+editable keyframes
|
* Quick macro to test if an anim-channel (F-Curve) is selected ok for editing purposes
|
||||||
|
* - `*_SELEDIT` means that only selected curves will have visible+editable key-frames.
|
||||||
*
|
*
|
||||||
* checks here work as follows:
|
* checks here work as follows:
|
||||||
* 1) seledit off - don't need to consider the implications of this option
|
* 1) SELEDIT off - don't need to consider the implications of this option.
|
||||||
* 2) foredit off - we're not considering editing, so channel is ok still
|
* 2) FOREDIT off - we're not considering editing, so channel is ok still.
|
||||||
* 3) test_func (i.e. selection test) - only if selected, this test will pass
|
* 3) test_func (i.e. selection test) - only if selected, this test will pass.
|
||||||
*/
|
*/
|
||||||
#define ANIMCHANNEL_SELEDITOK(test_func) \
|
#define ANIMCHANNEL_SELEDITOK(test_func) \
|
||||||
(!(filter_mode & ANIMFILTER_SELEDIT) || !(filter_mode & ANIMFILTER_FOREDIT) || (test_func))
|
(!(filter_mode & ANIMFILTER_SELEDIT) || !(filter_mode & ANIMFILTER_FOREDIT) || (test_func))
|
||||||
|
@ -1194,7 +1195,7 @@ static bool skip_fcurve_with_name(
|
||||||
*/
|
*/
|
||||||
static bool fcurve_has_errors(const FCurve *fcu)
|
static bool fcurve_has_errors(const FCurve *fcu)
|
||||||
{
|
{
|
||||||
/* F-Curve disabled - path eval error */
|
/* F-Curve disabled (path evaluation error). */
|
||||||
if (fcu->flag & FCURVE_DISABLED) {
|
if (fcu->flag & FCURVE_DISABLED) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,6 +265,10 @@ static bool need_extra_redraw_after_scrubbing_ends(bContext *C)
|
||||||
* scrubbing, the actual result should be shown again. */
|
* scrubbing, the actual result should be shown again. */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Scene *scene = CTX_data_scene(C);
|
||||||
|
if (scene->eevee.flag & SCE_EEVEE_TAA_REPROJECTION) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
wmWindowManager *wm = CTX_wm_manager(C);
|
wmWindowManager *wm = CTX_wm_manager(C);
|
||||||
Object *object = CTX_data_active_object(C);
|
Object *object = CTX_data_active_object(C);
|
||||||
if (object && object->type == OB_GPENCIL_LEGACY) {
|
if (object && object->type == OB_GPENCIL_LEGACY) {
|
||||||
|
|
|
@ -38,9 +38,9 @@ set(SRC
|
||||||
|
|
||||||
ED_asset_catalog.h
|
ED_asset_catalog.h
|
||||||
ED_asset_catalog.hh
|
ED_asset_catalog.hh
|
||||||
ED_asset_filter.h
|
ED_asset_filter.hh
|
||||||
ED_asset_handle.h
|
ED_asset_handle.h
|
||||||
ED_asset_import.h
|
ED_asset_import.hh
|
||||||
ED_asset_indexer.h
|
ED_asset_indexer.h
|
||||||
ED_asset_library.h
|
ED_asset_library.h
|
||||||
ED_asset_list.h
|
ED_asset_list.h
|
||||||
|
|
|
@ -10,12 +10,11 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct AssetFilterSettings;
|
struct AssetFilterSettings;
|
||||||
struct AssetHandle;
|
|
||||||
|
namespace blender::asset_system {
|
||||||
|
class AssetRepresentation;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare \a asset against the settings of \a filter.
|
* Compare \a asset against the settings of \a filter.
|
||||||
|
@ -29,9 +28,5 @@ struct AssetHandle;
|
||||||
* \returns True if the asset should be visible with these filter settings (parameters match).
|
* \returns True if the asset should be visible with these filter settings (parameters match).
|
||||||
* Otherwise returns false (mismatch).
|
* Otherwise returns false (mismatch).
|
||||||
*/
|
*/
|
||||||
bool ED_asset_filter_matches_asset(const struct AssetFilterSettings *filter,
|
bool ED_asset_filter_matches_asset(const AssetFilterSettings *filter,
|
||||||
const struct AssetHandle *asset);
|
const blender::asset_system::AssetRepresentation &asset);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -34,19 +34,7 @@ void ED_asset_handle_get_full_library_path(
|
||||||
/* `1024` for #FILE_MAX,
|
/* `1024` for #FILE_MAX,
|
||||||
* rely on warnings to let us know if this gets out of sync. */
|
* rely on warnings to let us know if this gets out of sync. */
|
||||||
char r_full_lib_path[1024]);
|
char r_full_lib_path[1024]);
|
||||||
bool ED_asset_handle_get_use_relative_path(const struct AssetHandle *asset);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
|
|
||||||
# include <optional>
|
|
||||||
|
|
||||||
/** The asset library may have an import method (e.g. append vs. link) defined to use. If so, this
|
|
||||||
* returns it. Otherwise a reasonable method should be used, usually "Append (Reuse Data)". */
|
|
||||||
std::optional<eAssetImportMethod> ED_asset_handle_get_import_method(
|
|
||||||
const struct AssetHandle *asset);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -10,16 +10,11 @@
|
||||||
|
|
||||||
#include "DNA_ID_enums.h"
|
#include "DNA_ID_enums.h"
|
||||||
|
|
||||||
struct AssetRepresentation;
|
|
||||||
struct Main;
|
struct Main;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
namespace blender::asset_system {
|
||||||
extern "C" {
|
class AssetRepresentation;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
struct ID *ED_asset_get_local_id_from_asset_or_append_and_reuse(
|
struct ID *ED_asset_get_local_id_from_asset_or_append_and_reuse(
|
||||||
struct Main *bmain, const struct AssetRepresentation *asset_c_ptr, ID_Type idtype);
|
Main *bmain, const blender::asset_system::AssetRepresentation &asset, ID_Type idtype);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -10,6 +10,12 @@
|
||||||
|
|
||||||
#include "DNA_asset_types.h"
|
#include "DNA_asset_types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
namespace blender::asset_system {
|
||||||
|
class AssetRepresentation;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -52,16 +58,19 @@ void ED_assetlist_storage_id_remap(struct ID *id_old, struct ID *id_new);
|
||||||
*/
|
*/
|
||||||
void ED_assetlist_storage_exit(void);
|
void ED_assetlist_storage_exit(void);
|
||||||
|
|
||||||
AssetHandle ED_assetlist_asset_get_by_index(const AssetLibraryReference *library_reference,
|
AssetHandle ED_assetlist_asset_handle_get_by_index(const AssetLibraryReference *library_reference,
|
||||||
int asset_index);
|
int asset_index);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
blender::asset_system::AssetRepresentation *ED_assetlist_asset_get_by_index(
|
||||||
|
const AssetLibraryReference &library_reference, int asset_index);
|
||||||
|
#endif
|
||||||
|
|
||||||
struct ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle);
|
struct ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return True if the region needs a UI redraw.
|
* \return True if the region needs a UI redraw.
|
||||||
*/
|
*/
|
||||||
bool ED_assetlist_listen(const struct AssetLibraryReference *library_reference,
|
bool ED_assetlist_listen(const struct wmNotifier *notifier);
|
||||||
const struct wmNotifier *notifier);
|
|
||||||
/**
|
/**
|
||||||
* \return The number of assets stored in the asset list for \a library_reference, or -1 if there
|
* \return The number of assets stored in the asset list for \a library_reference, or -1 if there
|
||||||
* is no list fetched for it.
|
* is no list fetched for it.
|
||||||
|
|
|
@ -17,7 +17,8 @@ struct AssetLibraryReference;
|
||||||
|
|
||||||
namespace blender::asset_system {
|
namespace blender::asset_system {
|
||||||
class AssetLibrary;
|
class AssetLibrary;
|
||||||
}
|
class AssetRepresentation;
|
||||||
|
} // namespace blender::asset_system
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the asset library being read into an asset-list and identified using \a library_reference.
|
* Get the asset library being read into an asset-list and identified using \a library_reference.
|
||||||
|
@ -31,9 +32,13 @@ blender::asset_system::AssetLibrary *ED_assetlist_library_get_once_available(
|
||||||
const AssetLibraryReference &library_reference);
|
const AssetLibraryReference &library_reference);
|
||||||
|
|
||||||
/* Can return false to stop iterating. */
|
/* Can return false to stop iterating. */
|
||||||
using AssetListIterFn = blender::FunctionRef<bool(AssetHandle)>;
|
using AssetListHandleIterFn = blender::FunctionRef<bool(AssetHandle)>;
|
||||||
|
using AssetListIterFn = blender::FunctionRef<bool(blender::asset_system::AssetRepresentation &)>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \warning Never keep the asset handle passed to \a fn outside of \a fn's scope. While iterating,
|
* \warning Never keep the asset handle passed to \a fn outside of \a fn's scope. While iterating,
|
||||||
* the file data wrapped by the asset handle can be freed, since the file cache has a maximum size.
|
* the file data wrapped by the asset handle can be freed, since the file cache has a maximum size.
|
||||||
*/
|
*/
|
||||||
|
void ED_assetlist_iterate(const AssetLibraryReference &library_reference,
|
||||||
|
AssetListHandleIterFn fn);
|
||||||
void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn);
|
void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn);
|
||||||
|
|
|
@ -6,29 +6,33 @@
|
||||||
* \ingroup edasset
|
* \ingroup edasset
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "AS_asset_representation.hh"
|
||||||
|
|
||||||
#include "BKE_idtype.h"
|
#include "BKE_idtype.h"
|
||||||
|
|
||||||
#include "BLI_listbase.h"
|
#include "BLI_listbase.h"
|
||||||
|
|
||||||
#include "DNA_asset_types.h"
|
#include "DNA_asset_types.h"
|
||||||
|
|
||||||
#include "ED_asset_filter.h"
|
#include "ED_asset_filter.hh"
|
||||||
#include "ED_asset_handle.h"
|
|
||||||
|
|
||||||
bool ED_asset_filter_matches_asset(const AssetFilterSettings *filter, const AssetHandle *asset)
|
using namespace blender;
|
||||||
|
|
||||||
|
bool ED_asset_filter_matches_asset(const AssetFilterSettings *filter,
|
||||||
|
const asset_system::AssetRepresentation &asset)
|
||||||
{
|
{
|
||||||
ID_Type asset_type = ED_asset_handle_get_id_type(asset);
|
ID_Type asset_type = asset.get_id_type();
|
||||||
uint64_t asset_id_filter = BKE_idtype_idcode_to_idfilter(asset_type);
|
uint64_t asset_id_filter = BKE_idtype_idcode_to_idfilter(asset_type);
|
||||||
|
|
||||||
if ((filter->id_types & asset_id_filter) == 0) {
|
if (filter->id_types && (filter->id_types & asset_id_filter) == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* Not very efficient (O(n^2)), could be improved quite a bit. */
|
/* Not very efficient (O(n^2)), could be improved quite a bit. */
|
||||||
LISTBASE_FOREACH (const AssetTag *, filter_tag, &filter->tags) {
|
LISTBASE_FOREACH (const AssetTag *, filter_tag, &filter->tags) {
|
||||||
AssetMetaData *asset_data = ED_asset_handle_get_metadata(asset);
|
AssetMetaData &asset_data = asset.get_metadata();
|
||||||
|
|
||||||
AssetTag *matched_tag = (AssetTag *)BLI_findstring(
|
AssetTag *matched_tag = (AssetTag *)BLI_findstring(
|
||||||
&asset_data->tags, filter_tag->name, offsetof(AssetTag, name));
|
&asset_data.tags, filter_tag->name, offsetof(AssetTag, name));
|
||||||
if (matched_tag == nullptr) {
|
if (matched_tag == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,14 +36,14 @@ AssetMetaData *ED_asset_handle_get_metadata(const AssetHandle *asset_handle)
|
||||||
return AS_asset_representation_metadata_get(asset_handle->file_data->asset);
|
return AS_asset_representation_metadata_get(asset_handle->file_data->asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
ID *ED_asset_handle_get_local_id(const AssetHandle *asset)
|
ID *ED_asset_handle_get_local_id(const AssetHandle *asset_handle)
|
||||||
{
|
{
|
||||||
return asset->file_data->id;
|
return AS_asset_representation_local_id_get(asset_handle->file_data->asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
ID_Type ED_asset_handle_get_id_type(const AssetHandle *asset)
|
ID_Type ED_asset_handle_get_id_type(const AssetHandle *asset_handle)
|
||||||
{
|
{
|
||||||
return static_cast<ID_Type>(asset->file_data->blentype);
|
return AS_asset_representation_id_type_get(asset_handle->file_data->asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ED_asset_handle_get_preview_icon_id(const AssetHandle *asset)
|
int ED_asset_handle_get_preview_icon_id(const AssetHandle *asset)
|
||||||
|
@ -51,12 +51,6 @@ int ED_asset_handle_get_preview_icon_id(const AssetHandle *asset)
|
||||||
return asset->file_data->preview_icon_id;
|
return asset->file_data->preview_icon_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<eAssetImportMethod> ED_asset_handle_get_import_method(
|
|
||||||
const AssetHandle *asset_handle)
|
|
||||||
{
|
|
||||||
return AS_asset_representation_import_method_get(asset_handle->file_data->asset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
|
void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
|
||||||
char r_full_lib_path[FILE_MAX])
|
char r_full_lib_path[FILE_MAX])
|
||||||
{
|
{
|
||||||
|
@ -70,8 +64,3 @@ void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
|
||||||
|
|
||||||
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX);
|
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ED_asset_handle_get_use_relative_path(const AssetHandle *asset)
|
|
||||||
{
|
|
||||||
return AS_asset_representation_use_relative_path_get(asset->file_data->asset);
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,24 +6,19 @@
|
||||||
* \ingroup edasset
|
* \ingroup edasset
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "AS_asset_representation.h"
|
|
||||||
#include "AS_asset_representation.hh"
|
#include "AS_asset_representation.hh"
|
||||||
|
|
||||||
#include "BLO_readfile.h"
|
#include "BLO_readfile.h"
|
||||||
|
|
||||||
#include "WM_api.h"
|
#include "WM_api.h"
|
||||||
|
|
||||||
#include "ED_asset_import.h"
|
#include "ED_asset_import.hh"
|
||||||
|
|
||||||
using namespace blender;
|
using namespace blender;
|
||||||
|
|
||||||
ID *ED_asset_get_local_id_from_asset_or_append_and_reuse(Main *bmain,
|
ID *ED_asset_get_local_id_from_asset_or_append_and_reuse(
|
||||||
const AssetRepresentation *asset_c_ptr,
|
Main *bmain, const asset_system::AssetRepresentation &asset, ID_Type idtype)
|
||||||
ID_Type idtype)
|
|
||||||
{
|
{
|
||||||
const asset_system::AssetRepresentation &asset =
|
|
||||||
*reinterpret_cast<const asset_system::AssetRepresentation *>(asset_c_ptr);
|
|
||||||
|
|
||||||
if (ID *local_id = asset.local_id()) {
|
if (ID *local_id = asset.local_id()) {
|
||||||
return local_id;
|
return local_id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include "../space_file/file_indexer.h"
|
#include "../space_file/file_indexer.h"
|
||||||
#include "../space_file/filelist.h"
|
#include "../space_file/filelist.h"
|
||||||
|
|
||||||
#include "ED_asset_handle.h"
|
|
||||||
#include "ED_asset_indexer.h"
|
#include "ED_asset_indexer.h"
|
||||||
#include "ED_asset_list.h"
|
#include "ED_asset_list.h"
|
||||||
#include "ED_asset_list.hh"
|
#include "ED_asset_list.hh"
|
||||||
|
@ -109,6 +108,8 @@ class AssetList : NonCopyable {
|
||||||
AssetList(AssetList &&other) = default;
|
AssetList(AssetList &&other) = default;
|
||||||
~AssetList() = default;
|
~AssetList() = default;
|
||||||
|
|
||||||
|
static bool listen(const wmNotifier ¬ifier);
|
||||||
|
|
||||||
void setup();
|
void setup();
|
||||||
void fetch(const bContext &C);
|
void fetch(const bContext &C);
|
||||||
void ensurePreviewsJob(const bContext *C);
|
void ensurePreviewsJob(const bContext *C);
|
||||||
|
@ -119,8 +120,8 @@ class AssetList : NonCopyable {
|
||||||
bool needsRefetch() const;
|
bool needsRefetch() const;
|
||||||
bool isLoaded() const;
|
bool isLoaded() const;
|
||||||
asset_system::AssetLibrary *asset_library() const;
|
asset_system::AssetLibrary *asset_library() const;
|
||||||
|
void iterate(AssetListHandleIterFn fn) const;
|
||||||
void iterate(AssetListIterFn fn) const;
|
void iterate(AssetListIterFn fn) const;
|
||||||
bool listen(const wmNotifier ¬ifier) const;
|
|
||||||
int size() const;
|
int size() const;
|
||||||
void tagMainDataDirty() const;
|
void tagMainDataDirty() const;
|
||||||
void remapID(ID *id_old, ID *id_new) const;
|
void remapID(ID *id_old, ID *id_new) const;
|
||||||
|
@ -195,7 +196,7 @@ asset_system::AssetLibrary *AssetList::asset_library() const
|
||||||
return reinterpret_cast<asset_system::AssetLibrary *>(filelist_asset_library(filelist_));
|
return reinterpret_cast<asset_system::AssetLibrary *>(filelist_asset_library(filelist_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetList::iterate(AssetListIterFn fn) const
|
void AssetList::iterate(AssetListHandleIterFn fn) const
|
||||||
{
|
{
|
||||||
FileList *files = filelist_;
|
FileList *files = filelist_;
|
||||||
int numfiles = filelist_files_ensure(files);
|
int numfiles = filelist_files_ensure(files);
|
||||||
|
@ -214,6 +215,16 @@ void AssetList::iterate(AssetListIterFn fn) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssetList::iterate(AssetListIterFn fn) const
|
||||||
|
{
|
||||||
|
iterate([&fn](AssetHandle handle) {
|
||||||
|
asset_system::AssetRepresentation &asset =
|
||||||
|
reinterpret_cast<blender::asset_system::AssetRepresentation &>(*handle.file_data->asset);
|
||||||
|
|
||||||
|
return fn(asset);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void AssetList::ensurePreviewsJob(const bContext *C)
|
void AssetList::ensurePreviewsJob(const bContext *C)
|
||||||
{
|
{
|
||||||
FileList *files = filelist_;
|
FileList *files = filelist_;
|
||||||
|
@ -259,7 +270,7 @@ AssetHandle AssetList::asset_get_by_index(int index) const
|
||||||
/**
|
/**
|
||||||
* \return True if the asset-list needs a UI redraw.
|
* \return True if the asset-list needs a UI redraw.
|
||||||
*/
|
*/
|
||||||
bool AssetList::listen(const wmNotifier ¬ifier) const
|
bool AssetList::listen(const wmNotifier ¬ifier)
|
||||||
{
|
{
|
||||||
switch (notifier.category) {
|
switch (notifier.category) {
|
||||||
case NC_ID: {
|
case NC_ID: {
|
||||||
|
@ -464,6 +475,14 @@ bool ED_assetlist_storage_has_list_for_library(const AssetLibraryReference *libr
|
||||||
return AssetListStorage::lookup_list(*library_reference) != nullptr;
|
return AssetListStorage::lookup_list(*library_reference) != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListHandleIterFn fn)
|
||||||
|
{
|
||||||
|
AssetList *list = AssetListStorage::lookup_list(library_reference);
|
||||||
|
if (list) {
|
||||||
|
list->iterate(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn)
|
void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn)
|
||||||
{
|
{
|
||||||
AssetList *list = AssetListStorage::lookup_list(library_reference);
|
AssetList *list = AssetListStorage::lookup_list(library_reference);
|
||||||
|
@ -482,13 +501,21 @@ asset_system::AssetLibrary *ED_assetlist_library_get_once_available(
|
||||||
return list->asset_library();
|
return list->asset_library();
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetHandle ED_assetlist_asset_get_by_index(const AssetLibraryReference *library_reference,
|
AssetHandle ED_assetlist_asset_handle_get_by_index(const AssetLibraryReference *library_reference,
|
||||||
int asset_index)
|
int asset_index)
|
||||||
{
|
{
|
||||||
const AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
const AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||||
return list->asset_get_by_index(asset_index);
|
return list->asset_get_by_index(asset_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asset_system::AssetRepresentation *ED_assetlist_asset_get_by_index(
|
||||||
|
const AssetLibraryReference &library_reference, int asset_index)
|
||||||
|
{
|
||||||
|
AssetHandle asset_handle = ED_assetlist_asset_handle_get_by_index(&library_reference,
|
||||||
|
asset_index);
|
||||||
|
return reinterpret_cast<asset_system::AssetRepresentation *>(asset_handle.file_data->asset);
|
||||||
|
}
|
||||||
|
|
||||||
ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
|
ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
|
||||||
{
|
{
|
||||||
ImBuf *imbuf = filelist_file_getimage(asset_handle->file_data);
|
ImBuf *imbuf = filelist_file_getimage(asset_handle->file_data);
|
||||||
|
@ -499,14 +526,9 @@ ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
|
||||||
return filelist_geticon_image_ex(asset_handle->file_data);
|
return filelist_geticon_image_ex(asset_handle->file_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ED_assetlist_listen(const AssetLibraryReference *library_reference,
|
bool ED_assetlist_listen(const wmNotifier *notifier)
|
||||||
const wmNotifier *notifier)
|
|
||||||
{
|
{
|
||||||
AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
return AssetList::listen(*notifier);
|
||||||
if (list) {
|
|
||||||
return list->listen(*notifier);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ED_assetlist_size(const AssetLibraryReference *library_reference)
|
int ED_assetlist_size(const AssetLibraryReference *library_reference)
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
#include "BLI_vector_set.hh"
|
#include "BLI_vector_set.hh"
|
||||||
|
|
||||||
|
#include "BLT_translation.h"
|
||||||
|
|
||||||
#include "ED_curves.h"
|
#include "ED_curves.h"
|
||||||
#include "ED_object.h"
|
#include "ED_object.h"
|
||||||
#include "ED_screen.h"
|
#include "ED_screen.h"
|
||||||
|
@ -938,15 +940,15 @@ static void CURVES_OT_select_random(wmOperatorType *ot)
|
||||||
1.0f);
|
1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int select_end_exec(bContext *C, wmOperator *op)
|
static int select_ends_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
VectorSet<Curves *> unique_curves = curves::get_unique_editable_curves(*C);
|
VectorSet<Curves *> unique_curves = curves::get_unique_editable_curves(*C);
|
||||||
const bool end_points = RNA_boolean_get(op->ptr, "end_points");
|
const int amount_start = RNA_int_get(op->ptr, "amount_start");
|
||||||
const int amount = RNA_int_get(op->ptr, "amount");
|
const int amount_end = RNA_int_get(op->ptr, "amount_end");
|
||||||
|
|
||||||
for (Curves *curves_id : unique_curves) {
|
for (Curves *curves_id : unique_curves) {
|
||||||
CurvesGeometry &curves = curves_id->geometry.wrap();
|
CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||||
select_ends(curves, amount, end_points);
|
select_ends(curves, amount_start, amount_end);
|
||||||
|
|
||||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||||
* attribute for now. */
|
* attribute for now. */
|
||||||
|
@ -957,24 +959,48 @@ static int select_end_exec(bContext *C, wmOperator *op)
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CURVES_OT_select_end(wmOperatorType *ot)
|
static void select_ends_ui(bContext * /*C*/, wmOperator *op)
|
||||||
{
|
{
|
||||||
ot->name = "Select End";
|
uiLayout *layout = op->layout;
|
||||||
|
|
||||||
|
uiLayoutSetPropSep(layout, true);
|
||||||
|
|
||||||
|
uiLayout *col = uiLayoutColumn(layout, true);
|
||||||
|
uiLayoutSetPropDecorate(col, false);
|
||||||
|
uiItemR(col, op->ptr, "amount_start", 0, IFACE_("Amount Start"), ICON_NONE);
|
||||||
|
uiItemR(col, op->ptr, "amount_end", 0, IFACE_("End"), ICON_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CURVES_OT_select_ends(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
ot->name = "Select Ends";
|
||||||
ot->idname = __func__;
|
ot->idname = __func__;
|
||||||
ot->description = "Select end points of curves";
|
ot->description = "Select end points of curves";
|
||||||
|
|
||||||
ot->exec = select_end_exec;
|
ot->exec = select_ends_exec;
|
||||||
|
ot->ui = select_ends_ui;
|
||||||
ot->poll = editable_curves_point_domain_poll;
|
ot->poll = editable_curves_point_domain_poll;
|
||||||
|
|
||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
|
|
||||||
RNA_def_boolean(ot->srna,
|
RNA_def_int(ot->srna,
|
||||||
"end_points",
|
"amount_start",
|
||||||
true,
|
0,
|
||||||
"End Points",
|
0,
|
||||||
"Select points at the end of the curve as opposed to the beginning");
|
INT32_MAX,
|
||||||
RNA_def_int(
|
"Amount Front",
|
||||||
ot->srna, "amount", 1, 0, INT32_MAX, "Amount", "Number of points to select", 0, INT32_MAX);
|
"Number of points to select from the front",
|
||||||
|
0,
|
||||||
|
INT32_MAX);
|
||||||
|
RNA_def_int(ot->srna,
|
||||||
|
"amount_end",
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
INT32_MAX,
|
||||||
|
"Amount Back",
|
||||||
|
"Number of points to select from the back",
|
||||||
|
0,
|
||||||
|
INT32_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int select_linked_exec(bContext *C, wmOperator * /*op*/)
|
static int select_linked_exec(bContext *C, wmOperator * /*op*/)
|
||||||
|
@ -1181,7 +1207,7 @@ void ED_operatortypes_curves()
|
||||||
WM_operatortype_append(CURVES_OT_set_selection_domain);
|
WM_operatortype_append(CURVES_OT_set_selection_domain);
|
||||||
WM_operatortype_append(CURVES_OT_select_all);
|
WM_operatortype_append(CURVES_OT_select_all);
|
||||||
WM_operatortype_append(CURVES_OT_select_random);
|
WM_operatortype_append(CURVES_OT_select_random);
|
||||||
WM_operatortype_append(CURVES_OT_select_end);
|
WM_operatortype_append(CURVES_OT_select_ends);
|
||||||
WM_operatortype_append(CURVES_OT_select_linked);
|
WM_operatortype_append(CURVES_OT_select_linked);
|
||||||
WM_operatortype_append(CURVES_OT_select_more);
|
WM_operatortype_append(CURVES_OT_select_more);
|
||||||
WM_operatortype_append(CURVES_OT_select_less);
|
WM_operatortype_append(CURVES_OT_select_less);
|
||||||
|
|
|
@ -222,7 +222,7 @@ void select_all(bke::CurvesGeometry &curves, const eAttrDomain selection_domain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void select_ends(bke::CurvesGeometry &curves, int amount, bool end_points)
|
void select_ends(bke::CurvesGeometry &curves, int amount_start, int amount_end)
|
||||||
{
|
{
|
||||||
const bool was_anything_selected = has_anything_selected(curves);
|
const bool was_anything_selected = has_anything_selected(curves);
|
||||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||||
|
@ -240,12 +240,9 @@ void select_ends(bke::CurvesGeometry &curves, int amount, bool end_points)
|
||||||
MutableSpan<T> selection_typed = selection.span.typed<T>();
|
MutableSpan<T> selection_typed = selection.span.typed<T>();
|
||||||
threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange range) {
|
threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange range) {
|
||||||
for (const int curve_i : range) {
|
for (const int curve_i : range) {
|
||||||
if (end_points) {
|
selection_typed
|
||||||
selection_typed.slice(points_by_curve[curve_i].drop_back(amount)).fill(T(0));
|
.slice(points_by_curve[curve_i].drop_front(amount_start).drop_back(amount_end))
|
||||||
}
|
.fill(T(0));
|
||||||
else {
|
|
||||||
selection_typed.slice(points_by_curve[curve_i].drop_front(amount)).fill(T(0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,28 +99,3 @@ void ED_gizmo_draw_preset_circle(const struct wmGizmo *gz,
|
||||||
single_axis_convert(OB_POSZ, mat, axis, mat_rotate);
|
single_axis_convert(OB_POSZ, mat, axis, mat_rotate);
|
||||||
ed_gizmo_draw_preset_geometry(gz, mat_rotate, select_id, &wm_gizmo_geom_data_dial);
|
ed_gizmo_draw_preset_geometry(gz, mat_rotate, select_id, &wm_gizmo_geom_data_dial);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ED_gizmo_draw_preset_facemap(
|
|
||||||
const bContext *C, const struct wmGizmo *gz, Object *ob, const int facemap, int select_id)
|
|
||||||
{
|
|
||||||
/* Dependency graph is supposed to be evaluated prior to draw. */
|
|
||||||
Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
|
|
||||||
const bool is_select = (select_id != -1);
|
|
||||||
const bool is_highlight = is_select && (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
|
|
||||||
|
|
||||||
float color[4];
|
|
||||||
gizmo_color_get(gz, is_highlight, color);
|
|
||||||
|
|
||||||
if (is_select) {
|
|
||||||
GPU_select_load_id(select_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
GPU_matrix_push();
|
|
||||||
GPU_matrix_mul(ob->object_to_world);
|
|
||||||
ED_draw_object_facemap(depsgraph, ob, color, facemap);
|
|
||||||
GPU_matrix_pop();
|
|
||||||
|
|
||||||
if (is_select) {
|
|
||||||
GPU_select_load_id(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -25,9 +25,7 @@ void ED_operatortypes_asset(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../asset/ED_asset_catalog.h"
|
#include "../asset/ED_asset_catalog.h"
|
||||||
#include "../asset/ED_asset_filter.h"
|
|
||||||
#include "../asset/ED_asset_handle.h"
|
#include "../asset/ED_asset_handle.h"
|
||||||
#include "../asset/ED_asset_import.h"
|
|
||||||
#include "../asset/ED_asset_library.h"
|
#include "../asset/ED_asset_library.h"
|
||||||
#include "../asset/ED_asset_list.h"
|
#include "../asset/ED_asset_list.h"
|
||||||
#include "../asset/ED_asset_mark_clear.h"
|
#include "../asset/ED_asset_mark_clear.h"
|
||||||
|
@ -37,5 +35,7 @@ void ED_operatortypes_asset(void);
|
||||||
/* C++ only headers. */
|
/* C++ only headers. */
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
# include "../asset/ED_asset_catalog.hh"
|
# include "../asset/ED_asset_catalog.hh"
|
||||||
|
# include "../asset/ED_asset_filter.hh"
|
||||||
|
# include "../asset/ED_asset_import.hh"
|
||||||
# include "../asset/ED_asset_list.hh"
|
# include "../asset/ED_asset_list.hh"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -150,10 +150,10 @@ void select_all(bke::CurvesGeometry &curves, eAttrDomain selection_domain, int a
|
||||||
/**
|
/**
|
||||||
* Select the ends (front or back) of all the curves.
|
* Select the ends (front or back) of all the curves.
|
||||||
*
|
*
|
||||||
* \param amount: The amount of points to select from the front or back.
|
* \param amount_start: The amount of points to select from the front.
|
||||||
* \param end_points: If true, select the last point(s), if false, select the first point(s).
|
* \param amount_end: The amount of points to select from the back.
|
||||||
*/
|
*/
|
||||||
void select_ends(bke::CurvesGeometry &curves, int amount, bool end_points);
|
void select_ends(bke::CurvesGeometry &curves, int amount_start, int amount_end);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select the points of all curves that have at least one point selected.
|
* Select the points of all curves that have at least one point selected.
|
||||||
|
|
|
@ -52,11 +52,6 @@ void ED_gizmo_draw_preset_circle(const struct wmGizmo *gz,
|
||||||
float mat[4][4],
|
float mat[4][4],
|
||||||
int axis,
|
int axis,
|
||||||
int select_id);
|
int select_id);
|
||||||
void ED_gizmo_draw_preset_facemap(const struct bContext *C,
|
|
||||||
const struct wmGizmo *gz,
|
|
||||||
struct Object *ob,
|
|
||||||
int facemap,
|
|
||||||
int select_id);
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* 3D Arrow Gizmo */
|
/* 3D Arrow Gizmo */
|
||||||
|
|
|
@ -34,7 +34,6 @@ struct ViewLayer;
|
||||||
struct XFormObjectData;
|
struct XFormObjectData;
|
||||||
struct bConstraint;
|
struct bConstraint;
|
||||||
struct bContext;
|
struct bContext;
|
||||||
struct bFaceMap;
|
|
||||||
struct bPoseChannel;
|
struct bPoseChannel;
|
||||||
struct uiLayout;
|
struct uiLayout;
|
||||||
struct wmKeyConfig;
|
struct wmKeyConfig;
|
||||||
|
@ -729,17 +728,6 @@ bool ED_object_jump_to_bone(struct bContext *C,
|
||||||
const char *bone_name,
|
const char *bone_name,
|
||||||
bool reveal_hidden);
|
bool reveal_hidden);
|
||||||
|
|
||||||
/* object_facemap_ops.c */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called while not in edit-mode.
|
|
||||||
*/
|
|
||||||
void ED_object_facemap_face_add(struct Object *ob, struct bFaceMap *fmap, int facenum);
|
|
||||||
/**
|
|
||||||
* Called while not in edit-mode.
|
|
||||||
*/
|
|
||||||
void ED_object_facemap_face_remove(struct Object *ob, struct bFaceMap *fmap, int facenum);
|
|
||||||
|
|
||||||
/* object_data_transform.cc */
|
/* object_data_transform.cc */
|
||||||
|
|
||||||
struct XFormObjectData *ED_object_data_xform_create_ex(struct ID *id, bool is_edit_mode);
|
struct XFormObjectData *ED_object_data_xform_create_ex(struct ID *id, bool is_edit_mode);
|
||||||
|
|
|
@ -1056,11 +1056,6 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d);
|
||||||
struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d);
|
struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d);
|
||||||
void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat);
|
void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat);
|
||||||
|
|
||||||
void ED_draw_object_facemap(struct Depsgraph *depsgraph,
|
|
||||||
struct Object *ob,
|
|
||||||
const float col[4],
|
|
||||||
int facemap);
|
|
||||||
|
|
||||||
struct RenderEngineType *ED_view3d_engine_type(const struct Scene *scene, int drawtype);
|
struct RenderEngineType *ED_view3d_engine_type(const struct Scene *scene, int drawtype);
|
||||||
|
|
||||||
bool ED_view3d_context_activate(struct bContext *C);
|
bool ED_view3d_context_activate(struct bContext *C);
|
||||||
|
|
|
@ -22,7 +22,7 @@ extern "C" {
|
||||||
|
|
||||||
struct ARegion;
|
struct ARegion;
|
||||||
struct AssetFilterSettings;
|
struct AssetFilterSettings;
|
||||||
struct AssetHandle;
|
struct AssetRepresentation;
|
||||||
struct AutoComplete;
|
struct AutoComplete;
|
||||||
struct EnumPropertyItem;
|
struct EnumPropertyItem;
|
||||||
struct FileSelectParams;
|
struct FileSelectParams;
|
||||||
|
@ -263,6 +263,13 @@ enum {
|
||||||
#define UI_NAVIGATION_REGION_WIDTH UI_COMPACT_PANEL_WIDTH
|
#define UI_NAVIGATION_REGION_WIDTH UI_COMPACT_PANEL_WIDTH
|
||||||
#define UI_NARROW_NAVIGATION_REGION_WIDTH 100
|
#define UI_NARROW_NAVIGATION_REGION_WIDTH 100
|
||||||
|
|
||||||
|
/* The width of one icon column of the Toolbar. */
|
||||||
|
#define UI_TOOLBAR_COLUMN (1.25f * ICON_DEFAULT_HEIGHT_TOOLBAR)
|
||||||
|
/* The space between the Toolbar and the area's edge. */
|
||||||
|
#define UI_TOOLBAR_MARGIN (0.5f * ICON_DEFAULT_HEIGHT_TOOLBAR)
|
||||||
|
/* Total width of Toolbar showing one icon column. */
|
||||||
|
#define UI_TOOLBAR_WIDTH UI_TOOLBAR_MARGIN + UI_TOOLBAR_COLUMN
|
||||||
|
|
||||||
#define UI_PANEL_CATEGORY_MARGIN_WIDTH (U.widget_unit * 1.0f)
|
#define UI_PANEL_CATEGORY_MARGIN_WIDTH (U.widget_unit * 1.0f)
|
||||||
|
|
||||||
/* Both these margins should be ignored if the panel doesn't show a background (check
|
/* Both these margins should be ignored if the panel doesn't show a background (check
|
||||||
|
@ -1806,8 +1813,7 @@ void UI_but_drag_attach_image(uiBut *but, struct ImBuf *imb, float scale);
|
||||||
* \param asset: May be passed from a temporary variable, drag data only stores a copy of this.
|
* \param asset: May be passed from a temporary variable, drag data only stores a copy of this.
|
||||||
*/
|
*/
|
||||||
void UI_but_drag_set_asset(uiBut *but,
|
void UI_but_drag_set_asset(uiBut *but,
|
||||||
const struct AssetHandle *asset,
|
const struct AssetRepresentation *asset,
|
||||||
const char *path,
|
|
||||||
int import_type, /* eAssetImportType */
|
int import_type, /* eAssetImportType */
|
||||||
int icon,
|
int icon,
|
||||||
struct ImBuf *imb,
|
struct ImBuf *imb,
|
||||||
|
|
|
@ -30,14 +30,13 @@ void UI_but_drag_attach_image(uiBut *but, ImBuf *imb, const float scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
void UI_but_drag_set_asset(uiBut *but,
|
void UI_but_drag_set_asset(uiBut *but,
|
||||||
const AssetHandle *asset_handle,
|
const AssetRepresentation *asset,
|
||||||
const char *path,
|
|
||||||
int import_type,
|
int import_type,
|
||||||
int icon,
|
int icon,
|
||||||
ImBuf *imb,
|
ImBuf *imb,
|
||||||
float scale)
|
float scale)
|
||||||
{
|
{
|
||||||
wmDragAsset *asset_drag = WM_drag_create_asset_data(asset_handle, path, import_type);
|
wmDragAsset *asset_drag = WM_drag_create_asset_data(asset, import_type);
|
||||||
|
|
||||||
/* FIXME: This is temporary evil solution to get scene/view-layer/etc in the copy callback of the
|
/* FIXME: This is temporary evil solution to get scene/view-layer/etc in the copy callback of the
|
||||||
* #wmDropBox.
|
* #wmDropBox.
|
||||||
|
|
|
@ -11729,7 +11729,12 @@ bool UI_textbutton_activate_rna(const bContext *C,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (but_text) {
|
if (but_text) {
|
||||||
|
ARegion *region_ctx = CTX_wm_region(C);
|
||||||
|
|
||||||
|
/* Temporary context override for activating the button. */
|
||||||
|
CTX_wm_region_set(const_cast<bContext *>(C), region);
|
||||||
UI_but_active_only(C, region, block_text, but_text);
|
UI_but_active_only(C, region, block_text, but_text);
|
||||||
|
CTX_wm_region_set(const_cast<bContext *>(C), region_ctx);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
* \ingroup edinterface
|
* \ingroup edinterface
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "AS_asset_representation.h"
|
||||||
|
#include "AS_asset_representation.hh"
|
||||||
|
|
||||||
#include "DNA_space_types.h"
|
#include "DNA_space_types.h"
|
||||||
#include "DNA_userdef_types.h"
|
#include "DNA_userdef_types.h"
|
||||||
|
|
||||||
|
@ -33,6 +36,8 @@
|
||||||
|
|
||||||
#include "interface_intern.hh"
|
#include "interface_intern.hh"
|
||||||
|
|
||||||
|
using namespace blender;
|
||||||
|
|
||||||
struct AssetViewListData {
|
struct AssetViewListData {
|
||||||
AssetLibraryReference asset_library_ref;
|
AssetLibraryReference asset_library_ref;
|
||||||
AssetFilterSettings filter_settings;
|
AssetFilterSettings filter_settings;
|
||||||
|
@ -42,28 +47,20 @@ struct AssetViewListData {
|
||||||
|
|
||||||
static void asset_view_item_but_drag_set(uiBut *but, AssetHandle *asset_handle)
|
static void asset_view_item_but_drag_set(uiBut *but, AssetHandle *asset_handle)
|
||||||
{
|
{
|
||||||
ID *id = ED_asset_handle_get_local_id(asset_handle);
|
AssetRepresentation *asset = ED_asset_handle_get_representation(asset_handle);
|
||||||
|
|
||||||
|
ID *id = AS_asset_representation_local_id_get(asset);
|
||||||
if (id != nullptr) {
|
if (id != nullptr) {
|
||||||
UI_but_drag_set_id(but, id);
|
UI_but_drag_set_id(but, id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char blend_path[FILE_MAX_LIBEXTRA];
|
|
||||||
ED_asset_handle_get_full_library_path(asset_handle, blend_path);
|
|
||||||
|
|
||||||
const eAssetImportMethod import_method =
|
const eAssetImportMethod import_method =
|
||||||
ED_asset_handle_get_import_method(asset_handle).value_or(ASSET_IMPORT_APPEND_REUSE);
|
AS_asset_representation_import_method_get(asset).value_or(ASSET_IMPORT_APPEND_REUSE);
|
||||||
|
|
||||||
if (blend_path[0]) {
|
ImBuf *imbuf = ED_assetlist_asset_image_get(asset_handle);
|
||||||
ImBuf *imbuf = ED_assetlist_asset_image_get(asset_handle);
|
UI_but_drag_set_asset(
|
||||||
UI_but_drag_set_asset(but,
|
but, asset, import_method, ED_asset_handle_get_preview_icon_id(asset_handle), imbuf, 1.0f);
|
||||||
asset_handle,
|
|
||||||
BLI_strdup(blend_path),
|
|
||||||
import_method,
|
|
||||||
ED_asset_handle_get_preview_icon_id(asset_handle),
|
|
||||||
imbuf,
|
|
||||||
1.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asset_view_draw_item(uiList *ui_list,
|
static void asset_view_draw_item(uiList *ui_list,
|
||||||
|
@ -79,7 +76,8 @@ static void asset_view_draw_item(uiList *ui_list,
|
||||||
{
|
{
|
||||||
AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
|
AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
|
||||||
|
|
||||||
AssetHandle asset_handle = ED_assetlist_asset_get_by_index(&list_data->asset_library_ref, index);
|
AssetHandle asset_handle = ED_assetlist_asset_handle_get_by_index(&list_data->asset_library_ref,
|
||||||
|
index);
|
||||||
|
|
||||||
PointerRNA file_ptr;
|
PointerRNA file_ptr;
|
||||||
RNA_pointer_create(&list_data->screen->id,
|
RNA_pointer_create(&list_data->screen->id,
|
||||||
|
@ -132,8 +130,10 @@ static void asset_view_filter_items(uiList *ui_list,
|
||||||
C,
|
C,
|
||||||
[&name_filter, list_data, &filter_settings](
|
[&name_filter, list_data, &filter_settings](
|
||||||
const PointerRNA &itemptr, blender::StringRefNull name, int index) {
|
const PointerRNA &itemptr, blender::StringRefNull name, int index) {
|
||||||
AssetHandle asset = ED_assetlist_asset_get_by_index(&list_data->asset_library_ref, index);
|
asset_system::AssetRepresentation *asset = ED_assetlist_asset_get_by_index(
|
||||||
if (!ED_asset_filter_matches_asset(&filter_settings, &asset)) {
|
list_data->asset_library_ref, index);
|
||||||
|
|
||||||
|
if (!ED_asset_filter_matches_asset(&filter_settings, *asset)) {
|
||||||
return UI_LIST_ITEM_NEVER_SHOW;
|
return UI_LIST_ITEM_NEVER_SHOW;
|
||||||
}
|
}
|
||||||
return name_filter(itemptr, name, index);
|
return name_filter(itemptr, name, index);
|
||||||
|
@ -141,14 +141,15 @@ static void asset_view_filter_items(uiList *ui_list,
|
||||||
dataptr,
|
dataptr,
|
||||||
propname,
|
propname,
|
||||||
[list_data](const PointerRNA & /*itemptr*/, int index) -> std::string {
|
[list_data](const PointerRNA & /*itemptr*/, int index) -> std::string {
|
||||||
AssetHandle asset = ED_assetlist_asset_get_by_index(&list_data->asset_library_ref, index);
|
asset_system::AssetRepresentation *asset = ED_assetlist_asset_get_by_index(
|
||||||
return ED_asset_handle_get_name(&asset);
|
list_data->asset_library_ref, index);
|
||||||
|
|
||||||
|
return asset->get_name();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asset_view_listener(uiList *ui_list, wmRegionListenerParams *params)
|
static void asset_view_listener(uiList * /*ui_list*/, wmRegionListenerParams *params)
|
||||||
{
|
{
|
||||||
AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
|
|
||||||
const wmNotifier *notifier = params->notifier;
|
const wmNotifier *notifier = params->notifier;
|
||||||
|
|
||||||
switch (notifier->category) {
|
switch (notifier->category) {
|
||||||
|
@ -160,7 +161,7 @@ static void asset_view_listener(uiList *ui_list, wmRegionListenerParams *params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ED_assetlist_listen(&list_data->asset_library_ref, params->notifier)) {
|
if (ED_assetlist_listen(params->notifier)) {
|
||||||
ED_region_tag_redraw(params->region);
|
ED_region_tag_redraw(params->region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -976,6 +976,9 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
|
||||||
id->us = 0;
|
id->us = 0;
|
||||||
undo_push_label = "Delete Data-Block";
|
undo_push_label = "Delete Data-Block";
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
undo_push_label = "Unlink Data-Block";
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case UI_ID_FAKE_USER:
|
case UI_ID_FAKE_USER:
|
||||||
|
|
|
@ -2221,23 +2221,6 @@ bool EDBM_select_pick(bContext *C, const int mval[2], const SelectPick_Params *p
|
||||||
vc.em->mat_nr = efa->mat_nr;
|
vc.em->mat_nr = efa->mat_nr;
|
||||||
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, nullptr);
|
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change active face-map on object. */
|
|
||||||
if (!BLI_listbase_is_empty(&vc.obedit->fmaps)) {
|
|
||||||
const int cd_fmap_offset = CustomData_get_offset(&vc.em->bm->pdata, CD_FACEMAP);
|
|
||||||
if (cd_fmap_offset != -1) {
|
|
||||||
int map = *((int *)BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset));
|
|
||||||
if ((map < -1) || (map > BLI_listbase_count_at_most(&vc.obedit->fmaps, map))) {
|
|
||||||
map = -1;
|
|
||||||
}
|
|
||||||
map += 1;
|
|
||||||
if (map != vc.obedit->actfmap) {
|
|
||||||
/* We may want to add notifiers later,
|
|
||||||
* currently select update handles redraw. */
|
|
||||||
vc.obedit->actfmap = map;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Changing active object is handy since it allows us to
|
/* Changing active object is handy since it allows us to
|
||||||
|
|
|
@ -76,7 +76,6 @@ static const EnumPropertyItem prop_similar_types[] = {
|
||||||
{SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
|
{SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
|
||||||
{SIMFACE_COPLANAR, "COPLANAR", 0, "Coplanar", ""},
|
{SIMFACE_COPLANAR, "COPLANAR", 0, "Coplanar", ""},
|
||||||
{SIMFACE_SMOOTH, "SMOOTH", 0, "Flat/Smooth", ""},
|
{SIMFACE_SMOOTH, "SMOOTH", 0, "Flat/Smooth", ""},
|
||||||
{SIMFACE_FACEMAP, "FACE_MAP", 0, "Face Map", ""},
|
|
||||||
#ifdef WITH_FREESTYLE
|
#ifdef WITH_FREESTYLE
|
||||||
{SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""},
|
{SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""},
|
||||||
#endif
|
#endif
|
||||||
|
@ -177,7 +176,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
||||||
KDTree_3d *tree_3d = NULL;
|
KDTree_3d *tree_3d = NULL;
|
||||||
KDTree_4d *tree_4d = NULL;
|
KDTree_4d *tree_4d = NULL;
|
||||||
GSet *gset = NULL;
|
GSet *gset = NULL;
|
||||||
GSet **gset_array = NULL;
|
|
||||||
int face_data_value = SIMFACE_DATA_NONE;
|
int face_data_value = SIMFACE_DATA_NONE;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -195,10 +193,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
||||||
case SIMFACE_MATERIAL:
|
case SIMFACE_MATERIAL:
|
||||||
gset = BLI_gset_ptr_new("Select similar face");
|
gset = BLI_gset_ptr_new("Select similar face");
|
||||||
break;
|
break;
|
||||||
case SIMFACE_FACEMAP:
|
|
||||||
gset_array = MEM_callocN(sizeof(GSet *) * objects_len,
|
|
||||||
"Select similar face: facemap gset array");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int tree_index = 0;
|
int tree_index = 0;
|
||||||
|
@ -208,7 +202,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
||||||
BMesh *bm = em->bm;
|
BMesh *bm = em->bm;
|
||||||
Material ***material_array = NULL;
|
Material ***material_array = NULL;
|
||||||
invert_m4_m4(ob->world_to_object, ob->object_to_world);
|
invert_m4_m4(ob->world_to_object, ob->object_to_world);
|
||||||
int custom_data_offset = 0;
|
|
||||||
|
|
||||||
if (bm->totfacesel == 0) {
|
if (bm->totfacesel == 0) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -232,13 +225,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SIMFACE_FACEMAP: {
|
|
||||||
custom_data_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
|
|
||||||
if (custom_data_offset == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
gset_array[ob_index] = BLI_gset_ptr_new("Select similar face: facemap gset");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BMFace *face; /* Mesh face. */
|
BMFace *face; /* Mesh face. */
|
||||||
|
@ -301,12 +287,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SIMFACE_FACEMAP: {
|
|
||||||
BLI_assert(custom_data_offset != -1);
|
|
||||||
int *face_map = BM_ELEM_CD_GET_VOID_P(face, custom_data_offset);
|
|
||||||
BLI_gset_add(gset_array[ob_index], face_map);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,7 +313,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
||||||
BMesh *bm = em->bm;
|
BMesh *bm = em->bm;
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
Material ***material_array = NULL;
|
Material ***material_array = NULL;
|
||||||
int custom_data_offset;
|
|
||||||
|
|
||||||
float ob_m3[3][3];
|
float ob_m3[3][3];
|
||||||
copy_m3_m4(ob_m3, ob->object_to_world);
|
copy_m3_m4(ob_m3, ob->object_to_world);
|
||||||
|
@ -354,12 +333,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SIMFACE_FACEMAP: {
|
|
||||||
custom_data_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
|
|
||||||
if (custom_data_offset == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BMFace *face; /* Mesh face. */
|
BMFace *face; /* Mesh face. */
|
||||||
|
@ -467,18 +440,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SIMFACE_FACEMAP: {
|
|
||||||
const int *face_map = BM_ELEM_CD_GET_VOID_P(face, custom_data_offset);
|
|
||||||
GSetIterator gs_iter;
|
|
||||||
GSET_ITER (gs_iter, gset_array[ob_index]) {
|
|
||||||
const int *face_map_iter = BLI_gsetIterator_getKey(&gs_iter);
|
|
||||||
if (*face_map == *face_map_iter) {
|
|
||||||
select = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (select) {
|
if (select) {
|
||||||
|
@ -533,14 +494,6 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
||||||
if (gset != NULL) {
|
if (gset != NULL) {
|
||||||
BLI_gset_free(gset, NULL);
|
BLI_gset_free(gset, NULL);
|
||||||
}
|
}
|
||||||
if (gset_array != NULL) {
|
|
||||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
||||||
if (gset_array[ob_index] != NULL) {
|
|
||||||
BLI_gset_free(gset_array[ob_index], NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MEM_freeN(gset_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
@ -1376,7 +1329,7 @@ static const EnumPropertyItem *select_similar_type_itemf(bContext *C,
|
||||||
#ifdef WITH_FREESTYLE
|
#ifdef WITH_FREESTYLE
|
||||||
const int a_end = SIMFACE_FREESTYLE;
|
const int a_end = SIMFACE_FREESTYLE;
|
||||||
#else
|
#else
|
||||||
const int a_end = SIMFACE_FACEMAP;
|
const int a_end = SIMFACE_MATERIAL;
|
||||||
#endif
|
#endif
|
||||||
for (a = SIMFACE_MATERIAL; a <= a_end; a++) {
|
for (a = SIMFACE_MATERIAL; a <= a_end; a++) {
|
||||||
RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
|
RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
#include "BKE_multires.h"
|
#include "BKE_multires.h"
|
||||||
#include "BKE_object.h"
|
#include "BKE_object.h"
|
||||||
#include "BKE_object_deform.h"
|
#include "BKE_object_deform.h"
|
||||||
#include "BKE_object_facemap.h"
|
|
||||||
#include "BKE_report.h"
|
#include "BKE_report.h"
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
#include "DEG_depsgraph.h"
|
||||||
|
@ -273,23 +272,6 @@ static void join_mesh_single(Depsgraph *depsgraph,
|
||||||
for (const int i : blender::IndexRange(me->totpoly)) {
|
for (const int i : blender::IndexRange(me->totpoly)) {
|
||||||
poly_offsets[i] = src_poly_offsets[i] + *loopofs;
|
poly_offsets[i] = src_poly_offsets[i] + *loopofs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Face maps. */
|
|
||||||
int *fmap = (int *)CustomData_get_for_write(pdata, *polyofs, CD_FACEMAP, totpoly);
|
|
||||||
const int *fmap_src = (const int *)CustomData_get_for_write(
|
|
||||||
&me->pdata, 0, CD_FACEMAP, me->totpoly);
|
|
||||||
|
|
||||||
/* Remap to correct new face-map indices, if needed. */
|
|
||||||
if (fmap_src) {
|
|
||||||
BLI_assert(fmap != nullptr);
|
|
||||||
int *fmap_index_map;
|
|
||||||
int fmap_index_map_len;
|
|
||||||
fmap_index_map = BKE_object_facemap_index_map_create(ob_src, ob_dst, &fmap_index_map_len);
|
|
||||||
BKE_object_facemap_index_map_apply(fmap, me->totpoly, fmap_index_map, fmap_index_map_len);
|
|
||||||
if (fmap_index_map != nullptr) {
|
|
||||||
MEM_freeN(fmap_index_map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* these are used for relinking (cannot be set earlier, or else reattaching goes wrong) */
|
/* these are used for relinking (cannot be set earlier, or else reattaching goes wrong) */
|
||||||
|
@ -483,19 +465,6 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
|
||||||
me->vertex_group_active_index = 1;
|
me->vertex_group_active_index = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Join this object's face maps to the base one's. */
|
|
||||||
LISTBASE_FOREACH (bFaceMap *, fmap, &ob_iter->fmaps) {
|
|
||||||
/* See if this group exists in the object (if it doesn't, add it to the end) */
|
|
||||||
if (BKE_object_facemap_find_name(ob, fmap->name) == nullptr) {
|
|
||||||
bFaceMap *fmap_new = static_cast<bFaceMap *>(MEM_mallocN(sizeof(bFaceMap), __func__));
|
|
||||||
memcpy(fmap_new, fmap, sizeof(bFaceMap));
|
|
||||||
BLI_addtail(&ob->fmaps, fmap_new);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ob->fmaps.first && ob->actfmap == 0) {
|
|
||||||
ob->actfmap = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh_join_offset_face_sets_ID(me, &face_set_id_offset);
|
mesh_join_offset_face_sets_ID(me, &face_set_id_offset);
|
||||||
|
|
||||||
if (me->totvert) {
|
if (me->totvert) {
|
||||||
|
|
|
@ -44,7 +44,6 @@ set(SRC
|
||||||
object_data_transfer.c
|
object_data_transfer.c
|
||||||
object_data_transform.cc
|
object_data_transform.cc
|
||||||
object_edit.cc
|
object_edit.cc
|
||||||
object_facemap_ops.c
|
|
||||||
object_gpencil_modifier.c
|
object_gpencil_modifier.c
|
||||||
object_hook.c
|
object_hook.c
|
||||||
object_light_linking_ops.cc
|
object_light_linking_ops.cc
|
||||||
|
|
|
@ -1,493 +0,0 @@
|
||||||
/* SPDX-FileCopyrightText: 2008 Blender Foundation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \ingroup edobj
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
|
||||||
|
|
||||||
#include "BLI_listbase.h"
|
|
||||||
#include "BLI_math.h"
|
|
||||||
#include "BLI_utildefines.h"
|
|
||||||
|
|
||||||
#include "DNA_mesh_types.h"
|
|
||||||
#include "DNA_object_types.h"
|
|
||||||
#include "DNA_workspace_types.h"
|
|
||||||
|
|
||||||
#include "BKE_context.h"
|
|
||||||
#include "BKE_customdata.h"
|
|
||||||
#include "BKE_editmesh.h"
|
|
||||||
#include "BKE_object.h"
|
|
||||||
#include "BKE_object_deform.h"
|
|
||||||
#include "BKE_object_facemap.h"
|
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
|
||||||
|
|
||||||
#include "RNA_access.h"
|
|
||||||
#include "RNA_define.h"
|
|
||||||
|
|
||||||
#include "WM_api.h"
|
|
||||||
#include "WM_types.h"
|
|
||||||
|
|
||||||
#include "ED_mesh.h"
|
|
||||||
#include "ED_object.h"
|
|
||||||
|
|
||||||
#include "object_intern.h"
|
|
||||||
|
|
||||||
void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum)
|
|
||||||
{
|
|
||||||
int fmap_nr;
|
|
||||||
if (GS(((ID *)ob->data)->name) != ID_ME) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the face map number, exit if it can't be found */
|
|
||||||
fmap_nr = BLI_findindex(&ob->fmaps, fmap);
|
|
||||||
|
|
||||||
if (fmap_nr != -1) {
|
|
||||||
int *facemap;
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
|
|
||||||
/* if there's is no facemap layer then create one */
|
|
||||||
if ((facemap = CustomData_get_layer_for_write(&me->pdata, CD_FACEMAP, me->totpoly)) == NULL) {
|
|
||||||
facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_SET_DEFAULT, me->totpoly);
|
|
||||||
}
|
|
||||||
|
|
||||||
facemap[facenum] = fmap_nr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum)
|
|
||||||
{
|
|
||||||
int fmap_nr;
|
|
||||||
if (GS(((ID *)ob->data)->name) != ID_ME) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the face map number, exit if it can't be found */
|
|
||||||
fmap_nr = BLI_findindex(&ob->fmaps, fmap);
|
|
||||||
|
|
||||||
if (fmap_nr != -1) {
|
|
||||||
int *facemap;
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
|
|
||||||
if ((facemap = CustomData_get_layer_for_write(&me->pdata, CD_FACEMAP, me->totpoly)) == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
facemap[facenum] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void object_fmap_remap_edit_mode(Object *ob, const int *remap)
|
|
||||||
{
|
|
||||||
if (ob->type != OB_MESH) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
if (me->edit_mesh) {
|
|
||||||
BMEditMesh *em = me->edit_mesh;
|
|
||||||
const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
|
|
||||||
|
|
||||||
if (cd_fmap_offset != -1) {
|
|
||||||
BMFace *efa;
|
|
||||||
BMIter iter;
|
|
||||||
int *map;
|
|
||||||
|
|
||||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
|
||||||
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
|
|
||||||
|
|
||||||
if (map && *map != -1) {
|
|
||||||
*map = remap[*map];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void object_fmap_remap_object_mode(Object *ob, const int *remap)
|
|
||||||
{
|
|
||||||
if (ob->type != OB_MESH) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
|
|
||||||
int *map = CustomData_get_layer_for_write(&me->pdata, CD_FACEMAP, me->totpoly);
|
|
||||||
if (map) {
|
|
||||||
for (int i = 0; i < me->totpoly; i++) {
|
|
||||||
if (map[i] != -1) {
|
|
||||||
map[i] = remap[map[i]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void object_facemap_remap(Object *ob, const int *remap)
|
|
||||||
{
|
|
||||||
if (BKE_object_is_in_editmode(ob)) {
|
|
||||||
object_fmap_remap_edit_mode(ob, remap);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
object_fmap_remap_object_mode(ob, remap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool face_map_supported_poll(bContext *C)
|
|
||||||
{
|
|
||||||
Object *ob = ED_object_context(C);
|
|
||||||
ID *data = (ob) ? ob->data : NULL;
|
|
||||||
return (ob && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && ob->type == OB_MESH && data &&
|
|
||||||
!ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool face_map_supported_edit_mode_poll(bContext *C)
|
|
||||||
{
|
|
||||||
Object *ob = ED_object_context(C);
|
|
||||||
|
|
||||||
if (face_map_supported_poll(C)) {
|
|
||||||
if (ob->mode == OB_MODE_EDIT) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool face_map_supported_remove_poll(bContext *C)
|
|
||||||
{
|
|
||||||
if (!face_map_supported_poll(C)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object *ob = ED_object_context(C);
|
|
||||||
bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
|
|
||||||
if (fmap) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int face_map_add_exec(bContext *C, wmOperator *UNUSED(op))
|
|
||||||
{
|
|
||||||
Object *ob = ED_object_context(C);
|
|
||||||
|
|
||||||
BKE_object_facemap_add(ob);
|
|
||||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
|
|
||||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBJECT_OT_face_map_add(wmOperatorType *ot)
|
|
||||||
{
|
|
||||||
/* identifiers */
|
|
||||||
ot->name = "Add Face Map";
|
|
||||||
ot->idname = "OBJECT_OT_face_map_add";
|
|
||||||
ot->description = "Add a new face map to the active object";
|
|
||||||
|
|
||||||
/* api callbacks */
|
|
||||||
ot->poll = face_map_supported_poll;
|
|
||||||
ot->exec = face_map_add_exec;
|
|
||||||
|
|
||||||
/* flags */
|
|
||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int face_map_remove_exec(bContext *C, wmOperator *UNUSED(op))
|
|
||||||
{
|
|
||||||
Object *ob = ED_object_context(C);
|
|
||||||
bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
|
|
||||||
|
|
||||||
if (fmap) {
|
|
||||||
BKE_object_facemap_remove(ob, fmap);
|
|
||||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
|
|
||||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
|
||||||
}
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBJECT_OT_face_map_remove(wmOperatorType *ot)
|
|
||||||
{
|
|
||||||
/* identifiers */
|
|
||||||
ot->name = "Remove Face Map";
|
|
||||||
ot->idname = "OBJECT_OT_face_map_remove";
|
|
||||||
ot->description = "Remove a face map from the active object";
|
|
||||||
|
|
||||||
/* api callbacks */
|
|
||||||
ot->poll = face_map_supported_remove_poll;
|
|
||||||
ot->exec = face_map_remove_exec;
|
|
||||||
|
|
||||||
/* flags */
|
|
||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int face_map_assign_exec(bContext *C, wmOperator *UNUSED(op))
|
|
||||||
{
|
|
||||||
Object *ob = ED_object_context(C);
|
|
||||||
bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
|
|
||||||
|
|
||||||
if (fmap) {
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
BMEditMesh *em = me->edit_mesh;
|
|
||||||
BMFace *efa;
|
|
||||||
BMIter iter;
|
|
||||||
int *map;
|
|
||||||
int cd_fmap_offset;
|
|
||||||
|
|
||||||
if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) {
|
|
||||||
BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
|
|
||||||
|
|
||||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
|
||||||
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
|
|
||||||
|
|
||||||
if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
|
|
||||||
*map = ob->actfmap - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
|
|
||||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
|
||||||
}
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBJECT_OT_face_map_assign(wmOperatorType *ot)
|
|
||||||
{
|
|
||||||
/* identifiers */
|
|
||||||
ot->name = "Assign Face Map";
|
|
||||||
ot->idname = "OBJECT_OT_face_map_assign";
|
|
||||||
ot->description = "Assign faces to a face map";
|
|
||||||
|
|
||||||
/* api callbacks */
|
|
||||||
ot->poll = face_map_supported_edit_mode_poll;
|
|
||||||
ot->exec = face_map_assign_exec;
|
|
||||||
|
|
||||||
/* flags */
|
|
||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int face_map_remove_from_exec(bContext *C, wmOperator *UNUSED(op))
|
|
||||||
{
|
|
||||||
Object *ob = ED_object_context(C);
|
|
||||||
bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
|
|
||||||
|
|
||||||
if (fmap) {
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
BMEditMesh *em = me->edit_mesh;
|
|
||||||
BMFace *efa;
|
|
||||||
BMIter iter;
|
|
||||||
int *map;
|
|
||||||
int cd_fmap_offset;
|
|
||||||
int mapindex = ob->actfmap - 1;
|
|
||||||
|
|
||||||
if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) {
|
|
||||||
return OPERATOR_CANCELLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
|
|
||||||
|
|
||||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
|
||||||
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
|
|
||||||
|
|
||||||
if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && *map == mapindex) {
|
|
||||||
*map = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
|
|
||||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
|
||||||
}
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBJECT_OT_face_map_remove_from(wmOperatorType *ot)
|
|
||||||
{
|
|
||||||
/* identifiers */
|
|
||||||
ot->name = "Remove from Face Map";
|
|
||||||
ot->idname = "OBJECT_OT_face_map_remove_from";
|
|
||||||
ot->description = "Remove faces from a face map";
|
|
||||||
|
|
||||||
/* api callbacks */
|
|
||||||
ot->poll = face_map_supported_edit_mode_poll;
|
|
||||||
ot->exec = face_map_remove_from_exec;
|
|
||||||
|
|
||||||
/* flags */
|
|
||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fmap_select(Object *ob, bool select)
|
|
||||||
{
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
BMEditMesh *em = me->edit_mesh;
|
|
||||||
BMFace *efa;
|
|
||||||
BMIter iter;
|
|
||||||
int *map;
|
|
||||||
int cd_fmap_offset;
|
|
||||||
int mapindex = ob->actfmap - 1;
|
|
||||||
|
|
||||||
if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) {
|
|
||||||
BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
|
|
||||||
|
|
||||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
|
||||||
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
|
|
||||||
|
|
||||||
if (*map == mapindex) {
|
|
||||||
BM_face_select_set(em->bm, efa, select);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int face_map_select_exec(bContext *C, wmOperator *UNUSED(op))
|
|
||||||
{
|
|
||||||
Object *ob = ED_object_context(C);
|
|
||||||
bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
|
|
||||||
|
|
||||||
if (fmap) {
|
|
||||||
fmap_select(ob, true);
|
|
||||||
|
|
||||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
|
|
||||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
|
||||||
}
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBJECT_OT_face_map_select(wmOperatorType *ot)
|
|
||||||
{
|
|
||||||
/* identifiers */
|
|
||||||
ot->name = "Select Face Map Faces";
|
|
||||||
ot->idname = "OBJECT_OT_face_map_select";
|
|
||||||
ot->description = "Select faces belonging to a face map";
|
|
||||||
|
|
||||||
/* api callbacks */
|
|
||||||
ot->poll = face_map_supported_edit_mode_poll;
|
|
||||||
ot->exec = face_map_select_exec;
|
|
||||||
|
|
||||||
/* flags */
|
|
||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int face_map_deselect_exec(bContext *C, wmOperator *UNUSED(op))
|
|
||||||
{
|
|
||||||
Object *ob = ED_object_context(C);
|
|
||||||
bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
|
|
||||||
|
|
||||||
if (fmap) {
|
|
||||||
fmap_select(ob, false);
|
|
||||||
|
|
||||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
|
|
||||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
|
||||||
}
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBJECT_OT_face_map_deselect(wmOperatorType *ot)
|
|
||||||
{
|
|
||||||
/* identifiers */
|
|
||||||
ot->name = "Deselect Face Map Faces";
|
|
||||||
ot->idname = "OBJECT_OT_face_map_deselect";
|
|
||||||
ot->description = "Deselect faces belonging to a face map";
|
|
||||||
|
|
||||||
/* api callbacks */
|
|
||||||
ot->poll = face_map_supported_edit_mode_poll;
|
|
||||||
ot->exec = face_map_deselect_exec;
|
|
||||||
|
|
||||||
/* flags */
|
|
||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int face_map_move_exec(bContext *C, wmOperator *op)
|
|
||||||
{
|
|
||||||
Object *ob = ED_object_context(C);
|
|
||||||
bFaceMap *fmap;
|
|
||||||
int dir = RNA_enum_get(op->ptr, "direction");
|
|
||||||
|
|
||||||
fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
|
|
||||||
if (!fmap) {
|
|
||||||
return OPERATOR_CANCELLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fmap->prev && !fmap->next) {
|
|
||||||
return OPERATOR_CANCELLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pos1 = BLI_findindex(&ob->fmaps, fmap);
|
|
||||||
int pos2 = pos1 - dir;
|
|
||||||
int len = BLI_listbase_count(&ob->fmaps);
|
|
||||||
int *map = MEM_mallocN(len * sizeof(*map), __func__);
|
|
||||||
|
|
||||||
if (!IN_RANGE(pos2, -1, len)) {
|
|
||||||
const int offset = len - dir;
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
map[i] = (i + offset) % len;
|
|
||||||
}
|
|
||||||
pos2 = map[pos1];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
range_vn_i(map, len, 0);
|
|
||||||
SWAP(int, map[pos1], map[pos2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *prev = fmap->prev;
|
|
||||||
void *next = fmap->next;
|
|
||||||
BLI_remlink(&ob->fmaps, fmap);
|
|
||||||
if (dir == 1) { /*up*/
|
|
||||||
BLI_insertlinkbefore(&ob->fmaps, prev, fmap);
|
|
||||||
}
|
|
||||||
else { /*down*/
|
|
||||||
BLI_insertlinkafter(&ob->fmaps, next, fmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Iterate through mesh and substitute the indices as necessary. */
|
|
||||||
object_facemap_remap(ob, map);
|
|
||||||
MEM_freeN(map);
|
|
||||||
|
|
||||||
ob->actfmap = pos2 + 1;
|
|
||||||
|
|
||||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
|
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBJECT_OT_face_map_move(wmOperatorType *ot)
|
|
||||||
{
|
|
||||||
static EnumPropertyItem fmap_slot_move[] = {
|
|
||||||
{1, "UP", 0, "Up", ""},
|
|
||||||
{-1, "DOWN", 0, "Down", ""},
|
|
||||||
{0, NULL, 0, NULL, NULL},
|
|
||||||
};
|
|
||||||
|
|
||||||
/* identifiers */
|
|
||||||
ot->name = "Move Face Map";
|
|
||||||
ot->idname = "OBJECT_OT_face_map_move";
|
|
||||||
ot->description = "Move the active face map up/down in the list";
|
|
||||||
|
|
||||||
/* api callbacks */
|
|
||||||
ot->poll = face_map_supported_poll;
|
|
||||||
ot->exec = face_map_move_exec;
|
|
||||||
|
|
||||||
/* flags */
|
|
||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
||||||
|
|
||||||
RNA_def_enum(
|
|
||||||
ot->srna, "direction", fmap_slot_move, 0, "Direction", "Direction to move, up or down");
|
|
||||||
}
|
|
|
@ -316,16 +316,6 @@ void OBJECT_OT_vertex_weight_set_active(struct wmOperatorType *ot);
|
||||||
void OBJECT_OT_vertex_weight_normalize_active_vertex(struct wmOperatorType *ot);
|
void OBJECT_OT_vertex_weight_normalize_active_vertex(struct wmOperatorType *ot);
|
||||||
void OBJECT_OT_vertex_weight_copy(struct wmOperatorType *ot);
|
void OBJECT_OT_vertex_weight_copy(struct wmOperatorType *ot);
|
||||||
|
|
||||||
/* object_facemap_ops.c */
|
|
||||||
|
|
||||||
void OBJECT_OT_face_map_add(struct wmOperatorType *ot);
|
|
||||||
void OBJECT_OT_face_map_remove(struct wmOperatorType *ot);
|
|
||||||
void OBJECT_OT_face_map_assign(struct wmOperatorType *ot);
|
|
||||||
void OBJECT_OT_face_map_remove_from(struct wmOperatorType *ot);
|
|
||||||
void OBJECT_OT_face_map_select(struct wmOperatorType *ot);
|
|
||||||
void OBJECT_OT_face_map_deselect(struct wmOperatorType *ot);
|
|
||||||
void OBJECT_OT_face_map_move(struct wmOperatorType *ot);
|
|
||||||
|
|
||||||
/* object_warp.c */
|
/* object_warp.c */
|
||||||
|
|
||||||
void TRANSFORM_OT_vertex_warp(struct wmOperatorType *ot);
|
void TRANSFORM_OT_vertex_warp(struct wmOperatorType *ot);
|
||||||
|
|
|
@ -226,14 +226,6 @@ void ED_operatortypes_object(void)
|
||||||
WM_operatortype_append(OBJECT_OT_vertex_weight_normalize_active_vertex);
|
WM_operatortype_append(OBJECT_OT_vertex_weight_normalize_active_vertex);
|
||||||
WM_operatortype_append(OBJECT_OT_vertex_weight_copy);
|
WM_operatortype_append(OBJECT_OT_vertex_weight_copy);
|
||||||
|
|
||||||
WM_operatortype_append(OBJECT_OT_face_map_add);
|
|
||||||
WM_operatortype_append(OBJECT_OT_face_map_remove);
|
|
||||||
WM_operatortype_append(OBJECT_OT_face_map_assign);
|
|
||||||
WM_operatortype_append(OBJECT_OT_face_map_remove_from);
|
|
||||||
WM_operatortype_append(OBJECT_OT_face_map_select);
|
|
||||||
WM_operatortype_append(OBJECT_OT_face_map_deselect);
|
|
||||||
WM_operatortype_append(OBJECT_OT_face_map_move);
|
|
||||||
|
|
||||||
WM_operatortype_append(TRANSFORM_OT_vertex_warp);
|
WM_operatortype_append(TRANSFORM_OT_vertex_warp);
|
||||||
|
|
||||||
WM_operatortype_append(OBJECT_OT_move_to_collection);
|
WM_operatortype_append(OBJECT_OT_move_to_collection);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "ED_screen.h"
|
#include "ED_screen.h"
|
||||||
|
|
||||||
|
#include "UI_interface.h"
|
||||||
#include "UI_interface_icons.h"
|
#include "UI_interface_icons.h"
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
@ -47,9 +48,8 @@ int ED_region_generic_tools_region_snap_size(const ARegion *region, int size, in
|
||||||
/* Using Y axis avoids slight feedback loop when adjusting X. */
|
/* Using Y axis avoids slight feedback loop when adjusting X. */
|
||||||
const float aspect = BLI_rctf_size_y(®ion->v2d.cur) /
|
const float aspect = BLI_rctf_size_y(®ion->v2d.cur) /
|
||||||
(BLI_rcti_size_y(®ion->v2d.mask) + 1);
|
(BLI_rcti_size_y(®ion->v2d.mask) + 1);
|
||||||
const float icon_size = ICON_DEFAULT_HEIGHT_TOOLBAR / aspect;
|
const float column = UI_TOOLBAR_COLUMN / aspect;
|
||||||
const float column = 1.25f * icon_size;
|
const float margin = UI_TOOLBAR_MARGIN / aspect;
|
||||||
const float margin = 0.5f * icon_size;
|
|
||||||
const float snap_units[] = {
|
const float snap_units[] = {
|
||||||
column + margin,
|
column + margin,
|
||||||
(2.0f * column) + margin,
|
(2.0f * column) + margin,
|
||||||
|
|
|
@ -464,7 +464,6 @@ enum eSculptFaceSetsInitMode {
|
||||||
SCULPT_FACE_SETS_FROM_CREASES = 4,
|
SCULPT_FACE_SETS_FROM_CREASES = 4,
|
||||||
SCULPT_FACE_SETS_FROM_SHARP_EDGES = 5,
|
SCULPT_FACE_SETS_FROM_SHARP_EDGES = 5,
|
||||||
SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT = 6,
|
SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT = 6,
|
||||||
SCULPT_FACE_SETS_FROM_FACE_MAPS = 7,
|
|
||||||
SCULPT_FACE_SETS_FROM_FACE_SET_BOUNDARIES = 8,
|
SCULPT_FACE_SETS_FROM_FACE_SET_BOUNDARIES = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -518,13 +517,7 @@ static EnumPropertyItem prop_sculpt_face_sets_init_types[] = {
|
||||||
"Face Sets from Sharp Edges",
|
"Face Sets from Sharp Edges",
|
||||||
"Create Face Sets using Sharp Edges as boundaries",
|
"Create Face Sets using Sharp Edges as boundaries",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
SCULPT_FACE_SETS_FROM_FACE_MAPS,
|
|
||||||
"FACE_MAPS",
|
|
||||||
0,
|
|
||||||
"Face Sets from Face Maps",
|
|
||||||
"Create a Face Set per Face Map",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
SCULPT_FACE_SETS_FROM_FACE_SET_BOUNDARIES,
|
SCULPT_FACE_SETS_FROM_FACE_SET_BOUNDARIES,
|
||||||
"FACE_SET_BOUNDARIES",
|
"FACE_SET_BOUNDARIES",
|
||||||
|
@ -610,13 +603,6 @@ static void sculpt_face_sets_init_loop(Object *ob, const int mode)
|
||||||
ss->face_sets[i] = material_indices[i] + 1;
|
ss->face_sets[i] = material_indices[i] + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mode == SCULPT_FACE_SETS_FROM_FACE_MAPS) {
|
|
||||||
const int *face_maps = static_cast<const int *>(
|
|
||||||
CustomData_get_layer(&mesh->pdata, CD_FACEMAP));
|
|
||||||
for (const int i : IndexRange(mesh->totpoly)) {
|
|
||||||
ss->face_sets[i] = face_maps ? face_maps[i] : 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
|
static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
|
||||||
|
@ -719,10 +705,6 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCULPT_FACE_SETS_FROM_FACE_MAPS: {
|
|
||||||
sculpt_face_sets_init_loop(ob, SCULPT_FACE_SETS_FROM_FACE_MAPS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SCULPT_undo_push_end(ob);
|
SCULPT_undo_push_end(ob);
|
||||||
|
|
|
@ -127,7 +127,7 @@ static SpaceLink *action_create(const ScrArea *area, const Scene *scene)
|
||||||
return (SpaceLink *)saction;
|
return (SpaceLink *)saction;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* not spacelink itself */
|
/* Doesn't free the space-link itself. */
|
||||||
static void action_free(SpaceLink * /*sl*/)
|
static void action_free(SpaceLink * /*sl*/)
|
||||||
{
|
{
|
||||||
// SpaceAction *saction = (SpaceAction *) sl;
|
// SpaceAction *saction = (SpaceAction *) sl;
|
||||||
|
|
|
@ -303,7 +303,7 @@ static SpaceLink *xxx_create(const ScrArea *UNUSED(area), const Scene *UNUSED(sc
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* not spacelink itself */
|
/* Doesn't free the space-link itself. */
|
||||||
static void xxx_free(SpaceLink *UNUSED(sl)) {}
|
static void xxx_free(SpaceLink *UNUSED(sl)) {}
|
||||||
|
|
||||||
/* spacetype; init callback for usage, should be re-doable. */
|
/* spacetype; init callback for usage, should be re-doable. */
|
||||||
|
|
|
@ -51,10 +51,7 @@ static int buttons_start_filter_exec(bContext *C, wmOperator *UNUSED(op))
|
||||||
ScrArea *area = CTX_wm_area(C);
|
ScrArea *area = CTX_wm_area(C);
|
||||||
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_HEADER);
|
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_HEADER);
|
||||||
|
|
||||||
ARegion *region_ctx = CTX_wm_region(C);
|
|
||||||
CTX_wm_region_set(C, region);
|
|
||||||
UI_textbutton_activate_rna(C, region, space, "search_filter");
|
UI_textbutton_activate_rna(C, region, space, "search_filter");
|
||||||
CTX_wm_region_set(C, region_ctx);
|
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue