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:
authorLukas Tönne <lukas.toenne@gmail.com>2015-02-10 19:09:00 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2015-02-10 19:09:00 +0300
commite89fd502d7b1ee5a4c17286a78ae0116f03510b7 (patch)
tree5c68b5cb560b3cc5ba62046167d364b2183abb11 /source/blender/editors
parent6cd3ebfc9fa4838a74192f2e5cc82b5d5d2e6fe7 (diff)
parent227a94077f508a47fe7595b9091ab86aecde4ad5 (diff)
Merge branch 'master' into alembic_pointcache
Conflicts: CMakeLists.txt build_files/build_environment/install_deps.sh source/blender/blenkernel/CMakeLists.txt source/blender/blenkernel/SConscript source/blender/blenkernel/intern/particle.c source/blender/blenkernel/intern/pointcache.c source/blender/editors/physics/particle_edit.c source/blender/editors/space_outliner/outliner_draw.c source/blender/makesdna/DNA_modifier_types.h source/blender/makesrna/SConscript source/blender/makesrna/intern/CMakeLists.txt source/blender/makesrna/intern/SConscript source/blender/makesrna/intern/rna_modifier.c source/blender/makesrna/intern/rna_object_force.c source/blender/modifiers/MOD_modifiertypes.h source/blender/modifiers/intern/MOD_util.c source/blender/render/intern/source/voxeldata.c
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c15
-rw-r--r--source/blender/editors/animation/anim_draw.c6
-rw-r--r--source/blender/editors/animation/anim_markers.c9
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c6
-rw-r--r--source/blender/editors/animation/keyframes_edit.c8
-rw-r--r--source/blender/editors/animation/keyframes_general.c8
-rw-r--r--source/blender/editors/animation/keyingsets.c49
-rw-r--r--source/blender/editors/armature/armature_add.c2
-rw-r--r--source/blender/editors/armature/armature_edit.c74
-rw-r--r--source/blender/editors/armature/armature_naming.c7
-rw-r--r--source/blender/editors/armature/armature_relations.c158
-rw-r--r--source/blender/editors/armature/armature_select.c2
-rw-r--r--source/blender/editors/armature/editarmature_retarget.c6
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c4
-rw-r--r--source/blender/editors/armature/pose_lib.c2
-rw-r--r--source/blender/editors/armature/pose_utils.c2
-rw-r--r--source/blender/editors/curve/editcurve.c611
-rw-r--r--source/blender/editors/curve/editcurve_add.c6
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c51
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c23
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c11
-rw-r--r--source/blender/editors/gpencil/gpencil_undo.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c53
-rw-r--r--source/blender/editors/include/BIF_gl.h10
-rw-r--r--source/blender/editors/include/ED_gpencil.h6
-rw-r--r--source/blender/editors/include/ED_image.h3
-rw-r--r--source/blender/editors/include/ED_object.h6
-rw-r--r--source/blender/editors/include/ED_screen.h2
-rw-r--r--source/blender/editors/include/ED_view3d.h1
-rw-r--r--source/blender/editors/include/UI_icons.h12
-rw-r--r--source/blender/editors/include/UI_interface.h25
-rw-r--r--source/blender/editors/include/UI_resources.h2
-rw-r--r--source/blender/editors/interface/interface.c2
-rw-r--r--source/blender/editors/interface/interface_draw.c55
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c240
-rw-r--r--source/blender/editors/interface/interface_handlers.c156
-rw-r--r--source/blender/editors/interface/interface_intern.h1
-rw-r--r--source/blender/editors/interface/interface_layout.c19
-rw-r--r--source/blender/editors/interface/interface_ops.c4
-rw-r--r--source/blender/editors/interface/interface_panel.c4
-rw-r--r--source/blender/editors/interface/interface_regions.c5
-rw-r--r--source/blender/editors/interface/interface_style.c119
-rw-r--r--source/blender/editors/interface/interface_templates.c5
-rw-r--r--source/blender/editors/interface/interface_widgets.c63
-rw-r--r--source/blender/editors/interface/resources.c59
-rw-r--r--source/blender/editors/interface/view2d.c6
-rw-r--r--source/blender/editors/interface/view2d_ops.c53
-rw-r--r--source/blender/editors/mesh/editmesh_add.c11
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c4
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c36
-rw-r--r--source/blender/editors/mesh/mesh_data.c66
-rw-r--r--source/blender/editors/mesh/mesh_intern.h3
-rw-r--r--source/blender/editors/mesh/mesh_ops.c3
-rw-r--r--source/blender/editors/mesh/meshtools.c2
-rw-r--r--source/blender/editors/object/object_add.c22
-rw-r--r--source/blender/editors/object/object_bake_api.c2
-rw-r--r--source/blender/editors/object/object_constraint.c2
-rw-r--r--source/blender/editors/object/object_data_transfer.c12
-rw-r--r--source/blender/editors/object/object_edit.c6
-rw-r--r--source/blender/editors/object/object_group.c53
-rw-r--r--source/blender/editors/object/object_hook.c14
-rw-r--r--source/blender/editors/object/object_modifier.c16
-rw-r--r--source/blender/editors/object/object_relations.c12
-rw-r--r--source/blender/editors/object/object_vgroup.c2
-rw-r--r--source/blender/editors/physics/particle_edit.c212
-rw-r--r--source/blender/editors/physics/particle_object.c495
-rw-r--r--source/blender/editors/physics/physics_intern.h3
-rw-r--r--source/blender/editors/physics/physics_ops.c3
-rw-r--r--source/blender/editors/render/render_opengl.c15
-rw-r--r--source/blender/editors/render/render_preview.c4
-rw-r--r--source/blender/editors/render/render_shading.c2
-rw-r--r--source/blender/editors/render/render_view.c23
-rw-r--r--source/blender/editors/screen/area.c3
-rw-r--r--source/blender/editors/screen/glutil.c6
-rw-r--r--source/blender/editors/screen/screen_context.c4
-rw-r--r--source/blender/editors/screen/screen_edit.c37
-rw-r--r--source/blender/editors/screen/screen_ops.c61
-rw-r--r--source/blender/editors/screen/screendump.c5
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c16
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c11
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c1039
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c9
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c86
-rw-r--r--source/blender/editors/sculpt_paint/paint_undo.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c14
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c12
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c8
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c16
-rw-r--r--source/blender/editors/sound/sound_ops.c8
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c2
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c2
-rw-r--r--source/blender/editors/space_clip/clip_ops.c3
-rw-r--r--source/blender/editors/space_console/console_ops.c6
-rw-r--r--source/blender/editors/space_file/file_draw.c15
-rw-r--r--source/blender/editors/space_file/file_ops.c10
-rw-r--r--source/blender/editors/space_file/filelist.c45
-rw-r--r--source/blender/editors/space_file/filesel.c2
-rw-r--r--source/blender/editors/space_file/fsmenu.c8
-rw-r--r--source/blender/editors/space_graph/graph_draw.c4
-rw-r--r--source/blender/editors/space_graph/graph_edit.c2
-rw-r--r--source/blender/editors/space_graph/graph_select.c66
-rw-r--r--source/blender/editors/space_image/image_buttons.c45
-rw-r--r--source/blender/editors/space_image/image_edit.c15
-rw-r--r--source/blender/editors/space_image/space_image.c4
-rw-r--r--source/blender/editors/space_logic/logic_ops.c9
-rw-r--r--source/blender/editors/space_logic/logic_window.c88
-rw-r--r--source/blender/editors/space_nla/nla_channels.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c98
-rw-r--r--source/blender/editors/space_node/node_draw.c5
-rw-r--r--source/blender/editors/space_node/node_edit.c2
-rw-r--r--source/blender/editors/space_node/space_node.c8
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c101
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c173
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h5
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c1
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c108
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c42
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c56
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c49
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c242
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_preview.c6
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c2
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c17
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c10
-rw-r--r--source/blender/editors/space_text/text_draw.c3
-rw-r--r--source/blender/editors/space_text/text_ops.c10
-rw-r--r--source/blender/editors/space_time/space_time.c16
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c2
-rw-r--r--source/blender/editors/space_view3d/drawobject.c158
-rw-r--r--source/blender/editors/space_view3d/drawsimdebug.c173
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c40
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c122
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h5
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c2
-rw-r--r--source/blender/editors/transform/transform.c233
-rw-r--r--source/blender/editors/transform/transform.h19
-rw-r--r--source/blender/editors/transform/transform_constraints.c2
-rw-r--r--source/blender/editors/transform/transform_conversions.c18
-rw-r--r--source/blender/editors/transform/transform_generics.c31
-rw-r--r--source/blender/editors/transform/transform_manipulator.c2
-rw-r--r--source/blender/editors/transform/transform_ops.c2
-rw-r--r--source/blender/editors/util/ed_util.c2
-rw-r--r--source/blender/editors/util/editmode_undo.c6
-rw-r--r--source/blender/editors/util/undo.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c6
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c11
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c2
155 files changed, 4568 insertions, 1919 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index d76eba93640..37c40052275 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -61,6 +61,7 @@
#include "RNA_access.h"
+#include "BKE_animsys.h"
#include "BKE_curve.h"
#include "BKE_key.h"
#include "BKE_nla.h"
@@ -3519,6 +3520,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* step 5) draw name ............................................... */
/* TODO: when renaming, we might not want to draw this, especially if name happens to be longer than channel */
if (acf->name) {
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */
/* set text color */
@@ -3532,7 +3534,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
acf->name(ale, name);
offset += 3;
- UI_draw_string(offset, ytext, name);
+ UI_fontstyle_draw_simple(fstyle, offset, ytext, name);
/* draw red underline if channel is disabled */
if ((ale->type == ANIMTYPE_FCURVE) && (ale->flag & FCURVE_DISABLED)) {
@@ -3688,6 +3690,7 @@ static void achannel_nlatrack_solo_widget_cb(bContext *C, void *adt_poin, void *
static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poin)
{
ID *id = (ID *)id_poin;
+ AnimData *adt = BKE_animdata_from_id(id);
FCurve *fcu = (FCurve *)fcu_poin;
ReportList *reports = CTX_wm_reports(C);
@@ -3698,9 +3701,8 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
bool done = false;
float cfra;
- /* get current frame */
- // NOTE: this will do for now...
- cfra = (float)CFRA;
+ /* get current frame and apply NLA-mapping to it (if applicable) */
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
/* get flags for keyframing */
flag = ANIM_get_keyframing_flags(scene, 1);
@@ -3737,9 +3739,8 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
bool done = false;
float cfra;
- /* get current frame */
- // NOTE: this will do for now...
- cfra = (float)CFRA;
+ /* get current frame and apply NLA-mapping to it (if applicable) */
+ cfra = BKE_nla_tweakedit_remap(key->adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
/* get flags for keyframing */
flag = ANIM_get_keyframing_flags(scene, 1);
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 2d7656642d3..0e052279796 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -59,6 +59,7 @@
/* Draw current frame number in a little green box beside the current frame indicator */
static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const bool time)
{
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
float xscale, yscale, x, y;
char numstr[32] = " t"; /* t is the character to start replacing from */
int slen;
@@ -78,7 +79,8 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const
else {
BLI_timecode_string_from_time_simple(&numstr[4], sizeof(numstr) - 4, 1, cfra);
}
- slen = UI_fontstyle_string_width(numstr) - 1;
+
+ slen = UI_fontstyle_string_width(fstyle, numstr) - 1;
/* get starting coordinates for drawing */
x = cfra * xscale;
@@ -90,7 +92,7 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const
/* draw current frame number - black text */
UI_ThemeColor(TH_TEXT);
- UI_draw_string(x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr);
+ UI_fontstyle_draw_simple(fstyle, x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr);
/* restore view transform */
glScalef(xscale, 1.0, 1.0);
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index b6c7a4aa5a0..140b7e0b117 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -317,7 +317,7 @@ void debug_markers_print_list(ListBase *markers)
/* function to draw markers */
static void draw_marker(
- View2D *v2d, TimeMarker *marker, int cfra, int flag,
+ View2D *v2d, const uiFontStyle *fstyle, TimeMarker *marker, int cfra, int flag,
/* avoid re-calculating each time */
const float ypixels, const float xscale, const float yscale)
{
@@ -399,13 +399,14 @@ static void draw_marker(
}
#endif
- UI_draw_string(x, y, marker->name);
+ UI_fontstyle_draw_simple(fstyle, x, y, marker->name);
}
}
/* Draw Scene-Markers in time window */
void ED_markers_draw(const bContext *C, int flag)
{
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
ListBase *markers = ED_context_get_markers(C);
View2D *v2d;
TimeMarker *marker;
@@ -455,7 +456,7 @@ void ED_markers_draw(const bContext *C, int flag)
if ((marker->frame >= v2d_clip_range_x[0]) &&
(marker->frame <= v2d_clip_range_x[1]))
{
- draw_marker(v2d, marker, scene->r.cfra, flag,
+ draw_marker(v2d, fstyle, marker, scene->r.cfra, flag,
ypixels, xscale, yscale);
}
}
@@ -1056,7 +1057,7 @@ static void select_timeline_marker_frame(ListBase *markers, int frame, bool exte
}
BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_first) {
- /* this way a not-extend select will allways give 1 selected marker */
+ /* this way a not-extend select will always give 1 selected marker */
if (marker->frame == frame) {
marker->flag ^= SELECT;
break;
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index 8ede1a0ad76..bcdad1c93ad 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -130,6 +130,7 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
switch (data->mode) {
case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
{
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
float *cp = NULL;
char xval[32];
unsigned int i;
@@ -147,11 +148,12 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
/* calculate maximum width of label for "x^n" labels */
if (data->arraysize > 2) {
BLI_snprintf(xval, sizeof(xval), "x^%u", data->arraysize);
- maxXWidth = UI_fontstyle_string_width(xval) + 0.5 * UI_UNIT_X; /* XXX: UI_fontstyle_string_width is not accurate */
+ /* XXX: UI_fontstyle_string_width is not accurate */
+ maxXWidth = UI_fontstyle_string_width(fstyle, xval) + 0.5 * UI_UNIT_X;
}
else {
/* basic size (just "x") */
- maxXWidth = UI_fontstyle_string_width("x") + 0.5 * UI_UNIT_X;
+ maxXWidth = UI_fontstyle_string_width(fstyle, "x") + 0.5 * UI_UNIT_X;
}
/* draw controls for each coefficient and a + sign at end of row */
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 439b3b94974..ee1bfdff0bd 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -785,7 +785,8 @@ static short mirror_bezier_cframe(KeyframeEditData *ked, BezTriple *bezt)
static short mirror_bezier_yaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
if (bezt->f2 & SELECT) {
- mirror_bezier_yaxis_ex(bezt, 0.0f);
+ /* Yes, names are inverted, we are mirroring accross y axis, hence along x axis... */
+ mirror_bezier_xaxis_ex(bezt, 0.0f);
}
return 0;
@@ -794,7 +795,8 @@ static short mirror_bezier_yaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
static short mirror_bezier_xaxis(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
if (bezt->f2 & SELECT) {
- mirror_bezier_xaxis_ex(bezt, 0.0f);
+ /* Yes, names are inverted, we are mirroring accross x axis, hence along y axis... */
+ mirror_bezier_yaxis_ex(bezt, 0.0f);
}
return 0;
@@ -814,7 +816,7 @@ static short mirror_bezier_value(KeyframeEditData *ked, BezTriple *bezt)
{
/* value to mirror over is stored in the custom data -> first float value slot */
if (bezt->f2 & SELECT) {
- mirror_bezier_xaxis_ex(bezt, ked->f1);
+ mirror_bezier_yaxis_ex(bezt, ked->f1);
}
return 0;
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index 7ac11c1cd06..932a00d1687 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -641,7 +641,7 @@ static void flip_names(tAnimCopybufItem *aci, char **name)
str_iter = *name = MEM_mallocN(sizeof(char) * (prefix_l + postfix_l + length + 1), "flipped_path");
BLI_strncpy(str_iter, aci->rna_path, prefix_l + 1);
- str_iter += prefix_l ;
+ str_iter += prefix_l;
BLI_strncpy(str_iter, bname_new, length + 1);
str_iter += length;
BLI_strncpy(str_iter, str_end, postfix_l + 1);
@@ -663,14 +663,14 @@ static tAnimCopybufItem *pastebuf_match_path_full(FCurve *fcu, const short from_
if ((from_single) || (aci->array_index == fcu->array_index)) {
char *name = NULL;
flip_names(aci, &name);
- if (strcmp(name, fcu->rna_path) == 0) {
+ if (STREQ(name, fcu->rna_path)) {
MEM_freeN(name);
break;
}
MEM_freeN(name);
}
}
- else if (to_simple || (strcmp(aci->rna_path, fcu->rna_path) == 0)) {
+ else if (to_simple || STREQ(aci->rna_path, fcu->rna_path)) {
if ((from_single) || (aci->array_index == fcu->array_index)) {
break;
}
@@ -711,7 +711,7 @@ static tAnimCopybufItem *pastebuf_match_path_property(FCurve *fcu, const short f
int len_path = strlen(fcu->rna_path);
if (len_id <= len_path) {
/* note, paths which end with "] will fail with this test - Animated ID Props */
- if (strcmp(identifier, fcu->rna_path + (len_path - len_id)) == 0) {
+ if (STREQ(identifier, fcu->rna_path + (len_path - len_id))) {
if ((from_single) || (aci->array_index == fcu->array_index))
break;
}
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index a5c0eee8d3b..4b9a629183e 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -556,7 +556,7 @@ KeyingSet *ANIM_builtin_keyingset_get_named(KeyingSet *prevKS, const char name[]
/* loop over KeyingSets checking names */
for (ks = first; ks; ks = ks->next) {
- if (strcmp(name, ks->idname) == 0)
+ if (STREQ(name, ks->idname))
return ks;
}
@@ -603,7 +603,7 @@ void ANIM_keyingset_info_unregister(Main *bmain, KeyingSetInfo *ksi)
ksn = ks->next;
/* remove if matching typeinfo name */
- if (strcmp(ks->typeinfo, ksi->idname) == 0) {
+ if (STREQ(ks->typeinfo, ksi->idname)) {
Scene *scene;
BKE_keyingset_free(ks);
BLI_remlink(&builtin_keyingsets, ks);
@@ -914,6 +914,37 @@ short ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks)
return 0;
}
+/* Determine which keying flags apply based on the override flags */
+static short keyingset_apply_keying_flags(const short base_flags, const short overrides, const short own_flags)
+{
+ short result = 0;
+
+ /* The logic for whether a keying flag applies is as follows:
+ * - If the flag in question is set in "overrides", that means that the
+ * status of that flag in "own_flags" is used
+ * - If however the flag isn't set, then its value in "base_flags" is used
+ * instead (i.e. no override)
+ */
+#define APPLY_KEYINGFLAG_OVERRIDE(kflag) \
+ if (overrides & kflag) { \
+ result |= (own_flags & kflag); \
+ } \
+ else { \
+ result |= (base_flags & kflag); \
+ }
+
+ /* Apply the flags one by one...
+ * (See rna_def_common_keying_flags() for the supported flags)
+ */
+ APPLY_KEYINGFLAG_OVERRIDE(INSERTKEY_NEEDED)
+ APPLY_KEYINGFLAG_OVERRIDE(INSERTKEY_MATRIX)
+ APPLY_KEYINGFLAG_OVERRIDE(INSERTKEY_XYZ2RGB)
+
+#undef APPLY_KEYINGFLAG_OVERRIDE
+
+ return result;
+}
+
/* Given a KeyingSet and context info (if required), modify keyframes for the channels specified
* by the KeyingSet. This takes into account many of the different combinations of using KeyingSets.
* Returns the number of channels that keyframes were added to
@@ -923,7 +954,8 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe
Scene *scene = CTX_data_scene(C);
ReportList *reports = CTX_wm_reports(C);
KS_Path *ksp;
- int kflag = 0, success = 0;
+ const short base_kflags = ANIM_get_keyframing_flags(scene, 1);
+ short kflag = 0, success = 0;
const char *groupname = NULL;
/* sanity checks */
@@ -932,11 +964,8 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe
/* get flags to use */
if (mode == MODIFYKEY_MODE_INSERT) {
- /* use KeyingSet's flags as base */
- kflag = ks->keyingflag;
-
- /* supplement with info from the context */
- kflag |= ANIM_get_keyframing_flags(scene, 1);
+ /* use context settings as base */
+ kflag = keyingset_apply_keying_flags(base_kflags, ks->keyingoverride, ks->keyingflag);
}
else if (mode == MODIFYKEY_MODE_DELETE)
kflag = 0;
@@ -962,8 +991,8 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe
continue;
}
- /* since keying settings can be defined on the paths too, extend the path before using it */
- kflag2 = (kflag | ksp->keyingflag);
+ /* since keying settings can be defined on the paths too, apply the settings for this path first */
+ kflag2 = keyingset_apply_keying_flags(kflag, ksp->keyingoverride, ksp->keyingflag);
/* get pointer to name of group to add channels to */
if (ksp->groupmode == KSP_GROUP_NONE)
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index eba1bc4d78d..22aaeccc4a8 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -270,7 +270,7 @@ static EditBone *get_named_editbone(ListBase *edbo, const char *name)
if (name) {
for (eBone = edbo->first; eBone; eBone = eBone->next) {
- if (!strcmp(name, eBone->name))
+ if (STREQ(name, eBone->name))
return eBone;
}
}
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index 7f7843a6d1d..88c52989c07 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -38,6 +38,8 @@
#include "MEM_guardedalloc.h"
+#include "BLF_translation.h"
+
#include "BLI_blenlib.h"
#include "BLI_math.h"
@@ -236,28 +238,49 @@ float ED_rollBoneToVector(EditBone *bone, const float align_axis[3], const bool
return roll;
}
-
+/* note, ranges arithmatic is used below */
typedef enum eCalcRollTypes {
- CALC_ROLL_X = 0,
- CALC_ROLL_Y = 1,
- CALC_ROLL_Z = 2,
-
- CALC_ROLL_TAN_X = 3,
- CALC_ROLL_TAN_Z = 4,
-
- CALC_ROLL_ACTIVE = 5,
- CALC_ROLL_VIEW = 6,
- CALC_ROLL_CURSOR = 7,
+ /* pos */
+ CALC_ROLL_POS_X = 0,
+ CALC_ROLL_POS_Y,
+ CALC_ROLL_POS_Z,
+
+ CALC_ROLL_TAN_POS_X,
+ CALC_ROLL_TAN_POS_Z,
+
+ /* neg */
+ CALC_ROLL_NEG_X,
+ CALC_ROLL_NEG_Y,
+ CALC_ROLL_NEG_Z,
+
+ CALC_ROLL_TAN_NEG_X,
+ CALC_ROLL_TAN_NEG_Z,
+
+ /* no sign */
+ CALC_ROLL_ACTIVE,
+ CALC_ROLL_VIEW,
+ CALC_ROLL_CURSOR,
} eCalcRollTypes;
static EnumPropertyItem prop_calc_roll_types[] = {
- {CALC_ROLL_TAN_X, "X", 0, "Local X Tangent", ""},
- {CALC_ROLL_TAN_Z, "Z", 0, "Local Z Tangent", ""},
+ {0, "", 0, N_("Positive"), ""},
+ {CALC_ROLL_TAN_POS_X, "POS_X", 0, "Local +X Tangent", ""},
+ {CALC_ROLL_TAN_POS_Z, "POS_Z", 0, "Local +Z Tangent", ""},
+
+ {CALC_ROLL_POS_X, "GLOBAL_POS_X", 0, "Global +X Axis", ""},
+ {CALC_ROLL_POS_Y, "GLOBAL_POS_Y", 0, "Global +Y Axis", ""},
+ {CALC_ROLL_POS_Z, "GLOBAL_POS_Z", 0, "Global +Z Axis", ""},
- {CALC_ROLL_X, "GLOBAL_X", 0, "Global X Axis", ""},
- {CALC_ROLL_Y, "GLOBAL_Y", 0, "Global Y Axis", ""},
- {CALC_ROLL_Z, "GLOBAL_Z", 0, "Global Z Axis", ""},
+ {0, "", 0, N_("Negative"), ""},
+ {CALC_ROLL_TAN_NEG_X, "NEG_X", 0, "Local -X Tangent", ""},
+ {CALC_ROLL_TAN_NEG_Z, "NEG_Z", 0, "Local -Z Tangent", ""},
+
+ {CALC_ROLL_NEG_X, "GLOBAL_NEG_X", 0, "Global -X Axis", ""},
+ {CALC_ROLL_NEG_Y, "GLOBAL_NEG_Y", 0, "Global -Y Axis", ""},
+ {CALC_ROLL_NEG_Z, "GLOBAL_NEG_Z", 0, "Global -Z Axis", ""},
+
+ {0, "", 0, N_("Other"), ""},
{CALC_ROLL_ACTIVE, "ACTIVE", 0, "Active Bone", ""},
{CALC_ROLL_VIEW, "VIEW", 0, "View Axis", ""},
{CALC_ROLL_CURSOR, "CURSOR", 0, "Cursor", ""},
@@ -268,15 +291,22 @@ static EnumPropertyItem prop_calc_roll_types[] = {
static int armature_calc_roll_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_edit_object(C);
- const short type = RNA_enum_get(op->ptr, "type");
+ eCalcRollTypes type = RNA_enum_get(op->ptr, "type");
const bool axis_only = RNA_boolean_get(op->ptr, "axis_only");
- const bool axis_flip = RNA_boolean_get(op->ptr, "axis_flip");
+ /* axis_flip when matching the active bone never makes sense */
+ bool axis_flip = ((type >= CALC_ROLL_ACTIVE) ? RNA_boolean_get(op->ptr, "axis_flip") :
+ (type >= CALC_ROLL_TAN_NEG_X) ? true : false);
float imat[3][3];
bArmature *arm = ob->data;
EditBone *ebone;
+ if ((type >= CALC_ROLL_NEG_X) && (type <= CALC_ROLL_TAN_NEG_Z)) {
+ type -= (CALC_ROLL_ACTIVE - CALC_ROLL_NEG_X);
+ axis_flip = true;
+ }
+
copy_m3_m4(imat, ob->obmat);
invert_m3(imat);
@@ -302,7 +332,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
}
}
}
- else if (ELEM(type, CALC_ROLL_TAN_X, CALC_ROLL_TAN_Z)) {
+ else if (ELEM(type, CALC_ROLL_TAN_POS_X, CALC_ROLL_TAN_POS_Z)) {
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
if (ebone->parent) {
bool is_edit = (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone));
@@ -323,7 +353,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
sub_v3_v3v3(dir_b, ebone_other->head, ebone_other->tail);
normalize_v3(dir_b);
- if (type == CALC_ROLL_TAN_Z) {
+ if (type == CALC_ROLL_TAN_POS_Z) {
cross_v3_v3v3(vec, dir_a, dir_b);
}
else {
@@ -374,7 +404,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
copy_v3_v3(vec, mat[2]);
}
else { /* Axis */
- assert(type >= 0 && type <= 5);
+ assert(type <= 5);
if (type < 3) vec[type] = 1.0f;
else vec[type - 2] = -1.0f;
mul_m3_v3(imat, vec);
@@ -423,7 +453,7 @@ void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_calc_roll_types, CALC_ROLL_TAN_X, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_calc_roll_types, CALC_ROLL_TAN_POS_X, "Type", "");
RNA_def_boolean(ot->srna, "axis_flip", 0, "Flip Axis", "Negate the alignment axis");
RNA_def_boolean(ot->srna, "axis_only", 0, "Shortest Rotation", "Ignore the axis direction, use the shortest rotation to align");
}
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 9afc45955bd..a8b5f888597 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -141,7 +141,7 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
char oldname[MAXBONENAME];
/* names better differ! */
- if (strncmp(oldnamep, newnamep, MAXBONENAME)) {
+ if (!STREQLEN(oldnamep, newnamep, MAXBONENAME)) {
/* we alter newname string... so make copy */
BLI_strncpy(newname, newnamep, MAXBONENAME);
@@ -219,7 +219,7 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
if (ob->parent && (ob->parent->data == arm)) {
if (ob->partype == PARBONE) {
/* bone name in object */
- if (!strcmp(ob->parsubstr, oldname))
+ if (STREQ(ob->parsubstr, oldname))
BLI_strncpy(ob->parsubstr, newname, MAXBONENAME);
}
}
@@ -267,6 +267,7 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
/* Fix all animdata that may refer to this bone - we can't just do the ones attached to objects, since
* other ID-blocks may have drivers referring to this bone [#29822]
*/
+ // XXX: the ID here is for armatures, but most bone drivers are actually on the object instead...
{
BKE_all_animdata_fix_paths_rename(&arm->id, "pose.bones", oldname, newname);
@@ -284,7 +285,7 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
if (v3d->ob_centre && v3d->ob_centre->data == arm) {
- if (!strcmp(v3d->ob_centre_bone, oldname)) {
+ if (STREQ(v3d->ob_centre_bone, oldname)) {
BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME);
}
}
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 3e226c39c8c..53989dd783c 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -29,20 +29,26 @@
* \ingroup edarmature
*/
+#include "MEM_guardedalloc.h"
+
+#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
#include "BLI_math.h"
#include "BLF_translation.h"
#include "BKE_action.h"
+#include "BKE_animsys.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -98,33 +104,122 @@ static void joined_armature_fix_links_constraints(
/* action constraint? (pose constraints only) */
if (con->type == CONSTRAINT_TYPE_ACTION) {
- bActionConstraint *data = con->data; // XXX old animation system
- bAction *act;
- bActionChannel *achan;
+ bActionConstraint *data = con->data;
if (data->act) {
- act = data->act;
+ BKE_action_fix_paths_rename(&tarArm->id, data->act, "pose.bones[",
+ pchan->name, curbone->name, 0, 0, false);
+ }
+ }
+
+ }
+}
+
+/* userdata for joined_armature_fix_animdata_cb() */
+typedef struct tJoinArmature_AdtFixData {
+ Object *srcArm;
+ Object *tarArm;
+
+ GHash *names_map;
+} tJoinArmature_AdtFixData;
- for (achan = act->chanbase.first; achan; achan = achan->next) {
- if (STREQ(achan->name, pchan->name)) {
- BLI_strncpy(achan->name, curbone->name, sizeof(achan->name));
+/* Callback to pass to void BKE_animdata_main_cb() for fixing driver ID's to point to the new ID */
+/* FIXME: For now, we only care about drivers here. When editing rigs, it's very rare to have animation
+ * on the rigs being edited already, so it should be safe to skip these.
+ */
+static void joined_armature_fix_animdata_cb(ID *id, AnimData *adt, void *user_data)
+{
+ tJoinArmature_AdtFixData *afd = (tJoinArmature_AdtFixData *)user_data;
+ ID *src_id = &afd->srcArm->id;
+ ID *dst_id = &afd->tarArm->id;
+
+ GHashIterator gh_iter;
+ FCurve *fcu;
+
+ /* Fix paths - If this is the target object, it will have some "dirty" paths */
+ if (id == src_id) {
+ /* Fix drivers */
+ for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
+ /* skip driver if it doesn't affect the bones */
+ if (strstr(fcu->rna_path, "pose.bones[") == NULL) {
+ continue;
+ }
+
+ // FIXME: this is too crude... it just does everything!
+ GHASH_ITER(gh_iter, afd->names_map) {
+ const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
+ const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
+
+ /* only remap if changed; this still means there will be some waste if there aren't many drivers/keys */
+ if (!STREQ(old_name, new_name) && strstr(fcu->rna_path, old_name)) {
+ fcu->rna_path = BKE_animsys_fix_rna_path_rename(id, fcu->rna_path, "pose.bones",
+ old_name, new_name, 0, 0, false);
+
+ /* we don't want to apply a second remapping on this driver now,
+ * so stop trying names, but keep fixing drivers
+ */
+ break;
+ }
+ }
+ }
+ }
+
+
+ /* Driver targets */
+ for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
+ ChannelDriver *driver = fcu->driver;
+ DriverVar *dvar;
+
+ /* Fix driver references to invalid ID's */
+ for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
+ /* only change the used targets, since the others will need fixing manually anyway */
+ DRIVER_TARGETS_USED_LOOPER(dvar)
+ {
+ /* change the ID's used... */
+ if (dtar->id == src_id) {
+ dtar->id = dst_id;
+
+ /* also check on the subtarget...
+ * XXX: We duplicate the logic from drivers_path_rename_fix() here, with our own
+ * little twists so that we know that it isn't going to clobber the wrong data
+ */
+ if ((dtar->rna_path && strstr(dtar->rna_path, "pose.bones[")) || (dtar->pchan_name[0])) {
+ GHASH_ITER(gh_iter, afd->names_map) {
+ const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
+ const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
+
+ /* only remap if changed */
+ if (!STREQ(old_name, new_name)) {
+ if ((dtar->rna_path) && strstr(dtar->rna_path, old_name)) {
+ /* Fix up path */
+ dtar->rna_path = BKE_animsys_fix_rna_path_rename(id, dtar->rna_path, "pose.bones",
+ old_name, new_name, 0, 0, false);
+ break; /* no need to try any more names for bone path */
+ }
+ else if (STREQ(dtar->pchan_name, old_name)) {
+ /* Change target bone name */
+ BLI_strncpy(dtar->pchan_name, new_name, sizeof(dtar->pchan_name));
+ break; /* no need to try any more names for bone subtarget */
+ }
+ }
+ }
}
}
}
+ DRIVER_TARGETS_LOOPER_END
}
-
}
}
/* Helper function for armature joining - link fixing */
-static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
+static void joined_armature_fix_links(Main *bmain, Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
{
Object *ob;
bPose *pose;
bPoseChannel *pchant;
/* let's go through all objects in database */
- for (ob = G.main->object.first; ob; ob = ob->id.next) {
+ for (ob = bmain->object.first; ob; ob = ob->id.next) {
/* do some object-type specific things */
if (ob->type == OB_ARMATURE) {
pose = ob->pose;
@@ -198,8 +293,17 @@ int join_armature_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
{
if ((base->object->type == OB_ARMATURE) && (base->object != ob)) {
+ tJoinArmature_AdtFixData afd = {NULL};
bArmature *curarm = base->object->data;
+ /* we assume that each armature datablock is only used in a single place */
+ BLI_assert(ob->data != base->object->data);
+
+ /* init callback data for fixing up AnimData links later */
+ afd.srcArm = base->object;
+ afd.tarArm = ob;
+ afd.names_map = BLI_ghash_str_new("join_armature_adt_fix");
+
/* Make a list of editbones in current armature */
ED_armature_to_edit(base->object->data);
@@ -219,6 +323,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
/* Get new name */
unique_editbone_name(arm->edbo, curbone->name, NULL);
+ BLI_ghash_insert(afd.names_map, BLI_strdup(pchan->name), curbone->name);
/* Transform the bone */
{
@@ -249,7 +354,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
}
/* Fix Constraints and Other Links to this Bone and Armature */
- joined_armature_fix_links(ob, base->object, pchan, curbone);
+ joined_armature_fix_links(bmain, ob, base->object, pchan, curbone);
/* Rename pchan */
BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name));
@@ -264,6 +369,37 @@ int join_armature_exec(bContext *C, wmOperator *op)
BKE_pose_channels_hash_free(pose);
}
+ /* Fix all the drivers (and animation data) */
+ BKE_animdata_main_cb(bmain, joined_armature_fix_animdata_cb, &afd);
+ BLI_ghash_free(afd.names_map, MEM_freeN, NULL);
+
+ /* Only copy over animdata now, after all the remapping has been done,
+ * so that we don't have to worry about ambiguities re which armature
+ * a bone came from!
+ */
+ if (base->object->adt) {
+ if (ob->adt == NULL) {
+ /* no animdata, so just use a copy of the whole thing */
+ ob->adt = BKE_copy_animdata(base->object->adt, false);
+ }
+ else {
+ /* merge in data - we'll fix the drivers manually */
+ BKE_animdata_merge_copy(&ob->id, &base->object->id, ADT_MERGECOPY_KEEP_DST, false);
+ }
+ }
+
+ if (curarm->adt) {
+ if (arm->adt == NULL) {
+ /* no animdata, so just use a copy of the whole thing */
+ arm->adt = BKE_copy_animdata(curarm->adt, false);
+ }
+ else {
+ /* merge in data - we'll fix the drivers manually */
+ BKE_animdata_merge_copy(&arm->id, &curarm->id, ADT_MERGECOPY_KEEP_DST, false);
+ }
+ }
+
+ /* Free the old object data */
ED_base_object_free_and_unlink(bmain, scene, base);
}
}
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index c6ef76c570c..307e6c076f2 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -254,7 +254,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv
static int armature_select_linked_poll(bContext *C)
{
- return (ED_operator_view3d_active(C) && ED_operator_editarmature(C) );
+ return (ED_operator_view3d_active(C) && ED_operator_editarmature(C));
}
void ARMATURE_OT_select_linked(wmOperatorType *ot)
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
index aace8c5434c..5376fc8c79b 100644
--- a/source/blender/editors/armature/editarmature_retarget.c
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -718,7 +718,7 @@ static void RIG_reconnectControlBones(RigGraph *rg)
cti->get_constraint_targets(con, &targets);
for (target_index = 0, ct = targets.first; ct; target_index++, ct = ct->next) {
- if ((ct->tar == rg->ob) && strcmp(ct->subtarget, ctrl->bone->name) == 0) {
+ if ((ct->tar == rg->ob) && STREQ(ct->subtarget, ctrl->bone->name)) {
/* SET bone link to bone corresponding to pchan */
EditBone *link = BLI_ghash_lookup(rg->bones_map, pchan->name);
@@ -841,7 +841,7 @@ static void RIG_reconnectControlBones(RigGraph *rg)
cti->get_constraint_targets(con, &targets);
for (ct = targets.first; ct; ct = ct->next) {
- if ((ct->tar == rg->ob) && strcmp(ct->subtarget, ctrl->bone->name) == 0) {
+ if ((ct->tar == rg->ob) && STREQ(ct->subtarget, ctrl->bone->name)) {
/* SET bone link to ctrl corresponding to pchan */
RigControl *link = BLI_ghash_lookup(rg->controls_map, pchan->name);
@@ -1160,7 +1160,7 @@ static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bo
last_bone = bone;
- if (strcmp(bone->name, "head") == 0) {
+ if (STREQ(bone->name, "head")) {
contain_head = 1;
}
}
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index 3dbf7b4b65a..6c2d4256a0f 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -333,11 +333,11 @@ static void sk_autoname(bContext *C, ReebArc *arc)
if (side[0] == '\0') {
valid = 1;
}
- else if (strcmp(side, "R") == 0 || strcmp(side, "L") == 0) {
+ else if (STREQ(side, "R") || STREQ(side, "L")) {
valid = 1;
caps = 1;
}
- else if (strcmp(side, "r") == 0 || strcmp(side, "l") == 0) {
+ else if (STREQ(side, "r") || STREQ(side, "l")) {
valid = 1;
caps = 0;
}
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index 2e6eace88aa..d571fb374d9 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -1050,7 +1050,7 @@ static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step)
LinkData *ld, *ldn, *ldc;
/* free and rebuild if needed (i.e. if search-str changed) */
- if (strcmp(pld->searchstr, pld->searchold)) {
+ if (!STREQ(pld->searchstr, pld->searchold)) {
/* free list of temporary search matches */
BLI_freelistN(&pld->searchp);
diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c
index 1297755b7d0..2ba1eedd33b 100644
--- a/source/blender/editors/armature/pose_utils.c
+++ b/source/blender/editors/armature/pose_utils.c
@@ -259,7 +259,7 @@ LinkData *poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, con
FCurve *fcu = (FCurve *)ld->data;
/* check if paths match */
- if (strcmp(path, fcu->rna_path) == 0)
+ if (STREQ(path, fcu->rna_path))
return ld;
}
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 99c64be5797..4aeeaa87269 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -643,25 +643,20 @@ static void keyData_switchDirectionNurb(Curve *cu, Nurb *nu)
static GHash *dupli_keyIndexHash(GHash *keyindex)
{
GHash *gh;
- GHashIterator *hashIter;
+ GHashIterator gh_iter;
gh = BLI_ghash_ptr_new_ex("dupli_keyIndex gh", BLI_ghash_size(keyindex));
- for (hashIter = BLI_ghashIterator_new(keyindex);
- BLI_ghashIterator_done(hashIter) == false;
- BLI_ghashIterator_step(hashIter))
- {
- void *cv = BLI_ghashIterator_getKey(hashIter);
- CVKeyIndex *index = BLI_ghashIterator_getValue(hashIter);
- CVKeyIndex *newIndex = MEM_callocN(sizeof(CVKeyIndex), "dupli_keyIndexHash index");
+ GHASH_ITER (gh_iter, keyindex) {
+ void *cv = BLI_ghashIterator_getKey(&gh_iter);
+ CVKeyIndex *index = BLI_ghashIterator_getValue(&gh_iter);
+ CVKeyIndex *newIndex = MEM_mallocN(sizeof(CVKeyIndex), "dupli_keyIndexHash index");
memcpy(newIndex, index, sizeof(CVKeyIndex));
BLI_ghash_insert(gh, cv, newIndex);
}
- BLI_ghashIterator_free(hashIter);
-
return gh;
}
@@ -999,7 +994,7 @@ static void fcurve_path_rename(AnimData *adt, const char *orig_rna_path, char *r
for (fcu = orig_curves->first; fcu; fcu = nextfcu) {
nextfcu = fcu->next;
- if (!strncmp(fcu->rna_path, orig_rna_path, len)) {
+ if (STREQLEN(fcu->rna_path, orig_rna_path, len)) {
char *spath, *suffix = fcu->rna_path + len;
nfcu = copy_fcurve(fcu);
spath = nfcu->rna_path;
@@ -1102,10 +1097,10 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
for (fcu = orig_curves->first; fcu; fcu = next) {
next = fcu->next;
- if (!strncmp(fcu->rna_path, "splines", 7)) {
+ if (STREQLEN(fcu->rna_path, "splines", 7)) {
const char *ch = strchr(fcu->rna_path, '.');
- if (ch && (!strncmp(ch, ".bezier_points", 14) || !strncmp(ch, ".points", 7)))
+ if (ch && (STREQLEN(ch, ".bezier_points", 14) || STREQLEN(ch, ".points", 7)))
fcurve_remove(adt, orig_curves, fcu);
}
}
@@ -1129,7 +1124,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
for (fcu = orig_curves->first; fcu; fcu = next) {
next = fcu->next;
- if (!strncmp(fcu->rna_path, "splines", 7)) fcurve_remove(adt, orig_curves, fcu);
+ if (STREQLEN(fcu->rna_path, "splines", 7)) fcurve_remove(adt, orig_curves, fcu);
else BLI_addtail(&curves, fcu);
}
@@ -2007,7 +2002,7 @@ static void ed_curve_delete_selected(Object *obedit)
}
/* only for OB_SURF */
-bool ed_editnurb_extrude_flag(EditNurb *editnurb, short flag)
+bool ed_editnurb_extrude_flag(EditNurb *editnurb, const short flag)
{
Nurb *nu;
BPoint *bp, *bpn, *newbp;
@@ -2368,7 +2363,6 @@ static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
}
else {
/* knots done after duplicate as pntsu may change */
- nu->knotsu = nu->knotsv = NULL;
BKE_nurb_order_clamp_u(nu);
BKE_nurb_knot_calc_u(nu);
@@ -4889,285 +4883,405 @@ void CURVE_OT_spin(wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "axis", 3, NULL, -FLT_MAX, FLT_MAX, "Axis", "Axis in global view space", -1.0f, 1.0f);
}
-/***************** add vertex operator **********************/
+/***************** extrude vertex operator **********************/
-static int addvert_Nurb(bContext *C, short mode, float location[3])
+static bool ed_editcurve_extrude(Curve *cu, EditNurb *editnurb)
{
- Object *obedit = CTX_data_edit_object(C);
- Curve *cu = (Curve *)obedit->data;
- EditNurb *editnurb = cu->editnurb;
- Nurb *nu, *newnu = NULL;
- BezTriple *bezt, *newbezt = NULL;
- BPoint *bp, *newbp = NULL;
- float imat[4][4], temp[3];
- bool ok = false;
- BezTriple *bezt_recalc[3] = {NULL};
+ Nurb *nu = NULL;
+ Nurb *nu_last = NULL;
- invert_m4_m4(imat, obedit->obmat);
+ bool changed = false;
- findselectedNurbvert(&editnurb->nurbs, &nu, &bezt, &bp);
-
- if ((nu == NULL) || (nu->type == CU_BEZIER && bezt == NULL) || (nu->type != CU_BEZIER && bp == NULL)) {
- if (mode != 'e') {
- if (cu->actnu != CU_ACT_NONE)
- nu = BLI_findlink(&editnurb->nurbs, cu->actnu);
-
- if (!nu || nu->type == CU_BEZIER) {
- newbezt = (BezTriple *)MEM_callocN(sizeof(BezTriple), "addvert_Nurb");
- newbezt->radius = 1;
- newbezt->alfa = 0;
- BEZ_SEL(newbezt);
- newbezt->h2 = newbezt->h1 = HD_AUTO;
-
- newnu = (Nurb *)MEM_callocN(sizeof(Nurb), "addvert_Nurb newnu");
- if (!nu) {
- /* no selected segment -- create new one which is BEZIER type
- * type couldn't be determined from Curve bt could be changed
- * in the future, so shouldn't make much headache */
- newnu->type = CU_BEZIER;
- newnu->resolu = cu->resolu;
- newnu->flag |= CU_SMOOTH;
- }
- else {
- memcpy(newnu, nu, sizeof(Nurb));
- }
+ Nurb *cu_actnu;
+ union {
+ BezTriple *bezt;
+ BPoint *bp;
+ void *p;
+ } cu_actvert;
- BLI_addtail(&editnurb->nurbs, newnu);
- newnu->bezt = newbezt;
- newnu->pntsu = 1;
+ BKE_curve_nurb_vert_active_get(cu, &cu_actnu, &cu_actvert.p);
+ BKE_curve_nurb_vert_active_set(cu, NULL, NULL);
- temp[0] = 1;
- temp[1] = 0;
- temp[2] = 0;
+ /* first pass (endpoints) */
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
- copy_v3_v3(newbezt->vec[1], location);
- sub_v3_v3v3(newbezt->vec[0], newbezt->vec[1], temp);
- add_v3_v3v3(newbezt->vec[2], newbezt->vec[1], temp);
+ if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
+ continue;
+ }
- mul_m4_v3(imat, newbezt->vec[0]);
- mul_m4_v3(imat, newbezt->vec[1]);
- mul_m4_v3(imat, newbezt->vec[2]);
+ if (nu->type == CU_BEZIER) {
- ok = 1;
- nu = newnu;
- }
- else if (nu->pntsv == 1) {
- newbp = (BPoint *)MEM_callocN(sizeof(BPoint), "addvert_Nurb5");
- newbp->radius = 1;
- newbp->alfa = 0;
- newbp->f1 |= SELECT;
+ /* Check to see if the first bezier point is selected */
+ if (nu->pntsu > 0 && nu->bezt != NULL) {
+ BezTriple *nu_bezt_old = nu->bezt;
+ BezTriple *bezt = nu->bezt;
+
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ BezTriple *bezt_new;
+ BEZ_DESEL(bezt);
- newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu");
- memcpy(newnu, nu, sizeof(Nurb));
- BLI_addtail(&editnurb->nurbs, newnu);
- newnu->bp = newbp;
- newnu->orderu = 2;
- newnu->pntsu = 1;
+ bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__);
+ ED_curve_beztcpy(editnurb, bezt_new + 1, bezt, nu->pntsu);
+ *bezt_new = *bezt;
- mul_v3_m4v3(newbp->vec, imat, location);
- newbp->vec[3] = 1.0;
- newnu->knotsu = newnu->knotsv = NULL;
- BKE_nurb_knot_calc_u(newnu);
+ MEM_freeN(nu->bezt);
+ nu->bezt = bezt_new;
- ok = 1;
- nu = newnu;
+ nu->pntsu += 1;
+
+ if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) {
+ cu_actvert.bezt = (cu_actvert.bezt == bezt) ?
+ bezt_new : &nu->bezt[(cu_actvert.bezt - nu_bezt_old) + 1];
+ BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt);
+ }
+
+ BEZ_SEL(bezt_new);
+ changed = true;
+ }
}
+ /* Check to see if the last bezier point is selected */
+ if (nu->pntsu > 1) {
+ BezTriple *nu_bezt_old = nu->bezt;
+ BezTriple *bezt = &nu->bezt[nu->pntsu - 1];
+
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ BezTriple *bezt_new;
+ BEZ_DESEL(bezt);
+
+ bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__);
+ ED_curve_beztcpy(editnurb, bezt_new, nu->bezt, nu->pntsu);
+ bezt_new[nu->pntsu] = *bezt;
+
+ MEM_freeN(nu->bezt);
+ nu->bezt = bezt_new;
+
+ bezt_new += nu->pntsu;
+ nu->pntsu += 1;
+
+ if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) {
+ cu_actvert.bezt = (cu_actvert.bezt == bezt) ?
+ bezt_new : &nu->bezt[cu_actvert.bezt - nu_bezt_old];
+ BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt);
+ }
+
+ BEZ_SEL(bezt_new);
+ changed = true;
+ }
+ }
}
+ else {
- if (!ok)
- return OPERATOR_CANCELLED;
- }
+ /* Check to see if the first bpoint is selected */
+ if (nu->pntsu > 0 && nu->bp != NULL) {
+ BPoint *nu_bp_old = nu->bp;
+ BPoint *bp = nu->bp;
- if (!ok && nu->type == CU_BEZIER) {
- /* which bezpoint? */
- if (bezt == &nu->bezt[nu->pntsu - 1]) { /* last */
- BEZ_DESEL(bezt);
- newbezt = (BezTriple *)MEM_callocN((nu->pntsu + 1) * sizeof(BezTriple), "addvert_Nurb");
- ED_curve_beztcpy(editnurb, newbezt, nu->bezt, nu->pntsu);
- newbezt[nu->pntsu] = *bezt;
- copy_v3_v3(temp, bezt->vec[1]);
- MEM_freeN(nu->bezt);
- nu->bezt = newbezt;
- newbezt += nu->pntsu;
- BEZ_SEL(newbezt);
- newbezt->h1 = newbezt->h2;
- bezt = &nu->bezt[nu->pntsu - 1];
- ok = 1;
+ if (bp->f1 & SELECT) {
+ BPoint *bp_new;
+ bp->f1 &= ~SELECT;
- if (nu->pntsu > 1) {
- bezt_recalc[1] = newbezt;
- bezt_recalc[0] = newbezt - 1;
- }
- }
- else if (bezt == nu->bezt) { /* first */
- BEZ_DESEL(bezt);
- newbezt = (BezTriple *)MEM_callocN((nu->pntsu + 1) * sizeof(BezTriple), "addvert_Nurb");
- ED_curve_beztcpy(editnurb, newbezt + 1, bezt, nu->pntsu);
- *newbezt = *bezt;
- BEZ_SEL(newbezt);
- newbezt->h2 = newbezt->h1;
- copy_v3_v3(temp, bezt->vec[1]);
- MEM_freeN(nu->bezt);
- nu->bezt = newbezt;
- bezt = newbezt + 1;
- ok = 1;
+ bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__);
+ ED_curve_bpcpy(editnurb, bp_new + 1, bp, nu->pntsu);
+ *bp_new = *bp;
+
+ MEM_freeN(nu->bp);
+ nu->bp = bp_new;
+ nu->pntsu += 1;
+ BKE_nurb_knot_calc_u(nu);
+
+ if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) {
+ cu_actvert.bp = (cu_actvert.bp == bp) ?
+ bp_new : &nu->bp[(cu_actvert.bp - nu_bp_old) + 1];
+ BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp);
+ }
+
+ bp_new->f1 |= SELECT;
+ changed = true;
+ }
+ }
+
+ /* Check to see if the last bpoint is selected */
if (nu->pntsu > 1) {
- bezt_recalc[1] = newbezt;
- bezt_recalc[2] = newbezt + 1;
+ BPoint *nu_bp_old = nu->bp;
+ BPoint *bp = &nu->bp[nu->pntsu - 1];
+
+ if (bp->f1 & SELECT) {
+ BPoint *bp_new;
+ bp->f1 &= ~SELECT;
+
+ bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__);
+ ED_curve_bpcpy(editnurb, bp_new, nu->bp, nu->pntsu);
+ bp_new[nu->pntsu] = *bp;
+
+ MEM_freeN(nu->bp);
+ nu->bp = bp_new;
+
+ bp_new += nu->pntsu;
+ nu->pntsu += 1;
+
+ if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) {
+ cu_actvert.bp = (cu_actvert.bp == bp) ?
+ bp_new : &nu->bp[cu_actvert.bp - nu_bp_old];
+ BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp);
+ }
+
+ BKE_nurb_knot_calc_u(nu);
+
+ bp_new->f1 |= SELECT;
+ changed = true;
+ }
}
}
- else if (mode != 'e') {
- BEZ_DESEL(bezt);
- newbezt = (BezTriple *)MEM_callocN(sizeof(BezTriple), "addvert_Nurb");
- *newbezt = *bezt;
- BEZ_SEL(newbezt);
- newbezt->h2 = newbezt->h1;
- copy_v3_v3(temp, bezt->vec[1]);
+ }
- newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu");
- memcpy(newnu, nu, sizeof(Nurb));
- BLI_addtail(&editnurb->nurbs, newnu);
- newnu->bezt = newbezt;
- newnu->pntsu = 1;
+ /* second pass (interior points) */
+ nu_last = editnurb->nurbs.last;
+ for (nu = editnurb->nurbs.first; (nu != nu_last->next); nu = nu->next) {
+ int i, i_end;
- nu = newnu;
- bezt = newbezt;
- ok = 1;
+ if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
+ /* all points are interior */
+ i = 0;
+ i_end = nu->pntsu;
}
else {
- bezt = NULL;
+ /* skip endpoints */
+ i = 1;
+ i_end = nu->pntsu - 1;
}
- if (bezt) {
- if (!newnu) nu->pntsu++;
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
- if (mode == 'e') {
- copy_v3_v3(newbezt->vec[0], bezt->vec[0]);
- copy_v3_v3(newbezt->vec[1], bezt->vec[1]);
- copy_v3_v3(newbezt->vec[2], bezt->vec[2]);
- }
- else {
- mul_v3_m4v3(newbezt->vec[1], imat, location);
- sub_v3_v3v3(temp, newbezt->vec[1], temp);
+ for (bezt = &nu->bezt[i]; i < i_end; i++, bezt++) {
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ Nurb *nurb_new;
+ BezTriple *bezt_new;
+
+ BEZ_DESEL(bezt);
+ nurb_new = BKE_nurb_copy(nu, 1, 1);
+ nurb_new->flagu &= ~CU_NURB_CYCLIC;
+ BLI_addtail(&editnurb->nurbs, nurb_new);
+ bezt_new = nurb_new->bezt;
+ ED_curve_beztcpy(editnurb, bezt_new, bezt, 1);
+ BEZ_SEL(bezt_new);
+
+ if (cu_actvert.bezt == bezt || cu_actnu == NULL) {
+ BKE_curve_nurb_vert_active_set(cu, nurb_new, bezt_new);
+ }
- if (bezt_recalc[1]) {
- const char h1 = bezt_recalc[1]->h1, h2 = bezt_recalc[1]->h2;
- bezt_recalc[1]->h1 = bezt_recalc[1]->h2 = HD_AUTO;
- BKE_nurb_handle_calc(bezt_recalc[1], bezt_recalc[0], bezt_recalc[2], 0);
- bezt_recalc[1]->h1 = h1;
- bezt_recalc[1]->h2 = h2;
- }
- else {
- add_v3_v3v3(newbezt->vec[0], bezt->vec[0], temp);
- add_v3_v3v3(newbezt->vec[2], bezt->vec[2], temp);
+ changed = true;
}
-
+ }
+ }
+ else {
+ BPoint *bp;
+
+ for (bp = &nu->bp[i]; i < i_end; i++, bp++) {
+ if (bp->f1 & SELECT) {
+ Nurb *nurb_new;
+ BPoint *bp_new;
+
+ bp->f1 &= ~SELECT;
+ nurb_new = BKE_nurb_copy(nu, 1, 1);
+ nurb_new->flagu &= ~CU_NURB_CYCLIC;
+ BLI_addtail(&editnurb->nurbs, nurb_new);
+ bp_new = nurb_new->bp;
+ ED_curve_bpcpy(editnurb, bp_new, bp, 1);
+ bp_new->f1 |= SELECT;
+
+ if (cu_actvert.bp == bp || cu_actnu == NULL) {
+ BKE_curve_nurb_vert_active_set(cu, nurb_new, bp_new);
+ }
- if (newnu) BKE_nurb_handles_calc(newnu);
- else BKE_nurb_handles_calc(nu);
+ changed = true;
+ }
}
}
}
- else if (!ok && nu->pntsv == 1) {
- /* which b-point? */
- if (bp == &nu->bp[nu->pntsu - 1]) { /* last */
- bp->f1 = 0;
- newbp = (BPoint *)MEM_callocN((nu->pntsu + 1) * sizeof(BPoint), "addvert_Nurb4");
- ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu);
- newbp[nu->pntsu] = *bp;
- MEM_freeN(nu->bp);
- nu->bp = newbp;
- newbp += nu->pntsu;
- newbp->f1 |= SELECT;
- bp = newbp - 1;
- ok = 1;
- }
- else if (bp == nu->bp) { /* first */
- bp->f1 = 0;
- newbp = (BPoint *)MEM_callocN((nu->pntsu + 1) * sizeof(BPoint), "addvert_Nurb3");
- ED_curve_bpcpy(editnurb, newbp + 1, bp, nu->pntsu);
- *newbp = *bp;
- newbp->f1 |= SELECT;
- MEM_freeN(nu->bp);
- nu->bp = newbp;
- bp = newbp + 1;
- ok = 1;
- }
- else if (mode != 'e') {
- bp->f1 = 0;
- newbp = (BPoint *)MEM_callocN(sizeof(BPoint), "addvert_Nurb5");
- *newbp = *bp;
- newbp->f1 |= SELECT;
- newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu");
- memcpy(newnu, nu, sizeof(Nurb));
- BLI_addtail(&editnurb->nurbs, newnu);
- newnu->bp = newbp;
- newnu->orderu = 2;
- newnu->pntsu = 1;
- newnu->knotsu = newnu->knotsv = NULL;
+ if (changed == false) {
+ BKE_curve_nurb_vert_active_set(cu, cu_actnu, cu_actvert.p);
+ }
- nu = newnu;
- bp = newbp;
- ok = 1;
+ return changed;
+}
+
+/***************** add vertex operator **********************/
+
+static int ed_editcurve_addvert(Curve *cu, EditNurb *editnurb, const float location[3])
+{
+ Nurb *nu;
+
+ float minmax[2][3];
+ float temp[3];
+ bool nu_has_select = false;
+
+ bool changed = false;
+
+ INIT_MINMAX(minmax[0], minmax[1]);
+
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ int i;
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
+
+ for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) {
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ minmax_v3v3_v3(UNPACK2(minmax), bezt->vec[1]);
+ nu_has_select = true;
+ }
+ }
}
else {
- bp = NULL;
+ BPoint *bp;
+
+ for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) {
+ if (bp->f1 & SELECT) {
+ minmax_v3v3_v3(UNPACK2(minmax), bp->vec);
+ nu_has_select = true;
+ }
+ }
}
+ }
+
+ if (nu_has_select && ed_editcurve_extrude(cu, editnurb)) {
+ float ofs[3], center[3];
+ int i;
+
+ mid_v3_v3v3(center, minmax[0], minmax[1]);
+ sub_v3_v3v3(ofs, location, center);
- if (bp) {
- if (mode == 'e') {
- copy_v3_v3(newbp->vec, bp->vec);
+ if ((cu->flag & CU_3D) == 0) {
+ ofs[2] = 0.0f;
+ }
+
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt;
+ for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) {
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ add_v3_v3(bezt->vec[0], ofs);
+ add_v3_v3(bezt->vec[1], ofs);
+ add_v3_v3(bezt->vec[2], ofs);
+
+ if (((nu->flagu & CU_NURB_CYCLIC) == 0) &&
+ (i == 0 || i == nu->pntsu - 1))
+ {
+ BKE_nurb_handle_calc_simple_auto(nu, bezt);
+ }
+ }
+ }
}
else {
- mul_v3_m4v3(newbp->vec, imat, location);
- newbp->vec[3] = 1.0;
+ BPoint *bp;
- if (!newnu && nu->orderu < 4 && nu->orderu <= nu->pntsu)
- nu->orderu++;
+ for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) {
+ if (bp->f1 & SELECT) {
+ add_v3_v3(bp->vec, ofs);
+ }
+ }
}
+ }
+ changed = true;
+ }
+ else {
+ /* nothing selected: create a new curve */
+ nu = BKE_curve_nurb_active_get(cu);
- if (!newnu) {
- nu->pntsu++;
- BKE_nurb_knot_calc_u(nu);
+ if (!nu || nu->type == CU_BEZIER) {
+ Nurb *nurb_new;
+ BezTriple *bezt_new;
+
+ if (nu) {
+ nurb_new = BKE_nurb_copy(nu, 1, 1);
}
else {
- BKE_nurb_knot_calc_u(newnu);
+ nurb_new = MEM_callocN(sizeof(Nurb), "BLI_editcurve_addvert new_bezt_nurb 2");
+ nurb_new->type = CU_BEZIER;
+ nurb_new->resolu = cu->resolu;
+ nurb_new->orderu = 4;
+ nurb_new->flag |= CU_SMOOTH;
+ BKE_nurb_bezierPoints_add(nurb_new, 1);
}
- }
- }
+ BLI_addtail(&editnurb->nurbs, nurb_new);
- if (ok) {
- if (nu->bezt) {
- BKE_curve_nurb_vert_active_set(cu, nu, newbezt);
+ bezt_new = nurb_new->bezt;
+
+ BEZ_SEL(bezt_new);
+
+ bezt_new->h1 = HD_AUTO;
+ bezt_new->h2 = HD_AUTO;
+
+ temp[0] = 1.0f;
+ temp[1] = 0.0f;
+ temp[2] = 0.0f;
+
+ copy_v3_v3(bezt_new->vec[1], location);
+ sub_v3_v3v3(bezt_new->vec[0], bezt_new->vec[1], temp);
+ add_v3_v3v3(bezt_new->vec[2], bezt_new->vec[1], temp);
+
+ changed = true;
}
else {
- BKE_curve_nurb_vert_active_set(cu, nu, newbp);
- }
+ Nurb *nurb_new;
+ BPoint *bp_new;
- BKE_nurb_test2D(nu);
+ {
+ nurb_new = MEM_callocN(sizeof(Nurb), __func__);
+ nurb_new->type = CU_POLY;
+ nurb_new->resolu = cu->resolu;
+ nurb_new->flag |= CU_SMOOTH;
+ nurb_new->orderu = 4;
+ BKE_nurb_points_add(nurb_new, 1);
+ }
+ BLI_addtail(&editnurb->nurbs, nurb_new);
- if (ED_curve_updateAnimPaths(obedit->data))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ bp_new = nurb_new->bp;
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ bp_new->f1 |= SELECT;
- return OPERATOR_FINISHED;
+ copy_v3_v3(bp_new->vec, location);
+ bp_new->vec[3] = 1.0f;
+
+ BKE_nurb_knot_calc_u(nurb_new);
+
+ changed = true;
+ }
}
- return OPERATOR_CANCELLED;
+ return changed;
}
static int add_vertex_exec(bContext *C, wmOperator *op)
{
+ Object *obedit = CTX_data_edit_object(C);
+ Curve *cu = obedit->data;
+ EditNurb *editnurb = cu->editnurb;
float location[3];
+ float imat[4][4];
RNA_float_get_array(op->ptr, "location", location);
- return addvert_Nurb(C, 0, location);
+
+ invert_m4_m4(imat, obedit->obmat);
+ mul_m4_v3(imat, location);
+
+ if (ed_editcurve_addvert(cu, editnurb, location)) {
+ if (ED_curve_updateAnimPaths(obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DAG_id_tag_update(obedit->data, 0);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -5236,29 +5350,39 @@ void CURVE_OT_vertex_add(wmOperatorType *ot)
/***************** extrude operator **********************/
-static int extrude_exec(bContext *C, wmOperator *UNUSED(op))
+static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
EditNurb *editnurb = cu->editnurb;
- Nurb *nu;
+ bool changed = false;
+ bool as_curve = false;
/* first test: curve? */
- for (nu = editnurb->nurbs.first; nu; nu = nu->next)
- if (nu->pntsv == 1 && isNurbsel_count(cu, nu) == 1)
- break;
+ if (obedit->type != OB_CURVE) {
+ Nurb *nu;
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ if (nu->pntsv == 1 && isNurbsel_count(cu, nu) == 1) {
+ as_curve = true;
+ break;
+ }
+ }
+ }
- if (obedit->type == OB_CURVE || nu) {
- addvert_Nurb(C, 'e', NULL);
+ if (obedit->type == OB_CURVE || as_curve) {
+ changed = ed_editcurve_extrude(cu, editnurb);
}
else {
- if (ed_editnurb_extrude_flag(editnurb, SELECT)) {
- if (ED_curve_updateAnimPaths(obedit->data))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ changed = ed_editnurb_extrude_flag(editnurb, SELECT);
+ }
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ if (changed) {
+ if (ED_curve_updateAnimPaths(obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
}
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DAG_id_tag_update(obedit->data, 0);
}
return OPERATOR_FINISHED;
@@ -5272,7 +5396,7 @@ void CURVE_OT_extrude(wmOperatorType *ot)
ot->idname = "CURVE_OT_extrude";
/* api callbacks */
- ot->exec = extrude_exec;
+ ot->exec = curve_extrude_exec;
ot->poll = ED_operator_editsurfcurve;
/* flags */
@@ -6543,7 +6667,6 @@ static int curve_delete_segments(Object *obedit, const bool split)
}
}
- nu->knotsu = nu->knotsv = NULL;
BKE_nurb_order_clamp_u(nu);
BKE_nurb_knot_calc_u(nu);
@@ -6640,7 +6763,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
ListBase *editnurb = object_editcurve_get(obedit);
Nurb *nu;
- int clear = (strcmp(op->idname, "CURVE_OT_shade_flat") == 0);
+ int clear = (STREQ(op->idname, "CURVE_OT_shade_flat"));
if (obedit->type != OB_CURVE)
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c
index c9a961d1a4d..7c53896b969 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -529,11 +529,9 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
if (newob && enter_editmode)
ED_undo_push(C, "Enter Editmode");
- ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, false);
+ ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
dia = RNA_float_get(op->ptr, "radius");
- mat[0][0] *= dia;
- mat[1][1] *= dia;
- mat[2][2] *= dia;
+ mul_mat3_m4_fl(mat, dia);
nu = add_nurbs_primitive(C, obedit, mat, type, newob);
editnurb = object_editcurve_get(obedit);
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index 97adaea41a8..a2ba6216f9c 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -390,7 +390,7 @@ void paste_gpdata(Scene *scene)
/* find suitable layer from buffer to use to paste from */
for (gpls = gpcopybuf.first; gpls; gpls = gpls->next) {
/* check if layer name matches */
- if ((no_name) || (strcmp(gpls->info, gpld->info) == 0))
+ if ((no_name) || STREQ(gpls->info, gpld->info))
break;
}
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 3dae25263e8..a830253f634 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -100,7 +100,8 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr
switch (sa->spacetype) {
case SPACE_VIEW3D: /* 3D-View */
- case SPACE_TIME: /* Timeline - XXX: this is a hack to get it to show GP keyframes for 3D view */
+ case SPACE_TIME: /* Timeline - XXX: this is a hack to get it to show GP keyframes for 3D view */
+ case SPACE_ACTION: /* DepeSheet - XXX: this is a hack to get the keyframe jump operator to take GP Keyframes into account */
{
BLI_assert(scene && ELEM(scene->toolsettings->gpencil_src,
GP_TOOL_SOURCE_SCENE, GP_TOOL_SOURCE_OBJECT));
@@ -620,6 +621,10 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op)
/* make copies of selected strokes, and deselect these once we're done */
for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
if (gps->flag & GP_STROKE_SELECT) {
if (gps->totpoints == 1) {
/* Special Case: If there's just a single point in this stroke... */
@@ -728,6 +733,10 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
/* make copies of selected strokes, and deselect these once we're done */
for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
if (gps->flag & GP_STROKE_SELECT) {
if (gps->totpoints == 1) {
/* Special Case: If there's just a single point in this stroke... */
@@ -936,6 +945,11 @@ static int gp_delete_selected_strokes(bContext *C)
for (gps = gpf->strokes.first; gps; gps = gpsn) {
gpsn = gps->next;
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ /* free stroke if selected */
if (gps->flag & GP_STROKE_SELECT) {
/* free stroke memory arrays, then stroke itself */
if (gps->points) MEM_freeN(gps->points);
@@ -975,6 +989,10 @@ static int gp_dissolve_selected_points(bContext *C)
for (gps = gpf->strokes.first; gps; gps = gpsn) {
gpsn = gps->next;
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
if (gps->flag & GP_STROKE_SELECT) {
bGPDspoint *pt;
int i;
@@ -1050,6 +1068,11 @@ static int gp_delete_selected_points(bContext *C)
for (gps = gpf->strokes.first; gps; gps = gpsn) {
gpsn = gps->next;
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+
if (gps->flag & GP_STROKE_SELECT) {
bGPDspoint *pt;
int i;
@@ -2480,50 +2503,50 @@ static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
const bool valid_timing = RNA_boolean_get(ptr, "use_timing_data");
/* Always show those props */
- if (strcmp(prop_id, "type") == 0 ||
- strcmp(prop_id, "use_normalize_weights") == 0 ||
- strcmp(prop_id, "radius_multiplier") == 0 ||
- strcmp(prop_id, "use_link_strokes") == 0)
+ if (STREQ(prop_id, "type") ||
+ STREQ(prop_id, "use_normalize_weights") ||
+ STREQ(prop_id, "radius_multiplier") ||
+ STREQ(prop_id, "use_link_strokes"))
{
return true;
}
/* Never show this prop */
- if (strcmp(prop_id, "use_timing_data") == 0)
+ if (STREQ(prop_id, "use_timing_data"))
return false;
if (link_strokes) {
/* Only show when link_stroke is true */
- if (strcmp(prop_id, "timing_mode") == 0)
+ if (STREQ(prop_id, "timing_mode"))
return true;
if (timing_mode != GP_STROKECONVERT_TIMING_NONE) {
/* Only show when link_stroke is true and stroke timing is enabled */
- if (strcmp(prop_id, "frame_range") == 0 ||
- strcmp(prop_id, "start_frame") == 0)
+ if (STREQ(prop_id, "frame_range") ||
+ STREQ(prop_id, "start_frame"))
{
return true;
}
/* Only show if we have valid timing data! */
- if (valid_timing && strcmp(prop_id, "use_realtime") == 0)
+ if (valid_timing && STREQ(prop_id, "use_realtime"))
return true;
/* Only show if realtime or valid_timing is false! */
- if ((!realtime || !valid_timing) && strcmp(prop_id, "end_frame") == 0)
+ if ((!realtime || !valid_timing) && STREQ(prop_id, "end_frame"))
return true;
if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
/* Only show for custom gaps! */
- if (strcmp(prop_id, "gap_duration") == 0)
+ if (STREQ(prop_id, "gap_duration"))
return true;
/* Only show randomness for non-null custom gaps! */
- if (strcmp(prop_id, "gap_randomness") == 0 && (gap_duration > 0.0f))
+ if (STREQ(prop_id, "gap_randomness") && (gap_duration > 0.0f))
return true;
/* Only show seed for randomize action! */
- if (strcmp(prop_id, "seed") == 0 && (gap_duration > 0.0f) && (gap_randomness > 0.0f))
+ if (STREQ(prop_id, "seed") && (gap_duration > 0.0f) && (gap_randomness > 0.0f))
return true;
}
}
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index e6f6644fd24..c03766a95e1 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -999,7 +999,7 @@ static void gp_session_validatebuffer(tGPsdata *p)
}
/* (re)init new painting data */
-static int gp_session_initdata(bContext *C, tGPsdata *p)
+static bool gp_session_initdata(bContext *C, tGPsdata *p)
{
bGPdata **gpd_ptr = NULL;
ScrArea *curarea = CTX_wm_area(C);
@@ -1082,7 +1082,13 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
case SPACE_CLIP:
{
SpaceClip *sc = curarea->spacedata.first;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ if (clip == NULL) {
+ p->status = GP_STATUS_ERROR;
+ return false;
+ }
+
/* set the current area */
p->sa = curarea;
p->ar = ar;
@@ -1097,13 +1103,18 @@ static int gp_session_initdata(bContext *C, tGPsdata *p)
p->custom_color[3] = 0.9f;
if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
int framenr = ED_space_clip_get_clip_frame_number(sc);
MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
-
- p->imat[3][0] -= marker->pos[0];
- p->imat[3][1] -= marker->pos[1];
+ MovieTrackingMarker *marker = track ? BKE_tracking_marker_get(track, framenr) : NULL;
+
+ if (marker) {
+ p->imat[3][0] -= marker->pos[0];
+ p->imat[3][1] -= marker->pos[1];
+ }
+ else {
+ p->status = GP_STATUS_ERROR;
+ return false;
+ }
}
invert_m4_m4(p->mat, p->imat);
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 7967d6a4d95..9ba77a4244e 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -136,11 +136,14 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op)
bGPDspoint *pt;
int i;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- pt->flag &= ~GP_SPOINT_SELECT;
+ /* only edit strokes that are valid in this view... */
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ gps->flag &= ~GP_STROKE_SELECT;
}
-
- gps->flag &= ~GP_STROKE_SELECT;
}
}
}
diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c
index 5f0647fb43d..34e640a4b7b 100644
--- a/source/blender/editors/gpencil/gpencil_undo.c
+++ b/source/blender/editors/gpencil/gpencil_undo.c
@@ -76,7 +76,7 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name)
if (step == 1) { /* undo */
//printf("\t\tGP - undo step\n");
if (cur_node->prev) {
- if (!name || strcmp(cur_node->name, name) == 0) {
+ if (!name || STREQ(cur_node->name, name)) {
cur_node = cur_node->prev;
new_gpd = cur_node->gpd;
}
@@ -85,7 +85,7 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name)
else if (step == -1) {
//printf("\t\tGP - redo step\n");
if (cur_node->next) {
- if (!name || strcmp(cur_node->name, name) == 0) {
+ if (!name || STREQ(cur_node->name, name)) {
cur_node = cur_node->next;
new_gpd = cur_node->gpd;
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 4a913c3d2e5..289cbc568d2 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -90,6 +90,42 @@ bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]),
/* ******************************************************** */
+/* Check whether given stroke can be edited given the supplied context */
+// XXX: do we need additional flags for screenspace vs dataspace?
+bool ED_gpencil_stroke_can_use_direct(const ScrArea *sa, const bGPDstroke *gps)
+{
+ /* sanity check */
+ if (ELEM(NULL, sa, gps))
+ return false;
+
+ /* filter stroke types by flags + spacetype */
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ /* 3D strokes - only in 3D view */
+ return (sa->spacetype == SPACE_VIEW3D);
+ }
+ else if (gps->flag & GP_STROKE_2DIMAGE) {
+ /* Special "image" strokes - only in Image Editor */
+ return (sa->spacetype == SPACE_IMAGE);
+ }
+ else if (gps->flag & GP_STROKE_2DSPACE) {
+ /* 2D strokes (dataspace) - for any 2D view (i.e. everything other than 3D view) */
+ return (sa->spacetype != SPACE_VIEW3D);
+ }
+ else {
+ /* view aligned - anything goes */
+ return true;
+ }
+}
+
+/* Check whether given stroke can be edited in the current context */
+bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ return ED_gpencil_stroke_can_use_direct(sa, gps);
+}
+
+/* ******************************************************** */
+
/* Init handling for space-conversion function (from passed-in parameters) */
void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
{
@@ -127,7 +163,9 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
}
-/* Convert Grease Pencil points to screen-space values */
+/* Convert Grease Pencil points to screen-space values
+ * WARNING: This assumes that the caller has already checked whether the stroke in question can be drawn
+ */
void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
int *r_x, int *r_y)
{
@@ -135,7 +173,12 @@ void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
View2D *v2d = gsc->v2d;
rctf *subrect = gsc->subrect;
int xyval[2];
-
+
+ /* sanity checks */
+ BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D));
+ BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D));
+
+
if (gps->flag & GP_STROKE_3DSPACE) {
if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
*r_x = xyval[0];
@@ -152,11 +195,13 @@ void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], r_x, r_y);
}
else {
- if (subrect == NULL) { /* normal 3D view */
+ if (subrect == NULL) {
+ /* normal 3D view (or view space) */
*r_x = (int)(pt->x / 100 * ar->winx);
*r_y = (int)(pt->y / 100 * ar->winy);
}
- else { /* camera view, use subrect */
+ else {
+ /* camera view, use subrect */
*r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin;
*r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin;
}
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index b06af01bab6..3b7d7bac44f 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -35,10 +35,6 @@
#include "GPU_glew.h"
-/* hacking pointsize and linewidth */
-#define glPointSize(f) glPointSize(U.pixelsize * (f))
-#define glLineWidth(f) glLineWidth(U.pixelsize * (f))
-
/*
* these should be phased out. cpack should be replaced in
* code with calls to glColor3ub. - zr
@@ -51,7 +47,6 @@
* */
void cpack(unsigned int x);
-
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
# define glMultMatrixf(x) \
glMultMatrixf(_Generic((x), \
@@ -71,9 +66,14 @@ void cpack(unsigned int x);
float (*)[4]: (float *)(x), \
float [4][4]: (float *)(x)) \
)
+/* hacking pointsize and linewidth */
+#define glPointSize(f) glPointSize(U.pixelsize * _Generic((f), double: (float)(f), default: (f)))
+#define glLineWidth(f) glLineWidth(U.pixelsize * _Generic((f), double: (float)(f), default: (f)))
#else
# define glMultMatrixf(x) glMultMatrixf((float *)(x))
# define glLoadMatrixf(x) glLoadMatrixf((float *)(x))
+#define glPointSize(f) glPointSize(U.pixelsize * (f))
+#define glLineWidth(f) glLineWidth(U.pixelsize * (f))
#endif
#define GLA_PIXEL_OFS 0.375f
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index b0d1be1bf5d..c4f08ca4775 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -43,6 +43,7 @@ struct Object;
struct bGPdata;
struct bGPDlayer;
struct bGPDframe;
+struct bGPDstroke;
struct PointerRNA;
struct ImBuf;
struct wmKeyConfig;
@@ -80,6 +81,11 @@ struct bGPdata *ED_gpencil_data_get_active_direct(struct ID *screen_id, struct S
/* 3D View */
struct bGPdata *ED_gpencil_data_get_active_v3d(struct Scene *scene, struct View3D *v3d);
+/* ----------- Stroke Editing Utilities ---------------- */
+
+bool ED_gpencil_stroke_can_use_direct(const struct ScrArea *sa, const struct bGPDstroke *gps);
+bool ED_gpencil_stroke_can_use(const struct bContext *C, const struct bGPDstroke *gps);
+
/* ----------- Grease Pencil Operators ----------------- */
void ED_keymap_gpencil(struct wmKeyConfig *keyconf);
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index 1188ecd0aa5..704876e1261 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -35,6 +35,7 @@ struct Main;
struct bContext;
struct Image;
struct ImageUser;
+struct ImBuf;
struct ToolSettings;
struct uiBlock;
struct wmWindowManager;
@@ -58,6 +59,8 @@ void ED_space_image_get_aspect(struct SpaceImage *sima, float *aspx, float *aspy
void ED_space_image_get_zoom(struct SpaceImage *sima, struct ARegion *ar, float *zoomx, float *zoomy);
void ED_space_image_get_uv_aspect(struct SpaceImage *sima, float *aspx, float *aspy);
+void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *sima, struct ImBuf *ibuf, bool use_view_settings);
+
void ED_space_image_paint_update(struct wmWindowManager *wm, struct ToolSettings *settings);
void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct ToolSettings *settings);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 900da3ee07c..ccdde39f263 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -141,9 +141,9 @@ bool ED_object_editmode_load(struct Object *obedit);
void ED_object_location_from_view(struct bContext *C, float loc[3]);
void ED_object_rotation_from_view(struct bContext *C, float rot[3], const char align_axis);
void ED_object_base_init_transform(struct bContext *C, struct Base *base, const float loc[3], const float rot[3]);
-float ED_object_new_primitive_matrix(struct bContext *C, struct Object *editob,
- const float loc[3], const float rot[3], float primmat[4][4],
- bool apply_diameter);
+float ED_object_new_primitive_matrix(
+ struct bContext *C, struct Object *editob,
+ const float loc[3], const float rot[3], float primmat[4][4]);
void ED_object_add_unit_props(struct wmOperatorType *ot);
void ED_object_add_generic_props(struct wmOperatorType *ot, bool do_editmode);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index b790c656b61..8c33395cc49 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -107,7 +107,7 @@ void ED_screen_set_subwinactive(struct bContext *C, struct wmEvent *event);
void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen);
void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable);
void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh);
-void ED_screen_retore_temp_type(struct bContext *C, ScrArea *sa, bool is_screen_change);
+void ED_screen_restore_temp_type(struct bContext *C, ScrArea *sa);
ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type);
void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa);
void ED_screen_full_restore(struct bContext *C, ScrArea *sa);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 76ad4ba7bdb..b62d9960117 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -310,7 +310,6 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D
bool draw_background, int alpha_mode, char err_out[256]);
struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype,
bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, char err_out[256]);
-void ED_view3d_offscreen_sky_color_get(struct Scene *scene, float sky_color[3]);
struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip);
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index fa349c4f006..bfb7a3420c9 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -54,7 +54,7 @@ DEF_ICON(DOT)
DEF_ICON(COLLAPSEMENU)
DEF_ICON(X)
#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK005)
+ DEF_ICON(BLANK005) /* XXX 'DOWNARROW' icon! */
#endif
DEF_ICON(GO_LEFT)
DEF_ICON(PLUG)
@@ -461,9 +461,9 @@ DEF_ICON(FORCE_SMOKEFLOW)
DEF_ICON(BLANK685)
/* EMPTY */
- DEF_ICON(BLANK690)
- DEF_ICON(BLANK691)
- DEF_ICON(BLANK692)
+ DEF_ICON(BLANK690) /* XXX 'Temperature' icon! */
+ DEF_ICON(BLANK691) /* XXX 'Temperature' icon! */
+ DEF_ICON(BLANK692) /* XXX 'Gear' icon! */
DEF_ICON(BLANK693)
DEF_ICON(BLANK694)
DEF_ICON(BLANK695)
@@ -590,8 +590,8 @@ DEF_ICON(MOD_SKIN)
DEF_ICON(MOD_TRIANGULATE)
DEF_ICON(MOD_WIREFRAME)
DEF_ICON(MOD_DATA_TRANSFER)
+DEF_ICON(MOD_NORMALEDIT)
#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK168)
DEF_ICON(BLANK169)
DEF_ICON(BLANK170)
DEF_ICON(BLANK171)
@@ -689,7 +689,7 @@ DEF_ICON(RNDCURVE)
DEF_ICON(PROP_OFF)
DEF_ICON(PROP_ON)
DEF_ICON(PROP_CON)
-DEF_ICON(SCULPT_DYNTOPO)
+DEF_ICON(SCULPT_DYNTOPO) /* XXX Empty icon! */
DEF_ICON(PARTICLE_POINT)
DEF_ICON(PARTICLE_TIP)
DEF_ICON(PARTICLE_PATH)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 8789e837f17..590ab1d694d 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -316,6 +316,10 @@ void UI_draw_roundbox_shade_x(int mode, float minx, float miny, float maxx, floa
void UI_draw_roundbox_shade_y(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeLeft, float shadeRight);
void UI_draw_text_underline(int pos_x, int pos_y, int len, int height);
+void UI_draw_safe_areas(
+ float x1, float x2, float y1, float y2,
+ const float title_aspect[2], const float action_aspect[2]);
+
/* state for scrolldrawing */
#define UI_SCROLL_PRESSED (1 << 0)
#define UI_SCROLL_ARROWS (1 << 1)
@@ -888,6 +892,7 @@ void uiTemplateGameStates(uiLayout *layout, struct PointerRNA *ptr, const char *
void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr, int compact);
void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr, int color_management);
void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser);
+void uiTemplateImageInfo(uiLayout *layout, struct bContext *C, Image *ima, ImageUser *iuser);
void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C);
void UI_but_func_operator_search(uiBut *but);
void uiTemplateOperatorSearch(uiLayout *layout);
@@ -970,15 +975,20 @@ void UI_context_active_but_prop_get_filebrowser(const struct bContext *C, struct
void UI_context_active_but_prop_get_templateID(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop);
/* Styled text draw */
-void UI_fontstyle_set(struct uiFontStyle *fs);
+void UI_fontstyle_set(const struct uiFontStyle *fs);
void UI_fontstyle_draw_ex(
- struct uiFontStyle *fs, const struct rcti *rect, const char *str,
+ const struct uiFontStyle *fs, const struct rcti *rect, const char *str,
size_t len, float *r_xofs, float *r_yofs);
-void UI_fontstyle_draw(struct uiFontStyle *fs, const struct rcti *rect, const char *str);
-void UI_fontstyle_draw_rotated(struct uiFontStyle *fs, const struct rcti *rect, const char *str);
+void UI_fontstyle_draw(const struct uiFontStyle *fs, const struct rcti *rect, const char *str);
+void UI_fontstyle_draw_rotated(const struct uiFontStyle *fs, const struct rcti *rect, const char *str);
+void UI_fontstyle_draw_simple(const struct uiFontStyle *fs, float x, float y, const char *str);
+void UI_fontstyle_draw_simple_backdrop(
+ const uiFontStyle *fs, float x, float y, const char *str,
+ const unsigned char fg[4], const unsigned char bg[4]);
+
+int UI_fontstyle_string_width(const struct uiFontStyle *fs, const char *str);
+int UI_fontstyle_height_max(const struct uiFontStyle *fs);
-int UI_fontstyle_string_width(const char *str); // XXX temp
-void UI_draw_string(float x, float y, const char *str); // XXX temp
void UI_draw_icon_tri(float x, float y, char dir);
uiStyle *UI_style_get(void); /* use for fonts etc */
@@ -1009,6 +1019,9 @@ void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p);
/* Float precision helpers */
#define UI_PRECISION_FLOAT_MAX 7
+/* Typical UI text */
+#define UI_FSTYLE_WIDGET (const uiFontStyle *)&(UI_style_get()->widget)
+
int UI_calc_float_precision(int prec, double value);
#endif /* __UI_INTERFACE_H__ */
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index d289e90c257..4a6d9911d3b 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -293,6 +293,8 @@ enum {
TH_INFO_DEBUG,
TH_INFO_DEBUG_TEXT,
TH_VIEW_OVERLAY,
+
+ TH_V3D_CLIPPING_BORDER
};
/* XXX WARNING: previous is saved in file, so do not change order! */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 0b1d1c8c30c..8fa604d57cb 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -297,7 +297,7 @@ void ui_block_bounds_calc(uiBlock *block)
/* hardcoded exception... but that one is annoying with larger safety */
bt = block->buttons.first;
- if (bt && strncmp(bt->str, "ERROR", 5) == 0) xof = 10;
+ if (bt && STREQLEN(bt->str, "ERROR", 5)) xof = 10;
else xof = 40;
block->safety.xmin = block->rect.xmin - xof;
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index bcd9b9a5547..e03ea5efba4 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -450,6 +450,51 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
#endif
}
+/**
+ * Draw title and text safe areas.
+ *
+ * The first 4 parameters are the offsets for the view, not the zones.
+ */
+void UI_draw_safe_areas(
+ float x1, float x2, float y1, float y2,
+ const float title_aspect[2], const float action_aspect[2])
+{
+ const float size_x_half = (x2 - x1) * 0.5f;
+ const float size_y_half = (y2 - y1) * 0.5f;
+
+ const float *safe_areas[] = {title_aspect, action_aspect};
+ int i, safe_len = ARRAY_SIZE(safe_areas);
+ bool is_first = true;
+
+ for (i = 0; i < safe_len; i++) {
+ if (safe_areas[i][0] || safe_areas[i][1]) {
+ float margin_x, margin_y;
+ float minx, miny, maxx, maxy;
+
+ if (is_first) {
+ UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
+ is_first = false;
+ }
+
+ margin_x = safe_areas[i][0] * size_x_half;
+ margin_y = safe_areas[i][1] * size_y_half;
+
+ minx = x1 + margin_x;
+ miny = y1 + margin_y;
+ maxx = x2 - margin_x;
+ maxy = y2 - margin_y;
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(maxx, miny);
+ glVertex2f(maxx, maxy);
+ glVertex2f(minx, maxy);
+ glVertex2f(minx, miny);
+ glEnd();
+ }
+ }
+}
+
+
static void draw_scope_end(const rctf *rect, GLint *scissor)
{
/* restore scissortest */
@@ -494,7 +539,7 @@ static void histogram_draw_one(float r, float g, float b, float alpha,
glColor4f(r, g, b, alpha);
glShadeModel(GL_FLAT);
- glBegin(GL_QUAD_STRIP);
+ glBegin(GL_TRIANGLE_STRIP);
glVertex2f(x, y);
glVertex2f(x, y + (data[0] * h));
for (i = 1; i < res; i++) {
@@ -777,8 +822,8 @@ static void vectorscope_draw_target(float centerx, float centery, float diam, co
if (u > 0 && v >= 0) tangle = atanf(v / u);
else if (u > 0 && v < 0) tangle = atanf(v / u) + 2.0f * (float)M_PI;
else if (u < 0) tangle = atanf(v / u) + (float)M_PI;
- else if (u == 0 && v > 0.0f) tangle = (float)M_PI / 2.0f;
- else if (u == 0 && v < 0.0f) tangle = -(float)M_PI / 2.0f;
+ else if (u == 0 && v > 0.0f) tangle = M_PI_2;
+ else if (u == 0 && v < 0.0f) tangle = -M_PI_2;
tampli = sqrtf(u * u + v * v);
/* small target vary by 2.5 degree and 2.5 IRE unit */
@@ -1102,7 +1147,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
v1[1] = y1 + sizey_solid;
v2[1] = rect->ymax;
- glBegin(GL_QUAD_STRIP);
+ glBegin(GL_TRIANGLE_STRIP);
for (a = 0; a <= sizex; a++) {
pos = ((float)a) / sizex;
do_colorband(coba, pos, colf);
@@ -1121,7 +1166,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
v1[1] = y1;
v2[1] = y1 + sizey_solid;
- glBegin(GL_QUAD_STRIP);
+ glBegin(GL_TRIANGLE_STRIP);
for (a = 0; a <= sizex; a++) {
pos = ((float)a) / sizex;
do_colorband(coba, pos, colf);
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index d7a4720d595..f5b24f49f98 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -73,10 +73,13 @@
static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, const char *name)
{
- int width;
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
wmWindow *win = CTX_wm_window(C);
int x = win->eventstate->x;
int y = win->eventstate->y;
+ const unsigned char fg[4] = {255, 255, 255, 255};
+ const unsigned char bg[4] = {0, 0, 0, 50};
+
if ((name[0] == '\0') ||
(BLI_rcti_isect_pt(&ar->winrct, x, y) == false))
@@ -84,19 +87,12 @@ static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, c
return;
}
- width = UI_fontstyle_string_width(name);
x = x - ar->winrct.xmin;
y = y - ar->winrct.ymin;
- y += 20;
-
- glColor4ub(0, 0, 0, 50);
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL | UI_RB_ALPHA);
- UI_draw_roundbox(x, y, x + width + 8, y + 15, 4);
+ y += U.widget_unit;
- glColor4ub(255, 255, 255, 255);
- UI_draw_string(x + 4, y + 4, name);
+ UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, fg, bg);
}
/** \} */
@@ -176,43 +172,42 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int
/* we could use some clever */
wmWindow *win = CTX_wm_window(C);
- ScrArea *sa;
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) {
- if (sa->spacetype == SPACE_IMAGE) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- SpaceImage *sima = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
-
- if (ED_space_image_color_sample(CTX_data_scene(C), sima, ar, mval, r_col)) {
- return;
- }
+ ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my);
+
+ if (sa) {
+ if (sa->spacetype == SPACE_IMAGE) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ SpaceImage *sima = sa->spacedata.first;
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+
+ if (ED_space_image_color_sample(CTX_data_scene(C), sima, ar, mval, r_col)) {
+ return;
}
}
- else if (sa->spacetype == SPACE_NODE) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- SpaceNode *snode = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
-
- if (ED_space_node_color_sample(CTX_data_scene(C), snode, ar, mval, r_col)) {
- return;
- }
+ }
+ else if (sa->spacetype == SPACE_NODE) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ SpaceNode *snode = sa->spacedata.first;
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+
+ if (ED_space_node_color_sample(CTX_data_scene(C), snode, ar, mval, r_col)) {
+ return;
}
}
- else if (sa->spacetype == SPACE_CLIP) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- SpaceClip *sc = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
-
- if (ED_space_clip_color_sample(CTX_data_scene(C), sc, ar, mval, r_col)) {
- return;
- }
+ }
+ else if (sa->spacetype == SPACE_CLIP) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ SpaceClip *sc = sa->spacedata.first;
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+
+ if (ED_space_clip_color_sample(CTX_data_scene(C), sc, ar, mval, r_col)) {
+ return;
}
}
}
@@ -477,53 +472,49 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int
/* we could use some clever */
wmWindow *win = CTX_wm_window(C);
- ScrArea *sa;
+ ScrArea *sa = BKE_screen_find_area_xy(win->screen, -1, mx, my);
ScrArea *area_prev = CTX_wm_area(C);
ARegion *ar_prev = CTX_wm_region(C);
ddr->name[0] = '\0';
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) {
- if (sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- const int mval[2] = {
- mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
- Base *base;
-
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
-
- /* grr, always draw else we leave stale text */
- ED_region_tag_redraw(ar);
-
- base = ED_view3d_give_base_under_cursor(C, mval);
- if (base) {
- Object *ob = base->object;
- ID *id = NULL;
- if (ddr->idcode == ID_OB) {
- id = (ID *)ob;
- }
- else if (ob->data) {
- if (GS(((ID *)ob->data)->name) == ddr->idcode) {
- id = (ID *)ob->data;
- }
- else {
- BLI_snprintf(ddr->name, sizeof(ddr->name), "Incompatible, expected a %s",
- ddr->idcode_name);
- }
+ if (sa) {
+ if (sa->spacetype == SPACE_VIEW3D) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ const int mval[2] = {
+ mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+ Base *base;
+
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+
+ /* grr, always draw else we leave stale text */
+ ED_region_tag_redraw(ar);
+
+ base = ED_view3d_give_base_under_cursor(C, mval);
+ if (base) {
+ Object *ob = base->object;
+ ID *id = NULL;
+ if (ddr->idcode == ID_OB) {
+ id = (ID *)ob;
+ }
+ else if (ob->data) {
+ if (GS(((ID *)ob->data)->name) == ddr->idcode) {
+ id = (ID *)ob->data;
}
-
- if (id) {
- BLI_snprintf(ddr->name, sizeof(ddr->name), "%s: %s",
- ddr->idcode_name, id->name + 2);
- *r_id = id;
+ else {
+ BLI_snprintf(ddr->name, sizeof(ddr->name), "Incompatible, expected a %s",
+ ddr->idcode_name);
}
+ }
- break;
+ if (id) {
+ BLI_snprintf(ddr->name, sizeof(ddr->name), "%s: %s",
+ ddr->idcode_name, id->name + 2);
+ *r_id = id;
}
}
}
@@ -760,7 +751,7 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx,
/* we could use some clever */
wmWindow *win = CTX_wm_window(C);
- ScrArea *sa;
+ ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my);
Scene *scene = win->screen->scene;
UnitSettings *unit = &scene->unit;
const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
@@ -770,47 +761,44 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx,
ddr->name[0] = '\0';
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) {
- if (sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- View3D *v3d = sa->spacedata.first;
- RegionView3D *rv3d = ar->regiondata;
- /* 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 - ar->winrct.xmin,
- my - ar->winrct.ymin};
- float co[3];
-
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
-
- /* grr, always draw else we leave stale text */
- ED_region_tag_redraw(ar);
-
- view3d_operator_needs_opengl(C);
-
- if (ED_view3d_autodist(scene, ar, v3d, mval, co, true, NULL)) {
- const float mval_center_fl[2] = {
- (float)ar->winx / 2,
- (float)ar->winy / 2};
- float co_align[3];
-
- /* quick way to get view-center aligned point */
- ED_view3d_win_to_3d(ar, co, mval_center_fl, co_align);
-
- *r_depth = len_v3v3(view_co, co_align);
-
- bUnit_AsString(ddr->name, sizeof(ddr->name),
- (double)*r_depth,
- 4, unit->system, B_UNIT_LENGTH, do_split, false);
- }
- else {
- BLI_strncpy(ddr->name, "Nothing under cursor", sizeof(ddr->name));
- }
- break;
+ if (sa) {
+ if (sa->spacetype == SPACE_VIEW3D) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ View3D *v3d = sa->spacedata.first;
+ RegionView3D *rv3d = ar->regiondata;
+ /* 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 - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+ float co[3];
+
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+
+ /* grr, always draw else we leave stale text */
+ ED_region_tag_redraw(ar);
+
+ view3d_operator_needs_opengl(C);
+
+ if (ED_view3d_autodist(scene, ar, v3d, mval, co, true, NULL)) {
+ const float mval_center_fl[2] = {
+ (float)ar->winx / 2,
+ (float)ar->winy / 2};
+ float co_align[3];
+
+ /* quick way to get view-center aligned point */
+ ED_view3d_win_to_3d(ar, co, mval_center_fl, co_align);
+
+ *r_depth = len_v3v3(view_co, co_align);
+
+ bUnit_AsString(ddr->name, sizeof(ddr->name),
+ (double)*r_depth,
+ 4, unit->system, B_UNIT_LENGTH, do_split, false);
+ }
+ else {
+ BLI_strncpy(ddr->name, "Nothing under cursor", sizeof(ddr->name));
}
}
}
@@ -830,8 +818,10 @@ static void depthdropper_depth_set(bContext *C, DepthDropper *ddr, const float d
/* set sample from accumulated values */
static void depthdropper_depth_set_accum(bContext *C, DepthDropper *ddr)
{
- float depth;
- depth = ddr->accum_depth * 1.0f / (float)ddr->accum_tot;
+ float depth = ddr->accum_depth;
+ if (ddr->accum_tot) {
+ depth /= (float)ddr->accum_tot;
+ }
depthdropper_depth_set(C, ddr, depth);
}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 98b065dabcf..96973194576 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -114,6 +114,7 @@
static void ui_but_smart_controller_add(bContext *C, uiBut *from, uiBut *to);
static void ui_but_link_add(bContext *C, uiBut *from, uiBut *to);
static int ui_do_but_EXIT(bContext *C, uiBut *but, struct uiHandleButtonData *data, const wmEvent *event);
+static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but_b);
#ifdef USE_KEYNAV_LIMIT
static void ui_mouse_motion_keynav_init(struct uiKeyNavLock *keynav, const wmEvent *event);
@@ -355,6 +356,12 @@ static enum eSnapType ui_event_to_snap(const wmEvent *event)
return (event->ctrl) ? (event->shift) ? SNAP_ON_SMALL : SNAP_ON : SNAP_OFF;
}
+static bool ui_event_is_snap(const wmEvent *event)
+{
+ return (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY) ||
+ ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY));
+}
+
static void ui_color_snap_hue(const enum eSnapType snap, float *r_hue)
{
const float snap_increment = (snap == SNAP_ON_SMALL) ? 24 : 12;
@@ -2749,7 +2756,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
case VKEY:
case XKEY:
case CKEY:
- if (event->ctrl || event->oskey) {
+ if (IS_EVENT_MOD(event, ctrl, oskey)) {
if (event->type == VKEY)
changed = ui_textedit_copypaste(but, data, UI_TEXTEDIT_PASTE);
else if (event->type == CKEY)
@@ -2822,10 +2829,10 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
/* Ctrl + A: Select all */
#if defined(__APPLE__)
/* OSX uses cmd-a systemwide, so add it */
- if ((event->oskey && !(event->alt || event->shift || event->ctrl)) ||
- (event->ctrl && !(event->alt || event->shift || event->oskey)))
+ if ((event->oskey && !IS_EVENT_MOD(event, shift, alt, ctrl)) ||
+ (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey)))
#else
- if (event->ctrl && !(event->alt || event->shift || event->oskey))
+ if (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey))
#endif
{
ui_textedit_move(but, data, STRCUR_DIR_PREV,
@@ -2848,7 +2855,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
update = true; /* do live update for tab key */
}
/* the hotkey here is not well defined, was G.qual so we check all */
- else if (event->shift || event->ctrl || event->alt || event->oskey) {
+ else if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
ui_textedit_prev_but(block, but, data);
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
@@ -3342,6 +3349,38 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_BREAK;
}
+ else if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
+ /* Support alt+wheel on expanded enum rows */
+ if (but->type == UI_BTYPE_ROW) {
+ const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1;
+ uiBut *but_select = ui_but_find_select_in_enum(but, direction);
+ if (but_select) {
+ uiBut *but_other = (direction == -1) ? but_select->next : but_select->prev;
+ if (but_other && ui_but_find_select_in_enum__cmp(but, but_other)) {
+ ARegion *ar = data->region;
+
+ data->cancel = true;
+ button_activate_exit(C, but, data, false, false);
+
+ /* Activate the text button. */
+ button_activate_init(C, ar, but_other, BUTTON_ACTIVATE_OVER);
+ data = but_other->active;
+ if (data) {
+ ui_apply_but(C, but->block, but_other, but_other->active, true);
+ button_activate_exit(C, but_other, data, false, false);
+
+ /* restore active button */
+ button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ }
+ else {
+ /* shouldn't happen */
+ BLI_assert(0);
+ }
+ }
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
}
return WM_UI_HANDLER_CONTINUE;
}
@@ -3706,7 +3745,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
click = 1;
}
}
- else if (event->type == MOUSEMOVE) {
+ else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
const enum eSnapType snap = ui_event_to_snap(event);
float fac;
@@ -4003,7 +4042,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
click = 1;
}
}
- else if (event->type == MOUSEMOVE) {
+ else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
#ifdef USE_DRAG_MULTINUM
data->multi_data.drag_dir[0] += abs(data->draglastx - mx);
data->multi_data.drag_dir[1] += abs(data->draglasty - my);
@@ -4542,8 +4581,8 @@ static int ui_do_but_UNITVEC(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
}
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
- if (event->type == MOUSEMOVE) {
- if (mx != data->draglastx || my != data->draglasty) {
+ if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
const enum eSnapType snap = ui_event_to_snap(event);
if (ui_numedit_but_UNITVEC(but, data, mx, my, snap))
ui_numedit_apply(C, block, but, data);
@@ -4862,8 +4901,8 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
}
- else if (event->type == MOUSEMOVE) {
- if (mx != data->draglastx || my != data->draglasty) {
+ else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
const enum eSnapType snap = ui_event_to_snap(event);
if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->shift != 0))
@@ -5134,8 +5173,8 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle
ui_but_hsv_set(but); /* converts to rgb */
ui_numedit_apply(C, block, but, data);
}
- else if (event->type == MOUSEMOVE) {
- if (mx != data->draglastx || my != data->draglasty) {
+ else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
const enum eSnapType snap = ui_event_to_snap(event);
if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->shift != 0)) {
@@ -6254,7 +6293,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
if ((data->state == BUTTON_STATE_HIGHLIGHT) || (event->type == EVT_DROP)) {
/* handle copy-paste */
- if (ELEM(event->type, CKEY, VKEY) && event->val == KM_PRESS && (event->ctrl || event->oskey)) {
+ if (ELEM(event->type, CKEY, VKEY) && event->val == KM_PRESS &&
+ IS_EVENT_MOD(event, ctrl, oskey))
+ {
/* Specific handling for listrows, we try to find their overlapping tex button. */
if (but->type == UI_BTYPE_LISTROW) {
uiBut *labelbut = ui_but_list_row_text_activate(C, but, data, event, BUTTON_ACTIVATE_OVER);
@@ -6273,7 +6314,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
/* handle eyedropper */
else if ((event->type == EKEY) && (event->val == KM_PRESS)) {
- if (event->alt || event->shift || event->ctrl || event->oskey) {
+ if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
/* pass */
}
else {
@@ -6305,7 +6346,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
/* handle keyframing */
else if ((event->type == IKEY) &&
- !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey) &&
+ !IS_EVENT_MOD(event, ctrl, oskey) &&
(event->val == KM_PRESS))
{
if (event->alt) {
@@ -6326,7 +6367,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
/* handle drivers */
else if ((event->type == DKEY) &&
- !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
+ !IS_EVENT_MOD(event, shift, ctrl, oskey) &&
(event->val == KM_PRESS))
{
if (event->alt)
@@ -6340,7 +6381,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
/* handle keyingsets */
else if ((event->type == KKEY) &&
- !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
+ !IS_EVENT_MOD(event, shift, ctrl, oskey) &&
(event->val == KM_PRESS))
{
if (event->alt)
@@ -6353,7 +6394,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
return WM_UI_HANDLER_BREAK;
}
/* handle menu */
- else if (event->type == RIGHTMOUSE && event->val == KM_PRESS) {
+ else if ((event->type == RIGHTMOUSE) &&
+ !IS_EVENT_MOD(event, shift, ctrl, alt, oskey) &&
+ (event->val == KM_PRESS))
+ {
/* RMB has two options now */
if (ui_but_menu(C, but)) {
return WM_UI_HANDLER_BREAK;
@@ -6591,6 +6635,45 @@ static bool ui_but_isect_pie_seg(uiBlock *block, uiBut *but)
return false;
}
+static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but_b)
+{
+ return ((but_a->type == but_b->type) &&
+ (but_a->alignnr == but_b->alignnr) &&
+ (but_a->poin == but_b->poin) &&
+ (but_a->rnapoin.type == but_b->rnapoin.type) &&
+ (but_a->rnaprop == but_b->rnaprop));
+}
+
+/**
+ * Finds the pressed button in an aligned row (typically an expanded enum).
+ *
+ * \param direction Use when there may be multiple buttons pressed.
+ */
+uiBut *ui_but_find_select_in_enum(uiBut *but, int direction)
+{
+ uiBut *but_iter = but;
+ uiBut *but_found = NULL;
+ BLI_assert(ELEM(direction, -1, 1));
+
+ while ((but_iter->prev) &&
+ ui_but_find_select_in_enum__cmp(but_iter->prev, but))
+ {
+ but_iter = but_iter->prev;
+ }
+
+ while (but_iter && ui_but_find_select_in_enum__cmp(but_iter, but)) {
+ if (but_iter->flag & UI_SELECT) {
+ but_found = but_iter;
+ if (direction == 1) {
+ break;
+ }
+ }
+ but_iter = but_iter->next;
+ }
+
+ return but_found;
+}
+
uiBut *ui_but_find_active_in_region(ARegion *ar)
{
uiBlock *block;
@@ -8301,7 +8384,7 @@ static int ui_handle_menu_event(
case WHEELDOWNMOUSE:
case MOUSEPAN:
/* arrowkeys: only handle for block_loop blocks */
- if (event->alt || event->shift || event->ctrl || event->oskey) {
+ if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
/* pass */
}
else if (inside || (block->flag & UI_BLOCK_LOOP)) {
@@ -8446,9 +8529,7 @@ static int ui_handle_menu_event(
case ZKEY:
{
if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) &&
- (event->shift == 0) &&
- (event->ctrl == 0) &&
- (event->oskey == 0))
+ !IS_EVENT_MOD(event, shift, ctrl, oskey))
{
if (ui_menu_pass_event_to_parent_if_nonactive(menu, but, level, retval))
break;
@@ -8825,7 +8906,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
block->pie_data.duration_gesture = duration;
}
- if (len_sq < 1.0) {
+ if (len_sq < 1.0f) {
uiBut *but = ui_but_find_active_in_region(menu->region);
if (but) {
@@ -8940,9 +9021,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
case ZKEY:
{
if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) &&
- (event->shift == 0) &&
- (event->ctrl == 0) &&
- (event->oskey == 0))
+ !IS_EVENT_MOD(event, shift, ctrl, oskey))
{
for (but = block->buttons.first; but; but = but->next) {
if (but->menu_key == event->type) {
@@ -9123,13 +9202,13 @@ static void ui_region_handler_remove(bContext *C, void *UNUSED(userdata))
ui_apply_but_funcs_after(C);
}
+/* handle buttons at the window level, modal, for example while
+ * number sliding, text editing, or when a menu block is open */
static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSED(userdata))
{
ARegion *ar;
uiBut *but;
- /* here we handle buttons at the window level, modal, for example
- * while number sliding, text editing, or when a menu block is open */
ar = CTX_wm_menu(C);
if (!ar)
ar = CTX_wm_region(C);
@@ -9137,13 +9216,32 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE
but = ui_but_find_active_in_region(ar);
if (but) {
+ bScreen *screen = CTX_wm_screen(C);
+ ARegion *ar_temp;
uiBut *but_other;
uiHandleButtonData *data;
+ bool is_inside_menu = false;
+
+ /* look for a popup menu containing the mouse */
+ for (ar_temp = screen->regionbase.first; ar_temp; ar_temp = ar_temp->next) {
+ rcti rect = ar_temp->winrct;
+
+ /* resize region rect to ignore shadow */
+ BLI_rcti_resize(&rect, (BLI_rcti_size_x(&ar_temp->winrct) - UI_ThemeMenuShadowWidth() * 2),
+ (BLI_rcti_size_y(&ar_temp->winrct) - UI_ThemeMenuShadowWidth() * 2));
+ if (BLI_rcti_isect_pt_v(&rect, &event->x)) {
+ BLI_assert(ar_temp->type->regionid == RGN_TYPE_TEMPORARY);
+
+ is_inside_menu = true;
+ break;
+ }
+ }
/* handle activated button events */
data = but->active;
if ((data->state == BUTTON_STATE_MENU_OPEN) &&
+ (is_inside_menu == false) && /* make sure mouse isn't inside another menu (see T43247) */
(but->type == UI_BTYPE_PULLDOWN) &&
(but_other = ui_but_find_mouse_over(ar, event)) &&
(but != but_other) &&
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 54ba3d784d1..458e268170f 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -616,6 +616,7 @@ extern void ui_but_active_free(const struct bContext *C, uiBut *but);
extern bool ui_but_is_active(struct ARegion *ar) ATTR_WARN_UNUSED_RESULT;
extern int ui_but_menu_direction(uiBut *but);
extern void ui_but_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, const bool restore);
+extern uiBut *ui_but_find_select_in_enum(uiBut *but, int direction);
extern uiBut *ui_but_find_active_in_region(struct ARegion *ar);
bool ui_but_is_editable(const uiBut *but);
bool ui_but_is_editable_as_text(const uiBut *but);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index f02c6a234a9..fb73b8ec34c 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -235,9 +235,10 @@ static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, bool
variable = (ui_layout_vary_direction(layout) == UI_ITEM_VARY_X);
if (variable) {
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
/* it may seem odd that the icon only adds (UI_UNIT_X / 4)
* but taking margins into account its fine */
- return (UI_fontstyle_string_width(name) +
+ return (UI_fontstyle_string_width(fstyle, name) +
(UI_UNIT_X * ((compact ? 1.25f : 1.50f) +
(icon ? 0.25f : 0.0f))));
}
@@ -639,7 +640,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n
if (name[0]) {
/* XXX UI_fontstyle_string_width is not accurate */
#if 0
- labelw = UI_fontstyle_string_width(name);
+ labelw = UI_fontstyle_string_width(fstyle, name);
CLAMP(labelw, w / 4, 3 * w / 4);
#endif
labelw = w / 3;
@@ -1003,7 +1004,7 @@ void uiItemEnumO_value(uiLayout *layout, const char *name, int icon, const char
PointerRNA ptr;
PropertyRNA *prop;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
WM_operator_properties_create_ptr(&ptr, ot);
@@ -1035,7 +1036,7 @@ void uiItemEnumO_string(uiLayout *layout, const char *name, int icon, const char
int value;
bool free;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
WM_operator_properties_create_ptr(&ptr, ot);
@@ -1074,7 +1075,7 @@ void uiItemBooleanO(uiLayout *layout, const char *name, int icon, const char *op
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
PointerRNA ptr;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
WM_operator_properties_create_ptr(&ptr, ot);
RNA_boolean_set(&ptr, propname, value);
@@ -1087,7 +1088,7 @@ void uiItemIntO(uiLayout *layout, const char *name, int icon, const char *opname
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
PointerRNA ptr;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
WM_operator_properties_create_ptr(&ptr, ot);
RNA_int_set(&ptr, propname, value);
@@ -1100,7 +1101,7 @@ void uiItemFloatO(uiLayout *layout, const char *name, int icon, const char *opna
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
PointerRNA ptr;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
WM_operator_properties_create_ptr(&ptr, ot);
RNA_float_set(&ptr, propname, value);
@@ -1113,7 +1114,7 @@ void uiItemStringO(uiLayout *layout, const char *name, int icon, const char *opn
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
PointerRNA ptr;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
WM_operator_properties_create_ptr(&ptr, ot);
RNA_string_set(&ptr, propname, value);
@@ -1877,7 +1878,7 @@ void uiItemMenuEnumO(uiLayout *layout, bContext *C, const char *opname, const ch
MenuItemLevel *lvl;
uiBut *but;
- UI_OPERATOR_ERROR_RET(ot, opname, return );
+ UI_OPERATOR_ERROR_RET(ot, opname, return);
if (!ot->srna) {
ui_item_disabled(layout, opname);
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 074faaa86bc..19e389154e4 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -515,7 +515,7 @@ static bool ui_editsource_uibut_match(uiBut *but_a, uiBut *but_b)
(but_a->rnaprop == but_b->rnaprop) &&
(but_a->optype == but_b->optype) &&
(but_a->unit_type == but_b->unit_type) &&
- (strncmp(but_a->drawstr, but_b->drawstr, UI_MAX_DRAW_STR) == 0))
+ STREQLEN(but_a->drawstr, but_b->drawstr, UI_MAX_DRAW_STR))
{
return true;
}
@@ -858,7 +858,7 @@ int UI_drop_color_poll(struct bContext *C, wmDrag *drag, const wmEvent *UNUSED(e
void UI_drop_color_copy(wmDrag *drag, wmDropBox *drop)
{
- uiDragColorHandle *drag_info = (uiDragColorHandle *)drag->poin;
+ uiDragColorHandle *drag_info = drag->poin;
RNA_float_set_array(drop->ptr, "color", drag_info->color);
RNA_boolean_set(drop->ptr, "gamma", drag_info->gamma_corrected);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index e68c86353a3..d165e2719c5 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -1490,7 +1490,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
}
BLF_enable(fontid, BLF_ROTATION);
- BLF_rotation(fontid, M_PI / 2);
+ BLF_rotation(fontid, M_PI_2);
//UI_fontstyle_set(&style->widget);
ui_fontscale(&fstyle_points, aspect / (U.pixelsize * 1.1f));
BLF_size(fontid, fstyle_points, U.dpi);
@@ -1757,7 +1757,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
/* XXX hardcoded key warning */
if ((inside || inside_header) && event->val == KM_PRESS) {
- if (event->type == AKEY && !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift, event->alt)) {
+ if (event->type == AKEY && ((event->ctrl + event->oskey + event->shift + event->alt) == 0)) {
if (pa->flag & PNL_CLOSEDY) {
if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my))
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 0ec59e4e4cd..b6a93c8306d 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -1919,7 +1919,7 @@ static void ui_update_color_picker_buts_rgb(uiBlock *block, ColorPicker *cpicker
ui_but_v3_set(bt, rgb);
}
- else if (strcmp(bt->str, "Hex: ") == 0) {
+ else if (STREQ(bt->str, "Hex: ")) {
float rgb_gamma[3];
unsigned char rgb_gamma_uchar[3];
double intpart;
@@ -2726,7 +2726,8 @@ static uiBlock *ui_block_func_PIE(bContext *UNUSED(C), uiPopupBlockHandle *handl
static float ui_pie_menu_title_width(const char *name, int icon)
{
- return (UI_fontstyle_string_width(name) +
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ return (UI_fontstyle_string_width(fstyle, name) +
(UI_UNIT_X * (1.50f + (icon ? 0.25f : 0.0f))));
}
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 8b2ce90dcf5..2f46c0906ae 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -45,6 +45,7 @@
#include "BKE_global.h"
+#include "BIF_gl.h"
#include "BLF_api.h"
#ifdef WITH_INTERNATIONAL
@@ -147,8 +148,9 @@ static uiFont *uifont_to_blfont(int id)
/* *************** draw ************************ */
-void UI_fontstyle_draw_ex(uiFontStyle *fs, const rcti *rect, const char *str,
- size_t len, float *r_xofs, float *r_yofs)
+void UI_fontstyle_draw_ex(
+ const uiFontStyle *fs, const rcti *rect, const char *str,
+ size_t len, float *r_xofs, float *r_yofs)
{
float height;
int xofs = 0, yofs;
@@ -194,15 +196,17 @@ void UI_fontstyle_draw_ex(uiFontStyle *fs, const rcti *rect, const char *str,
*r_yofs = yofs;
}
-void UI_fontstyle_draw(uiFontStyle *fs, const rcti *rect, const char *str)
+void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str)
{
float xofs, yofs;
- UI_fontstyle_draw_ex(fs, rect, str,
- BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs);
+
+ UI_fontstyle_draw_ex(
+ fs, rect, str,
+ BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs);
}
/* drawn same as above, but at 90 degree angle */
-void UI_fontstyle_draw_rotated(uiFontStyle *fs, const rcti *rect, const char *str)
+void UI_fontstyle_draw_rotated(const uiFontStyle *fs, const rcti *rect, const char *str)
{
float height;
int xofs, yofs;
@@ -220,7 +224,7 @@ void UI_fontstyle_draw_rotated(uiFontStyle *fs, const rcti *rect, const char *st
/* rotate counter-clockwise for now (assumes left-to-right language)*/
xofs += height;
yofs = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX) + 5;
- angle = (float)M_PI / 2.0f;
+ angle = M_PI_2;
/* translate rect to vertical */
txtrect.xmin = rect->xmin - BLI_rcti_size_y(rect);
@@ -255,6 +259,66 @@ void UI_fontstyle_draw_rotated(uiFontStyle *fs, const rcti *rect, const char *st
BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
}
+/**
+ * Similar to #UI_fontstyle_draw
+ * but ignore alignment, shadow & no clipping rect.
+ *
+ * For drawing on-screen labels.
+ */
+void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str)
+{
+ if (fs->kerning == 1)
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
+
+ UI_fontstyle_set(fs);
+ BLF_position(fs->uifont_id, x, y, 0.0f);
+ BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+
+ if (fs->kerning == 1)
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+}
+
+/**
+ * Same as #UI_fontstyle_draw but draw a colored backdrop.
+ */
+void UI_fontstyle_draw_simple_backdrop(
+ const uiFontStyle *fs, float x, float y, const char *str,
+ const unsigned char fg[4], const unsigned char bg[4])
+{
+ if (fs->kerning == 1)
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
+
+ UI_fontstyle_set(fs);
+
+ {
+ const float width = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ const float height = BLF_height_max(fs->uifont_id);
+ const float decent = BLF_descender(fs->uifont_id);
+ const float margin = height / 4.0f;
+
+ /* backdrop */
+ glColor4ubv(bg);
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL | UI_RB_ALPHA);
+ UI_draw_roundbox(
+ x - margin,
+ (y + decent) - margin,
+ x + width + margin,
+ (y + decent) + height + margin,
+ margin);
+
+ glColor4ubv(fg);
+ }
+
+
+ BLF_position(fs->uifont_id, x, y, 0.0f);
+ BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+
+ if (fs->kerning == 1)
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+}
+
+
/* ************** helpers ************************ */
/* XXX: read a style configure */
uiStyle *UI_style_get(void)
@@ -291,41 +355,29 @@ uiStyle *UI_style_get_dpi(void)
return &_style;
}
-/* temporarily, does widget font */
-int UI_fontstyle_string_width(const char *str)
+int UI_fontstyle_string_width(const uiFontStyle *fs, const char *str)
{
- uiStyle *style = UI_style_get();
- uiFontStyle *fstyle = &style->widget;
int width;
- if (fstyle->kerning == 1) /* for BLF_width */
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ if (fs->kerning == 1) /* for BLF_width */
+ BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
- UI_fontstyle_set(fstyle);
- width = BLF_width(fstyle->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ UI_fontstyle_set(fs);
+ width = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
- if (fstyle->kerning == 1)
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ if (fs->kerning == 1)
+ BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
return width;
}
-/* temporarily, does widget font */
-void UI_draw_string(float x, float y, const char *str)
+int UI_fontstyle_height_max(const uiFontStyle *fs)
{
- uiStyle *style = UI_style_get();
-
- if (style->widget.kerning == 1)
- BLF_enable(style->widget.uifont_id, BLF_KERNING_DEFAULT);
-
- UI_fontstyle_set(&style->widget);
- BLF_position(style->widget.uifont_id, x, y, 0.0f);
- BLF_draw(style->widget.uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
-
- if (style->widget.kerning == 1)
- BLF_disable(style->widget.uifont_id, BLF_KERNING_DEFAULT);
+ UI_fontstyle_set(fs);
+ return BLF_height_max(fs->uifont_id);
}
+
/* ************** init exit ************************ */
/* called on each startup.blend read */
@@ -398,11 +450,10 @@ void uiStyleInit(void)
if (font->blf_id == -1) {
font->blf_id = BLF_load_mem("default", (unsigned char *)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
}
- else {
- BLF_default_set(font->blf_id);
- }
}
+ BLF_default_set(font->blf_id);
+
if (font->blf_id == -1) {
if (G.debug & G_DEBUG)
printf("%s: error, no fonts available\n", __func__);
@@ -453,7 +504,7 @@ void uiStyleInit(void)
BLF_size(blf_mono_font_render, 12 * U.pixelsize, 72);
}
-void UI_fontstyle_set(uiFontStyle *fs)
+void UI_fontstyle_set(const uiFontStyle *fs)
{
uiFont *font = uifont_to_blfont(fs->uifont_id);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 407843d663c..5ac991cbd94 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -2862,7 +2862,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
/* validate arguments */
/* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */
- if (!strcmp(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) {
+ if (STREQ(UI_UL_DEFAULT_CLASS_NAME, listtype_name) && !(list_id && list_id[0])) {
RNA_warning("template_list using default '%s' UIList class must provide a custom list_id",
UI_UL_DEFAULT_CLASS_NAME);
return;
@@ -3570,8 +3570,7 @@ void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char
colorspace_settings_ptr = RNA_property_pointer_get(ptr, prop);
- uiItemL(layout, IFACE_("Input Color Space:"), ICON_NONE);
- uiItemR(layout, &colorspace_settings_ptr, "name", 0, "", ICON_NONE);
+ uiItemR(layout, &colorspace_settings_ptr, "name", 0, IFACE_("Color Space"), ICON_NONE);
}
void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr, const char *propname)
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 04a886ba2a8..9b22f8a1e7f 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -610,36 +610,36 @@ static void round_box_shade_col4_r(unsigned char r_col[4], const char col1[4], c
r_col[3] = (faci * col1[3] + facm * col2[3]) >> 8;
}
-static void widget_verts_to_quad_strip(uiWidgetBase *wtb, const int totvert, float quad_strip[WIDGET_SIZE_MAX * 2 + 2][2])
+static void widget_verts_to_triangle_strip(uiWidgetBase *wtb, const int totvert, float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2])
{
int a;
for (a = 0; a < totvert; a++) {
- copy_v2_v2(quad_strip[a * 2], wtb->outer_v[a]);
- copy_v2_v2(quad_strip[a * 2 + 1], wtb->inner_v[a]);
+ copy_v2_v2(triangle_strip[a * 2], wtb->outer_v[a]);
+ copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[a]);
}
- copy_v2_v2(quad_strip[a * 2], wtb->outer_v[0]);
- copy_v2_v2(quad_strip[a * 2 + 1], wtb->inner_v[0]);
+ copy_v2_v2(triangle_strip[a * 2], wtb->outer_v[0]);
+ copy_v2_v2(triangle_strip[a * 2 + 1], wtb->inner_v[0]);
}
-static void widget_verts_to_quad_strip_open(uiWidgetBase *wtb, const int totvert, float quad_strip[WIDGET_SIZE_MAX * 2][2])
+static void widget_verts_to_triangle_strip_open(uiWidgetBase *wtb, const int totvert, float triangle_strip[WIDGET_SIZE_MAX * 2][2])
{
int a;
for (a = 0; a < totvert; a++) {
- quad_strip[a * 2][0] = wtb->outer_v[a][0];
- quad_strip[a * 2][1] = wtb->outer_v[a][1];
- quad_strip[a * 2 + 1][0] = wtb->outer_v[a][0];
- quad_strip[a * 2 + 1][1] = wtb->outer_v[a][1] - 1.0f;
+ triangle_strip[a * 2][0] = wtb->outer_v[a][0];
+ triangle_strip[a * 2][1] = wtb->outer_v[a][1];
+ triangle_strip[a * 2 + 1][0] = wtb->outer_v[a][0];
+ triangle_strip[a * 2 + 1][1] = wtb->outer_v[a][1] - 1.0f;
}
}
static void widgetbase_outline(uiWidgetBase *wtb)
{
- float quad_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
- widget_verts_to_quad_strip(wtb, wtb->totvert, quad_strip);
+ float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
+ widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, quad_strip);
- glDrawArrays(GL_QUAD_STRIP, 0, wtb->totvert * 2 + 2);
+ glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2);
glDisableClientState(GL_VERTEX_ARRAY);
}
@@ -733,18 +733,18 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
/* for each AA step */
if (wtb->outline) {
- float quad_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
- float quad_strip_emboss[WIDGET_SIZE_MAX * 2][2]; /* only for emboss */
+ float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
+ float triangle_strip_emboss[WIDGET_SIZE_MAX * 2][2]; /* only for emboss */
const unsigned char tcol[4] = {wcol->outline[0],
wcol->outline[1],
wcol->outline[2],
wcol->outline[3] / WIDGET_AA_JITTER};
- widget_verts_to_quad_strip(wtb, wtb->totvert, quad_strip);
+ widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
if (wtb->emboss) {
- widget_verts_to_quad_strip_open(wtb, wtb->halfwayvert, quad_strip_emboss);
+ widget_verts_to_triangle_strip_open(wtb, wtb->halfwayvert, triangle_strip_emboss);
}
glEnableClientState(GL_VERTEX_ARRAY);
@@ -757,8 +757,8 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
/* outline */
glColor4ubv(tcol);
- glVertexPointer(2, GL_FLOAT, 0, quad_strip);
- glDrawArrays(GL_QUAD_STRIP, 0, wtb->totvert * 2 + 2);
+ glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2);
/* emboss bottom shadow */
if (wtb->emboss) {
@@ -766,8 +766,8 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
if (emboss[3]) {
glColor4ubv(emboss);
- glVertexPointer(2, GL_FLOAT, 0, quad_strip_emboss);
- glDrawArrays(GL_QUAD_STRIP, 0, wtb->halfwayvert * 2);
+ glVertexPointer(2, GL_FLOAT, 0, triangle_strip_emboss);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->halfwayvert * 2);
}
}
@@ -2098,7 +2098,7 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r
rcti rect1 = *rect;
float alphastep;
int step, totvert;
- float quad_strip[WIDGET_SIZE_MAX * 2 + 2][2];
+ float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2];
const float radout = UI_ThemeMenuShadowWidth();
/* disabled shadow */
@@ -2126,10 +2126,10 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r
glColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
- widget_verts_to_quad_strip(&wtb, totvert, quad_strip);
+ widget_verts_to_triangle_strip(&wtb, totvert, triangle_strip);
- glVertexPointer(2, GL_FLOAT, 0, quad_strip);
- glDrawArrays(GL_QUAD_STRIP, 0, totvert * 2); /* add + 2 for getting a complete soft rect. Now it skips top edge to allow transparent menus */
+ glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, totvert * 2); /* add + 2 for getting a complete soft rect. Now it skips top edge to allow transparent menus */
}
glDisableClientState(GL_VERTEX_ARRAY);
@@ -2210,7 +2210,7 @@ void ui_hsvcircle_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float
float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
float ang, radius_t;
- ang = 2.0f * (float)M_PI * hsv[0] + 0.5f * (float)M_PI;
+ ang = 2.0f * (float)M_PI * hsv[0] + (float)M_PI_2;
if ((but->flag & UI_BUT_COLOR_CUBIC) && (U.color_picker_type == USER_CP_CIRCLE_HSV))
radius_t = (1.0f - pow3f(1.0f - hsv[1]));
@@ -3007,11 +3007,8 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
float height = rect->ymax - rect->ymin;
/* find color luminance and change it slightly */
float bw = rgb_to_bw(col);
-
- if (bw > 0.5)
- bw -= 0.5;
- else
- bw += 0.5;
+
+ bw += (bw < 0.5f) ? 0.5f : -0.5f;
glColor4f(bw, bw, bw, 1.0);
glBegin(GL_TRIANGLES);
@@ -3947,7 +3944,7 @@ void ui_draw_pie_center(uiBlock *block)
int subd = 40;
float angle = atan2f(pie_dir[1], pie_dir[0]);
- float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? ((float)M_PI / 2.0f) : ((float)M_PI / 4.0f);
+ float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_2 : M_PI_4;
glPushMatrix();
glTranslatef(cx, cy, 0.0f);
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index aa5b2570952..dab4b6a941c 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -682,6 +682,9 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_INFO_DEBUG_TEXT:
cp = ts->info_debug_text;
break;
+ case TH_V3D_CLIPPING_BORDER:
+ cp = ts->clipping_border_3d;
+ break;
}
}
}
@@ -951,6 +954,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tv3d.gradients.high_gradient, 58, 58, 58, 255);
btheme->tv3d.gradients.show_grad = false;
+ rgba_char_args_set(btheme->tv3d.clipping_border_3d, 50, 50, 50, 255);
/* space buttons */
/* to have something initialized */
btheme->tbuts = btheme->tv3d;
@@ -1574,7 +1578,7 @@ void init_userdef_do_versions(void)
U.tb_rightmouse = 5;
}
if (U.mixbufsize == 0) U.mixbufsize = 2048;
- if (strcmp(U.tempdir, "/") == 0) {
+ if (STREQ(U.tempdir, "/")) {
BKE_tempdir_system_init(U.tempdir);
}
if (U.autokey_mode == 0) {
@@ -1907,39 +1911,39 @@ void init_userdef_do_versions(void)
wmKeyMap *km;
for (km = U.user_keymaps.first; km; km = km->next) {
- if (strcmp(km->idname, "Armature_Sketch") == 0)
+ if (STREQ(km->idname, "Armature_Sketch"))
strcpy(km->idname, "Armature Sketch");
- else if (strcmp(km->idname, "View3D") == 0)
+ else if (STREQ(km->idname, "View3D"))
strcpy(km->idname, "3D View");
- else if (strcmp(km->idname, "View3D Generic") == 0)
+ else if (STREQ(km->idname, "View3D Generic"))
strcpy(km->idname, "3D View Generic");
- else if (strcmp(km->idname, "EditMesh") == 0)
+ else if (STREQ(km->idname, "EditMesh"))
strcpy(km->idname, "Mesh");
- else if (strcmp(km->idname, "TimeLine") == 0)
+ else if (STREQ(km->idname, "TimeLine"))
strcpy(km->idname, "Timeline");
- else if (strcmp(km->idname, "UVEdit") == 0)
+ else if (STREQ(km->idname, "UVEdit"))
strcpy(km->idname, "UV Editor");
- else if (strcmp(km->idname, "Animation_Channels") == 0)
+ else if (STREQ(km->idname, "Animation_Channels"))
strcpy(km->idname, "Animation Channels");
- else if (strcmp(km->idname, "GraphEdit Keys") == 0)
+ else if (STREQ(km->idname, "GraphEdit Keys"))
strcpy(km->idname, "Graph Editor");
- else if (strcmp(km->idname, "GraphEdit Generic") == 0)
+ else if (STREQ(km->idname, "GraphEdit Generic"))
strcpy(km->idname, "Graph Editor Generic");
- else if (strcmp(km->idname, "Action_Keys") == 0)
+ else if (STREQ(km->idname, "Action_Keys"))
strcpy(km->idname, "Dopesheet");
- else if (strcmp(km->idname, "NLA Data") == 0)
+ else if (STREQ(km->idname, "NLA Data"))
strcpy(km->idname, "NLA Editor");
- else if (strcmp(km->idname, "Node Generic") == 0)
+ else if (STREQ(km->idname, "Node Generic"))
strcpy(km->idname, "Node Editor");
- else if (strcmp(km->idname, "Logic Generic") == 0)
+ else if (STREQ(km->idname, "Logic Generic"))
strcpy(km->idname, "Logic Editor");
- else if (strcmp(km->idname, "File") == 0)
+ else if (STREQ(km->idname, "File"))
strcpy(km->idname, "File Browser");
- else if (strcmp(km->idname, "FileMain") == 0)
+ else if (STREQ(km->idname, "FileMain"))
strcpy(km->idname, "File Browser Main");
- else if (strcmp(km->idname, "FileButtons") == 0)
+ else if (STREQ(km->idname, "FileButtons"))
strcpy(km->idname, "File Browser Buttons");
- else if (strcmp(km->idname, "Buttons Generic") == 0)
+ else if (STREQ(km->idname, "Buttons Generic"))
strcpy(km->idname, "Property Editor");
}
}
@@ -2572,6 +2576,25 @@ void init_userdef_do_versions(void)
}
}
+ if (U.versionfile < 273 || (U.versionfile == 273 && U.subversionfile < 5)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ unsigned char *cp = (unsigned char *)btheme->tv3d.clipping_border_3d;
+ int c;
+ copy_v4_v4_char((char *)cp, btheme->tv3d.back);
+ c = cp[0] - 8;
+ CLAMP(c, 0, 255);
+ cp[0] = c;
+ c = cp[1] - 8;
+ CLAMP(c, 0, 255);
+ cp[1] = c;
+ c = cp[2] - 8;
+ CLAMP(c, 0, 255);
+ cp[2] = c;
+ cp[3] = 255;
+ }
+ }
+
if (U.pixelsize == 0.0f)
U.pixelsize = 1.0f;
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index de46d47e5a3..b4a120b2dea 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -371,7 +371,8 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_
float winx, winy;
rctf *cur, *tot;
- /* use mask as size of region that View2D resides in, as it takes into account scrollbars already */
+ /* use mask as size of region that View2D resides in, as it takes into account
+ * scrollbars already - keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1);
winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1);
@@ -393,6 +394,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_
*/
totwidth = BLI_rctf_size_x(tot);
totheight = BLI_rctf_size_y(tot);
+ /* keep in sync with zoomx/zoomy in view_zoomstep_apply_ex! */
curwidth = width = BLI_rctf_size_x(cur);
curheight = height = BLI_rctf_size_y(cur);
@@ -1851,7 +1853,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* draw vertical steps */
if (dfac > 0.0f) {
- BLF_rotation_default(M_PI / 2);
+ BLF_rotation_default(M_PI_2);
BLF_enable_default(BLF_ROTATION);
for (; fac < vert.ymax - 10; fac += dfac, val += grid->dy) {
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 297d8d0f258..88140d897ae 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -625,6 +625,7 @@ static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool
{
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
+ const rctf cur_old = v2d->cur;
float dx, dy;
/* calculate amount to move view by, ensuring symmetry so the
@@ -651,17 +652,23 @@ static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool
v2d->cur.xmax -= 2 * dx;
}
else {
+
+ v2d->cur.xmin += dx;
+ v2d->cur.xmax -= dx;
+
if (use_mousepos && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
- float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
- float mval_faci = 1.0f - mval_fac;
- float ofs = (mval_fac * dx) - (mval_faci * dx);
-
- v2d->cur.xmin += ofs + dx;
- v2d->cur.xmax += ofs - dx;
- }
- else {
- v2d->cur.xmin += dx;
- v2d->cur.xmax -= dx;
+ /* get zoom fac the same way as in ui_view2d_curRect_validate_resize - better keep in sync! */
+ const float zoomx = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur);
+
+ /* only move view to mouse if zoom fac is inside minzoom/maxzoom */
+ if (IN_RANGE_INCL(zoomx, v2d->minzoom, v2d->maxzoom)) {
+ float mval_fac = (vzd->mx_2d - cur_old.xmin) / BLI_rctf_size_x(&cur_old);
+ float mval_faci = 1.0f - mval_fac;
+ float ofs = (mval_fac * dx) - (mval_faci * dx);
+
+ v2d->cur.xmin += ofs;
+ v2d->cur.xmax += ofs;
+ }
}
}
}
@@ -676,17 +683,23 @@ static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool
v2d->cur.ymax -= 2 * dy;
}
else {
+
+ v2d->cur.ymin += dy;
+ v2d->cur.ymax -= dy;
+
if (use_mousepos && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
- float mval_fac = (vzd->my_2d - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
- float mval_faci = 1.0f - mval_fac;
- float ofs = (mval_fac * dy) - (mval_faci * dy);
-
- v2d->cur.ymin += ofs + dy;
- v2d->cur.ymax += ofs - dy;
- }
- else {
- v2d->cur.ymin += dy;
- v2d->cur.ymax -= dy;
+ /* get zoom fac the same way as in ui_view2d_curRect_validate_resize - better keep in sync! */
+ const float zoomy = (float)(BLI_rcti_size_y(&v2d->mask) + 1) / BLI_rctf_size_y(&v2d->cur);
+
+ /* only move view to mouse if zoom fac is inside minzoom/maxzoom */
+ if (IN_RANGE_INCL(zoomy, v2d->minzoom, v2d->maxzoom)) {
+ float mval_fac = (vzd->my_2d - cur_old.ymin) / BLI_rctf_size_y(&cur_old);
+ float mval_faci = 1.0f - mval_fac;
+ float ofs = (mval_fac * dy) - (mval_faci * dy);
+
+ v2d->cur.ymin += ofs;
+ v2d->cur.ymax += ofs;
+ }
}
}
}
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index b288a02a3d1..6ce5e8a304b 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -32,6 +32,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BLI_math.h"
#include "BLF_translation.h"
@@ -71,7 +72,7 @@ static Object *make_prim_init(bContext *C, const char *idname,
*was_editmode = true;
}
- *dia = ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, false);
+ *dia = ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
return obedit;
}
@@ -421,7 +422,9 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
{
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3], mat[4][4], dia;
+ float mat[4][4];
+ float loc[3], rot[3];
+ float dia;
bool enter_editmode;
unsigned int layer;
bool was_editmode;
@@ -431,9 +434,7 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Suzanne"), &dia, mat, &was_editmode, loc, rot, layer);
dia = RNA_float_get(op->ptr, "radius");
- mat[0][0] *= dia;
- mat[1][1] *= dia;
- mat[2][2] *= dia;
+ mul_mat3_m4_fl(mat, dia);
em = BKE_editmesh_from_object(obedit);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 0a78f299159..e8a5202029b 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -1241,7 +1241,9 @@ static BMElem *bm_elem_from_knife_vert(KnifeVert *kfv, KnifeEdge **r_kfe)
for (ref = kfv->edges.first; ref; ref = ref->next) {
kfe = ref->ref;
if (kfe->e) {
- *r_kfe = kfe;
+ if (r_kfe) {
+ *r_kfe = kfe;
+ }
break;
}
}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index a480b2051cc..16b74c3bddd 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -964,6 +964,40 @@ void MESH_OT_vert_connect(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+static int edbm_vert_connect_concave_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (!EDBM_op_call_and_selectf(
+ em, op,
+ "faces.out", true,
+ "connect_verts_concave faces=%hf",
+ BM_ELEM_SELECT))
+ {
+ return OPERATOR_CANCELLED;
+ }
+
+
+ EDBM_update_generic(em, true, true);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_vert_connect_concave(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Split Concave Faces";
+ ot->idname = "MESH_OT_vert_connect_concave";
+ ot->description = "Make all faces convex";
+
+ /* api callbacks */
+ ot->exec = edbm_vert_connect_concave_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
static int edbm_vert_connect_nonplaner_exec(bContext *C, wmOperator *op)
{
@@ -4541,7 +4575,7 @@ static int edbm_noise_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
float tin, dum;
- externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum, 0, NULL);
+ externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum, 0, NULL, false);
eve->co[2] += fac * tin;
}
}
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index 152d055d239..30e9a85d083 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -57,6 +57,7 @@
#include "ED_mesh.h"
#include "ED_object.h"
+#include "ED_screen.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
@@ -838,6 +839,71 @@ void MESH_OT_customdata_clear_skin(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/* Clear custom loop normals */
+static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ Mesh *me = ob->data;
+
+ if (!BKE_mesh_has_custom_loop_normals(me)) {
+ CustomData *data = GET_CD_DATA(me, ldata);
+
+ if (me->edit_btmesh) {
+ BM_data_layer_add(me->edit_btmesh->bm, data, CD_CUSTOMLOOPNORMAL);
+ }
+ else {
+ CustomData_add_layer(data, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, me->totloop);
+ }
+
+ DAG_id_tag_update(&me->id, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_CANCELLED;
+}
+
+void MESH_OT_customdata_custom_splitnormals_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Custom Split Normals Data";
+ ot->idname = "MESH_OT_customdata_custom_splitnormals_add";
+ ot->description = "Add a custom split normals layer, if none exists yet";
+
+ /* api callbacks */
+ ot->exec = mesh_customdata_custom_splitnormals_add_exec;
+ ot->poll = ED_operator_object_active_editable_mesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int mesh_customdata_custom_splitnormals_clear_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ Mesh *me = ob->data;
+
+ if (BKE_mesh_has_custom_loop_normals(me)) {
+ return mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_CUSTOMLOOPNORMAL);
+ }
+ return OPERATOR_CANCELLED;
+}
+
+void MESH_OT_customdata_custom_splitnormals_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Clear Custom Split Normals Data";
+ ot->idname = "MESH_OT_customdata_custom_splitnormals_clear";
+ ot->description = "Remove the custom split normals layer, if it exists";
+
+ /* api callbacks */
+ ot->exec = mesh_customdata_custom_splitnormals_clear_exec;
+ ot->poll = ED_operator_object_active_editable_mesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/************************** Add Geometry Layers *************************/
void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges, int calc_tessface)
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 6ba91097ec4..8f5ecaed524 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -175,6 +175,7 @@ void MESH_OT_normals_make_consistent(struct wmOperatorType *ot);
void MESH_OT_vertices_smooth(struct wmOperatorType *ot);
void MESH_OT_vertices_smooth_laplacian(struct wmOperatorType *ot);
void MESH_OT_vert_connect(struct wmOperatorType *ot);
+void MESH_OT_vert_connect_concave(struct wmOperatorType *ot);
void MESH_OT_vert_connect_nonplanar(struct wmOperatorType *ot);
void MESH_OT_edge_split(struct wmOperatorType *ot);
void MESH_OT_bridge_edge_loops(struct wmOperatorType *ot);
@@ -237,6 +238,8 @@ void MESH_OT_vertex_color_remove(struct wmOperatorType *ot);
/* no create_mask yet */
void MESH_OT_customdata_clear_mask(struct wmOperatorType *ot);
void MESH_OT_customdata_clear_skin(struct wmOperatorType *ot);
+void MESH_OT_customdata_custom_splitnormals_add(struct wmOperatorType *ot);
+void MESH_OT_customdata_custom_splitnormals_clear(struct wmOperatorType *ot);
void MESH_OT_drop_named_image(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index e7dc5a69d53..59d0de87de6 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -153,6 +153,8 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_vertex_color_remove);
WM_operatortype_append(MESH_OT_customdata_clear_mask);
WM_operatortype_append(MESH_OT_customdata_clear_skin);
+ WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_add);
+ WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_clear);
WM_operatortype_append(MESH_OT_drop_named_image);
WM_operatortype_append(MESH_OT_edgering_select);
@@ -161,6 +163,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_solidify);
WM_operatortype_append(MESH_OT_select_nth);
WM_operatortype_append(MESH_OT_vert_connect);
+ WM_operatortype_append(MESH_OT_vert_connect_concave);
WM_operatortype_append(MESH_OT_vert_connect_nonplanar);
WM_operatortype_append(MESH_OT_knife_tool);
WM_operatortype_append(MESH_OT_knife_project);
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 19040062fda..dee216d9c73 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -329,7 +329,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
if (odg) {
/* Search for a match in the new object, and set new index */
for (dg = ob->defbase.first, index = 0; dg; dg = dg->next, index++) {
- if (!strcmp(dg->name, odg->name)) {
+ if (STREQ(dg->name, odg->name)) {
dvert[i].dw[j].def_nr = index;
break;
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index c3edd63b2d4..1180c082783 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -162,14 +162,13 @@ void ED_object_rotation_from_view(bContext *C, float rot[3], const char align_ax
BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
if (rv3d) {
- const float pi_2 = (float)M_PI / 2.0f;
float quat[4];
switch (align_axis) {
case 'X':
{
float quat_y[4];
- axis_angle_to_quat(quat_y, rv3d->viewinv[1], -pi_2);
+ axis_angle_to_quat(quat_y, rv3d->viewinv[1], -M_PI_2);
mul_qt_qtqt(quat, rv3d->viewquat, quat_y);
quat[0] = -quat[0];
@@ -182,7 +181,7 @@ void ED_object_rotation_from_view(bContext *C, float rot[3], const char align_ax
quat[0] = -quat[0];
quat_to_eul(rot, quat);
- rot[0] -= pi_2;
+ rot[0] -= (float)M_PI_2;
break;
}
case 'Z':
@@ -219,9 +218,9 @@ void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3],
/* Uses context to figure out transform for primitive.
* Returns standard diameter. */
-float ED_object_new_primitive_matrix(bContext *C, Object *obedit,
- const float loc[3], const float rot[3], float primmat[4][4],
- bool apply_diameter)
+float ED_object_new_primitive_matrix(
+ bContext *C, Object *obedit,
+ const float loc[3], const float rot[3], float primmat[4][4])
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -246,13 +245,6 @@ float ED_object_new_primitive_matrix(bContext *C, Object *obedit,
{
const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL);
-
- if (apply_diameter) {
- primmat[0][0] *= dia;
- primmat[1][1] *= dia;
- primmat[2][2] *= dia;
- }
-
return dia;
}
@@ -516,7 +508,7 @@ static int effector_add_exec(bContext *C, wmOperator *op)
cu = ob->data;
cu->flag |= CU_PATH | CU_3D;
ED_object_editmode_enter(C, 0);
- ED_object_new_primitive_matrix(C, ob, loc, rot, mat, false);
+ ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
BLI_addtail(&cu->editnurb->nurbs, add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, dia));
if (!enter_editmode)
ED_object_editmode_exit(C, EM_FREEDATA);
@@ -639,7 +631,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
}
- ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, false);
+ ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
dia = RNA_float_get(op->ptr, "radius");
add_metaball_primitive(C, obedit, mat, dia, RNA_enum_get(op->ptr, "type"));
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 83eeedfef52..fca527f8931 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -916,7 +916,7 @@ cage_cleanup:
BakeData *bake = &scene->r.bake;
char name[FILE_MAX];
- BKE_makepicstring_from_type(name, filepath, bmain->name, 0, bake->im_format.imtype, true, false);
+ BKE_image_path_from_imtype(name, filepath, bmain->name, 0, bake->im_format.imtype, true, false);
if (is_automatic_name) {
BLI_path_suffix(name, FILE_MAX, ob_low->id.name + 2, "_");
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 2596ea0a064..8f793f7f7f9 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -471,7 +471,7 @@ static void test_constraints(Object *owner, bPoseChannel *pchan)
/* TODO: clear subtarget? */
curcon->flag |= CONSTRAINT_DISABLE;
}
- else if (strcmp(pchan->name, ct->subtarget) == 0) {
+ else if (STREQ(pchan->name, ct->subtarget)) {
/* cannot target self */
ct->subtarget[0] = '\0';
curcon->flag |= CONSTRAINT_DISABLE;
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index f6cf0312e2d..c57cae41bf4 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -42,6 +42,7 @@
#include "BKE_context.h"
#include "BKE_data_transfer.h"
+#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_remap.h"
@@ -82,6 +83,7 @@ static EnumPropertyItem DT_layer_items[] = {
{DT_TYPE_BWEIGHT_EDGE, "BEVEL_WEIGHT_EDGE", 0, "Bevel Weight", "Transfer bevel weights"},
{DT_TYPE_FREESTYLE_EDGE, "FREESTYLE_EDGE", 0, "Freestyle Mark", "Transfer Freestyle edge mark"},
{0, "", 0, "Face Corner Data", ""},
+ {DT_TYPE_LNOR, "CUSTOM_NORMAL", 0, "Custom Normals", "Transfer custom normals"},
{DT_TYPE_VCOL, "VCOL", 0, "VCol", "Vertex (face corners) colors"},
{DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"},
{0, "", 0, "Face Data", ""},
@@ -393,6 +395,8 @@ static int data_transfer_exec(bContext *C, wmOperator *op)
}
}
+ DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
+
if (reverse_transfer) {
SWAP(Object *, ob_src, ob_dst);
}
@@ -400,6 +404,8 @@ static int data_transfer_exec(bContext *C, wmOperator *op)
BLI_freelistN(&ctx_objects);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
#if 0 /* TODO */
/* Note: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
@@ -592,6 +598,8 @@ static int datalayout_transfer_exec(bContext *C, wmOperator *op)
BKE_object_data_transfer_layout(scene, ob_src, ob_dst, dtmd->data_types, use_delete,
dtmd->layers_select_src, dtmd->layers_select_dst);
+
+ DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
}
else {
Object *ob_src = ob_act;
@@ -621,11 +629,15 @@ static int datalayout_transfer_exec(bContext *C, wmOperator *op)
BKE_object_data_transfer_layout(scene, ob_src, ob_dst, data_type, use_delete,
layers_select_src, layers_select_dst);
}
+
+ DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
}
BLI_freelistN(&ctx_objects);
}
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 0a053d771df..64004de1087 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -42,6 +42,8 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+#include "BLF_translation.h"
+
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
#include "DNA_group_types.h"
@@ -1347,7 +1349,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
ID *data;
Curve *cu;
Nurb *nu;
- int clear = (strcmp(op->idname, "OBJECT_OT_shade_flat") == 0);
+ int clear = (STREQ(op->idname, "OBJECT_OT_shade_flat"));
bool done = false, linked_data = false;
CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
@@ -1701,7 +1703,7 @@ static int game_property_new_exec(bContext *C, wmOperator *op)
BLI_strncpy(prop->name, name, sizeof(prop->name));
}
- BKE_bproperty_unique(NULL, prop, 0); // make_unique_prop_names(prop->name);
+ BLI_uniquename(&ob->prop, prop, DATA_("Property"), '.', offsetof(bProperty, name), sizeof(prop->name));
WM_event_add_notifier(C, NC_LOGIC, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 20e2e22cdf8..3c43f2729bd 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -61,47 +61,6 @@
/********************* 3d view operators ***********************/
-static bool group_link_early_exit_check(Group *group, Object *object)
-{
- GroupObject *group_object;
-
- for (group_object = group->gobject.first; group_object; group_object = group_object->next) {
- if (group_object->ob == object) {
- return true;
- }
- }
-
- return false;
-}
-
-static bool check_object_instances_group_recursive(Object *object, Group *group)
-{
- if (object->dup_group) {
- Group *dup_group = object->dup_group;
- if ((dup_group->id.flag & LIB_DOIT) == 0) {
- /* Cycle already exists in groups, let's prevent further crappyness */
- return true;
- }
- /* flag the object to identify cyclic dependencies in further dupli groups */
- dup_group->id.flag &= ~LIB_DOIT;
-
- if (dup_group == group)
- return true;
- else {
- GroupObject *gob;
- for (gob = dup_group->gobject.first; gob; gob = gob->next) {
- if (check_object_instances_group_recursive(gob->ob, group))
- return true;
- }
- }
-
- /* un-flag the object, it's allowed to have the same group multiple times in parallel */
- dup_group->id.flag |= LIB_DOIT;
- }
-
- return false;
-}
-
/* can be called with C == NULL */
static EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
@@ -185,15 +144,12 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
if (!BKE_group_object_exists(group, ob))
continue;
- /* for recursive check */
- BKE_main_id_tag_listbase(&bmain->group, true);
-
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- if (group_link_early_exit_check(group, base->object))
+ if (BKE_group_object_exists(group, base->object))
continue;
- if (!check_object_instances_group_recursive(base->object, group)) {
+ if (!BKE_group_object_cyclic_check(bmain, base->object, group)) {
BKE_group_object_add(group, base->object, scene, base);
updated = true;
}
@@ -486,7 +442,7 @@ static int group_link_exec(bContext *C, wmOperator *op)
* we could sckip all the dependency check and just consider
* operator is finished.
*/
- if (group_link_early_exit_check(group, ob)) {
+ if (BKE_group_object_exists(group, ob)) {
return OPERATOR_FINISHED;
}
@@ -495,8 +451,7 @@ static int group_link_exec(bContext *C, wmOperator *op)
* It is also bad idea to add object to group which is in group which
* contains our current object.
*/
- BKE_main_id_tag_listbase(&bmain->group, true);
- if (check_object_instances_group_recursive(ob, group)) {
+ if (BKE_group_object_cyclic_check(bmain, ob, group)) {
BKE_report(op->reports, RPT_ERROR, "Could not add the group because of dependency cycle detected");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 9f9a647c9f1..1d764ced524 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -503,6 +503,15 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob
unit_m4(pose_mat);
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ if (mode == OBJECT_ADDHOOK_NEWOB) {
+ /* pass */
+ }
+ else {
+ /* may overwrite with pose-bone location, below */
+ mul_v3_m4v3(cent, obedit->imat, ob->obmat[3]);
+ }
+
if (mode == OBJECT_ADDHOOK_SELOB_BONE) {
bArmature *arm = ob->data;
BLI_assert(ob->type == OB_ARMATURE);
@@ -514,6 +523,8 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob
pchan_act = BKE_pose_channel_active(ob);
if (LIKELY(pchan_act)) {
invert_m4_m4(pose_mat, pchan_act->pose_mat);
+ mul_v3_m4v3(cent, ob->obmat, pchan_act->pose_mat[3]);
+ mul_v3_m4v3(cent, obedit->imat, cent);
}
}
else {
@@ -521,6 +532,9 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob
}
}
+ copy_v3_v3(hmd->cent, cent);
+
+
/* matrix calculus */
/* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
/* (parentinv ) */
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 5a479af83b5..bed85444101 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -440,9 +440,9 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
for (a = 0; a < totpart; a++) {
key = cache[a];
- if (key->steps > 0) {
- totvert += key->steps + 1;
- totedge += key->steps;
+ if (key->segments > 0) {
+ totvert += key->segments + 1;
+ totedge += key->segments;
}
}
@@ -450,9 +450,9 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
for (a = 0; a < totchild; a++) {
key = cache[a];
- if (key->steps > 0) {
- totvert += key->steps + 1;
- totedge += key->steps;
+ if (key->segments > 0) {
+ totvert += key->segments + 1;
+ totedge += key->segments;
}
}
@@ -476,7 +476,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
cache = psys->pathcache;
for (a = 0; a < totpart; a++) {
key = cache[a];
- kmax = key->steps;
+ kmax = key->segments;
for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
copy_v3_v3(mvert->co, key->co);
if (k) {
@@ -495,7 +495,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
cache = psys->childcache;
for (a = 0; a < totchild; a++) {
key = cache[a];
- kmax = key->steps;
+ kmax = key->segments;
for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
copy_v3_v3(mvert->co, key->co);
if (k) {
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 67b5c8061cd..430994aed60 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -973,7 +973,7 @@ void OBJECT_OT_parent_set(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
RNA_def_boolean(ot->srna, "xmirror", false, "X Mirror",
"Apply weights symmetrically along X axis, for Envelope/Automatic vertex groups creation");
RNA_def_boolean(ot->srna, "keep_transform", false, "Keep Transform",
@@ -2344,10 +2344,8 @@ void OBJECT_OT_make_local(wmOperatorType *ot)
}
enum {
- /* Be careful with those values, they are used as bitflags in some cases, in others as bool...
- * See single_object_users, single_obdata_users, single_object_action_users, etc.< */
- MAKE_SINGLE_USER_ALL = 0,
- MAKE_SINGLE_USER_SELECTED = SELECT,
+ MAKE_SINGLE_USER_ALL = 1,
+ MAKE_SINGLE_USER_SELECTED = 2,
};
static int make_single_user_exec(bContext *C, wmOperator *op)
@@ -2355,7 +2353,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C); /* ok if this is NULL */
- const int flag = RNA_enum_get(op->ptr, "type");
+ const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0;
const bool copy_groups = false;
bool update_deps = false;
@@ -2421,7 +2419,7 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, SELECT, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", type_items, MAKE_SINGLE_USER_SELECTED, "Type", "");
RNA_def_boolean(ot->srna, "object", 0, "Object", "Make single user objects");
RNA_def_boolean(ot->srna, "obdata", 0, "Object Data", "Make single user object data");
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index e70281c502b..f885cbbb24f 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -1646,7 +1646,7 @@ static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const i
BMesh *bm = em ? em->bm : NULL;
Mesh *me = em ? NULL : ob->data;
- MeshElemMap *emap ;
+ MeshElemMap *emap;
int *emap_mem;
BLI_SMALLSTACK_DECLARE(dv_stack, MDeformVert *);
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 5e30ca4ed2f..fd32aad852d 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -61,7 +61,7 @@
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_report.h"
-
+#include "BKE_bvhutils.h"
#include "BKE_pointcache.h"
#include "BIF_gl.h"
@@ -85,8 +85,10 @@
static void PE_create_particle_edit_from_psys(Scene *scene, Object *ob, ParticleSystem *psys);
static void PE_create_particle_edit_from_cache(Scene *scene, Object *ob, PointCache *cache, ListBase *mem_cache);
-static void PTCacheUndo_clear(PTCacheEdit *edit);
-static void recalc_emitter_field(Object *ob, ParticleSystem *psys);
+void PTCacheUndo_clear(PTCacheEdit *edit);
+void recalc_lengths(PTCacheEdit *edit);
+void recalc_emitter_field(Object *ob, ParticleSystem *psys);
+void update_world_cos(Object *ob, PTCacheEdit *edit);
#define KEY_K PTCacheEditKey *key; int k
#define POINT_P PTCacheEditPoint *point; int p
@@ -362,6 +364,7 @@ typedef struct PEData {
Object *ob;
DerivedMesh *dm;
PTCacheEdit *edit;
+ BVHTreeFromMesh shape_bvh;
const int *mval;
rcti *rect;
@@ -418,6 +421,25 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
}
}
+static void PE_create_shape_tree(PEData *data, Object *shapeob)
+{
+ DerivedMesh *dm = shapeob->derivedFinal;
+
+ memset(&data->shape_bvh, 0, sizeof(data->shape_bvh));
+
+ if (!dm) {
+ return;
+ }
+
+ DM_ensure_tessface(dm);
+ bvhtree_from_mesh_faces(&data->shape_bvh, dm, 0.0f, 4, 8);
+}
+
+static void PE_free_shape_tree(PEData *data)
+{
+ free_bvhtree_from_mesh(&data->shape_bvh);
+}
+
/*************************** selection utilities *******************************/
static bool key_test_depth(PEData *data, const float co[3], const int screen_co[2])
@@ -1062,7 +1084,7 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
}
}
/* set current distances to be kept between neighbouting keys */
-static void recalc_lengths(PTCacheEdit *edit)
+void recalc_lengths(PTCacheEdit *edit)
{
POINT_P; KEY_K;
@@ -1078,7 +1100,7 @@ static void recalc_lengths(PTCacheEdit *edit)
}
/* calculate a tree for finding nearest emitter's vertice */
-static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
+void recalc_emitter_field(Object *ob, ParticleSystem *psys)
{
DerivedMesh *dm=psys_get_modifier(ob, psys)->dm;
PTCacheEdit *edit= psys->edit;
@@ -1166,7 +1188,7 @@ static void PE_update_selection(Scene *scene, Object *ob, int useflag)
point->flag &= ~PEP_EDIT_RECALC;
}
-static void update_world_cos(Object *ob, PTCacheEdit *edit)
+void update_world_cos(Object *ob, PTCacheEdit *edit)
{
ParticleSystem *psys = edit->psys;
ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
@@ -3236,7 +3258,7 @@ static void brush_puff(PEData *data, int point_index)
static void BKE_brush_weight_get(PEData *data, float UNUSED(mat[4][4]), float UNUSED(imat[4][4]), int point_index, int key_index, PTCacheEditKey *UNUSED(key))
{
- /* roots have full weight allways */
+ /* roots have full weight always */
if (key_index) {
PTCacheEdit *edit = data->edit;
ParticleSystem *psys = edit->psys;
@@ -4039,6 +4061,180 @@ void PARTICLE_OT_brush_edit(wmOperatorType *ot)
RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
}
+/*********************** cut shape ***************************/
+
+static int shape_cut_poll(bContext *C)
+{
+ if (PE_hair_poll(C)) {
+ Scene *scene= CTX_data_scene(C);
+ ParticleEditSettings *pset= PE_settings(scene);
+
+ if (pset->shape_object)
+ return true;
+ }
+
+ return false;
+}
+
+typedef struct PointInsideBVH {
+ BVHTreeFromMesh bvhdata;
+ int num_hits;
+} PointInsideBVH;
+
+static void point_inside_bvh_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ PointInsideBVH *data = userdata;
+
+ data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit);
+
+ if (hit->index != -1)
+ ++data->num_hits;
+}
+
+/* true if the point is inside the shape mesh */
+static bool shape_cut_test_point(PEData *data, ParticleCacheKey *key)
+{
+ BVHTreeFromMesh *shape_bvh = &data->shape_bvh;
+ const float dir[3] = {1.0f, 0.0f, 0.0f};
+ PointInsideBVH userdata;
+
+ userdata.bvhdata = data->shape_bvh;
+ userdata.num_hits = 0;
+
+ BLI_bvhtree_ray_cast_all(shape_bvh->tree, key->co, dir, 0.0f, point_inside_bvh_cb, &userdata);
+
+ /* for any point inside a watertight mesh the number of hits is uneven */
+ return (userdata.num_hits % 2) == 1;
+}
+
+static void shape_cut(PEData *data, int pa_index)
+{
+ PTCacheEdit *edit = data->edit;
+ Object *ob = data->ob;
+ ParticleEditSettings *pset = PE_settings(data->scene);
+ ParticleCacheKey *key;
+
+ bool cut;
+ float cut_time = 1.0;
+ int k, totkeys = 1 << pset->draw_step;
+
+ /* don't cut hidden */
+ if (edit->points[pa_index].flag & PEP_HIDE)
+ return;
+
+ cut = false;
+
+ /* check if root is inside the cut shape */
+ key = edit->pathcache[pa_index];
+ if (!shape_cut_test_point(data, key)) {
+ cut_time = -1.0f;
+ cut = true;
+ }
+ else {
+ for (k = 0; k < totkeys; k++, key++) {
+ BVHTreeRayHit hit;
+ float dir[3];
+ float len;
+
+ sub_v3_v3v3(dir, (key+1)->co, key->co);
+ len = normalize_v3(dir);
+
+ memset(&hit, 0, sizeof(hit));
+ hit.index = -1;
+ hit.dist = len;
+ BLI_bvhtree_ray_cast(data->shape_bvh.tree, key->co, dir, 0.0f, &hit, data->shape_bvh.raycast_callback, &data->shape_bvh);
+ if (hit.index >= 0) {
+ if (hit.dist < len) {
+ cut_time = (hit.dist / len + (float)k) / (float)totkeys;
+ cut = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (cut) {
+ if (cut_time < 0.0f) {
+ edit->points[pa_index].flag |= PEP_TAG;
+ }
+ else {
+ rekey_particle_to_time(data->scene, ob, pa_index, cut_time);
+ edit->points[pa_index].flag |= PEP_EDIT_RECALC;
+ }
+ }
+}
+
+static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ ParticleEditSettings *pset = PE_settings(scene);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ Object *shapeob = pset->shape_object;
+ int selected = count_selected_keys(scene, edit);
+ int lock_root = pset->flag & PE_LOCK_FIRST;
+
+ if (!PE_start_edit(edit))
+ return OPERATOR_CANCELLED;
+
+ /* disable locking temporatily for disconnected hair */
+ if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
+ pset->flag &= ~PE_LOCK_FIRST;
+
+ if (edit->psys && edit->pathcache) {
+ PEData data;
+ int removed;
+
+ PE_set_data(C, &data);
+ PE_create_shape_tree(&data, shapeob);
+
+ if (selected)
+ foreach_selected_point(&data, shape_cut);
+ else
+ foreach_point(&data, shape_cut);
+
+ removed = remove_tagged_particles(ob, edit->psys, pe_x_mirror(ob));
+ recalc_lengths(edit);
+
+ if (removed) {
+ update_world_cos(ob, edit);
+ psys_free_path_cache(NULL, edit);
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+ else
+ PE_update_object(scene, ob, 1);
+
+ if (edit->psys) {
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
+ }
+ else {
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
+ }
+
+ PE_free_shape_tree(&data);
+ }
+
+ pset->flag |= lock_root;
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_shape_cut(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Shape Cut";
+ ot->idname = "PARTICLE_OT_shape_cut";
+ ot->description = "Cut hair to conform to the set shape object";
+
+ /* api callbacks */
+ ot->exec = shape_cut_exec;
+ ot->poll = shape_cut_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
/*********************** undo ***************************/
static void free_PTCacheUndo(PTCacheUndo *undo)
@@ -4266,7 +4462,7 @@ int PE_undo_valid(Scene *scene)
return 0;
}
-static void PTCacheUndo_clear(PTCacheEdit *edit)
+void PTCacheUndo_clear(PTCacheEdit *edit)
{
PTCacheUndo *undo;
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 5a61f77e5a8..dba6d6f5085 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -40,18 +40,21 @@
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
+#include "BLI_string.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
+#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
@@ -62,8 +65,37 @@
#include "ED_screen.h"
#include "ED_object.h"
+#include "UI_resources.h"
+
#include "physics_intern.h"
+extern void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
+extern void PTCacheUndo_clear(PTCacheEdit *edit);
+extern void recalc_lengths(PTCacheEdit *edit);
+extern void recalc_emitter_field(Object *ob, ParticleSystem *psys);
+extern void update_world_cos(Object *ob, PTCacheEdit *edit);
+
+#define KEY_K PTCacheEditKey *key; int k
+#define POINT_P PTCacheEditPoint *point; int p
+#define LOOP_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++)
+#if 0
+#define LOOP_VISIBLE_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!(point->flag & PEP_HIDE))
+#define LOOP_SELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point_is_selected(point))
+#define LOOP_UNSELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!point_is_selected(point))
+#define LOOP_EDITED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_EDIT_RECALC)
+#define LOOP_TAGGED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_TAG)
+#endif
+#define LOOP_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++)
+#if 0
+#define LOOP_VISIBLE_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (!(key->flag & PEK_HIDE))
+#define LOOP_SELECTED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if ((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE))
+#define LOOP_TAGGED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (key->flag & PEK_TAG)
+
+#define KEY_WCO (key->flag & PEK_USE_WCO ? key->world_co : key->co)
+#endif
+
+static float I[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}};
+
/********************** particle system slot operators *********************/
static int particle_system_add_exec(bContext *C, wmOperator *UNUSED(op))
@@ -623,38 +655,50 @@ void PARTICLE_OT_disconnect_hair(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh");
}
-static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
+/* from/to_world_space : whether from/to particles are in world or hair space
+ * from/to_mat : additional transform for from/to particles (e.g. for using object space copying)
+ */
+static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
+ Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit,
+ float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global)
{
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- ParticleData *pa;
- PTCacheEdit *edit;
- PTCacheEditPoint *point;
- PTCacheEditKey *ekey = NULL;
- HairKey *key;
+ ParticleSystemModifierData *target_psmd = psys_get_modifier(target_ob, target_psys);
+ ParticleData *pa, *tpa;
+ PTCacheEditPoint *edit_point;
+ PTCacheEditKey *ekey;
BVHTreeFromMesh bvhtree= {NULL};
- BVHTreeNearest nearest;
MFace *mface = NULL, *mf;
MEdge *medge = NULL, *me;
MVert *mvert;
- DerivedMesh *dm = NULL;
+ DerivedMesh *dm, *target_dm;
int numverts;
int i, k;
- float hairmat[4][4], imat[4][4];
- float v[4][3], vec[3];
+ float from_ob_imat[4][4], to_ob_imat[4][4];
+ float from_imat[4][4], to_imat[4][4];
- if (!psys || !psys->part || psys->part->type != PART_HAIR || !psmd->dm)
+ if (!target_psmd->dm)
+ return false;
+ if (!psys->part || psys->part->type != PART_HAIR)
return false;
+ if (!target_psys->part || target_psys->part->type != PART_HAIR)
+ return false;
+
+ edit_point = target_edit ? target_edit->points : NULL;
- edit= psys->edit;
- point= edit ? edit->points : NULL;
+ invert_m4_m4(from_ob_imat, ob->obmat);
+ invert_m4_m4(to_ob_imat, target_ob->obmat);
+ invert_m4_m4(from_imat, from_mat);
+ invert_m4_m4(to_imat, to_mat);
- if (psmd->dm->deformedOnly) {
- /* we don't want to mess up psmd->dm when converting to global coordinates below */
- dm = psmd->dm;
+ if (target_psmd->dm->deformedOnly) {
+ /* we don't want to mess up target_psmd->dm when converting to global coordinates below */
+ dm = target_psmd->dm;
}
else {
- dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+ /* warning: this rebuilds target_psmd->dm! */
+ dm = mesh_get_derived_deform(scene, target_ob, CD_MASK_BAREMESH);
}
+ target_dm = target_psmd->dm;
/* don't modify the original vertices */
dm = CDDM_copy(dm);
@@ -662,12 +706,11 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
DM_ensure_tessface(dm);
numverts = dm->getNumVerts(dm);
-
mvert = dm->getVertArray(dm);
/* convert to global coordinates */
for (i=0; i<numverts; i++)
- mul_m4_v3(ob->obmat, mvert[i].co);
+ mul_m4_v3(to_mat, mvert[i].co);
if (dm->getNumTessFaces(dm) != 0) {
mface = dm->getTessFaceArray(dm);
@@ -682,13 +725,23 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
return false;
}
- for (i=0, pa= psys->particles; i<psys->totpart; i++, pa++) {
- key = pa->hair;
+ for (i = 0, tpa = target_psys->particles, pa = psys->particles;
+ i < target_psys->totpart;
+ i++, tpa++, pa++) {
+
+ float from_co[3];
+ BVHTreeNearest nearest;
+
+ if (from_global)
+ mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].co);
+ else
+ mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].world_co);
+ mul_m4_v3(from_mat, from_co);
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
- BLI_bvhtree_find_nearest(bvhtree.tree, key->co, &nearest, bvhtree.nearest_callback, &bvhtree);
+ BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
if (nearest.index == -1) {
if (G.debug & G_DEBUG)
@@ -697,6 +750,8 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
}
if (mface) {
+ float v[4][3];
+
mf = &mface[nearest.index];
copy_v3_v3(v[0], mvert[mf->v1].co);
@@ -704,44 +759,80 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
copy_v3_v3(v[2], mvert[mf->v3].co);
if (mf->v4) {
copy_v3_v3(v[3], mvert[mf->v4].co);
- interp_weights_poly_v3(pa->fuv, v, 4, nearest.co);
+ interp_weights_poly_v3(tpa->fuv, v, 4, nearest.co);
}
else
- interp_weights_poly_v3(pa->fuv, v, 3, nearest.co);
+ interp_weights_poly_v3(tpa->fuv, v, 3, nearest.co);
+ tpa->foffset = 0.0f;
- pa->num = nearest.index;
- pa->num_dmcache = psys_particle_dm_face_lookup(ob, psmd->dm, pa->num, pa->fuv, NULL);
+ tpa->num = nearest.index;
+ tpa->num_dmcache = psys_particle_dm_face_lookup(target_ob, target_dm, tpa->num, tpa->fuv, NULL);
}
else {
me = &medge[nearest.index];
- pa->fuv[1] = line_point_factor_v3(nearest.co,
- mvert[me->v2].co,
- mvert[me->v2].co);
- pa->fuv[0] = 1.0f - pa->fuv[1];
- pa->fuv[2] = pa->fuv[3] = 0.0f;
+ tpa->fuv[1] = line_point_factor_v3(nearest.co,
+ mvert[me->v1].co,
+ mvert[me->v2].co);
+ tpa->fuv[0] = 1.0f - tpa->fuv[1];
+ tpa->fuv[2] = tpa->fuv[3] = 0.0f;
+ tpa->foffset = 0.0f;
- pa->num = nearest.index;
- pa->num_dmcache = -1;
+ tpa->num = nearest.index;
+ tpa->num_dmcache = -1;
}
- psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
- invert_m4_m4(imat, hairmat);
-
- sub_v3_v3v3(vec, nearest.co, key->co);
-
- if (point) {
- ekey = point->keys;
- point++;
- }
-
- for (k=0, key=pa->hair; k<pa->totkey; k++, key++) {
- add_v3_v3(key->co, vec);
- mul_m4_v3(imat, key->co);
-
- if (ekey) {
- ekey->flag |= PEK_USE_WCO;
- ekey++;
+ /* translate hair keys */
+ {
+ HairKey *key, *tkey;
+ float hairmat[4][4], imat[4][4];
+ float offset[3];
+
+ if (to_global)
+ copy_m4_m4(imat, target_ob->obmat);
+ else {
+ /* note: using target_dm here, which is in target_ob object space and has full modifiers */
+ psys_mat_hair_to_object(target_ob, target_dm, target_psys->part->from, tpa, hairmat);
+ invert_m4_m4(imat, hairmat);
+ }
+ mul_m4_m4m4(imat, imat, to_imat);
+
+ /* offset in world space */
+ sub_v3_v3v3(offset, nearest.co, from_co);
+
+ if (edit_point) {
+ for (k=0, key=pa->hair, tkey=tpa->hair, ekey = edit_point->keys; k<tpa->totkey; k++, key++, tkey++, ekey++) {
+ float co_orig[3];
+
+ if (from_global)
+ mul_v3_m4v3(co_orig, from_ob_imat, key->co);
+ else
+ mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
+ mul_m4_v3(from_mat, co_orig);
+
+ add_v3_v3v3(tkey->co, co_orig, offset);
+
+ mul_m4_v3(imat, tkey->co);
+
+ ekey->flag |= PEK_USE_WCO;
+ }
+
+ edit_point++;
+ }
+ else {
+ for (k=0, key=pa->hair, tkey=tpa->hair; k<tpa->totkey; k++, key++, tkey++) {
+ float co_orig[3];
+
+ if (from_global)
+ mul_v3_m4v3(co_orig, from_ob_imat, key->co);
+ else
+ mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
+ mul_m4_v3(from_mat, co_orig);
+
+ add_v3_v3v3(tkey->co, co_orig, offset);
+
+ mul_m4_v3(imat, tkey->co);
+ }
}
}
}
@@ -749,15 +840,26 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
free_bvhtree_from_mesh(&bvhtree);
dm->release(dm);
- psys_free_path_cache(psys, psys->edit);
+ psys_free_path_cache(target_psys, target_edit);
- psys->flag &= ~PSYS_GLOBAL_HAIR;
-
- PE_update_object(scene, ob, 0);
+ PE_update_object(scene, target_ob, 0);
return true;
}
+static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+ bool ok;
+
+ if (!psys)
+ return false;
+
+ ok = remap_hair_emitter(scene, ob, psys, ob, psys, psys->edit, ob->obmat, ob->obmat, psys->flag & PSYS_GLOBAL_HAIR, false);
+ psys->flag &= ~PSYS_GLOBAL_HAIR;
+
+ return ok;
+}
+
static int connect_hair_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
@@ -805,3 +907,284 @@ void PARTICLE_OT_connect_hair(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh");
}
+/************************ particle system copy operator *********************/
+
+typedef enum eCopyParticlesSpace {
+ PAR_COPY_SPACE_OBJECT = 0,
+ PAR_COPY_SPACE_WORLD = 1,
+} eCopyParticlesSpace;
+
+static void copy_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystem *psys_from)
+{
+ PTCacheEdit *edit_from = psys_from->edit, *edit;
+ ParticleData *pa;
+ KEY_K;
+ POINT_P;
+
+ if (!edit_from)
+ return;
+
+ edit = MEM_dupallocN(edit_from);
+ edit->psys = psys;
+ psys->edit = edit;
+
+ edit->pathcache = NULL;
+ BLI_listbase_clear(&edit->pathcachebufs);
+
+ edit->emitter_field = NULL;
+ edit->emitter_cosnos = NULL;
+
+ BLI_listbase_clear(&edit->undo);
+ edit->curundo = NULL;
+
+ edit->points = MEM_dupallocN(edit_from->points);
+ pa = psys->particles;
+ LOOP_POINTS {
+ HairKey *hkey = pa->hair;
+
+ point->keys= MEM_dupallocN(point->keys);
+ LOOP_KEYS {
+ key->co = hkey->co;
+ key->time = &hkey->time;
+ key->flag = hkey->editflag;
+ if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
+ key->flag |= PEK_USE_WCO;
+ hkey->editflag |= PEK_USE_WCO;
+ }
+
+ hkey++;
+ }
+
+ pa++;
+ }
+ update_world_cos(ob, edit);
+
+ UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col);
+ UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col);
+
+ recalc_lengths(edit);
+ recalc_emitter_field(ob, psys);
+ PE_update_object(scene, ob, true);
+
+ PTCacheUndo_clear(edit);
+ PE_undo_push(scene, "Original");
+}
+
+static void remove_particle_systems_from_object(Object *ob_to)
+{
+ ModifierData *md, *md_next;
+
+ if (ob_to->type != OB_MESH)
+ return;
+ if (!ob_to->data || ((ID *)ob_to->data)->lib)
+ return;
+
+ for (md = ob_to->modifiers.first; md; md = md_next) {
+ md_next = md->next;
+
+ /* remove all particle system modifiers as well,
+ * these need to sync to the particle system list
+ */
+ if (ELEM(md->type, eModifierType_ParticleSystem, eModifierType_DynamicPaint, eModifierType_Smoke)) {
+ BLI_remlink(&ob_to->modifiers, md);
+ modifier_free(md);
+ }
+ }
+
+ BKE_object_free_particlesystems(ob_to);
+}
+
+/* single_psys_from is optional, if NULL all psys of ob_from are copied */
+static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, ParticleSystem *single_psys_from, Object *ob_to, int space)
+{
+ ModifierData *md;
+ ParticleSystem *psys_start, *psys, *psys_from;
+ ParticleSystem **tmp_psys;
+ DerivedMesh *final_dm;
+ CustomDataMask cdmask;
+ int i, totpsys;
+
+ if (ob_to->type != OB_MESH)
+ return false;
+ if (!ob_to->data || ((ID *)ob_to->data)->lib)
+ return false;
+
+ /* For remapping we need a valid DM.
+ * Because the modifiers are appended at the end it's safe to use
+ * the final DM of the object without particles.
+ * However, when evaluating the DM all the particle modifiers must be valid,
+ * i.e. have the psys assigned already.
+ * To break this hen/egg problem we create all psys separately first (to collect required customdata masks),
+ * then create the DM, then add them to the object and make the psys modifiers ...
+ */
+ #define PSYS_FROM_FIRST (single_psys_from ? single_psys_from : ob_from->particlesystem.first)
+ #define PSYS_FROM_NEXT(cur) (single_psys_from ? NULL : (cur)->next)
+ totpsys = single_psys_from ? 1 : BLI_listbase_count(&ob_from->particlesystem);
+
+ tmp_psys = MEM_mallocN(sizeof(ParticleSystem*) * totpsys, "temporary particle system array");
+
+ cdmask = 0;
+ for (psys_from = PSYS_FROM_FIRST, i = 0;
+ psys_from;
+ psys_from = PSYS_FROM_NEXT(psys_from), ++i) {
+
+ psys = BKE_object_copy_particlesystem(psys_from);
+ tmp_psys[i] = psys;
+
+ if (psys_start == NULL)
+ psys_start = psys;
+
+ cdmask |= psys_emitter_customdata_mask(psys);
+ }
+ /* to iterate source and target psys in sync,
+ * we need to know where the newly added psys start
+ */
+ psys_start = totpsys > 0 ? tmp_psys[0] : NULL;
+
+ /* get the DM (psys and their modifiers have not been appended yet) */
+ final_dm = mesh_get_derived_final(scene, ob_to, cdmask);
+
+ /* now append psys to the object and make modifiers */
+ for (i = 0, psys_from = PSYS_FROM_FIRST;
+ i < totpsys;
+ ++i, psys_from = PSYS_FROM_NEXT(psys_from)) {
+
+ ParticleSystemModifierData *psmd;
+
+ psys = tmp_psys[i];
+
+ /* append to the object */
+ BLI_addtail(&ob_to->particlesystem, psys);
+
+ /* add a particle system modifier for each system */
+ md = modifier_new(eModifierType_ParticleSystem);
+ psmd = (ParticleSystemModifierData *)md;
+ /* push on top of the stack, no use trying to reproduce old stack order */
+ BLI_addtail(&ob_to->modifiers, md);
+
+ BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", i);
+ modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd);
+
+ psmd->psys = psys;
+ psmd->dm = CDDM_copy(final_dm);
+ CDDM_calc_normals(psmd->dm);
+ DM_ensure_tessface(psmd->dm);
+
+ if (psys_from->edit)
+ copy_particle_edit(scene, ob_to, psys, psys_from);
+ }
+ MEM_freeN(tmp_psys);
+
+ /* note: do this after creating DM copies for all the particle system modifiers,
+ * the remapping otherwise makes final_dm invalid!
+ */
+ for (psys = psys_start, psys_from = PSYS_FROM_FIRST, i = 0;
+ psys;
+ psys = psys->next, psys_from = PSYS_FROM_NEXT(psys_from), ++i) {
+
+ float (*from_mat)[4], (*to_mat)[4];
+
+ switch (space) {
+ case PAR_COPY_SPACE_OBJECT:
+ from_mat = I;
+ to_mat = I;
+ break;
+ case PAR_COPY_SPACE_WORLD:
+ from_mat = ob_from->obmat;
+ to_mat = ob_to->obmat;
+ break;
+ default:
+ /* should not happen */
+ BLI_assert(false);
+ break;
+ }
+
+ remap_hair_emitter(scene, ob_from, psys_from, ob_to, psys, psys->edit, from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR);
+
+ /* tag for recalc */
+// psys->recalc |= PSYS_RECALC_RESET;
+ }
+
+ #undef PSYS_FROM_FIRST
+ #undef PSYS_FROM_NEXT
+
+ DAG_id_tag_update(&ob_to->id, OB_RECALC_DATA);
+ WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to);
+ return true;
+}
+
+static int copy_particle_systems_poll(bContext *C)
+{
+ Object *ob;
+ if (!ED_operator_object_active_editable(C))
+ return false;
+
+ ob = ED_object_active_context(C);
+ if (BLI_listbase_is_empty(&ob->particlesystem))
+ return false;
+
+ return true;
+}
+
+static int copy_particle_systems_exec(bContext *C, wmOperator *op)
+{
+ const int space = RNA_enum_get(op->ptr, "space");
+ const bool remove_target_particles = RNA_boolean_get(op->ptr, "remove_target_particles");
+ const bool use_active = RNA_boolean_get(op->ptr, "use_active");
+ Scene *scene = CTX_data_scene(C);
+ Object *ob_from = ED_object_active_context(C);
+ ParticleSystem *psys_from = use_active ? CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data : NULL;
+
+ int changed_tot = 0;
+ int fail = 0;
+
+ CTX_DATA_BEGIN (C, Object *, ob_to, selected_editable_objects)
+ {
+ if (ob_from != ob_to) {
+ bool changed = false;
+ if (remove_target_particles) {
+ remove_particle_systems_from_object(ob_to);
+ changed = true;
+ }
+ if (copy_particle_systems_to_object(scene, ob_from, psys_from, ob_to, space))
+ changed = true;
+ else
+ fail++;
+
+ if (changed)
+ changed_tot++;
+ }
+ }
+ CTX_DATA_END;
+
+ if ((changed_tot == 0 && fail == 0) || fail) {
+ BKE_reportf(op->reports, RPT_ERROR,
+ "Copy particle systems to selected: %d done, %d failed",
+ changed_tot, fail);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_copy_particle_systems(wmOperatorType *ot)
+{
+ static EnumPropertyItem space_items[] = {
+ {PAR_COPY_SPACE_OBJECT, "OBJECT", 0, "Object", "Copy inside each object's local space"},
+ {PAR_COPY_SPACE_WORLD, "WORLD", 0, "World", "Copy in world space"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ ot->name = "Copy Particle Systems";
+ ot->description = "Copy particle systems from the active object to selected objects";
+ ot->idname = "PARTICLE_OT_copy_particle_systems";
+
+ ot->poll = copy_particle_systems_poll;
+ ot->exec = copy_particle_systems_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "space", space_items, PAR_COPY_SPACE_OBJECT, "Space", "Space transform for copying from one object to another");
+ RNA_def_boolean(ot->srna, "remove_target_particles", true, "Remove Target Particles", "Remove particle systems on the target objects");
+ RNA_def_boolean(ot->srna, "use_active", false, "Use Active", "Use the active particle system from the context");
+}
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index 8c49bf21191..88542515553 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -56,6 +56,8 @@ void PARTICLE_OT_mirror(struct wmOperatorType *ot);
void PARTICLE_OT_brush_edit(struct wmOperatorType *ot);
+void PARTICLE_OT_shape_cut(struct wmOperatorType *ot);
+
void PARTICLE_OT_particle_edit_toggle(struct wmOperatorType *ot);
void PARTICLE_OT_edited_clear(struct wmOperatorType *ot);
@@ -70,6 +72,7 @@ void PARTICLE_OT_target_move_up(struct wmOperatorType *ot);
void PARTICLE_OT_target_move_down(struct wmOperatorType *ot);
void PARTICLE_OT_connect_hair(struct wmOperatorType *ot);
void PARTICLE_OT_disconnect_hair(struct wmOperatorType *ot);
+void PARTICLE_OT_copy_particle_systems(struct wmOperatorType *ot);
void PARTICLE_OT_dupliob_copy(struct wmOperatorType *ot);
void PARTICLE_OT_dupliob_remove(struct wmOperatorType *ot);
diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c
index 37cf95e5c2d..8f32b0dffe9 100644
--- a/source/blender/editors/physics/physics_ops.c
+++ b/source/blender/editors/physics/physics_ops.c
@@ -64,6 +64,8 @@ static void operatortypes_particle(void)
WM_operatortype_append(PARTICLE_OT_brush_edit);
+ WM_operatortype_append(PARTICLE_OT_shape_cut);
+
WM_operatortype_append(PARTICLE_OT_particle_edit_toggle);
WM_operatortype_append(PARTICLE_OT_edited_clear);
@@ -78,6 +80,7 @@ static void operatortypes_particle(void)
WM_operatortype_append(PARTICLE_OT_target_move_down);
WM_operatortype_append(PARTICLE_OT_connect_hair);
WM_operatortype_append(PARTICLE_OT_disconnect_hair);
+ WM_operatortype_append(PARTICLE_OT_copy_particle_systems);
WM_operatortype_append(PARTICLE_OT_dupliob_copy);
WM_operatortype_append(PARTICLE_OT_dupliob_remove);
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 8024add41cf..fc6ff4eb0c0 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -315,8 +315,9 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
/* rr->rectf is now filled with image data */
- if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW))
- BKE_stamp_buf(scene, camera, rect, rr->rectf, rr->rectx, rr->recty, 4);
+ if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) {
+ BKE_image_stamp_buf(scene, camera, rect, rr->rectf, rr->rectx, rr->recty, 4);
+ }
RE_ReleaseResult(oglrender->re);
@@ -335,8 +336,9 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
IMB_color_to_bw(ibuf);
}
- BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false);
+ BKE_image_path_from_imformat(
+ name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
+ &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false);
ok = BKE_imbuf_write_as(ibuf, name, &scene->r.im_format, true); /* no need to stamp here */
if (ok) printf("OpenGL Render written to '%s'\n", name);
else printf("OpenGL Render failed to write '%s'\n", name);
@@ -564,8 +566,9 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
if (!is_movie) {
- BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
- &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true);
+ BKE_image_path_from_imformat(
+ name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
+ &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true);
if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) {
BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name);
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index ea80a07fdd4..99edaff759e 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -359,7 +359,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
for (base = sce->base.first; base; base = base->next) {
if (base->object->type == OB_LAMP) {
/* if doesn't match 'Lamp.002' --> main key light */
- if (strcmp(base->object->id.name + 2, "Lamp.002") != 0) {
+ if (!STREQ(base->object->id.name + 2, "Lamp.002")) {
if (mat->material_type == MA_TYPE_VOLUME)
base->object->restrictflag |= OB_RESTRICT_RENDER;
else
@@ -1100,7 +1100,7 @@ static void icon_preview_free(void *customdata)
void ED_preview_icon_render(Scene *scene, ID *id, unsigned int *rect, int sizex, int sizey)
{
- IconPreview ip = {0};
+ IconPreview ip = {NULL};
short stop = false, update = false;
float progress = 0.0f;
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 91c689373be..94a3defa95a 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -1412,7 +1412,7 @@ static int envmap_save_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", path);
if (scene->r.scemode & R_EXTENSION) {
- BKE_add_image_extension(path, &scene->r.im_format);
+ BKE_image_path_ensure_ext_from_imformat(path, &scene->r.im_format);
}
WM_cursor_wait(1);
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index ab28f5fa675..fe357a7a0e2 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -161,11 +161,19 @@ ScrArea *render_view_open(bContext *C, int mx, int my)
}
else if (scene->r.displaymode == R_OUTPUT_SCREEN) {
sa = CTX_wm_area(C);
- if (sa && sa->spacetype == SPACE_IMAGE)
- area_was_image = true;
- /* this function returns with changed context */
- sa = ED_screen_full_newspace(C, sa, SPACE_IMAGE);
+ /* if the active screen is already in fullscreen mode, skip this and
+ * unset the area, so that the fullscreen area is just changed later */
+ if (sa && sa->full) {
+ sa = NULL;
+ }
+ else {
+ if (sa && sa->spacetype == SPACE_IMAGE)
+ area_was_image = true;
+
+ /* this function returns with changed context */
+ sa = ED_screen_full_newspace(C, sa, SPACE_IMAGE);
+ }
}
if (!sa) {
@@ -186,10 +194,15 @@ ScrArea *render_view_open(bContext *C, int mx, int my)
/* makes ESC go back to prev space */
sima->flag |= SI_PREVSPACE;
+
+ /* we already had a fullscreen here -> mark new space as a stacked fullscreen */
+ if (sa->full) {
+ sa->flag |= AREA_FLAG_STACKED_FULLSCREEN;
+ }
}
else {
/* use any area of decent size */
- sa = BKE_screen_find_big_area(CTX_wm_screen(C), -1, 0);
+ sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TYPE_ANY, 0);
if (sa->spacetype != SPACE_IMAGE) {
// XXX newspace(sa, SPACE_IMAGE);
sima = sa->spacedata.first;
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 71714bdcda9..83b22bb1a8a 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -1645,6 +1645,8 @@ void ED_area_prevspace(bContext *C, ScrArea *sa)
/* no change */
return;
}
+ sa->flag &= ~AREA_FLAG_STACKED_FULLSCREEN;
+
ED_area_tag_redraw(sa);
/* send space change notifier */
@@ -2161,4 +2163,3 @@ void ED_region_cache_draw_cached_segments(const ARegion *ar, const int num_segme
}
}
}
-
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 134feb59d55..4c1698bd1d4 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -1136,9 +1136,9 @@ void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int
void cpack(unsigned int x)
{
- glColor3ub( ( (x) & 0xFF),
- (((x) >> 8) & 0xFF),
- (((x) >> 16) & 0xFF) );
+ glColor3ub(( (x) & 0xFF),
+ (((x) >> 8) & 0xFF),
+ (((x) >> 16) & 0xFF));
}
void glaDrawBorderCorners(const rcti *border, float zoomx, float zoomy)
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index ce9c608247b..3431ce9f50a 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -497,7 +497,9 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
bGPDstroke *gps;
for (gps = gpf->strokes.first; gps; gps = gps->next) {
- CTX_data_list_add(result, &gpd->id, &RNA_GPencilStroke, gps);
+ if (ED_gpencil_stroke_can_use_direct(sa, gps)) {
+ CTX_data_list_add(result, &gpd->id, &RNA_GPencilStroke, gps);
+ }
}
}
}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 3972d00293c..f338fa160f5 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1762,15 +1762,16 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
void ED_screen_full_prevspace(bContext *C, ScrArea *sa)
{
- wmWindow *win = CTX_wm_window(C);
-
- ED_area_prevspace(C, sa);
-
- if (sa->full)
- ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
+ if (sa->flag & AREA_FLAG_STACKED_FULLSCREEN) {
+ /* stacked fullscreen -> only go back to previous screen and don't toggle out of fullscreen */
+ ED_area_prevspace(C, sa);
+ }
+ else {
+ ED_screen_restore_temp_type(C, sa);
+ }
}
-void ED_screen_retore_temp_type(bContext *C, ScrArea *sa, bool is_screen_change)
+void ED_screen_restore_temp_type(bContext *C, ScrArea *sa)
{
/* incase nether functions below run */
ED_area_tag_redraw(sa);
@@ -1780,7 +1781,7 @@ void ED_screen_retore_temp_type(bContext *C, ScrArea *sa, bool is_screen_change)
sa->flag &= ~AREA_FLAG_TEMP_TYPE;
}
- if (is_screen_change && sa->full) {
+ if (sa->full) {
ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
}
}
@@ -1793,25 +1794,11 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa)
bScreen *screen = CTX_wm_screen(C);
short state = (screen ? screen->state : SCREENMAXIMIZED);
- /* if fullscreen area has a secondary space (such as a file browser or fullscreen render
- * overlaid on top of a existing setup) then return to the previous space */
+ /* if fullscreen area has a temporary space (such as a file browser or fullscreen render
+ * overlaid on top of an existing setup) then return to the previous space */
if (sl->next) {
- /* specific checks for space types */
-
- /* Special check added for non-render image window (back from fullscreen through "Back to Previous" button) */
- if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
-
- if (sima->flag & (SI_PREVSPACE | SI_FULLWINDOW)) {
- sima->flag &= ~SI_PREVSPACE;
- sima->flag &= ~SI_FULLWINDOW;
- ED_screen_full_prevspace(C, sa);
- }
- else
- ED_screen_state_toggle(C, win, sa, state);
- }
- else if (sa->flag & AREA_FLAG_TEMP_TYPE) {
+ if (sa->flag & AREA_FLAG_TEMP_TYPE) {
ED_screen_full_prevspace(C, sa);
}
else {
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 39321ec0770..ad3d2d1a21a 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -598,19 +598,6 @@ typedef struct sActionzoneData {
int x, y, gesture_dir, modifier;
} sActionzoneData;
-/* used by other operators too */
-static ScrArea *screen_areahascursor(bScreen *scr, int x, int y)
-{
- ScrArea *sa = NULL;
- sa = scr->areabase.first;
- while (sa) {
- if (BLI_rcti_isect_pt(&sa->totrct, x, y)) break;
- sa = sa->next;
- }
-
- return sa;
-}
-
/* quick poll to save operators to be created and handled */
static int actionzone_area_poll(bContext *C)
{
@@ -808,7 +795,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* gesture is large enough? */
if (is_gesture) {
/* second area, for join when (sa1 != sa2) */
- sad->sa2 = screen_areahascursor(sc, event->x, event->y);
+ sad->sa2 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, event->x, event->y);
/* apply sends event */
actionzone_apply(C, op, sad->az->type);
actionzone_exit(op);
@@ -929,7 +916,7 @@ static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->type) {
case MOUSEMOVE:
/* second area, for join */
- sad->sa2 = screen_areahascursor(CTX_wm_screen(C), event->x, event->y);
+ sad->sa2 = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, event->x, event->y);
break;
case LEFTMOUSE: /* release LMB */
if (event->val == KM_RELEASE) {
@@ -1679,7 +1666,8 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
sd->sarea->flag &= ~(AREA_FLAG_DRAWSPLIT_H | AREA_FLAG_DRAWSPLIT_V);
ED_area_tag_redraw(sd->sarea);
}
- sd->sarea = screen_areahascursor(CTX_wm_screen(C), event->x, event->y); /* area context not set */
+ /* area context not set */
+ sd->sarea = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, event->x, event->y);
if (sd->sarea) {
ED_area_tag_redraw(sd->sarea);
@@ -2482,8 +2470,8 @@ static int area_join_init(bContext *C, wmOperator *op)
x2 = RNA_int_get(op->ptr, "max_x");
y2 = RNA_int_get(op->ptr, "max_y");
- sa1 = screen_areahascursor(CTX_wm_screen(C), x1, y1);
- sa2 = screen_areahascursor(CTX_wm_screen(C), x2, y2);
+ sa1 = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, x1, y1);
+ sa2 = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, x2, y2);
if (sa1 == NULL || sa2 == NULL || sa1 == sa2)
return 0;
@@ -2616,7 +2604,7 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
case MOUSEMOVE:
{
- ScrArea *sa = screen_areahascursor(sc, event->x, event->y);
+ ScrArea *sa = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, event->x, event->y);
int dir;
if (sa) {
@@ -3399,7 +3387,12 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
(sad->flag & ANIMPLAY_FLAG_REVERSE) == false &&
finite(time = sound_sync_scene(scene)))
{
- scene->r.cfra = (double)time * FPS + 0.5;
+ double newfra = (double)time * FPS;
+ /* give some space here to avoid jumps */
+ if (newfra + 0.5 > scene->r.cfra && newfra - 0.5 < scene->r.cfra)
+ scene->r.cfra++;
+ else
+ scene->r.cfra = newfra + 0.5;
}
else {
if (sync) {
@@ -3476,11 +3469,29 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
for (sa = window->screen->areabase.first; sa; sa = sa->next) {
ARegion *ar;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ bool redraw = false;
if (ar == sad->ar) {
- ED_region_tag_redraw(ar);
+ redraw = true;
}
else if (match_region_with_redraws(sa->spacetype, ar->regiontype, sad->redraws)) {
+ redraw = true;
+ }
+
+ if (redraw) {
ED_region_tag_redraw(ar);
+ /* do follow here if editor type supports it */
+ if ((sad->redraws & TIME_FOLLOW)) {
+ if ((ar->regiontype == RGN_TYPE_WINDOW &&
+ ELEM (sa->spacetype, SPACE_SEQ, SPACE_TIME, SPACE_IPO, SPACE_ACTION, SPACE_NLA)) ||
+ (sa->spacetype == SPACE_CLIP && ar->regiontype == RGN_TYPE_PREVIEW))
+ {
+ float w = BLI_rctf_size_x(&ar->v2d.cur);
+ if (scene->r.cfra < ar->v2d.cur.xmin || scene->r.cfra > (ar->v2d.cur.xmax)) {
+ ar->v2d.cur.xmin = scene->r.cfra;
+ ar->v2d.cur.xmax = ar->v2d.cur.xmin + w;
+ }
+ }
+ }
}
}
@@ -3546,6 +3557,8 @@ int ED_screen_animation_play(bContext *C, int sync, int mode)
/* stop playback now */
ED_screen_animation_timer(C, 0, 0, 0, 0);
sound_stop_scene(scene);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
else {
int refresh = SPACE_TIME; /* these settings are currently only available from a menu in the TimeLine */
@@ -3707,9 +3720,9 @@ static int fullscreen_back_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No fullscreen areas were found");
return OPERATOR_CANCELLED;
}
-
- ED_screen_full_restore(C, sa);
-
+
+ ED_screen_full_prevspace(C, sa);
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index e7f256e414a..9c05f1d4780 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -377,8 +377,9 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
char name[FILE_MAX];
int ok;
- BKE_makepicstring(name, rd.pic, sj->bmain->name, rd.cfra,
- &rd.im_format, (rd.scemode & R_EXTENSION) != 0, true);
+ BKE_image_path_from_imformat(
+ name, rd.pic, sj->bmain->name, rd.cfra,
+ &rd.im_format, (rd.scemode & R_EXTENSION) != 0, true);
ibuf->rect = sj->dumprect;
ok = BKE_imbuf_write(ibuf, name, &rd.im_format);
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 430ea1cc11d..2d425b7e5a0 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -652,16 +652,12 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
}
/* set quad color. Colored overlay does not get blending */
- if (col)
- glColor4f(1.0,
- 1.0,
- 1.0,
- overlay_alpha / 100.0f);
- else
- glColor4f(U.sculpt_paint_overlay_col[0],
- U.sculpt_paint_overlay_col[1],
- U.sculpt_paint_overlay_col[2],
- overlay_alpha / 100.0f);
+ if (col) {
+ glColor4f(1.0, 1.0, 1.0, overlay_alpha / 100.0f);
+ }
+ else {
+ glColor4f(UNPACK3(U.sculpt_paint_overlay_col), overlay_alpha / 100.0f);
+ }
/* draw textured quad */
glBegin(GL_QUADS);
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
index 1f5ee708ad0..439c2a639bd 100644
--- a/source/blender/editors/sculpt_paint/paint_curve.c
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -108,7 +108,7 @@ static void paintcurve_undo_restore(bContext *C, ListBase *lb)
uc = (UndoCurve *)lb->first;
- if (strncmp(uc->idname, pc->id.name, BLI_strnlen(uc->idname, sizeof(uc->idname))) == 0) {
+ if (STREQLEN(uc->idname, pc->id.name, BLI_strnlen(uc->idname, sizeof(uc->idname)))) {
SWAP(PaintCurvePoint *, pc->points, uc->points);
SWAP(int, pc->tot_points, uc->tot_points);
SWAP(int, pc->add_index, uc->active_point);
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index d52b17372f7..5cfbd164153 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -158,9 +158,10 @@ static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, Cop
}
}
else {
- if (mode == RESTORE_COPY)
+ if (mode == RESTORE_COPY) {
IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
- tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+ tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+ }
/* swap to the tmpbuf for easy copying */
if (ibuf->rect_float) {
SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
@@ -192,7 +193,7 @@ void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsi
for (tile = lb->first; tile; tile = tile->next) {
if (tile->x == x_tile && tile->y == y_tile && ima->gen_type == tile->gen_type && ima->source == tile->source) {
if (tile->use_float == use_float) {
- if (strcmp(tile->idname, ima->id.name) == 0 && strcmp(tile->ibufname, ibuf->name) == 0) {
+ if (STREQ(tile->idname, ima->id.name) && STREQ(tile->ibufname, ibuf->name)) {
if (mask) {
/* allocate mask if requested */
if (!tile->mask) {
@@ -327,7 +328,7 @@ void ED_image_undo_restore(bContext *C, ListBase *lb)
short use_float;
/* find image based on name, pointer becomes invalid with global undo */
- if (ima && strcmp(tile->idname, ima->id.name) == 0) {
+ if (ima && STREQ(tile->idname, ima->id.name)) {
/* ima is valid */
}
else {
@@ -336,7 +337,7 @@ void ED_image_undo_restore(bContext *C, ListBase *lb)
ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- if (ima && ibuf && strcmp(tile->ibufname, ibuf->name) != 0) {
+ if (ima && ibuf && !STREQ(tile->ibufname, ibuf->name)) {
/* current ImBuf filename was changed, probably current frame
* was changed when painting on image sequence, rather than storing
* full image user (which isn't so obvious, btw) try to find ImBuf with
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 3e675012d05..098477ed2a1 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -203,6 +203,7 @@ typedef struct ProjPaintState {
/* the paint color. It can change depending of inverted mode or not */
float paint_color[3];
float paint_color_linear[3];
+ float dither;
Brush *brush;
short tool, blend, mode;
@@ -422,17 +423,19 @@ static int project_bucket_offset_safe(const ProjPaintState *ps, const float proj
}
}
-static float VecZDepthOrtho(const float pt[2],
- const float v1[3], const float v2[3], const float v3[3],
- float w[3])
+static float VecZDepthOrtho(
+ const float pt[2],
+ const float v1[3], const float v2[3], const float v3[3],
+ float w[3])
{
barycentric_weights_v2(v1, v2, v3, pt, w);
return (v1[2] * w[0]) + (v2[2] * w[1]) + (v3[2] * w[2]);
}
-static float VecZDepthPersp(const float pt[2],
- const float v1[4], const float v2[4], const float v3[4],
- float w[3])
+static float VecZDepthPersp(
+ const float pt[2],
+ const float v1[4], const float v2[4], const float v3[4],
+ float w[3])
{
float wtot_inv, wtot;
float w_tmp[3];
@@ -542,8 +545,9 @@ static void uvco_to_wrapped_pxco(const float uv[2], int ibuf_x, int ibuf_y, floa
}
/* Set the top-most face color that the screen space coord 'pt' touches (or return 0 if none touch) */
-static bool project_paint_PickColor(const ProjPaintState *ps, const float pt[2],
- float *rgba_fp, unsigned char *rgba, const bool interp)
+static bool project_paint_PickColor(
+ const ProjPaintState *ps, const float pt[2],
+ float *rgba_fp, unsigned char *rgba, const bool interp)
{
float w[3], uv[2];
int side;
@@ -637,9 +641,10 @@ static bool project_paint_PickColor(const ProjPaintState *ps, const float pt[2],
* 1 : occluded
* 2 : occluded with w[3] weights set (need to know in some cases) */
-static int project_paint_occlude_ptv(const float pt[3],
- const float v1[4], const float v2[4], const float v3[4],
- float w[3], const bool is_ortho)
+static int project_paint_occlude_ptv(
+ const float pt[3],
+ const float v1[4], const float v2[4], const float v3[4],
+ float w[3], const bool is_ortho)
{
/* if all are behind us, return false */
if (v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2])
@@ -669,9 +674,10 @@ static int project_paint_occlude_ptv(const float pt[3],
}
-static int project_paint_occlude_ptv_clip(const ProjPaintState *ps, const MFace *mf,
- const float pt[3], const float v1[4], const float v2[4], const float v3[4],
- const int side)
+static int project_paint_occlude_ptv_clip(
+ const ProjPaintState *ps, const MFace *mf,
+ const float pt[3], const float v1[4], const float v2[4], const float v3[4],
+ const int side)
{
float w[3], wco[3];
int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, ps->is_ortho);
@@ -699,8 +705,9 @@ static int project_paint_occlude_ptv_clip(const ProjPaintState *ps, const MFace
/* Check if a screenspace location is occluded by any other faces
* check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison
* and doesn't need to be correct in relation to X and Y coords (this is the case in perspective view) */
-static bool project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *bucketFace,
- const int orig_face, const float pixelScreenCo[4])
+static bool project_bucket_point_occluded(
+ const ProjPaintState *ps, LinkNode *bucketFace,
+ const int orig_face, const float pixelScreenCo[4])
{
MFace *mf;
int face_index;
@@ -912,9 +919,10 @@ static void project_face_winding_init(const ProjPaintState *ps, const int face_i
/* This function returns 1 if this face has a seam along the 2 face-vert indices
* 'orig_i1_fidx' and 'orig_i2_fidx' */
-static bool check_seam(const ProjPaintState *ps,
- const int orig_face, const int orig_i1_fidx, const int orig_i2_fidx,
- int *other_face, int *orig_fidx)
+static bool check_seam(
+ const ProjPaintState *ps,
+ const int orig_face, const int orig_i1_fidx, const int orig_i2_fidx,
+ int *other_face, int *orig_fidx)
{
LinkNode *node;
int face_index;
@@ -1003,8 +1011,9 @@ BLI_INLINE float shell_v2v2_normal_dir_to_dist(float n[2], float d[2])
/* Calculate outset UV's, this is not the same as simply scaling the UVs,
* since the outset coords are a margin that keep an even distance from the original UV's,
* note that the image aspect is taken into account */
-static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const float scaler,
- const int ibuf_x, const int ibuf_y, const bool is_quad, const bool cw)
+static void uv_image_outset(
+ float (*orig_uv)[2], float (*outset_uv)[2], const float scaler,
+ const int ibuf_x, const int ibuf_y, const bool is_quad, const bool cw)
{
float a1, a2, a3, a4 = 0.0f;
float puv[4][2]; /* pixelspace uv's */
@@ -1212,8 +1221,9 @@ static void screen_px_from_persp(
}
-static void project_face_pixel(const MTFace *tf_other, ImBuf *ibuf_other, const float w[3],
- int side, unsigned char rgba_ub[4], float rgba_f[4])
+static void project_face_pixel(
+ const MTFace *tf_other, ImBuf *ibuf_other, const float w[3],
+ int side, unsigned char rgba_ub[4], float rgba_f[4])
{
const float *uvCo1, *uvCo2, *uvCo3;
float uv_other[2], x, y;
@@ -1454,7 +1464,7 @@ static ProjPixel *project_paint_uvpixel_init(
y_px = mod_i(y_px, ibuf->y);
BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool));
- projPixel = (ProjPixel *)BLI_memarena_alloc(arena, ps->pixel_sizeof);
+ projPixel = BLI_memarena_alloc(arena, ps->pixel_sizeof);
/* calculate the undo tile offset of the pixel, used to store the original
* pixel color and accumulated mask if any */
@@ -1585,7 +1595,7 @@ static ProjPixel *project_paint_uvpixel_init(
}
static bool line_clip_rect2f(
- rctf *rect,
+ const rctf *rect,
const float l1[2], const float l2[2],
float l1_clip[2], float l2_clip[2])
{
@@ -1800,7 +1810,7 @@ static float len_squared_v2v2_alt(const float v1[2], const float v2_1, const flo
/* note, use a squared value so we can use len_squared_v2v2
* be sure that you have done a bounds check first or this may fail */
/* only give bucket_bounds as an arg because we need it elsewhere */
-static bool project_bucket_isect_circle(const float cent[2], const float radius_squared, rctf *bucket_bounds)
+static bool project_bucket_isect_circle(const float cent[2], const float radius_squared, const rctf *bucket_bounds)
{
/* Would normally to a simple intersection test, however we know the bounds of these 2 already intersect
@@ -1855,7 +1865,7 @@ static bool project_bucket_isect_circle(const float cent[2], const float radius_
* however switching back to this for ortho is always an option */
static void rect_to_uvspace_ortho(
- rctf *bucket_bounds,
+ const rctf *bucket_bounds,
const float *v1coSS, const float *v2coSS, const float *v3coSS,
const float *uv1co, const float *uv2co, const float *uv3co,
float bucket_bounds_uv[4][2],
@@ -1888,7 +1898,7 @@ static void rect_to_uvspace_ortho(
/* same as above but use barycentric_weights_v2_persp */
static void rect_to_uvspace_persp(
- rctf *bucket_bounds,
+ const rctf *bucket_bounds,
const float *v1coSS, const float *v2coSS, const float *v3coSS,
const float *uv1co, const float *uv2co, const float *uv3co,
float bucket_bounds_uv[4][2],
@@ -1964,7 +1974,7 @@ static int float_z_sort(const void *p1, const void *p2)
/* assumes one point is within the rectangle */
static void line_rect_clip(
- rctf *rect,
+ const rctf *rect,
const float l1[4], const float l2[4],
const float uv1[2], const float uv2[2],
float uv[2], bool is_ortho)
@@ -1989,14 +1999,14 @@ static void line_rect_clip(
tmp = (is_ortho) ? 1.0f : (l1[3] + min * (l2[3] - l1[3]));
- uv[0] = (uv1[0] + min * (uv2[0] - uv1[0])) / tmp;
- uv[1] = (uv1[1] + min * (uv2[1] - uv1[1])) / tmp;
+ uv[0] = (uv1[0] + min / tmp * (uv2[0] - uv1[0]));
+ uv[1] = (uv1[1] + min / tmp * (uv2[1] - uv1[1]));
}
static void project_bucket_clip_face(
const bool is_ortho,
- rctf *bucket_bounds,
+ const rctf *bucket_bounds,
float *v1coSS, float *v2coSS, float *v3coSS,
const float *uv1co, const float *uv2co, const float *uv3co,
float bucket_bounds_uv[8][2],
@@ -2004,7 +2014,8 @@ static void project_bucket_clip_face(
{
int inside_bucket_flag = 0;
int inside_face_flag = 0;
- const int flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
+ const int flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) !=
+ (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
bool colinear = false;
float bucket_bounds_ss[4][2];
@@ -2020,7 +2031,8 @@ static void project_bucket_clip_face(
inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v3coSS) << 2;
if (inside_bucket_flag == ISECT_ALL3) {
- /* all screenspace points are inside the bucket bounding box, this means we don't need to clip and can simply return the UVs */
+ /* all screenspace points are inside the bucket bounding box,
+ * this means we don't need to clip and can simply return the UVs */
if (flip) { /* facing the back? */
copy_v2_v2(bucket_bounds_uv[0], uv3co);
copy_v2_v2(bucket_bounds_uv[1], uv2co);
@@ -2076,8 +2088,8 @@ static void project_bucket_clip_face(
/* at this point we have all uv points needed in a row. all that's needed is to invert them if necessary */
if (flip) {
/* flip only to the middle of the array */
- int i, max = *tot / 2;
- for (i = 0; i < max; i++) {
+ int i, max = *tot - 1, mid = *tot / 2;
+ for (i = 0; i < mid; i++) {
SWAP(float, bucket_bounds_uv[i][0], bucket_bounds_uv[max - i][0]);
SWAP(float, bucket_bounds_uv[i][1], bucket_bounds_uv[max - i][1]);
}
@@ -2205,7 +2217,8 @@ static void project_bucket_clip_face(
for (i = 0; i < (*tot); i++) {
v2_clipSS[0] = isectVCosSS[i][0] - cent[0];
v2_clipSS[1] = isectVCosSS[i][1] - cent[1];
- isectVCosSS[i][2] = atan2f(v1_clipSS[0] * v2_clipSS[1] - v1_clipSS[1] * v2_clipSS[0], v1_clipSS[0] * v2_clipSS[0] + v1_clipSS[1] * v2_clipSS[1]);
+ isectVCosSS[i][2] = atan2f(v1_clipSS[0] * v2_clipSS[1] - v1_clipSS[1] * v2_clipSS[0],
+ v1_clipSS[0] * v2_clipSS[0] + v1_clipSS[1] * v2_clipSS[1]);
}
if (flip) qsort(isectVCosSS, *tot, sizeof(float) * 3, float_z_sort_flip);
@@ -2260,7 +2273,9 @@ static void project_bucket_clip_face(
int i;
if (is_ortho) rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
else rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
- printf("( [(%f,%f), (%f,%f), (%f,%f), (%f,%f)], ", test_uv[0][0], test_uv[0][1], test_uv[1][0], test_uv[1][1], test_uv[2][0], test_uv[2][1], test_uv[3][0], test_uv[3][1]);
+ printf("( [(%f,%f), (%f,%f), (%f,%f), (%f,%f)], ",
+ test_uv[0][0], test_uv[0][1], test_uv[1][0], test_uv[1][1],
+ test_uv[2][0], test_uv[2][1], test_uv[3][0], test_uv[3][1]);
printf(" [(%f,%f), (%f,%f), (%f,%f)], ", uv1co[0], uv1co[1], uv2co[0], uv2co[1], uv3co[0], uv3co[1]);
@@ -2358,9 +2373,15 @@ static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot
return 1;
}
-/* One of the most important function for projection painting, since it selects the pixels to be added into each bucket.
- * initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */
-static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf, const short clamp_u, const short clamp_v)
+/* One of the most important function for projection painting,
+ * since it selects the pixels to be added into each bucket.
+ *
+ * initialize pixels from this face where it intersects with the bucket_index,
+ * optionally initialize pixels for removing seams */
+static void project_paint_face_init(
+ const ProjPaintState *ps,
+ const int thread_index, const int bucket_index, const int face_index, const int image_index,
+ const rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf, const short clamp_u, const short clamp_v)
{
/* Projection vars, to get the 3D locations into screen space */
MemArena *arena = ps->arena_mt[thread_index];
@@ -2824,7 +2845,7 @@ static void project_bucket_bounds(const ProjPaintState *ps, const int bucket_x,
/* Fill this bucket with pixels from the faces that intersect it.
*
* have bucket_bounds as an argument so we don't need to give bucket_x/y the rect function needs */
-static void project_bucket_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, rctf *bucket_bounds)
+static void project_bucket_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const rctf *bucket_bounds)
{
LinkNode *node;
int face_index, image_index = 0;
@@ -3000,145 +3021,9 @@ static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf,
#endif
}
-/* run once per stroke before projection painting */
-static void project_paint_begin(ProjPaintState *ps)
+/* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
+static void proj_paint_state_non_cddm_init(ProjPaintState *ps)
{
- /* Viewport vars */
- float mat[3][3];
-
- float no[3];
-
- float *projScreenCo; /* Note, we could have 4D vectors are only needed for */
- float projMargin;
-
- /* Image Vars - keep track of images we have used */
- LinkNode *image_LinkList = NULL;
- LinkNode *node;
-
- ProjPaintImage *projIma;
- Image *tpage_last = NULL, *tpage;
- TexPaintSlot *slot_last = NULL, *slot = NULL;
- TexPaintSlot *slot_last_clone = NULL, *slot_clone;
-
- /* Face vars */
- MPoly *mpoly_orig;
- MFace *mf;
- MTFace **tf;
- MTFace *tf_base;
-
- MTFace **tf_clone;
- MTFace *tf_clone_base = NULL;
-
- int a, i; /* generic looping vars */
- int image_index = -1, face_index;
-
- /* double lookup */
- const int *index_mf_to_mpoly = NULL;
- const int *index_mp_to_orig = NULL;
-
- MVert *mv;
-
- MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */
-
- const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush);
-
- bool reset_threads = false;
-
- /* ---- end defines ---- */
-
- if (ps->source == PROJ_SRC_VIEW)
- ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */
-
- ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0);
-
- /* paint onto the derived mesh */
-
- /* Workaround for subsurf selection, try the display mesh first */
- if (ps->source == PROJ_SRC_IMAGE_CAM) {
- /* using render mesh, assume only camera was rendered from */
- ps->dm = mesh_create_derived_render(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE);
- ps->dm_release = true;
- }
- else if (ps->ob->derivedFinal &&
- CustomData_has_layer(&ps->ob->derivedFinal->faceData, CD_MTFACE) &&
- (ps->do_face_sel == false || CustomData_has_layer(&ps->ob->derivedFinal->polyData, CD_ORIGINDEX)))
- {
- ps->dm = ps->ob->derivedFinal;
- ps->dm_release = false;
- }
- else {
- ps->dm = mesh_get_derived_final(
- ps->scene, ps->ob,
- ps->scene->customdata_mask | CD_MASK_MTFACE | (ps->do_face_sel ? CD_ORIGINDEX : 0));
- ps->dm_release = true;
- }
-
- if (!CustomData_has_layer(&ps->dm->faceData, CD_MTFACE)) {
-
- if (ps->dm_release)
- ps->dm->release(ps->dm);
-
- ps->dm = NULL;
- return;
- }
-
- DM_update_materials(ps->dm, ps->ob);
-
- ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
- ps->dm_totface = ps->dm->getNumTessFaces(ps->dm);
-
- ps->dm_mvert = ps->dm->getVertArray(ps->dm);
- ps->dm_mface = ps->dm->getTessFaceArray(ps->dm);
- ps->dm_mtface = MEM_mallocN(ps->dm_totface * sizeof(MTFace *), "proj_paint_mtfaces");
-
- if (ps->do_face_sel) {
- index_mf_to_mpoly = ps->dm->getTessFaceDataArray(ps->dm, CD_ORIGINDEX);
- index_mp_to_orig = ps->dm->getPolyDataArray(ps->dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
- else {
- mpoly_orig = ((Mesh *)ps->ob->data)->mpoly;
- }
- }
- else {
- mpoly_orig = NULL;
- }
-
- /* use clone mtface? */
- if (ps->do_layer_clone) {
- ps->dm_mtface_clone = MEM_mallocN(ps->dm_totface * sizeof(MTFace *), "proj_paint_mtfaces");
- }
-
- if (ps->do_layer_stencil || ps->do_stencil_brush) {
- //int layer_num = CustomData_get_stencil_layer(&ps->dm->faceData, CD_MTFACE);
- int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
- if (layer_num != -1)
- ps->dm_mtface_stencil = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
-
- if (ps->dm_mtface_stencil == NULL) {
- /* get active instead */
- ps->dm_mtface_stencil = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
- }
-
- if (ps->do_stencil_brush)
- tf_base = ps->dm_mtface_stencil;
- }
-
- if (ps->do_layer_clone) {
- int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
-
- if (layer_num != -1)
- tf_clone_base = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
-
- if (tf_clone_base == NULL) {
- /* get active instead */
- tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
- }
-
- }
-
- /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
if (ps->dm->type != DM_TYPE_CDDM) {
ps->dm_mvert = MEM_dupallocN(ps->dm_mvert);
ps->dm_mface = MEM_dupallocN(ps->dm_mface);
@@ -3149,97 +3034,108 @@ static void project_paint_begin(ProjPaintState *ps)
ps->dm_mtface_stencil = MEM_dupallocN(ps->dm_mtface_stencil);
#endif
}
+}
+
+static void proj_paint_state_viewport_init(ProjPaintState *ps)
+{
+ float mat[3][3];
+ float viewmat[4][4];
+ float viewinv[4][4];
ps->viewDir[0] = 0.0f;
ps->viewDir[1] = 0.0f;
ps->viewDir[2] = 1.0f;
- {
- float viewmat[4][4];
- float viewinv[4][4];
+ invert_m4_m4(ps->ob->imat, ps->ob->obmat);
- invert_m4_m4(ps->ob->imat, ps->ob->obmat);
+ if (ELEM(ps->source, PROJ_SRC_VIEW, PROJ_SRC_VIEW_FILL)) {
+ /* normal drawing */
+ ps->winx = ps->ar->winx;
+ ps->winy = ps->ar->winy;
- if (ELEM(ps->source, PROJ_SRC_VIEW, PROJ_SRC_VIEW_FILL)) {
- /* normal drawing */
- ps->winx = ps->ar->winx;
- ps->winy = ps->ar->winy;
+ copy_m4_m4(viewmat, ps->rv3d->viewmat);
+ copy_m4_m4(viewinv, ps->rv3d->viewinv);
- copy_m4_m4(viewmat, ps->rv3d->viewmat);
- copy_m4_m4(viewinv, ps->rv3d->viewinv);
+ ED_view3d_ob_project_mat_get(ps->rv3d, ps->ob, ps->projectMat);
- ED_view3d_ob_project_mat_get(ps->rv3d, ps->ob, ps->projectMat);
+ ps->is_ortho = ED_view3d_clip_range_get(ps->v3d, ps->rv3d, &ps->clipsta, &ps->clipend, true);
+ }
+ else {
+ /* re-projection */
+ float winmat[4][4];
+ float vmat[4][4];
- ps->is_ortho = ED_view3d_clip_range_get(ps->v3d, ps->rv3d, &ps->clipsta, &ps->clipend, true);
- }
- else {
- /* re-projection */
- float winmat[4][4];
- float vmat[4][4];
+ ps->winx = ps->reproject_ibuf->x;
+ ps->winy = ps->reproject_ibuf->y;
- ps->winx = ps->reproject_ibuf->x;
- ps->winy = ps->reproject_ibuf->y;
+ if (ps->source == PROJ_SRC_IMAGE_VIEW) {
+ /* image stores camera data, tricky */
+ IDProperty *idgroup = IDP_GetProperties(&ps->reproject_image->id, 0);
+ IDProperty *view_data = IDP_GetPropertyFromGroup(idgroup, PROJ_VIEW_DATA_ID);
- if (ps->source == PROJ_SRC_IMAGE_VIEW) {
- /* image stores camera data, tricky */
- IDProperty *idgroup = IDP_GetProperties(&ps->reproject_image->id, 0);
- IDProperty *view_data = IDP_GetPropertyFromGroup(idgroup, PROJ_VIEW_DATA_ID);
+ const float *array = (float *)IDP_Array(view_data);
- const float *array = (float *)IDP_Array(view_data);
+ /* use image array, written when creating image */
+ memcpy(winmat, array, sizeof(winmat)); array += sizeof(winmat) / sizeof(float);
+ memcpy(viewmat, array, sizeof(viewmat)); array += sizeof(viewmat) / sizeof(float);
+ ps->clipsta = array[0];
+ ps->clipend = array[1];
+ ps->is_ortho = array[2] ? 1 : 0;
- /* use image array, written when creating image */
- memcpy(winmat, array, sizeof(winmat)); array += sizeof(winmat) / sizeof(float);
- memcpy(viewmat, array, sizeof(viewmat)); array += sizeof(viewmat) / sizeof(float);
- ps->clipsta = array[0];
- ps->clipend = array[1];
- ps->is_ortho = array[2] ? 1 : 0;
+ invert_m4_m4(viewinv, viewmat);
+ }
+ else if (ps->source == PROJ_SRC_IMAGE_CAM) {
+ Object *cam_ob = ps->scene->camera;
+ CameraParams params;
- invert_m4_m4(viewinv, viewmat);
- }
- else if (ps->source == PROJ_SRC_IMAGE_CAM) {
- Object *cam_ob = ps->scene->camera;
- CameraParams params;
-
- /* viewmat & viewinv */
- copy_m4_m4(viewinv, cam_ob->obmat);
- normalize_m4(viewinv);
- invert_m4_m4(viewmat, viewinv);
-
- /* window matrix, clipping and ortho */
- BKE_camera_params_init(&params);
- BKE_camera_params_from_object(&params, cam_ob);
- BKE_camera_params_compute_viewplane(&params, ps->winx, ps->winy, 1.0f, 1.0f);
- BKE_camera_params_compute_matrix(&params);
-
- copy_m4_m4(winmat, params.winmat);
- ps->clipsta = params.clipsta;
- ps->clipend = params.clipend;
- ps->is_ortho = params.is_ortho;
- }
+ /* viewmat & viewinv */
+ copy_m4_m4(viewinv, cam_ob->obmat);
+ normalize_m4(viewinv);
+ invert_m4_m4(viewmat, viewinv);
+
+ /* window matrix, clipping and ortho */
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_object(&params, cam_ob);
+ BKE_camera_params_compute_viewplane(&params, ps->winx, ps->winy, 1.0f, 1.0f);
+ BKE_camera_params_compute_matrix(&params);
- /* same as #ED_view3d_ob_project_mat_get */
- mul_m4_m4m4(vmat, viewmat, ps->ob->obmat);
- mul_m4_m4m4(ps->projectMat, winmat, vmat);
+ copy_m4_m4(winmat, params.winmat);
+ ps->clipsta = params.clipsta;
+ ps->clipend = params.clipend;
+ ps->is_ortho = params.is_ortho;
+ }
+ else {
+ BLI_assert(0);
}
+ /* same as #ED_view3d_ob_project_mat_get */
+ mul_m4_m4m4(vmat, viewmat, ps->ob->obmat);
+ mul_m4_m4m4(ps->projectMat, winmat, vmat);
+ }
- /* viewDir - object relative */
- invert_m4_m4(ps->ob->imat, ps->ob->obmat);
- copy_m3_m4(mat, viewinv);
- mul_m3_v3(mat, ps->viewDir);
- copy_m3_m4(mat, ps->ob->imat);
- mul_m3_v3(mat, ps->viewDir);
- normalize_v3(ps->viewDir);
- /* viewPos - object relative */
- copy_v3_v3(ps->viewPos, viewinv[3]);
- copy_m3_m4(mat, ps->ob->imat);
- mul_m3_v3(mat, ps->viewPos);
- add_v3_v3(ps->viewPos, ps->ob->imat[3]);
- }
+ /* viewDir - object relative */
+ invert_m4_m4(ps->ob->imat, ps->ob->obmat);
+ copy_m3_m4(mat, viewinv);
+ mul_m3_v3(mat, ps->viewDir);
+ copy_m3_m4(mat, ps->ob->imat);
+ mul_m3_v3(mat, ps->viewDir);
+ normalize_v3(ps->viewDir);
+
+ /* viewPos - object relative */
+ copy_v3_v3(ps->viewPos, viewinv[3]);
+ copy_m3_m4(mat, ps->ob->imat);
+ mul_m3_v3(mat, ps->viewPos);
+ add_v3_v3(ps->viewPos, ps->ob->imat[3]);
+}
+
+static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int diameter)
+{
+ MVert *mv;
+ float *projScreenCo;
+ float projMargin;
+ int a;
- /* calculate vert screen coords
- * run this early so we can calculate the x/y resolution of our bucket rect */
INIT_MINMAX2(ps->screenMin, ps->screenMax);
ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, "ProjectPaint ScreenVerts");
@@ -3305,38 +3201,24 @@ static void project_paint_begin(ProjPaintState *ps)
ps->screenMin[1] = 0;
ps->screenMax[1] = (float)(ps->winy);
}
+}
- /* only for convenience */
- ps->screen_width = ps->screenMax[0] - ps->screenMin[0];
- ps->screen_height = ps->screenMax[1] - ps->screenMin[1];
-
- ps->buckets_x = (int)(ps->screen_width / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
- ps->buckets_y = (int)(ps->screen_height / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
-
- /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */
-
- if (ps->buckets_x > PROJ_BUCKET_RECT_MAX || ps->buckets_y > PROJ_BUCKET_RECT_MAX) {
- reset_threads = true;
- }
-
- /* really high values could cause problems since it has to allocate a few
- * (ps->buckets_x*ps->buckets_y) sized arrays */
- CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
- CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
-
- ps->bucketRect = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketRect");
- ps->bucketFaces = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
-
- ps->bucketFlags = (unsigned char *)MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
#ifndef PROJ_DEBUG_NOSEAMBLEED
+static void proj_paint_state_seam_bleed_init(ProjPaintState *ps)
+{
if (ps->seam_bleed_px > 0.0f) {
- ps->vertFaces = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->dm_totvert, "paint-vertFaces");
- ps->faceSeamFlags = (char *)MEM_callocN(sizeof(char) * ps->dm_totface, "paint-faceSeamFlags");
- ps->faceWindingFlags = (char *)MEM_callocN(sizeof(char) * ps->dm_totface, "paint-faceWindindFlags");
+ ps->vertFaces = MEM_callocN(sizeof(LinkNode *) * ps->dm_totvert, "paint-vertFaces");
+ ps->faceSeamFlags = MEM_callocN(sizeof(char) * ps->dm_totface, "paint-faceSeamFlags");
+ ps->faceWindingFlags = MEM_callocN(sizeof(char) * ps->dm_totface, "paint-faceWindindFlags");
ps->faceSeamUVs = MEM_mallocN(sizeof(float) * ps->dm_totface * 8, "paint-faceSeamUVs");
}
+}
#endif
+static void proj_paint_state_thread_init(ProjPaintState *ps, const bool reset_threads)
+{
+ int a;
+
/* Thread stuff
*
* very small brushes run a lot slower multithreaded since the advantage with
@@ -3360,11 +3242,15 @@ static void project_paint_begin(ProjPaintState *ps)
for (a = 0; a < ps->thread_tot; a++) {
ps->arena_mt[a] = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "project paint arena");
}
+}
- arena = ps->arena_mt[0];
-
+static void proj_paint_state_vert_flags_init(ProjPaintState *ps)
+{
if (ps->do_backfacecull && ps->do_mask_normal) {
float viewDirPersp[3];
+ MVert *mv;
+ float no[3];
+ int a;
ps->vertFlags = MEM_callocN(sizeof(char) * ps->dm_totvert, "paint-vertFlags");
@@ -3385,38 +3271,339 @@ static void project_paint_begin(ProjPaintState *ps)
}
}
}
-
- for (face_index = 0, tf = ps->dm_mtface, mf = ps->dm_mface; face_index < ps->dm_totface; mf++, tf++, face_index++) {
- bool is_face_sel;
+ else {
+ ps->vertFlags = NULL;
+ }
+}
#ifndef PROJ_DEBUG_NOSEAMBLEED
- /* add face user if we have bleed enabled, set the UV seam flags later */
- /* annoying but we need to add all faces even ones we never use elsewhere */
- if (ps->seam_bleed_px > 0.0f) {
- BLI_linklist_prepend_arena(&ps->vertFaces[mf->v1], SET_INT_IN_POINTER(face_index), arena);
- BLI_linklist_prepend_arena(&ps->vertFaces[mf->v2], SET_INT_IN_POINTER(face_index), arena);
- BLI_linklist_prepend_arena(&ps->vertFaces[mf->v3], SET_INT_IN_POINTER(face_index), arena);
- if (mf->v4) {
- BLI_linklist_prepend_arena(&ps->vertFaces[mf->v4], SET_INT_IN_POINTER(face_index), arena);
- }
+static void project_paint_bleed_add_face_user(
+ const ProjPaintState *ps, MemArena *arena,
+ const MFace *mf, const int face_index)
+{
+ /* add face user if we have bleed enabled, set the UV seam flags later */
+ /* annoying but we need to add all faces even ones we never use elsewhere */
+ if (ps->seam_bleed_px > 0.0f) {
+ BLI_linklist_prepend_arena(&ps->vertFaces[mf->v1], SET_INT_IN_POINTER(face_index), arena);
+ BLI_linklist_prepend_arena(&ps->vertFaces[mf->v2], SET_INT_IN_POINTER(face_index), arena);
+ BLI_linklist_prepend_arena(&ps->vertFaces[mf->v3], SET_INT_IN_POINTER(face_index), arena);
+ if (mf->v4) {
+ BLI_linklist_prepend_arena(&ps->vertFaces[mf->v4], SET_INT_IN_POINTER(face_index), arena);
}
+ }
+}
#endif
- if (ps->do_face_sel) {
- int orig_index;
- if (index_mp_to_orig && ((orig_index = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig,
- face_index))) != ORIGINDEX_NONE)
- {
- MPoly *mp = &mpoly_orig[orig_index];
- is_face_sel = ((mp->flag & ME_FACE_SEL) != 0);
+/* Return true if DM can be painted on, false otherwise */
+static bool proj_paint_state_dm_init(ProjPaintState *ps)
+{
+ /* Workaround for subsurf selection, try the display mesh first */
+ if (ps->source == PROJ_SRC_IMAGE_CAM) {
+ /* using render mesh, assume only camera was rendered from */
+ ps->dm = mesh_create_derived_render(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE);
+ ps->dm_release = true;
+ }
+ else if (ps->ob->derivedFinal &&
+ CustomData_has_layer(&ps->ob->derivedFinal->faceData, CD_MTFACE) &&
+ (ps->do_face_sel == false || CustomData_has_layer(&ps->ob->derivedFinal->polyData, CD_ORIGINDEX)))
+ {
+ ps->dm = ps->ob->derivedFinal;
+ ps->dm_release = false;
+ }
+ else {
+ ps->dm = mesh_get_derived_final(
+ ps->scene, ps->ob,
+ ps->scene->customdata_mask | CD_MASK_MTFACE | (ps->do_face_sel ? CD_ORIGINDEX : 0));
+ ps->dm_release = true;
+ }
+
+ if (!CustomData_has_layer(&ps->dm->faceData, CD_MTFACE)) {
+
+ if (ps->dm_release)
+ ps->dm->release(ps->dm);
+
+ ps->dm = NULL;
+ return false;
+ }
+
+ DM_update_materials(ps->dm, ps->ob);
+
+ ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
+ ps->dm_totface = ps->dm->getNumTessFaces(ps->dm);
+
+ ps->dm_mvert = ps->dm->getVertArray(ps->dm);
+ ps->dm_mface = ps->dm->getTessFaceArray(ps->dm);
+ ps->dm_mtface = MEM_mallocN(ps->dm_totface * sizeof(MTFace *), "proj_paint_mtfaces");
+
+ return true;
+}
+
+typedef struct {
+ MTFace *tf_clone_base;
+ MTFace **tf_clone;
+ TexPaintSlot *slot_last_clone;
+ TexPaintSlot *slot_clone;
+} ProjPaintLayerClone;
+
+static void proj_paint_layer_clone_init(
+ ProjPaintState *ps,
+ ProjPaintLayerClone *layer_clone)
+{
+ MTFace *tf_clone_base = NULL;
+
+ /* use clone mtface? */
+ if (ps->do_layer_clone) {
+ const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
+
+ ps->dm_mtface_clone = MEM_mallocN(ps->dm_totface * sizeof(MTFace *), "proj_paint_mtfaces");
+
+ if (layer_num != -1)
+ tf_clone_base = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
+
+ if (tf_clone_base == NULL) {
+ /* get active instead */
+ tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ }
+
+ }
+
+ memset(layer_clone, 0, sizeof(*layer_clone));
+ layer_clone->tf_clone_base = tf_clone_base;
+}
+
+/* Return true if face should be skipped, false otherwise */
+static bool project_paint_clone_face_skip(
+ ProjPaintState *ps,
+ ProjPaintLayerClone *lc,
+ const TexPaintSlot *slot,
+ const int face_index)
+{
+ if (ps->do_layer_clone) {
+ if (ps->do_material_slots) {
+ lc->slot_clone = project_paint_face_clone_slot(ps, face_index);
+ /* all faces should have a valid slot, reassert here */
+ if (ELEM(lc->slot_clone, NULL, slot))
+ return true;
+ }
+ else if (ps->clone_ima == ps->canvas_ima)
+ return true;
+
+ lc->tf_clone = ps->dm_mtface_clone + face_index;
+
+ if (ps->do_material_slots) {
+ if (lc->slot_clone != lc->slot_last_clone) {
+ if (!slot->uvname ||
+ !(lc->tf_clone_base = CustomData_get_layer_named(
+ &ps->dm->faceData, CD_MTFACE,
+ lc->slot_clone->uvname)))
+ {
+ lc->tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ }
+ lc->slot_last_clone = lc->slot_clone;
}
- else {
- is_face_sel = ((mf->flag & ME_FACE_SEL) != 0);
+ }
+
+ *lc->tf_clone = lc->tf_clone_base + face_index;
+ }
+ return false;
+}
+
+typedef struct {
+ MPoly *mpoly_orig;
+
+ /* double lookup */
+ const int *index_mf_to_mpoly;
+ const int *index_mp_to_orig;
+} ProjPaintFaceLookup;
+
+static void proj_paint_face_lookup_init(
+ const ProjPaintState *ps,
+ ProjPaintFaceLookup *face_lookup)
+{
+ memset(face_lookup, 0, sizeof(*face_lookup));
+ if (ps->do_face_sel) {
+ face_lookup->index_mf_to_mpoly = ps->dm->getTessFaceDataArray(ps->dm, CD_ORIGINDEX);
+ face_lookup->index_mp_to_orig = ps->dm->getPolyDataArray(ps->dm, CD_ORIGINDEX);
+ if (face_lookup->index_mf_to_mpoly == NULL) {
+ face_lookup->index_mp_to_orig = NULL;
+ }
+ else {
+ face_lookup->mpoly_orig = ((Mesh *)ps->ob->data)->mpoly;
+ }
+ }
+}
+
+/* Return true if face should be considered selected, false otherwise */
+static bool project_paint_check_face_sel(
+ const ProjPaintState *ps,
+ const ProjPaintFaceLookup *face_lookup,
+ const MFace *mf, const int face_index)
+{
+ if (ps->do_face_sel) {
+ int orig_index;
+ if (face_lookup->index_mp_to_orig &&
+ ((orig_index = DM_origindex_mface_mpoly(
+ face_lookup->index_mf_to_mpoly,
+ face_lookup->index_mp_to_orig,
+ face_index))) != ORIGINDEX_NONE)
+ {
+ MPoly *mp = &face_lookup->mpoly_orig[orig_index];
+ return ((mp->flag & ME_FACE_SEL) != 0);
+ }
+ else {
+ return ((mf->flag & ME_FACE_SEL) != 0);
+ }
+ }
+ else {
+ return true;
+ }
+}
+
+typedef struct {
+ const float *v1;
+ const float *v2;
+ const float *v3;
+ const float *v4;
+} ProjPaintFaceCoSS;
+
+static void proj_paint_face_coSS_init(
+ const ProjPaintState *ps, const MFace *mf,
+ ProjPaintFaceCoSS *coSS)
+{
+ coSS->v1 = ps->screenCoords[mf->v1];
+ coSS->v2 = ps->screenCoords[mf->v2];
+ coSS->v3 = ps->screenCoords[mf->v3];
+ coSS->v4 = mf->v4 ? ps->screenCoords[mf->v4] : NULL;
+}
+
+/* Return true if face should be culled, false otherwise */
+static bool project_paint_flt_max_cull(
+ const ProjPaintState *ps,
+ const ProjPaintFaceCoSS *coSS)
+{
+ if (!ps->is_ortho) {
+ if (coSS->v1[0] == FLT_MAX ||
+ coSS->v2[0] == FLT_MAX ||
+ coSS->v3[0] == FLT_MAX ||
+ (coSS->v4 && coSS->v4[0] == FLT_MAX))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+#ifdef PROJ_DEBUG_WINCLIP
+/* Return true if face should be culled, false otherwise */
+static bool project_paint_winclip(
+ const ProjPaintState *ps, const MFace *mf,
+ const ProjPaintFaceCoSS *coSS)
+{
+ /* ignore faces outside the view */
+ return ((ps->source != PROJ_SRC_VIEW_FILL) &&
+ ((coSS->v1[0] < ps->screenMin[0] &&
+ coSS->v2[0] < ps->screenMin[0] &&
+ coSS->v3[0] < ps->screenMin[0] &&
+ (mf->v4 && coSS->v4[0] < ps->screenMin[0])) ||
+
+ (coSS->v1[0] > ps->screenMax[0] &&
+ coSS->v2[0] > ps->screenMax[0] &&
+ coSS->v3[0] > ps->screenMax[0] &&
+ (mf->v4 && coSS->v4[0] > ps->screenMax[0])) ||
+
+ (coSS->v1[1] < ps->screenMin[1] &&
+ coSS->v2[1] < ps->screenMin[1] &&
+ coSS->v3[1] < ps->screenMin[1] &&
+ (mf->v4 && coSS->v4[1] < ps->screenMin[1])) ||
+
+ (coSS->v1[1] > ps->screenMax[1] &&
+ coSS->v2[1] > ps->screenMax[1] &&
+ coSS->v3[1] > ps->screenMax[1] &&
+ (mf->v4 && coSS->v4[1] > ps->screenMax[1]))));
+}
+#endif //PROJ_DEBUG_WINCLIP
+
+/* Return true if face should be culled, false otherwise */
+static bool project_paint_backface_cull(
+ const ProjPaintState *ps, const MFace *mf,
+ const ProjPaintFaceCoSS *coSS)
+{
+ if (ps->do_backfacecull) {
+ if (ps->do_mask_normal) {
+ /* Since we are interpolating the normals of faces, we want to make
+ * sure all the verts are pointing away from the view,
+ * not just the face */
+ if ((ps->vertFlags[mf->v1] & PROJ_VERT_CULL) &&
+ (ps->vertFlags[mf->v2] & PROJ_VERT_CULL) &&
+ (ps->vertFlags[mf->v3] & PROJ_VERT_CULL) &&
+ (mf->v4 == 0 || ps->vertFlags[mf->v4] & PROJ_VERT_CULL))
+ {
+ return true;
}
}
else {
- is_face_sel = true;
+ if (line_point_side_v2(coSS->v1, coSS->v2, coSS->v3) < 0.0f) {
+ return true;
+ }
+
}
+ }
+
+ return false;
+}
+
+static void project_paint_build_proj_ima(
+ ProjPaintState *ps, MemArena *arena,
+ LinkNode *image_LinkList)
+{
+ ProjPaintImage *projIma;
+ LinkNode *node;
+ int i;
+
+ /* build an array of images we use */
+ projIma = ps->projImages = BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
+
+ for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) {
+ int size;
+ projIma->ima = node->link;
+ projIma->touch = 0;
+ projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
+ size = sizeof(void **) * IMAPAINT_TILE_NUMBER(projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(projIma->ibuf->y);
+ projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ projIma->undoRect = (volatile void **) BLI_memarena_alloc(arena, size);
+ memset(projIma->undoRect, 0, size);
+ projIma->maskRect = BLI_memarena_alloc(arena, size);
+ memset(projIma->maskRect, 0, size);
+ projIma->valid = BLI_memarena_alloc(arena, size);
+ memset(projIma->valid, 0, size);
+ }
+}
+
+static void project_paint_prepare_all_faces(
+ ProjPaintState *ps, MemArena *arena,
+ const ProjPaintFaceLookup *face_lookup,
+ ProjPaintLayerClone *layer_clone,
+ MTFace *tf_base)
+{
+ /* Image Vars - keep track of images we have used */
+ LinkNode *image_LinkList = NULL;
+
+ Image *tpage_last = NULL, *tpage;
+ TexPaintSlot *slot_last = NULL;
+ TexPaintSlot *slot = NULL;
+ MTFace **tf;
+ MFace *mf;
+ int image_index = -1, face_index;
+
+ for (face_index = 0, tf = ps->dm_mtface, mf = ps->dm_mface; face_index < ps->dm_totface; mf++, tf++, face_index++) {
+ bool is_face_sel;
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ project_paint_bleed_add_face_user(ps, arena, mf, face_index);
+#endif
+
+ is_face_sel = project_paint_check_face_sel(ps, face_lookup, mf, face_index);
if (!ps->do_stencil_brush) {
slot = project_paint_face_paint_slot(ps, face_index);
@@ -3445,103 +3632,31 @@ static void project_paint_begin(ProjPaintState *ps)
*tf = tf_base + face_index;
- if (ps->do_layer_clone) {
- if (ps->do_material_slots) {
- slot_clone = project_paint_face_clone_slot(ps, face_index);
- /* all faces should have a valid slot, reassert here */
- if (ELEM(slot_clone, NULL, slot))
- continue;
- }
- else if (ps->clone_ima == ps->canvas_ima)
- continue;
-
- tf_clone = ps->dm_mtface_clone + face_index;
-
- if (ps->do_material_slots) {
- if (slot_clone != slot_last_clone) {
- if (!slot->uvname || !(tf_clone_base = CustomData_get_layer_named(&ps->dm->faceData, CD_MTFACE, slot_clone->uvname)))
- tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
- slot_last_clone = slot_clone;
- }
- }
-
- *tf_clone = tf_clone_base + face_index;
+ if (project_paint_clone_face_skip(ps, layer_clone, slot, face_index)) {
+ continue;
}
/* tfbase here should be non-null! */
BLI_assert (tf_base != NULL);
if (is_face_sel && tpage) {
- const float *v1coSS, *v2coSS, *v3coSS, *v4coSS = NULL;
+ ProjPaintFaceCoSS coSS;
+ proj_paint_face_coSS_init(ps, mf, &coSS);
- v1coSS = ps->screenCoords[mf->v1];
- v2coSS = ps->screenCoords[mf->v2];
- v3coSS = ps->screenCoords[mf->v3];
- if (mf->v4) {
- v4coSS = ps->screenCoords[mf->v4];
- }
-
-
- if (!ps->is_ortho) {
- if (v1coSS[0] == FLT_MAX ||
- v2coSS[0] == FLT_MAX ||
- v3coSS[0] == FLT_MAX ||
- (mf->v4 && v4coSS[0] == FLT_MAX))
- {
- continue;
- }
+ if (project_paint_flt_max_cull(ps, &coSS)) {
+ continue;
}
#ifdef PROJ_DEBUG_WINCLIP
- /* ignore faces outside the view */
- if ((ps->source != PROJ_SRC_VIEW_FILL) &&
- ((v1coSS[0] < ps->screenMin[0] &&
- v2coSS[0] < ps->screenMin[0] &&
- v3coSS[0] < ps->screenMin[0] &&
- (mf->v4 && v4coSS[0] < ps->screenMin[0])) ||
-
- (v1coSS[0] > ps->screenMax[0] &&
- v2coSS[0] > ps->screenMax[0] &&
- v3coSS[0] > ps->screenMax[0] &&
- (mf->v4 && v4coSS[0] > ps->screenMax[0])) ||
-
- (v1coSS[1] < ps->screenMin[1] &&
- v2coSS[1] < ps->screenMin[1] &&
- v3coSS[1] < ps->screenMin[1] &&
- (mf->v4 && v4coSS[1] < ps->screenMin[1])) ||
-
- (v1coSS[1] > ps->screenMax[1] &&
- v2coSS[1] > ps->screenMax[1] &&
- v3coSS[1] > ps->screenMax[1] &&
- (mf->v4 && v4coSS[1] > ps->screenMax[1])))
- )
- {
+ if (project_paint_winclip(ps, mf, &coSS)) {
continue;
}
#endif //PROJ_DEBUG_WINCLIP
- if (ps->do_backfacecull) {
- if (ps->do_mask_normal) {
- /* Since we are interpolating the normals of faces, we want to make
- * sure all the verts are pointing away from the view,
- * not just the face */
- if ((ps->vertFlags[mf->v1] & PROJ_VERT_CULL) &&
- (ps->vertFlags[mf->v2] & PROJ_VERT_CULL) &&
- (ps->vertFlags[mf->v3] & PROJ_VERT_CULL) &&
- (mf->v4 == 0 || ps->vertFlags[mf->v4] & PROJ_VERT_CULL)
- )
- {
- continue;
- }
- }
- else {
- if (line_point_side_v2(v1coSS, v2coSS, v3coSS) < 0.0f) {
- continue;
- }
-
- }
+ if (project_paint_backface_cull(ps, mf, &coSS)) {
+ continue;
}
if (tpage_last != tpage) {
@@ -3566,28 +3681,98 @@ static void project_paint_begin(ProjPaintState *ps)
}
/* build an array of images we use*/
- projIma = ps->projImages = (ProjPaintImage *)BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
-
- for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) {
- int size;
- projIma->ima = node->link;
- projIma->touch = 0;
- projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
- size = sizeof(void **) * IMAPAINT_TILE_NUMBER(projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(projIma->ibuf->y);
- projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
- memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
- projIma->undoRect = (volatile void **) BLI_memarena_alloc(arena, size);
- memset(projIma->undoRect, 0, size);
- projIma->maskRect = (unsigned short **) BLI_memarena_alloc(arena, size);
- memset(projIma->maskRect, 0, size);
- projIma->valid = (bool **) BLI_memarena_alloc(arena, size);
- memset(projIma->valid, 0, size);
- }
+ project_paint_build_proj_ima(ps, arena, image_LinkList);
/* we have built the array, discard the linked list */
BLI_linklist_free(image_LinkList, NULL);
}
+/* run once per stroke before projection painting */
+static void project_paint_begin(ProjPaintState *ps)
+{
+ ProjPaintLayerClone layer_clone;
+ ProjPaintFaceLookup face_lookup;
+ MTFace *tf_base;
+
+ MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */
+
+ const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush);
+
+ bool reset_threads = false;
+
+ /* ---- end defines ---- */
+
+ if (ps->source == PROJ_SRC_VIEW)
+ ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */
+
+ ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0);
+
+ /* paint onto the derived mesh */
+ if (!proj_paint_state_dm_init(ps)) {
+ return;
+ }
+
+ proj_paint_face_lookup_init(ps, &face_lookup);
+ proj_paint_layer_clone_init(ps, &layer_clone);
+
+ if (ps->do_layer_stencil || ps->do_stencil_brush) {
+ //int layer_num = CustomData_get_stencil_layer(&ps->dm->faceData, CD_MTFACE);
+ int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
+ if (layer_num != -1)
+ ps->dm_mtface_stencil = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
+
+ if (ps->dm_mtface_stencil == NULL) {
+ /* get active instead */
+ ps->dm_mtface_stencil = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ }
+
+ if (ps->do_stencil_brush)
+ tf_base = ps->dm_mtface_stencil;
+ }
+
+ /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
+ proj_paint_state_non_cddm_init(ps);
+
+ proj_paint_state_viewport_init(ps);
+
+ /* calculate vert screen coords
+ * run this early so we can calculate the x/y resolution of our bucket rect */
+ proj_paint_state_screen_coords_init(ps, diameter);
+
+ /* only for convenience */
+ ps->screen_width = ps->screenMax[0] - ps->screenMin[0];
+ ps->screen_height = ps->screenMax[1] - ps->screenMin[1];
+
+ ps->buckets_x = (int)(ps->screen_width / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
+ ps->buckets_y = (int)(ps->screen_height / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
+
+ /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */
+
+ if (ps->buckets_x > PROJ_BUCKET_RECT_MAX || ps->buckets_y > PROJ_BUCKET_RECT_MAX) {
+ reset_threads = true;
+ }
+
+ /* really high values could cause problems since it has to allocate a few
+ * (ps->buckets_x*ps->buckets_y) sized arrays */
+ CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
+ CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
+
+ ps->bucketRect = MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketRect");
+ ps->bucketFaces = MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
+
+ ps->bucketFlags = MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ proj_paint_state_seam_bleed_init(ps);
+#endif
+
+ proj_paint_state_thread_init(ps, reset_threads);
+ arena = ps->arena_mt[0];
+
+ proj_paint_state_vert_flags_init(ps);
+
+ project_paint_prepare_all_faces(ps, arena, &face_lookup, &layer_clone, tf_base);
+}
+
static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2])
{
/* setup clone offset */
@@ -3773,7 +3958,9 @@ static bool project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
}
-static bool project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2])
+static bool project_bucket_iter_next(
+ ProjPaintState *ps, int *bucket_index,
+ rctf *bucket_bounds, const float mval[2])
{
const int diameter = 2 * ps->brush_size;
@@ -4011,20 +4198,21 @@ static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, flo
}
}
-static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const float texrgb[3], float mask)
+static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const float texrgb[3], float mask, float dither, float u, float v)
{
float rgb[3];
unsigned char rgba_ub[4];
- copy_v3_v3(rgb, ps->paint_color);
-
if (ps->is_texbrush) {
- mul_v3_v3(rgb, texrgb);
+ mul_v3_v3v3(rgb, texrgb, ps->paint_color_linear);
/* TODO(sergey): Support texture paint color space. */
linearrgb_to_srgb_v3_v3(rgb, rgb);
}
+ else {
+ copy_v3_v3(rgb, ps->paint_color);
+ }
- rgb_float_to_uchar(rgba_ub, rgb);
+ float_to_byte_dither_v3(rgba_ub, rgb, dither, u, v);
rgba_ub[3] = f_to_char(mask);
if (ps->do_masking) {
@@ -4205,7 +4393,8 @@ static void *do_projectpaint_thread(void *ph_v)
}
else {
linearrgb_to_srgb_v3_v3(color_f, color_f);
- rgba_float_to_uchar(projPixel->newColor.ch, color_f);
+ float_to_byte_dither_v3(projPixel->newColor.ch, color_f, ps->dither, projPixel->x_px, projPixel->y_px);
+ projPixel->newColor.ch[3] = FTOCHAR(color_f[3]);
IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt,
projPixel->newColor.ch, ps->blend);
}
@@ -4401,7 +4590,7 @@ static void *do_projectpaint_thread(void *ph_v)
break;
default:
if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, texrgb, mask);
- else do_projectpaint_draw(ps, projPixel, texrgb, mask);
+ else do_projectpaint_draw(ps, projPixel, texrgb, mask, ps->dither, projPixel->x_px, projPixel->y_px);
break;
}
}
@@ -4485,13 +4674,13 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
/* thread specific */
handles[a].thread_index = a;
- handles[a].projImages = (ProjPaintImage *)BLI_memarena_alloc(ps->arena_mt[a], ps->image_tot * sizeof(ProjPaintImage));
+ handles[a].projImages = BLI_memarena_alloc(ps->arena_mt[a], ps->image_tot * sizeof(ProjPaintImage));
memcpy(handles[a].projImages, ps->projImages, ps->image_tot * sizeof(ProjPaintImage));
/* image bounds */
for (i = 0; i < ps->image_tot; i++) {
- handles[a].projImages[i].partRedrawRect = (ImagePaintPartialRedraw *)BLI_memarena_alloc(ps->arena_mt[a], sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ handles[a].projImages[i].partRedrawRect = BLI_memarena_alloc(ps->arena_mt[a], sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
}
@@ -4705,6 +4894,8 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
if (ps->normal_angle_range <= 0.0f)
ps->do_mask_normal = false; /* no need to do blending */
+ ps->dither = settings->imapaint.dither;
+
return;
}
@@ -4732,7 +4923,7 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m
/* Don't allow brush size below 2 */
if (BKE_brush_size_get(ps->scene, ps->brush) < 2)
- BKE_brush_size_set(ps->scene, ps->brush, 2);
+ BKE_brush_size_set(ps->scene, ps->brush, 2 * U.pixelsize);
/* allocate and initialize spatial data structures */
project_paint_begin(ps);
@@ -4851,7 +5042,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
ps.is_maskbrush = false;
ps.do_masking = false;
orig_brush_size = BKE_brush_size_get(scene, ps.brush);
- BKE_brush_size_set(scene, ps.brush, 32); /* cover the whole image */
+ BKE_brush_size_set(scene, ps.brush, 32 * U.pixelsize); /* cover the whole image */
ps.tool = PAINT_TOOL_DRAW; /* so pixels are initialized with minimal info */
@@ -4945,6 +5136,9 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
image = BKE_image_add_from_imbuf(ibuf);
+ /* Drop reference to ibuf so that the image owns it */
+ IMB_freeImBuf(ibuf);
+
if (image) {
/* now for the trickyness. store the view projection here!
* re-projection will reuse this */
@@ -4965,7 +5159,9 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
memcpy(array, rv3d->winmat, sizeof(rv3d->winmat)); array += sizeof(rv3d->winmat) / sizeof(float);
memcpy(array, rv3d->viewmat, sizeof(rv3d->viewmat)); array += sizeof(rv3d->viewmat) / sizeof(float);
is_ortho = ED_view3d_clip_range_get(v3d, rv3d, &array[0], &array[1], true);
- array[2] = is_ortho ? 1.0f : 0.0f; /* using float for a bool is dodgy but since its an extra member in the array... easier then adding a single bool prop */
+ /* using float for a bool is dodgy but since its an extra member in the array...
+ * easier then adding a single bool prop */
+ array[2] = is_ortho ? 1.0f : 0.0f;
IDP_AddToGroup(idgroup, view_data);
@@ -5041,17 +5237,17 @@ bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *m
hasmat = true;
if (!ma->texpaintslot) {
/* refresh here just in case */
- BKE_texpaint_slot_refresh_cache(scene, ma);
+ BKE_texpaint_slot_refresh_cache(scene, ma);
/* if still no slots, we have to add */
- if (ma->texpaintslot) {
+ if (ma->texpaintslot) {
hastex = true;
- break;
+ break;
}
}
else {
hastex = true;
- break;
+ break;
}
}
}
@@ -5060,7 +5256,7 @@ bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *m
else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
if (imapaint->canvas == NULL) {
hastex = false;
- }
+ }
}
me = BKE_mesh_from_object(ob);
@@ -5141,7 +5337,7 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain)
RNA_string_get(op->ptr, "name", imagename);
}
ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float,
- gen_type, color);
+ gen_type, color);
return ima;
}
@@ -5221,7 +5417,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
DAG_id_tag_update(&ma->id, 0);
ED_area_tag_redraw(CTX_wm_area(C));
- BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+ BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
return true;
}
@@ -5251,7 +5447,7 @@ static int texture_paint_add_texture_paint_slot_invoke(bContext *C, wmOperator *
if (!ma) {
ma = BKE_material_add(CTX_data_main(C), "Material");
/* no material found, just assign to first slot */
- assign_material(ob, ma, ob->actcol, BKE_MAT_ASSIGN_USERPREF);
+ assign_material(ob, ma, ob->actcol, BKE_MAT_ASSIGN_USERPREF);
}
type = RNA_enum_from_value(layer_type_items, type);
@@ -5323,8 +5519,13 @@ static int texture_paint_delete_texture_paint_slot_exec(bContext *C, wmOperator
slot = ma->texpaintslot + ma->paint_active_slot;
- if (ma->mtex[slot->index]->tex)
+ if (ma->mtex[slot->index]->tex) {
id_us_min(&ma->mtex[slot->index]->tex->id);
+
+ if (ma->mtex[slot->index]->tex->ima) {
+ id_us_min(&ma->mtex[slot->index]->tex->ima->id);
+ }
+ }
MEM_freeN(ma->mtex[slot->index]);
ma->mtex[slot->index] = NULL;
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index ea5f77acc5b..fac1a05862f 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -106,15 +106,14 @@ static int brush_scale_size_exec(bContext *C, wmOperator *op)
const int old_size = BKE_brush_size_get(scene, brush);
int size = (int)(scalar * old_size);
- if (old_size == size) {
+ if (abs(old_size - size) < U.pixelsize) {
if (scalar > 1) {
- size++;
+ size += U.pixelsize;
}
else if (scalar < 1) {
- size--;
+ size -= U.pixelsize;
}
}
- CLAMP(size, 1, 2000); // XXX magic number
BKE_brush_size_set(scene, brush, size);
}
@@ -128,6 +127,8 @@ static int brush_scale_size_exec(bContext *C, wmOperator *op)
BKE_brush_unprojected_radius_set(scene, brush, unprojected_radius);
}
+
+ WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);
}
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index bb875d2ef00..d9d0d8f5ef6 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -122,6 +122,10 @@ typedef struct PaintStroke {
float zoom_2d;
int pen_flip;
+
+ /* line constraint */
+ bool constrain_line;
+ float constrained_pos[2];
StrokeGetLocation get_location;
StrokeTestStart test_start;
@@ -161,13 +165,25 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
glColor4ub(0, 0, 0, paint->paint_cursor_col[3]);
glLineWidth(3.0);
- sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
- x, y);
+ if (stroke->constrain_line) {
+ sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
+ stroke->constrained_pos[0], stroke->constrained_pos[1]);
+ }
+ else {
+ sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
+ x, y);
+ }
glColor4ub(255, 255, 255, paint->paint_cursor_col[3]);
glLineWidth(1.0);
- sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
- x, y);
+ if (stroke->constrain_line) {
+ sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
+ stroke->constrained_pos[0], stroke->constrained_pos[1]);
+ }
+ else {
+ sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
+ x, y);
+ }
glDisable(GL_LINE_STIPPLE);
@@ -288,7 +304,7 @@ static bool paint_brush_update(bContext *C,
ups->anchored_size = ups->pixel_radius = sqrtf(dx * dx + dy * dy);
- ups->brush_rotation = ups->brush_rotation_sec = atan2f(dx, dy) + M_PI;
+ ups->brush_rotation = ups->brush_rotation_sec = atan2f(dx, dy) + (float)M_PI;
if (brush->flag & BRUSH_EDGE_TO_EDGE) {
halfway[0] = dx * 0.5f + stroke->initial_mouse[0];
@@ -654,10 +670,11 @@ PaintStroke *paint_stroke_new(bContext *C,
get_imapaint_zoom(C, &zoomx, &zoomy);
stroke->zoom_2d = max_ff(zoomx, zoomy);
- if ((br->flag & BRUSH_CURVE) &&
- RNA_struct_property_is_set(op->ptr, "mode"))
+ if (stroke->stroke_mode == BRUSH_STROKE_INVERT)
{
- RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL);
+ if (br->flag & (BRUSH_CURVE | BRUSH_LINE)) {
+ RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL);
+ }
}
/* initialize here */
ups->overlap_factor = 1.0;
@@ -996,6 +1013,34 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
return false;
}
+static void paint_stroke_line_constrain (PaintStroke *stroke, float mouse[2])
+{
+ if (stroke->constrain_line) {
+ float line[2];
+ float angle, len, res;
+
+ sub_v2_v2v2(line, mouse, stroke->last_mouse_position);
+ angle = atan2(line[1], line[0]);
+ len = len_v2(line);
+
+ /* divide angle by PI/4 */
+ angle = 4.0f * angle / (float)M_PI;
+
+ /* now take residue */
+ res = angle - floorf(angle);
+
+ /* residue decides how close we are at a certain angle */
+ if (res <= 0.5f) {
+ angle = floorf(angle) * (float)M_PI_4;
+ }
+ else {
+ angle = (floorf(angle) + 1.0f) * (float)M_PI_4;
+ }
+
+ mouse[0] = stroke->constrained_pos[0] = len * cosf(angle) + stroke->last_mouse_position[0];
+ mouse[1] = stroke->constrained_pos[1] = len * sinf(angle) + stroke->last_mouse_position[1];
+ }
+}
int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
@@ -1069,7 +1114,9 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event->type == stroke->event_type && !first_modal) {
if (event->val == KM_RELEASE) {
- paint_stroke_line_end (C, op, stroke, sample_average.mouse);
+ copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
+ paint_stroke_line_constrain(stroke, mouse);
+ paint_stroke_line_end (C, op, stroke, mouse);
stroke_done(C, op);
return OPERATOR_FINISHED;
}
@@ -1079,13 +1126,22 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
stroke_done(C, op);
return OPERATOR_FINISHED;
}
- else if ((br->flag & BRUSH_LINE) && stroke->stroke_started &&
- (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))))
- {
- if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || (br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
- copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position);
+ else if (br->flag & BRUSH_LINE) {
+ if (event->ctrl)
+ stroke->constrain_line = true;
+ else
+ stroke->constrain_line = false;
+
+ copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
+ paint_stroke_line_constrain(stroke, mouse);
+
+ if (stroke->stroke_started && (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))))
+ {
+ if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || (br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
+ copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position);
+ }
+ paint_calculate_rake_rotation(stroke->ups, br, mouse);
}
- paint_calculate_rake_rotation(stroke->ups, br, sample_average.mouse);
}
else if (first_modal ||
/* regular dabs */
diff --git a/source/blender/editors/sculpt_paint/paint_undo.c b/source/blender/editors/sculpt_paint/paint_undo.c
index 20e3155c01d..0293a0bfc00 100644
--- a/source/blender/editors/sculpt_paint/paint_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_undo.c
@@ -210,7 +210,7 @@ static int undo_stack_step(bContext *C, UndoStack *stack, int step, const char *
/* pass */
}
else {
- if (!name || strcmp(stack->current->name, name) == 0) {
+ if (!name || STREQ(stack->current->name, name)) {
if (G.debug & G_DEBUG_WM) {
printf("%s: undo '%s'\n", __func__, stack->current->name);
}
@@ -225,7 +225,7 @@ static int undo_stack_step(bContext *C, UndoStack *stack, int step, const char *
/* pass */
}
else {
- if (!name || strcmp(stack->current->name, name) == 0) {
+ if (!name || STREQ(stack->current->name, name)) {
undo = (stack->current && stack->current->next) ? stack->current->next : stack->elems.first;
undo_restore(C, stack, undo);
stack->current = undo;
@@ -394,7 +394,7 @@ int ED_undo_paint_valid(int type, const char *name)
/* pass */
}
else {
- if (name && strcmp(stack->current->name, name) == 0)
+ if (name && STREQ(stack->current->name, name))
return 1;
else
return stack->elems.first != stack->elems.last;
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 9c2c13f9a2d..c0ed5005397 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -177,7 +177,7 @@ float paint_get_tex_pixel(MTex *mtex, float u, float v, struct ImagePool *pool,
float co[3] = {u, v, 0.0f};
externtex(mtex, co, &intensity,
- rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
+ rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false);
return intensity;
}
@@ -189,7 +189,7 @@ void paint_get_tex_pixel_col(MTex *mtex, float u, float v, float rgba[4], struct
float intensity;
hasrgb = externtex(mtex, co, &intensity,
- rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
+ rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false);
if (!hasrgb) {
rgba[0] = intensity;
rgba[1] = intensity;
@@ -373,15 +373,15 @@ static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, c
}
/* returns 0 if not found, otherwise 1 */
-static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *r_index, unsigned int totface)
+static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *r_index, unsigned int totpoly)
{
- if (totface == 0)
+ if (totpoly == 0)
return 0;
/* sample only on the exact position */
*r_index = view3d_sample_backbuf(vc, mval[0], mval[1]);
- if ((*r_index) == 0 || (*r_index) > (unsigned int)totface) {
+ if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) {
return 0;
}
@@ -456,7 +456,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
ViewContext vc;
const int mval[2] = {x, y};
unsigned int faceindex;
- unsigned int totface = me->totface;
+ unsigned int totpoly = me->totpoly;
MTFace *dm_mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);
if (dm_mtface) {
@@ -464,7 +464,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
view3d_operator_needs_opengl(C);
- if (imapaint_pick_face(&vc, mval, &faceindex, totface)) {
+ if (imapaint_pick_face(&vc, mval, &faceindex, totpoly)) {
Image *image;
if (use_material)
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index dbb29997102..69428c0f0d7 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -4248,14 +4248,14 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(st
sculpt_restore_mesh(sd, ob);
if (sd->flags & SCULPT_DYNTOPO_DETAIL_CONSTANT) {
- BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
- sd->constant_detail / 100.0f);
+ BKE_pbvh_bmesh_detail_size_set(ss->pbvh, sd->constant_detail / 100.0f);
}
else {
- BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
- (ss->cache->radius /
- (float)ups->pixel_radius) *
- (float)sd->detail_size / 0.4f);
+ BKE_pbvh_bmesh_detail_size_set(
+ ss->pbvh,
+ (ss->cache->radius /
+ (float)ups->pixel_radius) *
+ (float)(sd->detail_size * U.pixelsize) / 0.4f);
}
if (sculpt_stroke_dynamic_topology(ss, brush)) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 4e9d23d3d97..a4adbc6bca8 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -104,7 +104,7 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo
if (unode->maxvert) {
/* regular mesh restore */
- if (ss->kb && strcmp(ss->kb->name, unode->shapeName)) {
+ if (ss->kb && !STREQ(ss->kb->name, unode->shapeName)) {
/* shape key has been changed before calling undo operator */
Key *key = BKE_key_from_object(ob);
@@ -404,7 +404,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
bool need_mask = false;
for (unode = lb->first; unode; unode = unode->next) {
- if (strcmp(unode->idname, ob->id.name) == 0) {
+ if (STREQ(unode->idname, ob->id.name)) {
if (unode->type == SCULPT_UNDO_MASK) {
/* is possible that we can't do the mask undo (below)
* because of the vertex count */
@@ -423,7 +423,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
return;
for (unode = lb->first; unode; unode = unode->next) {
- if (!(strcmp(unode->idname, ob->id.name) == 0))
+ if (!STREQ(unode->idname, ob->id.name))
continue;
/* check if undo data matches current data well enough to
@@ -550,7 +550,7 @@ static bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
unode = lb->first;
- if (unode && strcmp(unode->idname, ob->id.name) != 0) {
+ if (unode && !STREQ(unode->idname, ob->id.name)) {
if (unode->bm_entry)
BM_log_cleanup_entry(unode->bm_entry);
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index 23bc4a483d3..a9feb9f48de 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -598,7 +598,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
UvEdge *edges;
GHash *edgeHash;
- GHashIterator *ghi;
+ GHashIterator gh_iter;
bool do_island_optimization = !(ts->uv_sculpt_settings & UV_SCULPT_ALL_ISLANDS);
int island_index = 0;
@@ -754,21 +754,15 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
uv_sculpt_stroke_exit(C, op);
return NULL;
}
- ghi = BLI_ghashIterator_new(edgeHash);
- if (!ghi) {
- BLI_ghash_free(edgeHash, NULL, NULL);
- MEM_freeN(edges);
- uv_sculpt_stroke_exit(C, op);
- return NULL;
- }
+
/* fill the edges with data */
- for (i = 0; !BLI_ghashIterator_done(ghi); BLI_ghashIterator_step(ghi)) {
- data->uvedges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
+ i = 0;
+ GHASH_ITER (gh_iter, edgeHash) {
+ data->uvedges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(&gh_iter));
}
data->totalUvEdges = BLI_ghash_size(edgeHash);
/* cleanup temporary stuff */
- BLI_ghashIterator_free(ghi);
BLI_ghash_free(edgeHash, NULL, NULL);
MEM_freeN(edges);
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index d9f4b97fe09..5ce3517696e 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -399,7 +399,7 @@ static bool sound_mixdown_check(bContext *UNUSED(C), wmOperator *op)
if (item->value == container) {
const char **ext = snd_ext_sound;
while (*ext != NULL) {
- if (!strcmp(*ext + 1, item->name)) {
+ if (STREQ(*ext + 1, item->name)) {
extension = *ext;
break;
}
@@ -449,9 +449,9 @@ static int sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *even
static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
{
const char *prop_id = RNA_property_identifier(prop);
- return !(strcmp(prop_id, "filepath") == 0 ||
- strcmp(prop_id, "directory") == 0 ||
- strcmp(prop_id, "filename") == 0);
+ return !(STREQ(prop_id, "filepath") ||
+ STREQ(prop_id, "directory") ||
+ STREQ(prop_id, "filename"));
}
static void sound_mixdown_draw(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index a67af289f59..a263f22e072 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -559,7 +559,7 @@ static void template_texture_user_menu(bContext *C, uiLayout *layout, void *UNUS
char name[UI_MAX_NAME_STR];
/* add label per category */
- if (!last_category || strcmp(last_category, user->category) != 0) {
+ if (!last_category || !STREQ(last_category, user->category)) {
uiItemL(layout, user->category, ICON_NONE);
but = block->buttons.last;
but->drawflag = UI_BUT_TEXT_LEFT;
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index f8299a8d335..c32d06cf9b1 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -540,7 +540,7 @@ void uiTemplateMovieclipInformation(uiLayout *layout, PointerRNA *ptr, const cha
uiItemL(col, str, ICON_NONE);
/* Display current frame number. */
- framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr) ;
+ framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
if (framenr <= clip->len)
BLI_snprintf(str, sizeof(str), IFACE_("Frame: %d / %d"), framenr, clip->len);
else
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index e3d45a297a7..b99b23c60d3 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -1342,7 +1342,8 @@ static int clip_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
if (clip->anim) {
pj->index_context = IMB_anim_index_rebuild_context(clip->anim, clip->proxy.build_tc_flag,
- clip->proxy.build_size_flag, clip->proxy.quality);
+ clip->proxy.build_size_flag, clip->proxy.quality,
+ true, NULL);
}
WM_jobs_customdata_set(wm_job, pj, proxy_freejob);
diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c
index 2d5e5c6e0f2..8263268898f 100644
--- a/source/blender/editors/space_console/console_ops.c
+++ b/source/blender/editors/space_console/console_ops.c
@@ -107,7 +107,7 @@ static ConsoleLine *console_history_find(SpaceConsole *sc, const char *str, Cons
if (cl == cl_ignore)
continue;
- if (strcmp(str, cl->line) == 0)
+ if (STREQ(str, cl->line))
return cl;
}
@@ -722,7 +722,7 @@ static int console_history_cycle_exec(bContext *C, wmOperator *op)
if (ci->prev) {
ConsoleLine *ci_prev = (ConsoleLine *)ci->prev;
- if (strcmp(ci->line, ci_prev->line) == 0)
+ if (STREQ(ci->line, ci_prev->line))
console_history_free(sc, ci_prev);
}
@@ -791,7 +791,7 @@ static int console_history_append_exec(bContext *C, wmOperator *op)
while ((cl = console_history_find(sc, ci->line, ci)))
console_history_free(sc, cl);
- if (strcmp(str, ci->line) == 0) {
+ if (STREQ(str, ci->line)) {
MEM_freeN(str);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 3f3c14d3a7d..57611930e99 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -133,7 +133,8 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
loadbutton = 0;
}
else {
- loadbutton = UI_fontstyle_string_width(params->title) + btn_margin;
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ loadbutton = UI_fontstyle_string_width(fstyle, params->title) + btn_margin;
CLAMP_MIN(loadbutton, btn_minw);
if (available_w <= loadbutton + separator + input_minw) {
loadbutton = 0;
@@ -238,7 +239,7 @@ static void draw_tile(int sx, int sy, int width, int height, int colorid, int sh
static int get_file_icon(struct direntry *file)
{
if (file->type & S_IFDIR) {
- if (strcmp(file->relname, "..") == 0) {
+ if (FILENAME_IS_PARENT(file->relname)) {
return ICON_FILE_PARENT;
}
if (file->flags & FILE_TYPE_APPLICATIONBUNDLE) {
@@ -402,7 +403,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
BLI_strncpy(filename, sfile->params->renameedit, sizeof(filename));
BLI_make_file_string(G.main->name, newname, sfile->params->dir, filename);
- if (strcmp(orgname, newname) != 0) {
+ if (!STREQ(orgname, newname)) {
if (!BLI_exists(newname)) {
BLI_rename(orgname, newname);
/* to make sure we show what is on disk */
@@ -528,7 +529,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
int shade = (params->active_file == i) || (file->selflag & FILE_SEL_HIGHLIGHTED) ? 20 : 0;
/* readonly files (".." and ".") must not be drawn as selected - set color back to normal */
- if (STREQ(file->relname, "..") || STREQ(file->relname, ".")) {
+ if (FILENAME_IS_CURRPAR(file->relname)) {
colorid = TH_BACK;
}
draw_tile(sx, sy - 1, layout->tile_w + 4, sfile->layout->tile_h + layout->tile_border_y, colorid, shade);
@@ -537,7 +538,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
UI_draw_roundbox_corner_set(UI_CNR_NONE);
/* don't drag parent or refresh items */
- do_drag = !(STREQ(file->relname, "..") || STREQ(file->relname, "."));
+ do_drag = !(FILENAME_IS_CURRPAR(file->relname));
if (FILE_IMGDISPLAY == params->display) {
is_icon = 0;
@@ -590,7 +591,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
if (params->display == FILE_SHORTDISPLAY) {
sx += (int)layout->column_widths[COLUMN_NAME] + column_space;
- if (!(file->type & S_IFDIR)) {
+ if ((BLI_is_dir(file->path) == false) && file->size[0]) {
file_draw_string(sx, sy, file->size, layout->column_widths[COLUMN_SIZE], layout->tile_h, align);
sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
}
@@ -619,7 +620,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
file_draw_string(sx, sy, file->time, layout->column_widths[COLUMN_TIME], layout->tile_h, align);
sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
- if (!(file->type & S_IFDIR)) {
+ if ((BLI_is_dir(file->path) == false) && file->size[0]) {
file_draw_string(sx, sy, file->size, layout->column_widths[COLUMN_SIZE], layout->tile_h, align);
sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
}
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 3a579820106..ba6f91e8301 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -183,11 +183,11 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
retval = FILE_SELECT_DIR;
}
/* the path is too long and we are not going up! */
- else if (strcmp(file->relname, "..") && strlen(params->dir) + strlen(file->relname) >= FILE_MAX) {
+ else if (!FILENAME_IS_PARENT(file->relname) && strlen(params->dir) + strlen(file->relname) >= FILE_MAX) {
// XXX error("Path too long, cannot enter this directory");
}
else {
- if (strcmp(file->relname, "..") == 0) {
+ if (FILENAME_IS_PARENT(file->relname)) {
/* avoids /../../ */
BLI_parent_dir(params->dir);
}
@@ -269,7 +269,7 @@ static int file_border_select_modal(bContext *C, wmOperator *op, const wmEvent *
for (idx = sel.last; idx >= 0; idx--) {
struct direntry *file = filelist_file(sfile->files, idx);
- if (STREQ(file->relname, "..") || STREQ(file->relname, ".")) {
+ if (FILENAME_IS_CURRPAR(file->relname)) {
file->selflag &= ~FILE_SEL_HIGHLIGHTED;
}
@@ -362,7 +362,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (idx >= 0) {
struct direntry *file = filelist_file(sfile->files, idx);
- if (STREQ(file->relname, "..") || STREQ(file->relname, ".")) {
+ if (FILENAME_IS_CURRPAR(file->relname)) {
/* skip - If a readonly file (".." or ".") is selected, skip deselect all! */
}
else {
@@ -1531,7 +1531,7 @@ static int file_rename_poll(bContext *C)
if (idx >= 0) {
struct direntry *file = filelist_file(sfile->files, idx);
- if (STREQ(file->relname, "..") || STREQ(file->relname, ".")) {
+ if (FILENAME_IS_CURRPAR(file->relname)) {
poll = 0;
}
}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index bcef0817ffe..f0180c3c841 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -237,9 +237,6 @@ typedef struct FileList {
bool (*filterf)(struct direntry *, const char *, FileListFilter *);
} FileList;
-#define FILENAME_IS_BREADCRUMBS(_n) \
- ((_n)[0] == '.' && ((_n)[1] == '\0' || ((_n)[1] == '.' && (_n)[2] == '\0')))
-
#define SPECIAL_IMG_SIZE 48
#define SPECIAL_IMG_ROWS 4
#define SPECIAL_IMG_COLS 4
@@ -304,10 +301,10 @@ static int compare_direntry_generic(const struct direntry *entry1, const struct
if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
/* make sure "." and ".." are always first */
- if (strcmp(entry1->relname, ".") == 0) return (-1);
- if (strcmp(entry2->relname, ".") == 0) return (1);
- if (strcmp(entry1->relname, "..") == 0) return (-1);
- if (strcmp(entry2->relname, "..") == 0) return (1);
+ if (FILENAME_IS_CURRENT(entry1->relname)) return (-1);
+ if (FILENAME_IS_CURRENT(entry2->relname)) return (1);
+ if (FILENAME_IS_PARENT(entry1->relname)) return (-1);
+ if (FILENAME_IS_PARENT(entry2->relname)) return (1);
return 0;
}
@@ -447,7 +444,7 @@ static bool is_filtered_file(struct direntry *file, const char *UNUSED(root), Fi
{
bool is_filtered = !is_hidden_file(file->relname, filter);
- if (is_filtered && filter->filter && !FILENAME_IS_BREADCRUMBS(file->relname)) {
+ if (is_filtered && filter->filter && !FILENAME_IS_CURRPAR(file->relname)) {
if ((file->type & S_IFDIR) && !(filter->filter & FILE_TYPE_FOLDER)) {
is_filtered = false;
}
@@ -471,7 +468,7 @@ static bool is_filtered_lib(struct direntry *file, const char *root, FileListFil
if (BLO_is_a_library(root, dir, group)) {
is_filtered = !is_hidden_file(file->relname, filter);
- if (is_filtered && filter->filter && !FILENAME_IS_BREADCRUMBS(file->relname)) {
+ if (is_filtered && filter->filter && !FILENAME_IS_CURRPAR(file->relname)) {
if (is_filtered && (filter->filter_search[0] != '\0')) {
if (fnmatch(filter->filter_search, file->relname, FNM_CASEFOLD) != 0) {
is_filtered = false;
@@ -634,10 +631,10 @@ ImBuf *filelist_geticon(struct FileList *filelist, const int index)
fidx = filelist->fidx[index];
file = &filelist->filelist[fidx];
if (file->type & S_IFDIR) {
- if (strcmp(filelist->filelist[fidx].relname, "..") == 0) {
+ if (FILENAME_IS_PARENT(filelist->filelist[fidx].relname)) {
ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
}
- else if (strcmp(filelist->filelist[fidx].relname, ".") == 0) {
+ else if (FILENAME_IS_CURRENT(filelist->filelist[fidx].relname)) {
ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
}
else {
@@ -764,28 +761,20 @@ struct direntry *filelist_file(struct FileList *filelist, int index)
int filelist_find(struct FileList *filelist, const char *filename)
{
- int index = -1;
- int i;
int fidx = -1;
if (!filelist->fidx)
return fidx;
-
- for (i = 0; i < filelist->numfiles; ++i) {
- if (strcmp(filelist->filelist[i].relname, filename) == 0) { /* not dealing with user input so don't need BLI_path_cmp */
- index = i;
- break;
- }
- }
+ for (fidx = 0; fidx < filelist->numfiltered; fidx++) {
+ int index = filelist->fidx[fidx];
- for (i = 0; i < filelist->numfiltered; ++i) {
- if (filelist->fidx[i] == index) {
- fidx = i;
- break;
+ if (STREQ(filelist->filelist[index].relname, filename)) {
+ return fidx;
}
}
- return fidx;
+
+ return -1;
}
/* would recognize .blend as well */
@@ -1116,7 +1105,7 @@ static void filelist_from_library(struct FileList *filelist)
filelist->filelist = malloc(filelist->numfiles * sizeof(*filelist->filelist));
memset(filelist->filelist, 0, filelist->numfiles * sizeof(*filelist->filelist));
- filelist->filelist[0].relname = BLI_strdup("..");
+ filelist->filelist[0].relname = BLI_strdup(FILENAME_PARENT);
filelist->filelist[0].type |= S_IFDIR;
for (i = 0, l = names; i < nnames; i++, l = l->next) {
@@ -1191,7 +1180,7 @@ static void filelist_from_main(struct FileList *filelist)
filelist->filelist[a].type |= S_IFDIR;
}
- filelist->filelist[0].relname = BLI_strdup("..");
+ filelist->filelist[0].relname = BLI_strdup(FILENAME_PARENT);
filelist->filelist[1].relname = BLI_strdup("Scene");
filelist->filelist[2].relname = BLI_strdup("Object");
filelist->filelist[3].relname = BLI_strdup("Mesh");
@@ -1244,7 +1233,7 @@ static void filelist_from_main(struct FileList *filelist)
if (!filelist->filter_data.hide_parent) {
memset(&(filelist->filelist[0]), 0, sizeof(struct direntry));
- filelist->filelist[0].relname = BLI_strdup("..");
+ filelist->filelist[0].relname = BLI_strdup(FILENAME_PARENT);
filelist->filelist[0].type |= S_IFDIR;
files++;
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 3e663275dcd..c452f2e1ff4 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -669,7 +669,7 @@ int autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v))
AutoComplete *autocpl = UI_autocomplete_begin(str, FILE_MAX);
while ((de = readdir(dir)) != NULL) {
- if (strcmp(".", de->d_name) == 0 || strcmp("..", de->d_name) == 0) {
+ if (FILENAME_IS_CURRPAR(de->d_name)) {
/* pass */
}
else {
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index 4ab9bc6a849..05dfdf66ab6 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -283,10 +283,10 @@ void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename)
if (!fp) return;
while (fgets(line, sizeof(line), fp) != NULL) { /* read a line */
- if (strncmp(line, "[Bookmarks]", 11) == 0) {
+ if (STREQLEN(line, "[Bookmarks]", 11)) {
category = FS_CATEGORY_BOOKMARKS;
}
- else if (strncmp(line, "[Recent]", 8) == 0) {
+ else if (STREQLEN(line, "[Recent]", 8)) {
category = FS_CATEGORY_RECENT;
}
else {
@@ -359,7 +359,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
continue;
FSRefMakePath(&dir, path, FILE_MAX);
- if (strcmp((char *)path, "/home") && strcmp((char *)path, "/net")) {
+ if (!STREQ((char *)path, "/home") && !STREQ((char *)path, "/net")) {
/* /net and /home are meaningless on OSX, home folders are stored in /Users */
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)path, FS_INSERT_SORTED);
}
@@ -488,7 +488,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
else {
while ((mnt = getmntent(fp))) {
/* not sure if this is right, but seems to give the relevant mnts */
- if (strncmp(mnt->mnt_fsname, "/dev", 4))
+ if (!STREQLEN(mnt->mnt_fsname, "/dev", 4))
continue;
len = strlen(mnt->mnt_dir);
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 9093734f25f..2d8a0a3da29 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -848,11 +848,13 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
* NOTE: we need to scale the y-values to be valid for the units
*/
glBegin(GL_LINES);
+ {
t = v2d->cur.xmin;
glVertex2f(t, t * unitfac);
t = v2d->cur.xmax;
glVertex2f(t, t * unitfac);
+ }
glEnd();
/* cleanup line drawing */
@@ -875,6 +877,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
setlinestyle(5);
glBegin(GL_LINES);
+ {
/* x-axis lookup */
co[0] = x;
@@ -894,6 +897,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
co[0] = x;
glVertex2fv(co);
+ }
glEnd();
setlinestyle(0);
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index b87f80c4e62..2944901663b 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -1721,7 +1721,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
* so if the paths or the ID's don't match up, then a curve needs to be added
* to a new group
*/
- if ((euf) && (euf->id == ale->id) && (strcmp(euf->rna_path, fcu->rna_path) == 0)) {
+ if ((euf) && (euf->id == ale->id) && (STREQ(euf->rna_path, fcu->rna_path))) {
/* this should be fine to add to the existing group then */
euf->fcurves[fcu->array_index] = fcu;
}
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 78dbae7618b..46a39806ad7 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -66,6 +66,15 @@
/* ************************************************************************** */
/* KEYFRAMES STUFF */
+static void graphkeys_auto_view(bContext *C)
+{
+ const SpaceIpo *sipo = CTX_wm_space_graph(C);
+
+ if (sipo && sipo->flag & SIPO_AUTO_VIEW_SELECTED) {
+ WM_operator_name_call(C, "GRAPH_OT_view_selected", WM_OP_INVOKE_DEFAULT, NULL);
+ }
+}
+
/* ******************** Deselect All Operator ***************************** */
/* This operator works in one of three ways:
* 1) (de)select all (AKEY) - test if select all or deselect all
@@ -83,7 +92,7 @@
* 2 = invert
* - do_channels: whether to affect selection status of channels
*/
-static void deselect_graph_keys(bAnimContext *ac, short test, short sel, short do_channels)
+static short deselect_graph_keys(bAnimContext *ac, short test, short sel, short do_channels)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
@@ -142,6 +151,8 @@ static void deselect_graph_keys(bAnimContext *ac, short test, short sel, short d
/* Cleanup */
ANIM_animdata_freelist(&anim_data);
+
+ return sel;
}
/* ------------------- */
@@ -150,6 +161,7 @@ static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
bAnimListElem *ale_active = NULL;
+ short sel;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -163,9 +175,9 @@ static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
/* 'standard' behavior - check if selected, then apply relevant selection */
if (RNA_boolean_get(op->ptr, "invert"))
- deselect_graph_keys(&ac, 0, SELECT_INVERT, true);
+ sel = deselect_graph_keys(&ac, 0, SELECT_INVERT, true);
else
- deselect_graph_keys(&ac, 1, SELECT_ADD, true);
+ sel = deselect_graph_keys(&ac, 1, SELECT_ADD, true);
/* restore active F-Curve... */
if (ale_active) {
@@ -180,6 +192,9 @@ static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
ale_active = NULL;
}
+ if (sel != SELECT_SUBTRACT)
+ graphkeys_auto_view(C);
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@@ -374,6 +389,8 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
/* apply borderselect action */
borderselect_graphkeys(&ac, &rect_fl, mode, selectmode, incl_handles, NULL);
+ graphkeys_auto_view(C);
+
/* send notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@@ -461,6 +478,8 @@ static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op)
MEM_freeN((void *)data_lasso.mcords);
+ graphkeys_auto_view(C);
+
/* send notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@@ -491,6 +510,14 @@ void GRAPH_OT_select_lasso(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first");
}
+static int graph_circle_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (event->type == EVT_MODAL_MAP && event->val == GESTURE_MODAL_NOP)
+ graphkeys_auto_view(C);
+
+ return WM_gesture_circle_modal(C, op, event);
+}
+
static int graph_circle_select_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
@@ -552,7 +579,7 @@ void GRAPH_OT_select_circle(wmOperatorType *ot)
ot->idname = "GRAPH_OT_select_circle";
ot->invoke = WM_gesture_circle_invoke;
- ot->modal = WM_gesture_circle_modal;
+ ot->modal = graph_circle_select_modal;
ot->exec = graph_circle_select_exec;
ot->poll = graphop_visible_keyframes_poll;
ot->cancel = WM_gesture_circle_cancel;
@@ -725,6 +752,8 @@ static int graphkeys_columnselect_exec(bContext *C, wmOperator *op)
else
columnselect_graph_keys(&ac, mode);
+ graphkeys_auto_view(C);
+
/* set notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@@ -783,6 +812,8 @@ static int graphkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
/* Cleanup */
ANIM_animdata_freelist(&anim_data);
+ graphkeys_auto_view(C);
+
/* set notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@@ -807,12 +838,13 @@ void GRAPH_OT_select_linked(wmOperatorType *ot)
/* ******************** Select More/Less Operators *********************** */
/* Common code to perform selection */
-static void select_moreless_graph_keys(bAnimContext *ac, short mode)
+static void select_moreless_graph_keys(bContext *C, bAnimContext *ac, short mode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
+ const SpaceIpo *sipo = (SpaceIpo *)ac->sl;
KeyframeEditData ked;
KeyframeEditFunc build_cb;
@@ -842,6 +874,24 @@ static void select_moreless_graph_keys(bAnimContext *ac, short mode)
/* free the selmap used here */
MEM_freeN(ked.data);
ked.data = NULL;
+
+ /* only do auto view if a bezier point is selected */
+ if (sipo->flag & SIPO_AUTO_VIEW_SELECTED) {
+ const FCurve *fcu = (FCurve *)ale->key_data;
+ const BezTriple *bezt;
+ unsigned int i;
+
+ /* only continue if F-Curve has keyframes */
+ if (fcu->bezt == NULL)
+ continue;
+
+ for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) {
+ if (BEZSELECTED(bezt)) {
+ graphkeys_auto_view(C);
+ break;
+ }
+ }
+ }
}
/* Cleanup */
@@ -859,7 +909,7 @@ static int graphkeys_select_more_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
/* perform select changes */
- select_moreless_graph_keys(&ac, SELMAP_MORE);
+ select_moreless_graph_keys(C, &ac, SELMAP_MORE);
/* set notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@@ -893,7 +943,7 @@ static int graphkeys_select_less_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
/* perform select changes */
- select_moreless_graph_keys(&ac, SELMAP_LESS);
+ select_moreless_graph_keys(C, &ac, SELMAP_LESS);
/* set notifier that keyframe selection has changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@@ -1008,6 +1058,8 @@ static int graphkeys_select_leftright_exec(bContext *C, wmOperator *op)
/* do the selecting now */
graphkeys_select_leftright(&ac, leftright, selectmode);
+ graphkeys_auto_view(C);
+
/* set notifier that keyframe selection (and channels too) have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL);
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 05868283b2e..fb3c140fddf 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -64,6 +64,7 @@
#include "image_intern.h"
#define B_NOP -1
+#define MAX_IMAGE_INFO_LEN 128
/* proto */
@@ -640,8 +641,6 @@ static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, int compact)
{
-#define MAX_INFO_LEN 128
-
PropertyRNA *prop;
PointerRNA imaptr;
RNAUpdateCb *cb;
@@ -650,7 +649,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
Scene *scene = CTX_data_scene(C);
uiLayout *row, *split, *col;
uiBlock *block;
- char str[MAX_INFO_LEN];
+ char str[MAX_IMAGE_INFO_LEN];
void *lock;
@@ -687,14 +686,14 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
uiLayoutSetContextPointer(layout, "edit_image_user", userptr);
if (!compact)
- uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL);
+ uiTemplateID(layout, C, ptr, propname, ima ? NULL : "IMAGE_OT_new", "IMAGE_OT_open", NULL);
if (ima) {
UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL);
if (ima->source == IMA_SRC_VIEWER) {
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
- image_info(scene, iuser, ima, ibuf, str, MAX_INFO_LEN);
+ image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
BKE_image_release_ibuf(ima, ibuf, lock);
uiItemL(layout, ima->id.name + 2, ICON_NONE);
@@ -763,10 +762,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
}
else if (ima->source != IMA_SRC_GENERATED) {
if (compact == 0) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
- image_info(scene, iuser, ima, ibuf, str, MAX_INFO_LEN);
- BKE_image_release_ibuf(ima, ibuf, lock);
- uiItemL(layout, str, ICON_NONE);
+ uiTemplateImageInfo(layout, C, ima, iuser);
}
}
@@ -780,7 +776,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
bool has_alpha = true;
if (ibuf) {
- int imtype = BKE_ftype_to_imtype(ibuf->ftype);
+ int imtype = BKE_image_ftype_to_imtype(ibuf->ftype);
char valid_channels = BKE_imtype_valid_channels(imtype, false);
has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0;
@@ -791,7 +787,14 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
if (has_alpha) {
col = uiLayoutColumn(layout, false);
uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
- uiItemR(col, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
+ row = uiLayoutRow(col, false);
+ uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_alpha"));
+ uiItemR(row, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
+ }
+
+ if (ima->source == IMA_SRC_MOVIE) {
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE);
}
uiItemS(layout);
@@ -856,8 +859,6 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
}
MEM_freeN(cb);
-
-#undef MAX_INFO_LEN
}
void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_management)
@@ -977,6 +978,24 @@ void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser
}
}
+void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
+{
+ ImBuf *ibuf;
+ char str[MAX_IMAGE_INFO_LEN];
+ void *lock;
+
+ if (!ima || !iuser)
+ return;
+
+ ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
+
+ image_info(CTX_data_scene(C), iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ uiItemL(layout, str, ICON_NONE);
+}
+
+#undef MAX_IMAGE_INFO_LEN
+
void image_buttons_register(ARegionType *UNUSED(art))
{
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index 757059ebc29..8e2c6b97a5b 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -35,6 +35,7 @@
#include "BLI_rect.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
@@ -290,6 +291,20 @@ void ED_image_point_pos__reverse(SpaceImage *sima, ARegion *ar, const float co[2
r_co[1] = (co[1] * height * zoomy) + (float)sy;
}
+void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *sima, struct ImBuf *ibuf, bool use_view_settings)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+
+ /* scope update can be expensive, don't update during paint modes */
+ if (sima->mode == SI_MODE_PAINT)
+ return;
+ if (ob && ((ob->mode & OB_MODE_TEXTURE_PAINT) != 0))
+ return;
+
+ scopes_update(&sima->scopes, ibuf, use_view_settings ? &scene->view_settings : NULL, &scene->display_settings);
+}
+
bool ED_space_image_show_render(SpaceImage *sima)
{
return (sima->image && ELEM(sima->image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE));
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 6cf53533618..af1502509f5 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -899,9 +899,9 @@ static void image_tools_area_draw(const bContext *C, ARegion *ar)
BKE_histogram_update_sample_line(&sima->sample_line_hist, ibuf, &scene->view_settings, &scene->display_settings);
}
if (sima->image->flag & IMA_VIEW_AS_RENDER)
- scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings);
+ ED_space_image_scopes_update(C, sima, ibuf, true);
else
- scopes_update(&sima->scopes, ibuf, NULL, &scene->display_settings);
+ ED_space_image_scopes_update(C, sima, ibuf, false);
}
}
ED_space_image_release_buffer(sima, ibuf, lock);
diff --git a/source/blender/editors/space_logic/logic_ops.c b/source/blender/editors/space_logic/logic_ops.c
index 62703ba517e..2c6280f5670 100644
--- a/source/blender/editors/space_logic/logic_ops.c
+++ b/source/blender/editors/space_logic/logic_ops.c
@@ -39,6 +39,8 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_sca.h"
@@ -298,7 +300,7 @@ static int sensor_add_exec(bContext *C, wmOperator *op)
BLI_strncpy(sens->name, sens_name, sizeof(sens->name));
}
- make_unique_prop_names(C, sens->name);
+ BLI_uniquename(&ob->sensors, sens, DATA_("Sensor"), '.', offsetof(bSensor, name), sizeof(sens->name));
ob->scaflag |= OB_SHOWSENS;
WM_event_add_notifier(C, NC_LOGIC, NULL);
@@ -405,7 +407,8 @@ static int controller_add_exec(bContext *C, wmOperator *op)
BLI_strncpy(cont->name, cont_name, sizeof(cont->name));
}
- make_unique_prop_names(C, cont->name);
+ BLI_uniquename(&ob->controllers, cont, DATA_("Controller"), '.', offsetof(bController, name), sizeof(cont->name));
+
/* set the controller state mask from the current object state.
* A controller is always in a single state, so select the lowest bit set
* from the object state */
@@ -523,7 +526,7 @@ static int actuator_add_exec(bContext *C, wmOperator *op)
BLI_strncpy(act->name, act_name, sizeof(act->name));
}
- make_unique_prop_names(C, act->name);
+ BLI_uniquename(&ob->actuators, act, DATA_("Actuator"), '.', offsetof(bActuator, name), sizeof(act->name));
ob->scaflag |= OB_SHOWACT;
WM_event_add_notifier(C, NC_LOGIC, NULL);
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index 21a9246d7e6..37c634672df 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -48,6 +48,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
#include "BKE_action.h"
#include "BKE_context.h"
@@ -94,87 +95,6 @@
/* proto */
static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisflag);
-static int vergname(const void *v1, const void *v2)
-{
- const char * const *x1 = v1, * const *x2 = v2;
- return BLI_natstrcmp(*x1, *x2);
-}
-
-void make_unique_prop_names(bContext *C, char *str)
-{
- Object *ob;
- bProperty *prop;
- bSensor *sens;
- bController *cont;
- bActuator *act;
- ID **idar;
- short a, obcount, propcount=0, nr;
- const char **names;
-
- /* this function is called by a Button, and gives the current
- * stringpointer as an argument, this is the one that can change
- */
-
- idar= get_selected_and_linked_obs(C, &obcount, BUTS_SENS_SEL|BUTS_SENS_ACT|BUTS_ACT_SEL|BUTS_ACT_ACT|BUTS_CONT_SEL|BUTS_CONT_ACT);
-
- /* for each object, make properties and sca names unique */
-
- /* count total names */
- for (a=0; a<obcount; a++) {
- ob= (Object *)idar[a];
- propcount+= BLI_listbase_count(&ob->prop);
- propcount+= BLI_listbase_count(&ob->sensors);
- propcount+= BLI_listbase_count(&ob->controllers);
- propcount+= BLI_listbase_count(&ob->actuators);
- }
- if (propcount==0) {
- if (idar) MEM_freeN(idar);
- return;
- }
-
- /* make names array for sorting */
- names= MEM_callocN(propcount*sizeof(void *), "names");
-
- /* count total names */
- nr= 0;
- for (a=0; a<obcount; a++) {
- ob= (Object *)idar[a];
- prop= ob->prop.first;
- while (prop) {
- names[nr++] = prop->name;
- prop= prop->next;
- }
- sens= ob->sensors.first;
- while (sens) {
- names[nr++] = sens->name;
- sens= sens->next;
- }
- cont= ob->controllers.first;
- while (cont) {
- names[nr++] = cont->name;
- cont= cont->next;
- }
- act= ob->actuators.first;
- while (act) {
- names[nr++] = act->name;
- act= act->next;
- }
- }
-
- qsort(names, propcount, sizeof(void *), vergname);
-
- /* now we check for double names, and change them */
-
- for (nr=0; nr<propcount; nr++) {
- if (names[nr]!=str && strcmp( names[nr], str )==0 ) {
- BLI_newname(str, +1);
- }
- }
-
- MEM_freeN(idar);
- MEM_freeN(names);
-}
-
static void do_logic_buts(bContext *C, void *UNUSED(arg), int event)
{
Main *bmain= CTX_data_main(C);
@@ -206,7 +126,7 @@ static void do_logic_buts(bContext *C, void *UNUSED(arg), int event)
ob->scaflag &= ~OB_ADDSENS;
sens= new_sensor(SENS_ALWAYS);
BLI_addtail(&(ob->sensors), sens);
- make_unique_prop_names(C, sens->name);
+ BLI_uniquename(&ob->sensors, sens, DATA_("Sensor"), '.', offsetof(bSensor, name), sizeof(sens->name));
ob->scaflag |= OB_SHOWSENS;
}
}
@@ -248,7 +168,7 @@ static void do_logic_buts(bContext *C, void *UNUSED(arg), int event)
if (ob->scaflag & OB_ADDCONT) {
ob->scaflag &= ~OB_ADDCONT;
cont= new_controller(CONT_LOGIC_AND);
- make_unique_prop_names(C, cont->name);
+ BLI_uniquename(&ob->controllers, cont, DATA_("Controller"), '.', offsetof(bController, name), sizeof(cont->name));
ob->scaflag |= OB_SHOWCONT;
BLI_addtail(&(ob->controllers), cont);
/* set the controller state mask from the current object state.
@@ -324,7 +244,7 @@ static void do_logic_buts(bContext *C, void *UNUSED(arg), int event)
if (ob->scaflag & OB_ADDACT) {
ob->scaflag &= ~OB_ADDACT;
act= new_actuator(ACT_OBJECT);
- make_unique_prop_names(C, act->name);
+ BLI_uniquename(&ob->actuators, act, DATA_("Actuator"), '.', offsetof(bActuator, name), sizeof(act->name));
BLI_addtail(&(ob->actuators), act);
ob->scaflag |= OB_SHOWACT;
}
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 0abe5e42c3e..5476d1c2683 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -650,7 +650,7 @@ static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
/* get a list of the AnimData blocks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL);
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* delete tracks */
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index c45626e4284..2089dced7e3 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -38,6 +38,7 @@
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_text_types.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -389,6 +390,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
float width, ascender;
float x, y;
const int font_size = data->label_size / aspect;
+ const float margin = (float)(NODE_DY / 4);
nodeLabel(ntree, node, label, sizeof(label));
@@ -404,11 +406,42 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
/* 'x' doesn't need aspect correction */
x = BLI_rctf_cent_x(rct) - (0.5f * width);
- y = rct->ymax - (((NODE_DY / 4) / aspect) + (ascender * aspect));
+ y = rct->ymax - ((margin / aspect) + (ascender * aspect));
BLF_position(fontid, x, y, 0);
BLF_draw(fontid, label, BLF_DRAW_STR_DUMMY_MAX);
+ /* draw text body */
+ if (node->id) {
+ Text *text = (Text *)node->id;
+ TextLine *line;
+ const float line_spacing = (BLF_height_max(fontid) * aspect) * 0.7f;
+
+ /* 'x' doesn't need aspect correction */
+ x = rct->xmin + margin;
+ y = rct->ymax - ((margin / aspect) + (ascender * aspect));
+ y -= line_spacing;
+
+ BLF_enable(fontid, BLF_CLIPPING);
+ BLF_clipping(
+ fontid,
+ rct->xmin,
+ rct->ymin,
+ rct->xmin + ((rct->xmax - rct->xmin) / aspect) - margin,
+ rct->ymax);
+
+ for (line = text->lines.first; line; line = line->next) {
+ BLF_position(fontid, x, y, 0);
+ BLF_draw(fontid, line->line, line->len);
+ y -= line_spacing;
+ if (y < rct->ymin) {
+ break;
+ }
+ }
+
+ BLF_disable(fontid, BLF_CLIPPING);
+ }
+
BLF_disable(fontid, BLF_ASPECT);
}
@@ -498,6 +531,7 @@ static void node_buts_frame_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA
{
uiItemR(layout, ptr, "label_size", 0, IFACE_("Label Size"), ICON_NONE);
uiItemR(layout, ptr, "shrink", 0, IFACE_("Shrink"), ICON_NONE);
+ uiItemR(layout, ptr, "text", 0, NULL, ICON_NONE);
}
@@ -669,10 +703,10 @@ static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr,
uiItemR(col, ptr, "use_auto_refresh", 0, NULL, ICON_NONE);
}
- col = uiLayoutColumn(layout, false);
-
- if (RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER)
+ if (RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER) {
+ col = uiLayoutColumn(layout, false);
uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE);
+ }
}
static void node_shader_buts_material(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -805,10 +839,51 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
+
+ node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr);
+
uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
+}
- node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr);
+static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+ PointerRNA imaptr = RNA_pointer_get(ptr, "image");
+ PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
+ Image *ima = imaptr.data;
+
+ uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
+ uiTemplateID(layout, C, ptr, "image", ima ? NULL : "IMAGE_OT_new", "IMAGE_OT_open", NULL);
+
+ if (!ima)
+ return;
+
+ uiItemR(layout, &imaptr, "source", 0, IFACE_("Source"), ICON_NONE);
+
+ if (!(ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER))) {
+ uiLayout *row = uiLayoutRow(layout, true);
+
+ if (ima->packedfile)
+ uiItemO(row, "", ICON_PACKAGE, "image.unpack");
+ else
+ uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
+
+ row = uiLayoutRow(row, true);
+ uiLayoutSetEnabled(row, ima->packedfile == NULL);
+ uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
+ uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
+ }
+
+ /* multilayer? */
+ if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
+ uiTemplateImageLayers(layout, C, ima, iuserptr.data);
+ }
+ else if (ima->source != IMA_SRC_GENERATED) {
+ uiTemplateImageInfo(layout, C, ima, iuserptr.data);
+ }
+
+ uiItemR(layout, ptr, "color_space", 0, IFACE_("Color Space"), ICON_NONE);
+ uiItemR(layout, ptr, "projection", 0, IFACE_("Projection"), ICON_NONE);
}
static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -861,6 +936,7 @@ static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C),
static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
+ uiItemR(layout, ptr, "object", 0, NULL, 0);
uiItemR(layout, ptr, "from_dupli", 0, NULL, 0);
}
@@ -1071,6 +1147,7 @@ static void node_shader_set_butfunc(bNodeType *ntype)
break;
case SH_NODE_TEX_ENVIRONMENT:
ntype->draw_buttons = node_shader_buts_tex_environment;
+ ntype->draw_buttons_ex = node_shader_buts_tex_environment_ex;
break;
case SH_NODE_TEX_GRADIENT:
ntype->draw_buttons = node_shader_buts_tex_gradient;
@@ -2279,6 +2356,7 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
bNode *node = ptr->data;
+ NodePlaneTrackDeformData *data = node->storage;
uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
@@ -2307,6 +2385,12 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P
uiItemR(layout, ptr, "plane_track_name", 0, "", ICON_ANIM_DATA);
}
}
+
+ uiItemR(layout, ptr, "use_motion_blur", 0, NULL, ICON_NONE);
+ if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
+ uiItemR(layout, ptr, "motion_blur_samples", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "motion_blur_shutter", 0, NULL, ICON_NONE);
+ }
}
static void node_composit_buts_cornerpin(uiLayout *UNUSED(layout), bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
@@ -3053,9 +3137,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
/* somehow the offset has to be calculated inverse */
glaDefine2DArea(&ar->winrct);
- /* ortho at pixel level curarea */
- /* almost #wmOrtho2_region_pixelspace, but no +1 px */
- wmOrtho2_pixelspace(ar->winx, ar->winy);
+ wmOrtho2_region_pixelspace(ar);
x = (ar->winx - snode->zoom * ibuf->x) / 2 + snode->xof;
y = (ar->winy - snode->zoom * ibuf->y) / 2 + snode->yof;
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 16ad63bcafa..87a64e95e63 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -1304,6 +1304,11 @@ void drawnodespace(const bContext *C, ARegion *ar)
path = snode->treepath.last;
+ /* update tree path name (drawn in the bottom left) */
+ if (snode->id && UNLIKELY(!STREQ(path->node_name, snode->id->name + 2))) {
+ BLI_strncpy(path->node_name, snode->id->name + 2, sizeof(path->node_name));
+ }
+
/* current View2D center, will be set temporarily for parent node trees */
UI_view2d_center_get(v2d, &center[0], &center[1]);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 1e258368b8b..f79d6e26f22 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -566,7 +566,7 @@ void snode_set_context(const bContext *C)
return;
}
- if (snode->nodetree && strcmp(snode->nodetree->idname, snode->tree_idname) != 0) {
+ if (snode->nodetree && !STREQ(snode->nodetree->idname, snode->tree_idname)) {
/* current tree does not match selected type, clear tree path */
ntree = NULL;
id = NULL;
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index e3baddef158..62cb0bc73cd 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -668,7 +668,7 @@ static void node_main_area_draw(const bContext *C, ARegion *ar)
static int node_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_IM)
return 1;
}
@@ -682,7 +682,7 @@ static int node_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *
static int node_mask_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_MSK)
return 1;
}
@@ -691,14 +691,14 @@ static int node_mask_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (id) {
RNA_string_set(drop->ptr, "name", id->name + 2);
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 9bc043b384e..47bf87b360b 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -31,6 +31,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_group_types.h"
#include "DNA_lamp_types.h"
#include "DNA_object_types.h"
@@ -346,6 +347,11 @@ static void restrictbutton_ebone_visibility_cb(bContext *C, void *UNUSED(poin),
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
}
+static void restrictbutton_gp_layer_flag_cb(bContext *C, void *UNUSED(poin), void *UNUSED(poin2))
+{
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
+}
+
static int group_restrict_flag(Group *gr, int flag)
{
GroupObject *gob;
@@ -447,7 +453,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
TreeStoreElem *tselem = tsep;
if (ts && tselem) {
- TreeElement *te = outliner_find_tse(soops, tselem);
+ TreeElement *te = outliner_find_tree_element(&soops->tree, tselem);
if (tselem->type == 0) {
test_idbutton(tselem->id->name); // library.c, unique name and alpha sort
@@ -549,6 +555,17 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
break;
}
+ case TSE_GP_LAYER:
+ {
+ bGPdata *gpd = (bGPdata *)tselem->id; // id = GP Datablock
+ bGPDlayer *gpl = te->directdata;
+
+ // XXX: name needs translation stuff
+ BLI_uniquename(&gpd->layers, gpl, "GP Layer", '.',
+ offsetof(bGPDlayer, info), sizeof(gpl->info));
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, gpd);
+ break;
+ }
case TSE_R_LAYER:
break;
}
@@ -742,6 +759,29 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
UI_block_emboss_set(block, UI_EMBOSS);
}
+ else if (tselem->type == TSE_GP_LAYER) {
+ bGPDlayer *gpl = (bGPDlayer *)te->directdata;
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_HIDE, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0,
+ TIP_("Restrict/Allow visibility in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, NULL, gpl);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_LOCKED, 0, ICON_UNLOCKED,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0,
+ TIP_("Restrict/Allow editing of strokes and keyframes in this layer"));
+ UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, NULL, gpl);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ /* TODO: visibility in renders */
+
+ UI_block_emboss_set(block, UI_EMBOSS);
+ }
}
if (TSELEM_OPEN(tselem, soops)) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree);
@@ -877,6 +917,36 @@ static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon)
}
+static void tselem_draw_gp_icon_uibut(struct DrawIconArg *arg, ID *id, bGPDlayer *gpl)
+{
+ /* restrict column clip - skip it for now... */
+ if (arg->x >= arg->xmax) {
+ /* pass */
+ }
+ else {
+ PointerRNA ptr;
+ float w = 0.85f * U.widget_unit;
+ float h = 0.85f * UI_UNIT_Y;
+
+ RNA_pointer_create(id, &RNA_GPencilLayer, gpl, &ptr);
+
+ UI_block_align_begin(arg->block);
+
+ UI_block_emboss_set(arg->block, RNA_boolean_get(&ptr, "is_stroke_visible") ? UI_EMBOSS : UI_EMBOSS_NONE);
+ uiDefButR(arg->block, UI_BTYPE_COLOR, 1, "", arg->xb, arg->yb, w, h,
+ &ptr, "color", -1,
+ 0, 0, 0, 0, NULL);
+
+ UI_block_emboss_set(arg->block, RNA_boolean_get(&ptr, "is_fill_visible") ? UI_EMBOSS : UI_EMBOSS_NONE);
+ uiDefButR(arg->block, UI_BTYPE_COLOR, 1, "", arg->xb, arg->yb, w, h,
+ &ptr, "fill_color", -1,
+ 0, 0, 0, 0, NULL);
+
+ UI_block_emboss_set(arg->block, UI_EMBOSS_NONE);
+ UI_block_align_end(arg->block);
+ }
+}
+
static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te,
float alpha)
{
@@ -1020,6 +1090,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
case eModifierType_DataTransfer:
UI_icon_draw(x, y, ICON_MOD_DATA_TRANSFER); break;
+ case eModifierType_NormalEdit:
+ UI_icon_draw(x, y, ICON_MOD_NORMALEDIT); break;
case eModifierType_PointCache:
UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
/* Default */
@@ -1074,6 +1146,9 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
else
UI_icon_draw(x, y, RNA_struct_ui_icon(te->rnaptr.type));
break;
+ case TSE_GP_LAYER:
+ tselem_draw_gp_icon_uibut(&arg, tselem->id, te->directdata);
+ break;
default:
UI_icon_draw(x, y, ICON_DOT); break;
}
@@ -1167,6 +1242,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT); break;
case ID_LS:
tselem_draw_icon_uibut(&arg, ICON_LINE_DATA); break;
+ case ID_GD:
+ tselem_draw_icon_uibut(&arg, ICON_GREASEPENCIL); break;
}
}
}
@@ -1250,8 +1327,9 @@ static void outliner_set_coord_tree_element(SpaceOops *soops, TreeElement *te, i
}
-static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops,
- TreeElement *te, int startx, int *starty, TreeElement **te_edit)
+static void outliner_draw_tree_element(
+ bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ARegion *ar, SpaceOops *soops,
+ TreeElement *te, int startx, int *starty, TreeElement **te_edit)
{
TreeElement *ten;
TreeStoreElem *tselem;
@@ -1410,9 +1488,9 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
else if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.75f);
else UI_ThemeColor(TH_TEXT);
- UI_draw_string(startx + offsx, *starty + 5 * ufac, te->name);
+ UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name);
- offsx += (int)(UI_UNIT_X + UI_fontstyle_string_width(te->name));
+ offsx += (int)(UI_UNIT_X + UI_fontstyle_string_width(fstyle, te->name));
/* closed item, we draw the icons, not when it's a scene, or master-server list though */
if (!TSELEM_OPEN(tselem, soops)) {
@@ -1450,13 +1528,15 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
if (TSELEM_OPEN(tselem, soops)) {
*starty -= UI_UNIT_Y;
-
- for (ten = te->subtree.first; ten; ten = ten->next)
- outliner_draw_tree_element(C, block, scene, ar, soops, ten, startx + UI_UNIT_X, starty, te_edit);
+
+ for (ten = te->subtree.first; ten; ten = ten->next) {
+ outliner_draw_tree_element(C, block, fstyle, scene, ar, soops, ten, startx + UI_UNIT_X, starty, te_edit);
+ }
}
else {
- for (ten = te->subtree.first; ten; ten = ten->next)
+ for (ten = te->subtree.first; ten; ten = ten->next) {
outliner_set_coord_tree_element(soops, ten, startx, *starty);
+ }
*starty -= UI_UNIT_Y;
}
@@ -1539,6 +1619,7 @@ static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb,
static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegion *ar,
SpaceOops *soops, TreeElement **te_edit)
{
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
TreeElement *te;
int starty, startx;
float col[3];
@@ -1569,7 +1650,7 @@ static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegio
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
startx = 0;
for (te = soops->tree.first; te; te = te->next) {
- outliner_draw_tree_element(C, block, scene, ar, soops, te, startx, &starty, te_edit);
+ outliner_draw_tree_element(C, block, fstyle, scene, ar, soops, te, startx, &starty, te_edit);
}
}
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index ab7b1583275..d17ab33d0fa 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -50,6 +50,7 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_material.h"
+#include "BKE_group.h"
#include "ED_object.h"
#include "ED_screen.h"
@@ -73,22 +74,6 @@
/* This is not used anywhere at the moment */
#if 0
-/* return 1 when levels were opened */
-static int outliner_open_back(SpaceOops *soops, TreeElement *te)
-{
- TreeStoreElem *tselem;
- int retval = 0;
-
- for (te = te->parent; te; te = te->parent) {
- tselem = TREESTORE(te);
- if (tselem->flag & TSE_CLOSED) {
- tselem->flag &= ~TSE_CLOSED;
- retval = 1;
- }
- }
- return retval;
-}
-
static void outliner_open_reveal(SpaceOops *soops, ListBase *lb, TreeElement *teFind, int *found)
{
TreeElement *te;
@@ -113,7 +98,9 @@ static void outliner_open_reveal(SpaceOops *soops, ListBase *lb, TreeElement *te
}
#endif
-static TreeElement *outliner_dropzone_element(const SpaceOops *soops, TreeElement *te, const float fmval[2], const int children)
+static TreeElement *outliner_dropzone_element(
+ const SpaceOops *soops, TreeElement *te,
+ const float fmval[2], const bool children)
{
if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) {
/* name and first icon */
@@ -132,7 +119,7 @@ static TreeElement *outliner_dropzone_element(const SpaceOops *soops, TreeElemen
}
/* Used for drag and drop parenting */
-TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2], const int children)
+TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2], const bool children)
{
TreeElement *te;
@@ -601,6 +588,50 @@ void OUTLINER_OT_selected_toggle(wmOperatorType *ot)
/* Show Active --------------------------------------------------- */
+static void outliner_set_coordinates_element_recursive(SpaceOops *soops, TreeElement *te, int startx, int *starty)
+{
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ /* store coord and continue, we need coordinates for elements outside view too */
+ te->xs = (float)startx;
+ te->ys = (float)(*starty);
+ *starty -= UI_UNIT_Y;
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ TreeElement *ten;
+ for (ten = te->subtree.first; ten; ten = ten->next) {
+ outliner_set_coordinates_element_recursive(soops, ten, startx + UI_UNIT_X, starty);
+ }
+ }
+}
+
+/* to retrieve coordinates with redrawing the entire tree */
+static void outliner_set_coordinates(ARegion *ar, SpaceOops *soops)
+{
+ TreeElement *te;
+ int starty = (int)(ar->v2d.tot.ymax) - UI_UNIT_Y;
+
+ for (te = soops->tree.first; te; te = te->next) {
+ outliner_set_coordinates_element_recursive(soops, te, 0, &starty);
+ }
+}
+
+/* return 1 when levels were opened */
+static int outliner_open_back(TreeElement *te)
+{
+ TreeStoreElem *tselem;
+ int retval = 0;
+
+ for (te = te->parent; te; te = te->parent) {
+ tselem = TREESTORE(te);
+ if (tselem->flag & TSE_CLOSED) {
+ tselem->flag &= ~TSE_CLOSED;
+ retval = 1;
+ }
+ }
+ return retval;
+}
+
static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceOops *so = CTX_wm_space_outliner(C);
@@ -617,6 +648,11 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
te = outliner_find_id(so, &so->tree, (ID *)OBACT);
if (te) {
+ /* open up tree to active object */
+ if (outliner_open_back(te)) {
+ outliner_set_coordinates(ar, so);
+ }
+
/* make te->ys center of view */
ytop = te->ys + BLI_rcti_size_y(&v2d->mask) / 2;
if (ytop > 0) ytop = 0;
@@ -642,7 +678,7 @@ void OUTLINER_OT_show_active(wmOperatorType *ot)
/* identifiers */
ot->name = "Show Active";
ot->idname = "OUTLINER_OT_show_active";
- ot->description = "Adjust the view so that the active Object is shown centered";
+ ot->description = "Open up the tree and adjust the view so that the active Object is shown centered";
/* callbacks */
ot->exec = outliner_show_active_exec;
@@ -690,37 +726,6 @@ void OUTLINER_OT_scroll_page(wmOperatorType *ot)
#if 0
-/* recursive helper for function below */
-static void outliner_set_coordinates_element(SpaceOops *soops, TreeElement *te, int startx, int *starty)
-{
- TreeStoreElem *tselem = TREESTORE(te);
-
- /* store coord and continue, we need coordinates for elements outside view too */
- te->xs = (float)startx;
- te->ys = (float)(*starty);
- *starty -= UI_UNIT_Y;
-
- if (TSELEM_OPEN(tselem, soops)) {
- TreeElement *ten;
- for (ten = te->subtree.first; ten; ten = ten->next) {
- outliner_set_coordinates_element(soops, ten, startx + UI_UNIT_X, starty);
- }
- }
-
-}
-
-/* to retrieve coordinates with redrawing the entire tree */
-static void outliner_set_coordinates(ARegion *ar, SpaceOops *soops)
-{
- TreeElement *te;
- int starty = (int)(ar->v2d.tot.ymax) - UI_UNIT_Y;
- int startx = 0;
-
- for (te = soops->tree.first; te; te = te->next) {
- outliner_set_coordinates_element(soops, te, startx, &starty);
- }
-}
-
/* find next element that has this name */
static TreeElement *outliner_find_name(SpaceOops *soops, ListBase *lb, char *name, int flags,
TreeElement *prev, int *prevFound)
@@ -1500,7 +1505,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
/* Find object hovered over */
- te = outliner_dropzone_find(soops, fmval, 1);
+ te = outliner_dropzone_find(soops, fmval, true);
if (te) {
RNA_string_set(op->ptr, "parent", te->name);
@@ -1715,7 +1720,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
/* Find object hovered over */
- te = outliner_dropzone_find(soops, fmval, 0);
+ te = outliner_dropzone_find(soops, fmval, false);
if (te) {
Base *base;
@@ -1785,7 +1790,7 @@ static int material_drop_invoke(bContext *C, wmOperator *op, const wmEvent *even
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
/* Find object hovered over */
- te = outliner_dropzone_find(soops, fmval, 1);
+ te = outliner_dropzone_find(soops, fmval, true);
if (te) {
RNA_string_set(op->ptr, "object", te->name);
@@ -1829,3 +1834,65 @@ void OUTLINER_OT_material_drop(wmOperatorType *ot)
RNA_def_string(ot->srna, "material", "Material", MAX_ID_NAME, "Material", "Target Material");
}
+static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Main *bmain = CTX_data_main(C);
+ Group *group = NULL;
+ Object *ob = NULL;
+ Scene *scene = CTX_data_scene(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
+ TreeElement *te = NULL;
+ char ob_name[MAX_ID_NAME - 2];
+ float fmval[2];
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+
+ /* Find object hovered over */
+ te = outliner_dropzone_find(soops, fmval, true);
+
+ if (te) {
+ group = (Group *)BKE_libblock_find_name(ID_GR, te->name);
+
+ RNA_string_get(op->ptr, "object", ob_name);
+ ob = (Object *)BKE_libblock_find_name(ID_OB, ob_name);
+
+ if (ELEM(NULL, group, ob)) {
+ return OPERATOR_CANCELLED;
+ }
+ if (BKE_group_object_exists(group, ob)) {
+ return OPERATOR_FINISHED;
+ }
+
+ if (BKE_group_object_cyclic_check(bmain, ob, group)) {
+ BKE_report(op->reports, RPT_ERROR, "Could not add the group because of dependency cycle detected");
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_group_object_add(group, ob, scene, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void OUTLINER_OT_group_link(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Link Object to Group";
+ ot->description = "Link Object to Group in Outliner";
+ ot->idname = "OUTLINER_OT_group_link";
+
+ /* api callbacks */
+ ot->invoke = group_link_invoke;
+
+ ot->poll = ED_operator_outliner_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+
+ /* properties */
+ RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object");
+}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 317d33dd3e2..f0920466b85 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -104,6 +104,7 @@ typedef struct TreeElement {
#define TSE_KEYMAP 34
#define TSE_KEYMAP_ITEM 35
#define TSE_ID_BASE 36
+#define TSE_GP_LAYER 37
/* button events */
#define OL_NAMEBUTTON 1
@@ -166,6 +167,7 @@ void outliner_free_tree(ListBase *lb);
void outliner_cleanup_tree(struct SpaceOops *soops);
TreeElement *outliner_find_tse(struct SpaceOops *soops, TreeStoreElem *tse);
+TreeElement *outliner_find_tree_element(ListBase *lb, TreeStoreElem *store_elem);
TreeElement *outliner_find_id(struct SpaceOops *soops, ListBase *lb, struct ID *id);
struct ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode);
@@ -205,7 +207,7 @@ void group_toggle_renderability_cb(struct bContext *C, struct Scene *scene, Tree
void item_rename_cb(struct bContext *C, struct Scene *scene, TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem);
-TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const int children);
+TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const bool children);
/* ...................................................... */
void OUTLINER_OT_item_activate(struct wmOperatorType *ot);
@@ -237,6 +239,7 @@ void OUTLINER_OT_parent_drop(struct wmOperatorType *ot);
void OUTLINER_OT_parent_clear(struct wmOperatorType *ot);
void OUTLINER_OT_scene_drop(struct wmOperatorType *ot);
void OUTLINER_OT_material_drop(struct wmOperatorType *ot);
+void OUTLINER_OT_group_link(struct wmOperatorType *ot);
/* outliner_tools.c ---------------------------------------------- */
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 4f13454ef34..d54ae3f22a7 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -77,6 +77,7 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_parent_clear);
WM_operatortype_append(OUTLINER_OT_scene_drop);
WM_operatortype_append(OUTLINER_OT_material_drop);
+ WM_operatortype_append(OUTLINER_OT_group_link);
}
void outliner_keymap(wmKeyConfig *keyconf)
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 23586a6a509..730ee02f448 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -775,7 +775,7 @@ static eOLDrawState tree_element_active_sequence_dup(
continue;
}
-// if (!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
+// if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name))
// XXX select_single_seq(p, 0);
p = p->next;
}
@@ -873,6 +873,9 @@ eOLDrawState tree_element_type_active(
return tree_element_active_sequence_dup(scene, te, tselem, set);
case TSE_KEYMAP_ITEM:
return tree_element_active_keymap_item(C, te, tselem, set);
+ case TSE_GP_LAYER:
+ //return tree_element_active_gplayer(C, scene, te, tselem, set);
+ break;
}
return OL_DRAWSEL_NONE;
@@ -915,7 +918,7 @@ static bool do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, Sp
if (tselem->type != TSE_SEQUENCE && tselem->type != TSE_SEQ_STRIP && tselem->type != TSE_SEQUENCE_DUP)
tree_element_set_active_object(C, scene, soops, te,
(extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
- recursive && tselem->type == 0 );
+ recursive && tselem->type == 0);
if (tselem->type == 0) { // the lib blocks
/* editmode? */
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index d09ed1a100e..bd884039b30 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -499,19 +499,28 @@ static void refreshdrivers_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te
/* --------------------------------- */
+typedef enum eOutliner_PropDataOps {
+ OL_DOP_INVALID = 0,
+ OL_DOP_SELECT,
+ OL_DOP_DESELECT,
+ OL_DOP_HIDE,
+ OL_DOP_UNHIDE,
+ OL_DOP_SELECT_LINKED,
+} eOutliner_PropDataOps;
+
static void pchan_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
{
bPoseChannel *pchan = (bPoseChannel *)te->directdata;
- if (event == 1)
+ if (event == OL_DOP_SELECT)
pchan->bone->flag |= BONE_SELECTED;
- else if (event == 2)
+ else if (event == OL_DOP_DESELECT)
pchan->bone->flag &= ~BONE_SELECTED;
- else if (event == 3) {
+ else if (event == OL_DOP_HIDE) {
pchan->bone->flag |= BONE_HIDDEN_P;
pchan->bone->flag &= ~BONE_SELECTED;
}
- else if (event == 4)
+ else if (event == OL_DOP_UNHIDE)
pchan->bone->flag &= ~BONE_HIDDEN_P;
}
@@ -519,15 +528,15 @@ static void bone_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), v
{
Bone *bone = (Bone *)te->directdata;
- if (event == 1)
+ if (event == OL_DOP_SELECT)
bone->flag |= BONE_SELECTED;
- else if (event == 2)
+ else if (event == OL_DOP_DESELECT)
bone->flag &= ~BONE_SELECTED;
- else if (event == 3) {
+ else if (event == OL_DOP_HIDE) {
bone->flag |= BONE_HIDDEN_P;
bone->flag &= ~BONE_SELECTED;
}
- else if (event == 4)
+ else if (event == OL_DOP_UNHIDE)
bone->flag &= ~BONE_HIDDEN_P;
}
@@ -535,22 +544,22 @@ static void ebone_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem),
{
EditBone *ebone = (EditBone *)te->directdata;
- if (event == 1)
+ if (event == OL_DOP_SELECT)
ebone->flag |= BONE_SELECTED;
- else if (event == 2)
+ else if (event == OL_DOP_DESELECT)
ebone->flag &= ~BONE_SELECTED;
- else if (event == 3) {
+ else if (event == OL_DOP_HIDE) {
ebone->flag |= BONE_HIDDEN_A;
ebone->flag &= ~BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL;
}
- else if (event == 4)
+ else if (event == OL_DOP_UNHIDE)
ebone->flag &= ~BONE_HIDDEN_A;
}
static void sequence_cb(int event, TreeElement *te, TreeStoreElem *tselem, void *scene_ptr)
{
Sequence *seq = (Sequence *)te->directdata;
- if (event == 1) {
+ if (event == OL_DOP_SELECT) {
Scene *scene = (Scene *)scene_ptr;
Editing *ed = BKE_sequencer_editing_get(scene, false);
if (BLI_findindex(ed->seqbasep, seq) != -1) {
@@ -563,7 +572,7 @@ static void sequence_cb(int event, TreeElement *te, TreeStoreElem *tselem, void
static void data_select_linked_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *C_v)
{
- if (event == 5) {
+ if (event == OL_DOP_SELECT_LINKED) {
if (RNA_struct_is_ID(te->rnaptr.type)) {
bContext *C = (bContext *) C_v;
ID *id = te->rnaptr.data;
@@ -593,6 +602,49 @@ static void outliner_do_data_operation(SpaceOops *soops, int type, int event, Li
}
}
+static void outline_delete_hierarchy(bContext *C, Scene *scene, Base *base)
+{
+ Base *child_base;
+ Object *parent;
+
+ if (!base) {
+ return;
+ }
+
+ for (child_base = scene->base.first; child_base; child_base = child_base->next) {
+ for (parent = child_base->object->parent; parent && (parent != base->object); parent = parent->parent);
+ if (parent) {
+ outline_delete_hierarchy(C, scene, child_base);
+ }
+ }
+
+ ED_base_object_free_and_unlink(CTX_data_main(C), scene, base);
+}
+
+static void object_delete_hierarchy_cb(
+ bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem)
+{
+ Base *base = (Base *)te->directdata;
+ Object *obedit = scene->obedit;
+
+ if (!base) {
+ base = BKE_scene_base_find(scene, (Object *)tselem->id);
+ }
+ if (base) {
+ /* Check also library later. */
+ for (; obedit && (obedit != base->object); obedit = obedit->parent);
+ if (obedit == base->object) {
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
+ }
+
+ outline_delete_hierarchy(C, scene, base);
+ te->directdata = NULL;
+ tselem->id = NULL;
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+}
+
/* **************************************** */
enum {
@@ -601,6 +653,7 @@ enum {
OL_OP_DESELECT,
OL_OP_SELECT_HIERARCHY,
OL_OP_DELETE,
+ OL_OP_DELETE_HIERARCHY,
OL_OP_LOCALIZED, /* disabled, see below */
OL_OP_TOGVIS,
OL_OP_TOGSEL,
@@ -613,6 +666,7 @@ static EnumPropertyItem prop_object_op_types[] = {
{OL_OP_DESELECT, "DESELECT", 0, "Deselect", ""},
{OL_OP_SELECT_HIERARCHY, "SELECT_HIERARCHY", 0, "Select Hierarchy", ""},
{OL_OP_DELETE, "DELETE", 0, "Delete", ""},
+ {OL_OP_DELETE_HIERARCHY, "DELETE_HIERARCHY", 0, "Delete Hierarchy", ""},
{OL_OP_TOGVIS, "TOGVIS", 0, "Toggle Visible", ""},
{OL_OP_TOGSEL, "TOGSEL", 0, "Toggle Selectable", ""},
{OL_OP_TOGREN, "TOGREN", 0, "Toggle Renderable", ""},
@@ -672,6 +726,16 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
str = "Delete Objects";
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
+ else if (event == OL_OP_DELETE_HIERARCHY) {
+ outliner_do_object_operation(C, scene, soops, &soops->tree, object_delete_hierarchy_cb);
+
+ /* XXX: See OL_OP_DELETE comment above. */
+ outliner_cleanup_tree(soops);
+
+ DAG_relations_tag_update(bmain);
+ str = "Delete Object Hierarchy";
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ }
else if (event == OL_OP_LOCALIZED) { /* disabled, see above enum (ton) */
outliner_do_object_operation(C, scene, soops, &soops->tree, id_local_cb);
str = "Localized Objects";
@@ -1196,11 +1260,11 @@ void OUTLINER_OT_animdata_operation(wmOperatorType *ot)
/* **************************************** */
static EnumPropertyItem prop_data_op_types[] = {
- {1, "SELECT", 0, "Select", ""},
- {2, "DESELECT", 0, "Deselect", ""},
- {3, "HIDE", 0, "Hide", ""},
- {4, "UNHIDE", 0, "Unhide", ""},
- {5, "SELECT_LINKED", 0, "Select Linked", ""},
+ {OL_DOP_SELECT, "SELECT", 0, "Select", ""},
+ {OL_DOP_DESELECT, "DESELECT", 0, "Deselect", ""},
+ {OL_DOP_HIDE, "HIDE", 0, "Hide", ""},
+ {OL_DOP_UNHIDE, "UNHIDE", 0, "Unhide", ""},
+ {OL_DOP_SELECT_LINKED, "SELECT_LINKED", 0, "Select Linked", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1208,7 +1272,7 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
- int event;
+ eOutliner_PropDataOps event;
/* check for invalid states */
if (soops == NULL)
@@ -1217,7 +1281,7 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
event = RNA_enum_get(op->ptr, "type");
set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
- if (event <= 0)
+ if (event <= OL_DOP_INVALID)
return OPERATOR_CANCELLED;
switch (datalevel) {
@@ -1253,7 +1317,7 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
break;
case TSE_RNA_STRUCT:
- if (event == 5) {
+ if (event == OL_DOP_SELECT_LINKED) {
outliner_do_data_operation(soops, datalevel, event, &soops->tree, data_select_linked_cb, C);
}
break;
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 4aa36da594b..abc82775c8d 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -38,6 +38,7 @@
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_camera_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_group_types.h"
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
@@ -196,7 +197,7 @@ void outliner_cleanup_tree(SpaceOops *soops)
}
/* Find specific item from the treestore */
-static TreeElement *outliner_find_tree_element(ListBase *lb, TreeStoreElem *store_elem)
+TreeElement *outliner_find_tree_element(ListBase *lb, TreeStoreElem *store_elem)
{
TreeElement *te, *tes;
for (te = lb->first; te; te = te->next) {
@@ -430,6 +431,8 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
// TODO: move this to the front?
if (outliner_animdata_test(sce->adt))
outliner_add_element(soops, lb, sce, te, TSE_ANIM_DATA, 0);
+
+ outliner_add_element(soops, lb, sce->gpd, te, 0, 0);
outliner_add_element(soops, lb, sce->world, te, 0, 0);
@@ -451,6 +454,8 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
if (ob->proxy && ob->id.lib == NULL)
outliner_add_element(soops, &te->subtree, ob->proxy, te, TSE_PROXY, 0);
+
+ outliner_add_element(soops, &te->subtree, ob->gpd, te, 0, 0);
outliner_add_element(soops, &te->subtree, ob->data, te, 0, 0);
@@ -809,6 +814,21 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
}
break;
}
+ case ID_GD:
+ {
+ bGPdata *gpd = (bGPdata *)id;
+ bGPDlayer *gpl;
+ int a = 0;
+
+ if (outliner_animdata_test(gpd->adt))
+ outliner_add_element(soops, &te->subtree, gpd, te, TSE_ANIM_DATA, 0);
+
+ // TODO: base element for layers?
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ outliner_add_element(soops, &te->subtree, gpl, te, TSE_GP_LAYER, a);
+ a++;
+ }
+ }
}
}
@@ -856,6 +876,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (type == TSE_ANIM_DATA) {
/* pass */
}
+ else if (type == TSE_GP_LAYER) {
+ /* pass */
+ }
else if (type == TSE_ID_BASE) {
/* pass */
}
@@ -938,6 +961,12 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
}
}
+ else if (type == TSE_GP_LAYER) {
+ bGPDlayer *gpl = (bGPDlayer *)idv;
+
+ te->name = gpl->info;
+ te->directdata = gpl;
+ }
else if (type == TSE_SEQUENCE) {
Sequence *seq = (Sequence *) idv;
Sequence *p;
@@ -1160,7 +1189,7 @@ static int need_add_seq_dup(Sequence *seq)
continue;
}
- if (!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
+ if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name))
return(2);
p = p->prev;
}
@@ -1172,7 +1201,7 @@ static int need_add_seq_dup(Sequence *seq)
continue;
}
- if (!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
+ if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name))
return(0);
p = p->next;
}
@@ -1191,7 +1220,7 @@ static void outliner_add_seq_dup(SpaceOops *soops, Sequence *seq, TreeElement *t
continue;
}
- if (!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name))
+ if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name))
/* ch = */ /* UNUSED */ outliner_add_element(soops, &te->subtree, (void *)p, te, TSE_SEQUENCE, index);
p = p->next;
}
@@ -1311,7 +1340,10 @@ static void outliner_sort(SpaceOops *soops, ListBase *lb)
TreeElement *te;
TreeStoreElem *tselem;
int totelem = 0;
-
+
+ if (soops->flag & SO_SKIP_SORT_ALPHA)
+ return;
+
te = lb->last;
if (te == NULL) return;
tselem = TREESTORE(te);
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 504d9628d98..30de9c16500 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -98,10 +98,10 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_OB) {
/* Ensure item under cursor is valid drop target */
- TreeElement *te = outliner_dropzone_find(soops, fmval, 1);
+ TreeElement *te = outliner_dropzone_find(soops, fmval, true);
if (te && te->idcode == ID_OB && TREESTORE(te)->type == 0) {
Scene *scene;
@@ -129,7 +129,7 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
static void outliner_parent_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "child", id->name + 2);
}
@@ -148,10 +148,10 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
}
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_OB) {
if (((Object *)id)->parent) {
- if ((te = outliner_dropzone_find(soops, fmval, 1))) {
+ if ((te = outliner_dropzone_find(soops, fmval, true))) {
TreeStoreElem *tselem = TREESTORE(te);
switch (te->idcode) {
@@ -171,7 +171,7 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
static void outliner_parent_clear_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "dragged_obj", id->name + 2);
/* Set to simple parent clear type. Avoid menus for drag and drop if possible.
@@ -188,10 +188,10 @@ static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *ev
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_OB) {
/* Ensure item under cursor is valid drop target */
- TreeElement *te = outliner_dropzone_find(soops, fmval, 0);
+ TreeElement *te = outliner_dropzone_find(soops, fmval, false);
return (te && te->idcode == ID_SCE && TREESTORE(te)->type == 0);
}
}
@@ -200,7 +200,7 @@ static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *ev
static void outliner_scene_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "object", id->name + 2);
}
@@ -213,10 +213,10 @@ static int outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_MA) {
/* Ensure item under cursor is valid drop target */
- TreeElement *te = outliner_dropzone_find(soops, fmval, 1);
+ TreeElement *te = outliner_dropzone_find(soops, fmval, true);
return (te && te->idcode == ID_OB && TREESTORE(te)->type == 0);
}
}
@@ -225,11 +225,35 @@ static int outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent
static void outliner_material_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "material", id->name + 2);
}
+static int outliner_group_link_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ float fmval[2];
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+
+ if (drag->type == WM_DRAG_ID) {
+ ID *id = drag->poin;
+ if (GS(id->name) == ID_OB) {
+ /* Ensure item under cursor is valid drop target */
+ TreeElement *te = outliner_dropzone_find(soops, fmval, true);
+ return (te && te->idcode == ID_GR && TREESTORE(te)->type == 0);
+ }
+ }
+ return 0;
+}
+
+static void outliner_group_link_copy(wmDrag *drag, wmDropBox *drop)
+{
+ ID *id = drag->poin;
+ RNA_string_set(drop->ptr, "object", id->name + 2);
+}
+
/* region dropbox definition */
static void outliner_dropboxes(void)
{
@@ -239,6 +263,7 @@ static void outliner_dropboxes(void)
WM_dropbox_add(lb, "OUTLINER_OT_parent_clear", outliner_parent_clear_poll, outliner_parent_clear_copy);
WM_dropbox_add(lb, "OUTLINER_OT_scene_drop", outliner_scene_drop_poll, outliner_scene_drop_copy);
WM_dropbox_add(lb, "OUTLINER_OT_material_drop", outliner_material_drop_poll, outliner_material_drop_copy);
+ WM_dropbox_add(lb, "OUTLINER_OT_group_link", outliner_group_link_poll, outliner_group_link_copy);
}
static void outliner_main_area_draw(const bContext *C, ARegion *ar)
@@ -362,6 +387,13 @@ static void outliner_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
break;
}
break;
+ case NC_GPENCIL:
+ switch (wmn->data) {
+ case ND_DATA:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index afb650f8cfd..3be6cd79504 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -70,6 +70,7 @@
#include "WM_api.h"
+#include "MEM_guardedalloc.h"
/* own include */
#include "sequencer_intern.h"
@@ -200,23 +201,25 @@ static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequenc
SoundWaveform *waveform;
- if (!sound->mutex)
- sound->mutex = BLI_mutex_alloc();
+ if (!sound->spinlock) {
+ sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock");
+ BLI_spin_init(sound->spinlock);
+ }
- BLI_mutex_lock(sound->mutex);
+ BLI_spin_lock(sound->spinlock);
if (!seq->sound->waveform) {
if (!(sound->flags & SOUND_FLAGS_WAVEFORM_LOADING)) {
/* prevent sounds from reloading */
seq->sound->flags |= SOUND_FLAGS_WAVEFORM_LOADING;
- BLI_mutex_unlock(sound->mutex);
+ BLI_spin_unlock(sound->spinlock);
sequencer_preview_add_sound(C, seq);
}
else {
- BLI_mutex_unlock(sound->mutex);
+ BLI_spin_unlock(sound->spinlock);
}
return; /* nothing to draw */
}
- BLI_mutex_unlock(sound->mutex);
+ BLI_spin_unlock(sound->spinlock);
waveform = seq->sound->waveform;
@@ -467,7 +470,7 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
}
}
else if (seq->type == SEQ_TYPE_MOVIECLIP) {
- if (seq->clip && strcmp(name, seq->clip->id.name + 2) != 0) {
+ if (seq->clip && !STREQ(name, seq->clip->id.name + 2)) {
str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d",
name, seq->clip->id.name + 2, seq->len);
}
@@ -477,7 +480,7 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
}
}
else if (seq->type == SEQ_TYPE_MASK) {
- if (seq->mask && strcmp(name, seq->mask->id.name + 2) != 0) {
+ if (seq->mask && !STREQ(name, seq->mask->id.name + 2)) {
str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d",
name, seq->mask->id.name + 2, seq->len);
}
@@ -1292,24 +1295,18 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glEnd();
/* safety border */
- if ((sseq->flag & SEQ_DRAW_SAFE_MARGINS) != 0) {
- float fac = 0.1;
-
- float a = fac * (x2 - x1);
- x1 += a;
- x2 -= a;
-
- a = fac * (y2 - y1);
- y1 += a;
- y2 -= a;
-
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
-
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
+ if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) {
+ UI_draw_safe_areas(
+ x1, x2, y1, y2,
+ scene->safe_areas.title,
+ scene->safe_areas.action);
+
+ if (sseq->flag & SEQ_SHOW_SAFE_CENTER) {
+ UI_draw_safe_areas(
+ x1, x2, y1, y2,
+ scene->safe_areas.title_center,
+ scene->safe_areas.action_center);
+ }
}
setlinestyle(0);
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 81af6dccc70..8d4a82fc02c 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -37,6 +37,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
#include "BLF_translation.h"
@@ -58,12 +59,14 @@
/* for menu/popup icons etc etc*/
+#include "ED_numinput.h"
#include "ED_screen.h"
#include "ED_transform.h"
#include "ED_sequencer.h"
#include "ED_space_api.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
/* own include */
@@ -146,11 +149,12 @@ static void proxy_startjob(void *pjv, short *stop, short *do_update, float *prog
struct SeqIndexBuildContext *context = link->data;
BKE_sequencer_proxy_rebuild(context, stop, do_update, progress);
- }
-
- if (*stop) {
- pj->stop = 1;
- fprintf(stderr, "Canceling proxy rebuild on users request...\n");
+
+ if (*stop) {
+ pj->stop = 1;
+ fprintf(stderr, "Canceling proxy rebuild on users request...\n");
+ break;
+ }
}
}
@@ -179,7 +183,8 @@ static void seq_proxy_build_job(const bContext *C)
struct SeqIndexBuildContext *context;
LinkData *link;
Sequence *seq;
-
+ GSet *file_list;
+
if (ed == NULL) {
return;
}
@@ -200,16 +205,19 @@ static void seq_proxy_build_job(const bContext *C)
WM_jobs_callbacks(wm_job, proxy_startjob, NULL, NULL, proxy_endjob);
}
+ file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
SEQP_BEGIN (ed, seq)
{
if ((seq->flag & SELECT)) {
- context = BKE_sequencer_proxy_rebuild_context(pj->main, pj->scene, seq);
+ context = BKE_sequencer_proxy_rebuild_context(pj->main, pj->scene, seq, file_list);
link = BLI_genericNodeN(context);
BLI_addtail(&pj->queue, link);
}
}
SEQ_END
+ BLI_gset_free(file_list, MEM_freeN);
+
if (!WM_jobs_is_running(wm_job)) {
G.is_break = false;
WM_jobs_start(CTX_wm_manager(C), wm_job);
@@ -987,13 +995,13 @@ static void UNUSED_FUNCTION(seq_remap_paths) (Scene *scene)
// XXX if (0 == sbutton(to, 0, sizeof(to)-1, "To: "))
// return;
- if (strcmp(to, from) == 0)
+ if (STREQ(to, from))
return;
SEQP_BEGIN (ed, seq)
{
if (seq->flag & SELECT) {
- if (strncmp(seq->strip->dir, from, strlen(from)) == 0) {
+ if (STREQLEN(seq->strip->dir, from, strlen(from))) {
printf("found %s\n", seq->strip->dir);
/* strip off the beginning */
@@ -1262,6 +1270,7 @@ typedef struct SlipData {
bool slow;
int slow_offset; /* offset at the point where offset was turned on */
void *draw_handle;
+ NumInput num_input;
} SlipData;
static void transseq_backup(TransSeq *ts, Sequence *seq)
@@ -1375,6 +1384,13 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
data->trim = MEM_mallocN(num_seq * sizeof(bool), "trimdata_trim");
data->num_seq = num_seq;
+ initNumInput(&data->num_input);
+ data->num_input.idx_max = 0;
+ data->num_input.val_flag[0] |= NUM_NO_FRACTION;
+ data->num_input.unit_sys = USER_UNIT_NONE;
+ data->num_input.unit_type[0] = 0;
+
+
slip_add_sequences_rec(ed->seqbasep, data->seq_array, data->trim, 0, true);
for (i = 0; i < num_seq; i++) {
@@ -1500,47 +1516,83 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
}
}
+
+static void sequencer_slip_update_header(Scene *scene, ScrArea *sa, SlipData *data, int offset)
+{
+#define HEADER_LENGTH 40
+ char msg[HEADER_LENGTH];
+
+ if (sa) {
+ if (hasNumInput(&data->num_input)) {
+ char num_str[NUM_STR_REP_LEN];
+ outputNumInput(&data->num_input, num_str, &scene->unit);
+ BLI_snprintf(msg, HEADER_LENGTH, "Trim offset: %s", num_str);
+ }
+ else {
+ BLI_snprintf(msg, HEADER_LENGTH, "Trim offset: %d", offset);
+ }
+ }
+
+ ED_area_headerprint(sa, msg);
+
+#undef HEADER_LENGTH
+}
+
static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
SlipData *data = (SlipData *)op->customdata;
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
+ const bool has_numInput = hasNumInput(&data->num_input);
+ bool handled = true;
+
+ /* Modal numinput active, try to handle numeric inputs first... */
+ if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &data->num_input, event)) {
+ float offset;
+ applyNumInput(&data->num_input, &offset);
+
+ sequencer_slip_update_header(scene, sa, data, (int)offset);
+
+ RNA_int_set(op->ptr, "offset", offset);
+
+ if (sequencer_slip_recursively(scene, data, offset)) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+ }
switch (event->type) {
case MOUSEMOVE:
{
- float mouseloc[2];
- int offset;
- int mouse_x;
- View2D *v2d = UI_view2d_fromcontext(C);
-
- if (data->slow) {
- mouse_x = event->mval[0] - data->slow_offset;
- mouse_x *= 0.1f;
- mouse_x += data->slow_offset;
- }
- else {
- mouse_x = event->mval[0];
- }
+ if (!has_numInput) {
+ float mouseloc[2];
+ int offset;
+ int mouse_x;
+ View2D *v2d = UI_view2d_fromcontext(C);
+
+ if (data->slow) {
+ mouse_x = event->mval[0] - data->slow_offset;
+ mouse_x *= 0.1f;
+ mouse_x += data->slow_offset;
+ }
+ else {
+ mouse_x = event->mval[0];
+ }
- /* choose the side based on which side of the playhead the mouse is on */
- UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
- offset = mouseloc[0] - data->init_mouseloc[0];
+ /* choose the side based on which side of the playhead the mouse is on */
+ UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
+ offset = mouseloc[0] - data->init_mouseloc[0];
- RNA_int_set(op->ptr, "offset", offset);
+ sequencer_slip_update_header(scene, sa, data, offset);
- if (sa) {
-#define HEADER_LENGTH 40
- char msg[HEADER_LENGTH];
- BLI_snprintf(msg, HEADER_LENGTH, "Trim offset: %d", offset);
-#undef HEADER_LENGTH
- ED_area_headerprint(sa, msg);
- }
+ RNA_int_set(op->ptr, "offset", offset);
- if (sequencer_slip_recursively(scene, data, offset)) {
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ if (sequencer_slip_recursively(scene, data, offset)) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ }
}
break;
}
@@ -1597,19 +1649,36 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
case RIGHTSHIFTKEY:
case LEFTSHIFTKEY:
- if (event->val == KM_PRESS) {
- data->slow = true;
- data->slow_offset = event->mval[0];
- }
- else if (event->val == KM_RELEASE) {
- data->slow = false;
+ if (!has_numInput) {
+ if (event->val == KM_PRESS) {
+ data->slow = true;
+ data->slow_offset = event->mval[0];
+ }
+ else if (event->val == KM_RELEASE) {
+ data->slow = false;
+ }
}
break;
default:
+ handled = false;
break;
}
+ /* Modal numinput inactive, try to handle numeric inputs last... */
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &data->num_input, event)) {
+ float offset;
+ applyNumInput(&data->num_input, &offset);
+
+ sequencer_slip_update_header(scene, sa, data, (int)offset);
+
+ RNA_int_set(op->ptr, "offset", offset);
+
+ if (sequencer_slip_recursively(scene, data, offset)) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ }
+ }
+
return OPERATOR_RUNNING_MODAL;
}
@@ -3360,18 +3429,21 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq;
-
+ GSet *file_list;
+
if (ed == NULL) {
return OPERATOR_CANCELLED;
}
+ file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
+
SEQP_BEGIN(ed, seq)
{
if ((seq->flag & SELECT)) {
struct SeqIndexBuildContext *context;
short stop = 0, do_update;
float progress;
- context = BKE_sequencer_proxy_rebuild_context(bmain, scene, seq);
+ context = BKE_sequencer_proxy_rebuild_context(bmain, scene, seq, file_list);
BKE_sequencer_proxy_rebuild(context, &stop, &do_update, &progress);
BKE_sequencer_proxy_rebuild_finish(context, 0);
BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
@@ -3379,6 +3451,8 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
}
SEQ_END
+ BLI_gset_free(file_list, MEM_freeN);
+
return OPERATOR_FINISHED;
}
@@ -3397,6 +3471,88 @@ void SEQUENCER_OT_rebuild_proxy(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER;
}
+static int sequencer_enable_proxies_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 5 * UI_UNIT_Y);
+}
+
+static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ bool proxy_25 = RNA_boolean_get(op->ptr, "proxy_25");
+ bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50");
+ bool proxy_75 = RNA_boolean_get(op->ptr, "proxy_75");
+ bool proxy_100 = RNA_boolean_get(op->ptr, "proxy_100");
+ bool override = RNA_boolean_get(op->ptr, "override");
+ bool turnon = true;
+
+ if (ed == NULL || !(proxy_25 || proxy_50 || proxy_75 || proxy_100)) {
+ turnon = false;
+ }
+
+ SEQP_BEGIN(ed, seq)
+ {
+ if ((seq->flag & SELECT)) {
+ if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MULTICAM)) {
+ BKE_sequencer_proxy_set(seq, turnon);
+
+ if (proxy_25)
+ seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_25;
+ else
+ seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_25;
+
+ if (proxy_50)
+ seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_50;
+ else
+ seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_50;
+
+ if (proxy_75)
+ seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_75;
+ else
+ seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_75;
+
+ if (proxy_100)
+ seq->strip->proxy->build_size_flags |= SEQ_PROXY_IMAGE_SIZE_100;
+ else
+ seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_100;
+
+ if (!override)
+ seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING;
+ else
+ seq->strip->proxy->build_flags &= ~SEQ_PROXY_SKIP_EXISTING;
+ }
+ }
+ }
+ SEQ_END
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_enable_proxies(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Set Selected Strip Proxies";
+ ot->idname = "SEQUENCER_OT_enable_proxies";
+ ot->description = "Enable selected proxies on all selected Movie strips";
+
+ /* api callbacks */
+ ot->invoke = sequencer_enable_proxies_invoke;
+ ot->exec = sequencer_enable_proxies_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
+
+ RNA_def_boolean(ot->srna, "proxy_25", false, "25%", "");
+ RNA_def_boolean(ot->srna, "proxy_50", false, "50%", "");
+ RNA_def_boolean(ot->srna, "proxy_75", false, "75%", "");
+ RNA_def_boolean(ot->srna, "proxy_100", false, "100%", "");
+ RNA_def_boolean(ot->srna, "override", false, "Override", "");
+}
+
/* change ops */
static EnumPropertyItem prop_change_effect_input_types[] = {
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 5f1c9317fd9..461c72961c2 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -131,6 +131,7 @@ void SEQUENCER_OT_copy(struct wmOperatorType *ot);
void SEQUENCER_OT_paste(struct wmOperatorType *ot);
void SEQUENCER_OT_rebuild_proxy(struct wmOperatorType *ot);
+void SEQUENCER_OT_enable_proxies(struct wmOperatorType *ot);
/* preview specific operators */
void SEQUENCER_OT_view_all_preview(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index 9b5ef18f7cd..33a8a1c5b41 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -88,6 +88,7 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_view_ghost_border);
WM_operatortype_append(SEQUENCER_OT_rebuild_proxy);
+ WM_operatortype_append(SEQUENCER_OT_enable_proxies);
WM_operatortype_append(SEQUENCER_OT_change_effect_input);
WM_operatortype_append(SEQUENCER_OT_change_effect_type);
WM_operatortype_append(SEQUENCER_OT_change_path);
diff --git a/source/blender/editors/space_sequencer/sequencer_preview.c b/source/blender/editors/space_sequencer/sequencer_preview.c
index da00b0ff6e1..c8834d394f5 100644
--- a/source/blender/editors/space_sequencer/sequencer_preview.c
+++ b/source/blender/editors/space_sequencer/sequencer_preview.c
@@ -95,9 +95,9 @@ static void preview_startjob(void *data, short *stop, short *do_update, float *p
sound = previewjb->sound;
/* make sure we cleanup the loading flag! */
- BLI_mutex_lock(sound->mutex);
+ BLI_spin_lock(sound->spinlock);
sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
- BLI_mutex_unlock(sound->mutex);
+ BLI_spin_unlock(sound->spinlock);
BLI_mutex_lock(pj->mutex);
previewjb = previewjb->next;
@@ -117,7 +117,7 @@ static void preview_startjob(void *data, short *stop, short *do_update, float *p
BLI_freelinkN(&pj->previews, previewjb);
previewjb = preview_next;
pj->processed++;
- *progress = (pj->total > 0) ? (float)pj->processed / (float)pj->total : 1.0;
+ *progress = (pj->total > 0) ? (float)pj->processed / (float)pj->total : 1.0f;
*do_update = true;
BLI_mutex_unlock(pj->mutex);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 6792bbe0577..4fbe0c6a241 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -996,7 +996,7 @@ static bool select_grouped_data(Editing *ed, Sequence *actseq)
if (SEQ_HAS_PATH(actseq) && dir) {
SEQP_BEGIN (ed, seq)
{
- if (SEQ_HAS_PATH(seq) && seq->strip && strcmp(seq->strip->dir, dir) == 0) {
+ if (SEQ_HAS_PATH(seq) && seq->strip && STREQ(seq->strip->dir, dir)) {
seq->flag |= SELECT;
changed = true;
}
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 6231f02907a..7be356dd2ec 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -504,6 +504,13 @@ static void sequencer_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
break;
}
break;
+ case NC_ANIMATION:
+ switch (wmn->data) {
+ case ND_KEYFRAME:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
case NC_SPACE:
if (wmn->data == ND_SPACE_SEQUENCER)
ED_region_tag_redraw(ar);
@@ -599,6 +606,16 @@ static void sequencer_preview_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED
case ND_MARKERS:
case ND_SEQUENCER:
case ND_RENDER_OPTIONS:
+ case ND_DRAW_RENDER_VIEWPORT:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ break;
+ case NC_ANIMATION:
+ switch (wmn->data) {
+ case ND_KEYFRAME:
+ /* Otherwise, often prevents seing immediately effects of keyframe editing... */
+ BKE_sequencer_cache_cleanup();
ED_region_tag_redraw(ar);
break;
}
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index 99e1606c9bd..1637ae14892 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -183,7 +183,7 @@ static GHash *text_autocomplete_build(Text *text)
const int choice_len = i_end - i_start;
if ((choice_len > seek_len) &&
- (seek_len == 0 || strncmp(seek, str_sub, seek_len) == 0) &&
+ (seek_len == 0 || STREQLEN(seek, str_sub, seek_len)) &&
(seek != str_sub))
{
// printf("Adding: %s\n", s);
@@ -207,18 +207,16 @@ static GHash *text_autocomplete_build(Text *text)
}
{
- GHashIterator *iter = BLI_ghashIterator_new(gh);
+ GHashIterator gh_iter;
/* get the formatter for highlighting */
TextFormatType *tft;
tft = ED_text_format_get(text);
- for (; !BLI_ghashIterator_done(iter); BLI_ghashIterator_step(iter)) {
- const char *s = BLI_ghashIterator_getValue(iter);
+ GHASH_ITER (gh_iter, gh) {
+ const char *s = BLI_ghashIterator_getValue(&gh_iter);
texttool_suggest_add(s, tft->format_identifier(s));
}
- BLI_ghashIterator_free(iter);
-
}
}
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 31662c02966..462b619f497 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -549,7 +549,7 @@ static void text_update_drawcache(SpaceText *st, ARegion *ar)
full_update |= drawcache->tabnumber != st->tabnumber; /* word-wrapping option was toggled */
full_update |= drawcache->lheight != st->lheight_dpi; /* word-wrapping option was toggled */
full_update |= drawcache->cwidth != st->cwidth; /* word-wrapping option was toggled */
- full_update |= strncmp(drawcache->text_id, txt->id.name, MAX_ID_NAME); /* text datablock was changed */
+ full_update |= !STREQLEN(drawcache->text_id, txt->id.name, MAX_ID_NAME); /* text datablock was changed */
if (st->wordwrap) {
/* update line heights */
@@ -1447,7 +1447,6 @@ void draw_text_main(SpaceText *st, ARegion *ar)
/* draw other stuff */
draw_brackets(st, ar);
- glTranslatef(GLA_PIXEL_OFS, GLA_PIXEL_OFS, 0.0f); /* XXX scroll requires exact pixel space */
draw_textscroll(st, &scroll, &back);
draw_documentation(st, ar);
draw_suggestion_list(st, ar);
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 1cf0316aa06..ad8050a50e8 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -2537,10 +2537,14 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, con
y -= txt_get_span(text->lines.first, *linep) - st->top;
if (y > 0) {
- while (y-- != 0) if ((*linep)->next) *linep = (*linep)->next;
+ while (y-- != 0) {
+ if ((*linep)->next) *linep = (*linep)->next;
+ }
}
else if (y < 0) {
- while (y++ != 0) if ((*linep)->prev) *linep = (*linep)->prev;
+ while (y++ != 0) {
+ if ((*linep)->prev) *linep = (*linep)->prev;
+ }
}
@@ -2919,7 +2923,7 @@ static int text_find_and_replace(bContext *C, wmOperator *op, short mode)
if (mode != TEXT_FIND && txt_has_sel(text)) {
tmp = txt_sel_to_buf(text);
- if (flags & ST_MATCH_CASE) found = strcmp(st->findstr, tmp) == 0;
+ if (flags & ST_MATCH_CASE) found = STREQ(st->findstr, tmp);
else found = BLI_strcasecmp(st->findstr, tmp) == 0;
if (found) {
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index 820d1d68f8d..e2c195fd544 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -58,6 +58,7 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
#include "ED_space_api.h"
#include "ED_markers.h"
@@ -90,13 +91,12 @@ static void time_draw_sfra_efra(Scene *scene, View2D *v2d)
fdrawline((float)PEFRA, v2d->cur.ymin, (float)PEFRA, v2d->cur.ymax);
}
-#define CACHE_DRAW_HEIGHT 3.0f
-
static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
{
PTCacheID *pid;
ListBase pidlist;
SpaceTimeCache *stc = stime->caches.first;
+ const float cache_draw_height = (4.0f * UI_DPI_FAC * U.pixelsize);
float yoffs = 0.f;
if (!(stime->cache_display & TIME_CACHE_DISPLAY) || (!ob))
@@ -172,7 +172,7 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
glPushMatrix();
glTranslatef(0.0, (float)V2D_SCROLL_HEIGHT + yoffs, 0.0);
- glScalef(1.0, CACHE_DRAW_HEIGHT, 0.0);
+ glScalef(1.0, cache_draw_height, 0.0);
switch (pid->type) {
case PTCACHE_TYPE_SOFTBODY:
@@ -227,7 +227,7 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
glPopMatrix();
- yoffs += CACHE_DRAW_HEIGHT;
+ yoffs += cache_draw_height;
stc = stc->next;
}
@@ -292,6 +292,8 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
bDopeSheet ads = {NULL};
DLRBT_Tree keys;
ActKeyColumn *ak;
+ float ymin = v2d->tot.ymin;
+ float ymax = v2d->tot.ymax * 0.6f + ymin * 0.4f;
/* init binarytree-list for getting keyframes */
BLI_dlrbTree_init(&keys);
@@ -299,7 +301,7 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
/* init dopesheet settings */
if (onlysel)
ads.filterflag |= ADS_FILTER_ONLYSEL;
-
+
/* populate tree with keyframe nodes */
switch (GS(id->name)) {
case ID_SCE:
@@ -326,8 +328,8 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
(ak) && (ak->cfra <= v2d->cur.xmax);
ak = ak->next)
{
- glVertex2f(ak->cfra, v2d->tot.ymin);
- glVertex2f(ak->cfra, v2d->tot.ymax);
+ glVertex2f(ak->cfra, ymin);
+ glVertex2f(ak->cfra, ymax);
}
glEnd(); // GL_LINES
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 320267a4a7c..ab69e67361d 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -44,6 +44,7 @@ set(SRC
drawarmature.c
drawmesh.c
drawobject.c
+ drawsimdebug.c
drawvolume.c
space_view3d.c
view3d_buttons.c
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index 691da78f26b..f33f074e6c5 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -1619,7 +1619,7 @@ static void draw_pose_dofs(Object *ob)
for (a = -16; a <= 16; a++) {
/* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
float fac = ((float)a) / 16.0f * 0.5f;
- phi = (float)(0.5 * M_PI) + fac * (pchan->limitmax[0] - pchan->limitmin[0]);
+ phi = (float)M_PI_2 + fac * (pchan->limitmax[0] - pchan->limitmin[0]);
i = (a == -16) ? 2 : 3;
corner[i][0] = 0.0f;
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 1cbc8e5567c..add9b41a91f 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -733,7 +733,7 @@ void drawcircball(int mode, const float cent[3], float rad, float tmat[4][4])
}
/* circle for object centers, special_color is for library or ob users */
-static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
+static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, bool special_color)
{
const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
float verts[CIRCLE_RESOL][3];
@@ -741,6 +741,8 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3],
/* using gldepthfunc guarantees that it does write z values,
* but not checks for it, so centers remain visible independent order of drawing */
if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
+ /* write to near buffer always */
+ glDepthRange(0.0, 0.0);
glEnable(GL_BLEND);
if (special_color) {
@@ -770,6 +772,7 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3],
/* finish up */
glDisableClientState(GL_VERTEX_ARRAY);
+ glDepthRange(0.0, 1.0);
glDisable(GL_BLEND);
if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
@@ -4329,8 +4332,8 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
ListBase *lb = NULL;
DispList *dl;
Curve *cu;
- const short render_only = (v3d->flag2 & V3D_RENDER_OVERRIDE);
- const short solid = (dt > OB_WIRE);
+ const bool render_only = (v3d->flag2 & V3D_RENDER_OVERRIDE) != 0;
+ const bool solid = (dt > OB_WIRE);
if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == false) {
return false;
@@ -5145,7 +5148,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
cache = psys->pathcache;
for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
path = cache[a];
- if (path->steps > 0) {
+ if (path->segments > 0) {
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
if (1) { //ob_dt > OB_WIRE) {
@@ -5157,7 +5160,136 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
}
}
- glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
+ glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
+ }
+ }
+
+ if (part->type == PART_HAIR) {
+ if (part->draw & PART_DRAW_GUIDE_HAIRS) {
+ DerivedMesh *hair_dm = psys->hair_out_dm;
+
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
+ if (pa->totkey > 1) {
+ HairKey *hkey = pa->hair;
+
+ glVertexPointer(3, GL_FLOAT, sizeof(HairKey), hkey->world_co);
+
+ // XXX use proper theme color here
+// UI_ThemeColor(TH_NORMAL);
+ glColor3f(0.58f, 0.67f, 1.0f);
+
+ glDrawArrays(GL_LINE_STRIP, 0, pa->totkey);
+ }
+ }
+
+ if (hair_dm) {
+ MVert *mvert = hair_dm->getVertArray(hair_dm);
+ int i;
+
+ glColor3f(0.9f, 0.4f, 0.4f);
+
+ glBegin(GL_LINES);
+ for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
+ for (i = 1; i < pa->totkey; ++i) {
+ float v1[3], v2[3];
+
+ copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co);
+ copy_v3_v3(v2, mvert[pa->hair_index + i].co);
+
+ mul_m4_v3(ob->obmat, v1);
+ mul_m4_v3(ob->obmat, v2);
+
+ glVertex3fv(v1);
+ glVertex3fv(v2);
+ }
+ }
+ glEnd();
+ }
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_COLOR_MATERIAL);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ if ((dflag & DRAW_CONSTCOLOR) == 0)
+ if (part->draw_col == PART_DRAW_COL_MAT)
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+
+ if (part->draw & PART_DRAW_HAIR_GRID) {
+ ClothModifierData *clmd = psys->clmd;
+ if (clmd) {
+ float *a = clmd->hair_grid_min;
+ float *b = clmd->hair_grid_max;
+ int *res = clmd->hair_grid_res;
+ int i;
+
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ if (select)
+ UI_ThemeColor(TH_ACTIVE);
+ else
+ UI_ThemeColor(TH_WIRE);
+ glBegin(GL_LINES);
+ glVertex3f(a[0], a[1], a[2]); glVertex3f(b[0], a[1], a[2]);
+ glVertex3f(b[0], a[1], a[2]); glVertex3f(b[0], b[1], a[2]);
+ glVertex3f(b[0], b[1], a[2]); glVertex3f(a[0], b[1], a[2]);
+ glVertex3f(a[0], b[1], a[2]); glVertex3f(a[0], a[1], a[2]);
+
+ glVertex3f(a[0], a[1], b[2]); glVertex3f(b[0], a[1], b[2]);
+ glVertex3f(b[0], a[1], b[2]); glVertex3f(b[0], b[1], b[2]);
+ glVertex3f(b[0], b[1], b[2]); glVertex3f(a[0], b[1], b[2]);
+ glVertex3f(a[0], b[1], b[2]); glVertex3f(a[0], a[1], b[2]);
+
+ glVertex3f(a[0], a[1], a[2]); glVertex3f(a[0], a[1], b[2]);
+ glVertex3f(b[0], a[1], a[2]); glVertex3f(b[0], a[1], b[2]);
+ glVertex3f(a[0], b[1], a[2]); glVertex3f(a[0], b[1], b[2]);
+ glVertex3f(b[0], b[1], a[2]); glVertex3f(b[0], b[1], b[2]);
+ glEnd();
+
+ if (select)
+ UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -100);
+ else
+ UI_ThemeColorShadeAlpha(TH_WIRE, 0, -100);
+ glEnable(GL_BLEND);
+ glBegin(GL_LINES);
+ for (i = 1; i < res[0]-1; ++i) {
+ float f = interpf(b[0], a[0], (float)i / (float)(res[0]-1));
+ glVertex3f(f, a[1], a[2]); glVertex3f(f, b[1], a[2]);
+ glVertex3f(f, b[1], a[2]); glVertex3f(f, b[1], b[2]);
+ glVertex3f(f, b[1], b[2]); glVertex3f(f, a[1], b[2]);
+ glVertex3f(f, a[1], b[2]); glVertex3f(f, a[1], a[2]);
+ }
+ for (i = 1; i < res[1]-1; ++i) {
+ float f = interpf(b[1], a[1], (float)i / (float)(res[1]-1));
+ glVertex3f(a[0], f, a[2]); glVertex3f(b[0], f, a[2]);
+ glVertex3f(b[0], f, a[2]); glVertex3f(b[0], f, b[2]);
+ glVertex3f(b[0], f, b[2]); glVertex3f(a[0], f, b[2]);
+ glVertex3f(a[0], f, b[2]); glVertex3f(a[0], f, a[2]);
+ }
+ for (i = 1; i < res[2]-1; ++i) {
+ float f = interpf(b[2], a[2], (float)i / (float)(res[2]-1));
+ glVertex3f(a[0], a[1], f); glVertex3f(b[0], a[1], f);
+ glVertex3f(b[0], a[1], f); glVertex3f(b[0], b[1], f);
+ glVertex3f(b[0], b[1], f); glVertex3f(a[0], b[1], f);
+ glVertex3f(a[0], b[1], f); glVertex3f(a[0], a[1], f);
+ }
+ glEnd();
+ glDisable(GL_BLEND);
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_COLOR_MATERIAL);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ if ((dflag & DRAW_CONSTCOLOR) == 0)
+ if (part->draw_col == PART_DRAW_COL_MAT)
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
}
}
@@ -5176,7 +5308,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
}
}
- glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
+ glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
}
@@ -5328,7 +5460,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
PTCacheEditKey *key;
ParticleEditSettings *pset = PE_settings(scene);
int i, k, totpoint = edit->totpoint, timed = pset->flag & PE_FADE_TIME ? pset->fade_frames : 0;
- int steps = 1;
+ int totkeys = 1;
float sel_col[3];
float nosel_col[3];
float *pathcol = NULL, *pcol;
@@ -5347,10 +5479,10 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
UI_GetThemeColor3fv(TH_VERTEX, nosel_col);
/* draw paths */
- steps = (*edit->pathcache)->steps + 1;
+ totkeys = (*edit->pathcache)->segments + 1;
glEnable(GL_BLEND);
- pathcol = MEM_callocN(steps * 4 * sizeof(float), "particle path color data");
+ pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data");
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
@@ -5370,7 +5502,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
if (point->flag & PEP_HIDE) {
- for (k = 0, pcol = pathcol; k < steps; k++, pcol += 4) {
+ for (k = 0, pcol = pathcol; k < totkeys; k++, pcol += 4) {
copy_v3_v3(pcol, path->col);
pcol[3] = 0.25f;
}
@@ -5378,7 +5510,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol);
}
else if (timed) {
- for (k = 0, pcol = pathcol, pkey = path; k < steps; k++, pkey++, pcol += 4) {
+ for (k = 0, pcol = pathcol, pkey = path; k < totkeys; k++, pkey++, pcol += 4) {
copy_v3_v3(pcol, pkey->col);
pcol[3] = 1.0f - fabsf((float)(CFRA) -pkey->time) / (float)pset->fade_frames;
}
@@ -5388,7 +5520,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
else
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
- glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
+ glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
}
if (pathcol) { MEM_freeN(pathcol); pathcol = pcol = NULL; }
@@ -7727,7 +7859,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (render_override) {
/* don't draw */
}
- else if ((scene->basact) == base)
+ else if (is_obact)
do_draw_center = ACTIVE;
else if (base->flag & SELECT)
do_draw_center = SELECT;
diff --git a/source/blender/editors/space_view3d/drawsimdebug.c b/source/blender/editors/space_view3d/drawsimdebug.c
new file mode 100644
index 00000000000..6113bfd4143
--- /dev/null
+++ b/source/blender/editors/space_view3d/drawsimdebug.c
@@ -0,0 +1,173 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_view3d/drawsimdebug.c
+ * \ingroup spview3d
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+#include "BKE_effect.h"
+#include "BKE_global.h"
+#include "BKE_modifier.h"
+
+#include "view3d_intern.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_resources.h"
+
+static void draw_sim_debug_elements(SimDebugData *debug_data, float imat[4][4])
+{
+ GHashIterator iter;
+
+ /**** dots ****/
+
+ glPointSize(3.0f);
+ glBegin(GL_POINTS);
+ for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
+ SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
+ if (elem->type != SIM_DEBUG_ELEM_DOT)
+ continue;
+
+ glColor3f(elem->color[0], elem->color[1], elem->color[2]);
+ glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]);
+ }
+ glEnd();
+ glPointSize(1.0f);
+
+ /**** circles ****/
+
+ {
+ float circle[16][2] = {
+ {0.000000, 1.000000}, {0.382683, 0.923880}, {0.707107, 0.707107}, {0.923880, 0.382683},
+ {1.000000, -0.000000}, {0.923880, -0.382683}, {0.707107, -0.707107}, {0.382683, -0.923880},
+ {-0.000000, -1.000000}, {-0.382683, -0.923880}, {-0.707107, -0.707107}, {-0.923879, -0.382684},
+ {-1.000000, 0.000000}, {-0.923879, 0.382684}, {-0.707107, 0.707107}, {-0.382683, 0.923880} };
+ for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
+ SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
+ float radius = elem->v2[0];
+ float co[3];
+ int i;
+
+ if (elem->type != SIM_DEBUG_ELEM_CIRCLE)
+ continue;
+
+ glColor3f(elem->color[0], elem->color[1], elem->color[2]);
+ glBegin(GL_LINE_LOOP);
+ for (i = 0; i < 16; ++i) {
+ co[0] = radius * circle[i][0];
+ co[1] = radius * circle[i][1];
+ co[2] = 0.0f;
+ mul_mat3_m4_v3(imat, co);
+ add_v3_v3(co, elem->v1);
+
+ glVertex3f(co[0], co[1], co[2]);
+ }
+ glEnd();
+ }
+ }
+
+ /**** lines ****/
+
+ glBegin(GL_LINES);
+ for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
+ SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
+ if (elem->type != SIM_DEBUG_ELEM_LINE)
+ continue;
+
+ glColor3f(elem->color[0], elem->color[1], elem->color[2]);
+ glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]);
+ glVertex3f(elem->v2[0], elem->v2[1], elem->v2[2]);
+ }
+ glEnd();
+
+ /**** vectors ****/
+
+ glPointSize(2.0f);
+ glBegin(GL_POINTS);
+ for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
+ SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
+ if (elem->type != SIM_DEBUG_ELEM_VECTOR)
+ continue;
+
+ glColor3f(elem->color[0], elem->color[1], elem->color[2]);
+ glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]);
+ }
+ glEnd();
+ glPointSize(1.0f);
+
+ glBegin(GL_LINES);
+ for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
+ SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
+ float t[3];
+ if (elem->type != SIM_DEBUG_ELEM_VECTOR)
+ continue;
+
+ glColor3f(elem->color[0], elem->color[1], elem->color[2]);
+ glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]);
+ add_v3_v3v3(t, elem->v1, elem->v2);
+ glVertex3f(t[0], t[1], t[2]);
+ }
+ glEnd();
+}
+
+void draw_sim_debug_data(Scene *UNUSED(scene), View3D *UNUSED(v3d), ARegion *ar)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ /*Object *ob = base->object;*/
+ float imat[4][4];
+
+ if (!_sim_debug_data)
+ return;
+
+ invert_m4_m4(imat, rv3d->viewmatob);
+
+// glDepthMask(GL_FALSE);
+// glEnable(GL_BLEND);
+
+ glPushMatrix();
+
+ glLoadMatrixf(rv3d->viewmat);
+ draw_sim_debug_elements(_sim_debug_data, imat);
+
+ glPopMatrix();
+
+// glDepthMask(GL_TRUE);
+// glDisable(GL_BLEND);
+}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 55d5273b198..25085368dac 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -564,7 +564,7 @@ static void view3d_main_area_exit(wmWindowManager *wm, ARegion *ar)
static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_OB)
return 1;
}
@@ -574,7 +574,7 @@ static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_GR)
return 1;
}
@@ -584,7 +584,7 @@ static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEve
static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_MA)
return 1;
}
@@ -594,7 +594,7 @@ static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (GS(id->name) == ID_IM)
return 1;
}
@@ -641,14 +641,14 @@ static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
drop->opcontext = WM_OP_EXEC_DEFAULT;
RNA_string_set(drop->ptr, "name", id->name + 2);
@@ -656,14 +656,14 @@ static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
{
- ID *id = (ID *)drag->poin;
+ ID *id = drag->poin;
if (id) {
RNA_string_set(drop->ptr, "name", id->name + 2);
@@ -817,6 +817,16 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
case ND_WORLD:
/* handled by space_view3d_listener() for v3d access */
break;
+ case ND_DRAW_RENDER_VIEWPORT:
+ {
+ if (v3d->camera && (scene == wmn->reference)) {
+ RegionView3D *rv3d = ar->regiondata;
+ if (rv3d->persp == RV3D_CAMOB) {
+ ED_region_tag_redraw(ar);
+ }
+ }
+ break;
+ }
}
if (wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
@@ -856,6 +866,20 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
break;
}
break;
+ case NC_CAMERA:
+ switch (wmn->data) {
+ case ND_DRAW_RENDER_VIEWPORT:
+ {
+ if (v3d->camera && (v3d->camera->data == wmn->reference)) {
+ RegionView3D *rv3d = ar->regiondata;
+ if (rv3d->persp == RV3D_CAMOB) {
+ ED_region_tag_redraw(ar);
+ }
+ }
+ break;
+ }
+ }
+ break;
case NC_GROUP:
/* all group ops for now */
ED_region_tag_redraw(ar);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 65721d52dff..929929c7dd0 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -162,15 +162,15 @@ static void view3d_draw_clipping(RegionView3D *rv3d)
/* fill in zero alpha for rendering & re-projection [#31530] */
unsigned char col[4];
- UI_GetThemeColorShade3ubv(TH_BACK, -8, col);
- col[3] = 0;
+ UI_GetThemeColor4ubv(TH_V3D_CLIPPING_BORDER, col);
glColor4ubv(col);
+ glEnable(GL_BLEND);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, bb->vec);
glDrawElements(GL_QUADS, sizeof(clipping_index) / sizeof(unsigned int), GL_UNSIGNED_INT, clipping_index);
glDisableClientState(GL_VERTEX_ARRAY);
-
+ glDisable(GL_BLEND);
}
}
@@ -586,20 +586,26 @@ static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
float ydisp = 0.0; /* vertical displacement to allow obj info text */
int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */
float vec[3];
- char axis_text[2] = "x";
float dx, dy;
- int i;
-
+
+ int axis_order[3] = {0, 1, 2};
+ int axis_i;
+
startx += rect->xmin;
starty += rect->ymin;
-
+
+ axis_sort_v3(rv3d->viewinv[2], axis_order);
+
/* thickness of lines is proportional to k */
glLineWidth(2);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- for (i = 0; i < 3; i++) {
+ for (axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
+ const char axis_text[2] = {'x' + i, '\0'};
+
zero_v3(vec);
vec[i] = 1.0f;
mul_qt_v3(rv3d->viewquat, vec);
@@ -616,8 +622,6 @@ static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
BLF_draw_default_ascii(startx + dx + 2, starty + dy + ydisp + 2, 0.0f, axis_text, 1);
}
- axis_text[0]++;
-
/* BLF_draw_default disables blending */
glEnable(GL_BLEND);
}
@@ -1066,14 +1070,13 @@ static void drawviewborder_triangle(float x1, float x2, float y1, float y2, cons
static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
{
- float hmargin, vmargin;
float x1, x2, y1, y2;
float x1i, x2i, y1i, y2i;
rctf viewborder;
Camera *ca = NULL;
RegionView3D *rv3d = ar->regiondata;
-
+
if (v3d->camera == NULL)
return;
if (v3d->camera->type == OB_CAMERA)
@@ -1225,17 +1228,20 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
drawviewborder_triangle(x1, x2, y1, y2, 1, 'B');
}
- if (ca->flag & CAM_SHOWTITLESAFE) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
-
- hmargin = 0.1f * (x2 - x1);
- vmargin = 0.05f * (y2 - y1);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, x1 + hmargin, y1 + vmargin, x2 - hmargin, y2 - vmargin, 2.0f);
+ if (ca->flag & CAM_SHOW_SAFE_MARGINS) {
+ UI_draw_safe_areas(
+ x1, x2, y1, y2,
+ scene->safe_areas.title,
+ scene->safe_areas.action);
- hmargin = 0.035f * (x2 - x1);
- vmargin = 0.035f * (y2 - y1);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, x1 + hmargin, y1 + vmargin, x2 - hmargin, y2 - vmargin, 2.0f);
+ if (ca->flag & CAM_SHOW_SAFE_CENTER) {
+ UI_draw_safe_areas(
+ x1, x2, y1, y2,
+ scene->safe_areas.title_center,
+ scene->safe_areas.action_center);
+ }
}
+
if (ca->flag & CAM_SHOWSENSOR) {
/* determine sensor fit, and get sensor x/y, for auto fit we
* assume and square sensor and only use sensor_x */
@@ -1279,8 +1285,9 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
/* camera name - draw in highlighted text color */
if (ca && (ca->flag & CAM_SHOWNAME)) {
UI_ThemeColor(TH_TEXT_HI);
- BLF_draw_default(x1i, y1i - 15, 0.0f, v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2);
- UI_ThemeColor(TH_WIRE);
+ BLF_draw_default(
+ x1i, y1i - (0.7f * U.widget_unit), 0.0f,
+ v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2);
}
}
@@ -1608,7 +1615,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
{
float image_aspect[2];
float fac, asp, zoomx, zoomy;
- float x1, y1, x2, y2;
+ float x1, y1, x2, y2, centx, centy;
ImBuf *ibuf = NULL, *freeibuf, *releaseibuf;
void *lock;
@@ -1714,6 +1721,9 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
y2 += yof_scale;
}
+ centx = (x1 + x2) / 2.0f;
+ centy = (y1 + y2) / 2.0f;
+
/* aspect correction */
if (bgpic->flag & V3D_BGPIC_CAMERA_ASPECT) {
/* apply aspect from clip */
@@ -1731,16 +1741,14 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
if ((asp_src > asp_dst) == ((bgpic->flag & V3D_BGPIC_CAMERA_CROP) != 0)) {
/* fit X */
const float div = asp_src / asp_dst;
- const float cent = (x1 + x2) / 2.0f;
- x1 = ((x1 - cent) * div) + cent;
- x2 = ((x2 - cent) * div) + cent;
+ x1 = ((x1 - centx) * div) + centx;
+ x2 = ((x2 - centx) * div) + centx;
}
else {
/* fit Y */
const float div = asp_dst / asp_src;
- const float cent = (y1 + y2) / 2.0f;
- y1 = ((y1 - cent) * div) + cent;
- y2 = ((y2 - cent) * div) + cent;
+ y1 = ((y1 - centy) * div) + centy;
+ y2 = ((y2 - centy) * div) + centy;
}
}
}
@@ -1767,6 +1775,9 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
y1 = sco[1] + asp * fac * (bgpic->yof - bgpic->size);
x2 = sco[0] + fac * (bgpic->xof + bgpic->size);
y2 = sco[1] + asp * fac * (bgpic->yof + bgpic->size);
+
+ centx = (x1 + x2) / 2.0f;
+ centy = (y1 + y2) / 2.0f;
}
/* complete clip? */
@@ -1817,6 +1828,19 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
glPushMatrix();
ED_region_pixelspace(ar);
+ glTranslatef(centx, centy, 0.0);
+ if (rv3d->persp != RV3D_CAMOB) {
+ glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f);
+ }
+
+ if (bgpic->flag & V3D_BGPIC_FLIP_X) {
+ zoomx *= -1.0f;
+ x1 = x2;
+ }
+ if (bgpic->flag & V3D_BGPIC_FLIP_Y) {
+ zoomy *= -1.0f;
+ y1 = y2;
+ }
glPixelZoom(zoomx, zoomy);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend);
@@ -1824,7 +1848,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
* glaDrawPixelsSafe in some cases, which will end up in missing
* alpha transparency for the background image (sergey)
*/
- glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
+ glaDrawPixelsTex(x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
glPixelZoom(1.0, 1.0);
glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
@@ -2566,6 +2590,7 @@ CustomDataMask ED_view3d_screen_datamask(bScreen *screen)
void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
{
RegionView3D *rv3d = ar->regiondata;
+ rctf cameraborder;
/* setup window matrices */
if (winmat)
@@ -2583,7 +2608,23 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
invert_m4_m4(rv3d->persinv, rv3d->persmat);
invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
+
+ /* calculate GLSL view dependent values */
+ /* store window coordinates scaling/offset */
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false);
+ rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
+ rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder);
+
+ rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx;
+ rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy;
+ }
+ else {
+ rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f;
+ rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f;
+ }
+
/* calculate pixelsize factor once, is used for lamps and obcenters */
{
/* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])'
@@ -2815,15 +2856,15 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar, bool
{
/* clear background */
if (scene->world && ((v3d->flag3 & V3D_SHOW_WORLD) || force)) {
- float alpha = (force) ? 1.0f : 0.0;
+ float alpha = (force) ? 1.0f : 0.0f;
bool glsl = GPU_glsl_support() && BKE_scene_use_new_shading_nodes(scene) && scene->world->nodetree && scene->world->use_nodes;
if (glsl) {
RegionView3D *rv3d = ar->regiondata;
GPUMaterial *gpumat = GPU_material_world(scene, scene->world);
-
+
/* calculate full shader for background */
- GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, (v3d->scenelock != 0));
+ GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
@@ -3082,15 +3123,6 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
G.f &= ~G_RENDER_OGL;
}
-/* get a color used for offscreen sky, returns color in sRGB space */
-void ED_view3d_offscreen_sky_color_get(Scene *scene, float sky_color[3])
-{
- if (scene->world)
- linearrgb_to_srgb_v3_v3(sky_color, &scene->world->horr);
- else
- UI_GetThemeColor3fv(TH_BACK, sky_color);
-}
-
/* utility func for ED_view3d_draw_offscreen */
ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey, unsigned int flag,
bool draw_background, int alpha_mode, char err_out[256])
@@ -3573,9 +3605,13 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
/* draw viewport using opengl */
if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(scene) || clip_border) {
view3d_main_area_draw_objects(C, scene, v3d, ar, &grid_unit);
+
#ifdef DEBUG_DRAW
bl_debug_draw();
#endif
+ if (G.debug & G_DEBUG_SIMDATA)
+ draw_sim_debug_data(scene, v3d, ar);
+
ED_region_pixelspace(ar);
}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index aab307babe8..e6f61fb4aca 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -1034,7 +1034,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
* - of rotation is linearly proportional
* - to the distance that the mouse is
* - dragged. */
- phi = si * (float)(M_PI / 2.0);
+ phi = si * (float)M_PI_2;
q1[0] = cosf(phi);
mul_v3_fl(q1 + 1, sinf(phi));
@@ -3373,7 +3373,8 @@ void VIEW3D_OT_render_border(wmOperatorType *ot)
/* rna */
WM_operator_properties_border(ot);
- prop = RNA_def_boolean(ot->srna, "camera_only", 0, "Camera Only", "Set render border for camera view and final render only");
+ prop = RNA_def_boolean(ot->srna, "camera_only", false, "Camera Only",
+ "Set render border for camera view and final render only");
RNA_def_property_flag(prop, PROP_HIDDEN);
}
@@ -5003,8 +5004,9 @@ BGpic *ED_view3D_background_image_new(View3D *v3d)
{
BGpic *bgpic = MEM_callocN(sizeof(BGpic), "Background Image");
- bgpic->size = 5.0;
- bgpic->blend = 0.5;
+ bgpic->rotation = 0.0f;
+ bgpic->size = 5.0f;
+ bgpic->blend = 0.5f;
bgpic->iuser.fie_ima = 2;
bgpic->iuser.ok = 1;
bgpic->view = 0; /* 0 for all */
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index d3a9f5ca967..25dbc8830fe 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -48,9 +48,11 @@ struct bMotionPath;
struct bPoseChannel;
struct bScreen;
struct Mesh;
+struct SimDebugData;
struct wmNDOFMotionData;
struct wmOperatorType;
struct wmWindowManager;
+struct wmKeyConfig;
/* drawing flags: */
enum {
@@ -177,6 +179,9 @@ void draw_mesh_paint_weight_edges(RegionView3D *rv3d, struct DerivedMesh *dm,
void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
struct Object *ob, struct DerivedMesh *dm, const int draw_flags);
+/* drawsimdebug.c */
+void draw_sim_debug_data(Scene *scene, View3D *v3d, ARegion *ar);
+
/* view3d_draw.c */
void view3d_main_area_draw(const struct bContext *C, struct ARegion *ar);
void ED_view3d_draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, bool alphaoverride);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 5df348408df..0457f5f2d52 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -344,8 +344,8 @@ void view3d_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_all", NDOF_MOTION, 0, KM_CTRL | KM_SHIFT, 0);
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "use_all_regions", false);
- RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", NDOF_BUTTON_ROLL_CCW, KM_PRESS, 0, 0)->ptr, "angle", M_PI / -2);
- RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", NDOF_BUTTON_ROLL_CW, KM_PRESS, 0, 0)->ptr, "angle", M_PI / 2);
+ RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", NDOF_BUTTON_ROLL_CCW, KM_PRESS, 0, 0)->ptr, "angle", -M_PI_2);
+ RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", NDOF_BUTTON_ROLL_CW, KM_PRESS, 0, 0)->ptr, "angle", M_PI_2);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index f127f375a9f..af24a99a6f2 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -216,7 +216,7 @@ static void view3d_panel_tool_shelf(const bContext *C, Panel *pa)
CustomTool *ct;
for (ct = st->toolshelf.first; ct; ct = ct->next) {
- if (0 == strncmp(context, ct->context, OP_MAX_TYPENAME)) {
+ if (STREQLEN(context, ct->context, OP_MAX_TYPENAME)) {
col = uiLayoutColumn(pa->layout, true);
uiItemFullO(col, ct->opname, NULL, ICON_NONE, NULL, WM_OP_INVOKE_REGION_WIN, 0);
}
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index b727b96c8cc..14bbdebd138 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -93,8 +93,8 @@
#define MAX_INFO_LEN 256
static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg);
-static int doEdgeSlide(TransInfo *t, float perc);
-static int doVertSlide(TransInfo *t, float perc);
+static void doEdgeSlide(TransInfo *t, float perc);
+static void doVertSlide(TransInfo *t, float perc);
static void drawEdgeSlide(const struct bContext *C, TransInfo *t);
static void drawVertSlide(const struct bContext *C, TransInfo *t);
@@ -671,8 +671,11 @@ static void viewRedrawPost(bContext *C, TransInfo *t)
WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
/* redraw UV editor */
- if (t->mode == TFM_EDGE_SLIDE && (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT))
+ if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) &&
+ (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT))
+ {
WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+ }
/* XXX temp, first hack to get auto-render in compositor work (ton) */
WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C));
@@ -969,6 +972,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
{
char cmode = constraintModeToChar(t);
bool handled = false;
+ const int modifiers_prev = t->modifiers;
t->redraw |= handleMouseInput(t, &t->mouse, event);
@@ -1495,6 +1499,13 @@ int transformEvent(TransInfo *t, const wmEvent *event)
}
}
+ /* if we change snap options, get the unsnapped values back */
+ if ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) !=
+ (modifiers_prev & (MOD_SNAP | MOD_SNAP_INVERT)))
+ {
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
+ }
+
/* Per transform event, if present */
if (t->handleEvent &&
(!handled ||
@@ -3129,7 +3140,7 @@ static void initResize(TransInfo *t)
t->num.unit_type[2] = B_UNIT_NONE;
}
-static void headerResize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
+static void headerResize(TransInfo *t, const float vec[3], char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
size_t ofs = 0;
@@ -4102,7 +4113,7 @@ static void initTranslation(TransInfo *t)
}
}
-static void headerTranslation(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
+static void headerTranslation(TransInfo *t, const float vec[3], char str[MAX_INFO_LEN])
{
size_t ofs = 0;
char tvec[NUM_STR_REP_LEN * 3];
@@ -4195,7 +4206,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char str[MAX_INFO_LEN]
}
}
-static void applyTranslationValue(TransInfo *t, float vec[3])
+static void applyTranslationValue(TransInfo *t, const float vec[3])
{
TransData *td = t->data;
float tvec[3];
@@ -4932,7 +4943,7 @@ static void initBoneSize(TransInfo *t)
t->num.unit_type[2] = B_UNIT_NONE;
}
-static void headerBoneSize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN])
+static void headerBoneSize(TransInfo *t, const float vec[3], char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
if (hasNumInput(&t->num)) {
@@ -5102,6 +5113,85 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
}
/** \} */
+/* -------------------------------------------------------------------- */
+/* Original Data Store */
+
+/** \name Orig-Data Store Utility Functions
+ * \{ */
+
+static void slide_origdata_init_flag(
+ TransInfo *t, SlideOrigData *sod)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+
+ if ((t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) &&
+ /* don't do this at all for non-basis shape keys, too easy to
+ * accidentally break uv maps or vertex colors then */
+ (bm->shapenr <= 1))
+ {
+ sod->use_origfaces = true;
+ }
+ else {
+ sod->use_origfaces = false;
+ }
+}
+
+static void slide_origdata_init_data(
+ TransInfo *t, SlideOrigData *sod)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+
+ sod->origfaces = BLI_ghash_ptr_new(__func__);
+ sod->bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default);
+ /* we need to have matching customdata */
+ BM_mesh_copy_init_customdata(sod->bm_origfaces, bm, NULL);
+ }
+}
+
+static void slide_origdata_create_date(
+ TransInfo *t, SlideOrigData *sod,
+ BMVert **v_pt, unsigned int v_stride, unsigned int v_num)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+
+ unsigned int i;
+ for (i = 0; i < v_num; i++, v_pt = (void *)(((char *)v_pt) + v_stride)) {
+ BMIter fiter;
+ BMFace *f;
+ BMVert *v = *v_pt;
+
+ BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
+ if (!BLI_ghash_haskey(sod->origfaces, f)) {
+ BMFace *f_copy = BM_face_copy(sod->bm_origfaces, bm, f, true, true);
+ BLI_ghash_insert(sod->origfaces, f, f_copy);
+ }
+ }
+ }
+ }
+}
+
+static void slide_origdata_free_date(
+ SlideOrigData *sod)
+{
+ if (sod->use_origfaces) {
+ if (sod->bm_origfaces) {
+ BM_mesh_free(sod->bm_origfaces);
+ sod->bm_origfaces = NULL;
+ }
+
+ if (sod->origfaces) {
+ BLI_ghash_free(sod->origfaces, NULL, NULL);
+ sod->origfaces = NULL;
+ }
+ }
+}
+
+/** \} */
/* -------------------------------------------------------------------- */
/* Transform (Edge Slide) */
@@ -5360,16 +5450,7 @@ static bool createEdgeSlideVerts(TransInfo *t)
rv3d = t->ar ? t->ar->regiondata : NULL;
}
- if ((t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) &&
- /* don't do this at all for non-basis shape keys, too easy to
- * accidentally break uv maps or vertex colors then */
- (bm->shapenr <= 1))
- {
- sld->use_origfaces = true;
- }
- else {
- sld->use_origfaces = false;
- }
+ slide_origdata_init_flag(t, &sld->orig_data);
sld->is_proportional = true;
sld->curr_sv_index = 0;
@@ -5761,30 +5842,12 @@ static bool createEdgeSlideVerts(TransInfo *t)
}
bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
-
- if (sld->use_origfaces) {
- sld->origfaces = BLI_ghash_ptr_new(__func__);
- sld->bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default);
- /* we need to have matching customdata */
- BM_mesh_copy_init_customdata(sld->bm_origfaces, bm, NULL);
- }
+ slide_origdata_init_data(t, &sld->orig_data);
+ slide_origdata_create_date(t, &sld->orig_data, &sld->sv->v, sizeof(*sld->sv), sld->totsv);
/*create copies of faces for customdata projection*/
sv_array = sld->sv;
for (i = 0; i < sld->totsv; i++, sv_array++) {
- BMIter fiter;
- BMFace *f;
-
-
- if (sld->use_origfaces) {
- BM_ITER_ELEM (f, &fiter, sv_array->v, BM_FACES_OF_VERT) {
- if (!BLI_ghash_haskey(sld->origfaces, f)) {
- BMFace *f_copy = BM_face_copy(sld->bm_origfaces, bm, f, true, true);
- BLI_ghash_insert(sld->origfaces, f, f_copy);
- }
- }
- }
-
/* switch a/b if loop direction is different from global direction */
l_nr = sv_array->loop_nr;
if (dot_v3v3(loop_dir[l_nr], mval_dir) < 0.0f) {
@@ -5828,11 +5891,12 @@ static bool createEdgeSlideVerts(TransInfo *t)
void projectEdgeSlideData(TransInfo *t, bool is_final)
{
EdgeSlideData *sld = t->customData;
+ SlideOrigData *sod = &sld->orig_data;
TransDataEdgeSlideVert *sv;
BMEditMesh *em = sld->em;
int i;
- if (sld->use_origfaces == false) {
+ if (sod->use_origfaces == false) {
return;
}
@@ -5844,7 +5908,7 @@ void projectEdgeSlideData(TransInfo *t, bool is_final)
BMFace *f_copy; /* the copy of 'f' */
BMFace *f_copy_flip; /* the copy of 'f' or detect if we need to flip to the shorter side. */
- f_copy = BLI_ghash_lookup(sld->origfaces, l->f);
+ f_copy = BLI_ghash_lookup(sod->origfaces, l->f);
/* project onto copied projection face */
f_copy_flip = f_copy;
@@ -5858,12 +5922,12 @@ void projectEdgeSlideData(TransInfo *t, bool is_final)
if (sld->perc < 0.0f) {
if (BM_vert_in_face(sv->v_b, l_ed_sel->radial_next->f)) {
- f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_ed_sel->radial_next->f);
+ f_copy_flip = BLI_ghash_lookup(sod->origfaces, l_ed_sel->radial_next->f);
}
}
else if (sld->perc > 0.0f) {
if (BM_vert_in_face(sv->v_a, l_ed_sel->radial_next->f)) {
- f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_ed_sel->radial_next->f);
+ f_copy_flip = BLI_ghash_lookup(sod->origfaces, l_ed_sel->radial_next->f);
}
}
@@ -5949,7 +6013,7 @@ void projectEdgeSlideData(TransInfo *t, bool is_final)
l_adj = l;
}
- f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_adj->f);
+ f_copy_flip = BLI_ghash_lookup(sod->origfaces, l_adj->f);
}
}
}
@@ -5966,34 +6030,23 @@ void projectEdgeSlideData(TransInfo *t, bool is_final)
}
/* make sure face-attributes are correct (e.g. MTexPoly) */
- BM_elem_attrs_copy(sld->bm_origfaces, em->bm, f_copy, l->f);
+ BM_elem_attrs_copy(sod->bm_origfaces, em->bm, f_copy, l->f);
}
}
}
void freeEdgeSlideTempFaces(EdgeSlideData *sld)
{
- if (sld->use_origfaces) {
- if (sld->bm_origfaces) {
- BM_mesh_free(sld->bm_origfaces);
- sld->bm_origfaces = NULL;
- }
-
- if (sld->origfaces) {
- BLI_ghash_free(sld->origfaces, NULL, NULL);
- sld->origfaces = NULL;
- }
- }
+ slide_origdata_free_date(&sld->orig_data);
}
-
void freeEdgeSlideVerts(TransInfo *t)
{
EdgeSlideData *sld = t->customData;
if (!sld)
return;
-
+
freeEdgeSlideTempFaces(sld);
bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
@@ -6167,7 +6220,7 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t)
}
}
-static int doEdgeSlide(TransInfo *t, float perc)
+static void doEdgeSlide(TransInfo *t, float perc)
{
EdgeSlideData *sld = t->customData;
TransDataEdgeSlideVert *svlist = sld->sv, *sv;
@@ -6224,8 +6277,6 @@ static int doEdgeSlide(TransInfo *t, float perc)
}
projectEdgeSlideData(t, 0);
-
- return 1;
}
static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
@@ -6390,6 +6441,8 @@ static bool createVertSlideVerts(TransInfo *t)
rv3d = ar ? ar->regiondata : NULL;
}
+ slide_origdata_init_flag(t, &sld->orig_data);
+
sld->is_proportional = true;
sld->curr_sv_index = 0;
sld->flipped_vtx = false;
@@ -6485,6 +6538,10 @@ static bool createVertSlideVerts(TransInfo *t)
sld->sv = sv_array;
sld->totsv = j;
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ slide_origdata_init_data(t, &sld->orig_data);
+ slide_origdata_create_date(t, &sld->orig_data, &sld->sv->v, sizeof(*sld->sv), sld->totsv);
+
sld->em = em;
sld->perc = 0.0f;
@@ -6499,6 +6556,53 @@ static bool createVertSlideVerts(TransInfo *t)
return true;
}
+void projectVertSlideData(TransInfo *t, bool is_final)
+{
+ VertSlideData *sld = t->customData;
+ SlideOrigData *sod = &sld->orig_data;
+ TransDataVertSlideVert *sv;
+ BMEditMesh *em = sld->em;
+ int i;
+
+ if (sod->use_origfaces == false) {
+ return;
+ }
+
+ for (i = 0, sv = sld->sv; i < sld->totsv; sv++, i++) {
+ BMIter fiter;
+ BMLoop *l;
+
+ BM_ITER_ELEM (l, &fiter, sv->v, BM_LOOPS_OF_VERT) {
+ BMFace *f_copy; /* the copy of 'f' */
+ BMFace *f_copy_flip; /* the copy of 'f' or detect if we need to flip to the shorter side. */
+
+ f_copy = BLI_ghash_lookup(sod->origfaces, l->f);
+
+ /* project onto copied projection face */
+ f_copy_flip = f_copy;
+
+ /* only loop data, no vertex data since that contains shape keys,
+ * and we do not want to mess up other shape keys */
+ BM_loop_interp_from_face(em->bm, l, f_copy_flip, false, false);
+
+ if (is_final) {
+ BM_loop_interp_multires(em->bm, l, f_copy_flip);
+ if (f_copy != f_copy_flip) {
+ BM_loop_interp_multires(em->bm, l, f_copy);
+ }
+ }
+
+ /* make sure face-attributes are correct (e.g. MTexPoly) */
+ BM_elem_attrs_copy(sod->bm_origfaces, em->bm, f_copy, l->f);
+ }
+ }
+}
+
+void freeVertSlideTempFaces(VertSlideData *sld)
+{
+ slide_origdata_free_date(&sld->orig_data);
+}
+
void freeVertSlideVerts(TransInfo *t)
{
VertSlideData *sld = t->customData;
@@ -6506,6 +6610,9 @@ void freeVertSlideVerts(TransInfo *t)
if (!sld)
return;
+ freeVertSlideTempFaces(sld);
+
+ bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
if (sld->totsv > 0) {
TransDataVertSlideVert *sv = sld->sv;
@@ -6702,7 +6809,7 @@ static void drawVertSlide(const struct bContext *C, TransInfo *t)
}
}
-static int doVertSlide(TransInfo *t, float perc)
+static void doVertSlide(TransInfo *t, float perc)
{
VertSlideData *sld = t->customData;
TransDataVertSlideVert *svlist = sld->sv, *sv;
@@ -6742,7 +6849,7 @@ static int doVertSlide(TransInfo *t, float perc)
}
}
- return 1;
+ projectVertSlideData(t, false);
}
static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
@@ -7117,7 +7224,7 @@ static void initSeqSlide(TransInfo *t)
t->num.unit_type[1] = B_UNIT_NONE;
}
-static void headerSeqSlide(TransInfo *t, float val[2], char str[MAX_INFO_LEN])
+static void headerSeqSlide(TransInfo *t, const float val[2], char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
size_t ofs = 0;
@@ -7516,7 +7623,7 @@ static void initTimeSlide(TransInfo *t)
t->num.unit_type[0] = B_UNIT_NONE;
}
-static void headerTimeSlide(TransInfo *t, float sval, char str[MAX_INFO_LEN])
+static void headerTimeSlide(TransInfo *t, const float sval, char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 0d824be862e..2330ec6e79e 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -213,18 +213,23 @@ typedef struct TransDataEdgeSlideVert {
int loop_nr;
} TransDataEdgeSlideVert;
+
+/* store original data so we can correct UV's and similar when sliding */
+typedef struct SlideOrigData {
+ /* flag that is set when origfaces is initialized */
+ bool use_origfaces;
+ struct GHash *origfaces;
+ struct BMesh *bm_origfaces;
+} SlideOrigData;
+
typedef struct EdgeSlideData {
TransDataEdgeSlideVert *sv;
int totsv;
-
- struct GHash *origfaces;
int mval_start[2], mval_end[2];
struct BMEditMesh *em;
- /* flag that is set when origfaces is initialized */
- bool use_origfaces;
- struct BMesh *bm_origfaces;
+ SlideOrigData orig_data;
float perc;
@@ -251,6 +256,8 @@ typedef struct VertSlideData {
struct BMEditMesh *em;
+ SlideOrigData orig_data;
+
float perc;
bool is_proportional;
@@ -699,7 +706,9 @@ void freeEdgeSlideTempFaces(EdgeSlideData *sld);
void freeEdgeSlideVerts(TransInfo *t);
void projectEdgeSlideData(TransInfo *t, bool is_final);
+void freeVertSlideTempFaces(VertSlideData *sld);
void freeVertSlideVerts(TransInfo *t);
+void projectVertSlideData(TransInfo *t, bool is_final);
/* TODO. transform_queries.c */
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index d8f17315c01..ccb81c7342b 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -208,7 +208,7 @@ static void axisProjection(TransInfo *t, const float axis[3], const float in[3],
viewAxisCorrectCenter(t, t_con_center);
angle = fabsf(angle_v3v3(axis, t->viewinv[2]));
- if (angle > (float)M_PI / 2.0f) {
+ if (angle > (float)M_PI_2) {
angle = (float)M_PI - angle;
}
angle = RAD2DEGF(angle);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index c1350b1f076..42f7087d4a7 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -5354,7 +5354,7 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o
/* only if bone name matches too...
* NOTE: this will do constraints too, but those are ok to do here too?
*/
- if (pchanName && strcmp(pchanName, pchan->name) == 0)
+ if (pchanName && STREQ(pchanName, pchan->name))
insert_keyframe(reports, id, act, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
if (pchanName) MEM_freeN(pchanName);
@@ -5597,6 +5597,12 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
* during cleanup - psy-fi */
freeEdgeSlideTempFaces(sld);
}
+ else if (t->mode == TFM_VERT_SLIDE) {
+ /* as above */
+ VertSlideData *sld = t->customData;
+ projectVertSlideData(t, true);
+ freeVertSlideTempFaces(sld);
+ }
if (t->obedit->type == OB_MESH) {
special_aftertrans_update__mesh(C, t);
@@ -7321,6 +7327,11 @@ static void createTransGPencil(bContext *C, TransInfo *t)
bGPDstroke *gps;
for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+
if (propedit) {
/* Proportional Editing... */
if (propedit_connected) {
@@ -7424,6 +7435,11 @@ static void createTransGPencil(bContext *C, TransInfo *t)
TransData *tail = td;
bool stroke_ok;
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+
/* What we need to include depends on proportional editing settings... */
if (propedit) {
if (propedit_connected) {
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index fcf789546e8..3000b3e00bc 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1874,9 +1874,12 @@ void calculatePropRatio(TransInfo *t)
TransData *td = t->data;
int i;
float dist;
- short connected = t->flag & T_PROP_CONNECTED;
+ const bool connected = (t->flag & T_PROP_CONNECTED) != 0;
+
+ t->proptext[0] = '\0';
if (t->flag & T_PROP_EDIT) {
+ const char *pet_id = NULL;
for (i = 0; i < t->total; i++, td++) {
if (td->flag & TD_SELECTED) {
td->factor = 1.0f;
@@ -1937,6 +1940,9 @@ void calculatePropRatio(TransInfo *t)
case PROP_RANDOM:
td->factor = BLI_frand() * dist;
break;
+ case PROP_INVSQUARE:
+ td->factor = dist * (2.0f - dist);
+ break;
default:
td->factor = 1;
break;
@@ -1945,35 +1951,40 @@ void calculatePropRatio(TransInfo *t)
}
switch (t->prop_mode) {
case PROP_SHARP:
- strcpy(t->proptext, IFACE_("(Sharp)"));
+ pet_id = N_("(Sharp)");
break;
case PROP_SMOOTH:
- strcpy(t->proptext, IFACE_("(Smooth)"));
+ pet_id = N_("(Smooth)");
break;
case PROP_ROOT:
- strcpy(t->proptext, IFACE_("(Root)"));
+ pet_id = N_("(Root)");
break;
case PROP_LIN:
- strcpy(t->proptext, IFACE_("(Linear)"));
+ pet_id = N_("(Linear)");
break;
case PROP_CONST:
- strcpy(t->proptext, IFACE_("(Constant)"));
+ pet_id = N_("(Constant)");
break;
case PROP_SPHERE:
- strcpy(t->proptext, IFACE_("(Sphere)"));
+ pet_id = N_("(Sphere)");
break;
case PROP_RANDOM:
- strcpy(t->proptext, IFACE_("(Random)"));
+ pet_id = N_("(Random)");
+ break;
+ case PROP_INVSQUARE:
+ pet_id = N_("(InvSquare)");
break;
default:
- t->proptext[0] = '\0';
break;
}
+
+ if (pet_id) {
+ BLI_strncpy(t->proptext, IFACE_(pet_id), sizeof(t->proptext));
+ }
}
else {
for (i = 0; i < t->total; i++, td++) {
td->factor = 1.0;
}
- t->proptext[0] = '\0';
}
}
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index f2869843dd5..38190d407ab 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -177,7 +177,7 @@ static void axis_angle_to_gimbal_axis(float gmat[3][3], const float axis[3], con
mul_qt_v3(quat, gmat[0]);
/* Y-axis */
- axis_angle_to_quat(quat, axis, M_PI / 2.0);
+ axis_angle_to_quat(quat, axis, M_PI_2);
copy_v3_v3(gmat[1], gmat[0]);
mul_qt_v3(quat, gmat[1]);
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 25dee50a192..1498e2894d4 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -868,7 +868,7 @@ static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot)
RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
- Transform_Properties(ot, P_MIRROR | P_SNAP);
+ Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
}
static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot)
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 32d4f2e5a15..438eb1f3864 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -231,7 +231,7 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha
BLI_split_file_part(abs_name, fi, sizeof(fi));
BLI_snprintf(local_name, sizeof(local_name), "//%s/%s", folder, fi);
- if (strcmp(abs_name, local_name) != 0) {
+ if (!STREQ(abs_name, local_name)) {
switch (checkPackedFile(local_name, pf)) {
case PF_NOFILE:
BLI_snprintf(line, sizeof(line), IFACE_("Create %s"), local_name);
diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c
index 2428ee21367..7f5edb5ea9e 100644
--- a/source/blender/editors/util/editmode_undo.c
+++ b/source/blender/editors/util/editmode_undo.c
@@ -206,7 +206,7 @@ static void undo_clean_stack(bContext *C)
/* for when objects are converted, renamed, or global undo changes pointers... */
if (uel->type == obedit->type) {
- if (strcmp(uel->id.name, obedit->id.name) == 0) {
+ if (STREQ(uel->id.name, obedit->id.name)) {
if (uel->validate_undo == NULL)
is_valid = true;
else if (uel->validate_undo(uel->undodata, editdata))
@@ -305,7 +305,7 @@ void undo_editmode_name(bContext *C, const char *undoname)
UndoElem *uel;
for (uel = undobase.last; uel; uel = uel->prev) {
- if (strcmp(undoname, uel->name) == 0)
+ if (STREQ(undoname, uel->name))
break;
}
if (uel && uel->prev) {
@@ -321,7 +321,7 @@ int undo_editmode_valid(const char *undoname)
UndoElem *uel;
for (uel = undobase.last; uel; uel = uel->prev) {
- if (strcmp(undoname, uel->name) == 0)
+ if (STREQ(undoname, uel->name))
break;
}
return uel != NULL;
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index fac57490b44..ab882a388ad 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -580,7 +580,7 @@ static int undo_history_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
}
else if (undosys == UNDOSYSTEM_IMAPAINT) {
- ED_undo_paint_step_num(C, UNDO_PAINT_IMAGE, item );
+ ED_undo_paint_step_num(C, UNDO_PAINT_IMAGE, item);
}
else {
ED_viewport_render_kill_jobs(CTX_wm_manager(C), CTX_data_main(C), true);
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 569fe1c326d..00615f9bef7 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -2672,8 +2672,8 @@ static PBool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
}
for (i = 0; i < ninterior; i++) {
- sys->lambdaPlanar[i] += nlGetVariable(0, i);
- sys->lambdaLength[i] += nlGetVariable(0, ninterior + i);
+ sys->lambdaPlanar[i] += (float)nlGetVariable(0, i);
+ sys->lambdaLength[i] += (float)nlGetVariable(0, ninterior + i);
}
}
@@ -4561,7 +4561,7 @@ void param_pack(ParamHandle *handle, float margin, bool do_rotate)
box->index = i; /* warning this index skips PCHART_NOPACK boxes */
if (margin > 0.0f)
- area += sqrtf(box->w * box->h);
+ area += (double)sqrtf(box->w * box->h);
}
if (margin > 0.0f) {
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index c5931cf2943..4cb1f8943f9 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -1601,7 +1601,7 @@ static int stitch_init(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- GHashIterator *ghi;
+ GHashIterator gh_iter;
UvEdge *all_edges;
StitchState *state;
Scene *scene = CTX_data_scene(C);
@@ -1748,14 +1748,11 @@ static int stitch_init(bContext *C, wmOperator *op)
}
}
-
- ghi = BLI_ghashIterator_new(edge_hash);
total_edges = BLI_ghash_size(edge_hash);
state->edges = edges = MEM_mallocN(sizeof(*edges) * total_edges, "stitch_edges");
/* I assume any system will be able to at least allocate an iterator :p */
if (!edges) {
- BLI_ghashIterator_free(ghi);
state_delete(state);
return 0;
}
@@ -1763,12 +1760,12 @@ static int stitch_init(bContext *C, wmOperator *op)
state->total_separate_edges = total_edges;
/* fill the edges with data */
- for (i = 0, BLI_ghashIterator_init(ghi, edge_hash); !BLI_ghashIterator_done(ghi); BLI_ghashIterator_step(ghi)) {
- edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
+ i = 0;
+ GHASH_ITER (gh_iter, edge_hash) {
+ edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(&gh_iter));
}
/* cleanup temporary stuff */
- BLI_ghashIterator_free(ghi);
MEM_freeN(all_edges);
BLI_ghash_free(edge_hash, NULL, NULL);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index b5e27ab0cf6..793f84b05ec 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -1130,7 +1130,7 @@ void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
ParamHandle *handle;
const bool fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0;
- const bool correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) != 0;
+ const bool correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0;
bool use_subsurf;
modifier_unwrap_state(obedit, scene, &use_subsurf);