Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
# SPDX-FileCopyrightText: 2023 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
set(INC
../include
../../makesrna
# RNA_prototypes.hh
${CMAKE_BINARY_DIR}/source/blender/makesrna
)
set(INC_SYS
)
set(SRC
curve_ops.cc
editcurve.cc
editcurve_add.cc
editcurve_paint.cc
editcurve_pen.cc
editcurve_query.cc
editcurve_select.cc
editcurve_undo.cc
editfont.cc
editfont_undo.cc
curve_intern.hh
)
set(LIB
PRIVATE bf::blenkernel
PRIVATE bf::animrig
PRIVATE bf::blenlib
PRIVATE bf::blentranslation
PRIVATE bf::depsgraph
PRIVATE bf::dna
PRIVATE bf::extern::curve_fit_nd
PRIVATE bf::gpu
PRIVATE bf::intern::clog
PRIVATE bf::intern::guardedalloc
PRIVATE bf::windowmanager
)
blender_add_lib(bf_editor_curve "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# RNA_prototypes.hh
add_dependencies(bf_editor_curve bf_rna)

View File

@@ -0,0 +1,254 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edcurve
*/
#pragma once
#include "BLI_sys_types.h"
#include "DNA_curve_types.h"
#include "DNA_listBase.h"
namespace blender {
/* internal exports only */
struct BPoint;
struct Base;
struct BezTriple;
struct Curve;
struct EditNurb;
struct Nurb;
struct Object;
struct View3D;
struct ViewContext;
struct wmKeyConfig;
struct wmKeyMap;
struct wmOperatorType;
/* `editfont.cc` */
enum {
DEL_NEXT_CHAR,
DEL_PREV_CHAR,
DEL_NEXT_WORD,
DEL_PREV_WORD,
DEL_SELECTION,
DEL_NEXT_SEL,
DEL_PREV_SEL
};
enum { CASE_LOWER, CASE_UPPER };
enum {
LINE_BEGIN,
LINE_END,
TEXT_BEGIN,
TEXT_END,
PREV_CHAR,
NEXT_CHAR,
PREV_WORD,
NEXT_WORD,
PREV_LINE,
NEXT_LINE,
PREV_PAGE,
NEXT_PAGE
};
enum eVisible_Types {
HIDDEN = true,
VISIBLE = false,
};
enum eEndPoint_Types {
FIRST = true,
LAST = false,
};
enum eCurveElem_Types {
CURVE_VERTEX = 0,
CURVE_SEGMENT,
};
/* internal select utils */
/**
* Returns 1 in case (de)selection was successful.
*/
bool select_beztriple(BezTriple *bezt,
bool selstatus,
eBezTriple_Flag flag,
eVisible_Types hidden);
/**
* Returns 1 in case (de)selection was successful.
*/
bool select_bpoint(BPoint *bp, bool selstatus, eBezTriple_Flag flag, bool hidden);
void FONT_OT_text_insert(wmOperatorType *ot);
void FONT_OT_line_break(wmOperatorType *ot);
void FONT_OT_case_toggle(wmOperatorType *ot);
void FONT_OT_case_set(wmOperatorType *ot);
void FONT_OT_style_toggle(wmOperatorType *ot);
void FONT_OT_style_set(wmOperatorType *ot);
void FONT_OT_select_all(wmOperatorType *ot);
void FONT_OT_text_copy(wmOperatorType *ot);
void FONT_OT_text_cut(wmOperatorType *ot);
void FONT_OT_text_paste(wmOperatorType *ot);
void FONT_OT_text_paste_from_file(wmOperatorType *ot);
void FONT_OT_text_insert_unicode(wmOperatorType *ot);
void FONT_OT_selection_set(wmOperatorType *ot);
void FONT_OT_select_word(wmOperatorType *ot);
void FONT_OT_move(wmOperatorType *ot);
void FONT_OT_move_select(wmOperatorType *ot);
void FONT_OT_delete(wmOperatorType *ot);
void FONT_OT_change_character(wmOperatorType *ot);
void FONT_OT_change_spacing(wmOperatorType *ot);
void FONT_OT_open(wmOperatorType *ot);
void FONT_OT_unlink(wmOperatorType *ot);
void FONT_OT_textbox_add(wmOperatorType *ot);
void FONT_OT_textbox_remove(wmOperatorType *ot);
/* `editcurve.cc` */
void CURVE_OT_hide(wmOperatorType *ot);
void CURVE_OT_reveal(wmOperatorType *ot);
void CURVE_OT_separate(wmOperatorType *ot);
void CURVE_OT_split(wmOperatorType *ot);
void CURVE_OT_duplicate(wmOperatorType *ot);
void CURVE_OT_delete(wmOperatorType *ot);
void CURVE_OT_dissolve_verts(wmOperatorType *ot);
void CURVE_OT_spline_type_set(wmOperatorType *ot);
void CURVE_OT_radius_set(wmOperatorType *ot);
void CURVE_OT_spline_weight_set(wmOperatorType *ot);
void CURVE_OT_handle_type_set(wmOperatorType *ot);
void CURVE_OT_normals_make_consistent(wmOperatorType *ot);
void CURVE_OT_decimate(wmOperatorType *ot);
void CURVE_OT_shade_smooth(wmOperatorType *ot);
void CURVE_OT_shade_flat(wmOperatorType *ot);
void CURVE_OT_tilt_clear(wmOperatorType *ot);
void CURVE_OT_smooth(wmOperatorType *ot);
void CURVE_OT_smooth_weight(wmOperatorType *ot);
void CURVE_OT_smooth_radius(wmOperatorType *ot);
void CURVE_OT_smooth_tilt(wmOperatorType *ot);
void CURVE_OT_switch_direction(wmOperatorType *ot);
void CURVE_OT_subdivide(wmOperatorType *ot);
void CURVE_OT_make_segment(wmOperatorType *ot);
void CURVE_OT_spin(wmOperatorType *ot);
void CURVE_OT_vertex_add(wmOperatorType *ot);
void CURVE_OT_extrude(wmOperatorType *ot);
void CURVE_OT_cyclic_toggle(wmOperatorType *ot);
void CURVE_OT_match_texture_space(wmOperatorType *ot);
/* exported for editcurve_undo.cc */
CVKeyIndexMap *ED_curve_keyindex_hash_duplicate(CVKeyIndexMap *keyindex);
void ED_curve_keyindex_update_nurb(EditNurb *editnurb, Nurb *nu, Nurb *newnu);
/* exported for `editcurve_pen.cc` */
int ed_editcurve_addvert(Curve *cu, EditNurb *editnurb, View3D *v3d, const float location_init[3]);
bool curve_toggle_cyclic(View3D *v3d, ListBaseT<Nurb> *editnurb, int direction);
void ed_dissolve_bez_segment(BezTriple *bezt_prev,
BezTriple *bezt_next,
const Nurb *nu,
const Curve *cu,
const uint span_len,
const uint span_step[2]);
/* helper functions */
void ed_editnurb_translate_flag(ListBaseT<Nurb> *editnurb,
eBezTriple_Flag flag,
const float vec[3],
bool is_2d);
/**
* Only for #OB_SURF.
*/
bool ed_editnurb_extrude_flag(EditNurb *editnurb, eBezTriple_Flag flag);
/**
* \param axis: is in world-space.
* \param cent: is in object-space.
*/
bool ed_editnurb_spin(
float viewmat[4][4], View3D *v3d, Object *obedit, const float axis[3], const float cent[3]);
/* `editcurve_select.cc` */
void CURVE_OT_de_select_first(wmOperatorType *ot);
void CURVE_OT_de_select_last(wmOperatorType *ot);
void CURVE_OT_select_all(wmOperatorType *ot);
void CURVE_OT_select_linked(wmOperatorType *ot);
void CURVE_OT_select_linked_pick(wmOperatorType *ot);
void CURVE_OT_select_row(wmOperatorType *ot);
void CURVE_OT_select_next(wmOperatorType *ot);
void CURVE_OT_select_previous(wmOperatorType *ot);
void CURVE_OT_select_more(wmOperatorType *ot);
void CURVE_OT_select_less(wmOperatorType *ot);
void CURVE_OT_select_random(wmOperatorType *ot);
void CURVE_OT_select_nth(wmOperatorType *ot);
void CURVE_OT_select_similar(wmOperatorType *ot);
void CURVE_OT_shortest_path_pick(wmOperatorType *ot);
/* `editcurve_add.cc` */
void CURVE_OT_primitive_bezier_curve_add(wmOperatorType *ot);
void CURVE_OT_primitive_bezier_circle_add(wmOperatorType *ot);
void CURVE_OT_primitive_nurbs_curve_add(wmOperatorType *ot);
void CURVE_OT_primitive_nurbs_circle_add(wmOperatorType *ot);
void CURVE_OT_primitive_nurbs_path_add(wmOperatorType *ot);
void SURFACE_OT_primitive_nurbs_surface_curve_add(wmOperatorType *ot);
void SURFACE_OT_primitive_nurbs_surface_circle_add(wmOperatorType *ot);
void SURFACE_OT_primitive_nurbs_surface_surface_add(wmOperatorType *ot);
void SURFACE_OT_primitive_nurbs_surface_cylinder_add(wmOperatorType *ot);
void SURFACE_OT_primitive_nurbs_surface_sphere_add(wmOperatorType *ot);
void SURFACE_OT_primitive_nurbs_surface_torus_add(wmOperatorType *ot);
/* `editcurve_query.cc` */
bool ED_curve_pick_vert(ViewContext *vc,
short sel,
Nurb **r_nurb,
BezTriple **r_bezt,
BPoint **r_bp,
short *r_handle,
Base **r_base);
/**
* Pick the nearest `r_nurb` and `r_bezt` or `r_bp`.
* \param select: selected vertices have a disadvantage.
* \param dist_px: The selection distance in pixels.
* \param r_handle: For bezier triples, set the handle index [0, 1, 2].
*/
bool ED_curve_pick_vert_ex(ViewContext *vc,
bool select,
int dist_px,
Nurb **r_nurb,
BezTriple **r_bezt,
BPoint **r_bp,
short *r_handle,
Base **r_base);
void ED_curve_nurb_vert_selected_find(
Curve *cu, View3D *v3d, Nurb **r_nu, BezTriple **r_bezt, BPoint **r_bp);
/* `editcurve_paint.cc` */
void CURVE_OT_draw(wmOperatorType *ot);
/* `editcurve_pen.cc` */
void CURVE_OT_pen(wmOperatorType *ot);
wmKeyMap *curve_pen_modal_keymap(wmKeyConfig *keyconf);
} // namespace blender

View File

@@ -0,0 +1,161 @@
/* SPDX-FileCopyrightText: 2009 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edcurve
*/
#include <cstdlib>
#include "RNA_access.hh"
#include "WM_api.hh"
#include "WM_types.hh"
#include "ED_curve.hh"
#include "ED_screen.hh"
#include "curve_intern.hh"
namespace blender {
/************************* registration ****************************/
void ED_operatortypes_curve()
{
WM_operatortype_append(FONT_OT_text_insert);
WM_operatortype_append(FONT_OT_line_break);
WM_operatortype_append(FONT_OT_case_toggle);
WM_operatortype_append(FONT_OT_case_set);
WM_operatortype_append(FONT_OT_style_toggle);
WM_operatortype_append(FONT_OT_style_set);
WM_operatortype_append(FONT_OT_select_all);
WM_operatortype_append(FONT_OT_text_copy);
WM_operatortype_append(FONT_OT_text_cut);
WM_operatortype_append(FONT_OT_text_paste);
WM_operatortype_append(FONT_OT_text_paste_from_file);
WM_operatortype_append(FONT_OT_text_insert_unicode);
WM_operatortype_append(FONT_OT_selection_set);
WM_operatortype_append(FONT_OT_select_word);
WM_operatortype_append(FONT_OT_move);
WM_operatortype_append(FONT_OT_move_select);
WM_operatortype_append(FONT_OT_delete);
WM_operatortype_append(FONT_OT_change_character);
WM_operatortype_append(FONT_OT_change_spacing);
WM_operatortype_append(FONT_OT_open);
WM_operatortype_append(FONT_OT_unlink);
WM_operatortype_append(FONT_OT_textbox_add);
WM_operatortype_append(FONT_OT_textbox_remove);
WM_operatortype_append(CURVE_OT_hide);
WM_operatortype_append(CURVE_OT_reveal);
WM_operatortype_append(CURVE_OT_separate);
WM_operatortype_append(CURVE_OT_split);
WM_operatortype_append(CURVE_OT_duplicate);
WM_operatortype_append(CURVE_OT_delete);
WM_operatortype_append(CURVE_OT_dissolve_verts);
WM_operatortype_append(CURVE_OT_spline_type_set);
WM_operatortype_append(CURVE_OT_radius_set);
WM_operatortype_append(CURVE_OT_spline_weight_set);
WM_operatortype_append(CURVE_OT_handle_type_set);
WM_operatortype_append(CURVE_OT_normals_make_consistent);
WM_operatortype_append(CURVE_OT_decimate);
WM_operatortype_append(CURVE_OT_shade_smooth);
WM_operatortype_append(CURVE_OT_shade_flat);
WM_operatortype_append(CURVE_OT_tilt_clear);
WM_operatortype_append(CURVE_OT_primitive_bezier_curve_add);
WM_operatortype_append(CURVE_OT_primitive_bezier_circle_add);
WM_operatortype_append(CURVE_OT_primitive_nurbs_curve_add);
WM_operatortype_append(CURVE_OT_primitive_nurbs_circle_add);
WM_operatortype_append(CURVE_OT_primitive_nurbs_path_add);
WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_curve_add);
WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_circle_add);
WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_surface_add);
WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_cylinder_add);
WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_sphere_add);
WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_torus_add);
WM_operatortype_append(CURVE_OT_smooth);
WM_operatortype_append(CURVE_OT_smooth_weight);
WM_operatortype_append(CURVE_OT_smooth_radius);
WM_operatortype_append(CURVE_OT_smooth_tilt);
WM_operatortype_append(CURVE_OT_de_select_first);
WM_operatortype_append(CURVE_OT_de_select_last);
WM_operatortype_append(CURVE_OT_select_all);
WM_operatortype_append(CURVE_OT_select_linked);
WM_operatortype_append(CURVE_OT_select_linked_pick);
WM_operatortype_append(CURVE_OT_select_row);
WM_operatortype_append(CURVE_OT_select_next);
WM_operatortype_append(CURVE_OT_select_previous);
WM_operatortype_append(CURVE_OT_select_more);
WM_operatortype_append(CURVE_OT_select_less);
WM_operatortype_append(CURVE_OT_select_random);
WM_operatortype_append(CURVE_OT_select_nth);
WM_operatortype_append(CURVE_OT_select_similar);
WM_operatortype_append(CURVE_OT_shortest_path_pick);
WM_operatortype_append(CURVE_OT_switch_direction);
WM_operatortype_append(CURVE_OT_subdivide);
WM_operatortype_append(CURVE_OT_make_segment);
WM_operatortype_append(CURVE_OT_spin);
WM_operatortype_append(CURVE_OT_vertex_add);
WM_operatortype_append(CURVE_OT_draw);
WM_operatortype_append(CURVE_OT_pen);
WM_operatortype_append(CURVE_OT_extrude);
WM_operatortype_append(CURVE_OT_cyclic_toggle);
WM_operatortype_append(CURVE_OT_match_texture_space);
}
void ED_operatormacros_curve()
{
wmOperatorType *ot;
wmOperatorTypeMacro *otmacro;
ot = WM_operatortype_append_macro("CURVE_OT_duplicate_move",
"Add Duplicate",
"Duplicate curve and move",
OPTYPE_UNDO | OPTYPE_REGISTER);
WM_operatortype_macro_define(ot, "CURVE_OT_duplicate");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
RNA_boolean_set(otmacro->ptr, "mirror", false);
ot = WM_operatortype_append_macro("CURVE_OT_extrude_move",
"Extrude Curve and Move",
"Extrude curve and move result",
OPTYPE_UNDO | OPTYPE_REGISTER);
WM_operatortype_macro_define(ot, "CURVE_OT_extrude");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
RNA_boolean_set(otmacro->ptr, "mirror", false);
}
void ED_keymap_curve(wmKeyConfig *keyconf)
{
/* only set in editmode font, by space_view3d listener */
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Font", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = ED_operator_editfont;
/* only set in editmode curve, by space_view3d listener */
keymap = WM_keymap_ensure(keyconf, "Curve", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = ED_operator_editsurfcurve;
curve_pen_modal_keymap(keyconf);
}
} // namespace blender

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,832 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edcurve
*/
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BLT_translation.hh"
#include "BKE_context.hh"
#include "BKE_curve.hh"
#include "BKE_layer.hh"
#include "DEG_depsgraph.hh"
#include "RNA_access.hh"
#include "WM_api.hh"
#include "WM_types.hh"
#include "ED_curve.hh"
#include "ED_object.hh"
#include "ED_screen.hh"
#include "ED_view3d.hh"
#include "curve_intern.hh"
namespace blender {
static const float nurbcircle[8][2] = {
{0.0, -1.0},
{-1.0, -1.0},
{-1.0, 0.0},
{-1.0, 1.0},
{0.0, 1.0},
{1.0, 1.0},
{1.0, 0.0},
{1.0, -1.0},
};
/************ add primitive, used by object/ module ****************/
static const char *get_curve_defname(int type)
{
int stype = type & CU_PRIMITIVE;
if ((type & CU_TYPE) == CU_BEZIER) {
switch (stype) {
case CU_PRIM_CURVE:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "BézierCurve");
case CU_PRIM_CIRCLE:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "BézierCircle");
case CU_PRIM_PATH:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "CurvePath");
default:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "Curve");
}
}
else {
switch (stype) {
case CU_PRIM_CURVE:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "NurbsCurve");
case CU_PRIM_CIRCLE:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "NurbsCircle");
case CU_PRIM_PATH:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "NurbsPath");
default:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "Curve");
}
}
}
static const char *get_surf_defname(int type)
{
int stype = type & CU_PRIMITIVE;
switch (stype) {
case CU_PRIM_CURVE:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "SurfCurve");
case CU_PRIM_CIRCLE:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "SurfCircle");
case CU_PRIM_PATCH:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "SurfPatch");
case CU_PRIM_TUBE:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "SurfCylinder");
case CU_PRIM_SPHERE:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "SurfSphere");
case CU_PRIM_DONUT:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "SurfTorus");
default:
return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE_LEGACY, "Surface");
}
}
Nurb *ED_curve_add_nurbs_primitive(
bContext *C, Object *obedit, float mat[4][4], int type, int newob)
{
static int xzproj = 0; /* this function calls itself... */
ListBaseT<Nurb> *editnurb = object_editcurve_get(obedit);
RegionView3D *rv3d = ED_view3d_context_rv3d(C);
Nurb *nu = nullptr;
BezTriple *bezt;
BPoint *bp;
Curve *cu = id_cast<Curve *>(obedit->data);
float vec[3], zvec[3] = {0.0f, 0.0f, 1.0f};
float umat[4][4], viewmat[4][4];
float fac;
int a, b;
const float grid = 1.0f;
const eNurbType cutype = eNurbType(type & CU_TYPE); /* poly, bezier, nurbs, etc */
const int stype = (type & CU_PRIMITIVE);
unit_m4(umat);
unit_m4(viewmat);
if (rv3d) {
copy_m4_m4(viewmat, rv3d->viewmat);
copy_v3_v3(zvec, rv3d->viewinv[2]);
}
BKE_nurbList_flag_set(editnurb, BEZT_FLAG_SELECT, false);
/* these types call this function to return a Nurb */
if (!ELEM(stype, CU_PRIM_TUBE, CU_PRIM_DONUT)) {
nu = MEM_new<Nurb>("addNurbprim");
nu->type = cutype;
nu->resolu = cu->resolu;
nu->resolv = cu->resolv;
}
switch (stype) {
case CU_PRIM_CURVE: /* curve */
nu->resolu = cu->resolu;
if (cutype == CU_BEZIER) {
nu->pntsu = 2;
nu->bezt = MEM_new_array_zeroed<BezTriple>(nu->pntsu, "addNurbprim1");
bezt = nu->bezt;
bezt->h1 = bezt->h2 = HD_ALIGN;
bezt->f1 = bezt->f2 = bezt->f3 = BEZT_FLAG_SELECT;
bezt->radius = 1.0;
bezt->vec[1][0] += -grid;
bezt->vec[0][0] += -1.5f * grid;
bezt->vec[0][1] += -0.5f * grid;
bezt->vec[2][0] += -0.5f * grid;
bezt->vec[2][1] += 0.5f * grid;
for (a = 0; a < 3; a++) {
mul_m4_v3(mat, bezt->vec[a]);
}
bezt++;
bezt->h1 = bezt->h2 = HD_ALIGN;
bezt->f1 = bezt->f2 = bezt->f3 = BEZT_FLAG_SELECT;
bezt->radius = bezt->weight = 1.0;
bezt->vec[0][0] = 0;
bezt->vec[0][1] = 0;
bezt->vec[1][0] = grid;
bezt->vec[1][1] = 0;
bezt->vec[2][0] = grid * 2;
bezt->vec[2][1] = 0;
for (a = 0; a < 3; a++) {
mul_m4_v3(mat, bezt->vec[a]);
}
BKE_nurb_handles_calc(nu);
}
else {
nu->pntsu = 4;
nu->pntsv = 1;
nu->orderu = 4;
nu->bp = MEM_new_array_zeroed<BPoint>(nu->pntsu, "addNurbprim3");
bp = nu->bp;
for (a = 0; a < 4; a++, bp++) {
bp->vec[3] = 1.0;
bp->f1 = SELECT;
bp->radius = bp->weight = 1.0;
}
bp = nu->bp;
bp->vec[0] += -1.5f * grid;
bp++;
bp->vec[0] += -grid;
bp->vec[1] += grid;
bp++;
bp->vec[0] += grid;
bp->vec[1] += grid;
bp++;
bp->vec[0] += 1.5f * grid;
bp = nu->bp;
for (a = 0; a < 4; a++, bp++) {
mul_m4_v3(mat, bp->vec);
}
if (cutype == CU_NURBS) {
nu->knotsu = nullptr; /* nurbs_knot_calc_u allocates */
BKE_nurb_knot_calc_u(nu);
}
}
break;
case CU_PRIM_PATH: /* 5 point path */
nu->pntsu = 5;
nu->pntsv = 1;
nu->orderu = 5;
nu->flagu = CU_NURB_ENDPOINT; /* endpoint */
nu->resolu = cu->resolu;
nu->bp = MEM_new_array_zeroed<BPoint>(nu->pntsu, "addNurbprim3");
bp = nu->bp;
for (a = 0; a < 5; a++, bp++) {
bp->vec[3] = 1.0;
bp->f1 = SELECT;
bp->radius = bp->weight = 1.0;
}
bp = nu->bp;
bp->vec[0] += -2.0f * grid;
bp++;
bp->vec[0] += -grid;
bp++;
bp++;
bp->vec[0] += grid;
bp++;
bp->vec[0] += 2.0f * grid;
bp = nu->bp;
for (a = 0; a < 5; a++, bp++) {
mul_m4_v3(mat, bp->vec);
}
if (cutype == CU_NURBS) {
nu->knotsu = nullptr; /* nurbs_knot_calc_u allocates */
BKE_nurb_knot_calc_u(nu);
}
break;
case CU_PRIM_CIRCLE: /* circle */
nu->resolu = cu->resolu;
if (cutype == CU_BEZIER) {
nu->pntsu = 4;
nu->bezt = MEM_new_array_zeroed<BezTriple>(nu->pntsu, "addNurbprim1");
nu->flagu = CU_NURB_CYCLIC;
bezt = nu->bezt;
bezt->h1 = bezt->h2 = HD_AUTO;
bezt->f1 = bezt->f2 = bezt->f3 = BEZT_FLAG_SELECT;
bezt->vec[1][0] += -grid;
for (a = 0; a < 3; a++) {
mul_m4_v3(mat, bezt->vec[a]);
}
bezt->radius = bezt->weight = 1.0;
bezt++;
bezt->h1 = bezt->h2 = HD_AUTO;
bezt->f1 = bezt->f2 = bezt->f3 = BEZT_FLAG_SELECT;
bezt->vec[1][1] += grid;
for (a = 0; a < 3; a++) {
mul_m4_v3(mat, bezt->vec[a]);
}
bezt->radius = bezt->weight = 1.0;
bezt++;
bezt->h1 = bezt->h2 = HD_AUTO;
bezt->f1 = bezt->f2 = bezt->f3 = BEZT_FLAG_SELECT;
bezt->vec[1][0] += grid;
for (a = 0; a < 3; a++) {
mul_m4_v3(mat, bezt->vec[a]);
}
bezt->radius = bezt->weight = 1.0;
bezt++;
bezt->h1 = bezt->h2 = HD_AUTO;
bezt->f1 = bezt->f2 = bezt->f3 = BEZT_FLAG_SELECT;
bezt->vec[1][1] += -grid;
for (a = 0; a < 3; a++) {
mul_m4_v3(mat, bezt->vec[a]);
}
bezt->radius = bezt->weight = 1.0;
BKE_nurb_handles_calc(nu);
}
else if (cutype == CU_NURBS) { /* nurb */
nu->pntsu = 8;
nu->pntsv = 1;
nu->orderu = 3;
nu->bp = MEM_new_array_zeroed<BPoint>(nu->pntsu, "addNurbprim6");
nu->flagu = CU_NURB_CYCLIC | CU_NURB_BEZIER | CU_NURB_ENDPOINT;
bp = nu->bp;
for (a = 0; a < 8; a++) {
bp->f1 = SELECT;
if (xzproj == 0) {
bp->vec[0] += nurbcircle[a][0] * grid;
bp->vec[1] += nurbcircle[a][1] * grid;
}
else {
bp->vec[0] += 0.25f * nurbcircle[a][0] * grid - 0.75f * grid;
bp->vec[2] += 0.25f * nurbcircle[a][1] * grid;
}
if (a & 1) {
bp->vec[3] = 0.5 * M_SQRT2;
}
else {
bp->vec[3] = 1.0;
}
mul_m4_v3(mat, bp->vec);
bp->radius = bp->weight = 1.0;
bp++;
}
BKE_nurb_knot_calc_u(nu);
}
break;
case CU_PRIM_PATCH: /* 4x4 patch */
if (cutype == CU_NURBS) { /* nurb */
nu->pntsu = 4;
nu->pntsv = 4;
nu->orderu = 4;
nu->orderv = 4;
nu->flag = CU_SMOOTH;
nu->bp = MEM_new_array_zeroed<BPoint>((4 * 4), "addNurbprim6");
nu->flagu = {};
nu->flagv = {};
bp = nu->bp;
for (a = 0; a < 4; a++) {
for (b = 0; b < 4; b++) {
bp->f1 = SELECT;
fac = float(a) - 1.5f;
bp->vec[0] += fac * grid;
fac = float(b) - 1.5f;
bp->vec[1] += fac * grid;
if (ELEM(a, 1, 2) && ELEM(b, 1, 2)) {
bp->vec[2] += grid;
}
mul_m4_v3(mat, bp->vec);
bp->vec[3] = 1.0;
bp++;
}
}
BKE_nurb_knot_calc_u(nu);
BKE_nurb_knot_calc_v(nu);
}
break;
case CU_PRIM_TUBE: /* Cylinder */
if (cutype == CU_NURBS) {
nu = ED_curve_add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0);
nu->resolu = cu->resolu;
nu->flag = CU_SMOOTH;
BLI_addtail(editnurb, nu); /* temporal for extrude and translate */
vec[0] = vec[1] = 0.0;
vec[2] = -grid;
mul_mat3_m4_v3(mat, vec);
ed_editnurb_translate_flag(editnurb, BEZT_FLAG_SELECT, vec, CU_IS_2D(cu));
ed_editnurb_extrude_flag(cu->editnurb, BEZT_FLAG_SELECT);
mul_v3_fl(vec, -2.0f);
ed_editnurb_translate_flag(editnurb, BEZT_FLAG_SELECT, vec, CU_IS_2D(cu));
BLI_remlink(editnurb, nu);
a = nu->pntsu * nu->pntsv;
bp = nu->bp;
while (a-- > 0) {
bp->f1 |= SELECT;
bp++;
}
}
break;
case CU_PRIM_SPHERE: /* sphere */
if (cutype == CU_NURBS) {
const float tmp_cent[3] = {0.0f, 0.0f, 0.0f};
const float tmp_vec[3] = {0.0f, 0.0f, 1.0f};
nu->pntsu = 5;
nu->pntsv = 1;
nu->orderu = 3;
nu->resolu = cu->resolu;
nu->resolv = cu->resolv;
nu->flag = CU_SMOOTH;
nu->bp = MEM_new_array_zeroed<BPoint>(nu->pntsu, "addNurbprim6");
nu->flagu = {};
bp = nu->bp;
for (a = 0; a < 5; a++) {
bp->f1 = SELECT;
bp->vec[0] += nurbcircle[a][0] * grid;
bp->vec[2] += nurbcircle[a][1] * grid;
if (a & 1) {
bp->vec[3] = 0.5 * M_SQRT2;
}
else {
bp->vec[3] = 1.0;
}
mul_m4_v3(mat, bp->vec);
bp++;
}
nu->flagu = CU_NURB_BEZIER | CU_NURB_ENDPOINT;
BKE_nurb_knot_calc_u(nu);
BLI_addtail(editnurb, nu); /* temporal for spin */
if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) {
ed_editnurb_spin(umat, nullptr, obedit, tmp_vec, tmp_cent);
}
else if (U.flag & USER_ADD_VIEWALIGNED) {
ed_editnurb_spin(viewmat, nullptr, obedit, zvec, mat[3]);
}
else {
ed_editnurb_spin(umat, nullptr, obedit, tmp_vec, mat[3]);
}
BKE_nurb_knot_calc_v(nu);
a = nu->pntsu * nu->pntsv;
bp = nu->bp;
while (a-- > 0) {
bp->f1 |= SELECT;
bp++;
}
BLI_remlink(editnurb, nu);
}
break;
case CU_PRIM_DONUT: /* torus */
if (cutype == CU_NURBS) {
const float tmp_cent[3] = {0.0f, 0.0f, 0.0f};
const float tmp_vec[3] = {0.0f, 0.0f, 1.0f};
xzproj = 1;
nu = ED_curve_add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0);
xzproj = 0;
nu->resolu = cu->resolu;
nu->resolv = cu->resolv;
nu->flag = CU_SMOOTH;
BLI_addtail(editnurb, nu); /* temporal for spin */
/* same as above */
if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) {
ed_editnurb_spin(umat, nullptr, obedit, tmp_vec, tmp_cent);
}
else if (U.flag & USER_ADD_VIEWALIGNED) {
ed_editnurb_spin(viewmat, nullptr, obedit, zvec, mat[3]);
}
else {
ed_editnurb_spin(umat, nullptr, obedit, tmp_vec, mat[3]);
}
BLI_remlink(editnurb, nu);
a = nu->pntsu * nu->pntsv;
bp = nu->bp;
while (a-- > 0) {
bp->f1 |= SELECT;
bp++;
}
}
break;
default: /* should never happen */
BLI_assert_msg(0, "invalid nurbs type");
return nullptr;
}
BLI_assert(nu != nullptr);
if (nu) { /* should always be set */
nu->flag |= CU_SMOOTH;
cu->actnu = editnurb->count();
cu->actvert = CU_ACT_NONE;
if (CU_IS_2D(cu)) {
BKE_nurb_project_2d(nu);
}
}
return nu;
}
static wmOperatorStatus curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
BKE_view_layer_synced_ensure(*bmain, scene, view_layer);
Object *obedit = BKE_view_layer_edit_object_get(view_layer);
ListBaseT<Nurb> *editnurb;
Nurb *nu;
bool newob = false;
bool enter_editmode;
ushort local_view_bits;
float loc[3], rot[3];
float mat[4][4];
WM_operator_view3d_unit_defaults(C, op);
ed::object::add_generic_get_opts(
C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
if (!isSurf) { /* adding curve */
if (obedit == nullptr || obedit->type != OB_CURVES_LEGACY) {
const char *name = get_curve_defname(type);
Curve *cu;
obedit = ed::object::add_type(C, OB_CURVES_LEGACY, name, loc, rot, true, local_view_bits);
newob = true;
cu = id_cast<Curve *>(obedit->data);
if (type & CU_PRIM_PATH) {
cu->flag |= CU_PATH | CU_3D;
}
}
else {
DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
}
}
else { /* adding surface */
if (obedit == nullptr || obedit->type != OB_SURF) {
const char *name = get_surf_defname(type);
obedit = ed::object::add_type(C, OB_SURF, name, loc, rot, true, local_view_bits);
newob = true;
}
else {
DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
}
}
float radius = RNA_float_get(op->ptr, "radius");
float scale[3];
copy_v3_fl(scale, radius);
ed::object::new_primitive_matrix(C, obedit, loc, rot, scale, mat);
nu = ED_curve_add_nurbs_primitive(C, obedit, mat, type, newob);
editnurb = object_editcurve_get(obedit);
BLI_addtail(editnurb, nu);
/* userdef */
if (newob && !enter_editmode) {
ed::object::editmode_exit_ex(bmain, scene, obedit, ed::object::EM_FREEDATA);
}
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
return OPERATOR_FINISHED;
}
static wmOperatorStatus curve_prim_add(bContext *C, wmOperator *op, int type)
{
return curvesurf_prim_add(C, op, type, 0);
}
static wmOperatorStatus surf_prim_add(bContext *C, wmOperator *op, int type)
{
return curvesurf_prim_add(C, op, type, 1);
}
/* ******************** Curves ******************* */
static wmOperatorStatus add_primitive_bezier_exec(bContext *C, wmOperator *op)
{
return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CURVE);
}
void CURVE_OT_primitive_bezier_curve_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Bézier";
ot->description = "Construct a Bézier Curve";
ot->idname = "CURVE_OT_primitive_bezier_curve_add";
/* API callbacks. */
ot->exec = add_primitive_bezier_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ed::object::add_unit_props_radius(ot);
ed::object::add_generic_props(ot, true);
}
static wmOperatorStatus add_primitive_bezier_circle_exec(bContext *C, wmOperator *op)
{
return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CIRCLE);
}
void CURVE_OT_primitive_bezier_circle_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Bézier Circle";
ot->description = "Construct a Bézier Circle";
ot->idname = "CURVE_OT_primitive_bezier_circle_add";
/* API callbacks. */
ot->exec = add_primitive_bezier_circle_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ed::object::add_unit_props_radius(ot);
ed::object::add_generic_props(ot, true);
}
static wmOperatorStatus add_primitive_nurbs_curve_exec(bContext *C, wmOperator *op)
{
return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CURVE);
}
void CURVE_OT_primitive_nurbs_curve_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Nurbs Curve";
ot->description = "Construct a Nurbs Curve";
ot->idname = "CURVE_OT_primitive_nurbs_curve_add";
/* API callbacks. */
ot->exec = add_primitive_nurbs_curve_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ed::object::add_unit_props_radius(ot);
ed::object::add_generic_props(ot, true);
}
static wmOperatorStatus add_primitive_nurbs_circle_exec(bContext *C, wmOperator *op)
{
return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CIRCLE);
}
void CURVE_OT_primitive_nurbs_circle_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Nurbs Circle";
ot->description = "Construct a Nurbs Circle";
ot->idname = "CURVE_OT_primitive_nurbs_circle_add";
/* API callbacks. */
ot->exec = add_primitive_nurbs_circle_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ed::object::add_unit_props_radius(ot);
ed::object::add_generic_props(ot, true);
}
static wmOperatorStatus add_primitive_curve_path_exec(bContext *C, wmOperator *op)
{
return curve_prim_add(C, op, CU_NURBS | CU_PRIM_PATH);
}
void CURVE_OT_primitive_nurbs_path_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Path";
ot->description = "Construct a Path";
ot->idname = "CURVE_OT_primitive_nurbs_path_add";
/* API callbacks. */
ot->exec = add_primitive_curve_path_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ed::object::add_unit_props_radius(ot);
ed::object::add_generic_props(ot, true);
}
/* **************** NURBS surfaces ********************** */
static wmOperatorStatus add_primitive_nurbs_surface_curve_exec(bContext *C, wmOperator *op)
{
return surf_prim_add(C, op, CU_PRIM_CURVE | CU_NURBS);
}
void SURFACE_OT_primitive_nurbs_surface_curve_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Surface Curve";
ot->description = "Construct a NURBS surface curve";
ot->idname = "SURFACE_OT_primitive_nurbs_surface_curve_add";
/* API callbacks. */
ot->exec = add_primitive_nurbs_surface_curve_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ed::object::add_unit_props_radius(ot);
ed::object::add_generic_props(ot, true);
}
static wmOperatorStatus add_primitive_nurbs_surface_circle_exec(bContext *C, wmOperator *op)
{
return surf_prim_add(C, op, CU_PRIM_CIRCLE | CU_NURBS);
}
void SURFACE_OT_primitive_nurbs_surface_circle_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Surface Circle";
ot->description = "Construct a NURBS surface circle";
ot->idname = "SURFACE_OT_primitive_nurbs_surface_circle_add";
/* API callbacks. */
ot->exec = add_primitive_nurbs_surface_circle_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ed::object::add_unit_props_radius(ot);
ed::object::add_generic_props(ot, true);
}
static wmOperatorStatus add_primitive_nurbs_surface_surface_exec(bContext *C, wmOperator *op)
{
return surf_prim_add(C, op, CU_PRIM_PATCH | CU_NURBS);
}
void SURFACE_OT_primitive_nurbs_surface_surface_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Surface Patch";
ot->description = "Construct a NURBS surface patch";
ot->idname = "SURFACE_OT_primitive_nurbs_surface_surface_add";
/* API callbacks. */
ot->exec = add_primitive_nurbs_surface_surface_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ed::object::add_unit_props_radius(ot);
ed::object::add_generic_props(ot, true);
}
static wmOperatorStatus add_primitive_nurbs_surface_cylinder_exec(bContext *C, wmOperator *op)
{
return surf_prim_add(C, op, CU_PRIM_TUBE | CU_NURBS);
}
void SURFACE_OT_primitive_nurbs_surface_cylinder_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Surface Cylinder";
ot->description = "Construct a NURBS surface cylinder";
ot->idname = "SURFACE_OT_primitive_nurbs_surface_cylinder_add";
/* API callbacks. */
ot->exec = add_primitive_nurbs_surface_cylinder_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ed::object::add_unit_props_radius(ot);
ed::object::add_generic_props(ot, true);
}
static wmOperatorStatus add_primitive_nurbs_surface_sphere_exec(bContext *C, wmOperator *op)
{
return surf_prim_add(C, op, CU_PRIM_SPHERE | CU_NURBS);
}
void SURFACE_OT_primitive_nurbs_surface_sphere_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Surface Sphere";
ot->description = "Construct a NURBS surface sphere";
ot->idname = "SURFACE_OT_primitive_nurbs_surface_sphere_add";
/* API callbacks. */
ot->exec = add_primitive_nurbs_surface_sphere_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ed::object::add_unit_props_radius(ot);
ed::object::add_generic_props(ot, true);
}
static wmOperatorStatus add_primitive_nurbs_surface_torus_exec(bContext *C, wmOperator *op)
{
return surf_prim_add(C, op, CU_PRIM_DONUT | CU_NURBS);
}
void SURFACE_OT_primitive_nurbs_surface_torus_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Surface Torus";
ot->description = "Construct a NURBS surface torus";
ot->idname = "SURFACE_OT_primitive_nurbs_surface_torus_add";
/* API callbacks. */
ot->exec = add_primitive_nurbs_surface_torus_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ed::object::add_unit_props_radius(ot);
ed::object::add_generic_props(ot, true);
}
} // namespace blender

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,240 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edcurve
*/
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
#include "BLI_listbase.h"
#include "BLI_math_vector.h"
#include "BKE_curve.hh"
#include "BKE_layer.hh"
#include "ED_curve.hh"
#include "ED_view3d.hh"
#include "curve_intern.hh"
namespace blender {
/* -------------------------------------------------------------------- */
/** \name Cursor Picking API
* \{ */
struct PickUserData {
BPoint *bp;
BezTriple *bezt;
Nurb *nurb;
float dist;
int hpoint;
uint8_t select;
float mval_fl[2];
bool is_changed;
};
static void curve_pick_vert__do_closest(void *user_data,
Nurb *nu,
BPoint *bp,
BezTriple *bezt,
int beztindex,
bool handles_visible,
const float screen_co[2])
{
PickUserData *data = static_cast<PickUserData *>(user_data);
uint8_t flag;
float dist_test;
if (bp) {
flag = bp->f1;
}
else {
BLI_assert(handles_visible || beztindex == 1);
if (beztindex == 0) {
flag = bezt->f1;
}
else if (beztindex == 1) {
flag = bezt->f2;
}
else {
flag = bezt->f3;
}
}
dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
if ((flag & SELECT) == data->select) {
dist_test += 5.0f;
}
if (bezt && beztindex == 1) {
dist_test += 3.0f; /* middle points get a small disadvantage */
}
if (dist_test < data->dist) {
data->dist = dist_test;
data->bp = bp;
data->bezt = bezt;
data->nurb = nu;
data->hpoint = bezt ? beztindex : 0;
data->is_changed = true;
}
UNUSED_VARS_NDEBUG(handles_visible);
}
bool ED_curve_pick_vert_ex(ViewContext *vc,
const bool select,
const int dist_px,
Nurb **r_nurb,
BezTriple **r_bezt,
BPoint **r_bp,
short *r_handle,
Base **r_base)
{
PickUserData data{};
data.dist = dist_px;
data.hpoint = 0;
data.select = select ? SELECT : 0;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
Vector<Base *> bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
*vc->bmain, vc->scene, vc->view_layer, vc->v3d);
for (Base *base : bases) {
data.is_changed = false;
ED_view3d_viewcontext_init_object(vc, base->object);
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
nurbs_foreachScreenVert(vc, curve_pick_vert__do_closest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
if (r_base && data.is_changed) {
*r_base = base;
}
}
*r_nurb = data.nurb;
*r_bezt = data.bezt;
*r_bp = data.bp;
if (r_handle) {
*r_handle = data.hpoint;
}
return (data.bezt || data.bp);
}
bool ED_curve_pick_vert(ViewContext *vc,
short sel,
Nurb **r_nurb,
BezTriple **r_bezt,
BPoint **r_bp,
short *r_handle,
Base **r_base)
{
return ED_curve_pick_vert_ex(
vc, sel, ED_view3d_select_dist_px(), r_nurb, r_bezt, r_bp, r_handle, r_base);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Selection Queries
* \{ */
void ED_curve_nurb_vert_selected_find(
Curve *cu, View3D *v3d, Nurb **r_nu, BezTriple **r_bezt, BPoint **r_bp)
{
/* In nu and (bezt or bp) selected are written if there's 1 sel. */
/* If more points selected in 1 spline: return only nu, bezt and bp are 0. */
ListBaseT<Nurb> *editnurb = &cu->editnurb->nurbs;
BezTriple *bezt1;
BPoint *bp1;
int a;
*r_nu = nullptr;
*r_bezt = nullptr;
*r_bp = nullptr;
for (Nurb &nu1 : *editnurb) {
if (nu1.type == CU_BEZIER) {
bezt1 = nu1.bezt;
a = nu1.pntsu;
while (a--) {
if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1)) {
if (!ELEM(*r_nu, nullptr, &nu1)) {
*r_nu = nullptr;
*r_bp = nullptr;
*r_bezt = nullptr;
return;
}
if (*r_bezt || *r_bp) {
*r_bp = nullptr;
*r_bezt = nullptr;
}
else {
*r_bezt = bezt1;
*r_nu = &nu1;
}
}
bezt1++;
}
}
else {
bp1 = nu1.bp;
a = nu1.pntsu * nu1.pntsv;
while (a--) {
if (bp1->f1 & SELECT) {
if (!ELEM(*r_nu, nullptr, &nu1)) {
*r_bp = nullptr;
*r_bezt = nullptr;
*r_nu = nullptr;
return;
}
if (*r_bezt || *r_bp) {
*r_bp = nullptr;
*r_bezt = nullptr;
}
else {
*r_bp = bp1;
*r_nu = &nu1;
}
}
bp1++;
}
}
}
}
bool ED_curve_active_center(Curve *cu, float center[3])
{
Nurb *nu = nullptr;
void *vert = nullptr;
if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) {
return false;
}
if (nu->type == CU_BEZIER) {
BezTriple *bezt = static_cast<BezTriple *>(vert);
copy_v3_v3(center, bezt->vec[1]);
}
else {
BPoint *bp = static_cast<BPoint *>(vert);
copy_v3_v3(center, bp->vec);
}
return true;
}
/** \} */
} // namespace blender

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,324 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edcurve
*/
#include "MEM_guardedalloc.h"
#include "CLG_log.h"
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_array_utils.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BKE_anim_data.hh"
#include "BKE_context.hh"
#include "BKE_curve.hh"
#include "BKE_fcurve.hh"
#include "BKE_layer.hh"
#include "BKE_main.hh"
#include "BKE_object.hh"
#include "BKE_undo_system.hh"
#include "DEG_depsgraph.hh"
#include "ED_curve.hh"
#include "ED_undo.hh"
#include "WM_api.hh"
#include "WM_types.hh"
#include "curve_intern.hh"
namespace blender {
/** We only need this locally. */
static CLG_LogRef LOG = {"undo.curve"};
/* -------------------------------------------------------------------- */
/** \name Undo Conversion
* \{ */
namespace {
struct UndoCurve {
ListBaseT<Nurb> nubase;
int actvert;
CVKeyIndexMap *undoIndex;
/* Historical note: Once upon a time, this code also made a backup of F-Curves, in an attempt to
* enable undo of animation changes. This was very limited, as it only backed up the animation
* of the curve ID; all the other IDs whose animation was shown in the dope sheet, timeline, etc.
* was ignored. It also ignored the NLA, and deleted Action groups even when the animation was
* not touched by the user.
*
* With the introduction of slotted Actions, a decision had to be made to either port this
* behavior or remove it. The latter was chosen. For more information, see #135585. */
ListBaseT<FCurve> drivers;
int actnu;
eCurveFlag flag;
/* Stored in the object, needed since users may change the active key while in edit-mode. */
struct {
short shapenr;
} obedit;
size_t undo_size;
};
} // namespace
static void undocurve_to_editcurve(Main *bmain, UndoCurve *ucu, Curve *cu, short *r_shapenr)
{
ListBaseT<Nurb> *undobase = &ucu->nubase;
ListBaseT<Nurb> *editbase = BKE_curve_editNurbs_get(cu);
EditNurb *editnurb = cu->editnurb;
AnimData *ad = BKE_animdata_from_id(&cu->id);
BKE_nurbList_free(editbase);
if (ucu->undoIndex) {
BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex);
editnurb->keyindex = ED_curve_keyindex_hash_duplicate(ucu->undoIndex);
}
if (ad) {
BKE_fcurves_free(&ad->drivers);
BKE_fcurves_copy(&ad->drivers, &ucu->drivers);
}
/* Copy. */
for (Nurb &nu : *undobase) {
Nurb *newnu = BKE_nurb_duplicate(&nu);
if (editnurb->keyindex) {
ED_curve_keyindex_update_nurb(editnurb, &nu, newnu);
}
BLI_addtail(editbase, newnu);
}
cu->actvert = ucu->actvert;
cu->actnu = ucu->actnu;
cu->flag = ucu->flag;
*r_shapenr = ucu->obedit.shapenr;
ED_curve_updateAnimPaths(bmain, cu);
}
static void undocurve_from_editcurve(UndoCurve *ucu, Curve *cu, const short shapenr)
{
BLI_assert(BLI_array_is_zeroed(ucu, 1));
ListBaseT<Nurb> *nubase = BKE_curve_editNurbs_get(cu);
EditNurb *editnurb = cu->editnurb, tmpEditnurb;
AnimData *ad = BKE_animdata_from_id(&cu->id);
/* TODO: include size of drivers & undoIndex */
// ucu->undo_size = 0;
if (editnurb->keyindex) {
ucu->undoIndex = ED_curve_keyindex_hash_duplicate(editnurb->keyindex);
tmpEditnurb.keyindex = ucu->undoIndex;
}
if (ad) {
BKE_fcurves_copy(&ucu->drivers, &ad->drivers);
}
/* Copy. */
for (Nurb &nu : *nubase) {
Nurb *newnu = BKE_nurb_duplicate(&nu);
if (ucu->undoIndex) {
ED_curve_keyindex_update_nurb(&tmpEditnurb, &nu, newnu);
}
BLI_addtail(&ucu->nubase, newnu);
ucu->undo_size += ((nu.bezt ? (sizeof(BezTriple) * nu.pntsu) : 0) +
(nu.bp ? (sizeof(BPoint) * (nu.pntsu * nu.pntsv)) : 0) +
(nu.knotsu ? (sizeof(float) * KNOTSU(&nu)) : 0) +
(nu.knotsv ? (sizeof(float) * KNOTSV(&nu)) : 0) + sizeof(Nurb));
}
ucu->actvert = cu->actvert;
ucu->actnu = cu->actnu;
ucu->flag = cu->flag;
ucu->obedit.shapenr = shapenr;
}
static void undocurve_free_data(UndoCurve *uc)
{
BKE_nurbList_free(&uc->nubase);
BKE_curve_editNurb_keyIndex_free(&uc->undoIndex);
BKE_fcurves_free(&uc->drivers);
}
static Object *editcurve_object_from_context(bContext *C)
{
const Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
BKE_view_layer_synced_ensure(*bmain, scene, view_layer);
Object *obedit = BKE_view_layer_edit_object_get(view_layer);
if (obedit && ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) {
Curve *cu = id_cast<Curve *>(obedit->data);
if (BKE_curve_editNurbs_get(cu) != nullptr) {
return obedit;
}
}
return nullptr;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Implements ED Undo System
*
* \note This is similar for all edit-mode types.
* \{ */
struct CurveUndoStep_Elem {
UndoRefID_Object obedit_ref;
UndoCurve data;
};
struct CurveUndoStep {
UndoStep step;
/** See #ED_undo_object_editmode_validate_scene_from_windows code comment for details. */
UndoRefID_Scene scene_ref;
CurveUndoStep_Elem *elems;
uint elems_len;
};
static bool curve_undosys_poll(bContext *C)
{
Object *obedit = editcurve_object_from_context(C);
return (obedit != nullptr);
}
static bool curve_undosys_step_encode(bContext *C, Main *bmain, UndoStep *us_p)
{
CurveUndoStep *us = reinterpret_cast<CurveUndoStep *>(us_p);
/* Important not to use the 3D view when getting objects because all objects
* outside of this list will be moved out of edit-mode when reading back undo steps. */
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Vector<Object *> objects = ED_undo_editmode_objects_from_view_layer(*bmain, scene, view_layer);
us->scene_ref.ptr = scene;
us->elems = MEM_new_array_zeroed<CurveUndoStep_Elem>(objects.size(), __func__);
us->elems_len = objects.size();
for (uint i = 0; i < objects.size(); i++) {
Object *ob = objects[i];
Curve *cu = id_cast<Curve *>(ob->data);
CurveUndoStep_Elem *elem = &us->elems[i];
elem->obedit_ref.ptr = ob;
undocurve_from_editcurve(&elem->data, id_cast<Curve *>(ob->data), ob->shapenr);
cu->editnurb->needs_flush_to_id = 1;
us->step.data_size += elem->data.undo_size;
}
bmain->is_memfile_undo_flush_needed = true;
return true;
}
static void curve_undosys_step_decode(
bContext *C, Main *bmain, UndoStep *us_p, const eUndoStepDir /*dir*/, bool /*is_final*/)
{
CurveUndoStep *us = reinterpret_cast<CurveUndoStep *>(us_p);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
ED_undo_object_editmode_validate_scene_from_windows(
CTX_wm_manager(C), us->scene_ref.ptr, &scene, &view_layer);
ED_undo_object_editmode_restore_helper(
scene, view_layer, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems));
BLI_assert(BKE_object_is_in_editmode(us->elems[0].obedit_ref.ptr));
for (uint i = 0; i < us->elems_len; i++) {
CurveUndoStep_Elem *elem = &us->elems[i];
Object *obedit = elem->obedit_ref.ptr;
Curve *cu = id_cast<Curve *>(obedit->data);
if (cu->editnurb == nullptr) {
/* Should never fail, may not crash but can give odd behavior. */
CLOG_ERROR(&LOG,
"name='%s', failed to enter edit-mode for object '%s', undo state invalid",
us_p->name,
obedit->id.name);
continue;
}
undocurve_to_editcurve(bmain, &elem->data, id_cast<Curve *>(obedit->data), &obedit->shapenr);
cu->editnurb->needs_flush_to_id = 1;
DEG_id_tag_update(&cu->id, ID_RECALC_GEOMETRY);
}
/* The first element is always active */
ED_undo_object_set_active_or_warn(
*bmain, scene, view_layer, us->elems[0].obedit_ref.ptr, us_p->name, &LOG);
/* Check after setting active (unless undoing into another scene). */
BLI_assert(curve_undosys_poll(C) || (scene != CTX_data_scene(C)));
bmain->is_memfile_undo_flush_needed = true;
WM_event_add_notifier(C, NC_GEOM | ND_DATA, nullptr);
}
static void curve_undosys_step_free(UndoStep *us_p)
{
CurveUndoStep *us = reinterpret_cast<CurveUndoStep *>(us_p);
for (uint i = 0; i < us->elems_len; i++) {
CurveUndoStep_Elem *elem = &us->elems[i];
undocurve_free_data(&elem->data);
}
MEM_delete(us->elems);
}
static void curve_undosys_foreach_ID_ref(UndoStep *us_p,
UndoTypeForEachIDRefFn foreach_ID_ref_fn,
void *user_data)
{
CurveUndoStep *us = reinterpret_cast<CurveUndoStep *>(us_p);
foreach_ID_ref_fn(user_data, (reinterpret_cast<UndoRefID *>(&us->scene_ref)));
for (uint i = 0; i < us->elems_len; i++) {
CurveUndoStep_Elem *elem = &us->elems[i];
foreach_ID_ref_fn(user_data, (reinterpret_cast<UndoRefID *>(&elem->obedit_ref)));
}
}
void ED_curve_undosys_type(UndoType *ut)
{
ut->name = "Edit Curve";
ut->poll = curve_undosys_poll;
ut->step_encode = curve_undosys_step_encode;
ut->step_decode = curve_undosys_step_decode;
ut->step_free = curve_undosys_step_free;
ut->step_foreach_ID_ref = curve_undosys_foreach_ID_ref;
ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
ut->step_size = sizeof(CurveUndoStep);
}
/** \} */
} // namespace blender

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,428 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edcurve
*/
#include <cstdlib>
#include <cstring>
#include "MEM_guardedalloc.h"
#include "CLG_log.h"
#include "BLI_array_utils.h" /* For #BLI_array_is_zeroed. */
#include "BLI_utildefines.h"
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
#include "BKE_context.hh"
#include "BKE_layer.hh"
#include "BKE_main.hh"
#include "BKE_undo_system.hh"
#include "BKE_vfont.hh"
#include "DEG_depsgraph.hh"
#include "ED_curve.hh"
#include "ED_undo.hh"
#include "WM_api.hh"
#include "WM_types.hh"
#define USE_ARRAY_STORE
#ifdef USE_ARRAY_STORE
// # define DEBUG_PRINT
# include "BLI_array_store.h"
# include "BLI_array_store_utils.h"
# include "BLI_listbase.h"
# define ARRAY_CHUNK_SIZE 32
#endif
namespace blender {
/** Only needed this locally. */
static CLG_LogRef LOG = {"undo.font"};
/* -------------------------------------------------------------------- */
/** \name Undo Conversion
* \{ */
struct UndoFont {
char32_t *textbuf;
CharInfo *textbufinfo;
int len, pos, selstart, selend;
#ifdef USE_ARRAY_STORE
struct {
BArrayState *textbuf;
BArrayState *textbufinfo;
} store;
#endif
size_t undo_size;
};
/** \} */
#ifdef USE_ARRAY_STORE
/* -------------------------------------------------------------------- */
/** \name Array Store
* \{ */
static struct {
BArrayStore_AtSize bs_stride;
int users;
/* We could have the undo API pass in the previous state, for now store a local list */
ListBaseT<LinkData> local_links;
} uf_arraystore = {{nullptr}};
/**
* \param create: When false, only free the arrays.
* This is done since when reading from an undo state, they must be temporarily expanded.
* then discarded afterwards, having this argument avoids having 2x code paths.
*/
static void uf_arraystore_compact_ex(UndoFont *uf, const UndoFont *uf_ref, bool create)
{
# define STATE_COMPACT(uf, id, len) \
if ((uf)->id) { \
BLI_assert(create == ((uf)->store.id == nullptr)); \
if (create) { \
const BArrayState *state_reference = uf_ref ? uf_ref->store.id : nullptr; \
const size_t stride = sizeof(*(uf)->id); \
BArrayStore *bs = BLI_array_store_at_size_ensure( \
&uf_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE); \
(uf)->store.id = BLI_array_store_state_add( \
bs, (uf)->id, size_t(len) * stride, state_reference); \
} \
/* keep uf->len for validation */ \
MEM_delete((uf)->id); \
(uf)->id = nullptr; \
} \
((void)0)
STATE_COMPACT(uf, textbuf, uf->len + 1);
STATE_COMPACT(uf, textbufinfo, uf->len + 1);
# undef STATE_COMPACT
if (create) {
uf_arraystore.users += 1;
}
}
/**
* Move data from allocated arrays to de-duplicated states and clear arrays.
*/
static void uf_arraystore_compact(UndoFont *um, const UndoFont *uf_ref)
{
uf_arraystore_compact_ex(um, uf_ref, true);
}
static void uf_arraystore_compact_with_info(UndoFont *um, const UndoFont *uf_ref)
{
# ifdef DEBUG_PRINT
size_t size_expanded_prev, size_compacted_prev;
BLI_array_store_at_size_calc_memory_usage(
&uf_arraystore.bs_stride, &size_expanded_prev, &size_compacted_prev);
# endif
uf_arraystore_compact(um, uf_ref);
# ifdef DEBUG_PRINT
{
size_t size_expanded, size_compacted;
BLI_array_store_at_size_calc_memory_usage(
&uf_arraystore.bs_stride, &size_expanded, &size_compacted);
const double percent_total = size_expanded ?
((double(size_compacted) / double(size_expanded)) * 100.0) :
-1.0;
size_t size_expanded_step = size_expanded - size_expanded_prev;
size_t size_compacted_step = size_compacted - size_compacted_prev;
const double percent_step = size_expanded_step ?
((double(size_compacted_step) / double(size_expanded_step)) *
100.0) :
-1.0;
printf("overall memory use: %.8f%% of expanded size\n", percent_total);
printf("step memory use: %.8f%% of expanded size\n", percent_step);
}
# endif
}
/**
* Remove data we only expanded for temporary use.
*/
static void uf_arraystore_expand_clear(UndoFont *um)
{
uf_arraystore_compact_ex(um, nullptr, false);
}
static void uf_arraystore_expand(UndoFont *uf)
{
# define STATE_EXPAND(uf, id, len) \
if ((uf)->store.id) { \
const size_t stride = sizeof(*(uf)->id); \
const BArrayState *state = (uf)->store.id; \
size_t state_len; \
*(void **)&(uf)->id = BLI_array_store_state_data_get_alloc(state, &state_len); \
BLI_assert((len) == (state_len / stride)); \
UNUSED_VARS_NDEBUG(stride); \
} \
((void)0)
STATE_EXPAND(uf, textbuf, uf->len + 1);
STATE_EXPAND(uf, textbufinfo, uf->len + 1);
# undef STATE_EXPAND
}
static void uf_arraystore_free(UndoFont *uf)
{
# define STATE_FREE(uf, id) \
if ((uf)->store.id) { \
const size_t stride = sizeof(*(uf)->id); \
BArrayStore *bs = BLI_array_store_at_size_get(&uf_arraystore.bs_stride, stride); \
BArrayState *state = (uf)->store.id; \
BLI_array_store_state_remove(bs, state); \
(uf)->store.id = nullptr; \
} \
((void)0)
STATE_FREE(uf, textbuf);
STATE_FREE(uf, textbufinfo);
# undef STATE_FREE
uf_arraystore.users -= 1;
BLI_assert(uf_arraystore.users >= 0);
if (uf_arraystore.users == 0) {
# ifdef DEBUG_PRINT
printf("editfont undo store: freeing all data!\n");
# endif
BLI_array_store_at_size_clear(&uf_arraystore.bs_stride);
}
}
/** \} */
#endif /* USE_ARRAY_STORE */
/* -------------------------------------------------------------------- */
/** \name Undo/Redo Helper Functions
* \{ */
static void undofont_to_editfont(UndoFont *uf, Curve *cu)
{
EditFont *ef = cu->editfont;
size_t final_size;
#ifdef USE_ARRAY_STORE
uf_arraystore_expand(uf);
#endif
final_size = sizeof(*ef->textbuf) * (uf->len + 1);
memcpy(ef->textbuf, uf->textbuf, final_size);
final_size = sizeof(CharInfo) * (uf->len + 1);
memcpy(ef->textbufinfo, uf->textbufinfo, final_size);
ef->pos = uf->pos;
ef->selstart = uf->selstart;
ef->selend = uf->selend;
ef->len = uf->len;
#ifdef USE_ARRAY_STORE
uf_arraystore_expand_clear(uf);
#endif
}
static void *undofont_from_editfont(UndoFont *uf, Curve *cu)
{
BLI_assert(BLI_array_is_zeroed(uf, 1));
const EditFont *ef = cu->editfont;
size_t mem_used_prev = MEM_get_memory_in_use();
size_t alloc_len = ef->len + 1;
BLI_assert(sizeof(*uf->textbuf) == sizeof(*ef->textbuf));
uf->textbuf = MEM_new_array_uninitialized<char32_t>(alloc_len, __func__);
memcpy(uf->textbuf, ef->textbuf, sizeof(char32_t) * alloc_len);
uf->textbufinfo = MEM_new_array<CharInfo>(alloc_len, __func__);
memcpy(uf->textbufinfo, ef->textbufinfo, sizeof(CharInfo) * alloc_len);
uf->pos = ef->pos;
uf->selstart = ef->selstart;
uf->selend = ef->selend;
uf->len = ef->len;
#ifdef USE_ARRAY_STORE
{
const UndoFont *uf_ref = static_cast<const UndoFont *>(
uf_arraystore.local_links.last ?
(static_cast<LinkData *>(uf_arraystore.local_links.last))->data :
nullptr);
/* Add ourselves. */
BLI_addtail(&uf_arraystore.local_links, BLI_genericNodeN(uf));
uf_arraystore_compact_with_info(uf, uf_ref);
}
#endif
size_t mem_used_curr = MEM_get_memory_in_use();
uf->undo_size = mem_used_prev < mem_used_curr ? mem_used_curr - mem_used_prev : sizeof(UndoFont);
return uf;
}
static void undofont_free_data(UndoFont *uf)
{
#ifdef USE_ARRAY_STORE
{
LinkData *link = static_cast<LinkData *>(
BLI_findptr(&uf_arraystore.local_links, uf, offsetof(LinkData, data)));
BLI_remlink(&uf_arraystore.local_links, link);
MEM_delete(link);
}
uf_arraystore_free(uf);
#endif
if (uf->textbuf) {
MEM_delete(uf->textbuf);
}
if (uf->textbufinfo) {
MEM_delete(uf->textbufinfo);
}
}
static Object *editfont_object_from_context(bContext *C)
{
const Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
BKE_view_layer_synced_ensure(*bmain, scene, view_layer);
Object *obedit = BKE_view_layer_edit_object_get(view_layer);
if (obedit && obedit->type == OB_FONT) {
const Curve *cu = id_cast<Curve *>(obedit->data);
const EditFont *ef = cu->editfont;
if (ef != nullptr) {
return obedit;
}
}
return nullptr;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Implements ED Undo System
* \{ */
struct FontUndoStep {
UndoStep step;
/** See #ED_undo_object_editmode_validate_scene_from_windows code comment for details. */
UndoRefID_Scene scene_ref;
/* NOTE: will split out into list for multi-object-editmode. */
UndoRefID_Object obedit_ref;
UndoFont data;
};
static bool font_undosys_poll(bContext *C)
{
return editfont_object_from_context(C) != nullptr;
}
static bool font_undosys_step_encode(bContext *C, Main *bmain, UndoStep *us_p)
{
FontUndoStep *us = reinterpret_cast<FontUndoStep *>(us_p);
us->scene_ref.ptr = CTX_data_scene(C);
us->obedit_ref.ptr = editfont_object_from_context(C);
Curve *cu = id_cast<Curve *>(us->obedit_ref.ptr->data);
undofont_from_editfont(&us->data, cu);
us->step.data_size = us->data.undo_size;
cu->editfont->needs_flush_to_id = 1;
bmain->is_memfile_undo_flush_needed = true;
return true;
}
static void font_undosys_step_decode(
bContext *C, Main *bmain, UndoStep *us_p, const eUndoStepDir /*dir*/, bool /*is_final*/)
{
FontUndoStep *us = reinterpret_cast<FontUndoStep *>(us_p);
Object *obedit = us->obedit_ref.ptr;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
/* Pass in an array of 1 (typically used for multi-object edit-mode). */
ED_undo_object_editmode_validate_scene_from_windows(
CTX_wm_manager(C), us->scene_ref.ptr, &scene, &view_layer);
ED_undo_object_editmode_restore_helper(scene, view_layer, &obedit, 1, sizeof(Object *));
Curve *cu = id_cast<Curve *>(obedit->data);
undofont_to_editfont(&us->data, cu);
DEG_id_tag_update(&cu->id, ID_RECALC_GEOMETRY);
ED_undo_object_set_active_or_warn(*bmain, scene, view_layer, obedit, us_p->name, &LOG);
/* Check after setting active (unless undoing into another scene). */
BLI_assert(font_undosys_poll(C) || (scene != CTX_data_scene(C)));
cu->editfont->needs_flush_to_id = 1;
bmain->is_memfile_undo_flush_needed = true;
WM_event_add_notifier(C, NC_GEOM | ND_DATA, nullptr);
}
static void font_undosys_step_free(UndoStep *us_p)
{
FontUndoStep *us = reinterpret_cast<FontUndoStep *>(us_p);
undofont_free_data(&us->data);
}
static void font_undosys_foreach_ID_ref(UndoStep *us_p,
UndoTypeForEachIDRefFn foreach_ID_ref_fn,
void *user_data)
{
FontUndoStep *us = reinterpret_cast<FontUndoStep *>(us_p);
foreach_ID_ref_fn(user_data, (reinterpret_cast<UndoRefID *>(&us->scene_ref)));
foreach_ID_ref_fn(user_data, (reinterpret_cast<UndoRefID *>(&us->obedit_ref)));
}
void ED_font_undosys_type(UndoType *ut)
{
ut->name = "Edit Font";
ut->poll = font_undosys_poll;
ut->step_encode = font_undosys_step_encode;
ut->step_decode = font_undosys_step_decode;
ut->step_free = font_undosys_step_free;
ut->step_foreach_ID_ref = font_undosys_foreach_ID_ref;
ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
ut->step_size = sizeof(FontUndoStep);
}
/** \} */
} // namespace blender