44 if (frame.is_selected()) {
45 frame.type = key_type;
61 return floorf(frame_number / secf + 0.5f) * secf;
78 for (
auto [frame_number, frame] : layer.
frames().
items()) {
79 if (!frame.is_selected()) {
84 if (snapped != frame_number) {
85 frame_number_destinations.
add(frame_number, snapped);
91 grease_pencil.move_frames(layer, frame_number_destinations);
104 return 2 * scene.
r.
cfra - frame_number;
107 return -frame_number;
109 if (first_selected_marker ==
nullptr) {
112 return 2 * first_selected_marker->
frame - frame_number;
124 bool changed =
false;
132 for (
auto [frame_number, frame] : layer.
frames().
items()) {
133 if (!frame.is_selected()) {
138 frame_number, scene, mode, first_selected_marker);
140 if (mirrored_frame_number != frame_number) {
141 frame_number_destinations.
add(frame_number, mirrored_frame_number);
147 grease_pencil.move_frames(layer, frame_number_destinations);
156 bool changed =
false;
157 LayerTransformData &trans_data = layer.
runtime->trans_data_;
160 if (!frame.is_selected()) {
165 const Drawing *drawing = grease_pencil.get_editable_drawing_at(layer, frame_number);
166 if (drawing ==
nullptr) {
169 const int duplicated_drawing_index = grease_pencil.drawings().size();
170 grease_pencil.add_duplicate_drawings(1, *drawing);
175 trans_data.duplicated_frames_buffer.add_overwrite(frame_number, frame_duplicate);
193 for (
auto [frame_number, frame] : layer.
frames().
items()) {
194 if (!frame.is_selected()) {
197 frames_to_remove.
append(frame_number);
199 return grease_pencil.remove_frames(layer, frames_to_remove.
as_span());
204 switch (select_mode) {
218 const int frame_number,
219 const short select_mode)
223 if (frame ==
nullptr) {
232 const int frame_number,
233 const short select_mode)
256 for (
const auto &[frame_number, frame] : layer.
frames().
items()) {
257 if (frame.is_selected()) {
267 const short select_mode)
302 const short select_mode)
321 const int frame_number,
326 ce->
sel = frame.is_selected();
335 for (
const auto &[frame_number, frame] : layer.
frames().
items()) {
336 if (frame.is_selected()) {
345 const bool duplicate_previous_key,
346 bool &r_inserted_keyframe)
348 const int current_frame = scene.
r.
cfra;
356 const std::optional<int> previous_key_frame_start = layer.
start_frame_at(current_frame);
357 const bool has_previous_key = previous_key_frame_start.has_value();
358 const bool needs_new_drawing = is_first || !has_previous_key ||
359 (previous_key_frame_start < current_frame);
363 if (has_previous_key && (use_additive_drawing || duplicate_previous_key)) {
365 grease_pencil.insert_duplicate_frame(layer, *previous_key_frame_start, current_frame,
false);
369 grease_pencil.insert_frame(layer, current_frame);
371 r_inserted_keyframe =
true;
384 const int current_frame = scene->
r.
cfra;
388 bool changed =
false;
390 for (
Layer *layer : grease_pencil.layers_for_write()) {
391 if (!layer->is_editable()) {
394 changed |= grease_pencil.insert_frame(*layer, current_frame, duration) !=
nullptr;
398 if (!grease_pencil.has_active_layer()) {
401 changed |= grease_pencil.insert_frame(
402 *grease_pencil.get_active_layer(), current_frame, duration) !=
nullptr;
428 if (attrs_span_a.
data() == attrs_span_b.
data()) {
440 const std::optional<T> value_a = attributes_a.
get_if_single();
441 const std::optional<T> value_b = attributes_b.
get_if_single();
442 if (value_a.has_value() && value_b.has_value()) {
443 return value_a.value() == value_b.value();
450 attrs_span_a.
begin(), attrs_span_a.
end(), attrs_span_b.
begin(), attrs_span_b.
end());
473 if (ids_a != ids_b) {
489 bool attributes_are_equal =
true;
492 using T = decltype(dummy);
494 const VArray attributes_a = attrs_a.varray.typed<T>();
495 const VArray attributes_b = attrs_b.varray.typed<T>();
497 attributes_are_equal = attributes_elements_are_equal(attributes_a, attributes_b);
500 if (!attributes_are_equal) {
515 bool changed =
false;
517 for (
Layer *layer : grease_pencil.layers_for_write()) {
518 if (!layer->is_editable()) {
525 if (selected && !frame->is_selected()) {
528 if (frame->is_end()) {
531 start_frame_numbers.
append(
int(key));
536 const int current = start_frame_numbers[
i];
537 const int next = start_frame_numbers[
i + 1];
539 Drawing *drawing = grease_pencil.get_drawing_at(*layer, current);
540 Drawing *drawing_next = grease_pencil.get_drawing_at(*layer,
next);
542 if (!drawing || !drawing_next) {
556 grease_pencil.remove_frames(*layer, frame_numbers_to_delete.
as_span());
575 ot->name =
"Insert Blank Frame";
576 ot->idname =
"GREASE_PENCIL_OT_insert_blank_frame";
577 ot->description =
"Insert a blank frame on the current scene frame";
587 ot->srna,
"all_layers",
false,
"All Layers",
"Insert a blank frame in all editable layers");
597 ot->name =
"Delete Duplicate Frames";
598 ot->idname =
"GREASE_PENCIL_OT_frame_clean_duplicate";
599 ot->description =
"Remove any keyframe that is a duplicate of the previous one";
609 ot->srna,
"selected",
false,
"Selected",
"Only delete selected keyframes");
622 ListBase anim_data = {
nullptr,
nullptr};
635 Layer *layer =
reinterpret_cast<Layer *
>(ale->data);
637 FramesMapKeyT layer_first_frame = std::numeric_limits<int>::max();
638 FramesMapKeyT layer_last_frame = std::numeric_limits<int>::min();
639 for (
auto [frame_number, frame] : layer->
frames().
items()) {
640 if (frame.is_selected()) {
641 const Drawing *drawing = grease_pencil->get_drawing_at(*layer, frame_number);
647 layer_first_frame = std::min(frame_number, layer_first_frame);
648 layer_last_frame = std::max(frame_number, layer_last_frame);
653 clipboard.
copy_buffer.add_new(layer->name(), {buf, layer_first_frame, layer_last_frame});
675 switch (offset_mode) {
683 offset = (cfra - clipboard.
cfra);
708 ListBase anim_data = {
nullptr,
nullptr};
714 const bool from_single_channel = clipboard.
copy_buffer.size() == 1;
722 Layer &layer = *
reinterpret_cast<Layer *
>(ale->data);
723 const std::string layer_name = layer.name();
724 if (!from_single_channel && !clipboard.
copy_buffer.contains(layer_name)) {
728 from_single_channel ? *clipboard.
copy_buffer.values().begin() :
730 bool changed =
false;
733 switch (merge_mode) {
741 for (
auto frame_number : layer.
frames().
keys()) {
742 frames_to_remove.
append(frame_number);
744 grease_pencil->remove_frames(layer, frames_to_remove);
750 int frame_min, frame_max;
764 if (frame_min < frame_max) {
766 for (
auto frame_number : layer.
frames().
keys()) {
767 if (frame_min < frame_number && frame_number < frame_max) {
768 frames_to_remove.
append(frame_number);
771 grease_pencil->remove_frames(layer, frames_to_remove);
778 const int target_frame_number = item.
frame_number + offset;
780 grease_pencil->remove_frames(layer, {target_frame_number});
782 Drawing &dst_drawing = *grease_pencil->insert_frame(
806 const int current_frame = scene->
r.
cfra;
807 bool changed =
false;
809 auto insert_duplicate_frame = [&](
Layer &layer, std::optional<int> active_frame_number) {
810 if (!active_frame_number.has_value()) {
813 return grease_pencil.insert_duplicate_frame(
814 layer, active_frame_number.value(), current_frame,
false);
818 if (!grease_pencil.has_active_layer()) {
821 Layer &active_layer = *grease_pencil.get_active_layer();
822 const std::optional<int> active_frame_number = active_layer.
start_frame_at(current_frame);
823 changed |= insert_duplicate_frame(active_layer, active_frame_number);
826 for (
Layer *layer : grease_pencil.layers_for_write()) {
827 const std::optional<int> active_frame_number = layer->
start_frame_at(current_frame);
828 changed |= insert_duplicate_frame(*layer, active_frame_number);
845 ot->name =
"Duplicate Active Frame(s)";
846 ot->idname =
"GREASE_PENCIL_OT_frame_duplicate";
847 ot->description =
"Make a copy of the active Grease Pencil frame(s)";
857 ot->srna,
"all",
false,
"Duplicate all",
"Duplicate active keyframes of all layer");
867 const int current_frame = scene->
r.
cfra;
868 bool changed =
false;
871 Layer *active_layer = grease_pencil.get_active_layer();
872 if ((active_layer ==
nullptr) || active_layer->is_locked()) {
875 if (std::optional<int> active_frame_number = active_layer->
start_frame_at(current_frame)) {
876 changed |= grease_pencil.remove_frames(*active_layer, {active_frame_number.value()});
880 for (
Layer *layer : grease_pencil.layers_for_write()) {
881 if (layer->is_locked()) {
884 if (std::optional<int> active_frame_number = layer->start_frame_at(current_frame)) {
885 changed |= grease_pencil.remove_frames(*layer, {active_frame_number.value()});
903 ot->name =
"Delete Active Frame(s)";
904 ot->idname =
"GREASE_PENCIL_OT_active_frame_delete";
905 ot->description =
"Delete the active Grease Pencil frame(s)";
914 RNA_def_boolean(
ot->srna,
"all",
false,
"Delete all",
"Delete active keyframes of all layers");
946 const int curr_frame_index = sorted_keys.
first_index(current_frame);
949 for (
int i = curr_frame_index;
i <= sorted_keys.
size();
i++) {
950 int frame_number = sorted_keys[
i];
953 frame_numbers_to_remove.
append(frame_number);
958 for (
int i = curr_frame_index - 1;
i >= 0;
i--) {
959 int frame_number = sorted_keys[
i];
962 frame_numbers_to_remove.
append(frame_number);
968 if (frame_numbers_to_remove.
is_empty()) {
972 grease_pencil.remove_frames(*active_layer, frame_numbers_to_remove);
983 ot->name =
"Delete Breakdown Frames";
984 ot->idname =
"GREASE_PENCIL_OT_delete_breakdown";
986 "Remove breakdown frames generated by interpolating between two Grease Pencil frames";
Functions to insert, delete or modify keyframes.
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Low-level operations for curves.
Low-level operations for grease pencil.
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
MINLINE int round_fl_to_int(float a)
#define IN_RANGE(a, b, c)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ GP_TOOL_FLAG_RETAIN_LAST
@ ANIMTYPE_GREASE_PENCIL_LAYER
@ ANIMFILTER_DATA_VISIBLE
@ ANIMFILTER_LIST_VISIBLE
@ KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL
@ KEYFRAME_PASTE_MERGE_OVER_RANGE
@ KEYFRAME_PASTE_MERGE_OVER
@ KEYFRAME_PASTE_MERGE_MIX
@ KEYFRAME_PASTE_OFFSET_NONE
@ KEYFRAME_PASTE_OFFSET_CFRA_END
@ KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE
@ KEYFRAME_PASTE_OFFSET_CFRA_START
void ANIM_animdata_freelist(ListBase *anim_data)
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, const eAnimFilter_Flags filter_mode, void *data, const eAnimCont_Types datatype)
int ED_markers_find_nearest_marker_time(ListBase *markers, float x)
TimeMarker * ED_markers_get_first_selected(ListBase *markers)
const Value * lookup_ptr(const Key &key) const
ValueIterator values() const &
KeyIterator keys() const &
bool contains(const Key &key) const
ItemIterator items() const &
const void * data() const
GSpan get_internal_span() const
const CPPType & type() const
constexpr IndexRange drop_back(int64_t n) const
bool add(const Key &key, const Value &value)
constexpr int64_t first_index(const T &search_value) const
constexpr int64_t size() const
constexpr const T * end() const
constexpr const T * begin() const
std::optional< T > get_if_single() const
void append(const T &value)
IndexRange index_range() const
Span< T > as_span() const
GAttributeReader lookup(const StringRef attribute_id) const
Set< StringRefNull > all_ids() const
Span< int > offsets() const
AttributeAccessor attributes() const
bke::CurvesGeometry & strokes_for_write()
const Map< FramesMapKeyT, GreasePencilFrame > & frames() const
const GreasePencilFrame * frame_at(const int frame_number) const
void tag_frames_map_changed()
bool has_drawing_at(const int frame_number) const
int get_frame_duration_at(const int frame_number) const
std::optional< int > start_frame_at(int frame_number) const
Span< FramesMapKeyT > sorted_keys() const
Map< FramesMapKeyT, GreasePencilFrame > & frames_for_write()
const LayerGroup & as_group() const
const Layer & as_layer() const
void ED_operatortypes_grease_pencil_frames()
bool keyframe_region_lasso_test(const KeyframeEdit_LassoData *data_lasso, const float xy[2])
bool keyframe_region_circle_test(const KeyframeEdit_CircleData *data_circle, const float xy[2])
void * MEM_callocN(size_t len, const char *str)
bool is_autokey_on(const Scene *scene)
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
void select_frames_at(bke::greasepencil::LayerGroup &layer_group, const int frame_number, const short select_mode)
bool active_grease_pencil_poll(bContext *C)
static void GREASE_PENCIL_OT_active_frame_delete(wmOperatorType *ot)
bool remove_all_selected_frames(GreasePencil &grease_pencil, bke::greasepencil::Layer &layer)
bool grease_pencil_copy_keyframes(bAnimContext *ac, KeyframeClipboard &clipboard)
bool grease_pencil_paste_keyframes(bAnimContext *ac, const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, const KeyframeClipboard &clipboard)
bool ensure_active_keyframe(const Scene &scene, GreasePencil &grease_pencil, bke::greasepencil::Layer &layer, const bool duplicate_previous_key, bool &r_inserted_keyframe)
static wmOperatorStatus grease_pencil_delete_breakdown_frames_exec(bContext *C, wmOperator *)
static wmOperatorStatus frame_clean_duplicate_exec(bContext *C, wmOperator *op)
static float get_snapped_frame_number(const float frame_number, Scene &scene, const eEditKeyframes_Snap mode)
static wmOperatorStatus insert_blank_frame_exec(bContext *C, wmOperator *op)
void set_selected_frames_type(bke::greasepencil::Layer &layer, const eBezTriple_KeyframeType key_type)
static wmOperatorStatus grease_pencil_frame_duplicate_exec(bContext *C, wmOperator *op)
bool mirror_selected_frames(GreasePencil &grease_pencil, bke::greasepencil::Layer &layer, Scene &scene, const eEditKeyframes_Mirror mode)
void select_frames_range(bke::greasepencil::TreeNode &node, const float min, const float max, const short select_mode)
static bool curves_geometry_is_equal(const bke::CurvesGeometry &curves_a, const bke::CurvesGeometry &curves_b)
static int get_mirrored_frame_number(const int frame_number, const Scene &scene, const eEditKeyframes_Mirror mode, const TimeMarker *first_selected_marker)
static void select_frame(GreasePencilFrame &frame, const short select_mode)
void create_keyframe_edit_data_selected_frames_list(KeyframeEditData *ked, const bke::greasepencil::Layer &layer)
void select_frames_region(KeyframeEditData *ked, bke::greasepencil::TreeNode &node, const short tool, const short select_mode)
bool has_any_frame_selected(const bke::greasepencil::Layer &layer)
static bool attributes_varrays_not_equal(const bke::GAttributeReader &attrs_a, const bke::GAttributeReader &attrs_b)
static void GREASE_PENCIL_OT_frame_clean_duplicate(wmOperatorType *ot)
static bool attributes_elements_are_equal(const VArray< T > &attributes_a, const VArray< T > &attributes_b)
bool editable_grease_pencil_poll(bContext *C)
void select_all_frames(bke::greasepencil::Layer &layer, const short select_mode)
static void append_frame_to_key_edit_data(KeyframeEditData *ked, const int frame_number, const GreasePencilFrame &frame)
static void GREASE_PENCIL_OT_insert_blank_frame(wmOperatorType *ot)
static void GREASE_PENCIL_OT_frame_duplicate(wmOperatorType *ot)
bool duplicate_selected_frames(GreasePencil &grease_pencil, bke::greasepencil::Layer &layer)
static int calculate_offset(const eKeyPasteOffset offset_mode, const int cfra, const KeyframeClipboard &clipboard)
static wmOperatorStatus grease_pencil_active_frame_delete_exec(bContext *C, wmOperator *op)
static bool grease_pencil_active_breakdown_frame_poll(bContext *C)
static void GREASE_PENCIL_OT_delete_breakdown(wmOperatorType *ot)
static bool attributes_varrays_span_data_equal(const bke::GAttributeReader &attrs_a, const bke::GAttributeReader &attrs_b)
bool select_frame_at(bke::greasepencil::Layer &layer, const int frame_number, const short select_mode)
bool snap_selected_frames(GreasePencil &grease_pencil, bke::greasepencil::Layer &layer, Scene &scene, const eEditKeyframes_Snap mode)
VecBase< float, 2 > float2
int RNA_int_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
GreasePencilLayerRuntimeHandle * runtime
struct ToolSettings * toolsettings
eBezTriple_KeyframeType keytype
blender::bke::greasepencil::FramesMapKeyT frame_number
bke::greasepencil::Drawing drawing
blender::bke::greasepencil::FramesMapKeyT last_frame
Vector< DrawingBufferItem > drawing_buffers
blender::bke::greasepencil::FramesMapKeyT first_frame
Map< std::string, LayerBufferItem > copy_buffer
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))