Merge branch 'master' into sculpt-dev
This commit is contained in:
commit
0bf2a1f8fe
|
@ -46,3 +46,6 @@ Desktop.ini
|
|||
|
||||
# smoke simulation noise tile (generated)
|
||||
waveletNoiseTile.bin
|
||||
|
||||
# testing environment
|
||||
/Testing
|
||||
|
|
|
@ -1235,6 +1235,7 @@ if(WITH_OPENMP)
|
|||
string(APPEND CMAKE_C_FLAGS " ${OpenMP_C_FLAGS}")
|
||||
string(APPEND CMAKE_CXX_FLAGS " ${OpenMP_CXX_FLAGS}")
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS " ${OpenMP_LINKER_FLAGS}")
|
||||
string(APPEND CMAKE_MODULE_LINKER_FLAGS " ${OpenMP_LINKER_FLAGS}")
|
||||
else()
|
||||
# Typically avoid adding flags as defines but we can't
|
||||
# pass OpenMP flags to the linker for static builds, meaning
|
||||
|
|
|
@ -146,7 +146,7 @@ if(WITH_PYTHON)
|
|||
|
||||
set(PYTHON_INCLUDE_DIR "${_py_framework}/include/python${PYTHON_VERSION}")
|
||||
set(PYTHON_EXECUTABLE "${_py_framework}/bin/python${PYTHON_VERSION}")
|
||||
set(PYTHON_LIBPATH "${_py_framework}/lib/python${PYTHON_VERSION}/config-${PYTHON_VERSION}")
|
||||
set(PYTHON_LIBPATH "${_py_framework}/lib/python${PYTHON_VERSION}/")
|
||||
# set(PYTHON_LIBRARY python${PYTHON_VERSION})
|
||||
# set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework Python") # won't build with this enabled
|
||||
|
||||
|
|
|
@ -375,7 +375,7 @@ static void attr_create_generic(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool
|
|||
case BL::Attribute::domain_POINT:
|
||||
element = ATTR_ELEMENT_VERTEX;
|
||||
break;
|
||||
case BL::Attribute::domain_POLYGON:
|
||||
case BL::Attribute::domain_FACE:
|
||||
element = ATTR_ELEMENT_FACE;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -242,12 +242,15 @@ ccl_device float3 svm_math_blackbody_color(float t)
|
|||
return make_float3(4.70366907f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
/* Manually align for readability. */
|
||||
/* clang-format off */
|
||||
int i = (t >= 6365.0f) ? 5 :
|
||||
(t >= 3315.0f) ? 4 :
|
||||
(t >= 1902.0f) ? 3 :
|
||||
(t >= 1449.0f) ? 2 :
|
||||
(t >= 1167.0f) ? 1 :
|
||||
0;
|
||||
/* clang-format on */
|
||||
|
||||
ccl_constant float *r = blackbody_table_r[i];
|
||||
ccl_constant float *g = blackbody_table_g[i];
|
||||
|
|
|
@ -1584,7 +1584,6 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro
|
|||
dscene->tri_vnormal.tag_realloc();
|
||||
dscene->tri_vindex.tag_realloc();
|
||||
dscene->tri_patch.tag_realloc();
|
||||
dscene->tri_vnormal.tag_realloc();
|
||||
dscene->tri_patch_uv.tag_realloc();
|
||||
dscene->tri_shader.tag_realloc();
|
||||
dscene->patches.tag_realloc();
|
||||
|
|
|
@ -153,10 +153,6 @@ void Object::update_motion()
|
|||
|
||||
void Object::compute_bounds(bool motion_blur)
|
||||
{
|
||||
if (!is_modified() && !geometry->is_modified()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BoundBox mbounds = geometry->bounds;
|
||||
|
||||
if (motion_blur && use_motion()) {
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
/**
|
||||
* \code{.py}
|
||||
* import bpy
|
||||
* import textwrap
|
||||
*
|
||||
|
@ -42,6 +43,7 @@
|
|||
* print("%d,%d," % (w, h))
|
||||
* text = ", ".join(["0x%x" % p for p in pixels])
|
||||
* print(textwrap.fill(text, width=120), end=",\n")
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
|
@ -533,11 +533,18 @@ GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state)
|
|||
wp.showCmd = SW_SHOWMAXIMIZED;
|
||||
wp.ptMaxPosition.x = 0;
|
||||
wp.ptMaxPosition.y = 0;
|
||||
style &= ~WS_CAPTION;
|
||||
style &= ~(WS_CAPTION | WS_MAXIMIZE);
|
||||
break;
|
||||
case GHOST_kWindowStateNormal:
|
||||
default:
|
||||
wp.showCmd = SW_SHOWNORMAL;
|
||||
if (curstate == GHOST_kWindowStateFullScreen &&
|
||||
m_normal_state == GHOST_kWindowStateMaximized) {
|
||||
wp.showCmd = SW_SHOWMAXIMIZED;
|
||||
m_normal_state = GHOST_kWindowStateNormal;
|
||||
}
|
||||
else {
|
||||
wp.showCmd = SW_SHOWNORMAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
::SetWindowLongPtr(m_hWnd, GWL_STYLE, style);
|
||||
|
|
|
@ -349,6 +349,10 @@ def enable(module_name, *, default_set=False, persistent=False, handle_error=Non
|
|||
# 1) try import
|
||||
try:
|
||||
mod = __import__(module_name)
|
||||
if mod.__file__ is None:
|
||||
# This can happen when the addon has been removed but there are
|
||||
# residual `.pyc` files left behind.
|
||||
raise ImportError(name=module_name)
|
||||
mod.__time__ = os.path.getmtime(mod.__file__)
|
||||
mod.__addon_enabled__ = False
|
||||
except Exception as ex:
|
||||
|
|
|
@ -1694,6 +1694,7 @@ def km_image(params):
|
|||
("image.view_all", {"type": 'HOME', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("fit_view", True)]}),
|
||||
("image.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
|
||||
("image.view_cursor_center", {"type": 'C', "value": 'PRESS', "shift": True}, None),
|
||||
("image.view_pan", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
|
||||
("image.view_pan", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True}, None),
|
||||
("image.view_pan", {"type": 'TRACKPADPAN', "value": 'ANY'}, None),
|
||||
|
|
|
@ -355,7 +355,8 @@ class UpdateAnimatedTransformConstraint(Operator):
|
|||
|
||||
use_convert_to_radians: BoolProperty(
|
||||
name="Convert to Radians",
|
||||
description="Convert fcurves/drivers affecting rotations to radians (Warning: use this only once!)",
|
||||
description="Convert f-curves/drivers affecting rotations to radians.\n"
|
||||
"Warning: Use this only once",
|
||||
default=True,
|
||||
)
|
||||
|
||||
|
@ -430,22 +431,9 @@ class UpdateAnimatedTransformConstraint(Operator):
|
|||
return {'FINISHED'}
|
||||
|
||||
|
||||
class ANIM_OT_show_group_colors_deprecated(Operator):
|
||||
"""This option moved to Preferences > Animation"""
|
||||
|
||||
bl_idname = "anim.show_group_colors_deprecated"
|
||||
bl_label = "Show Group Colors"
|
||||
bl_options = {'REGISTER'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, _context):
|
||||
return False
|
||||
|
||||
|
||||
classes = (
|
||||
ANIM_OT_keying_set_export,
|
||||
NLA_OT_bake,
|
||||
ClearUselessActions,
|
||||
UpdateAnimatedTransformConstraint,
|
||||
ANIM_OT_show_group_colors_deprecated,
|
||||
)
|
||||
|
|
|
@ -74,10 +74,6 @@ class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
|
|||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.alignment = 'LEFT'
|
||||
row.label(text="Enable physics for:")
|
||||
|
||||
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
|
||||
|
||||
obj = context.object
|
||||
|
|
|
@ -348,8 +348,6 @@ class DOPESHEET_MT_view(Menu):
|
|||
col.active = context.space_data.mode != 'SHAPEKEY'
|
||||
col.prop(st, "show_sliders")
|
||||
|
||||
if bpy.app.version < (2, 93):
|
||||
layout.operator("anim.show_group_colors_deprecated", icon='CHECKBOX_HLT')
|
||||
layout.prop(st, "show_interpolation")
|
||||
layout.prop(st, "show_extremes")
|
||||
layout.prop(st, "use_auto_merge_keyframes")
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from bpy.types import Header, Menu, Panel
|
||||
from bl_ui.space_dopesheet import (
|
||||
DopesheetFilterPopoverBase,
|
||||
|
@ -120,10 +119,6 @@ class GRAPH_MT_view(Menu):
|
|||
layout.prop(st, "use_realtime_update")
|
||||
layout.prop(st, "show_cursor")
|
||||
layout.prop(st, "show_sliders")
|
||||
|
||||
if bpy.app.version < (2, 93):
|
||||
layout.operator("anim.show_group_colors_deprecated", icon='CHECKBOX_HLT')
|
||||
|
||||
layout.prop(st, "use_auto_merge_keyframes")
|
||||
|
||||
if st.mode != 'DRIVERS':
|
||||
|
|
|
@ -481,7 +481,7 @@ class NODE_MT_context_menu(Menu):
|
|||
class NODE_PT_active_node_generic(Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Item"
|
||||
bl_category = "Node"
|
||||
bl_label = "Node"
|
||||
|
||||
@classmethod
|
||||
|
@ -499,7 +499,7 @@ class NODE_PT_active_node_generic(Panel):
|
|||
class NODE_PT_active_node_color(Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Item"
|
||||
bl_category = "Node"
|
||||
bl_label = "Color"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_parent_id = 'NODE_PT_active_node_generic'
|
||||
|
@ -529,7 +529,7 @@ class NODE_PT_active_node_color(Panel):
|
|||
class NODE_PT_active_node_properties(Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Item"
|
||||
bl_category = "Node"
|
||||
bl_label = "Properties"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
|
@ -570,7 +570,7 @@ class NODE_PT_active_node_properties(Panel):
|
|||
class NODE_PT_texture_mapping(Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Item"
|
||||
bl_category = "Node"
|
||||
bl_label = "Texture Mapping"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
|
|
|
@ -484,6 +484,7 @@ geometry_node_categories = [
|
|||
GeometryNodeCategory("GEO_ATTRIBUTE", "Attribute", items=[
|
||||
NodeItem("GeometryNodeAttributeRandomize"),
|
||||
NodeItem("GeometryNodeAttributeMath"),
|
||||
NodeItem("GeometryNodeAttributeClamp"),
|
||||
NodeItem("GeometryNodeAttributeCompare"),
|
||||
NodeItem("GeometryNodeAttributeConvert"),
|
||||
NodeItem("GeometryNodeAttributeFill"),
|
||||
|
@ -495,6 +496,7 @@ geometry_node_categories = [
|
|||
NodeItem("GeometryNodeAttributeCombineXYZ"),
|
||||
NodeItem("GeometryNodeAttributeSeparateXYZ"),
|
||||
NodeItem("GeometryNodeAttributeRemove"),
|
||||
NodeItem("GeometryNodeAttributeMapRange"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_COLOR", "Color", items=[
|
||||
NodeItem("ShaderNodeValToRGB"),
|
||||
|
@ -520,7 +522,16 @@ geometry_node_categories = [
|
|||
NodeItem("GeometryNodeEdgeSplit"),
|
||||
NodeItem("GeometryNodeSubdivisionSurface"),
|
||||
NodeItem("GeometryNodeSubdivide"),
|
||||
|
||||
]),
|
||||
GeometryNodeCategory("GEO_PRIMITIVES", "Mesh Primitives", items=[
|
||||
NodeItem("GeometryNodeMeshCircle"),
|
||||
NodeItem("GeometryNodeMeshCone"),
|
||||
NodeItem("GeometryNodeMeshCube"),
|
||||
NodeItem("GeometryNodeMeshCylinder"),
|
||||
NodeItem("GeometryNodeMeshGrid"),
|
||||
NodeItem("GeometryNodeMeshIcoSphere"),
|
||||
NodeItem("GeometryNodeMeshLine"),
|
||||
NodeItem("GeometryNodeMeshUVSphere"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_POINT", "Point", items=[
|
||||
NodeItem("GeometryNodePointDistribute"),
|
||||
|
@ -531,20 +542,6 @@ geometry_node_categories = [
|
|||
NodeItem("GeometryNodeRotatePoints"),
|
||||
NodeItem("GeometryNodeAlignRotationToVector"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_VOLUME", "Volume", items=[
|
||||
NodeItem("GeometryNodePointsToVolume"),
|
||||
NodeItem("GeometryNodeVolumeToMesh"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_PRIMITIVES", "Mesh Primitives", items=[
|
||||
NodeItem("GeometryNodeMeshCube"),
|
||||
NodeItem("GeometryNodeMeshCircle"),
|
||||
NodeItem("GeometryNodeMeshUVSphere"),
|
||||
NodeItem("GeometryNodeMeshIcoSphere"),
|
||||
NodeItem("GeometryNodeMeshCylinder"),
|
||||
NodeItem("GeometryNodeMeshCone"),
|
||||
NodeItem("GeometryNodeMeshLine"),
|
||||
NodeItem("GeometryNodeMeshPlane"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_UTILITIES", "Utilities", items=[
|
||||
NodeItem("ShaderNodeMapRange"),
|
||||
NodeItem("ShaderNodeClamp"),
|
||||
|
@ -558,6 +555,10 @@ geometry_node_categories = [
|
|||
NodeItem("ShaderNodeVectorMath"),
|
||||
NodeItem("ShaderNodeVectorRotate"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_VOLUME", "Volume", items=[
|
||||
NodeItem("GeometryNodePointsToVolume"),
|
||||
NodeItem("GeometryNodeVolumeToMesh"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_GROUP", "Group", items=node_group_items),
|
||||
GeometryNodeCategory("GEO_LAYOUT", "Layout", items=[
|
||||
NodeItem("NodeFrame"),
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
shader basic_shader(
|
||||
float in_float = 1.0,
|
||||
color in_color = color(1.0, 1.0, 1.0),
|
||||
output float out_float = 0.0,
|
||||
output color out_color = color(0.0, 0.0, 0.0)
|
||||
)
|
||||
{
|
||||
out_float = in_float * 2.0;
|
||||
out_color = in_color * 2.0;
|
||||
}
|
|
@ -227,6 +227,9 @@ void BKE_pose_blend_read_data(struct BlendDataReader *reader, struct bPose *pose
|
|||
void BKE_pose_blend_read_lib(struct BlendLibReader *reader, struct Object *ob, struct bPose *pose);
|
||||
void BKE_pose_blend_read_expand(struct BlendExpander *expander, struct bPose *pose);
|
||||
|
||||
/* action_mirror.c */
|
||||
void BKE_action_flip_with_pose(struct bAction *act, struct Object *ob_arm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -39,12 +39,12 @@ struct ReportList;
|
|||
|
||||
/* Attribute.domain */
|
||||
typedef enum AttributeDomain {
|
||||
ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */
|
||||
ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */
|
||||
ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */
|
||||
ATTR_DOMAIN_CORNER = 2, /* Mesh Corner */
|
||||
ATTR_DOMAIN_POLYGON = 3, /* Mesh Polygon */
|
||||
ATTR_DOMAIN_CURVE = 4, /* Hair Curve */
|
||||
ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */
|
||||
ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */
|
||||
ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */
|
||||
ATTR_DOMAIN_CORNER = 2, /* Mesh Corner */
|
||||
ATTR_DOMAIN_FACE = 3, /* Mesh Face */
|
||||
ATTR_DOMAIN_CURVE = 4, /* Hair Curve */
|
||||
|
||||
ATTR_DOMAIN_NUM
|
||||
} AttributeDomain;
|
||||
|
|
|
@ -39,7 +39,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 14
|
||||
#define BLENDER_FILE_SUBVERSION 15
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -232,6 +232,19 @@ int BKE_fcurve_bezt_binarysearch_index(struct BezTriple array[],
|
|||
int arraylen,
|
||||
bool *r_replace);
|
||||
|
||||
/* fcurve_cache.c */
|
||||
/* Cached f-curve look-ups, use when this needs to be done many times. */
|
||||
struct FCurvePathCache;
|
||||
struct FCurvePathCache *BKE_fcurve_pathcache_create(ListBase *list);
|
||||
void BKE_fcurve_pathcache_destroy(struct FCurvePathCache *fcache);
|
||||
struct FCurve *BKE_fcurve_pathcache_find(struct FCurvePathCache *fcache,
|
||||
const char rna_path[],
|
||||
const int array_index);
|
||||
int BKE_fcurve_pathcache_find_array(struct FCurvePathCache *fcache,
|
||||
const char *rna_path,
|
||||
struct FCurve **fcurve_result,
|
||||
int fcurve_result_len);
|
||||
|
||||
/* get the time extents for F-Curve */
|
||||
bool BKE_fcurve_calc_range(
|
||||
struct FCurve *fcu, float *min, float *max, const bool do_sel_only, const bool do_min_length);
|
||||
|
@ -245,6 +258,14 @@ bool BKE_fcurve_calc_bounds(struct FCurve *fcu,
|
|||
const bool do_sel_only,
|
||||
const bool include_handles);
|
||||
|
||||
float *BKE_fcurves_calc_keyed_frames_ex(struct FCurve **fcurve_array,
|
||||
const int fcurve_array_len,
|
||||
const float interval,
|
||||
int *r_frames_len);
|
||||
float *BKE_fcurves_calc_keyed_frames(struct FCurve **fcurve_array,
|
||||
const int fcurve_array_len,
|
||||
int *r_frames_len);
|
||||
|
||||
void BKE_fcurve_active_keyframe_set(struct FCurve *fcu, const struct BezTriple *active_bezt);
|
||||
int BKE_fcurve_active_keyframe_index(const struct FCurve *fcu);
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@ struct GeometryInstanceGroup {
|
|||
Vector<float4x4> transforms;
|
||||
};
|
||||
|
||||
Vector<GeometryInstanceGroup> geometry_set_gather_instances(const GeometrySet &geometry_set);
|
||||
void geometry_set_gather_instances(const GeometrySet &geometry_set,
|
||||
Vector<GeometryInstanceGroup> &r_instance_groups);
|
||||
|
||||
GeometrySet geometry_set_realize_mesh_for_modifier(const GeometrySet &geometry_set);
|
||||
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set);
|
||||
|
|
|
@ -483,14 +483,14 @@ void ntreeBlendReadExpand(struct BlendExpander *expander, struct bNodeTree *ntre
|
|||
/** \name Node Tree Interface
|
||||
* \{ */
|
||||
struct bNodeSocket *ntreeFindSocketInterface(struct bNodeTree *ntree,
|
||||
int in_out,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *identifier);
|
||||
struct bNodeSocket *ntreeAddSocketInterface(struct bNodeTree *ntree,
|
||||
int in_out,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *idname,
|
||||
const char *name);
|
||||
struct bNodeSocket *ntreeInsertSocketInterface(struct bNodeTree *ntree,
|
||||
int in_out,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *idname,
|
||||
struct bNodeSocket *next_sock,
|
||||
const char *name);
|
||||
|
@ -556,30 +556,32 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype);
|
|||
} \
|
||||
((void)0)
|
||||
|
||||
struct bNodeSocket *nodeFindSocket(const struct bNode *node, int in_out, const char *identifier);
|
||||
struct bNodeSocket *nodeFindSocket(const struct bNode *node,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *identifier);
|
||||
struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
int in_out,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *idname,
|
||||
const char *identifier,
|
||||
const char *name);
|
||||
struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
int in_out,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *idname,
|
||||
struct bNodeSocket *next_sock,
|
||||
const char *identifier,
|
||||
const char *name);
|
||||
struct bNodeSocket *nodeAddStaticSocket(struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
int in_out,
|
||||
eNodeSocketInOut in_out,
|
||||
int type,
|
||||
int subtype,
|
||||
const char *identifier,
|
||||
const char *name);
|
||||
struct bNodeSocket *nodeInsertStaticSocket(struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
int in_out,
|
||||
eNodeSocketInOut in_out,
|
||||
int type,
|
||||
int subtype,
|
||||
struct bNodeSocket *next_sock,
|
||||
|
@ -1393,7 +1395,9 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
|
|||
#define GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE 1036
|
||||
#define GEO_NODE_MESH_PRIMITIVE_CONE 1037
|
||||
#define GEO_NODE_MESH_PRIMITIVE_LINE 1038
|
||||
#define GEO_NODE_MESH_PRIMITIVE_PLANE 1039
|
||||
#define GEO_NODE_MESH_PRIMITIVE_GRID 1039
|
||||
#define GEO_NODE_ATTRIBUTE_MAP_RANGE 1040
|
||||
#define GEO_NODE_ATTRIBUTE_CLAMP 1041
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -58,9 +58,7 @@ class NodeTreeEvaluationContext {
|
|||
|
||||
uint64_t hash() const
|
||||
{
|
||||
const uint64_t hash1 = blender::DefaultHash<std::string>{}(object_name_);
|
||||
const uint64_t hash2 = BLI_session_uuid_hash_uint64(&modifier_session_uuid_);
|
||||
return hash1 ^ (hash2 * 33); /* Copied from DefaultHash for std::pair. */
|
||||
return blender::get_default_hash_2(object_name_, modifier_session_uuid_);
|
||||
}
|
||||
|
||||
friend bool operator==(const NodeTreeEvaluationContext &a, const NodeTreeEvaluationContext &b)
|
||||
|
|
|
@ -69,6 +69,7 @@ set(SRC
|
|||
intern/CCGSubSurf_util.c
|
||||
intern/DerivedMesh.cc
|
||||
intern/action.c
|
||||
intern/action_mirror.c
|
||||
intern/addon.c
|
||||
intern/anim_data.c
|
||||
intern/anim_path.c
|
||||
|
@ -126,6 +127,7 @@ set(SRC
|
|||
intern/editmesh_tangent.c
|
||||
intern/effect.c
|
||||
intern/fcurve.c
|
||||
intern/fcurve_cache.c
|
||||
intern/fcurve_driver.c
|
||||
intern/fluid.c
|
||||
intern/fmodifier.c
|
||||
|
@ -385,6 +387,7 @@ set(SRC
|
|||
BKE_multires.h
|
||||
BKE_nla.h
|
||||
BKE_node.h
|
||||
BKE_node_ui_storage.hh
|
||||
BKE_object.h
|
||||
BKE_object_deform.h
|
||||
BKE_object_facemap.h
|
||||
|
@ -434,10 +437,10 @@ set(SRC
|
|||
nla_private.h
|
||||
particle_private.h
|
||||
tracking_private.h
|
||||
intern/attribute_access_intern.hh
|
||||
intern/CCGSubSurf.h
|
||||
intern/CCGSubSurf_inline.h
|
||||
intern/CCGSubSurf_intern.h
|
||||
intern/attribute_access_intern.hh
|
||||
intern/data_transfer_intern.h
|
||||
intern/lib_intern.h
|
||||
intern/multires_inline.h
|
||||
|
@ -742,7 +745,7 @@ if(WITH_GMP)
|
|||
list(APPEND INC_SYS
|
||||
${GMP_INCLUDE_DIRS}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# # Warnings as errors, this is too strict!
|
||||
# if(MSVC)
|
||||
|
|
|
@ -0,0 +1,457 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*
|
||||
* Mirror/Symmetry functions applying to actions.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_fcurve.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Flip the Action (Armature/Pose Objects)
|
||||
*
|
||||
* This flips the action using the rest pose (not the evaluated pose).
|
||||
*
|
||||
* Details:
|
||||
*
|
||||
* - Key-frames are modified in-place, creating new key-frames is not yet supported.
|
||||
* That could be useful if a user for example only has 2x rotation channels set.
|
||||
* In practice users typically keyframe all rotation channels or none.
|
||||
*
|
||||
* - F-curve modifiers are disabled for evaluation,
|
||||
* so the values written back to the keyframes don't include modifier offsets.
|
||||
*
|
||||
* - Sub-frame key-frames aren't supported,
|
||||
* this could be added if needed without much trouble.
|
||||
*
|
||||
* - F-curves must have a #FCurve.bezt array (sampled curves aren't supported).
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* This structure is created for each pose channels F-curve,
|
||||
* an action be evaluated and stored in `fcurve_eval`,
|
||||
* with the mirrored values written into `bezt_array`.
|
||||
*
|
||||
* Store F-curve evaluated values, constructed with a sorted array of rounded keyed-frames,
|
||||
* passed to #action_flip_pchan_cache_init.
|
||||
*/
|
||||
struct FCurve_KeyCache {
|
||||
/**
|
||||
* When NULL, ignore this channel.
|
||||
*/
|
||||
FCurve *fcurve;
|
||||
/**
|
||||
* Cached evaluated F-curve values (without modifiers).
|
||||
*/
|
||||
float *fcurve_eval;
|
||||
/**
|
||||
* Cached #FCurve.bezt values, NULL when no key-frame exists on this frame.
|
||||
*
|
||||
* \note The case where two keyframes round to the same frame isn't supported.
|
||||
* In this case only the first will be used.
|
||||
*/
|
||||
BezTriple **bezt_array;
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign `fkc` path, using a `path` lookup for a single value.
|
||||
*/
|
||||
static void action_flip_pchan_cache_fcurve_assign_value(struct FCurve_KeyCache *fkc,
|
||||
int index,
|
||||
const char *path,
|
||||
struct FCurvePathCache *fcache)
|
||||
{
|
||||
FCurve *fcu = BKE_fcurve_pathcache_find(fcache, path, index);
|
||||
if (fcu && fcu->bezt) {
|
||||
fkc->fcurve = fcu;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign #FCurve_KeyCache.fcurve path, using a `path` lookup for an array.
|
||||
*/
|
||||
static void action_flip_pchan_cache_fcurve_assign_array(struct FCurve_KeyCache *fkc,
|
||||
int fkc_len,
|
||||
const char *path,
|
||||
struct FCurvePathCache *fcache)
|
||||
{
|
||||
FCurve **fcurves = alloca(sizeof(*fcurves) * fkc_len);
|
||||
if (BKE_fcurve_pathcache_find_array(fcache, path, fcurves, fkc_len)) {
|
||||
for (int i = 0; i < fkc_len; i++) {
|
||||
if (fcurves[i] && fcurves[i]->bezt) {
|
||||
fkc[i].fcurve = fcurves[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill in pose channel cache for each frame in `keyed_frames`.
|
||||
*
|
||||
* \param keyed_frames: An array of keyed_frames to evaluate,
|
||||
* note that each frame is rounded to the nearest int.
|
||||
* \param keyed_frames_len: The length of the `keyed_frames` array.
|
||||
*/
|
||||
static void action_flip_pchan_cache_init(struct FCurve_KeyCache *fkc,
|
||||
const float *keyed_frames,
|
||||
int keyed_frames_len)
|
||||
{
|
||||
BLI_assert(fkc->fcurve != NULL);
|
||||
|
||||
/* Cache the F-curve values for `keyed_frames`. */
|
||||
const int fcurve_flag = fkc->fcurve->flag;
|
||||
fkc->fcurve->flag |= FCURVE_MOD_OFF;
|
||||
fkc->fcurve_eval = MEM_mallocN(sizeof(float) * keyed_frames_len, __func__);
|
||||
for (int frame_index = 0; frame_index < keyed_frames_len; frame_index++) {
|
||||
const float evaltime = keyed_frames[frame_index];
|
||||
fkc->fcurve_eval[frame_index] = evaluate_fcurve_only_curve(fkc->fcurve, evaltime);
|
||||
}
|
||||
fkc->fcurve->flag = fcurve_flag;
|
||||
|
||||
/* Cache the #BezTriple for `keyed_frames`, or leave as NULL. */
|
||||
fkc->bezt_array = MEM_mallocN(sizeof(*fkc->bezt_array) * keyed_frames_len, __func__);
|
||||
BezTriple *bezt = fkc->fcurve->bezt;
|
||||
BezTriple *bezt_end = fkc->fcurve->bezt + fkc->fcurve->totvert;
|
||||
|
||||
int frame_index = 0;
|
||||
while (frame_index < keyed_frames_len) {
|
||||
const float evaltime = keyed_frames[frame_index];
|
||||
const float bezt_time = roundf(bezt->vec[1][0]);
|
||||
if (bezt_time > evaltime) {
|
||||
fkc->bezt_array[frame_index++] = NULL;
|
||||
}
|
||||
else {
|
||||
if (bezt_time == evaltime) {
|
||||
fkc->bezt_array[frame_index++] = bezt;
|
||||
}
|
||||
bezt++;
|
||||
if (bezt == bezt_end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Clear remaining unset keyed_frames (if-any). */
|
||||
while (frame_index < keyed_frames_len) {
|
||||
fkc->bezt_array[frame_index++] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
static void action_flip_pchan(Object *ob_arm,
|
||||
const bPoseChannel *pchan,
|
||||
struct FCurvePathCache *fcache)
|
||||
{
|
||||
/* Begin F-Curve pose channel value extraction. */
|
||||
/* Use a fixed buffer size as it's known this can only be at most:
|
||||
* `pose.bones["{MAXBONENAME}"].rotation_quaternion`. */
|
||||
char path_xform[256];
|
||||
char pchan_name_esc[sizeof(((bActionChannel *)NULL)->name) * 2];
|
||||
BLI_str_escape(pchan_name_esc, pchan->name, sizeof(pchan_name_esc));
|
||||
const int path_xform_prefix_len = SNPRINTF(path_xform, "pose.bones[\"%s\"]", pchan_name_esc);
|
||||
char *path_xform_suffix = path_xform + path_xform_prefix_len;
|
||||
const int path_xform_suffix_len = sizeof(path_xform) - path_xform_prefix_len;
|
||||
|
||||
/* Lookup and assign all available #FCurve channels,
|
||||
* unavailable channels are left NULL. */
|
||||
|
||||
/**
|
||||
* Structure to store transformation F-curves corresponding to a pose bones transformation.
|
||||
* Match struct member names from #bPoseChannel so macros avoid repetition.
|
||||
*
|
||||
* \note There is no need to read values unless they influence the 4x4 transform matrix,
|
||||
* and no need to write values back unless they would be changed by a modified matrix.
|
||||
* So `rotmode` needs to be read, but doesn't need to be written back to.
|
||||
*
|
||||
* Most bendy-bone settings don't need to be included either, flipping their RNA paths is enough.
|
||||
* Although the X/Y settings could make sense to transform, in practice it would only
|
||||
* work well if the rotation happened to swap X/Y alignment, leave this for now.
|
||||
*/
|
||||
struct {
|
||||
struct FCurve_KeyCache loc[3], eul[3], quat[4], rotAxis[3], rotAngle, size[3], rotmode;
|
||||
} fkc_pchan = {{{NULL}}};
|
||||
|
||||
#define FCURVE_ASSIGN_VALUE(id, path_test_suffix, index) \
|
||||
BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_len); \
|
||||
action_flip_pchan_cache_fcurve_assign_value(&fkc_pchan.id, index, path_xform, fcache)
|
||||
|
||||
#define FCURVE_ASSIGN_ARRAY(id, path_test_suffix) \
|
||||
BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_len); \
|
||||
action_flip_pchan_cache_fcurve_assign_array( \
|
||||
fkc_pchan.id, ARRAY_SIZE(fkc_pchan.id), path_xform, fcache)
|
||||
|
||||
FCURVE_ASSIGN_ARRAY(loc, ".location");
|
||||
FCURVE_ASSIGN_ARRAY(eul, ".rotation_euler");
|
||||
FCURVE_ASSIGN_ARRAY(quat, ".rotation_quaternion");
|
||||
FCURVE_ASSIGN_ARRAY(rotAxis, ".rotation_axis_angle");
|
||||
FCURVE_ASSIGN_VALUE(rotAngle, ".rotation_axis_angle", 3);
|
||||
FCURVE_ASSIGN_ARRAY(size, ".scale");
|
||||
FCURVE_ASSIGN_VALUE(rotmode, ".rotation_mode", 0);
|
||||
|
||||
#undef FCURVE_ASSIGN_VALUE
|
||||
#undef FCURVE_ASSIGN_ARRAY
|
||||
|
||||
/* Array of F-curves, for convenient access. */
|
||||
#define FCURVE_CHANNEL_LEN (sizeof(fkc_pchan) / sizeof(struct FCurve_KeyCache))
|
||||
FCurve *fcurve_array[FCURVE_CHANNEL_LEN];
|
||||
int fcurve_array_len = 0;
|
||||
|
||||
for (int chan = 0; chan < FCURVE_CHANNEL_LEN; chan++) {
|
||||
struct FCurve_KeyCache *fkc = (struct FCurve_KeyCache *)(&fkc_pchan) + chan;
|
||||
if (fkc->fcurve != NULL) {
|
||||
fcurve_array[fcurve_array_len++] = fkc->fcurve;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this pose has no transform channels, there is nothing to do. */
|
||||
if (fcurve_array_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate an array of frames used by any of the key-frames in `fcurve_array`. */
|
||||
int keyed_frames_len;
|
||||
const float *keyed_frames = BKE_fcurves_calc_keyed_frames(
|
||||
fcurve_array, fcurve_array_len, &keyed_frames_len);
|
||||
|
||||
/* Initialize the pose channel curve cache from the F-curve. */
|
||||
for (int chan = 0; chan < FCURVE_CHANNEL_LEN; chan++) {
|
||||
struct FCurve_KeyCache *fkc = (struct FCurve_KeyCache *)(&fkc_pchan) + chan;
|
||||
if (fkc->fcurve == NULL) {
|
||||
continue;
|
||||
}
|
||||
action_flip_pchan_cache_init(fkc, keyed_frames, keyed_frames_len);
|
||||
}
|
||||
|
||||
/* X-axis flipping matrix. */
|
||||
float flip_mtx[4][4];
|
||||
unit_m4(flip_mtx);
|
||||
flip_mtx[0][0] = -1;
|
||||
|
||||
bPoseChannel *pchan_flip = NULL;
|
||||
char pchan_name_flip[MAXBONENAME];
|
||||
BLI_string_flip_side_name(pchan_name_flip, pchan->name, false, sizeof(pchan_name_flip));
|
||||
if (!STREQ(pchan_name_flip, pchan->name)) {
|
||||
pchan_flip = BKE_pose_channel_find_name(ob_arm->pose, pchan_name_flip);
|
||||
}
|
||||
|
||||
float arm_mat_inv[4][4];
|
||||
invert_m4_m4(arm_mat_inv, pchan_flip ? pchan_flip->bone->arm_mat : pchan->bone->arm_mat);
|
||||
|
||||
/* Now flip the transformation & write it back to the F-curves in `fkc_pchan`. */
|
||||
|
||||
for (int frame_index = 0; frame_index < keyed_frames_len; frame_index++) {
|
||||
|
||||
/* Temporary pose channel to write values into,
|
||||
* using the `fkc_pchan` values, falling back to the values in the pose channel. */
|
||||
bPoseChannel pchan_temp = *pchan;
|
||||
|
||||
/* Load the values into the channel. */
|
||||
#define READ_VALUE_FLT(id) \
|
||||
if (fkc_pchan.id.fcurve_eval != NULL) { \
|
||||
pchan_temp.id = fkc_pchan.id.fcurve_eval[frame_index]; \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
#define READ_VALUE_INT(id) \
|
||||
if (fkc_pchan.id.fcurve_eval != NULL) { \
|
||||
pchan_temp.id = floorf(fkc_pchan.id.fcurve_eval[frame_index] + 0.5f); \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
#define READ_ARRAY_FLT(id) \
|
||||
for (int i = 0; i < ARRAY_SIZE(pchan_temp.id); i++) { \
|
||||
READ_VALUE_FLT(id[i]); \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
READ_ARRAY_FLT(loc);
|
||||
READ_ARRAY_FLT(eul);
|
||||
READ_ARRAY_FLT(quat);
|
||||
READ_ARRAY_FLT(rotAxis);
|
||||
READ_VALUE_FLT(rotAngle);
|
||||
READ_ARRAY_FLT(size);
|
||||
READ_VALUE_INT(rotmode);
|
||||
|
||||
#undef READ_ARRAY_FLT
|
||||
#undef READ_VALUE_FLT
|
||||
#undef READ_VALUE_INT
|
||||
|
||||
float chan_mat[4][4];
|
||||
BKE_pchan_to_mat4(&pchan_temp, chan_mat);
|
||||
|
||||
/* Move to the pose-space. */
|
||||
mul_m4_m4m4(chan_mat, pchan->bone->arm_mat, chan_mat);
|
||||
|
||||
/* Flip the matrix. */
|
||||
mul_m4_m4m4(chan_mat, chan_mat, flip_mtx);
|
||||
mul_m4_m4m4(chan_mat, flip_mtx, chan_mat);
|
||||
|
||||
/* Move back to bone-space space, using the flipped bone if it exists. */
|
||||
mul_m4_m4m4(chan_mat, arm_mat_inv, chan_mat);
|
||||
|
||||
BKE_pchan_apply_mat4(&pchan_temp, chan_mat, false);
|
||||
|
||||
/* Write the values back to the F-curves. */
|
||||
#define WRITE_VALUE_FLT(id) \
|
||||
if (fkc_pchan.id.fcurve_eval != NULL) { \
|
||||
BezTriple *bezt = fkc_pchan.id.bezt_array[frame_index]; \
|
||||
if (bezt != NULL) { \
|
||||
const float delta = pchan_temp.id - bezt->vec[1][1]; \
|
||||
bezt->vec[0][1] += delta; \
|
||||
bezt->vec[1][1] += delta; \
|
||||
bezt->vec[2][1] += delta; \
|
||||
} \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
#define WRITE_ARRAY_FLT(id) \
|
||||
for (int i = 0; i < ARRAY_SIZE(pchan_temp.id); i++) { \
|
||||
WRITE_VALUE_FLT(id[i]); \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
/* Write the values back the the F-curves. */
|
||||
WRITE_ARRAY_FLT(loc);
|
||||
WRITE_ARRAY_FLT(eul);
|
||||
WRITE_ARRAY_FLT(quat);
|
||||
WRITE_ARRAY_FLT(rotAxis);
|
||||
WRITE_VALUE_FLT(rotAngle);
|
||||
WRITE_ARRAY_FLT(size);
|
||||
/* No need to write back 'rotmode' as it can't be transformed. */
|
||||
|
||||
#undef WRITE_ARRAY_FLT
|
||||
#undef WRITE_VALUE_FLT
|
||||
}
|
||||
|
||||
/* Recalculate handles. */
|
||||
for (int i = 0; i < fcurve_array_len; i++) {
|
||||
calchandles_fcurve_ex(fcurve_array[i], 0);
|
||||
}
|
||||
|
||||
MEM_freeN((void *)keyed_frames);
|
||||
|
||||
for (int chan = 0; chan < FCURVE_CHANNEL_LEN; chan++) {
|
||||
struct FCurve_KeyCache *fkc = (struct FCurve_KeyCache *)(&fkc_pchan) + chan;
|
||||
if (fkc->fcurve_eval) {
|
||||
MEM_freeN(fkc->fcurve_eval);
|
||||
}
|
||||
if (fkc->bezt_array) {
|
||||
MEM_freeN(fkc->bezt_array);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap all RNA paths left/right.
|
||||
*/
|
||||
static void action_flip_pchan_rna_paths(struct bAction *act)
|
||||
{
|
||||
const char *path_pose_prefix = "pose.bones[\"";
|
||||
const int path_pose_prefix_len = strlen(path_pose_prefix);
|
||||
|
||||
/* Tag curves that have renamed f-curves. */
|
||||
LISTBASE_FOREACH (bActionGroup *, agrp, &act->groups) {
|
||||
agrp->flag &= ~AGRP_TEMP;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
|
||||
if (!STRPREFIX(fcu->rna_path, path_pose_prefix)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *name_esc = fcu->rna_path + path_pose_prefix_len;
|
||||
const char *name_esc_end = BLI_str_escape_find_quote(name_esc);
|
||||
|
||||
/* While unlikely, an RNA path could be malformed. */
|
||||
if (UNLIKELY(name_esc_end == NULL)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char name[MAXBONENAME];
|
||||
const size_t name_esc_len = (size_t)(name_esc_end - name_esc);
|
||||
const size_t name_len = BLI_str_unescape(name, name_esc, name_esc_len);
|
||||
|
||||
/* While unlikely, data paths could be constructed that have longer names than
|
||||
* are currently supported. */
|
||||
if (UNLIKELY(name_len >= sizeof(name))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* When the flipped name differs, perform the rename. */
|
||||
char name_flip[MAXBONENAME];
|
||||
BLI_string_flip_side_name(name_flip, name, false, sizeof(name_flip));
|
||||
if (!STREQ(name_flip, name)) {
|
||||
char name_flip_esc[MAXBONENAME * 2];
|
||||
BLI_str_escape(name_flip_esc, name_flip, sizeof(name_flip_esc));
|
||||
char *path_flip = BLI_sprintfN("pose.bones[\"%s%s", name_flip_esc, name_esc_end);
|
||||
MEM_freeN(fcu->rna_path);
|
||||
fcu->rna_path = path_flip;
|
||||
|
||||
if (fcu->grp != NULL) {
|
||||
fcu->grp->flag |= AGRP_TEMP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Rename tagged groups. */
|
||||
LISTBASE_FOREACH (bActionGroup *, agrp, &act->groups) {
|
||||
if ((agrp->flag & AGRP_TEMP) == 0) {
|
||||
continue;
|
||||
}
|
||||
agrp->flag &= ~AGRP_TEMP;
|
||||
char name_flip[MAXBONENAME];
|
||||
BLI_string_flip_side_name(name_flip, agrp->name, false, sizeof(name_flip));
|
||||
if (!STREQ(name_flip, agrp->name)) {
|
||||
STRNCPY(agrp->name, name_flip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_action_flip_with_pose(struct bAction *act, struct Object *ob_arm)
|
||||
{
|
||||
struct FCurvePathCache *fcache = BKE_fcurve_pathcache_create(&act->curves);
|
||||
int i;
|
||||
LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob_arm->pose->chanbase, i) {
|
||||
action_flip_pchan(ob_arm, pchan, fcache);
|
||||
}
|
||||
BKE_fcurve_pathcache_destroy(fcache);
|
||||
|
||||
action_flip_pchan_rna_paths(act);
|
||||
|
||||
DEG_id_tag_update(&act->id, ID_RECALC_COPY_ON_WRITE);
|
||||
}
|
||||
|
||||
/** \} */
|
|
@ -69,8 +69,8 @@ static void get_domains(ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
|
|||
info[ATTR_DOMAIN_EDGE].length = mesh->totedge;
|
||||
info[ATTR_DOMAIN_CORNER].customdata = &mesh->ldata;
|
||||
info[ATTR_DOMAIN_CORNER].length = mesh->totloop;
|
||||
info[ATTR_DOMAIN_POLYGON].customdata = &mesh->pdata;
|
||||
info[ATTR_DOMAIN_POLYGON].length = mesh->totpoly;
|
||||
info[ATTR_DOMAIN_FACE].customdata = &mesh->pdata;
|
||||
info[ATTR_DOMAIN_FACE].length = mesh->totpoly;
|
||||
break;
|
||||
}
|
||||
case ID_HA: {
|
||||
|
|
|
@ -331,7 +331,7 @@ static int attribute_domain_priority(const AttributeDomain domain)
|
|||
case ATTR_DOMAIN_CURVE:
|
||||
return 0;
|
||||
#endif
|
||||
case ATTR_DOMAIN_POLYGON:
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return 1;
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return 2;
|
||||
|
@ -893,7 +893,7 @@ ReadAttributePtr GeometryComponent::attribute_try_get_for_read(
|
|||
return {};
|
||||
}
|
||||
|
||||
if (attribute->domain() != domain) {
|
||||
if (domain != ATTR_DOMAIN_AUTO && attribute->domain() != domain) {
|
||||
attribute = this->attribute_try_adapt_domain(std::move(attribute), domain);
|
||||
if (!attribute) {
|
||||
return {};
|
||||
|
|
|
@ -400,6 +400,8 @@ static void setup_app_data(bContext *C,
|
|||
bmain,
|
||||
curscene,
|
||||
bfd->cur_view_layer ? bfd->cur_view_layer : BKE_view_layer_default_view(curscene));
|
||||
/* We need to rebuild some of the deleted override rules (for UI feedback purpose). */
|
||||
BKE_lib_override_library_main_operations_create(bmain, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -99,6 +99,7 @@ static void cache_file_blend_write(BlendWriter *writer, ID *id, const void *id_a
|
|||
cache_file->handle_readers = NULL;
|
||||
|
||||
BLO_write_id_struct(writer, CacheFile, id_address, &cache_file->id);
|
||||
BKE_id_blend_write(writer, &cache_file->id);
|
||||
|
||||
if (cache_file->adt) {
|
||||
BKE_animdata_blend_write(writer, cache_file->adt);
|
||||
|
|
|
@ -425,6 +425,9 @@ static bool from_manifest(CryptomatteLayer &layer, blender::StringRefNull manife
|
|||
}
|
||||
|
||||
const int quoted_hash_len = quoted_string_len_(ref);
|
||||
if (quoted_hash_len < 2) {
|
||||
return false;
|
||||
}
|
||||
const int hash_len = quoted_hash_len - 2;
|
||||
CryptomatteHash hash = CryptomatteHash::from_hex_encoded(ref.substr(1, hash_len));
|
||||
ref = ref.drop_prefix(quoted_hash_len);
|
||||
|
|
|
@ -35,7 +35,9 @@
|
|||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_easing.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_sort_utils.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_animsys.h"
|
||||
|
@ -290,6 +292,12 @@ FCurve *BKE_fcurve_find(ListBase *list, const char rna_path[], const int array_i
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name FCurve Iteration
|
||||
* \{ */
|
||||
|
||||
/* Quick way to loop over all fcurves of a given 'path'. */
|
||||
FCurve *BKE_fcurve_iter_step(FCurve *fcu_iter, const char rna_path[])
|
||||
{
|
||||
|
@ -829,6 +837,56 @@ bool BKE_fcurve_calc_range(
|
|||
return foundvert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of keyed frames, rounded to `interval`.
|
||||
*
|
||||
* \param interval: Set to 1.0 to round to whole keyframes, 0.5 for in-between key-frames, etc.
|
||||
*
|
||||
* \note An interval of zero could be supported (this implies no rounding at all),
|
||||
* however this risks very small differences in float values being treated as separate keyframes.
|
||||
*/
|
||||
float *BKE_fcurves_calc_keyed_frames_ex(FCurve **fcurve_array,
|
||||
int fcurve_array_len,
|
||||
const float interval,
|
||||
int *r_frames_len)
|
||||
{
|
||||
/* Use `1e-3f` as the smallest possible value since these are converted to integers
|
||||
* and we can be sure `MAXFRAME / 1e-3f < INT_MAX` as it's around half the size. */
|
||||
const double interval_db = max_ff(interval, 1e-3f);
|
||||
GSet *frames_unique = BLI_gset_int_new(__func__);
|
||||
for (int fcurve_index = 0; fcurve_index < fcurve_array_len; fcurve_index++) {
|
||||
const FCurve *fcu = fcurve_array[fcurve_index];
|
||||
for (int i = 0; i < fcu->totvert; i++) {
|
||||
const BezTriple *bezt = &fcu->bezt[i];
|
||||
const double value = round((double)bezt->vec[1][0] / interval_db);
|
||||
BLI_assert(value > INT_MIN && value < INT_MAX);
|
||||
BLI_gset_add(frames_unique, POINTER_FROM_INT((int)value));
|
||||
}
|
||||
}
|
||||
|
||||
const size_t frames_len = BLI_gset_len(frames_unique);
|
||||
float *frames = MEM_mallocN(sizeof(*frames) * frames_len, __func__);
|
||||
|
||||
GSetIterator gs_iter;
|
||||
int i = 0;
|
||||
GSET_ITER_INDEX (gs_iter, frames_unique, i) {
|
||||
const int value = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter));
|
||||
frames[i] = (double)value * interval_db;
|
||||
}
|
||||
BLI_gset_free(frames_unique, NULL);
|
||||
|
||||
qsort(frames, frames_len, sizeof(*frames), BLI_sortutil_cmp_float);
|
||||
*r_frames_len = frames_len;
|
||||
return frames;
|
||||
}
|
||||
|
||||
float *BKE_fcurves_calc_keyed_frames(FCurve **fcurve_array,
|
||||
int fcurve_array_len,
|
||||
int *r_frames_len)
|
||||
{
|
||||
return BKE_fcurves_calc_keyed_frames_ex(fcurve_array, fcurve_array_len, 1.0f, r_frames_len);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*
|
||||
* Cache F-Curve look-ups.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "BKE_fcurve.h"
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name F-Curve Path Cache
|
||||
*
|
||||
* Cache for finding curves by RNA path & array index.
|
||||
* \{ */
|
||||
|
||||
struct FCurvePathCache_Span {
|
||||
/** Index in the #FCurvePathCache.fcurve_array indicating the start of the span. */
|
||||
uint index;
|
||||
/** Number of items in the span in #FCurvePathCache.fcurve_array that share an RNA path. */
|
||||
uint len;
|
||||
};
|
||||
|
||||
struct FCurvePathCache {
|
||||
/** All curves sorted by (#FCurve.rna_path, #FCurve.array_index) */
|
||||
FCurve **fcurve_array;
|
||||
uint fcurve_array_len;
|
||||
/** Storage for values of `span_from_rna_path`. */
|
||||
struct FCurvePathCache_Span *span_table;
|
||||
/** Map `FCurve.rna_path` to elements in #FCurvePathCache.span_table */
|
||||
GHash *span_from_rna_path;
|
||||
};
|
||||
|
||||
/**
|
||||
* #qsort callback for an #FCurve array.
|
||||
*/
|
||||
static int fcurve_cmp_for_cache(const void *fcu_a_p, const void *fcu_b_p)
|
||||
{
|
||||
const FCurve *fcu_a = *((const FCurve **)fcu_a_p);
|
||||
const FCurve *fcu_b = *((const FCurve **)fcu_b_p);
|
||||
const int cmp = strcmp(fcu_a->rna_path, fcu_b->rna_path);
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
if (fcu_a->array_index < fcu_b->array_index) {
|
||||
return -1;
|
||||
}
|
||||
if (fcu_a->array_index > fcu_b->array_index) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct FCurvePathCache *BKE_fcurve_pathcache_create(ListBase *list)
|
||||
{
|
||||
const uint fcurve_array_len = BLI_listbase_count(list);
|
||||
FCurve **fcurve_array = MEM_mallocN(sizeof(*fcurve_array) * fcurve_array_len, __func__);
|
||||
uint i;
|
||||
LISTBASE_FOREACH_INDEX (FCurve *, fcu, list, i) {
|
||||
fcurve_array[i] = fcu;
|
||||
}
|
||||
qsort(fcurve_array, fcurve_array_len, sizeof(FCurve *), fcurve_cmp_for_cache);
|
||||
|
||||
/* Allow for the case no F-curves share an RNA-path, otherwise this is over-allocated.
|
||||
* Although in practice it's likely to only be 3-4x as large as is needed
|
||||
* (with transform channels for e.g.). */
|
||||
struct FCurvePathCache_Span *span_table = MEM_mallocN(sizeof(*span_table) * fcurve_array_len,
|
||||
__func__);
|
||||
|
||||
/* May over reserve, harmless. */
|
||||
GHash *span_from_rna_path = BLI_ghash_str_new_ex(__func__, fcurve_array_len);
|
||||
uint span_index = 0;
|
||||
i = 0;
|
||||
while (i < fcurve_array_len) {
|
||||
uint i_end;
|
||||
for (i_end = i + 1; i_end < fcurve_array_len; i_end++) {
|
||||
/* As the indices are sorted, we know a decrease means a new RNA path is found. */
|
||||
if (fcurve_array[i]->array_index > fcurve_array[i_end]->array_index) {
|
||||
BLI_assert(!STREQ(fcurve_array[i]->rna_path, fcurve_array[i_end]->rna_path));
|
||||
break;
|
||||
}
|
||||
if (!STREQ(fcurve_array[i]->rna_path, fcurve_array[i_end]->rna_path)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct FCurvePathCache_Span *span = &span_table[span_index++];
|
||||
span->index = i;
|
||||
span->len = i_end - i;
|
||||
BLI_ghash_insert(span_from_rna_path, fcurve_array[i]->rna_path, span);
|
||||
i = i_end;
|
||||
}
|
||||
|
||||
struct FCurvePathCache *fcache = MEM_callocN(sizeof(struct FCurvePathCache), __func__);
|
||||
fcache->fcurve_array = fcurve_array;
|
||||
fcache->fcurve_array_len = fcurve_array_len;
|
||||
fcache->span_table = span_table;
|
||||
fcache->span_from_rna_path = span_from_rna_path;
|
||||
|
||||
return fcache;
|
||||
}
|
||||
|
||||
void BKE_fcurve_pathcache_destroy(struct FCurvePathCache *fcache)
|
||||
{
|
||||
MEM_freeN(fcache->fcurve_array);
|
||||
MEM_freeN(fcache->span_table);
|
||||
BLI_ghash_free(fcache->span_from_rna_path, NULL, NULL);
|
||||
MEM_freeN(fcache);
|
||||
}
|
||||
|
||||
FCurve *BKE_fcurve_pathcache_find(struct FCurvePathCache *fcache,
|
||||
const char *rna_path,
|
||||
const int array_index)
|
||||
{
|
||||
const struct FCurvePathCache_Span *span = BLI_ghash_lookup(fcache->span_from_rna_path, rna_path);
|
||||
if (span == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FCurve **fcurve = fcache->fcurve_array + span->index;
|
||||
const uint len = span->len;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (fcurve[i]->array_index == array_index) {
|
||||
return fcurve[i];
|
||||
}
|
||||
/* As these are sorted, early exit. */
|
||||
if (fcurve[i]->array_index > array_index) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill in an array of F-Curve, leave NULL when not found.
|
||||
*
|
||||
* \return The number of F-Curves found.
|
||||
*/
|
||||
int BKE_fcurve_pathcache_find_array(struct FCurvePathCache *fcache,
|
||||
const char *rna_path,
|
||||
FCurve **fcurve_result,
|
||||
int fcurve_result_len)
|
||||
{
|
||||
memset(fcurve_result, 0x0, sizeof(*fcurve_result) * fcurve_result_len);
|
||||
|
||||
const struct FCurvePathCache_Span *span = BLI_ghash_lookup(fcache->span_from_rna_path, rna_path);
|
||||
if (span == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int found = 0;
|
||||
FCurve **fcurve = fcache->fcurve_array + span->index;
|
||||
const uint len = span->len;
|
||||
for (int i = 0; i < len; i++) {
|
||||
/* As these are sorted, early exit. */
|
||||
if ((uint)fcurve[i]->array_index > (uint)fcurve_result_len) {
|
||||
break;
|
||||
}
|
||||
fcurve_result[fcurve[i]->array_index] = fcurve[i];
|
||||
found += 1;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/** \} */
|
|
@ -175,7 +175,7 @@ int MeshComponent::attribute_domain_size(const AttributeDomain domain) const
|
|||
return mesh_->totvert;
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return mesh_->totedge;
|
||||
case ATTR_DOMAIN_POLYGON:
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return mesh_->totpoly;
|
||||
default:
|
||||
break;
|
||||
|
@ -259,9 +259,9 @@ static ReadAttributePtr adapt_mesh_domain_point_to_corner(const Mesh &mesh,
|
|||
* only some values are required.
|
||||
*/
|
||||
template<typename T>
|
||||
static void adapt_mesh_domain_corner_to_polygon_impl(const Mesh &mesh,
|
||||
Span<T> old_values,
|
||||
MutableSpan<T> r_values)
|
||||
static void adapt_mesh_domain_corner_to_face_impl(const Mesh &mesh,
|
||||
Span<T> old_values,
|
||||
MutableSpan<T> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totpoly);
|
||||
attribute_math::DefaultMixer<T> mixer(r_values);
|
||||
|
@ -277,8 +277,8 @@ static void adapt_mesh_domain_corner_to_polygon_impl(const Mesh &mesh,
|
|||
mixer.finalize();
|
||||
}
|
||||
|
||||
static ReadAttributePtr adapt_mesh_domain_corner_to_polygon(const Mesh &mesh,
|
||||
ReadAttributePtr attribute)
|
||||
static ReadAttributePtr adapt_mesh_domain_corner_to_face(const Mesh &mesh,
|
||||
ReadAttributePtr attribute)
|
||||
{
|
||||
ReadAttributePtr new_attribute;
|
||||
const CustomDataType data_type = attribute->custom_data_type();
|
||||
|
@ -286,7 +286,7 @@ static ReadAttributePtr adapt_mesh_domain_corner_to_polygon(const Mesh &mesh,
|
|||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totpoly);
|
||||
adapt_mesh_domain_corner_to_polygon_impl<T>(mesh, attribute->get_span<T>(), values);
|
||||
adapt_mesh_domain_corner_to_face_impl<T>(mesh, attribute->get_span<T>(), values);
|
||||
new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT,
|
||||
std::move(values));
|
||||
}
|
||||
|
@ -336,9 +336,9 @@ static ReadAttributePtr adapt_mesh_domain_corner_to_edge(const Mesh &mesh,
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
void adapt_mesh_domain_polygon_to_point_impl(const Mesh &mesh,
|
||||
Span<T> old_values,
|
||||
MutableSpan<T> r_values)
|
||||
void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh,
|
||||
Span<T> old_values,
|
||||
MutableSpan<T> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totvert);
|
||||
attribute_math::DefaultMixer<T> mixer(r_values);
|
||||
|
@ -356,8 +356,8 @@ void adapt_mesh_domain_polygon_to_point_impl(const Mesh &mesh,
|
|||
mixer.finalize();
|
||||
}
|
||||
|
||||
static ReadAttributePtr adapt_mesh_domain_polygon_to_point(const Mesh &mesh,
|
||||
ReadAttributePtr attribute)
|
||||
static ReadAttributePtr adapt_mesh_domain_face_to_point(const Mesh &mesh,
|
||||
ReadAttributePtr attribute)
|
||||
{
|
||||
ReadAttributePtr new_attribute;
|
||||
const CustomDataType data_type = attribute->custom_data_type();
|
||||
|
@ -365,7 +365,7 @@ static ReadAttributePtr adapt_mesh_domain_polygon_to_point(const Mesh &mesh,
|
|||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totvert);
|
||||
adapt_mesh_domain_polygon_to_point_impl<T>(mesh, attribute->get_span<T>(), values);
|
||||
adapt_mesh_domain_face_to_point_impl<T>(mesh, attribute->get_span<T>(), values);
|
||||
new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT,
|
||||
std::move(values));
|
||||
}
|
||||
|
@ -374,9 +374,9 @@ static ReadAttributePtr adapt_mesh_domain_polygon_to_point(const Mesh &mesh,
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
void adapt_mesh_domain_polygon_to_corner_impl(const Mesh &mesh,
|
||||
const Span<T> old_values,
|
||||
MutableSpan<T> r_values)
|
||||
void adapt_mesh_domain_face_to_corner_impl(const Mesh &mesh,
|
||||
const Span<T> old_values,
|
||||
MutableSpan<T> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totloop);
|
||||
|
||||
|
@ -387,8 +387,8 @@ void adapt_mesh_domain_polygon_to_corner_impl(const Mesh &mesh,
|
|||
}
|
||||
}
|
||||
|
||||
static ReadAttributePtr adapt_mesh_domain_polygon_to_corner(const Mesh &mesh,
|
||||
ReadAttributePtr attribute)
|
||||
static ReadAttributePtr adapt_mesh_domain_face_to_corner(const Mesh &mesh,
|
||||
ReadAttributePtr attribute)
|
||||
{
|
||||
ReadAttributePtr new_attribute;
|
||||
const CustomDataType data_type = attribute->custom_data_type();
|
||||
|
@ -396,7 +396,7 @@ static ReadAttributePtr adapt_mesh_domain_polygon_to_corner(const Mesh &mesh,
|
|||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totloop);
|
||||
adapt_mesh_domain_polygon_to_corner_impl<T>(mesh, attribute->get_span<T>(), values);
|
||||
adapt_mesh_domain_face_to_corner_impl<T>(mesh, attribute->get_span<T>(), values);
|
||||
new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT,
|
||||
std::move(values));
|
||||
}
|
||||
|
@ -405,9 +405,9 @@ static ReadAttributePtr adapt_mesh_domain_polygon_to_corner(const Mesh &mesh,
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
void adapt_mesh_domain_polygon_to_edge_impl(const Mesh &mesh,
|
||||
const Span<T> old_values,
|
||||
MutableSpan<T> r_values)
|
||||
void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh,
|
||||
const Span<T> old_values,
|
||||
MutableSpan<T> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totedge);
|
||||
attribute_math::DefaultMixer<T> mixer(r_values);
|
||||
|
@ -423,8 +423,8 @@ void adapt_mesh_domain_polygon_to_edge_impl(const Mesh &mesh,
|
|||
mixer.finalize();
|
||||
}
|
||||
|
||||
static ReadAttributePtr adapt_mesh_domain_polygon_to_edge(const Mesh &mesh,
|
||||
ReadAttributePtr attribute)
|
||||
static ReadAttributePtr adapt_mesh_domain_face_to_edge(const Mesh &mesh,
|
||||
ReadAttributePtr attribute)
|
||||
{
|
||||
ReadAttributePtr new_attribute;
|
||||
const CustomDataType data_type = attribute->custom_data_type();
|
||||
|
@ -432,7 +432,7 @@ static ReadAttributePtr adapt_mesh_domain_polygon_to_edge(const Mesh &mesh,
|
|||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totedge);
|
||||
adapt_mesh_domain_polygon_to_edge_impl<T>(mesh, attribute->get_span<T>(), values);
|
||||
adapt_mesh_domain_face_to_edge_impl<T>(mesh, attribute->get_span<T>(), values);
|
||||
new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT,
|
||||
std::move(values));
|
||||
}
|
||||
|
@ -446,9 +446,9 @@ static ReadAttributePtr adapt_mesh_domain_polygon_to_edge(const Mesh &mesh,
|
|||
* only some values are required.
|
||||
*/
|
||||
template<typename T>
|
||||
static void adapt_mesh_domain_point_to_polygon_impl(const Mesh &mesh,
|
||||
const Span<T> old_values,
|
||||
MutableSpan<T> r_values)
|
||||
static void adapt_mesh_domain_point_to_face_impl(const Mesh &mesh,
|
||||
const Span<T> old_values,
|
||||
MutableSpan<T> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totpoly);
|
||||
attribute_math::DefaultMixer<T> mixer(r_values);
|
||||
|
@ -464,8 +464,8 @@ static void adapt_mesh_domain_point_to_polygon_impl(const Mesh &mesh,
|
|||
mixer.finalize();
|
||||
}
|
||||
|
||||
static ReadAttributePtr adapt_mesh_domain_point_to_polygon(const Mesh &mesh,
|
||||
ReadAttributePtr attribute)
|
||||
static ReadAttributePtr adapt_mesh_domain_point_to_face(const Mesh &mesh,
|
||||
ReadAttributePtr attribute)
|
||||
{
|
||||
ReadAttributePtr new_attribute;
|
||||
const CustomDataType data_type = attribute->custom_data_type();
|
||||
|
@ -473,7 +473,7 @@ static ReadAttributePtr adapt_mesh_domain_point_to_polygon(const Mesh &mesh,
|
|||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totpoly);
|
||||
adapt_mesh_domain_point_to_polygon_impl<T>(mesh, attribute->get_span<T>(), values);
|
||||
adapt_mesh_domain_point_to_face_impl<T>(mesh, attribute->get_span<T>(), values);
|
||||
new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT,
|
||||
std::move(values));
|
||||
}
|
||||
|
@ -531,7 +531,7 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
|
|||
for (const int poly_index : IndexRange(mesh.totpoly)) {
|
||||
const MPoly &poly = mesh.mpoly[poly_index];
|
||||
|
||||
/* For every corner, mix the values from the adjacent edges on the polygon. */
|
||||
/* For every corner, mix the values from the adjacent edges on the face. */
|
||||
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
|
||||
const int loop_index_prev = (loop_index - 1) % poly.totloop;
|
||||
const MLoop &loop = mesh.mloop[loop_index];
|
||||
|
@ -602,9 +602,9 @@ static ReadAttributePtr adapt_mesh_domain_edge_to_point(const Mesh &mesh,
|
|||
* only some values are required.
|
||||
*/
|
||||
template<typename T>
|
||||
static void adapt_mesh_domain_edge_to_polygon_impl(const Mesh &mesh,
|
||||
const Span<T> old_values,
|
||||
MutableSpan<T> r_values)
|
||||
static void adapt_mesh_domain_edge_to_face_impl(const Mesh &mesh,
|
||||
const Span<T> old_values,
|
||||
MutableSpan<T> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totpoly);
|
||||
attribute_math::DefaultMixer<T> mixer(r_values);
|
||||
|
@ -620,8 +620,8 @@ static void adapt_mesh_domain_edge_to_polygon_impl(const Mesh &mesh,
|
|||
mixer.finalize();
|
||||
}
|
||||
|
||||
static ReadAttributePtr adapt_mesh_domain_edge_to_polygon(const Mesh &mesh,
|
||||
ReadAttributePtr attribute)
|
||||
static ReadAttributePtr adapt_mesh_domain_edge_to_face(const Mesh &mesh,
|
||||
ReadAttributePtr attribute)
|
||||
{
|
||||
ReadAttributePtr new_attribute;
|
||||
const CustomDataType data_type = attribute->custom_data_type();
|
||||
|
@ -629,7 +629,7 @@ static ReadAttributePtr adapt_mesh_domain_edge_to_polygon(const Mesh &mesh,
|
|||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totpoly);
|
||||
adapt_mesh_domain_edge_to_polygon_impl<T>(mesh, attribute->get_span<T>(), values);
|
||||
adapt_mesh_domain_edge_to_face_impl<T>(mesh, attribute->get_span<T>(), values);
|
||||
new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT,
|
||||
std::move(values));
|
||||
}
|
||||
|
@ -658,8 +658,8 @@ ReadAttributePtr MeshComponent::attribute_try_adapt_domain(ReadAttributePtr attr
|
|||
switch (new_domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, std::move(attribute));
|
||||
case ATTR_DOMAIN_POLYGON:
|
||||
return blender::bke::adapt_mesh_domain_corner_to_polygon(*mesh_, std::move(attribute));
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, std::move(attribute));
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, std::move(attribute));
|
||||
default:
|
||||
|
@ -671,8 +671,8 @@ ReadAttributePtr MeshComponent::attribute_try_adapt_domain(ReadAttributePtr attr
|
|||
switch (new_domain) {
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, std::move(attribute));
|
||||
case ATTR_DOMAIN_POLYGON:
|
||||
return blender::bke::adapt_mesh_domain_point_to_polygon(*mesh_, std::move(attribute));
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, std::move(attribute));
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, std::move(attribute));
|
||||
default:
|
||||
|
@ -680,14 +680,14 @@ ReadAttributePtr MeshComponent::attribute_try_adapt_domain(ReadAttributePtr attr
|
|||
}
|
||||
break;
|
||||
}
|
||||
case ATTR_DOMAIN_POLYGON: {
|
||||
case ATTR_DOMAIN_FACE: {
|
||||
switch (new_domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return blender::bke::adapt_mesh_domain_polygon_to_point(*mesh_, std::move(attribute));
|
||||
return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, std::move(attribute));
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return blender::bke::adapt_mesh_domain_polygon_to_corner(*mesh_, std::move(attribute));
|
||||
return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, std::move(attribute));
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return blender::bke::adapt_mesh_domain_polygon_to_edge(*mesh_, std::move(attribute));
|
||||
return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, std::move(attribute));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -699,8 +699,8 @@ ReadAttributePtr MeshComponent::attribute_try_adapt_domain(ReadAttributePtr attr
|
|||
return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, std::move(attribute));
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, std::move(attribute));
|
||||
case ATTR_DOMAIN_POLYGON:
|
||||
return blender::bke::adapt_mesh_domain_edge_to_polygon(*mesh_, std::move(attribute));
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, std::move(attribute));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -774,14 +774,14 @@ static void set_material_index(MPoly &mpoly, const int &index)
|
|||
static ReadAttributePtr make_material_index_read_attribute(const void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<DerivedArrayReadAttribute<MPoly, int, get_material_index>>(
|
||||
ATTR_DOMAIN_POLYGON, Span<MPoly>((const MPoly *)data, domain_size));
|
||||
ATTR_DOMAIN_FACE, Span<MPoly>((const MPoly *)data, domain_size));
|
||||
}
|
||||
|
||||
static WriteAttributePtr make_material_index_write_attribute(void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<
|
||||
DerivedArrayWriteAttribute<MPoly, int, get_material_index, set_material_index>>(
|
||||
ATTR_DOMAIN_POLYGON, MutableSpan<MPoly>((MPoly *)data, domain_size));
|
||||
ATTR_DOMAIN_FACE, MutableSpan<MPoly>((MPoly *)data, domain_size));
|
||||
}
|
||||
|
||||
static bool get_shade_smooth(const MPoly &mpoly)
|
||||
|
@ -797,14 +797,14 @@ static void set_shade_smooth(MPoly &mpoly, const bool &value)
|
|||
static ReadAttributePtr make_shade_smooth_read_attribute(const void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<DerivedArrayReadAttribute<MPoly, bool, get_shade_smooth>>(
|
||||
ATTR_DOMAIN_POLYGON, Span<MPoly>((const MPoly *)data, domain_size));
|
||||
ATTR_DOMAIN_FACE, Span<MPoly>((const MPoly *)data, domain_size));
|
||||
}
|
||||
|
||||
static WriteAttributePtr make_shade_smooth_write_attribute(void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<
|
||||
DerivedArrayWriteAttribute<MPoly, bool, get_shade_smooth, set_shade_smooth>>(
|
||||
ATTR_DOMAIN_POLYGON, MutableSpan<MPoly>((MPoly *)data, domain_size));
|
||||
ATTR_DOMAIN_FACE, MutableSpan<MPoly>((MPoly *)data, domain_size));
|
||||
}
|
||||
|
||||
static float2 get_loop_uv(const MLoopUV &uv)
|
||||
|
@ -1045,7 +1045,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
|
|||
public:
|
||||
NormalAttributeProvider()
|
||||
: BuiltinAttributeProvider(
|
||||
"normal", ATTR_DOMAIN_POLYGON, CD_PROP_FLOAT3, NonCreatable, Readonly, NonDeletable)
|
||||
"normal", ATTR_DOMAIN_FACE, CD_PROP_FLOAT3, NonCreatable, Readonly, NonDeletable)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1063,7 +1063,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
|
|||
const void *data = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
|
||||
|
||||
return std::make_unique<ArrayReadAttribute<float3>>(
|
||||
ATTR_DOMAIN_POLYGON, Span<float3>((const float3 *)data, mesh->totpoly));
|
||||
ATTR_DOMAIN_FACE, Span<float3>((const float3 *)data, mesh->totpoly));
|
||||
}
|
||||
|
||||
Array<float3> normals(mesh->totpoly);
|
||||
|
@ -1072,8 +1072,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
|
|||
BKE_mesh_calc_poly_normal(poly, &mesh->mloop[poly->loopstart], mesh->mvert, normals[i]);
|
||||
}
|
||||
|
||||
return std::make_unique<OwnedArrayReadAttribute<float3>>(ATTR_DOMAIN_POLYGON,
|
||||
std::move(normals));
|
||||
return std::make_unique<OwnedArrayReadAttribute<float3>>(ATTR_DOMAIN_FACE, std::move(normals));
|
||||
}
|
||||
|
||||
WriteAttributePtr try_get_for_write(GeometryComponent &UNUSED(component)) const final
|
||||
|
@ -1093,7 +1092,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
|
|||
|
||||
bool exists(const GeometryComponent &component) const final
|
||||
{
|
||||
return component.attribute_domain_size(ATTR_DOMAIN_POLYGON) != 0;
|
||||
return component.attribute_domain_size(ATTR_DOMAIN_FACE) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1130,9 +1129,9 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
|
|||
static CustomDataAccessInfo edge_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(edata),
|
||||
MAKE_CONST_CUSTOM_DATA_GETTER(edata),
|
||||
update_custom_data_pointers};
|
||||
static CustomDataAccessInfo polygon_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(pdata),
|
||||
MAKE_CONST_CUSTOM_DATA_GETTER(pdata),
|
||||
update_custom_data_pointers};
|
||||
static CustomDataAccessInfo face_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(pdata),
|
||||
MAKE_CONST_CUSTOM_DATA_GETTER(pdata),
|
||||
update_custom_data_pointers};
|
||||
|
||||
#undef MAKE_CONST_CUSTOM_DATA_GETTER
|
||||
#undef MAKE_MUTABLE_CUSTOM_DATA_GETTER
|
||||
|
@ -1152,25 +1151,25 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
|
|||
static NormalAttributeProvider normal;
|
||||
|
||||
static BuiltinCustomDataLayerProvider material_index("material_index",
|
||||
ATTR_DOMAIN_POLYGON,
|
||||
ATTR_DOMAIN_FACE,
|
||||
CD_PROP_INT32,
|
||||
CD_MPOLY,
|
||||
BuiltinAttributeProvider::NonCreatable,
|
||||
BuiltinAttributeProvider::Writable,
|
||||
BuiltinAttributeProvider::NonDeletable,
|
||||
polygon_access,
|
||||
face_access,
|
||||
make_material_index_read_attribute,
|
||||
make_material_index_write_attribute,
|
||||
nullptr);
|
||||
|
||||
static BuiltinCustomDataLayerProvider shade_smooth("shade_smooth",
|
||||
ATTR_DOMAIN_POLYGON,
|
||||
ATTR_DOMAIN_FACE,
|
||||
CD_PROP_BOOL,
|
||||
CD_MPOLY,
|
||||
BuiltinAttributeProvider::NonCreatable,
|
||||
BuiltinAttributeProvider::Writable,
|
||||
BuiltinAttributeProvider::NonDeletable,
|
||||
polygon_access,
|
||||
face_access,
|
||||
make_shade_smooth_read_attribute,
|
||||
make_shade_smooth_write_attribute,
|
||||
nullptr);
|
||||
|
@ -1205,7 +1204,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
|
|||
static CustomDataAttributeProvider corner_custom_data(ATTR_DOMAIN_CORNER, corner_access);
|
||||
static CustomDataAttributeProvider point_custom_data(ATTR_DOMAIN_POINT, point_access);
|
||||
static CustomDataAttributeProvider edge_custom_data(ATTR_DOMAIN_EDGE, edge_access);
|
||||
static CustomDataAttributeProvider polygon_custom_data(ATTR_DOMAIN_POLYGON, polygon_access);
|
||||
static CustomDataAttributeProvider face_custom_data(ATTR_DOMAIN_FACE, face_access);
|
||||
|
||||
return ComponentAttributeProviders({&position, &material_index, &shade_smooth, &normal, &crease},
|
||||
{&uvs,
|
||||
|
@ -1214,7 +1213,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
|
|||
&vertex_groups,
|
||||
&point_custom_data,
|
||||
&edge_custom_data,
|
||||
&polygon_custom_data});
|
||||
&face_custom_data});
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -153,16 +153,13 @@ static void geometry_set_collect_recursive(const GeometrySet &geometry_set,
|
|||
*
|
||||
* \note This doesn't extract instances from the "dupli" system for non-geometry-nodes instances.
|
||||
*/
|
||||
Vector<GeometryInstanceGroup> geometry_set_gather_instances(const GeometrySet &geometry_set)
|
||||
void geometry_set_gather_instances(const GeometrySet &geometry_set,
|
||||
Vector<GeometryInstanceGroup> &r_instance_groups)
|
||||
{
|
||||
Vector<GeometryInstanceGroup> result_vector;
|
||||
|
||||
float4x4 unit_transform;
|
||||
unit_m4(unit_transform.values);
|
||||
|
||||
geometry_set_collect_recursive(geometry_set, unit_transform, result_vector);
|
||||
|
||||
return result_vector;
|
||||
geometry_set_collect_recursive(geometry_set, unit_transform, r_instance_groups);
|
||||
}
|
||||
|
||||
void gather_attribute_info(Map<std::string, AttributeKind> &attributes,
|
||||
|
@ -436,7 +433,8 @@ GeometrySet geometry_set_realize_mesh_for_modifier(const GeometrySet &geometry_s
|
|||
}
|
||||
|
||||
GeometrySet new_geometry_set = geometry_set;
|
||||
Vector<GeometryInstanceGroup> set_groups = geometry_set_gather_instances(geometry_set);
|
||||
Vector<GeometryInstanceGroup> set_groups;
|
||||
geometry_set_gather_instances(geometry_set, set_groups);
|
||||
join_instance_groups_mesh(set_groups, true, new_geometry_set);
|
||||
/* Remove all instances, even though some might contain other non-mesh data. We can't really
|
||||
* keep only non-mesh instances in general. */
|
||||
|
@ -454,7 +452,8 @@ GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)
|
|||
|
||||
GeometrySet new_geometry_set;
|
||||
|
||||
Vector<GeometryInstanceGroup> set_groups = geometry_set_gather_instances(geometry_set);
|
||||
Vector<GeometryInstanceGroup> set_groups;
|
||||
geometry_set_gather_instances(geometry_set, set_groups);
|
||||
join_instance_groups_mesh(set_groups, false, new_geometry_set);
|
||||
join_instance_groups_pointcloud(set_groups, new_geometry_set);
|
||||
join_instance_groups_volume(set_groups, new_geometry_set);
|
||||
|
|
|
@ -3663,7 +3663,7 @@ static int generate_perimeter_cap(const float point[4],
|
|||
|
||||
/**
|
||||
* Calculate the perimeter (outline) of a stroke as list of tPerimeterPoint.
|
||||
* \param subdivisions: Number of subdivions for the start and end caps
|
||||
* \param subdivisions: Number of subdivisions for the start and end caps
|
||||
* \return: list of tPerimeterPoint
|
||||
*/
|
||||
static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd,
|
||||
|
@ -3710,7 +3710,7 @@ static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd,
|
|||
copy_v3_v3(first_next_pt, &first_next->x);
|
||||
copy_v3_v3(last_prev_pt, &last_prev->x);
|
||||
|
||||
/* edgecase if single point */
|
||||
/* Edge-case if single point. */
|
||||
if (gps->totpoints == 1) {
|
||||
first_next_pt[0] += 1.0f;
|
||||
last_prev_pt[0] -= 1.0f;
|
||||
|
@ -3784,7 +3784,7 @@ static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd,
|
|||
negate_v2(vec_miter_right);
|
||||
|
||||
float angle = dot_v2v2(vec_next, nvec_prev);
|
||||
/* add two points if angle is close to beeing straight */
|
||||
/* Add two points if angle is close to being straight. */
|
||||
if (fabsf(angle) < 0.0001f) {
|
||||
normalize_v2_length(nvec_prev, radius);
|
||||
normalize_v2_length(nvec_next, radius);
|
||||
|
@ -3910,7 +3910,7 @@ static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd,
|
|||
/**
|
||||
* Calculates the perimeter of a stroke projected from the view and
|
||||
* returns it as a new stroke.
|
||||
* \param subdivisions: Number of subdivions for the start and end caps
|
||||
* \param subdivisions: Number of subdivisions for the start and end caps
|
||||
* \return: bGPDstroke pointer to stroke perimeter
|
||||
*/
|
||||
bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
|
||||
|
|
|
@ -437,6 +437,10 @@ static bool lib_override_hierarchy_dependencies_recursive_tag(LibOverrideGroupTa
|
|||
}
|
||||
/* We only consider IDs from the same library. */
|
||||
ID *to_id = *to_id_entry->id_pointer.to;
|
||||
if (!ID_IS_LINKED(to_id) && !ID_IS_OVERRIDE_LIBRARY(to_id)) {
|
||||
/* Pure local data is a barrier of dependency in override cases. */
|
||||
continue;
|
||||
}
|
||||
if (to_id != NULL && to_id->lib == id->lib) {
|
||||
LibOverrideGroupTagData sub_data = *data;
|
||||
sub_data.id_root = to_id;
|
||||
|
@ -812,6 +816,9 @@ bool BKE_lib_override_library_create(
|
|||
BKE_main_id_clear_newpoins(bmain);
|
||||
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
|
||||
|
||||
/* We need to rebuild some of the deleted override rules (for UI feedback purpose). */
|
||||
BKE_lib_override_library_main_operations_create(bmain, true);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
|
@ -1364,7 +1364,9 @@ GHashIterator *nodeSocketTypeGetIterator(void)
|
|||
return BLI_ghashIterator_new(nodesockettypes_hash);
|
||||
}
|
||||
|
||||
struct bNodeSocket *nodeFindSocket(const bNode *node, int in_out, const char *identifier)
|
||||
struct bNodeSocket *nodeFindSocket(const bNode *node,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *identifier)
|
||||
{
|
||||
const ListBase *sockets = (in_out == SOCK_IN) ? &node->inputs : &node->outputs;
|
||||
LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
|
||||
|
@ -1521,7 +1523,7 @@ void nodeModifySocketType(
|
|||
|
||||
bNodeSocket *nodeAddSocket(bNodeTree *ntree,
|
||||
bNode *node,
|
||||
int in_out,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *idname,
|
||||
const char *identifier,
|
||||
const char *name)
|
||||
|
@ -1543,7 +1545,7 @@ bNodeSocket *nodeAddSocket(bNodeTree *ntree,
|
|||
|
||||
bNodeSocket *nodeInsertSocket(bNodeTree *ntree,
|
||||
bNode *node,
|
||||
int in_out,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *idname,
|
||||
bNodeSocket *next_sock,
|
||||
const char *identifier,
|
||||
|
@ -1704,7 +1706,7 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype)
|
|||
|
||||
bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree,
|
||||
bNode *node,
|
||||
int in_out,
|
||||
eNodeSocketInOut in_out,
|
||||
int type,
|
||||
int subtype,
|
||||
const char *identifier,
|
||||
|
@ -1724,7 +1726,7 @@ bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree,
|
|||
|
||||
bNodeSocket *nodeInsertStaticSocket(bNodeTree *ntree,
|
||||
bNode *node,
|
||||
int in_out,
|
||||
eNodeSocketInOut in_out,
|
||||
int type,
|
||||
int subtype,
|
||||
bNodeSocket *next_sock,
|
||||
|
@ -3220,7 +3222,7 @@ void ntreeLocalMerge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree)
|
|||
/* ************ NODE TREE INTERFACE *************** */
|
||||
|
||||
static bNodeSocket *make_socket_interface(bNodeTree *ntree,
|
||||
int in_out,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *idname,
|
||||
const char *name)
|
||||
{
|
||||
|
@ -3256,7 +3258,9 @@ static bNodeSocket *make_socket_interface(bNodeTree *ntree,
|
|||
return sock;
|
||||
}
|
||||
|
||||
bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree, int in_out, const char *identifier)
|
||||
bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *identifier)
|
||||
{
|
||||
ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs;
|
||||
LISTBASE_FOREACH (bNodeSocket *, iosock, sockets) {
|
||||
|
@ -3268,7 +3272,7 @@ bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree, int in_out, const char *
|
|||
}
|
||||
|
||||
bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree,
|
||||
int in_out,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *idname,
|
||||
const char *name)
|
||||
{
|
||||
|
@ -3284,8 +3288,11 @@ bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree,
|
|||
return iosock;
|
||||
}
|
||||
|
||||
bNodeSocket *ntreeInsertSocketInterface(
|
||||
bNodeTree *ntree, int in_out, const char *idname, bNodeSocket *next_sock, const char *name)
|
||||
bNodeSocket *ntreeInsertSocketInterface(bNodeTree *ntree,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *idname,
|
||||
bNodeSocket *next_sock,
|
||||
const char *name)
|
||||
{
|
||||
bNodeSocket *iosock = make_socket_interface(ntree, in_out, idname, name);
|
||||
if (in_out == SOCK_IN) {
|
||||
|
@ -3304,7 +3311,7 @@ struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(bNodeTree *ntree,
|
|||
bNodeSocket *from_sock)
|
||||
{
|
||||
bNodeSocket *iosock = ntreeAddSocketInterface(
|
||||
ntree, from_sock->in_out, from_sock->idname, from_sock->name);
|
||||
ntree, static_cast<eNodeSocketInOut>(from_sock->in_out), from_sock->idname, from_sock->name);
|
||||
if (iosock) {
|
||||
if (iosock->typeinfo->interface_from_socket) {
|
||||
iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
|
||||
|
@ -3319,7 +3326,11 @@ struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(bNodeTree *ntree,
|
|||
bNodeSocket *from_sock)
|
||||
{
|
||||
bNodeSocket *iosock = ntreeInsertSocketInterface(
|
||||
ntree, from_sock->in_out, from_sock->idname, next_sock, from_sock->name);
|
||||
ntree,
|
||||
static_cast<eNodeSocketInOut>(from_sock->in_out),
|
||||
from_sock->idname,
|
||||
next_sock,
|
||||
from_sock->name);
|
||||
if (iosock) {
|
||||
if (iosock->typeinfo->interface_from_socket) {
|
||||
iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
|
||||
|
@ -4903,11 +4914,13 @@ static void registerGeometryNodes()
|
|||
register_node_type_geo_group();
|
||||
|
||||
register_node_type_geo_align_rotation_to_vector();
|
||||
register_node_type_geo_attribute_clamp();
|
||||
register_node_type_geo_attribute_color_ramp();
|
||||
register_node_type_geo_attribute_combine_xyz();
|
||||
register_node_type_geo_attribute_compare();
|
||||
register_node_type_geo_attribute_convert();
|
||||
register_node_type_geo_attribute_fill();
|
||||
register_node_type_geo_attribute_map_range();
|
||||
register_node_type_geo_attribute_math();
|
||||
register_node_type_geo_attribute_mix();
|
||||
register_node_type_geo_attribute_proximity();
|
||||
|
@ -4924,9 +4937,9 @@ static void registerGeometryNodes()
|
|||
register_node_type_geo_mesh_primitive_cone();
|
||||
register_node_type_geo_mesh_primitive_cube();
|
||||
register_node_type_geo_mesh_primitive_cylinder();
|
||||
register_node_type_geo_mesh_primitive_grid();
|
||||
register_node_type_geo_mesh_primitive_ico_sphere();
|
||||
register_node_type_geo_mesh_primitive_line();
|
||||
register_node_type_geo_mesh_primitive_plane();
|
||||
register_node_type_geo_mesh_primitive_uv_sphere();
|
||||
register_node_type_geo_object_info();
|
||||
register_node_type_geo_point_distribute();
|
||||
|
|
|
@ -567,9 +567,6 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
/* Set up the codec context */
|
||||
|
||||
c = st->codec;
|
||||
c->thread_count = BLI_system_thread_count();
|
||||
c->thread_type = FF_THREAD_SLICE;
|
||||
|
||||
c->codec_id = codec_id;
|
||||
c->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||
|
||||
|
@ -727,6 +724,20 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
|
||||
set_ffmpeg_properties(rd, c, "video", &opts);
|
||||
|
||||
if (codec->capabilities & AV_CODEC_CAP_AUTO_THREADS) {
|
||||
c->thread_count = 0;
|
||||
}
|
||||
else {
|
||||
c->thread_count = BLI_system_thread_count();
|
||||
}
|
||||
|
||||
if (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
|
||||
c->thread_type = FF_THREAD_FRAME;
|
||||
}
|
||||
else if (codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
|
||||
c->thread_type = FF_THREAD_SLICE;
|
||||
}
|
||||
|
||||
if (avcodec_open2(c, codec, &opts) < 0) {
|
||||
BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
|
||||
av_dict_free(&opts);
|
||||
|
|
|
@ -206,19 +206,38 @@ template<typename T> struct DefaultHash<T *> {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T> uint64_t get_default_hash(const T &v)
|
||||
{
|
||||
return DefaultHash<T>{}(v);
|
||||
}
|
||||
|
||||
template<typename T1, typename T2> uint64_t get_default_hash_2(const T1 &v1, const T2 &v2)
|
||||
{
|
||||
const uint64_t h1 = get_default_hash(v1);
|
||||
const uint64_t h2 = get_default_hash(v2);
|
||||
return h1 ^ (h2 * 19349669);
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
uint64_t get_default_hash_3(const T1 &v1, const T2 &v2, const T3 &v3)
|
||||
{
|
||||
const uint64_t h1 = get_default_hash(v1);
|
||||
const uint64_t h2 = get_default_hash(v2);
|
||||
const uint64_t h3 = get_default_hash(v3);
|
||||
return h1 ^ (h2 * 19349669) ^ (h3 * 83492791);
|
||||
}
|
||||
|
||||
template<typename T> struct DefaultHash<std::unique_ptr<T>> {
|
||||
uint64_t operator()(const std::unique_ptr<T> &value) const
|
||||
{
|
||||
return DefaultHash<T *>{}(value.get());
|
||||
return get_default_hash(value.get());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T1, typename T2> struct DefaultHash<std::pair<T1, T2>> {
|
||||
uint64_t operator()(const std::pair<T1, T2> &value) const
|
||||
{
|
||||
uint64_t hash1 = DefaultHash<T1>{}(value.first);
|
||||
uint64_t hash2 = DefaultHash<T2>{}(value.second);
|
||||
return hash1 ^ (hash2 * 33);
|
||||
return get_default_hash_2(value.first, value.second);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -788,6 +788,8 @@ class Set {
|
|||
template<typename ForwardKey>
|
||||
const Key &lookup_key_or_add__impl(ForwardKey &&key, const uint64_t hash)
|
||||
{
|
||||
this->ensure_can_add();
|
||||
|
||||
SET_SLOT_PROBING_BEGIN (hash, slot) {
|
||||
if (slot.contains(key, is_equal_, hash)) {
|
||||
return *slot.key();
|
||||
|
|
|
@ -125,7 +125,7 @@ template<typename T> class UserCounter {
|
|||
|
||||
uint64_t hash() const
|
||||
{
|
||||
return DefaultHash<T *>{}(data_);
|
||||
return get_default_hash(data_);
|
||||
}
|
||||
|
||||
friend bool operator==(const UserCounter &a, const UserCounter &b)
|
||||
|
|
|
@ -263,6 +263,7 @@ set(SRC
|
|||
BLI_session_uuid.h
|
||||
BLI_set.hh
|
||||
BLI_set_slots.hh
|
||||
BLI_simd.h
|
||||
BLI_smallhash.h
|
||||
BLI_sort.h
|
||||
BLI_sort_utils.h
|
||||
|
|
|
@ -173,7 +173,7 @@ mpq3 mpq3::cross_poly(Span<mpq3> poly)
|
|||
uint64_t hash_mpq_class(const mpq_class &value)
|
||||
{
|
||||
/* TODO: better/faster implementation of this. */
|
||||
return DefaultHash<float>{}(static_cast<float>(value.get_d()));
|
||||
return get_default_hash(static_cast<float>(value.get_d()));
|
||||
}
|
||||
|
||||
uint64_t mpq2::hash() const
|
||||
|
|
|
@ -97,10 +97,7 @@ class Edge {
|
|||
|
||||
uint64_t hash() const
|
||||
{
|
||||
constexpr uint64_t h1 = 33;
|
||||
uint64_t v0hash = DefaultHash<int>{}(v_[0]->id);
|
||||
uint64_t v1hash = DefaultHash<int>{}(v_[1]->id);
|
||||
return v0hash ^ (v1hash * h1);
|
||||
return get_default_hash_2(v_[0]->id, v_[1]->id);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -456,8 +456,8 @@ TEST(set, LookupKeyPtr)
|
|||
TEST(set, LookupKeyOrAdd)
|
||||
{
|
||||
Set<MyKeyType> set;
|
||||
set.add({1, 10});
|
||||
set.add({2, 20});
|
||||
set.lookup_key_or_add({1, 10});
|
||||
set.lookup_key_or_add({2, 20});
|
||||
EXPECT_EQ(set.size(), 2);
|
||||
EXPECT_EQ(set.lookup_key_or_add({2, 40}).attached_data, 20);
|
||||
EXPECT_EQ(set.size(), 2);
|
||||
|
|
|
@ -2497,9 +2497,12 @@ static void direct_link_id_common(
|
|||
/* Link direct data of overrides. */
|
||||
if (id->override_library) {
|
||||
BLO_read_data_address(reader, &id->override_library);
|
||||
BLO_read_list_cb(
|
||||
reader, &id->override_library->properties, direct_link_id_override_property_cb);
|
||||
id->override_library->runtime = NULL;
|
||||
/* Work around file corruption on writing, see T86853. */
|
||||
if (id->override_library != NULL) {
|
||||
BLO_read_list_cb(
|
||||
reader, &id->override_library->properties, direct_link_id_override_property_cb);
|
||||
id->override_library->runtime = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
|
||||
|
|
|
@ -1926,6 +1926,18 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 293, 15)) {
|
||||
LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
|
||||
if (ntree->type == NTREE_GEOMETRY) {
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (STREQ(node->idname, "GeometryNodeMeshPlane")) {
|
||||
STRNCPY(node->idname, "GeometryNodeMeshGrid");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
|
|
|
@ -261,17 +261,7 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
|
|||
FROM_DEFAULT_V4_UCHAR(space_node.nodeclass_shader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
* \note Be sure to check when bumping the version:
|
||||
* - #blo_do_versions_userdef in this file.
|
||||
* - "versioning_{BLENDER_VERSION}.c"
|
||||
*
|
||||
* \note Keep this message at the bottom of the function.
|
||||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
if (!USER_VERSION_ATLEAST(293, 15)) {
|
||||
FROM_DEFAULT_V4_UCHAR(space_properties.active);
|
||||
|
||||
FROM_DEFAULT_V4_UCHAR(space_info.info_error);
|
||||
|
@ -286,6 +276,19 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
|
|||
btheme->space_spreadsheet = btheme->space_outliner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
* \note Be sure to check when bumping the version:
|
||||
* - #blo_do_versions_userdef in this file.
|
||||
* - "versioning_{BLENDER_VERSION}.c"
|
||||
*
|
||||
* \note Keep this message at the bottom of the function.
|
||||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
}
|
||||
|
||||
#undef FROM_DEFAULT_V4_UCHAR
|
||||
|
||||
#undef USER_VERSION_ATLEAST
|
||||
|
|
|
@ -87,8 +87,6 @@ set(SRC
|
|||
intern/COM_OpenCLDevice.h
|
||||
intern/COM_SingleThreadedOperation.cc
|
||||
intern/COM_SingleThreadedOperation.h
|
||||
intern/COM_SocketReader.cc
|
||||
intern/COM_SocketReader.h
|
||||
intern/COM_WorkPackage.cc
|
||||
intern/COM_WorkPackage.h
|
||||
intern/COM_WorkScheduler.cc
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "COM_defines.h"
|
||||
#include <cstdio>
|
||||
|
||||
#include "BLI_assert.h"
|
||||
|
||||
CompositorContext::CompositorContext()
|
||||
{
|
||||
this->m_scene = nullptr;
|
||||
|
@ -33,9 +35,6 @@ CompositorContext::CompositorContext()
|
|||
|
||||
int CompositorContext::getFramenumber() const
|
||||
{
|
||||
if (this->m_rd) {
|
||||
return this->m_rd->cfra;
|
||||
}
|
||||
|
||||
return -1; /* this should never happen */
|
||||
BLI_assert(m_rd);
|
||||
return m_rd->cfra;
|
||||
}
|
||||
|
|
|
@ -454,7 +454,7 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
|
|||
NodeOperationOutput *fromSocket,
|
||||
NodeOperationInput *toSocket)
|
||||
{
|
||||
InputResizeMode mode = toSocket->getResizeMode();
|
||||
ResizeMode mode = toSocket->getResizeMode();
|
||||
|
||||
NodeOperation *toOperation = &toSocket->getOperation();
|
||||
const float toWidth = toOperation->getWidth();
|
||||
|
@ -470,22 +470,22 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
|
|||
float scaleY = 0;
|
||||
|
||||
switch (mode) {
|
||||
case COM_SC_NO_RESIZE:
|
||||
case ResizeMode::None:
|
||||
break;
|
||||
case COM_SC_CENTER:
|
||||
case ResizeMode::Center:
|
||||
doCenter = true;
|
||||
break;
|
||||
case COM_SC_FIT_WIDTH:
|
||||
case ResizeMode::FitWidth:
|
||||
doCenter = true;
|
||||
doScale = true;
|
||||
scaleX = scaleY = toWidth / fromWidth;
|
||||
break;
|
||||
case COM_SC_FIT_HEIGHT:
|
||||
case ResizeMode::FitHeight:
|
||||
doCenter = true;
|
||||
doScale = true;
|
||||
scaleX = scaleY = toHeight / fromHeight;
|
||||
break;
|
||||
case COM_SC_FIT:
|
||||
case ResizeMode::FitAny:
|
||||
doCenter = true;
|
||||
doScale = true;
|
||||
scaleX = toWidth / fromWidth;
|
||||
|
@ -497,7 +497,7 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
|
|||
scaleY = scaleX;
|
||||
}
|
||||
break;
|
||||
case COM_SC_STRETCH:
|
||||
case ResizeMode::Stretch:
|
||||
doCenter = true;
|
||||
doScale = true;
|
||||
scaleX = toWidth / fromWidth;
|
||||
|
@ -510,8 +510,8 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
|
|||
ScaleOperation *scaleOperation = nullptr;
|
||||
if (doScale) {
|
||||
scaleOperation = new ScaleOperation();
|
||||
scaleOperation->getInputSocket(1)->setResizeMode(COM_SC_NO_RESIZE);
|
||||
scaleOperation->getInputSocket(2)->setResizeMode(COM_SC_NO_RESIZE);
|
||||
scaleOperation->getInputSocket(1)->setResizeMode(ResizeMode::None);
|
||||
scaleOperation->getInputSocket(2)->setResizeMode(ResizeMode::None);
|
||||
first = scaleOperation;
|
||||
SetValueOperation *sxop = new SetValueOperation();
|
||||
sxop->setValue(scaleX);
|
||||
|
@ -530,8 +530,8 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
|
|||
}
|
||||
|
||||
TranslateOperation *translateOperation = new TranslateOperation();
|
||||
translateOperation->getInputSocket(1)->setResizeMode(COM_SC_NO_RESIZE);
|
||||
translateOperation->getInputSocket(2)->setResizeMode(COM_SC_NO_RESIZE);
|
||||
translateOperation->getInputSocket(1)->setResizeMode(ResizeMode::None);
|
||||
translateOperation->getInputSocket(2)->setResizeMode(ResizeMode::None);
|
||||
if (!first) {
|
||||
first = translateOperation;
|
||||
}
|
||||
|
@ -551,14 +551,14 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
|
|||
builder.addOperation(translateOperation);
|
||||
|
||||
if (doScale) {
|
||||
translateOperation->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
|
||||
translateOperation->getInputSocket(0)->setResizeMode(ResizeMode::None);
|
||||
builder.addLink(scaleOperation->getOutputSocket(), translateOperation->getInputSocket(0));
|
||||
}
|
||||
|
||||
/* remove previous link and replace */
|
||||
builder.removeInputLink(toSocket);
|
||||
first->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
|
||||
toSocket->setResizeMode(COM_SC_NO_RESIZE);
|
||||
first->getInputSocket(0)->setResizeMode(ResizeMode::None);
|
||||
toSocket->setResizeMode(ResizeMode::None);
|
||||
builder.addLink(fromSocket, first->getInputSocket(0));
|
||||
builder.addLink(translateOperation->getOutputSocket(), toSocket);
|
||||
}
|
||||
|
|
|
@ -70,17 +70,17 @@ class ExecutionGroup;
|
|||
*
|
||||
* - Image size conversions: the system can automatically convert when resolutions do not match.
|
||||
* An NodeInput has a resize mode. This can be any of the following settings.
|
||||
* - [@ref InputSocketResizeMode.COM_SC_CENTER]:
|
||||
* - [@ref InputSocketResizeMode.ResizeMode::Center]:
|
||||
* The center of both images are aligned
|
||||
* - [@ref InputSocketResizeMode.COM_SC_FIT_WIDTH]:
|
||||
* - [@ref InputSocketResizeMode.ResizeMode::FitWidth]:
|
||||
* The width of both images are aligned
|
||||
* - [@ref InputSocketResizeMode.COM_SC_FIT_HEIGHT]:
|
||||
* - [@ref InputSocketResizeMode.ResizeMode::FitHeight]:
|
||||
* The height of both images are aligned
|
||||
* - [@ref InputSocketResizeMode.COM_SC_FIT]:
|
||||
* - [@ref InputSocketResizeMode.ResizeMode::FitAny]:
|
||||
* The width, or the height of both images are aligned to make sure that it fits.
|
||||
* - [@ref InputSocketResizeMode.COM_SC_STRETCH]:
|
||||
* - [@ref InputSocketResizeMode.ResizeMode::Stretch]:
|
||||
* The width and the height of both images are aligned.
|
||||
* - [@ref InputSocketResizeMode.COM_SC_NO_RESIZE]:
|
||||
* - [@ref InputSocketResizeMode.ResizeMode::None]:
|
||||
* Bottom left of the images are aligned.
|
||||
*
|
||||
* \see COM_convert_data_type Datatype conversions
|
||||
|
|
|
@ -22,7 +22,6 @@ class MemoryBuffer;
|
|||
|
||||
#include "COM_ExecutionGroup.h"
|
||||
#include "COM_MemoryProxy.h"
|
||||
#include "COM_SocketReader.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_rect.h"
|
||||
|
|
|
@ -83,7 +83,7 @@ void NodeGraph::add_node(Node *node,
|
|||
node->setInstanceKey(key);
|
||||
node->setIsInActiveGroup(is_active_group);
|
||||
|
||||
m_nodes.push_back(node);
|
||||
m_nodes.append(node);
|
||||
|
||||
DebugInfo::node_added(node);
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ void NodeGraph::add_bNode(const CompositorContext &context,
|
|||
NodeGraph::NodeInputs NodeGraph::find_inputs(const NodeRange &node_range, bNodeSocket *b_socket)
|
||||
{
|
||||
NodeInputs result;
|
||||
for (NodeGraph::NodeIterator it = node_range.first; it != node_range.second; ++it) {
|
||||
for (blender::Vector<Node *>::iterator it = node_range.first; it != node_range.second; ++it) {
|
||||
Node *node = *it;
|
||||
for (int index = 0; index < node->getNumberOfInputSockets(); index++) {
|
||||
NodeInput *input = node->getInputSocket(index);
|
||||
|
@ -170,7 +170,7 @@ NodeGraph::NodeInputs NodeGraph::find_inputs(const NodeRange &node_range, bNodeS
|
|||
|
||||
NodeOutput *NodeGraph::find_output(const NodeRange &node_range, bNodeSocket *b_socket)
|
||||
{
|
||||
for (NodeGraph::NodeIterator it = node_range.first; it != node_range.second; ++it) {
|
||||
for (blender::Vector<Node *>::iterator it = node_range.first; it != node_range.second; ++it) {
|
||||
Node *node = *it;
|
||||
for (int index = 0; index < node->getNumberOfOutputSockets(); index++) {
|
||||
NodeOutput *output = node->getOutputSocket(index);
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
|
@ -50,18 +49,15 @@ class NodeGraph {
|
|||
}
|
||||
};
|
||||
|
||||
typedef std::vector<Node *> Nodes;
|
||||
typedef Nodes::iterator NodeIterator;
|
||||
|
||||
private:
|
||||
Nodes m_nodes;
|
||||
blender::Vector<Node *> m_nodes;
|
||||
blender::Vector<Link> m_links;
|
||||
|
||||
public:
|
||||
NodeGraph();
|
||||
~NodeGraph();
|
||||
|
||||
const Nodes &nodes() const
|
||||
const blender::Vector<Node *> &nodes() const
|
||||
{
|
||||
return m_nodes;
|
||||
}
|
||||
|
@ -73,7 +69,8 @@ class NodeGraph {
|
|||
void from_bNodeTree(const CompositorContext &context, bNodeTree *tree);
|
||||
|
||||
protected:
|
||||
typedef std::pair<NodeIterator, NodeIterator> NodeRange;
|
||||
typedef std::pair<blender::Vector<Node *>::iterator, blender::Vector<Node *>::iterator>
|
||||
NodeRange;
|
||||
typedef std::vector<NodeInput *> NodeInputs;
|
||||
|
||||
static bNodeSocket *find_b_node_input(bNode *b_node, const char *identifier);
|
||||
|
|
|
@ -39,68 +39,47 @@ NodeOperation::NodeOperation()
|
|||
this->m_btree = nullptr;
|
||||
}
|
||||
|
||||
NodeOperation::~NodeOperation()
|
||||
NodeOperationOutput *NodeOperation::getOutputSocket(unsigned int index)
|
||||
{
|
||||
while (!this->m_outputs.empty()) {
|
||||
delete (this->m_outputs.back());
|
||||
this->m_outputs.pop_back();
|
||||
}
|
||||
while (!this->m_inputs.empty()) {
|
||||
delete (this->m_inputs.back());
|
||||
this->m_inputs.pop_back();
|
||||
}
|
||||
return &m_outputs[index];
|
||||
}
|
||||
|
||||
NodeOperationOutput *NodeOperation::getOutputSocket(unsigned int index) const
|
||||
NodeOperationInput *NodeOperation::getInputSocket(unsigned int index)
|
||||
{
|
||||
BLI_assert(index < m_outputs.size());
|
||||
return m_outputs[index];
|
||||
return &m_inputs[index];
|
||||
}
|
||||
|
||||
NodeOperationInput *NodeOperation::getInputSocket(unsigned int index) const
|
||||
void NodeOperation::addInputSocket(DataType datatype, ResizeMode resize_mode)
|
||||
{
|
||||
BLI_assert(index < m_inputs.size());
|
||||
return m_inputs[index];
|
||||
}
|
||||
|
||||
void NodeOperation::addInputSocket(DataType datatype, InputResizeMode resize_mode)
|
||||
{
|
||||
NodeOperationInput *socket = new NodeOperationInput(this, datatype, resize_mode);
|
||||
m_inputs.push_back(socket);
|
||||
m_inputs.append(NodeOperationInput(this, datatype, resize_mode));
|
||||
}
|
||||
|
||||
void NodeOperation::addOutputSocket(DataType datatype)
|
||||
{
|
||||
NodeOperationOutput *socket = new NodeOperationOutput(this, datatype);
|
||||
m_outputs.push_back(socket);
|
||||
m_outputs.append(NodeOperationOutput(this, datatype));
|
||||
}
|
||||
|
||||
void NodeOperation::determineResolution(unsigned int resolution[2],
|
||||
unsigned int preferredResolution[2])
|
||||
{
|
||||
unsigned int temp[2];
|
||||
unsigned int temp2[2];
|
||||
|
||||
for (unsigned int index = 0; index < m_inputs.size(); index++) {
|
||||
NodeOperationInput *input = m_inputs[index];
|
||||
if (input->isConnected()) {
|
||||
if (index == this->m_resolutionInputSocketIndex) {
|
||||
input->determineResolution(resolution, preferredResolution);
|
||||
temp2[0] = resolution[0];
|
||||
temp2[1] = resolution[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_resolutionInputSocketIndex < m_inputs.size()) {
|
||||
NodeOperationInput &input = m_inputs[m_resolutionInputSocketIndex];
|
||||
input.determineResolution(resolution, preferredResolution);
|
||||
}
|
||||
unsigned int temp2[2] = {resolution[0], resolution[1]};
|
||||
|
||||
unsigned int temp[2];
|
||||
for (unsigned int index = 0; index < m_inputs.size(); index++) {
|
||||
NodeOperationInput *input = m_inputs[index];
|
||||
if (input->isConnected()) {
|
||||
if (index != this->m_resolutionInputSocketIndex) {
|
||||
input->determineResolution(temp, temp2);
|
||||
}
|
||||
if (index == this->m_resolutionInputSocketIndex) {
|
||||
continue;
|
||||
}
|
||||
NodeOperationInput &input = m_inputs[index];
|
||||
if (input.isConnected()) {
|
||||
input.determineResolution(temp, temp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeOperation::setResolutionInputSocketIndex(unsigned int index)
|
||||
{
|
||||
this->m_resolutionInputSocketIndex = index;
|
||||
|
@ -149,15 +128,6 @@ NodeOperation *NodeOperation::getInputOperation(unsigned int inputSocketIndex)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void NodeOperation::getConnectedInputSockets(Inputs *sockets)
|
||||
{
|
||||
for (NodeOperationInput *input : m_inputs) {
|
||||
if (input->isConnected()) {
|
||||
sockets->push_back(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NodeOperation::determineDependingAreaOfInterest(rcti *input,
|
||||
ReadBufferOperation *readOperation,
|
||||
rcti *output)
|
||||
|
@ -195,9 +165,7 @@ bool NodeOperation::determineDependingAreaOfInterest(rcti *input,
|
|||
**** OpInput ****
|
||||
*****************/
|
||||
|
||||
NodeOperationInput::NodeOperationInput(NodeOperation *op,
|
||||
DataType datatype,
|
||||
InputResizeMode resizeMode)
|
||||
NodeOperationInput::NodeOperationInput(NodeOperation *op, DataType datatype, ResizeMode resizeMode)
|
||||
: m_operation(op), m_datatype(datatype), m_resizeMode(resizeMode), m_link(nullptr)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
|
||||
#include "COM_MemoryBuffer.h"
|
||||
#include "COM_MemoryProxy.h"
|
||||
#include "COM_MetaData.h"
|
||||
#include "COM_Node.h"
|
||||
#include "COM_SocketReader.h"
|
||||
|
||||
#include "clew.h"
|
||||
|
||||
|
@ -37,32 +37,131 @@ class OpenCLDevice;
|
|||
class ReadBufferOperation;
|
||||
class WriteBufferOperation;
|
||||
|
||||
class NodeOperationInput;
|
||||
class NodeOperationOutput;
|
||||
class NodeOperation;
|
||||
typedef NodeOperation SocketReader;
|
||||
|
||||
/**
|
||||
* \brief Resize modes of inputsockets
|
||||
* How are the input and working resolutions matched
|
||||
* \ingroup Model
|
||||
*/
|
||||
typedef enum InputResizeMode {
|
||||
enum class ResizeMode {
|
||||
/** \brief Center the input image to the center of the working area of the node, no resizing
|
||||
* occurs */
|
||||
COM_SC_CENTER = NS_CR_CENTER,
|
||||
Center = NS_CR_CENTER,
|
||||
/** \brief The bottom left of the input image is the bottom left of the working area of the node,
|
||||
* no resizing occurs */
|
||||
COM_SC_NO_RESIZE = NS_CR_NONE,
|
||||
None = NS_CR_NONE,
|
||||
/** \brief Fit the width of the input image to the width of the working area of the node */
|
||||
COM_SC_FIT_WIDTH = NS_CR_FIT_WIDTH,
|
||||
FitWidth = NS_CR_FIT_WIDTH,
|
||||
/** \brief Fit the height of the input image to the height of the working area of the node */
|
||||
COM_SC_FIT_HEIGHT = NS_CR_FIT_HEIGHT,
|
||||
FitHeight = NS_CR_FIT_HEIGHT,
|
||||
/** \brief Fit the width or the height of the input image to the width or height of the working
|
||||
* area of the node, image will be larger than the working area */
|
||||
COM_SC_FIT = NS_CR_FIT,
|
||||
FitAny = NS_CR_FIT,
|
||||
/** \brief Fit the width and the height of the input image to the width and height of the working
|
||||
* area of the node, image will be equally larger than the working area */
|
||||
COM_SC_STRETCH = NS_CR_STRETCH,
|
||||
} InputResizeMode;
|
||||
Stretch = NS_CR_STRETCH,
|
||||
};
|
||||
|
||||
enum class PixelSampler {
|
||||
Nearest = 0,
|
||||
Bilinear = 1,
|
||||
Bicubic = 2,
|
||||
};
|
||||
|
||||
class NodeOperationInput {
|
||||
private:
|
||||
NodeOperation *m_operation;
|
||||
|
||||
/** Datatype of this socket. Is used for automatically data transformation.
|
||||
* \section data-conversion
|
||||
*/
|
||||
DataType m_datatype;
|
||||
|
||||
/** Resize mode of this socket */
|
||||
ResizeMode m_resizeMode;
|
||||
|
||||
/** Connected output */
|
||||
NodeOperationOutput *m_link;
|
||||
|
||||
public:
|
||||
NodeOperationInput(NodeOperation *op,
|
||||
DataType datatype,
|
||||
ResizeMode resizeMode = ResizeMode::Center);
|
||||
|
||||
NodeOperation &getOperation() const
|
||||
{
|
||||
return *m_operation;
|
||||
}
|
||||
DataType getDataType() const
|
||||
{
|
||||
return m_datatype;
|
||||
}
|
||||
|
||||
void setLink(NodeOperationOutput *link)
|
||||
{
|
||||
m_link = link;
|
||||
}
|
||||
NodeOperationOutput *getLink() const
|
||||
{
|
||||
return m_link;
|
||||
}
|
||||
bool isConnected() const
|
||||
{
|
||||
return m_link;
|
||||
}
|
||||
|
||||
void setResizeMode(ResizeMode resizeMode)
|
||||
{
|
||||
this->m_resizeMode = resizeMode;
|
||||
}
|
||||
ResizeMode getResizeMode() const
|
||||
{
|
||||
return this->m_resizeMode;
|
||||
}
|
||||
|
||||
SocketReader *getReader();
|
||||
|
||||
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
|
||||
#endif
|
||||
};
|
||||
|
||||
class NodeOperationOutput {
|
||||
private:
|
||||
NodeOperation *m_operation;
|
||||
|
||||
/** Datatype of this socket. Is used for automatically data transformation.
|
||||
* \section data-conversion
|
||||
*/
|
||||
DataType m_datatype;
|
||||
|
||||
public:
|
||||
NodeOperationOutput(NodeOperation *op, DataType datatype);
|
||||
|
||||
NodeOperation &getOperation() const
|
||||
{
|
||||
return *m_operation;
|
||||
}
|
||||
DataType getDataType() const
|
||||
{
|
||||
return m_datatype;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief determine the resolution of this data going through this socket
|
||||
* \param resolution: the result of this operation
|
||||
* \param preferredResolution: the preferable resolution as no resolution could be determined
|
||||
*/
|
||||
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief NodeOperation contains calculation logic
|
||||
|
@ -70,14 +169,10 @@ typedef enum InputResizeMode {
|
|||
* Subclasses needs to implement the execution method (defined in SocketReader) to implement logic.
|
||||
* \ingroup Model
|
||||
*/
|
||||
class NodeOperation : public SocketReader {
|
||||
public:
|
||||
typedef std::vector<NodeOperationInput *> Inputs;
|
||||
typedef std::vector<NodeOperationOutput *> Outputs;
|
||||
|
||||
class NodeOperation {
|
||||
private:
|
||||
Inputs m_inputs;
|
||||
Outputs m_outputs;
|
||||
blender::Vector<NodeOperationInput> m_inputs;
|
||||
blender::Vector<NodeOperationOutput> m_outputs;
|
||||
|
||||
/**
|
||||
* \brief the index of the input socket that will be used to determine the resolution
|
||||
|
@ -119,8 +214,21 @@ class NodeOperation : public SocketReader {
|
|||
*/
|
||||
bool m_isResolutionSet;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Width of the output of this operation.
|
||||
*/
|
||||
unsigned int m_width;
|
||||
|
||||
/**
|
||||
* Height of the output of this operation.
|
||||
*/
|
||||
unsigned int m_height;
|
||||
|
||||
public:
|
||||
virtual ~NodeOperation();
|
||||
virtual ~NodeOperation()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int getNumberOfInputSockets() const
|
||||
{
|
||||
|
@ -130,19 +238,15 @@ class NodeOperation : public SocketReader {
|
|||
{
|
||||
return m_outputs.size();
|
||||
}
|
||||
NodeOperationOutput *getOutputSocket(unsigned int index) const;
|
||||
NodeOperationOutput *getOutputSocket() const
|
||||
{
|
||||
return getOutputSocket(0);
|
||||
}
|
||||
NodeOperationInput *getInputSocket(unsigned int index) const;
|
||||
NodeOperationOutput *getOutputSocket(unsigned int index = 0);
|
||||
NodeOperationInput *getInputSocket(unsigned int index);
|
||||
|
||||
/** Check if this is an input operation
|
||||
* An input operation is an operation that only has output sockets and no input sockets
|
||||
*/
|
||||
bool isInputOperation() const
|
||||
{
|
||||
return m_inputs.empty();
|
||||
return m_inputs.is_empty();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -259,8 +363,6 @@ class NodeOperation : public SocketReader {
|
|||
}
|
||||
}
|
||||
|
||||
void getConnectedInputSockets(Inputs *sockets);
|
||||
|
||||
/**
|
||||
* \brief is this operation complex
|
||||
*
|
||||
|
@ -373,10 +475,58 @@ class NodeOperation : public SocketReader {
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int getWidth() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
unsigned int getHeight() const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
inline void readSampled(float result[4], float x, float y, PixelSampler sampler)
|
||||
{
|
||||
executePixelSampled(result, x, y, sampler);
|
||||
}
|
||||
|
||||
inline void readFiltered(float result[4], float x, float y, float dx[2], float dy[2])
|
||||
{
|
||||
executePixelFiltered(result, x, y, dx, dy);
|
||||
}
|
||||
|
||||
inline void read(float result[4], int x, int y, void *chunkData)
|
||||
{
|
||||
executePixel(result, x, y, chunkData);
|
||||
}
|
||||
|
||||
virtual void *initializeTileData(rcti * /*rect*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void deinitializeTileData(rcti * /*rect*/, void * /*data*/)
|
||||
{
|
||||
}
|
||||
|
||||
virtual MemoryBuffer *getInputMemoryBuffer(MemoryBuffer ** /*memoryBuffers*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the meta data associated with this branch.
|
||||
*
|
||||
* The return parameter holds an instance or is an nullptr. */
|
||||
virtual std::unique_ptr<MetaData> getMetaData()
|
||||
{
|
||||
return std::unique_ptr<MetaData>();
|
||||
}
|
||||
|
||||
protected:
|
||||
NodeOperation();
|
||||
|
||||
void addInputSocket(DataType datatype, InputResizeMode resize_mode = COM_SC_CENTER);
|
||||
void addInputSocket(DataType datatype, ResizeMode resize_mode = ResizeMode::Center);
|
||||
void addOutputSocket(DataType datatype);
|
||||
|
||||
void setWidth(unsigned int width)
|
||||
|
@ -416,6 +566,50 @@ class NodeOperation : public SocketReader {
|
|||
this->m_openCL = openCL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief calculate a single pixel
|
||||
* \note this method is called for non-complex
|
||||
* \param result: is a float[4] array to store the result
|
||||
* \param x: the x-coordinate of the pixel to calculate in image space
|
||||
* \param y: the y-coordinate of the pixel to calculate in image space
|
||||
* \param inputBuffers: chunks that can be read by their ReadBufferOperation.
|
||||
*/
|
||||
virtual void executePixelSampled(float /*output*/[4],
|
||||
float /*x*/,
|
||||
float /*y*/,
|
||||
PixelSampler /*sampler*/)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief calculate a single pixel
|
||||
* \note this method is called for complex
|
||||
* \param result: is a float[4] array to store the result
|
||||
* \param x: the x-coordinate of the pixel to calculate in image space
|
||||
* \param y: the y-coordinate of the pixel to calculate in image space
|
||||
* \param inputBuffers: chunks that can be read by their ReadBufferOperation.
|
||||
* \param chunkData: chunk specific data a during execution time.
|
||||
*/
|
||||
virtual void executePixel(float output[4], int x, int y, void * /*chunkData*/)
|
||||
{
|
||||
executePixelSampled(output, x, y, PixelSampler::Nearest);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief calculate a single pixel using an EWA filter
|
||||
* \note this method is called for complex
|
||||
* \param result: is a float[4] array to store the result
|
||||
* \param x: the x-coordinate of the pixel to calculate in image space
|
||||
* \param y: the y-coordinate of the pixel to calculate in image space
|
||||
* \param dx:
|
||||
* \param dy:
|
||||
* \param inputBuffers: chunks that can be read by their ReadBufferOperation.
|
||||
*/
|
||||
virtual void executePixelFiltered(
|
||||
float /*output*/[4], float /*x*/, float /*y*/, float /*dx*/[2], float /*dy*/[2])
|
||||
{
|
||||
}
|
||||
|
||||
/* allow the DebugInfo class to look at internals */
|
||||
friend class DebugInfo;
|
||||
|
||||
|
@ -423,96 +617,3 @@ class NodeOperation : public SocketReader {
|
|||
MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
|
||||
#endif
|
||||
};
|
||||
|
||||
class NodeOperationInput {
|
||||
private:
|
||||
NodeOperation *m_operation;
|
||||
|
||||
/** Datatype of this socket. Is used for automatically data transformation.
|
||||
* \section data-conversion
|
||||
*/
|
||||
DataType m_datatype;
|
||||
|
||||
/** Resize mode of this socket */
|
||||
InputResizeMode m_resizeMode;
|
||||
|
||||
/** Connected output */
|
||||
NodeOperationOutput *m_link;
|
||||
|
||||
public:
|
||||
NodeOperationInput(NodeOperation *op,
|
||||
DataType datatype,
|
||||
InputResizeMode resizeMode = COM_SC_CENTER);
|
||||
|
||||
NodeOperation &getOperation() const
|
||||
{
|
||||
return *m_operation;
|
||||
}
|
||||
DataType getDataType() const
|
||||
{
|
||||
return m_datatype;
|
||||
}
|
||||
|
||||
void setLink(NodeOperationOutput *link)
|
||||
{
|
||||
m_link = link;
|
||||
}
|
||||
NodeOperationOutput *getLink() const
|
||||
{
|
||||
return m_link;
|
||||
}
|
||||
bool isConnected() const
|
||||
{
|
||||
return m_link;
|
||||
}
|
||||
|
||||
void setResizeMode(InputResizeMode resizeMode)
|
||||
{
|
||||
this->m_resizeMode = resizeMode;
|
||||
}
|
||||
InputResizeMode getResizeMode() const
|
||||
{
|
||||
return this->m_resizeMode;
|
||||
}
|
||||
|
||||
SocketReader *getReader();
|
||||
|
||||
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
|
||||
#endif
|
||||
};
|
||||
|
||||
class NodeOperationOutput {
|
||||
private:
|
||||
NodeOperation *m_operation;
|
||||
|
||||
/** Datatype of this socket. Is used for automatically data transformation.
|
||||
* \section data-conversion
|
||||
*/
|
||||
DataType m_datatype;
|
||||
|
||||
public:
|
||||
NodeOperationOutput(NodeOperation *op, DataType datatype);
|
||||
|
||||
NodeOperation &getOperation() const
|
||||
{
|
||||
return *m_operation;
|
||||
}
|
||||
DataType getDataType() const
|
||||
{
|
||||
return m_datatype;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief determine the resolution of this data going through this socket
|
||||
* \param resolution: the result of this operation
|
||||
* \param preferredResolution: the preferable resolution as no resolution could be determined
|
||||
*/
|
||||
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -53,9 +53,7 @@ void NodeOperationBuilder::convertToOperations(ExecutionSystem *system)
|
|||
/* interface handle for nodes */
|
||||
NodeConverter converter(this);
|
||||
|
||||
for (int index = 0; index < m_graph.nodes().size(); index++) {
|
||||
Node *node = (Node *)m_graph.nodes()[index];
|
||||
|
||||
for (Node *node : m_graph.nodes()) {
|
||||
m_current_node = node;
|
||||
|
||||
DebugInfo::node_to_operations(node);
|
||||
|
@ -401,7 +399,7 @@ void NodeOperationBuilder::determineResolutions()
|
|||
{
|
||||
blender::Vector<Link> convert_links;
|
||||
for (const Link &link : m_links) {
|
||||
if (link.to()->getResizeMode() != COM_SC_NO_RESIZE) {
|
||||
if (link.to()->getResizeMode() != ResizeMode::None) {
|
||||
NodeOperation &from_op = link.from()->getOperation();
|
||||
NodeOperation &to_op = link.to()->getOperation();
|
||||
if (from_op.getWidth() != to_op.getWidth() || from_op.getHeight() != to_op.getHeight()) {
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*/
|
||||
|
||||
#include "COM_SocketReader.h"
|
|
@ -1,153 +0,0 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_rect.h"
|
||||
#include "COM_MetaData.h"
|
||||
#include "COM_defines.h"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
# include "MEM_guardedalloc.h"
|
||||
#endif
|
||||
|
||||
typedef enum PixelSampler {
|
||||
COM_PS_NEAREST = 0,
|
||||
COM_PS_BILINEAR = 1,
|
||||
COM_PS_BICUBIC = 2,
|
||||
} PixelSampler;
|
||||
|
||||
class MemoryBuffer;
|
||||
|
||||
/**
|
||||
* \brief Helper class for reading socket data.
|
||||
* Only use this class for dispatching (un-ary and n-ary) executions.
|
||||
* \ingroup Execution
|
||||
*/
|
||||
class SocketReader {
|
||||
private:
|
||||
protected:
|
||||
/**
|
||||
* \brief Holds the width of the output of this operation.
|
||||
*/
|
||||
unsigned int m_width;
|
||||
|
||||
/**
|
||||
* \brief Holds the height of the output of this operation.
|
||||
*/
|
||||
unsigned int m_height;
|
||||
|
||||
/**
|
||||
* \brief calculate a single pixel
|
||||
* \note this method is called for non-complex
|
||||
* \param result: is a float[4] array to store the result
|
||||
* \param x: the x-coordinate of the pixel to calculate in image space
|
||||
* \param y: the y-coordinate of the pixel to calculate in image space
|
||||
* \param inputBuffers: chunks that can be read by their ReadBufferOperation.
|
||||
*/
|
||||
virtual void executePixelSampled(float /*output*/[4],
|
||||
float /*x*/,
|
||||
float /*y*/,
|
||||
PixelSampler /*sampler*/)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief calculate a single pixel
|
||||
* \note this method is called for complex
|
||||
* \param result: is a float[4] array to store the result
|
||||
* \param x: the x-coordinate of the pixel to calculate in image space
|
||||
* \param y: the y-coordinate of the pixel to calculate in image space
|
||||
* \param inputBuffers: chunks that can be read by their ReadBufferOperation.
|
||||
* \param chunkData: chunk specific data a during execution time.
|
||||
*/
|
||||
virtual void executePixel(float output[4], int x, int y, void * /*chunkData*/)
|
||||
{
|
||||
executePixelSampled(output, x, y, COM_PS_NEAREST);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief calculate a single pixel using an EWA filter
|
||||
* \note this method is called for complex
|
||||
* \param result: is a float[4] array to store the result
|
||||
* \param x: the x-coordinate of the pixel to calculate in image space
|
||||
* \param y: the y-coordinate of the pixel to calculate in image space
|
||||
* \param dx:
|
||||
* \param dy:
|
||||
* \param inputBuffers: chunks that can be read by their ReadBufferOperation.
|
||||
*/
|
||||
virtual void executePixelFiltered(
|
||||
float /*output*/[4], float /*x*/, float /*y*/, float /*dx*/[2], float /*dy*/[2])
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
inline void readSampled(float result[4], float x, float y, PixelSampler sampler)
|
||||
{
|
||||
executePixelSampled(result, x, y, sampler);
|
||||
}
|
||||
inline void read(float result[4], int x, int y, void *chunkData)
|
||||
{
|
||||
executePixel(result, x, y, chunkData);
|
||||
}
|
||||
inline void readFiltered(float result[4], float x, float y, float dx[2], float dy[2])
|
||||
{
|
||||
executePixelFiltered(result, x, y, dx, dy);
|
||||
}
|
||||
|
||||
virtual void *initializeTileData(rcti * /*rect*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual void deinitializeTileData(rcti * /*rect*/, void * /*data*/)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~SocketReader()
|
||||
{
|
||||
}
|
||||
|
||||
virtual MemoryBuffer *getInputMemoryBuffer(MemoryBuffer ** /*memoryBuffers*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline unsigned int getWidth() const
|
||||
{
|
||||
return this->m_width;
|
||||
}
|
||||
inline unsigned int getHeight() const
|
||||
{
|
||||
return this->m_height;
|
||||
}
|
||||
|
||||
/* Return the meta data associated with this branch.
|
||||
*
|
||||
* The return parameter holds an instance or is an nullptr. */
|
||||
virtual std::unique_ptr<MetaData> getMetaData() const
|
||||
{
|
||||
return std::unique_ptr<MetaData>();
|
||||
}
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("COM:SocketReader")
|
||||
#endif
|
||||
};
|
|
@ -60,7 +60,7 @@ void BoxMaskNode::convertToOperations(NodeConverter &converter,
|
|||
scaleOperation->setOffset(0.0f, 0.0f);
|
||||
scaleOperation->setNewWidth(rd->xsch * render_size_factor);
|
||||
scaleOperation->setNewHeight(rd->ysch * render_size_factor);
|
||||
scaleOperation->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
|
||||
scaleOperation->getInputSocket(0)->setResizeMode(ResizeMode::None);
|
||||
converter.addOperation(scaleOperation);
|
||||
|
||||
converter.addLink(valueOperation->getOutputSocket(0), scaleOperation->getInputSocket(0));
|
||||
|
|
|
@ -60,7 +60,7 @@ void EllipseMaskNode::convertToOperations(NodeConverter &converter,
|
|||
scaleOperation->setOffset(0.0f, 0.0f);
|
||||
scaleOperation->setNewWidth(rd->xsch * render_size_factor);
|
||||
scaleOperation->setNewHeight(rd->ysch * render_size_factor);
|
||||
scaleOperation->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
|
||||
scaleOperation->getInputSocket(0)->setResizeMode(ResizeMode::None);
|
||||
converter.addOperation(scaleOperation);
|
||||
|
||||
converter.addLink(valueOperation->getOutputSocket(0), scaleOperation->getInputSocket(0));
|
||||
|
|
|
@ -65,7 +65,7 @@ void GlareNode::convertToOperations(NodeConverter &converter,
|
|||
|
||||
MixGlareOperation *mixoperation = new MixGlareOperation();
|
||||
mixoperation->setResolutionInputSocketIndex(1);
|
||||
mixoperation->getInputSocket(2)->setResizeMode(COM_SC_FIT);
|
||||
mixoperation->getInputSocket(2)->setResizeMode(ResizeMode::FitAny);
|
||||
|
||||
converter.addOperation(glareoperation);
|
||||
converter.addOperation(thresholdOperation);
|
||||
|
|
|
@ -79,7 +79,7 @@ void ScaleNode::convertToOperations(NodeConverter &converter,
|
|||
operation->setOffset(bnode->custom3, bnode->custom4);
|
||||
operation->setNewWidth(rd->xsch * render_size_factor);
|
||||
operation->setNewHeight(rd->ysch * render_size_factor);
|
||||
operation->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
|
||||
operation->getInputSocket(0)->setResizeMode(ResizeMode::None);
|
||||
converter.addOperation(operation);
|
||||
|
||||
converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
|
||||
|
|
|
@ -167,7 +167,7 @@ void BlurBaseOperation::updateSize()
|
|||
{
|
||||
if (!this->m_sizeavailable) {
|
||||
float result[4];
|
||||
this->getInputSocketReader(1)->readSampled(result, 0, 0, COM_PS_NEAREST);
|
||||
this->getInputSocketReader(1)->readSampled(result, 0, 0, PixelSampler::Nearest);
|
||||
this->m_size = result[0];
|
||||
this->m_sizeavailable = true;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
BokehBlurOperation::BokehBlurOperation()
|
||||
{
|
||||
this->addInputSocket(DataType::Color);
|
||||
this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
|
||||
this->addInputSocket(DataType::Color, ResizeMode::None);
|
||||
this->addInputSocket(DataType::Value);
|
||||
this->addInputSocket(DataType::Value);
|
||||
this->addOutputSocket(DataType::Color);
|
||||
|
@ -76,7 +76,7 @@ void BokehBlurOperation::executePixel(float output[4], int x, int y, void *data)
|
|||
float tempBoundingBox[4];
|
||||
float bokeh[4];
|
||||
|
||||
this->m_inputBoundingBoxReader->readSampled(tempBoundingBox, x, y, COM_PS_NEAREST);
|
||||
this->m_inputBoundingBoxReader->readSampled(tempBoundingBox, x, y, PixelSampler::Nearest);
|
||||
if (tempBoundingBox[0] > 0.0f) {
|
||||
float multiplier_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
MemoryBuffer *inputBuffer = (MemoryBuffer *)data;
|
||||
|
@ -90,7 +90,7 @@ void BokehBlurOperation::executePixel(float output[4], int x, int y, void *data)
|
|||
zero_v4(color_accum);
|
||||
|
||||
if (pixelSize < 2) {
|
||||
this->m_inputProgram->readSampled(color_accum, x, y, COM_PS_NEAREST);
|
||||
this->m_inputProgram->readSampled(color_accum, x, y, PixelSampler::Nearest);
|
||||
multiplier_accum[0] = 1.0f;
|
||||
multiplier_accum[1] = 1.0f;
|
||||
multiplier_accum[2] = 1.0f;
|
||||
|
@ -115,7 +115,7 @@ void BokehBlurOperation::executePixel(float output[4], int x, int y, void *data)
|
|||
for (int nx = minx; nx < maxx; nx += step) {
|
||||
float u = this->m_bokehMidX - (nx - x) * m;
|
||||
float v = this->m_bokehMidY - (ny - y) * m;
|
||||
this->m_inputBokehProgram->readSampled(bokeh, u, v, COM_PS_NEAREST);
|
||||
this->m_inputBokehProgram->readSampled(bokeh, u, v, PixelSampler::Nearest);
|
||||
madd_v4_v4v4(color_accum, bokeh, &buffer[bufferindex]);
|
||||
add_v4_v4(multiplier_accum, bokeh);
|
||||
bufferindex += offsetadd;
|
||||
|
@ -127,7 +127,7 @@ void BokehBlurOperation::executePixel(float output[4], int x, int y, void *data)
|
|||
output[3] = color_accum[3] * (1.0f / multiplier_accum[3]);
|
||||
}
|
||||
else {
|
||||
this->m_inputProgram->readSampled(output, x, y, COM_PS_NEAREST);
|
||||
this->m_inputProgram->readSampled(output, x, y, PixelSampler::Nearest);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ void BokehBlurOperation::updateSize()
|
|||
{
|
||||
if (!this->m_sizeavailable) {
|
||||
float result[4];
|
||||
this->getInputSocketReader(3)->readSampled(result, 0, 0, COM_PS_NEAREST);
|
||||
this->getInputSocketReader(3)->readSampled(result, 0, 0, PixelSampler::Nearest);
|
||||
this->m_size = result[0];
|
||||
CLAMP(this->m_size, 0.0f, 10.0f);
|
||||
this->m_sizeavailable = true;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
CalculateMeanOperation::CalculateMeanOperation()
|
||||
{
|
||||
this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
|
||||
this->addInputSocket(DataType::Color, ResizeMode::None);
|
||||
this->addOutputSocket(DataType::Value);
|
||||
this->m_imageReader = nullptr;
|
||||
this->m_iscalculated = false;
|
||||
|
|
|
@ -196,14 +196,14 @@ void CompositorOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
|
|||
for (x = x1; x < x2 && (!breaked); x++) {
|
||||
int input_x = x + dx, input_y = y + dy;
|
||||
|
||||
this->m_imageInput->readSampled(color, input_x, input_y, COM_PS_NEAREST);
|
||||
this->m_imageInput->readSampled(color, input_x, input_y, PixelSampler::Nearest);
|
||||
if (this->m_useAlphaInput) {
|
||||
this->m_alphaInput->readSampled(&(color[3]), input_x, input_y, COM_PS_NEAREST);
|
||||
this->m_alphaInput->readSampled(&(color[3]), input_x, input_y, PixelSampler::Nearest);
|
||||
}
|
||||
|
||||
copy_v4_v4(buffer + offset4, color);
|
||||
|
||||
this->m_depthInput->readSampled(color, input_x, input_y, COM_PS_NEAREST);
|
||||
this->m_depthInput->readSampled(color, input_x, input_y, PixelSampler::Nearest);
|
||||
zbuffer[offset] = color[0];
|
||||
offset4 += COM_NUM_CHANNELS_COLOR;
|
||||
offset++;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
CropBaseOperation::CropBaseOperation()
|
||||
{
|
||||
this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
|
||||
this->addInputSocket(DataType::Color, ResizeMode::None);
|
||||
this->addOutputSocket(DataType::Color);
|
||||
this->m_inputOperation = nullptr;
|
||||
this->m_settings = nullptr;
|
||||
|
|
|
@ -66,7 +66,7 @@ void DirectionalBlurOperation::executePixel(float output[4], int x, int y, void
|
|||
const int iterations = pow(2.0f, this->m_data->iter);
|
||||
float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
float col2[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
this->m_inputProgram->readSampled(col2, x, y, COM_PS_BILINEAR);
|
||||
this->m_inputProgram->readSampled(col2, x, y, PixelSampler::Bilinear);
|
||||
float ltx = this->m_tx;
|
||||
float lty = this->m_ty;
|
||||
float lsc = this->m_sc;
|
||||
|
@ -82,7 +82,7 @@ void DirectionalBlurOperation::executePixel(float output[4], int x, int y, void
|
|||
this->m_inputProgram->readSampled(col,
|
||||
cs * u + ss * v + this->m_center_x_pix,
|
||||
cs * v - ss * u + this->m_center_y_pix,
|
||||
COM_PS_BILINEAR);
|
||||
PixelSampler::Bilinear);
|
||||
|
||||
add_v4_v4(col2, col);
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ void DisplaceOperation::executePixelSampled(float output[4],
|
|||
|
||||
pixelTransform(xy, uv, deriv);
|
||||
if (is_zero_v2(deriv[0]) && is_zero_v2(deriv[1])) {
|
||||
this->m_inputColorProgram->readSampled(output, uv[0], uv[1], COM_PS_BILINEAR);
|
||||
this->m_inputColorProgram->readSampled(output, uv[0], uv[1], PixelSampler::Bilinear);
|
||||
}
|
||||
else {
|
||||
/* EWA filtering (without nearest it gets blurry with NO distortion) */
|
||||
|
@ -76,7 +76,7 @@ bool DisplaceOperation::read_displacement(
|
|||
}
|
||||
|
||||
float col[4];
|
||||
m_inputVectorProgram->readSampled(col, x, y, COM_PS_BILINEAR);
|
||||
m_inputVectorProgram->readSampled(col, x, y, PixelSampler::Bilinear);
|
||||
r_u = origin[0] - col[0] * xscale;
|
||||
r_v = origin[1] - col[1] * yscale;
|
||||
return true;
|
||||
|
@ -88,9 +88,9 @@ void DisplaceOperation::pixelTransform(const float xy[2], float r_uv[2], float r
|
|||
float uv[2]; /* temporary variables for derivative estimation */
|
||||
int num;
|
||||
|
||||
m_inputScaleXProgram->readSampled(col, xy[0], xy[1], COM_PS_NEAREST);
|
||||
m_inputScaleXProgram->readSampled(col, xy[0], xy[1], PixelSampler::Nearest);
|
||||
float xs = col[0];
|
||||
m_inputScaleYProgram->readSampled(col, xy[0], xy[1], COM_PS_NEAREST);
|
||||
m_inputScaleYProgram->readSampled(col, xy[0], xy[1], PixelSampler::Nearest);
|
||||
float ys = col[0];
|
||||
/* clamp x and y displacement to triple image resolution -
|
||||
* to prevent hangs from huge values mistakenly plugged in eg. z buffers */
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
GlareThresholdOperation::GlareThresholdOperation()
|
||||
{
|
||||
this->addInputSocket(DataType::Color, COM_SC_FIT);
|
||||
this->addInputSocket(DataType::Color, ResizeMode::FitAny);
|
||||
this->addOutputSocket(DataType::Color);
|
||||
this->m_inputProgram = nullptr;
|
||||
}
|
||||
|
|
|
@ -123,13 +123,13 @@ static void sampleImageAtLocation(
|
|||
{
|
||||
if (ibuf->rect_float) {
|
||||
switch (sampler) {
|
||||
case COM_PS_NEAREST:
|
||||
case PixelSampler::Nearest:
|
||||
nearest_interpolation_color(ibuf, nullptr, color, x, y);
|
||||
break;
|
||||
case COM_PS_BILINEAR:
|
||||
case PixelSampler::Bilinear:
|
||||
bilinear_interpolation_color(ibuf, nullptr, color, x, y);
|
||||
break;
|
||||
case COM_PS_BICUBIC:
|
||||
case PixelSampler::Bicubic:
|
||||
bicubic_interpolation_color(ibuf, nullptr, color, x, y);
|
||||
break;
|
||||
}
|
||||
|
@ -137,13 +137,13 @@ static void sampleImageAtLocation(
|
|||
else {
|
||||
unsigned char byte_color[4];
|
||||
switch (sampler) {
|
||||
case COM_PS_NEAREST:
|
||||
case PixelSampler::Nearest:
|
||||
nearest_interpolation_color(ibuf, byte_color, nullptr, x, y);
|
||||
break;
|
||||
case COM_PS_BILINEAR:
|
||||
case PixelSampler::Bilinear:
|
||||
bilinear_interpolation_color(ibuf, byte_color, nullptr, x, y);
|
||||
break;
|
||||
case COM_PS_BICUBIC:
|
||||
case PixelSampler::Bicubic:
|
||||
bicubic_interpolation_color(ibuf, byte_color, nullptr, x, y);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
MapUVOperation::MapUVOperation()
|
||||
{
|
||||
this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
|
||||
this->addInputSocket(DataType::Color, ResizeMode::None);
|
||||
this->addInputSocket(DataType::Vector);
|
||||
this->addOutputSocket(DataType::Color);
|
||||
this->m_alpha = 0.0f;
|
||||
|
@ -89,7 +89,7 @@ bool MapUVOperation::read_uv(float x, float y, float &r_u, float &r_v, float &r_
|
|||
}
|
||||
|
||||
float vector[3];
|
||||
m_inputUVProgram->readSampled(vector, x, y, COM_PS_BILINEAR);
|
||||
m_inputUVProgram->readSampled(vector, x, y, PixelSampler::Bilinear);
|
||||
r_u = vector[0] * m_inputColorProgram->getWidth();
|
||||
r_v = vector[1] * m_inputColorProgram->getHeight();
|
||||
r_alpha = vector[2];
|
||||
|
|
|
@ -101,13 +101,13 @@ void MovieClipBaseOperation::executePixelSampled(float output[4],
|
|||
}
|
||||
else {
|
||||
switch (sampler) {
|
||||
case COM_PS_NEAREST:
|
||||
case PixelSampler::Nearest:
|
||||
nearest_interpolation_color(ibuf, nullptr, output, x, y);
|
||||
break;
|
||||
case COM_PS_BILINEAR:
|
||||
case PixelSampler::Bilinear:
|
||||
bilinear_interpolation_color(ibuf, nullptr, output, x, y);
|
||||
break;
|
||||
case COM_PS_BICUBIC:
|
||||
case PixelSampler::Bicubic:
|
||||
bicubic_interpolation_color(ibuf, nullptr, output, x, y);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -107,10 +107,10 @@ void MovieDistortionOperation::executePixelSampled(float output[4],
|
|||
float u = out[0] * aspx /* + 0.5 * overscan * w */,
|
||||
v = (out[1] * aspy /* + 0.5 * overscan * h */) * pixel_aspect;
|
||||
|
||||
this->m_inputOperation->readSampled(output, u, v, COM_PS_BILINEAR);
|
||||
this->m_inputOperation->readSampled(output, u, v, PixelSampler::Bilinear);
|
||||
}
|
||||
else {
|
||||
this->m_inputOperation->readSampled(output, x, y, COM_PS_BILINEAR);
|
||||
this->m_inputOperation->readSampled(output, x, y, PixelSampler::Bilinear);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ ImBuf *MultilayerBaseOperation::getImBuf()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<MetaData> MultilayerColorOperation::getMetaData() const
|
||||
std::unique_ptr<MetaData> MultilayerColorOperation::getMetaData()
|
||||
{
|
||||
BLI_assert(this->m_buffer);
|
||||
MetaDataExtractCallbackData callback_data = {nullptr};
|
||||
|
@ -86,13 +86,13 @@ void MultilayerColorOperation::executePixelSampled(float output[4],
|
|||
else {
|
||||
if (this->m_numberOfChannels == 4) {
|
||||
switch (sampler) {
|
||||
case COM_PS_NEAREST:
|
||||
case PixelSampler::Nearest:
|
||||
nearest_interpolation_color(this->m_buffer, nullptr, output, x, y);
|
||||
break;
|
||||
case COM_PS_BILINEAR:
|
||||
case PixelSampler::Bilinear:
|
||||
bilinear_interpolation_color(this->m_buffer, nullptr, output, x, y);
|
||||
break;
|
||||
case COM_PS_BICUBIC:
|
||||
case PixelSampler::Bicubic:
|
||||
bicubic_interpolation_color(this->m_buffer, nullptr, output, x, y);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class MultilayerColorOperation : public MultilayerBaseOperation {
|
|||
this->addOutputSocket(DataType::Color);
|
||||
}
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
std::unique_ptr<MetaData> getMetaData() const override;
|
||||
std::unique_ptr<MetaData> getMetaData() override;
|
||||
};
|
||||
|
||||
class MultilayerValueOperation : public MultilayerBaseOperation {
|
||||
|
|
|
@ -191,7 +191,7 @@ static void write_buffer_rect(rcti *rect,
|
|||
|
||||
for (y = y1; y < y2 && (!breaked); y++) {
|
||||
for (x = x1; x < x2 && (!breaked); x++) {
|
||||
reader->readSampled(color, x, y, COM_PS_NEAREST);
|
||||
reader->readSampled(color, x, y, PixelSampler::Nearest);
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
buffer[offset + i] = color[i];
|
||||
|
|
|
@ -60,7 +60,7 @@ static void readCornersFromSockets(rcti *rect, SocketReader *readers[4], float c
|
|||
{
|
||||
for (int i = 0; i < 4; i++) {
|
||||
float result[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
readers[i]->readSampled(result, rect->xmin, rect->ymin, COM_PS_NEAREST);
|
||||
readers[i]->readSampled(result, rect->xmin, rect->ymin, PixelSampler::Nearest);
|
||||
corners[i][0] = result[0];
|
||||
corners[i][1] = result[1];
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ BLI_INLINE void warpCoord(float x, float y, float matrix[3][3], float uv[2], flo
|
|||
|
||||
PlaneDistortWarpImageOperation::PlaneDistortWarpImageOperation()
|
||||
{
|
||||
this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
|
||||
this->addInputSocket(DataType::Color, ResizeMode::None);
|
||||
this->addOutputSocket(DataType::Color);
|
||||
this->m_pixelReader = nullptr;
|
||||
this->m_motion_blur_samples = 1;
|
||||
|
|
|
@ -39,7 +39,7 @@ PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings,
|
|||
const unsigned int defaultHeight)
|
||||
|
||||
{
|
||||
this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
|
||||
this->addInputSocket(DataType::Color, ResizeMode::None);
|
||||
this->m_preview = nullptr;
|
||||
this->m_outputBuffer = nullptr;
|
||||
this->m_input = nullptr;
|
||||
|
@ -104,7 +104,7 @@ void PreviewOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
|
|||
color[1] = 0.0f;
|
||||
color[2] = 0.0f;
|
||||
color[3] = 1.0f;
|
||||
this->m_input->readSampled(color, rx, ry, COM_PS_NEAREST);
|
||||
this->m_input->readSampled(color, rx, ry, PixelSampler::Nearest);
|
||||
IMB_colormanagement_processor_apply_v4(cm_processor, color);
|
||||
rgba_float_to_uchar(this->m_outputBuffer + offset, color);
|
||||
offset += 4;
|
||||
|
|
|
@ -103,7 +103,7 @@ void ProjectorLensDistortionOperation::updateDispersion()
|
|||
this->lockMutex();
|
||||
if (!this->m_dispersionAvailable) {
|
||||
float result[4];
|
||||
this->getInputSocketReader(1)->readSampled(result, 1, 1, COM_PS_NEAREST);
|
||||
this->getInputSocketReader(1)->readSampled(result, 1, 1, PixelSampler::Nearest);
|
||||
this->m_dispersion = result[0];
|
||||
this->m_kr = 0.25f * max_ff(min_ff(this->m_dispersion, 1.0f), 0.0f);
|
||||
this->m_kr2 = this->m_kr * 20;
|
||||
|
|
|
@ -60,14 +60,14 @@ void ReadBufferOperation::executePixelSampled(float output[4],
|
|||
}
|
||||
else {
|
||||
switch (sampler) {
|
||||
case COM_PS_NEAREST:
|
||||
case PixelSampler::Nearest:
|
||||
m_buffer->read(output, x, y);
|
||||
break;
|
||||
case COM_PS_BILINEAR:
|
||||
case PixelSampler::Bilinear:
|
||||
default:
|
||||
m_buffer->readBilinear(output, x, y);
|
||||
break;
|
||||
case COM_PS_BICUBIC:
|
||||
case PixelSampler::Bicubic:
|
||||
m_buffer->readBilinear(output, x, y);
|
||||
break;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ void ReadBufferOperation::executePixelExtend(float output[4],
|
|||
/* write buffer has a single value stored at (0,0) */
|
||||
m_buffer->read(output, 0, 0);
|
||||
}
|
||||
else if (sampler == COM_PS_NEAREST) {
|
||||
else if (sampler == PixelSampler::Nearest) {
|
||||
m_buffer->read(output, x, y, extend_x, extend_y);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -92,7 +92,7 @@ void RenderLayersProg::doInterpolation(float output[4], float x, float y, PixelS
|
|||
}
|
||||
|
||||
switch (sampler) {
|
||||
case COM_PS_NEAREST: {
|
||||
case PixelSampler::Nearest: {
|
||||
offset = (iy * width + ix) * this->m_elementsize;
|
||||
|
||||
if (this->m_elementsize == 1) {
|
||||
|
@ -107,12 +107,12 @@ void RenderLayersProg::doInterpolation(float output[4], float x, float y, PixelS
|
|||
break;
|
||||
}
|
||||
|
||||
case COM_PS_BILINEAR:
|
||||
case PixelSampler::Bilinear:
|
||||
BLI_bilinear_interpolation_fl(
|
||||
this->m_inputBuffer, output, width, height, this->m_elementsize, x, y);
|
||||
break;
|
||||
|
||||
case COM_PS_BICUBIC:
|
||||
case PixelSampler::Bicubic:
|
||||
BLI_bicubic_interpolation_fl(
|
||||
this->m_inputBuffer, output, width, height, this->m_elementsize, x, y);
|
||||
break;
|
||||
|
@ -216,7 +216,7 @@ void RenderLayersProg::determineResolution(unsigned int resolution[2],
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<MetaData> RenderLayersProg::getMetaData() const
|
||||
std::unique_ptr<MetaData> RenderLayersProg::getMetaData()
|
||||
{
|
||||
Scene *scene = this->getScene();
|
||||
Render *re = (scene) ? RE_GetSceneRender(scene) : nullptr;
|
||||
|
|
|
@ -123,7 +123,7 @@ class RenderLayersProg : public NodeOperation {
|
|||
void deinitExecution() override;
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
std::unique_ptr<MetaData> getMetaData() const override;
|
||||
std::unique_ptr<MetaData> getMetaData() override;
|
||||
};
|
||||
|
||||
class RenderLayersAOOperation : public RenderLayersProg {
|
||||
|
|
|
@ -48,7 +48,7 @@ inline void RotateOperation::ensureDegree()
|
|||
{
|
||||
if (!this->m_isDegreeSet) {
|
||||
float degree[4];
|
||||
this->m_degreeSocket->readSampled(degree, 0, 0, COM_PS_NEAREST);
|
||||
this->m_degreeSocket->readSampled(degree, 0, 0, PixelSampler::Nearest);
|
||||
double rad;
|
||||
if (this->m_doDegree2RadConversion) {
|
||||
rad = DEG2RAD((double)degree[0]);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
BaseScaleOperation::BaseScaleOperation()
|
||||
{
|
||||
#ifdef USE_FORCE_BILINEAR
|
||||
m_sampler = (int)COM_PS_BILINEAR;
|
||||
m_sampler = (int)PixelSampler::Bilinear;
|
||||
#else
|
||||
m_sampler = -1;
|
||||
#endif
|
||||
|
@ -89,8 +89,8 @@ bool ScaleOperation::determineDependingAreaOfInterest(rcti *input,
|
|||
float scaleX[4];
|
||||
float scaleY[4];
|
||||
|
||||
this->m_inputXOperation->readSampled(scaleX, 0, 0, COM_PS_NEAREST);
|
||||
this->m_inputYOperation->readSampled(scaleY, 0, 0, COM_PS_NEAREST);
|
||||
this->m_inputXOperation->readSampled(scaleX, 0, 0, PixelSampler::Nearest);
|
||||
this->m_inputYOperation->readSampled(scaleY, 0, 0, PixelSampler::Nearest);
|
||||
|
||||
const float scx = scaleX[0];
|
||||
const float scy = scaleY[0];
|
||||
|
@ -174,8 +174,8 @@ bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input,
|
|||
float scaleX[4];
|
||||
float scaleY[4];
|
||||
|
||||
this->m_inputXOperation->readSampled(scaleX, 0, 0, COM_PS_NEAREST);
|
||||
this->m_inputYOperation->readSampled(scaleY, 0, 0, COM_PS_NEAREST);
|
||||
this->m_inputXOperation->readSampled(scaleX, 0, 0, PixelSampler::Nearest);
|
||||
this->m_inputYOperation->readSampled(scaleY, 0, 0, PixelSampler::Nearest);
|
||||
|
||||
const float scx = scaleX[0];
|
||||
const float scy = scaleY[0];
|
||||
|
@ -203,7 +203,7 @@ bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input,
|
|||
// Absolute fixed size
|
||||
ScaleFixedSizeOperation::ScaleFixedSizeOperation() : BaseScaleOperation()
|
||||
{
|
||||
this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
|
||||
this->addInputSocket(DataType::Color, ResizeMode::None);
|
||||
this->addOutputSocket(DataType::Color);
|
||||
this->setResolutionInputSocketIndex(0);
|
||||
this->m_inputOperation = nullptr;
|
||||
|
|
|
@ -83,12 +83,12 @@ void *ScreenLensDistortionOperation::initializeTileData(rcti * /*rect*/)
|
|||
|
||||
if (!m_distortion_const) {
|
||||
float result[4];
|
||||
getInputSocketReader(1)->readSampled(result, 0, 0, COM_PS_NEAREST);
|
||||
getInputSocketReader(1)->readSampled(result, 0, 0, PixelSampler::Nearest);
|
||||
m_distortion = result[0];
|
||||
}
|
||||
if (!m_dispersion_const) {
|
||||
float result[4];
|
||||
getInputSocketReader(2)->readSampled(result, 0, 0, COM_PS_NEAREST);
|
||||
getInputSocketReader(2)->readSampled(result, 0, 0, PixelSampler::Nearest);
|
||||
m_dispersion = result[0];
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ SocketProxyOperation::SocketProxyOperation(DataType type, bool use_conversion)
|
|||
this->addOutputSocket(type);
|
||||
}
|
||||
|
||||
std::unique_ptr<MetaData> SocketProxyOperation::getMetaData() const
|
||||
std::unique_ptr<MetaData> SocketProxyOperation::getMetaData()
|
||||
{
|
||||
return this->getInputSocket(0)->getReader()->getMetaData();
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ class SocketProxyOperation : public NodeOperation {
|
|||
{
|
||||
m_use_conversion = use_conversion;
|
||||
}
|
||||
std::unique_ptr<MetaData> getMetaData() const override;
|
||||
std::unique_ptr<MetaData> getMetaData() override;
|
||||
|
||||
private:
|
||||
bool m_use_conversion;
|
||||
|
|
|
@ -58,10 +58,10 @@ void SplitOperation::executePixelSampled(float output[4],
|
|||
this->m_splitPercentage * this->getHeight() / 100.0f;
|
||||
bool image1 = this->m_xSplit ? x > perc : y > perc;
|
||||
if (image1) {
|
||||
this->m_image1Input->readSampled(output, x, y, COM_PS_NEAREST);
|
||||
this->m_image1Input->readSampled(output, x, y, PixelSampler::Nearest);
|
||||
}
|
||||
else {
|
||||
this->m_image2Input->readSampled(output, x, y, COM_PS_NEAREST);
|
||||
this->m_image2Input->readSampled(output, x, y, PixelSampler::Nearest);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
TonemapOperation::TonemapOperation()
|
||||
{
|
||||
this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE);
|
||||
this->addInputSocket(DataType::Color, ResizeMode::None);
|
||||
this->addOutputSocket(DataType::Color);
|
||||
this->m_imageReader = nullptr;
|
||||
this->m_data = nullptr;
|
||||
|
|
|
@ -56,7 +56,7 @@ void TranslateOperation::executePixelSampled(float output[4],
|
|||
float originalXPos = x - this->getDeltaX();
|
||||
float originalYPos = y - this->getDeltaY();
|
||||
|
||||
this->m_inputOperation->readSampled(output, originalXPos, originalYPos, COM_PS_BILINEAR);
|
||||
this->m_inputOperation->readSampled(output, originalXPos, originalYPos, PixelSampler::Bilinear);
|
||||
}
|
||||
|
||||
bool TranslateOperation::determineDependingAreaOfInterest(rcti *input,
|
||||
|
|
|
@ -54,9 +54,9 @@ class TranslateOperation : public NodeOperation {
|
|||
{
|
||||
if (!this->m_isDeltaSet) {
|
||||
float tempDelta[4];
|
||||
this->m_inputXOperation->readSampled(tempDelta, 0, 0, COM_PS_NEAREST);
|
||||
this->m_inputXOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest);
|
||||
this->m_deltaX = tempDelta[0];
|
||||
this->m_inputYOperation->readSampled(tempDelta, 0, 0, COM_PS_NEAREST);
|
||||
this->m_inputYOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest);
|
||||
this->m_deltaY = tempDelta[0];
|
||||
this->m_isDeltaSet = true;
|
||||
}
|
||||
|
|
|
@ -25,11 +25,11 @@
|
|||
VariableSizeBokehBlurOperation::VariableSizeBokehBlurOperation()
|
||||
{
|
||||
this->addInputSocket(DataType::Color);
|
||||
this->addInputSocket(DataType::Color, COM_SC_NO_RESIZE); // do not resize the bokeh image.
|
||||
this->addInputSocket(DataType::Color, ResizeMode::None); // do not resize the bokeh image.
|
||||
this->addInputSocket(DataType::Value); // radius
|
||||
#ifdef COM_DEFOCUS_SEARCH
|
||||
this->addInputSocket(DataType::Color,
|
||||
COM_SC_NO_RESIZE); // inverse search radius optimization structure.
|
||||
ResizeMode::None); // inverse search radius optimization structure.
|
||||
#endif
|
||||
this->addOutputSocket(DataType::Color);
|
||||
this->setComplex(true);
|
||||
|
@ -278,7 +278,7 @@ bool VariableSizeBokehBlurOperation::determineDependingAreaOfInterest(
|
|||
// InverseSearchRadiusOperation
|
||||
InverseSearchRadiusOperation::InverseSearchRadiusOperation()
|
||||
{
|
||||
this->addInputSocket(DataType::Value, COM_SC_NO_RESIZE); // radius
|
||||
this->addInputSocket(DataType::Value, ResizeMode::None); // radius
|
||||
this->addOutputSocket(DataType::Color);
|
||||
this->setComplex(true);
|
||||
this->m_inputRadius = nullptr;
|
||||
|
@ -319,7 +319,7 @@ void *InverseSearchRadiusOperation::initializeTileData(rcti *rect)
|
|||
|
||||
// for (int x2 = 0 ; x2 < DIVIDER ; x2 ++) {
|
||||
// for (int y2 = 0 ; y2 < DIVIDER ; y2 ++) {
|
||||
// this->m_inputRadius->read(temp, rx+x2, ry+y2, COM_PS_NEAREST);
|
||||
// this->m_inputRadius->read(temp, rx+x2, ry+y2, PixelSampler::Nearest);
|
||||
// if (radius < temp[0]) {
|
||||
// radius = temp[0];
|
||||
// maxx = x2;
|
||||
|
|
|
@ -98,12 +98,12 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
|
|||
|
||||
for (y = y1; y < y2 && (!breaked); y++) {
|
||||
for (x = x1; x < x2; x++) {
|
||||
this->m_imageInput->readSampled(&(buffer[offset4]), x, y, COM_PS_NEAREST);
|
||||
this->m_imageInput->readSampled(&(buffer[offset4]), x, y, PixelSampler::Nearest);
|
||||
if (this->m_useAlphaInput) {
|
||||
this->m_alphaInput->readSampled(alpha, x, y, COM_PS_NEAREST);
|
||||
this->m_alphaInput->readSampled(alpha, x, y, PixelSampler::Nearest);
|
||||
buffer[offset4 + 3] = alpha[0];
|
||||
}
|
||||
this->m_depthInput->readSampled(depth, x, y, COM_PS_NEAREST);
|
||||
this->m_depthInput->readSampled(depth, x, y, PixelSampler::Nearest);
|
||||
depthbuffer[offset] = depth[0];
|
||||
|
||||
offset++;
|
||||
|
|
|
@ -97,7 +97,7 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/
|
|||
for (y = y1; y < y2 && (!breaked); y++) {
|
||||
int offset4 = (y * memoryBuffer->getWidth() + x1) * num_channels;
|
||||
for (x = x1; x < x2; x++) {
|
||||
this->m_input->readSampled(&(buffer[offset4]), x, y, COM_PS_NEAREST);
|
||||
this->m_input->readSampled(&(buffer[offset4]), x, y, PixelSampler::Nearest);
|
||||
offset4 += num_channels;
|
||||
}
|
||||
if (isBraked()) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue