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
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/* -------------------------------------------------------------------- */
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 }
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,
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,
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,
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,
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,
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,
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 &all_names,
642 ListBase &r_vertex_group_names,
643 Array<int> &r_indices)
644{
645 const int num_vertex_groups = BLI_listbase_count(&all_names);
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 >= dvert.totweight) {
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, &all_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. */
827 CurvesGeometry &curves = drawing.strokes_for_write();
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 find_used_vertex_groups(gpf, vertex_group_names, stroke_vertex_group_names, stroke_def_nr_map);
847 BLI_assert(BLI_listbase_is_empty(&curves.vertex_group_names));
848 curves.vertex_group_names = stroke_vertex_group_names;
849 const bool use_dverts = !BLI_listbase_is_empty(&curves.vertex_group_names);
850
851 /* Copy vertex weights and map the vertex group indices. */
852 auto copy_dvert = [&](const MDeformVert &src_dvert, MDeformVert &dst_dvert) {
853 dst_dvert = src_dvert;
854 dst_dvert.dw = static_cast<MDeformWeight *>(MEM_dupallocN(src_dvert.dw));
855 const MutableSpan<MDeformWeight> vertex_weights = {dst_dvert.dw, dst_dvert.totweight};
856 for (MDeformWeight &weight : vertex_weights) {
857 if (weight.def_nr >= dst_dvert.totweight) {
858 /* Ignore invalid deform weight group indices. */
859 continue;
860 }
861 /* Map def_nr to the reduced vertex group list. */
862 weight.def_nr = stroke_def_nr_map[weight.def_nr];
863 }
864 };
865
866 /* Point Attributes. */
867 MutableSpan<float3> positions = curves.positions_for_write();
868 MutableSpan<float3> handle_positions_left = has_bezier_stroke ?
869 curves.handle_positions_left_for_write() :
871 MutableSpan<float3> handle_positions_right = has_bezier_stroke ?
872 curves.handle_positions_right_for_write() :
874 MutableSpan<float> radii = drawing.radii_for_write();
875 MutableSpan<float> opacities = drawing.opacities_for_write();
876 SpanAttributeWriter<float> delta_times = attributes.lookup_or_add_for_write_span<float>(
877 "delta_time", AttrDomain::Point);
878 SpanAttributeWriter<float> rotations = attributes.lookup_or_add_for_write_span<float>(
879 "rotation", AttrDomain::Point);
881 SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_span<bool>(
882 ".selection", AttrDomain::Point);
883 MutableSpan<MDeformVert> dverts = use_dverts ? curves.wrap().deform_verts_for_write() :
885
886 /* Curve Attributes. */
887 SpanAttributeWriter<bool> stroke_cyclic = attributes.lookup_or_add_for_write_span<bool>(
888 "cyclic", AttrDomain::Curve);
889 SpanAttributeWriter<float> stroke_init_times = attributes.lookup_or_add_for_write_span<float>(
890 "init_time", AttrDomain::Curve);
891 SpanAttributeWriter<int8_t> stroke_start_caps = attributes.lookup_or_add_for_write_span<int8_t>(
892 "start_cap", AttrDomain::Curve);
893 SpanAttributeWriter<int8_t> stroke_end_caps = attributes.lookup_or_add_for_write_span<int8_t>(
894 "end_cap", AttrDomain::Curve);
895 SpanAttributeWriter<float> stroke_softness = attributes.lookup_or_add_for_write_span<float>(
896 "softness", AttrDomain::Curve);
897 SpanAttributeWriter<float> stroke_point_aspect_ratios =
898 attributes.lookup_or_add_for_write_span<float>("aspect_ratio", AttrDomain::Curve);
899 MutableSpan<ColorGeometry4f> stroke_fill_colors = drawing.fill_colors_for_write();
900 SpanAttributeWriter<int> stroke_materials = attributes.lookup_or_add_for_write_span<int>(
901 "material_index", AttrDomain::Curve);
902
903 Array<float4x2> legacy_texture_matrices(num_strokes);
904
905 int stroke_i = 0;
906 LISTBASE_FOREACH (bGPDstroke *, gps, &gpf.strokes) {
907 /* In GPv2 strokes with 0 points could technically be represented. In `CurvesGeometry` this is
908 * not the case and would be a bug. So we explicitly make sure to skip over strokes with no
909 * points. */
910 if (gps->totpoints == 0 ||
911 (gps->editcurve != nullptr && gps->editcurve->tot_curve_points == 0))
912 {
913 continue;
914 }
915
916 stroke_cyclic.span[stroke_i] = (gps->flag & GP_STROKE_CYCLIC) != 0;
917 /* Truncating time in ms to uint32 then we don't lose precision in lower bits. */
918 stroke_init_times.span[stroke_i] = float(uint32_t(gps->inittime * double(1e3))) / float(1e3);
919 stroke_start_caps.span[stroke_i] = int8_t(gps->caps[0]);
920 stroke_end_caps.span[stroke_i] = int8_t(gps->caps[1]);
921 stroke_softness.span[stroke_i] = 1.0f - gps->hardness;
922 stroke_point_aspect_ratios.span[stroke_i] = gps->aspect_ratio[0] /
923 max_ff(gps->aspect_ratio[1], 1e-8);
924 stroke_fill_colors[stroke_i] = ColorGeometry4f(gps->vert_color_fill);
925 stroke_materials.span[stroke_i] = gps->mat_nr;
926
927 const IndexRange points = points_by_curve[stroke_i];
928
929 const float stroke_thickness = float(gps->thickness) * LEGACY_RADIUS_CONVERSION_FACTOR;
930 MutableSpan<float3> dst_positions = positions.slice(points);
931 MutableSpan<float3> dst_handle_positions_left = has_bezier_stroke ?
932 handle_positions_left.slice(points) :
934 MutableSpan<float3> dst_handle_positions_right = has_bezier_stroke ?
935 handle_positions_right.slice(points) :
937 MutableSpan<float> dst_radii = radii.slice(points);
938 MutableSpan<float> dst_opacities = opacities.slice(points);
939 MutableSpan<float> dst_deltatimes = delta_times.span.slice(points);
940 MutableSpan<float> dst_rotations = rotations.span.slice(points);
941 MutableSpan<ColorGeometry4f> dst_vertex_colors = vertex_colors.slice(points);
942 MutableSpan<bool> dst_selection = selection.span.slice(points);
943 MutableSpan<MDeformVert> dst_dverts = use_dverts ? dverts.slice(points) :
945
946 if (curve_types[stroke_i] == CURVE_TYPE_POLY) {
947 BLI_assert(points.size() == gps->totpoints);
948 const Span<bGPDspoint> src_points{gps->points, gps->totpoints};
949 threading::parallel_for(src_points.index_range(), 4096, [&](const IndexRange range) {
950 for (const int point_i : range) {
951 const bGPDspoint &pt = src_points[point_i];
952 dst_positions[point_i] = float3(pt.x, pt.y, pt.z);
953 dst_radii[point_i] = stroke_thickness * pt.pressure;
954 dst_opacities[point_i] = pt.strength;
955 dst_deltatimes[point_i] = pt.time;
956 dst_rotations[point_i] = pt.uv_rot;
957 dst_vertex_colors[point_i] = ColorGeometry4f(pt.vert_color);
958 dst_selection[point_i] = (pt.flag & GP_SPOINT_SELECT) != 0;
959 if (use_dverts && gps->dvert) {
960 copy_dvert(gps->dvert[point_i], dst_dverts[point_i]);
961 }
962 }
963 });
964 }
965 else if (curve_types[stroke_i] == CURVE_TYPE_BEZIER) {
966 BLI_assert(gps->editcurve != nullptr);
967 BLI_assert(points.size() == gps->editcurve->tot_curve_points);
968 Span<bGPDcurve_point> src_curve_points{gps->editcurve->curve_points,
969 gps->editcurve->tot_curve_points};
970
971 threading::parallel_for(src_curve_points.index_range(), 4096, [&](const IndexRange range) {
972 for (const int point_i : range) {
973 const bGPDcurve_point &cpt = src_curve_points[point_i];
974 dst_positions[point_i] = float3(cpt.bezt.vec[1]);
975 dst_handle_positions_left[point_i] = float3(cpt.bezt.vec[0]);
976 dst_handle_positions_right[point_i] = float3(cpt.bezt.vec[2]);
977 dst_radii[point_i] = stroke_thickness * cpt.pressure;
978 dst_opacities[point_i] = cpt.strength;
979 dst_rotations[point_i] = cpt.uv_rot;
980 dst_vertex_colors[point_i] = ColorGeometry4f(cpt.vert_color);
981 dst_selection[point_i] = (cpt.flag & GP_CURVE_POINT_SELECT) != 0;
982 if (use_dverts && gps->dvert) {
983 copy_dvert(gps->dvert[point_i], dst_dverts[point_i]);
984 }
985 }
986 });
987 }
988 else {
989 /* Unknown curve type. */
991 }
992
993 const float4x2 legacy_texture_matrix = get_legacy_texture_matrix(gps);
994 legacy_texture_matrices[stroke_i] = legacy_texture_matrix;
995
996 stroke_i++;
997 }
998
999 /* Ensure that the normals are up to date. */
1000 curves.tag_normals_changed();
1001 drawing.set_texture_matrices(legacy_texture_matrices.as_span(), curves.curves_range());
1002
1003 delta_times.finish();
1004 rotations.finish();
1005 selection.finish();
1006
1007 stroke_cyclic.finish();
1008 stroke_init_times.finish();
1009 stroke_start_caps.finish();
1010 stroke_end_caps.finish();
1011 stroke_softness.finish();
1012 stroke_point_aspect_ratios.finish();
1013 stroke_materials.finish();
1014
1015 return drawing;
1016}
1017
1019 GreasePencil &grease_pencil,
1020 bGPdata &gpd)
1021{
1022 using namespace blender::bke::greasepencil;
1023
1024 if (gpd.flag & ID_FLAG_FAKEUSER) {
1025 id_fake_user_set(&grease_pencil.id);
1026 }
1027
1028 BLI_assert(!grease_pencil.id.properties);
1029 if (gpd.id.properties) {
1030 grease_pencil.id.properties = IDP_CopyProperty(gpd.id.properties);
1031 }
1032
1035 grease_pencil.flag, (gpd.flag & GP_DATA_EXPAND) != 0, GREASE_PENCIL_ANIM_CHANNEL_EXPANDED);
1036 SET_FLAG_FROM_TEST(grease_pencil.flag,
1037 (gpd.flag & GP_DATA_AUTOLOCK_LAYERS) != 0,
1041
1042 int layer_idx = 0;
1043 LISTBASE_FOREACH_INDEX (bGPDlayer *, gpl, &gpd.layers, layer_idx) {
1044 /* Create a new layer. */
1045 Layer &new_layer = grease_pencil.add_layer(
1046 StringRefNull(gpl->info, BLI_strnlen(gpl->info, 128)));
1047
1048 /* Flags. */
1049 new_layer.set_visible((gpl->flag & GP_LAYER_HIDE) == 0);
1050 new_layer.set_locked((gpl->flag & GP_LAYER_LOCKED) != 0);
1051 new_layer.set_selected((gpl->flag & GP_LAYER_SELECT) != 0);
1053 new_layer.base.flag, (gpl->flag & GP_LAYER_FRAMELOCK) != 0, GP_LAYER_TREE_NODE_MUTE);
1054 SET_FLAG_FROM_TEST(new_layer.base.flag,
1055 (gpl->flag & GP_LAYER_USE_LIGHTS) != 0,
1057 SET_FLAG_FROM_TEST(new_layer.base.flag,
1058 (gpl->onion_flag & GP_LAYER_ONIONSKIN) == 0,
1061 new_layer.base.flag, (gpl->flag & GP_LAYER_USE_MASK) == 0, GP_LAYER_TREE_NODE_HIDE_MASKS);
1062
1063 new_layer.blend_mode = int8_t(gpl->blend_mode);
1064
1065 new_layer.parent = gpl->parent;
1066 new_layer.set_parent_bone_name(gpl->parsubstr);
1067 /* GPv2 parent inverse matrix is only valid when parent is set. */
1068 if (gpl->parent) {
1069 copy_m4_m4(new_layer.parentinv, gpl->inverse);
1070 }
1071
1072 copy_v3_v3(new_layer.translation, gpl->location);
1073 copy_v3_v3(new_layer.rotation, gpl->rotation);
1074 copy_v3_v3(new_layer.scale, gpl->scale);
1075
1076 new_layer.set_view_layer_name(gpl->viewlayername);
1077 SET_FLAG_FROM_TEST(new_layer.base.flag,
1078 (gpl->flag & GP_LAYER_DISABLE_MASKS_IN_VIEWLAYER) != 0,
1080
1081 /* Convert the layer masks. */
1082 LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl->mask_layers) {
1083 LayerMask *new_mask = MEM_new<LayerMask>(__func__, mask->name);
1084 new_mask->flag = mask->flag;
1085 BLI_addtail(&new_layer.masks, new_mask);
1086 }
1087 new_layer.opacity = gpl->opacity;
1088
1089 LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1090 Drawing *dst_drawing = grease_pencil.insert_frame(
1091 new_layer, gpf->framenum, 0, eBezTriple_KeyframeType(gpf->key_type));
1092 if (dst_drawing == nullptr) {
1093 /* Might fail because GPv2 technically allowed overlapping keyframes on the same frame
1094 * (very unlikely to occur in real world files). In GPv3, keyframes always have to be on
1095 * different frames. In this case we can't create a keyframe and have to skip it. */
1096 continue;
1097 }
1098 /* Convert the frame to a drawing. */
1100
1101 /* This frame was just inserted above, so it should always exist. */
1102 GreasePencilFrame &new_frame = *new_layer.frame_at(gpf->framenum);
1103 SET_FLAG_FROM_TEST(new_frame.flag, (gpf->flag & GP_FRAME_SELECT), GP_FRAME_SELECTED);
1104 }
1105
1106 if ((gpl->flag & GP_LAYER_ACTIVE) != 0) {
1107 grease_pencil.set_active_layer(&new_layer);
1108 }
1109 }
1110
1111 /* Second loop, to write to layer attributes after all layers were created. */
1112 MutableAttributeAccessor layer_attributes = grease_pencil.attributes_for_write();
1113 /* NOTE: Layer Adjustments like the tint and the radius offsets are deliberately ignored here!
1114 * These are converted to modifiers at the bottom of the stack to keep visual compatibility with
1115 * GPv2. */
1116 SpanAttributeWriter<int> layer_passes = layer_attributes.lookup_or_add_for_write_span<int>(
1117 "pass_index", bke::AttrDomain::Layer);
1118
1119 layer_idx = 0;
1120 LISTBASE_FOREACH_INDEX (bGPDlayer *, gpl, &gpd.layers, layer_idx) {
1121 layer_passes.span[layer_idx] = int(gpl->pass_index);
1122 }
1123
1124 layer_passes.finish();
1125
1126 /* Copy vertex group names and settings. */
1129
1130 /* Convert the onion skinning settings. */
1132 settings.opacity = gpd.onion_factor;
1133 settings.mode = gpd.onion_mode;
1134 SET_FLAG_FROM_TEST(settings.flag,
1135 ((gpd.onion_flag & GP_ONION_GHOST_PREVCOL) != 0 &&
1136 (gpd.onion_flag & GP_ONION_GHOST_NEXTCOL) != 0),
1139 settings.flag, (gpd.onion_flag & GP_ONION_FADE) != 0, GP_ONION_SKINNING_USE_FADE);
1141 settings.flag, (gpd.onion_flag & GP_ONION_LOOP) != 0, GP_ONION_SKINNING_SHOW_LOOP);
1142 /* Convert keytype filter to a bit flag. */
1143 if (gpd.onion_keytype == -1) {
1145 }
1146 else {
1147 settings.filter = (1 << gpd.onion_keytype);
1148 }
1149 settings.num_frames_before = gpd.gstep;
1150 settings.num_frames_after = gpd.gstep_next;
1151 copy_v3_v3(settings.color_before, gpd.gcolor_prev);
1152 copy_v3_v3(settings.color_after, gpd.gcolor_next);
1153
1154 BKE_id_materials_copy(&conversion_data.bmain, &gpd.id, &grease_pencil.id);
1155
1156 /* Copy animation data from legacy GP data.
1157 *
1158 * Note that currently, Actions IDs are not duplicated. They may be needed ultimately, but for
1159 * the time being, assuming invalid fcurves/drivers are fine here. */
1160 if (AnimData *gpd_animdata = BKE_animdata_from_id(&gpd.id)) {
1161 grease_pencil.adt = BKE_animdata_copy_in_lib(
1162 &conversion_data.bmain, gpd.id.lib, gpd_animdata, LIB_ID_COPY_DEFAULT);
1163
1164 /* Some property was renamed between legacy GP layers and new GreasePencil ones. */
1165 AnimDataConvertor animdata_gpdata_transfer(
1166 conversion_data, grease_pencil.id, gpd.id, {{".location", ".translation"}});
1167 for (const Layer *layer_iter : grease_pencil.layers()) {
1168 /* Data comes from versioned GPv2 layers, which have a fixed max length. */
1169 char layer_name_esc[sizeof((bGPDlayer{}).info) * 2];
1170 BLI_str_escape(layer_name_esc, layer_iter->name().c_str(), sizeof(layer_name_esc));
1171 std::string layer_root_path = fmt::format("layers[\"{}\"]", layer_name_esc);
1172 animdata_gpdata_transfer.root_path_dst = layer_root_path;
1173 animdata_gpdata_transfer.root_path_src = layer_root_path;
1174 animdata_gpdata_transfer.fcurves_convert();
1175 }
1176 animdata_gpdata_transfer.fcurves_convert_finalize();
1177 }
1178}
1179
1180constexpr const char *OFFSET_RADIUS_NODETREE_NAME = "Offset Radius GPv3 Conversion";
1182{
1183 using namespace blender;
1184 /* NOTE: DO NOT translate this ID name, it is used to find a potentially already existing
1185 * node-tree. */
1186 bNodeTree *group = bke::node_tree_add_in_lib(
1187 &conversion_data.bmain, library, OFFSET_RADIUS_NODETREE_NAME, "GeometryNodeTree");
1188
1189 if (!group->geometry_node_asset_traits) {
1190 group->geometry_node_asset_traits = MEM_cnew<GeometryNodeAssetTraits>(__func__);
1191 }
1192 group->geometry_node_asset_traits->flag |= GEO_NODE_ASSET_MODIFIER;
1193
1194 group->tree_interface.add_socket(
1195 DATA_("Geometry"), "", "NodeSocketGeometry", NODE_INTERFACE_SOCKET_INPUT, nullptr);
1196 group->tree_interface.add_socket(
1197 DATA_("Geometry"), "", "NodeSocketGeometry", NODE_INTERFACE_SOCKET_OUTPUT, nullptr);
1198
1199 bNodeTreeInterfaceSocket *radius_offset = group->tree_interface.add_socket(
1200 DATA_("Offset"), "", "NodeSocketFloat", NODE_INTERFACE_SOCKET_INPUT, nullptr);
1201 auto &radius_offset_data = *static_cast<bNodeSocketValueFloat *>(radius_offset->socket_data);
1202 radius_offset_data.subtype = PROP_DISTANCE;
1203 radius_offset_data.min = -FLT_MAX;
1204 radius_offset_data.max = FLT_MAX;
1205
1206 group->tree_interface.add_socket(
1207 DATA_("Layer"), "", "NodeSocketString", NODE_INTERFACE_SOCKET_INPUT, nullptr);
1208
1209 bNode *group_output = bke::node_add_node(nullptr, group, "NodeGroupOutput");
1210 group_output->locx = 800;
1211 group_output->locy = 160;
1212 bNode *group_input = bke::node_add_node(nullptr, group, "NodeGroupInput");
1213 group_input->locx = 0;
1214 group_input->locy = 160;
1215
1216 bNode *set_curve_radius = bke::node_add_node(nullptr, group, "GeometryNodeSetCurveRadius");
1217 set_curve_radius->locx = 600;
1218 set_curve_radius->locy = 160;
1219 bNode *named_layer_selection = bke::node_add_node(
1220 nullptr, group, "GeometryNodeInputNamedLayerSelection");
1221 named_layer_selection->locx = 200;
1222 named_layer_selection->locy = 100;
1223 bNode *input_radius = bke::node_add_node(nullptr, group, "GeometryNodeInputRadius");
1224 input_radius->locx = 0;
1225 input_radius->locy = 0;
1226
1227 bNode *add = bke::node_add_node(nullptr, group, "ShaderNodeMath");
1228 add->custom1 = NODE_MATH_ADD;
1229 add->locx = 200;
1230 add->locy = 0;
1231
1232 bNode *clamp_radius = bke::node_add_node(nullptr, group, "ShaderNodeClamp");
1233 clamp_radius->locx = 400;
1234 clamp_radius->locy = 0;
1235 bNodeSocket *sock_max = bke::node_find_socket(clamp_radius, SOCK_IN, "Max");
1236 static_cast<bNodeSocketValueFloat *>(sock_max->default_value)->value = FLT_MAX;
1237
1238 bke::node_add_link(group,
1239 group_input,
1240 bke::node_find_socket(group_input, SOCK_OUT, "Socket_0"),
1241 set_curve_radius,
1242 bke::node_find_socket(set_curve_radius, SOCK_IN, "Curve"));
1243 bke::node_add_link(group,
1244 set_curve_radius,
1245 bke::node_find_socket(set_curve_radius, SOCK_OUT, "Curve"),
1246 group_output,
1247 bke::node_find_socket(group_output, SOCK_IN, "Socket_1"));
1248
1249 bke::node_add_link(group,
1250 group_input,
1251 bke::node_find_socket(group_input, SOCK_OUT, "Socket_3"),
1252 named_layer_selection,
1253 bke::node_find_socket(named_layer_selection, SOCK_IN, "Name"));
1254 bke::node_add_link(group,
1255 named_layer_selection,
1256 bke::node_find_socket(named_layer_selection, SOCK_OUT, "Selection"),
1257 set_curve_radius,
1258 bke::node_find_socket(set_curve_radius, SOCK_IN, "Selection"));
1259
1260 bke::node_add_link(group,
1261 group_input,
1262 bke::node_find_socket(group_input, SOCK_OUT, "Socket_2"),
1263 add,
1264 bke::node_find_socket(add, SOCK_IN, "Value"));
1265 bke::node_add_link(group,
1266 input_radius,
1267 bke::node_find_socket(input_radius, SOCK_OUT, "Radius"),
1268 add,
1269 bke::node_find_socket(add, SOCK_IN, "Value_001"));
1270 bke::node_add_link(group,
1271 add,
1272 bke::node_find_socket(add, SOCK_OUT, "Value"),
1273 clamp_radius,
1274 bke::node_find_socket(clamp_radius, SOCK_IN, "Value"));
1275 bke::node_add_link(group,
1276 clamp_radius,
1277 bke::node_find_socket(clamp_radius, SOCK_OUT, "Result"),
1278 set_curve_radius,
1279 bke::node_find_socket(set_curve_radius, SOCK_IN, "Radius"));
1280
1281 LISTBASE_FOREACH (bNode *, node, &group->nodes) {
1282 bke::node_set_selected(node, false);
1283 }
1284
1285 return group;
1286}
1287
1289 bGPdata &src_object_data,
1290 Object &dst_object)
1291{
1292 AnimDataConvertor animdata_thickness_transfer(
1293 conversion_data, dst_object.id, src_object_data.id, {{"pixel_factor", ".thickness_factor"}});
1294 animdata_thickness_transfer.root_path_src = "";
1295
1296 const float thickness_factor = src_object_data.pixfactor;
1297 const bool has_thickness_factor_animation =
1298 animdata_thickness_transfer.source_has_animation_to_convert();
1299 const bool has_thickness_factor = thickness_factor != 1.0f || has_thickness_factor_animation;
1300
1301 if (!has_thickness_factor) {
1302 return;
1303 }
1304
1306 GreasePencilThickModifierData *tmd = reinterpret_cast<GreasePencilThickModifierData *>(md);
1307
1308 tmd->thickness_fac = thickness_factor;
1309
1310 STRNCPY(md->name, DATA_("Thickness"));
1311 BKE_modifier_unique_name(&dst_object.modifiers, md);
1312
1313 BLI_addtail(&dst_object.modifiers, md);
1314 BKE_modifiers_persistent_uid_init(dst_object, *md);
1315
1316 if (has_thickness_factor_animation) {
1317 char modifier_name_esc[MAX_NAME * 2];
1318 BLI_str_escape(modifier_name_esc, md->name, sizeof(modifier_name_esc));
1319 animdata_thickness_transfer.root_path_dst = fmt::format("modifiers[\"{}\"]",
1320 modifier_name_esc);
1321
1322 animdata_thickness_transfer.fcurves_convert();
1323 }
1324
1325 animdata_thickness_transfer.fcurves_convert_finalize();
1326}
1327
1329{
1330 if (fcurve.bezt) {
1331 for (uint i = 0; i < fcurve.totvert; i++) {
1332 BezTriple &bezier_triple = fcurve.bezt[i];
1333 bezier_triple.vec[0][1] *= LEGACY_RADIUS_CONVERSION_FACTOR;
1334 bezier_triple.vec[1][1] *= LEGACY_RADIUS_CONVERSION_FACTOR;
1335 bezier_triple.vec[2][1] *= LEGACY_RADIUS_CONVERSION_FACTOR;
1336 }
1337 }
1338 if (fcurve.fpt) {
1339 for (uint i = 0; i < fcurve.totvert; i++) {
1340 FPoint &fpoint = fcurve.fpt[i];
1342 }
1343 }
1344 fcurve.flag &= ~FCURVE_INT_VALUES;
1346}
1347
1349 Object &object)
1350{
1351 if (BKE_animdata_from_id(&object.id) == nullptr) {
1352 return;
1353 }
1354
1355 /* NOTE: At this point, the animation was already transferred to the destination object. Now we
1356 * just need to convert the fcurve data to be in the right space. */
1357 AnimDataConvertor animdata_convert_thickness(
1358 conversion_data,
1359 object.id,
1360 object.id,
1361 {{".thickness", ".thickness", fcurve_convert_thickness_cb}});
1362
1363 LISTBASE_FOREACH (ModifierData *, tmd, &object.modifiers) {
1365 continue;
1366 }
1367
1368 char modifier_name[MAX_NAME * 2];
1369 BLI_str_escape(modifier_name, tmd->name, sizeof(modifier_name));
1370 animdata_convert_thickness.root_path_src = fmt::format("modifiers[\"{}\"]", modifier_name);
1371 animdata_convert_thickness.root_path_dst = fmt::format("modifiers[\"{}\"]", modifier_name);
1372
1373 if (!animdata_convert_thickness.source_has_animation_to_convert()) {
1374 continue;
1375 }
1376 animdata_convert_thickness.fcurves_convert();
1377 }
1378
1379 animdata_convert_thickness.fcurves_convert_finalize();
1380 DEG_relations_tag_update(&conversion_data.bmain);
1381}
1382
1384 bGPdata &src_object_data,
1385 Object &dst_object)
1386{
1387 /* Handling of animation here is a bit complex, since paths needs to be updated, but also
1388 * FCurves need to be transferred from legacy GPData animation to Object animation. */
1389 AnimDataConvertor animdata_tint_transfer(
1390 conversion_data,
1391 dst_object.id,
1392 src_object_data.id,
1393 {{".tint_color", ".color"}, {".tint_factor", ".factor"}});
1394
1395 AnimDataConvertor animdata_thickness_transfer(
1396 conversion_data,
1397 dst_object.id,
1398 src_object_data.id,
1399 {{".line_change", "[\"Socket_2\"]", fcurve_convert_thickness_cb}});
1400
1401 /* Replace layer adjustments with modifiers. */
1402 LISTBASE_FOREACH (bGPDlayer *, gpl, &src_object_data.layers) {
1403 const float3 tint_color = float3(gpl->tintcolor);
1404 const float tint_factor = gpl->tintcolor[3];
1405 const int thickness_px = gpl->line_change;
1406
1407 char layer_name_esc[sizeof(gpl->info) * 2];
1408 BLI_str_escape(layer_name_esc, gpl->info, sizeof(layer_name_esc));
1409 animdata_tint_transfer.root_path_src = fmt::format("layers[\"{}\"]", layer_name_esc);
1410 animdata_thickness_transfer.root_path_src = fmt::format("layers[\"{}\"]", layer_name_esc);
1411
1412 const bool has_tint_adjustment_animation =
1413 animdata_tint_transfer.source_has_animation_to_convert();
1414 const bool has_thickness_adjustment_animation =
1415 animdata_thickness_transfer.source_has_animation_to_convert();
1416
1417 /* If tint or thickness are animated, relevant modifiers also need to be created. */
1418 const bool has_tint_adjustment = tint_factor > 0.0f || has_tint_adjustment_animation;
1419 const bool has_thickness_adjustment = thickness_px != 0 || has_thickness_adjustment_animation;
1420
1421 /* Tint adjustment. */
1422 if (has_tint_adjustment) {
1424 GreasePencilTintModifierData *tmd = reinterpret_cast<GreasePencilTintModifierData *>(md);
1425
1426 copy_v3_v3(tmd->color, tint_color);
1427 tmd->factor = tint_factor;
1428 STRNCPY(tmd->influence.layer_name, gpl->info);
1429
1430 char modifier_name[MAX_NAME];
1431 SNPRINTF(modifier_name, "Tint %s", gpl->info);
1433 BKE_modifier_unique_name(&dst_object.modifiers, md);
1434
1435 BLI_addtail(&dst_object.modifiers, md);
1436 BKE_modifiers_persistent_uid_init(dst_object, *md);
1437
1438 if (has_tint_adjustment_animation) {
1439 char modifier_name_esc[MAX_NAME * 2];
1440 BLI_str_escape(modifier_name_esc, md->name, sizeof(modifier_name_esc));
1441 animdata_tint_transfer.root_path_dst = fmt::format("modifiers[\"{}\"]", modifier_name_esc);
1442
1443 animdata_tint_transfer.fcurves_convert();
1444 }
1445 }
1446 /* Thickness adjustment. */
1447 if (has_thickness_adjustment) {
1448 /* Convert the "pixel" offset value into a radius value.
1449 * GPv2 used a conversion of 1 "px" = 0.001. */
1450 /* NOTE: this offset may be negative. */
1451 const float uniform_object_scale = math::average(float3(dst_object.scale));
1452 const float radius_offset = math::safe_divide(
1453 float(thickness_px) * LEGACY_RADIUS_CONVERSION_FACTOR, uniform_object_scale);
1454
1455 const auto offset_radius_ntree_ensure = [&](Library *owner_library) {
1456 if (bNodeTree **ntree = conversion_data.offset_radius_ntree_by_library.lookup_ptr(
1457 owner_library))
1458 {
1459 /* Node tree has already been found/created for this versioning call. */
1460 return *ntree;
1461 }
1462 /* Try to find an existing group added by previous versioning to avoid adding duplicates.
1463 */
1464 LISTBASE_FOREACH (bNodeTree *, ntree_iter, &conversion_data.bmain.nodetrees) {
1465 if (ntree_iter->id.lib != owner_library) {
1466 continue;
1467 }
1468 if (STREQ(ntree_iter->id.name + 2, OFFSET_RADIUS_NODETREE_NAME)) {
1469 conversion_data.offset_radius_ntree_by_library.add_new(owner_library, ntree_iter);
1470 return ntree_iter;
1471 }
1472 }
1473 bNodeTree *new_ntree = offset_radius_node_tree_add(conversion_data, owner_library);
1474 /* Remove the default user. The count is tracked manually when assigning to modifiers. */
1475 id_us_min(&new_ntree->id);
1476 conversion_data.offset_radius_ntree_by_library.add_new(owner_library, new_ntree);
1477 BKE_ntree_update_main_tree(&conversion_data.bmain, new_ntree, nullptr);
1478 return new_ntree;
1479 };
1480 bNodeTree *offset_radius_node_tree = offset_radius_ntree_ensure(dst_object.id.lib);
1481
1482 auto *md = reinterpret_cast<NodesModifierData *>(BKE_modifier_new(eModifierType_Nodes));
1483
1484 char modifier_name[MAX_NAME];
1485 SNPRINTF(modifier_name, "Thickness %s", gpl->info);
1486 STRNCPY(md->modifier.name, modifier_name);
1487 BKE_modifier_unique_name(&dst_object.modifiers, &md->modifier);
1488 md->node_group = offset_radius_node_tree;
1489
1490 BLI_addtail(&dst_object.modifiers, md);
1491 BKE_modifiers_persistent_uid_init(dst_object, md->modifier);
1492
1493 md->settings.properties = bke::idprop::create_group("Nodes Modifier Settings").release();
1494 IDProperty *radius_offset_prop =
1495 bke::idprop::create(DATA_("Socket_2"), radius_offset).release();
1496 auto *ui_data = reinterpret_cast<IDPropertyUIDataFloat *>(
1497 IDP_ui_data_ensure(radius_offset_prop));
1498 ui_data->soft_min = 0.0;
1499 ui_data->base.rna_subtype = PROP_TRANSLATION;
1500 IDP_AddToGroup(md->settings.properties, radius_offset_prop);
1501 IDP_AddToGroup(md->settings.properties,
1502 bke::idprop::create(DATA_("Socket_3"), gpl->info).release());
1503
1504 if (has_thickness_adjustment_animation) {
1505 char modifier_name_esc[MAX_NAME * 2];
1506 BLI_str_escape(modifier_name_esc, md->modifier.name, sizeof(modifier_name_esc));
1507 animdata_thickness_transfer.root_path_dst = fmt::format("modifiers[\"{}\"]",
1508 modifier_name_esc);
1509
1510 animdata_thickness_transfer.fcurves_convert();
1511 }
1512 }
1513 }
1514
1515 animdata_tint_transfer.fcurves_convert_finalize();
1516 animdata_thickness_transfer.fcurves_convert_finalize();
1517
1518 DEG_relations_tag_update(&conversion_data.bmain);
1519}
1520
1522 Object &object,
1523 const ModifierType type,
1524 GpencilModifierData &legacy_md)
1525{
1526 /* TODO: Copy of most of #ed::object::modifier_add, this should be a BKE_modifiers function
1527 * actually. */
1528 const ModifierTypeInfo *mti = BKE_modifier_get_info(type);
1529
1530 ModifierData &new_md = *BKE_modifier_new(type);
1531
1533 ModifierData *md;
1534 for (md = static_cast<ModifierData *>(object.modifiers.first);
1536 md = md->next)
1537 ;
1538 BLI_insertlinkbefore(&object.modifiers, md, &new_md);
1539 }
1540 else {
1541 BLI_addtail(&object.modifiers, &new_md);
1542 }
1543
1544 /* Generate new persistent UID and best possible unique name. */
1545 BKE_modifiers_persistent_uid_init(object, new_md);
1546 if (legacy_md.name[0]) {
1547 STRNCPY_UTF8(new_md.name, legacy_md.name);
1548 }
1549 BKE_modifier_unique_name(&object.modifiers, &new_md);
1550
1551 /* Handle common modifier data. */
1552 new_md.mode = legacy_md.mode;
1554
1555 /* Attempt to copy UI state (panels) as best as possible. */
1556 new_md.ui_expand_flag = legacy_md.ui_expand_flag;
1557
1558 /* Convert animation data if needed. */
1559 if (BKE_animdata_from_id(&object.id)) {
1560 AnimDataConvertor anim_convertor(conversion_data, object.id);
1561
1562 char legacy_name_esc[MAX_NAME * 2];
1563 BLI_str_escape(legacy_name_esc, legacy_md.name, sizeof(legacy_name_esc));
1564 anim_convertor.root_path_src = fmt::format("grease_pencil_modifiers[\"{}\"]", legacy_name_esc);
1565
1566 char new_name_esc[MAX_NAME * 2];
1567 BLI_str_escape(new_name_esc, new_md.name, sizeof(new_name_esc));
1568 anim_convertor.root_path_dst = fmt::format("modifiers[\"{}\"]", new_name_esc);
1569
1570 anim_convertor.fcurves_convert();
1571 anim_convertor.fcurves_convert_finalize();
1572 }
1573
1574 return new_md;
1575}
1576
1578 StringRef layername,
1579 const int layer_pass,
1580 const bool invert_layer,
1581 const bool invert_layer_pass,
1582 Material **material,
1583 const int material_pass,
1584 const bool invert_material,
1585 const bool invert_material_pass,
1586 StringRef vertex_group_name,
1587 const bool invert_vertex_group,
1588 CurveMapping **custom_curve,
1589 const bool use_custom_curve)
1590{
1591 influence.flag = 0;
1592
1593 STRNCPY(influence.layer_name, layername.data());
1594 if (invert_layer) {
1596 }
1597 influence.layer_pass = layer_pass;
1598 if (layer_pass > 0) {
1600 }
1601 if (invert_layer_pass) {
1603 }
1604
1605 if (material) {
1606 influence.material = *material;
1607 *material = nullptr;
1608 }
1609 if (invert_material) {
1611 }
1612 influence.material_pass = material_pass;
1613 if (material_pass > 0) {
1615 }
1616 if (invert_material_pass) {
1618 }
1619
1620 STRNCPY(influence.vertex_group_name, vertex_group_name.data());
1621 if (invert_vertex_group) {
1623 }
1624
1625 if (custom_curve) {
1626 if (influence.custom_curve) {
1628 }
1629 influence.custom_curve = *custom_curve;
1630 *custom_curve = nullptr;
1631 }
1632 if (use_custom_curve) {
1634 }
1635}
1636
1638 Object &object,
1639 GpencilModifierData &legacy_md)
1640{
1642 conversion_data, object, eModifierType_GreasePencilArmature, legacy_md);
1643 auto &md_armature = reinterpret_cast<GreasePencilArmatureModifierData &>(md);
1644 auto &legacy_md_armature = reinterpret_cast<ArmatureGpencilModifierData &>(legacy_md);
1645
1646 md_armature.object = legacy_md_armature.object;
1647 legacy_md_armature.object = nullptr;
1648 md_armature.deformflag = legacy_md_armature.deformflag;
1649
1650 legacy_object_modifier_influence(md_armature.influence,
1651 "",
1652 0,
1653 false,
1654 false,
1655 nullptr,
1656 0,
1657 false,
1658 false,
1659 legacy_md_armature.vgname,
1660 legacy_md_armature.deformflag & ARM_DEF_INVERT_VGROUP,
1661 nullptr,
1662 false);
1663}
1664
1666 Object &object,
1667 GpencilModifierData &legacy_md)
1668{
1670 conversion_data, object, eModifierType_GreasePencilArray, legacy_md);
1671 auto &md_array = reinterpret_cast<GreasePencilArrayModifierData &>(md);
1672 auto &legacy_md_array = reinterpret_cast<ArrayGpencilModifierData &>(legacy_md);
1673
1674 md_array.object = legacy_md_array.object;
1675 legacy_md_array.object = nullptr;
1676 md_array.count = legacy_md_array.count;
1677 md_array.flag = 0;
1678 if (legacy_md_array.flag & GP_ARRAY_UNIFORM_RANDOM_SCALE) {
1680 }
1681 if (legacy_md_array.flag & GP_ARRAY_USE_OB_OFFSET) {
1683 }
1684 if (legacy_md_array.flag & GP_ARRAY_USE_OFFSET) {
1685 md_array.flag |= MOD_GREASE_PENCIL_ARRAY_USE_OFFSET;
1686 }
1687 if (legacy_md_array.flag & GP_ARRAY_USE_RELATIVE) {
1688 md_array.flag |= MOD_GREASE_PENCIL_ARRAY_USE_RELATIVE;
1689 }
1690 copy_v3_v3(md_array.offset, legacy_md_array.offset);
1691 copy_v3_v3(md_array.shift, legacy_md_array.shift);
1692 copy_v3_v3(md_array.rnd_offset, legacy_md_array.rnd_offset);
1693 copy_v3_v3(md_array.rnd_rot, legacy_md_array.rnd_rot);
1694 copy_v3_v3(md_array.rnd_scale, legacy_md_array.rnd_scale);
1695 md_array.seed = legacy_md_array.seed;
1696 md_array.mat_rpl = legacy_md_array.mat_rpl;
1697
1698 legacy_object_modifier_influence(md_array.influence,
1699 legacy_md_array.layername,
1700 legacy_md_array.layer_pass,
1701 legacy_md_array.flag & GP_ARRAY_INVERT_LAYER,
1702 legacy_md_array.flag & GP_ARRAY_INVERT_LAYERPASS,
1703 &legacy_md_array.material,
1704 legacy_md_array.pass_index,
1705 legacy_md_array.flag & GP_ARRAY_INVERT_MATERIAL,
1706 legacy_md_array.flag & GP_ARRAY_INVERT_PASS,
1707 "",
1708 false,
1709 nullptr,
1710 false);
1711}
1712
1714 Object &object,
1715 GpencilModifierData &legacy_md)
1716{
1718 conversion_data, object, eModifierType_GreasePencilColor, legacy_md);
1719 auto &md_color = reinterpret_cast<GreasePencilColorModifierData &>(md);
1720 auto &legacy_md_color = reinterpret_cast<ColorGpencilModifierData &>(legacy_md);
1721
1722 switch (eModifyColorGpencil_Flag(legacy_md_color.modify_color)) {
1724 md_color.color_mode = MOD_GREASE_PENCIL_COLOR_BOTH;
1725 break;
1727 md_color.color_mode = MOD_GREASE_PENCIL_COLOR_STROKE;
1728 break;
1730 md_color.color_mode = MOD_GREASE_PENCIL_COLOR_FILL;
1731 break;
1733 md_color.color_mode = MOD_GREASE_PENCIL_COLOR_HARDNESS;
1734 break;
1735 }
1736 copy_v3_v3(md_color.hsv, legacy_md_color.hsv);
1737
1738 legacy_object_modifier_influence(md_color.influence,
1739 legacy_md_color.layername,
1740 legacy_md_color.layer_pass,
1741 legacy_md_color.flag & GP_COLOR_INVERT_LAYER,
1742 legacy_md_color.flag & GP_COLOR_INVERT_LAYERPASS,
1743 &legacy_md_color.material,
1744 legacy_md_color.pass_index,
1745 legacy_md_color.flag & GP_COLOR_INVERT_MATERIAL,
1746 legacy_md_color.flag & GP_COLOR_INVERT_PASS,
1747 "",
1748 false,
1749 &legacy_md_color.curve_intensity,
1750 legacy_md_color.flag & GP_COLOR_CUSTOM_CURVE);
1751}
1752
1753static void legacy_object_modifier_dash(ConversionData &conversion_data,
1754 Object &object,
1755 GpencilModifierData &legacy_md)
1756{
1758 conversion_data, object, eModifierType_GreasePencilDash, legacy_md);
1759 auto &md_dash = reinterpret_cast<GreasePencilDashModifierData &>(md);
1760 auto &legacy_md_dash = reinterpret_cast<DashGpencilModifierData &>(legacy_md);
1761
1762 md_dash.dash_offset = legacy_md_dash.dash_offset;
1763 md_dash.segment_active_index = legacy_md_dash.segment_active_index;
1764 md_dash.segments_num = legacy_md_dash.segments_len;
1765 MEM_SAFE_FREE(md_dash.segments_array);
1766 md_dash.segments_array = MEM_cnew_array<GreasePencilDashModifierSegment>(
1767 legacy_md_dash.segments_len, __func__);
1768 for (const int i : IndexRange(md_dash.segments_num)) {
1769 GreasePencilDashModifierSegment &dst_segment = md_dash.segments_array[i];
1770 const DashGpencilModifierSegment &src_segment = legacy_md_dash.segments[i];
1771 STRNCPY(dst_segment.name, src_segment.name);
1772 dst_segment.flag = 0;
1773 if (src_segment.flag & GP_DASH_USE_CYCLIC) {
1775 }
1776 dst_segment.dash = src_segment.dash;
1777 dst_segment.gap = src_segment.gap;
1778 dst_segment.opacity = src_segment.opacity;
1779 dst_segment.radius = src_segment.radius;
1780 dst_segment.mat_nr = src_segment.mat_nr;
1781 }
1782
1783 legacy_object_modifier_influence(md_dash.influence,
1784 legacy_md_dash.layername,
1785 legacy_md_dash.layer_pass,
1786 legacy_md_dash.flag & GP_DASH_INVERT_LAYER,
1787 legacy_md_dash.flag & GP_DASH_INVERT_LAYERPASS,
1788 &legacy_md_dash.material,
1789 legacy_md_dash.pass_index,
1790 legacy_md_dash.flag & GP_DASH_INVERT_MATERIAL,
1791 legacy_md_dash.flag & GP_DASH_INVERT_PASS,
1792 "",
1793 false,
1794 nullptr,
1795 false);
1796}
1797
1799 Object &object,
1800 GpencilModifierData &legacy_md)
1801{
1803 conversion_data, object, eModifierType_GreasePencilEnvelope, legacy_md);
1804 auto &md_envelope = reinterpret_cast<GreasePencilEnvelopeModifierData &>(md);
1805 auto &legacy_md_envelope = reinterpret_cast<EnvelopeGpencilModifierData &>(legacy_md);
1806
1807 switch (eEnvelopeGpencil_Mode(legacy_md_envelope.mode)) {
1808 case GP_ENVELOPE_DEFORM:
1810 break;
1812 md_envelope.mode = MOD_GREASE_PENCIL_ENVELOPE_SEGMENTS;
1813 break;
1814 case GP_ENVELOPE_FILLS:
1815 md_envelope.mode = MOD_GREASE_PENCIL_ENVELOPE_FILLS;
1816 break;
1817 }
1818 md_envelope.mat_nr = legacy_md_envelope.mat_nr;
1819 md_envelope.thickness = legacy_md_envelope.thickness;
1820 md_envelope.strength = legacy_md_envelope.strength;
1821 md_envelope.skip = legacy_md_envelope.skip;
1822 md_envelope.spread = legacy_md_envelope.spread;
1823
1824 legacy_object_modifier_influence(md_envelope.influence,
1825 legacy_md_envelope.layername,
1826 legacy_md_envelope.layer_pass,
1827 legacy_md_envelope.flag & GP_ENVELOPE_INVERT_LAYER,
1828 legacy_md_envelope.flag & GP_ENVELOPE_INVERT_LAYERPASS,
1829 &legacy_md_envelope.material,
1830 legacy_md_envelope.pass_index,
1831 legacy_md_envelope.flag & GP_ENVELOPE_INVERT_MATERIAL,
1832 legacy_md_envelope.flag & GP_ENVELOPE_INVERT_PASS,
1833 legacy_md_envelope.vgname,
1834 legacy_md_envelope.flag & GP_ENVELOPE_INVERT_VGROUP,
1835 nullptr,
1836 false);
1837}
1838
1839static void legacy_object_modifier_hook(ConversionData &conversion_data,
1840 Object &object,
1841 GpencilModifierData &legacy_md)
1842{
1844 conversion_data, object, eModifierType_GreasePencilHook, legacy_md);
1845 auto &md_hook = reinterpret_cast<GreasePencilHookModifierData &>(md);
1846 auto &legacy_md_hook = reinterpret_cast<HookGpencilModifierData &>(legacy_md);
1847
1848 md_hook.flag = 0;
1849 if (legacy_md_hook.flag & GP_HOOK_UNIFORM_SPACE) {
1851 }
1852 switch (eHookGpencil_Falloff(legacy_md_hook.falloff_type)) {
1854 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_None;
1855 break;
1857 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Curve;
1858 break;
1860 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Sharp;
1861 break;
1863 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Smooth;
1864 break;
1866 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Root;
1867 break;
1869 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Linear;
1870 break;
1872 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Const;
1873 break;
1875 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_Sphere;
1876 break;
1878 md_hook.falloff_type = MOD_GREASE_PENCIL_HOOK_Falloff_InvSquare;
1879 break;
1880 }
1881 md_hook.object = legacy_md_hook.object;
1882 legacy_md_hook.object = nullptr;
1883 STRNCPY(md_hook.subtarget, legacy_md_hook.subtarget);
1884 copy_m4_m4(md_hook.parentinv, legacy_md_hook.parentinv);
1885 copy_v3_v3(md_hook.cent, legacy_md_hook.cent);
1886 md_hook.falloff = legacy_md_hook.falloff;
1887 md_hook.force = legacy_md_hook.force;
1888
1889 legacy_object_modifier_influence(md_hook.influence,
1890 legacy_md_hook.layername,
1891 legacy_md_hook.layer_pass,
1892 legacy_md_hook.flag & GP_HOOK_INVERT_LAYER,
1893 legacy_md_hook.flag & GP_HOOK_INVERT_LAYERPASS,
1894 &legacy_md_hook.material,
1895 legacy_md_hook.pass_index,
1896 legacy_md_hook.flag & GP_HOOK_INVERT_MATERIAL,
1897 legacy_md_hook.flag & GP_HOOK_INVERT_PASS,
1898 legacy_md_hook.vgname,
1899 legacy_md_hook.flag & GP_HOOK_INVERT_VGROUP,
1900 &legacy_md_hook.curfalloff,
1901 true);
1902}
1903
1905 Object &object,
1906 GpencilModifierData &legacy_md)
1907{
1909 conversion_data, object, eModifierType_GreasePencilLattice, legacy_md);
1910 auto &md_lattice = reinterpret_cast<GreasePencilLatticeModifierData &>(md);
1911 auto &legacy_md_lattice = reinterpret_cast<LatticeGpencilModifierData &>(legacy_md);
1912
1913 md_lattice.object = legacy_md_lattice.object;
1914 legacy_md_lattice.object = nullptr;
1915 md_lattice.strength = legacy_md_lattice.strength;
1916
1917 legacy_object_modifier_influence(md_lattice.influence,
1918 legacy_md_lattice.layername,
1919 legacy_md_lattice.layer_pass,
1920 legacy_md_lattice.flag & GP_LATTICE_INVERT_LAYER,
1921 legacy_md_lattice.flag & GP_LATTICE_INVERT_LAYERPASS,
1922 &legacy_md_lattice.material,
1923 legacy_md_lattice.pass_index,
1924 legacy_md_lattice.flag & GP_LATTICE_INVERT_MATERIAL,
1925 legacy_md_lattice.flag & GP_LATTICE_INVERT_PASS,
1926 legacy_md_lattice.vgname,
1927 legacy_md_lattice.flag & GP_LATTICE_INVERT_VGROUP,
1928 nullptr,
1929 false);
1930}
1931
1933 Object &object,
1934 GpencilModifierData &legacy_md)
1935{
1937 conversion_data, object, eModifierType_GreasePencilLength, legacy_md);
1938 auto &md_length = reinterpret_cast<GreasePencilLengthModifierData &>(md);
1939 auto &legacy_md_length = reinterpret_cast<LengthGpencilModifierData &>(legacy_md);
1940
1941 md_length.flag = legacy_md_length.flag;
1942 md_length.start_fac = legacy_md_length.start_fac;
1943 md_length.end_fac = legacy_md_length.end_fac;
1944 md_length.rand_start_fac = legacy_md_length.rand_start_fac;
1945 md_length.rand_end_fac = legacy_md_length.rand_end_fac;
1946 md_length.rand_offset = legacy_md_length.rand_offset;
1947 md_length.overshoot_fac = legacy_md_length.overshoot_fac;
1948 md_length.seed = legacy_md_length.seed;
1949 md_length.step = legacy_md_length.step;
1950 md_length.mode = legacy_md_length.mode;
1951 md_length.point_density = legacy_md_length.point_density;
1952 md_length.segment_influence = legacy_md_length.segment_influence;
1953 md_length.max_angle = legacy_md_length.max_angle;
1954
1955 legacy_object_modifier_influence(md_length.influence,
1956 legacy_md_length.layername,
1957 legacy_md_length.layer_pass,
1958 legacy_md_length.flag & GP_LENGTH_INVERT_LAYER,
1959 legacy_md_length.flag & GP_LENGTH_INVERT_LAYERPASS,
1960 &legacy_md_length.material,
1961 legacy_md_length.pass_index,
1962 legacy_md_length.flag & GP_LENGTH_INVERT_MATERIAL,
1963 legacy_md_length.flag & GP_LENGTH_INVERT_PASS,
1964 "",
1965 false,
1966 nullptr,
1967 false);
1968}
1969
1971 Object &object,
1972 GpencilModifierData &legacy_md)
1973{
1975 conversion_data, object, eModifierType_GreasePencilMirror, legacy_md);
1976 auto &md_mirror = reinterpret_cast<GreasePencilMirrorModifierData &>(md);
1977 auto &legacy_md_mirror = reinterpret_cast<MirrorGpencilModifierData &>(legacy_md);
1978
1979 md_mirror.object = legacy_md_mirror.object;
1980 legacy_md_mirror.object = nullptr;
1981 md_mirror.flag = 0;
1982 if (legacy_md_mirror.flag & GP_MIRROR_AXIS_X) {
1983 md_mirror.flag |= MOD_GREASE_PENCIL_MIRROR_AXIS_X;
1984 }
1985 if (legacy_md_mirror.flag & GP_MIRROR_AXIS_Y) {
1986 md_mirror.flag |= MOD_GREASE_PENCIL_MIRROR_AXIS_Y;
1987 }
1988 if (legacy_md_mirror.flag & GP_MIRROR_AXIS_Z) {
1989 md_mirror.flag |= MOD_GREASE_PENCIL_MIRROR_AXIS_Z;
1990 }
1991
1992 legacy_object_modifier_influence(md_mirror.influence,
1993 legacy_md_mirror.layername,
1994 legacy_md_mirror.layer_pass,
1995 legacy_md_mirror.flag & GP_MIRROR_INVERT_LAYER,
1996 legacy_md_mirror.flag & GP_MIRROR_INVERT_LAYERPASS,
1997 &legacy_md_mirror.material,
1998 legacy_md_mirror.pass_index,
1999 legacy_md_mirror.flag & GP_MIRROR_INVERT_MATERIAL,
2000 legacy_md_mirror.flag & GP_MIRROR_INVERT_PASS,
2001 "",
2002 false,
2003 nullptr,
2004 false);
2005}
2006
2008 Object &object,
2009 GpencilModifierData &legacy_md)
2010{
2012 conversion_data, object, eModifierType_GreasePencilMultiply, legacy_md);
2013 auto &md_multiply = reinterpret_cast<GreasePencilMultiModifierData &>(md);
2014 auto &legacy_md_multiply = reinterpret_cast<MultiplyGpencilModifierData &>(legacy_md);
2015
2016 md_multiply.flag = 0;
2017 if (legacy_md_multiply.flags & GP_MULTIPLY_ENABLE_FADING) {
2018 md_multiply.flag |= MOD_GREASE_PENCIL_MULTIPLY_ENABLE_FADING;
2019 }
2020 md_multiply.duplications = legacy_md_multiply.duplications;
2021 md_multiply.distance = legacy_md_multiply.distance;
2022 md_multiply.offset = legacy_md_multiply.offset;
2023 md_multiply.fading_center = legacy_md_multiply.fading_center;
2024 md_multiply.fading_thickness = legacy_md_multiply.fading_thickness;
2025 md_multiply.fading_opacity = legacy_md_multiply.fading_opacity;
2026
2027 /* NOTE: This looks wrong, but GPv2 version uses Mirror modifier flags in its `flag` property
2028 * and own flags in its `flags` property. */
2029 legacy_object_modifier_influence(md_multiply.influence,
2030 legacy_md_multiply.layername,
2031 legacy_md_multiply.layer_pass,
2032 legacy_md_multiply.flag & GP_MIRROR_INVERT_LAYER,
2033 legacy_md_multiply.flag & GP_MIRROR_INVERT_LAYERPASS,
2034 &legacy_md_multiply.material,
2035 legacy_md_multiply.pass_index,
2036 legacy_md_multiply.flag & GP_MIRROR_INVERT_MATERIAL,
2037 legacy_md_multiply.flag & GP_MIRROR_INVERT_PASS,
2038 "",
2039 false,
2040 nullptr,
2041 false);
2042}
2043
2045 Object &object,
2046 GpencilModifierData &legacy_md)
2047{
2049 conversion_data, object, eModifierType_GreasePencilNoise, legacy_md);
2050 auto &md_noise = reinterpret_cast<GreasePencilNoiseModifierData &>(md);
2051 auto &legacy_md_noise = reinterpret_cast<NoiseGpencilModifierData &>(legacy_md);
2052
2053 md_noise.flag = legacy_md_noise.flag;
2054 md_noise.factor = legacy_md_noise.factor;
2055 md_noise.factor_strength = legacy_md_noise.factor_strength;
2056 md_noise.factor_thickness = legacy_md_noise.factor_thickness;
2057 md_noise.factor_uvs = legacy_md_noise.factor_uvs;
2058 md_noise.noise_scale = legacy_md_noise.noise_scale;
2059 md_noise.noise_offset = legacy_md_noise.noise_offset;
2060 md_noise.noise_mode = legacy_md_noise.noise_mode;
2061 md_noise.step = legacy_md_noise.step;
2062 md_noise.seed = legacy_md_noise.seed;
2063
2064 legacy_object_modifier_influence(md_noise.influence,
2065 legacy_md_noise.layername,
2066 legacy_md_noise.layer_pass,
2067 legacy_md_noise.flag & GP_NOISE_INVERT_LAYER,
2068 legacy_md_noise.flag & GP_NOISE_INVERT_LAYERPASS,
2069 &legacy_md_noise.material,
2070 legacy_md_noise.pass_index,
2071 legacy_md_noise.flag & GP_NOISE_INVERT_MATERIAL,
2072 legacy_md_noise.flag & GP_NOISE_INVERT_PASS,
2073 legacy_md_noise.vgname,
2074 legacy_md_noise.flag & GP_NOISE_INVERT_VGROUP,
2075 &legacy_md_noise.curve_intensity,
2076 legacy_md_noise.flag & GP_NOISE_CUSTOM_CURVE);
2077}
2078
2080 Object &object,
2081 GpencilModifierData &legacy_md)
2082{
2084 conversion_data, object, eModifierType_GreasePencilOffset, legacy_md);
2085 auto &md_offset = reinterpret_cast<GreasePencilOffsetModifierData &>(md);
2086 auto &legacy_md_offset = reinterpret_cast<OffsetGpencilModifierData &>(legacy_md);
2087
2088 md_offset.flag = 0;
2089 if (legacy_md_offset.flag & GP_OFFSET_UNIFORM_RANDOM_SCALE) {
2091 }
2092 switch (eOffsetGpencil_Mode(legacy_md_offset.mode)) {
2093 case GP_OFFSET_RANDOM:
2094 md_offset.offset_mode = MOD_GREASE_PENCIL_OFFSET_RANDOM;
2095 break;
2096 case GP_OFFSET_LAYER:
2097 md_offset.offset_mode = MOD_GREASE_PENCIL_OFFSET_LAYER;
2098 break;
2099 case GP_OFFSET_MATERIAL:
2100 md_offset.offset_mode = MOD_GREASE_PENCIL_OFFSET_MATERIAL;
2101 break;
2102 case GP_OFFSET_STROKE:
2103 md_offset.offset_mode = MOD_GREASE_PENCIL_OFFSET_STROKE;
2104 break;
2105 }
2106 copy_v3_v3(md_offset.loc, legacy_md_offset.loc);
2107 copy_v3_v3(md_offset.rot, legacy_md_offset.rot);
2108 copy_v3_v3(md_offset.scale, legacy_md_offset.scale);
2109 copy_v3_v3(md_offset.stroke_loc, legacy_md_offset.rnd_offset);
2110 copy_v3_v3(md_offset.stroke_rot, legacy_md_offset.rnd_rot);
2111 copy_v3_v3(md_offset.stroke_scale, legacy_md_offset.rnd_scale);
2112 md_offset.seed = legacy_md_offset.seed;
2113 md_offset.stroke_step = legacy_md_offset.stroke_step;
2114 md_offset.stroke_start_offset = legacy_md_offset.stroke_start_offset;
2115
2116 legacy_object_modifier_influence(md_offset.influence,
2117 legacy_md_offset.layername,
2118 legacy_md_offset.layer_pass,
2119 legacy_md_offset.flag & GP_OFFSET_INVERT_LAYER,
2120 legacy_md_offset.flag & GP_OFFSET_INVERT_LAYERPASS,
2121 &legacy_md_offset.material,
2122 legacy_md_offset.pass_index,
2123 legacy_md_offset.flag & GP_OFFSET_INVERT_MATERIAL,
2124 legacy_md_offset.flag & GP_OFFSET_INVERT_PASS,
2125 legacy_md_offset.vgname,
2126 legacy_md_offset.flag & GP_OFFSET_INVERT_VGROUP,
2127 nullptr,
2128 false);
2129}
2130
2132 Object &object,
2133 GpencilModifierData &legacy_md)
2134{
2136 conversion_data, object, eModifierType_GreasePencilOpacity, legacy_md);
2137 auto &md_opacity = reinterpret_cast<GreasePencilOpacityModifierData &>(md);
2138 auto &legacy_md_opacity = reinterpret_cast<OpacityGpencilModifierData &>(legacy_md);
2139
2140 md_opacity.flag = 0;
2141 if (legacy_md_opacity.flag & GP_OPACITY_NORMALIZE) {
2143 }
2144 if (legacy_md_opacity.flag & GP_OPACITY_WEIGHT_FACTOR) {
2146 }
2147 switch (eModifyColorGpencil_Flag(legacy_md_opacity.modify_color)) {
2149 md_opacity.color_mode = MOD_GREASE_PENCIL_COLOR_BOTH;
2150 break;
2152 md_opacity.color_mode = MOD_GREASE_PENCIL_COLOR_STROKE;
2153 break;
2155 md_opacity.color_mode = MOD_GREASE_PENCIL_COLOR_FILL;
2156 break;
2158 md_opacity.color_mode = MOD_GREASE_PENCIL_COLOR_HARDNESS;
2159 break;
2160 }
2161 md_opacity.color_factor = legacy_md_opacity.factor;
2162 md_opacity.hardness_factor = legacy_md_opacity.hardness;
2163
2164 legacy_object_modifier_influence(md_opacity.influence,
2165 legacy_md_opacity.layername,
2166 legacy_md_opacity.layer_pass,
2167 legacy_md_opacity.flag & GP_OPACITY_INVERT_LAYER,
2168 legacy_md_opacity.flag & GP_OPACITY_INVERT_LAYERPASS,
2169 &legacy_md_opacity.material,
2170 legacy_md_opacity.pass_index,
2171 legacy_md_opacity.flag & GP_OPACITY_INVERT_MATERIAL,
2172 legacy_md_opacity.flag & GP_OPACITY_INVERT_PASS,
2173 legacy_md_opacity.vgname,
2174 legacy_md_opacity.flag & GP_OPACITY_INVERT_VGROUP,
2175 &legacy_md_opacity.curve_intensity,
2176 legacy_md_opacity.flag & GP_OPACITY_CUSTOM_CURVE);
2177}
2178
2180 Object &object,
2181 GpencilModifierData &legacy_md)
2182{
2184 conversion_data, object, eModifierType_GreasePencilOutline, legacy_md);
2185 auto &md_outline = reinterpret_cast<GreasePencilOutlineModifierData &>(md);
2186 auto &legacy_md_outline = reinterpret_cast<OutlineGpencilModifierData &>(legacy_md);
2187
2188 md_outline.flag = 0;
2189 if (legacy_md_outline.flag & GP_OUTLINE_KEEP_SHAPE) {
2190 md_outline.flag |= MOD_GREASE_PENCIL_OUTLINE_KEEP_SHAPE;
2191 }
2192 md_outline.object = legacy_md_outline.object;
2193 legacy_md_outline.object = nullptr;
2194 md_outline.outline_material = legacy_md_outline.outline_material;
2195 legacy_md_outline.outline_material = nullptr;
2196 md_outline.sample_length = legacy_md_outline.sample_length;
2197 md_outline.subdiv = legacy_md_outline.subdiv;
2198 md_outline.thickness = legacy_md_outline.thickness;
2199
2200 legacy_object_modifier_influence(md_outline.influence,
2201 legacy_md_outline.layername,
2202 legacy_md_outline.layer_pass,
2203 legacy_md_outline.flag & GP_OUTLINE_INVERT_LAYER,
2204 legacy_md_outline.flag & GP_OUTLINE_INVERT_LAYERPASS,
2205 &legacy_md_outline.material,
2206 legacy_md_outline.pass_index,
2207 legacy_md_outline.flag & GP_OUTLINE_INVERT_MATERIAL,
2208 legacy_md_outline.flag & GP_OUTLINE_INVERT_PASS,
2209 "",
2210 false,
2211 nullptr,
2212 false);
2213}
2214
2216 Object &object,
2217 GpencilModifierData &legacy_md)
2218{
2220 conversion_data, object, eModifierType_GreasePencilShrinkwrap, legacy_md);
2221 auto &md_shrinkwrap = reinterpret_cast<GreasePencilShrinkwrapModifierData &>(md);
2222 auto &legacy_md_shrinkwrap = reinterpret_cast<ShrinkwrapGpencilModifierData &>(legacy_md);
2223
2224 /* Shrinkwrap enums and flags do not have named types. */
2225 /* MOD_SHRINKWRAP_NEAREST_SURFACE etc. */
2226 md_shrinkwrap.shrink_type = legacy_md_shrinkwrap.shrink_type;
2227 /* MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR etc. */
2228 md_shrinkwrap.shrink_opts = legacy_md_shrinkwrap.shrink_opts;
2229 /* MOD_SHRINKWRAP_ON_SURFACE etc. */
2230 md_shrinkwrap.shrink_mode = legacy_md_shrinkwrap.shrink_mode;
2231 /* MOD_SHRINKWRAP_PROJECT_OVER_NORMAL etc. */
2232 md_shrinkwrap.proj_axis = legacy_md_shrinkwrap.proj_axis;
2233
2234 md_shrinkwrap.target = legacy_md_shrinkwrap.target;
2235 legacy_md_shrinkwrap.target = nullptr;
2236 md_shrinkwrap.aux_target = legacy_md_shrinkwrap.aux_target;
2237 legacy_md_shrinkwrap.aux_target = nullptr;
2238 md_shrinkwrap.keep_dist = legacy_md_shrinkwrap.keep_dist;
2239 md_shrinkwrap.proj_limit = legacy_md_shrinkwrap.proj_limit;
2240 md_shrinkwrap.subsurf_levels = legacy_md_shrinkwrap.subsurf_levels;
2241 md_shrinkwrap.smooth_factor = legacy_md_shrinkwrap.smooth_factor;
2242 md_shrinkwrap.smooth_step = legacy_md_shrinkwrap.smooth_step;
2243
2244 legacy_object_modifier_influence(md_shrinkwrap.influence,
2245 legacy_md_shrinkwrap.layername,
2246 legacy_md_shrinkwrap.layer_pass,
2247 legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_LAYER,
2248 legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_LAYERPASS,
2249 &legacy_md_shrinkwrap.material,
2250 legacy_md_shrinkwrap.pass_index,
2251 legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_MATERIAL,
2252 legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_PASS,
2253 legacy_md_shrinkwrap.vgname,
2254 legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_VGROUP,
2255 nullptr,
2256 false);
2257}
2258
2260 Object &object,
2261 GpencilModifierData &legacy_md)
2262{
2264 conversion_data, object, eModifierType_GreasePencilSmooth, legacy_md);
2265 auto &md_smooth = reinterpret_cast<GreasePencilSmoothModifierData &>(md);
2266 auto &legacy_md_smooth = reinterpret_cast<SmoothGpencilModifierData &>(legacy_md);
2267
2268 md_smooth.flag = 0;
2269 if (legacy_md_smooth.flag & GP_SMOOTH_MOD_LOCATION) {
2270 md_smooth.flag |= MOD_GREASE_PENCIL_SMOOTH_MOD_LOCATION;
2271 }
2272 if (legacy_md_smooth.flag & GP_SMOOTH_MOD_STRENGTH) {
2273 md_smooth.flag |= MOD_GREASE_PENCIL_SMOOTH_MOD_STRENGTH;
2274 }
2275 if (legacy_md_smooth.flag & GP_SMOOTH_MOD_THICKNESS) {
2277 }
2278 if (legacy_md_smooth.flag & GP_SMOOTH_MOD_UV) {
2279 md_smooth.flag |= MOD_GREASE_PENCIL_SMOOTH_MOD_UV;
2280 }
2281 if (legacy_md_smooth.flag & GP_SMOOTH_KEEP_SHAPE) {
2282 md_smooth.flag |= MOD_GREASE_PENCIL_SMOOTH_KEEP_SHAPE;
2283 }
2284 md_smooth.factor = legacy_md_smooth.factor;
2285 md_smooth.step = legacy_md_smooth.step;
2286
2287 legacy_object_modifier_influence(md_smooth.influence,
2288 legacy_md_smooth.layername,
2289 legacy_md_smooth.layer_pass,
2290 legacy_md_smooth.flag & GP_SMOOTH_INVERT_LAYER,
2291 legacy_md_smooth.flag & GP_SMOOTH_INVERT_LAYERPASS,
2292 &legacy_md_smooth.material,
2293 legacy_md_smooth.pass_index,
2294 legacy_md_smooth.flag & GP_SMOOTH_INVERT_MATERIAL,
2295 legacy_md_smooth.flag & GP_SMOOTH_INVERT_PASS,
2296 legacy_md_smooth.vgname,
2297 legacy_md_smooth.flag & GP_SMOOTH_INVERT_VGROUP,
2298 &legacy_md_smooth.curve_intensity,
2299 legacy_md_smooth.flag & GP_SMOOTH_CUSTOM_CURVE);
2300}
2301
2303 Object &object,
2304 GpencilModifierData &legacy_md)
2305{
2307 conversion_data, object, eModifierType_GreasePencilSubdiv, legacy_md);
2308 auto &md_subdiv = reinterpret_cast<GreasePencilSubdivModifierData &>(md);
2309 auto &legacy_md_subdiv = reinterpret_cast<SubdivGpencilModifierData &>(legacy_md);
2310
2311 switch (eSubdivGpencil_Type(legacy_md_subdiv.type)) {
2312 case GP_SUBDIV_CATMULL:
2314 break;
2315 case GP_SUBDIV_SIMPLE:
2316 md_subdiv.type = MOD_GREASE_PENCIL_SUBDIV_SIMPLE;
2317 break;
2318 }
2319 md_subdiv.level = legacy_md_subdiv.level;
2320
2321 legacy_object_modifier_influence(md_subdiv.influence,
2322 legacy_md_subdiv.layername,
2323 legacy_md_subdiv.layer_pass,
2324 legacy_md_subdiv.flag & GP_SUBDIV_INVERT_LAYER,
2325 legacy_md_subdiv.flag & GP_SUBDIV_INVERT_LAYERPASS,
2326 &legacy_md_subdiv.material,
2327 legacy_md_subdiv.pass_index,
2328 legacy_md_subdiv.flag & GP_SUBDIV_INVERT_MATERIAL,
2329 legacy_md_subdiv.flag & GP_SUBDIV_INVERT_PASS,
2330 "",
2331 false,
2332 nullptr,
2333 false);
2334}
2335
2337 Object &object,
2338 GpencilModifierData &legacy_md)
2339{
2341 conversion_data, object, eModifierType_GreasePencilTexture, legacy_md);
2342 auto &md_texture = reinterpret_cast<GreasePencilTextureModifierData &>(md);
2343 auto &legacy_md_texture = reinterpret_cast<TextureGpencilModifierData &>(legacy_md);
2344
2345 switch (eTextureGpencil_Mode(legacy_md_texture.mode)) {
2346 case STROKE:
2348 break;
2349 case FILL:
2350 md_texture.mode = MOD_GREASE_PENCIL_TEXTURE_FILL;
2351 break;
2352 case STROKE_AND_FILL:
2354 break;
2355 }
2356 switch (eTextureGpencil_Fit(legacy_md_texture.fit_method)) {
2357 case GP_TEX_FIT_STROKE:
2358 md_texture.fit_method = MOD_GREASE_PENCIL_TEXTURE_FIT_STROKE;
2359 break;
2361 md_texture.fit_method = MOD_GREASE_PENCIL_TEXTURE_CONSTANT_LENGTH;
2362 break;
2363 }
2364 md_texture.uv_offset = legacy_md_texture.uv_offset;
2365 md_texture.uv_scale = legacy_md_texture.uv_scale;
2366 md_texture.fill_rotation = legacy_md_texture.fill_rotation;
2367 copy_v2_v2(md_texture.fill_offset, legacy_md_texture.fill_offset);
2368 md_texture.fill_scale = legacy_md_texture.fill_scale;
2369 md_texture.layer_pass = legacy_md_texture.layer_pass;
2370 md_texture.alignment_rotation = legacy_md_texture.alignment_rotation;
2371
2372 legacy_object_modifier_influence(md_texture.influence,
2373 legacy_md_texture.layername,
2374 legacy_md_texture.layer_pass,
2375 legacy_md_texture.flag & GP_TEX_INVERT_LAYER,
2376 legacy_md_texture.flag & GP_TEX_INVERT_LAYERPASS,
2377 &legacy_md_texture.material,
2378 legacy_md_texture.pass_index,
2379 legacy_md_texture.flag & GP_TEX_INVERT_MATERIAL,
2380 legacy_md_texture.flag & GP_TEX_INVERT_PASS,
2381 legacy_md_texture.vgname,
2382 legacy_md_texture.flag & GP_TEX_INVERT_VGROUP,
2383 nullptr,
2384 false);
2385}
2386
2388 Object &object,
2389 GpencilModifierData &legacy_md)
2390{
2392 conversion_data, object, eModifierType_GreasePencilThickness, legacy_md);
2393 auto &md_thickness = reinterpret_cast<GreasePencilThickModifierData &>(md);
2394 auto &legacy_md_thickness = reinterpret_cast<ThickGpencilModifierData &>(legacy_md);
2395
2396 md_thickness.flag = 0;
2397 if (legacy_md_thickness.flag & GP_THICK_NORMALIZE) {
2398 md_thickness.flag |= MOD_GREASE_PENCIL_THICK_NORMALIZE;
2399 }
2400 if (legacy_md_thickness.flag & GP_THICK_WEIGHT_FACTOR) {
2401 md_thickness.flag |= MOD_GREASE_PENCIL_THICK_WEIGHT_FACTOR;
2402 }
2403 md_thickness.thickness_fac = legacy_md_thickness.thickness_fac;
2404 md_thickness.thickness = legacy_md_thickness.thickness * LEGACY_RADIUS_CONVERSION_FACTOR;
2405
2406 legacy_object_modifier_influence(md_thickness.influence,
2407 legacy_md_thickness.layername,
2408 legacy_md_thickness.layer_pass,
2409 legacy_md_thickness.flag & GP_THICK_INVERT_LAYER,
2410 legacy_md_thickness.flag & GP_THICK_INVERT_LAYERPASS,
2411 &legacy_md_thickness.material,
2412 legacy_md_thickness.pass_index,
2413 legacy_md_thickness.flag & GP_THICK_INVERT_MATERIAL,
2414 legacy_md_thickness.flag & GP_THICK_INVERT_PASS,
2415 legacy_md_thickness.vgname,
2416 legacy_md_thickness.flag & GP_THICK_INVERT_VGROUP,
2417 &legacy_md_thickness.curve_thickness,
2418 legacy_md_thickness.flag & GP_THICK_CUSTOM_CURVE);
2419}
2420
2421static void legacy_object_modifier_time(ConversionData &conversion_data,
2422 Object &object,
2423 GpencilModifierData &legacy_md)
2424{
2426 conversion_data, object, eModifierType_GreasePencilTime, legacy_md);
2427 auto &md_time = reinterpret_cast<GreasePencilTimeModifierData &>(md);
2428 auto &legacy_md_time = reinterpret_cast<TimeGpencilModifierData &>(legacy_md);
2429
2430 md_time.flag = 0;
2431 if (legacy_md_time.flag & GP_TIME_CUSTOM_RANGE) {
2433 }
2434 if (legacy_md_time.flag & GP_TIME_KEEP_LOOP) {
2435 md_time.flag |= MOD_GREASE_PENCIL_TIME_KEEP_LOOP;
2436 }
2437 switch (eTimeGpencil_Mode(legacy_md_time.mode)) {
2440 break;
2443 break;
2444 case GP_TIME_MODE_FIX:
2445 md_time.mode = MOD_GREASE_PENCIL_TIME_MODE_FIX;
2446 break;
2449 break;
2450 case GP_TIME_MODE_CHAIN:
2451 md_time.mode = MOD_GREASE_PENCIL_TIME_MODE_CHAIN;
2452 break;
2453 }
2454 md_time.offset = legacy_md_time.offset;
2455 md_time.frame_scale = legacy_md_time.frame_scale;
2456 md_time.sfra = legacy_md_time.sfra;
2457 md_time.efra = legacy_md_time.efra;
2458 md_time.segment_active_index = legacy_md_time.segment_active_index;
2459 md_time.segments_num = legacy_md_time.segments_len;
2460 MEM_SAFE_FREE(md_time.segments_array);
2461 md_time.segments_array = MEM_cnew_array<GreasePencilTimeModifierSegment>(
2462 legacy_md_time.segments_len, __func__);
2463 for (const int i : IndexRange(md_time.segments_num)) {
2464 GreasePencilTimeModifierSegment &dst_segment = md_time.segments_array[i];
2465 const TimeGpencilModifierSegment &src_segment = legacy_md_time.segments[i];
2466 STRNCPY(dst_segment.name, src_segment.name);
2467 switch (eTimeGpencil_Seg_Mode(src_segment.seg_mode)) {
2470 break;
2473 break;
2476 break;
2477 }
2478 dst_segment.segment_start = src_segment.seg_start;
2479 dst_segment.segment_end = src_segment.seg_end;
2480 dst_segment.segment_repeat = src_segment.seg_repeat;
2481 }
2482
2483 /* NOTE: GPv2 time modifier has a material pointer but it is unused. */
2484 legacy_object_modifier_influence(md_time.influence,
2485 legacy_md_time.layername,
2486 legacy_md_time.layer_pass,
2487 legacy_md_time.flag & GP_TIME_INVERT_LAYER,
2488 legacy_md_time.flag & GP_TIME_INVERT_LAYERPASS,
2489 nullptr,
2490 0,
2491 false,
2492 false,
2493 "",
2494 false,
2495 nullptr,
2496 false);
2497}
2498
2499static void legacy_object_modifier_tint(ConversionData &conversion_data,
2500 Object &object,
2501 GpencilModifierData &legacy_md)
2502{
2504 conversion_data, object, eModifierType_GreasePencilTint, legacy_md);
2505 auto &md_tint = reinterpret_cast<GreasePencilTintModifierData &>(md);
2506 auto &legacy_md_tint = reinterpret_cast<TintGpencilModifierData &>(legacy_md);
2507
2508 md_tint.flag = 0;
2509 if (legacy_md_tint.flag & GP_TINT_WEIGHT_FACTOR) {
2511 }
2512 switch (eGp_Vertex_Mode(legacy_md_tint.mode)) {
2513 case GPPAINT_MODE_BOTH:
2514 md_tint.color_mode = MOD_GREASE_PENCIL_COLOR_BOTH;
2515 break;
2517 md_tint.color_mode = MOD_GREASE_PENCIL_COLOR_STROKE;
2518 break;
2519 case GPPAINT_MODE_FILL:
2520 md_tint.color_mode = MOD_GREASE_PENCIL_COLOR_FILL;
2521 break;
2522 }
2523 switch (eTintGpencil_Type(legacy_md_tint.type)) {
2524 case GP_TINT_UNIFORM:
2525 md_tint.tint_mode = MOD_GREASE_PENCIL_TINT_UNIFORM;
2526 break;
2527 case GP_TINT_GRADIENT:
2528 md_tint.tint_mode = MOD_GREASE_PENCIL_TINT_GRADIENT;
2529 break;
2530 }
2531 md_tint.factor = legacy_md_tint.factor;
2532 md_tint.radius = legacy_md_tint.radius;
2533 copy_v3_v3(md_tint.color, legacy_md_tint.rgb);
2534 md_tint.object = legacy_md_tint.object;
2535 legacy_md_tint.object = nullptr;
2536 MEM_SAFE_FREE(md_tint.color_ramp);
2537 md_tint.color_ramp = legacy_md_tint.colorband;
2538 legacy_md_tint.colorband = nullptr;
2539
2540 legacy_object_modifier_influence(md_tint.influence,
2541 legacy_md_tint.layername,
2542 legacy_md_tint.layer_pass,
2543 legacy_md_tint.flag & GP_TINT_INVERT_LAYER,
2544 legacy_md_tint.flag & GP_TINT_INVERT_LAYERPASS,
2545 &legacy_md_tint.material,
2546 legacy_md_tint.pass_index,
2547 legacy_md_tint.flag & GP_TINT_INVERT_MATERIAL,
2548 legacy_md_tint.flag & GP_TINT_INVERT_PASS,
2549 legacy_md_tint.vgname,
2550 legacy_md_tint.flag & GP_TINT_INVERT_VGROUP,
2551 &legacy_md_tint.curve_intensity,
2552 legacy_md_tint.flag & GP_TINT_CUSTOM_CURVE);
2553}
2554
2556 Object &object,
2557 GpencilModifierData &legacy_md)
2558{
2560 conversion_data, object, eModifierType_GreasePencilWeightAngle, legacy_md);
2561 auto &md_weight_angle = reinterpret_cast<GreasePencilWeightAngleModifierData &>(md);
2562 auto &legacy_md_weight_angle = reinterpret_cast<WeightAngleGpencilModifierData &>(legacy_md);
2563
2564 md_weight_angle.flag = 0;
2565 if (legacy_md_weight_angle.flag & GP_WEIGHT_MULTIPLY_DATA) {
2566 md_weight_angle.flag |= MOD_GREASE_PENCIL_WEIGHT_ANGLE_MULTIPLY_DATA;
2567 }
2568 if (legacy_md_weight_angle.flag & GP_WEIGHT_INVERT_OUTPUT) {
2569 md_weight_angle.flag |= MOD_GREASE_PENCIL_WEIGHT_ANGLE_INVERT_OUTPUT;
2570 }
2571 switch (eGpencilModifierSpace(legacy_md_weight_angle.space)) {
2572 case GP_SPACE_LOCAL:
2573 md_weight_angle.space = MOD_GREASE_PENCIL_WEIGHT_ANGLE_SPACE_LOCAL;
2574 break;
2575 case GP_SPACE_WORLD:
2576 md_weight_angle.space = MOD_GREASE_PENCIL_WEIGHT_ANGLE_SPACE_WORLD;
2577 break;
2578 }
2579 md_weight_angle.axis = legacy_md_weight_angle.axis;
2580 STRNCPY(md_weight_angle.target_vgname, legacy_md_weight_angle.target_vgname);
2581 md_weight_angle.min_weight = legacy_md_weight_angle.min_weight;
2582 md_weight_angle.angle = legacy_md_weight_angle.angle;
2583
2584 legacy_object_modifier_influence(md_weight_angle.influence,
2585 legacy_md_weight_angle.layername,
2586 legacy_md_weight_angle.layer_pass,
2587 legacy_md_weight_angle.flag & GP_WEIGHT_INVERT_LAYER,
2588 legacy_md_weight_angle.flag & GP_WEIGHT_INVERT_LAYERPASS,
2589 &legacy_md_weight_angle.material,
2590 legacy_md_weight_angle.pass_index,
2591 legacy_md_weight_angle.flag & GP_WEIGHT_INVERT_MATERIAL,
2592 legacy_md_weight_angle.flag & GP_WEIGHT_INVERT_PASS,
2593 legacy_md_weight_angle.vgname,
2594 legacy_md_weight_angle.flag & GP_WEIGHT_INVERT_VGROUP,
2595 nullptr,
2596 false);
2597}
2598
2600 Object &object,
2601 GpencilModifierData &legacy_md)
2602{
2604 conversion_data, object, eModifierType_GreasePencilWeightProximity, legacy_md);
2605 auto &md_weight_prox = reinterpret_cast<GreasePencilWeightProximityModifierData &>(md);
2606 auto &legacy_md_weight_prox = reinterpret_cast<WeightProxGpencilModifierData &>(legacy_md);
2607
2608 md_weight_prox.flag = 0;
2609 if (legacy_md_weight_prox.flag & GP_WEIGHT_MULTIPLY_DATA) {
2611 }
2612 if (legacy_md_weight_prox.flag & GP_WEIGHT_INVERT_OUTPUT) {
2614 }
2615 STRNCPY(md_weight_prox.target_vgname, legacy_md_weight_prox.target_vgname);
2616 md_weight_prox.min_weight = legacy_md_weight_prox.min_weight;
2617 md_weight_prox.dist_start = legacy_md_weight_prox.dist_start;
2618 md_weight_prox.dist_end = legacy_md_weight_prox.dist_end;
2619 md_weight_prox.object = legacy_md_weight_prox.object;
2620 legacy_md_weight_prox.object = nullptr;
2621
2622 legacy_object_modifier_influence(md_weight_prox.influence,
2623 legacy_md_weight_prox.layername,
2624 legacy_md_weight_prox.layer_pass,
2625 legacy_md_weight_prox.flag & GP_WEIGHT_INVERT_LAYER,
2626 legacy_md_weight_prox.flag & GP_WEIGHT_INVERT_LAYERPASS,
2627 &legacy_md_weight_prox.material,
2628 legacy_md_weight_prox.pass_index,
2629 legacy_md_weight_prox.flag & GP_WEIGHT_INVERT_MATERIAL,
2630 legacy_md_weight_prox.flag & GP_WEIGHT_INVERT_PASS,
2631 legacy_md_weight_prox.vgname,
2632 legacy_md_weight_prox.flag & GP_WEIGHT_INVERT_VGROUP,
2633 nullptr,
2634 false);
2635}
2636
2638 Object &object,
2639 GpencilModifierData &legacy_md)
2640{
2642 conversion_data, object, eModifierType_GreasePencilLineart, legacy_md);
2643 auto &md_lineart = reinterpret_cast<GreasePencilLineartModifierData &>(md);
2644 auto &legacy_md_lineart = reinterpret_cast<LineartGpencilModifierData &>(legacy_md);
2645
2646 greasepencil::convert::lineart_wrap_v3(&legacy_md_lineart, &md_lineart);
2647}
2648
2650 Object &object,
2651 GpencilModifierData &legacy_md)
2652{
2654 conversion_data, object, eModifierType_GreasePencilBuild, legacy_md);
2655 auto &md_build = reinterpret_cast<GreasePencilBuildModifierData &>(md);
2656 auto &legacy_md_build = reinterpret_cast<BuildGpencilModifierData &>(legacy_md);
2657
2658 md_build.flag = 0;
2659 if (legacy_md_build.flag & GP_BUILD_RESTRICT_TIME) {
2661 }
2662 if (legacy_md_build.flag & GP_BUILD_USE_FADING) {
2663 md_build.flag |= MOD_GREASE_PENCIL_BUILD_USE_FADING;
2664 }
2665
2666 switch (legacy_md_build.mode) {
2669 break;
2672 break;
2674 default:
2676 break;
2677 }
2678
2679 switch (legacy_md_build.time_alignment) {
2680 default:
2682 md_build.time_alignment = MOD_GREASE_PENCIL_BUILD_TIMEALIGN_START;
2683 break;
2685 md_build.time_alignment = MOD_GREASE_PENCIL_BUILD_TIMEALIGN_END;
2686 break;
2687 }
2688
2689 switch (legacy_md_build.time_mode) {
2690 default:
2692 md_build.time_mode = MOD_GREASE_PENCIL_BUILD_TIMEMODE_FRAMES;
2693 break;
2696 break;
2698 md_build.time_mode = MOD_GREASE_PENCIL_BUILD_TIMEMODE_DRAWSPEED;
2699 break;
2700 }
2701
2702 switch (legacy_md_build.transition) {
2703 default:
2705 md_build.transition = MOD_GREASE_PENCIL_BUILD_TRANSITION_GROW;
2706 break;
2708 md_build.transition = MOD_GREASE_PENCIL_BUILD_TRANSITION_SHRINK;
2709 break;
2711 md_build.transition = MOD_GREASE_PENCIL_BUILD_TRANSITION_VANISH;
2712 break;
2713 }
2714
2715 md_build.start_frame = legacy_md_build.start_frame;
2716 md_build.end_frame = legacy_md_build.end_frame;
2717 md_build.start_delay = legacy_md_build.start_delay;
2718 md_build.length = legacy_md_build.length;
2719 md_build.fade_fac = legacy_md_build.fade_fac;
2720 md_build.fade_opacity_strength = legacy_md_build.fade_opacity_strength;
2721 md_build.fade_thickness_strength = legacy_md_build.fade_thickness_strength;
2722 md_build.percentage_fac = legacy_md_build.percentage_fac;
2723 md_build.speed_fac = legacy_md_build.speed_fac;
2724 md_build.speed_maxgap = legacy_md_build.speed_maxgap;
2725 md_build.object = legacy_md_build.object;
2726 STRNCPY(md_build.target_vgname, legacy_md_build.target_vgname);
2727
2728 legacy_object_modifier_influence(md_build.influence,
2729 legacy_md_build.layername,
2730 legacy_md_build.layer_pass,
2731 legacy_md_build.flag & GP_WEIGHT_INVERT_LAYER,
2732 legacy_md_build.flag & GP_WEIGHT_INVERT_LAYERPASS,
2733 &legacy_md_build.material,
2734 legacy_md_build.pass_index,
2735 legacy_md_build.flag & GP_WEIGHT_INVERT_MATERIAL,
2736 legacy_md_build.flag & GP_WEIGHT_INVERT_PASS,
2737 legacy_md_build.target_vgname,
2738 legacy_md_build.flag & GP_WEIGHT_INVERT_VGROUP,
2739 nullptr,
2740 false);
2741}
2742
2744 Object &object,
2745 GpencilModifierData &legacy_md)
2746{
2748 conversion_data, object, eModifierType_GreasePencilSimplify, legacy_md);
2749 auto &md_simplify = reinterpret_cast<GreasePencilSimplifyModifierData &>(md);
2750 auto &legacy_md_simplify = reinterpret_cast<SimplifyGpencilModifierData &>(legacy_md);
2751
2752 switch (legacy_md_simplify.mode) {
2753 case GP_SIMPLIFY_FIXED:
2755 break;
2757 md_simplify.mode = MOD_GREASE_PENCIL_SIMPLIFY_ADAPTIVE;
2758 break;
2759 case GP_SIMPLIFY_SAMPLE:
2760 md_simplify.mode = MOD_GREASE_PENCIL_SIMPLIFY_SAMPLE;
2761 break;
2762 case GP_SIMPLIFY_MERGE:
2763 md_simplify.mode = MOD_GREASE_PENCIL_SIMPLIFY_MERGE;
2764 break;
2765 }
2766
2767 md_simplify.step = legacy_md_simplify.step;
2768 md_simplify.factor = legacy_md_simplify.factor;
2769 md_simplify.length = legacy_md_simplify.length;
2770 md_simplify.sharp_threshold = legacy_md_simplify.sharp_threshold;
2771 md_simplify.distance = legacy_md_simplify.distance;
2772
2773 legacy_object_modifier_influence(md_simplify.influence,
2774 legacy_md_simplify.layername,
2775 legacy_md_simplify.layer_pass,
2776 legacy_md_simplify.flag & GP_SIMPLIFY_INVERT_LAYER,
2777 legacy_md_simplify.flag & GP_SIMPLIFY_INVERT_LAYERPASS,
2778 &legacy_md_simplify.material,
2779 legacy_md_simplify.pass_index,
2780 legacy_md_simplify.flag & GP_SIMPLIFY_INVERT_MATERIAL,
2781 legacy_md_simplify.flag & GP_SIMPLIFY_INVERT_PASS,
2782 "",
2783 false,
2784 nullptr,
2785 false);
2786}
2787
2788static void legacy_object_modifiers(ConversionData &conversion_data, Object &object)
2789{
2790 BLI_assert(BLI_listbase_is_empty(&object.modifiers));
2791
2792 while (GpencilModifierData *gpd_md = static_cast<GpencilModifierData *>(
2793 BLI_pophead(&object.greasepencil_modifiers)))
2794 {
2795 switch (gpd_md->type) {
2797 /* Unknown type, just ignore. */
2798 break;
2800 legacy_object_modifier_armature(conversion_data, object, *gpd_md);
2801 break;
2803 legacy_object_modifier_array(conversion_data, object, *gpd_md);
2804 break;
2806 legacy_object_modifier_color(conversion_data, object, *gpd_md);
2807 break;
2809 legacy_object_modifier_dash(conversion_data, object, *gpd_md);
2810 break;
2812 legacy_object_modifier_envelope(conversion_data, object, *gpd_md);
2813 break;
2815 legacy_object_modifier_hook(conversion_data, object, *gpd_md);
2816 break;
2818 legacy_object_modifier_lattice(conversion_data, object, *gpd_md);
2819 break;
2821 legacy_object_modifier_length(conversion_data, object, *gpd_md);
2822 break;
2824 legacy_object_modifier_mirror(conversion_data, object, *gpd_md);
2825 break;
2827 legacy_object_modifier_multiply(conversion_data, object, *gpd_md);
2828 break;
2830 legacy_object_modifier_noise(conversion_data, object, *gpd_md);
2831 break;
2833 legacy_object_modifier_offset(conversion_data, object, *gpd_md);
2834 break;
2836 legacy_object_modifier_opacity(conversion_data, object, *gpd_md);
2837 break;
2839 legacy_object_modifier_outline(conversion_data, object, *gpd_md);
2840 break;
2842 legacy_object_modifier_shrinkwrap(conversion_data, object, *gpd_md);
2843 break;
2845 legacy_object_modifier_smooth(conversion_data, object, *gpd_md);
2846 break;
2848 legacy_object_modifier_subdiv(conversion_data, object, *gpd_md);
2849 break;
2851 legacy_object_modifier_texture(conversion_data, object, *gpd_md);
2852 break;
2854 legacy_object_modifier_thickness(conversion_data, object, *gpd_md);
2855 break;
2857 legacy_object_modifier_time(conversion_data, object, *gpd_md);
2858 break;
2860 legacy_object_modifier_tint(conversion_data, object, *gpd_md);
2861 break;
2863 legacy_object_modifier_weight_angle(conversion_data, object, *gpd_md);
2864 break;
2866 legacy_object_modifier_weight_proximity(conversion_data, object, *gpd_md);
2867 break;
2869 legacy_object_modifier_lineart(conversion_data, object, *gpd_md);
2870 break;
2872 legacy_object_modifier_build(conversion_data, object, *gpd_md);
2873 break;
2875 legacy_object_modifier_simplify(conversion_data, object, *gpd_md);
2876 break;
2877 }
2878
2880 }
2881}
2882
2901{
2902 /* Annotations mapping, keys are existing GPv2 IDs actually used as annotations, values are
2903 * either:
2904 * - nullptr: this annotation is never used by any object, there was no need to duplicate it.
2905 * - new GPv2 ID: this annotation was also used by objects, this is its new duplicated ID. */
2906 Map<bGPdata *, bGPdata *> annotations_gpv2;
2907 /* All legacy GPv2 data used by objects. */
2908 Set<bGPdata *> object_gpv2;
2909
2910 /* Check all GP objects. */
2911 LISTBASE_FOREACH (Object *, object, &bmain.objects) {
2912 if (object->type != OB_GPENCIL_LEGACY) {
2913 continue;
2914 }
2915 bGPdata *legacy_gpd = static_cast<bGPdata *>(object->data);
2916 if (!legacy_gpd) {
2917 continue;
2918 }
2919 if ((legacy_gpd->flag & GP_DATA_ANNOTATIONS) != 0) {
2920 legacy_gpd->flag &= ~GP_DATA_ANNOTATIONS;
2921 }
2922 object_gpv2.add(legacy_gpd);
2923 }
2924
2925 /* Detect all annotations currently used as such, and de-duplicate them if they are also used by
2926 * objects. */
2927
2928 auto sanitize_gpv2_annotation = [&](bGPdata **legacy_gpd_p) {
2929 bGPdata *legacy_gpd = *legacy_gpd_p;
2930 if (!legacy_gpd) {
2931 return;
2932 }
2933
2934 bGPdata *new_annotation_gpd = annotations_gpv2.lookup_or_add(legacy_gpd, nullptr);
2935 if (!object_gpv2.contains(legacy_gpd)) {
2936 /* Legacy annotation GPv2 data not used by any object, just ensure that it is properly
2937 * tagged. */
2938 BLI_assert(!new_annotation_gpd);
2939 if ((legacy_gpd->flag & GP_DATA_ANNOTATIONS) == 0) {
2940 legacy_gpd->flag |= GP_DATA_ANNOTATIONS;
2941 }
2942 return;
2943 }
2944
2945 /* Legacy GP data also used by objects. Create the duplicate of legacy GPv2 data for
2946 * annotations, if not yet done. */
2947 if (!new_annotation_gpd) {
2948 new_annotation_gpd = reinterpret_cast<bGPdata *>(BKE_id_copy_in_lib(
2949 &bmain, legacy_gpd->id.lib, &legacy_gpd->id, nullptr, nullptr, LIB_ID_COPY_DEFAULT));
2950 new_annotation_gpd->flag |= GP_DATA_ANNOTATIONS;
2951 id_us_min(&new_annotation_gpd->id);
2952 annotations_gpv2.add_overwrite(legacy_gpd, new_annotation_gpd);
2953 }
2954
2955 /* Assign the annotation duplicate ID to the annotation pointer. */
2956 BLI_assert(new_annotation_gpd->flag & GP_DATA_ANNOTATIONS);
2957 id_us_min(&legacy_gpd->id);
2958 *legacy_gpd_p = new_annotation_gpd;
2959 id_us_plus_no_lib(&new_annotation_gpd->id);
2960 };
2961
2962 LISTBASE_FOREACH (Scene *, scene, &bmain.scenes) {
2963 sanitize_gpv2_annotation(&scene->gpd);
2964 }
2965
2966 ID *id_iter;
2967 FOREACH_MAIN_ID_BEGIN (&bmain, id_iter) {
2968 if (bNodeTree *node_tree = bke::node_tree_from_id(id_iter)) {
2969 sanitize_gpv2_annotation(&node_tree->gpd);
2970 }
2971 }
2974 sanitize_gpv2_annotation(&node_tree->gpd);
2975 }
2976
2977 LISTBASE_FOREACH (MovieClip *, movie_clip, &bmain.movieclips) {
2978 sanitize_gpv2_annotation(&movie_clip->gpd);
2979
2980 LISTBASE_FOREACH (MovieTrackingObject *, mvc_tracking_object, &movie_clip->tracking.objects) {
2981 LISTBASE_FOREACH (MovieTrackingTrack *, mvc_track, &mvc_tracking_object->tracks) {
2982 sanitize_gpv2_annotation(&mvc_track->gpd);
2983 }
2985 MovieTrackingPlaneTrack *, mvc_plane_track, &mvc_tracking_object->plane_tracks)
2986 {
2987 for (int i = 0; i < mvc_plane_track->point_tracksnr; i++) {
2988 sanitize_gpv2_annotation(&mvc_plane_track->point_tracks[i]->gpd);
2989 }
2990 }
2991 }
2992 }
2993
2994 LISTBASE_FOREACH (bScreen *, screen, &bmain.screens) {
2995 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
2996 LISTBASE_FOREACH (SpaceLink *, space_link, &area->spacedata) {
2997 switch (eSpace_Type(space_link->spacetype)) {
2998 case SPACE_SEQ: {
2999 SpaceSeq *space_sequencer = reinterpret_cast<SpaceSeq *>(space_link);
3000 sanitize_gpv2_annotation(&space_sequencer->gpd);
3001 break;
3002 }
3003 case SPACE_IMAGE: {
3004 SpaceImage *space_image = reinterpret_cast<SpaceImage *>(space_link);
3005 sanitize_gpv2_annotation(&space_image->gpd);
3006 break;
3007 }
3008 case SPACE_NODE: {
3009 SpaceNode *space_node = reinterpret_cast<SpaceNode *>(space_link);
3010 sanitize_gpv2_annotation(&space_node->gpd);
3011 break;
3012 }
3013 case SPACE_EMPTY:
3014 case SPACE_VIEW3D:
3015 /* #View3D.gpd is deprecated and can be ignored here. */
3016 case SPACE_GRAPH:
3017 case SPACE_OUTLINER:
3018 case SPACE_PROPERTIES:
3019 case SPACE_FILE:
3020 case SPACE_INFO:
3021 case SPACE_TEXT:
3022 case SPACE_ACTION:
3023 case SPACE_NLA:
3024 case SPACE_SCRIPT:
3025 case SPACE_CONSOLE:
3026 case SPACE_USERPREF:
3027 case SPACE_CLIP:
3028 case SPACE_TOPBAR:
3029 case SPACE_STATUSBAR:
3030 case SPACE_SPREADSHEET:
3031 break;
3032 }
3033 }
3034 }
3035 }
3036}
3037
3038static void legacy_gpencil_object(ConversionData &conversion_data, Object &object)
3039{
3040 BLI_assert((GS(static_cast<ID *>(object.data)->name) == ID_GD_LEGACY));
3041
3042 bGPdata *gpd = static_cast<bGPdata *>(object.data);
3043
3044 GreasePencil *new_grease_pencil = conversion_data.legacy_to_greasepencil_data.lookup_default(
3045 gpd, nullptr);
3046 const bool do_gpencil_data_conversion = (new_grease_pencil == nullptr);
3047
3048 if (!new_grease_pencil) {
3049 new_grease_pencil = static_cast<GreasePencil *>(
3050 BKE_id_new_in_lib(&conversion_data.bmain, gpd->id.lib, ID_GP, gpd->id.name + 2));
3051 id_us_min(&new_grease_pencil->id);
3052 }
3053
3054 object.data = new_grease_pencil;
3055 object.type = OB_GREASE_PENCIL;
3056
3057 /* NOTE: Could also use #BKE_id_free_us, to also free the legacy GP if not used anymore? */
3058 id_us_min(&gpd->id);
3059 id_us_plus(&new_grease_pencil->id);
3060
3061 if (do_gpencil_data_conversion) {
3062 legacy_gpencil_to_grease_pencil(conversion_data, *new_grease_pencil, *gpd);
3063 conversion_data.legacy_to_greasepencil_data.add(gpd, new_grease_pencil);
3064 }
3065
3066 legacy_object_modifiers(conversion_data, object);
3067 /* Convert the animation of the "uniform thickness" setting of the thickness modifier. */
3068 legacy_object_thickness_modifier_thickness_anim(conversion_data, object);
3069
3070 /* Layer adjustments should be added after all other modifiers. */
3071 layer_adjustments_to_modifiers(conversion_data, *gpd, object);
3072 /* Thickness factor is applied after all other changes to the radii. */
3073 thickness_factor_to_modifier(conversion_data, *gpd, object);
3074
3076}
3077
3078void legacy_main(Main &bmain,
3079 BlendfileLinkAppendContext *lapp_context,
3080 BlendFileReadReport & /*reports*/)
3081{
3082 ConversionData conversion_data(bmain, lapp_context);
3083
3084 /* Ensure that annotations are fully separated from object usages of legacy GPv2 data. */
3086
3087 LISTBASE_FOREACH (Object *, object, &bmain.objects) {
3088 if (object->type != OB_GPENCIL_LEGACY) {
3089 continue;
3090 }
3091 legacy_gpencil_object(conversion_data, *object);
3092 }
3093
3094 /* Potential other usages of legacy bGPdata IDs also need to be remapped to their matching new
3095 * GreasePencil counterparts. */
3096 bke::id::IDRemapper gpd_remapper;
3097 /* Allow remapping from legacy bGPdata IDs to new GreasePencil ones. */
3098 gpd_remapper.allow_idtype_mismatch = true;
3099
3100 LISTBASE_FOREACH (bGPdata *, legacy_gpd, &bmain.gpencils) {
3101 /* Annotations still use legacy `bGPdata`, these should not be converted. Call to
3102 * #legacy_gpencil_sanitize_annotations above ensured to fully separate annotations from object
3103 * legacy grease pencil. */
3104 if ((legacy_gpd->flag & GP_DATA_ANNOTATIONS) != 0) {
3105 continue;
3106 }
3107 GreasePencil *new_grease_pencil = conversion_data.legacy_to_greasepencil_data.lookup_default(
3108 legacy_gpd, nullptr);
3109 if (!new_grease_pencil) {
3110 new_grease_pencil = static_cast<GreasePencil *>(
3111 BKE_id_new_in_lib(&bmain, legacy_gpd->id.lib, ID_GP, legacy_gpd->id.name + 2));
3112 id_us_min(&new_grease_pencil->id);
3113 legacy_gpencil_to_grease_pencil(conversion_data, *new_grease_pencil, *legacy_gpd);
3114 conversion_data.legacy_to_greasepencil_data.add(legacy_gpd, new_grease_pencil);
3115 }
3116 gpd_remapper.add(&legacy_gpd->id, &new_grease_pencil->id);
3117 }
3118
3120
3121 if (conversion_data.lapp_context) {
3123 conversion_data.lapp_context,
3124 [&conversion_data](BlendfileLinkAppendContext *lapp_context,
3125 BlendfileLinkAppendContextItem *item) -> bool {
3126 ID *item_new_id = BKE_blendfile_link_append_context_item_newid_get(lapp_context, item);
3127 if (!item_new_id || GS(item_new_id->name) != ID_GD_LEGACY) {
3128 return true;
3129 }
3130 GreasePencil **item_grease_pencil =
3132 reinterpret_cast<bGPdata *>(item_new_id));
3133 if (item_grease_pencil && *item_grease_pencil) {
3135 lapp_context, item, &(*item_grease_pencil)->id);
3136 }
3137 return true;
3138 },
3142 }
3143}
3144
3147{
3148 lmd->edge_types = lmd_legacy->edge_types;
3149 lmd->source_type = lmd_legacy->source_type;
3150 lmd->use_multiple_levels = lmd_legacy->use_multiple_levels;
3151 lmd->level_start = lmd_legacy->level_start;
3152 lmd->level_end = lmd_legacy->level_end;
3153 lmd->source_camera = lmd_legacy->source_camera;
3154 lmd->light_contour_object = lmd_legacy->light_contour_object;
3155 lmd->source_object = lmd_legacy->source_object;
3156 lmd->source_collection = lmd_legacy->source_collection;
3157 lmd->target_material = lmd_legacy->target_material;
3158 STRNCPY(lmd->target_layer, lmd_legacy->target_layer);
3160 STRNCPY(lmd->vgname, lmd_legacy->vgname);
3161 lmd->overscan = lmd_legacy->overscan;
3162 lmd->shadow_camera_fov = lmd_legacy->shadow_camera_fov;
3163 lmd->shadow_camera_size = lmd_legacy->shadow_camera_size;
3164 lmd->shadow_camera_near = lmd_legacy->shadow_camera_near;
3165 lmd->shadow_camera_far = lmd_legacy->shadow_camera_far;
3166 lmd->opacity = lmd_legacy->opacity;
3167 lmd->thickness = lmd_legacy->thickness;
3168 lmd->mask_switches = lmd_legacy->mask_switches;
3169 lmd->material_mask_bits = lmd_legacy->material_mask_bits;
3170 lmd->intersection_mask = lmd_legacy->intersection_mask;
3171 lmd->shadow_selection = lmd_legacy->shadow_selection;
3172 lmd->silhouette_selection = lmd_legacy->silhouette_selection;
3173 lmd->crease_threshold = lmd_legacy->crease_threshold;
3177 lmd->calculation_flags = lmd_legacy->calculation_flags;
3178 lmd->flags = lmd_legacy->flags;
3179 lmd->stroke_depth_offset = lmd_legacy->stroke_depth_offset;
3180 lmd->level_start_override = lmd_legacy->level_start_override;
3181 lmd->level_end_override = lmd_legacy->level_end_override;
3182 lmd->edge_types_override = lmd_legacy->edge_types_override;
3185 lmd->cache = lmd_legacy->cache;
3186 lmd->la_data_ptr = lmd_legacy->la_data_ptr;
3187}
3188
3191{
3192 lmd_legacy->edge_types = lmd->edge_types;
3193 lmd_legacy->source_type = lmd->source_type;
3194 lmd_legacy->use_multiple_levels = lmd->use_multiple_levels;
3195 lmd_legacy->level_start = lmd->level_start;
3196 lmd_legacy->level_end = lmd->level_end;
3197 lmd_legacy->source_camera = lmd->source_camera;
3198 lmd_legacy->light_contour_object = lmd->light_contour_object;
3199 lmd_legacy->source_object = lmd->source_object;
3200 lmd_legacy->source_collection = lmd->source_collection;
3201 lmd_legacy->target_material = lmd->target_material;
3203 STRNCPY(lmd_legacy->vgname, lmd->vgname);
3204 lmd_legacy->overscan = lmd->overscan;
3205 lmd_legacy->shadow_camera_fov = lmd->shadow_camera_fov;
3206 lmd_legacy->shadow_camera_size = lmd->shadow_camera_size;
3207 lmd_legacy->shadow_camera_near = lmd->shadow_camera_near;
3208 lmd_legacy->shadow_camera_far = lmd->shadow_camera_far;
3209 lmd_legacy->opacity = lmd->opacity;
3210 lmd_legacy->thickness = lmd->thickness;
3211 lmd_legacy->mask_switches = lmd->mask_switches;
3212 lmd_legacy->material_mask_bits = lmd->material_mask_bits;
3213 lmd_legacy->intersection_mask = lmd->intersection_mask;
3214 lmd_legacy->shadow_selection = lmd->shadow_selection;
3215 lmd_legacy->silhouette_selection = lmd->silhouette_selection;
3216 lmd_legacy->crease_threshold = lmd->crease_threshold;
3220 lmd_legacy->calculation_flags = lmd->calculation_flags;
3221 lmd_legacy->flags = lmd->flags;
3222 lmd_legacy->stroke_depth_offset = lmd->stroke_depth_offset;
3223 lmd_legacy->level_start_override = lmd->level_start_override;
3224 lmd_legacy->level_end_override = lmd->level_end_override;
3225 lmd_legacy->edge_types_override = lmd->edge_types_override;
3228 lmd_legacy->cache = lmd->cache;
3229 lmd_legacy->la_data_ptr = lmd->la_data_ptr;
3230}
3231
3232} // 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
@ LIB_ID_COPY_DEFAULT
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
@ 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
@ 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
@ 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
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
unsigned int U
Definition btGjkEpa3.h:78
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
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:388
bool is_empty() const
Definition BLI_array.hh:253
const Value * lookup_ptr(const Key &key) const
Definition BLI_map.hh:484
bool add_overwrite(const Key &key, const Value &value)
Definition BLI_map.hh:301
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
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 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)
void resize(int points_num, int curves_num)
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)
Material material
DEGForeachIDComponentCallback callback
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)
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)
decltype(::ActionSlot::handle) slot_handle_t
bool assign_tmpaction(bAction *action, OwnedAnimData owned_adt)
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 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 find_used_vertex_groups(const bGPDframe &gpf, const ListBase &all_names, ListBase &r_vertex_group_names, Array< int > &r_indices)
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
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, 3 > float4x3
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:337
VecBase< float, 3 > float3
#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
ModifierTypeType type
ListBase strips
bAction * act
struct Object * parent
struct bGPdata * gpd
struct bGPdata * gpd
struct bGPdata * gpd
ListBase vertex_group_names
void * default_value
float locy
float locx
static MatBase identity()
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)