Blender V4.3
grease_pencil_convert_legacy.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <optional>
10
11#include <fmt/format.h>
12
13#include "BKE_action.hh"
14#include "BKE_anim_data.hh"
15#include "BKE_attribute.hh"
17#include "BKE_colorband.hh"
18#include "BKE_colortools.hh"
19#include "BKE_curves.hh"
20#include "BKE_deform.hh"
21#include "BKE_fcurve.hh"
23#include "BKE_grease_pencil.hh"
25#include "BKE_idprop.hh"
26#include "BKE_lib_id.hh"
27#include "BKE_lib_remap.hh"
28#include "BKE_main.hh"
29#include "BKE_material.h"
30#include "BKE_modifier.hh"
31#include "BKE_node.hh"
33#include "BKE_object.hh"
34#include "BKE_screen.hh"
35
36#include "BLO_readfile.hh"
37
38#include "BLI_color.hh"
39#include "BLI_function_ref.hh"
40#include "BLI_listbase.h"
41#include "BLI_map.hh"
42#include "BLI_math_matrix.h"
44#include "BLI_string.h"
45#include "BLI_string_utf8.h"
46#include "BLI_vector.hh"
47
48#include "BLT_translation.hh"
49
50#include "DNA_anim_types.h"
54#include "DNA_meshdata_types.h"
55#include "DNA_modifier_types.h"
56#include "DNA_screen_types.h"
57#include "DNA_space_types.h"
58
59#include "DEG_depsgraph.hh"
61
62#include "ANIM_action.hh"
64#include "ANIM_action_legacy.hh"
65
67
84
85/* -------------------------------------------------------------------- */
91
92using FCurveConvertCB = void(FCurve &fcurve);
93
118
138 ConversionData &conversion_data;
139
140 ID &id_src;
141 ID &id_dst;
142 AnimData *animdata_src;
143 AnimData *animdata_dst;
144
146 const bool is_transfer_between_ids;
152 const bool skip_nla;
153
162 const Array<AnimDataFCurveConvertor> fcurve_convertors;
163
164 public:
169 std::string root_path_src = "";
170 std::string root_path_dst = "";
171
172 private:
179 blender::Vector<FCurve *> fcurves_from_src_main_action = {};
180 blender::Vector<FCurve *> fcurves_from_src_tmp_action = {};
181 blender::Vector<FCurve *> fcurves_from_src_drivers = {};
184 bool has_changes = false;
185
186 public:
189 ID &id_src,
190 const Array<AnimDataFCurveConvertor> fcurve_convertors = {})
191 : conversion_data(conversion_data),
192 id_src(id_src),
193 id_dst(id_src),
194 animdata_src(BKE_animdata_from_id(&id_src)),
195 animdata_dst(BKE_animdata_from_id(&id_dst)),
196 is_transfer_between_ids(false),
197 skip_nla(false),
198 fcurve_convertors(fcurve_convertors)
199 {
200 }
201
203 ID &id_dst,
204 ID &id_src,
205 const Array<AnimDataFCurveConvertor> fcurve_convertors = {})
206 : conversion_data(conversion_data),
207 id_src(id_src),
208 id_dst(id_dst),
209 animdata_src(BKE_animdata_from_id(&id_src)),
210 animdata_dst(BKE_animdata_from_id(&id_dst)),
211 is_transfer_between_ids(true),
212 skip_nla(true),
213 fcurve_convertors(fcurve_convertors)
214 {
215 }
217
218 private:
219 using FCurveCallback = bool(bAction *owner_action, FCurve &fcurve);
220 using ActionCallback = bool(bAction &action);
221
224 bool is_valid() const
225 {
226 return this->animdata_src != nullptr;
227 }
228
229 /* Basic common check to decide whether a legacy fcurve should be processed or not. */
230 bool legacy_fcurves_is_valid_for_root_path(FCurve &fcurve, StringRefNull legacy_root_path) const
231 {
232 if (!fcurve.rna_path) {
233 return false;
234 }
235 StringRefNull rna_path = fcurve.rna_path;
236 if (!rna_path.startswith(legacy_root_path)) {
237 return false;
238 }
239 return true;
240 }
241
246 bool animation_fcurve_is_valid(bAction *owner_action, FCurve &fcurve) const
247 {
248 if (!this->is_valid()) {
249 return false;
250 }
251 /* Only take into account drivers (nullptr `action_owner`), and Actions directly assigned
252 * to the animdata, not the NLA ones. */
253 if (owner_action &&
254 !ELEM(owner_action, this->animdata_src->action, this->animdata_src->tmpact))
255 {
256 return false;
257 }
258 if (!legacy_fcurves_is_valid_for_root_path(fcurve, this->root_path_src)) {
259 return false;
260 }
261 return true;
262 }
263
264 /* Iterator over all FCurves in a given animation data. */
265
266 bool fcurve_foreach_in_action(bAction *owner_action,
267 blender::FunctionRef<FCurveCallback> callback) const
268 {
269 bool is_changed = false;
270 animrig::foreach_fcurve_in_action(owner_action->wrap(), [&](FCurve &fcurve) {
271 const bool local_is_changed = callback(owner_action, fcurve);
272 is_changed = is_changed || local_is_changed;
273 });
274
275 return is_changed;
276 }
277
278 bool fcurve_foreach_in_listbase(ListBase &fcurves,
279 blender::FunctionRef<FCurveCallback> callback) const
280 {
281 bool is_changed = false;
282 LISTBASE_FOREACH (FCurve *, fcurve, &fcurves) {
283 const bool local_is_changed = callback(nullptr, *fcurve);
284 is_changed = is_changed || local_is_changed;
285 }
286 return is_changed;
287 }
288
289 bool nla_strip_fcurve_foreach(NlaStrip &nla_strip,
290 blender::FunctionRef<FCurveCallback> callback) const
291 {
292 bool is_changed = false;
293 if (nla_strip.act) {
294 if (this->fcurve_foreach_in_action(nla_strip.act, callback)) {
296 is_changed = true;
297 }
298 }
299 LISTBASE_FOREACH (NlaStrip *, nla_strip_children, &nla_strip.strips) {
300 const bool local_is_changed = this->nla_strip_fcurve_foreach(*nla_strip_children, callback);
301 is_changed = is_changed || local_is_changed;
302 }
303 return is_changed;
304 }
305
306 bool animdata_fcurve_foreach(AnimData &anim_data,
307 blender::FunctionRef<FCurveCallback> callback) const
308 {
309 bool is_changed = false;
310 if (anim_data.action) {
311 if (this->fcurve_foreach_in_action(anim_data.action, callback)) {
313 is_changed = true;
314 }
315 }
316 if (anim_data.tmpact) {
317 if (this->fcurve_foreach_in_action(anim_data.tmpact, callback)) {
319 is_changed = true;
320 }
321 }
322
323 {
324 const bool local_is_changed = this->fcurve_foreach_in_listbase(anim_data.drivers, callback);
325 is_changed = is_changed || local_is_changed;
326 }
327
328 /* NOTE: New layered actions system can be ignored here, it did not exist together with GPv2.
329 */
330
331 if (this->skip_nla) {
332 return is_changed;
333 }
334
335 LISTBASE_FOREACH (NlaTrack *, nla_track, &anim_data.nla_tracks) {
336 LISTBASE_FOREACH (NlaStrip *, nla_strip, &nla_track->strips) {
337 const bool local_is_changed = this->nla_strip_fcurve_foreach(*nla_strip, callback);
338 is_changed = is_changed || local_is_changed;
339 }
340 }
341 return is_changed;
342 }
343
344 bool action_process(bAction &action, blender::FunctionRef<ActionCallback> callback) const
345 {
346 if (callback(action)) {
348 return true;
349 }
350 return false;
351 }
352
353 bool nla_strip_action_foreach(NlaStrip &nla_strip,
354 blender::FunctionRef<ActionCallback> callback) const
355 {
356 bool is_changed = false;
357 if (nla_strip.act) {
358 is_changed = action_process(*nla_strip.act, callback);
359 }
360 LISTBASE_FOREACH (NlaStrip *, nla_strip_children, &nla_strip.strips) {
361 is_changed = is_changed || this->nla_strip_action_foreach(*nla_strip_children, callback);
362 }
363 return is_changed;
364 }
365
366 bool animdata_action_foreach(AnimData &anim_data,
367 blender::FunctionRef<ActionCallback> callback) const
368 {
369 bool is_changed = false;
370
371 if (anim_data.action) {
372 is_changed = is_changed || action_process(*anim_data.action, callback);
373 }
374 if (anim_data.tmpact) {
375 is_changed = is_changed || action_process(*anim_data.tmpact, callback);
376 }
377
378 /* NOTE: New layered actions system can be ignored here, it did not exist together with GPv2.
379 */
380
381 if (this->skip_nla) {
382 return is_changed;
383 }
384
385 LISTBASE_FOREACH (NlaTrack *, nla_track, &anim_data.nla_tracks) {
386 LISTBASE_FOREACH (NlaStrip *, nla_strip, &nla_track->strips) {
387 is_changed = is_changed || this->nla_strip_action_foreach(*nla_strip, callback);
388 }
389 }
390 return is_changed;
391 }
392
393 public:
399 {
400 if (!this->is_valid()) {
401 return false;
402 }
403
404 if (GS(id_src.name) != GS(id_dst.name)) {
405 return true;
406 }
407
408 bool has_animation = false;
409 auto animation_detection_cb = [&](bAction *owner_action, FCurve &fcurve) -> bool {
410 /* Early out if we already know that the target data is animated. */
411 if (has_animation) {
412 return false;
413 }
414 if (!this->animation_fcurve_is_valid(owner_action, fcurve)) {
415 return false;
416 }
417 if (this->fcurve_convertors.is_empty()) {
418 has_animation = true;
419 return false;
420 }
421 StringRefNull rna_path = fcurve.rna_path;
422 for (const AnimDataFCurveConvertor &fcurve_convertor : this->fcurve_convertors) {
423 const std::string rna_path_src = fmt::format(
424 "{}{}", this->root_path_src, fcurve_convertor.relative_rna_path_src);
425 if (rna_path == rna_path_src) {
426 has_animation = true;
427 return false;
428 }
429 }
430 return false;
431 };
432
433 this->animdata_fcurve_foreach(*this->animdata_src, animation_detection_cb);
434 return has_animation;
435 }
436
444 {
445 if (!this->is_valid()) {
446 return;
447 }
448
449 auto fcurve_convert_cb = [&](const AnimDataFCurveConvertor *fcurve_convertor,
450 bAction *owner_action,
451 FCurve &fcurve,
452 const std::string &rna_path_dst) {
453 MEM_freeN(fcurve.rna_path);
454 fcurve.rna_path = BLI_strdupn(rna_path_dst.c_str(), rna_path_dst.size());
455 if (fcurve_convertor && fcurve_convertor->convert_cb) {
456 fcurve_convertor->convert_cb(fcurve);
457 }
458 this->has_changes = true;
459
460 if (!this->is_transfer_between_ids) {
461 return;
462 }
463 if (owner_action) {
464 if (owner_action == this->animdata_src->action) {
465 this->fcurves_from_src_main_action.append(&fcurve);
466 }
467 else if (owner_action == this->animdata_src->tmpact) {
468 this->fcurves_from_src_tmp_action.append(&fcurve);
469 }
470 }
471 else { /* Driver */
472 this->fcurves_from_src_drivers.append(&fcurve);
473 }
474 };
475
476 /* Update all FCurves which RNA path starts with the #root_path_src. */
477 if (this->fcurve_convertors.is_empty()) {
478 auto fcurve_root_path_convert_cb = [&](bAction *owner_action, FCurve &fcurve) -> bool {
479 if (!legacy_fcurves_is_valid_for_root_path(fcurve, this->root_path_src)) {
480 return false;
481 }
482 StringRefNull rna_path = fcurve.rna_path;
483 const std::string rna_path_dst = fmt::format(
484 "{}{}", this->root_path_dst, rna_path.substr(int64_t(this->root_path_src.size())));
485 fcurve_convert_cb(nullptr, owner_action, fcurve, rna_path_dst);
486 return true;
487 };
488
489 this->animdata_fcurve_foreach(*(this->animdata_src), fcurve_root_path_convert_cb);
490 return;
491 }
492
493 /* Update all FCurves which RNA path starts with the #root_path_src, and remains of the path
494 * matches one of the entries in #fcurve_convertors. */
495 auto fcurve_full_path_convert_cb = [&](bAction *owner_action, FCurve &fcurve) -> bool {
496 if (!animation_fcurve_is_valid(owner_action, fcurve)) {
497 return false;
498 }
499 StringRefNull rna_path = fcurve.rna_path;
500 for (const AnimDataFCurveConvertor &fcurve_convertor : this->fcurve_convertors) {
501 const std::string rna_path_src = fmt::format(
502 "{}{}", this->root_path_src, fcurve_convertor.relative_rna_path_src);
503 if (rna_path == rna_path_src) {
504 const std::string rna_path_dst = fmt::format(
505 "{}{}", this->root_path_dst, fcurve_convertor.relative_rna_path_dst);
506 fcurve_convert_cb(&fcurve_convertor, owner_action, fcurve, rna_path_dst);
507 return true;
508 }
509 }
510 return false;
511 };
512
513 this->animdata_fcurve_foreach(*(this->animdata_src), fcurve_full_path_convert_cb);
514 }
515
527 {
528 if (!this->is_valid()) {
529 return;
530 }
531
532 /* Ensure existing actions moved to a different ID type keep a 'valid' `idroot` value. Not
533 * essential, but 'nice to have'. */
534 if (GS(this->id_src.name) != GS(this->id_dst.name)) {
535 if (!this->animdata_dst) {
536 this->animdata_dst = BKE_animdata_ensure_id(&this->id_dst);
537 }
538 auto actions_idroot_ensure = [&](bAction &action) -> bool {
539 action.idroot = GS(this->id_dst.name);
540 return true;
541 };
542 this->animdata_action_foreach(*this->animdata_dst, actions_idroot_ensure);
543 }
544
545 if (&id_src == &id_dst) {
546 if (this->has_changes) {
548 DEG_relations_tag_update(&this->conversion_data.bmain);
549 }
550 return;
551 }
552
553 if (this->fcurves_from_src_main_action.is_empty() &&
554 this->fcurves_from_src_tmp_action.is_empty() && this->fcurves_from_src_drivers.is_empty())
555 {
556 return;
557 }
558 if (!this->animdata_dst) {
559 this->animdata_dst = BKE_animdata_ensure_id(&this->id_dst);
560 }
561
562 auto fcurves_move = [&](bAction *action_dst,
563 const animrig::slot_handle_t slot_handle_dst,
564 bAction *action_src,
565 const Span<FCurve *> fcurves) {
566 for (FCurve *fcurve : fcurves) {
568 action_dst->wrap(), slot_handle_dst, action_src->wrap(), *fcurve);
569 }
570 };
571
572 auto fcurves_move_between_listbases =
573 [&](ListBase &fcurves_dst, ListBase &fcurves_src, const Span<FCurve *> fcurves) {
574 for (FCurve *fcurve : fcurves) {
575 BLI_assert(BLI_findindex(&fcurves_src, fcurve) >= 0);
576 BLI_remlink(&fcurves_src, fcurve);
577 BLI_addtail(&fcurves_dst, fcurve);
578 }
579 };
580
581 if (!this->fcurves_from_src_main_action.is_empty()) {
582 if (!this->animdata_dst->action) {
583 /* Create a new action. */
585 this->conversion_data.bmain,
586 this->animdata_src->action ? this->animdata_src->action->id.name + 2 : nullptr);
587 if (USER_EXPERIMENTAL_TEST(&U, use_animation_baklava)) {
588 action.slot_add_for_id(this->id_dst);
589 }
590 const bool ok = animrig::assign_action(&action, {this->id_dst, *this->animdata_dst});
591 BLI_assert_msg(ok, "Expecting action assignment to work when converting Grease Pencil");
593 }
594 fcurves_move(this->animdata_dst->action,
595 this->animdata_dst->slot_handle,
596 this->animdata_src->action,
597 this->fcurves_from_src_main_action);
598 this->fcurves_from_src_main_action.clear();
599 }
600 if (!this->fcurves_from_src_tmp_action.is_empty()) {
601 if (!this->animdata_dst->tmpact) {
602 /* Create a new tmpact. */
604 this->conversion_data.bmain,
605 this->animdata_src->tmpact ? this->animdata_src->tmpact->id.name + 2 : nullptr);
606 if (USER_EXPERIMENTAL_TEST(&U, use_animation_baklava)) {
607 tmpact.slot_add_for_id(this->id_dst);
608 }
609 const bool ok = animrig::assign_tmpaction(&tmpact, {this->id_dst, *this->animdata_dst});
610 BLI_assert_msg(ok, "Expecting tmpact assignment to work when converting Grease Pencil");
612 }
613 fcurves_move(this->animdata_dst->tmpact,
614 this->animdata_dst->tmp_slot_handle,
615 this->animdata_src->tmpact,
616 this->fcurves_from_src_tmp_action);
617 this->fcurves_from_src_tmp_action.clear();
618 }
619 if (!this->fcurves_from_src_drivers.is_empty()) {
620 fcurves_move_between_listbases(this->animdata_dst->drivers,
621 this->animdata_src->drivers,
622 this->fcurves_from_src_drivers);
623 this->fcurves_from_src_drivers.clear();
624 }
625
628 DEG_relations_tag_update(&this->conversion_data.bmain);
629 }
630};
631
632/* \} */
633
640static void find_used_vertex_groups(const bGPDframe &gpf,
641 const ListBase &vertex_group_names,
642 const int num_vertex_groups,
643 ListBase &r_vertex_group_names,
644 Array<int> &r_indices)
645{
646 Array<int> is_group_used(num_vertex_groups, false);
647 LISTBASE_FOREACH (bGPDstroke *, gps, &gpf.strokes) {
648 if (!gps->dvert) {
649 continue;
650 }
651 Span<MDeformVert> dverts = {gps->dvert, gps->totpoints};
652 for (const MDeformVert &dvert : dverts) {
653 for (const MDeformWeight &weight : Span<MDeformWeight>{dvert.dw, dvert.totweight}) {
654 if (weight.def_nr >= num_vertex_groups) {
655 /* Ignore invalid deform weight group indices. */
656 continue;
657 }
658 is_group_used[weight.def_nr] = true;
659 }
660 }
661 }
662 BLI_listbase_clear(&r_vertex_group_names);
663 r_indices.reinitialize(num_vertex_groups);
664 int new_group_i = 0;
665 int old_group_i;
666 LISTBASE_FOREACH_INDEX (const bDeformGroup *, def_group, &vertex_group_names, old_group_i) {
667 if (!is_group_used[old_group_i]) {
668 r_indices[old_group_i] = -1;
669 continue;
670 }
671 r_indices[old_group_i] = new_group_i++;
672
673 bDeformGroup *def_group_copy = static_cast<bDeformGroup *>(MEM_dupallocN(def_group));
674 BLI_addtail(&r_vertex_group_names, def_group_copy);
675 }
676}
677
678/*
679 * This takes the legacy UV transforms and returns the stroke-space to texture-space matrix.
680 */
682 const float uv_rotation,
683 const float2 uv_scale)
684{
685 using namespace blender;
686
687 /* Bounding box data. */
688 const float2 minv = float2(-1.0f, -1.0f);
689 const float2 maxv = float2(1.0f, 1.0f);
690 /* Center of rotation. */
691 const float2 center = float2(0.5f, 0.5f);
692
693 const float2 uv_scale_inv = math::safe_rcp(uv_scale);
694 const float2 diagonal = maxv - minv;
695 const float sin_rotation = sin(uv_rotation);
696 const float cos_rotation = cos(uv_rotation);
697 const float2x2 rotation = float2x2(float2(cos_rotation, sin_rotation),
698 float2(-sin_rotation, cos_rotation));
699
700 float3x2 texture_matrix = float3x2::identity();
701
702 /* Apply bounding box re-scaling. */
703 texture_matrix[2] -= minv;
704 texture_matrix = math::from_scale<float2x2>(1.0f / diagonal) * texture_matrix;
705
706 /* Apply translation. */
707 texture_matrix[2] += uv_translation;
708
709 /* Apply rotation. */
710 texture_matrix[2] -= center;
711 texture_matrix = rotation * texture_matrix;
712 texture_matrix[2] += center;
713
714 /* Apply scale. */
715 texture_matrix = math::from_scale<float2x2>(uv_scale_inv) * texture_matrix;
716
717 return texture_matrix;
718}
719
720/*
721 * This gets the legacy layer-space to stroke-space matrix.
722 */
724{
725 using namespace blender;
726 using namespace blender::math;
727
728 const bGPDspoint *points = gps->points;
729 const int totpoints = gps->totpoints;
730
731 if (totpoints < 2) {
732 return float4x2::identity();
733 }
734
735 const bGPDspoint *point0 = &points[0];
736 const bGPDspoint *point1 = &points[1];
737 const bGPDspoint *point3 = &points[int(totpoints * 0.75f)];
738
739 const float3 pt0 = float3(point0->x, point0->y, point0->z);
740 const float3 pt1 = float3(point1->x, point1->y, point1->z);
741 const float3 pt3 = float3(point3->x, point3->y, point3->z);
742
743 /* Local X axis (p0 -> p1) */
744 const float3 local_x = normalize(pt1 - pt0);
745
746 /* Point vector at 3/4 */
747 const float3 local_3 = (totpoints == 2) ? (pt3 * 0.001f) - pt0 : pt3 - pt0;
748
749 /* Vector orthogonal to polygon plane. */
750 const float3 normal = cross(local_x, local_3);
751
752 /* Local Y axis (cross to normal/x axis). */
753 const float3 local_y = normalize(cross(normal, local_x));
754
755 /* Get local space using first point as origin. */
756 const float4x2 mat = transpose(
757 float2x4(float4(local_x, -dot(pt0, local_x)), float4(local_y, -dot(pt0, local_y))));
758
759 return mat;
760}
761
763{
764 const float3x2 texture_matrix = get_legacy_stroke_to_texture_matrix(
765 float2(gps->uv_translation), gps->uv_rotation, float2(gps->uv_scale));
766
767 const float4x2 strokemat = get_legacy_layer_to_stroke_matrix(gps);
768 float4x3 strokemat4x3 = float4x3(strokemat);
769 /*
770 * We need the diagonal of ones to start from the bottom right instead top left to properly apply
771 * the two matrices.
772 *
773 * i.e.
774 * # # # # # # # #
775 * We need # # # # Instead of # # # #
776 * 0 0 0 1 0 0 1 0
777 *
778 */
779 strokemat4x3[2][2] = 0.0f;
780 strokemat4x3[3][2] = 1.0f;
781
782 return texture_matrix * strokemat4x3;
783}
784
786 const ListBase &vertex_group_names)
787{
788 /* Create a new empty drawing. */
789 Drawing drawing;
790
791 /* Get the number of points, number of strokes and the offsets for each stroke. */
792 Vector<int> offsets;
793 Vector<int8_t> curve_types;
794 offsets.append(0);
795 int num_strokes = 0;
796 int num_points = 0;
797 bool has_bezier_stroke = false;
798 LISTBASE_FOREACH (bGPDstroke *, gps, &gpf.strokes) {
799 /* Check for a valid edit curve. This is only the case when the `editcurve` exists and wasn't
800 * tagged for a stroke update. This tag indicates that the stroke points have changed,
801 * invalidating the edit curve. */
802 if (gps->editcurve != nullptr && (gps->editcurve->flag & GP_CURVE_NEEDS_STROKE_UPDATE) == 0) {
803 if (gps->editcurve->tot_curve_points == 0) {
804 continue;
805 }
806 has_bezier_stroke = true;
807 num_points += gps->editcurve->tot_curve_points;
808 curve_types.append(CURVE_TYPE_BEZIER);
809 }
810 else {
811 if (gps->totpoints == 0) {
812 continue;
813 }
814 num_points += gps->totpoints;
815 curve_types.append(CURVE_TYPE_POLY);
816 }
817 num_strokes++;
818 offsets.append(num_points);
819 }
820
821 /* Return if the legacy frame contains no strokes (or zero points). */
822 if (num_strokes == 0) {
823 return drawing;
824 }
825
826 /* Resize the CurvesGeometry. */
828 curves.resize(num_points, num_strokes);
829 curves.offsets_for_write().copy_from(offsets);
830
831 OffsetIndices<int> points_by_curve = curves.points_by_curve();
832 MutableAttributeAccessor attributes = curves.attributes_for_write();
833
834 if (!has_bezier_stroke) {
835 /* All strokes are poly curves. */
836 curves.fill_curve_types(CURVE_TYPE_POLY);
837 }
838 else {
839 curves.curve_types_for_write().copy_from(curve_types);
840 curves.update_curve_types();
841 }
842
843 /* Find used vertex groups in this drawing. */
844 ListBase stroke_vertex_group_names;
845 Array<int> stroke_def_nr_map;
846 const int num_vertex_groups = BLI_listbase_count(&vertex_group_names);
848 gpf, vertex_group_names, num_vertex_groups, stroke_vertex_group_names, stroke_def_nr_map);
849 BLI_assert(BLI_listbase_is_empty(&curves.vertex_group_names));
850 curves.vertex_group_names = stroke_vertex_group_names;
851 const bool use_dverts = !BLI_listbase_is_empty(&curves.vertex_group_names);
852
853 /* Copy vertex weights and map the vertex group indices. */
854 auto copy_dvert = [&](const MDeformVert &src_dvert, MDeformVert &dst_dvert) {
855 dst_dvert = src_dvert;
856 dst_dvert.dw = static_cast<MDeformWeight *>(MEM_dupallocN(src_dvert.dw));
857 const MutableSpan<MDeformWeight> vertex_weights = {dst_dvert.dw, dst_dvert.totweight};
858 for (MDeformWeight &weight : vertex_weights) {
859 if (weight.def_nr >= num_vertex_groups) {
860 /* Ignore invalid deform weight group indices. */
861 continue;
862 }
863 /* Map def_nr to the reduced vertex group list. */
864 weight.def_nr = stroke_def_nr_map[weight.def_nr];
865 }
866 };
867
868 /* Point Attributes. */
869 MutableSpan<float3> positions = curves.positions_for_write();
870 MutableSpan<float3> handle_positions_left = has_bezier_stroke ?
871 curves.handle_positions_left_for_write() :
873 MutableSpan<float3> handle_positions_right = has_bezier_stroke ?
874 curves.handle_positions_right_for_write() :
876 MutableSpan<float> radii = drawing.radii_for_write();
877 MutableSpan<float> opacities = drawing.opacities_for_write();
878 SpanAttributeWriter<float> delta_times = attributes.lookup_or_add_for_write_span<float>(
879 "delta_time", AttrDomain::Point);
880 SpanAttributeWriter<float> rotations = attributes.lookup_or_add_for_write_span<float>(
881 "rotation", AttrDomain::Point);
884 ".selection", AttrDomain::Point);
885 MutableSpan<MDeformVert> dverts = use_dverts ? curves.wrap().deform_verts_for_write() :
887
888 /* Curve Attributes. */
889 SpanAttributeWriter<bool> stroke_cyclic = attributes.lookup_or_add_for_write_span<bool>(
890 "cyclic", AttrDomain::Curve);
891 SpanAttributeWriter<float> stroke_init_times = attributes.lookup_or_add_for_write_span<float>(
892 "init_time", AttrDomain::Curve);
894 "start_cap", AttrDomain::Curve);
896 "end_cap", AttrDomain::Curve);
897 SpanAttributeWriter<float> stroke_softness = attributes.lookup_or_add_for_write_span<float>(
898 "softness", AttrDomain::Curve);
899 SpanAttributeWriter<float> stroke_point_aspect_ratios =
900 attributes.lookup_or_add_for_write_span<float>("aspect_ratio", AttrDomain::Curve);
901 MutableSpan<ColorGeometry4f> stroke_fill_colors = drawing.fill_colors_for_write();
902 SpanAttributeWriter<int> stroke_materials = attributes.lookup_or_add_for_write_span<int>(
903 "material_index", AttrDomain::Curve);
904
905 Array<float4x2> legacy_texture_matrices(num_strokes);
906
907 int stroke_i = 0;
908 LISTBASE_FOREACH (bGPDstroke *, gps, &gpf.strokes) {
909 /* In GPv2 strokes with 0 points could technically be represented. In `CurvesGeometry` this is
910 * not the case and would be a bug. So we explicitly make sure to skip over strokes with no
911 * points. */
912 if (gps->totpoints == 0 ||
913 (gps->editcurve != nullptr && gps->editcurve->tot_curve_points == 0))
914 {
915 continue;
916 }
917
918 stroke_cyclic.span[stroke_i] = (gps->flag & GP_STROKE_CYCLIC) != 0;
919 /* Truncating time in ms to uint32 then we don't lose precision in lower bits. */
920 stroke_init_times.span[stroke_i] = float(uint32_t(gps->inittime * double(1e3))) / float(1e3);
921 stroke_start_caps.span[stroke_i] = int8_t(gps->caps[0]);
922 stroke_end_caps.span[stroke_i] = int8_t(gps->caps[1]);
923 stroke_softness.span[stroke_i] = 1.0f - gps->hardness;
924 stroke_point_aspect_ratios.span[stroke_i] = gps->aspect_ratio[0] /
925 max_ff(gps->aspect_ratio[1], 1e-8);
926 stroke_fill_colors[stroke_i] = ColorGeometry4f(gps->vert_color_fill);
927 stroke_materials.span[stroke_i] = gps->mat_nr;
928
929 const IndexRange points = points_by_curve[stroke_i];
930
931 const float stroke_thickness = float(gps->thickness) * LEGACY_RADIUS_CONVERSION_FACTOR;
932 MutableSpan<float3> dst_positions = positions.slice(points);
933 MutableSpan<float3> dst_handle_positions_left = has_bezier_stroke ?
934 handle_positions_left.slice(points) :
936 MutableSpan<float3> dst_handle_positions_right = has_bezier_stroke ?
937 handle_positions_right.slice(points) :
939 MutableSpan<float> dst_radii = radii.slice(points);
940 MutableSpan<float> dst_opacities = opacities.slice(points);
941 MutableSpan<float> dst_deltatimes = delta_times.span.slice(points);
942 MutableSpan<float> dst_rotations = rotations.span.slice(points);
943 MutableSpan<ColorGeometry4f> dst_vertex_colors = vertex_colors.slice(points);
944 MutableSpan<bool> dst_selection = selection.span.slice(points);
945 MutableSpan<MDeformVert> dst_dverts = use_dverts ? dverts.slice(points) :
947
948 if (curve_types[stroke_i] == CURVE_TYPE_POLY) {
949 BLI_assert(points.size() == gps->totpoints);
950 const Span<bGPDspoint> src_points{gps->points, gps->totpoints};
951 threading::parallel_for(src_points.index_range(), 4096, [&](const IndexRange range) {
952 for (const int point_i : range) {
953 const bGPDspoint &pt = src_points[point_i];
954 dst_positions[point_i] = float3(pt.x, pt.y, pt.z);
955 dst_radii[point_i] = stroke_thickness * pt.pressure;
956 dst_opacities[point_i] = pt.strength;
957 dst_deltatimes[point_i] = pt.time;
958 dst_rotations[point_i] = pt.uv_rot;
959 dst_vertex_colors[point_i] = ColorGeometry4f(pt.vert_color);
960 dst_selection[point_i] = (pt.flag & GP_SPOINT_SELECT) != 0;
961 if (use_dverts && gps->dvert) {
962 copy_dvert(gps->dvert[point_i], dst_dverts[point_i]);
963 }
964 }
965 });
966 }
967 else if (curve_types[stroke_i] == CURVE_TYPE_BEZIER) {
968 BLI_assert(gps->editcurve != nullptr);
969 BLI_assert(points.size() == gps->editcurve->tot_curve_points);
970 Span<bGPDcurve_point> src_curve_points{gps->editcurve->curve_points,
971 gps->editcurve->tot_curve_points};
972
973 threading::parallel_for(src_curve_points.index_range(), 4096, [&](const IndexRange range) {
974 for (const int point_i : range) {
975 const bGPDcurve_point &cpt = src_curve_points[point_i];
976 dst_positions[point_i] = float3(cpt.bezt.vec[1]);
977 dst_handle_positions_left[point_i] = float3(cpt.bezt.vec[0]);
978 dst_handle_positions_right[point_i] = float3(cpt.bezt.vec[2]);
979 dst_radii[point_i] = stroke_thickness * cpt.pressure;
980 dst_opacities[point_i] = cpt.strength;
981 dst_rotations[point_i] = cpt.uv_rot;
982 dst_vertex_colors[point_i] = ColorGeometry4f(cpt.vert_color);
983 dst_selection[point_i] = (cpt.flag & GP_CURVE_POINT_SELECT) != 0;
984 if (use_dverts && gps->dvert) {
985 copy_dvert(gps->dvert[point_i], dst_dverts[point_i]);
986 }
987 }
988 });
989 }
990 else {
991 /* Unknown curve type. */
993 }
994
995 const float4x2 legacy_texture_matrix = get_legacy_texture_matrix(gps);
996 legacy_texture_matrices[stroke_i] = legacy_texture_matrix;
997
998 stroke_i++;
999 }
1000
1001 /* Ensure that the normals are up to date. */
1002 curves.tag_normals_changed();
1003 drawing.set_texture_matrices(legacy_texture_matrices.as_span(), curves.curves_range());
1004
1005 delta_times.finish();
1006 rotations.finish();
1007 selection.finish();
1008
1009 stroke_cyclic.finish();
1010 stroke_init_times.finish();
1011 stroke_start_caps.finish();
1012 stroke_end_caps.finish();
1013 stroke_softness.finish();
1014 stroke_point_aspect_ratios.finish();
1015 stroke_materials.finish();
1016
1017 return drawing;
1018}
1019
1021 GreasePencil &grease_pencil,
1022 bGPdata &gpd)
1023{
1024 using namespace blender::bke::greasepencil;
1025
1026 if (gpd.flag & ID_FLAG_FAKEUSER) {
1027 id_fake_user_set(&grease_pencil.id);
1028 }
1029
1030 BLI_assert(!grease_pencil.id.properties);
1031 if (gpd.id.properties) {
1032 grease_pencil.id.properties = IDP_CopyProperty(gpd.id.properties);
1033 }
1034
1037 grease_pencil.flag, (gpd.flag & GP_DATA_EXPAND) != 0, GREASE_PENCIL_ANIM_CHANNEL_EXPANDED);
1038 SET_FLAG_FROM_TEST(grease_pencil.flag,
1039 (gpd.flag & GP_DATA_AUTOLOCK_LAYERS) != 0,
1043
1044 int layer_idx = 0;
1045 LISTBASE_FOREACH_INDEX (bGPDlayer *, gpl, &gpd.layers, layer_idx) {
1046 /* Create a new layer. */
1047 Layer &new_layer = grease_pencil.add_layer(
1048 StringRefNull(gpl->info, BLI_strnlen(gpl->info, 128)));
1049
1050 /* Flags. */
1051 new_layer.set_visible((gpl->flag & GP_LAYER_HIDE) == 0);
1052 new_layer.set_locked((gpl->flag & GP_LAYER_LOCKED) != 0);
1053 new_layer.set_selected((gpl->flag & GP_LAYER_SELECT) != 0);
1055 new_layer.base.flag, (gpl->flag & GP_LAYER_FRAMELOCK) != 0, GP_LAYER_TREE_NODE_MUTE);
1056 SET_FLAG_FROM_TEST(new_layer.base.flag,
1057 (gpl->flag & GP_LAYER_USE_LIGHTS) != 0,
1059 SET_FLAG_FROM_TEST(new_layer.base.flag,
1060 (gpl->onion_flag & GP_LAYER_ONIONSKIN) == 0,
1063 new_layer.base.flag, (gpl->flag & GP_LAYER_USE_MASK) == 0, GP_LAYER_TREE_NODE_HIDE_MASKS);
1064
1065 new_layer.blend_mode = int8_t(gpl->blend_mode);
1066
1067 new_layer.parent = gpl->parent;
1068 new_layer.set_parent_bone_name(gpl->parsubstr);
1069 /* GPv2 parent inverse matrix is only valid when parent is set. */
1070 if (gpl->parent) {
1071 copy_m4_m4(new_layer.parentinv, gpl->inverse);
1072 }
1073
1074 copy_v3_v3(new_layer.translation, gpl->location);
1075 copy_v3_v3(new_layer.rotation, gpl->rotation);
1076 copy_v3_v3(new_layer.scale, gpl->scale);
1077
1078 new_layer.set_view_layer_name(gpl->viewlayername);
1079 SET_FLAG_FROM_TEST(new_layer.base.flag,
1080 (gpl->flag & GP_LAYER_DISABLE_MASKS_IN_VIEWLAYER) != 0,
1082
1083 /* Convert the layer masks. */
1084 LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl->mask_layers) {
1085 LayerMask *new_mask = MEM_new<LayerMask>(__func__, mask->name);
1086 new_mask->flag = mask->flag;
1087 BLI_addtail(&new_layer.masks, new_mask);
1088 }
1089 new_layer.opacity = gpl->opacity;
1090
1091 LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1092 Drawing *dst_drawing = grease_pencil.insert_frame(
1093 new_layer, gpf->framenum, 0, eBezTriple_KeyframeType(gpf->key_type));
1094 if (dst_drawing == nullptr) {
1095 /* Might fail because GPv2 technically allowed overlapping keyframes on the same frame
1096 * (very unlikely to occur in real world files). In GPv3, keyframes always have to be on
1097 * different frames. In this case we can't create a keyframe and have to skip it. */
1098 continue;
1099 }
1100 /* Convert the frame to a drawing. */
1102
1103 /* This frame was just inserted above, so it should always exist. */
1104 GreasePencilFrame &new_frame = *new_layer.frame_at(gpf->framenum);
1105 SET_FLAG_FROM_TEST(new_frame.flag, (gpf->flag & GP_FRAME_SELECT), GP_FRAME_SELECTED);
1106 }
1107
1108 if ((gpl->flag & GP_LAYER_ACTIVE) != 0) {
1109 grease_pencil.set_active_layer(&new_layer);
1110 }
1111 }
1112
1113 /* Second loop, to write to layer attributes after all layers were created. */
1114 MutableAttributeAccessor layer_attributes = grease_pencil.attributes_for_write();
1115 /* NOTE: Layer Adjustments like the tint and the radius offsets are deliberately ignored here!
1116 * These are converted to modifiers at the bottom of the stack to keep visual compatibility with
1117 * GPv2. */
1118 SpanAttributeWriter<int> layer_passes = layer_attributes.lookup_or_add_for_write_span<int>(
1119 "pass_index", bke::AttrDomain::Layer);
1120
1121 layer_idx = 0;
1122 LISTBASE_FOREACH_INDEX (bGPDlayer *, gpl, &gpd.layers, layer_idx) {
1123 layer_passes.span[layer_idx] = int(gpl->pass_index);
1124 }
1125
1126 layer_passes.finish();
1127
1128 /* Copy vertex group names and settings. */
1131
1132 /* Convert the onion skinning settings. */
1134 settings.opacity = gpd.onion_factor;
1135 settings.mode = gpd.onion_mode;
1136 SET_FLAG_FROM_TEST(settings.flag,
1137 ((gpd.onion_flag & GP_ONION_GHOST_PREVCOL) != 0 &&
1138 (gpd.onion_flag & GP_ONION_GHOST_NEXTCOL) != 0),
1144 /* Convert keytype filter to a bit flag. */
1145 if (gpd.onion_keytype == -1) {
1147 }
1148 else {
1149 settings.filter = (1 << gpd.onion_keytype);
1150 }
1151 settings.num_frames_before = gpd.gstep;
1152 settings.num_frames_after = gpd.gstep_next;
1153 copy_v3_v3(settings.color_before, gpd.gcolor_prev);
1154 copy_v3_v3(settings.color_after, gpd.gcolor_next);
1155
1156 BKE_id_materials_copy(&conversion_data.bmain, &gpd.id, &grease_pencil.id);
1157
1158 /* Copy animation data from legacy GP data.
1159 *
1160 * Note that currently, Actions IDs are not duplicated. They may be needed ultimately, but for
1161 * the time being, assuming invalid fcurves/drivers are fine here. */
1162 if (AnimData *gpd_animdata = BKE_animdata_from_id(&gpd.id)) {
1163 grease_pencil.adt = BKE_animdata_copy_in_lib(
1164 &conversion_data.bmain, gpd.id.lib, gpd_animdata, LIB_ID_COPY_DEFAULT);
1165
1166 /* Some property was renamed between legacy GP layers and new GreasePencil ones. */
1167 AnimDataConvertor animdata_gpdata_transfer(
1168 conversion_data, grease_pencil.id, gpd.id, {{".location", ".translation"}});
1169 for (const Layer *layer_iter : grease_pencil.layers()) {
1170 /* Data comes from versioned GPv2 layers, which have a fixed max length. */
1171 char layer_name_esc[sizeof((bGPDlayer{}).info) * 2];
1172 BLI_str_escape(layer_name_esc, layer_iter->name().c_str(), sizeof(layer_name_esc));
1173 std::string layer_root_path = fmt::format("layers[\"{}\"]", layer_name_esc);
1174 animdata_gpdata_transfer.root_path_dst = layer_root_path;
1175 animdata_gpdata_transfer.root_path_src = layer_root_path;
1176 animdata_gpdata_transfer.fcurves_convert();
1177 }
1178 animdata_gpdata_transfer.fcurves_convert_finalize();
1179 }
1180}
1181
1182constexpr const char *OFFSET_RADIUS_NODETREE_NAME = "Offset Radius GPv3 Conversion";
1184{
1185 using namespace blender;
1186 /* NOTE: DO NOT translate this ID name, it is used to find a potentially already existing
1187 * node-tree. */
1189 &conversion_data.bmain, library, OFFSET_RADIUS_NODETREE_NAME, "GeometryNodeTree");
1190
1191 if (!group->geometry_node_asset_traits) {
1192 group->geometry_node_asset_traits = MEM_cnew<GeometryNodeAssetTraits>(__func__);
1193 }
1195
1196 group->tree_interface.add_socket(
1197 DATA_("Geometry"), "", "NodeSocketGeometry", NODE_INTERFACE_SOCKET_INPUT, nullptr);
1198 group->tree_interface.add_socket(
1199 DATA_("Geometry"), "", "NodeSocketGeometry", NODE_INTERFACE_SOCKET_OUTPUT, nullptr);
1200
1201 bNodeTreeInterfaceSocket *radius_offset = group->tree_interface.add_socket(
1202 DATA_("Offset"), "", "NodeSocketFloat", NODE_INTERFACE_SOCKET_INPUT, nullptr);
1203 auto &radius_offset_data = *static_cast<bNodeSocketValueFloat *>(radius_offset->socket_data);
1204 radius_offset_data.subtype = PROP_DISTANCE;
1205 radius_offset_data.min = -FLT_MAX;
1206 radius_offset_data.max = FLT_MAX;
1207
1208 group->tree_interface.add_socket(
1209 DATA_("Layer"), "", "NodeSocketString", NODE_INTERFACE_SOCKET_INPUT, nullptr);
1210
1211 bNode *group_output = bke::node_add_node(nullptr, group, "NodeGroupOutput");
1212 group_output->locx = 800;
1213 group_output->locy = 160;
1214 bNode *group_input = bke::node_add_node(nullptr, group, "NodeGroupInput");
1215 group_input->locx = 0;
1216 group_input->locy = 160;
1217
1218 bNode *set_curve_radius = bke::node_add_node(nullptr, group, "GeometryNodeSetCurveRadius");
1219 set_curve_radius->locx = 600;
1220 set_curve_radius->locy = 160;
1221 bNode *named_layer_selection = bke::node_add_node(
1222 nullptr, group, "GeometryNodeInputNamedLayerSelection");
1223 named_layer_selection->locx = 200;
1224 named_layer_selection->locy = 100;
1225 bNode *input_radius = bke::node_add_node(nullptr, group, "GeometryNodeInputRadius");
1226 input_radius->locx = 0;
1227 input_radius->locy = 0;
1228
1229 bNode *add = bke::node_add_node(nullptr, group, "ShaderNodeMath");
1230 add->custom1 = NODE_MATH_ADD;
1231 add->locx = 200;
1232 add->locy = 0;
1233
1234 bNode *clamp_radius = bke::node_add_node(nullptr, group, "ShaderNodeClamp");
1235 clamp_radius->locx = 400;
1236 clamp_radius->locy = 0;
1237 bNodeSocket *sock_max = bke::node_find_socket(clamp_radius, SOCK_IN, "Max");
1238 static_cast<bNodeSocketValueFloat *>(sock_max->default_value)->value = FLT_MAX;
1239
1240 bke::node_add_link(group,
1241 group_input,
1242 bke::node_find_socket(group_input, SOCK_OUT, "Socket_0"),
1243 set_curve_radius,
1244 bke::node_find_socket(set_curve_radius, SOCK_IN, "Curve"));
1245 bke::node_add_link(group,
1246 set_curve_radius,
1247 bke::node_find_socket(set_curve_radius, SOCK_OUT, "Curve"),
1248 group_output,
1249 bke::node_find_socket(group_output, SOCK_IN, "Socket_1"));
1250
1251 bke::node_add_link(group,
1252 group_input,
1253 bke::node_find_socket(group_input, SOCK_OUT, "Socket_3"),
1254 named_layer_selection,
1255 bke::node_find_socket(named_layer_selection, SOCK_IN, "Name"));
1256 bke::node_add_link(group,
1257 named_layer_selection,
1258 bke::node_find_socket(named_layer_selection, SOCK_OUT, "Selection"),
1259 set_curve_radius,
1260 bke::node_find_socket(set_curve_radius, SOCK_IN, "Selection"));
1261
1262 bke::node_add_link(group,
1263 group_input,
1264 bke::node_find_socket(group_input, SOCK_OUT, "Socket_2"),
1265 add,
1266 bke::node_find_socket(add, SOCK_IN, "Value"));
1267 bke::node_add_link(group,
1268 input_radius,
1269 bke::node_find_socket(input_radius, SOCK_OUT, "Radius"),
1270 add,
1271 bke::node_find_socket(add, SOCK_IN, "Value_001"));
1272 bke::node_add_link(group,
1273 add,
1275 clamp_radius,
1276 bke::node_find_socket(clamp_radius, SOCK_IN, "Value"));
1277 bke::node_add_link(group,
1278 clamp_radius,
1279 bke::node_find_socket(clamp_radius, SOCK_OUT, "Result"),
1280 set_curve_radius,
1281 bke::node_find_socket(set_curve_radius, SOCK_IN, "Radius"));
1282
1283 LISTBASE_FOREACH (bNode *, node, &group->nodes) {
1284 bke::node_set_selected(node, false);
1285 }
1286
1287 return group;
1288}
1289
1291 bGPdata &src_object_data,
1292 Object &dst_object)
1293{
1294 AnimDataConvertor animdata_thickness_transfer(
1295 conversion_data, dst_object.id, src_object_data.id, {{"pixel_factor", ".thickness_factor"}});
1296 animdata_thickness_transfer.root_path_src = "";
1297
1298 const float thickness_factor = src_object_data.pixfactor;
1299 const bool has_thickness_factor_animation =
1300 animdata_thickness_transfer.source_has_animation_to_convert();
1301 const bool has_thickness_factor = thickness_factor != 1.0f || has_thickness_factor_animation;
1302
1303 if (!has_thickness_factor) {
1304 return;
1305 }
1306
1308 GreasePencilThickModifierData *tmd = reinterpret_cast<GreasePencilThickModifierData *>(md);
1309
1310 tmd->thickness_fac = thickness_factor;
1311
1312 STRNCPY(md->name, DATA_("Thickness"));
1313 BKE_modifier_unique_name(&dst_object.modifiers, md);
1314
1315 BLI_addtail(&dst_object.modifiers, md);
1316 BKE_modifiers_persistent_uid_init(dst_object, *md);
1317
1318 if (has_thickness_factor_animation) {
1319 char modifier_name_esc[MAX_NAME * 2];
1320 BLI_str_escape(modifier_name_esc, md->name, sizeof(modifier_name_esc));
1321 animdata_thickness_transfer.root_path_dst = fmt::format("modifiers[\"{}\"]",
1322 modifier_name_esc);
1323
1324 animdata_thickness_transfer.fcurves_convert();
1325 }
1326
1327 animdata_thickness_transfer.fcurves_convert_finalize();
1328}
1329
1331{
1332 if (fcurve.bezt) {
1333 for (uint i = 0; i < fcurve.totvert; i++) {
1334 BezTriple &bezier_triple = fcurve.bezt[i];
1335 bezier_triple.vec[0][1] *= LEGACY_RADIUS_CONVERSION_FACTOR;
1336 bezier_triple.vec[1][1] *= LEGACY_RADIUS_CONVERSION_FACTOR;
1337 bezier_triple.vec[2][1] *= LEGACY_RADIUS_CONVERSION_FACTOR;
1338 }
1339 }
1340 if (fcurve.fpt) {
1341 for (uint i = 0; i < fcurve.totvert; i++) {
1342 FPoint &fpoint = fcurve.fpt[i];
1344 }
1345 }
1346 fcurve.flag &= ~FCURVE_INT_VALUES;
1348}
1349
1351 Object &object)
1352{
1353 if (BKE_animdata_from_id(&object.id) == nullptr) {
1354 return;
1355 }
1356
1357 /* NOTE: At this point, the animation was already transferred to the destination object. Now we
1358 * just need to convert the fcurve data to be in the right space. */
1359 AnimDataConvertor animdata_convert_thickness(
1360 conversion_data,
1361 object.id,
1362 object.id,
1363 {{".thickness", ".thickness", fcurve_convert_thickness_cb}});
1364
1365 LISTBASE_FOREACH (ModifierData *, tmd, &object.modifiers) {
1367 continue;
1368 }
1369
1370 char modifier_name[MAX_NAME * 2];
1371 BLI_str_escape(modifier_name, tmd->name, sizeof(modifier_name));
1372 animdata_convert_thickness.root_path_src = fmt::format("modifiers[\"{}\"]", modifier_name);
1373 animdata_convert_thickness.root_path_dst = fmt::format("modifiers[\"{}\"]", modifier_name);
1374
1375 if (!animdata_convert_thickness.source_has_animation_to_convert()) {
1376 continue;
1377 }
1378 animdata_convert_thickness.fcurves_convert();
1379 }
1380
1381 animdata_convert_thickness.fcurves_convert_finalize();
1382 DEG_relations_tag_update(&conversion_data.bmain);
1383}
1384
1386 bGPdata &src_object_data,
1387 Object &dst_object)
1388{
1389 /* Handling of animation here is a bit complex, since paths needs to be updated, but also
1390 * FCurves need to be transferred from legacy GPData animation to Object animation. */
1391 AnimDataConvertor animdata_tint_transfer(
1392 conversion_data,
1393 dst_object.id,
1394 src_object_data.id,
1395 {{".tint_color", ".color"}, {".tint_factor", ".factor"}});
1396
1397 AnimDataConvertor animdata_thickness_transfer(
1398 conversion_data,
1399 dst_object.id,
1400 src_object_data.id,
1401 {{".line_change", "[\"Socket_2\"]", fcurve_convert_thickness_cb}});
1402
1403 /* Replace layer adjustments with modifiers. */
1404 LISTBASE_FOREACH (bGPDlayer *, gpl, &src_object_data.layers) {
1405 const float3 tint_color = float3(gpl->tintcolor);
1406 const float tint_factor = gpl->tintcolor[3];
1407 const int thickness_px = gpl->line_change;
1408
1409 char layer_name_esc[sizeof(gpl->info) * 2];
1410 BLI_str_escape(layer_name_esc, gpl->info, sizeof(layer_name_esc));
1411 animdata_tint_transfer.root_path_src = fmt::format("layers[\"{}\"]", layer_name_esc);
1412 animdata_thickness_transfer.root_path_src = fmt::format("layers[\"{}\"]", layer_name_esc);
1413
1414 const bool has_tint_adjustment_animation =
1415 animdata_tint_transfer.source_has_animation_to_convert();
1416 const bool has_thickness_adjustment_animation =
1417 animdata_thickness_transfer.source_has_animation_to_convert();
1418
1419 /* If tint or thickness are animated, relevant modifiers also need to be created. */
1420 const bool has_tint_adjustment = tint_factor > 0.0f || has_tint_adjustment_animation;
1421 const bool has_thickness_adjustment = thickness_px != 0 || has_thickness_adjustment_animation;
1422
1423 /* Tint adjustment. */
1424 if (has_tint_adjustment) {
1426 GreasePencilTintModifierData *tmd = reinterpret_cast<GreasePencilTintModifierData *>(md);
1427
1428 copy_v3_v3(tmd->color, tint_color);
1429 tmd->factor = tint_factor;
1430 STRNCPY(tmd->influence.layer_name, gpl->info);
1431
1432 char modifier_name[MAX_NAME];
1433 SNPRINTF(modifier_name, "Tint %s", gpl->info);
1435 BKE_modifier_unique_name(&dst_object.modifiers, md);
1436
1437 BLI_addtail(&dst_object.modifiers, md);
1438 BKE_modifiers_persistent_uid_init(dst_object, *md);
1439
1440 if (has_tint_adjustment_animation) {
1441 char modifier_name_esc[MAX_NAME * 2];
1442 BLI_str_escape(modifier_name_esc, md->name, sizeof(modifier_name_esc));
1443 animdata_tint_transfer.root_path_dst = fmt::format("modifiers[\"{}\"]", modifier_name_esc);
1444
1445 animdata_tint_transfer.fcurves_convert();
1446 }
1447 }
1448 /* Thickness adjustment. */
1449 if (has_thickness_adjustment) {
1450 /* Convert the "pixel" offset value into a radius value.
1451 * GPv2 used a conversion of 1 "px" = 0.001. */
1452 /* NOTE: this offset may be negative. */
1453 const float uniform_object_scale = math::average(float3(dst_object.scale));
1454 const float radius_offset = math::safe_divide(
1455 float(thickness_px) * LEGACY_RADIUS_CONVERSION_FACTOR, uniform_object_scale);
1456
1457 const auto offset_radius_ntree_ensure = [&](Library *owner_library) {
1458 if (bNodeTree **ntree = conversion_data.offset_radius_ntree_by_library.lookup_ptr(
1459 owner_library))
1460 {
1461 /* Node tree has already been found/created for this versioning call. */
1462 return *ntree;
1463 }
1464 /* Try to find an existing group added by previous versioning to avoid adding duplicates.
1465 */
1466 LISTBASE_FOREACH (bNodeTree *, ntree_iter, &conversion_data.bmain.nodetrees) {
1467 if (ntree_iter->id.lib != owner_library) {
1468 continue;
1469 }
1470 if (STREQ(ntree_iter->id.name + 2, OFFSET_RADIUS_NODETREE_NAME)) {
1471 conversion_data.offset_radius_ntree_by_library.add_new(owner_library, ntree_iter);
1472 return ntree_iter;
1473 }
1474 }
1475 bNodeTree *new_ntree = offset_radius_node_tree_add(conversion_data, owner_library);
1476 /* Remove the default user. The count is tracked manually when assigning to modifiers. */
1477 id_us_min(&new_ntree->id);
1478 conversion_data.offset_radius_ntree_by_library.add_new(owner_library, new_ntree);
1479 BKE_ntree_update_main_tree(&conversion_data.bmain, new_ntree, nullptr);
1480 return new_ntree;
1481 };
1482 bNodeTree *offset_radius_node_tree = offset_radius_ntree_ensure(dst_object.id.lib);
1483
1484 auto *md = reinterpret_cast<NodesModifierData *>(BKE_modifier_new(eModifierType_Nodes));
1485
1486 char modifier_name[MAX_NAME];
1487 SNPRINTF(modifier_name, "Thickness %s", gpl->info);
1488 STRNCPY(md->modifier.name, modifier_name);
1489 BKE_modifier_unique_name(&dst_object.modifiers, &md->modifier);
1490 md->node_group = offset_radius_node_tree;
1491
1492 BLI_addtail(&dst_object.modifiers, md);
1493 BKE_modifiers_persistent_uid_init(dst_object, md->modifier);
1494
1495 md->settings.properties = bke::idprop::create_group("Nodes Modifier Settings").release();
1496 IDProperty *radius_offset_prop =
1497 bke::idprop::create(DATA_("Socket_2"), radius_offset).release();
1498 auto *ui_data = reinterpret_cast<IDPropertyUIDataFloat *>(
1499 IDP_ui_data_ensure(radius_offset_prop));
1500 ui_data->soft_min = 0.0;
1501 ui_data->base.rna_subtype = PROP_TRANSLATION;
1502 IDP_AddToGroup(md->settings.properties, radius_offset_prop);
1503 IDP_AddToGroup(md->settings.properties,
1504 bke::idprop::create(DATA_("Socket_3"), gpl->info).release());
1505
1506 if (has_thickness_adjustment_animation) {
1507 char modifier_name_esc[MAX_NAME * 2];
1508 BLI_str_escape(modifier_name_esc, md->modifier.name, sizeof(modifier_name_esc));
1509 animdata_thickness_transfer.root_path_dst = fmt::format("modifiers[\"{}\"]",
1510 modifier_name_esc);
1511
1512 animdata_thickness_transfer.fcurves_convert();
1513 }
1514 }
1515 }
1516
1517 animdata_tint_transfer.fcurves_convert_finalize();
1518 animdata_thickness_transfer.fcurves_convert_finalize();
1519
1520 DEG_relations_tag_update(&conversion_data.bmain);
1521}
1522
1524 Object &object,
1525 const ModifierType type,
1526 GpencilModifierData &legacy_md)
1527{
1528 /* TODO: Copy of most of #ed::object::modifier_add, this should be a BKE_modifiers function
1529 * actually. */
1530 const ModifierTypeInfo *mti = BKE_modifier_get_info(type);
1531
1532 ModifierData &new_md = *BKE_modifier_new(type);
1533
1535 ModifierData *md;
1536 for (md = static_cast<ModifierData *>(object.modifiers.first);
1538 md = md->next)
1539 ;
1540 BLI_insertlinkbefore(&object.modifiers, md, &new_md);
1541 }
1542 else {
1543 BLI_addtail(&object.modifiers, &new_md);
1544 }
1545
1546 /* Generate new persistent UID and best possible unique name. */
1547 BKE_modifiers_persistent_uid_init(object, new_md);
1548 if (legacy_md.name[0]) {
1549 STRNCPY_UTF8(new_md.name, legacy_md.name);
1550 }
1551 BKE_modifier_unique_name(&object.modifiers, &new_md);
1552
1553 /* Handle common modifier data. */
1554 new_md.mode = legacy_md.mode;
1556
1557 /* Attempt to copy UI state (panels) as best as possible. */
1558 new_md.ui_expand_flag = legacy_md.ui_expand_flag;
1559
1560 /* Convert animation data if needed. */
1561 if (BKE_animdata_from_id(&object.id)) {
1562 AnimDataConvertor anim_convertor(conversion_data, object.id);
1563
1564 char legacy_name_esc[MAX_NAME * 2];
1565 BLI_str_escape(legacy_name_esc, legacy_md.name, sizeof(legacy_name_esc));
1566 anim_convertor.root_path_src = fmt::format("grease_pencil_modifiers[\"{}\"]", legacy_name_esc);
1567
1568 char new_name_esc[MAX_NAME * 2];
1569 BLI_str_escape(new_name_esc, new_md.name, sizeof(new_name_esc));
1570 anim_convertor.root_path_dst = fmt::format("modifiers[\"{}\"]", new_name_esc);
1571
1572 anim_convertor.fcurves_convert();
1573 anim_convertor.fcurves_convert_finalize();
1574 }
1575
1576 return new_md;
1577}
1578
1580 StringRef layername,
1581 const int layer_pass,
1582 const bool invert_layer,
1583 const bool invert_layer_pass,
1584 Material **material,
1585 const int material_pass,
1586 const bool invert_material,
1587 const bool invert_material_pass,
1588 StringRef vertex_group_name,
1589 const bool invert_vertex_group,
1590 CurveMapping **custom_curve,
1591 const bool use_custom_curve)
1592{
1593 influence.flag = 0;
1594
1595 STRNCPY(influence.layer_name, layername.data());
1596 if (invert_layer) {
1598 }
1599 influence.layer_pass = layer_pass;
1600 if (layer_pass > 0) {
1602 }
1603 if (invert_layer_pass) {
1605 }
1606
1607 if (material) {
1608 influence.material = *material;
1609 *material = nullptr;
1610 }
1611 if (invert_material) {
1613 }
1614 influence.material_pass = material_pass;
1615 if (material_pass > 0) {
1617 }
1618 if (invert_material_pass) {
1620 }
1621
1622 STRNCPY(influence.vertex_group_name, vertex_group_name.data());
1623 if (invert_vertex_group) {
1625 }
1626
1627 if (custom_curve) {
1628 if (influence.custom_curve) {
1630 }
1631 influence.custom_curve = *custom_curve;
1632 *custom_curve = nullptr;
1633 }
1634 if (use_custom_curve) {
1636 }
1637}
1638
1640 Object &object,
1641 GpencilModifierData &legacy_md)
1642{
1644 conversion_data, object, eModifierType_GreasePencilArmature, legacy_md);
1645 auto &md_armature = reinterpret_cast<GreasePencilArmatureModifierData &>(md);
1646 auto &legacy_md_armature = reinterpret_cast<ArmatureGpencilModifierData &>(legacy_md);
1647
1648 md_armature.object = legacy_md_armature.object;
1649 legacy_md_armature.object = nullptr;
1650 md_armature.deformflag = legacy_md_armature.deformflag;
1651
1652 legacy_object_modifier_influence(md_armature.influence,
1653 "",
1654 0,
1655 false,
1656 false,
1657 nullptr,
1658 0,
1659 false,
1660 false,
1661 legacy_md_armature.vgname,
1662 legacy_md_armature.deformflag & ARM_DEF_INVERT_VGROUP,
1663 nullptr,
1664 false);
1665}
1666
1668 Object &object,
1669 GpencilModifierData &legacy_md)
1670{
1672 conversion_data, object, eModifierType_GreasePencilArray, legacy_md);
1673 auto &md_array = reinterpret_cast<GreasePencilArrayModifierData &>(md);
1674 auto &legacy_md_array = reinterpret_cast<ArrayGpencilModifierData &>(legacy_md);
1675
1676 md_array.object = legacy_md_array.object;
1677 legacy_md_array.object = nullptr;
1678 md_array.count = legacy_md_array.count;
1679 md_array.flag = 0;
1680 if (legacy_md_array.flag & GP_ARRAY_UNIFORM_RANDOM_SCALE) {
1682 }
1683 if (legacy_md_array.flag & GP_ARRAY_USE_OB_OFFSET) {
1685 }
1686 if (legacy_md_array.flag & GP_ARRAY_USE_OFFSET) {
1687 md_array.flag |= MOD_GREASE_PENCIL_ARRAY_USE_OFFSET;
1688 }
1689 if (legacy_md_array.flag & GP_ARRAY_USE_RELATIVE) {
1690 md_array.flag |= MOD_GREASE_PENCIL_ARRAY_USE_RELATIVE;
1691 }
1692 copy_v3_v3(md_array.offset, legacy_md_array.offset);
1693 copy_v3_v3(md_array.shift, legacy_md_array.shift);
1694 copy_v3_v3(md_array.rnd_offset, legacy_md_array.rnd_offset);
1695 copy_v3_v3(md_array.rnd_rot, legacy_md_array.rnd_rot);
1696 copy_v3_v3(md_array.rnd_scale, legacy_md_array.rnd_scale);
1697 md_array.seed = legacy_md_array.seed;
1698 md_array.mat_rpl = legacy_md_array.mat_rpl;
1699
1700 legacy_object_modifier_influence(md_array.influence,
1701 legacy_md_array.layername,
1702 legacy_md_array.layer_pass,
1703 legacy_md_array.flag & GP_ARRAY_INVERT_LAYER,
1704 legacy_md_array.flag & GP_ARRAY_INVERT_LAYERPASS,
1705 &legacy_md_array.material,
1706 legacy_md_array.pass_index,
1707 legacy_md_array.flag & GP_ARRAY_INVERT_MATERIAL,
1708 legacy_md_array.flag & GP_ARRAY_INVERT_PASS,
1709 "",
1710 false,
1711 nullptr,
1712 false);
1713}
1714
1716 Object &object,
1717 GpencilModifierData &legacy_md)
1718{
1720 conversion_data, object, eModifierType_GreasePencilColor, legacy_md);
1721 auto &md_color = reinterpret_cast<GreasePencilColorModifierData &>(md);
1722 auto &legacy_md_color = reinterpret_cast<ColorGpencilModifierData &>(legacy_md);
1723
1724 switch (eModifyColorGpencil_Flag(legacy_md_color.modify_color)) {
1726 md_color.color_mode = MOD_GREASE_PENCIL_COLOR_BOTH;
1727 break;
1729 md_color.color_mode = MOD_GREASE_PENCIL_COLOR_STROKE;
1730 break;
1732 md_color.color_mode = MOD_GREASE_PENCIL_COLOR_FILL;
1733 break;
1735 md_color.color_mode = MOD_GREASE_PENCIL_COLOR_HARDNESS;
1736 break;
1737 }
1738 copy_v3_v3(md_color.hsv, legacy_md_color.hsv);
1739
1740 legacy_object_modifier_influence(md_color.influence,
1741 legacy_md_color.layername,
1742 legacy_md_color.layer_pass,
1743 legacy_md_color.flag & GP_COLOR_INVERT_LAYER,
1744 legacy_md_color.flag & GP_COLOR_INVERT_LAYERPASS,
1745 &legacy_md_color.material,
1746 legacy_md_color.pass_index,
1747 legacy_md_color.flag & GP_COLOR_INVERT_MATERIAL,
1748 legacy_md_color.flag & GP_COLOR_INVERT_PASS,
1749 "",
1750 false,
1751 &legacy_md_color.curve_intensity,
1752 legacy_md_color.flag & GP_COLOR_CUSTOM_CURVE);
1753}
1754
1755static void legacy_object_modifier_dash(ConversionData &conversion_data,
1756 Object &object,
1757 GpencilModifierData &legacy_md)
1758{
1760 conversion_data, object, eModifierType_GreasePencilDash, legacy_md);
1761 auto &md_dash = reinterpret_cast<GreasePencilDashModifierData &>(md);
1762 auto &legacy_md_dash = reinterpret_cast<DashGpencilModifierData &>(legacy_md);
1763
1764 md_dash.dash_offset = legacy_md_dash.dash_offset;
1765 md_dash.segment_active_index = legacy_md_dash.segment_active_index;
1766 md_dash.segments_num = legacy_md_dash.segments_len;
1767 MEM_SAFE_FREE(md_dash.segments_array);
1768 md_dash.segments_array = MEM_cnew_array<GreasePencilDashModifierSegment>(
1769 legacy_md_dash.segments_len, __func__);
1770 for (const int i : IndexRange(md_dash.segments_num)) {
1771 GreasePencilDashModifierSegment &dst_segment = md_dash.segments_array[i];
1772 const DashGpencilModifierSegment &src_segment = legacy_md_dash.segments[i];
1773 STRNCPY(dst_segment.name, src_segment.name);
1774 dst_segment.flag = 0;
1775 if (src_segment.flag & GP_DASH_USE_CYCLIC) {
1777 }
1778 dst_segment.dash = src_segment.dash;
1779 dst_segment.gap = src_segment.gap;
1780 dst_segment.opacity = src_segment.opacity;
1781 dst_segment.radius = src_segment.radius;
1782 dst_segment.mat_nr = src_segment.mat_nr;
1783 }
1784
1785 legacy_object_modifier_influence(md_dash.influence,
1786 legacy_md_dash.layername,
1787 legacy_md_dash.layer_pass,
1788 legacy_md_dash.flag & GP_DASH_INVERT_LAYER,
1789 legacy_md_dash.flag & GP_DASH_INVERT_LAYERPASS,
1790 &legacy_md_dash.material,
1791 legacy_md_dash.pass_index,
1792 legacy_md_dash.flag & GP_DASH_INVERT_MATERIAL,
1793 legacy_md_dash.flag & GP_DASH_INVERT_PASS,
1794 "",
1795 false,
1796 nullptr,
1797 false);
1798}
1799
1801 Object &object,
1802 GpencilModifierData &legacy_md)
1803{
1805 conversion_data, object, eModifierType_GreasePencilEnvelope, legacy_md);
1806 auto &md_envelope = reinterpret_cast<GreasePencilEnvelopeModifierData &>(md);
1807 auto &legacy_md_envelope = reinterpret_cast<EnvelopeGpencilModifierData &>(legacy_md);
1808
1809 switch (eEnvelopeGpencil_Mode(legacy_md_envelope.mode)) {
1810 case GP_ENVELOPE_DEFORM:
1811 md_envelope.mode = MOD_GREASE_PENCIL_ENVELOPE_DEFORM;
1812 break;
1814 md_envelope.mode = MOD_GREASE_PENCIL_ENVELOPE_SEGMENTS;
1815 break;
1816 case GP_ENVELOPE_FILLS:
1817 md_envelope.mode = MOD_GREASE_PENCIL_ENVELOPE_FILLS;
1818 break;
1819 }
1820 md_envelope.mat_nr = legacy_md_envelope.mat_nr;
1821 md_envelope.thickness = legacy_md_envelope.thickness;
1822 md_envelope.strength = legacy_md_envelope.strength;
1823 md_envelope.skip = legacy_md_envelope.skip;
1824 md_envelope.spread = legacy_md_envelope.spread;
1825
1826 legacy_object_modifier_influence(md_envelope.influence,
1827 legacy_md_envelope.layername,
1828 legacy_md_envelope.layer_pass,
1829 legacy_md_envelope.flag & GP_ENVELOPE_INVERT_LAYER,
1830 legacy_md_envelope.flag & GP_ENVELOPE_INVERT_LAYERPASS,
1831 &legacy_md_envelope.material,
1832 legacy_md_envelope.pass_index,
1833 legacy_md_envelope.flag & GP_ENVELOPE_INVERT_MATERIAL,
1834 legacy_md_envelope.flag & GP_ENVELOPE_INVERT_PASS,
1835 legacy_md_envelope.vgname,
1836 legacy_md_envelope.flag & GP_ENVELOPE_INVERT_VGROUP,
1837 nullptr,
1838 false);
1839}
1840
1841static void legacy_object_modifier_hook(ConversionData &conversion_data,
1842 Object &object,
1843 GpencilModifierData &legacy_md)
1844{
1846 conversion_data, object, eModifierType_GreasePencilHook, legacy_md);
1847 auto &md_hook = reinterpret_cast<GreasePencilHookModifierData &>(md);
1848 auto &legacy_md_hook = reinterpret_cast<HookGpencilModifierData &>(legacy_md);
1849
1850 md_hook.flag = 0;
1851 if (legacy_md_hook.flag & GP_HOOK_UNIFORM_SPACE) {
1853 }
1854 switch (eHookGpencil_Falloff(legacy_md_hook.falloff_type)) {
1856 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_None;
1857 break;
1859 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Curve;
1860 break;
1862 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Sharp;
1863 break;
1865 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Smooth;
1866 break;
1868 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Root;
1869 break;
1871 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Linear;
1872 break;
1874 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Const;
1875 break;
1877 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Sphere;
1878 break;
1880 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_InvSquare;
1881 break;
1882 }
1883 md_hook.object = legacy_md_hook.object;
1884 legacy_md_hook.object = nullptr;
1885 STRNCPY(md_hook.subtarget, legacy_md_hook.subtarget);
1886 copy_m4_m4(md_hook.parentinv, legacy_md_hook.parentinv);
1887 copy_v3_v3(md_hook.cent, legacy_md_hook.cent);
1888 md_hook.falloff = legacy_md_hook.falloff;
1889 md_hook.force = legacy_md_hook.force;
1890
1891 legacy_object_modifier_influence(md_hook.influence,
1892 legacy_md_hook.layername,
1893 legacy_md_hook.layer_pass,
1894 legacy_md_hook.flag & GP_HOOK_INVERT_LAYER,
1895 legacy_md_hook.flag & GP_HOOK_INVERT_LAYERPASS,
1896 &legacy_md_hook.material,
1897 legacy_md_hook.pass_index,
1898 legacy_md_hook.flag & GP_HOOK_INVERT_MATERIAL,
1899 legacy_md_hook.flag & GP_HOOK_INVERT_PASS,
1900 legacy_md_hook.vgname,
1901 legacy_md_hook.flag & GP_HOOK_INVERT_VGROUP,
1902 &legacy_md_hook.curfalloff,
1903 true);
1904}
1905
1907 Object &object,
1908 GpencilModifierData &legacy_md)
1909{
1911 conversion_data, object, eModifierType_GreasePencilLattice, legacy_md);
1912 auto &md_lattice = reinterpret_cast<GreasePencilLatticeModifierData &>(md);
1913 auto &legacy_md_lattice = reinterpret_cast<LatticeGpencilModifierData &>(legacy_md);
1914
1915 md_lattice.object = legacy_md_lattice.object;
1916 legacy_md_lattice.object = nullptr;
1917 md_lattice.strength = legacy_md_lattice.strength;
1918
1919 legacy_object_modifier_influence(md_lattice.influence,
1920 legacy_md_lattice.layername,
1921 legacy_md_lattice.layer_pass,
1922 legacy_md_lattice.flag & GP_LATTICE_INVERT_LAYER,
1923 legacy_md_lattice.flag & GP_LATTICE_INVERT_LAYERPASS,
1924 &legacy_md_lattice.material,
1925 legacy_md_lattice.pass_index,
1926 legacy_md_lattice.flag & GP_LATTICE_INVERT_MATERIAL,
1927 legacy_md_lattice.flag & GP_LATTICE_INVERT_PASS,
1928 legacy_md_lattice.vgname,
1929 legacy_md_lattice.flag & GP_LATTICE_INVERT_VGROUP,
1930 nullptr,
1931 false);
1932}
1933
1935 Object &object,
1936 GpencilModifierData &legacy_md)
1937{
1939 conversion_data, object, eModifierType_GreasePencilLength, legacy_md);
1940 auto &md_length = reinterpret_cast<GreasePencilLengthModifierData &>(md);
1941 auto &legacy_md_length = reinterpret_cast<LengthGpencilModifierData &>(legacy_md);
1942
1943 md_length.flag = legacy_md_length.flag;
1944 md_length.start_fac = legacy_md_length.start_fac;
1945 md_length.end_fac = legacy_md_length.end_fac;
1946 md_length.rand_start_fac = legacy_md_length.rand_start_fac;
1947 md_length.rand_end_fac = legacy_md_length.rand_end_fac;
1948 md_length.rand_offset = legacy_md_length.rand_offset;
1949 md_length.overshoot_fac = legacy_md_length.overshoot_fac;
1950 md_length.seed = legacy_md_length.seed;
1951 md_length.step = legacy_md_length.step;
1952 md_length.mode = legacy_md_length.mode;
1953 md_length.point_density = legacy_md_length.point_density;
1954 md_length.segment_influence = legacy_md_length.segment_influence;
1955 md_length.max_angle = legacy_md_length.max_angle;
1956
1957 legacy_object_modifier_influence(md_length.influence,
1958 legacy_md_length.layername,
1959 legacy_md_length.layer_pass,
1960 legacy_md_length.flag & GP_LENGTH_INVERT_LAYER,
1961 legacy_md_length.flag & GP_LENGTH_INVERT_LAYERPASS,
1962 &legacy_md_length.material,
1963 legacy_md_length.pass_index,
1964 legacy_md_length.flag & GP_LENGTH_INVERT_MATERIAL,
1965 legacy_md_length.flag & GP_LENGTH_INVERT_PASS,
1966 "",
1967 false,
1968 nullptr,
1969 false);
1970}
1971
1973 Object &object,
1974 GpencilModifierData &legacy_md)
1975{
1977 conversion_data, object, eModifierType_GreasePencilMirror, legacy_md);
1978 auto &md_mirror = reinterpret_cast<GreasePencilMirrorModifierData &>(md);
1979 auto &legacy_md_mirror = reinterpret_cast<MirrorGpencilModifierData &>(legacy_md);
1980
1981 md_mirror.object = legacy_md_mirror.object;
1982 legacy_md_mirror.object = nullptr;
1983 md_mirror.flag = 0;
1984 if (legacy_md_mirror.flag & GP_MIRROR_AXIS_X) {
1985 md_mirror.flag |= MOD_GREASE_PENCIL_MIRROR_AXIS_X;
1986 }
1987 if (legacy_md_mirror.flag & GP_MIRROR_AXIS_Y) {
1988 md_mirror.flag |= MOD_GREASE_PENCIL_MIRROR_AXIS_Y;
1989 }
1990 if (legacy_md_mirror.flag & GP_MIRROR_AXIS_Z) {
1991 md_mirror.flag |= MOD_GREASE_PENCIL_MIRROR_AXIS_Z;
1992 }
1993
1994 legacy_object_modifier_influence(md_mirror.influence,
1995 legacy_md_mirror.layername,
1996 legacy_md_mirror.layer_pass,
1997 legacy_md_mirror.flag & GP_MIRROR_INVERT_LAYER,
1998 legacy_md_mirror.flag & GP_MIRROR_INVERT_LAYERPASS,
1999 &legacy_md_mirror.material,
2000 legacy_md_mirror.pass_index,
2001 legacy_md_mirror.flag & GP_MIRROR_INVERT_MATERIAL,
2002 legacy_md_mirror.flag & GP_MIRROR_INVERT_PASS,
2003 "",
2004 false,
2005 nullptr,
2006 false);
2007}
2008
2010 Object &object,
2011 GpencilModifierData &legacy_md)
2012{
2014 conversion_data, object, eModifierType_GreasePencilMultiply, legacy_md);
2015 auto &md_multiply = reinterpret_cast<GreasePencilMultiModifierData &>(md);
2016 auto &legacy_md_multiply = reinterpret_cast<MultiplyGpencilModifierData &>(legacy_md);
2017
2018 md_multiply.flag = 0;
2019 if (legacy_md_multiply.flags & GP_MULTIPLY_ENABLE_FADING) {
2020 md_multiply.flag |= MOD_GREASE_PENCIL_MULTIPLY_ENABLE_FADING;
2021 }
2022 md_multiply.duplications = legacy_md_multiply.duplications;
2023 md_multiply.distance = legacy_md_multiply.distance;
2024 md_multiply.offset = legacy_md_multiply.offset;
2025 md_multiply.fading_center = legacy_md_multiply.fading_center;
2026 md_multiply.fading_thickness = legacy_md_multiply.fading_thickness;
2027 md_multiply.fading_opacity = legacy_md_multiply.fading_opacity;
2028
2029 /* NOTE: This looks wrong, but GPv2 version uses Mirror modifier flags in its `flag` property
2030 * and own flags in its `flags` property. */
2031 legacy_object_modifier_influence(md_multiply.influence,
2032 legacy_md_multiply.layername,
2033 legacy_md_multiply.layer_pass,
2034 legacy_md_multiply.flag & GP_MIRROR_INVERT_LAYER,
2035 legacy_md_multiply.flag & GP_MIRROR_INVERT_LAYERPASS,
2036 &legacy_md_multiply.material,
2037 legacy_md_multiply.pass_index,
2038 legacy_md_multiply.flag & GP_MIRROR_INVERT_MATERIAL,
2039 legacy_md_multiply.flag & GP_MIRROR_INVERT_PASS,
2040 "",
2041 false,
2042 nullptr,
2043 false);
2044}
2045
2047 Object &object,
2048 GpencilModifierData &legacy_md)
2049{
2051 conversion_data, object, eModifierType_GreasePencilNoise, legacy_md);
2052 auto &md_noise = reinterpret_cast<GreasePencilNoiseModifierData &>(md);
2053 auto &legacy_md_noise = reinterpret_cast<NoiseGpencilModifierData &>(legacy_md);
2054
2055 md_noise.flag = legacy_md_noise.flag;
2056 md_noise.factor = legacy_md_noise.factor;
2057 md_noise.factor_strength = legacy_md_noise.factor_strength;
2058 md_noise.factor_thickness = legacy_md_noise.factor_thickness;
2059 md_noise.factor_uvs = legacy_md_noise.factor_uvs;
2060 md_noise.noise_scale = legacy_md_noise.noise_scale;
2061 md_noise.noise_offset = legacy_md_noise.noise_offset;
2062 md_noise.noise_mode = legacy_md_noise.noise_mode;
2063 md_noise.step = legacy_md_noise.step;
2064 md_noise.seed = legacy_md_noise.seed;
2065
2066 legacy_object_modifier_influence(md_noise.influence,
2067 legacy_md_noise.layername,
2068 legacy_md_noise.layer_pass,
2069 legacy_md_noise.flag & GP_NOISE_INVERT_LAYER,
2070 legacy_md_noise.flag & GP_NOISE_INVERT_LAYERPASS,
2071 &legacy_md_noise.material,
2072 legacy_md_noise.pass_index,
2073 legacy_md_noise.flag & GP_NOISE_INVERT_MATERIAL,
2074 legacy_md_noise.flag & GP_NOISE_INVERT_PASS,
2075 legacy_md_noise.vgname,
2076 legacy_md_noise.flag & GP_NOISE_INVERT_VGROUP,
2077 &legacy_md_noise.curve_intensity,
2078 legacy_md_noise.flag & GP_NOISE_CUSTOM_CURVE);
2079}
2080
2082 Object &object,
2083 GpencilModifierData &legacy_md)
2084{
2086 conversion_data, object, eModifierType_GreasePencilOffset, legacy_md);
2087 auto &md_offset = reinterpret_cast<GreasePencilOffsetModifierData &>(md);
2088 auto &legacy_md_offset = reinterpret_cast<OffsetGpencilModifierData &>(legacy_md);
2089
2090 md_offset.flag = 0;
2091 if (legacy_md_offset.flag & GP_OFFSET_UNIFORM_RANDOM_SCALE) {
2093 }
2094 switch (eOffsetGpencil_Mode(legacy_md_offset.mode)) {
2095 case GP_OFFSET_RANDOM:
2096 md_offset.offset_mode = MOD_GREASE_PENCIL_OFFSET_RANDOM;
2097 break;
2098 case GP_OFFSET_LAYER:
2099 md_offset.offset_mode = MOD_GREASE_PENCIL_OFFSET_LAYER;
2100 break;
2101 case GP_OFFSET_MATERIAL:
2102 md_offset.offset_mode = MOD_GREASE_PENCIL_OFFSET_MATERIAL;
2103 break;
2104 case GP_OFFSET_STROKE:
2105 md_offset.offset_mode = MOD_GREASE_PENCIL_OFFSET_STROKE;
2106 break;
2107 }
2108 copy_v3_v3(md_offset.loc, legacy_md_offset.loc);
2109 copy_v3_v3(md_offset.rot, legacy_md_offset.rot);
2110 copy_v3_v3(md_offset.scale, legacy_md_offset.scale);
2111 copy_v3_v3(md_offset.stroke_loc, legacy_md_offset.rnd_offset);
2112 copy_v3_v3(md_offset.stroke_rot, legacy_md_offset.rnd_rot);
2113 copy_v3_v3(md_offset.stroke_scale, legacy_md_offset.rnd_scale);
2114 md_offset.seed = legacy_md_offset.seed;
2115 md_offset.stroke_step = legacy_md_offset.stroke_step;
2116 md_offset.stroke_start_offset = legacy_md_offset.stroke_start_offset;
2117
2118 legacy_object_modifier_influence(md_offset.influence,
2119 legacy_md_offset.layername,
2120 legacy_md_offset.layer_pass,
2121 legacy_md_offset.flag & GP_OFFSET_INVERT_LAYER,
2122 legacy_md_offset.flag & GP_OFFSET_INVERT_LAYERPASS,
2123 &legacy_md_offset.material,
2124 legacy_md_offset.pass_index,
2125 legacy_md_offset.flag & GP_OFFSET_INVERT_MATERIAL,
2126 legacy_md_offset.flag & GP_OFFSET_INVERT_PASS,
2127 legacy_md_offset.vgname,
2128 legacy_md_offset.flag & GP_OFFSET_INVERT_VGROUP,
2129 nullptr,
2130 false);
2131}
2132
2134 Object &object,
2135 GpencilModifierData &legacy_md)
2136{
2138 conversion_data, object, eModifierType_GreasePencilOpacity, legacy_md);
2139 auto &md_opacity = reinterpret_cast<GreasePencilOpacityModifierData &>(md);
2140 auto &legacy_md_opacity = reinterpret_cast<OpacityGpencilModifierData &>(legacy_md);
2141
2142 md_opacity.flag = 0;
2143 if (legacy_md_opacity.flag & GP_OPACITY_NORMALIZE) {
2145 }
2146 if (legacy_md_opacity.flag & GP_OPACITY_WEIGHT_FACTOR) {
2148 }
2149 switch (eModifyColorGpencil_Flag(legacy_md_opacity.modify_color)) {
2151 md_opacity.color_mode = MOD_GREASE_PENCIL_COLOR_BOTH;
2152 break;
2154 md_opacity.color_mode = MOD_GREASE_PENCIL_COLOR_STROKE;
2155 break;
2157 md_opacity.color_mode = MOD_GREASE_PENCIL_COLOR_FILL;
2158 break;
2160 md_opacity.color_mode = MOD_GREASE_PENCIL_COLOR_HARDNESS;
2161 break;
2162 }
2163 md_opacity.color_factor = legacy_md_opacity.factor;
2164 md_opacity.hardness_factor = legacy_md_opacity.hardness;
2165
2166 legacy_object_modifier_influence(md_opacity.influence,
2167 legacy_md_opacity.layername,
2168 legacy_md_opacity.layer_pass,
2169 legacy_md_opacity.flag & GP_OPACITY_INVERT_LAYER,
2170 legacy_md_opacity.flag & GP_OPACITY_INVERT_LAYERPASS,
2171 &legacy_md_opacity.material,
2172 legacy_md_opacity.pass_index,
2173 legacy_md_opacity.flag & GP_OPACITY_INVERT_MATERIAL,
2174 legacy_md_opacity.flag & GP_OPACITY_INVERT_PASS,
2175 legacy_md_opacity.vgname,
2176 legacy_md_opacity.flag & GP_OPACITY_INVERT_VGROUP,
2177 &legacy_md_opacity.curve_intensity,
2178 legacy_md_opacity.flag & GP_OPACITY_CUSTOM_CURVE);
2179}
2180
2182 Object &object,
2183 GpencilModifierData &legacy_md)
2184{
2186 conversion_data, object, eModifierType_GreasePencilOutline, legacy_md);
2187 auto &md_outline = reinterpret_cast<GreasePencilOutlineModifierData &>(md);
2188 auto &legacy_md_outline = reinterpret_cast<OutlineGpencilModifierData &>(legacy_md);
2189
2190 md_outline.flag = 0;
2191 if (legacy_md_outline.flag & GP_OUTLINE_KEEP_SHAPE) {
2192 md_outline.flag |= MOD_GREASE_PENCIL_OUTLINE_KEEP_SHAPE;
2193 }
2194 md_outline.object = legacy_md_outline.object;
2195 legacy_md_outline.object = nullptr;
2196 md_outline.outline_material = legacy_md_outline.outline_material;
2197 legacy_md_outline.outline_material = nullptr;
2198 md_outline.sample_length = legacy_md_outline.sample_length;
2199 md_outline.subdiv = legacy_md_outline.subdiv;
2200 md_outline.thickness = legacy_md_outline.thickness;
2201
2202 legacy_object_modifier_influence(md_outline.influence,
2203 legacy_md_outline.layername,
2204 legacy_md_outline.layer_pass,
2205 legacy_md_outline.flag & GP_OUTLINE_INVERT_LAYER,
2206 legacy_md_outline.flag & GP_OUTLINE_INVERT_LAYERPASS,
2207 &legacy_md_outline.material,
2208 legacy_md_outline.pass_index,
2209 legacy_md_outline.flag & GP_OUTLINE_INVERT_MATERIAL,
2210 legacy_md_outline.flag & GP_OUTLINE_INVERT_PASS,
2211 "",
2212 false,
2213 nullptr,
2214 false);
2215}
2216
2218 Object &object,
2219 GpencilModifierData &legacy_md)
2220{
2222 conversion_data, object, eModifierType_GreasePencilShrinkwrap, legacy_md);
2223 auto &md_shrinkwrap = reinterpret_cast<GreasePencilShrinkwrapModifierData &>(md);
2224 auto &legacy_md_shrinkwrap = reinterpret_cast<ShrinkwrapGpencilModifierData &>(legacy_md);
2225
2226 /* Shrinkwrap enums and flags do not have named types. */
2227 /* MOD_SHRINKWRAP_NEAREST_SURFACE etc. */
2228 md_shrinkwrap.shrink_type = legacy_md_shrinkwrap.shrink_type;
2229 /* MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR etc. */
2230 md_shrinkwrap.shrink_opts = legacy_md_shrinkwrap.shrink_opts;
2231 /* MOD_SHRINKWRAP_ON_SURFACE etc. */
2232 md_shrinkwrap.shrink_mode = legacy_md_shrinkwrap.shrink_mode;
2233 /* MOD_SHRINKWRAP_PROJECT_OVER_NORMAL etc. */
2234 md_shrinkwrap.proj_axis = legacy_md_shrinkwrap.proj_axis;
2235
2236 md_shrinkwrap.target = legacy_md_shrinkwrap.target;
2237 legacy_md_shrinkwrap.target = nullptr;
2238 md_shrinkwrap.aux_target = legacy_md_shrinkwrap.aux_target;
2239 legacy_md_shrinkwrap.aux_target = nullptr;
2240 md_shrinkwrap.keep_dist = legacy_md_shrinkwrap.keep_dist;
2241 md_shrinkwrap.proj_limit = legacy_md_shrinkwrap.proj_limit;
2242 md_shrinkwrap.subsurf_levels = legacy_md_shrinkwrap.subsurf_levels;
2243 md_shrinkwrap.smooth_factor = legacy_md_shrinkwrap.smooth_factor;
2244 md_shrinkwrap.smooth_step = legacy_md_shrinkwrap.smooth_step;
2245
2246 legacy_object_modifier_influence(md_shrinkwrap.influence,
2247 legacy_md_shrinkwrap.layername,
2248 legacy_md_shrinkwrap.layer_pass,
2249 legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_LAYER,
2250 legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_LAYERPASS,
2251 &legacy_md_shrinkwrap.material,
2252 legacy_md_shrinkwrap.pass_index,
2253 legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_MATERIAL,
2254 legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_PASS,
2255 legacy_md_shrinkwrap.vgname,
2256 legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_VGROUP,
2257 nullptr,
2258 false);
2259}
2260
2262 Object &object,
2263 GpencilModifierData &legacy_md)
2264{
2266 conversion_data, object, eModifierType_GreasePencilSmooth, legacy_md);
2267 auto &md_smooth = reinterpret_cast<GreasePencilSmoothModifierData &>(md);
2268 auto &legacy_md_smooth = reinterpret_cast<SmoothGpencilModifierData &>(legacy_md);
2269
2270 md_smooth.flag = 0;
2271 if (legacy_md_smooth.flag & GP_SMOOTH_MOD_LOCATION) {
2272 md_smooth.flag |= MOD_GREASE_PENCIL_SMOOTH_MOD_LOCATION;
2273 }
2274 if (legacy_md_smooth.flag & GP_SMOOTH_MOD_STRENGTH) {
2275 md_smooth.flag |= MOD_GREASE_PENCIL_SMOOTH_MOD_STRENGTH;
2276 }
2277 if (legacy_md_smooth.flag & GP_SMOOTH_MOD_THICKNESS) {
2279 }
2280 if (legacy_md_smooth.flag & GP_SMOOTH_MOD_UV) {
2281 md_smooth.flag |= MOD_GREASE_PENCIL_SMOOTH_MOD_UV;
2282 }
2283 if (legacy_md_smooth.flag & GP_SMOOTH_KEEP_SHAPE) {
2284 md_smooth.flag |= MOD_GREASE_PENCIL_SMOOTH_KEEP_SHAPE;
2285 }
2286 md_smooth.factor = legacy_md_smooth.factor;
2287 md_smooth.step = legacy_md_smooth.step;
2288
2289 legacy_object_modifier_influence(md_smooth.influence,
2290 legacy_md_smooth.layername,
2291 legacy_md_smooth.layer_pass,
2292 legacy_md_smooth.flag & GP_SMOOTH_INVERT_LAYER,
2293 legacy_md_smooth.flag & GP_SMOOTH_INVERT_LAYERPASS,
2294 &legacy_md_smooth.material,
2295 legacy_md_smooth.pass_index,
2296 legacy_md_smooth.flag & GP_SMOOTH_INVERT_MATERIAL,
2297 legacy_md_smooth.flag & GP_SMOOTH_INVERT_PASS,
2298 legacy_md_smooth.vgname,
2299 legacy_md_smooth.flag & GP_SMOOTH_INVERT_VGROUP,
2300 &legacy_md_smooth.curve_intensity,
2301 legacy_md_smooth.flag & GP_SMOOTH_CUSTOM_CURVE);
2302}
2303
2305 Object &object,
2306 GpencilModifierData &legacy_md)
2307{
2309 conversion_data, object, eModifierType_GreasePencilSubdiv, legacy_md);
2310 auto &md_subdiv = reinterpret_cast<GreasePencilSubdivModifierData &>(md);
2311 auto &legacy_md_subdiv = reinterpret_cast<SubdivGpencilModifierData &>(legacy_md);
2312
2313 switch (eSubdivGpencil_Type(legacy_md_subdiv.type)) {
2314 case GP_SUBDIV_CATMULL:
2315 md_subdiv.type = MOD_GREASE_PENCIL_SUBDIV_CATMULL;
2316 break;
2317 case GP_SUBDIV_SIMPLE:
2318 md_subdiv.type = MOD_GREASE_PENCIL_SUBDIV_SIMPLE;
2319 break;
2320 }
2321 md_subdiv.level = legacy_md_subdiv.level;
2322
2323 legacy_object_modifier_influence(md_subdiv.influence,
2324 legacy_md_subdiv.layername,
2325 legacy_md_subdiv.layer_pass,
2326 legacy_md_subdiv.flag & GP_SUBDIV_INVERT_LAYER,
2327 legacy_md_subdiv.flag & GP_SUBDIV_INVERT_LAYERPASS,
2328 &legacy_md_subdiv.material,
2329 legacy_md_subdiv.pass_index,
2330 legacy_md_subdiv.flag & GP_SUBDIV_INVERT_MATERIAL,
2331 legacy_md_subdiv.flag & GP_SUBDIV_INVERT_PASS,
2332 "",
2333 false,
2334 nullptr,
2335 false);
2336}
2337
2339 Object &object,
2340 GpencilModifierData &legacy_md)
2341{
2343 conversion_data, object, eModifierType_GreasePencilTexture, legacy_md);
2344 auto &md_texture = reinterpret_cast<GreasePencilTextureModifierData &>(md);
2345 auto &legacy_md_texture = reinterpret_cast<TextureGpencilModifierData &>(legacy_md);
2346
2347 switch (eTextureGpencil_Mode(legacy_md_texture.mode)) {
2348 case STROKE:
2349 md_texture.mode = MOD_GREASE_PENCIL_TEXTURE_STROKE;
2350 break;
2351 case FILL:
2352 md_texture.mode = MOD_GREASE_PENCIL_TEXTURE_FILL;
2353 break;
2354 case STROKE_AND_FILL:
2356 break;
2357 }
2358 switch (eTextureGpencil_Fit(legacy_md_texture.fit_method)) {
2359 case GP_TEX_FIT_STROKE:
2360 md_texture.fit_method = MOD_GREASE_PENCIL_TEXTURE_FIT_STROKE;
2361 break;
2363 md_texture.fit_method = MOD_GREASE_PENCIL_TEXTURE_CONSTANT_LENGTH;
2364 break;
2365 }
2366 md_texture.uv_offset = legacy_md_texture.uv_offset;
2367 md_texture.uv_scale = legacy_md_texture.uv_scale;
2368 md_texture.fill_rotation = legacy_md_texture.fill_rotation;
2369 copy_v2_v2(md_texture.fill_offset, legacy_md_texture.fill_offset);
2370 md_texture.fill_scale = legacy_md_texture.fill_scale;
2371 md_texture.layer_pass = legacy_md_texture.layer_pass;
2372 md_texture.alignment_rotation = legacy_md_texture.alignment_rotation;
2373
2374 legacy_object_modifier_influence(md_texture.influence,
2375 legacy_md_texture.layername,
2376 legacy_md_texture.layer_pass,
2377 legacy_md_texture.flag & GP_TEX_INVERT_LAYER,
2378 legacy_md_texture.flag & GP_TEX_INVERT_LAYERPASS,
2379 &legacy_md_texture.material,
2380 legacy_md_texture.pass_index,
2381 legacy_md_texture.flag & GP_TEX_INVERT_MATERIAL,
2382 legacy_md_texture.flag & GP_TEX_INVERT_PASS,
2383 legacy_md_texture.vgname,
2384 legacy_md_texture.flag & GP_TEX_INVERT_VGROUP,
2385 nullptr,
2386 false);
2387}
2388
2390 Object &object,
2391 GpencilModifierData &legacy_md)
2392{
2394 conversion_data, object, eModifierType_GreasePencilThickness, legacy_md);
2395 auto &md_thickness = reinterpret_cast<GreasePencilThickModifierData &>(md);
2396 auto &legacy_md_thickness = reinterpret_cast<ThickGpencilModifierData &>(legacy_md);
2397
2398 md_thickness.flag = 0;
2399 if (legacy_md_thickness.flag & GP_THICK_NORMALIZE) {
2400 md_thickness.flag |= MOD_GREASE_PENCIL_THICK_NORMALIZE;
2401 }
2402 if (legacy_md_thickness.flag & GP_THICK_WEIGHT_FACTOR) {
2403 md_thickness.flag |= MOD_GREASE_PENCIL_THICK_WEIGHT_FACTOR;
2404 }
2405 md_thickness.thickness_fac = legacy_md_thickness.thickness_fac;
2406 md_thickness.thickness = legacy_md_thickness.thickness * LEGACY_RADIUS_CONVERSION_FACTOR;
2407
2408 legacy_object_modifier_influence(md_thickness.influence,
2409 legacy_md_thickness.layername,
2410 legacy_md_thickness.layer_pass,
2411 legacy_md_thickness.flag & GP_THICK_INVERT_LAYER,
2412 legacy_md_thickness.flag & GP_THICK_INVERT_LAYERPASS,
2413 &legacy_md_thickness.material,
2414 legacy_md_thickness.pass_index,
2415 legacy_md_thickness.flag & GP_THICK_INVERT_MATERIAL,
2416 legacy_md_thickness.flag & GP_THICK_INVERT_PASS,
2417 legacy_md_thickness.vgname,
2418 legacy_md_thickness.flag & GP_THICK_INVERT_VGROUP,
2419 &legacy_md_thickness.curve_thickness,
2420 legacy_md_thickness.flag & GP_THICK_CUSTOM_CURVE);
2421}
2422
2423static void legacy_object_modifier_time(ConversionData &conversion_data,
2424 Object &object,
2425 GpencilModifierData &legacy_md)
2426{
2428 conversion_data, object, eModifierType_GreasePencilTime, legacy_md);
2429 auto &md_time = reinterpret_cast<GreasePencilTimeModifierData &>(md);
2430 auto &legacy_md_time = reinterpret_cast<TimeGpencilModifierData &>(legacy_md);
2431
2432 md_time.flag = 0;
2433 if (legacy_md_time.flag & GP_TIME_CUSTOM_RANGE) {
2435 }
2436 if (legacy_md_time.flag & GP_TIME_KEEP_LOOP) {
2437 md_time.flag |= MOD_GREASE_PENCIL_TIME_KEEP_LOOP;
2438 }
2439 switch (eTimeGpencil_Mode(legacy_md_time.mode)) {
2442 break;
2445 break;
2446 case GP_TIME_MODE_FIX:
2447 md_time.mode = MOD_GREASE_PENCIL_TIME_MODE_FIX;
2448 break;
2451 break;
2452 case GP_TIME_MODE_CHAIN:
2453 md_time.mode = MOD_GREASE_PENCIL_TIME_MODE_CHAIN;
2454 break;
2455 }
2456 md_time.offset = legacy_md_time.offset;
2457 md_time.frame_scale = legacy_md_time.frame_scale;
2458 md_time.sfra = legacy_md_time.sfra;
2459 md_time.efra = legacy_md_time.efra;
2460 md_time.segment_active_index = legacy_md_time.segment_active_index;
2461 md_time.segments_num = legacy_md_time.segments_len;
2462 MEM_SAFE_FREE(md_time.segments_array);
2463 md_time.segments_array = MEM_cnew_array<GreasePencilTimeModifierSegment>(
2464 legacy_md_time.segments_len, __func__);
2465 for (const int i : IndexRange(md_time.segments_num)) {
2466 GreasePencilTimeModifierSegment &dst_segment = md_time.segments_array[i];
2467 const TimeGpencilModifierSegment &src_segment = legacy_md_time.segments[i];
2468 STRNCPY(dst_segment.name, src_segment.name);
2469 switch (eTimeGpencil_Seg_Mode(src_segment.seg_mode)) {
2472 break;
2475 break;
2478 break;
2479 }
2480 dst_segment.segment_start = src_segment.seg_start;
2481 dst_segment.segment_end = src_segment.seg_end;
2482 dst_segment.segment_repeat = src_segment.seg_repeat;
2483 }
2484
2485 /* NOTE: GPv2 time modifier has a material pointer but it is unused. */
2486 legacy_object_modifier_influence(md_time.influence,
2487 legacy_md_time.layername,
2488 legacy_md_time.layer_pass,
2489 legacy_md_time.flag & GP_TIME_INVERT_LAYER,
2490 legacy_md_time.flag & GP_TIME_INVERT_LAYERPASS,
2491 nullptr,
2492 0,
2493 false,
2494 false,
2495 "",
2496 false,
2497 nullptr,
2498 false);
2499}
2500
2501static void legacy_object_modifier_tint(ConversionData &conversion_data,
2502 Object &object,
2503 GpencilModifierData &legacy_md)
2504{
2506 conversion_data, object, eModifierType_GreasePencilTint, legacy_md);
2507 auto &md_tint = reinterpret_cast<GreasePencilTintModifierData &>(md);
2508 auto &legacy_md_tint = reinterpret_cast<TintGpencilModifierData &>(legacy_md);
2509
2510 md_tint.flag = 0;
2511 if (legacy_md_tint.flag & GP_TINT_WEIGHT_FACTOR) {
2513 }
2514 switch (eGp_Vertex_Mode(legacy_md_tint.mode)) {
2515 case GPPAINT_MODE_BOTH:
2516 md_tint.color_mode = MOD_GREASE_PENCIL_COLOR_BOTH;
2517 break;
2519 md_tint.color_mode = MOD_GREASE_PENCIL_COLOR_STROKE;
2520 break;
2521 case GPPAINT_MODE_FILL:
2522 md_tint.color_mode = MOD_GREASE_PENCIL_COLOR_FILL;
2523 break;
2524 }
2525 switch (eTintGpencil_Type(legacy_md_tint.type)) {
2526 case GP_TINT_UNIFORM:
2527 md_tint.tint_mode = MOD_GREASE_PENCIL_TINT_UNIFORM;
2528 break;
2529 case GP_TINT_GRADIENT:
2530 md_tint.tint_mode = MOD_GREASE_PENCIL_TINT_GRADIENT;
2531 break;
2532 }
2533 md_tint.factor = legacy_md_tint.factor;
2534 md_tint.radius = legacy_md_tint.radius;
2535 copy_v3_v3(md_tint.color, legacy_md_tint.rgb);
2536 md_tint.object = legacy_md_tint.object;
2537 legacy_md_tint.object = nullptr;
2538 MEM_SAFE_FREE(md_tint.color_ramp);
2539 md_tint.color_ramp = legacy_md_tint.colorband;
2540 legacy_md_tint.colorband = nullptr;
2541
2542 legacy_object_modifier_influence(md_tint.influence,
2543 legacy_md_tint.layername,
2544 legacy_md_tint.layer_pass,
2545 legacy_md_tint.flag & GP_TINT_INVERT_LAYER,
2546 legacy_md_tint.flag & GP_TINT_INVERT_LAYERPASS,
2547 &legacy_md_tint.material,
2548 legacy_md_tint.pass_index,
2549 legacy_md_tint.flag & GP_TINT_INVERT_MATERIAL,
2550 legacy_md_tint.flag & GP_TINT_INVERT_PASS,
2551 legacy_md_tint.vgname,
2552 legacy_md_tint.flag & GP_TINT_INVERT_VGROUP,
2553 &legacy_md_tint.curve_intensity,
2554 legacy_md_tint.flag & GP_TINT_CUSTOM_CURVE);
2555}
2556
2558 Object &object,
2559 GpencilModifierData &legacy_md)
2560{
2562 conversion_data, object, eModifierType_GreasePencilWeightAngle, legacy_md);
2563 auto &md_weight_angle = reinterpret_cast<GreasePencilWeightAngleModifierData &>(md);
2564 auto &legacy_md_weight_angle = reinterpret_cast<WeightAngleGpencilModifierData &>(legacy_md);
2565
2566 md_weight_angle.flag = 0;
2567 if (legacy_md_weight_angle.flag & GP_WEIGHT_MULTIPLY_DATA) {
2568 md_weight_angle.flag |= MOD_GREASE_PENCIL_WEIGHT_ANGLE_MULTIPLY_DATA;
2569 }
2570 if (legacy_md_weight_angle.flag & GP_WEIGHT_INVERT_OUTPUT) {
2571 md_weight_angle.flag |= MOD_GREASE_PENCIL_WEIGHT_ANGLE_INVERT_OUTPUT;
2572 }
2573 switch (eGpencilModifierSpace(legacy_md_weight_angle.space)) {
2574 case GP_SPACE_LOCAL:
2575 md_weight_angle.space = MOD_GREASE_PENCIL_WEIGHT_ANGLE_SPACE_LOCAL;
2576 break;
2577 case GP_SPACE_WORLD:
2578 md_weight_angle.space = MOD_GREASE_PENCIL_WEIGHT_ANGLE_SPACE_WORLD;
2579 break;
2580 }
2581 md_weight_angle.axis = legacy_md_weight_angle.axis;
2582 STRNCPY(md_weight_angle.target_vgname, legacy_md_weight_angle.target_vgname);
2583 md_weight_angle.min_weight = legacy_md_weight_angle.min_weight;
2584 md_weight_angle.angle = legacy_md_weight_angle.angle;
2585
2586 legacy_object_modifier_influence(md_weight_angle.influence,
2587 legacy_md_weight_angle.layername,
2588 legacy_md_weight_angle.layer_pass,
2589 legacy_md_weight_angle.flag & GP_WEIGHT_INVERT_LAYER,
2590 legacy_md_weight_angle.flag & GP_WEIGHT_INVERT_LAYERPASS,
2591 &legacy_md_weight_angle.material,
2592 legacy_md_weight_angle.pass_index,
2593 legacy_md_weight_angle.flag & GP_WEIGHT_INVERT_MATERIAL,
2594 legacy_md_weight_angle.flag & GP_WEIGHT_INVERT_PASS,
2595 legacy_md_weight_angle.vgname,
2596 legacy_md_weight_angle.flag & GP_WEIGHT_INVERT_VGROUP,
2597 nullptr,
2598 false);
2599}
2600
2602 Object &object,
2603 GpencilModifierData &legacy_md)
2604{
2606 conversion_data, object, eModifierType_GreasePencilWeightProximity, legacy_md);
2607 auto &md_weight_prox = reinterpret_cast<GreasePencilWeightProximityModifierData &>(md);
2608 auto &legacy_md_weight_prox = reinterpret_cast<WeightProxGpencilModifierData &>(legacy_md);
2609
2610 md_weight_prox.flag = 0;
2611 if (legacy_md_weight_prox.flag & GP_WEIGHT_MULTIPLY_DATA) {
2613 }
2614 if (legacy_md_weight_prox.flag & GP_WEIGHT_INVERT_OUTPUT) {
2616 }
2617 STRNCPY(md_weight_prox.target_vgname, legacy_md_weight_prox.target_vgname);
2618 md_weight_prox.min_weight = legacy_md_weight_prox.min_weight;
2619 md_weight_prox.dist_start = legacy_md_weight_prox.dist_start;
2620 md_weight_prox.dist_end = legacy_md_weight_prox.dist_end;
2621 md_weight_prox.object = legacy_md_weight_prox.object;
2622 legacy_md_weight_prox.object = nullptr;
2623
2624 legacy_object_modifier_influence(md_weight_prox.influence,
2625 legacy_md_weight_prox.layername,
2626 legacy_md_weight_prox.layer_pass,
2627 legacy_md_weight_prox.flag & GP_WEIGHT_INVERT_LAYER,
2628 legacy_md_weight_prox.flag & GP_WEIGHT_INVERT_LAYERPASS,
2629 &legacy_md_weight_prox.material,
2630 legacy_md_weight_prox.pass_index,
2631 legacy_md_weight_prox.flag & GP_WEIGHT_INVERT_MATERIAL,
2632 legacy_md_weight_prox.flag & GP_WEIGHT_INVERT_PASS,
2633 legacy_md_weight_prox.vgname,
2634 legacy_md_weight_prox.flag & GP_WEIGHT_INVERT_VGROUP,
2635 nullptr,
2636 false);
2637}
2638
2640 Object &object,
2641 GpencilModifierData &legacy_md)
2642{
2644 conversion_data, object, eModifierType_GreasePencilLineart, legacy_md);
2645 auto &md_lineart = reinterpret_cast<GreasePencilLineartModifierData &>(md);
2646 auto &legacy_md_lineart = reinterpret_cast<LineartGpencilModifierData &>(legacy_md);
2647
2648 greasepencil::convert::lineart_wrap_v3(&legacy_md_lineart, &md_lineart);
2649}
2650
2652 Object &object,
2653 GpencilModifierData &legacy_md)
2654{
2656 conversion_data, object, eModifierType_GreasePencilBuild, legacy_md);
2657 auto &md_build = reinterpret_cast<GreasePencilBuildModifierData &>(md);
2658 auto &legacy_md_build = reinterpret_cast<BuildGpencilModifierData &>(legacy_md);
2659
2660 md_build.flag = 0;
2661 if (legacy_md_build.flag & GP_BUILD_RESTRICT_TIME) {
2663 }
2664 if (legacy_md_build.flag & GP_BUILD_USE_FADING) {
2665 md_build.flag |= MOD_GREASE_PENCIL_BUILD_USE_FADING;
2666 }
2667
2668 switch (legacy_md_build.mode) {
2671 break;
2674 break;
2676 default:
2678 break;
2679 }
2680
2681 switch (legacy_md_build.time_alignment) {
2682 default:
2684 md_build.time_alignment = MOD_GREASE_PENCIL_BUILD_TIMEALIGN_START;
2685 break;
2687 md_build.time_alignment = MOD_GREASE_PENCIL_BUILD_TIMEALIGN_END;
2688 break;
2689 }
2690
2691 switch (legacy_md_build.time_mode) {
2692 default:
2694 md_build.time_mode = MOD_GREASE_PENCIL_BUILD_TIMEMODE_FRAMES;
2695 break;
2698 break;
2700 md_build.time_mode = MOD_GREASE_PENCIL_BUILD_TIMEMODE_DRAWSPEED;
2701 break;
2702 }
2703
2704 switch (legacy_md_build.transition) {
2705 default:
2707 md_build.transition = MOD_GREASE_PENCIL_BUILD_TRANSITION_GROW;
2708 break;
2710 md_build.transition = MOD_GREASE_PENCIL_BUILD_TRANSITION_SHRINK;
2711 break;
2713 md_build.transition = MOD_GREASE_PENCIL_BUILD_TRANSITION_VANISH;
2714 break;
2715 }
2716
2717 md_build.start_frame = legacy_md_build.start_frame;
2718 md_build.end_frame = legacy_md_build.end_frame;
2719 md_build.start_delay = legacy_md_build.start_delay;
2720 md_build.length = legacy_md_build.length;
2721 md_build.fade_fac = legacy_md_build.fade_fac;
2722 md_build.fade_opacity_strength = legacy_md_build.fade_opacity_strength;
2723 md_build.fade_thickness_strength = legacy_md_build.fade_thickness_strength;
2724 md_build.percentage_fac = legacy_md_build.percentage_fac;
2725 md_build.speed_fac = legacy_md_build.speed_fac;
2726 md_build.speed_maxgap = legacy_md_build.speed_maxgap;
2727 md_build.object = legacy_md_build.object;
2728 STRNCPY(md_build.target_vgname, legacy_md_build.target_vgname);
2729
2730 legacy_object_modifier_influence(md_build.influence,
2731 legacy_md_build.layername,
2732 legacy_md_build.layer_pass,
2733 legacy_md_build.flag & GP_WEIGHT_INVERT_LAYER,
2734 legacy_md_build.flag & GP_WEIGHT_INVERT_LAYERPASS,
2735 &legacy_md_build.material,
2736 legacy_md_build.pass_index,
2737 legacy_md_build.flag & GP_WEIGHT_INVERT_MATERIAL,
2738 legacy_md_build.flag & GP_WEIGHT_INVERT_PASS,
2739 legacy_md_build.target_vgname,
2740 legacy_md_build.flag & GP_WEIGHT_INVERT_VGROUP,
2741 nullptr,
2742 false);
2743}
2744
2746 Object &object,
2747 GpencilModifierData &legacy_md)
2748{
2750 conversion_data, object, eModifierType_GreasePencilSimplify, legacy_md);
2751 auto &md_simplify = reinterpret_cast<GreasePencilSimplifyModifierData &>(md);
2752 auto &legacy_md_simplify = reinterpret_cast<SimplifyGpencilModifierData &>(legacy_md);
2753
2754 switch (legacy_md_simplify.mode) {
2755 case GP_SIMPLIFY_FIXED:
2756 md_simplify.mode = MOD_GREASE_PENCIL_SIMPLIFY_FIXED;
2757 break;
2759 md_simplify.mode = MOD_GREASE_PENCIL_SIMPLIFY_ADAPTIVE;
2760 break;
2761 case GP_SIMPLIFY_SAMPLE:
2762 md_simplify.mode = MOD_GREASE_PENCIL_SIMPLIFY_SAMPLE;
2763 break;
2764 case GP_SIMPLIFY_MERGE:
2765 md_simplify.mode = MOD_GREASE_PENCIL_SIMPLIFY_MERGE;
2766 break;
2767 }
2768
2769 md_simplify.step = legacy_md_simplify.step;
2770 md_simplify.factor = legacy_md_simplify.factor;
2771 md_simplify.length = legacy_md_simplify.length;
2772 md_simplify.sharp_threshold = legacy_md_simplify.sharp_threshold;
2773 md_simplify.distance = legacy_md_simplify.distance;
2774
2775 legacy_object_modifier_influence(md_simplify.influence,
2776 legacy_md_simplify.layername,
2777 legacy_md_simplify.layer_pass,
2778 legacy_md_simplify.flag & GP_SIMPLIFY_INVERT_LAYER,
2779 legacy_md_simplify.flag & GP_SIMPLIFY_INVERT_LAYERPASS,
2780 &legacy_md_simplify.material,
2781 legacy_md_simplify.pass_index,
2782 legacy_md_simplify.flag & GP_SIMPLIFY_INVERT_MATERIAL,
2783 legacy_md_simplify.flag & GP_SIMPLIFY_INVERT_PASS,
2784 "",
2785 false,
2786 nullptr,
2787 false);
2788}
2789
2790static void legacy_object_modifiers(ConversionData &conversion_data, Object &object)
2791{
2792 BLI_assert(BLI_listbase_is_empty(&object.modifiers));
2793
2794 while (GpencilModifierData *gpd_md = static_cast<GpencilModifierData *>(
2795 BLI_pophead(&object.greasepencil_modifiers)))
2796 {
2797 switch (gpd_md->type) {
2799 /* Unknown type, just ignore. */
2800 break;
2802 legacy_object_modifier_armature(conversion_data, object, *gpd_md);
2803 break;
2805 legacy_object_modifier_array(conversion_data, object, *gpd_md);
2806 break;
2808 legacy_object_modifier_color(conversion_data, object, *gpd_md);
2809 break;
2811 legacy_object_modifier_dash(conversion_data, object, *gpd_md);
2812 break;
2814 legacy_object_modifier_envelope(conversion_data, object, *gpd_md);
2815 break;
2817 legacy_object_modifier_hook(conversion_data, object, *gpd_md);
2818 break;
2820 legacy_object_modifier_lattice(conversion_data, object, *gpd_md);
2821 break;
2823 legacy_object_modifier_length(conversion_data, object, *gpd_md);
2824 break;
2826 legacy_object_modifier_mirror(conversion_data, object, *gpd_md);
2827 break;
2829 legacy_object_modifier_multiply(conversion_data, object, *gpd_md);
2830 break;
2832 legacy_object_modifier_noise(conversion_data, object, *gpd_md);
2833 break;
2835 legacy_object_modifier_offset(conversion_data, object, *gpd_md);
2836 break;
2838 legacy_object_modifier_opacity(conversion_data, object, *gpd_md);
2839 break;
2841 legacy_object_modifier_outline(conversion_data, object, *gpd_md);
2842 break;
2844 legacy_object_modifier_shrinkwrap(conversion_data, object, *gpd_md);
2845 break;
2847 legacy_object_modifier_smooth(conversion_data, object, *gpd_md);
2848 break;
2850 legacy_object_modifier_subdiv(conversion_data, object, *gpd_md);
2851 break;
2853 legacy_object_modifier_texture(conversion_data, object, *gpd_md);
2854 break;
2856 legacy_object_modifier_thickness(conversion_data, object, *gpd_md);
2857 break;
2859 legacy_object_modifier_time(conversion_data, object, *gpd_md);
2860 break;
2862 legacy_object_modifier_tint(conversion_data, object, *gpd_md);
2863 break;
2865 legacy_object_modifier_weight_angle(conversion_data, object, *gpd_md);
2866 break;
2868 legacy_object_modifier_weight_proximity(conversion_data, object, *gpd_md);
2869 break;
2871 legacy_object_modifier_lineart(conversion_data, object, *gpd_md);
2872 break;
2874 legacy_object_modifier_build(conversion_data, object, *gpd_md);
2875 break;
2877 legacy_object_modifier_simplify(conversion_data, object, *gpd_md);
2878 break;
2879 }
2880
2882 }
2883}
2884
2903{
2904 /* Annotations mapping, keys are existing GPv2 IDs actually used as annotations, values are
2905 * either:
2906 * - nullptr: this annotation is never used by any object, there was no need to duplicate it.
2907 * - new GPv2 ID: this annotation was also used by objects, this is its new duplicated ID. */
2908 Map<bGPdata *, bGPdata *> annotations_gpv2;
2909 /* All legacy GPv2 data used by objects. */
2910 Set<bGPdata *> object_gpv2;
2911
2912 /* Check all GP objects. */
2913 LISTBASE_FOREACH (Object *, object, &bmain.objects) {
2914 if (object->type != OB_GPENCIL_LEGACY) {
2915 continue;
2916 }
2917 bGPdata *legacy_gpd = static_cast<bGPdata *>(object->data);
2918 if (!legacy_gpd) {
2919 continue;
2920 }
2921 if ((legacy_gpd->flag & GP_DATA_ANNOTATIONS) != 0) {
2922 legacy_gpd->flag &= ~GP_DATA_ANNOTATIONS;
2923 }
2924 object_gpv2.add(legacy_gpd);
2925 }
2926
2927 /* Detect all annotations currently used as such, and de-duplicate them if they are also used by
2928 * objects. */
2929
2930 auto sanitize_gpv2_annotation = [&](bGPdata **legacy_gpd_p) {
2931 bGPdata *legacy_gpd = *legacy_gpd_p;
2932 if (!legacy_gpd) {
2933 return;
2934 }
2935
2936 bGPdata *new_annotation_gpd = annotations_gpv2.lookup_or_add(legacy_gpd, nullptr);
2937 if (!object_gpv2.contains(legacy_gpd)) {
2938 /* Legacy annotation GPv2 data not used by any object, just ensure that it is properly
2939 * tagged. */
2940 BLI_assert(!new_annotation_gpd);
2941 if ((legacy_gpd->flag & GP_DATA_ANNOTATIONS) == 0) {
2942 legacy_gpd->flag |= GP_DATA_ANNOTATIONS;
2943 }
2944 return;
2945 }
2946
2947 /* Legacy GP data also used by objects. Create the duplicate of legacy GPv2 data for
2948 * annotations, if not yet done. */
2949 if (!new_annotation_gpd) {
2950 new_annotation_gpd = reinterpret_cast<bGPdata *>(BKE_id_copy_in_lib(
2951 &bmain, legacy_gpd->id.lib, &legacy_gpd->id, nullptr, nullptr, LIB_ID_COPY_DEFAULT));
2952 new_annotation_gpd->flag |= GP_DATA_ANNOTATIONS;
2953 id_us_min(&new_annotation_gpd->id);
2954 annotations_gpv2.add_overwrite(legacy_gpd, new_annotation_gpd);
2955 }
2956
2957 /* Assign the annotation duplicate ID to the annotation pointer. */
2958 BLI_assert(new_annotation_gpd->flag & GP_DATA_ANNOTATIONS);
2959 id_us_min(&legacy_gpd->id);
2960 *legacy_gpd_p = new_annotation_gpd;
2961 id_us_plus_no_lib(&new_annotation_gpd->id);
2962 };
2963
2964 LISTBASE_FOREACH (Scene *, scene, &bmain.scenes) {
2965 sanitize_gpv2_annotation(&scene->gpd);
2966 }
2967
2968 ID *id_iter;
2969 FOREACH_MAIN_ID_BEGIN (&bmain, id_iter) {
2970 if (bNodeTree *node_tree = bke::node_tree_from_id(id_iter)) {
2971 sanitize_gpv2_annotation(&node_tree->gpd);
2972 }
2973 }
2976 sanitize_gpv2_annotation(&node_tree->gpd);
2977 }
2978
2979 LISTBASE_FOREACH (MovieClip *, movie_clip, &bmain.movieclips) {
2980 sanitize_gpv2_annotation(&movie_clip->gpd);
2981
2982 LISTBASE_FOREACH (MovieTrackingObject *, mvc_tracking_object, &movie_clip->tracking.objects) {
2983 LISTBASE_FOREACH (MovieTrackingTrack *, mvc_track, &mvc_tracking_object->tracks) {
2984 sanitize_gpv2_annotation(&mvc_track->gpd);
2985 }
2987 MovieTrackingPlaneTrack *, mvc_plane_track, &mvc_tracking_object->plane_tracks)
2988 {
2989 for (int i = 0; i < mvc_plane_track->point_tracksnr; i++) {
2990 sanitize_gpv2_annotation(&mvc_plane_track->point_tracks[i]->gpd);
2991 }
2992 }
2993 }
2994 }
2995
2996 LISTBASE_FOREACH (bScreen *, screen, &bmain.screens) {
2997 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
2998 LISTBASE_FOREACH (SpaceLink *, space_link, &area->spacedata) {
2999 switch (eSpace_Type(space_link->spacetype)) {
3000 case SPACE_SEQ: {
3001 SpaceSeq *space_sequencer = reinterpret_cast<SpaceSeq *>(space_link);
3002 sanitize_gpv2_annotation(&space_sequencer->gpd);
3003 break;
3004 }
3005 case SPACE_IMAGE: {
3006 SpaceImage *space_image = reinterpret_cast<SpaceImage *>(space_link);
3007 sanitize_gpv2_annotation(&space_image->gpd);
3008 break;
3009 }
3010 case SPACE_NODE: {
3011 SpaceNode *space_node = reinterpret_cast<SpaceNode *>(space_link);
3012 sanitize_gpv2_annotation(&space_node->gpd);
3013 break;
3014 }
3015 case SPACE_EMPTY:
3016 case SPACE_VIEW3D:
3017 /* #View3D.gpd is deprecated and can be ignored here. */
3018 case SPACE_GRAPH:
3019 case SPACE_OUTLINER:
3020 case SPACE_PROPERTIES:
3021 case SPACE_FILE:
3022 case SPACE_INFO:
3023 case SPACE_TEXT:
3024 case SPACE_ACTION:
3025 case SPACE_NLA:
3026 case SPACE_SCRIPT:
3027 case SPACE_CONSOLE:
3028 case SPACE_USERPREF:
3029 case SPACE_CLIP:
3030 case SPACE_TOPBAR:
3031 case SPACE_STATUSBAR:
3032 case SPACE_SPREADSHEET:
3033 break;
3034 }
3035 }
3036 }
3037 }
3038}
3039
3040static void legacy_gpencil_object(ConversionData &conversion_data, Object &object)
3041{
3042 BLI_assert((GS(static_cast<ID *>(object.data)->name) == ID_GD_LEGACY));
3043
3044 bGPdata *gpd = static_cast<bGPdata *>(object.data);
3045
3046 GreasePencil *new_grease_pencil = conversion_data.legacy_to_greasepencil_data.lookup_default(
3047 gpd, nullptr);
3048 const bool do_gpencil_data_conversion = (new_grease_pencil == nullptr);
3049
3050 if (!new_grease_pencil) {
3051 new_grease_pencil = static_cast<GreasePencil *>(
3052 BKE_id_new_in_lib(&conversion_data.bmain, gpd->id.lib, ID_GP, gpd->id.name + 2));
3053 id_us_min(&new_grease_pencil->id);
3054 }
3055
3056 object.data = new_grease_pencil;
3057 object.type = OB_GREASE_PENCIL;
3058
3059 /* NOTE: Could also use #BKE_id_free_us, to also free the legacy GP if not used anymore? */
3060 id_us_min(&gpd->id);
3061 id_us_plus(&new_grease_pencil->id);
3062
3063 if (do_gpencil_data_conversion) {
3064 legacy_gpencil_to_grease_pencil(conversion_data, *new_grease_pencil, *gpd);
3065 conversion_data.legacy_to_greasepencil_data.add(gpd, new_grease_pencil);
3066 }
3067
3068 legacy_object_modifiers(conversion_data, object);
3069 /* Convert the animation of the "uniform thickness" setting of the thickness modifier. */
3070 legacy_object_thickness_modifier_thickness_anim(conversion_data, object);
3071
3072 /* Layer adjustments should be added after all other modifiers. */
3073 layer_adjustments_to_modifiers(conversion_data, *gpd, object);
3074 /* Thickness factor is applied after all other changes to the radii. */
3075 thickness_factor_to_modifier(conversion_data, *gpd, object);
3076
3078}
3079
3080void legacy_main(Main &bmain,
3081 BlendfileLinkAppendContext *lapp_context,
3082 BlendFileReadReport & /*reports*/)
3083{
3084 ConversionData conversion_data(bmain, lapp_context);
3085
3086 /* Ensure that annotations are fully separated from object usages of legacy GPv2 data. */
3088
3089 LISTBASE_FOREACH (Object *, object, &bmain.objects) {
3090 if (object->type != OB_GPENCIL_LEGACY) {
3091 continue;
3092 }
3093 legacy_gpencil_object(conversion_data, *object);
3094 }
3095
3096 /* Potential other usages of legacy bGPdata IDs also need to be remapped to their matching new
3097 * GreasePencil counterparts. */
3098 bke::id::IDRemapper gpd_remapper;
3099 /* Allow remapping from legacy bGPdata IDs to new GreasePencil ones. */
3100 gpd_remapper.allow_idtype_mismatch = true;
3101
3102 LISTBASE_FOREACH (bGPdata *, legacy_gpd, &bmain.gpencils) {
3103 /* Annotations still use legacy `bGPdata`, these should not be converted. Call to
3104 * #legacy_gpencil_sanitize_annotations above ensured to fully separate annotations from object
3105 * legacy grease pencil. */
3106 if ((legacy_gpd->flag & GP_DATA_ANNOTATIONS) != 0) {
3107 continue;
3108 }
3109 GreasePencil *new_grease_pencil = conversion_data.legacy_to_greasepencil_data.lookup_default(
3110 legacy_gpd, nullptr);
3111 if (!new_grease_pencil) {
3112 new_grease_pencil = static_cast<GreasePencil *>(
3113 BKE_id_new_in_lib(&bmain, legacy_gpd->id.lib, ID_GP, legacy_gpd->id.name + 2));
3114 id_us_min(&new_grease_pencil->id);
3115 legacy_gpencil_to_grease_pencil(conversion_data, *new_grease_pencil, *legacy_gpd);
3116 conversion_data.legacy_to_greasepencil_data.add(legacy_gpd, new_grease_pencil);
3117 }
3118 gpd_remapper.add(&legacy_gpd->id, &new_grease_pencil->id);
3119 }
3120
3122
3123 if (conversion_data.lapp_context) {
3125 conversion_data.lapp_context,
3126 [&conversion_data](BlendfileLinkAppendContext *lapp_context,
3127 BlendfileLinkAppendContextItem *item) -> bool {
3128 ID *item_new_id = BKE_blendfile_link_append_context_item_newid_get(lapp_context, item);
3129 if (!item_new_id || GS(item_new_id->name) != ID_GD_LEGACY) {
3130 return true;
3131 }
3132 GreasePencil **item_grease_pencil =
3134 reinterpret_cast<bGPdata *>(item_new_id));
3135 if (item_grease_pencil && *item_grease_pencil) {
3137 lapp_context, item, &(*item_grease_pencil)->id);
3138 }
3139 return true;
3140 },
3144 }
3145}
3146
3149{
3150 lmd->edge_types = lmd_legacy->edge_types;
3151 lmd->source_type = lmd_legacy->source_type;
3152 lmd->use_multiple_levels = lmd_legacy->use_multiple_levels;
3153 lmd->level_start = lmd_legacy->level_start;
3154 lmd->level_end = lmd_legacy->level_end;
3155 lmd->source_camera = lmd_legacy->source_camera;
3156 lmd->light_contour_object = lmd_legacy->light_contour_object;
3157 lmd->source_object = lmd_legacy->source_object;
3158 lmd->source_collection = lmd_legacy->source_collection;
3159 lmd->target_material = lmd_legacy->target_material;
3160 STRNCPY(lmd->target_layer, lmd_legacy->target_layer);
3162 STRNCPY(lmd->vgname, lmd_legacy->vgname);
3163 lmd->overscan = lmd_legacy->overscan;
3164 lmd->shadow_camera_fov = lmd_legacy->shadow_camera_fov;
3165 lmd->shadow_camera_size = lmd_legacy->shadow_camera_size;
3166 lmd->shadow_camera_near = lmd_legacy->shadow_camera_near;
3167 lmd->shadow_camera_far = lmd_legacy->shadow_camera_far;
3168 lmd->opacity = lmd_legacy->opacity;
3169 lmd->thickness = lmd_legacy->thickness;
3170 lmd->mask_switches = lmd_legacy->mask_switches;
3171 lmd->material_mask_bits = lmd_legacy->material_mask_bits;
3172 lmd->intersection_mask = lmd_legacy->intersection_mask;
3173 lmd->shadow_selection = lmd_legacy->shadow_selection;
3174 lmd->silhouette_selection = lmd_legacy->silhouette_selection;
3175 lmd->crease_threshold = lmd_legacy->crease_threshold;
3179 lmd->calculation_flags = lmd_legacy->calculation_flags;
3180 lmd->flags = lmd_legacy->flags;
3181 lmd->stroke_depth_offset = lmd_legacy->stroke_depth_offset;
3182 lmd->level_start_override = lmd_legacy->level_start_override;
3183 lmd->level_end_override = lmd_legacy->level_end_override;
3184 lmd->edge_types_override = lmd_legacy->edge_types_override;
3187 lmd->cache = lmd_legacy->cache;
3188 lmd->la_data_ptr = lmd_legacy->la_data_ptr;
3189}
3190
3193{
3194 lmd_legacy->edge_types = lmd->edge_types;
3195 lmd_legacy->source_type = lmd->source_type;
3196 lmd_legacy->use_multiple_levels = lmd->use_multiple_levels;
3197 lmd_legacy->level_start = lmd->level_start;
3198 lmd_legacy->level_end = lmd->level_end;
3199 lmd_legacy->source_camera = lmd->source_camera;
3200 lmd_legacy->light_contour_object = lmd->light_contour_object;
3201 lmd_legacy->source_object = lmd->source_object;
3202 lmd_legacy->source_collection = lmd->source_collection;
3203 lmd_legacy->target_material = lmd->target_material;
3205 STRNCPY(lmd_legacy->vgname, lmd->vgname);
3206 lmd_legacy->overscan = lmd->overscan;
3207 lmd_legacy->shadow_camera_fov = lmd->shadow_camera_fov;
3208 lmd_legacy->shadow_camera_size = lmd->shadow_camera_size;
3209 lmd_legacy->shadow_camera_near = lmd->shadow_camera_near;
3210 lmd_legacy->shadow_camera_far = lmd->shadow_camera_far;
3211 lmd_legacy->opacity = lmd->opacity;
3212 lmd_legacy->thickness = lmd->thickness;
3213 lmd_legacy->mask_switches = lmd->mask_switches;
3214 lmd_legacy->material_mask_bits = lmd->material_mask_bits;
3215 lmd_legacy->intersection_mask = lmd->intersection_mask;
3216 lmd_legacy->shadow_selection = lmd->shadow_selection;
3217 lmd_legacy->silhouette_selection = lmd->silhouette_selection;
3218 lmd_legacy->crease_threshold = lmd->crease_threshold;
3222 lmd_legacy->calculation_flags = lmd->calculation_flags;
3223 lmd_legacy->flags = lmd->flags;
3224 lmd_legacy->stroke_depth_offset = lmd->stroke_depth_offset;
3225 lmd_legacy->level_start_override = lmd->level_start_override;
3226 lmd_legacy->level_end_override = lmd->level_end_override;
3227 lmd_legacy->edge_types_override = lmd->edge_types_override;
3230 lmd_legacy->cache = lmd->cache;
3231 lmd_legacy->la_data_ptr = lmd->la_data_ptr;
3232}
3233
3234} // namespace blender::bke::greasepencil::convert
Functions and classes to work with Actions.
Functionality to iterate an Action in various ways.
Functions for backward compatibility with the legacy Action API.
Blender kernel action and pose functionality.
AnimData * BKE_animdata_copy_in_lib(Main *bmain, std::optional< Library * > owner_library, AnimData *adt, int flag)
Definition anim_data.cc:364
AnimData * BKE_animdata_ensure_id(ID *id)
Definition anim_data.cc:103
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:89
void BKE_curvemapping_free(CurveMapping *cumap)
Low-level operations for curves.
support for deformation groups and hooks.
void BKE_defgroup_copy_list(ListBase *outbase, const ListBase *inbase)
Definition deform.cc:76
void BKE_fcurve_handles_recalc(FCurve *fcu)
void BKE_gpencil_modifier_free_ex(struct GpencilModifierData *md, int flag)
Low-level operations for grease pencil.
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:722
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:861
IDPropertyUIData * IDP_ui_data_ensure(IDProperty *prop)
Definition idprop.cc:1739
void id_us_plus(ID *id)
Definition lib_id.cc:351
void * BKE_id_new_in_lib(Main *bmain, std::optional< Library * > owner_library, short type, const char *name)
Definition lib_id.cc:1464
void id_fake_user_set(ID *id)
Definition lib_id.cc:389
struct ID * BKE_id_copy_in_lib(Main *bmain, std::optional< Library * > owner_library, const ID *id, const ID *new_owner_id, ID **new_id_p, int flag)
Definition lib_id.cc:656
void id_us_plus_no_lib(ID *id)
Definition lib_id.cc:335
void id_us_min(ID *id)
Definition lib_id.cc:359
@ LIB_ID_COPY_DEFAULT
@ ID_REMAP_ALLOW_IDTYPE_MISMATCH
void BKE_libblock_remap_multiple(Main *bmain, blender::bke::id::IDRemapper &mappings, const int remap_flags)
Definition lib_remap.cc:701
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:500
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:494
General operations, lookup, etc. for materials.
void BKE_id_materials_copy(struct Main *bmain, struct ID *id_src, struct ID *id_dst)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md)
@ eModifierTypeFlag_RequiresOriginalData
void BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md)
ModifierData * BKE_modifier_new(int type)
void BKE_ntree_update_main_tree(Main *bmain, bNodeTree *ntree, NodeTreeUpdateExtraParams *params)
General operations, lookup, etc. for blender objects.
void BKE_object_free_derived_caches(Object *ob)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:370
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:251
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
void copy_m4_m4(float m1[4][4], const float m2[4][4])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define STRNCPY(dst, src)
Definition BLI_string.h:593
char * BLI_strdupn(const char *str, size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition string.c:29
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
int char char int int int int size_t BLI_strnlen(const char *str, size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition string.c:909
size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STRNCPY_UTF8(dst, src)
unsigned int uint
#define UNUSED_VARS_NDEBUG(...)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define STREQ(a, b)
external readfile function prototypes.
#define DATA_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:1044
@ ID_FLAG_FAKEUSER
Definition DNA_ID.h:720
@ ID_GD_LEGACY
@ ID_GP
struct bAction bAction
struct FCurve FCurve
struct NlaStrip NlaStrip
@ FCURVE_INT_VALUES
struct AnimData AnimData
struct NlaTrack NlaTrack
@ ARM_DEF_INVERT_VGROUP
eGp_Vertex_Mode
@ GPPAINT_MODE_STROKE
@ GPPAINT_MODE_FILL
@ GPPAINT_MODE_BOTH
eBezTriple_KeyframeType
@ CURVE_TYPE_BEZIER
@ CURVE_TYPE_POLY
#define MAX_NAME
Definition DNA_defs.h:50
@ GP_CURVE_NEEDS_STROKE_UPDATE
@ GP_LAYER_DISABLE_MASKS_IN_VIEWLAYER
@ GP_ONION_GHOST_NEXTCOL
@ GP_ONION_GHOST_PREVCOL
@ GP_DATA_AUTOLOCK_LAYERS
@ GP_OUTLINE_INVERT_MATERIAL
@ GP_OUTLINE_INVERT_LAYERPASS
@ GP_LENGTH_INVERT_MATERIAL
@ GP_LENGTH_INVERT_LAYERPASS
@ GP_TIME_SEG_MODE_PINGPONG
@ GP_SUBDIV_INVERT_MATERIAL
@ GP_SUBDIV_INVERT_LAYERPASS
@ GP_LATTICE_INVERT_LAYERPASS
@ GP_LATTICE_INVERT_MATERIAL
@ GP_BUILD_TRANSITION_SHRINK
@ GP_BUILD_TRANSITION_VANISH
@ GP_ENVELOPE_INVERT_LAYERPASS
@ GP_ENVELOPE_INVERT_MATERIAL
@ GP_SIMPLIFY_INVERT_MATERIAL
@ GP_SIMPLIFY_INVERT_LAYERPASS
@ GP_COLOR_INVERT_LAYERPASS
@ GP_SMOOTH_INVERT_LAYERPASS
@ GP_SMOOTH_INVERT_MATERIAL
@ GP_OPACITY_INVERT_MATERIAL
@ GP_OPACITY_INVERT_LAYERPASS
@ GP_THICK_INVERT_LAYERPASS
@ GP_MULTIPLY_ENABLE_FADING
@ GP_BUILD_TIMEMODE_PERCENTAGE
@ GP_BUILD_TIMEMODE_DRAWSPEED
@ eGPHook_Falloff_InvSquare
@ GP_ARRAY_UNIFORM_RANDOM_SCALE
@ GP_ARRAY_INVERT_LAYERPASS
@ GP_OFFSET_INVERT_MATERIAL
@ GP_OFFSET_UNIFORM_RANDOM_SCALE
@ GP_OFFSET_INVERT_LAYERPASS
@ GP_MIRROR_INVERT_MATERIAL
@ GP_MIRROR_INVERT_LAYERPASS
@ GP_SHRINKWRAP_INVERT_VGROUP
@ GP_SHRINKWRAP_INVERT_LAYERPASS
@ GP_SHRINKWRAP_INVERT_MATERIAL
@ eGpencilModifierType_Dash
@ eGpencilModifierType_Array
@ eGpencilModifierType_Noise
@ eGpencilModifierType_Mirror
@ eGpencilModifierType_Color
@ eGpencilModifierType_Multiply
@ eGpencilModifierType_Texture
@ eGpencilModifierType_Subdiv
@ eGpencilModifierType_Length
@ eGpencilModifierType_Lattice
@ eGpencilModifierType_Opacity
@ eGpencilModifierType_Hook
@ eGpencilModifierType_Simplify
@ eGpencilModifierType_Shrinkwrap
@ eGpencilModifierType_WeightProximity
@ eGpencilModifierType_Armature
@ eGpencilModifierType_WeightAngle
@ eGpencilModifierType_Lineart
@ eGpencilModifierType_None
@ eGpencilModifierType_Smooth
@ eGpencilModifierType_Tint
@ eGpencilModifierType_Outline
@ eGpencilModifierType_Envelope
@ eGpencilModifierType_Time
@ eGpencilModifierType_Thick
@ eGpencilModifierType_Build
@ eGpencilModifierType_Offset
@ GP_NOISE_INVERT_LAYERPASS
@ GP_LAYER_TREE_NODE_MUTE
@ GP_LAYER_TREE_NODE_HIDE_ONION_SKINNING
@ GP_LAYER_TREE_NODE_USE_LIGHTS
@ GP_LAYER_TREE_NODE_HIDE_MASKS
@ GP_LAYER_TREE_NODE_DISABLE_MASKS_IN_VIEWLAYER
@ GREASE_PENCIL_AUTOLOCK_LAYERS
@ GREASE_PENCIL_ANIM_CHANNEL_EXPANDED
@ GREASE_PENCIL_STROKE_ORDER_3D
@ GP_ONION_SKINNING_USE_FADE
@ GP_ONION_SKINNING_SHOW_LOOP
@ GP_ONION_SKINNING_USE_CUSTOM_COLORS
#define GREASE_PENCIL_ONION_SKINNING_FILTER_ALL
struct ListBase ListBase
@ eModifierFlag_OverrideLibrary_Local
@ eModifierFlag_Active
@ MOD_GREASE_PENCIL_MULTIPLY_ENABLE_FADING
@ MOD_GREASE_PENCIL_SMOOTH_MOD_LOCATION
@ MOD_GREASE_PENCIL_SMOOTH_MOD_STRENGTH
@ MOD_GREASE_PENCIL_SMOOTH_KEEP_SHAPE
@ MOD_GREASE_PENCIL_SMOOTH_MOD_UV
@ MOD_GREASE_PENCIL_SMOOTH_MOD_THICKNESS
@ GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP
@ GREASE_PENCIL_INFLUENCE_USE_MATERIAL_PASS_FILTER
@ GREASE_PENCIL_INFLUENCE_USE_LAYER_PASS_FILTER
@ GREASE_PENCIL_INFLUENCE_INVERT_LAYER_FILTER
@ GREASE_PENCIL_INFLUENCE_USE_CUSTOM_CURVE
@ GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_PASS_FILTER
@ GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_FILTER
@ GREASE_PENCIL_INFLUENCE_INVERT_LAYER_PASS_FILTER
@ MOD_GREASE_PENCIL_WEIGHT_ANGLE_SPACE_WORLD
@ MOD_GREASE_PENCIL_WEIGHT_ANGLE_SPACE_LOCAL
@ MOD_GREASE_PENCIL_HOOK_UNIFORM_SPACE
@ MOD_GREASE_PENCIL_OFFSET_UNIFORM_RANDOM_SCALE
@ MOD_GREASE_PENCIL_MIRROR_AXIS_Z
@ MOD_GREASE_PENCIL_MIRROR_AXIS_X
@ MOD_GREASE_PENCIL_MIRROR_AXIS_Y
@ MOD_GREASE_PENCIL_WEIGHT_ANGLE_MULTIPLY_DATA
@ MOD_GREASE_PENCIL_WEIGHT_ANGLE_INVERT_OUTPUT
@ MOD_GREASE_PENCIL_OPACITY_USE_WEIGHT_AS_FACTOR
@ MOD_GREASE_PENCIL_OPACITY_USE_UNIFORM_OPACITY
@ MOD_GREASE_PENCIL_ARRAY_USE_OFFSET
@ MOD_GREASE_PENCIL_ARRAY_USE_RELATIVE
@ MOD_GREASE_PENCIL_ARRAY_USE_OB_OFFSET
@ MOD_GREASE_PENCIL_ARRAY_UNIFORM_RANDOM_SCALE
@ MOD_GREASE_PENCIL_BUILD_TIMEMODE_PERCENTAGE
@ MOD_GREASE_PENCIL_BUILD_TIMEMODE_DRAWSPEED
@ MOD_GREASE_PENCIL_BUILD_TIMEMODE_FRAMES
@ MOD_GREASE_PENCIL_BUILD_TIMEALIGN_START
@ MOD_GREASE_PENCIL_BUILD_TIMEALIGN_END
@ MOD_GREASE_PENCIL_THICK_WEIGHT_FACTOR
@ MOD_GREASE_PENCIL_THICK_NORMALIZE
@ MOD_GREASE_PENCIL_SIMPLIFY_FIXED
@ MOD_GREASE_PENCIL_SIMPLIFY_MERGE
@ MOD_GREASE_PENCIL_SIMPLIFY_ADAPTIVE
@ MOD_GREASE_PENCIL_SIMPLIFY_SAMPLE
@ MOD_GREASE_PENCIL_TIME_MODE_FIX
@ MOD_GREASE_PENCIL_TIME_MODE_CHAIN
@ MOD_GREASE_PENCIL_TIME_MODE_PINGPONG
@ MOD_GREASE_PENCIL_TIME_MODE_NORMAL
@ MOD_GREASE_PENCIL_TIME_MODE_REVERSE
@ MOD_GREASE_PENCIL_SUBDIV_CATMULL
@ MOD_GREASE_PENCIL_SUBDIV_SIMPLE
@ MOD_GREASE_PENCIL_COLOR_FILL
@ MOD_GREASE_PENCIL_COLOR_STROKE
@ MOD_GREASE_PENCIL_COLOR_BOTH
@ MOD_GREASE_PENCIL_COLOR_HARDNESS
@ MOD_GREASE_PENCIL_BUILD_MODE_SEQUENTIAL
@ MOD_GREASE_PENCIL_BUILD_MODE_ADDITIVE
@ MOD_GREASE_PENCIL_BUILD_MODE_CONCURRENT
@ MOD_GREASE_PENCIL_TIME_KEEP_LOOP
@ MOD_GREASE_PENCIL_TIME_CUSTOM_RANGE
@ MOD_GREASE_PENCIL_BUILD_RESTRICT_TIME
@ MOD_GREASE_PENCIL_BUILD_USE_FADING
@ MOD_GREASE_PENCIL_DASH_USE_CYCLIC
@ MOD_GREASE_PENCIL_TINT_UNIFORM
@ MOD_GREASE_PENCIL_TINT_GRADIENT
@ MOD_GREASE_PENCIL_OUTLINE_KEEP_SHAPE
@ MOD_GREASE_PENCIL_TINT_USE_WEIGHT_AS_FACTOR
@ eModifierType_GreasePencilSmooth
@ eModifierType_GreasePencilWeightProximity
@ eModifierType_GreasePencilMirror
@ eModifierType_GreasePencilOffset
@ eModifierType_GreasePencilThickness
@ eModifierType_GreasePencilEnvelope
@ eModifierType_GreasePencilArmature
@ eModifierType_GreasePencilSubdiv
@ eModifierType_GreasePencilTint
@ eModifierType_GreasePencilNoise
@ eModifierType_GreasePencilMultiply
@ eModifierType_GreasePencilBuild
@ eModifierType_GreasePencilTime
@ eModifierType_GreasePencilTexture
@ eModifierType_GreasePencilSimplify
@ eModifierType_GreasePencilColor
@ eModifierType_GreasePencilDash
@ eModifierType_GreasePencilLineart
@ eModifierType_Nodes
@ eModifierType_GreasePencilOutline
@ eModifierType_GreasePencilWeightAngle
@ eModifierType_GreasePencilOpacity
@ eModifierType_GreasePencilLength
@ eModifierType_GreasePencilShrinkwrap
@ eModifierType_GreasePencilLattice
@ eModifierType_GreasePencilHook
@ eModifierType_GreasePencilArray
@ MOD_GREASE_PENCIL_HOOK_Falloff_None
@ MOD_GREASE_PENCIL_HOOK_Falloff_Root
@ MOD_GREASE_PENCIL_HOOK_Falloff_InvSquare
@ MOD_GREASE_PENCIL_HOOK_Falloff_Const
@ MOD_GREASE_PENCIL_HOOK_Falloff_Linear
@ MOD_GREASE_PENCIL_HOOK_Falloff_Sphere
@ MOD_GREASE_PENCIL_HOOK_Falloff_Smooth
@ MOD_GREASE_PENCIL_HOOK_Falloff_Curve
@ MOD_GREASE_PENCIL_HOOK_Falloff_Sharp
@ MOD_GREASE_PENCIL_TEXTURE_STROKE_AND_FILL
@ MOD_GREASE_PENCIL_TEXTURE_FILL
@ MOD_GREASE_PENCIL_TEXTURE_STROKE
@ MOD_GREASE_PENCIL_WEIGHT_PROXIMITY_INVERT_OUTPUT
@ MOD_GREASE_PENCIL_WEIGHT_PROXIMITY_MULTIPLY_DATA
@ MOD_GREASE_PENCIL_ENVELOPE_SEGMENTS
@ MOD_GREASE_PENCIL_ENVELOPE_FILLS
@ MOD_GREASE_PENCIL_ENVELOPE_DEFORM
@ MOD_GREASE_PENCIL_BUILD_TRANSITION_VANISH
@ MOD_GREASE_PENCIL_BUILD_TRANSITION_SHRINK
@ MOD_GREASE_PENCIL_BUILD_TRANSITION_GROW
@ MOD_GREASE_PENCIL_TEXTURE_FIT_STROKE
@ MOD_GREASE_PENCIL_TEXTURE_CONSTANT_LENGTH
@ MOD_GREASE_PENCIL_OFFSET_STROKE
@ MOD_GREASE_PENCIL_OFFSET_MATERIAL
@ MOD_GREASE_PENCIL_OFFSET_LAYER
@ MOD_GREASE_PENCIL_OFFSET_RANDOM
@ MOD_GREASE_PENCIL_TIME_SEG_MODE_NORMAL
@ MOD_GREASE_PENCIL_TIME_SEG_MODE_REVERSE
@ MOD_GREASE_PENCIL_TIME_SEG_MODE_PINGPONG
@ NODE_MATH_ADD
@ GEO_NODE_ASSET_MODIFIER
@ SOCK_OUT
@ SOCK_IN
@ OB_GREASE_PENCIL
@ OB_GPENCIL_LEGACY
eSpace_Type
@ SPACE_TEXT
@ SPACE_CLIP
@ SPACE_ACTION
@ SPACE_CONSOLE
@ SPACE_OUTLINER
@ SPACE_STATUSBAR
@ SPACE_TOPBAR
@ SPACE_NODE
@ SPACE_SPREADSHEET
@ SPACE_USERPREF
@ SPACE_FILE
@ SPACE_PROPERTIES
@ SPACE_NLA
@ SPACE_SEQ
@ SPACE_EMPTY
@ SPACE_SCRIPT
@ SPACE_IMAGE
@ SPACE_GRAPH
@ SPACE_VIEW3D
@ SPACE_INFO
#define USER_EXPERIMENTAL_TEST(userdef, member)
#define MEM_SAFE_FREE(v)
def_group
@ PROP_DISTANCE
Definition RNA_types.hh:159
@ PROP_TRANSLATION
Definition RNA_types.hh:164
#define U
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
btMatrix3x3 transpose() const
Return the transpose of the matrix.
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
VecBase< float, 3 > float3
const Value * lookup_ptr(const Key &key) const
Definition BLI_map.hh:484
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:271
Value lookup_default(const Key &key, const Value &default_value) const
Definition BLI_map.hh:531
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:241
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:388
bool is_empty() const
Definition BLI_array.hh:253
constexpr int64_t size() const
bool add_overwrite(const Key &key, const Value &value)
Definition BLI_map.hh:301
Value & lookup_or_add(const Key &key, const Value &value)
Definition BLI_map.hh:551
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
Definition BLI_span.hh:574
bool contains(const Key &key) const
Definition BLI_set.hh:291
bool add(const Key &key)
Definition BLI_set.hh:248
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
constexpr StringRef substr(int64_t start, int64_t size) const
constexpr bool startswith(StringRef prefix) const
constexpr const char * data() const
void append(const T &value)
bool is_empty() const
Slot & slot_add_for_id(const ID &animated_id)
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
MutableSpan< float > opacities_for_write()
MutableSpan< float > radii_for_write()
bke::CurvesGeometry & strokes_for_write()
MutableSpan< ColorGeometry4f > fill_colors_for_write()
MutableSpan< ColorGeometry4f > vertex_colors_for_write()
void set_parent_bone_name(const char *new_name)
void set_view_layer_name(const char *new_name)
const GreasePencilFrame * frame_at(const int frame_number) const
AnimDataConvertor(ConversionData &conversion_data, ID &id_dst, ID &id_src, const Array< AnimDataFCurveConvertor > fcurve_convertors={})
AnimDataConvertor(ConversionData &conversion_data, ID &id_src, const Array< AnimDataFCurveConvertor > fcurve_convertors={})
void add(ID *old_id, ID *new_id)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define GS(x)
Definition iris.cc:202
static const char * modifier_name[LS_MODIFIER_NUM]
Definition linestyle.cc:680
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
ccl_device_inline float cross(const float2 a, const float2 b)
ccl_device_inline float3 cos(float3 v)
ccl_device_inline float4 mask(const int4 mask, const float4 a)
static void add(blender::Map< std::string, std::string > &messages, Message &msg)
Definition msgfmt.cc:227
void action_fcurve_move(Action &action_dst, slot_handle_t action_slot_dst, Action &action_src, FCurve &fcurve)
Action & action_add(Main &bmain, StringRefNull name)
void foreach_fcurve_in_action(Action &action, FunctionRef< void(FCurve &fcurve)> callback)
bool assign_tmpaction(bAction *action, OwnedAnimData owned_adt)
decltype(::ActionSlot::handle) slot_handle_t
bool assign_action(bAction *action, ID &animated_id)
static void legacy_object_modifier_subdiv(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_mirror(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static bNodeTree * offset_radius_node_tree_add(ConversionData &conversion_data, Library *library)
static void legacy_object_modifier_time(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_color(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static ModifierData & legacy_object_modifier_common(ConversionData &conversion_data, Object &object, const ModifierType type, GpencilModifierData &legacy_md)
static void legacy_object_modifier_offset(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_opacity(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_lineart(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_armature(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_shrinkwrap(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void thickness_factor_to_modifier(ConversionData &conversion_data, bGPdata &src_object_data, Object &dst_object)
static void legacy_object_modifier_envelope(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_outline(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_thickness(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_gpencil_to_grease_pencil(ConversionData &conversion_data, GreasePencil &grease_pencil, bGPdata &gpd)
static void legacy_object_modifier_weight_angle(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_tint(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
void lineart_unwrap_v3(LineartGpencilModifierData *lmd_legacy, const GreasePencilLineartModifierData *lmd)
static void legacy_object_modifier_noise(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
void legacy_main(Main &bmain, BlendfileLinkAppendContext *lapp_context, BlendFileReadReport &reports)
static blender::float4x2 get_legacy_texture_matrix(bGPDstroke *gps)
static void legacy_object_thickness_modifier_thickness_anim(ConversionData &conversion_data, Object &object)
static void layer_adjustments_to_modifiers(ConversionData &conversion_data, bGPdata &src_object_data, Object &dst_object)
static void legacy_object_modifier_texture(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifiers(ConversionData &conversion_data, Object &object)
static Drawing legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf, const ListBase &vertex_group_names)
static float3x2 get_legacy_stroke_to_texture_matrix(const float2 uv_translation, const float uv_rotation, const float2 uv_scale)
static void legacy_object_modifier_dash(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_build(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_array(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_multiply(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_smooth(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void find_used_vertex_groups(const bGPDframe &gpf, const ListBase &vertex_group_names, const int num_vertex_groups, ListBase &r_vertex_group_names, Array< int > &r_indices)
static blender::float4x2 get_legacy_layer_to_stroke_matrix(bGPDstroke *gps)
void lineart_wrap_v3(const LineartGpencilModifierData *lmd_legacy, GreasePencilLineartModifierData *lmd)
static void legacy_object_modifier_lattice(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_weight_proximity(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_influence(GreasePencilModifierInfluenceData &influence, StringRef layername, const int layer_pass, const bool invert_layer, const bool invert_layer_pass, Material **material, const int material_pass, const bool invert_material, const bool invert_material_pass, StringRef vertex_group_name, const bool invert_vertex_group, CurveMapping **custom_curve, const bool use_custom_curve)
static void legacy_object_modifier_hook(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_gpencil_object(ConversionData &conversion_data, Object &object)
static void legacy_object_modifier_length(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
static void legacy_object_modifier_simplify(ConversionData &conversion_data, Object &object, GpencilModifierData &legacy_md)
constexpr float LEGACY_RADIUS_CONVERSION_FACTOR
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_INT, set its name and value.
std::unique_ptr< IDProperty, IDPropertyDeleter > create_group(StringRefNull prop_name, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_GROUP.
bNodeTree * node_tree_add_in_lib(Main *bmain, Library *owner_library, const char *name, const char *idname)
Definition node.cc:3231
bNodeLink * node_add_link(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
Definition node.cc:2912
bNode * node_add_node(const bContext *C, bNodeTree *ntree, const char *idname)
Definition node.cc:2617
bool node_set_selected(bNode *node, bool select)
Definition node.cc:3863
bNodeTree * node_tree_from_id(ID *id)
Definition node.cc:3732
bNodeSocket * node_find_socket(bNode *node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:1829
T safe_rcp(const T &a)
T safe_divide(const T &a, const T &b)
T average(const VecBase< T, Size > &a)
MatT from_scale(const VecBase< typename MatT::base_type, ScaleDim > &scale)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:95
MatBase< float, 2, 2 > float2x2
MatBase< float, 2, 4 > float2x4
VecBase< float, 4 > float4
VecBase< float, 2 > float2
MatBase< float, 4, 2 > float4x2
MatBase< float, 3, 2 > float3x2
MatBase< float, 4, 3 > float4x3
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:337
VecBase< float, 3 > float3
GPU_SHADER_INTERFACE_INFO(overlay_edit_curve_handle_iface, "vert").flat(Type pos vertex_in(1, Type::UINT, "data") .vertex_out(overlay_edit_curve_handle_iface) .geometry_layout(PrimitiveIn Frequency::GEOMETRY storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY) .push_constant(Type Frequency::GEOMETRY selection[]
#define FLT_MAX
Definition stdcycles.h:14
unsigned int uint32_t
Definition stdint.h:80
__int64 int64_t
Definition stdint.h:89
signed char int8_t
Definition stdint.h:75
bAction * action
bAction * tmpact
ListBase drivers
ListBase nla_tracks
float vec[3][3]
char * rna_path
FPoint * fpt
BezTriple * bezt
unsigned int totvert
float vec[2]
GreasePencilLayerTreeNode base
GreasePencilModifierInfluenceData influence
GreasePencilOnionSkinningSettings onion_skinning_settings
struct AnimData * adt
Definition DNA_ID.h:413
struct Library * lib
Definition DNA_ID.h:419
IDProperty * properties
Definition DNA_ID.h:456
char name[66]
Definition DNA_ID.h:425
struct MDeformWeight * dw
ListBase scenes
Definition BKE_main.hh:210
ListBase movieclips
Definition BKE_main.hh:242
ListBase nodetrees
Definition BKE_main.hh:234
ListBase screens
Definition BKE_main.hh:225
ListBase gpencils
Definition BKE_main.hh:240
ListBase objects
Definition BKE_main.hh:212
struct ModifierData * next
ModifierTypeFlag flags
ListBase strips
bAction * act
struct Object * parent
struct bGPdata * gpd
struct bGPdata * gpd
struct bGPdata * gpd
ListBase vertex_group_names
void * default_value
struct GeometryNodeAssetTraits * geometry_node_asset_traits
bNodeTreeInterface tree_interface
ListBase nodes
float locy
float locx
AnimDataFCurveConvertor(const char *relative_rna_path_src, const char *relative_rna_path_dst, blender::FunctionRef< FCurveConvertCB > convert_cb={nullptr})
ConversionData(Main &bmain, BlendfileLinkAppendContext *lapp_context)