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
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_subdiv_ccg.h5
-rw-r--r--source/blender/blenkernel/BKE_subdiv_deform.h4
-rw-r--r--source/blender/blenkernel/BKE_subdiv_eval.h4
-rw-r--r--source/blender/blenkernel/BKE_subdiv_foreach.h4
-rw-r--r--source/blender/blenkernel/intern/blender_undo.c3
-rw-r--r--source/blender/blenkernel/intern/subdiv_foreach.c7
-rw-r--r--source/blender/blenkernel/intern/undo_system.c4
-rw-r--r--source/blender/blenloader/BLO_undofile.h1
-rw-r--r--source/blender/blenloader/intern/undofile.c8
-rw-r--r--source/blender/blenloader/intern/writefile.c9
-rw-r--r--source/blender/draw/engines/eevee/eevee_bloom.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h1
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c4
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c6
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl11
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl2
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_antialiasing.c9
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h1
-rw-r--r--source/blender/draw/intern/DRW_render.h1
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.c67
-rw-r--r--source/blender/draw/intern/draw_cache_impl_gpencil.c9
-rw-r--r--source/blender/draw/intern/draw_manager.c9
-rw-r--r--source/blender/editors/armature/armature_intern.h1
-rw-r--r--source/blender/editors/armature/armature_ops.c1
-rw-r--r--source/blender/editors/armature/armature_select.c270
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c124
-rw-r--r--source/blender/editors/transform/transform_convert.c248
-rw-r--r--source/blender/editors/transform/transform_convert_armature.c9
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h4
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c6
-rw-r--r--source/creator/blender.map82
-rw-r--r--source/creator/creator_args.c2
-rw-r--r--source/creator/osx_locals.map64
35 files changed, 733 insertions, 257 deletions
diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h
index 7d612f293ab..f8534371b17 100644
--- a/source/blender/blenkernel/BKE_subdiv_ccg.h
+++ b/source/blender/blenkernel/BKE_subdiv_ccg.h
@@ -216,7 +216,10 @@ typedef struct SubdivCCG {
} dirty;
} SubdivCCG;
-/* Create real hi-res CCG from subdivision.
+/* Create CCG representation of subdivision surface.
+ *
+ * NOTE: CCG stores dense verticies in a grid-like storage. There is no edges or
+ * polygons informations for the high-poly surface.
*
* NOTE: Subdiv is expected to be refined and ready for evaluation.
* NOTE: CCG becomes an owner of subdiv.
diff --git a/source/blender/blenkernel/BKE_subdiv_deform.h b/source/blender/blenkernel/BKE_subdiv_deform.h
index 72d2b252cf7..11ef225de27 100644
--- a/source/blender/blenkernel/BKE_subdiv_deform.h
+++ b/source/blender/blenkernel/BKE_subdiv_deform.h
@@ -34,6 +34,10 @@ struct Mesh;
struct Subdiv;
/* Special version of subdivision surface which calculates final positions for coarse vertices.
+ * Effectively is pushsing the coarse positions to the limit surface.
+ *
+ * One of the usage examples is calculation of crazy space of subdivision modifier, allowing to
+ * paint on a deformed mesh with subsurf on it.
*
* vertex_cos are supposed to hold coordinates of the coarse mesh. */
void BKE_subdiv_deform_coarse_vertices(struct Subdiv *subdiv,
diff --git a/source/blender/blenkernel/BKE_subdiv_eval.h b/source/blender/blenkernel/BKE_subdiv_eval.h
index 095d3c17d63..3f682716928 100644
--- a/source/blender/blenkernel/BKE_subdiv_eval.h
+++ b/source/blender/blenkernel/BKE_subdiv_eval.h
@@ -50,6 +50,8 @@ void BKE_subdiv_eval_init_displacement(struct Subdiv *subdiv);
/* Single point queries. */
+/* Evaluate point at a limit surface, with optional derivatives and normal. */
+
void BKE_subdiv_eval_limit_point(
struct Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_P[3]);
void BKE_subdiv_eval_limit_point_and_derivatives(struct Subdiv *subdiv,
@@ -72,6 +74,7 @@ void BKE_subdiv_eval_limit_point_and_short_normal(struct Subdiv *subdiv,
float r_P[3],
short r_N[3]);
+/* Evaluate face-varying layer (such as UV). */
void BKE_subdiv_eval_face_varying(struct Subdiv *subdiv,
const int face_varying_channel,
const int ptex_face_index,
@@ -93,6 +96,7 @@ void BKE_subdiv_eval_displacement(struct Subdiv *subdiv,
const float dPdv[3],
float r_D[3]);
+/* Evaluate point on a limit surface with displacement applied to it. */
void BKE_subdiv_eval_final_point(
struct Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_P[3]);
diff --git a/source/blender/blenkernel/BKE_subdiv_foreach.h b/source/blender/blenkernel/BKE_subdiv_foreach.h
index f1d4adda37c..bef141b5ac5 100644
--- a/source/blender/blenkernel/BKE_subdiv_foreach.h
+++ b/source/blender/blenkernel/BKE_subdiv_foreach.h
@@ -160,6 +160,10 @@ typedef struct SubdivForeachContext {
/* Invokes callbacks in the order and with values which corresponds to creation
* of final subdivided mesh.
*
+ * Main goal is to abstract all the traversal routines to give geometry element
+ * indices (for vertices, edges, loops, polygons) in the same way as subdivision
+ * modifier will do for a dense mesh.
+ *
* Returns truth if the whole topology was traversed, without any early exits.
*
* TODO(sergey): Need to either get rid of subdiv or of coarse_mesh.
diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c
index 99eb4dc9122..ab382d0e8ff 100644
--- a/source/blender/blenkernel/intern/blender_undo.c
+++ b/source/blender/blenkernel/intern/blender_undo.c
@@ -124,6 +124,9 @@ MemFileUndoData *BKE_memfile_undo_encode(Main *bmain, MemFileUndoData *mfu_prev)
}
else {
MemFile *prevfile = (mfu_prev) ? &(mfu_prev->memfile) : NULL;
+ if (prevfile) {
+ BLO_memfile_clear_future(prevfile);
+ }
/* success = */ /* UNUSED */ BLO_write_file_mem(bmain, prevfile, &mfu->memfile, G.fileflags);
mfu->undo_size = mfu->memfile.size;
}
diff --git a/source/blender/blenkernel/intern/subdiv_foreach.c b/source/blender/blenkernel/intern/subdiv_foreach.c
index 533279f4425..6e39f9f302b 100644
--- a/source/blender/blenkernel/intern/subdiv_foreach.c
+++ b/source/blender/blenkernel/intern/subdiv_foreach.c
@@ -1875,6 +1875,13 @@ bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv,
if (context->user_data_tls_free != NULL) {
parallel_range_settings.func_finalize = subdiv_foreach_finalize;
}
+
+ /* TODO(sergey): Possible optimization is to have a single pool and push all
+ * the tasks into it.
+ * NOTE: Watch out for callbacks which needs to run for loose geometry as they
+ * currently are relying on the fact that face/grid callbacks will tag non-
+ * loose geomtry. */
+
BLI_task_parallel_range(
0, coarse_mesh->totpoly, &ctx, subdiv_foreach_task, &parallel_range_settings);
if (context->vertex_loose != NULL) {
diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
index 6d484a7b702..b111dee80ad 100644
--- a/source/blender/blenkernel/intern/undo_system.c
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -464,12 +464,12 @@ UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack,
}
UndoStep *us = MEM_callocN(ut->step_size, __func__);
- CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, name, ut->name);
if (name != NULL) {
BLI_strncpy(us->name, name, sizeof(us->name));
}
us->type = ut;
ustack->step_init = us;
+ CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
ut->step_encode_init(C, us);
undosys_stack_validate(ustack, false);
return us;
@@ -552,6 +552,8 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack,
us->type = ut;
/* Initialized, not added yet. */
+ CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
+
if (!undosys_step_encode(C, G_MAIN, ustack, us)) {
MEM_freeN(us);
undosys_stack_validate(ustack, true);
diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h
index 5f1142cc20e..f280b8f3b9c 100644
--- a/source/blender/blenloader/BLO_undofile.h
+++ b/source/blender/blenloader/BLO_undofile.h
@@ -60,6 +60,7 @@ extern void memfile_chunk_add(MemFile *memfile,
/* exports */
extern void BLO_memfile_free(MemFile *memfile);
extern void BLO_memfile_merge(MemFile *first, MemFile *second);
+extern void BLO_memfile_clear_future(MemFile *memfile);
/* utilities */
extern struct Main *BLO_memfile_main_get(struct MemFile *memfile,
diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c
index 06469a0c087..69c4ba2b1f2 100644
--- a/source/blender/blenloader/intern/undofile.c
+++ b/source/blender/blenloader/intern/undofile.c
@@ -92,6 +92,14 @@ void BLO_memfile_merge(MemFile *first, MemFile *second)
BLO_memfile_free(first);
}
+/* Clear is_identical_future before adding next memfile. */
+void BLO_memfile_clear_future(MemFile *memfile)
+{
+ for (MemFileChunk *chunk = memfile->chunks.first; chunk; chunk = chunk->next) {
+ chunk->is_identical_future = false;
+ }
+}
+
void memfile_chunk_add(MemFile *memfile, const char *buf, uint size, MemFileChunk **compchunk_step)
{
MemFileChunk *curchunk = MEM_mallocN(sizeof(MemFileChunk), "MemFileChunk");
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index bdab4fc8219..8b6ddd99749 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -734,11 +734,6 @@ static void write_iddata(WriteData *wd, ID *id)
}
}
}
-
- /* Clear the accumulated recalc flags in case of undo step saving. */
- if (wd->use_memfile) {
- id->recalc_undo_accumulated = 0;
- }
}
static void write_previews(WriteData *wd, const PreviewImage *prv_orig)
@@ -2244,6 +2239,7 @@ static void write_mesh(WriteData *wd, Mesh *mesh)
mesh->mface = NULL;
mesh->totface = 0;
memset(&mesh->fdata, 0, sizeof(mesh->fdata));
+ memset(&mesh->runtime, 0, sizeof(mesh->runtime));
/* Reduce xdata layers, fill xlayers with layers to be written.
* This makes xdata invalid for Blender, which is why we made a
@@ -4173,6 +4169,9 @@ static bool write_file_handle(Main *mainvar,
/* Very important to do it after every ID write now, otherwise we cannot know whether a
* specific ID changed or not. */
mywrite_flush(wd);
+
+ /* Clear the accumulated recalc flags in case of undo step saving. */
+ id->recalc_undo_accumulated = 0;
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c
index 6545a1bca84..8fd953478d5 100644
--- a/source/blender/draw/engines/eevee/eevee_bloom.c
+++ b/source/blender/draw/engines/eevee/eevee_bloom.c
@@ -323,8 +323,8 @@ void EEVEE_bloom_draw(EEVEE_Data *vedata)
/* Upsample and accumulate */
for (int i = effects->bloom_iteration_len - 2; i >= 0; i--) {
copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i]);
- effects->unf_source_buffer = effects->bloom_downsample[i];
- effects->unf_base_buffer = last;
+ effects->unf_source_buffer = last;
+ effects->unf_base_buffer = effects->bloom_downsample[i];
GPU_framebuffer_bind(fbl->bloom_accum_fb[i]);
DRW_draw_pass(psl->bloom_upsample);
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index e2470b4fa76..264f301e52c 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -600,6 +600,7 @@ typedef struct EEVEE_EffectsInfo {
int taa_total_sample;
float taa_alpha;
bool prev_drw_support;
+ bool prev_is_navigating;
float prev_drw_persmat[4][4];
struct DRWView *taa_view;
/* Ambient Occlusion */
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index 1f44b815a42..b70d872c4af 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -244,8 +244,10 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
copy_m4_m4(effects->prev_drw_persmat, persmat);
/* Prevent ghosting from probe data. */
- view_is_valid = view_is_valid && (effects->prev_drw_support == DRW_state_draw_support());
+ view_is_valid = view_is_valid && (effects->prev_drw_support == DRW_state_draw_support()) &&
+ (effects->prev_is_navigating == DRW_state_is_navigating());
effects->prev_drw_support = DRW_state_draw_support();
+ effects->prev_is_navigating = DRW_state_is_navigating();
if (((effects->taa_total_sample == 0) ||
(effects->taa_current_sample < effects->taa_total_sample)) ||
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index a5f67b7831e..f8f55843a29 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -314,12 +314,12 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd,
break;
case eGplBlendMode_Multiply:
case eGplBlendMode_Divide:
- case eGplBlendMode_Overlay:
+ case eGplBlendMode_HardLight:
state |= DRW_STATE_BLEND_MUL;
break;
}
- if (ELEM(gpl->blend_mode, eGplBlendMode_Subtract, eGplBlendMode_Overlay)) {
+ if (ELEM(gpl->blend_mode, eGplBlendMode_Subtract, eGplBlendMode_HardLight)) {
/* For these effect to propagate, we need a signed floating point buffer. */
pd->use_signed_fb = true;
}
@@ -336,7 +336,7 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd,
DRW_shgroup_stencil_mask(grp, 0xFF);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
- if (gpl->blend_mode == eGplBlendMode_Overlay) {
+ if (gpl->blend_mode == eGplBlendMode_HardLight) {
/* We cannot do custom blending on MultiTarget framebuffers.
* Workaround by doing 2 passes. */
grp = DRW_shgroup_create(sh, tgp_layer->blend_ps);
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
index cb34515a960..54b2369b32b 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
@@ -77,12 +77,12 @@ layout(std140) uniform gpLightBlock
/* Must match eGPLayerBlendModes */
#define MODE_REGULAR 0
-#define MODE_OVERLAY 1
+#define MODE_HARDLIGHT 1
#define MODE_ADD 2
#define MODE_SUB 3
#define MODE_MULTIPLY 4
#define MODE_DIVIDE 5
-#define MODE_OVERLAY_SECOND_PASS 999
+#define MODE_HARDLIGHT_SECOND_PASS 999
void blend_mode_output(
int blend_mode, vec4 color, float opacity, out vec4 frag_color, out vec4 frag_revealage)
@@ -104,7 +104,7 @@ void blend_mode_output(
color.a *= opacity;
frag_revealage = frag_color = clamp(1.0 / max(vec4(1e-6), 1.0 - color * color.a), 0.0, 1e18);
break;
- case MODE_OVERLAY:
+ case MODE_HARDLIGHT:
/* Reminder: Blending func is multiply blend (dst.rgba * src.rgba).*/
/**
* We need to separate the overlay equation into 2 term (one mul and one add).
@@ -120,11 +120,13 @@ void blend_mode_output(
color = mix(vec4(0.5), color, color.a * opacity);
vec4 s = step(-0.5, -color);
frag_revealage = frag_color = 2.0 * s + 2.0 * color * (1.0 - s * 2.0);
+ frag_revealage = max(vec4(0.0), frag_revealage);
break;
- case MODE_OVERLAY_SECOND_PASS:
+ case MODE_HARDLIGHT_SECOND_PASS:
/* Reminder: Blending func is additive blend (dst.rgba + src.rgba).*/
color = mix(vec4(0.5), color, color.a * opacity);
frag_revealage = frag_color = (-1.0 + 2.0 * color) * step(-0.5, -color);
+ frag_revealage = max(vec4(0.0), frag_revealage);
break;
case MODE_SUB:
case MODE_ADD:
@@ -572,6 +574,7 @@ void fill_vertex()
finalUvs = rot_scale * uv1.xy + loc;
# endif
+ strokeHardeness = 1.0;
strokeThickness = 1e18;
strokeAspect = vec2(1.0);
strokePt1 = strokePt2 = vec2(0.0);
diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl
index 8833490e818..fd37bc8c534 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl
@@ -40,7 +40,7 @@ void main()
}
else {
nor = norAndFlag.xyz;
- if (all(equal(nor, vec3(0.0)))) {
+ if (all(equal(nor, vec3(0)))) {
finalColor = vec4(0.0);
return;
}
diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index fc047eadf55..6ef9cbfab57 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -182,7 +182,7 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
WORKBENCH_ViewLayerData *vldata = workbench_view_layer_data_ensure_ex(draw_ctx->view_layer);
wpd->is_playback = DRW_state_is_playback();
- wpd->is_navigating = rv3d && (rv3d->rflag & (RV3D_NAVIGATING | RV3D_PAINTING));
+ wpd->is_navigating = DRW_state_is_navigating();
wpd->ctx_mode = CTX_data_mode_enum_ex(
draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
diff --git a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
index a0db09e9273..094d13fb84c 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
@@ -168,10 +168,17 @@ void workbench_antialiasing_engine_init(WORKBENCH_Data *vedata)
wpd->view = NULL;
- /* reset complete drawing when navigating or during viewport playback. */
+ /* Reset complete drawing when navigating or during viewport playback or when
+ * leaving one of those states. In case of multires modifier the navigation
+ * mesh differs from the viewport mesh, so we need to be sure to restart. */
if (wpd->taa_sample != 0) {
if (wpd->is_navigating || wpd->is_playback) {
wpd->taa_sample = 0;
+ wpd->reset_next_sample = true;
+ }
+ else if (wpd->reset_next_sample) {
+ wpd->taa_sample = 0;
+ wpd->reset_next_sample = false;
}
}
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 87b1c82ce94..a5e80f417d3 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -333,6 +333,7 @@ typedef struct WORKBENCH_PrivateData {
bool dof_enabled;
bool is_playback;
bool is_navigating;
+ bool reset_next_sample;
} WORKBENCH_PrivateData; /* Transient data */
typedef struct WORKBENCH_ObjectData {
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 382e7313f21..2d6d6c7d9d0 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -670,6 +670,7 @@ bool DRW_state_do_color_management(void);
bool DRW_state_is_scene_render(void);
bool DRW_state_is_opengl_render(void);
bool DRW_state_is_playback(void);
+bool DRW_state_is_navigating(void);
bool DRW_state_show_text(void);
bool DRW_state_draw_support(void);
bool DRW_state_draw_background(void);
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c
index 54e745102f0..f54fef63c82 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.c
@@ -191,7 +191,17 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
else {
mr->me = me;
mr->edit_bmesh = NULL;
- mr->extract_type = MR_EXTRACT_MESH;
+
+ bool use_mapped = mr->me && !mr->me->runtime.is_original;
+ if (use_mapped) {
+ mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX);
+ mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX);
+ mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
+
+ use_mapped = (mr->v_origindex || mr->e_origindex || mr->p_origindex);
+ }
+
+ mr->extract_type = use_mapped ? MR_EXTRACT_MAPPED : MR_EXTRACT_MESH;
}
if (mr->extract_type != MR_EXTRACT_BMESH) {
@@ -924,10 +934,14 @@ static void extract_lines_paint_mask_loop_mesh(const MeshRenderData *mr,
void *_data)
{
MeshExtract_LinePaintMask_Data *data = (MeshExtract_LinePaintMask_Data *)_data;
- if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) {
+ const int edge_idx = mloop->e;
+ const MEdge *medge = &mr->medge[edge_idx];
+ if (!((mr->use_hide && (medge->flag & ME_HIDE)) ||
+ ((mr->extract_type == MR_EXTRACT_MAPPED) &&
+ (mr->e_origindex[edge_idx] == ORIGINDEX_NONE)))) {
+
int loopend = mpoly->totloop + mpoly->loopstart - 1;
int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1);
- int edge_idx = mloop->e;
if (mpoly->flag & ME_FACE_SEL) {
if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, edge_idx)) {
/* Hide edge as it has more than 2 selected loop. */
@@ -945,6 +959,9 @@ static void extract_lines_paint_mask_loop_mesh(const MeshRenderData *mr,
}
}
}
+ else {
+ GPU_indexbuf_set_line_restart(&data->elb, edge_idx);
+ }
}
static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr),
void *ibo,
@@ -1500,7 +1517,8 @@ static void extract_pos_nor_loop_mesh(const MeshRenderData *mr,
copy_v3_v3(vert->pos, mvert->co);
vert->nor = data->packed_nor[mloop->v];
/* Flag for paint mode overlay. */
- if (mpoly->flag & ME_HIDE || mvert->flag & ME_HIDE) {
+ if (mpoly->flag & ME_HIDE || mvert->flag & ME_HIDE ||
+ ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex[mloop->v] == ORIGINDEX_NONE))) {
vert->nor.w = -1;
}
else if (mvert->flag & SELECT) {
@@ -1617,24 +1635,27 @@ static void extract_lnor_hq_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *
static void extract_lnor_hq_loop_mesh(
const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data)
{
+ gpuHQNor *lnor_data = &((gpuHQNor *)data)[l];
if (mr->loop_normals) {
- normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->loop_normals[l]);
+ normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[l]);
}
else if (mpoly->flag & ME_SMOOTH) {
- copy_v3_v3_short(&((gpuHQNor *)data)[l].x, mr->mvert[mloop->v].no);
+ copy_v3_v3_short(&lnor_data->x, mr->mvert[mloop->v].no);
}
else {
- normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->poly_normals[p]);
+ normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[p]);
}
+
/* Flag for paint mode overlay. */
- if (mpoly->flag & ME_HIDE) {
- ((gpuHQNor *)data)[l].w = -1;
+ if (mpoly->flag & ME_HIDE ||
+ (mr->extract_type == MR_EXTRACT_MAPPED && mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
+ lnor_data->w = -1;
}
else if (mpoly->flag & ME_FACE_SEL) {
- ((gpuHQNor *)data)[l].w = 1;
+ lnor_data->w = 1;
}
else {
- ((gpuHQNor *)data)[l].w = 0;
+ lnor_data->w = 0;
}
}
@@ -1690,24 +1711,27 @@ static void extract_lnor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loo
static void extract_lnor_loop_mesh(
const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data)
{
+ GPUPackedNormal *lnor_data = &((GPUPackedNormal *)data)[l];
if (mr->loop_normals) {
- ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(mr->loop_normals[l]);
+ *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[l]);
}
else if (mpoly->flag & ME_SMOOTH) {
- ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_s3(mr->mvert[mloop->v].no);
+ *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[mloop->v].no);
}
else {
- ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(mr->poly_normals[p]);
+ *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[p]);
}
+
/* Flag for paint mode overlay. */
- if (mpoly->flag & ME_HIDE) {
- ((GPUPackedNormal *)data)[l].w = -1;
+ if (mpoly->flag & ME_HIDE ||
+ (mr->extract_type == MR_EXTRACT_MAPPED && mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
+ lnor_data->w = -1;
}
else if (mpoly->flag & ME_FACE_SEL) {
- ((GPUPackedNormal *)data)[l].w = 1;
+ lnor_data->w = 1;
}
else {
- ((GPUPackedNormal *)data)[l].w = 0;
+ lnor_data->w = 0;
}
}
@@ -3890,7 +3914,8 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void *
for (int f = 0; f < mr->poly_len; f++) {
efa = BM_face_at_index(mr->bm, f);
const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
- if (is_face_hidden) {
+ if (is_face_hidden ||
+ (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex[f] == ORIGINDEX_NONE)) {
nor[f] = GPU_normal_convert_i10_v3(invalid_normal);
nor[f].w = NOR_AND_FLAG_HIDDEN;
}
@@ -3906,7 +3931,9 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void *
else {
for (int f = 0; f < mr->poly_len; f++) {
efa = bm_original_face_get(mr, f);
- if (!efa || BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ const bool is_face_hidden = efa && BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
+ if (is_face_hidden ||
+ (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex[f] == ORIGINDEX_NONE)) {
nor[f] = GPU_normal_convert_i10_v3(invalid_normal);
nor[f].w = NOR_AND_FLAG_HIDDEN;
}
diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c
index 4a474768226..3cbcdc1ede6 100644
--- a/source/blender/draw/intern/draw_cache_impl_gpencil.c
+++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c
@@ -62,8 +62,6 @@ typedef struct GpencilBatchCache {
/** Cache is dirty */
bool is_dirty;
- /** Edit mode flag */
- bool is_editmode;
/** Last cache frame */
int cache_frame;
} GpencilBatchCache;
@@ -71,21 +69,17 @@ typedef struct GpencilBatchCache {
static bool gpencil_batch_cache_valid(GpencilBatchCache *cache, bGPdata *gpd, int cfra)
{
bool valid = true;
+
if (cache == NULL) {
return false;
}
- cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);
if (cfra != cache->cache_frame) {
valid = false;
}
else if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) {
valid = false;
}
- else if (gpd->flag & GP_DATA_PYTHON_UPDATED) {
- gpd->flag &= ~GP_DATA_PYTHON_UPDATED;
- valid = false;
- }
else if (cache->is_dirty) {
valid = false;
}
@@ -106,7 +100,6 @@ static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
memset(cache, 0, sizeof(*cache));
}
- cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);
cache->is_dirty = true;
cache->cache_frame = cfra;
return cache;
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index cc618c76ccd..b265035f449 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -2575,6 +2575,15 @@ bool DRW_state_is_playback(void)
}
/**
+ * Is the user navigating the region.
+ */
+bool DRW_state_is_navigating(void)
+{
+ const RegionView3D *rv3d = DST.draw_ctx.rv3d;
+ return (rv3d) && (rv3d->rflag & (RV3D_NAVIGATING | RV3D_PAINTING));
+}
+
+/**
* Should text draw in this mode?
*/
bool DRW_state_show_text(void)
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index ba914080d98..37f0c7197a9 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -59,6 +59,7 @@ void ARMATURE_OT_select_mirror(struct wmOperatorType *ot);
void ARMATURE_OT_select_more(struct wmOperatorType *ot);
void ARMATURE_OT_select_less(struct wmOperatorType *ot);
void ARMATURE_OT_select_hierarchy(struct wmOperatorType *ot);
+void ARMATURE_OT_select_linked_pick(struct wmOperatorType *ot);
void ARMATURE_OT_select_linked(struct wmOperatorType *ot);
void ARMATURE_OT_select_similar(struct wmOperatorType *ot);
void ARMATURE_OT_shortest_path_pick(struct wmOperatorType *ot);
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index 097d384a609..b304ce92a54 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -56,6 +56,7 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(ARMATURE_OT_select_less);
WM_operatortype_append(ARMATURE_OT_select_hierarchy);
WM_operatortype_append(ARMATURE_OT_select_linked);
+ WM_operatortype_append(ARMATURE_OT_select_linked_pick);
WM_operatortype_append(ARMATURE_OT_select_similar);
WM_operatortype_append(ARMATURE_OT_shortest_path_pick);
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index e927765304f..99dcd5bb42b 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -59,7 +59,9 @@
#define EBONE_PREV_FLAG_GET(ebone) ((void)0, (ebone)->temp.i)
#define EBONE_PREV_FLAG_SET(ebone, val) ((ebone)->temp.i = val)
-/* **************** PoseMode & EditMode Selection Buffer Queries *************************** */
+/* -------------------------------------------------------------------- */
+/** \name Select Buffer Queries for PoseMode & EditMode
+ * \{ */
Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
uint bases_len,
@@ -293,25 +295,29 @@ void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel, Base **r_ba
return NULL;
}
-/* **************** EditMode stuff ********************** */
-
-static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- const bool select = !RNA_boolean_get(op->ptr, "deselect");
- /* true: select all connected bones traveling up & down forks.
- * false: select all parents and all children, but not the children of the root bone. */
- const bool all_forks = RNA_boolean_get(op->ptr, "all_forks");
+/** \} */
- view3d_operator_needs_opengl(C);
- BKE_object_update_select_id(CTX_data_main(C));
+/* -------------------------------------------------------------------- */
+/** \name Select Linked Implementation
+ *
+ * Shared logic for select linked all/pick.
+ *
+ * Use #BONE_DONE flag to select linked.
+ * \{ */
- Base *base = NULL;
- EditBone *ebone_active = get_nearest_bone(C, event->mval, true, &base);
- bArmature *arm = base->object->data;
+/**
+ * \param all_forks: Control how chains are stepped over.
+ * true: select all connected bones traveling up & down forks.
+ * false: select all parents and all children, but not the children of the root bone.
+ */
+static bool armature_select_linked_impl(Object *ob, const bool select, const bool all_forks)
+{
+ bool changed = false;
+ bArmature *arm = ob->data;
- if (ebone_active == NULL || !EBONE_SELECTABLE(arm, ebone_active)) {
- return OPERATOR_CANCELLED;
- }
+ /* Implementation note, this flood-fills selected bones with the 'TOUCH' flag,
+ * even though this is a loop-within a loop, walking up the parent chain only touches new bones.
+ * Bones that have been touched are skipped, so the complexity is OK. */
enum {
/* Bone has been walked over, it's LINK value can be read. */
@@ -320,36 +326,44 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv
LINK = (1 << 1),
};
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- ebone->temp.i = 0;
- }
-
#define CHECK_PARENT(ebone) \
(((ebone)->flag & BONE_CONNECTED) && \
((ebone)->parent ? EBONE_SELECTABLE(arm, (ebone)->parent) : false))
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ ebone->temp.i = 0;
+ }
+
/* Select parents. */
- for (EditBone *ebone = ebone_active; ebone; ebone = CHECK_PARENT(ebone) ? ebone->parent : NULL) {
- if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
+ for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
+ if (ebone_iter->temp.i & TOUCH) {
+ continue;
+ }
+ if ((ebone_iter->flag & BONE_DONE) == 0) {
+ continue;
+ }
+
+ ebone_iter->temp.i |= TOUCH | LINK;
+
+ /* We have an un-touched link. */
+ for (EditBone *ebone = ebone_iter; ebone; ebone = CHECK_PARENT(ebone) ? ebone->parent : NULL) {
ED_armature_ebone_select_set(ebone, select);
+ changed = true;
+
if (all_forks) {
- ebone->temp.i = (TOUCH | LINK);
+ ebone->temp.i |= (TOUCH | LINK);
}
else {
- ebone->temp.i = TOUCH;
+ ebone->temp.i |= TOUCH;
+ }
+ /* Don't walk onto links (messes up 'all_forks' logic). */
+ if (ebone->parent && ebone->parent->temp.i & LINK) {
+ break;
}
}
}
- if (all_forks == false) {
- ebone_active->temp.i = LINK;
- }
-
- /* Select children.
- *
- * Implementation note, this flood-fills selected bones with the 'TOUCH' flag,
- * even though this is a loop-within a loop, walking up the parent chain only touches new bones.
- * Bones that have been touched are skipped, so the complexity is OK. */
+ /* Select children. */
for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
/* No need to 'touch' this bone as it won't be walked over when scanning up the chain. */
if (!CHECK_PARENT(ebone_iter)) {
@@ -374,6 +388,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv
if ((ebone->temp.i & LINK) == 0) {
ebone->temp.i |= LINK;
ED_armature_ebone_select_set(ebone, select);
+ changed = true;
}
}
}
@@ -381,32 +396,129 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv
#undef CHECK_PARENT
- ED_outliner_select_sync_from_edit_bone_tag(C);
+ if (changed) {
+ ED_armature_edit_sync_selection(arm->edbo);
+ DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, ob);
+ }
- ED_armature_edit_sync_selection(arm->edbo);
+ return changed;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Linked Operator
+ * \{ */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
- DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+static int armature_select_linked_exec(bContext *C, wmOperator *op)
+{
+ const bool all_forks = RNA_boolean_get(op->ptr, "all_forks");
+ bool changed_multi = false;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+ bArmature *arm = ob->data;
+
+ bool found = false;
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone) &&
+ (ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL))) {
+ ebone->flag |= BONE_DONE;
+ found = true;
+ }
+ else {
+ ebone->flag &= ~BONE_DONE;
+ }
+ }
+
+ if (found) {
+ if (armature_select_linked_impl(ob, true, all_forks)) {
+ changed_multi = true;
+ }
+ }
+ }
+ MEM_freeN(objects);
+
+ if (changed_multi) {
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+ }
return OPERATOR_FINISHED;
}
-static bool armature_select_linked_poll(bContext *C)
+void ARMATURE_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Linked All";
+ ot->idname = "ARMATURE_OT_select_linked";
+ ot->description = "Select all bones linked by parent/child connections to the current selection";
+
+ /* api callbacks */
+ ot->exec = armature_select_linked_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Leave disabled by default as this matches pose mode. */
+ RNA_def_boolean(ot->srna, "all_forks", 0, "All Forks", "Follow forks in the parents chain");
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Linked (Cursor Pick) Operator
+ * \{ */
+
+static int armature_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const bool select = !RNA_boolean_get(op->ptr, "deselect");
+ const bool all_forks = RNA_boolean_get(op->ptr, "all_forks");
+
+ view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
+
+ Base *base = NULL;
+ EditBone *ebone_active = get_nearest_bone(C, event->mval, true, &base);
+ bArmature *arm = base->object->data;
+
+ if (ebone_active == NULL || !EBONE_SELECTABLE(arm, ebone_active)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Initialize flags. */
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ ebone->flag &= ~BONE_DONE;
+ }
+ ebone_active->flag |= BONE_DONE;
+
+ if (armature_select_linked_impl(base->object, select, all_forks)) {
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static bool armature_select_linked_pick_poll(bContext *C)
{
return (ED_operator_view3d_active(C) && ED_operator_editarmature(C));
}
-void ARMATURE_OT_select_linked(wmOperatorType *ot)
+void ARMATURE_OT_select_linked_pick(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select Connected";
- ot->idname = "ARMATURE_OT_select_linked";
- ot->description = "Select bones related to selected ones by parent/child relationships";
+ ot->name = "Select Linked";
+ ot->idname = "ARMATURE_OT_select_linked_pick";
+ ot->description = "(De)select bones linked by parent/child connections under the mouse cursor";
/* api callbacks */
/* leave 'exec' unset */
- ot->invoke = armature_select_linked_invoke;
- ot->poll = armature_select_linked_poll;
+ ot->invoke = armature_select_linked_pick_invoke;
+ ot->poll = armature_select_linked_pick_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -416,6 +528,12 @@ void ARMATURE_OT_select_linked(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all_forks", 0, "All Forks", "Follow forks in the parents chain");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Buffer Queries EditMode
+ * \{ */
+
/* utility function for get_nearest_editbonepoint */
static int selectbuffer_ret_hits_12(unsigned int *UNUSED(buffer), const int hits12)
{
@@ -620,6 +738,12 @@ cache_end:
return NULL;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Utility Functions
+ * \{ */
+
bool ED_armature_edit_deselect_all(Object *obedit)
{
bArmature *arm = obedit->data;
@@ -686,6 +810,12 @@ bool ED_armature_edit_deselect_all_visible_multi(bContext *C)
return changed_multi;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cursor Picking API
+ * \{ */
+
/* accounts for connected parents */
static int ebone_select_flag(EditBone *ebone)
{
@@ -825,6 +955,8 @@ bool ED_armature_edit_select_pick(
return false;
}
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Select Op From Tagged
*
@@ -1009,7 +1141,9 @@ bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op)
/** \} */
-/* **************** Selections ******************/
+/* -------------------------------------------------------------------- */
+/** \name (De)Select All Operator
+ * \{ */
static int armature_de_select_all_exec(bContext *C, wmOperator *op)
{
@@ -1088,7 +1222,11 @@ void ARMATURE_OT_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
-/**************** Select more/less **************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select More/Less Implementation
+ * \{ */
static void armature_select_more(bArmature *arm, EditBone *ebone)
{
@@ -1175,6 +1313,12 @@ static void armature_select_more_less(Object *ob, bool more)
ED_armature_edit_sync_selection(arm->edbo);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select More Operator
+ * \{ */
+
static int armature_de_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -1208,6 +1352,12 @@ void ARMATURE_OT_select_more(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Less Operator
+ * \{ */
+
static int armature_de_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -1241,6 +1391,12 @@ void ARMATURE_OT_select_less(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Similar
+ * \{ */
+
enum {
SIMEDBONE_CHILDREN = 1,
SIMEDBONE_CHILDREN_IMMEDIATE,
@@ -1656,7 +1812,11 @@ void ARMATURE_OT_select_similar(wmOperatorType *ot)
RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
}
-/* ********************* select hierarchy operator ************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Hierarchy Operator
+ * \{ */
/* No need to convert to multi-objects. Just like we keep the non-active bones
* selected we then keep the non-active objects untouched (selected/unselected). */
@@ -1762,7 +1922,11 @@ void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
-/****************** Mirror Select ****************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Mirror Operator
+ * \{ */
/**
* \note clone of #pose_select_mirror_exec keep in sync
@@ -1847,7 +2011,11 @@ void ARMATURE_OT_select_mirror(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
-/****************** Select Path ****************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Path Operator
+ * \{ */
static bool armature_shortest_path_select(
bArmature *arm, EditBone *ebone_parent, EditBone *ebone_child, bool use_parent, bool is_test)
@@ -1973,3 +2141,5 @@ void ARMATURE_OT_shortest_path_pick(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/** \} */
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 6b5a7215709..1a25e582859 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -1771,8 +1771,93 @@ void MESH_OT_face_make_planar(wmOperatorType *ot)
/** \name Split Edge Operator
* \{ */
+static bool edbm_edge_split_selected_edges(wmOperator *op, Object *obedit, BMEditMesh *em)
+{
+ BMesh *bm = em->bm;
+ if (bm->totedgesel == 0) {
+ return false;
+ }
+ if (!EDBM_op_call_and_selectf(
+ em, op, "edges.out", false, "split_edges edges=%he", BM_ELEM_SELECT)) {
+ return false;
+ }
+
+ EDBM_select_flush(em);
+ EDBM_update_generic(obedit->data, true, true);
+
+ return true;
+}
+
+static bool edbm_edge_split_selected_verts(wmOperator *op, Object *obedit, BMEditMesh *em)
+{
+ BMesh *bm = em->bm;
+
+ /* Note that tracking vertices through the 'split_edges' operator is complicated.
+ * Instead, tag loops for selection. */
+ if (bm->totvertsel == 0) {
+ return false;
+ }
+
+ /* Flush from vertices to edges. */
+ BMIter iter;
+ BMEdge *eed;
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_disable(eed, BM_ELEM_TAG);
+ if (eed->l != NULL) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) &&
+ (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
+ BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))) {
+ BM_elem_flag_enable(eed, BM_ELEM_TAG);
+ }
+ /* Store selection in loop tags. */
+ BMLoop *l_iter = eed->l;
+ do {
+ BM_elem_flag_set(l_iter, BM_ELEM_TAG, BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT));
+ } while ((l_iter = l_iter->radial_next) != eed->l);
+ }
+ }
+
+ if (!EDBM_op_callf(em,
+ op,
+ "split_edges edges=%he verts=%hv use_verts=%b",
+ BM_ELEM_TAG,
+ BM_ELEM_SELECT,
+ true)) {
+ return false;
+ }
+
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (eed->l != NULL) {
+ BMLoop *l_iter = eed->l;
+ do {
+ if (BM_elem_flag_test(l_iter, BM_ELEM_TAG)) {
+ BM_vert_select_set(em->bm, l_iter->v, true);
+ }
+ } while ((l_iter = l_iter->radial_next) != eed->l);
+ }
+ else {
+ /* Split out wire. */
+ for (int i = 0; i < 2; i++) {
+ BMVert *v = *(&eed->v1 + i);
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ if (eed != BM_DISK_EDGE_NEXT(eed, v)) {
+ BM_vert_separate(bm, v, &eed, 1, true, NULL, NULL);
+ }
+ }
+ }
+ }
+ }
+
+ EDBM_select_flush(em);
+ EDBM_update_generic(obedit->data, true, true);
+
+ return true;
+}
+
static int edbm_edge_split_exec(bContext *C, wmOperator *op)
{
+ const int type = RNA_enum_get(op->ptr, "type");
+
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
@@ -1780,20 +1865,21 @@ static int edbm_edge_split_exec(bContext *C, wmOperator *op)
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (em->bm->totedgesel == 0) {
- continue;
- }
- if (!EDBM_op_call_and_selectf(
- em, op, "edges.out", false, "split_edges edges=%he", BM_ELEM_SELECT)) {
- continue;
- }
-
- if (em->selectmode == SCE_SELECT_FACE) {
- EDBM_select_flush(em);
+ switch (type) {
+ case BM_VERT:
+ if (!edbm_edge_split_selected_verts(op, obedit, em)) {
+ continue;
+ }
+ break;
+ case BM_EDGE:
+ if (!edbm_edge_split_selected_edges(op, obedit, em)) {
+ continue;
+ }
+ break;
+ default:
+ BLI_assert(0);
}
-
- EDBM_update_generic(obedit->data, true, true);
}
MEM_freeN(objects);
@@ -1813,6 +1899,20 @@ void MESH_OT_edge_split(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ static const EnumPropertyItem merge_type_items[] = {
+ {BM_EDGE, "EDGE", 0, "Faces by Edges", "Split faces along selected edges"},
+ {BM_VERT,
+ "VERT",
+ 0,
+ "Faces & Edges by Vertices",
+ "Split faces & edges connected to selected vertices"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", merge_type_items, BM_EDGE, "Type", "Method to use for splitting");
}
/** \} */
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index c3949899dff..1049db74a75 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -459,15 +459,20 @@ int count_set_pose_transflags(Object *ob,
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
bone = pchan->bone;
- bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR);
if (PBONE_VISIBLE(arm, bone)) {
if ((bone->flag & BONE_SELECTED)) {
bone->flag |= BONE_TRANSFORM;
}
+ else {
+ bone->flag &= ~BONE_TRANSFORM;
+ }
bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
bone->flag &= ~BONE_TRANSFORM_CHILD;
}
+ else {
+ bone->flag &= ~BONE_TRANSFORM;
+ }
}
/* make sure no bone can be transformed when a parent is transformed */
@@ -1581,145 +1586,148 @@ void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, int tmode, short t
FCurve *fcu;
// TODO: this should probably be done per channel instead...
- if (autokeyframe_cfra_can_key(scene, id)) {
- ReportList *reports = CTX_wm_reports(C);
- ToolSettings *ts = scene->toolsettings;
- KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
- ListBase nla_cache = {NULL, NULL};
- float cfra = (float)CFRA;
- eInsertKeyFlags flag = 0;
+ if (!autokeyframe_cfra_can_key(scene, id)) {
+ /* tag channels that should have unkeyed data */
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone->flag & BONE_TRANSFORM) {
+ /* tag this channel */
+ pchan->bone->flag |= BONE_UNKEYED;
+ }
+ }
+ return;
+ }
- /* flag is initialized from UserPref keyframing settings
- * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get
- * visual keyframes even if flag not set, as it's not that useful otherwise
- * (for quick animation recording)
- */
- flag = ANIM_get_keyframing_flags(scene, true);
+ ReportList *reports = CTX_wm_reports(C);
+ ToolSettings *ts = scene->toolsettings;
+ KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
+ ListBase nla_cache = {NULL, NULL};
+ float cfra = (float)CFRA;
+ eInsertKeyFlags flag = 0;
+
+ /* flag is initialized from UserPref keyframing settings
+ * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get
+ * visual keyframes even if flag not set, as it's not that useful otherwise
+ * (for quick animation recording)
+ */
+ flag = ANIM_get_keyframing_flags(scene, true);
+
+ if (targetless_ik) {
+ flag |= INSERTKEY_MATRIX;
+ }
- if (targetless_ik) {
- flag |= INSERTKEY_MATRIX;
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((pchan->bone->flag & BONE_TRANSFORM) == 0 &&
+ !((pose->flag & POSE_MIRROR_EDIT) && (pchan->bone->flag & BONE_TRANSFORM_MIRROR))) {
+ continue;
}
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if ((pchan->bone->flag & BONE_TRANSFORM) ||
- ((pose->flag & POSE_MIRROR_EDIT) && (pchan->bone->flag & BONE_TRANSFORM_MIRROR))) {
- ListBase dsources = {NULL, NULL};
-
- /* clear any 'unkeyed' flag it may have */
- pchan->bone->flag &= ~BONE_UNKEYED;
-
- /* add datasource override for the camera object */
- ANIM_relative_keyingset_add_source(&dsources, id, &RNA_PoseBone, pchan);
-
- /* only insert into active keyingset? */
- if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
- /* run the active Keying Set on the current datasource */
- ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- /* only insert into available channels? */
- else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
- if (act) {
- for (fcu = act->curves.first; fcu; fcu = fcu->next) {
- /* only insert keyframes for this F-Curve if it affects the current bone */
- if (strstr(fcu->rna_path, "bones")) {
- char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones[");
-
- /* only if bone name matches too...
- * NOTE: this will do constraints too, but those are ok to do here too?
- */
- if (pchanName && STREQ(pchanName, pchan->name)) {
- insert_keyframe(bmain,
- reports,
- id,
- act,
- ((fcu->grp) ? (fcu->grp->name) : (NULL)),
- fcu->rna_path,
- fcu->array_index,
- cfra,
- ts->keyframe_type,
- &nla_cache,
- flag);
- }
-
- if (pchanName) {
- MEM_freeN(pchanName);
- }
- }
- }
- }
- }
- /* only insert keyframe if needed? */
- else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) {
- bool do_loc = false, do_rot = false, do_scale = false;
+ ListBase dsources = {NULL, NULL};
- /* Filter the conditions when this happens
- * (assume that 'curarea->spacetype == SPACE_VIEW3D'). */
- if (tmode == TFM_TRANSLATION) {
- if (targetless_ik) {
- do_rot = true;
- }
- else {
- do_loc = true;
- }
- }
- else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
- if (ELEM(scene->toolsettings->transform_pivot_point,
- V3D_AROUND_CURSOR,
- V3D_AROUND_ACTIVE)) {
- do_loc = true;
- }
+ /* clear any 'unkeyed' flag it may have */
+ pchan->bone->flag &= ~BONE_UNKEYED;
- if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
- do_rot = true;
- }
- }
- else if (tmode == TFM_RESIZE) {
- if (ELEM(scene->toolsettings->transform_pivot_point,
- V3D_AROUND_CURSOR,
- V3D_AROUND_ACTIVE)) {
- do_loc = true;
- }
+ /* add datasource override for the camera object */
+ ANIM_relative_keyingset_add_source(&dsources, id, &RNA_PoseBone, pchan);
- if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
- do_scale = true;
- }
+ /* only insert into active keyingset? */
+ if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
+ /* run the active Keying Set on the current datasource */
+ ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ /* only insert into available channels? */
+ else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
+ if (act) {
+ for (fcu = act->curves.first; fcu; fcu = fcu->next) {
+ /* only insert keyframes for this F-Curve if it affects the current bone */
+ if (strstr(fcu->rna_path, "bones") == NULL) {
+ continue;
}
+ char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones[");
- if (do_loc) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- if (do_rot) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ /* only if bone name matches too...
+ * NOTE: this will do constraints too, but those are ok to do here too?
+ */
+ if (pchanName && STREQ(pchanName, pchan->name)) {
+ insert_keyframe(bmain,
+ reports,
+ id,
+ act,
+ ((fcu->grp) ? (fcu->grp->name) : (NULL)),
+ fcu->rna_path,
+ fcu->array_index,
+ cfra,
+ ts->keyframe_type,
+ &nla_cache,
+ flag);
}
- if (do_scale) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+
+ if (pchanName) {
+ MEM_freeN(pchanName);
}
}
- /* insert keyframe in all (transform) channels */
+ }
+ }
+ /* only insert keyframe if needed? */
+ else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) {
+ bool do_loc = false, do_rot = false, do_scale = false;
+
+ /* Filter the conditions when this happens
+ * (assume that 'curarea->spacetype == SPACE_VIEW3D'). */
+ if (tmode == TFM_TRANSLATION) {
+ if (targetless_ik) {
+ do_rot = true;
+ }
else {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ do_loc = true;
+ }
+ }
+ else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
+ if (ELEM(scene->toolsettings->transform_pivot_point,
+ V3D_AROUND_CURSOR,
+ V3D_AROUND_ACTIVE)) {
+ do_loc = true;
}
- /* free temp info */
- BLI_freelistN(&dsources);
+ if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
+ do_rot = true;
+ }
}
- }
+ else if (tmode == TFM_RESIZE) {
+ if (ELEM(scene->toolsettings->transform_pivot_point,
+ V3D_AROUND_CURSOR,
+ V3D_AROUND_ACTIVE)) {
+ do_loc = true;
+ }
- BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
- }
- else {
- /* tag channels that should have unkeyed data */
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & BONE_TRANSFORM) {
- /* tag this channel */
- pchan->bone->flag |= BONE_UNKEYED;
+ if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
+ do_scale = true;
+ }
+ }
+
+ if (do_loc) {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ if (do_rot) {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ if (do_scale) {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
}
}
+ /* insert keyframe in all (transform) channels */
+ else {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+
+ /* free temp info */
+ BLI_freelistN(&dsources);
}
+
+ BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
}
/** \} */
diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c
index 4e8e0cc2369..53dd54d4b53 100644
--- a/source/blender/editors/transform/transform_convert_armature.c
+++ b/source/blender/editors/transform/transform_convert_armature.c
@@ -530,6 +530,12 @@ void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, Object *
unit_m4(flip_mtx);
flip_mtx[0][0] = -1;
+ for (bPoseChannel *pchan_orig = ob->pose->chanbase.first; pchan_orig;
+ pchan_orig = pchan_orig->next) {
+ /* Clear the MIRROR flag from previous runs. */
+ pchan_orig->bone->flag &= ~BONE_TRANSFORM_MIRROR;
+ }
+
bPose *pose = ob->pose;
PoseInitData_Mirror *pid = NULL;
if ((t->mode != TFM_BONESIZE) && (pose->flag & POSE_MIRROR_RELATIVE)) {
@@ -565,6 +571,9 @@ void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, Object *
}
BKE_pchan_apply_mat4(pchan, pchan_mtx_final, false);
+ /* Set flag to let autokeyframe know to keyframe the mirrred bone. */
+ pchan->bone->flag |= BONE_TRANSFORM_MIRROR;
+
/* In this case we can do target-less IK grabbing. */
if (t->mode == TFM_TRANSLATION) {
bKinematicConstraint *data = has_targetless_ik(pchan);
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index a90935bfe62..a3b1f315f04 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -468,7 +468,7 @@ typedef enum eGPDlayer_OnionFlag {
/* layer blend_mode */
typedef enum eGPLayerBlendModes {
eGplBlendMode_Regular = 0,
- eGplBlendMode_Overlay = 1,
+ eGplBlendMode_HardLight = 1,
eGplBlendMode_Add = 2,
eGplBlendMode_Subtract = 3,
eGplBlendMode_Multiply = 4,
@@ -661,8 +661,6 @@ typedef enum eGPdata_Flag {
/* Autolock not active layers */
GP_DATA_AUTOLOCK_LAYERS = (1 << 20),
- /* Internal flag for python update */
- GP_DATA_PYTHON_UPDATED = (1 << 21),
} eGPdata_Flag;
/* gpd->onion_flag */
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index deacd8e1cfc..4afa467d2e3 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -114,7 +114,7 @@ static const EnumPropertyItem rna_enum_gplayer_move_type_items[] = {
static const EnumPropertyItem rna_enum_layer_blend_modes_items[] = {
{eGplBlendMode_Regular, "REGULAR", 0, "Regular", ""},
- {eGplBlendMode_Overlay, "OVERLAY", 0, "Overlay", ""},
+ {eGplBlendMode_HardLight, "HARDLIGHT", 0, "Hard Light", ""},
{eGplBlendMode_Add, "ADD", 0, "Add", ""},
{eGplBlendMode_Subtract, "SUBTRACT", 0, "Subtract", ""},
{eGplBlendMode_Multiply, "MULTIPLY", 0, "Multiply", ""},
@@ -642,7 +642,6 @@ static void rna_GPencil_stroke_point_add(
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(stroke);
- gpd->flag |= GP_DATA_PYTHON_UPDATED;
DEG_id_tag_update(&gpd->id,
ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
@@ -704,7 +703,6 @@ static void rna_GPencil_stroke_point_pop(ID *id,
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(stroke);
- gpd->flag |= GP_DATA_PYTHON_UPDATED;
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index b4b1c1d3698..bfef9341913 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -154,6 +154,12 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
/* equivalent to normal_world_to_object */
GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &norm);
+ {
+ /* See SHD_PROJ_FLAT for explanation. */
+ GPU_link(mat, "set_rgb", *texco, texco);
+ GPU_link(mat, "set_rgb", *texco, &input_coords);
+ in[0].link = input_coords;
+ }
GPU_link(
mat, gpu_node_name, *texco, norm, GPU_image(mat, ima, iuser), &col1, &col2, &col3);
GPU_stack_link(
diff --git a/source/creator/blender.map b/source/creator/blender.map
index 4c34dea3338..3e447ec9e89 100644
--- a/source/creator/blender.map
+++ b/source/creator/blender.map
@@ -6,21 +6,71 @@
{
global:
- *;
- *_boost*;
+ *;
+ *_boost*;
local:
- *default_error_condition*;
- *llvm*;
- *LLVM*;
- decodeInstruction;
- ForceStackAlign;
- _Jv_RegisterClasses;
- Name;
- NumNamedVarArgParams;
- X86CompilationCallback*;
- *boost*;
- *SDL*;
- *embree*;
- cu*;
+ al*;
+ *Alembic*;
+ av*;
+ blosc*;
+ *boost*;
+ *ceres*;
+ *cineon*;
+ *COLLADA*;
+ cu*;
+ decodeInstruction;
+ *default_error_condition*;
+ *dpx*;
+ *embree*;
+ ff_*;
+ fftw*;
+ FLAC*;
+ ForceStackAlign;
+ FT_*;
+ *GeneratedSaxParser*;
+ *google*;
+ gsm*;
+ Gsm*;
+ html*;
+ id3tag*;
+ *Iex*;
+ *Ilm*;
+ *Imath*;
+ *Imf*;
+ jack_*;
+ jpeg_*;
+ jsimd**;
+ _Jv_RegisterClasses;
+ lame_*;
+ *llvm*;
+ *LLVM*;
+ *MathML*;
+ *mkldnn*;
+ Name;
+ NumNamedVarArgParams;
+ oc_*;
+ ogg*;
+ *oidn*;
+ *OpenColorIO*;
+ *OpenImageIO*;
+ *OpenSubdiv*;
+ *openvdb*;
+ opj_*;
+ opus_*;
+ *OSL*;
+ png_*;
+ *SDL*;
+ *squish*;
+ *tbb*;
+ *TIFF*;
+ *tinyformat*;
+ vorbis*;
+ vp8*;
+ vp9*;
+ vpx*;
+ x264_*;
+ X86CompilationCallback*;
+ xml*;
+ xvid*;
+ *YAML*;
};
-
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index 7b5a448fc53..a5b9df166a4 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -619,7 +619,7 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
printf("Misc Options:\n");
BLI_argsPrintArgDoc(ba, "--app-template");
BLI_argsPrintArgDoc(ba, "--factory-startup");
- BLI_argsPrintArgDoc(ba, "--enable-library-override");
+ BLI_argsPrintArgDoc(ba, "--disable-library-override");
BLI_argsPrintArgDoc(ba, "--enable-event-simulate");
printf("\n");
BLI_argsPrintArgDoc(ba, "--env-system-datafiles");
diff --git a/source/creator/osx_locals.map b/source/creator/osx_locals.map
index 3382ac954e2..908bfdae6cb 100644
--- a/source/creator/osx_locals.map
+++ b/source/creator/osx_locals.map
@@ -1,10 +1,66 @@
## The symbols will be treated as if they were marked as __private_extern__
## (aka visibility=hidden) and will not be global in the output file
+al*
+*Alembic*
+av*
+blosc*
*boost*
-*__ZNSt6vector*
+*ceres*
+*cineon*
+*COLLADA*
+cu*
+decodeInstruction
+*default_error_condition*
+*dpx*
+*embree*
+ff_*
+fftw*
+FLAC*
+ForceStackAlign
+FT_*
+*GeneratedSaxParser*
+*google*
+gsm*
+Gsm*
+html*
+id3tag*
+*Iex*
+*Ilm*
+*Imath*
+*Imf*
+jack_*
+jpeg_*
+jsimd**
+_Jv_RegisterClasses
+lame_*
*llvm*
*LLVM*
+*MathML*
+*mkldnn*
+Name
+NumNamedVarArgParams
+oc_*
+ogg*
+*oidn*
+*OpenColorIO*
+*OpenImageIO*
+*OpenSubdiv*
+*openvdb*
+opj_*
+opus_*
*OSL*
-*embree*
-cu*
-
+png_*
+*SDL*
+*squish*
+*tbb*
+*TIFF*
+*tinyformat*
+vorbis*
+vp8*
+vp9*
+vpx*
+x264_*
+X86CompilationCallback*
+xml*
+xvid*
+*YAML*