Fix #106235: Use consistent order for multi-input socket links #106320

Closed
Iliya Katushenock wants to merge 17 commits from mod_moder:fix_internal_link_drawing into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
19 changed files with 441 additions and 123 deletions
Showing only changes of commit cd556fb4cc - Show all commits

View File

@ -870,7 +870,7 @@ class RENDER_PT_eevee_next_sampling_viewport(RenderButtonsPanel, Panel):
col.prop(props, "taa_samples", text="Samples")
col.prop(props, "use_taa_reprojection", text="Temporal Reprojection")
# Add sss sample count here
# Add SSS sample count here.
class RENDER_PT_eevee_next_sampling_render(RenderButtonsPanel, Panel):
@ -893,7 +893,7 @@ class RENDER_PT_eevee_next_sampling_render(RenderButtonsPanel, Panel):
col = layout.column(align=True)
col.prop(props, "taa_render_samples", text="Samples")
# Add sss sample count here
# Add SSS sample count here.
class RENDER_PT_eevee_indirect_lighting(RenderButtonsPanel, Panel):

View File

@ -5,7 +5,7 @@
/** \file
* \ingroup animrig
*
* \brief Functions to work with the visal keying system.
* \brief Functions to work with the visual keying system.
*/
struct PointerRNA;

View File

