Merge branch 'refactor-mesh-position-generic' into refactor-mesh-corners-generic
This commit is contained in:
commit
06265a6a06
|
@ -1532,7 +1532,7 @@ ccl_device_extern void osl_texture_set_missingcolor_alpha(ccl_private OSLTexture
|
|||
ccl_device_extern bool osl_texture(ccl_private ShaderGlobals *sg,
|
||||
DeviceString filename,
|
||||
ccl_private void *texture_handle,
|
||||
OSLTextureOptions *opt,
|
||||
ccl_private OSLTextureOptions *opt,
|
||||
float s,
|
||||
float t,
|
||||
float dsdx,
|
||||
|
@ -1557,13 +1557,14 @@ ccl_device_extern bool osl_texture(ccl_private ShaderGlobals *sg,
|
|||
|
||||
const float4 rgba = kernel_tex_image_interp(nullptr, id, s, 1.0f - t);
|
||||
|
||||
result[0] = rgba.x;
|
||||
if (nchannels > 0)
|
||||
result[0] = rgba.x;
|
||||
if (nchannels > 1)
|
||||
result[1] = rgba.y;
|
||||
if (nchannels > 2)
|
||||
result[2] = rgba.z;
|
||||
if (nchannels > 3)
|
||||
result[3] = rgba.w;
|
||||
if (alpha)
|
||||
*alpha = rgba.w;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1571,7 +1572,7 @@ ccl_device_extern bool osl_texture(ccl_private ShaderGlobals *sg,
|
|||
ccl_device_extern bool osl_texture3d(ccl_private ShaderGlobals *sg,
|
||||
DeviceString filename,
|
||||
ccl_private void *texture_handle,
|
||||
OSLTextureOptions *opt,
|
||||
ccl_private OSLTextureOptions *opt,
|
||||
ccl_private const float3 *P,
|
||||
ccl_private const float3 *dPdx,
|
||||
ccl_private const float3 *dPdy,
|
||||
|
@ -1594,13 +1595,14 @@ ccl_device_extern bool osl_texture3d(ccl_private ShaderGlobals *sg,
|
|||
|
||||
const float4 rgba = kernel_tex_image_interp_3d(nullptr, id, *P, INTERPOLATION_NONE);
|
||||
|
||||
result[0] = rgba.x;
|
||||
if (nchannels > 0)
|
||||
result[0] = rgba.x;
|
||||
if (nchannels > 1)
|
||||
result[1] = rgba.y;
|
||||
if (nchannels > 2)
|
||||
result[2] = rgba.z;
|
||||
if (nchannels > 3)
|
||||
result[3] = rgba.w;
|
||||
if (alpha)
|
||||
*alpha = rgba.w;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1608,7 +1610,7 @@ ccl_device_extern bool osl_texture3d(ccl_private ShaderGlobals *sg,
|
|||
ccl_device_extern bool osl_environment(ccl_private ShaderGlobals *sg,
|
||||
DeviceString filename,
|
||||
ccl_private void *texture_handle,
|
||||
OSLTextureOptions *opt,
|
||||
ccl_private OSLTextureOptions *opt,
|
||||
ccl_private const float3 *R,
|
||||
ccl_private const float3 *dRdx,
|
||||
ccl_private const float3 *dRdy,
|
||||
|
@ -1621,13 +1623,14 @@ ccl_device_extern bool osl_environment(ccl_private ShaderGlobals *sg,
|
|||
ccl_private float *dalphay,
|
||||
ccl_private void *errormessage)
|
||||
{
|
||||
result[0] = 1.0f;
|
||||
if (nchannels > 0)
|
||||
result[0] = 1.0f;
|
||||
if (nchannels > 1)
|
||||
result[1] = 0.0f;
|
||||
if (nchannels > 2)
|
||||
result[2] = 1.0f;
|
||||
if (nchannels > 3)
|
||||
result[3] = 1.0f;
|
||||
if (alpha)
|
||||
*alpha = 1.0f;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -540,7 +540,7 @@ class CLIP_OT_setup_tracking_scene(Operator):
|
|||
sc = context.space_data
|
||||
if sc and sc.type == 'CLIP_EDITOR':
|
||||
clip = sc.clip
|
||||
if clip and clip.tracking.reconstruction.is_valid:
|
||||
if clip and clip.tracking.objects.active.reconstruction.is_valid:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*
|
||||
* Pose Backups can be created from the current pose, and later restored. The
|
||||
* backup is restricted to those bones animated by a given Action, so that
|
||||
* operations are as fast as possible.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct PoseBackup;
|
||||
|
||||
/**
|
||||
* Create a backup of those bones that are selected AND animated in the given action.
|
||||
*
|
||||
* The backup is owned by the caller, and should be freed with `BKE_pose_backup_free()`.
|
||||
*/
|
||||
struct PoseBackup *BKE_pose_backup_create_selected_bones(
|
||||
const struct Object *ob, const struct bAction *action) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* Create a backup of those bones that are animated in the given action.
|
||||
*
|
||||
* The backup is owned by the caller, and should be freed with `BKE_pose_backup_free()`.
|
||||
*/
|
||||
struct PoseBackup *BKE_pose_backup_create_all_bones(
|
||||
const struct Object *ob, const struct bAction *action) ATTR_WARN_UNUSED_RESULT;
|
||||
bool BKE_pose_backup_is_selection_relevant(const struct PoseBackup *pose_backup);
|
||||
void BKE_pose_backup_restore(const struct PoseBackup *pbd);
|
||||
void BKE_pose_backup_free(struct PoseBackup *pbd);
|
||||
|
||||
/**
|
||||
* Create a backup of those bones that are animated in the given action.
|
||||
*
|
||||
* The backup is owned by the Object, and there can be only one backup at a time.
|
||||
* It should be freed with `BKE_pose_backup_clear(ob)`.
|
||||
*/
|
||||
void BKE_pose_backup_create_on_object(struct Object *ob, const struct bAction *action);
|
||||
|
||||
/**
|
||||
* Restore the pose backup owned by this OBject.
|
||||
*
|
||||
* \return true on success, false if there was no pose backup to restore.
|
||||
*
|
||||
* \see #BKE_pose_backup_create_on_object
|
||||
*/
|
||||
bool BKE_pose_backup_restore_on_object(struct Object *ob);
|
||||
|
||||
/**
|
||||
* Free the pose backup that was stored on this object's runtime data.
|
||||
*/
|
||||
void BKE_pose_backup_clear(struct Object *ob);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -254,6 +254,7 @@ set(SRC
|
|||
intern/pbvh_uv_islands.cc
|
||||
intern/pointcache.c
|
||||
intern/pointcloud.cc
|
||||
intern/pose_backup.cc
|
||||
intern/preferences.c
|
||||
intern/report.c
|
||||
intern/rigidbody.c
|
||||
|
|
|
@ -1462,7 +1462,7 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
|||
|
||||
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, ((ID *)ob->data)->name + 2);
|
||||
|
||||
mesh->totvert = (int)process.curvertex;
|
||||
mesh->totvert = int(process.curvertex);
|
||||
CustomData_add_layer_named(
|
||||
&mesh->vdata, CD_PROP_FLOAT3, CD_ASSIGN, process.co, mesh->totvert, "position");
|
||||
process.co = nullptr;
|
||||
|
|
|
@ -3558,8 +3558,6 @@ void nodeSetActive(bNodeTree *ntree, bNode *node)
|
|||
node->flag |= flags_to_set;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void nodeSetSocketAvailability(bNodeTree *ntree, bNodeSocket *sock, bool is_available)
|
||||
{
|
||||
const bool was_available = (sock->flag & SOCK_UNAVAIL) == 0;
|
||||
|
|
|
@ -117,6 +117,7 @@
|
|||
#include "BKE_pbvh.h"
|
||||
#include "BKE_pointcache.h"
|
||||
#include "BKE_pointcloud.h"
|
||||
#include "BKE_pose_backup.h"
|
||||
#include "BKE_rigidbody.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_shader_fx.h"
|
||||
|
@ -1814,6 +1815,7 @@ void BKE_object_free_derived_caches(Object *ob)
|
|||
}
|
||||
|
||||
BKE_object_to_mesh_clear(ob);
|
||||
BKE_pose_backup_clear(ob);
|
||||
BKE_object_to_curve_clear(ob);
|
||||
BKE_object_free_curve_cache(ob);
|
||||
|
||||
|
@ -5132,6 +5134,7 @@ void BKE_object_runtime_reset_on_copy(Object *object, const int /*flag*/)
|
|||
runtime->mesh_deform_eval = nullptr;
|
||||
runtime->curve_cache = nullptr;
|
||||
runtime->object_as_temp_mesh = nullptr;
|
||||
runtime->pose_backup = nullptr;
|
||||
runtime->object_as_temp_curve = nullptr;
|
||||
runtime->geometry_set_eval = nullptr;
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edarmature
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "ED_armature.h"
|
||||
#include "BKE_pose_backup.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
@ -38,6 +38,14 @@ struct PoseBackup {
|
|||
ListBase /* PoseChannelBackup* */ backups;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a backup of the pose, for only those bones that are animated in the
|
||||
* given Action. If `selected_bone_names` is not empty, the set of bones to back
|
||||
* up is intersected with these bone names such that only the selected subset is
|
||||
* backed up.
|
||||
*
|
||||
* The returned pointer is owned by the caller.
|
||||
*/
|
||||
static PoseBackup *pose_backup_create(const Object *ob,
|
||||
const bAction *action,
|
||||
const BoneNameSet &selected_bone_names)
|
||||
|
@ -86,24 +94,24 @@ static PoseBackup *pose_backup_create(const Object *ob,
|
|||
return pose_backup;
|
||||
}
|
||||
|
||||
PoseBackup *ED_pose_backup_create_all_bones(const Object *ob, const bAction *action)
|
||||
PoseBackup *BKE_pose_backup_create_all_bones(const Object *ob, const bAction *action)
|
||||
{
|
||||
return pose_backup_create(ob, action, BoneNameSet());
|
||||
}
|
||||
|
||||
PoseBackup *ED_pose_backup_create_selected_bones(const Object *ob, const bAction *action)
|
||||
PoseBackup *BKE_pose_backup_create_selected_bones(const Object *ob, const bAction *action)
|
||||
{
|
||||
const bArmature *armature = static_cast<const bArmature *>(ob->data);
|
||||
const BoneNameSet selected_bone_names = BKE_armature_find_selected_bone_names(armature);
|
||||
return pose_backup_create(ob, action, selected_bone_names);
|
||||
}
|
||||
|
||||
bool ED_pose_backup_is_selection_relevant(const struct PoseBackup *pose_backup)
|
||||
bool BKE_pose_backup_is_selection_relevant(const struct PoseBackup *pose_backup)
|
||||
{
|
||||
return pose_backup->is_bone_selection_relevant;
|
||||
}
|
||||
|
||||
void ED_pose_backup_restore(const PoseBackup *pbd)
|
||||
void BKE_pose_backup_restore(const PoseBackup *pbd)
|
||||
{
|
||||
LISTBASE_FOREACH (PoseChannelBackup *, chan_bak, &pbd->backups) {
|
||||
memcpy(chan_bak->pchan, &chan_bak->olddata, sizeof(chan_bak->olddata));
|
||||
|
@ -117,7 +125,7 @@ void ED_pose_backup_restore(const PoseBackup *pbd)
|
|||
}
|
||||
}
|
||||
|
||||
void ED_pose_backup_free(PoseBackup *pbd)
|
||||
void BKE_pose_backup_free(PoseBackup *pbd)
|
||||
{
|
||||
LISTBASE_FOREACH_MUTABLE (PoseChannelBackup *, chan_bak, &pbd->backups) {
|
||||
if (chan_bak->oldprops) {
|
||||
|
@ -127,3 +135,29 @@ void ED_pose_backup_free(PoseBackup *pbd)
|
|||
}
|
||||
MEM_freeN(pbd);
|
||||
}
|
||||
|
||||
void BKE_pose_backup_create_on_object(Object *ob, const bAction *action)
|
||||
{
|
||||
BKE_pose_backup_clear(ob);
|
||||
PoseBackup *pose_backup = BKE_pose_backup_create_all_bones(ob, action);
|
||||
ob->runtime.pose_backup = pose_backup;
|
||||
}
|
||||
|
||||
bool BKE_pose_backup_restore_on_object(struct Object *ob)
|
||||
{
|
||||
if (ob->runtime.pose_backup == nullptr) {
|
||||
return false;
|
||||
}
|
||||
BKE_pose_backup_restore(ob->runtime.pose_backup);
|
||||
return true;
|
||||
}
|
||||
|
||||
void BKE_pose_backup_clear(Object *ob)
|
||||
{
|
||||
if (ob->runtime.pose_backup == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
BKE_pose_backup_free(ob->runtime.pose_backup);
|
||||
ob->runtime.pose_backup = nullptr;
|
||||
}
|
|
@ -88,8 +88,8 @@ struct bNodeSocket *version_node_add_socket_if_not_exist(struct bNodeTree *ntree
|
|||
const char *name);
|
||||
|
||||
/**
|
||||
* The versioning code generally expects `SOCK_IS_LINKED` to be set correctly. This function updates
|
||||
* the flag on all sockets after changes to the node tree.
|
||||
* The versioning code generally expects `SOCK_IS_LINKED` to be set correctly. This function
|
||||
* updates the flag on all sockets after changes to the node tree.
|
||||
*/
|
||||
void version_socket_update_is_used(bNodeTree *ntree);
|
||||
ARegion *do_versions_add_region(int regiontype, const char *name);
|
||||
|
|
|
@ -1675,8 +1675,11 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
|
|||
continue;
|
||||
}
|
||||
|
||||
OperationCode target_op = driver_targets_bbone ? OperationCode::BONE_SEGMENTS :
|
||||
OperationCode::BONE_LOCAL;
|
||||
OperationCode target_op = OperationCode::BONE_LOCAL;
|
||||
if (driver_targets_bbone) {
|
||||
target_op = check_pchan_has_bbone_segments(object, pchan) ? OperationCode::BONE_SEGMENTS :
|
||||
OperationCode::BONE_DONE;
|
||||
}
|
||||
OperationKey bone_key(&object->id, NodeType::BONE, pchan->name, target_op);
|
||||
add_relation(driver_key, bone_key, "Arm Bone -> Driver -> Bone");
|
||||
}
|
||||
|
|
|
@ -105,8 +105,7 @@ void evaluate_node(const DepsgraphEvalState *state, OperationNode *operation_nod
|
|||
* times.
|
||||
* This is a thread-safe modification as the node's flags are only read for a non-scheduled nodes
|
||||
* and this node has been scheduled. */
|
||||
operation_node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE |
|
||||
DEPSOP_FLAG_USER_MODIFIED);
|
||||
operation_node->flag &= ~DEPSOP_FLAG_CLEAR_ON_EVAL;
|
||||
}
|
||||
|
||||
void deg_task_run_func(TaskPool *pool, void *taskdata)
|
||||
|
@ -270,6 +269,10 @@ void schedule_node(DepsgraphEvalState *state,
|
|||
bool is_scheduled = atomic_fetch_and_or_uint8((uint8_t *)&node->scheduled, uint8_t(true));
|
||||
if (!is_scheduled) {
|
||||
if (node->is_noop()) {
|
||||
/* Clear flags to avoid affecting subsequent update propagation.
|
||||
* For normal nodes these are cleared when it is evaluated. */
|
||||
node->flag &= ~DEPSOP_FLAG_CLEAR_ON_EVAL;
|
||||
|
||||
/* skip NOOP node, schedule children right away */
|
||||
schedule_children(state, node, schedule_fn);
|
||||
}
|
||||
|
|
|
@ -224,6 +224,10 @@ enum OperationFlag {
|
|||
|
||||
/* Set of flags which gets flushed along the relations. */
|
||||
DEPSOP_FLAG_FLUSH = (DEPSOP_FLAG_USER_MODIFIED),
|
||||
|
||||
/* Set of flags which get cleared upon evaluation. */
|
||||
DEPSOP_FLAG_CLEAR_ON_EVAL = (DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE |
|
||||
DEPSOP_FLAG_USER_MODIFIED),
|
||||
};
|
||||
|
||||
/* Atomic Operation - Base type for all operations */
|
||||
|
|
|
@ -30,7 +30,6 @@ set(SRC
|
|||
armature_utils.c
|
||||
editarmature_undo.c
|
||||
meshlaplacian.c
|
||||
pose_backup.cc
|
||||
pose_edit.c
|
||||
pose_group.c
|
||||
pose_lib_2.c
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "BKE_context.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_pose_backup.h"
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
@ -37,7 +38,6 @@
|
|||
|
||||
#include "UI_interface.h"
|
||||
|
||||
#include "ED_armature.h"
|
||||
#include "ED_asset.h"
|
||||
#include "ED_keyframing.h"
|
||||
#include "ED_screen.h"
|
||||
|
@ -83,10 +83,12 @@ typedef struct PoseBlendData {
|
|||
char headerstr[UI_MAX_DRAW_STR];
|
||||
} PoseBlendData;
|
||||
|
||||
static void poselib_blend_flip_pose(bContext *C, wmOperator *op);
|
||||
|
||||
/* Makes a copy of the current pose for restoration purposes - doesn't do constraints currently */
|
||||
static void poselib_backup_posecopy(PoseBlendData *pbd)
|
||||
{
|
||||
pbd->pose_backup = ED_pose_backup_create_selected_bones(pbd->ob, pbd->act);
|
||||
pbd->pose_backup = BKE_pose_backup_create_selected_bones(pbd->ob, pbd->act);
|
||||
|
||||
if (pbd->state == POSE_BLEND_INIT) {
|
||||
/* Ready for blending now. */
|
||||
|
@ -125,7 +127,7 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, PoseBlendData *pbd)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ED_pose_backup_is_selection_relevant(pbd->pose_backup) &&
|
||||
if (BKE_pose_backup_is_selection_relevant(pbd->pose_backup) &&
|
||||
!PBONE_SELECTED(armature, pchan->bone)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -152,7 +154,7 @@ static void poselib_blend_apply(bContext *C, wmOperator *op)
|
|||
}
|
||||
pbd->needs_redraw = false;
|
||||
|
||||
ED_pose_backup_restore(pbd->pose_backup);
|
||||
BKE_pose_backup_restore(pbd->pose_backup);
|
||||
|
||||
/* The pose needs updating, whether it's for restoring the original pose or for showing the
|
||||
* result of the blend. */
|
||||
|
@ -178,7 +180,7 @@ static void poselib_blend_set_factor(PoseBlendData *pbd, const float new_factor)
|
|||
}
|
||||
|
||||
/* Return operator return value. */
|
||||
static int poselib_blend_handle_event(bContext *UNUSED(C), wmOperator *op, const wmEvent *event)
|
||||
static int poselib_blend_handle_event(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
PoseBlendData *pbd = op->customdata;
|
||||
|
||||
|
@ -225,7 +227,9 @@ static int poselib_blend_handle_event(bContext *UNUSED(C), wmOperator *op, const
|
|||
pbd->needs_redraw = true;
|
||||
break;
|
||||
|
||||
/* TODO(Sybren): use better UI for slider. */
|
||||
case EVT_FKEY:
|
||||
poselib_blend_flip_pose(C, op);
|
||||
break;
|
||||
}
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
|
@ -276,6 +280,30 @@ static bAction *flip_pose(bContext *C, Object *ob, bAction *action)
|
|||
return action_copy;
|
||||
}
|
||||
|
||||
/* Flip the target pose the interactive blend operator is currently using. */
|
||||
static void poselib_blend_flip_pose(bContext *C, wmOperator *op)
|
||||
{
|
||||
PoseBlendData *pbd = op->customdata;
|
||||
bAction *old_action = pbd->act;
|
||||
bAction *new_action = flip_pose(C, pbd->ob, old_action);
|
||||
|
||||
/* Before flipping over to the other side, this side needs to be restored. */
|
||||
BKE_pose_backup_restore(pbd->pose_backup);
|
||||
BKE_pose_backup_free(pbd->pose_backup);
|
||||
pbd->pose_backup = NULL;
|
||||
|
||||
if (pbd->free_action) {
|
||||
BKE_id_free(NULL, old_action);
|
||||
}
|
||||
|
||||
pbd->free_action = true;
|
||||
pbd->act = new_action;
|
||||
pbd->needs_redraw = true;
|
||||
|
||||
/* Refresh the pose backup to use the flipped bones. */
|
||||
poselib_backup_posecopy(pbd);
|
||||
}
|
||||
|
||||
/* Return true on success, false if the context isn't suitable. */
|
||||
static bool poselib_blend_init_data(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
|
@ -381,7 +409,7 @@ static void poselib_blend_cleanup(bContext *C, wmOperator *op)
|
|||
BKE_report(op->reports, RPT_ERROR, "Internal pose library error, canceling operator");
|
||||
ATTR_FALLTHROUGH;
|
||||
case POSE_BLEND_CANCEL:
|
||||
ED_pose_backup_restore(pbd->pose_backup);
|
||||
BKE_pose_backup_restore(pbd->pose_backup);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -406,7 +434,7 @@ static void poselib_blend_free(wmOperator *op)
|
|||
poselib_tempload_exit(pbd);
|
||||
|
||||
/* Free temp data for operator */
|
||||
ED_pose_backup_free(pbd->pose_backup);
|
||||
BKE_pose_backup_free(pbd->pose_backup);
|
||||
pbd->pose_backup = NULL;
|
||||
|
||||
MEM_SAFE_FREE(op->customdata);
|
||||
|
@ -461,7 +489,11 @@ static int poselib_blend_modal(bContext *C, wmOperator *op, const wmEvent *event
|
|||
strcpy(tab_string, TIP_("[Tab] - Show blended pose"));
|
||||
}
|
||||
|
||||
BLI_snprintf(status_string, sizeof(status_string), "%s | %s", tab_string, slider_string);
|
||||
BLI_snprintf(status_string,
|
||||
sizeof(status_string),
|
||||
"[F] - Flip pose | %s | %s",
|
||||
tab_string,
|
||||
slider_string);
|
||||
ED_workspace_status_text(C, status_string);
|
||||
|
||||
poselib_blend_apply(C, op);
|
||||
|
|
|
@ -3356,7 +3356,7 @@ void ED_gpencil_layer_merge(bGPdata *gpd,
|
|||
}
|
||||
}
|
||||
|
||||
void gpencil_layer_new_name_get(bGPdata *gpd, char *rname)
|
||||
static void gpencil_layer_new_name_get(bGPdata *gpd, char *rname)
|
||||
{
|
||||
int index = 0;
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
|
|
|
@ -369,19 +369,6 @@ void ED_mesh_deform_bind_callback(struct Object *object,
|
|||
int verts_num,
|
||||
float cagemat[4][4]);
|
||||
|
||||
/* Pose backups, pose_backup.c */
|
||||
struct PoseBackup;
|
||||
/**
|
||||
* Create a backup of those bones that are animated in the given action.
|
||||
*/
|
||||
struct PoseBackup *ED_pose_backup_create_selected_bones(
|
||||
const struct Object *ob, const struct bAction *action) ATTR_WARN_UNUSED_RESULT;
|
||||
struct PoseBackup *ED_pose_backup_create_all_bones(
|
||||
const struct Object *ob, const struct bAction *action) ATTR_WARN_UNUSED_RESULT;
|
||||
bool ED_pose_backup_is_selection_relevant(const struct PoseBackup *pose_backup);
|
||||
void ED_pose_backup_restore(const struct PoseBackup *pbd);
|
||||
void ED_pose_backup_free(struct PoseBackup *pbd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meta_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_pointcloud_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_array.hh"
|
||||
|
@ -44,6 +45,7 @@
|
|||
#include "BKE_mesh.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_pointcloud.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_tracking.h"
|
||||
|
@ -639,6 +641,17 @@ static bool apply_objects_internal_need_single_user(bContext *C)
|
|||
return (ID_REAL_USERS(ob->data) > CTX_DATA_COUNT(C, selected_editable_objects));
|
||||
}
|
||||
|
||||
static void transform_positions(blender::MutableSpan<blender::float3> positions,
|
||||
const blender::float4x4 &matrix)
|
||||
{
|
||||
using namespace blender;
|
||||
threading::parallel_for(positions.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (float3 &position : positions.slice(range)) {
|
||||
position = matrix * position;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static int apply_objects_internal(bContext *C,
|
||||
ReportList *reports,
|
||||
bool apply_loc,
|
||||
|
@ -647,6 +660,7 @@ static int apply_objects_internal(bContext *C,
|
|||
bool do_props,
|
||||
bool do_single_user)
|
||||
{
|
||||
using namespace blender;
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
|
@ -696,7 +710,8 @@ static int apply_objects_internal(bContext *C,
|
|||
OB_SURF,
|
||||
OB_FONT,
|
||||
OB_GPENCIL,
|
||||
OB_CURVES)) {
|
||||
OB_CURVES,
|
||||
OB_POINTCLOUD)) {
|
||||
ID *obdata = static_cast<ID *>(ob->data);
|
||||
if (!do_multi_user && ID_REAL_USERS(obdata) > 1) {
|
||||
BKE_reportf(reports,
|
||||
|
@ -932,6 +947,14 @@ static int apply_objects_internal(bContext *C,
|
|||
blender::bke::CurvesGeometry::wrap(curves.geometry).transform(mat);
|
||||
blender::bke::CurvesGeometry::wrap(curves.geometry).calculate_bezier_auto_handles();
|
||||
}
|
||||
else if (ob->type == OB_POINTCLOUD) {
|
||||
PointCloud &pointcloud = *static_cast<PointCloud *>(ob->data);
|
||||
bke::MutableAttributeAccessor attributes = pointcloud.attributes_for_write();
|
||||
bke::SpanAttributeWriter position = attributes.lookup_or_add_for_write_span<float3>(
|
||||
"position", ATTR_DOMAIN_POINT);
|
||||
transform_positions(position.span, float4x4(mat));
|
||||
position.finish();
|
||||
}
|
||||
else if (ob->type == OB_CAMERA) {
|
||||
MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
|
||||
|
||||
|
@ -1230,8 +1253,29 @@ enum {
|
|||
ORIGIN_TO_CENTER_OF_MASS_VOLUME,
|
||||
};
|
||||
|
||||
static float3 calculate_mean(const blender::Span<blender::float3> values)
|
||||
{
|
||||
if (values.is_empty()) {
|
||||
return float3(0);
|
||||
}
|
||||
/* TODO: Use a method that avoids overflow. */
|
||||
return std::accumulate(values.begin(), values.end(), float3(0)) / values.size();
|
||||
}
|
||||
|
||||
static void translate_positions(blender::MutableSpan<blender::float3> positions,
|
||||
const blender::float3 &translation)
|
||||
{
|
||||
using namespace blender;
|
||||
threading::parallel_for(positions.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (float3 &position : positions.slice(range)) {
|
||||
position += translation;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static int object_origin_set_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
using namespace blender;
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *obact = CTX_data_active_object(C);
|
||||
|
@ -1653,9 +1697,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
}
|
||||
else if (around == V3D_AROUND_CENTER_MEDIAN) {
|
||||
Span<float3> positions = curves.positions();
|
||||
cent = std::accumulate(positions.begin(), positions.end(), float3(0)) /
|
||||
curves.points_num();
|
||||
cent = calculate_mean(curves.positions());
|
||||
}
|
||||
|
||||
tot_change++;
|
||||
|
@ -1663,6 +1705,39 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
|
|||
curves_id.id.tag |= LIB_TAG_DOIT;
|
||||
do_inverse_offset = true;
|
||||
}
|
||||
else if (ob->type == OB_POINTCLOUD) {
|
||||
PointCloud &pointcloud = *static_cast<PointCloud *>(ob->data);
|
||||
bke::MutableAttributeAccessor attributes = pointcloud.attributes_for_write();
|
||||
bke::SpanAttributeWriter positions = attributes.lookup_or_add_for_write_span<float3>(
|
||||
"position", ATTR_DOMAIN_POINT);
|
||||
if (ELEM(centermode, ORIGIN_TO_CENTER_OF_MASS_SURFACE, ORIGIN_TO_CENTER_OF_MASS_VOLUME) ||
|
||||
!ELEM(around, V3D_AROUND_CENTER_BOUNDS, V3D_AROUND_CENTER_MEDIAN)) {
|
||||
BKE_report(op->reports,
|
||||
RPT_WARNING,
|
||||
"Point cloud object does not support this set origin operation");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (centermode == ORIGIN_TO_CURSOR) {
|
||||
/* Done. */
|
||||
}
|
||||
else if (around == V3D_AROUND_CENTER_BOUNDS) {
|
||||
float3 min(std::numeric_limits<float>::max());
|
||||
float3 max(-std::numeric_limits<float>::max());
|
||||
if (pointcloud.bounds_min_max(min, max)) {
|
||||
cent = math::midpoint(min, max);
|
||||
}
|
||||
}
|
||||
else if (around == V3D_AROUND_CENTER_MEDIAN) {
|
||||
cent = calculate_mean(positions.span);
|
||||
}
|
||||
|
||||
tot_change++;
|
||||
translate_positions(positions.span, -cent);
|
||||
positions.finish();
|
||||
pointcloud.id.tag |= LIB_TAG_DOIT;
|
||||
do_inverse_offset = true;
|
||||
}
|
||||
|
||||
/* offset other selected objects */
|
||||
if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "BKE_material.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_pose_backup.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_texture.h"
|
||||
|
@ -81,7 +82,6 @@
|
|||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "ED_armature.h"
|
||||
#include "ED_datafiles.h"
|
||||
#include "ED_render.h"
|
||||
#include "ED_screen.h"
|
||||
|
@ -955,7 +955,7 @@ static struct PoseBackup *action_preview_render_prepare(IconPreview *preview)
|
|||
|
||||
/* Create a backup of the current pose. */
|
||||
struct bAction *action = (struct bAction *)preview->id;
|
||||
struct PoseBackup *pose_backup = ED_pose_backup_create_all_bones(object, action);
|
||||
struct PoseBackup *pose_backup = BKE_pose_backup_create_all_bones(object, action);
|
||||
|
||||
/* Apply the Action as pose, so that it can be rendered. This assumes the Action represents a
|
||||
* single pose, and that thus the evaluation time doesn't matter. */
|
||||
|
@ -974,8 +974,8 @@ static void action_preview_render_cleanup(IconPreview *preview, struct PoseBacku
|
|||
if (pose_backup == nullptr) {
|
||||
return;
|
||||
}
|
||||
ED_pose_backup_restore(pose_backup);
|
||||
ED_pose_backup_free(pose_backup);
|
||||
BKE_pose_backup_restore(pose_backup);
|
||||
BKE_pose_backup_free(pose_backup);
|
||||
|
||||
DEG_id_tag_update(&preview->active_object->id, ID_RECALC_GEOMETRY);
|
||||
}
|
||||
|
|
|
@ -2144,11 +2144,9 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
|
|||
BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &nodes_num);
|
||||
for (int i = 0; i < nodes_num; i++) {
|
||||
PBVHVertexIter vd;
|
||||
bool update = false;
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, nodes[i], vd, PBVH_ITER_UNIQUE) {
|
||||
*vd.mask = 1.0f;
|
||||
update = true;
|
||||
}
|
||||
BKE_pbvh_vertex_iter_end;
|
||||
|
||||
|
|
|
@ -1293,7 +1293,8 @@ static void std_node_socket_draw(
|
|||
return;
|
||||
}
|
||||
|
||||
if ((sock->in_out == SOCK_OUT) || (sock->flag & SOCK_IS_LINKED) || (sock->flag & SOCK_HIDE_VALUE)) {
|
||||
if ((sock->in_out == SOCK_OUT) || (sock->flag & SOCK_IS_LINKED) ||
|
||||
(sock->flag & SOCK_HIDE_VALUE)) {
|
||||
node_socket_button_label(C, layout, ptr, node_ptr, text);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -75,10 +75,13 @@ typedef struct tSlider {
|
|||
/** Last mouse cursor position used for mouse movement delta calculation. */
|
||||
float last_cursor[2];
|
||||
|
||||
/** Enable range beyond 0-100%. */
|
||||
/** Enable range beyond 0-100%.
|
||||
* This is set by the code that uses the slider, as not all operations support
|
||||
* extrapolation. */
|
||||
bool allow_overshoot;
|
||||
|
||||
/** Allow overshoot or clamp between 0% and 100%. */
|
||||
/** Allow overshoot or clamp between 0% and 100%.
|
||||
* This is set by the artist while using the slider. */
|
||||
bool overshoot;
|
||||
|
||||
/** Move factor in 10% steps. */
|
||||
|
|
|
@ -355,7 +355,7 @@ class Executor {
|
|||
this->ensure_thread_locals();
|
||||
/* Construct all node states in parallel. */
|
||||
threading::parallel_for(nodes.index_range(), 256, [&](const IndexRange range) {
|
||||
LinearAllocator<> &allocator = this->get_main_or_local_allocator();
|
||||
LinearAllocator<> &allocator = thread_locals_->local().allocator;
|
||||
construct_node_range(range, allocator);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -337,6 +337,9 @@ void OBJWriter::write_poly_elements(FormatHandler &fh,
|
|||
const int tot_polygons = obj_mesh_data.tot_polygons();
|
||||
const int tot_deform_groups = obj_mesh_data.tot_deform_groups();
|
||||
threading::EnumerableThreadSpecific<Vector<float>> group_weights;
|
||||
const bke::AttributeAccessor attributes = obj_mesh_data.get_mesh()->attributes();
|
||||
const VArray<int> material_indices = attributes.lookup_or_default<int>(
|
||||
"material_index", ATTR_DOMAIN_FACE, 0);
|
||||
|
||||
obj_parallel_chunked_output(fh, tot_polygons, [&](FormatHandler &buf, int idx) {
|
||||
/* Polygon order for writing into the file is not necessarily the same
|
||||
|
@ -372,10 +375,6 @@ void OBJWriter::write_poly_elements(FormatHandler &fh,
|
|||
}
|
||||
}
|
||||
|
||||
const bke::AttributeAccessor attributes = obj_mesh_data.get_mesh()->attributes();
|
||||
const VArray<int> material_indices = attributes.lookup_or_default<int>(
|
||||
"material_index", ATTR_DOMAIN_FACE, 0);
|
||||
|
||||
/* Write material name and material group if different from previous. */
|
||||
if (export_params_.export_materials && obj_mesh_data.tot_materials() > 0) {
|
||||
const int16_t prev_mat = idx == 0 ? NEGATIVE_INIT : std::max(0, material_indices[prev_i]);
|
||||
|
@ -392,7 +391,7 @@ void OBJWriter::write_poly_elements(FormatHandler &fh,
|
|||
if (export_params_.export_material_groups) {
|
||||
std::string object_name = obj_mesh_data.get_object_name();
|
||||
spaces_to_underscores(object_name);
|
||||
fh.write_obj_group(object_name + "_" + mat_name);
|
||||
buf.write_obj_group(object_name + "_" + mat_name);
|
||||
}
|
||||
buf.write_obj_usemtl(mat_name);
|
||||
}
|
||||
|
|
|
@ -192,6 +192,14 @@ typedef struct Object_Runtime {
|
|||
*/
|
||||
struct Mesh *object_as_temp_mesh;
|
||||
|
||||
/**
|
||||
* Backup of the object's pose (might be a subset, i.e. not contain all bones).
|
||||
*
|
||||
* Created by `BKE_pose_backup_create_on_object()`. This memory is owned by the Object.
|
||||
* It is freed along with the object, or when `BKE_pose_backup_clear()` is called.
|
||||
*/
|
||||
struct PoseBackup *pose_backup;
|
||||
|
||||
/**
|
||||
* This is a curve representation of corresponding object.
|
||||
* It created when Python calls `object.to_curve()`.
|
||||
|
@ -200,6 +208,7 @@ typedef struct Object_Runtime {
|
|||
|
||||
/** Runtime evaluated curve-specific data, not stored in the file. */
|
||||
struct CurveCache *curve_cache;
|
||||
void *_pad4;
|
||||
|
||||
unsigned short local_collections_bits;
|
||||
short _pad2[3];
|
||||
|
|
|
@ -712,9 +712,9 @@ static void rna_AttributeGroup_active_color_name_set(PointerRNA *ptr, const char
|
|||
ID *id = ptr->owner_id;
|
||||
if (GS(id->name) == ID_ME) {
|
||||
Mesh *mesh = (Mesh *)id;
|
||||
MEM_SAFE_FREE(mesh->default_color_attribute);
|
||||
MEM_SAFE_FREE(mesh->active_color_attribute);
|
||||
if (value[0]) {
|
||||
mesh->default_color_attribute = BLI_strdup(value);
|
||||
mesh->active_color_attribute = BLI_strdup(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
# include "BKE_animsys.h"
|
||||
# include "BKE_armature.h"
|
||||
# include "BKE_context.h"
|
||||
# include "BKE_pose_backup.h"
|
||||
|
||||
# include "DNA_action_types.h"
|
||||
# include "DNA_anim_types.h"
|
||||
|
@ -108,6 +109,56 @@ static void rna_Pose_apply_pose_from_action(ID *pose_owner,
|
|||
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pose_owner);
|
||||
}
|
||||
|
||||
static void rna_Pose_blend_pose_from_action(ID *pose_owner,
|
||||
bContext *C,
|
||||
bAction *action,
|
||||
const float blend_factor,
|
||||
const float evaluation_time)
|
||||
{
|
||||
BLI_assert(GS(pose_owner->name) == ID_OB);
|
||||
Object *pose_owner_ob = (Object *)pose_owner;
|
||||
|
||||
AnimationEvalContext anim_eval_context = {CTX_data_depsgraph_pointer(C), evaluation_time};
|
||||
BKE_pose_apply_action_blend(pose_owner_ob, action, &anim_eval_context, blend_factor);
|
||||
|
||||
/* Do NOT tag with ID_RECALC_ANIMATION, as that would overwrite the just-applied pose. */
|
||||
DEG_id_tag_update(pose_owner, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pose_owner);
|
||||
}
|
||||
|
||||
static void rna_Pose_backup_create(ID *pose_owner, bAction *action)
|
||||
{
|
||||
BLI_assert(GS(pose_owner->name) == ID_OB);
|
||||
Object *pose_owner_ob = (Object *)pose_owner;
|
||||
|
||||
BKE_pose_backup_create_on_object(pose_owner_ob, action);
|
||||
}
|
||||
|
||||
static bool rna_Pose_backup_restore(ID *pose_owner, bContext *C)
|
||||
{
|
||||
BLI_assert(GS(pose_owner->name) == ID_OB);
|
||||
Object *pose_owner_ob = (Object *)pose_owner;
|
||||
|
||||
const bool success = BKE_pose_backup_restore_on_object(pose_owner_ob);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Do NOT tag with ID_RECALC_ANIMATION, as that would overwrite the just-applied pose. */
|
||||
DEG_id_tag_update(pose_owner, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pose_owner);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rna_Pose_backup_clear(ID *pose_owner)
|
||||
{
|
||||
BLI_assert(GS(pose_owner->name) == ID_OB);
|
||||
Object *pose_owner_ob = (Object *)pose_owner;
|
||||
|
||||
BKE_pose_backup_clear(pose_owner_ob);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void RNA_api_pose(StructRNA *srna)
|
||||
|
@ -121,10 +172,8 @@ void RNA_api_pose(StructRNA *srna)
|
|||
func,
|
||||
"Apply the given action to this pose by evaluating it at a specific time. Only updates the "
|
||||
"pose of selected bones, or all bones if none are selected.");
|
||||
|
||||
parm = RNA_def_pointer(func, "action", "Action", "Action", "The Action containing the pose");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
|
||||
parm = RNA_def_float(func,
|
||||
"evaluation_time",
|
||||
0.0f,
|
||||
|
@ -134,6 +183,67 @@ void RNA_api_pose(StructRNA *srna)
|
|||
"Time at which the given action is evaluated to obtain the pose",
|
||||
-FLT_MAX,
|
||||
FLT_MAX);
|
||||
|
||||
func = RNA_def_function(srna, "blend_pose_from_action", "rna_Pose_blend_pose_from_action");
|
||||
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF | FUNC_USE_CONTEXT);
|
||||
RNA_def_function_ui_description(func,
|
||||
"Blend the given action into this pose by evaluating it at a "
|
||||
"specific time. Only updates the "
|
||||
"pose of selected bones, or all bones if none are selected.");
|
||||
parm = RNA_def_pointer(func, "action", "Action", "Action", "The Action containing the pose");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_float(func,
|
||||
"blend_factor",
|
||||
1.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
"Blend Factor",
|
||||
"How much the given Action affects the final pose",
|
||||
0.0f,
|
||||
1.0f);
|
||||
parm = RNA_def_float(func,
|
||||
"evaluation_time",
|
||||
0.0f,
|
||||
-FLT_MAX,
|
||||
FLT_MAX,
|
||||
"Evaluation Time",
|
||||
"Time at which the given action is evaluated to obtain the pose",
|
||||
-FLT_MAX,
|
||||
FLT_MAX);
|
||||
|
||||
func = RNA_def_function(srna, "backup_create", "rna_Pose_backup_create");
|
||||
RNA_def_function_ui_description(
|
||||
func,
|
||||
"Create a backup of the current pose. Only those bones that are animated in the Action are "
|
||||
"backed up. The object owns the backup, and each object can have only one backup at a time. "
|
||||
"When you no longer need it, it must be freed use `backup_clear()`.");
|
||||
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF);
|
||||
parm = RNA_def_pointer(func,
|
||||
"action",
|
||||
"Action",
|
||||
"Action",
|
||||
"An Action with animation data for the bones. Only the animated bones "
|
||||
"will be included in the backup.");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
|
||||
func = RNA_def_function(srna, "backup_restore", "rna_Pose_backup_restore");
|
||||
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF | FUNC_USE_CONTEXT);
|
||||
RNA_def_function_ui_description(func,
|
||||
"Restore the previously made pose backup. This can be called "
|
||||
"multiple times. See `Pose.backup_create()` for more info.");
|
||||
/* return value */
|
||||
parm = RNA_def_boolean(
|
||||
func,
|
||||
"success",
|
||||
false,
|
||||
"",
|
||||
"`True` when the backup was restored, `False` if there was no backup to restore.");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(srna, "backup_clear", "rna_Pose_backup_clear");
|
||||
RNA_def_function_ui_description(
|
||||
func, "Free a previously made pose backup. See `Pose.backup_create()` for more info.");
|
||||
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF);
|
||||
}
|
||||
|
||||
void RNA_api_pose_channel(StructRNA *srna)
|
||||
|
|
|
@ -101,6 +101,15 @@ static void rna_trackingPlaneTracks_begin(CollectionPropertyIterator *iter, Poin
|
|||
rna_iterator_listbase_begin(iter, &tracking_camera_object->plane_tracks, NULL);
|
||||
}
|
||||
|
||||
static PointerRNA rna_trackingReconstruction_get(PointerRNA *ptr)
|
||||
{
|
||||
MovieClip *clip = (MovieClip *)ptr->owner_id;
|
||||
MovieTrackingObject *tracking_camera_object = BKE_tracking_object_get_camera(&clip->tracking);
|
||||
|
||||
return rna_pointer_inherit_refine(
|
||||
ptr, &RNA_MovieTrackingReconstruction, &tracking_camera_object->reconstruction);
|
||||
}
|
||||
|
||||
static void rna_trackingObjects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
MovieClip *clip = (MovieClip *)ptr->owner_id;
|
||||
|
@ -2609,6 +2618,7 @@ static void rna_def_tracking(BlenderRNA *brna)
|
|||
/* reconstruction */
|
||||
prop = RNA_def_property(srna, "reconstruction", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "reconstruction_legacy");
|
||||
RNA_def_property_pointer_funcs(prop, "rna_trackingReconstruction_get", NULL, NULL, NULL);
|
||||
RNA_def_property_struct_type(prop, "MovieTrackingReconstruction");
|
||||
|
||||
/* objects */
|
||||
|
|
|
@ -6,11 +6,10 @@
|
|||
*/
|
||||
|
||||
/* Screw modifier: revolves the edges about an axis */
|
||||
#include <limits.h>
|
||||
#include <climits>
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLI_alloca.h"
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_math.h"
|
||||
|
||||
|
@ -53,7 +52,7 @@ static void initData(ModifierData *md)
|
|||
}
|
||||
|
||||
/** Used for gathering edge connectivity. */
|
||||
typedef struct ScrewVertConnect {
|
||||
struct ScrewVertConnect {
|
||||
/** Distance from the center axis. */
|
||||
float dist_sq;
|
||||
/** Location relative to the transformed axis. */
|
||||
|
@ -63,14 +62,14 @@ typedef struct ScrewVertConnect {
|
|||
/** Edges on either side, a bit of a waste since each edge ref's 2 edges. */
|
||||
MEdge *e[2];
|
||||
char flag;
|
||||
} ScrewVertConnect;
|
||||
};
|
||||
|
||||
typedef struct ScrewVertIter {
|
||||
struct ScrewVertIter {
|
||||
ScrewVertConnect *v_array;
|
||||
ScrewVertConnect *v_poin;
|
||||
uint v, v_other;
|
||||
MEdge *e;
|
||||
} ScrewVertIter;
|
||||
};
|
||||
|
||||
#define SV_UNUSED (UINT_MAX)
|
||||
#define SV_INVALID ((UINT_MAX)-1)
|
||||
|
@ -336,9 +335,9 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
|
|||
}
|
||||
|
||||
/* apply the multiplier */
|
||||
angle *= (float)ltmd->iter;
|
||||
screw_ofs *= (float)ltmd->iter;
|
||||
uv_u_scale = 1.0f / (float)(step_tot);
|
||||
angle *= float(ltmd->iter);
|
||||
screw_ofs *= float(ltmd->iter);
|
||||
uv_u_scale = 1.0f / float(step_tot);
|
||||
|
||||
/* multiplying the steps is a bit tricky, this works best */
|
||||
step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1);
|
||||
|
@ -473,22 +472,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
|
|||
* Sort edge verts for correct face flipping
|
||||
* NOT REALLY NEEDED but face flipping is nice. */
|
||||
|
||||
/* Notice!
|
||||
*
|
||||
* Since we are only ordering the edges here it can avoid mallocing the
|
||||
* extra space by abusing the vert array before its filled with new verts.
|
||||
* The new array for vert_connect must be at least `sizeof(ScrewVertConnect) * totvert`
|
||||
* and the size of our resulting meshes array is `sizeof(MVert) * totvert * 3`
|
||||
* so its safe to use the second 2 thirds of #MVert the array for vert_connect,
|
||||
* just make sure #ScrewVertConnect struct is no more than twice as big as #MVert,
|
||||
* at the moment there is no chance of that being a problem,
|
||||
* unless #MVert becomes half its current size.
|
||||
*
|
||||
* once the edges are ordered, vert_connect is not needed and it can be used for verts
|
||||
*
|
||||
* This makes the modifier faster with one less allocate.
|
||||
*/
|
||||
|
||||
vert_connect = static_cast<ScrewVertConnect *>(
|
||||
MEM_malloc_arrayN(totvert, sizeof(ScrewVertConnect), __func__));
|
||||
/* skip the first slice of verts. */
|
||||
|
|
|
@ -34,6 +34,24 @@ static bool use_translate(const float3 rotation, const float3 scale)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void translate_positions(MutableSpan<float3> positions, const float3 &translation)
|
||||
{
|
||||
threading::parallel_for(positions.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (float3 &position : positions.slice(range)) {
|
||||
position += translation;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void transform_positions(MutableSpan<float3> positions, const float4x4 &matrix)
|
||||
{
|
||||
threading::parallel_for(positions.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (float3 &position : positions.slice(range)) {
|
||||
position = matrix * position;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void translate_mesh(Mesh &mesh, const float3 translation)
|
||||
{
|
||||
if (!math::is_zero(translation)) {
|
||||
|
@ -51,9 +69,7 @@ static void translate_pointcloud(PointCloud &pointcloud, const float3 translatio
|
|||
MutableAttributeAccessor attributes = pointcloud.attributes_for_write();
|
||||
SpanAttributeWriter position = attributes.lookup_or_add_for_write_span<float3>(
|
||||
"position", ATTR_DOMAIN_POINT);
|
||||
for (const int i : position.span.index_range()) {
|
||||
position.span[i] += translation;
|
||||
}
|
||||
translate_positions(position.span, translation);
|
||||
position.finish();
|
||||
}
|
||||
|
||||
|
@ -62,26 +78,28 @@ static void transform_pointcloud(PointCloud &pointcloud, const float4x4 &transfo
|
|||
MutableAttributeAccessor attributes = pointcloud.attributes_for_write();
|
||||
SpanAttributeWriter position = attributes.lookup_or_add_for_write_span<float3>(
|
||||
"position", ATTR_DOMAIN_POINT);
|
||||
for (const int i : position.span.index_range()) {
|
||||
position.span[i] = transform * position.span[i];
|
||||
}
|
||||
transform_positions(position.span, transform);
|
||||
position.finish();
|
||||
}
|
||||
|
||||
static void translate_instances(bke::Instances &instances, const float3 translation)
|
||||
{
|
||||
MutableSpan<float4x4> transforms = instances.transforms();
|
||||
for (float4x4 &transform : transforms) {
|
||||
add_v3_v3(transform.ptr()[3], translation);
|
||||
}
|
||||
threading::parallel_for(transforms.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (float4x4 &instance_transform : transforms.slice(range)) {
|
||||
add_v3_v3(instance_transform.ptr()[3], translation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void transform_instances(bke::Instances &instances, const float4x4 &transform)
|
||||
{
|
||||
MutableSpan<float4x4> transforms = instances.transforms();
|
||||
for (float4x4 &instance_transform : transforms) {
|
||||
instance_transform = transform * instance_transform;
|
||||
}
|
||||
threading::parallel_for(transforms.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (float4x4 &instance_transform : transforms.slice(range)) {
|
||||
instance_transform = transform * instance_transform;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void transform_volume(GeoNodeExecParams ¶ms,
|
||||
|
|
Loading…
Reference in New Issue