Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2021-08-27 07:15:27 +0300
committerHans Goudey <h.goudey@me.com>2021-08-27 07:15:27 +0300
commitad0dbde6536c1ac21554451ce922611287afafb9 (patch)
tree98e52be91df997110392aec094ff6489741a6412
parentef2a48329d8db78d7c98580970fbe15a84334f38 (diff)
parent523bc981cfeecead5050e7af44bbe252c166d718 (diff)
Merge branch 'master' into temp-geometry-nodes-fields
-rw-r--r--release/scripts/startup/bl_ui/properties_data_gpencil.py5
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c38
-rw-r--r--source/blender/editors/interface/interface_eyedropper_color.c38
-rw-r--r--source/blender/editors/interface/interface_eyedropper_datablock.c46
-rw-r--r--source/blender/editors/interface/interface_eyedropper_depth.c9
-rw-r--r--source/blender/editors/interface/interface_eyedropper_intern.h9
-rw-r--r--source/blender/editors/object/object_vgroup.c40
-rw-r--r--source/blender/editors/screen/screen_ops.c26
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c6
-rw-r--r--source/blender/modifiers/intern/MOD_mask.cc433
-rw-r--r--source/blender/python/gpu/gpu_py_shader.c39
-rw-r--r--source/blender/python/gpu/gpu_py_state.c26
-rw-r--r--source/blender/sequencer/intern/effects.c53
-rw-r--r--source/blender/windowmanager/WM_api.h16
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c4
-rw-r--r--source/blender/windowmanager/intern/wm_window.c16
17 files changed, 668 insertions, 137 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_gpencil.py b/release/scripts/startup/bl_ui/properties_data_gpencil.py
index b273eee4e19..793c4a52350 100644
--- a/release/scripts/startup/bl_ui/properties_data_gpencil.py
+++ b/release/scripts/startup/bl_ui/properties_data_gpencil.py
@@ -342,6 +342,11 @@ class DATA_PT_gpencil_vertex_groups(ObjectButtonsPanel, Panel):
col.operator("object.vertex_group_add", icon='ADD', text="")
col.operator("object.vertex_group_remove", icon='REMOVE', text="").all = False
+ if group:
+ col.separator()
+ col.operator("object.vertex_group_move", icon='TRIA_UP', text="").direction = 'UP'
+ col.operator("object.vertex_group_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+
if ob.vertex_groups:
row = layout.row()
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index b52bfc81b7a..2e7b0ce532c 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -125,24 +125,13 @@ void eyedropper_draw_cursor_text_window(const struct wmWindow *window, const cha
eyedropper_draw_cursor_text_ex(x, y, name);
}
-void eyedropper_draw_cursor_text_region(const struct bContext *C,
- const ARegion *region,
- const char *name)
+void eyedropper_draw_cursor_text_region(const int x, const int y, const char *name)
{
- wmWindow *win = CTX_wm_window(C);
- const int x = win->eventstate->x;
- const int y = win->eventstate->y;
-
- if ((name[0] == '\0') || (BLI_rcti_isect_pt(&region->winrct, x, y) == false)) {
+ if (name[0] == '\0') {
return;
}
- const int mval[2] = {
- x - region->winrct.xmin,
- y - region->winrct.ymin,
- };
-
- eyedropper_draw_cursor_text_ex(mval[0], mval[1], name);
+ eyedropper_draw_cursor_text_ex(x, y, name);
}
/**
@@ -168,4 +157,25 @@ uiBut *eyedropper_get_property_button_under_mouse(bContext *C, const wmEvent *ev
return but;
}
+void datadropper_win_area_find(
+ const bContext *C, const int mval[2], int r_mval[2], wmWindow **r_win, ScrArea **r_area)
+{
+ bScreen *screen = CTX_wm_screen(C);
+
+ *r_win = CTX_wm_window(C);
+ *r_area = BKE_screen_find_area_xy(screen, -1, mval[0], mval[1]);
+ if (*r_area == NULL) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ *r_win = WM_window_find_under_cursor(wm, NULL, *r_win, mval, r_mval);
+ if (*r_win) {
+ screen = WM_window_get_active_screen(*r_win);
+ *r_area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, r_mval[0], r_mval[1]);
+ }
+ }
+ else if (mval != r_mval) {
+ r_mval[0] = mval[0];
+ r_mval[1] = mval[1];
+ }
+}
+
/** \} */
diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c
index ba72cecc514..9d06fb2b27a 100644
--- a/source/blender/editors/interface/interface_eyedropper_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_color.c
@@ -337,52 +337,41 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
const char *display_device = CTX_data_scene(C)->display_settings.display_device;
struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
- wmWindow *win = CTX_wm_window(C);
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
- if (area == NULL) {
- int mval[2] = {mx, my};
- if (WM_window_find_under_cursor(wm, NULL, win, mval, &win, mval)) {
- mx = mval[0];
- my = mval[1];
- screen = WM_window_get_active_screen(win);
- area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
- }
- else {
- win = NULL;
- }
- }
+ wmWindow *win;
+ ScrArea *area;
+ int mval[2] = {mx, my};
+ datadropper_win_area_find(C, mval, mval, &win, &area);
if (area) {
if (area->spacetype == SPACE_IMAGE) {
- ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my);
+ ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mval[0], mval[1]);
if (region) {
SpaceImage *sima = area->spacedata.first;
- int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
+ int region_mval[2] = {mval[0] - region->winrct.xmin, mval[1] - region->winrct.ymin};
- if (ED_space_image_color_sample(sima, region, mval, r_col, NULL)) {
+ if (ED_space_image_color_sample(sima, region, region_mval, r_col, NULL)) {
return;
}
}
}
else if (area->spacetype == SPACE_NODE) {
- ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my);
+ ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mval[0], mval[1]);
if (region) {
SpaceNode *snode = area->spacedata.first;
- const int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
+ int region_mval[2] = {mval[0] - region->winrct.xmin, mval[1] - region->winrct.ymin};
- if (ED_space_node_color_sample(bmain, snode, region, mval, r_col)) {
+ if (ED_space_node_color_sample(bmain, snode, region, region_mval, r_col)) {
return;
}
}
}
else if (area->spacetype == SPACE_CLIP) {
- ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my);
+ ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mval[0], mval[1]);
if (region) {
SpaceClip *sc = area->spacedata.first;
- int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
+ int region_mval[2] = {mval[0] - region->winrct.xmin, mval[1] - region->winrct.ymin};
- if (ED_space_clip_color_sample(sc, region, mval, r_col)) {
+ if (ED_space_clip_color_sample(sc, region, region_mval, r_col)) {
return;
}
}
@@ -391,7 +380,6 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
if (win) {
/* Fallback to simple opengl picker. */
- const int mval[2] = {mx, my};
WM_window_pixel_sample_read(wm, win, mval, r_col);
IMB_colormanagement_display_to_scene_linear_v3(r_col, display);
}
diff --git a/source/blender/editors/interface/interface_eyedropper_datablock.c b/source/blender/editors/interface/interface_eyedropper_datablock.c
index 8c605598cbc..4996c803dfe 100644
--- a/source/blender/editors/interface/interface_eyedropper_datablock.c
+++ b/source/blender/editors/interface/interface_eyedropper_datablock.c
@@ -71,13 +71,16 @@ typedef struct DataDropper {
ScrArea *cursor_area; /* Area under the cursor */
ARegionType *art;
void *draw_handle_pixel;
+ int name_pos[2];
char name[200];
} DataDropper;
-static void datadropper_draw_cb(const struct bContext *C, ARegion *region, void *arg)
+static void datadropper_draw_cb(const struct bContext *UNUSED(C),
+ ARegion *UNUSED(region),
+ void *arg)
{
DataDropper *ddr = arg;
- eyedropper_draw_cursor_text_region(C, region, ddr->name);
+ eyedropper_draw_cursor_text_region(UNPACK2(ddr->name_pos), ddr->name);
}
static int datadropper_init(bContext *C, wmOperator *op)
@@ -148,12 +151,10 @@ static void datadropper_exit(bContext *C, wmOperator *op)
/**
* \brief get the ID from the 3D view or outliner.
*/
-static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int my, ID **r_id)
+static void datadropper_id_sample_pt(
+ bContext *C, wmWindow *win, ScrArea *area, DataDropper *ddr, int mx, int my, ID **r_id)
{
- /* we could use some clever */
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *area = BKE_screen_find_area_xy(screen, -1, mx, my);
-
+ wmWindow *win_prev = CTX_wm_window(C);
ScrArea *area_prev = CTX_wm_area(C);
ARegion *region_prev = CTX_wm_region(C);
@@ -166,6 +167,7 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int
const int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
Base *base;
+ CTX_wm_window_set(C, win);
CTX_wm_area_set(C, area);
CTX_wm_region_set(C, region);
@@ -202,11 +204,15 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int
BLI_snprintf(ddr->name, sizeof(ddr->name), "%s: %s", ddr->idcode_name, id->name + 2);
*r_id = id;
}
+
+ ddr->name_pos[0] = mval[0];
+ ddr->name_pos[1] = mval[1];
}
}
}
}
+ CTX_wm_window_set(C, win_prev);
CTX_wm_area_set(C, area_prev);
CTX_wm_region_set(C, region_prev);
}
@@ -232,7 +238,13 @@ static bool datadropper_id_sample(bContext *C, DataDropper *ddr, int mx, int my)
{
ID *id = NULL;
- datadropper_id_sample_pt(C, ddr, mx, my, &id);
+ wmWindow *win;
+ ScrArea *area;
+
+ int mval[] = {mx, my};
+ datadropper_win_area_find(C, mval, mval, &win, &area);
+
+ datadropper_id_sample_pt(C, win, area, ddr, mval[0], mval[1], &id);
return datadropper_id_set(C, ddr, id);
}
@@ -244,14 +256,8 @@ static void datadropper_cancel(bContext *C, wmOperator *op)
}
/* To switch the draw callback when region under mouse event changes */
-static void datadropper_set_draw_callback_region(bContext *C,
- DataDropper *ddr,
- const int mx,
- const int my)
+static void datadropper_set_draw_callback_region(ScrArea *area, DataDropper *ddr)
{
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *area = BKE_screen_find_area_xy(screen, -1, mx, my);
-
if (area) {
/* If spacetype changed */
if (area->spacetype != ddr->cursor_area->spacetype) {
@@ -300,10 +306,16 @@ static int datadropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
else if (event->type == MOUSEMOVE) {
ID *id = NULL;
+ wmWindow *win;
+ ScrArea *area;
+
+ int mval[] = {event->x, event->y};
+ datadropper_win_area_find(C, mval, mval, &win, &area);
+
/* Set the region for eyedropper cursor text drawing */
- datadropper_set_draw_callback_region(C, ddr, event->x, event->y);
+ datadropper_set_draw_callback_region(area, ddr);
- datadropper_id_sample_pt(C, ddr, event->x, event->y, &id);
+ datadropper_id_sample_pt(C, win, area, ddr, mval[0], mval[1], &id);
}
return OPERATOR_RUNNING_MODAL;
diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c
index a64fad8c333..311f718d950 100644
--- a/source/blender/editors/interface/interface_eyedropper_depth.c
+++ b/source/blender/editors/interface/interface_eyedropper_depth.c
@@ -72,13 +72,16 @@ typedef struct DepthDropper {
ARegionType *art;
void *draw_handle_pixel;
+ int name_pos[2];
char name[200];
} DepthDropper;
-static void depthdropper_draw_cb(const struct bContext *C, ARegion *region, void *arg)
+static void depthdropper_draw_cb(const struct bContext *UNUSED(C),
+ ARegion *UNUSED(region),
+ void *arg)
{
DepthDropper *ddr = arg;
- eyedropper_draw_cursor_text_region(C, region, ddr->name);
+ eyedropper_draw_cursor_text_region(UNPACK2(ddr->name_pos), ddr->name);
}
static int depthdropper_init(bContext *C, wmOperator *op)
@@ -172,6 +175,8 @@ static void depthdropper_depth_sample_pt(
/* weak, we could pass in some reference point */
const float *view_co = v3d->camera ? v3d->camera->obmat[3] : rv3d->viewinv[3];
const int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
+ copy_v2_v2_int(ddr->name_pos, mval);
+
float co[3];
CTX_wm_area_set(C, area);
diff --git a/source/blender/editors/interface/interface_eyedropper_intern.h b/source/blender/editors/interface/interface_eyedropper_intern.h
index 96a2c6ed111..f9f3fcfb5d1 100644
--- a/source/blender/editors/interface/interface_eyedropper_intern.h
+++ b/source/blender/editors/interface/interface_eyedropper_intern.h
@@ -24,10 +24,13 @@
/* interface_eyedropper.c */
void eyedropper_draw_cursor_text_window(const struct wmWindow *window, const char *name);
-void eyedropper_draw_cursor_text_region(const struct bContext *C,
- const struct ARegion *region,
- const char *name);
+void eyedropper_draw_cursor_text_region(const int x, const int y, const char *name);
uiBut *eyedropper_get_property_button_under_mouse(bContext *C, const wmEvent *event);
+void datadropper_win_area_find(const struct bContext *C,
+ const int mval[2],
+ int r_mval[2],
+ struct wmWindow **r_win,
+ struct ScrArea **r_area);
/* interface_eyedropper_color.c (expose for color-band picker) */
void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3]);
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 7a42c9d5d8b..f0ab082cd9c 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -28,6 +28,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_curve_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -39,6 +40,7 @@
#include "BLI_alloca.h"
#include "BLI_array.h"
#include "BLI_blenlib.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_utildefines_stack.h"
@@ -4083,16 +4085,38 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
}
else {
int dvert_tot = 0;
+ /* Grease pencil stores vertex groups separately for each stroke,
+ * so remap each stroke's weights separately. */
+ if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = ob->data;
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ dvert = gps->dvert;
+ dvert_tot = gps->totpoints;
+ if (dvert) {
+ while (dvert_tot--) {
+ if (dvert->totweight) {
+ BKE_defvert_remap(dvert, sort_map, defbase_tot);
+ }
+ dvert++;
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ BKE_object_defgroup_array_get(ob->data, &dvert, &dvert_tot);
- BKE_object_defgroup_array_get(ob->data, &dvert, &dvert_tot);
-
- /* Create as necessary. */
- if (dvert) {
- while (dvert_tot--) {
- if (dvert->totweight) {
- BKE_defvert_remap(dvert, sort_map, defbase_tot);
+ /* Create as necessary. */
+ if (dvert) {
+ while (dvert_tot--) {
+ if (dvert->totweight) {
+ BKE_defvert_remap(dvert, sort_map, defbase_tot);
+ }
+ dvert++;
}
- dvert++;
}
}
}
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index cff3ecfbbd3..daac196a90c 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -1738,19 +1738,19 @@ static int area_snap_calc_location(const bScreen *screen,
int snap_dist_best = INT_MAX;
{
const float div_array[] = {
- /* Middle. */
- 1.0f / 2.0f,
- /* Thirds. */
- 1.0f / 3.0f,
- 2.0f / 3.0f,
- /* Quarters. */
- 1.0f / 4.0f,
- 3.0f / 4.0f,
- /* Eighth. */
- 1.0f / 8.0f,
- 3.0f / 8.0f,
- 5.0f / 8.0f,
- 7.0f / 8.0f,
+ 0.0f,
+ 1.0f / 12.0f,
+ 2.0f / 12.0f,
+ 3.0f / 12.0f,
+ 4.0f / 12.0f,
+ 5.0f / 12.0f,
+ 6.0f / 12.0f,
+ 7.0f / 12.0f,
+ 8.0f / 12.0f,
+ 9.0f / 12.0f,
+ 10.0f / 12.0f,
+ 11.0f / 12.0f,
+ 1.0f,
};
/* Test the snap to the best division. */
for (int i = 0; i < ARRAY_SIZE(div_array); i++) {
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 1bebbc35747..13213f70fed 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -298,6 +298,7 @@ enum {
/* Mask Modifier -> flag */
enum {
MOD_MASK_INV = (1 << 0),
+ MOD_MASK_SMOOTH = (1 << 1),
};
typedef struct ArrayModifierData {
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 486d8d13564..f11d845c582 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -4431,6 +4431,12 @@ static void rna_def_modifier_mask(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Invert", "Use vertices that are not part of region defined");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "use_smooth", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MASK_SMOOTH);
+ RNA_def_property_ui_text(
+ prop, "Smooth", "Use vertex group weights to cut faces at the weight contour");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "threshold");
RNA_def_property_range(prop, 0.0, 1.0);
diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc
index 9aa8e3dd7c8..aca90e0533c 100644
--- a/source/blender/modifiers/intern/MOD_mask.cc
+++ b/source/blender/modifiers/intern/MOD_mask.cc
@@ -27,6 +27,7 @@
#include "BLI_ghash.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLT_translation.h"
@@ -214,6 +215,40 @@ static void computed_masked_edges(const Mesh *mesh,
*r_num_masked_edges = num_masked_edges;
}
+static void computed_masked_edges_smooth(const Mesh *mesh,
+ Span<bool> vertex_mask,
+ MutableSpan<int> r_edge_map,
+ uint *r_num_masked_edges,
+ uint *r_num_add_vertices)
+{
+ BLI_assert(mesh->totedge == r_edge_map.size());
+
+ uint num_masked_edges = 0;
+ uint num_add_vertices = 0;
+ for (int i : IndexRange(mesh->totedge)) {
+ const MEdge &edge = mesh->medge[i];
+
+ /* only add if both verts will be in new mesh */
+ bool v1 = vertex_mask[edge.v1];
+ bool v2 = vertex_mask[edge.v2];
+ if (v1 && v2) {
+ r_edge_map[i] = num_masked_edges;
+ num_masked_edges++;
+ }
+ else if (v1 != v2) {
+ r_edge_map[i] = -2;
+ num_add_vertices++;
+ }
+ else {
+ r_edge_map[i] = -1;
+ }
+ }
+
+ num_masked_edges += num_add_vertices;
+ *r_num_masked_edges = num_masked_edges;
+ *r_num_add_vertices = num_add_vertices;
+}
+
static void computed_masked_polygons(const Mesh *mesh,
Span<bool> vertex_mask,
Vector<int> &r_masked_poly_indices,
@@ -224,7 +259,7 @@ static void computed_masked_polygons(const Mesh *mesh,
BLI_assert(mesh->totvert == vertex_mask.size());
r_masked_poly_indices.reserve(mesh->totpoly);
- r_loop_starts.reserve(mesh->totloop);
+ r_loop_starts.reserve(mesh->totpoly);
uint num_masked_loops = 0;
for (int i : IndexRange(mesh->totpoly)) {
@@ -250,6 +285,76 @@ static void computed_masked_polygons(const Mesh *mesh,
*r_num_masked_loops = num_masked_loops;
}
+static void compute_interpolated_polygons(const Mesh *mesh,
+ Span<bool> vertex_mask,
+ uint num_add_vertices,
+ uint num_masked_loops,
+ Vector<int> &r_masked_poly_indices,
+ Vector<int> &r_loop_starts,
+ uint *r_num_add_edges,
+ uint *r_num_add_polys,
+ uint *r_num_add_loops)
+{
+ BLI_assert(mesh->totvert == vertex_mask.size());
+
+ /* Can't really know ahead of time how much space to use exactly. Estimate limit instead. */
+ /* NOTE: this reserve can only lift the capacity if there are ngons, which get split. */
+ r_masked_poly_indices.reserve(r_masked_poly_indices.size() + num_add_vertices);
+ r_loop_starts.reserve(r_loop_starts.size() + num_add_vertices);
+
+ uint num_add_edges = 0;
+ uint num_add_polys = 0;
+ uint num_add_loops = 0;
+ for (int i : IndexRange(mesh->totpoly)) {
+ const MPoly &poly_src = mesh->mpoly[i];
+
+ int in_count = 0;
+ int start = -1;
+ int dst_totloop = -1;
+ Span<MLoop> loops_src(&mesh->mloop[poly_src.loopstart], poly_src.totloop);
+ for (const int j : loops_src.index_range()) {
+ const MLoop &loop = loops_src[j];
+ if (vertex_mask[loop.v]) {
+ in_count++;
+ }
+ else if (start == -1) {
+ start = j;
+ }
+ }
+ if (0 < in_count && in_count < poly_src.totloop) {
+ /* Ring search starting at a vertex which is not included in the mask. */
+ const MLoop *last_loop = &loops_src[start];
+ bool v_loop_in_mask_last = vertex_mask[last_loop->v];
+ for (const int j : loops_src.index_range()) {
+ const MLoop &loop = loops_src[(start + 1 + j) % poly_src.totloop];
+ const bool v_loop_in_mask = vertex_mask[loop.v];
+ if (v_loop_in_mask && !v_loop_in_mask_last) {
+ dst_totloop = 3;
+ }
+ else if (!v_loop_in_mask && v_loop_in_mask_last) {
+ BLI_assert(dst_totloop > 2);
+ r_masked_poly_indices.append(i);
+ r_loop_starts.append(num_masked_loops + num_add_loops);
+ num_add_loops += dst_totloop;
+ num_add_polys++;
+ num_add_edges++;
+ dst_totloop = -1;
+ }
+ else if (v_loop_in_mask && v_loop_in_mask_last) {
+ BLI_assert(dst_totloop > 2);
+ dst_totloop++;
+ }
+ last_loop = &loop;
+ v_loop_in_mask_last = v_loop_in_mask;
+ }
+ }
+ }
+
+ *r_num_add_edges = num_add_edges;
+ *r_num_add_polys = num_add_polys;
+ *r_num_add_loops = num_add_loops;
+}
+
void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span<int> vertex_map)
{
BLI_assert(src_mesh.totvert == vertex_map.size());
@@ -267,6 +372,89 @@ void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span
}
}
+static float get_interp_factor_from_vgroup(
+ MDeformVert *dvert, int defgrp_index, float threshold, uint v1, uint v2)
+{
+ /* NOTE: this calculation is done twice for every vertex,
+ * instead of storing it the first time and then reusing it. */
+ float value1 = BKE_defvert_find_weight(&dvert[v1], defgrp_index);
+ float value2 = BKE_defvert_find_weight(&dvert[v2], defgrp_index);
+ return (threshold - value1) / (value2 - value1);
+}
+
+static void add_interp_verts_copy_edges_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ Span<bool> vertex_mask,
+ Span<int> vertex_map,
+ MDeformVert *dvert,
+ int defgrp_index,
+ float threshold,
+ uint num_masked_edges,
+ uint num_add_verts,
+ MutableSpan<int> r_edge_map)
+{
+ BLI_assert(src_mesh.totvert == vertex_mask.size());
+ BLI_assert(src_mesh.totedge == r_edge_map.size());
+
+ uint vert_index = dst_mesh.totvert - num_add_verts;
+ uint edge_index = num_masked_edges - num_add_verts;
+ for (int i_src : IndexRange(src_mesh.totedge)) {
+ if (r_edge_map[i_src] != -1) {
+ int i_dst = r_edge_map[i_src];
+ if (i_dst == -2) {
+ i_dst = edge_index;
+ }
+ const MEdge &e_src = src_mesh.medge[i_src];
+ MEdge &e_dst = dst_mesh.medge[i_dst];
+
+ CustomData_copy_data(&src_mesh.edata, &dst_mesh.edata, i_src, i_dst, 1);
+ e_dst = e_src;
+ e_dst.v1 = vertex_map[e_src.v1];
+ e_dst.v2 = vertex_map[e_src.v2];
+ }
+ if (r_edge_map[i_src] == -2) {
+ const int i_dst = edge_index++;
+ r_edge_map[i_src] = i_dst;
+ const MEdge &e_src = src_mesh.medge[i_src];
+ /* Cut destination edge and make v1 the new vertex. */
+ MEdge &e_dst = dst_mesh.medge[i_dst];
+ if (!vertex_mask[e_src.v1]) {
+ e_dst.v1 = vert_index;
+ }
+ else {
+ BLI_assert(!vertex_mask[e_src.v2]);
+ e_dst.v2 = e_dst.v1;
+ e_dst.v1 = vert_index;
+ }
+ /* Create the new vertex. */
+ float fac = get_interp_factor_from_vgroup(
+ dvert, defgrp_index, threshold, e_src.v1, e_src.v2);
+
+ float weights[2] = {1.0f - fac, fac};
+ CustomData_interp(
+ &src_mesh.vdata, &dst_mesh.vdata, (int *)&e_src.v1, weights, NULL, 2, vert_index);
+ MVert &v = dst_mesh.mvert[vert_index];
+ MVert &v1 = src_mesh.mvert[e_src.v1];
+ MVert &v2 = src_mesh.mvert[e_src.v2];
+
+ interp_v3_v3v3(v.co, v1.co, v2.co, fac);
+
+ float no1[3];
+ float no2[3];
+ normal_short_to_float_v3(no1, v1.no);
+ normal_short_to_float_v3(no2, v2.no);
+ mul_v3_fl(no1, weights[0]);
+ madd_v3_v3fl(no1, no2, weights[1]);
+ normalize_v3(no1);
+ normal_float_to_short_v3(v.no, no1);
+
+ vert_index++;
+ }
+ }
+ BLI_assert(vert_index == dst_mesh.totvert);
+ BLI_assert(edge_index == num_masked_edges);
+}
+
void copy_masked_edges_to_new_mesh(const Mesh &src_mesh,
Mesh &dst_mesh,
Span<int> vertex_map,
@@ -276,7 +464,7 @@ void copy_masked_edges_to_new_mesh(const Mesh &src_mesh,
BLI_assert(src_mesh.totedge == edge_map.size());
for (const int i_src : IndexRange(src_mesh.totedge)) {
const int i_dst = edge_map[i_src];
- if (i_dst == -1) {
+ if (i_dst == -1 || i_dst == -2) {
continue;
}
@@ -290,6 +478,36 @@ void copy_masked_edges_to_new_mesh(const Mesh &src_mesh,
}
}
+static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ Span<int> vertex_map,
+ Span<int> edge_map,
+ Span<int> masked_poly_indices,
+ Span<int> new_loop_starts,
+ int num_masked_polys)
+{
+ for (const int i_dst : IndexRange(num_masked_polys)) {
+ const int i_src = masked_poly_indices[i_dst];
+
+ const MPoly &mp_src = src_mesh.mpoly[i_src];
+ MPoly &mp_dst = dst_mesh.mpoly[i_dst];
+ const int i_ml_src = mp_src.loopstart;
+ const int i_ml_dst = new_loop_starts[i_dst];
+
+ CustomData_copy_data(&src_mesh.pdata, &dst_mesh.pdata, i_src, i_dst, 1);
+ CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src, i_ml_dst, mp_src.totloop);
+
+ const MLoop *ml_src = src_mesh.mloop + i_ml_src;
+ MLoop *ml_dst = dst_mesh.mloop + i_ml_dst;
+
+ mp_dst = mp_src;
+ mp_dst.loopstart = i_ml_dst;
+ for (int i : IndexRange(mp_src.totloop)) {
+ ml_dst[i].v = vertex_map[ml_src[i].v];
+ ml_dst[i].e = edge_map[ml_src[i].e];
+ }
+ }
+}
void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
Mesh &dst_mesh,
Span<int> vertex_map,
@@ -320,6 +538,137 @@ void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
}
}
+static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ Span<bool> vertex_mask,
+ Span<int> vertex_map,
+ Span<int> edge_map,
+ MDeformVert *dvert,
+ int defgrp_index,
+ float threshold,
+ Span<int> masked_poly_indices,
+ Span<int> new_loop_starts,
+ int num_masked_polys,
+ int num_add_edges)
+{
+ int edge_index = dst_mesh.totedge - num_add_edges;
+ int sub_poly_index = 0;
+ int last_i_src = -1;
+ for (const int i_dst :
+ IndexRange(num_masked_polys, masked_poly_indices.size() - num_masked_polys)) {
+ const int i_src = masked_poly_indices[i_dst];
+ if (i_src == last_i_src) {
+ sub_poly_index++;
+ }
+ else {
+ sub_poly_index = 0;
+ last_i_src = i_src;
+ }
+
+ const MPoly &mp_src = src_mesh.mpoly[i_src];
+ MPoly &mp_dst = dst_mesh.mpoly[i_dst];
+ const int i_ml_src = mp_src.loopstart;
+ int i_ml_dst = new_loop_starts[i_dst];
+ const int mp_totloop = (i_dst + 1 < new_loop_starts.size() ? new_loop_starts[i_dst + 1] :
+ dst_mesh.totloop) -
+ i_ml_dst;
+
+ CustomData_copy_data(&src_mesh.pdata, &dst_mesh.pdata, i_src, i_dst, 1);
+
+ mp_dst = mp_src;
+ mp_dst.loopstart = i_ml_dst;
+ mp_dst.totloop = mp_totloop;
+
+ /* Ring search starting at a vertex which is not included in the mask. */
+ int start = -sub_poly_index - 1;
+ bool skip = false;
+ Span<MLoop> loops_src(&src_mesh.mloop[i_ml_src], mp_src.totloop);
+ for (const int j : loops_src.index_range()) {
+ if (!vertex_mask[loops_src[j].v]) {
+ if (start == -1) {
+ start = j;
+ break;
+ }
+ else if (!skip) {
+ skip = true;
+ }
+ }
+ else if (skip) {
+ skip = false;
+ start++;
+ }
+ }
+
+ BLI_assert(start >= 0);
+ BLI_assert(edge_index < dst_mesh.totedge);
+
+ const MLoop *last_loop = &loops_src[start];
+ bool v_loop_in_mask_last = vertex_mask[last_loop->v];
+ int last_index = start;
+ for (const int j : loops_src.index_range()) {
+ const int index = (start + 1 + j) % mp_src.totloop;
+ const MLoop &loop = loops_src[index];
+ const bool v_loop_in_mask = vertex_mask[loop.v];
+ if (v_loop_in_mask && !v_loop_in_mask_last) {
+ /* Start new cut. */
+ float fac = get_interp_factor_from_vgroup(
+ dvert, defgrp_index, threshold, last_loop->v, loop.v);
+ float weights[2] = {1.0f - fac, fac};
+ int indices[2] = {i_ml_src + last_index, i_ml_src + index};
+ CustomData_interp(&src_mesh.ldata, &dst_mesh.ldata, indices, weights, NULL, 2, i_ml_dst);
+ MLoop &cut_dst_loop = dst_mesh.mloop[i_ml_dst];
+ cut_dst_loop.e = edge_map[last_loop->e];
+ cut_dst_loop.v = dst_mesh.medge[cut_dst_loop.e].v1;
+ i_ml_dst++;
+
+ CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src + index, i_ml_dst, 1);
+ MLoop &next_dst_loop = dst_mesh.mloop[i_ml_dst];
+ next_dst_loop.v = vertex_map[loop.v];
+ next_dst_loop.e = edge_map[loop.e];
+ i_ml_dst++;
+ }
+ else if (!v_loop_in_mask && v_loop_in_mask_last) {
+ BLI_assert(i_ml_dst != mp_dst.loopstart);
+ /* End active cut. */
+ float fac = get_interp_factor_from_vgroup(
+ dvert, defgrp_index, threshold, last_loop->v, loop.v);
+ float weights[2] = {1.0f - fac, fac};
+ int indices[2] = {i_ml_src + last_index, i_ml_src + index};
+ CustomData_interp(&src_mesh.ldata, &dst_mesh.ldata, indices, weights, NULL, 2, i_ml_dst);
+ MLoop &cut_dst_loop = dst_mesh.mloop[i_ml_dst];
+ cut_dst_loop.e = edge_index;
+ cut_dst_loop.v = dst_mesh.medge[edge_map[last_loop->e]].v1;
+ i_ml_dst++;
+
+ /* Create closing edge. */
+ MEdge &cut_edge = dst_mesh.medge[edge_index];
+ cut_edge.v1 = dst_mesh.mloop[mp_dst.loopstart].v;
+ cut_edge.v2 = cut_dst_loop.v;
+ BLI_assert(cut_edge.v1 != cut_edge.v2);
+ cut_edge.flag = ME_EDGEDRAW | ME_EDGERENDER;
+ edge_index++;
+
+ /* Only handle one of the cuts per iteration. */
+ break;
+ }
+ else if (v_loop_in_mask && v_loop_in_mask_last) {
+ BLI_assert(i_ml_dst != mp_dst.loopstart);
+ /* Extend active poly. */
+ CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src + index, i_ml_dst, 1);
+ MLoop &dst_loop = dst_mesh.mloop[i_ml_dst];
+ dst_loop.v = vertex_map[loop.v];
+ dst_loop.e = edge_map[loop.e];
+ i_ml_dst++;
+ }
+ last_loop = &loop;
+ last_index = index;
+ v_loop_in_mask_last = v_loop_in_mask;
+ }
+ BLI_assert(mp_dst.loopstart + mp_dst.totloop == i_ml_dst);
+ }
+ BLI_assert(edge_index == dst_mesh.totedge);
+}
+
/* Components of the algorithm:
* 1. Figure out which vertices should be present in the output mesh.
* 2. Find edges and polygons only using those vertices.
@@ -329,6 +678,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx)
{
MaskModifierData *mmd = reinterpret_cast<MaskModifierData *>(md);
const bool invert_mask = mmd->flag & MOD_MASK_INV;
+ const bool use_interpolation = mmd->mode == MOD_MASK_MODE_VGROUP &&
+ (mmd->flag & MOD_MASK_SMOOTH);
/* Return empty or input mesh when there are no vertex groups. */
MDeformVert *dvert = (MDeformVert *)CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT);
@@ -342,6 +693,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx)
return mesh;
}
+ int defgrp_index = -1;
+
Array<bool> vertex_mask;
if (mmd->mode == MOD_MASK_MODE_ARM) {
Object *armature_ob = mmd->ob_arm;
@@ -355,7 +708,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx)
compute_vertex_mask__armature_mode(dvert, mesh, armature_ob, mmd->threshold, vertex_mask);
}
else {
- int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, mmd->vgroup);
+ BLI_assert(mmd->mode == MOD_MASK_MODE_VGROUP);
+ defgrp_index = BKE_id_defgroup_name_index(&mesh->id, mmd->vgroup);
/* Return input mesh if the vertex group does not exist. */
if (defgrp_index == -1) {
@@ -376,7 +730,15 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx)
Array<int> edge_map(mesh->totedge);
uint num_masked_edges;
- computed_masked_edges(mesh, vertex_mask, edge_map, &num_masked_edges);
+ uint num_add_vertices;
+ if (use_interpolation) {
+ computed_masked_edges_smooth(
+ mesh, vertex_mask, edge_map, &num_masked_edges, &num_add_vertices);
+ }
+ else {
+ computed_masked_edges(mesh, vertex_mask, edge_map, &num_masked_edges);
+ num_add_vertices = 0;
+ }
Vector<int> masked_poly_indices;
Vector<int> new_loop_starts;
@@ -389,13 +751,65 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx)
&num_masked_polys,
&num_masked_loops);
- Mesh *result = BKE_mesh_new_nomain_from_template(
- mesh, num_masked_vertices, num_masked_edges, 0, num_masked_loops, num_masked_polys);
+ uint num_add_edges = 0;
+ uint num_add_polys = 0;
+ uint num_add_loops = 0;
+ if (use_interpolation) {
+ compute_interpolated_polygons(mesh,
+ vertex_mask,
+ num_add_vertices,
+ num_masked_loops,
+ masked_poly_indices,
+ new_loop_starts,
+ &num_add_edges,
+ &num_add_polys,
+ &num_add_loops);
+ }
+
+ Mesh *result = BKE_mesh_new_nomain_from_template(mesh,
+ num_masked_vertices + num_add_vertices,
+ num_masked_edges + num_add_edges,
+ 0,
+ num_masked_loops + num_add_loops,
+ num_masked_polys + num_add_polys);
copy_masked_vertices_to_new_mesh(*mesh, *result, vertex_map);
- copy_masked_edges_to_new_mesh(*mesh, *result, vertex_map, edge_map);
- copy_masked_polys_to_new_mesh(
- *mesh, *result, vertex_map, edge_map, masked_poly_indices, new_loop_starts);
+ if (use_interpolation) {
+ add_interp_verts_copy_edges_to_new_mesh(*mesh,
+ *result,
+ vertex_mask,
+ vertex_map,
+ dvert,
+ defgrp_index,
+ mmd->threshold,
+ num_masked_edges,
+ num_add_vertices,
+ edge_map);
+ }
+ else {
+ copy_masked_edges_to_new_mesh(*mesh, *result, vertex_map, edge_map);
+ }
+ copy_masked_polys_to_new_mesh(*mesh,
+ *result,
+ vertex_map,
+ edge_map,
+ masked_poly_indices,
+ new_loop_starts,
+ num_masked_polys);
+ if (use_interpolation) {
+ add_interpolated_polys_to_new_mesh(*mesh,
+ *result,
+ vertex_mask,
+ vertex_map,
+ edge_map,
+ dvert,
+ defgrp_index,
+ mmd->threshold,
+ masked_poly_indices,
+ new_loop_starts,
+ num_masked_polys,
+ num_add_edges);
+ }
BKE_mesh_calc_edges_loose(result);
/* Tag to recalculate normals later. */
@@ -441,6 +855,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
}
else if (mode == MOD_MASK_MODE_VGROUP) {
modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", nullptr);
+ uiItemR(layout, ptr, "use_smooth", 0, nullptr, ICON_NONE);
}
uiItemR(layout, ptr, "threshold", 0, nullptr, ICON_NONE);
diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c
index 145586d8ab0..c7b59ee0d6e 100644
--- a/source/blender/python/gpu/gpu_py_shader.c
+++ b/source/blender/python/gpu/gpu_py_shader.c
@@ -70,6 +70,12 @@ static const struct PyC_StringEnumItems pygpu_shader_builtin_items[] = {
{0, NULL},
};
+static const struct PyC_StringEnumItems pygpu_shader_config_items[] = {
+ {GPU_SHADER_CFG_DEFAULT, "DEFAULT"},
+ {GPU_SHADER_CFG_CLIPPED, "CLIPPED"},
+ {0, NULL},
+};
+
static int pygpu_shader_uniform_location_get(GPUShader *shader,
const char *name,
const char *error_prefix)
@@ -711,29 +717,48 @@ static PyObject *pygpu_shader_unbind(BPyGPUShader *UNUSED(self))
}
PyDoc_STRVAR(pygpu_shader_from_builtin_doc,
- ".. function:: from_builtin(pygpu_shader_name)\n"
+ ".. function:: from_builtin(shader_name, config='DEFAULT')\n"
"\n"
" Shaders that are embedded in the blender internal code.\n"
" They all read the uniform ``mat4 ModelViewProjectionMatrix``,\n"
" which can be edited by the :mod:`gpu.matrix` module.\n"
+ " You can also choose a shader configuration that uses clip_planes by setting the "
+ "``CLIPPED`` value to the config parameter. Note that in this case you also need to "
+ "manually set the value of ``ModelMatrix``.\n"
+ "\n"
" For more details, you can check the shader code with the\n"
" :func:`gpu.shader.code_from_builtin` function.\n"
"\n"
- " :param pygpu_shader_name: One of these builtin shader names:\n"
+ " :param shader_name: One of these builtin shader names:\n"
"\n" PYDOC_BUILTIN_SHADER_LIST
- " :type pygpu_shader_name: str\n"
+ " :type shader_name: str\n"
+ " :param config: One of these types of shader configuration:\n"
+ " - ``DEFAULT``\n"
+ " - ``CLIPPED``\n"
+ " :type config: str\n"
" :return: Shader object corresponding to the given name.\n"
" :rtype: :class:`bpy.types.GPUShader`\n");
-static PyObject *pygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *arg)
+static PyObject *pygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
{
BPYGPU_IS_INIT_OR_ERROR_OBJ;
struct PyC_StringEnum pygpu_bultinshader = {pygpu_shader_builtin_items};
- if (!PyC_ParseStringEnum(arg, &pygpu_bultinshader)) {
+ struct PyC_StringEnum pygpu_config = {pygpu_shader_config_items, GPU_SHADER_CFG_DEFAULT};
+
+ static const char *_keywords[] = {"shader_name", "config", NULL};
+ static _PyArg_Parser _parser = {"O&|$O&:from_builtin", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(args,
+ kwds,
+ &_parser,
+ PyC_ParseStringEnum,
+ &pygpu_bultinshader,
+ PyC_ParseStringEnum,
+ &pygpu_config)) {
return NULL;
}
- GPUShader *shader = GPU_shader_get_builtin_shader(pygpu_bultinshader.value_found);
+ GPUShader *shader = GPU_shader_get_builtin_shader_with_config(pygpu_bultinshader.value_found,
+ pygpu_config.value_found);
return BPyGPUShader_CreatePyObject(shader, true);
}
@@ -788,7 +813,7 @@ static struct PyMethodDef pygpu_shader_module__tp_methods[] = {
{"unbind", (PyCFunction)pygpu_shader_unbind, METH_NOARGS, pygpu_shader_unbind_doc},
{"from_builtin",
(PyCFunction)pygpu_shader_from_builtin,
- METH_O,
+ METH_VARARGS | METH_KEYWORDS,
pygpu_shader_from_builtin_doc},
{"code_from_builtin",
(PyCFunction)pygpu_shader_code_from_builtin,
diff --git a/source/blender/python/gpu/gpu_py_state.c b/source/blender/python/gpu/gpu_py_state.c
index 7b7a61cc338..757c787882b 100644
--- a/source/blender/python/gpu/gpu_py_state.c
+++ b/source/blender/python/gpu/gpu_py_state.c
@@ -123,6 +123,28 @@ static PyObject *pygpu_state_blend_get(PyObject *UNUSED(self))
return PyUnicode_FromString(PyC_StringEnum_FindIDFromValue(pygpu_state_blend_items, blend));
}
+PyDoc_STRVAR(pygpu_state_clip_distances_set_doc,
+ ".. function:: clip_distances_set(distances_enabled)\n"
+ "\n"
+ " Sets number of `gl_ClipDistance`s that will be used for clip geometry.\n"
+ "\n"
+ " :param distances_enabled: Number of clip distances enabled.\n"
+ " :type distances_enabled: int\n");
+static PyObject *pygpu_state_clip_distances_set(PyObject *UNUSED(self), PyObject *value)
+{
+ int distances_enabled = (int)PyLong_AsUnsignedLong(value);
+ if (distances_enabled == -1) {
+ return NULL;
+ }
+
+ if (distances_enabled > 6) {
+ PyErr_SetString(PyExc_ValueError, "too many distances enabled, max is 6");
+ }
+
+ GPU_clip_distances(distances_enabled);
+ Py_RETURN_NONE;
+}
+
PyDoc_STRVAR(pygpu_state_depth_test_set_doc,
".. function:: depth_test_set(mode)\n"
"\n"
@@ -356,6 +378,10 @@ static struct PyMethodDef pygpu_state__tp_methods[] = {
/* Manage Stack */
{"blend_set", (PyCFunction)pygpu_state_blend_set, METH_O, pygpu_state_blend_set_doc},
{"blend_get", (PyCFunction)pygpu_state_blend_get, METH_NOARGS, pygpu_state_blend_get_doc},
+ {"clip_distances_set",
+ (PyCFunction)pygpu_state_clip_distances_set,
+ METH_O,
+ pygpu_state_clip_distances_set_doc},
{"depth_test_set",
(PyCFunction)pygpu_state_depth_test_set,
METH_O,
diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c
index d4adad9a34d..37bac523645 100644
--- a/source/blender/sequencer/intern/effects.c
+++ b/source/blender/sequencer/intern/effects.c
@@ -39,6 +39,7 @@
#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
+#include "DNA_packedFile_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
@@ -3755,31 +3756,47 @@ static void init_text_effect(Sequence *seq)
void SEQ_effect_text_font_unload(TextVars *data, const bool do_id_user)
{
- if (data) {
- /* Unlink the VFont */
- if (do_id_user && data->text_font != NULL) {
- id_us_min(&data->text_font->id);
- data->text_font = NULL;
- }
+ if (data == NULL) {
+ return;
+ }
- /* Unload the BLF font. */
- if (data->text_blf_id >= 0) {
- BLF_unload_id(data->text_blf_id);
- }
+ /* Unlink the VFont */
+ if (do_id_user && data->text_font != NULL) {
+ id_us_min(&data->text_font->id);
+ data->text_font = NULL;
+ }
+
+ /* Unload the BLF font. */
+ if (data->text_blf_id >= 0) {
+ BLF_unload_id(data->text_blf_id);
}
}
void SEQ_effect_text_font_load(TextVars *data, const bool do_id_user)
{
- if (data->text_font != NULL) {
- if (do_id_user) {
- id_us_plus(&data->text_font->id);
- }
+ VFont *vfont = data->text_font;
+ if (vfont == NULL) {
+ return;
+ }
+
+ if (do_id_user) {
+ id_us_plus(&vfont->id);
+ }
+ if (vfont->packedfile != NULL) {
+ PackedFile *pf = vfont->packedfile;
+ /* Create a name that's unique between library data-blocks to avoid loading
+ * a font per strip which will load fonts many times. */
+ char name[MAX_ID_FULL_NAME];
+ BKE_id_full_name_get(name, &vfont->id, 0);
+
+ data->text_blf_id = BLF_load_mem(name, pf->data, pf->size);
+ }
+ else {
char path[FILE_MAX];
- STRNCPY(path, data->text_font->filepath);
+ STRNCPY(path, vfont->filepath);
BLI_assert(BLI_thread_is_main());
- BLI_path_abs(path, ID_BLEND_PATH_FROM_GLOBAL(&data->text_font->id));
+ BLI_path_abs(path, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
data->text_blf_id = BLF_load(path);
}
@@ -3850,9 +3867,7 @@ static ImBuf *do_text_effect(const SeqRenderData *context,
if (data->text_blf_id == SEQ_FONT_NOT_LOADED) {
data->text_blf_id = -1;
- if (data->text_font) {
- data->text_blf_id = BLF_load(data->text_font->filepath);
- }
+ SEQ_effect_text_font_load(data, false);
}
if (data->text_blf_id >= 0) {
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 3027df41e77..ca1610a8101 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -111,12 +111,11 @@ void WM_reinit_gizmomap_all(struct Main *bmain);
void WM_script_tag_reload(void);
-bool WM_window_find_under_cursor(const wmWindowManager *wm,
- const wmWindow *win_ignore,
- const wmWindow *win,
- const int mval[2],
- wmWindow **r_win,
- int r_mval[2]);
+wmWindow *WM_window_find_under_cursor(const wmWindowManager *wm,
+ const wmWindow *win_ignore,
+ const wmWindow *win,
+ const int mval[2],
+ int r_mval[2]);
void WM_window_pixel_sample_read(const wmWindowManager *wm,
const wmWindow *win,
const int pos[2],
@@ -263,9 +262,8 @@ struct wmEventHandler_Keymap *WM_event_add_keymap_handler_priority(ListBase *han
wmKeyMap *keymap,
int priority);
-typedef struct wmKeyMap *(wmEventHandler_KeymapDynamicFn)(wmWindowManager *wm,
- struct wmEventHandler_Keymap *handler)
- ATTR_WARN_UNUSED_RESULT;
+typedef struct wmKeyMap *(wmEventHandler_KeymapDynamicFn)(
+ wmWindowManager *wm, struct wmEventHandler_Keymap *handler)ATTR_WARN_UNUSED_RESULT;
struct wmKeyMap *WM_event_get_keymap_from_toolsystem_fallback(
struct wmWindowManager *wm, struct wmEventHandler_Keymap *handler);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index b9a3dd0c3fb..1f47b152a2b 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -4357,8 +4357,8 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi
}
}
- wmWindow *win_other;
- if (WM_window_find_under_cursor(wm, win, win, mval, &win_other, mval)) {
+ wmWindow *win_other = WM_window_find_under_cursor(wm, win, win, mval, mval);
+ if (win_other) {
event->x = mval[0];
event->y = mval[1];
return win_other;
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 93417213a65..e9d0adf6798 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -1922,12 +1922,11 @@ static void wm_window_screen_pos_get(const wmWindow *win,
r_scr_pos[1] = desktop_pos[1] - (int)(U.pixelsize * win->posy);
}
-bool WM_window_find_under_cursor(const wmWindowManager *wm,
- const wmWindow *win_ignore,
- const wmWindow *win,
- const int mval[2],
- wmWindow **r_win,
- int r_mval[2])
+wmWindow *WM_window_find_under_cursor(const wmWindowManager *wm,
+ const wmWindow *win_ignore,
+ const wmWindow *win,
+ const int mval[2],
+ int r_mval[2])
{
int desk_pos[2];
wm_window_desktop_pos_get(win, mval, desk_pos);
@@ -1949,13 +1948,12 @@ bool WM_window_find_under_cursor(const wmWindowManager *wm,
if (scr_pos[0] >= 0 && win_iter->posy >= 0 && scr_pos[0] <= WM_window_pixels_x(win_iter) &&
scr_pos[1] <= WM_window_pixels_y(win_iter)) {
- *r_win = win_iter;
copy_v2_v2_int(r_mval, scr_pos);
- return true;
+ return win_iter;
}
}
- return false;
+ return NULL;
}
void WM_window_pixel_sample_read(const wmWindowManager *wm,