Compare commits
22 Commits
main
...
temp-nla-s
Author | SHA1 | Date | |
---|---|---|---|
8118685a83 | |||
188dc880c6 | |||
0b2c79e88b | |||
5e12a5622c | |||
a30c8168a0 | |||
5d4a514a88 | |||
7c80dddb8c | |||
d52a4fa0c6 | |||
30efd99a84 | |||
962e481f26 | |||
d9280548ff | |||
d40ea0b3f4 | |||
28fefc3205 | |||
a87a4de7b1 | |||
465eeddc04 | |||
a586fd4e3d | |||
27388587e6 | |||
cfa7e581da | |||
7728869f24 | |||
![]() |
a052813127 | ||
![]() |
8a74c60c4a | ||
![]() |
24442431d4 |
@@ -2167,6 +2167,9 @@ def km_nla_generic(_params):
|
||||
{"properties": [("isolate_action", True)]}),
|
||||
("nla.tweakmode_exit", {"type": 'TAB', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("isolate_action", True)]}),
|
||||
("nla.tweakmode_enter", {"type": 'TAB', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("use_upper_stack_evaluation", False)]}),
|
||||
("nla.tweakmode_exit", {"type": 'TAB', "value": 'PRESS', "ctrl": True},None),
|
||||
("anim.channels_find", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
|
||||
])
|
||||
|
||||
@@ -2250,6 +2253,7 @@ def km_nla_editor(params):
|
||||
("nla.delete", {"type": 'X', "value": 'PRESS'}, None),
|
||||
("nla.delete", {"type": 'DEL', "value": 'PRESS'}, None),
|
||||
("nla.split", {"type": 'Y', "value": 'PRESS'}, None),
|
||||
("NLA_OT_resample_strips", {"type": 'M', "value": 'PRESS',"shift":True},None),
|
||||
("nla.mute_toggle", {"type": 'H', "value": 'PRESS'}, None),
|
||||
("nla.swap", {"type": 'F', "value": 'PRESS', "alt": True}, None),
|
||||
("nla.move_up", {"type": 'PAGE_UP', "value": 'PRESS', "repeat": True}, None),
|
||||
|
@@ -49,6 +49,7 @@ _modules = [
|
||||
"properties_mask_common",
|
||||
"properties_material",
|
||||
"properties_material_gpencil",
|
||||
"properties_nla",
|
||||
"properties_object",
|
||||
"properties_paint_common",
|
||||
"properties_grease_pencil_common",
|
||||
|
173
release/scripts/startup/bl_ui/properties_nla.py
Normal file
173
release/scripts/startup/bl_ui/properties_nla.py
Normal file
@@ -0,0 +1,173 @@
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
import bpy
|
||||
from bpy.types import Panel
|
||||
from bpy.props import (StringProperty,
|
||||
BoolProperty,
|
||||
IntProperty,
|
||||
FloatProperty,
|
||||
EnumProperty,
|
||||
PointerProperty,
|
||||
CollectionProperty,
|
||||
FloatVectorProperty,
|
||||
IntVectorProperty,
|
||||
)
|
||||
def get_active_strip(context):
|
||||
items = [strip for strip in context.selected_nla_strips if strip.active]
|
||||
return items[0] if items else None
|
||||
|
||||
class OBJECT_OT_nla_add_blend(bpy.types.Operator):
|
||||
bl_idname = "object.nla_add_blend"
|
||||
bl_label = "Add Preblend Transform"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls,context):
|
||||
return context.selected_nla_strips
|
||||
|
||||
def execute(self, context):
|
||||
active_strip = get_active_strip(context)
|
||||
print(dict(active_strip.blend_transforms))
|
||||
k = active_strip.blend_transforms.add()
|
||||
|
||||
# print(k.path_from_id("location"))
|
||||
# print(active_strip.path_resolve("blend_transforms"))
|
||||
# print(k.id_data)
|
||||
return {'FINISHED'}
|
||||
class OBJECT_OT_nla_remove_blend(bpy.types.Operator):
|
||||
bl_idname = "object.nla_remove_blend"
|
||||
bl_label = "Remove Preblend Transform"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
blend_index : IntProperty()
|
||||
|
||||
@classmethod
|
||||
def poll(cls,context):
|
||||
return context.selected_nla_strips
|
||||
|
||||
def execute(self, context):
|
||||
active_strip = get_active_strip(context)
|
||||
active_strip.blend_transforms.remove_at(blend_index=self.blend_index)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
class OBJECT_OT_nla_blend_add_bone(bpy.types.Operator):
|
||||
bl_idname = "object.blend_add_bone"
|
||||
bl_label = "Preblend Add Bone"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
blend_index : IntProperty()
|
||||
|
||||
@classmethod
|
||||
def poll(cls,context):
|
||||
return context.selected_nla_strips
|
||||
|
||||
def execute(self, context):
|
||||
active_strip = get_active_strip(context)
|
||||
blend = active_strip.blend_transforms[self.blend_index]
|
||||
bone = blend.bones.add()
|
||||
bone.name ="Hips"
|
||||
return {'FINISHED'}
|
||||
class OBJECT_OT_nla_blend_remove_bone(bpy.types.Operator):
|
||||
bl_idname = "object.blend_remove_bone"
|
||||
bl_label = "Preblend Remove Bone"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
blend_index : IntProperty()
|
||||
bone_index : IntProperty()
|
||||
|
||||
@classmethod
|
||||
def poll(cls,context):
|
||||
return context.selected_nla_strips
|
||||
|
||||
def execute(self, context):
|
||||
active_strip = get_active_strip(context)
|
||||
blend = active_strip.blend_transforms[self.blend_index]
|
||||
blend.bones.remove_at(bone_index=self.bone_index)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
class OBJECT_PT_nla_alignment(Panel):
|
||||
bl_space_type = 'NLA_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_label = "Alignment"
|
||||
bl_category = "Strip"
|
||||
bl_context = "object"
|
||||
|
||||
|
||||
def draw(self, context):
|
||||
#Q: not in a poll() so it doesnt disappear on nla strip deselection (annoying)
|
||||
if not context.selected_nla_strips:
|
||||
return
|
||||
|
||||
layout = self.layout
|
||||
active_strip = get_active_strip(context)
|
||||
|
||||
|
||||
layout.prop(active_strip,"name")
|
||||
# layout.prop(active_strip,"action")
|
||||
# layout.prop(active_strip,"blend_transforms")
|
||||
|
||||
# layout.prop(active_strip,"frame_start")
|
||||
# layout.prop(context.active_object,"location")
|
||||
# layout.prop(context.active_object.pose.bones["Hips"],"location")
|
||||
# if(context.active_pose_bone):
|
||||
# c = context.active_pose_bone.constraints
|
||||
# if(c):
|
||||
# layout.prop(c[0],'type')
|
||||
layout.operator(OBJECT_OT_nla_add_blend.bl_idname,text='New Transform',icon='ADD')
|
||||
for i,blend in enumerate(active_strip.blend_transforms):
|
||||
box = layout.box()
|
||||
row = box.row(align=True)
|
||||
row.label(text="World Transform")
|
||||
row.operator(OBJECT_OT_nla_remove_blend.bl_idname,text='',icon='REMOVE').blend_index = i
|
||||
|
||||
box.prop(blend,"location")
|
||||
box.prop(blend,"euler")
|
||||
box.prop(blend,"scale")
|
||||
|
||||
col = box.column(align=True)
|
||||
row = col.row(align=True)
|
||||
#todo: support for objects?
|
||||
row.label(text="Bones")
|
||||
row.operator(OBJECT_OT_nla_blend_add_bone.bl_idname,text='',icon='ADD').blend_index = i
|
||||
for j,bone in enumerate(blend.bones):
|
||||
row = col.row(align=True)
|
||||
# print([b for b in context.active_object.data.bones])
|
||||
row.prop_search(bone,"name",context.active_object.data,"bones",text='')
|
||||
#row.prop(bone,"name")
|
||||
op = row.operator(OBJECT_OT_nla_blend_remove_bone.bl_idname,text='',icon='REMOVE')
|
||||
op.blend_index = i
|
||||
op.bone_index = j
|
||||
|
||||
|
||||
classes = (
|
||||
# Object Panels
|
||||
OBJECT_PT_nla_alignment,
|
||||
OBJECT_OT_nla_add_blend,
|
||||
OBJECT_OT_nla_remove_blend,
|
||||
OBJECT_OT_nla_blend_remove_bone,
|
||||
OBJECT_OT_nla_blend_add_bone,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
from bpy.utils import register_class
|
||||
for cls in classes:
|
||||
register_class(cls)
|
@@ -165,6 +165,7 @@ class NLA_MT_edit(Menu):
|
||||
layout.separator()
|
||||
layout.operator("nla.duplicate", text="Duplicate").linked = False
|
||||
layout.operator("nla.duplicate", text="Linked Duplicate").linked = True
|
||||
layout.operator("nla.resample_strips")
|
||||
layout.operator("nla.split")
|
||||
layout.operator("nla.delete")
|
||||
layout.operator("nla.tracks_delete")
|
||||
@@ -198,6 +199,7 @@ class NLA_MT_edit(Menu):
|
||||
else:
|
||||
layout.operator("nla.tweakmode_enter", text="Start Editing Stashed Action").isolate_action = True
|
||||
layout.operator("nla.tweakmode_enter", text="Start Tweaking Strip Actions")
|
||||
layout.operator("nla.tweakmode_enter", text="Start Tweaking Strip Actions (Exclude Upper Stack)").use_upper_stack_evaluation = False
|
||||
|
||||
|
||||
class NLA_MT_add(Menu):
|
||||
@@ -260,6 +262,7 @@ class NLA_MT_context_menu(Menu):
|
||||
else:
|
||||
layout.operator("nla.tweakmode_enter", text="Start Editing Stashed Action").isolate_action = True
|
||||
layout.operator("nla.tweakmode_enter", text="Start Tweaking Strip Actions")
|
||||
layout.operator("nla.tweakmode_enter", text="Start Tweaking Strip Actions (Exclude Upper Stack)").use_upper_stack_evaluation = False
|
||||
|
||||
layout.separator()
|
||||
|
||||
@@ -268,6 +271,10 @@ class NLA_MT_context_menu(Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
col = layout.column()
|
||||
col.operator_context="INVOKE_DEFAULT"
|
||||
col.operator("nla.resample_strips")
|
||||
|
||||
layout.operator("nla.split")
|
||||
layout.operator("nla.delete")
|
||||
|
||||
|
@@ -217,13 +217,24 @@ struct NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
|
||||
const struct AnimationEvalContext *anim_eval_context,
|
||||
const bool flush_to_original);
|
||||
bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context,
|
||||
const AnimationEvalContext *anim_eval_context,
|
||||
struct PointerRNA *prop_ptr,
|
||||
struct PropertyRNA *prop,
|
||||
char rna_path[],
|
||||
float *values,
|
||||
int count,
|
||||
int index,
|
||||
bool *r_force_all);
|
||||
void BKE_animsys_free_nla_keyframing_context_cache(struct ListBase *cache);
|
||||
struct NlaTrack *BKE_animsys_resample_selected_strips(struct Main *main,
|
||||
struct Depsgraph *depsgraph,
|
||||
struct AnimData *adt,
|
||||
struct PointerRNA *id_ptr,
|
||||
char resample_name[],
|
||||
short resample_blendmode,
|
||||
float resample_influence,
|
||||
int resample_insertion_nlt_index,
|
||||
bool insert_track_lower);
|
||||
|
||||
/* ************************************* */
|
||||
/* Evaluation API */
|
||||
|
@@ -59,6 +59,7 @@ struct NlaTrack *BKE_nlatrack_copy(struct Main *bmain,
|
||||
const bool use_same_actions,
|
||||
const int flag);
|
||||
void BKE_nla_tracks_copy(struct Main *bmain, ListBase *dst, ListBase *src, const int flag);
|
||||
struct NlaBlendTransform *BKE_nlastrip_blend_transform_copy(struct NlaBlendTransform *strip);
|
||||
|
||||
struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt,
|
||||
struct NlaTrack *prev,
|
||||
@@ -67,6 +68,15 @@ struct NlaStrip *BKE_nlastrip_new(struct bAction *act);
|
||||
struct NlaStrip *BKE_nlastack_add_strip(struct AnimData *adt,
|
||||
struct bAction *act,
|
||||
const bool is_liboverride);
|
||||
|
||||
struct NlaBlendTransform *BKE_nlastrip_new_blend_transform();
|
||||
void BKE_nlastrip_free_blend_transform(struct NlaStrip *strip, struct NlaBlendTransform *blend);
|
||||
void BKE_nlastrip_free_blend_transform_at(struct NlaStrip *strip, int blend_index);
|
||||
|
||||
struct NlaBlendTransform_BoneTarget *BKE_blend_transform_new_bone();
|
||||
void BKE_blend_transform_free_bone(struct NlaBlendTransform *blend,
|
||||
struct NlaBlendTransform_BoneTarget *bone_name);
|
||||
void BKE_blend_transform_free_bone_at(struct NlaBlendTransform *blend, int bone_name_index);
|
||||
struct NlaStrip *BKE_nla_add_soundstrip(struct Main *bmain,
|
||||
struct Scene *scene,
|
||||
struct Speaker *speaker);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,8 @@
|
||||
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_rotation.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_utildefines.h"
|
||||
@@ -211,10 +213,32 @@ NlaStrip *BKE_nlastrip_copy(Main *bmain,
|
||||
BLI_addtail(&strip_d->strips, cs_d);
|
||||
}
|
||||
|
||||
BLI_listbase_clear(&strip_d->blend_transforms);
|
||||
LISTBASE_FOREACH (NlaBlendTransform *, blend_xform, &strip->blend_transforms) {
|
||||
NlaBlendTransform *duplicate_blend_xform = BKE_nlastrip_blend_transform_copy(blend_xform);
|
||||
BLI_addtail(&strip_d->blend_transforms, duplicate_blend_xform);
|
||||
}
|
||||
|
||||
/* return the strip */
|
||||
return strip_d;
|
||||
}
|
||||
|
||||
struct NlaBlendTransform *BKE_nlastrip_blend_transform_copy(NlaBlendTransform *blend_xform)
|
||||
{
|
||||
NlaBlendTransform *duplicate_blend_xform = BKE_nlastrip_new_blend_transform();
|
||||
copy_v3_v3(duplicate_blend_xform->location, blend_xform->location);
|
||||
copy_v3_v3(duplicate_blend_xform->euler, blend_xform->euler);
|
||||
copy_v3_v3(duplicate_blend_xform->scale, blend_xform->scale);
|
||||
|
||||
LISTBASE_FOREACH (NlaBlendTransform_BoneTarget *, bone_target, &blend_xform->bones) {
|
||||
NlaBlendTransform_BoneTarget *duplicate_target = BKE_blend_transform_new_bone();
|
||||
BLI_addtail(&duplicate_blend_xform->bones, duplicate_target);
|
||||
|
||||
strcpy(duplicate_target->name, bone_target->name);
|
||||
}
|
||||
|
||||
return duplicate_blend_xform;
|
||||
}
|
||||
/**
|
||||
* Copy a single NLA Track.
|
||||
* \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_...
|
||||
@@ -357,6 +381,9 @@ NlaStrip *BKE_nlastrip_new(bAction *act)
|
||||
strip->scale = 1.0f;
|
||||
strip->repeat = 1.0f;
|
||||
|
||||
/* For convenience, (see T82309#1055954). */
|
||||
strip->flag |= NLASTRIP_FLAG_SYNC_LENGTH;
|
||||
|
||||
/* return the new strip */
|
||||
return strip;
|
||||
}
|
||||
@@ -395,6 +422,61 @@ NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act, const bool is_libo
|
||||
return strip;
|
||||
}
|
||||
|
||||
NlaBlendTransform *BKE_nlastrip_new_blend_transform()
|
||||
{
|
||||
NlaBlendTransform *blend = MEM_callocN(sizeof(NlaBlendTransform), __func__);
|
||||
blend->location[0] = 0;
|
||||
blend->location[1] = 0;
|
||||
blend->location[2] = 0;
|
||||
blend->euler[0] = 0;
|
||||
blend->euler[1] = 0;
|
||||
blend->euler[2] = 0;
|
||||
blend->scale[0] = 1;
|
||||
blend->scale[1] = 1;
|
||||
blend->scale[2] = 1;
|
||||
|
||||
return blend;
|
||||
}
|
||||
|
||||
NlaBlendTransform *BKE_nlastrip_copy_blend_transform(NlaStrip *strip)
|
||||
{
|
||||
}
|
||||
void BKE_nlastrip_free_blend_transform(NlaStrip *strip, NlaBlendTransform *blend)
|
||||
{
|
||||
// todo: ensure pattern of add/removal matches others (assumptions, that remove also frees, etc)
|
||||
BLI_remlink(&strip->blend_transforms, blend);
|
||||
MEM_freeN(blend);
|
||||
}
|
||||
void BKE_nlastrip_free_blend_transform_at(NlaStrip *strip, int blend_index)
|
||||
{
|
||||
NlaBlendTransform *blend = BLI_findlink(&strip->blend_transforms, blend_index);
|
||||
if (blend) {
|
||||
BKE_nlastrip_free_blend_transform(strip, blend);
|
||||
}
|
||||
}
|
||||
|
||||
NlaBlendTransform_BoneTarget *BKE_blend_transform_new_bone()
|
||||
{
|
||||
NlaBlendTransform_BoneTarget *bone_target = MEM_callocN(sizeof(NlaBlendTransform_BoneTarget),
|
||||
__func__);
|
||||
|
||||
return bone_target;
|
||||
}
|
||||
void BKE_blend_transform_free_bone(NlaBlendTransform *blend,
|
||||
NlaBlendTransform_BoneTarget *bone_name)
|
||||
{
|
||||
// todo: ensure pattern of add/removal matches others (assumptions, that remove also frees, etc)
|
||||
BLI_remlink(&blend->bones, bone_name);
|
||||
MEM_freeN(bone_name);
|
||||
}
|
||||
void BKE_blend_transform_free_bone_at(NlaBlendTransform *blend, int bone_name_index)
|
||||
{
|
||||
NlaBlendTransform_BoneTarget *bone_name = BLI_findlink(&blend->bones, bone_name_index);
|
||||
if (bone_name) {
|
||||
BKE_blend_transform_free_bone(blend, bone_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a NLA Strip referencing the given speaker's sound */
|
||||
NlaStrip *BKE_nla_add_soundstrip(Main *bmain, Scene *scene, Speaker *speaker)
|
||||
{
|
||||
@@ -2115,8 +2197,11 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
|
||||
/* go over all the tracks after AND INCLUDING the active one, tagging them as being disabled
|
||||
* - the active track needs to also be tagged, otherwise, it'll overlap with the tweaks going on
|
||||
*/
|
||||
for (nlt = activeTrack; nlt; nlt = nlt->next) {
|
||||
nlt->flag |= NLATRACK_DISABLED;
|
||||
activeTrack->flag |= NLATRACK_DISABLED;
|
||||
if ((adt->flag & ADT_NLA_EVAL_UPPER_TRACKS) == 0) {
|
||||
for (nlt = activeTrack->next; nlt; nlt = nlt->next) {
|
||||
nlt->flag |= NLATRACK_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle AnimData level changes:
|
||||
@@ -2210,6 +2295,11 @@ static void blend_write_nla_strips(BlendWriter *writer, ListBase *strips)
|
||||
BKE_fcurve_blend_write(writer, &strip->fcurves);
|
||||
BKE_fmodifiers_blend_write(writer, &strip->modifiers);
|
||||
|
||||
BLO_write_struct_list(writer, NlaBlendTransform, &strip->blend_transforms);
|
||||
LISTBASE_FOREACH (NlaBlendTransform *, blend, &strip->blend_transforms) {
|
||||
|
||||
BLO_write_struct_list(writer, NlaBlendTransform_BoneTarget, &blend->bones);
|
||||
}
|
||||
/* write the strip's children */
|
||||
blend_write_nla_strips(writer, &strip->strips);
|
||||
}
|
||||
@@ -2229,6 +2319,12 @@ static void blend_data_read_nla_strips(BlendDataReader *reader, ListBase *strips
|
||||
/* strip's F-Modifiers */
|
||||
BLO_read_list(reader, &strip->modifiers);
|
||||
BKE_fmodifiers_blend_read_data(reader, &strip->modifiers, NULL);
|
||||
|
||||
BLO_read_list(reader, &strip->blend_transforms);
|
||||
LISTBASE_FOREACH (NlaBlendTransform *, blend, &strip->blend_transforms) {
|
||||
|
||||
BLO_read_list(reader, &blend->bones);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -79,6 +79,15 @@ typedef struct NlaValidMask {
|
||||
typedef struct NlaEvalChannelSnapshot {
|
||||
struct NlaEvalChannel *channel;
|
||||
|
||||
/** Only used for keyframe remapping for inverting through a transition. Bit set if raw value was
|
||||
* written so we know where the channel value comes from (whether it's the property's default or
|
||||
* from the strip). */
|
||||
NlaValidMask raw_value_sampled;
|
||||
|
||||
/** Only used for keyframe remapping to know whether channel value can be further inverted to
|
||||
* solve for tweak strip value. */
|
||||
NlaValidMask invertible;
|
||||
|
||||
int length; /* Number of values in the property. */
|
||||
bool is_base; /* Base snapshot of the channel. */
|
||||
|
||||
@@ -113,7 +122,7 @@ typedef struct NlaEvalChannel {
|
||||
NlaEvalChannelSnapshot *blend_snapshot;
|
||||
|
||||
/* Mask of array items controlled by NLA. */
|
||||
NlaValidMask valid;
|
||||
NlaValidMask domain;
|
||||
|
||||
/* Base set of values. */
|
||||
NlaEvalChannelSnapshot base_snapshot;
|
||||
@@ -155,9 +164,13 @@ typedef struct NlaKeyframingContext {
|
||||
/* Data of the currently edited strip (copy, or fake strip for the main action). */
|
||||
NlaStrip strip;
|
||||
NlaEvalStrip *eval_strip;
|
||||
/** Storage for the non-stashed action as a strip. Only used for keyframing. */
|
||||
NlaStrip nonuser_act_strip;
|
||||
|
||||
/* Evaluated NLA stack below the current strip. */
|
||||
NlaEvalData nla_channels;
|
||||
/* Strips above tweaked strip. */
|
||||
ListBase upper_estrips;
|
||||
/* Evaluated NLA stack below the tweak strip. */
|
||||
NlaEvalData lower_nla_channels;
|
||||
} NlaKeyframingContext;
|
||||
|
||||
/* --------------- NLA Functions (not to be used as a proper API) ----------------------- */
|
||||
@@ -180,7 +193,23 @@ void nlastrip_evaluate(PointerRNA *ptr,
|
||||
NlaEvalStrip *nes,
|
||||
NlaEvalSnapshot *snapshot,
|
||||
const struct AnimationEvalContext *anim_eval_context,
|
||||
const bool flush_to_original);
|
||||
const bool flush_to_original,
|
||||
bool allow_alloc_channels);
|
||||
void nlastrip_evaluate_invert_get_lower_values(
|
||||
PointerRNA *ptr,
|
||||
NlaEvalData *upper_eval_data,
|
||||
ListBase *modifiers,
|
||||
NlaEvalStrip *nes,
|
||||
NlaEvalSnapshot *snapshot,
|
||||
const struct AnimationEvalContext *anim_eval_context);
|
||||
void nlastrip_evaluate_raw_value(PointerRNA *ptr,
|
||||
NlaEvalData *upper_eval_data,
|
||||
ListBase *modifiers,
|
||||
NlaEvalStrip *nes,
|
||||
NlaEvalSnapshot *snapshot,
|
||||
const struct AnimationEvalContext *anim_eval_context,
|
||||
short *r_blendmode,
|
||||
float *r_influence);
|
||||
void nladata_flush_channels(PointerRNA *ptr,
|
||||
NlaEvalData *channels,
|
||||
NlaEvalSnapshot *snapshot,
|
||||
|
@@ -1116,8 +1116,10 @@ static float *visualkey_get_values(
|
||||
static float *get_keyframe_values(ReportList *reports,
|
||||
PointerRNA ptr,
|
||||
PropertyRNA *prop,
|
||||
char rna_path[],
|
||||
int index,
|
||||
struct NlaKeyframingContext *nla_context,
|
||||
const AnimationEvalContext *anim_eval_context,
|
||||
eInsertKeyFlags flag,
|
||||
float *buffer,
|
||||
int buffer_size,
|
||||
@@ -1139,8 +1141,15 @@ static float *get_keyframe_values(ReportList *reports,
|
||||
}
|
||||
|
||||
/* adjust the value for NLA factors */
|
||||
if (!BKE_animsys_nla_remap_keyframe_values(
|
||||
nla_context, &ptr, prop, values, *r_count, index, r_force_all)) {
|
||||
if (!BKE_animsys_nla_remap_keyframe_values(nla_context,
|
||||
anim_eval_context,
|
||||
&ptr,
|
||||
prop,
|
||||
rna_path,
|
||||
values,
|
||||
*r_count,
|
||||
index,
|
||||
r_force_all)) {
|
||||
BKE_report(
|
||||
reports, RPT_ERROR, "Could not insert keyframe due to zero NLA influence or base value");
|
||||
|
||||
@@ -1300,8 +1309,10 @@ bool insert_keyframe_direct(ReportList *reports,
|
||||
float *values = get_keyframe_values(reports,
|
||||
ptr,
|
||||
prop,
|
||||
fcu->rna_path,
|
||||
index,
|
||||
nla_context,
|
||||
anim_eval_context,
|
||||
flag,
|
||||
value_buffer,
|
||||
RNA_MAX_ARRAY_LENGTH,
|
||||
@@ -1474,8 +1485,10 @@ int insert_keyframe(Main *bmain,
|
||||
float *values = get_keyframe_values(reports,
|
||||
ptr,
|
||||
prop,
|
||||
rna_path,
|
||||
array_index,
|
||||
nla_context,
|
||||
anim_eval_context,
|
||||
flag,
|
||||
value_buffer,
|
||||
RNA_MAX_ARRAY_LENGTH,
|
||||
|
@@ -663,7 +663,8 @@ static eContextResult screen_ctx_selected_nla_strips(const bContext *C, bContext
|
||||
NlaTrack *nlt = (NlaTrack *)ale->data;
|
||||
LISTBASE_FOREACH (NlaStrip *, strip, &nlt->strips) {
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
CTX_data_list_add(result, &scene->id, &RNA_NlaStrip, strip);
|
||||
|
||||
CTX_data_list_add(result, ale->id, &RNA_NlaStrip, strip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -38,6 +38,7 @@
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_lib_id.h"
|
||||
@@ -110,6 +111,7 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
|
||||
int filter;
|
||||
|
||||
const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action");
|
||||
const bool use_upper_stack_evaluation = RNA_boolean_get(op->ptr, "use_upper_stack_evaluation");
|
||||
bool ok = false;
|
||||
|
||||
/* get editor data */
|
||||
@@ -131,6 +133,12 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
|
||||
for (ale = anim_data.first; ale; ale = ale->next) {
|
||||
AnimData *adt = ale->data;
|
||||
|
||||
if (use_upper_stack_evaluation) {
|
||||
adt->flag |= ADT_NLA_EVAL_UPPER_TRACKS;
|
||||
}
|
||||
else {
|
||||
adt->flag &= ~ADT_NLA_EVAL_UPPER_TRACKS;
|
||||
}
|
||||
/* try entering tweakmode if valid */
|
||||
ok |= BKE_nla_tweakmode_enter(adt);
|
||||
|
||||
@@ -194,6 +202,14 @@ void NLA_OT_tweakmode_enter(wmOperatorType *ot)
|
||||
"Enable 'solo' on the NLA Track containing the active strip, "
|
||||
"to edit it without seeing the effects of the NLA stack");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
prop = RNA_def_boolean(
|
||||
ot->srna,
|
||||
"use_upper_stack_evaluation",
|
||||
true,
|
||||
"Evaluate Upper Stack",
|
||||
"In tweak mode, display the effects of the tracks above the tweak strip. ");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
/* ------------- */
|
||||
@@ -1436,6 +1452,278 @@ void NLA_OT_split(wmOperatorType *ot)
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************** Resample Strips Operator ***************************** */
|
||||
/** Resample the selected NLA-Strips into a single strip, preserving the overall NLA stack
|
||||
* animation.
|
||||
*/
|
||||
|
||||
/** Enum used for resample operator. */
|
||||
typedef enum eNlaTrackInsertion_Location {
|
||||
NLT_INSERT_ABOVE_SELECTED_STRIPS = 0,
|
||||
NLT_INSERT_BELOW_SELECTED_STRIPS,
|
||||
NLT_INSERT_ABOVE_ACTIVE_STRIP,
|
||||
NLT_INSERT_BELOW_ACTIVE_STRIP,
|
||||
NLT_INSERT_ABOVE_SELECTED_TRACKS,
|
||||
NLT_INSERT_BELOW_SELECTED_TRACKS,
|
||||
NLT_INSERT_ABOVE_ACTIVE_TRACK,
|
||||
NLT_INSERT_BELOW_ACTIVE_TRACK,
|
||||
} eNlaTrackInsertion_Location;
|
||||
|
||||
const EnumPropertyItem rna_enum_nla_insertion_location[] = {
|
||||
{NLT_INSERT_ABOVE_ACTIVE_TRACK,
|
||||
"ABOVE_ACTIVE_TRACK",
|
||||
0,
|
||||
"Above Active Track",
|
||||
"Insert track above active track"},
|
||||
{NLT_INSERT_ABOVE_SELECTED_TRACKS,
|
||||
"ABOVE_SELECTED_TRACKS",
|
||||
0,
|
||||
"Above Selected Tracks",
|
||||
"Insert track above all selected tracks"},
|
||||
{NLT_INSERT_ABOVE_ACTIVE_STRIP,
|
||||
"ABOVE_ACTIVE_STRIP",
|
||||
0,
|
||||
"Above Active Strip",
|
||||
"Insert track above active strip"},
|
||||
{NLT_INSERT_ABOVE_SELECTED_STRIPS,
|
||||
"ABOVE_SELECTED_STRIPS",
|
||||
0,
|
||||
"Above Selected Strips",
|
||||
"Insert track above all selected strips"},
|
||||
{NLT_INSERT_BELOW_ACTIVE_TRACK,
|
||||
"BELOW_ACTIVE_TRACK",
|
||||
0,
|
||||
"Below Active Track",
|
||||
"Insert track below active track"},
|
||||
{NLT_INSERT_BELOW_SELECTED_TRACKS,
|
||||
"BELOW_SELECTED_TRACKS",
|
||||
0,
|
||||
"Below Selected Tracks",
|
||||
"Insert track below all selected tracks"},
|
||||
{NLT_INSERT_BELOW_ACTIVE_STRIP,
|
||||
"BELOW_ACTIVE_STRIP",
|
||||
0,
|
||||
"Below Active Strip",
|
||||
"Insert track below active strip"},
|
||||
{NLT_INSERT_BELOW_SELECTED_STRIPS,
|
||||
"BELOW_SELECTED_STRIPS",
|
||||
0,
|
||||
"Below Selected Strips",
|
||||
"Insert track below all selected strips"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static void resample_strips_get_insertion_index(ListBase *nla_tracks,
|
||||
int insertion_location,
|
||||
int *r_insertion_index,
|
||||
bool *r_insert_below)
|
||||
{
|
||||
|
||||
int active_strip_nlt_index = -1;
|
||||
int lowest_selected_strip_nlt_index = -1;
|
||||
int highest_selected_strip_nlt_index = -1;
|
||||
|
||||
int active_nlt_index = -1;
|
||||
int lowest_selected_nlt_index = -1;
|
||||
int highest_selected_nlt_index = -1;
|
||||
|
||||
/** Obtain indices for each variable above.
|
||||
*
|
||||
* \note We don't care if insertion location based on track or strip that is not evaluated or
|
||||
* muted. We only care about selection. This allows user to choose resample location without
|
||||
* having to first create dummy tracks or strips.
|
||||
*/
|
||||
int nlt_index;
|
||||
LISTBASE_FOREACH_INDEX (NlaTrack *, nlt, nla_tracks, nlt_index) {
|
||||
|
||||
if ((nlt->flag & NLATRACK_SELECTED) != 0) {
|
||||
highest_selected_nlt_index = nlt_index;
|
||||
|
||||
if (lowest_selected_nlt_index == -1) {
|
||||
lowest_selected_nlt_index = nlt_index;
|
||||
}
|
||||
}
|
||||
|
||||
if (nlt->flag & NLATRACK_ACTIVE) {
|
||||
active_nlt_index = nlt_index;
|
||||
}
|
||||
|
||||
for (NlaStrip *strip = nlt->strips.first; strip; strip = strip->next) {
|
||||
|
||||
if ((strip->flag & NLASTRIP_FLAG_SELECT) != 0) {
|
||||
highest_selected_strip_nlt_index = nlt_index;
|
||||
|
||||
if (lowest_selected_strip_nlt_index == -1) {
|
||||
lowest_selected_strip_nlt_index = nlt_index;
|
||||
}
|
||||
}
|
||||
|
||||
if (strip->flag & NLASTRIP_FLAG_ACTIVE) {
|
||||
active_strip_nlt_index = nlt_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Write outputs. */
|
||||
switch (insertion_location) {
|
||||
|
||||
case NLT_INSERT_ABOVE_ACTIVE_STRIP:
|
||||
*r_insertion_index = active_strip_nlt_index;
|
||||
*r_insert_below = false;
|
||||
|
||||
break;
|
||||
case NLT_INSERT_BELOW_ACTIVE_STRIP:
|
||||
*r_insertion_index = active_strip_nlt_index;
|
||||
*r_insert_below = true;
|
||||
break;
|
||||
|
||||
case NLT_INSERT_ABOVE_SELECTED_STRIPS:
|
||||
*r_insertion_index = highest_selected_strip_nlt_index;
|
||||
*r_insert_below = false;
|
||||
break;
|
||||
|
||||
case NLT_INSERT_BELOW_SELECTED_STRIPS:
|
||||
*r_insertion_index = lowest_selected_strip_nlt_index;
|
||||
*r_insert_below = true;
|
||||
break;
|
||||
|
||||
case NLT_INSERT_ABOVE_ACTIVE_TRACK:
|
||||
*r_insertion_index = active_nlt_index;
|
||||
*r_insert_below = false;
|
||||
|
||||
break;
|
||||
case NLT_INSERT_BELOW_ACTIVE_TRACK:
|
||||
*r_insertion_index = active_nlt_index;
|
||||
*r_insert_below = true;
|
||||
break;
|
||||
|
||||
case NLT_INSERT_ABOVE_SELECTED_TRACKS:
|
||||
*r_insertion_index = highest_selected_nlt_index;
|
||||
*r_insert_below = false;
|
||||
break;
|
||||
|
||||
case NLT_INSERT_BELOW_SELECTED_TRACKS:
|
||||
*r_insertion_index = lowest_selected_nlt_index;
|
||||
*r_insert_below = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
*r_insertion_index = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int nlaedit_resample_strips_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
char resample_name[MAX_NAME];
|
||||
RNA_string_get(op->ptr, "name", resample_name);
|
||||
int insertion_location = RNA_enum_get(op->ptr, "insertion_location");
|
||||
short resample_blendmode = RNA_enum_get(op->ptr, "blendmode");
|
||||
float resample_influence = RNA_float_get(op->ptr, "influence");
|
||||
|
||||
bAnimContext ac;
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* Get a list of AnimDatas being shown in the NLA. */
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
PointerRNA id_ptr;
|
||||
bool any_resample_succeeded = false;
|
||||
for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
|
||||
|
||||
int resample_insertion_index;
|
||||
bool insert_below;
|
||||
resample_strips_get_insertion_index(
|
||||
&ale->adt->nla_tracks, insertion_location, &resample_insertion_index, &insert_below);
|
||||
|
||||
if (resample_insertion_index == -1) {
|
||||
/** No strip selected. */
|
||||
BKE_report(op->reports, RPT_ERROR, "Insertion Location not found!");
|
||||
continue;
|
||||
}
|
||||
|
||||
RNA_id_pointer_create(ale->id, &id_ptr);
|
||||
NlaTrack *resampled_nlt = BKE_animsys_resample_selected_strips(ac.bmain,
|
||||
ac.depsgraph,
|
||||
ale->adt,
|
||||
&id_ptr,
|
||||
resample_name,
|
||||
resample_blendmode,
|
||||
resample_influence,
|
||||
resample_insertion_index,
|
||||
insert_below);
|
||||
if (resampled_nlt) {
|
||||
any_resample_succeeded = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free temp data. */
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
|
||||
if (!any_resample_succeeded) {
|
||||
/** Avoid pushing undo. */
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* Refresh auto strip properties. */
|
||||
ED_nla_postop_refresh(&ac);
|
||||
|
||||
/* New f-curves were added, meaning it's possible that it affects dependency graph components
|
||||
* which weren't previously animated. */
|
||||
DEG_relations_tag_update(ac.bmain);
|
||||
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_resample_strips(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Resample Strips To New";
|
||||
ot->idname = "NLA_OT_resample_strips";
|
||||
ot->description = "Resample selected strips into new strip";
|
||||
|
||||
/* api callbacks */
|
||||
|
||||
ot->invoke = WM_operator_props_popup_confirm;
|
||||
ot->exec = nlaedit_resample_strips_exec;
|
||||
ot->poll = nlaop_poll_tweakmode_off;
|
||||
|
||||
/* own properties */
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_string(
|
||||
ot->srna, "name", "Resample", sizeof(((NlaTrack *)NULL)->name), "Name", "");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
prop = RNA_def_enum(ot->srna,
|
||||
"blendmode",
|
||||
rna_enum_nla_mode_blend_items,
|
||||
NLASTRIP_MODE_REPLACE,
|
||||
"Blend Mode",
|
||||
"");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
prop = RNA_def_float_factor(ot->srna, "influence", 1, 0, 1, "Influence", "", 0, 1);
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
prop = RNA_def_enum(ot->srna,
|
||||
"insertion_location",
|
||||
rna_enum_nla_insertion_location,
|
||||
NLT_INSERT_BELOW_SELECTED_STRIPS,
|
||||
"Insertion Location",
|
||||
"");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
/* NLA Editing Operations (Modifying) */
|
||||
|
||||
|
@@ -98,6 +98,7 @@ void NLA_OT_meta_remove(wmOperatorType *ot);
|
||||
void NLA_OT_duplicate(wmOperatorType *ot);
|
||||
void NLA_OT_delete(wmOperatorType *ot);
|
||||
void NLA_OT_split(wmOperatorType *ot);
|
||||
void NLA_OT_resample_strips(wmOperatorType *ot);
|
||||
|
||||
void NLA_OT_mute_toggle(wmOperatorType *ot);
|
||||
|
||||
|
@@ -143,6 +143,7 @@ void nla_operatortypes(void)
|
||||
WM_operatortype_append(NLA_OT_duplicate);
|
||||
WM_operatortype_append(NLA_OT_delete);
|
||||
WM_operatortype_append(NLA_OT_split);
|
||||
WM_operatortype_append(NLA_OT_resample_strips);
|
||||
|
||||
WM_operatortype_append(NLA_OT_mute_toggle);
|
||||
|
||||
|
@@ -696,6 +696,32 @@ typedef enum eFCurve_Smoothing {
|
||||
|
||||
/* NLA Strips ------------------------------------- */
|
||||
|
||||
typedef struct NlaBlendTransform {
|
||||
struct NlaBlendTransform *prev, *next;
|
||||
/** Used for Strip Alignment of bones: This applies a transform to strip bone channels before
|
||||
* blending. This allows the animator to align traversal bones (like root bone) so that
|
||||
blending
|
||||
* will occur in the proper blend space. Otherwise, blending a Run midway through a Walk
|
||||
cycle,
|
||||
* where the root travels, results in the root blending to Run frame0, where the root is at
|
||||
zero.
|
||||
*/
|
||||
float location[3];
|
||||
float euler[3];
|
||||
float scale[3];
|
||||
float _pad;
|
||||
// char transform_target;
|
||||
// char _pad0[3];
|
||||
|
||||
/*Element: NlaBlendTransform_BoneTarget*/
|
||||
ListBase bones;
|
||||
} NlaBlendTransform;
|
||||
|
||||
typedef struct NlaBlendTransform_BoneTarget {
|
||||
struct NlaBlendTransform_BoneTarget *prev, *next;
|
||||
char name[64];
|
||||
} NlaBlendTransform_BoneTarget;
|
||||
|
||||
/**
|
||||
* NLA Strip (strip)
|
||||
*
|
||||
@@ -755,6 +781,9 @@ typedef struct NlaStrip {
|
||||
/* Pointer to an original NLA strip. */
|
||||
struct NlaStrip *orig_strip;
|
||||
|
||||
/*Element: NlaBlendTransform */
|
||||
ListBase blend_transforms;
|
||||
|
||||
void *_pad3;
|
||||
} NlaStrip;
|
||||
|
||||
@@ -797,6 +826,7 @@ typedef enum eNlaStrip_Flag {
|
||||
NLASTRIP_FLAG_USR_INFLUENCE = (1 << 5),
|
||||
NLASTRIP_FLAG_USR_TIME = (1 << 6),
|
||||
NLASTRIP_FLAG_USR_TIME_CYCLIC = (1 << 7),
|
||||
NLASTRIP_FLAG_ALIGNED = (1 << 8),
|
||||
|
||||
/** NLA strip length is synced to the length of the referenced action */
|
||||
NLASTRIP_FLAG_SYNC_LENGTH = (1 << 9),
|
||||
@@ -1124,6 +1154,8 @@ typedef enum eAnimData_Flag {
|
||||
ADT_NLA_EDIT_NOMAP = (1 << 3),
|
||||
/** NLA-Strip F-Curves are expanded in UI. */
|
||||
ADT_NLA_SKEYS_COLLAPSED = (1 << 4),
|
||||
/** Evaluate Tracks above tweaked strip. */
|
||||
ADT_NLA_EVAL_UPPER_TRACKS = (1 << 5),
|
||||
|
||||
/** Drivers expanded in UI. */
|
||||
ADT_DRIVERS_COLLAPSED = (1 << 10),
|
||||
|
@@ -429,6 +429,8 @@ extern StructRNA RNA_MulticamSequence;
|
||||
extern StructRNA RNA_MultiplyGpencilModifier;
|
||||
extern StructRNA RNA_MultiresModifier;
|
||||
extern StructRNA RNA_MusgraveTexture;
|
||||
extern StructRNA RNA_NlaBlendTransform_BoneTarget;
|
||||
extern StructRNA RNA_NlaBlendTransform;
|
||||
extern StructRNA RNA_NlaStrip;
|
||||
extern StructRNA RNA_NlaTrack;
|
||||
extern StructRNA RNA_Node;
|
||||
|
@@ -134,6 +134,23 @@ static void rna_AnimData_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *p
|
||||
ANIM_id_update(bmain, id);
|
||||
}
|
||||
|
||||
static void rna_AnimData_upper_stack_evaluation_set(PointerRNA *ptr, const bool value)
|
||||
{
|
||||
AnimData *adt = (AnimData *)ptr->data;
|
||||
if ((adt->flag & ADT_NLA_EDIT_ON) && adt->act_track) {
|
||||
|
||||
if (value) {
|
||||
for (NlaTrack *nlt = adt->act_track; nlt; nlt = nlt->next) {
|
||||
nlt->flag &= ~NLATRACK_DISABLED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (NlaTrack *nlt = adt->act_track; nlt; nlt = nlt->next) {
|
||||
nlt->flag |= NLATRACK_DISABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static void rna_AnimData_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
DEG_relations_tag_update(bmain);
|
||||
@@ -1384,8 +1401,14 @@ static void rna_def_animdata(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Pin in Graph Editor", "");
|
||||
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
|
||||
|
||||
RNA_define_lib_overridable(false);
|
||||
prop = RNA_def_property(srna, "use_upper_stack_evaluation", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", ADT_NLA_EVAL_UPPER_TRACKS);
|
||||
RNA_def_property_boolean_funcs(prop, NULL, "rna_AnimData_upper_stack_evaluation_set");
|
||||
RNA_def_property_ui_text(prop, "Evaluate tracks above tweaked strip. ", "");
|
||||
RNA_def_property_update(
|
||||
prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED | ND_NLA, "rna_AnimData_update");
|
||||
|
||||
RNA_define_lib_overridable(false);
|
||||
/* Animation Data API */
|
||||
RNA_api_animdata(srna);
|
||||
}
|
||||
|
@@ -37,6 +37,49 @@
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
/* enum defines exported for rna_animation.c */
|
||||
const EnumPropertyItem rna_enum_nla_mode_blend_items[] = {
|
||||
{NLASTRIP_MODE_REPLACE,
|
||||
"REPLACE",
|
||||
0,
|
||||
"Replace",
|
||||
"The strip values replace the accumulated results by amount specified by influence"},
|
||||
{NLASTRIP_MODE_COMBINE,
|
||||
"COMBINE",
|
||||
0,
|
||||
"Combine",
|
||||
"The strip values are combined with accumulated results by appropriately using addition, "
|
||||
"multiplication, or quaternion math, based on channel type"},
|
||||
{0, "", 0, NULL, NULL},
|
||||
{NLASTRIP_MODE_ADD,
|
||||
"ADD",
|
||||
0,
|
||||
"Add",
|
||||
"Weighted result of strip is added to the accumulated results"},
|
||||
{NLASTRIP_MODE_SUBTRACT,
|
||||
"SUBTRACT",
|
||||
0,
|
||||
"Subtract",
|
||||
"Weighted result of strip is removed from the accumulated results"},
|
||||
{NLASTRIP_MODE_MULTIPLY,
|
||||
"MULTIPLY",
|
||||
0,
|
||||
"Multiply",
|
||||
"Weighted result of strip is multiplied with the accumulated results"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
const EnumPropertyItem rna_enum_nla_mode_extend_items[] = {
|
||||
{NLASTRIP_EXTEND_NOTHING, "NOTHING", 0, "Nothing", "Strip has no influence past its extents"},
|
||||
{NLASTRIP_EXTEND_HOLD,
|
||||
"HOLD",
|
||||
0,
|
||||
"Hold",
|
||||
"Hold the first frame if no previous strips in track, and always hold last frame"},
|
||||
{NLASTRIP_EXTEND_HOLD_FORWARD, "HOLD_FORWARD", 0, "Hold Forward", "Only hold last frame"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
# include <math.h>
|
||||
@@ -101,6 +144,93 @@ static char *rna_NlaStrip_path(PointerRNA *ptr)
|
||||
return BLI_strdup("");
|
||||
}
|
||||
|
||||
static char *rna_NlaBlendTransform_path(PointerRNA *ptr)
|
||||
{
|
||||
NlaBlendTransform *blend_xform = (NlaBlendTransform *)ptr->data;
|
||||
AnimData *adt = BKE_animdata_from_id(ptr->owner_id);
|
||||
|
||||
/* if we're attached to AnimData, try to resolve path back to AnimData */
|
||||
if (adt) {
|
||||
NlaTrack *nlt;
|
||||
NlaStrip *nls;
|
||||
NlaBlendTransform *pbxform;
|
||||
|
||||
int pbxform_index;
|
||||
for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
|
||||
for (nls = nlt->strips.first; nls; nls = nls->next) {
|
||||
pbxform_index = 0;
|
||||
for (pbxform = nls->blend_transforms.first; pbxform;
|
||||
pbxform = pbxform->next, pbxform_index++) {
|
||||
if (pbxform == blend_xform) {
|
||||
/* XXX but if we animate like this, the control will never work... */
|
||||
char name_esc_nlt[sizeof(nlt->name) * 2];
|
||||
char name_esc_nls[sizeof(nls->name) * 2];
|
||||
|
||||
BLI_strescape(name_esc_nlt, nlt->name, sizeof(name_esc_nlt));
|
||||
BLI_strescape(name_esc_nls, nls->name, sizeof(name_esc_nls));
|
||||
return BLI_sprintfN(
|
||||
"animation_data.nla_tracks[\"%s\"].strips[\"%s\"].blend_transforms[%i]",
|
||||
name_esc_nlt,
|
||||
name_esc_nls,
|
||||
pbxform_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* no path */
|
||||
return BLI_strdup("");
|
||||
}
|
||||
|
||||
static char *rna_NlaBlendTransform_BoneTarget_path(PointerRNA *ptr)
|
||||
{
|
||||
NlaBlendTransform_BoneTarget *search_bone_name = (NlaBlendTransform_BoneTarget *)ptr->data;
|
||||
AnimData *adt = BKE_animdata_from_id(ptr->owner_id);
|
||||
|
||||
/* if we're attached to AnimData, try to resolve path back to AnimData */
|
||||
if (adt) {
|
||||
NlaTrack *nlt;
|
||||
NlaStrip *nls;
|
||||
NlaBlendTransform *pbxform;
|
||||
NlaBlendTransform_BoneTarget *bone_name;
|
||||
|
||||
int pbxform_index;
|
||||
int bone_index;
|
||||
for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
|
||||
for (nls = nlt->strips.first; nls; nls = nls->next) {
|
||||
pbxform_index = 0;
|
||||
for (pbxform = nls->blend_transforms.first; pbxform;
|
||||
pbxform = pbxform->next, pbxform_index++) {
|
||||
bone_index = 0;
|
||||
for (bone_name = pbxform->bones.first; bone_name;
|
||||
bone_name = bone_name->next, bone_index++) {
|
||||
|
||||
if (bone_name == search_bone_name) {
|
||||
/* XXX but if we animate like this, the control will never work... */
|
||||
char name_esc_nlt[sizeof(nlt->name) * 2];
|
||||
char name_esc_nls[sizeof(nls->name) * 2];
|
||||
|
||||
BLI_strescape(name_esc_nlt, nlt->name, sizeof(name_esc_nlt));
|
||||
BLI_strescape(name_esc_nls, nls->name, sizeof(name_esc_nls));
|
||||
return BLI_sprintfN(
|
||||
"animation_data.nla_tracks[\"%s\"].strips[\"%s\"].blend_transforms[%i].bones["
|
||||
"%i]",
|
||||
name_esc_nlt,
|
||||
name_esc_nls,
|
||||
pbxform_index,
|
||||
bone_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* no path */
|
||||
return BLI_strdup("");
|
||||
}
|
||||
|
||||
static void rna_NlaStrip_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
|
||||
{
|
||||
ID *id = ptr->owner_id;
|
||||
@@ -506,51 +636,52 @@ static void rna_NlaTrack_solo_set(PointerRNA *ptr, bool value)
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_nlastrip_blendXform_bone_name_set(PointerRNA *ptr, const char *value)
|
||||
{
|
||||
NlaBlendTransform_BoneTarget *pbxform_bone_name = (NlaBlendTransform_BoneTarget *)ptr->data;
|
||||
BLI_strncpy_utf8(pbxform_bone_name->name, value, sizeof(pbxform_bone_name->name));
|
||||
}
|
||||
|
||||
static NlaBlendTransform *rna_NlaStrip_blend_new(NlaStrip *strip, ReportList *reports)
|
||||
{
|
||||
NlaBlendTransform *blend_xform = BKE_nlastrip_new_blend_transform();
|
||||
BLI_addtail(&strip->blend_transforms, blend_xform);
|
||||
|
||||
return blend_xform;
|
||||
}
|
||||
|
||||
static void rna_NlaStrip_blend_remove(NlaStrip *strip, ReportList *reports, PointerRNA *blend)
|
||||
{
|
||||
BKE_nlastrip_free_blend_transform(strip, (NlaBlendTransform *)blend->data);
|
||||
}
|
||||
static void rna_NlaStrip_blend_remove_at(NlaStrip *strip, ReportList *reports, int blend_index)
|
||||
{
|
||||
BKE_nlastrip_free_blend_transform_at(strip, blend_index);
|
||||
}
|
||||
|
||||
static NlaBlendTransform_BoneTarget *rna_blend_bone_name_new(NlaBlendTransform *blend,
|
||||
ReportList *reports)
|
||||
{
|
||||
NlaBlendTransform_BoneTarget *bone_target = BKE_blend_transform_new_bone();
|
||||
BLI_addtail(&blend->bones, bone_target);
|
||||
return bone_target;
|
||||
}
|
||||
|
||||
static void rna_blend_bone_name_remove(NlaBlendTransform *blend,
|
||||
ReportList *reports,
|
||||
PointerRNA *bone_name)
|
||||
{
|
||||
BKE_blend_transform_free_bone(blend, (NlaBlendTransform_BoneTarget *)bone_name->data);
|
||||
}
|
||||
static void rna_blend_bone_name_remove_at(NlaBlendTransform *blend,
|
||||
ReportList *reports,
|
||||
int bone_name_index)
|
||||
{
|
||||
BKE_blend_transform_free_bone_at(blend, bone_name_index);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* enum defines exported for rna_animation.c */
|
||||
const EnumPropertyItem rna_enum_nla_mode_blend_items[] = {
|
||||
{NLASTRIP_MODE_REPLACE,
|
||||
"REPLACE",
|
||||
0,
|
||||
"Replace",
|
||||
"The strip values replace the accumulated results by amount specified by influence"},
|
||||
{NLASTRIP_MODE_COMBINE,
|
||||
"COMBINE",
|
||||
0,
|
||||
"Combine",
|
||||
"The strip values are combined with accumulated results by appropriately using addition, "
|
||||
"multiplication, or quaternion math, based on channel type"},
|
||||
{0, "", 0, NULL, NULL},
|
||||
{NLASTRIP_MODE_ADD,
|
||||
"ADD",
|
||||
0,
|
||||
"Add",
|
||||
"Weighted result of strip is added to the accumulated results"},
|
||||
{NLASTRIP_MODE_SUBTRACT,
|
||||
"SUBTRACT",
|
||||
0,
|
||||
"Subtract",
|
||||
"Weighted result of strip is removed from the accumulated results"},
|
||||
{NLASTRIP_MODE_MULTIPLY,
|
||||
"MULTIPLY",
|
||||
0,
|
||||
"Multiply",
|
||||
"Weighted result of strip is multiplied with the accumulated results"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
const EnumPropertyItem rna_enum_nla_mode_extend_items[] = {
|
||||
{NLASTRIP_EXTEND_NOTHING, "NOTHING", 0, "Nothing", "Strip has no influence past its extents"},
|
||||
{NLASTRIP_EXTEND_HOLD,
|
||||
"HOLD",
|
||||
0,
|
||||
"Hold",
|
||||
"Hold the first frame if no previous strips in track, and always hold last frame"},
|
||||
{NLASTRIP_EXTEND_HOLD_FORWARD, "HOLD_FORWARD", 0, "Hold Forward", "Only hold last frame"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static void rna_def_strip_fcurves(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -579,6 +710,46 @@ static void rna_def_strip_fcurves(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
static void rna_def_nlastrip_blendXforms(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
RNA_def_property_srna(cprop, "NlaBlendTransforms");
|
||||
srna = RNA_def_struct(brna, "NlaBlendTransforms", NULL);
|
||||
RNA_def_struct_sdna(srna, "NlaStrip");
|
||||
RNA_def_struct_ui_text(
|
||||
srna, "Nla Strip Preblend Transforms", "Collection of Preblend Transforms");
|
||||
|
||||
/* add target */
|
||||
func = RNA_def_function(srna, "add", "rna_NlaStrip_blend_new");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_function_ui_description(func, "Add a new bone");
|
||||
/* return type */
|
||||
parm = RNA_def_pointer(func, "blend", "NlaBlendTransform", "", "");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
/* remove target */
|
||||
func = RNA_def_function(srna, "remove", "rna_NlaStrip_blend_remove");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_function_ui_description(func, "Remove an existing bone from the armature");
|
||||
|
||||
/* target to remove*/
|
||||
parm = RNA_def_pointer(func, "blend", "NlaBlendTransform", "", "NlaBlendTransform to remove");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
|
||||
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
|
||||
|
||||
/* remove target */
|
||||
func = RNA_def_function(srna, "remove_at", "rna_NlaStrip_blend_remove_at");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_function_ui_description(func, "Remove an existing bone from the armature");
|
||||
|
||||
/* target to remove*/
|
||||
parm = RNA_def_int(func, "blend_index", 0, 0, INT_MAX, "blend_index", "", 0, INT_MAX);
|
||||
}
|
||||
|
||||
static void rna_def_nlastrip(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -823,6 +994,18 @@ static void rna_def_nlastrip(BlenderRNA *brna)
|
||||
"after tweaking strip and its keyframes");
|
||||
RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update");
|
||||
|
||||
// prop = RNA_def_property(srna, "use_alignment", PROP_BOOLEAN, PROP_NONE);
|
||||
// RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_ALIGNED);
|
||||
// RNA_def_property_ui_text(
|
||||
// prop, "Use Alignment", "Mark strip as aligned with other marked overlapping strips");
|
||||
|
||||
prop = RNA_def_property(srna, "blend_transforms", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "blend_transforms", NULL);
|
||||
RNA_def_property_struct_type(prop, "NlaBlendTransform");
|
||||
RNA_def_property_ui_text(prop, "PreBlendTransforms", "");
|
||||
rna_def_nlastrip_blendXforms(
|
||||
brna, prop); // GG: todo: test to ensure add/removal works before copying to bones
|
||||
|
||||
RNA_define_lib_overridable(false);
|
||||
}
|
||||
|
||||
@@ -931,13 +1114,105 @@ static void rna_def_nlatrack(BlenderRNA *brna)
|
||||
|
||||
RNA_define_lib_overridable(false);
|
||||
}
|
||||
static void rna_def_blend_bones(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
RNA_def_property_srna(cprop, "NlaBlendTransform_BoneTargets");
|
||||
srna = RNA_def_struct(brna, "NlaBlendTransform_BoneTargets", NULL);
|
||||
RNA_def_struct_sdna(srna, "NlaBlendTransform");
|
||||
RNA_def_struct_ui_text(srna,
|
||||
"Nla Strip Preblend Transform Bone Names",
|
||||
"Collection of Preblend Transform Bone Names");
|
||||
|
||||
/* add target */
|
||||
func = RNA_def_function(srna, "add", "rna_blend_bone_name_new");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_function_ui_description(func, "Add a new bone");
|
||||
/* return type */
|
||||
parm = RNA_def_pointer(func, "bone_name", "NlaBlendTransform_BoneTarget", "", "");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
/* remove target */
|
||||
func = RNA_def_function(srna, "remove", "rna_blend_bone_name_remove");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_function_ui_description(func, "Remove an existing bone from the armature");
|
||||
|
||||
/* target to remove*/
|
||||
parm = RNA_def_pointer(
|
||||
func, "bone_name", "NlaBlendTransform_BoneTarget", "", "NlaBlendTransform to remove");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
|
||||
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
|
||||
|
||||
/* remove target */
|
||||
func = RNA_def_function(srna, "remove_at", "rna_blend_bone_name_remove_at");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_function_ui_description(func, "Remove an existing bone from the armature");
|
||||
|
||||
/* target to remove*/
|
||||
parm = RNA_def_int(func, "bone_index", 0, 0, INT_MAX, "bone_index", "", 0, INT_MAX);
|
||||
}
|
||||
|
||||
static void rna_def_nlastrip_blendXform(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* struct definition */
|
||||
srna = RNA_def_struct(brna, "NlaBlendTransform", NULL);
|
||||
RNA_def_struct_ui_text(srna, "NLA Strip Pre-Blend Transform", "");
|
||||
RNA_def_struct_path_func(srna, "rna_NlaBlendTransform_path");
|
||||
/* name property */
|
||||
/** Note: should not be animated */
|
||||
prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION);
|
||||
RNA_def_property_ui_text(prop, "Location", "");
|
||||
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
|
||||
RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update");
|
||||
|
||||
prop = RNA_def_property(srna, "euler", PROP_FLOAT, PROP_EULER);
|
||||
RNA_def_property_ui_text(prop, "Rotation", "");
|
||||
RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update");
|
||||
|
||||
prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ);
|
||||
RNA_def_property_flag(prop, PROP_PROPORTIONAL);
|
||||
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 3);
|
||||
RNA_def_property_ui_text(prop, "Scale", "");
|
||||
RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update");
|
||||
|
||||
prop = RNA_def_property(srna, "bones", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "NlaBlendTransform_BoneTarget");
|
||||
RNA_def_property_ui_text(prop, "Bones", "Bones to apply pre-blend transform to before blending");
|
||||
rna_def_blend_bones(brna, prop);
|
||||
}
|
||||
|
||||
static void rna_def_nlastrip_blendXform_bone_name(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* struct definition */
|
||||
srna = RNA_def_struct(brna, "NlaBlendTransform_BoneTarget", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Bone Name", "");
|
||||
RNA_def_struct_path_func(srna, "rna_NlaBlendTransform_BoneTarget_path");
|
||||
RNA_def_struct_ui_icon(srna, ICON_GIZMO); /* XXX */
|
||||
|
||||
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Name", "Bone Name");
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_nlastrip_blendXform_bone_name_set");
|
||||
}
|
||||
/* --------- */
|
||||
|
||||
void RNA_def_nla(BlenderRNA *brna)
|
||||
{
|
||||
rna_def_nlatrack(brna);
|
||||
rna_def_nlastrip(brna);
|
||||
rna_def_nlastrip_blendXform(brna);
|
||||
rna_def_nlastrip_blendXform_bone_name(brna);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user