@ -672,13 +672,34 @@ void blf_font_draw_buffer(FontBLF *font, const char *str, const size_t str_len,
* - #BLF_width_to_rstrlen
* \{ */
static bool blf_font_width_to_strlen_glyph_process(
FontBLF *font, GlyphBLF *g_prev, GlyphBLF *g, ft_pix *pen_x, const int width_i)
static bool blf_font_width_to_strlen_glyph_process(FontBLF *font,
GlyphCacheBLF *gc,
GlyphBLF *g_prev,
GlyphBLF *g,
ft_pix *pen_x,
const int width_i)
{
if (UNLIKELY(g == nullptr)) {
return false; /* continue the calling loop. */
}
*pen_x += blf_kerning(font, g_prev, g) + g->advance_x;
if (g && pen_x && !(font->flags & BLF_MONOSPACED)) {
*pen_x += blf_kerning(font, g_prev, g);
#ifdef BLF_SUBPIXEL_POSITION
if (!(font->flags & BLF_RENDER_SUBPIXELAA)) {
*pen_x = FT_PIX_ROUND(*pen_x);
}
#else
*pen_x = FT_PIX_ROUND(*pen_x);
#endif
#ifdef BLF_SUBPIXEL_AA
g = blf_glyph_ensure_subpixel(font, gc, g, *pen_x);
#endif
}
*pen_x += g->advance_x;
/* When true, break the calling loop. */
return (ft_pix_to_int(*pen_x) >= width_i);
@ -699,7 +720,7 @@ size_t blf_font_width_to_strlen(
i_prev = i, width_new = pen_x, g_prev = g)
{
g = blf_glyph_from_utf8_and_step(font, gc, nullptr, str, str_len, &i, nullptr);
if (blf_font_width_to_strlen_glyph_process(font, g_prev, g, &pen_x, width_i)) {
if (blf_font_width_to_strlen_glyph_process(font, gc, g_prev, g, &pen_x, width_i)) {
break;
}
}
@ -742,7 +763,7 @@ size_t blf_font_width_to_rstrlen(
BLI_assert(i_tmp == i);
}
if (blf_font_width_to_strlen_glyph_process(font, g_prev, g, &pen_x, width)) {
if (blf_font_width_to_strlen_glyph_process(font, gc, g_prev, g, &pen_x, width)) {
break;
}
}
@ -1344,6 +1365,176 @@ static void blf_font_fill(FontBLF *font)
font->buf_info.col_init[3] = 0;
}
/* Note that the data the following function creates is not yet used.
* But do not remove it as it will be used in the near future - Harley */
static void blf_font_metrics(FT_Face face, FontMetrics *metrics)
{
/* Members with non-zero defaults. */
metrics->weight = 400;
metrics->width = 1.0f;
metrics->spacing = 1.0f;
TT_OS2 *os2_table = (TT_OS2 *)FT_Get_Sfnt_Table(face, FT_SFNT_OS2);
if (os2_table) {
/* The default (resting) font weight. */
if (os2_table->usWeightClass >= 1 && os2_table->usWeightClass <= 1000) {
metrics->weight = short(os2_table->usWeightClass);
}
/* Width value is one of integers 1-9 with known values. */
if (os2_table->usWidthClass >= 1 && os2_table->usWidthClass <= 9) {
switch (os2_table->usWidthClass) {
case 1:
metrics->width = 0.5f;
break;
case 2:
metrics->width = 0.625f;
break;
case 3:
metrics->width = 0.75f;
break;
case 4:
metrics->width = 0.875f;
break;
case 5:
metrics->width = 1.0f;
break;
case 6:
metrics->width = 1.125f;
break;
case 7:
metrics->width = 1.25f;
break;
case 8:
metrics->width = 1.5f;
break;
case 9:
metrics->width = 2.0f;
break;
}
}
metrics->strikeout_position = short(os2_table->yStrikeoutPosition);
metrics->strikeout_thickness = short(os2_table->yStrikeoutSize);
metrics->subscript_size = short(os2_table->ySubscriptYSize);
metrics->subscript_xoffset = short(os2_table->ySubscriptXOffset);
metrics->subscript_yoffset = short(os2_table->ySubscriptYOffset);
metrics->superscript_size = short(os2_table->ySuperscriptYSize);
metrics->superscript_xoffset = short(os2_table->ySuperscriptXOffset);
metrics->superscript_yoffset = short(os2_table->ySuperscriptYOffset);
metrics->family_class = short(os2_table->sFamilyClass);
metrics->selection_flags = short(os2_table->fsSelection);
metrics->first_charindex = short(os2_table->usFirstCharIndex);
metrics->last_charindex = short(os2_table->usLastCharIndex);
if (os2_table->version > 1) {
metrics->cap_height = short(os2_table->sCapHeight);
metrics->x_height = short(os2_table->sxHeight);
}
}
/* The Post table usually contains a slant value, but in counter-clockwise degrees. */
TT_Postscript *post_table = (TT_Postscript *)FT_Get_Sfnt_Table(face, FT_SFNT_POST);
if (post_table) {
if (post_table->italicAngle != 0) {
metrics->slant = float(post_table->italicAngle) / -65536.0f;
}
}
/* Metrics copied from those gathered by FreeType. */
metrics->units_per_EM = short(face->units_per_EM);
metrics->ascender = short(face->ascender);
metrics->descender = short(face->descender);
metrics->line_height = short(face->height);
metrics->max_advance_width = short(face->max_advance_width);
metrics->max_advance_height = short(face->max_advance_height);
metrics->underline_position = short(face->underline_position);
metrics->underline_thickness = short(face->underline_thickness);
metrics->num_glyphs = int(face->num_glyphs);
metrics->bounding_box.xmin = int(face->bbox.xMin);
metrics->bounding_box.xmax = int(face->bbox.xMax);
metrics->bounding_box.ymin = int(face->bbox.yMin);
metrics->bounding_box.ymax = int(face->bbox.yMax);
if (metrics->cap_height == 0) {
/* Calculate or guess cap height if it is not set in the font. */
FT_UInt gi = FT_Get_Char_Index(face, uint('H'));
if (gi && FT_Load_Glyph(face, gi, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP) == FT_Err_Ok) {
metrics->cap_height = short(face->glyph->metrics.height);
}
else {
metrics->cap_height = short(float(metrics->units_per_EM) * 0.7f);
}
}
if (metrics->x_height == 0) {
/* Calculate or guess x-height if it is not set in the font. */
FT_UInt gi = FT_Get_Char_Index(face, uint('x'));
if (gi && FT_Load_Glyph(face, gi, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP) == FT_Err_Ok) {
metrics->x_height = short(face->glyph->metrics.height);
}
else {
metrics->x_height = short(float(metrics->units_per_EM) * 0.5f);
}
}
FT_UInt gi = FT_Get_Char_Index(face, uint('o'));
if (gi && FT_Load_Glyph(face, gi, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP) == FT_Err_Ok) {
metrics->o_proportion = float(face->glyph->metrics.width) / float(face->glyph->metrics.height);
}
if (metrics->ascender == 0) {
/* Set a sane value for ascender if not set in the font. */
metrics->ascender = short(float(metrics->units_per_EM) * 0.8f);
}
if (metrics->descender == 0) {
/* Set a sane value for descender if not set in the font. */
metrics->descender = metrics->ascender - metrics->units_per_EM;
}
if (metrics->weight == 400 && face->style_flags & FT_STYLE_FLAG_BOLD) {
/* Normal weight yet this is an bold font, so set a sane weight value. */
metrics->weight = 700;
}
if (metrics->slant == 0.0f && face->style_flags & FT_STYLE_FLAG_ITALIC) {
/* No slant yet this is an italic font, so set a sane slant value. */
metrics->slant = 8.0f;
}
if (metrics->underline_position == 0) {
metrics->underline_position = short(float(metrics->units_per_EM) * -0.2f);
}
if (metrics->underline_thickness == 0) {
metrics->underline_thickness = short(float(metrics->units_per_EM) * 0.07f);
}
if (metrics->strikeout_position == 0) {
metrics->strikeout_position = short(float(metrics->x_height) * 0.6f);
}
if (metrics->strikeout_thickness == 0) {
metrics->strikeout_thickness = metrics->underline_thickness;
}
if (metrics->subscript_size == 0) {
metrics->subscript_size = short(float(metrics->units_per_EM) * 0.6f);
}
if (metrics->subscript_yoffset == 0) {
metrics->subscript_yoffset = short(float(metrics->units_per_EM) * 0.075f);
}
if (metrics->superscript_size == 0) {
metrics->superscript_size = short(float(metrics->units_per_EM) * 0.6f);
}
if (metrics->superscript_yoffset == 0) {
metrics->superscript_yoffset = short(float(metrics->units_per_EM) * 0.35f);
}
}
bool blf_ensure_face(FontBLF *font)
{
if (font->face) {
@ -1431,6 +1622,9 @@ bool blf_ensure_face(FontBLF *font)
FT_Get_MM_Var(font->face, &(font->variations));
}
blf_ensure_size(font);
blf_font_metrics(font->face, &font->metrics);
/* Save TrueType table with bits to quickly test most unicode block coverage. */
TT_OS2 *os2_table = (TT_OS2 *)FT_Get_Sfnt_Table(font->face, FT_SFNT_OS2);
if (os2_table) {

View File

@ -209,6 +209,75 @@ typedef struct FontBufInfoBLF {
} FontBufInfoBLF;
typedef struct FontMetrics {
/** This font's default weight, 100-900, 400 is normal. */
short weight;
/** This font's default width, 1 is normal, 2 is twice as wide. */
float width;
/** This font's slant in clockwise degrees, 0 being upright. */
float slant;
/** This font's default spacing, 1 is normal. */
float spacing;
/** Number of font units in an EM square. 2048, 1024, 1000 are typical. */
short units_per_EM; /* */
/** Design classification from OS/2 sFamilyClass. */
short family_class;
/** Style classification from OS/2 fsSelection. */
short selection_flags;
/** Total number of glyphs in the font. */
int num_glyphs;
/** Minimum Unicode index, typically 0x0020. */
short first_charindex;
/** Maximum Unicode index, or 0xFFFF if greater than. */
short last_charindex;
/**
* Bounds that can contain every glyph in the font when in default positions. Can be used for
* maximum ascender, minimum descender. Can be out by a pixel when hinting. Does not change with
* variation axis changes. */
rcti bounding_box;
/**
* Positive number of font units from baseline to top of typical capitals. Can be slightly more
* than cap height when head serifs, terminals, or apexes extend above cap line. */
short ascender;
/** Negative (!) number of font units from baseline to bottom of letters like `gjpqy`. */
short descender;
/** Positive number of font units between consecutive baselines. */
short line_height;
/** Font units from baseline to lowercase mean line, typically to top of "x". */
short x_height;
/** Font units from baseline to top of capital letters, specifically "H". */
short cap_height;
/** Ratio width to height of lowercase "O". Reliable indication of font proportion. */
float o_proportion;
/** Font unit maximum horizontal advance for all glyphs in font. Can help with wrapping. */
short max_advance_width;
/** As above but only for vertical layout fonts, otherwise is set to line_height value. */
short max_advance_height;
/** Negative (!) number of font units below baseline to center (!) of underlining stem. */
short underline_position;
/** thickness of the underline in font units. */
short underline_thickness;
/** Positive number of font units above baseline to the top (!) of strikeout stroke. */
short strikeout_position;
/** thickness of the strikeout line in font units. */
short strikeout_thickness;
/** EM size font units of recommended subscript letters. */
short subscript_size;
/** Horizontal offset before first subscript character, typically 0. */
short subscript_xoffset;
/** Positive number of font units above baseline for subscript characters. */
short subscript_yoffset;
/** EM size font units of recommended superscript letters. */
short superscript_size;
/** Horizontal offset before first superscript character, typically 0. */
short superscript_xoffset;
/** Positive (!) number of font units below baseline for subscript characters. */
short superscript_yoffset;
} FontMetrics;
typedef struct FontBLF {
/** Full path to font file or NULL if from memory. */
char *filepath;
@ -307,6 +376,9 @@ typedef struct FontBLF {
/** Copy of the font->face->face_flags, in case we don't have a face loaded. */
FT_Long face_flags;
/** Details about the font's design and style and sizes (in un-sized font units). */
FontMetrics metrics;
/** Data for buffer usage (drawing into a texture buffer) */
FontBufInfoBLF buf_info;

View File

@ -706,6 +706,15 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
ASSERT_IS_VALID_MESH(mesh_final);
}
if (mti->required_data_mask) {
CustomData_MeshMasks mask{};
mti->required_data_mask(md, &mask);
if (mask.vmask & CD_MASK_ORCO) {
add_orco_mesh(ob, nullptr, mesh_final, nullptr, CD_ORCO);
}
}
BKE_modifier_deform_verts(
md,
&mectx,

View File

@ -529,7 +529,7 @@ GVArray NormalFieldInput::get_varray_for_context(const GeometryFieldContext &con
if (const Mesh *mesh = context.mesh()) {
return mesh_normals_varray(*mesh, mask, context.domain());
}
if (const CurvesGeometry *curves = context.curves()) {
if (const CurvesGeometry *curves = context.curves_or_strokes()) {
return curve_normals_varray(*curves, context.domain());
}
return {};

View File

@ -155,7 +155,7 @@ vec3 drw_point_ndc_to_world(vec3 ssP)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Transform Screen Postions
/** \name Transform Screen Positions
* \{ */
vec3 drw_point_view_to_screen(vec3 vP)

View File

@ -1790,6 +1790,7 @@ typedef enum uiTooltipStyle {
UI_TIP_STYLE_HEADER, /* Header text. */
UI_TIP_STYLE_MONO, /* Mono-spaced text. */
UI_TIP_STYLE_IMAGE, /* Image field. */
UI_TIP_STYLE_SPACER, /* Padding to separate sections. */
} uiTooltipStyle;
typedef enum uiTooltipColorID {

View File

@ -5929,7 +5929,7 @@ const char *ui_but_placeholder_get(uiBut *but)
RNA_enum_name(rna_enum_id_type_items, idcode, &placeholder);
placeholder = CTX_IFACE_(BLT_I18NCONTEXT_ID_ID, placeholder);
}
else if (type) {
else if (type && !STREQ(RNA_struct_identifier(type), "UnknownType")) {
placeholder = RNA_struct_ui_name(type);
}
}

View File

@ -10778,8 +10778,8 @@ static int ui_handle_menu_event(bContext *C,
(event->flag & WM_EVENT_IS_REPEAT) == 0)
{
/* Menu search if spacebar or SearchOnKeyPress. */
MenuType *mt = WM_menutype_find(menu->menu_idname, false);
/* Menu search if space-bar or #MenuTypeFlag::SearchOnKeyPress. */
MenuType *mt = WM_menutype_find(menu->menu_idname, true);
if ((mt && bool(mt->flag & MenuTypeFlag::SearchOnKeyPress)) ||
event->type == EVT_SPACEKEY) {
if ((level != 0) && (but == nullptr || !menu->menu_idname[0])) {

View File

@ -66,8 +66,8 @@
#include "interface_intern.hh"
#include "interface_regions_intern.hh"
#define UI_TIP_PAD_FAC 1.3f
#define UI_TIP_PADDING int(UI_TIP_PAD_FAC * UI_UNIT_Y)
#define UI_TIP_SPACER 0.3f
#define UI_TIP_PADDING int(1.3f * UI_UNIT_Y)
#define UI_TIP_MAXWIDTH 600
#define UI_TIP_MAXIMAGEWIDTH 500
#define UI_TIP_MAXIMAGEHEIGHT 300
@ -76,7 +76,6 @@
struct uiTooltipFormat {
uiTooltipStyle style;
uiTooltipColorID color_id;
bool is_pad;
};
struct uiTooltipField {
@ -121,11 +120,16 @@ void UI_tooltip_text_field_add(uiTooltipData *data,
const uiTooltipColorID color_id,
const bool is_pad)
{
if (is_pad) {
/* Add a spacer field before this one. */
UI_tooltip_text_field_add(
data, nullptr, nullptr, UI_TIP_STYLE_SPACER, UI_TIP_LC_NORMAL, false);
}
uiTooltipField *field = text_field_add_only(data);
field->format = {};
field->format.style = style;
field->format.color_id = color_id;
field->format.is_pad = is_pad;
field->text = text;
field->text_suffix = suffix;
}
@ -215,8 +219,6 @@ static void ui_tooltip_region_draw_cb(const bContext * /*C*/, ARegion *region)
for (int i = 0; i < data->fields_len; i++) {
const uiTooltipField *field = &data->fields[i];
const uiTooltipField *field_next = (i + 1) != data->fields_len ? &data->fields[i + 1] :
nullptr;
bbox.ymin = bbox.ymax - (data->lineh * field->geom.lines);
if (field->format.style == UI_TIP_STYLE_HEADER) {
@ -280,6 +282,9 @@ static void ui_tooltip_region_draw_cb(const bContext * /*C*/, ARegion *region)
GPU_blend(GPU_BLEND_ALPHA);
}
else if (field->format.style == UI_TIP_STYLE_SPACER) {
bbox.ymax -= data->lineh * UI_TIP_SPACER;
}
else {
BLI_assert(field->format.style == UI_TIP_STYLE_NORMAL);
uiFontStyleDraw_Params fs_params{};
@ -293,10 +298,6 @@ static void ui_tooltip_region_draw_cb(const bContext * /*C*/, ARegion *region)
}
bbox.ymax -= data->lineh * field->geom.lines;
if (field_next && field_next->format.is_pad) {
bbox.ymax -= data->lineh * (UI_TIP_PAD_FAC - 1);
}
}
BLF_disable(data->fstyle.uifont_id, BLF_WORD_WRAP);
@ -1223,8 +1224,6 @@ static ARegion *ui_tooltip_create_with_data(bContext *C,
int i, fonth, fontw;
for (i = 0, fontw = 0, fonth = 0; i < data->fields_len; i++) {
uiTooltipField *field = &data->fields[i];
uiTooltipField *field_next = (i + 1) != data->fields_len ? &data->fields[i + 1] : nullptr;
ResultBLF info = {0};
int w = 0;
int x_pos = 0;
@ -1249,8 +1248,9 @@ static ARegion *ui_tooltip_create_with_data(bContext *C,
}
fonth += h * info.lines;
if (field_next && field_next->format.is_pad) {
fonth += h * (UI_TIP_PAD_FAC - 1);
if (field->format.style == UI_TIP_STYLE_SPACER) {
fonth += h * UI_TIP_SPACER;
}
if (field->format.style == UI_TIP_STYLE_IMAGE) {

View File

@ -1659,10 +1659,9 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle,
/* The following assert is meant to catch code changes that break this function's result, but
* some wriggle room is fine and needed. Just a couple pixels for large sizes and with some
* settings like "Full" hinting which can move features both left and right a pixel. We could
* probably reduce this to one pixel if we consolodate text output with length measuring. But
* probably reduce this to one pixel if we consolidate text output with length measuring. But
* our text string lengths include the last character's right-side bearing anyway, so a string
* can be longer by that amount and still fit visibly in the required space.
*/
* can be longer by that amount and still fit visibly in the required space. */
BLI_assert((strwidth <= (okwidth + 2)) || (okwidth <= 0.0f));

View File

@ -1474,7 +1474,7 @@ static void grease_pencil_eraser_draw(PaintCursorContext *pcontext)
{
float radius = static_cast<float>(BKE_brush_size_get(pcontext->scene, pcontext->brush));
/* Redish color with alpha. */
/* Red-ish color with alpha. */
immUniformColor4ub(255, 100, 100, 20);
imm_draw_circle_fill_2d(pcontext->pos, pcontext->x, pcontext->y, radius, 40);

View File

@ -173,7 +173,7 @@ float safe_sqrt(float a)
}
/**
* Safe arccosine function. Returns `acos(a)`.
* Safe `arccosine` function. Returns `acos(a)`.
* If `a` is greater than 1, returns 0.
* If `a` is less than -1, returns PI.
*/

View File

@ -265,7 +265,7 @@ messenger_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
* Some message IDs are turned of globally to reduce console flooding.
*
* - 0xec321b6c: `VUID-VkBufferCreateInfo-size-06409` is disabled as all allocations are reported
* to be larger than the maximum allowed buffer size, although the buffersize is 4GB. Detected
* to be larger than the maximum allowed buffer size, although the buffer-size is 4GB. Detected
* on Mesa 23.0.4.
*/
if (ELEM(callback_data->messageIdNumber, 0xec321b6c)) {

View File

@ -304,7 +304,7 @@ static void export_startjob(void *customdata, wmJobWorkerStatus *worker_status)
}
G.is_break = false;
/* Evaluate the despgraph for exporting.
/* Evaluate the depsgraph for exporting.
*
* Note that, unlike with its building, this is expected to be safe to perform from worker
* thread, since UI is locked during export, so there should not be any more changes in the Main
@ -443,7 +443,7 @@ bool USD_export(bContext *C,
/* Construct the depsgraph for exporting.
*
* Has to be done from main thread currently, as it may affect Main original data (e.g. when
* doing deferred update of the viewlayers, see #112534 for details). */
* doing deferred update of the view-layers, see #112534 for details). */
if (job->params.visible_objects_only) {
DEG_graph_build_from_view_layer(job->depsgraph);
}

View File

@ -3,6 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_curves.hh"
#include "BKE_grease_pencil.hh"
#include "UI_interface.hh"
#include "UI_resources.hh"
@ -17,7 +18,8 @@ namespace blender::nodes::node_geo_set_curve_normal_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>("Curve").supported_type(GeometryComponent::Type::Curve);
b.add_input<decl::Geometry>("Curve").supported_type(
{GeometryComponent::Type::Curve, GeometryComponent::Type::GreasePencil});
b.add_input<decl::Bool>("Selection").default_value(true).hide_value().field_on_all();
b.add_output<decl::Geometry>("Curve").propagate_all();
}
@ -32,11 +34,11 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
node->custom1 = NORMAL_MODE_MINIMUM_TWIST;
}
static void set_normal_mode(bke::CurvesGeometry &curves,
const NormalMode mode,
const Field<bool> &selection_field)
static void set_curve_normal(bke::CurvesGeometry &curves,
const NormalMode mode,
const fn::FieldContext field_context,
const Field<bool> &selection_field)
{
const bke::CurvesFieldContext field_context{curves, ATTR_DOMAIN_CURVE};
fn::FieldEvaluator evaluator{field_context, curves.curves_num()};
evaluator.set_selection(selection_field);
evaluator.evaluate();
@ -45,6 +47,23 @@ static void set_normal_mode(bke::CurvesGeometry &curves,
curves.tag_normals_changed();
}
static void set_grease_pencil_normal(GreasePencil &grease_pencil,
const NormalMode mode,
const Field<bool> &selection_field)
{
using namespace blender::bke::greasepencil;
for (const int layer_index : grease_pencil.layers().index_range()) {
Drawing *drawing = get_eval_grease_pencil_layer_drawing_for_write(grease_pencil, layer_index);
if (drawing == nullptr) {
continue;
}
bke::CurvesGeometry &curves = drawing->strokes_for_write();
const bke::GreasePencilLayerFieldContext field_context(
grease_pencil, ATTR_DOMAIN_CURVE, layer_index);
set_curve_normal(curves, mode, field_context, selection_field);
}
}
static void node_geo_exec(GeoNodeExecParams params)
{
const NormalMode mode = static_cast<NormalMode>(params.node().custom1);
@ -55,7 +74,11 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (Curves *curves_id = geometry_set.get_curves_for_write()) {
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
set_normal_mode(curves, mode, selection_field);
const bke::CurvesFieldContext field_context{curves, ATTR_DOMAIN_CURVE};
set_curve_normal(curves, mode, field_context, selection_field);
}
if (geometry_set.has_grease_pencil()) {
set_grease_pencil_normal(*geometry_set.get_grease_pencil_for_write(), mode, selection_field);
}
});

View File

@ -176,6 +176,11 @@ struct GhostData {
eWS_Qual qual;
};
struct PlayArgs {
int argc;
char **argv;
};
/**
* The minimal context necessary for displaying an image.
* Used while displaying images both on load and while playing.
@ -247,7 +252,8 @@ struct PlayState {
int font_size;
/** Restarts player for file drop (drag & drop). */
char dropped_file[FILE_MAX];
int argc_next;
char **argv_next;
/** Force update when scrubbing with the cursor. */
bool need_frame_update;
@ -841,13 +847,15 @@ static void build_pict_list_from_image_sequence(GhostData *ghost_data,
const int fstep,
const bool *loading_p)
{
/* Load images into cache until the cache is full,
* this resolves choppiness for images that are slow to load, see: #81751. */
/* Load images into cache until the cache is full,
* this resolves choppiness for images that are slow to load, see: #81751. */
bool fill_cache = (
#ifdef USE_FRAME_CACHE_LIMIT
bool fill_cache = true;
true
#else
bool fill_cache = false;
false
#endif
);
int fp_framenr;
struct {
@ -986,28 +994,27 @@ static void update_sound_fps()
#endif
}
static void tag_change_frame(PlayState *ps, int cx)
static void playanim_change_frame_tag(PlayState *ps, int cx)
{
ps->need_frame_update = true;
ps->frame_cursor_x = cx;
}
static void change_frame(PlayState *ps)
static void playanim_change_frame(PlayState *ps)
{
if (!ps->need_frame_update) {
return;
}
int sizex, sizey;
int i, i_last;
if (BLI_listbase_is_empty(&picsbase)) {
return;
}
int sizex, sizey;
playanim_window_get_size(ps->ghost_data.window, &sizex, &sizey);
i_last = ((PlayAnimPict *)picsbase.last)->frame;
i = (i_last * ps->frame_cursor_x) / sizex;
const int i_last = ((PlayAnimPict *)picsbase.last)->frame;
/* Without this the indicator location isn't closest to the cursor. */
const int correct_rounding = (sizex / i_last) / 2;
int i = (i_last * (ps->frame_cursor_x + correct_rounding)) / sizex;
CLAMP(i, 0, i_last);
#ifdef WITH_AUDASPACE
@ -1409,7 +1416,7 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
if (type == GHOST_kEventButtonDown) {
if (inside_window) {
ps->ghost_data.qual |= WS_QUAL_LMOUSE;
tag_change_frame(ps, cx);
playanim_change_frame_tag(ps, cx);
}
}
else {
@ -1458,7 +1465,7 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
}
}
tag_change_frame(ps, cx);
playanim_change_frame_tag(ps, cx);
}
break;
}
@ -1506,14 +1513,14 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
if (ddd->dataType == GHOST_kDragnDropTypeFilenames) {
const GHOST_TStringArray *stra = static_cast<const GHOST_TStringArray *>(ddd->data);
int a;
for (a = 0; a < stra->count; a++) {
STRNCPY(ps->dropped_file, (char *)stra->strings[a]);
ps->go = false;
printf("drop file %s\n", stra->strings[a]);
break; /* only one drop element supported now */
ps->argc_next = stra->count;
ps->argv_next = static_cast<char **>(
MEM_mallocN(sizeof(char **) * ps->argc_next, __func__));
for (int i = 0; i < stra->count; i++) {
ps->argv_next[i] = BLI_strdup(reinterpret_cast<const char *>(stra->strings[i]));
}
ps->go = false;
printf("dropped %s, %d file(s)\n", ps->argv_next[0], ps->argc_next);
}
break;
}
@ -1627,18 +1634,15 @@ static bool playanim_window_font_scale_from_dpi(PlayState *ps)
}
/**
* \return The a path used to restart the animation player or nullptr to exit.
* \return True when `args_next` is filled with arguments used to re-run this function
* (used for drag & drop).
*/
static char *wm_main_playanim_intern(int argc, const char **argv)
static bool wm_main_playanim_intern(int argc, const char **argv, PlayArgs *args_next)
{
ImBuf *ibuf = nullptr;
static char filepath[FILE_MAX]; /* abused to return dropped file path */
int i;
/* This was done to disambiguate the name for use under c++. */
int start_x = 0, start_y = 0;
int window_pos[2] = {0, 0};
int sfra = -1;
int efra = -1;
int totblock;
PlayState ps{};
@ -1654,7 +1658,8 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
ps.loading = false;
ps.picture = nullptr;
ps.indicator = false;
ps.dropped_file[0] = 0;
ps.argc_next = 0;
ps.argv_next = nullptr;
ps.zoom = 1.0f;
ps.draw_flip[0] = false;
ps.draw_flip[1] = false;
@ -1669,17 +1674,16 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
&ps.display_ctx.display_settings);
ps.display_ctx.ui_scale = 1.0f;
/* Skip the first argument which is assumed to be '-a' (used to launch this player). */
while (argc > 1) {
if (argv[1][0] == '-') {
switch (argv[1][1]) {
while (argc > 0) {
if (argv[0][0] == '-') {
switch (argv[0][1]) {
case 'm':
fromdisk = true;
break;
case 'p':
if (argc > 3) {
start_x = atoi(argv[2]);
start_y = atoi(argv[3]);
if (argc > 2) {
window_pos[0] = atoi(argv[1]);
window_pos[1] = atoi(argv[2]);
argc -= 2;
argv += 2;
}
@ -1688,9 +1692,9 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
}
break;
case 'f':
if (argc > 3) {
double fps = atof(argv[2]);
double fps_base = atof(argv[3]);
if (argc > 2) {
double fps = atof(argv[1]);
double fps_base = atof(argv[2]);
if (fps == 0.0) {
fps = 1;
printf(
@ -1706,19 +1710,19 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
}
break;
case 's':
sfra = atoi(argv[2]);
sfra = atoi(argv[1]);
CLAMP(sfra, 1, MAXFRAME);
argc--;
argv++;
break;
case 'e':
efra = atoi(argv[2]);
efra = atoi(argv[1]);
CLAMP(efra, 1, MAXFRAME);
argc--;
argv++;
break;
case 'j':
ps.fstep = atoi(argv[2]);
ps.fstep = atoi(argv[1]);
CLAMP(ps.fstep, 1, MAXFRAME);
swaptime *= ps.fstep;
argc--;
@ -1726,7 +1730,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
break;
case 'c': {
#ifdef USE_FRAME_CACHE_LIMIT
const int memory_in_mb = max_ii(0, atoi(argv[2]));
const int memory_in_mb = max_ii(0, atoi(argv[1]));
g_frame_cache.memory_limit = size_t(memory_in_mb) * (1024 * 1024);
#endif
argc--;
@ -1734,7 +1738,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
break;
}
default:
printf("unknown option '%c': skipping\n", argv[1][1]);
printf("unknown option '%c': skipping\n", argv[0][1]);
break;
}
argc--;
@ -1745,14 +1749,13 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
}
}
if (argc > 1) {
STRNCPY(filepath, argv[1]);
}
else {
if (argc == 0) {
printf("%s: no filepath argument given\n", __func__);
exit(EXIT_FAILURE);
}
const char *filepath = argv[0];
if (IMB_isanim(filepath)) {
/* OCIO_TODO: support different input color spaces */
anim *anim;
@ -1795,8 +1798,12 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
GHOST_AddEventConsumer(ps.ghost_data.system, ghost_event_consumer);
ps.ghost_data.window = playanim_window_open(
ps.ghost_data.system, "Blender Animation Player", start_x, start_y, ibuf->x, ibuf->y);
ps.ghost_data.window = playanim_window_open(ps.ghost_data.system,
"Blender Animation Player",
window_pos[0],
window_pos[1],
ibuf->x,
ibuf->y);
}
// GHOST_ActivateWindowDrawingContext(ps.ghost_data.window);
@ -1830,10 +1837,19 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
GHOST_SwapWindowBuffers(ps.ghost_data.window);
/* One of the frames was invalid or not passed in. */
if (sfra == -1 || efra == -1) {
/* one of the frames was invalid, just use all images */
sfra = 1;
efra = MAXFRAME;
if (argc == 1) {
/* A single file was passed in, attempt to load all images from an image sequence.
* (if it is an image sequence). */
efra = MAXFRAME;
}
else {
/* Multiple files passed in, show each file without expanding image sequences.
* This occurs when dropping multiple files. */
efra = 1;
}
}
build_pict_list(
@ -1856,8 +1872,8 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
}
#endif
for (i = 2; i < argc; i++) {
STRNCPY(filepath, argv[i]);
for (int i = 1; i < argc; i++) {
filepath = argv[i];
build_pict_list(
&ps.ghost_data, &ps.display_ctx, filepath, (efra - sfra) + 1, ps.fstep, &ps.loading);
}
@ -1964,7 +1980,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
if (ps.go == false) {
break;
}
change_frame(&ps);
playanim_change_frame(&ps);
if (!has_event) {
PIL_sleep_ms(1);
}
@ -2053,8 +2069,8 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
g_audaspace.source = nullptr;
#endif
/* we still miss freeing a lot!,
* but many areas could skip initialization too for anim play */
/* We still miss freeing a lot!
* But many areas could skip initialization too for anim play. */
DEG_free_node_types();
@ -2072,32 +2088,30 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
GHOST_DisposeWindow(ps.ghost_data.system, ps.ghost_data.window);
/* early exit, IMB and BKE should be exited only in end */
if (ps.dropped_file[0]) {
STRNCPY(filepath, ps.dropped_file);
return filepath;
if (ps.argv_next) {
args_next->argc = ps.argc_next;
args_next->argv = ps.argv_next;
return true;
}
GHOST_DisposeSystem(ps.ghost_data.system);
IMB_exit();
totblock = MEM_get_memory_blocks_in_use();
if (totblock != 0) {
/* prints many bAKey, bArgument's which are tricky to fix */
#if 0
const int totblock = MEM_get_memory_blocks_in_use();
if (totblock != 0) {
/* Prints many bAKey, bArgument's which are tricky to fix. */
printf("Error Totblock: %d\n", totblock);
MEM_printmemlist();
#endif
}
#endif
return nullptr;
return false;
}
void WM_main_playanim(int argc, const char **argv)
{
const char *argv_next[2];
bool looping = true;
#ifdef WITH_AUDASPACE
{
AUD_DeviceSpecs specs;
@ -2114,21 +2128,27 @@ void WM_main_playanim(int argc, const char **argv)
}
#endif
while (looping) {
const char *filepath = wm_main_playanim_intern(argc, argv);
PlayArgs args_next = {0};
do {
PlayArgs args_free = args_next;
args_next = {0};
if (filepath) { /* use simple args */
argv_next[0] = argv[0];
argv_next[1] = filepath;
argc = 2;
/* continue with new args */
argv = argv_next;
if (wm_main_playanim_intern(argc, argv, &args_next)) {
argc = args_next.argc;
argv = const_cast<const char **>(args_next.argv);
}
else {
looping = false;
argc = 0;
argv = nullptr;
}
}
if (args_free.argv) {
for (int i = 0; i < args_free.argc; i++) {
MEM_freeN(args_free.argv[i]);
}
MEM_freeN(args_free.argv);
}
} while (argv != nullptr);
#ifdef WITH_AUDASPACE
AUD_exit(g_audaspace.audio_device);

View File

@ -1394,8 +1394,8 @@ static int arg_handle_playback_mode(int argc, const char **argv, void * /*data*/
IMB_ffmpeg_init();
# endif
/* This function knows to skip this argument ('-a'). */
WM_main_playanim(argc, argv);
/* Skip this argument (`-a`). */
WM_main_playanim(argc - 1, argv + 1);
exit(EXIT_SUCCESS);
}