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:
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2013-01-06 02:24:05 +0400
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2013-01-06 02:24:05 +0400
commitfeccbaabbd39c18b2f552964ebd8dfab4eeaed89 (patch)
tree0069f654883a7a02dd320649ce61bd7933748111 /source/blender/editors
parenta22096e8019c461128a0907e4026859996ec1b5c (diff)
parent37ba969c74840142682cf22f34610f3b65b86cf4 (diff)
Merged changes in the trunk up to revision 53584.
Conflicts resolved: release/scripts/startup/bl_ui/properties_render.py source/blender/blenloader/intern/readfile.c source/blender/editors/interface/interface_templates.c source/blender/makesrna/RNA_enum_types.h Also made additional code updates for: r53355 UIList - Python-extendable list of UI items r53460 Alpha premul pipeline cleanup
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/anim_ops.c30
-rw-r--r--source/blender/editors/animation/keyframing.c133
-rw-r--r--source/blender/editors/armature/editarmature.c14
-rw-r--r--source/blender/editors/armature/editarmature_retarget.c12
-rw-r--r--source/blender/editors/armature/meshlaplacian.c4
-rw-r--r--source/blender/editors/armature/poseobject.c6
-rw-r--r--source/blender/editors/include/ED_mesh.h6
-rw-r--r--source/blender/editors/include/ED_view3d.h5
-rw-r--r--source/blender/editors/include/UI_icons.h4
-rw-r--r--source/blender/editors/include/UI_interface.h8
-rw-r--r--source/blender/editors/include/UI_interface_icons.h3
-rw-r--r--source/blender/editors/include/UI_resources.h3
-rw-r--r--source/blender/editors/include/UI_view2d.h1
-rw-r--r--source/blender/editors/interface/interface.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c207
-rw-r--r--source/blender/editors/interface/interface_icons.c53
-rw-r--r--source/blender/editors/interface/interface_intern.h4
-rw-r--r--source/blender/editors/interface/interface_layout.c17
-rw-r--r--source/blender/editors/interface/interface_panel.c30
-rw-r--r--source/blender/editors/interface/interface_regions.c25
-rw-r--r--source/blender/editors/interface/interface_templates.c523
-rw-r--r--source/blender/editors/interface/interface_widgets.c18
-rw-r--r--source/blender/editors/interface/resources.c30
-rw-r--r--source/blender/editors/interface/view2d.c471
-rw-r--r--source/blender/editors/interface/view2d_ops.c10
-rw-r--r--source/blender/editors/mesh/editface.c20
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c20
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c32
-rw-r--r--source/blender/editors/mesh/mesh_navmesh.c46
-rw-r--r--source/blender/editors/mesh/meshtools.c113
-rw-r--r--source/blender/editors/object/object_add.c12
-rw-r--r--source/blender/editors/object/object_bake.c13
-rw-r--r--source/blender/editors/object/object_constraint.c28
-rw-r--r--source/blender/editors/object/object_edit.c2
-rw-r--r--source/blender/editors/object/object_group.c2
-rw-r--r--source/blender/editors/object/object_lattice.c10
-rw-r--r--source/blender/editors/object/object_ops.c9
-rw-r--r--source/blender/editors/object/object_relations.c12
-rw-r--r--source/blender/editors/object/object_select.c28
-rw-r--r--source/blender/editors/render/render_opengl.c4
-rw-r--r--source/blender/editors/render/render_preview.c57
-rw-r--r--source/blender/editors/render/render_shading.c2
-rw-r--r--source/blender/editors/screen/area.c222
-rw-r--r--source/blender/editors/screen/screendump.c4
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt1
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c100
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c25
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c561
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c10
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c12
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c1
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c311
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c985
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h26
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c278
-rw-r--r--source/blender/editors/space_action/action_draw.c16
-rw-r--r--source/blender/editors/space_action/space_action.c9
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c4
-rw-r--r--source/blender/editors/space_file/file_draw.c3
-rw-r--r--source/blender/editors/space_graph/space_graph.c6
-rw-r--r--source/blender/editors/space_image/image_buttons.c28
-rw-r--r--source/blender/editors/space_image/image_draw.c86
-rw-r--r--source/blender/editors/space_image/image_ops.c7
-rw-r--r--source/blender/editors/space_image/space_image.c1
-rw-r--r--source/blender/editors/space_info/info_intern.h4
-rw-r--r--source/blender/editors/space_info/info_ops.c70
-rw-r--r--source/blender/editors/space_info/info_stats.c66
-rw-r--r--source/blender/editors/space_info/space_info.c3
-rw-r--r--source/blender/editors/space_logic/logic_window.c4
-rw-r--r--source/blender/editors/space_logic/space_logic.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c8
-rw-r--r--source/blender/editors/space_node/node_view.c20
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c94
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h4
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c18
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c17
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c5
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c5
-rw-r--r--source/blender/editors/space_text/CMakeLists.txt3
-rw-r--r--source/blender/editors/space_text/space_text.c7
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c541
-rw-r--r--source/blender/editors/space_text/text_draw.c107
-rw-r--r--source/blender/editors/space_text/text_format.c18
-rw-r--r--source/blender/editors/space_text/text_format.h49
-rw-r--r--source/blender/editors/space_text/text_format_osl.c335
-rw-r--r--source/blender/editors/space_text/text_format_py.c236
-rw-r--r--source/blender/editors/space_text/text_intern.h5
-rw-r--r--source/blender/editors/space_text/text_ops.c7
-rw-r--r--source/blender/editors/space_text/text_python.c358
-rw-r--r--source/blender/editors/space_userpref/space_userpref.c8
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c23
-rw-r--r--source/blender/editors/space_view3d/drawobject.c58
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c241
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c15
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h1
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c47
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c61
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c228
-rw-r--r--source/blender/editors/transform/transform.c43
-rw-r--r--source/blender/editors/transform/transform_conversions.c6
-rw-r--r--source/blender/editors/transform/transform_generics.c4
-rw-r--r--source/blender/editors/transform/transform_orientations.c2
-rw-r--r--source/blender/editors/util/undo.c42
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h1
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c89
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c10
109 files changed, 5253 insertions, 2353 deletions
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index ca036a8540e..6687cce88cd 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -62,16 +62,28 @@
/* Check if the operator can be run from the current context */
static int change_frame_poll(bContext *C)
{
- ScrArea *curarea = CTX_wm_area(C);
+ ScrArea *sa = CTX_wm_area(C);
/* XXX temp? prevent changes during render */
- if (G.is_rendering) return 0;
+ if (G.is_rendering) return FALSE;
- /* as long as there is an active area, and it isn't a Graph Editor
- * (since the Graph Editor has its own version which does extra stuff),
- * we're fine
+ /* although it's only included in keymaps for regions using ED_KEYMAP_ANIMATION,
+ * this shouldn't show up in 3D editor (or others without 2D timeline view) via search
*/
- return ((curarea) && (curarea->spacetype != SPACE_IPO));
+ if (sa) {
+ if (ELEM5(sa->spacetype, SPACE_TIME, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
+ return TRUE;
+ }
+ else if (sa->spacetype == SPACE_IPO) {
+ /* NOTE: Graph Editor has special version which does some extra stuff.
+ * No need to show the generic error message for that case though!
+ */
+ return FALSE;
+ }
+ }
+
+ CTX_wm_operator_poll_msg_set(C, "Expected an timeline/animation area to be active");
+ return FALSE;
}
/* Set the new frame number */
@@ -83,7 +95,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
/* set the new frame number */
CFRA = RNA_int_get(op->ptr, "frame");
FRAMENUMBER_MIN_CLAMP(CFRA);
- SUBFRA = 0.f;
+ SUBFRA = 0.0f;
/* do updates */
sound_seek_scene(bmain, scene);
@@ -161,7 +173,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event)
static void ANIM_OT_change_frame(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Change frame";
+ ot->name = "Change Frame";
ot->idname = "ANIM_OT_change_frame";
ot->description = "Interactively change the current frame number";
@@ -175,7 +187,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_POINTER;
/* rna */
- RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
+ ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
}
/* ****************** set preview range operator ****************************/
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 8ba330e7c3c..9add193a514 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -540,8 +540,8 @@ static float setting_get_rna_value(PointerRNA *ptr, PropertyRNA *prop, int index
enum {
VISUALKEY_NONE = 0,
VISUALKEY_LOC,
- VISUALKEY_ROT
- /* VISUALKEY_SCA */ /* TODO - looks like support can be added now */
+ VISUALKEY_ROT,
+ VISUALKEY_SCA,
};
/* This helper function determines if visual-keyframing should be used when
@@ -560,7 +560,7 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
/* validate data */
if (ELEM3(NULL, ptr, ptr->data, prop))
return 0;
-
+
/* get first constraint and determine type of keyframe constraints to check for
* - constraints can be on either Objects or PoseChannels, so we only check if the
* ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
@@ -586,7 +586,7 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
/* check if any data to search using */
if (ELEM(NULL, con, identifier) && (has_parent == FALSE))
return 0;
-
+
/* location or rotation identifiers only... */
if (identifier == NULL) {
printf("%s failed: NULL identifier\n", __func__);
@@ -598,6 +598,9 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
else if (strstr(identifier, "rotation")) {
searchtype = VISUALKEY_ROT;
}
+ else if (strstr(identifier, "scale")) {
+ searchtype = VISUALKEY_SCA;
+ }
else {
printf("%s failed: identifier - '%s'\n", __func__, identifier);
return 0;
@@ -628,7 +631,7 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
return 1;
case CONSTRAINT_TYPE_KINEMATIC:
return 1;
-
+
/* single-transform constraits */
case CONSTRAINT_TYPE_TRACKTO:
if (searchtype == VISUALKEY_ROT) return 1;
@@ -642,15 +645,21 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
case CONSTRAINT_TYPE_LOCLIMIT:
if (searchtype == VISUALKEY_LOC) return 1;
break;
- case CONSTRAINT_TYPE_ROTLIKE:
- if (searchtype == VISUALKEY_ROT) return 1;
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ if (searchtype == VISUALKEY_SCA) return 1;
break;
case CONSTRAINT_TYPE_DISTLIMIT:
if (searchtype == VISUALKEY_LOC) return 1;
break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ if (searchtype == VISUALKEY_ROT) return 1;
+ break;
case CONSTRAINT_TYPE_LOCLIKE:
if (searchtype == VISUALKEY_LOC) return 1;
break;
+ case CONSTRAINT_TYPE_SIZELIKE:
+ if (searchtype == VISUALKEY_SCA) return 1;
+ break;
case CONSTRAINT_TYPE_LOCKTRACK:
if (searchtype == VISUALKEY_ROT) return 1;
break;
@@ -675,45 +684,26 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
static float visualkey_get_value(PointerRNA *ptr, PropertyRNA *prop, int array_index)
{
const char *identifier = RNA_property_identifier(prop);
+ float tmat[4][4];
+ int rotmode;
/* handle for Objects or PoseChannels only
+ * - only Location, Rotation or Scale keyframes are supported curently
* - constraints can be on either Objects or PoseChannels, so we only check if the
- * ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
+ * ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
* those structs, allowing us to identify the owner of the data
- * - assume that array_index will be sane
+ * - assume that array_index will be sane
*/
if (ptr->type == &RNA_Object) {
Object *ob = (Object *)ptr->data;
-
- /* only Location or Rotation keyframes are supported now */
+
+ /* Loc code is specific... */
if (strstr(identifier, "location")) {
return ob->obmat[3][array_index];
}
- else if (strstr(identifier, "rotation_euler")) {
- float eul[3];
-
- mat4_to_eulO(eul, ob->rotmode, ob->obmat);
- return eul[array_index];
- }
- else if (strstr(identifier, "rotation_quaternion")) {
- float trimat[3][3], quat[4];
-
- copy_m3_m4(trimat, ob->obmat);
- mat3_to_quat_is_ok(quat, trimat);
-
- return quat[array_index];
- }
- else if (strstr(identifier, "rotation_axis_angle")) {
- float axis[3], angle;
-
- mat4_to_axis_angle(axis, &angle, ob->obmat);
-
- /* w = 0, x,y,z = 1,2,3 */
- if (array_index == 0)
- return angle;
- else
- return axis[array_index - 1];
- }
+
+ copy_m4_m4(tmat, ob->obmat);
+ rotmode = ob->rotmode;
}
else if (ptr->type == &RNA_PoseBone) {
Object *ob = (Object *)ptr->id.data; /* we assume that this is always set, and is an object */
@@ -726,42 +716,53 @@ static float visualkey_get_value(PointerRNA *ptr, PropertyRNA *prop, int array_i
* will be what owns the pose-channel that is getting this anyway.
*/
copy_m4_m4(tmat, pchan->pose_mat);
- constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+ rotmode = pchan->rotmode;
- /* Loc, Rot/Quat keyframes are supported... */
+ /* Loc code is specific... */
if (strstr(identifier, "location")) {
/* only use for non-connected bones */
- if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED))
+ if ((pchan->bone->parent == NULL) || !(pchan->bone->flag & BONE_CONNECTED))
return tmat[3][array_index];
- else if (pchan->bone->parent == NULL)
- return tmat[3][array_index];
- }
- else if (strstr(identifier, "rotation_euler")) {
- float eul[3];
-
- mat4_to_eulO(eul, pchan->rotmode, tmat);
- return eul[array_index];
- }
- else if (strstr(identifier, "rotation_quaternion")) {
- float trimat[3][3], quat[4];
-
- copy_m3_m4(trimat, tmat);
- mat3_to_quat_is_ok(quat, trimat);
-
- return quat[array_index];
- }
- else if (strstr(identifier, "rotation_axis_angle")) {
- float axis[3], angle;
-
- mat4_to_axis_angle(axis, &angle, tmat);
-
- /* w = 0, x,y,z = 1,2,3 */
- if (array_index == 0)
- return angle;
- else
- return axis[array_index - 1];
}
}
+ else {
+ return setting_get_rna_value(ptr, prop, array_index);
+ }
+
+ /* Rot/Scale code are common! */
+ if (strstr(identifier, "rotation_euler")) {
+ float eul[3];
+
+ mat4_to_eulO(eul, rotmode, tmat);
+ return eul[array_index];
+ }
+ else if (strstr(identifier, "rotation_quaternion")) {
+ float mat3[3][3], quat[4];
+
+ copy_m3_m4(mat3, tmat);
+ mat3_to_quat_is_ok(quat, mat3);
+
+ return quat[array_index];
+ }
+ else if (strstr(identifier, "rotation_axis_angle")) {
+ float axis[3], angle;
+
+ mat4_to_axis_angle(axis, &angle, tmat);
+
+ /* w = 0, x,y,z = 1,2,3 */
+ if (array_index == 0)
+ return angle;
+ else
+ return axis[array_index - 1];
+ }
+ else if (strstr(identifier, "scale")) {
+ float scale[3];
+
+ mat4_to_size(scale, tmat);
+
+ return scale[array_index];
+ }
/* as the function hasn't returned yet, read value from system in the default way */
return setting_get_rna_value(ptr, prop, array_index);
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c
index ae405c0e113..37314373e98 100644
--- a/source/blender/editors/armature/editarmature.c
+++ b/source/blender/editors/armature/editarmature.c
@@ -812,7 +812,7 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann
pose = ob->pose;
for (pchant = pose->chanbase.first; pchant; pchant = pchant->next) {
for (con = pchant->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -859,7 +859,7 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann
/* fix object-level constraints */
if (ob != srcArm) {
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -1032,7 +1032,7 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
if (ob->type == OB_ARMATURE) {
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -1070,7 +1070,7 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
/* fix object-level constraints */
if (ob != origArm) {
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -1712,7 +1712,7 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
}
else {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -2523,7 +2523,7 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Obj
/* does this constraint have a subtarget in
* this armature?
*/
- bConstraintTypeInfo *cti = constraint_get_typeinfo(curcon);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -5533,7 +5533,7 @@ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, char *oldnam
bConstraintTarget *ct;
for (curcon = conlist->first; curcon; curcon = curcon->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(curcon);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon);
ListBase targets = {NULL, NULL};
if (cti && cti->get_constraint_targets) {
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
index 68cfc7fb8c0..3e34a4c6808 100644
--- a/source/blender/editors/armature/editarmature_retarget.c
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -725,7 +725,7 @@ static void RIG_reconnectControlBones(RigGraph *rg)
/* DO SOME MAGIC HERE */
for (pchan = rg->ob->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -850,7 +850,7 @@ static void RIG_reconnectControlBones(RigGraph *rg)
/* DO SOME MAGIC HERE */
for (pchan = rg->ob->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -1830,7 +1830,9 @@ static float calcCostLengthDistance(BArcIterator *iter, float **vec_cache, RigEd
}
#endif
-static float calcCostAngleLengthDistance(BArcIterator *iter, float **UNUSED(vec_cache), RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2, float angle_weight, float length_weight, float distance_weight)
+static float calcCostAngleLengthDistance(BArcIterator *iter, float **UNUSED(vec_cache), RigEdge *edge,
+ float *vec0, float *vec1, float *vec2, int i1, int i2,
+ float angle_weight, float length_weight, float distance_weight)
{
float vec_second[3], vec_first[3];
float length2;
@@ -1878,7 +1880,9 @@ static void copyMemoPositions(int *positions, MemoNode *table, int nb_positions,
}
}
-static MemoNode *solveJoints(MemoNode *table, BArcIterator *iter, float **vec_cache, int nb_joints, int nb_positions, int previous, int current, RigEdge *edge, int joints_left, float angle_weight, float length_weight, float distance_weight)
+static MemoNode *solveJoints(MemoNode *table, BArcIterator *iter, float **vec_cache,
+ int nb_joints, int nb_positions, int previous, int current, RigEdge *edge,
+ int joints_left, float angle_weight, float length_weight, float distance_weight)
{
MemoNode *node;
int index = indexMemoNode(nb_positions, previous, current, joints_left);
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 2848db18d59..19a97fa0810 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -649,7 +649,9 @@ static float heat_limit_weight(float weight)
return weight;
}
-void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected, const char **err_str)
+void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
+ bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
+ float (*root)[3], float (*tip)[3], int *selected, const char **err_str)
{
LaplacianSystem *sys;
MPoly *mp;
diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c
index 576e5983d16..49d4b670cde 100644
--- a/source/blender/editors/armature/poseobject.c
+++ b/source/blender/editors/armature/poseobject.c
@@ -417,7 +417,7 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op
{
if (pchan->bone->flag & BONE_SELECTED) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -925,7 +925,7 @@ static void pose_copy_menu(Scene *scene)
/* copy constraints to tmpbase and apply 'local' tags before
* appending to list of constraints for this channel
*/
- copy_constraints(&tmp_constraints, &pchanact->constraints, TRUE);
+ BKE_copy_constraints(&tmp_constraints, &pchanact->constraints, TRUE);
if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
bConstraint *con;
@@ -1034,7 +1034,7 @@ static void pose_copy_menu(Scene *scene)
/* copy constraints to tmpbase and apply 'local' tags before
* appending to list of constraints for this channel
*/
- copy_constraints(&tmp_constraints, &const_copy, TRUE);
+ BKE_copy_constraints(&tmp_constraints, &const_copy, TRUE);
if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
/* add proxy-local tags */
for (con = tmp_constraints.first; con; con = con->next)
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 1b4a67d38c0..f5ab002e0ef 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -291,9 +291,9 @@ int mesh_get_x_mirror_vert(struct Object *ob, int index);
struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em, struct BMVert *eve, const float co[3], int index);
int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em);
-int ED_mesh_pick_vert(struct bContext *C, struct Mesh *me, const int mval[2], unsigned int *index, int size);
-int ED_mesh_pick_face(struct bContext *C, struct Mesh *me, const int mval[2], unsigned int *index, int size);
-int ED_mesh_pick_face_vert(struct bContext *C, struct Mesh *me, struct Object *ob, const int mval[2], unsigned int *index, int size);
+int ED_mesh_pick_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size, int use_zbuf);
+int ED_mesh_pick_face(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size);
+int ED_mesh_pick_face_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size);
#define ED_MESH_PICK_DEFAULT_VERT_SIZE 50
#define ED_MESH_PICK_DEFAULT_FACE_SIZE 3
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index f7f58a4ee7a..3d13938c204 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -85,6 +85,7 @@ typedef struct ViewDepths {
} ViewDepths;
float *give_cursor(struct Scene *scene, struct View3D *v3d);
+void ED_view3d_cursor3d_position(struct bContext *C, float *fp, int mx, int my);
void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float dist);
void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist);
@@ -124,6 +125,10 @@ typedef enum {
/* view3d_iterators.c */
/* foreach iterators */
+void meshobject_foreachScreenVert(
+ struct ViewContext *vc,
+ void (*func)(void *userData, struct MVert *eve, const float screen_co[2], int index),
+ void *userData, const eV3DProjTest clip_flag);
void mesh_foreachScreenVert(
struct ViewContext *vc,
void (*func)(void *userData, struct BMVert *eve, const float screen_co[2], int index),
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 99f7f0856b3..0a794040692 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -699,9 +699,7 @@ DEF_ICON(RNDCURVE)
DEF_ICON(PROP_OFF)
DEF_ICON(PROP_ON)
DEF_ICON(PROP_CON)
-#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK212)
-#endif
+DEF_ICON(SCULPT_DYNTOPO)
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 90f8779b2c7..080367c4325 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -56,6 +56,7 @@ struct PropertyRNA;
struct ReportList;
struct rcti;
struct rctf;
+struct uiList;
struct uiStyle;
struct uiFontStyle;
struct uiWidgetColors;
@@ -658,6 +659,7 @@ void uiDrawPanels(const struct bContext *C, struct ARegion *ar);
struct Panel *uiBeginPanel(struct ScrArea *sa, struct ARegion *ar, uiBlock *block, struct PanelType *pt, int *open);
void uiEndPanel(uiBlock *block, int width, int height);
+void uiScalePanels(struct ARegion *ar, float new_width);
/* Handlers
*
@@ -778,7 +780,7 @@ uiLayout *uiLayoutRow(uiLayout *layout, int align);
uiLayout *uiLayoutColumn(uiLayout *layout, int align);
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align);
uiLayout *uiLayoutBox(uiLayout *layout);
-uiLayout *uiLayoutListBox(uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop,
+uiLayout *uiLayoutListBox(uiLayout *layout, struct uiList *ui_list, struct PointerRNA *ptr, struct PropertyRNA *prop,
struct PointerRNA *actptr, struct PropertyRNA *actprop);
uiLayout *uiLayoutAbsolute(uiLayout *layout, int align);
uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align);
@@ -824,7 +826,9 @@ void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *te
void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
-void uiTemplateList(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *activeptr, const char *activeprop, const char *prop_list, int rows, int maxrows, int type);
+void uiTemplateList(uiLayout *layout, struct bContext *C, const char *listtype_name, const char *list_id,
+ struct PointerRNA *dataptr, const char *propname, struct PointerRNA *active_dataptr,
+ const char *active_propname, int rows, int maxrows, int layout_type);
void uiTemplateNodeLink(uiLayout *layout, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
void uiTemplateNodeView(uiLayout *layout, struct bContext *C, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
void uiTemplateTextureUser(uiLayout *layout, struct bContext *C);
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index aa94bdec724..f578d68b852 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -32,12 +32,14 @@
#ifndef __UI_INTERFACE_ICONS_H__
#define __UI_INTERFACE_ICONS_H__
+struct bContext;
struct Image;
struct ImBuf;
struct World;
struct Tex;
struct Lamp;
struct Material;
+struct PointerRNA;
typedef struct IconFile {
struct IconFile *next, *prev;
@@ -74,5 +76,6 @@ void UI_icons_free_drawinfo(void *drawinfo);
struct ListBase *UI_iconfile_list(void);
int UI_iconfile_get_index(const char *filename);
+int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, int big);
#endif /* __UI_INTERFACE_ICONS_H__ */
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 236cc371d8b..1035f5815f2 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -122,9 +122,12 @@ enum {
TH_SYNTAX_B,
TH_SYNTAX_V,
+ TH_SYNTAX_R,
TH_SYNTAX_C,
TH_SYNTAX_L,
+ TH_SYNTAX_D,
TH_SYNTAX_N,
+ TH_SYNTAX_S,
TH_BONE_SOLID,
TH_BONE_POSE,
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 3ae1e93dc3d..81a0f526049 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -148,7 +148,6 @@ typedef struct View2DScrollers View2DScrollers;
void UI_view2d_region_reinit(struct View2D *v2d, short type, int winx, int winy);
void UI_view2d_curRect_validate(struct View2D *v2d);
-void UI_view2d_curRect_validate_resize(struct View2D *v2d, int resize);
void UI_view2d_curRect_reset(struct View2D *v2d);
void UI_view2d_sync(struct bScreen *screen, struct ScrArea *sa, struct View2D *v2dcur, int flag);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 25f85883d9c..1d26cbd344b 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -2666,6 +2666,8 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
/* we could do some more error checks here */
if ((type & BUTTYPE) == LABEL) {
+ if ((poin != NULL || min != 0.0f || max != 0.0f || (a1 == 0.0f && a2 != 0.0f) || (a1 != 0.0f && a1 != 1.0f)))
+ printf("blah\n");
BLI_assert((poin != NULL || min != 0.0f || max != 0.0f || (a1 == 0.0f && a2 != 0.0f) || (a1 != 0.0f && a1 != 1.0f)) == FALSE);
}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index fed84092133..1c9cd92271c 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -44,6 +44,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -219,6 +220,29 @@ static void button_timers_tooltip_remove(bContext *C, uiBut *but);
/* ******************** menu navigation helpers ************** */
+/* assumes event type is MOUSEPAN */
+void ui_pan_to_scroll(wmEvent *event, int *type, int *val)
+{
+ static int lastdy = 0;
+ int dy = event->prevy - event->y;
+
+ /* sign differs, reset */
+ if ((dy > 0 && lastdy < 0) || (dy < 0 && lastdy > 0))
+ lastdy = dy;
+ else {
+ lastdy += dy;
+
+ if (ABS(lastdy) > (int)UI_UNIT_Y) {
+ *val = KM_PRESS;
+ if (event->prevy - event->y > 0)
+ *type = WHEELUPMOUSE;
+ else
+ *type = WHEELDOWNMOUSE;
+ lastdy = 0;
+ }
+ }
+}
+
static int ui_but_editable(uiBut *but)
{
return ELEM5(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX, PROGRESSBAR);
@@ -1893,6 +1917,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
case WHEELUPMOUSE:
case WHEELDOWNMOUSE:
case MOUSEMOVE:
+ case MOUSEPAN:
if (data->searchbox)
ui_searchbox_event(C, data->searchbox, but, event);
@@ -2687,12 +2712,16 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
ui_window_to_block(data->region, block, &mx, &my);
if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ int type = event->type, val = event->val;
+
+ ui_pan_to_scroll(event, &type, &val);
+
/* XXX hardcoded keymap check.... */
- if (event->type == WHEELDOWNMOUSE && event->alt) {
+ if (type == WHEELDOWNMOUSE && event->alt) {
mx = but->rect.xmin;
click = 1;
}
- else if (event->type == WHEELUPMOUSE && event->alt) {
+ else if (type == WHEELUPMOUSE && event->alt) {
mx = but->rect.xmax;
click = 1;
}
@@ -2911,12 +2940,16 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
ui_window_to_block(data->region, block, &mx, &my);
if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ int type = event->type, val = event->val;
+
+ ui_pan_to_scroll(event, &type, &val);
+
/* XXX hardcoded keymap check.... */
- if (event->type == WHEELDOWNMOUSE && event->alt) {
+ if (type == WHEELDOWNMOUSE && event->alt) {
mx = but->rect.xmin;
click = 2;
}
- else if (event->type == WHEELUPMOUSE && event->alt) {
+ else if (type == WHEELUPMOUSE && event->alt) {
mx = but->rect.xmax;
click = 2;
}
@@ -3142,7 +3175,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm
}
}
else if (but->type == COLOR) {
- if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
+ if (ELEM3(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
float *hsv = ui_block_hsv_get(but->block);
float col[3];
@@ -3151,8 +3184,12 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm
if (event->type == WHEELDOWNMOUSE)
hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f);
- else
+ else if (event->type == WHEELUPMOUSE)
hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f);
+ else {
+ float fac = 0.005 * (event->y - event->prevy);
+ hsv[2] = CLAMPIS(hsv[2] + fac, 0.0f, 1.0f);
+ }
hsv_to_rgb_v(hsv, data->vec);
ui_set_but_vectorf(but, data->vec);
@@ -5248,32 +5285,15 @@ static int ui_mouse_inside_region(ARegion *ar, int x, int y)
*/
if (ar->v2d.mask.xmin != ar->v2d.mask.xmax) {
View2D *v2d = &ar->v2d;
- rcti mask_rct;
int mx, my;
/* convert window coordinates to region coordinates */
mx = x;
my = y;
ui_window_to_region(ar, &mx, &my);
-
- /* make a copy of the mask rect, and tweak accordingly for hidden scrollbars */
- mask_rct = v2d->mask;
-
- if (v2d->scroll & (V2D_SCROLL_VERTICAL_HIDE | V2D_SCROLL_VERTICAL_FULLR)) {
- if (v2d->scroll & V2D_SCROLL_LEFT)
- mask_rct.xmin = v2d->vert.xmin;
- else if (v2d->scroll & V2D_SCROLL_RIGHT)
- mask_rct.xmax = v2d->vert.xmax;
- }
- if (v2d->scroll & (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_HORIZONTAL_FULLR)) {
- if (v2d->scroll & (V2D_SCROLL_BOTTOM | V2D_SCROLL_BOTTOM_O))
- mask_rct.ymin = v2d->hor.ymin;
- else if (v2d->scroll & V2D_SCROLL_TOP)
- mask_rct.ymax = v2d->hor.ymax;
- }
-
+
/* check if in the rect */
- if (!BLI_rcti_isect_pt(&mask_rct, mx, my))
+ if (!BLI_rcti_isect_pt(&v2d->mask, mx, my))
return 0;
}
@@ -6109,64 +6129,81 @@ static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
uiBut *but = ui_list_find_mouse_over(ar, event->x, event->y);
int retval = WM_UI_HANDLER_CONTINUE;
int value, min, max;
+ int type = event->type, val = event->val;
- if (but && (event->val == KM_PRESS)) {
- Panel *pa = but->block->panel;
+ if (but) {
+ uiList *ui_list = but->custom_data;
- if (ELEM(event->type, UPARROWKEY, DOWNARROWKEY) ||
- ((ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
- {
- /* activate up/down the list */
- value = RNA_property_int_get(&but->rnapoin, but->rnaprop);
+ if (ui_list) {
+
+ /* convert pan to scrollwheel */
+ if (type == MOUSEPAN) {
+ ui_pan_to_scroll(event, &type, &val);
+
+ /* if type still is mousepan, we call it handled, since delta-y accumulate */
+ /* also see wm_event_system.c do_wheel_ui hack */
+ if (type == MOUSEPAN)
+ retval = WM_UI_HANDLER_BREAK;
+ }
+
+ if (val == KM_PRESS) {
+
+ if (ELEM(type, UPARROWKEY, DOWNARROWKEY) ||
+ ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
+ {
+ /* activate up/down the list */
+ value = RNA_property_int_get(&but->rnapoin, but->rnaprop);
- if (ELEM(event->type, UPARROWKEY, WHEELUPMOUSE))
- value--;
- else
- value++;
+ if (ELEM(type, UPARROWKEY, WHEELUPMOUSE))
+ value--;
+ else
+ value++;
- CLAMP(value, 0, pa->list_last_len - 1);
+ CLAMP(value, 0, ui_list->list_last_len - 1);
- if (value < pa->list_scroll)
- pa->list_scroll = value;
- else if (value >= pa->list_scroll + pa->list_size)
- pa->list_scroll = value - pa->list_size + 1;
+ if (value < ui_list->list_scroll)
+ ui_list->list_scroll = value;
+ else if (value >= ui_list->list_scroll + ui_list->list_size)
+ ui_list->list_scroll = value - ui_list->list_size + 1;
- RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
- value = CLAMPIS(value, min, max);
+ RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
+ value = CLAMPIS(value, min, max);
- RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
- RNA_property_update(C, &but->rnapoin, but->rnaprop);
- ED_region_tag_redraw(ar);
+ RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
+ RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ ED_region_tag_redraw(ar);
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
- /* silly replacement for proper grip */
- if (pa->list_grip_size == 0)
- pa->list_grip_size = pa->list_size;
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
+ /* silly replacement for proper grip */
+ if (ui_list->list_grip_size == 0)
+ ui_list->list_grip_size = ui_list->list_size;
- if (event->type == WHEELUPMOUSE)
- pa->list_grip_size--;
- else
- pa->list_grip_size++;
+ if (type == WHEELUPMOUSE)
+ ui_list->list_grip_size--;
+ else
+ ui_list->list_grip_size++;
- pa->list_grip_size = MAX2(pa->list_grip_size, 1);
+ ui_list->list_grip_size = MAX2(ui_list->list_grip_size, 1);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
- if (pa->list_last_len > pa->list_size) {
- /* list template will clamp */
- if (event->type == WHEELUPMOUSE)
- pa->list_scroll--;
- else
- pa->list_scroll++;
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
+ if (ui_list->list_last_len > ui_list->list_size) {
+ /* list template will clamp */
+ if (type == WHEELUPMOUSE)
+ ui_list->list_scroll--;
+ else
+ ui_list->list_scroll++;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- retval = WM_UI_HANDLER_BREAK;
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
}
}
}
@@ -6472,21 +6509,29 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
case DOWNARROWKEY:
case WHEELUPMOUSE:
case WHEELDOWNMOUSE:
+ case MOUSEPAN:
/* arrowkeys: only handle for block_loop blocks */
if (event->alt || event->shift || event->ctrl || event->oskey) {
/* pass */
}
else if (inside || (block->flag & UI_BLOCK_LOOP)) {
- if (event->val == KM_PRESS) {
+ int type = event->type;
+ int val = event->val;
+
+ /* convert pan to scrollwheel */
+ if (type == MOUSEPAN)
+ ui_pan_to_scroll(event, &type, &val);
+
+ if (val == KM_PRESS) {
PASS_EVENT_TO_PARENT_IF_NONACTIVE;
but = ui_but_find_activated(ar);
if (but) {
/* is there a situation where UI_LEFT or UI_RIGHT would also change navigation direction? */
- if (((ELEM(event->type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_DOWN)) ||
- ((ELEM(event->type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_RIGHT)) ||
- ((ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_TOP)))
+ if (((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_DOWN)) ||
+ ((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_RIGHT)) ||
+ ((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_TOP)))
{
/* the following is just a hack - uiBut->type set to BUT and BUTM have there menus built
* opposite ways - this should be changed so that all popup-menus use the same uiBlock->direction */
@@ -6509,9 +6554,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
}
if (!but) {
- if (((ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_DOWN)) ||
- ((ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_RIGHT)) ||
- ((ELEM(event->type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_TOP)))
+ if (((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_DOWN)) ||
+ ((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_RIGHT)) ||
+ ((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_TOP)))
{
if ((bt = ui_but_first(block)) && (bt->type & BUT)) {
bt = ui_but_last(block);
@@ -6928,8 +6973,6 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *UNUSED(user
{
ARegion *ar;
uiBut *but;
- uiHandleButtonData *data;
- int retval;
/* here we handle buttons at the window level, modal, for example
* while number sliding, text editing, or when a menu block is open */
@@ -6940,17 +6983,23 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *UNUSED(user
but = ui_but_find_activated(ar);
if (but) {
+ uiHandleButtonData *data;
+
/* handle activated button events */
data = but->active;
if (data->state == BUTTON_STATE_MENU_OPEN) {
+ int retval;
+
/* handle events for menus and their buttons recursively,
* this will handle events from the top to the bottom menu */
if (data->menu)
retval = ui_handle_menus_recursive(C, event, data->menu, 0);
/* handle events for the activated button */
- if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) {
+ if ((data->menu && (retval == WM_UI_HANDLER_CONTINUE)) ||
+ (event->type == TIMER))
+ {
if (data->menu && data->menu->menuretval)
ui_handle_button_return_submenu(C, event, but);
else
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 2928a5607c0..ebc80d61af3 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -49,6 +49,7 @@
#include "BLI_utildefines.h"
#include "DNA_brush_types.h"
+#include "DNA_dynamicpaint_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -75,8 +76,8 @@
#include "interface_intern.h"
-#define ICON_IMAGE_W 600
-#define ICON_IMAGE_H 640
+// #define ICON_IMAGE_W 600
+// #define ICON_IMAGE_H 640
#define ICON_GRID_COLS 26
#define ICON_GRID_ROWS 30
@@ -574,13 +575,15 @@ static void init_internal_icons(void)
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, b16buf->x, b16buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b16buf->rect);
while (b16buf->x > 1) {
- b16buf = IMB_onehalf(b16buf);
- glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, b16buf->x, b16buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b16buf->rect);
+ ImBuf *nbuf = IMB_onehalf(b16buf);
+ glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, nbuf->x, nbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nbuf->rect);
level++;
+ IMB_freeImBuf(b16buf);
+ b16buf = nbuf;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
@@ -597,7 +600,7 @@ static void init_internal_icons(void)
else
icontype = ICON_TYPE_BUFFER;
- if (b16buf) {
+ if (b32buf) {
for (y = 0; y < ICON_GRID_ROWS; y++) {
for (x = 0; x < ICON_GRID_COLS; x++) {
def_internal_icon(b32buf, BIFICONID_FIRST + y * ICON_GRID_COLS + x,
@@ -1179,6 +1182,44 @@ int ui_id_icon_get(bContext *C, ID *id, int big)
return iconid;
}
+int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, int big)
+{
+ ID *id = NULL;
+
+ if (!ptr->data)
+ return rnaicon;
+
+ /* try ID, material, texture or dynapaint slot */
+ if (RNA_struct_is_ID(ptr->type)) {
+ id = ptr->id.data;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_MaterialSlot)) {
+ id = RNA_pointer_get(ptr, "material").data;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_TextureSlot)) {
+ id = RNA_pointer_get(ptr, "texture").data;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) {
+ DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data;
+
+ if (surface->format == MOD_DPAINT_SURFACE_F_PTEX)
+ return ICON_TEXTURE_SHADED;
+ else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX)
+ return ICON_OUTLINER_DATA_MESH;
+ else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
+ return ICON_FILE_IMAGE;
+ }
+
+ /* get icon from ID */
+ if (id) {
+ int icon = ui_id_icon_get(C, id, big);
+
+ return icon ? icon : rnaicon;
+ }
+
+ return rnaicon;
+}
+
static void icon_draw_at_size(float x, float y, int icon_id, float aspect, float alpha, enum eIconSizes size, int nocreate)
{
int draw_size = get_draw_size(size);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index f088b3a54f4..706301dc060 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -271,6 +271,9 @@ struct uiBut {
/* active button data */
struct uiHandleButtonData *active;
+ /* Custom button data. */
+ void *custom_data;
+
char *editstr;
double *editval;
float *editvec;
@@ -504,6 +507,7 @@ void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rct
void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
/* interface_handlers.c */
+extern void ui_pan_to_scroll(struct wmEvent *event, int *type, int *val);
extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but);
extern void ui_button_active_free(const struct bContext *C, uiBut *but);
extern int ui_button_is_active(struct ARegion *ar);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index a15256bc86f..f4af1f036a3 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -186,13 +186,13 @@ static const char *ui_item_name_add_colon(const char *name, char namestr[UI_MAX_
static int ui_item_fit(int item, int pos, int all, int available, int last, int alignment, int *offset)
{
+ if (offset)
+ *offset = 0;
+
/* available == 0 is unlimited */
if (available == 0)
return item;
-
- if (offset)
- *offset = 0;
-
+
if (all > available) {
/* contents is bigger than available space */
if (last)
@@ -346,7 +346,9 @@ static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index)
}
/* create buttons for an item with an RNA array */
-static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int UNUSED(h), int expand, int slider, int toggle, int icon_only)
+static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, int icon,
+ PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int UNUSED(h),
+ int expand, int slider, int toggle, int icon_only)
{
uiStyle *style = layout->root->style;
uiBut *but;
@@ -2306,11 +2308,14 @@ uiLayout *uiLayoutBox(uiLayout *layout)
return (uiLayout *)ui_layout_box(layout, ROUNDBOX);
}
-uiLayout *uiLayoutListBox(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr, PropertyRNA *actprop)
+uiLayout *uiLayoutListBox(uiLayout *layout, uiList *ui_list, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr,
+ PropertyRNA *actprop)
{
uiLayoutItemBx *box = ui_layout_box(layout, LISTBOX);
uiBut *but = box->roundbox;
+ but->custom_data = ui_list;
+
but->rnasearchpoin = *ptr;
but->rnasearchprop = prop;
but->rnapoin = *actptr;
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 5b6a609e4d2..9fbf2fe8898 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -112,7 +112,7 @@ static int panel_aligned(ScrArea *sa, ARegion *ar)
else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS)
return BUT_VERTICAL;
else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW)
- return BUT_VERTICAL;
+ return BUT_VERTICAL;
else if (ELEM3(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS))
return BUT_VERTICAL;
@@ -812,8 +812,8 @@ static void ui_panels_size(ScrArea *sa, ARegion *ar, int *x, int *y)
{
Panel *pa;
int align = panel_aligned(sa, ar);
- int sizex = UI_PANEL_WIDTH;
- int sizey = UI_PANEL_WIDTH;
+ int sizex = 0;
+ int sizey = 0;
/* compute size taken up by panels, for setting in view2d */
for (pa = ar->panels.first; pa; pa = pa->next) {
@@ -834,6 +834,11 @@ static void ui_panels_size(ScrArea *sa, ARegion *ar, int *x, int *y)
}
}
+ if (sizex == 0)
+ sizex = UI_PANEL_WIDTH;
+ if (sizey == 0)
+ sizey = -UI_PANEL_WIDTH;
+
*x = sizex;
*y = sizey;
}
@@ -956,6 +961,25 @@ void uiDrawPanels(const bContext *C, ARegion *ar)
}
}
+void uiScalePanels(ARegion *ar, float new_width)
+{
+ uiBlock *block;
+ uiBut *but;
+
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ if (block->panel) {
+ float fac = new_width / (float)block->panel->sizex;
+ printf("scaled %f\n", fac);
+ block->panel->sizex = new_width;
+
+ for (but = block->buttons.first; but; but = but->next) {
+ but->rect.xmin *= fac;
+ but->rect.xmax *= fac;
+ }
+ }
+ }
+}
+
/* ------------ panel merging ---------------- */
static void check_panel_overlap(ARegion *ar, Panel *panel)
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 57c126c31c5..4a8ad5d24a6 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -651,10 +651,10 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
ofsx = 0; //(but->block->panel) ? but->block->panel->ofsx : 0;
ofsy = 0; //(but->block->panel) ? but->block->panel->ofsy : 0;
- rect_fl.xmin = (but->rect.xmin + but->rect.xmax) * 0.5f + ofsx - (TIP_BORDER_X );
- rect_fl.xmax = rect_fl.xmin + fontw + (TIP_BORDER_X );
- rect_fl.ymax = but->rect.ymin + ofsy - (TIP_BORDER_Y );
- rect_fl.ymin = rect_fl.ymax - fonth - (TIP_BORDER_Y );
+ rect_fl.xmin = (but->rect.xmin + but->rect.xmax) * 0.5f + ofsx - TIP_BORDER_X;
+ rect_fl.xmax = rect_fl.xmin + fontw + TIP_BORDER_X;
+ rect_fl.ymax = but->rect.ymin + ofsy - TIP_BORDER_Y;
+ rect_fl.ymin = rect_fl.ymax - fonth - TIP_BORDER_Y;
#undef TIP_MARGIN_Y
#undef TIP_BORDER_X
@@ -896,8 +896,12 @@ void ui_searchbox_apply(uiBut *but, ARegion *ar)
void ui_searchbox_event(bContext *C, ARegion *ar, uiBut *but, wmEvent *event)
{
uiSearchboxData *data = ar->regiondata;
+ int type = event->type, val = event->val;
- switch (event->type) {
+ if (type == MOUSEPAN)
+ ui_pan_to_scroll(event, &type, &val);
+
+ switch (type) {
case WHEELUPMOUSE:
case UPARROWKEY:
ui_searchbox_select(C, ar, but, -1);
@@ -1527,6 +1531,7 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar)
static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
{
+ uiBut *bt;
int width = UI_ThemeMenuShadowWidth();
int winx, winy;
@@ -1536,7 +1541,6 @@ static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
winx = WM_window_pixels_x(window);
winy = WM_window_pixels_y(window);
- // wm_window_get_size(window, &winx, &winy);
if (block->rect.xmin < width)
block->rect.xmin = width;
@@ -1547,6 +1551,15 @@ static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
block->rect.ymin = width;
if (block->rect.ymax > winy - MENU_TOP)
block->rect.ymax = winy - MENU_TOP;
+
+ /* ensure menu items draw inside left/right boundary */
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ if (bt->rect.xmin < block->rect.xmin)
+ bt->rect.xmin = block->rect.xmin;
+ if (bt->rect.xmax > block->rect.xmax)
+ bt->rect.xmax = block->rect.xmax;
+ }
+
}
void ui_popup_block_scrolltest(uiBlock *block)
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 33f647d1db6..f704ac0e203 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -31,18 +31,16 @@
#include "MEM_guardedalloc.h"
-#include "DNA_anim_types.h"
#include "DNA_dynamicpaint_types.h"
-#include "DNA_key_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "DNA_userdef_types.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "BLI_ghash.h"
#include "BLI_rect.h"
+#include "BLF_api.h"
#include "BLF_translation.h"
#include "BKE_animsys.h"
@@ -59,6 +57,7 @@
#include "BKE_displist.h"
#include "BKE_sca.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "ED_screen.h"
#include "ED_object.h"
@@ -71,11 +70,9 @@
#include "WM_types.h"
#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "interface_intern.h"
-#include "BLF_api.h"
-#include "BLF_translation.h"
-
void UI_template_fix_linking(void)
{
}
@@ -1090,7 +1087,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
// int rb_col; // UNUSED
/* get constraint typeinfo */
- cti = constraint_get_typeinfo(con);
+ cti = BKE_constraint_get_typeinfo(con);
if (cti == NULL) {
/* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
BLI_strncpy(typestr, (con->type == CONSTRAINT_TYPE_NULL) ? "Null" : "Unknown", sizeof(typestr));
@@ -1099,7 +1096,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
BLI_strncpy(typestr, cti->name, sizeof(typestr));
/* determine whether constraint is proxy protected or not */
- if (proxylocked_constraints_owner(ob, pchan))
+ if (BKE_proxylocked_constraints_owner(ob, pchan))
proxy_protected = (con->flag & CONSTRAINT_PROXY_LOCAL) == 0;
else
proxy_protected = 0;
@@ -1161,7 +1158,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
*
* Up/Down buttons should only be shown (or not grayed - todo) if they serve some purpose.
*/
- if (proxylocked_constraints_owner(ob, pchan)) {
+ if (BKE_proxylocked_constraints_owner(ob, pchan)) {
if (con->prev) {
prev_proxylock = (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
}
@@ -2341,437 +2338,195 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam
/************************* List Template **************************/
-
-static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int big)
+static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout,
+ struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon,
+ struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname),
+ int UNUSED(index))
{
- ID *id = NULL;
- int icon;
-
- if (!itemptr->data)
- return rnaicon;
-
- /* try ID, material or texture slot */
- if (RNA_struct_is_ID(itemptr->type)) {
- id = itemptr->id.data;
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
- id = RNA_pointer_get(itemptr, "material").data;
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_TextureSlot)) {
- id = RNA_pointer_get(itemptr, "texture").data;
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_DynamicPaintSurface)) {
- DynamicPaintSurface *surface = (DynamicPaintSurface *)itemptr->data;
-
- if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) return ICON_TEXTURE_SHADED;
- else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) return ICON_OUTLINER_DATA_MESH;
- else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return ICON_FILE_IMAGE;
- }
-
- /* get icon from ID */
- if (id) {
- icon = ui_id_icon_get(C, id, big);
-
- if (icon)
- return icon;
- }
-
- return rnaicon;
-}
-
-static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i,
- int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop, const char *prop_list_id)
-{
- uiBlock *block = uiLayoutGetBlock(layout);
- uiBut *but;
- uiLayout *split, *overlap, *sub, *row;
char *namebuf;
const char *name;
- int icon;
-
- overlap = uiLayoutOverlap(layout);
-
- /* list item behind label & other buttons */
- sub = uiLayoutRow(overlap, FALSE);
-
- but = uiDefButR_prop(block, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, activeprop,
- 0, 0, i, 0, 0, "");
- uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
-
- sub = uiLayoutRow(overlap, FALSE);
-
- /* retrieve icon and name */
- icon = list_item_icon_get(C, itemptr, rnaicon, 0);
- if (icon == ICON_NONE || icon == ICON_DOT)
- icon = 0;
namebuf = RNA_struct_name_get_alloc(itemptr, NULL, 0, NULL);
name = (namebuf) ? namebuf : "";
- /* hardcoded types */
- if (itemptr->type == &RNA_MeshTexturePolyLayer || itemptr->type == &RNA_MeshLoopColorLayer) {
- uiItemL(sub, name, icon);
- uiBlockSetEmboss(block, UI_EMBOSSN);
- uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render",
- 0, 0, 0, 0, 0, NULL);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ /* Simplest one! */
+ switch (ui_list->layout_type) {
+ case UILST_LAYOUT_GRID:
+ uiItemL(layout, "", icon);
+ break;
+ case UILST_LAYOUT_DEFAULT:
+ case UILST_LAYOUT_COMPACT:
+ default:
+ uiItemL(layout, name, icon);
+ break;
}
- else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) {
- uiItemL(sub, name, icon);
- uiBlockSetEmboss(block, UI_EMBOSS);
- uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL);
- }
-#ifdef WITH_FREESTYLE
- else if (RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer) ||
- RNA_struct_is_a(itemptr->type, &RNA_FreestyleLineSet)) {
-#else
- else if (RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
-#endif
- uiItemL(sub, name, icon);
- uiBlockSetEmboss(block, UI_EMBOSS);
- uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0, NULL);
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
- /* provision to draw active node name */
- Material *ma, *manode;
- Scene *scene = CTX_data_scene(C);
- Object *ob = (Object *)ptr->id.data;
- int index = (Material **)itemptr->data - ob->mat;
-
- /* default item with material base name */
- uiItemL(sub, name, icon);
- ma = give_current_material(ob, index + 1);
- if (ma && !BKE_scene_use_new_shading_nodes(scene)) {
- manode = give_node_material(ma);
- if (manode) {
- char str[MAX_ID_NAME + 12];
- BLI_snprintf(str, sizeof(str), IFACE_("Node %s"), manode->id.name + 2);
- uiItemL(sub, str, ui_id_icon_get(C, &manode->id, 1));
- }
- else if (ma->use_nodes) {
- uiItemL(sub, IFACE_("Node <none>"), ICON_NONE);
- }
- }
- }
- else if (itemptr->type == &RNA_ShapeKey) {
- Object *ob = (Object *)activeptr->data;
- Key *key = (Key *)itemptr->id.data;
- KeyBlock *kb = (KeyBlock *)itemptr->data;
-
- split = uiLayoutSplit(sub, 0.66f, FALSE);
-
- uiItemL(split, name, icon);
-
- uiBlockSetEmboss(block, UI_EMBOSSN);
- row = uiLayoutRow(split, TRUE);
- if (i == 0 || (key->type != KEY_RELATIVE)) uiItemL(row, "", ICON_NONE);
- else uiItemR(row, itemptr, "value", 0, "", ICON_NONE);
- uiItemR(row, itemptr, "mute", 0, "", ICON_NONE);
-
- if ((kb->flag & KEYBLOCK_MUTE) ||
- (ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH)))
- {
- uiLayoutSetActive(row, FALSE);
- }
- uiBlockSetEmboss(block, UI_EMBOSS);
- }
- else if (itemptr->type == &RNA_VertexGroup) {
- bDeformGroup *dg = (bDeformGroup *)itemptr->data;
- uiItemL(sub, name, icon);
- /* RNA does not allow nice lock icons, use lower level buttons */
-#if 0
- uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "lock_weight", 0, 0, 0, 0, 0, NULL);
-#else
- uiBlockSetEmboss(block, UI_EMBOSSN);
- uiDefIconButBitC(block, TOG, DG_LOCK_WEIGHT, 0, (dg->flag & DG_LOCK_WEIGHT) ? ICON_LOCKED : ICON_UNLOCKED,
- 0, 0, UI_UNIT_X, UI_UNIT_Y, &dg->flag, 0, 0, 0, 0,
- TIP_("Maintain relative weights while painting"));
- uiBlockSetEmboss(block, UI_EMBOSS);
-#endif
- }
- else if (itemptr->type == &RNA_KeyingSetPath) {
- KS_Path *ksp = (KS_Path *)itemptr->data;
-
- /* icon needs to be the type of ID which is currently active */
- RNA_enum_icon_from_value(id_type_items, ksp->idtype, &icon);
-
- /* nothing else special to do... */
- uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
- }
- else if (itemptr->type == &RNA_DynamicPaintSurface) {
- char name_final[96];
- const char *enum_name;
- PropertyRNA *prop = RNA_struct_find_property(itemptr, "surface_type");
- DynamicPaintSurface *surface = (DynamicPaintSurface *)itemptr->data;
-
- RNA_property_enum_name(C, itemptr, prop, RNA_property_enum_get(itemptr, prop), &enum_name);
-
- BLI_snprintf(name_final, sizeof(name_final), "%s (%s)", name, enum_name);
- uiItemL(sub, name_final, icon);
- if (dynamicPaint_surfaceHasColorPreview(surface)) {
- uiBlockSetEmboss(block, UI_EMBOSSN);
- uiDefIconButR(block, OPTION, 0,
- (surface->flags & MOD_DPAINT_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON,
- 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "show_preview", 0, 0, 0, 0, 0, NULL);
- uiBlockSetEmboss(block, UI_EMBOSS);
- }
- uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "is_active", i, 0, 0, 0, 0, NULL);
- }
- else if (itemptr->type == &RNA_MovieTrackingObject) {
- MovieTrackingObject *tracking_object = (MovieTrackingObject *)itemptr->data;
-
- split = uiLayoutSplit(sub, 0.75f, FALSE);
- if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- uiItemL(split, name, ICON_CAMERA_DATA);
- }
- else {
- uiItemL(split, name, ICON_OBJECT_DATA);
- }
- }
- else if (itemptr->type == &RNA_MaskLayer) {
- split = uiLayoutRow(sub, FALSE);
-
- uiItemL(split, name, icon);
-
- uiBlockSetEmboss(block, UI_EMBOSSN);
- row = uiLayoutRow(split, TRUE);
- uiItemR(row, itemptr, "alpha", 0, "", ICON_NONE);
- uiItemR(row, itemptr, "hide", 0, "", ICON_NONE);
- uiItemR(row, itemptr, "hide_select", 0, "", ICON_NONE);
- uiItemR(row, itemptr, "hide_render", 0, "", ICON_NONE);
-
- uiBlockSetEmboss(block, UI_EMBOSS);
- }
-
- /* There is a last chance to display custom controls (in addition to the name/label):
- * If the given item property group features a string property named as prop_list,
- * this tries to add controls for all properties of the item listed in that string property.
- * (colon-separated names).
- *
- * This is especially useful for python. E.g., if you list a collection of this property
- * group:
- *
- * class TestPropertyGroup(bpy.types.PropertyGroup):
- * bool = BoolProperty(default=False)
- * integer = IntProperty()
- * string = StringProperty()
- *
- * # A string of all identifiers (colon-separated) which property's controls should be
- * # displayed in a template_list.
- * template_list_controls = StringProperty(default="integer:bool:string", options={"HIDDEN"})
- *
- * ... you'll get a numfield for the integer prop, a check box for the bool prop, and a textfield
- * for the string prop, after the name of each item of the collection.
- */
- else if (prop_list_id) {
- row = uiLayoutRow(sub, TRUE);
- uiItemL(row, name, icon);
-
- /* XXX: Check, as sometimes we get an itemptr looking like
- * {id = {data = 0x0}, type = 0x0, data = 0x0}
- * which would obviously produce a sigsev... */
- if (itemptr->type) {
- /* If the special property is set for the item, and it is a collection... */
- PropertyRNA *prop_list = RNA_struct_find_property(itemptr, prop_list_id);
-
- if (prop_list && RNA_property_type(prop_list) == PROP_STRING) {
- int prop_names_len;
- char *prop_names = RNA_property_string_get_alloc(itemptr, prop_list, NULL, 0, &prop_names_len);
- char *prop_names_end = prop_names + prop_names_len;
- char *id = prop_names;
- char *id_next;
- while (id < prop_names_end) {
- if ((id_next = strchr(id, ':'))) *id_next++ = '\0';
- else id_next = prop_names_end;
- uiItemR(row, itemptr, id, 0, NULL, ICON_NONE);
- id = id_next;
- }
- MEM_freeN(prop_names);
- }
- }
- }
-
- else
- uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
-
/* free name */
if (namebuf) {
MEM_freeN(namebuf);
}
}
-void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr,
- const char *activepropname, const char *prop_list, int rows, int maxrows, int listtype)
+void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id,
+ PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr,
+ const char *active_propname, int rows, int maxrows, int layout_type)
{
+ uiListType *ui_list_type;
+ uiList *ui_list = NULL;
+ ARegion *ar;
+ uiListDrawItemFunc draw_item;
+
PropertyRNA *prop = NULL, *activeprop;
PropertyType type, activetype;
StructRNA *ptype;
- uiLayout *box, *row, *col;
- uiBlock *block;
+ uiLayout *box, *row, *col, *sub, *overlap;
+ uiBlock *block, *subblock;
uiBut *but;
- Panel *pa;
- const char *name;
+
+ char ui_list_id[UI_MAX_NAME_STR];
char numstr[32];
- int rnaicon = 0, icon = 0, i = 0, activei = 0, len = 0, items, found, min, max;
+ int rnaicon = ICON_NONE, icon = ICON_NONE;
+ int i = 0, activei = 0;
+ int len = 0;
+ int items;
+ int found;
+ int min, max;
/* validate arguments */
block = uiLayoutGetBlock(layout);
- pa = block->panel;
- if (!pa) {
- RNA_warning("Only works inside a panel");
+ if (!active_dataptr->data) {
+ RNA_warning("No active data");
return;
}
- if (!activeptr->data)
- return;
-
- if (ptr->data) {
- prop = RNA_struct_find_property(ptr, propname);
+ if (dataptr->data) {
+ prop = RNA_struct_find_property(dataptr, propname);
if (!prop) {
- RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ RNA_warning("Property not found: %s.%s", RNA_struct_identifier(dataptr->type), propname);
return;
}
}
- activeprop = RNA_struct_find_property(activeptr, activepropname);
+ activeprop = RNA_struct_find_property(active_dataptr, active_propname);
if (!activeprop) {
- RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), activepropname);
+ RNA_warning("Property not found: %s.%s", RNA_struct_identifier(active_dataptr->type), active_propname);
return;
}
if (prop) {
type = RNA_property_type(prop);
if (type != PROP_COLLECTION) {
- RNA_warning("uiExpected collection property");
+ RNA_warning("Expected a collection data property");
return;
}
}
activetype = RNA_property_type(activeprop);
if (activetype != PROP_INT) {
- RNA_warning("Expected integer property");
+ RNA_warning("Expected an integer active data property");
return;
}
/* get icon */
- if (ptr->data && prop) {
- ptype = RNA_property_pointer_type(ptr, prop);
+ if (dataptr->data && prop) {
+ ptype = RNA_property_pointer_type(dataptr, prop);
rnaicon = RNA_struct_ui_icon(ptype);
}
/* get active data */
- activei = RNA_property_int_get(activeptr, activeprop);
-
- if (listtype == 'i') {
- box = uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
- col = uiLayoutColumn(box, TRUE);
- row = uiLayoutRow(col, FALSE);
+ activei = RNA_property_int_get(active_dataptr, activeprop);
- if (ptr->data && prop) {
- /* create list items */
- RNA_PROP_BEGIN (ptr, itemptr, prop)
- {
- /* create button */
- if (!(i % 9))
- row = uiLayoutRow(col, FALSE);
+ /* Find the uiList type. */
+ ui_list_type = WM_uilisttype_find(listtype_name, FALSE);
- icon = list_item_icon_get(C, &itemptr, rnaicon, 1);
- but = uiDefIconButR_prop(block, LISTROW, 0, icon, 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr,
- activeprop, 0, 0, i, 0, 0, "");
- uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
-
-
- i++;
+ if (ui_list_type == NULL) {
+ RNA_warning("List type %s not found", listtype_name);
+ return;
}
- RNA_PROP_END;
- }
- }
- else if (listtype == 'c') {
- /* compact layout */
- row = uiLayoutRow(layout, TRUE);
+ draw_item = ui_list_type->draw_item ? ui_list_type->draw_item : uilist_draw_item_default;
- if (ptr->data && prop) {
- /* create list items */
- RNA_PROP_BEGIN (ptr, itemptr, prop)
- {
- found = (activei == i);
+ /* Find or add the uiList to the current Region. */
+ /* We tag the list id with the list type... */
+ BLI_snprintf(ui_list_id, sizeof(ui_list_id), "%s_%s", ui_list_type->idname, list_id ? list_id : "");
- if (found) {
- /* create button */
- name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
- icon = list_item_icon_get(C, &itemptr, rnaicon, 0);
- uiItemL(row, (name) ? name : "", icon);
+ ar = CTX_wm_region(C);
+ ui_list = BLI_findstring(&ar->ui_lists, ui_list_id, offsetof(uiList, list_id));
- if (name) {
- MEM_freeN((void *)name);
+ if (!ui_list) {
+ ui_list = MEM_callocN(sizeof(uiList), __func__);
+ BLI_strncpy(ui_list->list_id, ui_list_id, sizeof(ui_list->list_id));
+ BLI_addtail(&ar->ui_lists, ui_list);
}
- }
- i++;
- }
- RNA_PROP_END;
- }
-
- /* if not found, add in dummy button */
- if (i == 0)
- uiItemL(row, "", ICON_NONE);
+ /* Because we can't actually pass type across save&load... */
+ ui_list->type = ui_list_type;
+ ui_list->layout_type = layout_type;
- /* next/prev button */
- BLI_snprintf(numstr, sizeof(numstr), "%d :", i);
- but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, activeptr,
- activeprop, 0, 0, 0, 0, 0, "");
- if (i == 0)
- uiButSetFlag(but, UI_BUT_DISABLED);
- }
- else {
+ switch (layout_type) {
+ case UILST_LAYOUT_DEFAULT:
/* default rows */
if (rows == 0)
rows = 5;
if (maxrows == 0)
maxrows = 5;
- if (pa->list_grip_size != 0)
- rows = pa->list_grip_size;
+ if (ui_list->list_grip_size != 0)
+ rows = ui_list->list_grip_size;
/* layout */
- box = uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
+ box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
row = uiLayoutRow(box, FALSE);
col = uiLayoutColumn(row, TRUE);
/* init numbers */
- RNA_property_int_range(activeptr, activeprop, &min, &max);
+ RNA_property_int_range(active_dataptr, activeprop, &min, &max);
if (prop)
- len = RNA_property_collection_length(ptr, prop);
+ len = RNA_property_collection_length(dataptr, prop);
items = CLAMPIS(len, rows, MAX2(rows, maxrows));
/* if list length changes and active is out of view, scroll to it */
- if (pa->list_last_len != len)
- if ((activei < pa->list_scroll || activei >= pa->list_scroll + items))
- pa->list_scroll = activei;
+ if ((ui_list->list_last_len != len) &&
+ (activei < ui_list->list_scroll || activei >= ui_list->list_scroll + items)) {
+ ui_list->list_scroll = activei;
+ }
- pa->list_scroll = MIN2(pa->list_scroll, len - items);
- pa->list_scroll = MAX2(pa->list_scroll, 0);
- pa->list_size = items;
- pa->list_last_len = len;
+ ui_list->list_scroll = min_ii(ui_list->list_scroll, len - items);
+ ui_list->list_scroll = max_ii(ui_list->list_scroll, 0);
+ ui_list->list_size = items;
+ ui_list->list_last_len = len;
- if (ptr->data && prop) {
+ if (dataptr->data && prop) {
/* create list items */
- RNA_PROP_BEGIN (ptr, itemptr, prop)
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
{
- if (i >= pa->list_scroll && i < pa->list_scroll + items)
- list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activeprop, prop_list);
+ if (i >= ui_list->list_scroll && i < ui_list->list_scroll + items) {
+ subblock = uiLayoutGetBlock(col);
+ overlap = uiLayoutOverlap(col);
+
+ /* list item behind label & other buttons */
+ sub = uiLayoutRow(overlap, FALSE);
+
+ but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ active_dataptr, activeprop, 0, 0, i, 0, 0, "");
+ uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
+
+ sub = uiLayoutRow(overlap, FALSE);
+ icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+ if (icon == ICON_DOT)
+ icon = ICON_NONE;
+ draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+ }
i++;
}
RNA_PROP_END;
}
/* add dummy buttons to fill space */
- while (i < pa->list_scroll + items) {
- if (i >= pa->list_scroll)
+ while (i < ui_list->list_scroll + items) {
+ if (i >= ui_list->list_scroll)
uiItemL(col, "", ICON_NONE);
i++;
}
@@ -2779,9 +2534,75 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *
/* add scrollbar */
if (len > items) {
col = uiLayoutColumn(row, FALSE);
- uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &pa->list_scroll,
+ uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &ui_list->list_scroll,
0, len - items, items, 0, "");
}
+ break;
+ case UILST_LAYOUT_COMPACT:
+ row = uiLayoutRow(layout, TRUE);
+
+ if (dataptr->data && prop) {
+ /* create list items */
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
+ {
+ found = (activei == i);
+
+ if (found) {
+ icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+ if (icon == ICON_DOT)
+ icon = ICON_NONE;
+ draw_item(ui_list, C, row, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+ }
+
+ i++;
+}
+ RNA_PROP_END;
+ }
+
+ /* if list is empty, add in dummy button */
+ if (i == 0)
+ uiItemL(row, "", ICON_NONE);
+
+ /* next/prev button */
+ BLI_snprintf(numstr, sizeof(numstr), "%d :", i);
+ but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y,
+ active_dataptr, activeprop, 0, 0, 0, 0, 0, "");
+ if (i == 0)
+ uiButSetFlag(but, UI_BUT_DISABLED);
+ break;
+ case UILST_LAYOUT_GRID:
+ box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
+ col = uiLayoutColumn(box, TRUE);
+ row = uiLayoutRow(col, FALSE);
+
+ if (dataptr->data && prop) {
+ /* create list items */
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
+ {
+ /* create button */
+ if (!(i % 9))
+ row = uiLayoutRow(col, FALSE);
+
+ subblock = uiLayoutGetBlock(row);
+ overlap = uiLayoutOverlap(row);
+
+ /* list item behind label & other buttons */
+ sub = uiLayoutRow(overlap, FALSE);
+
+ but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ active_dataptr, activeprop, 0, 0, i, 0, 0, "");
+ uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
+
+ sub = uiLayoutRow(overlap, FALSE);
+
+ icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+ draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+
+ i++;
+ }
+ RNA_PROP_END;
+ }
+ break;
}
}
@@ -3095,7 +2916,7 @@ void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char
colorspace_settings_ptr = RNA_property_pointer_get(ptr, prop);
- uiItemL(layout, "Color Space:", ICON_NONE);
+ uiItemL(layout, "Input Color Space:", ICON_NONE);
uiItemR(layout, &colorspace_settings_ptr, "name", 0, "", ICON_NONE);
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 4687647223a..e4ad3a4f73b 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1324,11 +1324,13 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* icons default draw 0.8f x height */
rect->xmin += (int)(0.8f * BLI_rcti_size_y(rect));
- if (but->editstr || (but->flag & UI_TEXT_LEFT))
- rect->xmin += 0.4f * U.widget_unit;
+ if (but->editstr || (but->flag & UI_TEXT_LEFT)) {
+ rect->xmin += (0.4f * U.widget_unit) / but->block->aspect;
+ }
+ }
+ else if ((but->flag & UI_TEXT_LEFT)) {
+ rect->xmin += (0.4f * U.widget_unit) / but->block->aspect;
}
- else if ((but->flag & UI_TEXT_LEFT))
- rect->xmin += 0.4f * U.widget_unit;
/* always draw text for textbutton cursor */
widget_draw_text(fstyle, wcol, but, rect);
@@ -2319,7 +2321,7 @@ void ui_draw_link_bezier(const rcti *rect)
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, coord_array);
- glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL);
+ glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL + 1);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);
@@ -3467,14 +3469,14 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
if (iconid) {
float height, aspect;
int xs = rect->xmin + 0.2f * UI_UNIT_X;
- int ys = 1 + (rect->ymin + rect->ymax - UI_DPI_ICON_SIZE) / 2;
+ int ys = rect->ymin + 0.1f * BLI_rcti_size_y(rect);
/* icons are 80% of height of button (16 pixels inside 20 height) */
height = 0.8f * BLI_rcti_size_y(rect);
aspect = ICON_DEFAULT_HEIGHT / height;
-
+
glEnable(GL_BLEND);
- UI_icon_draw_aspect(xs, ys, iconid, aspect, 0.5f); /* XXX scale weak get from fstyle? */
+ UI_icon_draw_aspect(xs, ys, iconid, aspect, 1.0f); /* XXX scale weak get from fstyle? */
glDisable(GL_BLEND);
}
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index fd84c1fd4c4..361bdfacbb2 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -364,8 +364,14 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->syntaxc; break;
case TH_SYNTAX_L:
cp = ts->syntaxl; break;
+ case TH_SYNTAX_D:
+ cp = ts->syntaxd; break;
+ case TH_SYNTAX_R:
+ cp = ts->syntaxr; break;
case TH_SYNTAX_N:
cp = ts->syntaxn; break;
+ case TH_SYNTAX_S:
+ cp = ts->syntaxs; break;
case TH_NODE:
cp = ts->syntaxl; break;
@@ -879,8 +885,8 @@ void ui_theme_init_default(void)
rgba_char_args_set_fl(btheme->tima.preview_stitch_vert, 0.0, 0.0, 1.0, 0.2);
rgba_char_args_set_fl(btheme->tima.preview_stitch_stitchable, 0.0, 1.0, 0.0, 1.0);
rgba_char_args_set_fl(btheme->tima.preview_stitch_unstitchable, 1.0, 0.0, 0.0, 1.0);
- rgba_char_args_set_fl(btheme->tima.preview_stitch_active, 0.886, 0.824, 0.765, 0.140);
-
+ rgba_char_args_set_fl(btheme->tima.preview_stitch_active, 0.886, 0.824, 0.765, 0.140);
+
/* space text */
btheme->text = btheme->tv3d;
rgba_char_args_set(btheme->text.back, 153, 153, 153, 255);
@@ -890,10 +896,13 @@ void ui_theme_init_default(void)
/* syntax highlighting */
rgba_char_args_set(btheme->text.syntaxn, 0, 0, 200, 255); /* Numbers Blue*/
- rgba_char_args_set(btheme->text.syntaxl, 100, 0, 0, 255); /* Strings red */
- rgba_char_args_set(btheme->text.syntaxc, 0, 100, 50, 255); /* Comments greenish */
- rgba_char_args_set(btheme->text.syntaxv, 95, 95, 0, 255); /* Special */
- rgba_char_args_set(btheme->text.syntaxb, 128, 0, 80, 255); /* Builtin, red-purple */
+ rgba_char_args_set(btheme->text.syntaxl, 100, 0, 0, 255); /* Strings Red */
+ rgba_char_args_set(btheme->text.syntaxc, 0, 100, 50, 255); /* Comments Greenish */
+ rgba_char_args_set(btheme->text.syntaxv, 95, 95, 0, 255); /* Special Yellow*/
+ rgba_char_args_set(btheme->text.syntaxd, 50, 0, 140, 255); /* Decorator/Preprocessor Dir. Blue-purple */
+ rgba_char_args_set(btheme->text.syntaxr, 140, 60, 0, 255); /* Reserved Orange*/
+ rgba_char_args_set(btheme->text.syntaxb, 128, 0, 80, 255); /* Builtin Red-purple */
+ rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Grey (mix between fg/bg) */
/* space oops */
btheme->toops = btheme->tv3d;
@@ -2106,6 +2115,15 @@ void init_userdef_do_versions(void)
}
}
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 266, 4)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ rgba_char_args_set(btheme->text.syntaxd, 50, 0, 140, 255); /* Decorator/Preprocessor Dir. Blue-purple */
+ rgba_char_args_set(btheme->text.syntaxr, 140, 60, 0, 255); /* Reserved Orange */
+ rgba_char_args_set(btheme->text.syntaxs, 76, 76, 76, 255); /* Grey (mix between fg/bg) */
+ }
+ }
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 190d90b3c36..d0d631e14a5 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -60,6 +60,8 @@
#include "interface_intern.h"
+static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_scrollers);
+
/* *********************************************************************** */
/* XXX still unresolved: scrolls hide/unhide vs region mask handling */
@@ -73,15 +75,15 @@
*/
static int view2d_scroll_mapped(int scroll)
{
- if (scroll & V2D_SCROLL_HORIZONTAL_HIDE)
+ if (scroll & V2D_SCROLL_HORIZONTAL_FULLR)
scroll &= ~(V2D_SCROLL_HORIZONTAL);
- if (scroll & V2D_SCROLL_VERTICAL_HIDE)
+ if (scroll & V2D_SCROLL_VERTICAL_FULLR)
scroll &= ~(V2D_SCROLL_VERTICAL);
return scroll;
}
/* called each time cur changes, to dynamically update masks */
-static void view2d_masks(View2D *v2d)
+static void view2d_masks(View2D *v2d, int check_scrollers)
{
int scroll;
@@ -90,19 +92,26 @@ static void view2d_masks(View2D *v2d)
v2d->mask.xmax = v2d->winx - 1; /* -1 yes! masks are pixels */
v2d->mask.ymax = v2d->winy - 1;
-#if 0
- /* XXX see above */
- v2d->scroll &= ~(V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_VERTICAL_HIDE);
- /* check size if: */
- if (v2d->scroll & V2D_SCROLL_HORIZONTAL)
- if (!(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL))
- if (BLI_rctf_size_x(&v2d->tot) <= BLI_rcti_size_x(&v2d->cur))
- v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
- if (v2d->scroll & V2D_SCROLL_VERTICAL)
- if (!(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL))
- if (BLI_rctf_size_y(&v2d->tot) <= BLI_rctf_size_y(&v2d->cur))
- v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
-#endif
+ if (check_scrollers) {
+ /* check size if hiding flag is set: */
+ if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) {
+ if (!(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL)) {
+ if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur))
+ v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR;
+ else
+ v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR;
+ }
+ }
+ if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) {
+ if (!(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL)) {
+ if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur))
+ v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR;
+ else
+ v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR;
+ }
+ }
+ }
+
scroll = view2d_scroll_mapped(v2d->scroll);
/* scrollers shrink mask area, but should be based off regionsize
@@ -126,8 +135,8 @@ static void view2d_masks(View2D *v2d)
}
/* horizontal scroller */
- if (scroll & (V2D_SCROLL_BOTTOM | V2D_SCROLL_BOTTOM_O)) {
- /* on bottom edge of region (V2D_SCROLL_BOTTOM_O is outliner, the other is for standard) */
+ if (scroll & (V2D_SCROLL_BOTTOM)) {
+ /* on bottom edge of region */
v2d->hor = v2d->mask;
v2d->hor.ymax = V2D_SCROLL_HEIGHT;
v2d->mask.ymin = v2d->hor.ymax + 1;
@@ -142,8 +151,8 @@ static void view2d_masks(View2D *v2d)
/* adjust vertical scroller if there's a horizontal scroller, to leave corner free */
if (scroll & V2D_SCROLL_VERTICAL) {
/* just set y min/max for vertical scroller to y min/max of mask as appropriate */
- if (scroll & (V2D_SCROLL_BOTTOM | V2D_SCROLL_BOTTOM_O)) {
- /* on bottom edge of region (V2D_SCROLL_BOTTOM_O is outliner, the other is for standard) */
+ if (scroll & (V2D_SCROLL_BOTTOM)) {
+ /* on bottom edge of region */
v2d->vert.ymin = v2d->mask.ymin;
}
else if (scroll & V2D_SCROLL_TOP) {
@@ -152,7 +161,6 @@ static void view2d_masks(View2D *v2d)
}
}
}
-
}
/* Refresh and Validation */
@@ -165,163 +173,173 @@ static void view2d_masks(View2D *v2d)
*/
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
{
- short tot_changed = 0, init = 0;
+ short tot_changed = 0, do_init;
uiStyle *style = UI_GetStyle();
- /* initialize data if there is a need for such */
- if ((v2d->flag & V2D_IS_INITIALISED) == 0) {
- /* set initialized flag so that View2D doesn't get reinitialised next time again */
- v2d->flag |= V2D_IS_INITIALISED;
-
- init = 1;
+ do_init = (v2d->flag & V2D_IS_INITIALISED) == 0;
- /* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */
- switch (type) {
- /* 'standard view' - optimum setup for 'standard' view behavior,
- * that should be used new views as basis for their
- * own unique View2D settings, which should be used instead of this in most cases...
+ /* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */
+ switch (type) {
+ /* 'standard view' - optimum setup for 'standard' view behavior,
+ * that should be used new views as basis for their
+ * own unique View2D settings, which should be used instead of this in most cases...
+ */
+ case V2D_COMMONVIEW_STANDARD:
+ {
+ /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
+ v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM);
+ v2d->minzoom = 0.01f;
+ v2d->maxzoom = 1000.0f;
+
+ /* tot rect and cur should be same size, and aligned using 'standard' OpenGL coordinates for now
+ * - region can resize 'tot' later to fit other data
+ * - keeptot is only within bounds, as strict locking is not that critical
+ * - view is aligned for (0,0) -> (winx-1, winy-1) setup
*/
- case V2D_COMMONVIEW_STANDARD:
- {
- /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
- v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM);
- v2d->minzoom = 0.01f;
- v2d->maxzoom = 1000.0f;
-
- /* tot rect and cur should be same size, and aligned using 'standard' OpenGL coordinates for now
- * - region can resize 'tot' later to fit other data
- * - keeptot is only within bounds, as strict locking is not that critical
- * - view is aligned for (0,0) -> (winx-1, winy-1) setup
- */
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
- v2d->keeptot = V2D_KEEPTOT_BOUNDS;
-
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
+ v2d->keeptot = V2D_KEEPTOT_BOUNDS;
+
+ if (do_init) {
v2d->tot.xmin = v2d->tot.ymin = 0.0f;
v2d->tot.xmax = (float)(winx - 1);
v2d->tot.ymax = (float)(winy - 1);
v2d->cur = v2d->tot;
-
- /* scrollers - should we have these by default? */
- /* XXX for now, we don't override this, or set it either! */
}
- break;
+ /* scrollers - should we have these by default? */
+ /* XXX for now, we don't override this, or set it either! */
+ }
+ break;
+
+ /* 'list/channel view' - zoom, aspect ratio, and alignment restrictions are set here */
+ case V2D_COMMONVIEW_LIST:
+ {
+ /* zoom + aspect ratio are locked */
+ v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ v2d->minzoom = v2d->maxzoom = 1.0f;
- /* 'list/channel view' - zoom, aspect ratio, and alignment restrictions are set here */
- case V2D_COMMONVIEW_LIST:
- {
- /* zoom + aspect ratio are locked */
- v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- v2d->minzoom = v2d->maxzoom = 1.0f;
-
- /* tot rect has strictly regulated placement, and must only occur in +/- quadrant */
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
- v2d->keeptot = V2D_KEEPTOT_STRICT;
- tot_changed = 1;
-
- /* scroller settings are currently not set here... that is left for regions... */
- }
- break;
-
- /* 'stack view' - practically the same as list/channel view, except is located in the pos y half instead.
- * zoom, aspect ratio, and alignment restrictions are set here */
- case V2D_COMMONVIEW_STACK:
- {
- /* zoom + aspect ratio are locked */
- v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- v2d->minzoom = v2d->maxzoom = 1.0f;
-
- /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
- v2d->keeptot = V2D_KEEPTOT_STRICT;
- tot_changed = 1;
-
- /* scroller settings are currently not set here... that is left for regions... */
- }
- break;
+ /* tot rect has strictly regulated placement, and must only occur in +/- quadrant */
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+ v2d->keeptot = V2D_KEEPTOT_STRICT;
+ tot_changed = do_init;
+
+ /* scroller settings are currently not set here... that is left for regions... */
+ }
+ break;
+
+ /* 'stack view' - practically the same as list/channel view, except is located in the pos y half instead.
+ * zoom, aspect ratio, and alignment restrictions are set here */
+ case V2D_COMMONVIEW_STACK:
+ {
+ /* zoom + aspect ratio are locked */
+ v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ v2d->minzoom = v2d->maxzoom = 1.0f;
+
+ /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
+ v2d->keeptot = V2D_KEEPTOT_STRICT;
+ tot_changed = do_init;
+
+ /* scroller settings are currently not set here... that is left for regions... */
+ }
+ break;
+
+ /* 'header' regions - zoom, aspect ratio, alignment, and panning restrictions are set here */
+ case V2D_COMMONVIEW_HEADER:
+ {
+ /* zoom + aspect ratio are locked */
+ v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ v2d->minzoom = v2d->maxzoom = 1.0f;
+
+ if (do_init) {
+ v2d->tot.xmin = 0.0f;
+ v2d->tot.xmax = winx;
+ v2d->tot.ymin = 0.0f;
+ v2d->tot.ymax = winy;
+ v2d->cur = v2d->tot;
- /* 'header' regions - zoom, aspect ratio, alignment, and panning restrictions are set here */
- case V2D_COMMONVIEW_HEADER:
- {
- /* zoom + aspect ratio are locked */
- v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- v2d->minzoom = v2d->maxzoom = 1.0f;
v2d->min[0] = v2d->max[0] = (float)(winx - 1);
v2d->min[1] = v2d->max[1] = (float)(winy - 1);
-
- /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
- v2d->keeptot = V2D_KEEPTOT_STRICT;
- tot_changed = 1;
-
- /* panning in y-axis is prohibited */
- v2d->keepofs = V2D_LOCKOFS_Y;
-
- /* absolutely no scrollers allowed */
- v2d->scroll = 0;
-
}
- break;
+ /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
+ v2d->keeptot = V2D_KEEPTOT_STRICT;
+ tot_changed = do_init;
+
+ /* panning in y-axis is prohibited */
+ v2d->keepofs = V2D_LOCKOFS_Y;
+
+ /* absolutely no scrollers allowed */
+ v2d->scroll = 0;
+
+ }
+ break;
+
+ /* panels view, with horizontal/vertical align */
+ case V2D_COMMONVIEW_PANELS_UI:
+ {
- /* panels view, with horizontal/vertical align */
- case V2D_COMMONVIEW_PANELS_UI:
- {
+ /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
+ v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM | V2D_KEEPZOOM);
+ v2d->minzoom = 0.5f;
+ v2d->maxzoom = 2.0f;
+
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+ v2d->keeptot = V2D_KEEPTOT_BOUNDS;
+
+ /* note, scroll is being flipped in ED_region_panels() drawing */
+ v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+ v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
+
+ if (do_init) {
float panelzoom = (style) ? style->panelzoom : 1.0f;
+ float scrolw = v2d->scroll & V2D_SCROLL_RIGHT ? V2D_SCROLL_WIDTH : 0.0f;
- /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
- v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM | V2D_KEEPZOOM);
- v2d->minzoom = 0.5f;
- v2d->maxzoom = 2.0f;
- //tot_changed = 1;
-
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
- v2d->keeptot = V2D_KEEPTOT_BOUNDS;
-
- v2d->scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
- v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
- v2d->scroll &= ~V2D_SCROLL_VERTICAL_HIDE;
-
v2d->tot.xmin = 0.0f;
- v2d->tot.xmax = winx;
+ v2d->tot.xmax = winx - scrolw;
v2d->tot.ymax = 0.0f;
v2d->tot.ymin = -winy;
v2d->cur.xmin = 0.0f;
- /* bad workaround for keeping zoom level with scrollers */
- v2d->cur.xmax = (winx - V2D_SCROLL_WIDTH) * panelzoom;
+ v2d->cur.xmax = (winx) * panelzoom - scrolw;
v2d->cur.ymax = 0.0f;
v2d->cur.ymin = (-winy) * panelzoom;
}
- break;
-
- /* other view types are completely defined using their own settings already */
- default:
- /* we don't do anything here, as settings should be fine, but just make sure that rect */
- break;
}
+ break;
+
+ /* other view types are completely defined using their own settings already */
+ default:
+ /* we don't do anything here, as settings should be fine, but just make sure that rect */
+ break;
}
+ /* set initialized flag so that View2D doesn't get reinitialised next time again */
+ v2d->flag |= V2D_IS_INITIALISED;
+
/* store view size */
v2d->winx = winx;
v2d->winy = winy;
- /* set masks */
- view2d_masks(v2d);
+ /* set masks (always do), but leave scroller scheck to totrect_set */
+ view2d_masks(v2d, 0);
/* set 'tot' rect before setting cur? */
- if (tot_changed)
- UI_view2d_totRect_set_resize(v2d, winx, winy, !init);
+ /* XXX confusing stuff here still - I made this function not check scroller hide - that happens in totrect_set */
+ if (tot_changed)
+ UI_view2d_totRect_set_resize(v2d, winx, winy, !do_init);
else
- UI_view2d_curRect_validate_resize(v2d, !init);
+ ui_view2d_curRect_validate_resize(v2d, !do_init, 0);
+
}
/* Ensure View2D rects remain in a viable configuration
* - cur is not allowed to be: larger than max, smaller than min, or outside of tot
*/
// XXX pre2.5 -> this used to be called test_view2d()
-void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
+static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_scrollers)
{
float totwidth, totheight, curwidth, curheight, width, height;
float winx, winy;
@@ -715,12 +733,12 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
}
/* set masks */
- view2d_masks(v2d);
+ view2d_masks(v2d, mask_scrollers);
}
void UI_view2d_curRect_validate(View2D *v2d)
{
- UI_view2d_curRect_validate_resize(v2d, 0);
+ ui_view2d_curRect_validate_resize(v2d, 0, 1);
}
/* ------------------ */
@@ -844,7 +862,7 @@ void UI_view2d_curRect_reset(View2D *v2d)
/* Change the size of the maximum viewable area (i.e. 'tot' rect) */
void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, int resize)
{
- int scroll = view2d_scroll_mapped(v2d->scroll);
+// int scroll = view2d_scroll_mapped(v2d->scroll);
/* don't do anything if either value is 0 */
width = abs(width);
@@ -853,10 +871,10 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, int resize
/* hrumf! */
/* XXX: there are work arounds for this in the panel and file browse code. */
/* round to int, because this is called with width + V2D_SCROLL_WIDTH */
- if (scroll & V2D_SCROLL_HORIZONTAL)
- width -= (int)V2D_SCROLL_WIDTH;
- if (scroll & V2D_SCROLL_VERTICAL)
- height -= (int)V2D_SCROLL_HEIGHT;
+// if (scroll & V2D_SCROLL_HORIZONTAL)
+// width -= (int)V2D_SCROLL_WIDTH;
+// if (scroll & V2D_SCROLL_VERTICAL)
+// height -= (int)V2D_SCROLL_HEIGHT;
if (ELEM(0, width, height)) {
if (G.debug & G_DEBUG)
@@ -903,12 +921,21 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, int resize
}
/* make sure that 'cur' rect is in a valid state as a result of these changes */
- UI_view2d_curRect_validate_resize(v2d, resize);
+ ui_view2d_curRect_validate_resize(v2d, resize, 1);
+
}
void UI_view2d_totRect_set(View2D *v2d, int width, int height)
{
+ int scroll = view2d_scroll_mapped(v2d->scroll);
+
UI_view2d_totRect_set_resize(v2d, width, height, 0);
+
+ /* solve bad recursion... if scroller state changed, mask is different, so you get different rects */
+ if (scroll != view2d_scroll_mapped(v2d->scroll)) {
+ UI_view2d_totRect_set_resize(v2d, width, height, 0);
+ }
+
}
int UI_view2d_tab_set(View2D *v2d, int tab)
@@ -1494,15 +1521,6 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d,
CLAMP(scrollers->hor_min, hor.xmin, hor.xmax - V2D_SCROLLER_HANDLE_SIZE);
}
- /* check whether sliders can disappear due to the full-range being used */
- if (v2d->keeptot) {
- if ((fac1 <= 0.0f) && (fac2 >= 1.0f)) {
- v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR;
- scrollers->horfull = 1;
- }
- else
- v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR;
- }
}
/* vertical scrollers */
@@ -1536,15 +1554,6 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d,
CLAMP(scrollers->vert_min, vert.ymin, vert.ymax - V2D_SCROLLER_HANDLE_SIZE);
}
- /* check whether sliders can disappear due to the full-range being used */
- if (v2d->keeptot) {
- if ((fac1 <= 0.0f) && (fac2 >= 1.0f)) {
- v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR;
- scrollers->vertfull = 1;
- }
- else
- v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR;
- }
}
/* grid markings on scrollbars */
@@ -1618,45 +1627,42 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* horizontal scrollbar */
if (scroll & V2D_SCROLL_HORIZONTAL) {
- /* only draw scrollbar when it doesn't fill the entire space */
- if (vs->horfull == 0) {
- bTheme *btheme = UI_GetTheme();
- uiWidgetColors wcol = btheme->tui.wcol_scroll;
- rcti slider;
- int state;
- unsigned char col[4];
-
- slider.xmin = vs->hor_min;
- slider.xmax = vs->hor_max;
- slider.ymin = hor.ymin;
- slider.ymax = hor.ymax;
-
- state = (v2d->scroll_ui & V2D_SCROLL_H_ACTIVE) ? UI_SCROLL_PRESSED : 0;
-
- /* show zoom handles if:
- * - zooming on x-axis is allowed (no scroll otherwise)
- * - slider bubble is large enough (no overdraw confusion)
- * - scale is shown on the scroller
- * (workaround to make sure that button windows don't show these,
- * and only the time-grids with their zoomability can do so)
- */
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 &&
- (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) &&
- (BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE))
- {
- state |= UI_SCROLL_ARROWS;
- }
-
- /* clean rect behind slider, but not with transparent background */
- UI_GetThemeColor4ubv(TH_BACK, col);
- if (col[3] == 255) {
- glColor3ub(col[0], col[1], col[2]);
- glRecti(v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax);
- }
-
- uiWidgetScrollDraw(&wcol, &hor, &slider, state);
+ bTheme *btheme = UI_GetTheme();
+ uiWidgetColors wcol = btheme->tui.wcol_scroll;
+ rcti slider;
+ int state;
+ unsigned char col[4];
+
+ slider.xmin = vs->hor_min;
+ slider.xmax = vs->hor_max;
+ slider.ymin = hor.ymin;
+ slider.ymax = hor.ymax;
+
+ state = (v2d->scroll_ui & V2D_SCROLL_H_ACTIVE) ? UI_SCROLL_PRESSED : 0;
+
+ /* show zoom handles if:
+ * - zooming on x-axis is allowed (no scroll otherwise)
+ * - slider bubble is large enough (no overdraw confusion)
+ * - scale is shown on the scroller
+ * (workaround to make sure that button windows don't show these,
+ * and only the time-grids with their zoomability can do so)
+ */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 &&
+ (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) &&
+ (BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE))
+ {
+ state |= UI_SCROLL_ARROWS;
}
+ /* clean rect behind slider, but not with transparent background */
+ UI_GetThemeColor4ubv(TH_BACK, col);
+ if (col[3] == 255) {
+ glColor3ub(col[0], col[1], col[2]);
+ glRecti(v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax);
+ }
+
+ uiWidgetScrollDraw(&wcol, &hor, &slider, state);
+
/* scale indicators */
if ((scroll & V2D_SCROLL_SCALE_HORIZONTAL) && (vs->grid)) {
View2DGrid *grid = vs->grid;
@@ -1734,45 +1740,42 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* vertical scrollbar */
if (scroll & V2D_SCROLL_VERTICAL) {
- /* only draw scrollbar when it doesn't fill the entire space */
- if (vs->vertfull == 0) {
- bTheme *btheme = UI_GetTheme();
- uiWidgetColors wcol = btheme->tui.wcol_scroll;
- rcti slider;
- int state;
- unsigned char col[4];
-
- slider.xmin = vert.xmin;
- slider.xmax = vert.xmax;
- slider.ymin = vs->vert_min;
- slider.ymax = vs->vert_max;
-
- state = (v2d->scroll_ui & V2D_SCROLL_V_ACTIVE) ? UI_SCROLL_PRESSED : 0;
-
- /* show zoom handles if:
- * - zooming on y-axis is allowed (no scroll otherwise)
- * - slider bubble is large enough (no overdraw confusion)
- * - scale is shown on the scroller
- * (workaround to make sure that button windows don't show these,
- * and only the time-grids with their zoomability can do so)
- */
- if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 &&
- (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) &&
- (BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE))
- {
- state |= UI_SCROLL_ARROWS;
- }
-
- /* clean rect behind slider, but not with transparent background */
- UI_GetThemeColor4ubv(TH_BACK, col);
- if (col[3] == 255) {
- glColor3ub(col[0], col[1], col[2]);
- glRecti(v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax);
- }
-
- uiWidgetScrollDraw(&wcol, &vert, &slider, state);
+ bTheme *btheme = UI_GetTheme();
+ uiWidgetColors wcol = btheme->tui.wcol_scroll;
+ rcti slider;
+ int state;
+ unsigned char col[4];
+
+ slider.xmin = vert.xmin;
+ slider.xmax = vert.xmax;
+ slider.ymin = vs->vert_min;
+ slider.ymax = vs->vert_max;
+
+ state = (v2d->scroll_ui & V2D_SCROLL_V_ACTIVE) ? UI_SCROLL_PRESSED : 0;
+
+ /* show zoom handles if:
+ * - zooming on y-axis is allowed (no scroll otherwise)
+ * - slider bubble is large enough (no overdraw confusion)
+ * - scale is shown on the scroller
+ * (workaround to make sure that button windows don't show these,
+ * and only the time-grids with their zoomability can do so)
+ */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 &&
+ (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) &&
+ (BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE))
+ {
+ state |= UI_SCROLL_ARROWS;
}
+ /* clean rect behind slider, but not with transparent background */
+ UI_GetThemeColor4ubv(TH_BACK, col);
+ if (col[3] == 255) {
+ glColor3ub(col[0], col[1], col[2]);
+ glRecti(v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax);
+ }
+
+ uiWidgetScrollDraw(&wcol, &vert, &slider, state);
+
/* scale indiators */
if ((scroll & V2D_SCROLL_SCALE_VERTICAL) && (vs->grid)) {
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 006644bf366..cc473998340 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -937,7 +937,7 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event)
vzd = op->customdata;
v2d = vzd->v2d;
- if (event->type == MOUSEZOOM) {
+ if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
float dx, dy, fac;
vzd->lastx = event->prevx;
@@ -948,6 +948,8 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event)
*/
fac = 0.01f * (event->x - event->prevx);
dx = fac * BLI_rctf_size_x(&v2d->cur) / 10.0f;
+ if (event->type == MOUSEPAN)
+ fac = 0.01f * (event->y - event->prevy);
dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f;
RNA_float_set(op->ptr, "deltax", dx);
@@ -1744,8 +1746,8 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
/* zone is also inappropriate if scroller is not visible... */
- if (((vsm->scroller == 'h') && (v2d->scroll & (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_HORIZONTAL_FULLR))) ||
- ((vsm->scroller == 'v') && (v2d->scroll & (V2D_SCROLL_VERTICAL_HIDE | V2D_SCROLL_VERTICAL_FULLR))) )
+ if (((vsm->scroller == 'h') && (v2d->scroll & (V2D_SCROLL_HORIZONTAL_FULLR))) ||
+ ((vsm->scroller == 'v') && (v2d->scroll & (V2D_SCROLL_VERTICAL_FULLR))) )
{
/* free customdata initialized */
scroller_activate_exit(C, op);
@@ -1903,6 +1905,7 @@ void UI_view2d_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", PADMINUS, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEPAN, 0, KM_CTRL, 0);
WM_keymap_verify_item(keymap, "VIEW2D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0);
@@ -1951,6 +1954,7 @@ void UI_view2d_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEZOOM, 0, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEPAN, 0, KM_CTRL, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", PADMINUS, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_reset", HOMEKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 29139c5154f..3fbfaabbc0d 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -69,7 +69,14 @@ void paintface_flush_flags(Object *ob)
int totface, totpoly;
int i;
- if (me == NULL || dm == NULL)
+ if (me == NULL)
+ return;
+
+ /* we could call this directly in all areas that change selection,
+ * since this could become slow for realtime updates (circle-select for eg) */
+ BKE_mesh_flush_select_from_polys(me);
+
+ if (dm == NULL)
return;
/*
@@ -477,7 +484,7 @@ int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], in
/* Get the face under the cursor */
me = BKE_mesh_from_object(ob);
- if (!ED_mesh_pick_face(C, me, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE))
+ if (!ED_mesh_pick_face(C, ob, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE))
return 0;
if (index >= me->totpoly)
@@ -603,7 +610,14 @@ void paintvert_flush_flags(Object *ob)
int totvert;
int i;
- if (me == NULL || dm == NULL)
+ if (me == NULL)
+ return;
+
+ /* we could call this directly in all areas that change selection,
+ * since this could become slow for realtime updates (circle-select for eg) */
+ BKE_mesh_flush_select_from_verts(me);
+
+ if (dm == NULL)
return;
index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index c8a1264fd10..590bcd5939e 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -1315,7 +1315,7 @@ static void knife_bgl_get_mats(KnifeTool_OpData *UNUSED(kcd), bglMats *mats)
//copy_m4_m4(mats->projection, kcd->vc.rv3d->winmat);
}
-/* Calculate maximum excursion (doubled) from (0,0,0) of mesh */
+/* Calculate maximum excursion from (0,0,0) of mesh */
static void calc_ortho_extent(KnifeTool_OpData *kcd)
{
BMIter iter;
@@ -1328,7 +1328,19 @@ static void calc_ortho_extent(KnifeTool_OpData *kcd)
for (i = 0; i < 3; i++)
max_xyz = max_ff(max_xyz, fabs(v->co[i]));
}
- kcd->ortho_extent = 2 * max_xyz;
+ kcd->ortho_extent = max_xyz;
+}
+
+/* Clip the line (v1, v2) to planes perpendicular to it and distances d from
+ * the closest point on the line to the origin */
+static void clip_to_ortho_planes(float v1[3], float v2[3], float d)
+{
+ float closest[3];
+ const float origin[3] = {0.0f, 0.0f, 0.0f};
+
+ closest_to_line_v3(closest, origin, v1, v2);
+ dist_ensure_v3_v3fl(v1, closest, d);
+ dist_ensure_v3_v3fl(v2, closest, d);
}
/* Finds visible (or all, if cutting through) edges that intersects the current screen drag line */
@@ -1375,8 +1387,8 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
if (kcd->is_ortho) {
if (kcd->ortho_extent == 0.0f)
calc_ortho_extent(kcd);
- limit_dist_v3(v1, v3, kcd->ortho_extent + 10.0f);
- limit_dist_v3(v2, v4, kcd->ortho_extent + 10.0f);
+ clip_to_ortho_planes(v1, v3, kcd->ortho_extent + 10.0f);
+ clip_to_ortho_planes(v2, v4, kcd->ortho_extent + 10.0f);
}
BLI_smallhash_init(ehash);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 41b263e8929..27c68ce21bc 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -1674,7 +1674,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BMEdit_FromObject(obedit);
int usex = TRUE, usey = TRUE, usez = TRUE, preserve_volume = TRUE;
int i, repeat;
- float lambda;
+ float lambda_factor;
float lambda_border;
BMIter fiter;
BMFace *f;
@@ -1695,7 +1695,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
}
repeat = RNA_int_get(op->ptr, "repeat");
- lambda = RNA_float_get(op->ptr, "lambda");
+ lambda_factor = RNA_float_get(op->ptr, "lambda_factor");
lambda_border = RNA_float_get(op->ptr, "lambda_border");
usex = RNA_boolean_get(op->ptr, "use_x");
usey = RNA_boolean_get(op->ptr, "use_y");
@@ -1706,8 +1706,8 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
for (i = 0; i < repeat; i++) {
if (!EDBM_op_callf(em, op,
- "smooth_laplacian_vert verts=%hv lambda=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b",
- BM_ELEM_SELECT, lambda, lambda_border, usex, usey, usez, preserve_volume))
+ "smooth_laplacian_vert verts=%hv lambda_factor=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b",
+ BM_ELEM_SELECT, lambda_factor, lambda_border, usex, usey, usez, preserve_volume))
{
return OPERATOR_CANCELLED;
}
@@ -1740,7 +1740,7 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
RNA_def_int(ot->srna, "repeat", 1, 1, 200,
"Number of iterations to smooth the mesh", "", 1, 200);
- RNA_def_float(ot->srna, "lambda", 0.00005f, 0.0000001f, 1000.0f,
+ RNA_def_float(ot->srna, "lambda_factor", 0.00005f, 0.0000001f, 1000.0f,
"Lambda factor", "", 0.0000001f, 1000.0f);
RNA_def_float(ot->srna, "lambda_border", 0.00005f, 0.0000001f, 1000.0f,
"Lambda factor in border", "", 0.0000001f, 1000.0f);
@@ -3582,7 +3582,7 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot)
prop = RNA_def_float_rotation(ot->srna, "angle_limit", 0, NULL, 0.0f, DEG2RADF(180.0f),
"Max Angle", "Angle limit", 0.0f, DEG2RADF(180.0f));
- RNA_def_property_float_default(prop, DEG2RADF(15.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(5.0f));
RNA_def_boolean(ot->srna, "use_dissolve_boundaries", 0, "All Boundaries",
"Dissolve all vertices inbetween face boundaries");
}
@@ -4768,6 +4768,7 @@ static int edbm_bevel_calc(wmOperator *op)
#ifdef NEW_BEVEL
float offset = RNA_float_get(op->ptr, "offset");
int segments = RNA_int_get(op->ptr, "segments");
+ int vertex_only = RNA_boolean_get(op->ptr, "vertex_only");
/* revert to original mesh */
if (opdata->is_modal) {
@@ -4775,8 +4776,8 @@ static int edbm_bevel_calc(wmOperator *op)
}
if (!EDBM_op_init(em, &bmop, op,
- "bevel geom=%hev offset=%f segments=%i",
- BM_ELEM_SELECT, offset, segments))
+ "bevel geom=%hev offset=%f segments=%i vertex_only=%b",
+ BM_ELEM_SELECT, offset, segments, vertex_only))
{
return 0;
}
@@ -5101,6 +5102,7 @@ void MESH_OT_bevel(wmOperatorType *ot)
#ifdef NEW_BEVEL
RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Offset", "", 0.0f, 1.0f);
RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8);
+ RNA_def_boolean(ot->srna, "vertex_only", FALSE, "Vertex only", "Bevel only vertices");
#else
/* take note, used as a factor _and_ a distance depending on 'use_dist' */
RNA_def_float(ot->srna, "percent", 0.0f, -FLT_MAX, FLT_MAX, "Percentage", "", 0.0f, 1.0f);
@@ -5732,18 +5734,6 @@ static int mesh_symmetrize_exec(bContext *C, wmOperator *op)
void MESH_OT_symmetrize(struct wmOperatorType *ot)
{
- static EnumPropertyItem axis_direction_items[] = {
- {BMO_SYMMETRIZE_NEGATIVE_X, "NEGATIVE_X", 0, "-X to +X", ""},
- {BMO_SYMMETRIZE_POSITIVE_X, "POSITIVE_X", 0, "+X to -X", ""},
-
- {BMO_SYMMETRIZE_NEGATIVE_Y, "NEGATIVE_Y", 0, "-Y to +Y", ""},
- {BMO_SYMMETRIZE_POSITIVE_Y, "POSITIVE_Y", 0, "+Y to -Y", ""},
-
- {BMO_SYMMETRIZE_NEGATIVE_Z, "NEGATIVE_Z", 0, "-Z to +Z", ""},
- {BMO_SYMMETRIZE_POSITIVE_Z, "POSITIVE_Z", 0, "+Z to -Z", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
/* identifiers */
ot->name = "Symmetrize";
ot->description = "Enforce symmetry (both form and topological) across an axis";
@@ -5756,7 +5746,7 @@ void MESH_OT_symmetrize(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "direction", axis_direction_items,
+ ot->prop = RNA_def_enum(ot->srna, "direction", symmetrize_direction_items,
BMO_SYMMETRIZE_NEGATIVE_X,
"Direction", "Which sides to copy from and to");
}
diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index 1a81cab8de7..99fa85b3ee7 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -157,8 +157,9 @@ static void createVertsTrisData(bContext *C, LinkNode *obs, int *nverts_r, float
*tris_r = tris;
}
-static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts, int ntris, int *tris,
- struct recast_polyMesh **pmesh, struct recast_polyMeshDetail **dmesh)
+static bool buildNavMesh(const RecastData *recastParams, int nverts, float *verts, int ntris, int *tris,
+ struct recast_polyMesh **pmesh, struct recast_polyMeshDetail **dmesh,
+ ReportList *reports)
{
float bmin[3], bmax[3];
struct recast_heightfield *solid;
@@ -185,14 +186,20 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
/* Set the area where the navigation will be build. */
recast_calcGridSize(bmin, bmax, recastParams->cellsize, &width, &height);
+ /* zero dimensions cause zero alloc later on [#33758] */
+ if (width <= 0 || height <= 0) {
+ BKE_report(reports, RPT_ERROR, "Object has a width or height of zero");
+ return false;
+ }
+
/* ** Step 2: Rasterize input polygon soup ** */
/* Allocate voxel heightfield where we rasterize our input data to */
solid = recast_newHeightfield();
if (!recast_createHeightfield(solid, width, height, bmin, bmax, recastParams->cellsize, recastParams->cellheight)) {
recast_destroyHeightfield(solid);
-
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to create height field");
+ return false;
}
/* Allocate array that can hold triangle flags */
@@ -215,7 +222,8 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
recast_destroyHeightfield(solid);
recast_destroyCompactHeightfield(chf);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to create compact height field");
+ return false;
}
recast_destroyHeightfield(solid);
@@ -224,21 +232,24 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
if (!recast_erodeWalkableArea(walkableRadius, chf)) {
recast_destroyCompactHeightfield(chf);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to erode walkable area");
+ return false;
}
/* Prepare for region partitioning, by calculating distance field along the walkable surface */
if (!recast_buildDistanceField(chf)) {
recast_destroyCompactHeightfield(chf);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to build distance field");
+ return false;
}
/* Partition the walkable surface into simple regions without holes */
if (!recast_buildRegions(chf, 0, minRegionArea, mergeRegionArea)) {
recast_destroyCompactHeightfield(chf);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to build regions");
+ return false;
}
/* ** Step 5: Trace and simplify region contours ** */
@@ -249,7 +260,8 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
recast_destroyCompactHeightfield(chf);
recast_destroyContourSet(cset);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to build contours");
+ return false;
}
/* ** Step 6: Build polygons mesh from contours ** */
@@ -259,7 +271,8 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
recast_destroyContourSet(cset);
recast_destroyPolyMesh(*pmesh);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to build poly mesh");
+ return false;
}
@@ -272,13 +285,14 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
recast_destroyPolyMesh(*pmesh);
recast_destroyPolyMeshDetail(*dmesh);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to build poly mesh detail");
+ return false;
}
recast_destroyCompactHeightfield(chf);
recast_destroyContourSet(cset);
- return 1;
+ return true;
}
static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, struct recast_polyMeshDetail *dmesh, Base *base)
@@ -437,6 +451,7 @@ static int navmesh_create_exec(bContext *C, wmOperator *op)
if (obs) {
struct recast_polyMesh *pmesh = NULL;
struct recast_polyMeshDetail *dmesh = NULL;
+ bool ok;
int nverts = 0, ntris = 0;
int *tris = 0;
@@ -444,13 +459,14 @@ static int navmesh_create_exec(bContext *C, wmOperator *op)
createVertsTrisData(C, obs, &nverts, &verts, &ntris, &tris);
BLI_linklist_free(obs, NULL);
- buildNavMesh(&scene->gm.recastData, nverts, verts, ntris, tris, &pmesh, &dmesh);
- createRepresentation(C, pmesh, dmesh, navmeshBase);
+ if ((ok = buildNavMesh(&scene->gm.recastData, nverts, verts, ntris, tris, &pmesh, &dmesh, op->reports))) {
+ createRepresentation(C, pmesh, dmesh, navmeshBase);
+ }
MEM_freeN(verts);
MEM_freeN(tris);
- return OPERATOR_FINISHED;
+ return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
else {
BKE_report(op->reports, RPT_ERROR, "No mesh objects found");
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 773331d20f8..96b8f1080b9 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -40,6 +40,8 @@
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -1165,9 +1167,12 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em)
*
* \return boolean TRUE == Found
*/
-int ED_mesh_pick_face(bContext *C, Mesh *me, const int mval[2], unsigned int *index, int size)
+int ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size)
{
ViewContext vc;
+ Mesh *me = ob->data;
+
+ BLI_assert(me && GS(me->id.name) == ID_ME);
if (!me || me->totpoly == 0)
return 0;
@@ -1197,11 +1202,14 @@ int ED_mesh_pick_face(bContext *C, Mesh *me, const int mval[2], unsigned int *in
* Use when the back buffer stores face index values. but we want a vert.
* This gets the face then finds the closest vertex to mval.
*/
-int ED_mesh_pick_face_vert(bContext *C, Mesh *me, Object *ob, const int mval[2], unsigned int *index, int size)
+int ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size)
{
unsigned int poly_index;
+ Mesh *me = ob->data;
- if (ED_mesh_pick_face(C, me, mval, &poly_index, size)) {
+ BLI_assert(me && GS(me->id.name) == ID_ME);
+
+ if (ED_mesh_pick_face(C, ob, mval, &poly_index, size)) {
Scene *scene = CTX_data_scene(C);
struct ARegion *ar = CTX_wm_region(C);
@@ -1210,6 +1218,8 @@ int ED_mesh_pick_face_vert(bContext *C, Mesh *me, Object *ob, const int mval[2],
int v_idx_best = -1;
if (dm->getVertCo) {
+ RegionView3D *rv3d = ar->regiondata;
+
/* find the vert closest to 'mval' */
const float mval_f[2] = {(float)mval[0],
(float)mval[1]};
@@ -1217,14 +1227,15 @@ int ED_mesh_pick_face_vert(bContext *C, Mesh *me, Object *ob, const int mval[2],
int fidx;
float len_best = FLT_MAX;
+ ED_view3d_init_mats_rv3d(ob, rv3d);
+
fidx = mp->totloop - 1;
do {
float co[3], sco[2], len;
const int v_idx = me->mloop[mp->loopstart + fidx].v;
dm->getVertCo(dm, v_idx, co);
- mul_m4_v3(ob->obmat, co);
- if (ED_view3d_project_float_global(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- len = len_squared_v2v2(mval_f, sco);
+ if (ED_view3d_project_float_object(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ len = len_manhattan_v2v2(mval_f, sco);
if (len < len_best) {
len_best = len;
v_idx_best = v_idx;
@@ -1250,31 +1261,97 @@ int ED_mesh_pick_face_vert(bContext *C, Mesh *me, Object *ob, const int mval[2],
*
* \return boolean TRUE == Found
*/
-int ED_mesh_pick_vert(bContext *C, Mesh *me, const int mval[2], unsigned int *index, int size)
+typedef struct VertPickData {
+ const MVert *mvert;
+ const float *mval_f; /* [2] */
+ ARegion *ar;
+
+ /* runtime */
+ float len_best;
+ int v_idx_best;
+} VertPickData;
+
+static void ed_mesh_pick_vert__mapFunc(void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+ VertPickData *data = userData;
+ if ((data->mvert[index].flag & ME_HIDE) == 0) {
+ float sco[2];
+
+ if (ED_view3d_project_float_object(data->ar, co, sco, V3D_PROJ_TEST_CLIP_DEFAULT) == V3D_PROJ_RET_OK) {
+ const float len = len_manhattan_v2v2(data->mval_f, sco);
+ if (len < data->len_best) {
+ data->len_best = len;
+ data->v_idx_best = index;
+ }
+ }
+ }
+}
+int ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size, int use_zbuf)
{
ViewContext vc;
+ Mesh *me = ob->data;
+
+ BLI_assert(me && GS(me->id.name) == ID_ME);
if (!me || me->totvert == 0)
return 0;
view3d_set_viewcontext(C, &vc);
- if (size > 0) {
- /* sample rect to increase chances of selecting, so that when clicking
- * on an face in the backbuf, we can still select a vert */
+ if (use_zbuf) {
+ if (size > 0) {
+ /* sample rect to increase chances of selecting, so that when clicking
+ * on an face in the backbuf, we can still select a vert */
- float dummy_dist;
- *index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist, 0, NULL, NULL);
+ float dummy_dist;
+ *index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist, 0, NULL, NULL);
+ }
+ else {
+ /* sample only on the exact position */
+ *index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
+ }
+
+ if ((*index) <= 0 || (*index) > (unsigned int)me->totvert)
+ return 0;
+
+ (*index)--;
}
else {
- /* sample only on the exact position */
- *index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
- }
+ /* derived mesh to find deformed locations */
+ DerivedMesh *dm = mesh_get_derived_final(vc.scene, ob, CD_MASK_BAREMESH);
+ ARegion *ar = vc.ar;
+ RegionView3D *rv3d = ar->regiondata;
- if ((*index) <= 0 || (*index) > (unsigned int)me->totvert)
- return 0;
+ /* find the vert closest to 'mval' */
+ const float mval_f[2] = {(float)mval[0],
+ (float)mval[1]};
- (*index)--;
+ VertPickData data = {0};
+
+ ED_view3d_init_mats_rv3d(ob, rv3d);
+
+ if (dm == NULL) {
+ return 0;
+ }
+
+ /* setup data */
+ data.mvert = me->mvert;
+ data.ar = ar;
+ data.mval_f = mval_f;
+ data.len_best = FLT_MAX;
+ data.v_idx_best = -1;
+
+ dm->foreachMappedVert(dm, ed_mesh_pick_vert__mapFunc, &data);
+
+ dm->release(dm);
+
+ if (data.v_idx_best == -1) {
+ return 0;
+ }
+
+ *index = data.v_idx_best;
+ }
return 1;
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 473119c90f3..4db416b6f72 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -808,9 +808,16 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
if (RNA_struct_property_is_set(op->ptr, "name")) {
char name[MAX_ID_NAME - 2];
-
+
RNA_string_get(op->ptr, "name", name);
group = (Group *)BKE_libblock_find_name(ID_GR, name);
+
+ if (0 == RNA_struct_property_is_set(op->ptr, "location")) {
+ wmEvent *event = CTX_wm_window(C)->eventstate;
+ ED_object_location_from_view(C, loc);
+ ED_view3d_cursor3d_position(C, loc, event->x, event->y);
+ RNA_float_set_array(op->ptr, "location", loc);
+ }
}
else
group = BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "group"));
@@ -1994,6 +2001,7 @@ void OBJECT_OT_duplicate(wmOperatorType *ot)
static int add_named_exec(bContext *C, wmOperator *op)
{
+ wmEvent *event = CTX_wm_window(C)->eventstate;
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Base *basen, *base;
@@ -2026,6 +2034,8 @@ static int add_named_exec(bContext *C, wmOperator *op)
basen->lay = basen->object->lay = scene->lay;
ED_object_location_from_view(C, basen->object->loc);
+ ED_view3d_cursor3d_position(C, basen->object->loc, event->x, event->y);
+
ED_base_object_activate(C, basen);
copy_object_set_idnew(C, dupflag);
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index d3ebd1dae0a..f36c6d79783 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -89,6 +89,7 @@ typedef struct MultiresBakerJobData {
struct MultiresBakerJobData *next, *prev;
DerivedMesh *lores_dm, *hires_dm;
int simple, lvl, tot_lvl;
+ ListBase images;
} MultiresBakerJobData;
/* data passing to multires-baker job */
@@ -429,7 +430,7 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
RE_multires_bake_images(&bkr);
- BLI_freelistN(&bkr.image);
+ data->images = bkr.image;
baked_objects++;
}
@@ -439,12 +440,22 @@ static void multiresbake_freejob(void *bkv)
{
MultiresBakeJob *bkj = bkv;
MultiresBakerJobData *data, *next;
+ LinkData *link;
data = bkj->data.first;
while (data) {
next = data->next;
data->lores_dm->release(data->lores_dm);
data->hires_dm->release(data->hires_dm);
+
+ /* delete here, since this delete will be called from main thread */
+ for (link = data->images.first; link; link = link->next) {
+ Image *ima = (Image *)link->data;
+ GPU_free_image(ima);
+ }
+
+ BLI_freelistN(&data->images);
+
MEM_freeN(data);
data = next;
}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index f78e1203bc4..6cb7cd5e326 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -141,7 +141,7 @@ ListBase *get_constraint_lb(Object *ob, bConstraint *con, bPoseChannel **pchan_r
/* single constraint */
bConstraint *get_active_constraint(Object *ob)
{
- return constraints_get_active(get_active_constraints(ob));
+ return BKE_constraints_get_active(get_active_constraints(ob));
}
/* -------------- Constraint Management (Add New, Remove, Rename) -------------------- */
@@ -225,7 +225,7 @@ static void update_pyconstraint_cb(void *arg1, void *arg2)
/* helper function for add_constriant - sets the last target for the active constraint */
static void set_constraint_nth_target(bConstraint *con, Object *target, const char subtarget[], int index)
{
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
int num_targets, i;
@@ -297,7 +297,7 @@ static void test_constraints(Object *owner, bPoseChannel *pchan)
/* Check all constraints - is constraint valid? */
if (conlist) {
for (curcon = conlist->first; curcon; curcon = curcon->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(curcon);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -610,7 +610,7 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
list = get_active_constraints(ob);
}
- con = constraints_findByName(list, constraint_name);
+ con = BKE_constraints_findByName(list, constraint_name);
//if (G.debug & G_DEBUG)
//printf("constraint found = %p, %s\n", (void *)con, (con)?con->name:"<Not found>");
@@ -1123,7 +1123,7 @@ void ED_object_constraint_set_active(Object *ob, bConstraint *con)
if ((lb && con) && (con->flag & CONSTRAINT_ACTIVE))
return;
- constraints_set_active(lb, con);
+ BKE_constraints_set_active(lb, con);
}
void ED_object_constraint_update(Object *ob)
@@ -1162,9 +1162,9 @@ static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op))
const short is_ik = ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK);
/* free the constraint */
- if (remove_constraint(lb, con)) {
+ if (BKE_remove_constraint(lb, con)) {
/* there's no active constraint now, so make sure this is the case */
- constraints_set_active(lb, NULL);
+ BKE_constraints_set_active(lb, NULL);
ED_object_constraint_update(ob); /* needed to set the flags on posebones correctly */
@@ -1308,7 +1308,7 @@ static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
/* free constraints for all selected bones */
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
{
- free_constraints(&pchan->constraints);
+ BKE_free_constraints(&pchan->constraints);
pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_SPLINEIK | PCHAN_HAS_CONST);
}
CTX_DATA_END;
@@ -1346,7 +1346,7 @@ static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
/* do freeing */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
- free_constraints(&ob->constraints);
+ BKE_free_constraints(&ob->constraints);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
CTX_DATA_END;
@@ -1391,7 +1391,7 @@ static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
{
/* if we're not handling the object we're copying from, copy all constraints over */
if (pchan != chan) {
- copy_constraints(&chan->constraints, &pchan->constraints, TRUE);
+ BKE_copy_constraints(&chan->constraints, &pchan->constraints, TRUE);
/* update flags (need to add here, not just copy) */
chan->constflag |= pchan->constflag;
}
@@ -1432,7 +1432,7 @@ static int object_constraint_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
/* if we're not handling the object we're copying from, copy all constraints over */
if (obact != ob) {
- copy_constraints(&ob->constraints, &obact->constraints, TRUE);
+ BKE_copy_constraints(&ob->constraints, &obact->constraints, TRUE);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
@@ -1642,9 +1642,9 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
/* create a new constraint of the type requried, and add it to the active/given constraints list */
if (pchan)
- con = add_pose_constraint(ob, pchan, NULL, type);
+ con = BKE_add_pose_constraint(ob, pchan, NULL, type);
else
- con = add_ob_constraint(ob, NULL, type);
+ con = BKE_add_ob_constraint(ob, NULL, type);
/* get the first selected object/bone, and make that the target
* - apart from the buttons-window add buttons, we shouldn't add in this way
@@ -1940,7 +1940,7 @@ static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op))
for (con = pchan->constraints.first; con; con = next) {
next = con->next;
if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- remove_constraint(&pchan->constraints, con);
+ BKE_remove_constraint(&pchan->constraints, con);
}
}
pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index c9492d8f683..fcc3b5d012e 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -954,7 +954,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
}
else if (event == 22) {
/* Copy the constraint channels over */
- copy_constraints(&base->object->constraints, &ob->constraints, TRUE);
+ BKE_copy_constraints(&base->object->constraints, &ob->constraints, TRUE);
do_scene_sort = TRUE;
}
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index a3bf27a19d6..7bf1a5db3b1 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -313,7 +313,7 @@ static int group_create_exec(bContext *C, wmOperator *op)
group = add_group(name);
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
add_to_group(group, base->object, scene, base);
}
diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c
index 4aa2e825954..c9eae776ac7 100644
--- a/source/blender/editors/object/object_lattice.c
+++ b/source/blender/editors/object/object_lattice.c
@@ -52,7 +52,7 @@
#include "BKE_depsgraph.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
-#include "BKE_mesh.h"
+#include "BKE_deform.h"
#include "ED_lattice.h"
#include "ED_object.h"
@@ -77,7 +77,7 @@ void free_editLatt(Object *ob)
if (editlt->def)
MEM_freeN(editlt->def);
if (editlt->dvert)
- free_dverts(editlt->dvert, editlt->pntsu * editlt->pntsv * editlt->pntsw);
+ BKE_defvert_array_free(editlt->dvert, editlt->pntsu * editlt->pntsv * editlt->pntsw);
MEM_freeN(editlt);
MEM_freeN(lt->editlatt);
@@ -104,7 +104,7 @@ void make_editLatt(Object *obedit)
if (lt->dvert) {
int tot = lt->pntsu * lt->pntsv * lt->pntsw;
lt->editlatt->latt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
- copy_dverts(lt->editlatt->latt->dvert, lt->dvert, tot);
+ BKE_defvert_array_copy(lt->editlatt->latt->dvert, lt->dvert, tot);
}
if (lt->key) lt->editlatt->shapenr = obedit->shapenr;
@@ -156,7 +156,7 @@ void load_editLatt(Object *obedit)
}
if (lt->dvert) {
- free_dverts(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+ BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
lt->dvert = NULL;
}
@@ -164,7 +164,7 @@ void load_editLatt(Object *obedit)
tot = lt->pntsu * lt->pntsv * lt->pntsw;
lt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
- copy_dverts(lt->dvert, editlt->dvert, tot);
+ BKE_defvert_array_copy(lt->dvert, editlt->dvert, tot);
}
}
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index d19277d20a2..03b50c05071 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -252,15 +252,6 @@ void ED_operatormacros_object(void)
RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
}
- /* XXX */
- ot = WM_operatortype_append_macro("OBJECT_OT_add_named_cursor", "Add Named At Cursor",
- "Add named object at cursor", OPTYPE_UNDO | OPTYPE_REGISTER);
- if (ot) {
- RNA_def_string(ot->srna, "name", "Cube", MAX_ID_NAME - 2, "Name", "Object name to add");
-
- WM_operatortype_macro_define(ot, "VIEW3D_OT_cursor3d");
- WM_operatortype_macro_define(ot, "OBJECT_OT_add_named");
- }
}
static int object_mode_poll(bContext *C)
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 0988a196fb1..fa44d3d7fb4 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -716,12 +716,12 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
bFollowPathConstraint *data;
float cmat[4][4], vec[3];
- con = add_ob_constraint(ob, "AutoPath", CONSTRAINT_TYPE_FOLLOWPATH);
+ con = BKE_add_ob_constraint(ob, "AutoPath", CONSTRAINT_TYPE_FOLLOWPATH);
data = con->data;
data->tar = par;
- get_constraint_target_matrix(scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
+ BKE_get_constraint_target_matrix(scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
sub_v3_v3v3(vec, ob->obmat[3], cmat[3]);
ob->loc[0] = vec[0];
@@ -1051,7 +1051,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
for (con = ob->constraints.last; con; con = pcon) {
pcon = con->prev;
if (ELEM3(con->type, CONSTRAINT_TYPE_TRACKTO, CONSTRAINT_TYPE_LOCKTRACK, CONSTRAINT_TYPE_DAMPTRACK))
- remove_constraint(&ob->constraints, con);
+ BKE_remove_constraint(&ob->constraints, con);
}
if (type == 1)
@@ -1109,7 +1109,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (ob != obact) {
- con = add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_DAMPTRACK);
+ con = BKE_add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_DAMPTRACK);
data = con->data;
data->tar = obact;
@@ -1129,7 +1129,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (ob != obact) {
- con = add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
+ con = BKE_add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
data = con->data;
data->tar = obact;
@@ -1151,7 +1151,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (ob != obact) {
- con = add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_LOCKTRACK);
+ con = BKE_add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_LOCKTRACK);
data = con->data;
data->tar = obact;
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 2aa737d204d..07eca749a74 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -42,6 +42,7 @@
#include "DNA_property_types.h"
#include "DNA_scene_types.h"
#include "DNA_armature_types.h"
+#include "DNA_lamp_types.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
@@ -525,6 +526,7 @@ static EnumPropertyItem prop_select_grouped_types[] = {
{10, "COLOR", 0, "Color", "Object Color"},
{11, "PROPERTIES", 0, "Properties", "Game Properties"},
{12, "KEYINGSET", 0, "Keying Set", "Objects included in active Keying Set"},
+ {13, "LAMP_TYPE", 0, "Lamp Type", "Matching lamp types"},
{0, NULL, 0, NULL, NULL}
};
@@ -656,7 +658,25 @@ static short select_grouped_siblings(bContext *C, Object *ob)
CTX_DATA_END;
return changed;
}
+static short select_similar_lamps(bContext *C, Object *ob)
+{
+ Lamp *la = ob->data;
+
+ short changed = 0;
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ {
+ if (base->object->type == OB_LAMP) {
+ Lamp *la_test = base->object->data;
+ if ((la->type == la_test->type) && !(base->flag & SELECT)) {
+ ED_base_object_select(base, BA_SELECT);
+ changed = 1;
+ }
+ }
+ }
+ CTX_DATA_END;
+ return changed;
+}
static short select_grouped_type(bContext *C, Object *ob)
{
short changed = 0;
@@ -803,7 +823,12 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No active object");
return OPERATOR_CANCELLED;
}
-
+
+ if (nr == 13 && ob->type != OB_LAMP) {
+ BKE_report(op->reports, RPT_ERROR, "Active object must be a lamp");
+ return OPERATOR_CANCELLED;
+ }
+
if (nr == 1) changed |= select_grouped_children(C, ob, 1);
else if (nr == 2) changed |= select_grouped_children(C, ob, 0);
else if (nr == 3) changed |= select_grouped_parent(C);
@@ -816,6 +841,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
else if (nr == 10) changed |= select_grouped_color(C, ob);
else if (nr == 11) changed |= select_grouped_gameprops(C, ob);
else if (nr == 12) changed |= select_grouped_keyingset(C, ob);
+ else if (nr == 13) changed |= select_similar_lamps(C, ob);
if (changed) {
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 16fe94ff2e5..cbc076b3342 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -281,7 +281,7 @@ 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.imtype, scene->r.scemode & R_EXTENSION, FALSE);
+ BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, 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);
@@ -505,7 +505,7 @@ static int 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.imtype, scene->r.scemode & R_EXTENSION, TRUE);
+ BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE);
if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) {
printf("skipping existing frame \"%s\"\n", name);
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index a864fe306b3..8d748d3ea20 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -280,11 +280,6 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
sce->r.tiley = sce->r.ysch / 4;
}
- /* exception: don't apply render part of display transform for texture previews or icons */
- if ((id && sp->pr_method == PR_ICON_RENDER) || id_type == ID_TE) {
- BKE_scene_disable_color_management(sce);
- }
-
if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO)
sce->r.alphamode = R_ALPHAPREMUL;
else
@@ -488,24 +483,15 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
/* new UI convention: draw is in pixel space already. */
/* uses ROUNDBOX button in block to get the rect */
-static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int first, rcti *rect, rcti *newrect)
+static int ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, rcti *newrect)
{
Render *re;
RenderResult rres;
char name[32];
- int do_gamma_correct = FALSE, do_predivide = FALSE;
int offx = 0;
int newx = BLI_rcti_size_x(rect);
int newy = BLI_rcti_size_y(rect);
- if (id && GS(id->name) != ID_TE) {
- /* exception: don't color manage texture previews - show the raw values */
- if (sce) {
- do_gamma_correct = TRUE;
- do_predivide = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE;
- }
- }
-
if (!split || first) sprintf(name, "Preview %p", (void *)sa);
else sprintf(name, "SecondPreview %p", (void *)sa);
@@ -520,8 +506,10 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int
}
}
+ /* test if something rendered ok */
re = RE_GetRender(name);
RE_AcquireResultImage(re, &rres);
+ RE_ReleaseResultImage(re);
if (rres.rectf) {
@@ -531,40 +519,20 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int
newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty);
if (rres.rectx && rres.recty) {
- /* temporary conversion to byte for drawing */
+ unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect");
float fx = rect->xmin + offx;
float fy = rect->ymin;
- int dither = 0;
- unsigned char *rect_byte;
-
- rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect");
-
- if (do_gamma_correct) {
- IMB_display_buffer_transform_apply(rect_byte, rres.rectf, rres.rectx, rres.recty, 4,
- &sce->view_settings, &sce->display_settings, do_predivide);
-
- }
- else {
- /* OCIO_TODO: currently seems an exception for textures (came fro mlegacish time),
- * but is it indeed expected behavior, or textures should be
- * color managed as well?
- */
- IMB_buffer_byte_from_float(rect_byte, rres.rectf,
- 4, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, do_predivide,
- rres.rectx, rres.recty, rres.rectx, rres.rectx);
- }
-
+
+ RE_ResultGet32(re, (unsigned int *)rect_byte);
glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte);
-
+
MEM_freeN(rect_byte);
+
+ return 1;
}
-
- RE_ReleaseResultImage(re);
- return 1;
}
}
- RE_ReleaseResultImage(re);
return 0;
}
@@ -572,7 +540,6 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
{
if (idp) {
ScrArea *sa = CTX_wm_area(C);
- Scene *sce = CTX_data_scene(C);
ID *id = (ID *)idp;
ID *parent = (ID *)parentp;
MTex *slot = (MTex *)slotp;
@@ -588,11 +555,11 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
newrect.ymax = rect->ymin;
if (parent) {
- ok = ed_preview_draw_rect(sa, sce, id, 1, 1, rect, &newrect);
- ok &= ed_preview_draw_rect(sa, sce, parent, 1, 0, rect, &newrect);
+ ok = ed_preview_draw_rect(sa, 1, 1, rect, &newrect);
+ ok &= ed_preview_draw_rect(sa, 1, 0, rect, &newrect);
}
else
- ok = ed_preview_draw_rect(sa, sce, id, 0, 0, rect, &newrect);
+ ok = ed_preview_draw_rect(sa, 0, 0, rect, &newrect);
if (ok)
*rect = newrect;
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index bc33936b2e3..dfc53d0b195 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -1310,7 +1310,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, imtype);
+ BKE_add_image_extension(path, &scene->r.im_format);
}
WM_cursor_wait(1);
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index fbdec3dd8ad..5af60726f14 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -574,8 +574,8 @@ static void area_azone_initialize(bScreen *screen, ScrArea *sa)
az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
BLI_addtail(&(sa->actionzones), az);
az->type = AZONE_AREA;
- az->x1 = sa->totrct.xmin - 1;
- az->y1 = sa->totrct.ymin - 1;
+ az->x1 = sa->totrct.xmin;
+ az->y1 = sa->totrct.ymin;
az->x2 = sa->totrct.xmin + (AZONESPOT - 1);
az->y2 = sa->totrct.ymin + (AZONESPOT - 1);
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
@@ -917,7 +917,7 @@ static int region_is_overlap(wmWindow *win, ScrArea *sa, ARegion *ar)
{
if (U.uiflag2 & USER_REGION_OVERLAP)
if (WM_is_draw_triple(win))
- if (ELEM5(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_SEQ, SPACE_CLIP, SPACE_NODE))
+ if (ELEM4(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_SEQ, SPACE_CLIP))
if (ELEM3(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS))
return 1;
return 0;
@@ -1300,6 +1300,9 @@ void ED_region_init(bContext *C, ARegion *ar)
ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
ar->winy = BLI_rcti_size_y(&ar->winrct) + 1;
+ /* v2d mask is used to subtract scrollbars from a 2d view. Needs initialize here. */
+ BLI_rcti_init(&ar->v2d.mask, 0, ar->winx - 1, 0, ar->winy -1);
+
/* UI convention */
wmOrtho2(-0.01f, ar->winx - 0.01f, -0.01f, ar->winy - 0.01f);
glLoadIdentity();
@@ -1612,86 +1615,141 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
View2D *v2d = &ar->v2d;
View2DScrollers *scrollers;
int x, y, xco, yco, w, em, triangle, open, newcontext = 0;
-
+ int redo;
+ int scroll;
+
if (contextnr >= 0)
newcontext = UI_view2d_tab_set(v2d, contextnr);
-
+
+ /* before setting the view */
if (vertical) {
- w = BLI_rctf_size_x(&v2d->cur);
- em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+ /* only allow scrolling in vertical direction */
+ v2d->keepofs |= V2D_LOCKOFS_X | V2D_KEEPOFS_Y;
+ v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X);
+ v2d->scroll &= ~(V2D_SCROLL_BOTTOM);
+ v2d->scroll |= (V2D_SCROLL_RIGHT);
}
else {
- w = UI_PANEL_WIDTH;
- em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+ /* for now, allow scrolling in both directions (since layouts are optimized for vertical,
+ * they often don't fit in horizontal layout)
+ */
+ v2d->keepofs &= ~(V2D_LOCKOFS_X | V2D_LOCKOFS_Y | V2D_KEEPOFS_X | V2D_KEEPOFS_Y);
+ v2d->scroll |= (V2D_SCROLL_BOTTOM);
+ v2d->scroll &= ~(V2D_SCROLL_RIGHT);
}
- /* create panels */
- uiBeginPanels(C, ar);
+ scroll = v2d->scroll;
+
+ /* sortof hack - but we cannot predict the height of panels, until it's being generated */
+ /* the layout engine works with fixed width (from v2d->cur), which is being set at end of the loop */
+ /* in case scroller settings (hide flags) differ from previous, the whole loop gets done again */
+ for (redo = 2; redo > 0; redo--) {
+
+ if (vertical) {
+ w = BLI_rctf_size_x(&v2d->cur);
+ em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+ }
+ else {
+ w = UI_PANEL_WIDTH;
+ em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+ }
+
+ /* create panels */
+ uiBeginPanels(C, ar);
- /* set view2d view matrix for scrolling (without scrollers) */
- UI_view2d_view_ortho(v2d);
+ /* set view2d view matrix - uiBeginBlock() stores it */
+ UI_view2d_view_ortho(v2d);
- for (pt = ar->type->paneltypes.first; pt; pt = pt->next) {
- /* verify context */
- if (context)
- if (pt->context[0] && strcmp(context, pt->context) != 0)
- continue;
+ for (pt = ar->type->paneltypes.first; pt; pt = pt->next) {
+ /* verify context */
+ if (context)
+ if (pt->context[0] && strcmp(context, pt->context) != 0)
+ continue;
- /* draw panel */
- if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
- block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
- panel = uiBeginPanel(sa, ar, block, pt, &open);
+ /* draw panel */
+ if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
+ block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
+ panel = uiBeginPanel(sa, ar, block, pt, &open);
- /* bad fixed values */
- triangle = (int)(UI_UNIT_Y * 1.1f);
+ /* bad fixed values */
+ triangle = (int)(UI_UNIT_Y * 1.1f);
- if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
- /* for enabled buttons */
- panel->layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
- triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, style);
+ if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
+ /* for enabled buttons */
+ panel->layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
+ triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, style);
- pt->draw_header(C, panel);
+ pt->draw_header(C, panel);
- uiBlockLayoutResolve(block, &xco, &yco);
- panel->labelofs = xco - triangle;
- panel->layout = NULL;
- }
- else {
- panel->labelofs = 0;
- }
+ uiBlockLayoutResolve(block, &xco, &yco);
+ panel->labelofs = xco - triangle;
+ panel->layout = NULL;
+ }
+ else {
+ panel->labelofs = 0;
+ }
- if (open) {
- short panelContext;
-
- /* panel context can either be toolbar region or normal panels region */
- if (ar->regiontype == RGN_TYPE_TOOLS)
- panelContext = UI_LAYOUT_TOOLBAR;
- else
- panelContext = UI_LAYOUT_PANEL;
-
- panel->layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
- style->panelspace, 0, w - 2 * style->panelspace, em, style);
+ if (open) {
+ short panelContext;
+
+ /* panel context can either be toolbar region or normal panels region */
+ if (ar->regiontype == RGN_TYPE_TOOLS)
+ panelContext = UI_LAYOUT_TOOLBAR;
+ else
+ panelContext = UI_LAYOUT_PANEL;
+
+ panel->layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
+ style->panelspace, 0, w - 2 * style->panelspace, em, style);
- pt->draw(C, panel);
+ pt->draw(C, panel);
- uiBlockLayoutResolve(block, &xco, &yco);
- panel->layout = NULL;
+ uiBlockLayoutResolve(block, &xco, &yco);
+ panel->layout = NULL;
- yco -= 2 * style->panelspace;
- uiEndPanel(block, w, -yco);
- }
- else {
- yco = 0;
- uiEndPanel(block, w, 0);
+ yco -= 2 * style->panelspace;
+ uiEndPanel(block, w, -yco);
+ }
+ else {
+ yco = 0;
+ uiEndPanel(block, w, 0);
+ }
+
+ uiEndBlock(C, block);
}
+ }
- uiEndBlock(C, block);
+ /* align panels and return size */
+ uiEndPanels(C, ar, &x, &y);
+
+ /* before setting the view */
+ if (vertical) {
+ /* we always keep the scroll offset - so the total view gets increased with the scrolled away part */
+ if (v2d->cur.ymax < - 0.001f)
+ y = min_ii(y, v2d->cur.ymin);
+
+ y = -y;
+ }
+ else {
+ /* don't jump back when panels close or hide */
+ if (!newcontext)
+ x = max_ii(x, v2d->cur.xmax);
+ y = -y;
}
+
+ /* this also changes the 'cur' */
+ UI_view2d_totRect_set(v2d, x, y);
+
+ if (scroll != v2d->scroll) {
+ /* Note: this code scales fine, but because of rounding differences, positions of elements
+ * flip +1 or -1 pixel compared to redoing the entire layout again.
+ * Leaving in commented code for future tests */
+ /* uiScalePanels(ar, BLI_rctf_size_x(&v2d->cur));
+ break; */
+ }
+ else break;
}
-
- /* align panels and return size */
- uiEndPanels(C, ar, &x, &y);
-
+
+
/* clear */
if (ar->overlap) {
/* view should be in pixelspace */
@@ -1706,36 +1764,6 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
glClear(GL_COLOR_BUFFER_BIT);
}
- /* before setting the view */
- if (vertical) {
- /* only allow scrolling in vertical direction */
- v2d->keepofs |= V2D_LOCKOFS_X | V2D_KEEPOFS_Y;
- v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X);
- v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
- v2d->scroll &= ~V2D_SCROLL_VERTICAL_HIDE;
-
- /* ensure tot is set correctly, to keep views on bottons, with sliders */
- y = min_ii(y, v2d->cur.ymin);
- y = -y;
- }
- else {
- /* for now, allow scrolling in both directions (since layouts are optimized for vertical,
- * they often don't fit in horizontal layout)
- */
- v2d->keepofs &= ~(V2D_LOCKOFS_X | V2D_LOCKOFS_Y | V2D_KEEPOFS_X | V2D_KEEPOFS_Y);
- //v2d->keepofs |= V2D_LOCKOFS_Y|V2D_KEEPOFS_X;
- //v2d->keepofs &= ~(V2D_LOCKOFS_X|V2D_KEEPOFS_Y);
- v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
- v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_HIDE;
-
- /* don't jump back when panels close or hide */
- if (!newcontext)
- x = max_ii(x, v2d->cur.xmax);
- y = -y;
- }
-
- /* +V2D_SCROLL_HEIGHT is workaround to set the actual height (needs to be int) */
- UI_view2d_totRect_set(v2d, x + (int)V2D_SCROLL_WIDTH, y + (int)V2D_SCROLL_HEIGHT);
/* set the view */
UI_view2d_view_ortho(v2d);
@@ -1755,17 +1783,6 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
void ED_region_panels_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
- /* XXX quick hacks for files saved with 2.5 already (i.e. the builtin defaults file)
- * scrollbars for button regions */
- ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
- ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
- ar->v2d.scroll &= ~V2D_SCROLL_VERTICAL_HIDE;
- ar->v2d.keepzoom |= V2D_KEEPZOOM;
-
- /* correctly initialized User-Prefs? */
- if (!(ar->v2d.align & V2D_ALIGN_NO_POS_Y))
- ar->v2d.flag &= ~V2D_IS_INITIALISED;
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
@@ -1828,6 +1845,7 @@ void ED_region_header(const bContext *C, ARegion *ar)
void ED_region_header_init(ARegion *ar)
{
+ ar->v2d.flag &= ~V2D_IS_INITIALISED;
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
}
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index ca85daadf3b..2982e1f21af 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -223,7 +223,7 @@ static int screenshot_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)
static int screenshot_check(bContext *UNUSED(C), wmOperator *op)
{
ScreenshotData *scd = op->customdata;
- return WM_operator_filesel_ensure_ext_imtype(op, scd->im_format.imtype);
+ return WM_operator_filesel_ensure_ext_imtype(op, &scd->im_format);
}
static int screenshot_cancel(bContext *UNUSED(C), wmOperator *op)
@@ -361,7 +361,7 @@ 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.imtype, rd.scemode & R_EXTENSION, TRUE);
+ BKE_makepicstring(name, rd.pic, sj->bmain->name, rd.cfra, &rd.im_format, rd.scemode & R_EXTENSION, TRUE);
ibuf->rect = sj->dumprect;
ok = BKE_imbuf_write(ibuf, name, &rd.im_format);
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index ae72dce1415..5bed31e2e52 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -42,6 +42,7 @@ set(SRC
paint_cursor.c
paint_hide.c
paint_image.c
+ paint_image_2d.c
paint_mask.c
paint_ops.c
paint_stroke.c
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index 36fe4715fc0..d50261a3b98 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -112,8 +112,8 @@ static void partialvis_update_mesh(Object *ob,
int *vert_indices;
int any_changed = 0, any_visible = 0, totvert, i;
- BLI_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
- BLI_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
+ BKE_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
+ BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
paint_mask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK);
sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
@@ -136,8 +136,8 @@ static void partialvis_update_mesh(Object *ob,
}
if (any_changed) {
- BLI_pbvh_node_mark_rebuild_draw(node);
- BLI_pbvh_node_fully_hidden_set(node, !any_visible);
+ BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_fully_hidden_set(node, !any_visible);
}
}
@@ -157,11 +157,11 @@ static void partialvis_update_grids(Object *ob,
int *grid_indices, totgrid, any_changed, i;
/* get PBVH data */
- BLI_pbvh_node_get_grids(pbvh, node,
+ BKE_pbvh_node_get_grids(pbvh, node,
&grid_indices, &totgrid, NULL, NULL,
&grids, NULL);
- grid_hidden = BLI_pbvh_grid_hidden(pbvh);
- BLI_pbvh_get_grid_key(pbvh, &key);
+ grid_hidden = BKE_pbvh_grid_hidden(pbvh);
+ BKE_pbvh_get_grid_key(pbvh, &key);
sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
@@ -226,12 +226,81 @@ static void partialvis_update_grids(Object *ob,
/* mark updates if anything was hidden/shown */
if (any_changed) {
- BLI_pbvh_node_mark_rebuild_draw(node);
- BLI_pbvh_node_fully_hidden_set(node, !any_visible);
+ BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_fully_hidden_set(node, !any_visible);
multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED);
}
}
+static void partialvis_update_bmesh_verts(BMesh *bm,
+ GHash *verts,
+ PartialVisAction action,
+ PartialVisArea area,
+ float planes[4][4],
+ int *any_changed,
+ int *any_visible)
+{
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, verts) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ float *vmask = CustomData_bmesh_get(&bm->vdata,
+ v->head.data,
+ CD_PAINT_MASK);
+
+ /* hide vertex if in the hide volume */
+ if (is_effected(area, planes, v->co, *vmask)) {
+ if (action == PARTIALVIS_HIDE)
+ BM_elem_flag_enable(v, BM_ELEM_HIDDEN);
+ else
+ BM_elem_flag_disable(v, BM_ELEM_HIDDEN);
+ (*any_changed) = TRUE;
+ }
+
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
+ (*any_visible) = TRUE;
+ }
+}
+
+static void partialvis_update_bmesh(Object *ob,
+ PBVH *pbvh,
+ PBVHNode *node,
+ PartialVisAction action,
+ PartialVisArea area,
+ float planes[4][4])
+{
+ BMesh *bm;
+ GHash *unique, *other;
+ int any_changed = 0, any_visible = 0;
+
+ bm = BKE_pbvh_get_bmesh(pbvh);
+ unique = BKE_pbvh_bmesh_node_unique_verts(node);
+ other = BKE_pbvh_bmesh_node_other_verts(node);
+
+ sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
+
+ partialvis_update_bmesh_verts(bm,
+ unique,
+ action,
+ area,
+ planes,
+ &any_changed,
+ &any_visible);
+
+ partialvis_update_bmesh_verts(bm,
+ other,
+ action,
+ area,
+ planes,
+ &any_changed,
+ &any_visible);
+
+ if (any_changed) {
+ BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_fully_hidden_set(node, !any_visible);
+ }
+}
+
static void rect_from_props(rcti *rect, PointerRNA *ptr)
{
rect->xmin = RNA_int_get(ptr, "xmin");
@@ -265,22 +334,22 @@ static void get_pbvh_nodes(PBVH *pbvh,
float clip_planes[4][4],
PartialVisArea mode)
{
- BLI_pbvh_SearchCallback cb = NULL;
+ BKE_pbvh_SearchCallback cb = NULL;
/* select search callback */
switch (mode) {
case PARTIALVIS_INSIDE:
- cb = BLI_pbvh_node_planes_contain_AABB;
+ cb = BKE_pbvh_node_planes_contain_AABB;
break;
case PARTIALVIS_OUTSIDE:
- cb = BLI_pbvh_node_planes_exclude_AABB;
+ cb = BKE_pbvh_node_planes_exclude_AABB;
break;
case PARTIALVIS_ALL:
case PARTIALVIS_MASKED:
break;
}
- BLI_pbvh_search_gather(pbvh, cb, clip_planes, nodes, totnode);
+ BKE_pbvh_search_gather(pbvh, cb, clip_planes, nodes, totnode);
}
static int hide_show_exec(bContext *C, wmOperator *op)
@@ -310,7 +379,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
ob->sculpt->pbvh = pbvh;
get_pbvh_nodes(pbvh, &nodes, &totnode, clip_planes, area);
- pbvh_type = BLI_pbvh_type(pbvh);
+ pbvh_type = BKE_pbvh_type(pbvh);
/* start undo */
switch (action) {
@@ -330,6 +399,9 @@ static int hide_show_exec(bContext *C, wmOperator *op)
case PBVH_GRIDS:
partialvis_update_grids(ob, pbvh, nodes[i], action, area, clip_planes);
break;
+ case PBVH_BMESH:
+ partialvis_update_bmesh(ob, pbvh, nodes[i], action, area, clip_planes);
+ break;
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 8c9531e5554..fa8252c824d 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -42,7 +42,6 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_dynstr.h"
#include "BLI_linklist.h"
#include "BLI_memarena.h"
#include "BLI_threads.h"
@@ -54,13 +53,9 @@
#include "IMB_imbuf_types.h"
#include "DNA_brush_types.h"
-#include "DNA_camera_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_texture_types.h"
#include "BKE_camera.h"
#include "BKE_context.h"
@@ -77,8 +72,7 @@
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_scene.h"
-#include "BKE_global.h"
-#include "BKE_deform.h"
+#include "BKE_colortools.h"
#include "BKE_tessmesh.h"
@@ -102,7 +96,6 @@
#include "RNA_enum_types.h"
#include "GPU_draw.h"
-#include "GPU_extensions.h"
#include "IMB_colormanagement.h"
@@ -5142,15 +5135,16 @@ static int texture_paint_init(bContext *C, wmOperator *op)
return 0;
}
}
-
- paint_brush_init_tex(pop->s.brush);
-
+
/* note, if we have no UVs on the derived mesh, then we must return here */
if (pop->mode == PAINT_MODE_3D_PROJECT) {
/* initialize all data from the context */
project_state_init(C, OBACT, &pop->ps);
-
+
+ /* needed so multiple threads don't try to initialize the brush at once (can leak memory) */
+ curvemapping_initialize(pop->ps.brush->curve);
+
paint_brush_init_tex(pop->ps.brush);
pop->ps.source = PROJ_SRC_VIEW;
@@ -5168,6 +5162,9 @@ static int texture_paint_init(bContext *C, wmOperator *op)
if (pop->ps.dm == NULL)
return 0;
}
+ else {
+ paint_brush_init_tex(pop->s.brush);
+ }
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
@@ -5237,8 +5234,6 @@ static void paint_exit(bContext *C, wmOperator *op)
if (pop->restore_projection)
settings->imapaint.flag &= ~IMAGEPAINT_PROJECT_DISABLE;
- paint_brush_exit_tex(pop->s.brush);
-
settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
imapaint_canvas_free(&pop->s);
BKE_brush_painter_free(pop->painter);
@@ -5250,6 +5245,8 @@ static void paint_exit(bContext *C, wmOperator *op)
project_paint_end(&pop->ps);
}
else {
+ paint_brush_exit_tex(pop->s.brush);
+
/* non projection 3d paint, could move into own function of more needs adding */
if (pop->s.dm_release)
pop->s.dm->release(pop->s.dm);
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
new file mode 100644
index 00000000000..c30996f03de
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -0,0 +1,561 @@
+/*
+ * ***** 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/sculpt_paint/paint_image_2d.c
+ * \ingroup bke
+ */
+//#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_brush.h"
+
+#include "BLI_math.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "RE_shader_ext.h"
+
+ /* Brush Painting for 2D image editor */
+
+typedef struct BrushPainterCache {
+ short enabled;
+
+ int size; /* size override, if 0 uses 2*BKE_brush_size_get(brush) */
+ short flt; /* need float imbuf? */
+ short texonly; /* no alpha, color or fallof, only texture in imbuf */
+
+ int lastsize;
+ float lastalpha;
+ float lastjitter;
+
+ ImBuf *ibuf;
+ ImBuf *texibuf;
+ ImBuf *maskibuf;
+} BrushPainterCache;
+
+struct BrushPainter {
+ Scene *scene;
+ Brush *brush;
+
+ float lastmousepos[2]; /* mouse position of last paint call */
+
+ float accumdistance; /* accumulated distance of brush since last paint op */
+ float lastpaintpos[2]; /* position of last paint op */
+ float startpaintpos[2]; /* position of first paint */
+
+ double accumtime; /* accumulated time since last paint op (airbrush) */
+ double lasttime; /* time of last update */
+
+ float lastpressure;
+
+ short firsttouch; /* first paint op */
+
+ float startsize;
+ float startalpha;
+ float startjitter;
+ float startspacing;
+
+ BrushPainterCache cache;
+};
+
+BrushPainter *BKE_brush_painter_new(Scene *scene, Brush *brush)
+{
+ BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
+
+ painter->brush = brush;
+ painter->scene = scene;
+ painter->firsttouch = 1;
+ painter->cache.lastsize = -1; /* force ibuf create in refresh */
+
+ painter->startsize = BKE_brush_size_get(scene, brush);
+ painter->startalpha = BKE_brush_alpha_get(scene, brush);
+ painter->startjitter = brush->jitter;
+ painter->startspacing = brush->spacing;
+
+ return painter;
+}
+
+
+static void brush_pressure_apply(BrushPainter *painter, Brush *brush, float pressure)
+{
+ if (BKE_brush_use_alpha_pressure(painter->scene, brush))
+ BKE_brush_alpha_set(painter->scene, brush, max_ff(0.0f, painter->startalpha * pressure));
+ if (BKE_brush_use_size_pressure(painter->scene, brush))
+ BKE_brush_size_set(painter->scene, brush, max_ff(1.0f, painter->startsize * pressure));
+ if (brush->flag & BRUSH_JITTER_PRESSURE)
+ brush->jitter = max_ff(0.0f, painter->startjitter * pressure);
+ if (brush->flag & BRUSH_SPACING_PRESSURE)
+ brush->spacing = max_ff(1.0f, painter->startspacing * (1.5f - pressure));
+}
+
+
+void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
+{
+ if ((painter->cache.flt != flt) || (painter->cache.size != size) ||
+ ((painter->cache.texonly != texonly) && texonly))
+ {
+ if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
+ if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
+ painter->cache.ibuf = painter->cache.maskibuf = NULL;
+ painter->cache.lastsize = -1; /* force ibuf create in refresh */
+ }
+
+ if (painter->cache.flt != flt) {
+ if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
+ painter->cache.texibuf = NULL;
+ painter->cache.lastsize = -1; /* force ibuf create in refresh */
+ }
+
+ painter->cache.size = size;
+ painter->cache.flt = flt;
+ painter->cache.texonly = texonly;
+ painter->cache.enabled = 1;
+}
+
+void BKE_brush_painter_free(BrushPainter *painter)
+{
+ Brush *brush = painter->brush;
+
+ BKE_brush_size_set(painter->scene, brush, painter->startsize);
+ BKE_brush_alpha_set(painter->scene, brush, painter->startalpha);
+ brush->jitter = painter->startjitter;
+ brush->spacing = painter->startspacing;
+
+ if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
+ if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
+ if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
+ MEM_freeN(painter);
+}
+
+static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf,
+ int x, int y, int w, int h, int xt, int yt,
+ const float pos[2])
+{
+ Scene *scene = painter->scene;
+ Brush *brush = painter->brush;
+ ImBuf *ibuf, *maskibuf, *texibuf;
+ float *bf, *mf, *tf, *otf = NULL, xoff, yoff, xy[2], rgba[4];
+ unsigned char *b, *m, *t, *ot = NULL;
+ int dotexold, origx = x, origy = y;
+ const int radius = BKE_brush_size_get(painter->scene, brush);
+
+ xoff = -radius + 0.5f;
+ yoff = -radius + 0.5f;
+ xoff += (int)pos[0] - (int)painter->startpaintpos[0];
+ yoff += (int)pos[1] - (int)painter->startpaintpos[1];
+
+ ibuf = painter->cache.ibuf;
+ texibuf = painter->cache.texibuf;
+ maskibuf = painter->cache.maskibuf;
+
+ dotexold = (oldtexibuf != NULL);
+
+ /* not sure if it's actually needed or it's a mistake in coords/sizes
+ * calculation in brush_painter_fixed_tex_partial_update(), but without this
+ * limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */
+ w = min_ii(w, ibuf->x);
+ h = min_ii(h, ibuf->y);
+
+ if (painter->cache.flt) {
+ for (; y < h; y++) {
+ bf = ibuf->rect_float + (y * ibuf->x + origx) * 4;
+ tf = texibuf->rect_float + (y * texibuf->x + origx) * 4;
+ mf = maskibuf->rect_float + (y * maskibuf->x + origx) * 4;
+
+ if (dotexold)
+ otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
+
+ for (x = origx; x < w; x++, bf += 4, mf += 4, tf += 4) {
+ if (dotexold) {
+ copy_v3_v3(tf, otf);
+ tf[3] = otf[3];
+ otf += 4;
+ }
+ else {
+ xy[0] = x + xoff;
+ xy[1] = y + yoff;
+
+ BKE_brush_sample_tex(scene, brush, xy, tf, 0);
+ }
+
+ bf[0] = tf[0] * mf[0];
+ bf[1] = tf[1] * mf[1];
+ bf[2] = tf[2] * mf[2];
+ bf[3] = tf[3] * mf[3];
+ }
+ }
+ }
+ else {
+ for (; y < h; y++) {
+ b = (unsigned char *)ibuf->rect + (y * ibuf->x + origx) * 4;
+ t = (unsigned char *)texibuf->rect + (y * texibuf->x + origx) * 4;
+ m = (unsigned char *)maskibuf->rect + (y * maskibuf->x + origx) * 4;
+
+ if (dotexold)
+ ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
+
+ for (x = origx; x < w; x++, b += 4, m += 4, t += 4) {
+ if (dotexold) {
+ t[0] = ot[0];
+ t[1] = ot[1];
+ t[2] = ot[2];
+ t[3] = ot[3];
+ ot += 4;
+ }
+ else {
+ xy[0] = x + xoff;
+ xy[1] = y + yoff;
+
+ BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
+ rgba_float_to_uchar(t, rgba);
+ }
+
+ b[0] = t[0] * m[0] / 255;
+ b[1] = t[1] * m[1] / 255;
+ b[2] = t[2] * m[2] / 255;
+ b[3] = t[3] * m[3] / 255;
+ }
+ }
+ }
+}
+
+static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, const float pos[2])
+{
+ const Scene *scene = painter->scene;
+ Brush *brush = painter->brush;
+ BrushPainterCache *cache = &painter->cache;
+ ImBuf *oldtexibuf, *ibuf;
+ int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
+ const int diameter = 2 * BKE_brush_size_get(scene, brush);
+
+ imbflag = (cache->flt) ? IB_rectfloat : IB_rect;
+ if (!cache->ibuf)
+ cache->ibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
+ ibuf = cache->ibuf;
+
+ oldtexibuf = cache->texibuf;
+ cache->texibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
+
+ if (oldtexibuf) {
+ srcx = srcy = 0;
+ destx = (int)painter->lastpaintpos[0] - (int)pos[0];
+ desty = (int)painter->lastpaintpos[1] - (int)pos[1];
+ w = oldtexibuf->x;
+ h = oldtexibuf->y;
+
+ IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
+ }
+ else {
+ srcx = srcy = 0;
+ destx = desty = 0;
+ w = h = 0;
+ }
+
+ x1 = destx;
+ y1 = desty;
+ x2 = destx + w;
+ y2 = desty + h;
+
+ /* blend existing texture in new position */
+ if ((x1 < x2) && (y1 < y2))
+ brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
+
+ if (oldtexibuf)
+ IMB_freeImBuf(oldtexibuf);
+
+ /* sample texture in new areas */
+ if ((0 < x1) && (0 < ibuf->y))
+ brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
+ if ((x2 < ibuf->x) && (0 < ibuf->y))
+ brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
+ if ((x1 < x2) && (0 < y1))
+ brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
+ if ((x1 < x2) && (y2 < ibuf->y))
+ brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
+}
+
+static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction)
+{
+ const Scene *scene = painter->scene;
+ Brush *brush = painter->brush;
+ BrushPainterCache *cache = &painter->cache;
+ MTex *mtex = &brush->mtex;
+ int size;
+ short flt;
+ const int diameter = 2 * BKE_brush_size_get(scene, brush);
+ const float alpha = BKE_brush_alpha_get(scene, brush);
+
+ if (diameter != cache->lastsize ||
+ alpha != cache->lastalpha ||
+ brush->jitter != cache->lastjitter)
+ {
+ if (cache->ibuf) {
+ IMB_freeImBuf(cache->ibuf);
+ cache->ibuf = NULL;
+ }
+ if (cache->maskibuf) {
+ IMB_freeImBuf(cache->maskibuf);
+ cache->maskibuf = NULL;
+ }
+
+ flt = cache->flt;
+ size = (cache->size) ? cache->size : diameter;
+
+ if (brush->flag & BRUSH_FIXED_TEX) {
+ BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction);
+ brush_painter_fixed_tex_partial_update(painter, pos);
+ }
+ else
+ BKE_brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction);
+
+ cache->lastsize = diameter;
+ cache->lastalpha = alpha;
+ cache->lastjitter = brush->jitter;
+ }
+ else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
+ int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
+ int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
+
+ if ((dx != 0) || (dy != 0))
+ brush_painter_fixed_tex_partial_update(painter, pos);
+ }
+}
+
+void BKE_brush_painter_break_stroke(BrushPainter *painter)
+{
+ painter->firsttouch = 1;
+}
+
+
+int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2], double time, float pressure,
+ void *user, int use_color_correction)
+{
+ Scene *scene = painter->scene;
+ Brush *brush = painter->brush;
+ int totpaintops = 0;
+
+ if (pressure == 0.0f) {
+ if (painter->lastpressure) // XXX - hack, operator misses
+ pressure = painter->lastpressure;
+ else
+ pressure = 1.0f; /* zero pressure == not using tablet */
+ }
+ if (painter->firsttouch) {
+ /* paint exactly once on first touch */
+ painter->startpaintpos[0] = pos[0];
+ painter->startpaintpos[1] = pos[1];
+
+ brush_pressure_apply(painter, brush, pressure);
+ if (painter->cache.enabled)
+ brush_painter_refresh_cache(painter, pos, use_color_correction);
+ totpaintops += func(user, painter->cache.ibuf, pos, pos);
+
+ painter->lasttime = time;
+ painter->firsttouch = 0;
+ painter->lastpaintpos[0] = pos[0];
+ painter->lastpaintpos[1] = pos[1];
+ }
+#if 0
+ else if (painter->brush->flag & BRUSH_AIRBRUSH) {
+ float spacing, step, paintpos[2], dmousepos[2], len;
+ double starttime, curtime = time;
+
+ /* compute brush spacing adapted to brush size */
+ spacing = brush->rate; //radius*brush->spacing*0.01f;
+
+ /* setup starting time, direction vector and accumulated time */
+ starttime = painter->accumtime;
+ sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
+ len = normalize_v2(dmousepos);
+ painter->accumtime += curtime - painter->lasttime;
+
+ /* do paint op over unpainted time distance */
+ while (painter->accumtime >= spacing) {
+ step = (spacing - starttime) * len;
+ paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
+ paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
+
+ if (painter->cache.enabled)
+ brush_painter_refresh_cache(painter);
+ totpaintops += func(user, painter->cache.ibuf,
+ painter->lastpaintpos, paintpos);
+
+ painter->lastpaintpos[0] = paintpos[0];
+ painter->lastpaintpos[1] = paintpos[1];
+ painter->accumtime -= spacing;
+ starttime -= spacing;
+ }
+
+ painter->lasttime = curtime;
+ }
+#endif
+ else {
+ float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2];
+ float t, len, press;
+ const int radius = BKE_brush_size_get(scene, brush);
+
+ /* compute brush spacing adapted to brush radius, spacing may depend
+ * on pressure, so update it */
+ brush_pressure_apply(painter, brush, painter->lastpressure);
+ spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
+
+ /* setup starting distance, direction vector and accumulated distance */
+ startdistance = painter->accumdistance;
+ sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
+ len = normalize_v2(dmousepos);
+ painter->accumdistance += len;
+
+ if (brush->flag & BRUSH_SPACE) {
+ /* do paint op over unpainted distance */
+ while ((len > 0.0f) && (painter->accumdistance >= spacing)) {
+ step = spacing - startdistance;
+ paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
+ paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
+
+ t = step / len;
+ press = (1.0f - t) * painter->lastpressure + t * pressure;
+ brush_pressure_apply(painter, brush, press);
+ spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
+
+ BKE_brush_jitter_pos(scene, brush, paintpos, finalpos);
+
+ if (painter->cache.enabled)
+ brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+
+ totpaintops +=
+ func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos);
+
+ painter->lastpaintpos[0] = paintpos[0];
+ painter->lastpaintpos[1] = paintpos[1];
+ painter->accumdistance -= spacing;
+ startdistance -= spacing;
+ }
+ }
+ else {
+ BKE_brush_jitter_pos(scene, brush, pos, finalpos);
+
+ if (painter->cache.enabled)
+ brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+
+ totpaintops += func(user, painter->cache.ibuf, pos, finalpos);
+
+ painter->lastpaintpos[0] = pos[0];
+ painter->lastpaintpos[1] = pos[1];
+ painter->accumdistance = 0;
+ }
+
+ /* do airbrush paint ops, based on the number of paint ops left over
+ * from regular painting. this is a temporary solution until we have
+ * accurate time stamps for mouse move events */
+ if (brush->flag & BRUSH_AIRBRUSH) {
+ double curtime = time;
+ double painttime = brush->rate * totpaintops;
+
+ painter->accumtime += curtime - painter->lasttime;
+ if (painter->accumtime <= painttime)
+ painter->accumtime = 0.0;
+ else
+ painter->accumtime -= painttime;
+
+ while (painter->accumtime >= (double)brush->rate) {
+ brush_pressure_apply(painter, brush, pressure);
+
+ BKE_brush_jitter_pos(scene, brush, pos, finalpos);
+
+ if (painter->cache.enabled)
+ brush_painter_refresh_cache(painter, finalpos, use_color_correction);
+
+ totpaintops +=
+ func(user, painter->cache.ibuf, painter->lastmousepos, finalpos);
+ painter->accumtime -= (double)brush->rate;
+ }
+
+ painter->lasttime = curtime;
+ }
+ }
+
+ painter->lastmousepos[0] = pos[0];
+ painter->lastmousepos[1] = pos[1];
+ painter->lastpressure = pressure;
+
+ BKE_brush_alpha_set(scene, brush, painter->startalpha);
+ BKE_brush_size_set(scene, brush, painter->startsize);
+ brush->jitter = painter->startjitter;
+ brush->spacing = painter->startspacing;
+
+ return totpaintops;
+}
+
+
+/* TODO: should probably be unified with BrushPainter stuff? */
+unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
+{
+ unsigned int *texcache = NULL;
+ MTex *mtex = &br->mtex;
+ TexResult texres = {0};
+ int hasrgb, ix, iy;
+ int side = half_side * 2;
+
+ if (mtex->tex) {
+ float x, y, step = 2.0 / side, co[3];
+
+ texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
+
+ /*do normalized cannonical view coords for texture*/
+ for (y = -1.0, iy = 0; iy < side; iy++, y += step) {
+ for (x = -1.0, ix = 0; ix < side; ix++, x += step) {
+ co[0] = x;
+ co[1] = y;
+ co[2] = 0.0f;
+
+ /* This is copied from displace modifier code */
+ hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres);
+
+ /* if the texture gave an RGB value, we assume it didn't give a valid
+ * intensity, so calculate one (formula from do_material_tex).
+ * if the texture didn't give an RGB value, copy the intensity across
+ */
+ if (hasrgb & TEX_RGB)
+ texres.tin = rgb_to_grayscale(&texres.tr);
+
+ ((char *)texcache)[(iy * side + ix) * 4] =
+ ((char *)texcache)[(iy * side + ix) * 4 + 1] =
+ ((char *)texcache)[(iy * side + ix) * 4 + 2] =
+ ((char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(texres.tin * 255.0f);
+ }
+ }
+ }
+
+ return texcache;
+}
+
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 9fe7fc1d3ac..3cf67667f39 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -96,7 +96,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
pbvh = dm->getPBVH(ob, dm);
ob->sculpt->pbvh = pbvh;
- BLI_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
sculpt_undo_push_begin("Mask flood fill");
@@ -105,12 +105,12 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
sculpt_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
- BLI_pbvh_vertex_iter_begin(pbvh, nodes[i], vi, PBVH_ITER_UNIQUE) {
+ BKE_pbvh_vertex_iter_begin(pbvh, nodes[i], vi, PBVH_ITER_UNIQUE) {
mask_flood_fill_set_elem(vi.mask, mode, value);
- } BLI_pbvh_vertex_iter_end;
+ } BKE_pbvh_vertex_iter_end;
- BLI_pbvh_node_mark_update(nodes[i]);
- if (BLI_pbvh_type(pbvh) == PBVH_GRIDS)
+ BKE_pbvh_node_mark_update(nodes[i]);
+ if (BKE_pbvh_type(pbvh) == PBVH_GRIDS)
multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
}
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 10b9f26dbcd..9e702c16e2f 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -648,6 +648,18 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "PAINT_OT_mask_flood_fill", IKEY, KM_PRESS, KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "mode", PAINT_MASK_INVERT);
+ /* Toggle dynamic topology */
+ WM_keymap_add_item(keymap, "SCULPT_OT_dynamic_topology_toggle", DKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* Dynamic-topology detail size
+ *
+ * This should be improved further, perhaps by showing a triangle
+ * grid rather than brush alpha */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", DKEY, KM_PRESS, KM_SHIFT, 0);
+ set_brush_rc_props(kmi->ptr, "sculpt", "detail_size", NULL, 0);
+ RNA_string_set(kmi->ptr, "data_path_primary",
+ "tool_settings.sculpt.detail_size");
+
/* multires switch */
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_subdivision_set", PAGEUPKEY, KM_PRESS, 0, 0);
RNA_int_set(kmi->ptr, "level", 1);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 9ebeb61a7bb..2f4115dcd94 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -416,6 +416,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
if (!stroke->stroke_started) {
copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
+ BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */
if (stroke->stroke_started) {
stroke->smooth_stroke_cursor =
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 359486a4a8d..08c26aaa755 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -372,31 +372,22 @@ static int wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
bDeformGroup *defgroup = BLI_findlink(&ob->defbase, vgroup_active);
if (defgroup) {
- bDeformGroup *curdef;
int mirrdef;
char name[MAXBONENAME];
flip_side_name(name, defgroup->name, FALSE);
-
- if (strcmp(name, defgroup->name) != 0) {
- for (curdef = ob->defbase.first, mirrdef = 0; curdef; curdef = curdef->next, mirrdef++) {
- if (!strcmp(curdef->name, name)) {
- break;
- }
- }
-
- if (curdef == NULL) {
- int olddef = ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */
- curdef = ED_vgroup_add_name(ob, name);
- ob->actdef = olddef;
- }
-
- /* curdef should never be NULL unless this is
- * a lamp and ED_vgroup_add_name fails */
- if (curdef) {
- return mirrdef;
+ mirrdef = defgroup_name_index(ob, name);
+ if (mirrdef == -1) {
+ int olddef = ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */
+ if (ED_vgroup_add_name(ob, name)) {
+ mirrdef = BLI_countlist(&ob->defbase) - 1;
}
+ ob->actdef = olddef;
}
+
+ /* curdef should never be NULL unless this is
+ * a lamp and ED_vgroup_add_name fails */
+ return mirrdef;
}
return -1;
@@ -414,7 +405,7 @@ static void free_vpaint_prev(VPaint *vp)
static void free_wpaint_prev(VPaint *vp)
{
if (vp->wpaint_prev) {
- MEM_freeN(vp->wpaint_prev);
+ BKE_defvert_array_free(vp->wpaint_prev, vp->tot);
vp->wpaint_prev = NULL;
vp->tot = 0;
}
@@ -441,7 +432,7 @@ static void copy_wpaint_prev(VPaint *wp, MDeformVert *dverts, int dcount)
wp->wpaint_prev = MEM_mallocN(sizeof(MDeformVert) * dcount, "wpaint prev");
wp->tot = dcount;
- copy_dverts(wp->wpaint_prev, dverts, dcount);
+ BKE_defvert_array_copy(wp->wpaint_prev, dverts, dcount);
}
}
@@ -868,7 +859,10 @@ static float calc_vp_strength_dl(VPaint *vp, ViewContext *vc, const float co[3],
{
float vertco[2];
- if (ED_view3d_project_float_global(vc->ar, co, vertco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(vc->ar,
+ co, vertco,
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+ {
float delta[2];
float dist_squared;
@@ -1037,15 +1031,15 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
view3d_operator_needs_opengl(C);
if (use_vert_sel) {
- if (ED_mesh_pick_vert(C, me, event->mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE)) {
+ if (ED_mesh_pick_vert(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, TRUE)) {
v_idx_best = index;
}
}
else {
- if (ED_mesh_pick_face_vert(C, me, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
+ if (ED_mesh_pick_face_vert(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
v_idx_best = index;
}
- else if (ED_mesh_pick_face(C, me, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
+ else if (ED_mesh_pick_face(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
/* this relies on knowning the internal worksings of ED_mesh_pick_face_vert() */
BKE_report(op->reports, RPT_WARNING, "The modifier used does not support deformed locations");
}
@@ -1126,13 +1120,13 @@ static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA
view3d_operator_needs_opengl(C);
if (use_vert_sel) {
- if (ED_mesh_pick_vert(C, me, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE)) {
+ if (ED_mesh_pick_vert(C, vc.obact, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, TRUE)) {
MDeformVert *dvert = &me->dvert[index];
found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups);
}
}
else {
- if (ED_mesh_pick_face(C, me, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
+ if (ED_mesh_pick_face(C, vc.obact, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
MPoly *mp = &me->mpoly[index];
unsigned int fidx = mp->totloop - 1;
@@ -2058,32 +2052,28 @@ struct WPaintData {
int vgroup_mirror;
DMCoNo *vertexcosnos;
float wpimat[3][3];
-
+
/* variables for auto normalize */
const char *vgroup_validmap; /* stores if vgroups tie to deforming bones or not */
const char *lock_flags;
int defbase_tot;
};
-static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNUSED(mouse[2]))
+/* ensure we have data on wpaint start, add if needed */
+static int wpaint_ensure_data(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- struct PaintStroke *stroke = op->customdata;
- ToolSettings *ts = scene->toolsettings;
- VPaint *wp = ts->wpaint;
Object *ob = CTX_data_active_object(C);
- struct WPaintData *wpd;
- Mesh *me;
+ Mesh *me = BKE_mesh_from_object(ob);
- float mat[4][4], imat[4][4];
-
if (scene->obedit) {
return FALSE;
}
-
- me = BKE_mesh_from_object(ob);
- if (me == NULL || me->totpoly == 0) return OPERATOR_PASS_THROUGH;
-
+
+ if (me == NULL || me->totpoly == 0) {
+ return FALSE;
+ }
+
/* if nothing was added yet, we make dverts and a vertex deform group */
if (!me->dvert) {
ED_vgroup_data_create(&me->id);
@@ -2122,6 +2112,25 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNU
return FALSE;
}
+ return TRUE;
+}
+
+static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNUSED(mouse[2]))
+{
+ Scene *scene = CTX_data_scene(C);
+ struct PaintStroke *stroke = op->customdata;
+ ToolSettings *ts = scene->toolsettings;
+ VPaint *wp = ts->wpaint;
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me = BKE_mesh_from_object(ob);
+ struct WPaintData *wpd;
+
+ float mat[4][4], imat[4][4];
+
+ if (wpaint_ensure_data(C, op) == FALSE) {
+ return FALSE;
+ }
+
{
/* check if we are attempting to paint onto a locked vertex group,
* and other options disallow it from doing anything useful */
@@ -2184,7 +2193,15 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
unsigned int index, totindex;
float alpha;
float mval[2];
- int use_vert_sel;
+ bool use_vert_sel;
+ bool use_face_sel;
+ bool use_depth;
+
+ MDeformWeight *(*dw_func)(MDeformVert *, const int) =
+ (brush->vertexpaint_tool == PAINT_BLEND_BLUR) ?
+ ((wp->flag & VP_ONLYVGROUP) ?
+ (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index :
+ defvert_verify_index) : NULL;
const float pressure = RNA_float_get(itemptr, "pressure");
const float brush_size_pressure = BKE_brush_size_get(scene, brush) * (BKE_brush_use_size_pressure(scene, brush) ? pressure : 1.0f);
@@ -2201,7 +2218,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
ED_region_tag_redraw(CTX_wm_region(C));
return;
}
-
+
vc = &wpd->vc;
ob = vc->obact;
me = ob->data;
@@ -2242,31 +2259,38 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
swap_m4m4(wpd->vc.rv3d->persmat, mat);
use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ use_depth = (vc->v3d->flag & V3D_ZBUF_SELECT);
/* which faces are involved */
- if (wp->flag & VP_AREA) {
- /* Ugly hack, to avoid drawing vertex index when getting the face index buffer - campbell */
- me->editflag &= ~ME_EDIT_PAINT_VERT_SEL;
- totindex = sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure);
- me->editflag |= use_vert_sel ? ME_EDIT_PAINT_VERT_SEL : 0;
- }
- else {
- indexar[0] = view3d_sample_backbuf(vc, mval[0], mval[1]);
- if (indexar[0]) totindex = 1;
- else totindex = 0;
- }
+ if (use_depth) {
+ if (wp->flag & VP_AREA) {
+ /* Ugly hack, to avoid drawing vertex index when getting the face index buffer - campbell */
+ me->editflag &= ~ME_EDIT_PAINT_VERT_SEL;
+ totindex = sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure);
+ me->editflag |= use_vert_sel ? ME_EDIT_PAINT_VERT_SEL : 0;
+ }
+ else {
+ indexar[0] = view3d_sample_backbuf(vc, mval[0], mval[1]);
+ if (indexar[0]) totindex = 1;
+ else totindex = 0;
+ }
- if ((me->editflag & ME_EDIT_PAINT_FACE_SEL) && me->mpoly) {
- for (index = 0; index < totindex; index++) {
- if (indexar[index] && indexar[index] <= me->totpoly) {
- MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1);
-
- if ((mpoly->flag & ME_FACE_SEL) == 0) {
- indexar[index] = 0;
+ if (use_face_sel && me->mpoly) {
+ for (index = 0; index < totindex; index++) {
+ if (indexar[index] && indexar[index] <= me->totpoly) {
+ MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1);
+
+ if ((mpoly->flag & ME_FACE_SEL) == 0) {
+ indexar[index] = 0;
+ }
}
}
}
}
+ else {
+ indexar = NULL;
+ }
/* make sure each vertex gets treated only once */
/* and calculate filter weight */
@@ -2275,80 +2299,121 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
paintweight = 0.0f;
else
paintweight = BKE_brush_weight_get(scene, brush);
-
- for (index = 0; index < totindex; index++) {
- if (indexar[index] && indexar[index] <= me->totpoly) {
- MPoly *mpoly = me->mpoly + (indexar[index] - 1);
- MLoop *ml = me->mloop + mpoly->loopstart;
- int i;
- if (use_vert_sel) {
- for (i = 0; i < mpoly->totloop; i++, ml++) {
- me->dvert[ml->v].flag = (me->mvert[ml->v].flag & SELECT);
+#define WP_BLUR_ACCUM(v_idx_var) \
+ { \
+ const unsigned int vidx = v_idx_var; \
+ const float fac = calc_vp_strength_dl(wp, vc, wpd->vertexcosnos[vidx].co, mval, brush_size_pressure); \
+ if (fac > 0.0f) { \
+ MDeformWeight *dw = dw_func(&me->dvert[vidx], wpi.vgroup_active); \
+ paintweight += dw ? (dw->weight * fac) : 0.0f; \
+ totw += fac; \
+ } \
+ } (void)0
+
+
+ if (use_depth) {
+ for (index = 0; index < totindex; index++) {
+ if (indexar[index] && indexar[index] <= me->totpoly) {
+ MPoly *mpoly = me->mpoly + (indexar[index] - 1);
+ MLoop *ml = me->mloop + mpoly->loopstart;
+ int i;
+
+ if (use_vert_sel) {
+ for (i = 0; i < mpoly->totloop; i++, ml++) {
+ me->dvert[ml->v].flag = (me->mvert[ml->v].flag & SELECT);
+ }
}
- }
- else {
- for (i = 0; i < mpoly->totloop; i++, ml++) {
- me->dvert[ml->v].flag = 1;
+ else {
+ for (i = 0; i < mpoly->totloop; i++, ml++) {
+ me->dvert[ml->v].flag = 1;
+ }
}
- }
-
- if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
- MDeformWeight *dw, *(*dw_func)(MDeformVert *, const int);
-
- if (wp->flag & VP_ONLYVGROUP)
- dw_func = (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index;
- else
- dw_func = defvert_verify_index;
-
- ml = me->mloop + mpoly->loopstart;
- for (i = 0; i < mpoly->totloop; i++, ml++) {
- unsigned int vidx = ml->v;
- const float fac = calc_vp_strength_dl(wp, vc, wpd->vertexcosnos[vidx].co, mval, brush_size_pressure);
- if (fac > 0.0f) {
- dw = dw_func(&me->dvert[vidx], wpi.vgroup_active);
- paintweight += dw ? (dw->weight * fac) : 0.0f;
- totw += fac;
+
+ if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
+ ml = me->mloop + mpoly->loopstart;
+ for (i = 0; i < mpoly->totloop; i++, ml++) {
+ WP_BLUR_ACCUM(ml->v);
}
}
}
}
}
-
+ else {
+ const unsigned int totvert = me->totvert;
+ unsigned int i;
+
+ /* in the case of face selection we need to flush */
+ if (use_vert_sel || use_face_sel) {
+ for (i = 0; i < totvert; i++) {
+ me->dvert[i].flag = me->mvert[i].flag & SELECT;
+ }
+ }
+ else {
+ for (i = 0; i < totvert; i++) {
+ me->dvert[i].flag = SELECT;
+ }
+ }
+
+ if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
+ for (i = 0; i < totvert; i++) {
+ WP_BLUR_ACCUM(i);
+ }
+ }
+ }
+
+#undef WP_BLUR_ACCUM
+
+
if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
paintweight /= totw;
}
- for (index = 0; index < totindex; index++) {
+#define WP_PAINT(v_idx_var) \
+ { \
+ unsigned int vidx = v_idx_var; \
+ if (me->dvert[vidx].flag) { \
+ alpha = calc_vp_alpha_dl(wp, vc, wpd->wpimat, &wpd->vertexcosnos[vidx], \
+ mval, brush_size_pressure, brush_alpha_pressure); \
+ if (alpha) { \
+ do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight); \
+ } \
+ me->dvert[vidx].flag = 0; \
+ } \
+ } (void)0
+
+ if (use_depth) {
+ for (index = 0; index < totindex; index++) {
- if (indexar[index] && indexar[index] <= me->totpoly) {
- MPoly *mpoly = me->mpoly + (indexar[index] - 1);
- MLoop *ml = me->mloop + mpoly->loopstart;
- int i;
-
- for (i = 0; i < mpoly->totloop; i++, ml++) {
- unsigned int vidx = ml->v;
-
- if (me->dvert[vidx].flag) {
- alpha = calc_vp_alpha_dl(wp, vc, wpd->wpimat, &wpd->vertexcosnos[vidx],
- mval, brush_size_pressure, brush_alpha_pressure);
- if (alpha) {
- do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight);
- }
- me->dvert[vidx].flag = 0;
+ if (indexar[index] && indexar[index] <= me->totpoly) {
+ MPoly *mpoly = me->mpoly + (indexar[index] - 1);
+ MLoop *ml = me->mloop + mpoly->loopstart;
+ int i;
+
+ for (i = 0; i < mpoly->totloop; i++, ml++) {
+ WP_PAINT(ml->v);
}
}
}
}
+ else {
+ const unsigned int totvert = me->totvert;
+ unsigned int i;
+
+ for (i = 0; i < totvert; i++) {
+ WP_PAINT(i);
+ }
+ }
+#undef WP_PAINT
/* *** free wpi members */
MEM_freeN((void *)wpi.defbase_sel);
- /* *** don't freeing wpi members */
+ /* *** done freeing wpi members */
swap_m4m4(vc->rv3d->persmat, mat);
-
+
DAG_id_tag_update(ob->data, 0);
ED_region_tag_redraw(vc->ar);
}
@@ -2442,7 +2507,7 @@ void PAINT_OT_weight_paint(wmOperatorType *ot)
RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
}
-static int weight_paint_set_exec(bContext *C, wmOperator *UNUSED(op))
+static int weight_paint_set_exec(bContext *C, wmOperator *op)
{
struct Scene *scene = CTX_data_scene(C);
Object *obact = CTX_data_active_object(C);
@@ -2450,6 +2515,10 @@ static int weight_paint_set_exec(bContext *C, wmOperator *UNUSED(op))
Brush *brush = paint_brush(&ts->wpaint->paint);
float vgroup_weight = BKE_brush_weight_get(scene, brush);
+ if (wpaint_ensure_data(C, op) == FALSE) {
+ return OPERATOR_CANCELLED;
+ }
+
wpaint_fill(scene->toolsettings->wpaint, obact, vgroup_weight);
ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */
return OPERATOR_FINISHED;
@@ -2992,9 +3061,9 @@ static void gradientVert__mapFunc(void *userData, int index, const float co[3],
* the screen coords of the verts need to be cached because
* updating the mesh may move them about (entering feedback loop) */
if (grad_data->is_init) {
- if (ED_view3d_project_float_global(grad_data->ar,
+ if (ED_view3d_project_float_object(grad_data->ar,
co, vs->sco,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
/* ok */
MDeformVert *dv = &me->dvert[index];
@@ -3022,11 +3091,9 @@ static void gradientVert__mapFunc(void *userData, int index, const float co[3],
if (grad_data->type == WPAINT_GRADIENT_TYPE_LINEAR) {
alpha = line_point_factor_v2(vs->sco, grad_data->sco_start, grad_data->sco_end);
}
- else if (grad_data->type == WPAINT_GRADIENT_TYPE_RADIAL) {
- alpha = len_v2v2(grad_data->sco_start, vs->sco) * grad_data->sco_line_div;
- }
else {
- BLI_assert(0);
+ BLI_assert(grad_data->type == WPAINT_GRADIENT_TYPE_RADIAL);
+ alpha = len_v2v2(grad_data->sco_start, vs->sco) * grad_data->sco_line_div;
}
/* no need to clamp 'alpha' yet */
@@ -3082,7 +3149,7 @@ static int paint_weight_gradient_modal(bContext *C, wmOperator *op, wmEvent *eve
VPaint *wp = ts->wpaint;
Object *ob = CTX_data_active_object(C);
Mesh *me = ob->data;
- copy_dverts(me->dvert, wp->wpaint_prev, me->totvert);
+ BKE_defvert_array_copy(me->dvert, wp->wpaint_prev, me->totvert);
free_wpaint_prev(wp);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -3159,7 +3226,13 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
static int paint_weight_gradient_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
- int ret = WM_gesture_straightline_invoke(C, op, event);
+ int ret;
+
+ if (wpaint_ensure_data(C, op) == FALSE) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ret = WM_gesture_straightline_invoke(C, op, event);
if (ret & OPERATOR_RUNNING_MODAL) {
struct ARegion *ar = CTX_wm_region(C);
if (ar->regiontype == RGN_TYPE_WINDOW) {
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 8325b47beab..54ae2ebf588 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -65,6 +65,7 @@
#include "BKE_report.h"
#include "BKE_lattice.h" /* for armature_deform_verts */
#include "BKE_node.h"
+#include "BKE_object.h"
#include "BKE_subsurf.h"
#include "BIF_glutil.h"
@@ -86,6 +87,8 @@
#include "GPU_buffers.h"
+#include "bmesh.h"
+
#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -98,8 +101,13 @@ void ED_sculpt_force_update(bContext *C)
{
Object *ob = CTX_data_active_object(C);
- if (ob && (ob->mode & OB_MODE_SCULPT))
+ if (ob && (ob->mode & OB_MODE_SCULPT)) {
multires_force_update(ob);
+
+ /* Set reorder=false so that saving the file doesn't reorder
+ * the BMesh's elements */
+ sculptsession_bm_to_me(ob, FALSE);
+ }
}
float *ED_sculpt_get_last_stroke(struct Object *ob)
@@ -172,7 +180,8 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
Mesh *me = (Mesh *)ob->data;
MultiresModifierData *mmd = sculpt_multires_active(scene, ob);
- if (mmd) return 0;
+ if (mmd || ob->sculpt->bm)
+ return 0;
/* non-locked shape keys could be handled in the same way as deformed mesh */
if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr)
@@ -281,12 +290,130 @@ typedef struct StrokeCache {
rcti previous_r; /* previous redraw rectangle */
} StrokeCache;
+/************** Access to original unmodified vertex data *************/
+
+typedef struct {
+ BMLog *bm_log;
+
+ SculptUndoNode *unode;
+ float (*coords)[3];
+ short (*normals)[3];
+ float *vmasks;
+
+ /* Original coordinate, normal, and mask */
+ const float *co;
+ float mask;
+ short no[3];
+} SculptOrigVertData;
+
+
+/* Initialize a SculptOrigVertData for accessing original vertex data;
+ * handles BMesh, mesh, and multires */
+static void sculpt_orig_vert_data_unode_init(SculptOrigVertData *data,
+ Object *ob,
+ SculptUndoNode *unode)
+{
+ SculptSession *ss = ob->sculpt;
+ BMesh *bm = ss->bm;
+
+ memset(data, 0, sizeof(*data));
+ data->unode = unode;
+
+ if (bm) {
+ data->bm_log = ss->bm_log;
+ }
+ else {
+ data->coords = data->unode->co;
+ data->normals = data->unode->no;
+ data->vmasks = data->unode->mask;
+ }
+}
+
+/* Initialize a SculptOrigVertData for accessing original vertex data;
+ * handles BMesh, mesh, and multires */
+static void sculpt_orig_vert_data_init(SculptOrigVertData *data,
+ Object *ob,
+ PBVHNode *node)
+{
+ SculptUndoNode *unode;
+ unode = sculpt_undo_push_node(ob, node, SCULPT_UNDO_COORDS);
+ sculpt_orig_vert_data_unode_init(data, ob, unode);
+
+}
+
+/* Update a SculptOrigVertData for a particular vertex from the PBVH
+ * iterator */
+static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data,
+ PBVHVertexIter *iter)
+{
+ if (orig_data->unode->type == SCULPT_UNDO_COORDS) {
+ if (orig_data->coords) {
+ orig_data->co = orig_data->coords[iter->i];
+ }
+ else {
+ orig_data->co = BM_log_original_vert_co(orig_data->bm_log, iter->bm_vert);
+ }
+
+ if (orig_data->normals) {
+ copy_v3_v3_short(orig_data->no, orig_data->normals[iter->i]);
+ }
+ else {
+ /* TODO: log doesn't store normals yet */
+ normal_float_to_short_v3(orig_data->no, iter->bm_vert->no);
+ }
+ }
+ else if (orig_data->unode->type == SCULPT_UNDO_MASK) {
+ if (orig_data->vmasks) {
+ orig_data->mask = orig_data->vmasks[iter->i];
+ }
+ else {
+ orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert);
+ }
+ }
+}
+
+/**********************************************************************/
+
+/* Returns true if the stroke will use dynamic topology, false
+ otherwise.
+
+ Factors: some brushes like grab cannot do dynamic topology.
+ Others, like smooth, are better without. Same goes for alt-
+ key smoothing. */
+static int sculpt_stroke_dynamic_topology(const SculptSession *ss,
+ const Brush *brush)
+{
+ return ((BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) &&
+
+ (!ss->cache || (!ss->cache->alt_smooth)) &&
+
+ /* Requires mesh restore, which doesn't work with
+ * dynamic-topology */
+ !(brush->flag & BRUSH_ANCHORED) &&
+ !(brush->flag & BRUSH_RESTORE_MESH) &&
+
+ (!ELEM6(brush->sculpt_tool,
+ /* These brushes, as currently coded, cannot
+ * support dynamic topology */
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_LAYER,
+
+ /* These brushes could handle dynamic topology,
+ * but user feedback indicates it's better not
+ * to */
+ SCULPT_TOOL_SMOOTH,
+ SCULPT_TOOL_MASK)));
+}
/*** paint mesh ***/
-static void paint_mesh_restore_co(Sculpt *sd, SculptSession *ss)
+static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
{
+ SculptSession *ss = ob->sculpt;
StrokeCache *cache = ss->cache;
+ const Brush *brush = paint_brush(&sd->paint);
int i;
PBVHNode **nodes;
@@ -296,31 +423,38 @@ static void paint_mesh_restore_co(Sculpt *sd, SculptSession *ss)
(void)sd; /* quied unused warning */
#endif
- BLI_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
for (n = 0; n < totnode; n++) {
SculptUndoNode *unode;
-
- unode = sculpt_undo_get_node(nodes[n]);
+ SculptUndoType type = (brush->sculpt_tool == SCULPT_TOOL_MASK ?
+ SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
+
+ unode = sculpt_undo_push_node(ob, nodes[n], type);
if (unode) {
PBVHVertexIter vd;
+ SculptOrigVertData orig_data;
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ sculpt_orig_vert_data_unode_init(&orig_data, ob, unode);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (unode->type == SCULPT_UNDO_COORDS) {
- copy_v3_v3(vd.co, unode->co[vd.i]);
- if (vd.no) copy_v3_v3_short(vd.no, unode->no[vd.i]);
- else normal_short_to_float_v3(vd.fno, unode->no[vd.i]);
+ sculpt_orig_vert_data_update(&orig_data, &vd);
+
+ if (orig_data.unode->type == SCULPT_UNDO_COORDS) {
+ copy_v3_v3(vd.co, orig_data.co);
+ if (vd.no) copy_v3_v3_short(vd.no, orig_data.no);
+ else normal_short_to_float_v3(vd.fno, orig_data.no);
}
- else if (unode->type == SCULPT_UNDO_MASK) {
- *vd.mask = unode->mask[vd.i];
+ else if (orig_data.unode->type == SCULPT_UNDO_MASK) {
+ *vd.mask = orig_data.mask;
}
if (vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
- BLI_pbvh_node_mark_update(nodes[n]);
+ BKE_pbvh_node_mark_update(nodes[n]);
}
}
@@ -347,7 +481,7 @@ static int sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d,
if (!pbvh)
return 0;
- BLI_pbvh_redraw_BB(pbvh, bb_min, bb_max);
+ BKE_pbvh_redraw_BB(pbvh, bb_min, bb_max);
/* convert 3D bounding box to screen space */
if (!paint_convert_bb_to_rect(rect,
@@ -387,7 +521,7 @@ void sculpt_get_redraw_planes(float planes[4][4], ARegion *ar,
/* clear redraw flag from nodes */
if (pbvh)
- BLI_pbvh_update(pbvh, PBVH_UpdateRedraw, NULL);
+ BKE_pbvh_update(pbvh, PBVH_UpdateRedraw, NULL);
}
/************************ Brush Testing *******************/
@@ -405,7 +539,7 @@ static void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test)
test->dist = 0.0f; /* just for initialize */
}
-static int sculpt_brush_test(SculptBrushTest *test, float co[3])
+static int sculpt_brush_test(SculptBrushTest *test, const float co[3])
{
float distsq = len_squared_v3v3(co, test->location);
@@ -418,7 +552,7 @@ static int sculpt_brush_test(SculptBrushTest *test, float co[3])
}
}
-static int sculpt_brush_test_sq(SculptBrushTest *test, float co[3])
+static int sculpt_brush_test_sq(SculptBrushTest *test, const float co[3])
{
float distsq = len_squared_v3v3(co, test->location);
@@ -734,7 +868,8 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather)
}
/* Return a multiplier for brush strength on a particular vertex. */
-static float tex_strength(SculptSession *ss, Brush *br, float point[3],
+static float tex_strength(SculptSession *ss, Brush *br,
+ const float point[3],
const float len,
const float sculpt_normal[3],
const short vno[3],
@@ -871,9 +1006,9 @@ static int sculpt_search_sphere_cb(PBVHNode *node, void *data_v)
int i;
if (data->original)
- BLI_pbvh_node_get_original_BB(node, bb_min, bb_max);
+ BKE_pbvh_node_get_original_BB(node, bb_min, bb_max);
else
- BLI_pbvh_node_get_BB(node, bb_min, bb_max);
+ BKE_pbvh_node_get_BB(node, bb_min, bb_max);
for (i = 0; i < 3; ++i) {
if (bb_min[i] > center[i])
@@ -926,6 +1061,11 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
original = (paint_brush(&sd->paint)->sculpt_tool == SCULPT_TOOL_GRAB ?
TRUE : ss->cache->original);
+ /* In general the original coords are not available with dynamic
+ * topology */
+ if (ss->bm)
+ original = FALSE;
+
(void)sd; /* unused w/o openmp */
zero_v3(an);
@@ -942,7 +1082,7 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
sculpt_brush_test_init(ss, &test);
if (original) {
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_fast(&test, unode->co[vd.i])) {
float fno[3];
@@ -951,10 +1091,10 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno);
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
else {
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_fast(&test, vd.co)) {
if (vd.no) {
@@ -968,7 +1108,7 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
}
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
#pragma omp critical
@@ -1210,6 +1350,71 @@ static float neighbor_average_mask(SculptSession *ss, unsigned vert)
return vmask[vert];
}
+/* Same logic as neighbor_average(), but for bmesh rather than mesh */
+static void bmesh_neighbor_average(float avg[3], BMVert *v)
+{
+ const int vfcount = BM_vert_face_count(v);
+
+ zero_v3(avg);
+
+ /* Don't modify corner vertices */
+ if (vfcount > 1) {
+ BMIter liter;
+ BMLoop *l;
+ int i, total = 0;
+
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ BMVert *adj_v[3] = {l->prev->v, v, l->next->v};
+
+ for (i = 0; i < 3; i++) {
+ if (vfcount != 2 || BM_vert_face_count(adj_v[i]) <= 2) {
+ add_v3_v3(avg, adj_v[i]->co);
+ total++;
+ }
+ }
+ }
+
+ if (total > 0) {
+ mul_v3_fl(avg, 1.0f / total);
+ return;
+ }
+ }
+
+ copy_v3_v3(avg, v->co);
+}
+
+/* Same logic as neighbor_average_mask(), but for bmesh rather than mesh */
+static float bmesh_neighbor_average_mask(BMesh *bm, BMVert *v)
+{
+ BMIter liter;
+ BMLoop *l;
+ float avg = 0;
+ int i, total = 0;
+
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ BMVert *adj_v[3] = {l->prev->v, v, l->next->v};
+
+ for (i = 0; i < 3; i++) {
+ BMVert *v2 = adj_v[i];
+ float *vmask = CustomData_bmesh_get(&bm->vdata,
+ v2->head.data,
+ CD_PAINT_MASK);
+ avg += (*vmask);
+ total++;
+ }
+ }
+
+ if (total > 0) {
+ return avg / (float)total;
+ }
+ else {
+ float *vmask = CustomData_bmesh_get(&bm->vdata,
+ v->head.data,
+ CD_PAINT_MASK);
+ return (*vmask);
+ }
+}
+
static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, float bstrength, int smooth_mask)
{
Brush *brush = paint_brush(&sd->paint);
@@ -1220,7 +1425,7 @@ static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
@@ -1248,7 +1453,48 @@ static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void do_bmesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, float bstrength, int smooth_mask)
+{
+ Brush *brush = paint_brush(&sd->paint);
+ PBVHVertexIter vd;
+ SculptBrushTest test;
+
+ CLAMP(bstrength, 0.0f, 1.0f);
+
+ sculpt_brush_test_init(ss, &test);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ if (sculpt_brush_test(&test, vd.co)) {
+ const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
+ ss->cache->view_normal, vd.no, vd.fno,
+ smooth_mask ? 0 : *vd.mask);
+ if (smooth_mask) {
+ float val = bmesh_neighbor_average_mask(ss->bm, vd.bm_vert) - *vd.mask;
+ val *= fade * bstrength;
+ *vd.mask += val;
+ CLAMP(*vd.mask, 0, 1);
+ }
+ else {
+ float avg[3], val[3];
+
+ bmesh_neighbor_average(avg, vd.bm_vert);
+ sub_v3_v3v3(val, avg, vd.co);
+ mul_v3_fl(val, fade);
+
+ add_v3_v3(val, vd.co);
+
+ sculpt_clip(sd, ss, vd.co, val);
+ }
+
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
@@ -1269,9 +1515,9 @@ static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *no
CLAMP(bstrength, 0.0f, 1.0f);
- BLI_pbvh_node_get_grids(ss->pbvh, node, &grid_indices, &totgrid,
+ BKE_pbvh_node_get_grids(ss->pbvh, node, &grid_indices, &totgrid,
NULL, &gridsize, &griddata, &gridadj);
- BLI_pbvh_get_grid_key(ss->pbvh, &key);
+ BKE_pbvh_get_grid_key(ss->pbvh, &key);
thread_num = 0;
#ifdef _OPENMP
@@ -1405,7 +1651,7 @@ static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode,
SculptSession *ss = ob->sculpt;
const int max_iterations = 4;
const float fract = 1.0f / max_iterations;
- PBVHType type = BLI_pbvh_type(ss->pbvh);
+ PBVHType type = BKE_pbvh_type(ss->pbvh);
int iteration, n, count;
float last;
@@ -1433,6 +1679,9 @@ static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode,
do_mesh_smooth_brush(sd, ss, nodes[n], strength,
smooth_mask);
break;
+ case PBVH_BMESH:
+ do_bmesh_smooth_brush(sd, ss, nodes[n], strength, smooth_mask);
+ break;
}
}
@@ -1462,7 +1711,7 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
float fade = tex_strength(ss, brush, vd.co, test.dist,
@@ -1474,7 +1723,7 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot
if (vd.mvert)
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
}
@@ -1514,11 +1763,11 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
/* offset vertex */
@@ -1532,7 +1781,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1570,11 +1819,11 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
/* offset vertex */
@@ -1597,7 +1846,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1614,11 +1863,11 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
@@ -1633,7 +1882,7 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1659,26 +1908,27 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
- SculptUndoNode *unode;
SculptBrushTest test;
- float (*origco)[3];
- short (*origno)[3];
+ SculptOrigVertData orig_data;
float (*proxy)[3];
- unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
- origco = unode->co;
- origno = unode->no;
+ sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test(&test, origco[vd.i])) {
- const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist,
- ss->cache->sculpt_normal_symm, origno[vd.i],
- NULL, vd.mask ? *vd.mask : 0.0f);
+ sculpt_orig_vert_data_update(&orig_data, &vd);
+
+ if (sculpt_brush_test(&test, orig_data.co)) {
+ const float fade = bstrength * tex_strength(ss, brush,
+ orig_data.co,
+ test.dist,
+ ss->cache->sculpt_normal_symm,
+ orig_data.no,
+ NULL, vd.mask ? *vd.mask : 0.0f);
mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
@@ -1686,7 +1936,7 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1710,11 +1960,11 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
@@ -1727,7 +1977,7 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1759,11 +2009,11 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
@@ -1776,7 +2026,7 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1797,26 +2047,27 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
- SculptUndoNode *unode;
SculptBrushTest test;
- float (*origco)[3];
- short (*origno)[3];
+ SculptOrigVertData orig_data;
float (*proxy)[3];
- unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
- origco = unode->co;
- origno = unode->no;
+ sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test(&test, origco[vd.i])) {
- const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist,
+ sculpt_orig_vert_data_update(&orig_data, &vd);
+
+ if (sculpt_brush_test(&test, orig_data.co)) {
+ const float fade = bstrength * tex_strength(ss, brush,
+ orig_data.co,
+ test.dist,
ss->cache->sculpt_normal_symm,
- origno[vd.i], NULL, vd.mask ? *vd.mask : 0.0f);
+ orig_data.no,
+ NULL, vd.mask ? *vd.mask : 0.0f);
mul_v3_v3fl(proxy[vd.i], cono, fade);
@@ -1824,7 +2075,7 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1850,36 +2101,37 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
- SculptUndoNode *unode;
SculptBrushTest test;
- float (*origco)[3];
- short (*origno)[3];
+ SculptOrigVertData orig_data;
float (*proxy)[3];
- unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
- origco = unode->co;
- origno = unode->no;
+ sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test(&test, origco[vd.i])) {
- const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist,
+ sculpt_orig_vert_data_update(&orig_data, &vd);
+
+ if (sculpt_brush_test(&test, orig_data.co)) {
+ const float fade = bstrength * tex_strength(ss, brush,
+ orig_data.co,
+ test.dist,
ss->cache->sculpt_normal_symm,
- origno[vd.i], NULL, vd.mask ? *vd.mask : 0.0f);
+ orig_data.no,
+ NULL, vd.mask ? *vd.mask : 0.0f);
- mul_v3_m4v3(proxy[vd.i], m, origco[vd.i]);
- sub_v3_v3(proxy[vd.i], origco[vd.i]);
+ mul_v3_m4v3(proxy[vd.i], m, orig_data.co);
+ sub_v3_v3(proxy[vd.i], orig_data.co);
mul_v3_fl(proxy[vd.i], fade);
if (vd.mvert)
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1901,25 +2153,25 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
- SculptUndoNode *unode;
- float (*origco)[3], *layer_disp;
+ SculptOrigVertData orig_data;
+ float *layer_disp;
/* XXX: layer brush needs conversion to proxy but its more complicated */
- /* proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; */
+ /* proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; */
- unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
- origco = unode->co;
- if (!unode->layer_disp) {
- #pragma omp critical
- unode->layer_disp = MEM_callocN(sizeof(float) * unode->totvert, "layer disp");
- }
-
- layer_disp = unode->layer_disp;
+ sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
+ #pragma omp critical
+ {
+ layer_disp = BKE_pbvh_node_layer_disp_get(ss->pbvh, nodes[n]);
+ }
+
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test(&test, origco[vd.i])) {
+ sculpt_orig_vert_data_update(&orig_data, &vd);
+
+ if (sculpt_brush_test(&test, orig_data.co)) {
const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
ss->cache->sculpt_normal_symm,
vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f);
@@ -1941,7 +2193,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
add_v3_v3(val, ss->layer_co[index]);
}
else {
- add_v3_v3(val, origco[vd.i]);
+ add_v3_v3(val, orig_data.co);
}
sculpt_clip(sd, ss, vd.co, val);
@@ -1950,7 +2202,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1967,11 +2219,11 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
@@ -1989,7 +2241,7 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -2016,24 +2268,24 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
sculpt_brush_test_init(ss, &test);
if (ss->cache->original) {
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_fast(&test, unode->co[vd.i])) {
add_v3_v3(private_fc, unode->co[vd.i]);
private_count++;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
else {
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_fast(&test, vd.co)) {
add_v3_v3(private_fc, vd.co);
private_count++;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
#pragma omp critical
@@ -2082,8 +2334,8 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
sculpt_brush_test_init(ss, &test);
- if (ss->cache->original) {
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ if (ss->cache->original && unode->co) {
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_fast(&test, unode->co[vd.i])) {
/* for area normal */
@@ -2097,10 +2349,10 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
private_count++;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
else {
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_fast(&test, vd.co)) {
/* for area normal */
@@ -2119,7 +2371,7 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
private_count++;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
#pragma omp critical
@@ -2301,11 +2553,11 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq(&test, vd.co)) {
float intr[3];
@@ -2326,7 +2578,7 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
}
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -2373,11 +2625,11 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq(&test, vd.co)) {
if (plane_point_side_flip(vd.co, an, fc, flip)) {
@@ -2401,7 +2653,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
}
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -2475,11 +2727,11 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_cube(&test, vd.co, mat)) {
if (plane_point_side_flip(vd.co, sn, fc, flip)) {
@@ -2503,7 +2755,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
}
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -2539,11 +2791,11 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq(&test, vd.co)) {
if (plane_point_side(vd.co, an, fc)) {
@@ -2567,7 +2819,7 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
}
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -2603,11 +2855,11 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq(&test, vd.co)) {
if (!plane_point_side(vd.co, an, fc)) {
@@ -2631,7 +2883,7 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
}
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -2688,6 +2940,65 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
BKE_key_convert_from_vertcos(ob, kb, vertCos);
}
+/* Note: we do the topology update before any brush actions to avoid
+ * issues with the proxies. The size of the proxy can't change, so
+ * topology must be updated first. */
+static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
+{
+ SculptSession *ss = ob->sculpt;
+ SculptSearchSphereData data;
+ PBVHNode **nodes = NULL;
+ float radius;
+ int n, totnode;
+
+ /* Build a list of all nodes that are potentially within the
+ * brush's area of influence */
+ data.ss = ss;
+ data.sd = sd;
+
+ radius = ss->cache->radius * 1.25f;
+
+ data.radius_squared = radius * radius;
+ data.original = ELEM4(brush->sculpt_tool,
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_LAYER);
+
+ BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
+
+ /* Only act if some verts are inside the brush area */
+ if (totnode) {
+ PBVHTopologyUpdateMode mode = PBVH_Subdivide;
+
+ if ((sd->flags & SCULPT_DYNTOPO_COLLAPSE) ||
+ (brush->sculpt_tool == SCULPT_TOOL_SIMPLIFY))
+ {
+ mode |= PBVH_Collapse;
+ }
+
+ for (n = 0; n < totnode; n++) {
+ sculpt_undo_push_node(ob, nodes[n],
+ brush->sculpt_tool == SCULPT_TOOL_MASK ?
+ SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
+ BKE_pbvh_node_mark_update(nodes[n]);
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ BKE_pbvh_node_mark_topology_update(nodes[n]);
+ BKE_pbvh_bmesh_node_save_orig(nodes[n]);
+ }
+ }
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ BKE_pbvh_bmesh_update_topology(ss->pbvh, mode,
+ ss->cache->location,
+ ss->cache->radius);
+ }
+
+ MEM_freeN(nodes);
+ }
+}
+
static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
{
SculptSession *ss = ob->sculpt;
@@ -2704,7 +3015,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
SCULPT_TOOL_ROTATE,
SCULPT_TOOL_THUMB,
SCULPT_TOOL_LAYER);
- BLI_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
+ BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
/* Only act if some verts are inside the brush area */
if (totnode) {
@@ -2713,7 +3024,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
sculpt_undo_push_node(ob, nodes[n],
brush->sculpt_tool == SCULPT_TOOL_MASK ?
SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
- BLI_pbvh_node_mark_update(nodes[n]);
+ BKE_pbvh_node_mark_update(nodes[n]);
}
if (brush_needs_sculpt_normal(brush))
@@ -2821,7 +3132,7 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
PBVHNode **nodes;
int totnode, n;
- BLI_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
+ BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_LAYER)) {
/* these brushes start from original coordinates */
@@ -2835,18 +3146,25 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
int proxy_count;
float (*orco)[3];
- if (use_orco)
+ if (use_orco && !ss->bm)
orco = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS)->co;
- BLI_pbvh_node_get_proxies(nodes[n], &proxies, &proxy_count);
+ BKE_pbvh_node_get_proxies(nodes[n], &proxies, &proxy_count);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
float val[3];
int p;
- if (use_orco)
- copy_v3_v3(val, orco[vd.i]);
+ if (use_orco) {
+ if (ss->bm) {
+ copy_v3_v3(val,
+ BM_log_original_vert_co(ss->bm_log,
+ vd.bm_vert));
+ }
+ else
+ copy_v3_v3(val, orco[vd.i]);
+ }
else
copy_v3_v3(val, vd.co);
@@ -2858,9 +3176,9 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
if (ss->modifiers_active)
sculpt_flush_pbvhvert_deform(ob, &vd);
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
- BLI_pbvh_node_free_proxies(nodes[n]);
+ BKE_pbvh_node_free_proxies(nodes[n]);
}
}
@@ -2877,7 +3195,7 @@ static void sculpt_update_keyblock(Object *ob)
/* Keyblock update happens after handling deformation caused by modifiers,
* so ss->orig_cos would be updated with new stroke */
if (ss->orig_cos) vertCos = ss->orig_cos;
- else vertCos = BLI_pbvh_get_vertCos(ss->pbvh);
+ else vertCos = BKE_pbvh_get_vertCos(ss->pbvh);
if (vertCos) {
sculpt_vertcos_to_key(ob, ss->kb, vertCos);
@@ -2905,13 +3223,13 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob)
if (ss->kb)
vertCos = MEM_callocN(sizeof(*vertCos) * me->totvert, "flushStrokeDeofrm keyVerts");
- BLI_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
sculpt_flush_pbvhvert_deform(ob, &vd);
@@ -2920,7 +3238,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob)
copy_v3_v3(vertCos[index], ss->orig_cos[index]);
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
if (vertCos) {
@@ -2978,7 +3296,10 @@ static void calc_brushdata_symm(Sculpt *sd, StrokeCache *cache, const char symm,
mul_m4_v3(cache->symm_rot_mat, cache->grab_delta_symmetry);
}
+typedef void (*BrushActionFunc)(Sculpt *sd, Object *ob, Brush *brush);
+
static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush,
+ BrushActionFunc action,
const char symm, const int axis,
const float feather)
{
@@ -2989,7 +3310,7 @@ static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush,
const float angle = 2 * M_PI * i / sd->radial_symm[axis - 'X'];
ss->cache->radial_symmetry_pass = i;
calc_brushdata_symm(sd, ss->cache, symm, axis, angle, feather);
- do_brush_action(sd, ob, brush);
+ action(sd, ob, brush);
}
}
@@ -3006,7 +3327,8 @@ static void sculpt_fix_noise_tear(Sculpt *sd, Object *ob)
multires_stitch_grids(ob);
}
-static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob)
+static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob,
+ BrushActionFunc action)
{
Brush *brush = paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
@@ -3017,7 +3339,6 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob)
float feather = calc_symmetry_feather(sd, ss->cache);
cache->bstrength = brush_strength(sd, cache, feather);
-
cache->symmetry = symm;
/* symm is a bit combination of XYZ - 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
@@ -3027,23 +3348,13 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob)
cache->radial_symmetry_pass = 0;
calc_brushdata_symm(sd, cache, i, 0, 0, feather);
- do_brush_action(sd, ob, brush);
+ action(sd, ob, brush);
- do_radial_symmetry(sd, ob, brush, i, 'X', feather);
- do_radial_symmetry(sd, ob, brush, i, 'Y', feather);
- do_radial_symmetry(sd, ob, brush, i, 'Z', feather);
+ do_radial_symmetry(sd, ob, brush, action, i, 'X', feather);
+ do_radial_symmetry(sd, ob, brush, action, i, 'Y', feather);
+ do_radial_symmetry(sd, ob, brush, action, i, 'Z', feather);
}
}
-
- sculpt_combine_proxies(sd, ob);
-
- /* hack to fix noise texture tearing mesh */
- sculpt_fix_noise_tear(sd, ob);
-
- if (ss->modifiers_active)
- sculpt_flush_stroke_deform(sd, ob);
-
- cache->first_time = 0;
}
static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
@@ -3142,7 +3453,7 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
ss->orig_cos = (ss->kb) ? BKE_key_convert_to_vertcos(ob, ss->kb) : mesh_getVertexCos(me, NULL);
crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos);
- BLI_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos);
+ BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos);
for (a = 0; a < me->totvert; ++a) {
invert_m3(ss->deform_imats[a]);
@@ -3152,12 +3463,12 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
else free_sculptsession_deformMats(ss);
/* if pbvh is deformed, key block is already applied to it */
- if (ss->kb && !BLI_pbvh_isDeformed(ss->pbvh)) {
+ if (ss->kb && !BKE_pbvh_isDeformed(ss->pbvh)) {
float (*vertCos)[3] = BKE_key_convert_to_vertcos(ob, ss->kb);
if (vertCos) {
/* apply shape keys coordinates to PBVH */
- BLI_pbvh_apply_vertCos(ss->pbvh, vertCos);
+ BKE_pbvh_apply_vertCos(ss->pbvh, vertCos);
MEM_freeN(vertCos);
}
}
@@ -3220,6 +3531,8 @@ static const char *sculpt_tool_name(Sculpt *sd)
return "Rotate Brush";
case SCULPT_TOOL_MASK:
return "Mask Brush";
+ case SCULPT_TOOL_SIMPLIFY:
+ return "Simplify Brush";
}
return "Sculpting";
@@ -3291,7 +3604,7 @@ static void sculpt_omp_start(Sculpt *sd, SculptSession *ss)
if (ss->multires) {
int i, gridsize, array_mem_size;
- BLI_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL,
+ BKE_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL,
&gridsize, NULL, NULL);
array_mem_size = cache->num_threads * sizeof(void *);
@@ -3406,8 +3719,9 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
ED_view3d_global_to_vector(cache->vc->rv3d, cache->vc->rv3d->twmat[3], cache->true_view_normal);
/* Initialize layer brush displacements and persistent coords */
if (brush->sculpt_tool == SCULPT_TOOL_LAYER) {
- /* not supported yet for multires */
- if (!ss->multires && !ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) {
+ /* not supported yet for multires or dynamic topology */
+ if (!ss->multires && !ss->bm && !ss->layer_co &&
+ (brush->flag & BRUSH_PERSISTENT)) {
if (!ss->layer_co)
ss->layer_co = MEM_mallocN(sizeof(float) * 3 * ss->totvert,
"sculpt mesh vertices copy");
@@ -3721,17 +4035,26 @@ typedef struct {
static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
{
- if (BLI_pbvh_node_get_tmin(node) < *tmin) {
+ if (BKE_pbvh_node_get_tmin(node) < *tmin) {
SculptRaycastData *srd = data_v;
float (*origco)[3] = NULL;
+ int use_origco = FALSE;
if (srd->original && srd->ss->cache) {
- /* intersect with coordinates from before we started stroke */
- SculptUndoNode *unode = sculpt_undo_get_node(node);
- origco = (unode) ? unode->co : NULL;
+ if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) {
+ use_origco = TRUE;
+ }
+ else {
+ /* intersect with coordinates from before we started stroke */
+ SculptUndoNode *unode = sculpt_undo_get_node(node);
+ origco = (unode) ? unode->co : NULL;
+ use_origco = origco ? TRUE : FALSE;
+ }
}
- if (BLI_pbvh_node_raycast(srd->ss->pbvh, node, origco, srd->ray_start, srd->ray_normal, &srd->dist)) {
+ if (BKE_pbvh_node_raycast(srd->ss->pbvh, node, origco, use_origco,
+ srd->ray_start, srd->ray_normal, &srd->dist))
+ {
srd->hit = 1;
*tmin = srd->dist;
}
@@ -3780,7 +4103,7 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
srd.dist = dist;
srd.hit = 0;
srd.original = (cache) ? cache->original : 0;
- BLI_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd,
+ BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd,
ray_start, ray_normal, srd.original);
copy_v3_v3(out, ray_normal);
@@ -3829,8 +4152,9 @@ static int sculpt_brush_stroke_init(bContext *C, wmOperator *op)
return 1;
}
-static void sculpt_restore_mesh(Sculpt *sd, SculptSession *ss)
+static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
{
+ SculptSession *ss = ob->sculpt;
Brush *brush = paint_brush(&sd->paint);
/* Restore the mesh before continuing with anchored stroke */
@@ -3839,7 +4163,7 @@ static void sculpt_restore_mesh(Sculpt *sd, SculptSession *ss)
BKE_brush_use_size_pressure(ss->cache->vc->scene, brush)) ||
(brush->flag & BRUSH_RESTORE_MESH))
{
- paint_mesh_restore_co(sd, ss);
+ paint_mesh_restore_co(sd, ob);
}
}
@@ -3862,7 +4186,7 @@ static void sculpt_flush_update(bContext *C)
else {
rcti r;
- BLI_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL);
+ BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL);
if (sculpt_get_redraw_rect(ar, CTX_wm_region_view3d(C), ob, &r)) {
if (ss->cache)
ss->cache->previous_r = r;
@@ -3917,11 +4241,33 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
+ const Brush *brush = paint_brush(&sd->paint);
sculpt_stroke_modifiers_check(C, ob);
sculpt_update_cache_variants(C, sd, ob, stroke, itemptr);
- sculpt_restore_mesh(sd, ss);
- do_symmetrical_brush_actions(sd, ob);
+ sculpt_restore_mesh(sd, ob);
+
+ BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
+ (ss->cache->radius /
+ (float)ss->cache->pixel_radius) *
+ (float)sd->detail_size);
+
+ if (sculpt_stroke_dynamic_topology(ss, brush)) {
+ do_symmetrical_brush_actions(sd, ob, sculpt_topology_update);
+ }
+
+ if (paint_brush(&sd->paint)->sculpt_tool != SCULPT_TOOL_SIMPLIFY)
+ do_symmetrical_brush_actions(sd, ob, do_brush_action);
+
+ sculpt_combine_proxies(sd, ob);
+
+ /* hack to fix noise texture tearing mesh */
+ sculpt_fix_noise_tear(sd, ob);
+
+ if (ss->modifiers_active)
+ sculpt_flush_stroke_deform(sd, ob);
+
+ ss->cache->first_time = FALSE;
/* Cleanup */
sculpt_flush_update(C);
@@ -3980,7 +4326,10 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
sculpt_undo_push_end();
- BLI_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL);
+ BKE_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL);
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH)
+ BKE_pbvh_bmesh_after_stroke(ss->pbvh);
/* optimization: if there is locked key and active modifiers present in */
/* the stack, keyblock is updating at each step. otherwise we could update */
@@ -4055,7 +4404,7 @@ static int sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
if (ss->cache) {
- paint_mesh_restore_co(sd, ss);
+ paint_mesh_restore_co(sd, ob);
}
paint_stroke_cancel(C, op);
@@ -4137,6 +4486,266 @@ static void SCULPT_OT_set_persistent_base(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/************************** Dynamic Topology **************************/
+
+static void sculpt_dynamic_topology_triangulate(BMesh *bm)
+{
+ BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "triangulate faces=%af");
+}
+
+void sculpt_pbvh_clear(Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ DerivedMesh *dm = ob->derivedFinal;
+
+ /* Clear out any existing DM and PBVH */
+ if (ss->pbvh)
+ BKE_pbvh_free(ss->pbvh);
+ ss->pbvh = NULL;
+ if (dm)
+ dm->getPBVH(NULL, dm);
+ BKE_object_free_display(ob);
+}
+
+void sculpt_update_after_dynamic_topology_toggle(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ Sculpt *sd = scene->toolsettings->sculpt;
+
+ /* Create the PBVH */
+ sculpt_update_mesh_elements(scene, sd, ob, FALSE, FALSE);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+}
+
+void sculpt_dynamic_topology_enable(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Mesh *me = ob->data;
+
+ sculpt_pbvh_clear(ob);
+
+ ss->bm_smooth_shading = (scene->toolsettings->sculpt->flags &
+ SCULPT_DYNTOPO_SMOOTH_SHADING);
+
+ /* Create triangles-only BMesh */
+ ss->bm = BM_mesh_create(&bm_mesh_allocsize_default);
+
+ BM_mesh_bm_from_me(ss->bm, me, TRUE, ob->shapenr);
+ sculpt_dynamic_topology_triangulate(ss->bm);
+ BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
+ BM_mesh_normals_update(ss->bm, TRUE);
+
+ /* Enable dynamic topology */
+ me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
+
+ /* Enable logging for undo/redo */
+ ss->bm_log = BM_log_create(ss->bm);
+
+ /* Refresh */
+ sculpt_update_after_dynamic_topology_toggle(C);
+}
+
+/* Free the sculpt BMesh and BMLog
+ *
+ * If 'unode' is given, the BMesh's data is copied out to the unode
+ * before the BMesh is deleted so that it can be restored from */
+void sculpt_dynamic_topology_disable(bContext *C,
+ SculptUndoNode *unode)
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Mesh *me = ob->data;
+
+ sculpt_pbvh_clear(ob);
+
+ if (unode) {
+ /* Free all existing custom data */
+ CustomData_free(&me->vdata, me->totvert);
+ CustomData_free(&me->edata, me->totedge);
+ CustomData_free(&me->fdata, me->totface);
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
+
+ /* Copy over stored custom data */
+ me->totvert = unode->bm_enter_totvert;
+ me->totloop = unode->bm_enter_totloop;
+ me->totpoly = unode->bm_enter_totpoly;
+ me->totedge = unode->bm_enter_totedge;
+ me->totface = 0;
+ CustomData_copy(&unode->bm_enter_vdata, &me->vdata, CD_MASK_MESH,
+ CD_DUPLICATE, unode->bm_enter_totvert);
+ CustomData_copy(&unode->bm_enter_edata, &me->edata, CD_MASK_MESH,
+ CD_DUPLICATE, unode->bm_enter_totedge);
+ CustomData_copy(&unode->bm_enter_ldata, &me->ldata, CD_MASK_MESH,
+ CD_DUPLICATE, unode->bm_enter_totloop);
+ CustomData_copy(&unode->bm_enter_pdata, &me->pdata, CD_MASK_MESH,
+ CD_DUPLICATE, unode->bm_enter_totpoly);
+
+ mesh_update_customdata_pointers(me, FALSE);
+ } else {
+ sculptsession_bm_to_me(ob, TRUE);
+ }
+
+ BM_mesh_free(ss->bm);
+
+ /* Clear data */
+ me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
+ ss->bm = NULL;
+ BM_log_free(ss->bm_log);
+ ss->bm_log = NULL;
+
+ /* Refresh */
+ sculpt_update_after_dynamic_topology_toggle(C);
+}
+
+static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+
+ if (ss->bm) {
+ sculpt_undo_push_begin("Dynamic topology disable");
+ sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END);
+ sculpt_dynamic_topology_disable(C, NULL);
+ }
+ else {
+ sculpt_undo_push_begin("Dynamic topology enable");
+ sculpt_dynamic_topology_enable(C);
+ sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
+ }
+ sculpt_undo_push_end();
+
+ return OPERATOR_FINISHED;
+}
+
+static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op,
+ wmEvent *UNUSED(event))
+{
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me = ob->data;
+ SculptSession *ss = ob->sculpt;
+ const char *msg = "Dynamic-topology sculpting will not preserve"
+ "vertex colors, UVs, or other customdata";
+
+ if (!ss->bm) {
+ int i;
+
+ for (i = 0; i < CD_NUMTYPES; i++) {
+ if (!ELEM7(i, CD_MVERT, CD_MEDGE, CD_MFACE,
+ CD_MLOOP, CD_MPOLY, CD_PAINT_MASK,
+ CD_ORIGINDEX) &&
+ (CustomData_has_layer(&me->vdata, i) ||
+ CustomData_has_layer(&me->edata, i) ||
+ CustomData_has_layer(&me->fdata, i))) {
+ /* The mesh has customdata that will be lost, let the
+ * user confirm this is OK */
+ return WM_operator_confirm_message(C, op, msg);
+ }
+ }
+ }
+
+ return sculpt_dynamic_topology_toggle_exec(C, op);
+}
+
+static void SCULPT_OT_dynamic_topology_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Dynamic Topology Toggle";
+ ot->idname = "SCULPT_OT_dynamic_topology_toggle";
+ ot->description = "Dynamic topology alters the mesh topology while sculpting";
+
+ /* api callbacks */
+ ot->invoke = sculpt_dynamic_topology_toggle_invoke;
+ ot->exec = sculpt_dynamic_topology_toggle_exec;
+ ot->poll = sculpt_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/************************* SCULPT_OT_optimize *************************/
+
+static int sculpt_optimize_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_active_object(C);
+
+ sculpt_pbvh_clear(ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int sculpt_and_dynamic_topology_poll(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+
+ return sculpt_mode_poll(C) && ob->sculpt->bm;
+}
+
+/* The BVH gets less optimal more quickly with dynamic topology than
+ * regular sculpting. There is no doubt more clever stuff we can do to
+ * optimize it on the fly, but for now this gives the user a nicer way
+ * to recalculate it than toggling modes. */
+static void SCULPT_OT_optimize(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Optimize";
+ ot->idname = "SCULPT_OT_optimize";
+ ot->description = "Recalculate the sculpt BVH to improve performance";
+
+ /* api callbacks */
+ ot->exec = sculpt_optimize_exec;
+ ot->poll = sculpt_and_dynamic_topology_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/********************* Dynamic topology symmetrize ********************/
+
+static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_active_object(C);
+ const Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ SculptSession *ss = ob->sculpt;
+
+ /* To simplify undo for symmetrize, all BMesh elements are logged
+ * as deleted, then after symmetrize operation all BMesh elements
+ * are logged as added (as opposed to attempting to store just the
+ * parts that symmetrize modifies) */
+ sculpt_undo_push_begin("Dynamic topology symmetrize");
+ sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_SYMMETRIZE);
+ BM_log_before_all_removed(ss->bm, ss->bm_log);
+
+ /* Symmetrize and re-triangulate */
+ BMO_op_callf(ss->bm, BMO_FLAG_DEFAULTS,
+ "symmetrize input=%avef direction=%i",
+ sd->symmetrize_direction);
+ sculpt_dynamic_topology_triangulate(ss->bm);
+
+ /* Finish undo */
+ BM_log_all_added(ss->bm, ss->bm_log);
+ sculpt_undo_push_end();
+
+ /* Redraw */
+ sculpt_pbvh_clear(ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static void SCULPT_OT_symmetrize(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Symmetrize";
+ ot->idname = "SCULPT_OT_symmetrize";
+
+ /* api callbacks */
+ ot->exec = sculpt_symmetrize_exec;
+ ot->poll = sculpt_and_dynamic_topology_poll;
+}
+
/**** Toggle operator for turning sculpt mode on or off ****/
static void sculpt_init_session(Scene *scene, Object *ob)
@@ -4222,6 +4831,7 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = CTX_data_tool_settings(C);
Object *ob = CTX_data_active_object(C);
+ Mesh *me = ob->data;
MultiresModifierData *mmd = sculpt_multires_active(scene, ob);
int flush_recalc = 0;
@@ -4234,9 +4844,16 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op))
if (mmd)
multires_force_update(ob);
- if (flush_recalc)
+ if (flush_recalc || (ob->sculpt && ob->sculpt->bm))
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
+ /* Dynamic topology must be disabled before exiting sculpt
+ * mode to ensure the undo stack stays in a consistent
+ * state */
+ sculpt_dynamic_topology_toggle_exec(C, NULL);
+ }
+
/* Leave sculptmode */
ob->mode &= ~OB_MODE_SCULPT;
@@ -4257,6 +4874,9 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op))
ts->sculpt->flags |= SCULPT_SYMM_X;
}
+ if (!ts->sculpt->detail_size)
+ ts->sculpt->detail_size = 30;
+
/* Create sculpt mode session data */
if (ob->sculpt)
free_sculptsession(ob);
@@ -4271,7 +4891,7 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op))
}
BKE_paint_init(&ts->sculpt->paint, PAINT_CURSOR_SCULPT);
-
+
paint_cursor_start(C, sculpt_poll);
}
@@ -4299,4 +4919,7 @@ void ED_operatortypes_sculpt(void)
WM_operatortype_append(SCULPT_OT_brush_stroke);
WM_operatortype_append(SCULPT_OT_sculptmode_toggle);
WM_operatortype_append(SCULPT_OT_set_persistent_base);
+ WM_operatortype_append(SCULPT_OT_dynamic_topology_toggle);
+ WM_operatortype_append(SCULPT_OT_optimize);
+ WM_operatortype_append(SCULPT_OT_symmetrize);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 44068122b89..e56962a3964 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -49,6 +49,7 @@ struct Object;
struct Scene;
struct Sculpt;
struct SculptStroke;
+struct SculptUndoNode;
/* Interface */
struct MultiresModifierData *sculpt_multires_active(struct Scene *scene, struct Object *ob);
@@ -67,12 +68,22 @@ void free_sculptsession_deformMats(struct SculptSession *ss);
/* Stroke */
int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]);
+/* Dynamic topology */
+void sculpt_pbvh_clear(Object *ob);
+void sculpt_update_after_dynamic_topology_toggle(bContext *C);
+void sculpt_dynamic_topology_enable(struct bContext *C);
+void sculpt_dynamic_topology_disable(struct bContext *C,
+ struct SculptUndoNode *unode);
+
/* Undo */
typedef enum {
SCULPT_UNDO_COORDS,
SCULPT_UNDO_HIDDEN,
- SCULPT_UNDO_MASK
+ SCULPT_UNDO_MASK,
+ SCULPT_UNDO_DYNTOPO_BEGIN,
+ SCULPT_UNDO_DYNTOPO_END,
+ SCULPT_UNDO_DYNTOPO_SYMMETRIZE,
} SculptUndoType;
typedef struct SculptUndoNode {
@@ -101,8 +112,17 @@ typedef struct SculptUndoNode {
int *grids; /* to restore into right location */
BLI_bitmap *grid_hidden;
- /* layer brush */
- float *layer_disp;
+ /* bmesh */
+ struct BMLogEntry *bm_entry;
+ int applied;
+ CustomData bm_enter_vdata;
+ CustomData bm_enter_edata;
+ CustomData bm_enter_ldata;
+ CustomData bm_enter_pdata;
+ int bm_enter_totvert;
+ int bm_enter_totedge;
+ int bm_enter_totloop;
+ int bm_enter_totpoly;
/* shape keys */
char shapeName[sizeof(((KeyBlock *)0))->name];
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 1b3fd24ae22..c828e8c8651 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -65,6 +65,7 @@
#include "GPU_buffers.h"
#include "ED_sculpt.h"
+#include "bmesh.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
@@ -72,10 +73,10 @@
static void update_cb(PBVHNode *node, void *rebuild)
{
- BLI_pbvh_node_mark_update(node);
+ BKE_pbvh_node_mark_update(node);
if (*((int *)rebuild))
- BLI_pbvh_node_mark_rebuild_draw(node);
- BLI_pbvh_node_fully_hidden_set(node, 0);
+ BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_fully_hidden_set(node, 0);
}
static void sculpt_undo_restore_deformed(const SculptSession *ss,
@@ -142,7 +143,7 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo
/* pbvh uses it's own mvert array, so coords should be */
/* propagated to pbvh here */
- BLI_pbvh_apply_vertCos(ss->pbvh, vertCos);
+ BKE_pbvh_apply_vertCos(ss->pbvh, vertCos);
MEM_freeN(vertCos);
}
@@ -261,6 +262,111 @@ static int sculpt_undo_restore_mask(bContext *C, DerivedMesh *dm, SculptUndoNode
return 1;
}
+static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode,
+ Object *ob,
+ SculptSession *ss)
+{
+ if (unode->applied) {
+ BM_log_undo(ss->bm, ss->bm_log);
+ unode->applied = FALSE;
+ }
+ else {
+ BM_log_redo(ss->bm, ss->bm_log);
+ unode->applied = TRUE;
+ }
+
+ /* A bit lame, but for now just recreate the PBVH. The alternative
+ * is to store changes to the PBVH in the undo stack. */
+ sculpt_pbvh_clear(ob);
+}
+
+/* Create empty sculpt BMesh and enable logging */
+static void sculpt_undo_bmesh_enable(Object *ob,
+ SculptUndoNode *unode)
+{
+ SculptSession *ss = ob->sculpt;
+ Mesh *me = ob->data;
+
+ sculpt_pbvh_clear(ob);
+
+ /* Create empty BMesh and enable logging */
+ ss->bm = BM_mesh_create(&bm_mesh_allocsize_default);
+ BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
+ me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
+
+ /* Restore the BMLog using saved entries */
+ ss->bm_log = BM_log_from_existing_entries_create(ss->bm,
+ unode->bm_entry);
+}
+
+static void sculpt_undo_bmesh_restore_begin(bContext *C,
+ SculptUndoNode *unode,
+ Object *ob,
+ SculptSession *ss)
+{
+ if (unode->applied) {
+ sculpt_dynamic_topology_disable(C, unode);
+ unode->applied = FALSE;
+ }
+ else {
+ sculpt_undo_bmesh_enable(ob, unode);
+
+ /* Restore the mesh from the first log entry */
+ BM_log_redo(ss->bm, ss->bm_log);
+
+ unode->applied = TRUE;
+ }
+}
+
+static void sculpt_undo_bmesh_restore_end(bContext *C,
+ SculptUndoNode *unode,
+ Object *ob,
+ SculptSession *ss)
+{
+ if (unode->applied) {
+ sculpt_undo_bmesh_enable(ob, unode);
+
+ /* Restore the mesh from the last log entry */
+ BM_log_undo(ss->bm, ss->bm_log);
+
+ unode->applied = FALSE;
+ }
+ else {
+ /* Disable dynamic topology sculpting */
+ sculpt_dynamic_topology_disable(C, NULL);
+ unode->applied = TRUE;
+ }
+}
+
+/* Handle all dynamic-topology updates
+ *
+ * Returns TRUE if this was a dynamic-topology undo step, otherwise
+ * returns FALSE to indicate the non-dyntopo code should run. */
+static int sculpt_undo_bmesh_restore(bContext *C,
+ SculptUndoNode *unode,
+ Object *ob,
+ SculptSession *ss)
+{
+ switch (unode->type) {
+ case SCULPT_UNDO_DYNTOPO_BEGIN:
+ sculpt_undo_bmesh_restore_begin(C, unode, ob, ss);
+ return TRUE;
+
+ case SCULPT_UNDO_DYNTOPO_END:
+ sculpt_undo_bmesh_restore_end(C, unode, ob, ss);
+ return TRUE;
+
+ default:
+ if (ss->bm_log) {
+ sculpt_undo_bmesh_restore_generic(unode, ob, ss);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
static void sculpt_undo_restore(bContext *C, ListBase *lb)
{
Scene *scene = CTX_data_scene(C);
@@ -289,6 +395,9 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
/* call _after_ sculpt_update_mesh_elements() which may update 'ob->derivedFinal' */
dm = mesh_get_derived_final(scene, ob, 0);
+ if (lb->first && sculpt_undo_bmesh_restore(C, lb->first, ob, ss))
+ return;
+
for (unode = lb->first; unode; unode = unode->next) {
if (!(strcmp(unode->idname, ob->id.name) == 0))
continue;
@@ -306,9 +415,6 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
continue;
}
}
- else {
- continue;
- }
switch (unode->type) {
case SCULPT_UNDO_COORDS:
@@ -323,6 +429,12 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
if (sculpt_undo_restore_mask(C, dm, unode))
update = TRUE;
break;
+
+ case SCULPT_UNDO_DYNTOPO_BEGIN:
+ case SCULPT_UNDO_DYNTOPO_END:
+ case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+ BLI_assert(!"Dynamic topology should've already been handled");
+ break;
}
}
@@ -331,8 +443,8 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
/* we update all nodes still, should be more clever, but also
* needs to work correct when exiting/entering sculpt mode and
* the nodes get recreated, though in that case it could do all */
- BLI_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild);
- BLI_pbvh_update(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw, NULL);
+ BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild);
+ BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw, NULL);
if ((mmd = sculpt_multires_active(scene, ob))) {
if (rebuild)
@@ -374,8 +486,6 @@ static void sculpt_undo_free(ListBase *lb)
MEM_freeN(unode->index);
if (unode->grids)
MEM_freeN(unode->grids);
- if (unode->layer_disp)
- MEM_freeN(unode->layer_disp);
if (unode->orig_co)
MEM_freeN(unode->orig_co);
if (unode->vert_hidden)
@@ -389,6 +499,17 @@ static void sculpt_undo_free(ListBase *lb)
}
if (unode->mask)
MEM_freeN(unode->mask);
+ if (unode->bm_entry) {
+ BM_log_entry_drop(unode->bm_entry);
+ }
+ if (unode->bm_enter_totvert)
+ CustomData_free(&unode->bm_enter_vdata, unode->bm_enter_totvert);
+ if (unode->bm_enter_totedge)
+ CustomData_free(&unode->bm_enter_edata, unode->bm_enter_totedge);
+ if (unode->bm_enter_totloop)
+ CustomData_free(&unode->bm_enter_ldata, unode->bm_enter_totloop);
+ if (unode->bm_enter_totpoly)
+ CustomData_free(&unode->bm_enter_pdata, unode->bm_enter_totpoly);
}
}
@@ -410,9 +531,9 @@ static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh,
BLI_bitmap *grid_hidden;
int i, *grid_indices, totgrid;
- grid_hidden = BLI_pbvh_grid_hidden(pbvh);
+ grid_hidden = BKE_pbvh_grid_hidden(pbvh);
- BLI_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid,
+ BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid,
NULL, NULL, NULL, NULL);
unode->grid_hidden = MEM_mapallocN(sizeof(BLI_bitmap) * totgrid,
@@ -439,11 +560,13 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
unode->type = type;
unode->node = node;
- BLI_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
- BLI_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
- &maxgrid, &gridsize, NULL, NULL);
+ if (node) {
+ BKE_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
+ BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
+ &maxgrid, &gridsize, NULL, NULL);
- unode->totvert = totvert;
+ unode->totvert = totvert;
+ }
/* we will use this while sculpting, is mapalloc slow to access then? */
@@ -468,6 +591,11 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
unode->mask = MEM_mapallocN(sizeof(float) * allvert, "SculptUndoNode.mask");
undo_paint_push_count_alloc(UNDO_PAINT_MESH, (sizeof(float) * sizeof(int)) * allvert);
break;
+ case SCULPT_UNDO_DYNTOPO_BEGIN:
+ case SCULPT_UNDO_DYNTOPO_END:
+ case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+ BLI_assert(!"Dynamic topology should've already been handled");
+ break;
}
BLI_addtail(lb, unode);
@@ -496,7 +624,7 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
SculptSession *ss = ob->sculpt;
PBVHVertexIter vd;
- BLI_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
{
copy_v3_v3(unode->co[vd.i], vd.co);
if (vd.no) copy_v3_v3_short(unode->no[vd.i], vd.no);
@@ -505,7 +633,7 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
if (ss->modifiers_active)
copy_v3_v3(unode->orig_co[vd.i], ss->orig_cos[unode->index[vd.i]]);
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
@@ -521,8 +649,8 @@ static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
int *vert_indices, allvert;
int i;
- BLI_pbvh_node_num_verts(pbvh, node, NULL, &allvert);
- BLI_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
+ BKE_pbvh_node_num_verts(pbvh, node, NULL, &allvert);
+ BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
for (i = 0; i < allvert; i++) {
BLI_BITMAP_MODIFY(unode->vert_hidden, i,
mvert[vert_indices[i]].flag & ME_HIDE);
@@ -535,11 +663,85 @@ static void sculpt_undo_store_mask(Object *ob, SculptUndoNode *unode)
SculptSession *ss = ob->sculpt;
PBVHVertexIter vd;
- BLI_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
{
unode->mask[vd.i] = *vd.mask;
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
+}
+
+static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
+ PBVHNode *node,
+ SculptUndoType type)
+{
+ ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH);
+ SculptUndoNode *unode = lb->first;
+ SculptSession *ss = ob->sculpt;
+ PBVHVertexIter vd;
+
+ if (!lb->first) {
+ unode = MEM_callocN(sizeof(*unode), AT);
+
+ BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname));
+ unode->type = type;
+ unode->applied = TRUE;
+
+ if (type == SCULPT_UNDO_DYNTOPO_END) {
+ unode->bm_entry = BM_log_entry_add(ss->bm_log);
+ BM_log_before_all_removed(ss->bm, ss->bm_log);
+ }
+ else if (type == SCULPT_UNDO_DYNTOPO_BEGIN) {
+ Mesh *me = ob->data;
+
+ /* Store a copy of the mesh's current vertices, loops, and
+ * polys. A full copy like this is needed because entering
+ * dynamic-topology immediately does topological edits
+ * (converting polys to triangles) that the BMLog can't
+ * fully restore from */
+ CustomData_copy(&me->vdata, &unode->bm_enter_vdata, CD_MASK_MESH,
+ CD_DUPLICATE, me->totvert);
+ CustomData_copy(&me->edata, &unode->bm_enter_edata, CD_MASK_MESH,
+ CD_DUPLICATE, me->totedge);
+ CustomData_copy(&me->ldata, &unode->bm_enter_ldata, CD_MASK_MESH,
+ CD_DUPLICATE, me->totloop);
+ CustomData_copy(&me->pdata, &unode->bm_enter_pdata, CD_MASK_MESH,
+ CD_DUPLICATE, me->totpoly);
+ unode->bm_enter_totvert = me->totvert;
+ unode->bm_enter_totedge = me->totedge;
+ unode->bm_enter_totloop = me->totloop;
+ unode->bm_enter_totpoly = me->totpoly;
+
+ unode->bm_entry = BM_log_entry_add(ss->bm_log);
+ BM_log_all_added(ss->bm, ss->bm_log);
+ }
+ else {
+ unode->bm_entry = BM_log_entry_add(ss->bm_log);
+ }
+
+ BLI_addtail(lb, unode);
+ }
+
+ if (node) {
+ switch (type) {
+ case SCULPT_UNDO_COORDS:
+ case SCULPT_UNDO_HIDDEN:
+ case SCULPT_UNDO_MASK:
+ /* Before any vertex values get modified, ensure their
+ * original positions are logged */
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) {
+ BM_log_vert_before_modified(ss->bm, ss->bm_log, vd.bm_vert);
+ }
+ BKE_pbvh_vertex_iter_end;
+ break;
+
+ case SCULPT_UNDO_DYNTOPO_BEGIN:
+ case SCULPT_UNDO_DYNTOPO_END:
+ case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+ break;
+ }
+ }
+
+ return unode;
}
SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
@@ -551,7 +753,18 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
/* list is manipulated by multiple threads, so we lock */
BLI_lock_thread(LOCK_CUSTOM1);
- if ((unode = sculpt_undo_get_node(node))) {
+ if (ss->bm ||
+ ELEM(type,
+ SCULPT_UNDO_DYNTOPO_BEGIN,
+ SCULPT_UNDO_DYNTOPO_END))
+ {
+ /* Dynamic topology stores only one undo node per stroke,
+ * regardless of the number of PBVH nodes modified */
+ unode = sculpt_undo_bmesh_push(ob, node, type);
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ return unode;
+ }
+ else if ((unode = sculpt_undo_get_node(node))) {
BLI_unlock_thread(LOCK_CUSTOM1);
return unode;
}
@@ -564,14 +777,14 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
if (unode->grids) {
int totgrid, *grids;
- BLI_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
+ BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
NULL, NULL, NULL, NULL);
memcpy(unode->grids, grids, sizeof(int) * totgrid);
}
else {
int *vert_indices, allvert;
- BLI_pbvh_node_num_verts(ss->pbvh, node, NULL, &allvert);
- BLI_pbvh_node_get_verts(ss->pbvh, node, &vert_indices, NULL);
+ BKE_pbvh_node_num_verts(ss->pbvh, node, NULL, &allvert);
+ BKE_pbvh_node_get_verts(ss->pbvh, node, &vert_indices, NULL);
memcpy(unode->index, vert_indices, sizeof(int) * unode->totvert);
}
@@ -585,6 +798,11 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
case SCULPT_UNDO_MASK:
sculpt_undo_store_mask(ob, unode);
break;
+ case SCULPT_UNDO_DYNTOPO_BEGIN:
+ case SCULPT_UNDO_DYNTOPO_END:
+ case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+ BLI_assert(!"Dynamic topology should've already been handled");
+ break;
}
/* store active shape key */
@@ -612,10 +830,8 @@ void sculpt_undo_push_end(void)
unode->no = NULL;
}
- if (unode->layer_disp) {
- MEM_freeN(unode->layer_disp);
- unode->layer_disp = NULL;
- }
+ if (unode->node)
+ BKE_pbvh_node_layer_disp_free(unode->node);
}
undo_paint_push_end(UNDO_PAINT_MESH);
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 9bd7d2a44ca..4b1954c8889 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -82,13 +82,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* Update max-extent of channels here (taking into account scrollers):
- * - this is done to allow the channel list to be scrollable, but must be done here
- * to avoid regenerating the list again and/or also because channels list is drawn first
- * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
- * start of list offset, and the second is as a correction for the scrollers.
- */
- height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT * 2));
+ height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT));
if (height > BLI_rcti_size_y(&v2d->mask)) {
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
@@ -199,13 +193,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* Update max-extent of channels here (taking into account scrollers):
- * - this is done to allow the channel list to be scrollable, but must be done here
- * to avoid regenerating the list again and/or also because channels list is drawn first
- * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
- * start of list offset, and the second is as a correction for the scrollers.
- */
- height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT * 2));
+ height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT));
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
*/
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index c5f3ccee101..e0ca589c1fb 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -219,6 +219,9 @@ static void action_channel_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
+ /* ensure the 2d view sync works - main region has bottom scroller */
+ ar->v2d.scroll = V2D_SCROLL_BOTTOM;
+
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
/* own keymap */
@@ -231,7 +234,6 @@ static void action_channel_area_draw(const bContext *C, ARegion *ar)
/* draw entirely, view changes should be handled here */
bAnimContext ac;
View2D *v2d = &ar->v2d;
- View2DScrollers *scrollers;
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
@@ -247,10 +249,7 @@ static void action_channel_area_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
- /* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
+ /* no scrollers here */
}
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index 77662d8ac13..56a890c714a 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -1801,7 +1801,7 @@ static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat
int found = FALSE;
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
if (!cti)
continue;
@@ -1832,7 +1832,7 @@ static Object *object_solver_camera(Scene *scene, Object *ob)
bConstraint *con;
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
if (!cti)
continue;
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index fb438ae45fb..08f01b47b52 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -321,8 +321,7 @@ void file_calc_previews(const bContext *C, ARegion *ar)
View2D *v2d = &ar->v2d;
ED_fileselect_init_layout(sfile, ar);
- /* +SCROLL_HEIGHT is bad hack to work around issue in UI_view2d_totRect_set */
- UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height + V2D_SCROLL_HEIGHT);
+ UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height);
}
static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int sy, ImBuf *imb, FileLayout *layout, short dropshadow)
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index fa7c6bd472a..734c0e6c479 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -309,6 +309,12 @@ static void graph_channel_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
+ /* make sure we keep the hide flags */
+ ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+ ar->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP); /* prevent any noise of past */
+ ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+ ar->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE;
+
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
/* own keymap */
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index d02186e59dd..060a181612b 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -219,7 +219,7 @@ static void preview_cb(ScrArea *sa, struct uiBlock *block)
BLI_rcti_translate(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
calc_image_view(sima, 'p');
-// printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
+// printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
/* map to image space coordinates */
mval[0] = disprect->xmin; mval[1] = disprect->ymin;
areamouseco_to_ipoco(v2d, mval, &dispf.xmin, &dispf.ymin);
@@ -236,7 +236,7 @@ static void preview_cb(ScrArea *sa, struct uiBlock *block)
CLAMP(disprect->xmax, 0, winx);
CLAMP(disprect->ymin, 0, winy);
CLAMP(disprect->ymax, 0, winy);
-// printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
+// printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
}
@@ -674,6 +674,24 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
if (ima->source != IMA_SRC_GENERATED) {
if (compact == 0) { /* background image view doesnt need these */
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
+ int has_alpha = TRUE;
+
+ if (ibuf) {
+ int imtype = BKE_ftype_to_imtype(ibuf->ftype);
+ char valid_channels = BKE_imtype_valid_channels(imtype);
+
+ has_alpha = valid_channels & IMA_CHAN_FLAG_ALPHA;
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+
+ if (has_alpha) {
+ col = uiLayoutColumn(layout, FALSE);
+ uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
+ uiItemR(col, &imaptr, "alpha_mode", 0, "Alpha", ICON_NONE);
+ }
+
uiItemS(layout);
split = uiLayoutSplit(layout, 0.0f, FALSE);
@@ -694,10 +712,6 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
row = uiLayoutRow(col, FALSE);
uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields"));
uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
-
- row = uiLayoutRow(layout, FALSE);
- uiItemR(row, &imaptr, "use_premultiply", 0, NULL, ICON_NONE);
- uiItemR(row, &imaptr, "use_color_unpremultiply", 0, NULL, ICON_NONE);
}
}
@@ -796,6 +810,8 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man
}
if (imf->imtype == R_IMF_IMTYPE_JP2) {
+ uiItemR(col, imfptr, "jpeg2k_codec", 0, NULL, ICON_NONE);
+
row = uiLayoutRow(col, FALSE);
uiItemR(row, imfptr, "use_jpeg2k_cinema_preset", 0, NULL, ICON_NONE);
uiItemR(row, imfptr, "use_jpeg2k_cinema_48", 0, NULL, ICON_NONE);
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index d565e6f9e9a..0534b9f4ffd 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -75,13 +75,15 @@
#include "WM_types.h"
#include "RE_pipeline.h"
+#include "RE_engine.h"
#include "image_intern.h"
-static void draw_render_info(Scene *scene, Image *ima, ARegion *ar)
+static void draw_render_info(Scene *scene, Image *ima, ARegion *ar, float zoomx, float zoomy)
{
RenderResult *rr;
-
+ Render *re = RE_GetRender(scene->id.name);
+
rr = BKE_image_acquire_renderresult(scene, ima);
if (rr && rr->text) {
@@ -89,6 +91,73 @@ static void draw_render_info(Scene *scene, Image *ima, ARegion *ar)
}
BKE_image_release_renderresult(scene, ima);
+
+ if (re) {
+ int total_tiles;
+ rcti *tiles;
+
+ RE_engine_get_current_tiles(re, &total_tiles, &tiles);
+
+ if (total_tiles) {
+ int i, x, y;
+ rcti *tile;
+
+ /* find window pixel coordinates of origin */
+ UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);
+
+ glPushMatrix();
+ glTranslatef(x, y, 0.0f);
+ glScalef(zoomx, zoomy, 1.0f);
+
+ if (scene->r.mode & R_BORDER) {
+ glTranslatef(-scene->r.border.xmin * scene->r.xsch * scene->r.size / 100.0f,
+ -scene->r.border.ymin * scene->r.ysch * scene->r.size / 100.0f,
+ 0.0f);
+ }
+
+ UI_ThemeColor(TH_FACE_SELECT);
+
+ for (i = 0, tile = tiles; i < total_tiles; i++, tile++) {
+ float delta_x = 4.0f * UI_DPI_FAC / zoomx;
+ float delta_y = 4.0f * UI_DPI_FAC / zoomy;
+
+ delta_x = min_ff(delta_x, tile->xmax - tile->xmin);
+ delta_y = min_ff(delta_y, tile->ymax - tile->ymin);
+
+ /* left bottom corner */
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(tile->xmin, tile->ymin + delta_y);
+ glVertex2f(tile->xmin, tile->ymin);
+ glVertex2f(tile->xmin + delta_x, tile->ymin);
+ glEnd();
+
+ /* left top corner */
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(tile->xmin, tile->ymax - delta_y);
+ glVertex2f(tile->xmin, tile->ymax);
+ glVertex2f(tile->xmin + delta_x, tile->ymax);
+ glEnd();
+
+ /* right bottom corner */
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(tile->xmax - delta_x, tile->ymin);
+ glVertex2f(tile->xmax, tile->ymin);
+ glVertex2f(tile->xmax, tile->ymin + delta_y);
+ glEnd();
+
+ /* right top corner */
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(tile->xmax - delta_x, tile->ymax);
+ glVertex2f(tile->xmax, tile->ymax);
+ glVertex2f(tile->xmax, tile->ymax - delta_y);
+ glEnd();
+ }
+
+ MEM_freeN(tiles);
+
+ glPopMatrix();
+ }
+ }
}
/* used by node view too */
@@ -146,7 +215,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
if (channels >= 3) {
glColor3ubv(red);
if (fp)
- BLI_snprintf(str, sizeof(str), " R:%-.4f", fp[0]);
+ BLI_snprintf(str, sizeof(str), " R:%-.5f", fp[0]);
else if (cp)
BLI_snprintf(str, sizeof(str), " R:%-3d", cp[0]);
else
@@ -157,7 +226,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
glColor3ubv(green);
if (fp)
- BLI_snprintf(str, sizeof(str), " G:%-.4f", fp[1]);
+ BLI_snprintf(str, sizeof(str), " G:%-.5f", fp[1]);
else if (cp)
BLI_snprintf(str, sizeof(str), " G:%-3d", cp[1]);
else
@@ -168,7 +237,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
glColor3ubv(blue);
if (fp)
- BLI_snprintf(str, sizeof(str), " B:%-.4f", fp[2]);
+ BLI_snprintf(str, sizeof(str), " B:%-.5f", fp[2]);
else if (cp)
BLI_snprintf(str, sizeof(str), " B:%-3d", cp[2]);
else
@@ -518,8 +587,8 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
sima->curtile = ima->xrep * ima->yrep - 1;
/* retrieve part of image buffer */
- dx = ibuf->x / ima->xrep;
- dy = ibuf->y / ima->yrep;
+ dx = max_ii(ibuf->x / ima->xrep, 1);
+ dy = max_ii(ibuf->y / ima->yrep, 1);
sx = (sima->curtile % ima->xrep) * dx;
sy = (sima->curtile / ima->xrep) * dy;
rect = get_part_from_buffer((unsigned int *)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy);
@@ -786,7 +855,6 @@ void draw_image_main(const bContext *C, ARegion *ar)
if (sima->mode == SI_MODE_PAINT)
draw_image_paint_helpers(C, ar, scene, zoomx, zoomy);
-
/* XXX integrate this code */
#if 0
if (ibuf) {
@@ -812,5 +880,5 @@ void draw_image_main(const bContext *C, ARegion *ar)
/* render info */
if (ima && show_render)
- draw_render_info(scene, ima, ar);
+ draw_render_info(scene, ima, ar, zoomx, zoomy);
}
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 0d0fdc6be1c..f1662bc254d 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -457,7 +457,7 @@ enum {
static int image_view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
- if (event->type == MOUSEZOOM) {
+ if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
SpaceImage *sima = CTX_wm_space_image(C);
ARegion *ar = CTX_wm_region(C);
float delta, factor, location[2];
@@ -1217,7 +1217,7 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
simopts->im_format.imtype = R_IMF_IMTYPE_PNG;
}
else {
- simopts->im_format.imtype = BKE_ftype_to_imtype(ibuf->ftype);
+ BKE_imbuf_to_image_format(&simopts->im_format, ibuf);
}
//simopts->subimtype = scene->r.subimtype; /* XXX - this is lame, we need to make these available too! */
simopts->im_format.quality = ibuf->ftype & 0xff;
@@ -1434,7 +1434,7 @@ static int image_save_as_exec(bContext *C, wmOperator *op)
static int image_save_as_check(bContext *UNUSED(C), wmOperator *op)
{
ImageFormatData *imf = op->customdata;
- return WM_operator_filesel_ensure_ext_imtype(op, imf->imtype);
+ return WM_operator_filesel_ensure_ext_imtype(op, imf);
}
static int image_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
@@ -1559,6 +1559,7 @@ static int image_save_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
SaveImageOptions simopts;
+ save_image_options_defaults(&simopts);
if (save_image_options_init(&simopts, sima, scene, FALSE) == 0)
return OPERATOR_CANCELLED;
save_image_options_from_op(&simopts, op);
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index b0e9f8bcf99..9492e29734d 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -292,6 +292,7 @@ static void image_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", PADMINUS, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom", MOUSEZOOM, 0, 0, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom", MOUSEPAN, 0, KM_CTRL, 0);
/* ctrl now works as well, shift + numpad works as arrow keys on Windows */
RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD8, KM_PRESS, KM_CTRL, 0)->ptr, "ratio", 8.0f);
diff --git a/source/blender/editors/space_info/info_intern.h b/source/blender/editors/space_info/info_intern.h
index 80018e849d3..62e9a3a7f73 100644
--- a/source/blender/editors/space_info/info_intern.h
+++ b/source/blender/editors/space_info/info_intern.h
@@ -39,11 +39,15 @@ struct ReportList;
void FILE_OT_pack_all(struct wmOperatorType *ot);
void FILE_OT_unpack_all(struct wmOperatorType *ot);
+void FILE_OT_pack_libraries(struct wmOperatorType *ot);
+void FILE_OT_unpack_libraries(struct wmOperatorType *ot);
+
void FILE_OT_make_paths_relative(struct wmOperatorType *ot);
void FILE_OT_make_paths_absolute(struct wmOperatorType *ot);
void FILE_OT_report_missing_files(struct wmOperatorType *ot);
void FILE_OT_find_missing_files(struct wmOperatorType *ot);
+
void INFO_OT_reports_display_update(struct wmOperatorType *ot);
/* info_draw.c */
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index e902a4ea6f4..104349e172a 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -66,15 +66,70 @@
#include "info_intern.h"
+/********************* pack blend file libararies operator *********************/
+
+static int pack_libraries_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+
+ packLibraries(bmain, op->reports);
+
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_pack_libraries(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Pack Blender Libraries";
+ ot->idname = "FILE_OT_pack_libraries";
+ ot->description = "Pack all used Blender library files into the current .blend";
+
+ /* api callbacks */
+ ot->exec = pack_libraries_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int unpack_libraries_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+
+ unpackLibraries(bmain, op->reports);
+
+ return OPERATOR_FINISHED;
+}
+
+static int unpack_libraries_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+{
+ return WM_operator_confirm_message(C, op, "Unpack Blender Libraries - creates directories, all new paths should work");
+}
+
+void FILE_OT_unpack_libraries(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Unpack Blender Libraries";
+ ot->idname = "FILE_OT_unpack_libraries";
+ ot->description = "Unpack all used Blender library files from this .blend file";
+
+ /* api callbacks */
+ ot->invoke = unpack_libraries_invoke;
+ ot->exec = unpack_libraries_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
/********************* pack all operator *********************/
static int pack_all_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
-
+
packAll(bmain, op->reports);
G.fileflags |= G_AUTOPACK;
-
+
return OPERATOR_FINISHED;
}
@@ -83,7 +138,7 @@ static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
Main *bmain = CTX_data_main(C);
Image *ima;
ImBuf *ibuf;
-
+
// first check for dirty images
for (ima = bmain->image.first; ima; ima = ima->id.next) {
if (ima->ibufs.first) { /* XXX FIX */
@@ -93,16 +148,16 @@ static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
BKE_image_release_ibuf(ima, ibuf, NULL);
break;
}
-
+
BKE_image_release_ibuf(ima, ibuf, NULL);
}
}
-
+
if (ima) {
uiPupMenuOkee(C, "FILE_OT_pack_all", "Some images are painted on. These changes will be lost. Continue?");
return OPERATOR_CANCELLED;
}
-
+
return pack_all_exec(C, op);
}
@@ -116,11 +171,12 @@ void FILE_OT_pack_all(wmOperatorType *ot)
/* api callbacks */
ot->exec = pack_all_exec;
ot->invoke = pack_all_invoke;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
/********************* unpack all operator *********************/
static const EnumPropertyItem unpack_all_method_items[] = {
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 5e5e0c87feb..3f73fc2605a 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -39,6 +39,7 @@
#include "DNA_scene_types.h"
#include "BLI_utildefines.h"
+#include "BLI_math.h"
#include "BKE_anim.h"
#include "BKE_blender.h"
@@ -47,6 +48,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_key.h"
#include "BKE_mesh.h"
+#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_tessmesh.h"
@@ -62,7 +64,7 @@ typedef struct SceneStats {
int totbone, totbonesel;
int totobj, totobjsel;
int totlamp, totlampsel;
- int tottri, totmesh, totcurve;
+ int tottri, totmesh;
char infostr[512];
} SceneStats;
@@ -74,7 +76,7 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
{
/* we assume derivedmesh is already built, this strictly does stats now. */
DerivedMesh *dm = ob->derivedFinal;
- int totvert, totedge, totface;
+ int totvert, totedge, totface, totloop;
stats->totmesh += totob;
@@ -82,10 +84,12 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
totvert = dm->getNumVerts(dm);
totedge = dm->getNumEdges(dm);
totface = dm->getNumPolys(dm);
+ totloop = dm->getNumLoops(dm);
stats->totvert += totvert * totob;
stats->totedge += totedge * totob;
stats->totface += totface * totob;
+ stats->tottri += poly_to_tri_count(totface, totloop) * totob;
if (sel) {
stats->totvertsel += totvert;
@@ -103,40 +107,23 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
case OB_SURF:
case OB_CURVE:
case OB_FONT:
- {
- int tot = 0, totf = 0;
-
- stats->totcurve += totob;
-
- if (ob->disp.first)
- BKE_displist_count(&ob->disp, &tot, &totf);
-
- tot *= totob;
- totf *= totob;
-
- stats->totvert += tot;
- stats->totface += totf;
-
- if (sel) {
- stats->totvertsel += tot;
- stats->totfacesel += totf;
- }
- break;
- }
case OB_MBALL:
{
- int tot = 0, totf = 0;
+ int totv = 0, totf = 0, tottri = 0;
- BKE_displist_count(&ob->disp, &tot, &totf);
+ if (ob->disp.first)
+ BKE_displist_count(&ob->disp, &totv, &totf, &tottri);
- tot *= totob;
- totf *= totob;
+ totv *= totob;
+ totf *= totob;
+ tottri *= totob;
- stats->totvert += tot;
+ stats->totvert += totv;
stats->totface += totf;
+ stats->tottri += tottri;
if (sel) {
- stats->totvertsel += tot;
+ stats->totvertsel += totv;
stats->totfacesel += totf;
}
break;
@@ -260,6 +247,12 @@ static void stats_object_pose(Object *ob, SceneStats *stats)
}
}
+static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats)
+{
+ stats->totvert = ob->sculpt->bm->totvert;
+ stats->tottri = ob->sculpt->bm->totface;
+}
+
static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
{
if (base->flag & SELECT) stats->totobjsel++;
@@ -319,6 +312,12 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
}
}
+static int stats_is_object_dynamic_topology_sculpt(Object *ob)
+{
+ return (ob && (ob->mode & OB_MODE_SCULPT) &&
+ ob->sculpt && ob->sculpt->bm);
+}
+
/* Statistics displayed in info header. Called regularly on scene changes. */
static void stats_update(Scene *scene)
{
@@ -334,6 +333,10 @@ static void stats_update(Scene *scene)
/* Pose Mode */
stats_object_pose(ob, &stats);
}
+ else if (stats_is_object_dynamic_topology_sculpt(ob)) {
+ /* Dynamic-topology sculpt mode */
+ stats_object_sculpt_dynamic_topology(ob, &stats);
+ }
else {
/* Objects */
for (base = scene->base.first; base; base = base->next)
@@ -388,9 +391,12 @@ static void stats_string(Scene *scene)
s += sprintf(s, "Bones:%d/%d %s",
stats->totbonesel, stats->totbone, memstr);
}
+ else if (stats_is_object_dynamic_topology_sculpt(ob)) {
+ s += sprintf(s, "Verts:%d | Tris:%d", stats->totvert, stats->tottri);
+ }
else {
- s += sprintf(s, "Verts:%d | Faces:%d | Objects:%d/%d | Lamps:%d/%d%s",
- stats->totvert, stats->totface, stats->totobjsel, stats->totobj, stats->totlampsel, stats->totlamp, memstr);
+ s += sprintf(s, "Verts:%d | Faces:%d| Tris:%d | Objects:%d/%d | Lamps:%d/%d%s",
+ stats->totvert, stats->totface, stats->tottri, stats->totobjsel, stats->totobj, stats->totlampsel, stats->totlamp, memstr);
}
if (ob)
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index db9be22eedb..60b04f7b029 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -178,7 +178,10 @@ static void info_main_area_draw(const bContext *C, ARegion *ar)
static void info_operatortypes(void)
{
WM_operatortype_append(FILE_OT_pack_all);
+ WM_operatortype_append(FILE_OT_pack_libraries);
WM_operatortype_append(FILE_OT_unpack_all);
+ WM_operatortype_append(FILE_OT_unpack_libraries);
+
WM_operatortype_append(FILE_OT_make_paths_relative);
WM_operatortype_append(FILE_OT_make_paths_absolute);
WM_operatortype_append(FILE_OT_report_missing_files);
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index 00745062582..a7599f21ad5 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -1006,7 +1006,7 @@ static void draw_sensor_actuator(uiLayout *layout, PointerRNA *ptr)
static void draw_sensor_armature(uiLayout *layout, PointerRNA *ptr)
{
- bSensor *sens = (bSensor*)ptr->data;
+ bSensor *sens = (bSensor *)ptr->data;
bArmatureSensor *as = (bArmatureSensor *) sens->data;
Object *ob = (Object *)ptr->id.data;
PointerRNA pose_ptr, pchan_ptr;
@@ -1476,7 +1476,7 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr)
static void draw_actuator_armature(uiLayout *layout, PointerRNA *ptr)
{
- bActuator *act = (bActuator*)ptr->data;
+ bActuator *act = (bActuator *)ptr->data;
bArmatureActuator *aa = (bArmatureActuator *) act->data;
Object *ob = (Object *)ptr->id.data;
bConstraint *constraint = NULL;
diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c
index 4cd53215697..8795d655e77 100644
--- a/source/blender/editors/space_logic/space_logic.c
+++ b/source/blender/editors/space_logic/space_logic.c
@@ -148,7 +148,7 @@ static SpaceLink *logic_new(const bContext *C)
/* not spacelink itself */
static void logic_free(SpaceLink *UNUSED(sl))
{
-// Spacelogic *slogic= (SpaceLogic*) sl;
+// Spacelogic *slogic= (SpaceLogic *) sl;
// if (slogic->gpd)
// XXX BKE_gpencil_free(slogic->gpd);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 59dd66a0207..8797cb4a459 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -399,8 +399,8 @@ static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA
static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree*)ptr->id.data;
- bNode *node = (bNode*)ptr->data;
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNode *node = (bNode *)ptr->data;
bNodeSocket *sock = node->outputs.first; /* first socket stores normal */
PointerRNA sockptr;
@@ -2152,12 +2152,12 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C
active_index = RNA_int_get(ptr, "active_input_index");
/* using different collection properties if multilayer format is enabled */
if (multilayer) {
- uiTemplateList(col, C, ptr, "layer_slots", ptr, "active_input_index", NULL, 0, 0, 0);
+ uiTemplateList(col, C, "UI_UL_list", "", ptr, "layer_slots", ptr, "active_input_index", 0, 0, 0);
RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"),
active_index, &active_input_ptr);
}
else {
- uiTemplateList(col, C, ptr, "file_slots", ptr, "active_input_index", NULL, 0, 0, 0);
+ uiTemplateList(col, C, "UI_UL_list", "", ptr, "file_slots", ptr, "active_input_index", 0, 0, 0);
RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"),
active_index, &active_input_ptr);
}
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index f386657c460..492ff0dcbd4 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -69,12 +69,15 @@ static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, cons
bNode *node;
rctf cur_new;
float oldwidth, oldheight, width, height;
+ float oldasp, asp;
int tot = 0;
int has_frame = FALSE;
oldwidth = BLI_rctf_size_x(&ar->v2d.cur);
oldheight = BLI_rctf_size_y(&ar->v2d.cur);
+ oldasp = oldwidth / oldheight;
+
BLI_rctf_init_minmax(&cur_new);
if (snode->edittree) {
@@ -93,6 +96,7 @@ static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, cons
if (tot) {
width = BLI_rctf_size_x(&cur_new);
height = BLI_rctf_size_y(&cur_new);
+ asp = width / height;
/* for single non-frame nodes, don't zoom in, just pan view,
* but do allow zooming out, this allows for big nodes to be zoomed out */
@@ -104,17 +108,15 @@ static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, cons
BLI_rctf_resize(&cur_new, oldwidth, oldheight);
}
else {
- if (width > height) {
- float newheight;
- newheight = oldheight * width / oldwidth;
- cur_new.ymin = cur_new.ymin - newheight / 4;
- cur_new.ymax = cur_new.ymax + newheight / 4;
+ if (oldasp < asp) {
+ const float height_new = width / oldasp;
+ cur_new.ymin = cur_new.ymin - height_new / 2.0f;
+ cur_new.ymax = cur_new.ymax + height_new / 2.0f;
}
else {
- float newwidth;
- newwidth = oldwidth * height / oldheight;
- cur_new.xmin = cur_new.xmin - newwidth / 4;
- cur_new.xmax = cur_new.xmax + newwidth / 4;
+ const float width_new = height * oldasp;
+ cur_new.xmin = cur_new.xmin - width_new / 2.0f;
+ cur_new.xmax = cur_new.xmax + width_new / 2.0f;
}
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 6913ebc8a11..1a058104c78 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -421,17 +421,17 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
uiBlockSetEmboss(block, UI_EMBOSSN);
bt = uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_VIEW_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
&ptr, "hide", -1, 0, 0, -1, -1, NULL);
uiButSetFunc(bt, restrictbutton_view_cb, scene, ob);
bt = uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_SELECT_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
&ptr, "hide_select", -1, 0, 0, -1, -1, NULL);
uiButSetFunc(bt, restrictbutton_sel_cb, scene, ob);
bt = uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_RENDER_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
&ptr, "hide_render", -1, 0, 0, -1, -1, NULL);
uiButSetFunc(bt, restrictbutton_rend_cb, scene, ob);
@@ -445,15 +445,21 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
uiBlockSetEmboss(block, UI_EMBOSSN);
restrict_bool = group_restrict_flag(gr, OB_RESTRICT_VIEW);
- bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF, (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+ bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ NULL, 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
uiButSetFunc(bt, restrictbutton_gr_restrict_view, scene, gr);
restrict_bool = group_restrict_flag(gr, OB_RESTRICT_SELECT);
- bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF, (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
+ bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ NULL, 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
uiButSetFunc(bt, restrictbutton_gr_restrict_select, scene, gr);
restrict_bool = group_restrict_flag(gr, OB_RESTRICT_RENDER);
- bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF, (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Restrict/Allow renderability");
+ bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ NULL, 0, 0, 0, 0, "Restrict/Allow renderability");
uiButSetFunc(bt, restrictbutton_gr_restrict_render, scene, gr);
uiBlockSetEmboss(block, UI_EMBOSS);
@@ -463,7 +469,8 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
uiBlockSetEmboss(block, UI_EMBOSSN);
bt = uiDefIconButBitI(block, ICONTOGN, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT - 1,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, te->directdata, 0, 0, 0, 0, "Render this RenderLayer");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ te->directdata, 0, 0, 0, 0, "Render this RenderLayer");
uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
uiBlockSetEmboss(block, UI_EMBOSS);
@@ -476,13 +483,18 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
bt = uiDefIconButBitI(block, ICONTOG, passflag, 0, ICON_CHECKBOX_HLT - 1,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, layflag, 0, 0, 0, 0, "Render this Pass");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ layflag, 0, 0, 0, 0, "Render this Pass");
uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
layflag++; /* is lay_xor */
- if (ELEM8(passflag, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT, SCE_PASS_INDIRECT, SCE_PASS_EMIT, SCE_PASS_ENVIRONMENT))
+ if (ELEM8(passflag, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT,
+ SCE_PASS_INDIRECT, SCE_PASS_EMIT, SCE_PASS_ENVIRONMENT))
+ {
bt = uiDefIconButBitI(block, TOG, passflag, 0, (*layflag & passflag) ? ICON_DOT : ICON_BLANK1,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, layflag, 0, 0, 0, 0, "Exclude this Pass from Combined");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ layflag, 0, 0, 0, 0, "Exclude this Pass from Combined");
+ }
uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
uiBlockSetEmboss(block, UI_EMBOSS);
@@ -493,11 +505,13 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
uiBlockSetEmboss(block, UI_EMBOSSN);
bt = uiDefIconButBitI(block, ICONTOGN, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &(md->mode), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
bt = uiDefIconButBitI(block, ICONTOGN, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability");
uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob);
}
else if (tselem->type == TSE_POSE_CHANNEL) {
@@ -506,11 +520,13 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
uiBlockSetEmboss(block, UI_EMBOSSN);
bt = uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
uiButSetFunc(bt, restrictbutton_bone_cb, NULL, bone);
bt = uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL);
}
else if (tselem->type == TSE_EBONE) {
@@ -518,11 +534,13 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
uiBlockSetEmboss(block, UI_EMBOSSN);
bt = uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, ebone);
bt = uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X, UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, NULL);
}
}
@@ -535,7 +553,7 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex)
{
View2D *v2d = &ar->v2d;
- float miny = v2d->cur.ymin - V2D_SCROLL_HEIGHT;
+ float miny = v2d->cur.ymin;
if (miny < v2d->tot.ymin) miny = v2d->tot.ymin;
UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
@@ -832,7 +850,7 @@ static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soo
/* rna property */
if (kmi->ptr && kmi->ptr->data) {
- uiDefBut(block, LABEL, 0, "(RNA property)", xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->oskey, 0, 0, 0, 0, ""); xstart += butw2;
+ uiDefBut(block, LABEL, 0, "(RNA property)", xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, NULL, 0, 0, 0, 0, ""); xstart += butw2;
}
(void)xstart;
@@ -1515,13 +1533,13 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
/* selection status */
if (TSELEM_OPEN(tselem, soops))
if (tselem->type == TSE_RNA_STRUCT)
- glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax + V2D_SCROLL_WIDTH, *starty + UI_UNIT_Y - 1);
+ glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
*starty -= UI_UNIT_Y;
if (TSELEM_OPEN(tselem, soops)) {
outliner_draw_struct_marks(ar, soops, &te->subtree, starty);
if (tselem->type == TSE_RNA_STRUCT)
- fdrawline(0, (float)*starty + UI_UNIT_Y, ar->v2d.cur.xmax + V2D_SCROLL_WIDTH, (float)*starty + UI_UNIT_Y);
+ fdrawline(0, (float)*starty + UI_UNIT_Y, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
}
}
}
@@ -1590,7 +1608,7 @@ static void outliner_back(ARegion *ar)
ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
while (ystart + 2 * UI_UNIT_Y > ar->v2d.cur.ymin) {
- glRecti(0, ystart, (int)ar->v2d.cur.xmax + V2D_SCROLL_WIDTH, ystart + UI_UNIT_Y);
+ glRecti(0, ystart, (int)ar->v2d.cur.xmax, ystart + UI_UNIT_Y);
ystart -= 2 * UI_UNIT_Y;
}
}
@@ -1601,10 +1619,8 @@ static void outliner_draw_restrictcols(ARegion *ar)
/* background underneath */
UI_ThemeColor(TH_BACK);
- glRecti((int)ar->v2d.cur.xmax - OL_TOGW,
- (int)ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT - 1,
- (int)ar->v2d.cur.xmax + V2D_SCROLL_WIDTH,
- (int)ar->v2d.cur.ymax);
+ glRecti((int)(ar->v2d.cur.xmax - OL_TOGW),
+ (int)(ar->v2d.cur.ymin - 1), (int)ar->v2d.cur.xmax, (int)ar->v2d.cur.ymax);
UI_ThemeColorShade(TH_BACK, 6);
ystart = (int)ar->v2d.tot.ymax;
@@ -1618,22 +1634,22 @@ static void outliner_draw_restrictcols(ARegion *ar)
UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
/* view */
- fdrawline(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX,
- ar->v2d.cur.ymax,
- ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX,
- ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT);
+ sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ (int)ar->v2d.cur.ymax,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ (int)ar->v2d.cur.ymin);
/* render */
- fdrawline(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX,
- ar->v2d.cur.ymax,
- ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX,
- ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT);
+ sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+ (int)ar->v2d.cur.ymax,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+ (int)ar->v2d.cur.ymin);
/* render */
- fdrawline(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX,
- ar->v2d.cur.ymax,
- ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX,
- ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT);
+ sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ (int)ar->v2d.cur.ymax,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ (int)ar->v2d.cur.ymin);
}
/* ****************************************************** */
@@ -1682,11 +1698,9 @@ void draw_outliner(const bContext *C)
// XXX this isn't that great yet...
if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0)
sizex += OL_TOGW * 3;
+
}
- /* tweak to display last line (when list bigger than window) */
- sizey += V2D_SCROLL_HEIGHT;
-
/* adds vertical offset */
sizey += OL_Y_OFFSET;
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index f9fca378568..63452de18d0 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -116,8 +116,8 @@ typedef struct TreeElement {
/* size constants */
#define OL_Y_OFFSET 2
-#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 3)
-#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 2)
+#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 3.0f)
+#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 2.0f)
#define OL_TOG_RESTRICT_RENDERX UI_UNIT_X
#define OL_TOGW OL_TOG_RESTRICT_VIEWX
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index ddbc49bf995..f723fbedc7b 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -803,8 +803,12 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
/* One exception */
- if (type == TSE_ID_BASE);
- else if (id == NULL) return NULL;
+ if (type == TSE_ID_BASE) {
+ /* pass */
+ }
+ else if (id == NULL) {
+ return NULL;
+ }
te = MEM_callocN(sizeof(TreeElement), "tree elem");
/* add to the visual tree */
@@ -832,7 +836,11 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
/* pass */
}
else {
- te->name = id->name + 2; // default, can be overridden by Library or non-ID data
+ /* do here too, for blend file viewer, own ID_LI then shows file name */
+ if (GS(id->name) == ID_LI)
+ te->name = ((Library *)id)->name;
+ else
+ te->name = id->name + 2; // default, can be overridden by Library or non-ID data
te->idcode = GS(id->name);
}
@@ -840,7 +848,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
TreeStoreElem *tsepar = parent ? TREESTORE(parent) : NULL;
/* ID datablock */
- if (tsepar==NULL || tsepar->type != TSE_ID_BASE)
+ if (tsepar == NULL || tsepar->type != TSE_ID_BASE)
outliner_add_id_contents(soops, te, tselem, id);
}
else if (type == TSE_ANIM_DATA) {
@@ -1511,7 +1519,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
}
/* make hierarchy */
ten = soops->tree.first;
- ten= ten->next; /* first one is main */
+ ten = ten->next; /* first one is main */
while (ten) {
TreeElement *nten = ten->next, *par;
tselem = TREESTORE(ten);
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index ecc09a35670..4bf88376b74 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -67,6 +67,17 @@ static void outliner_main_area_init(wmWindowManager *wm, ARegion *ar)
ListBase *lb;
wmKeyMap *keymap;
+ /* make sure we keep the hide flags */
+ ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+ ar->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP); /* prevent any noise of past */
+ ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+ ar->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE;
+
+ ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+ ar->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
+ ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f;
+
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
/* own keymap */
@@ -410,12 +421,6 @@ static SpaceLink *outliner_new(const bContext *UNUSED(C))
BLI_addtail(&soutliner->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
- ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM_O);
- ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
- ar->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
- ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f;
-
return (SpaceLink *)soutliner;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 6219a9061f4..29a6a1f6d50 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -49,6 +49,8 @@
#include "DNA_mask_types.h"
#include "DNA_userdef_types.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_library.h"
@@ -400,6 +402,7 @@ void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot)
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
prop = RNA_def_enum(ot->srna, "clip", DummyRNA_NULL_items, 0, "Clip", "");
RNA_def_enum_funcs(prop, RNA_movieclip_itemf);
+ RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_MOVIECLIP);
ot->prop = prop;
}
@@ -871,7 +874,7 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
if (BKE_sequence_test_overlap(ed->seqbasep, seq)) BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
}
- BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1); /* runs calc_sequence */
+ BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1); /* runs BKE_sequence_calc */
/* not sure if this is needed with update_changed_seq_and_deps.
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 409f655bb79..c6c70ccb424 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -925,7 +925,7 @@ static void set_filter_seq(Scene *scene)
if (seq->type == SEQ_TYPE_MOVIE) {
seq->flag |= SEQ_FILTERY;
reload_sequence_new_file(scene, seq, FALSE);
- calc_sequence(scene, seq);
+ BKE_sequence_calc(scene, seq);
}
}
@@ -1906,6 +1906,9 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
for (seq = ed->seqbasep->first; seq; seq = seq->next)
BKE_sequence_calc(scene, seq);
+ if (BKE_sequence_test_overlap(ed->seqbasep, ms->parseq))
+ BKE_sequence_base_shuffle(ed->seqbasep, ms->parseq, scene);
+
BKE_sequencer_active_set(scene, ms->parseq);
ms->parseq->flag |= SELECT;
diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt
index 6aaf4212779..a33a9abada1 100644
--- a/source/blender/editors/space_text/CMakeLists.txt
+++ b/source/blender/editors/space_text/CMakeLists.txt
@@ -36,12 +36,13 @@ set(INC_SYS
set(SRC
space_text.c
+ text_autocomplete.c
text_draw.c
text_format.c
+ text_format_osl.c
text_format_py.c
text_header.c
text_ops.c
- text_python.c
text_format.h
text_intern.h
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index 9ac66ca1698..fa3eefcc0f7 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -223,6 +223,8 @@ static void text_operatortypes(void)
WM_operatortype_append(TEXT_OT_to_3d_object);
WM_operatortype_append(TEXT_OT_resolve_conflict);
+
+ WM_operatortype_append(TEXT_OT_autocomplete);
}
static void text_keymap(struct wmKeyConfig *keyconf)
@@ -276,7 +278,7 @@ static void text_keymap(struct wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADMINUS, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
RNA_boolean_set(kmi->ptr, "reverse", TRUE);
-
+
WM_keymap_add_item(keymap, "TEXT_OT_new", NKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "TEXT_OT_open", OKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "TEXT_OT_reload", RKEY, KM_PRESS, KM_ALT, 0);
@@ -375,6 +377,8 @@ static void text_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "TEXT_OT_line_break", PADENTER, KM_PRESS, 0, 0);
WM_keymap_add_menu(keymap, "TEXT_MT_toolbox", RIGHTMOUSE, KM_PRESS, KM_ANY, 0);
+
+ WM_keymap_add_item(keymap, "TEXT_OT_autocomplete", SPACEKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "TEXT_OT_line_number", KM_TEXTINPUT, KM_ANY, KM_ANY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_insert", KM_TEXTINPUT, KM_ANY, KM_ANY, 0); // last!
@@ -555,5 +559,6 @@ void ED_spacetype_text(void)
/* register formatters */
ED_text_format_register_py();
+ ED_text_format_register_osl();
}
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
new file mode 100644
index 00000000000..e406a1b7166
--- /dev/null
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -0,0 +1,541 @@
+/*
+ * ***** 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_text/text_autocomplete.c
+ * \ingroup sptext
+ */
+
+#include <ctype.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_text_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+
+#include "BKE_context.h"
+#include "BKE_text.h"
+#include "BKE_screen.h"
+#include "BKE_suggestions.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "UI_interface.h"
+
+#include "text_format.h"
+#include "text_intern.h" /* own include */
+
+
+/* -------------------------------------------------------------------- */
+/* Public API */
+
+int text_do_suggest_select(SpaceText *st, ARegion *ar)
+{
+ SuggItem *item, *first, *last /* , *sel */ /* UNUSED */;
+ TextLine *tmp;
+ int l, x, y, w, h, i;
+ int tgti, *top;
+ int mval[2] = {0, 0};
+
+ if (!st || !st->text) return 0;
+ if (!texttool_text_is_active(st->text)) return 0;
+
+ first = texttool_suggest_first();
+ last = texttool_suggest_last();
+ /* sel = texttool_suggest_selected(); */ /* UNUSED */
+ top = texttool_suggest_top();
+
+ if (!last || !first)
+ return 0;
+
+ /* Count the visible lines to the cursor */
+ for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ;
+ if (l < 0) return 0;
+
+ text_update_character_width(st);
+
+ if (st->showlinenrs) {
+ x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
+ }
+ else {
+ x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
+ }
+ y = ar->winy - st->lheight_dpi * l - 2;
+
+ w = SUGG_LIST_WIDTH * st->cwidth + U.widget_unit;
+ h = SUGG_LIST_SIZE * st->lheight_dpi + 0.4f * U.widget_unit;
+
+ // XXX getmouseco_areawin(mval);
+
+ if (mval[0] < x || x + w < mval[0] || mval[1] < y - h || y < mval[1])
+ return 0;
+
+ /* Work out which of the items is at the top of the visible list */
+ for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ;
+
+ /* Work out the target item index in the visible list */
+ tgti = (y - mval[1] - 4) / st->lheight_dpi;
+ if (tgti < 0 || tgti > SUGG_LIST_SIZE)
+ return 1;
+
+ for (i = tgti; i > 0 && item->next; i--, item = item->next) ;
+ if (item)
+ texttool_suggest_select(item);
+ return 1;
+}
+
+void text_pop_suggest_list(void)
+{
+ SuggItem *item, *sel;
+ int *top, i;
+
+ item = texttool_suggest_first();
+ sel = texttool_suggest_selected();
+ top = texttool_suggest_top();
+
+ i = 0;
+ while (item && item != sel) {
+ item = item->next;
+ i++;
+ }
+ if (i > *top + SUGG_LIST_SIZE - 1)
+ *top = i - SUGG_LIST_SIZE + 1;
+ else if (i < *top)
+ *top = i;
+}
+
+/* -------------------------------------------------------------------- */
+/* Private API */
+
+static void text_autocomplete_free(bContext *C, wmOperator *op);
+
+static GHash *text_autocomplete_build(Text *text)
+{
+ GHash *gh;
+ int seek_len = 0;
+ const char *seek;
+ texttool_text_clear();
+
+ texttool_text_set_active(text);
+
+ /* first get the word we're at */
+ {
+ const int i = text_find_identifier_start(text->curl->line, text->curc);
+ seek_len = text->curc - i;
+ seek = text->curl->line + i;
+
+ // BLI_strncpy(seek, seek_ptr, seek_len);
+ }
+
+ /* now walk over entire doc and suggest words */
+ {
+ TextLine *linep;
+
+ gh = BLI_ghash_str_new(__func__);
+
+ for (linep = text->lines.first; linep; linep = linep->next) {
+ int i_start = 0;
+ int i_end = 0;
+
+ while (i_start < linep->len) {
+ /* seek identifier beginning */
+ while (i_start < linep->len && !text_check_identifier(linep->line[i_start])) {
+ i_start++;
+ }
+ i_end = i_start;
+ while (i_end < linep->len && text_check_identifier(linep->line[i_end])) {
+ i_end++;
+ }
+
+ if (i_start != i_end) {
+ char *str_sub = &linep->line[i_start];
+ const int choice_len = i_end - i_start;
+
+ if ((choice_len > seek_len) &&
+ (seek_len == 0 || strncmp(seek, str_sub, seek_len) == 0) &&
+ (seek != str_sub))
+ {
+ // printf("Adding: %s\n", s);
+ char str_sub_last = str_sub[choice_len];
+ str_sub[choice_len] = '\0';
+ if (!BLI_ghash_lookup(gh, str_sub)) {
+ char *str_dup = BLI_strdupn(str_sub, choice_len);
+ BLI_ghash_insert(gh, str_dup, str_dup); /* A 'set' would make more sense here */
+ }
+ str_sub[choice_len] = str_sub_last;
+ }
+ }
+ i_start = i_end;
+ }
+ }
+
+ {
+ GHashIterator *iter = BLI_ghashIterator_new(gh);
+
+ /* get the formatter for highlighting */
+ TextFormatType *tft;
+ tft = ED_text_format_get(text);
+
+ for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
+ const char *s = BLI_ghashIterator_getValue(iter);
+ texttool_suggest_add(s, tft->format_identifier(s));
+ }
+ BLI_ghashIterator_free(iter);
+
+ }
+ }
+
+ texttool_suggest_prefix(seek, seek_len);
+
+ return gh;
+}
+
+/* -- */
+
+static void get_suggest_prefix(Text *text, int offset)
+{
+ int i, len;
+ char *line;
+
+ if (!text) return;
+ if (!texttool_text_is_active(text)) return;
+
+ line = text->curl->line;
+ i = text_find_identifier_start(line, text->curc + offset);
+ len = text->curc - i + offset;
+ texttool_suggest_prefix(line + i, len);
+}
+
+static void confirm_suggestion(Text *text)
+{
+ SuggItem *sel;
+ int i, over = 0;
+ const char *line;
+
+ if (!text) return;
+ if (!texttool_text_is_active(text)) return;
+
+ sel = texttool_suggest_selected();
+ if (!sel) return;
+
+ line = text->curl->line;
+ i = text_find_identifier_start(line, text->curc /* - skipleft */);
+ over = text->curc - i;
+
+// for (i = 0; i < skipleft; i++)
+// txt_move_left(text, 0);
+ for (i = 0; i < over; i++)
+ txt_move_left(text, 1);
+
+ txt_insert_buf(text, sel->name);
+
+// for (i = 0; i < skipleft; i++)
+// txt_move_right(text, 0);
+
+ texttool_text_clear();
+}
+
+/* -- */
+
+
+static int text_autocomplete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+{
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
+
+ st->doplugins = TRUE;
+ op->customdata = text_autocomplete_build(text);
+
+ if (texttool_suggest_first()) {
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ if (texttool_suggest_first() == texttool_suggest_last()) {
+ confirm_suggestion(st->text);
+ text_update_line_edited(st->text->curl);
+ text_autocomplete_free(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ else {
+ text_autocomplete_free(C, op);
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static int doc_scroll = 0;
+
+static int text_autocomplete_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceText *st = CTX_wm_space_text(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+
+ int draw = 0, tools = 0, swallow = 0, scroll = 1;
+ Text *text = CTX_data_edit_text(C);
+ int retval = OPERATOR_RUNNING_MODAL;
+
+ (void)text;
+
+ if (st->doplugins && texttool_text_is_active(st->text)) {
+ if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST;
+ if (texttool_docs_get()) tools |= TOOL_DOCUMENT;
+ }
+
+ switch (event->type) {
+ case LEFTMOUSE:
+ if (event->val == KM_PRESS) {
+ if (text_do_suggest_select(st, ar))
+ swallow = 1;
+ else {
+ if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
+ if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+ retval = OPERATOR_FINISHED;
+ }
+ draw = 1;
+ }
+ break;
+ case MIDDLEMOUSE:
+ if (event->val == KM_PRESS) {
+ if (text_do_suggest_select(st, ar)) {
+ confirm_suggestion(st->text);
+ text_update_line_edited(st->text->curl);
+ swallow = 1;
+ }
+ else {
+ if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
+ if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+ retval = OPERATOR_FINISHED;
+ }
+ draw = 1;
+ }
+ break;
+ case ESCKEY:
+ if (event->val == KM_PRESS) {
+ draw = swallow = 1;
+ if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
+ else if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+ else draw = swallow = 0;
+ retval = OPERATOR_CANCELLED;
+ }
+ break;
+ case RETKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_SUGG_LIST) {
+ confirm_suggestion(st->text);
+ text_update_line_edited(st->text->curl);
+ swallow = 1;
+ draw = 1;
+ }
+ if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
+ retval = OPERATOR_FINISHED;
+ }
+ break;
+ case LEFTARROWKEY:
+ case BACKSPACEKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_SUGG_LIST) {
+ if (event->ctrl) {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ else {
+ /* Work out which char we are about to delete/pass */
+ if (st->text->curl && st->text->curc > 0) {
+ char ch = st->text->curl->line[st->text->curc - 1];
+ if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
+ get_suggest_prefix(st->text, -1);
+ text_pop_suggest_list();
+ }
+ else {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ }
+ }
+ if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+ }
+ break;
+ case RIGHTARROWKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_SUGG_LIST) {
+ if (event->ctrl) {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ else {
+ /* Work out which char we are about to pass */
+ if (st->text->curl && st->text->curc < st->text->curl->len) {
+ char ch = st->text->curl->line[st->text->curc + 1];
+ if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
+ get_suggest_prefix(st->text, 1);
+ text_pop_suggest_list();
+ }
+ else {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ }
+ }
+ if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+ }
+ break;
+ case PAGEDOWNKEY:
+ scroll = SUGG_LIST_SIZE - 1;
+ case WHEELDOWNMOUSE:
+ case DOWNARROWKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_DOCUMENT) {
+ doc_scroll++;
+ swallow = 1;
+ draw = 1;
+ }
+ else if (tools & TOOL_SUGG_LIST) {
+ SuggItem *sel = texttool_suggest_selected();
+ if (!sel) {
+ texttool_suggest_select(texttool_suggest_first());
+ }
+ else {
+ while (sel && sel != texttool_suggest_last() && sel->next && scroll--) {
+ texttool_suggest_select(sel->next);
+ sel = sel->next;
+ }
+ }
+ text_pop_suggest_list();
+ swallow = 1;
+ draw = 1;
+ }
+ }
+ break;
+ case PAGEUPKEY:
+ scroll = SUGG_LIST_SIZE - 1;
+ case WHEELUPMOUSE:
+ case UPARROWKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_DOCUMENT) {
+ if (doc_scroll > 0) doc_scroll--;
+ swallow = 1;
+ draw = 1;
+ }
+ else if (tools & TOOL_SUGG_LIST) {
+ SuggItem *sel = texttool_suggest_selected();
+ while (sel && sel != texttool_suggest_first() && sel->prev && scroll--) {
+ texttool_suggest_select(sel->prev);
+ sel = sel->prev;
+ }
+ text_pop_suggest_list();
+ swallow = 1;
+ draw = 1;
+ }
+ }
+ break;
+ case RIGHTSHIFTKEY:
+ case LEFTSHIFTKEY:
+ break;
+#if 0
+ default:
+ if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw = 1;
+ if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
+#endif
+ }
+
+ if (draw) {
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+// if (swallow) {
+// retval = OPERATOR_RUNNING_MODAL;
+// }
+
+ if (texttool_suggest_first()) {
+ if (retval != OPERATOR_RUNNING_MODAL) {
+ text_autocomplete_free(C, op);
+ }
+ return retval;
+ }
+ else {
+ text_autocomplete_free(C, op);
+ return OPERATOR_FINISHED;
+ }
+}
+
+static void text_autocomplete_free(bContext *C, wmOperator *op)
+{
+ GHash *gh = op->customdata;
+ if (gh) {
+ BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
+ op->customdata = NULL;
+ }
+
+ /* other stuff */
+ {
+ SpaceText *st = CTX_wm_space_text(C);
+ st->doplugins = FALSE;
+ texttool_text_clear();
+ }
+}
+
+static int text_autocomplete_cancel(bContext *C, wmOperator *op)
+{
+ text_autocomplete_free(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+void TEXT_OT_autocomplete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Text Auto Complete";
+ ot->description = "Show a list of used text in the open document";
+ ot->idname = "TEXT_OT_autocomplete";
+
+ /* api callbacks */
+ ot->invoke = text_autocomplete_invoke;
+ ot->cancel = text_autocomplete_cancel;
+ ot->modal = text_autocomplete_modal;
+ ot->poll = text_space_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
+}
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 7d4c9e5af98..c264368e714 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -77,26 +77,17 @@ static int text_font_draw(SpaceText *UNUSED(st), int x, int y, const char *str)
static int text_font_draw_character(SpaceText *st, int x, int y, char c)
{
- char str[2];
- str[0] = c;
- str[1] = '\0';
-
BLF_position(mono, x, y, 0);
- BLF_draw(mono, str, 1);
+ BLF_draw(mono, &c, 1);
return st->cwidth;
}
static int text_font_draw_character_utf8(SpaceText *st, int x, int y, const char *c)
{
- char str[BLI_UTF8_MAX + 1];
- size_t len = BLI_str_utf8_size_safe(c);
- memcpy(str, c, len);
- str[len] = '\0';
-
+ const size_t len = BLI_str_utf8_size_safe(c);
BLF_position(mono, x, y, 0);
- BLF_draw(mono, str, len);
-
+ BLF_draw(mono, c, len);
return st->cwidth;
}
@@ -117,27 +108,33 @@ static void txt_format_text(SpaceText *st)
static void format_draw_color(char formatchar)
{
switch (formatchar) {
- case '_': /* Whitespace */
+ case FMT_TYPE_WHITESPACE:
break;
- case '!': /* Symbols */
- UI_ThemeColorBlend(TH_TEXT, TH_BACK, 0.5f);
+ case FMT_TYPE_SYMBOL:
+ UI_ThemeColor(TH_SYNTAX_S);
break;
- case '#': /* Comments */
+ case FMT_TYPE_COMMENT:
UI_ThemeColor(TH_SYNTAX_C);
break;
- case 'n': /* Numerals */
+ case FMT_TYPE_NUMERAL:
UI_ThemeColor(TH_SYNTAX_N);
break;
- case 'l': /* Strings */
+ case FMT_TYPE_STRING:
UI_ThemeColor(TH_SYNTAX_L);
break;
- case 'v': /* Specials: class, def */
+ case FMT_TYPE_DIRECTIVE:
+ UI_ThemeColor(TH_SYNTAX_D);
+ break;
+ case FMT_TYPE_SPECIAL:
UI_ThemeColor(TH_SYNTAX_V);
break;
- case 'b': /* Keywords: for, print, etc. */
+ case FMT_TYPE_RESERVED:
+ UI_ThemeColor(TH_SYNTAX_R);
+ break;
+ case FMT_TYPE_KEYWORD:
UI_ThemeColor(TH_SYNTAX_B);
break;
- case 'q': /* Other text (identifiers) */
+ case FMT_TYPE_DEFAULT:
default:
UI_ThemeColor(TH_TEXT);
break;
@@ -359,6 +356,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
FlattenString fs;
int basex, i, a, start, end, max, lines; /* view */
int mi, ma, mstart, mend; /* mem */
+ char fmt_prev = 0xff;
flatten_string(st, &fs, str);
str = fs.buf;
@@ -382,7 +380,9 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
/* Draw the visible portion of text on the overshot line */
for (a = start, ma = mstart; a < end; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
- if (st->showsyntax && format) format_draw_color(format[a]);
+ if (st->showsyntax && format) {
+ if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
+ }
x += text_font_draw_character_utf8(st, x, y, str + ma);
}
y -= st->lheight_dpi + TXT_LINE_SPACING;
@@ -400,8 +400,9 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
/* Draw the remaining text */
for (a = start, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
- if (st->showsyntax && format)
- format_draw_color(format[a]);
+ if (st->showsyntax && format) {
+ if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
+ }
x += text_font_draw_character_utf8(st, x, y, str + ma);
}
@@ -432,15 +433,18 @@ static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int dra
if (st->showsyntax && format) {
int a, str_shift = 0;
+ char fmt_prev = 0xff;
format = format + cshift;
for (a = 0; a < amount; a++) {
- format_draw_color(format[a]);
+ if (format[a] != fmt_prev) format_draw_color(fmt_prev = format[a]);
x += text_font_draw_character_utf8(st, x, y, in + str_shift);
str_shift += BLI_str_utf8_size_safe(in + str_shift);
}
}
- else text_font_draw(st, x, y, in);
+ else {
+ text_font_draw(st, x, y, in);
+ }
}
else {
while (w-- && *acc++ < maxwidth)
@@ -890,7 +894,7 @@ static void draw_documentation(SpaceText *st, ARegion *ar)
/* top = */ /* UNUSED */ y = ar->winy - st->lheight_dpi * l - 2;
boxw = DOC_WIDTH * st->cwidth + 20;
- boxh = (DOC_HEIGHT + 1) * st->lheight_dpi;
+ boxh = (DOC_HEIGHT + 1) * (st->lheight_dpi + TXT_LINE_SPACING);
/* Draw panel */
UI_ThemeColor(TH_BACK);
@@ -953,9 +957,11 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
SuggItem *item, *first, *last, *sel;
TextLine *tmp;
char str[SUGG_LIST_WIDTH + 1];
- int w, boxw = 0, boxh, i, l, x, y, b, *top;
+ int w, boxw = 0, boxh, i, l, x, y, *top;
+ const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
+ const int margin_x = 2;
- if (!st || !st->text) return;
+ if (!st->text) return;
if (!texttool_text_is_active(st->text)) return;
first = texttool_suggest_first();
@@ -977,14 +983,20 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
else {
x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
}
- y = ar->winy - st->lheight_dpi * l - 2;
+ /* offset back so the start of the text lines up with the suggestions,
+ * not essential but makes suggestions easier to follow */
+ x -= st->cwidth * (st->text->curc - text_find_identifier_start(st->text->curl->line, st->text->curc));
+ y = ar->winy - lheight * l - 2;
boxw = SUGG_LIST_WIDTH * st->cwidth + 20;
- boxh = SUGG_LIST_SIZE * st->lheight_dpi + 8;
+ boxh = SUGG_LIST_SIZE * lheight + 8;
+ /* not needed but stands out nicer */
+ uiDrawBoxShadow(220, x, y - boxh, x + boxw, y);
+
UI_ThemeColor(TH_SHADE1);
glRecti(x - 1, y + 1, x + boxw + 1, y - boxh - 1);
- UI_ThemeColor(TH_BACK);
+ UI_ThemeColorShade(TH_BACK, 16);
glRecti(x, y, x + boxw, y - boxh);
/* Set the top 'item' of the visible list */
@@ -992,7 +1004,7 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
for (i = 0; i < SUGG_LIST_SIZE && item; i++, item = item->next) {
- y -= st->lheight_dpi;
+ y -= lheight;
BLI_strncpy(str, item->name, SUGG_LIST_WIDTH);
@@ -1000,21 +1012,11 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
if (item == sel) {
UI_ThemeColor(TH_SHADE2);
- glRecti(x + 16, y - 3, x + 16 + w, y + st->lheight_dpi - 3);
+ glRecti(x + margin_x, y - 3, x + margin_x + w, y + lheight - 3);
}
- b = 1; /* b=1 color block, text is default. b=0 no block, color text */
- switch (item->type) {
- case 'k': UI_ThemeColor(TH_SYNTAX_B); b = 0; break;
- case 'm': UI_ThemeColor(TH_TEXT); break;
- case 'f': UI_ThemeColor(TH_SYNTAX_L); break;
- case 'v': UI_ThemeColor(TH_SYNTAX_N); break;
- case '?': UI_ThemeColor(TH_TEXT); b = 0; break;
- }
- if (b) {
- glRecti(x + 8, y + 2, x + 11, y + 5);
- UI_ThemeColor(TH_TEXT);
- }
- text_draw(st, str, 0, 0, 1, x + 16, y - 1, NULL);
+
+ format_draw_color(item->type);
+ text_draw(st, str, 0, 0, 1, x + margin_x, y - 1, NULL);
if (item == last) break;
}
@@ -1027,7 +1029,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
Text *text = st->text;
int vcurl, vcurc, vsell, vselc, hidden = 0;
int x, y, w, i;
- int lheight = st->lheight_dpi + TXT_LINE_SPACING;
+ const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
/* Draw the selection */
if (text->curl != text->sell || text->curc != text->selc) {
@@ -1168,7 +1170,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
stack = 0;
/* Don't highlight backets if syntax HL is off or bracket in string or comment. */
- if (!linep->format || linep->format[fc] == 'l' || linep->format[fc] == '#')
+ if (!linep->format || linep->format[fc] == FMT_TYPE_STRING || linep->format[fc] == FMT_TYPE_COMMENT)
return;
if (b > 0) {
@@ -1177,7 +1179,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
c += BLI_str_utf8_size_safe(linep->line + c);
while (linep) {
while (c < linep->len) {
- if (linep->format && linep->format[fc] != 'l' && linep->format[fc] != '#') {
+ if (linep->format && linep->format[fc] != FMT_TYPE_STRING && linep->format[fc] != FMT_TYPE_COMMENT) {
b = text_check_bracket(linep->line[c]);
if (b == find) {
if (stack == 0) {
@@ -1206,7 +1208,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
if (c > 0) c -= linep->line + c - BLI_str_prev_char_utf8(linep->line + c);
while (linep) {
while (fc >= 0) {
- if (linep->format && linep->format[fc] != 'l' && linep->format[fc] != '#') {
+ if (linep->format && linep->format[fc] != FMT_TYPE_STRING && linep->format[fc] != FMT_TYPE_COMMENT) {
b = text_check_bracket(linep->line[c]);
if (b == find) {
if (stack == 0) {
@@ -1271,7 +1273,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
void draw_text_main(SpaceText *st, ARegion *ar)
{
Text *text = st->text;
- TextFormatType *tft = ED_text_format_get(text);
+ TextFormatType *tft;
TextLine *tmp;
rcti scroll, back;
char linenr[12];
@@ -1299,6 +1301,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
calc_text_rcts(st, ar, &scroll, &back); /* scroll will hold the entire bar size */
/* update syntax formatting if needed */
+ tft = ED_text_format_get(text);
tmp = text->lines.first;
lineno = 0;
for (i = 0; i < st->top && tmp; i++) {
diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c
index 0b3856f4414..294f94dd4b7 100644
--- a/source/blender/editors/space_text/text_format.c
+++ b/source/blender/editors/space_text/text_format.c
@@ -113,6 +113,14 @@ void flatten_string_free(FlattenString *fs)
MEM_freeN(fs->accum);
}
+/* takes a string within fs->buf and returns its length */
+int flatten_string_strlen(FlattenString *fs, const char *str)
+{
+ const int len = (fs->pos - (int)(str - fs->buf)) - 1;
+ BLI_assert(strlen(str) == len);
+ return len;
+}
+
/* Ensures the format string for the given line is long enough, reallocating
* as needed. Allocation is done here, alone, to ensure consistency. */
int text_check_format_len(TextLine *line, unsigned int len)
@@ -139,10 +147,16 @@ void ED_text_format_register(TextFormatType *tft)
BLI_addtail(&tft_lb, tft);
}
-TextFormatType *ED_text_format_get(Text *UNUSED(text))
+TextFormatType *ED_text_format_get(Text *text)
{
/* NOTE: once more types are added we'll need to return some type based on 'text'
* for now this function is more of a placeholder */
- return tft_lb.first;
+ /* XXX, wrong, but OK for testing */
+ if (text && BLI_testextensie(text->id.name + 2, ".osl")) {
+ return tft_lb.last;
+ }
+ else {
+ return tft_lb.first;
+ }
}
diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h
index 7b5b326db6a..e593e41d42c 100644
--- a/source/blender/editors/space_text/text_format.h
+++ b/source/blender/editors/space_text/text_format.h
@@ -41,8 +41,24 @@ typedef struct FlattenString {
int pos, len;
} FlattenString;
+/* format continuation flags (stored just after the NULL terminator) */
+enum {
+ FMT_CONT_NOP = 0, /* no continuation */
+ FMT_CONT_QUOTESINGLE = (1 << 0), /* single quotes */
+ FMT_CONT_QUOTEDOUBLE = (1 << 1), /* double quotes */
+ FMT_CONT_TRIPLE = (1 << 2), /* triplets of quotes: """ or ''' */
+ FMT_CONT_QUOTESINGLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTESINGLE),
+ FMT_CONT_QUOTEDOUBLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTEDOUBLE),
+ FMT_CONT_COMMENT_C = (1 << 3), /* multi-line comments, OSL only (C style) */
+ FMT_CONT_COMMENT_CXX = (1 << 4), /* single-line comments, OSL only (C++ style) */
+};
+#define FMT_CONT_ALL \
+ (FMT_CONT_QUOTESINGLE | FMT_CONT_QUOTEDOUBLE | FMT_CONT_TRIPLE | FMT_CONT_COMMENT_C | FMT_CONT_COMMENT_CXX)
+
int flatten_string(struct SpaceText *st, FlattenString *fs, const char *in);
void flatten_string_free(FlattenString *fs);
+int flatten_string_strlen(FlattenString *fs, const char *str);
+
int text_check_format_len(TextLine *line, unsigned int len);
@@ -50,28 +66,43 @@ int text_check_format_len(TextLine *line, unsigned int len);
typedef struct TextFormatType {
struct TextFormatType *next, *prev;
+ char (*format_identifier)(const char *string);
+
/* Formats the specified line. If do_next is set, the process will move on to
* the succeeding line if it is affected (eg. multiline strings). Format strings
* may contain any of the following characters:
- * '_' Whitespace
- * '#' Comment text
- * '!' Punctuation and other symbols
- * 'n' Numerals
- * 'l' String letters
- * 'v' Special variables (class, def)
- * 'b' Built-in names (print, for, etc.)
- * 'q' Other text (identifiers, etc.)
+ *
* It is terminated with a null-terminator '\0' followed by a continuation
- * flag indicating whether the line is part of a multi-line string. */
+ * flag indicating whether the line is part of a multi-line string.
+ *
+ * See: FMT_TYPE_ enums below
+ */
void (*format_line)(SpaceText *st, TextLine *line, int do_next);
const char **ext; /* NULL terminated extensions */
} TextFormatType;
+enum {
+ FMT_TYPE_WHITESPACE = '_', /* Whitespace */
+ FMT_TYPE_COMMENT = '#', /* Comment text */
+ FMT_TYPE_SYMBOL = '!', /* Punctuation and other symbols */
+ FMT_TYPE_NUMERAL = 'n', /* Numerals */
+ FMT_TYPE_STRING = 'l', /* String letters */
+ FMT_TYPE_DIRECTIVE = 'd', /* Decorator / Preprocessor directive */
+ FMT_TYPE_SPECIAL = 'v', /* Special variables (class, def) */
+ FMT_TYPE_RESERVED = 'r', /* Reserved keywords currently not in use, but still prohibited (OSL -> switch e.g.) */
+ FMT_TYPE_KEYWORD = 'b', /* Built-in names (return, for, etc.) */
+ FMT_TYPE_DEFAULT = 'q', /* Regular text (identifiers, etc.) */
+};
+
TextFormatType *ED_text_format_get(Text *text);
void ED_text_format_register(TextFormatType *tft);
/* formatters */
void ED_text_format_register_py(void);
+void ED_text_format_register_osl(void);
+
+#define STR_LITERAL_STARTSWITH(str, str_literal, len_var) \
+ (strncmp(str, str_literal, len_var = (sizeof(str_literal) - 1)) == 0)
#endif /* __TEXT_FORMAT_H__ */
diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
new file mode 100644
index 00000000000..3120e88163e
--- /dev/null
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -0,0 +1,335 @@
+/*
+ * ***** 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
+ * 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_text/text_format_osl.c
+ * \ingroup sptext
+ */
+
+#include <string.h>
+
+#include "BLI_blenlib.h"
+
+#include "DNA_text_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_text.h"
+
+#include "text_format.h"
+
+/* *** Local Functions (for format_line) *** */
+
+static int txtfmt_osl_find_builtinfunc(const char *string)
+{
+ int i, len;
+ /* list is from
+ * https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
+ */
+ if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "closure", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "continue", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "do", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "emit", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "float", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "illuminance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "illuminate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "int", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "matrix", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "output", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "point", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "public", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "string", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "struct", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vector", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "void", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
+}
+
+static int txtfmt_osl_find_reserved(const char *string)
+{
+ int i, len;
+ /* list is from...
+ * https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
+ */
+ if (STR_LITERAL_STARTSWITH(string, "bool", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "catch", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "char", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "const", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "delete", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "double", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "enum", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "extern", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "friend", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "goto", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "long", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "new", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "operator", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "private", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "protected", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "short", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "signed", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sizeof", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "static", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "template", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "this", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "throw", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "try", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "typedef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uniform", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "union", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "unsigned", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "varying", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "virtual", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "volatile", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
+}
+
+/* Checks the specified source string for a OSL special name. This name must
+ * start at the beginning of the source string and must be followed by a non-
+ * identifier (see text_check_identifier(char)) or null character.
+ *
+ * If a special name is found, the length of the matching name is returned.
+ * Otherwise, -1 is returned. */
+
+static int txtfmt_osl_find_specialvar(const char *string)
+{
+ int i, len;
+
+ /* OSL shader types */
+ if (STR_LITERAL_STARTSWITH(string, "shader", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "surface", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "volume", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "displacement", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
+}
+
+/* matches py 'txtfmt_osl_find_decorator' */
+static int txtfmt_osl_find_preprocessor(const char *string)
+{
+ if (string[0] == '#') {
+ int i = 1;
+ /* Whitespace is ok '# foo' */
+ while (text_check_whitespace(string[i])) {
+ i++;
+ }
+ while (text_check_identifier(string[i])) {
+ i++;
+ }
+ return i;
+ }
+ return -1;
+}
+
+static char txtfmt_osl_format_identifier(const char *str)
+{
+ char fmt;
+ if ((txtfmt_osl_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
+ else if ((txtfmt_osl_find_builtinfunc(str)) != -1) fmt = FMT_TYPE_KEYWORD;
+ else if ((txtfmt_osl_find_reserved(str)) != -1) fmt = FMT_TYPE_RESERVED;
+ else if ((txtfmt_osl_find_preprocessor(str)) != -1) fmt = FMT_TYPE_DIRECTIVE;
+ else fmt = FMT_TYPE_DEFAULT;
+ return fmt;
+}
+
+static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_next)
+{
+ FlattenString fs;
+ const char *str;
+ char *fmt;
+ char cont_orig, cont, find, prev = ' ';
+ int len, i;
+
+ /* Get continuation from previous line */
+ if (line->prev && line->prev->format != NULL) {
+ fmt = line->prev->format;
+ cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont) == cont);
+ }
+ else {
+ cont = FMT_CONT_NOP;
+ }
+
+ /* Get original continuation from this line */
+ if (line->format != NULL) {
+ fmt = line->format;
+ cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
+ }
+ else {
+ cont_orig = 0xFF;
+ }
+
+ len = flatten_string(st, &fs, line->line);
+ str = fs.buf;
+ if (!text_check_format_len(line, len)) {
+ flatten_string_free(&fs);
+ return;
+ }
+ fmt = line->format;
+
+ while (*str) {
+ /* Handle escape sequences by skipping both \ and next char */
+ if (*str == '\\') {
+ *fmt = prev; fmt++; str++;
+ if (*str == '\0') break;
+ *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
+ continue;
+ }
+ /* Handle continuations */
+ else if (cont) {
+ /* C-Style comments */
+ if (cont & FMT_CONT_COMMENT_CXX) {
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ else if (cont & FMT_CONT_COMMENT_C) {
+ if (*str == '*' && *(str + 1) == '/') {
+ *fmt = FMT_TYPE_COMMENT; fmt++; str++;
+ *fmt = FMT_TYPE_COMMENT;
+ cont = FMT_CONT_NOP;
+ }
+ else {
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* Handle other comments */
+ }
+ else {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find) cont = 0;
+ *fmt = FMT_TYPE_STRING;
+ }
+
+ str += BLI_str_utf8_size_safe(str) - 1;
+ }
+ /* Not in a string... */
+ else {
+ /* Deal with comments first */
+ if (*str == '/' && *(str + 1) == '/') {
+ cont = FMT_CONT_COMMENT_CXX;
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* C-Style (multi-line) comments */
+ else if (*str == '/' && *(str + 1) == '*') {
+ cont = FMT_CONT_COMMENT_C;
+ *fmt = FMT_TYPE_COMMENT; fmt++; str++;
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ else if (*str == '"' || *str == '\'') {
+ /* Strings */
+ find = *str;
+ cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
+ *fmt = FMT_TYPE_STRING;
+ }
+ /* Whitespace (all ws. has been converted to spaces) */
+ else if (*str == ' ') {
+ *fmt = FMT_TYPE_WHITESPACE;
+ }
+ /* Numbers (digits not part of an identifier and periods followed by digits) */
+ else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+ (*str == '.' && text_check_digit(*(str + 1))))
+ {
+ *fmt = FMT_TYPE_NUMERAL;
+ }
+ /* Punctuation */
+ else if ((*str != '#') && text_check_delim(*str)) {
+ *fmt = FMT_TYPE_SYMBOL;
+ }
+ /* Identifiers and other text (no previous ws. or delims. so text continues) */
+ else if (prev == FMT_TYPE_DEFAULT) {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
+ else {
+ /* Special vars(v) or built-in keywords(b) */
+ /* keep in sync with 'txtfmt_osl_format_identifier()' */
+ if ((i = txtfmt_osl_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
+ else if ((i = txtfmt_osl_find_builtinfunc(str)) != -1) prev = FMT_TYPE_KEYWORD;
+ else if ((i = txtfmt_osl_find_reserved(str)) != -1) prev = FMT_TYPE_RESERVED;
+ else if ((i = txtfmt_osl_find_preprocessor(str)) != -1) prev = FMT_TYPE_DIRECTIVE;
+
+ if (i > 0) {
+ memset(fmt, prev, i);
+ i--; fmt += i; str += i;
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ }
+ prev = *fmt; fmt++; str++;
+ }
+
+ /* Terminate and add continuation char */
+ *fmt = '\0'; fmt++;
+ *fmt = cont;
+
+ /* If continuation has changed and we're allowed, process the next line */
+ if (cont != cont_orig && do_next && line->next) {
+ txtfmt_osl_format_line(st, line->next, do_next);
+ }
+
+ flatten_string_free(&fs);
+}
+
+void ED_text_format_register_osl(void)
+{
+ static TextFormatType tft = {0};
+ static const char *ext[] = {"osl", NULL};
+
+ tft.format_identifier = txtfmt_osl_format_identifier;
+ tft.format_line = txtfmt_osl_format_line;
+ tft.ext = ext;
+
+ ED_text_format_register(&tft);
+}
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
index 2a0f483d80c..cbccc6a770f 100644
--- a/source/blender/editors/space_text/text_format_py.c
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -41,7 +41,6 @@
/* *** Local Functions (for format_line) *** */
-
/* Checks the specified source string for a Python built-in function name. This
* name must start at the beginning of the source string and must be followed by
* a non-identifier (see text_check_identifier(char)) or null character.
@@ -53,38 +52,53 @@
* http://docs.python.org/py3k/reference/lexical_analysis.html#keywords
*/
-static int txtfmt_py_find_builtinfunc(char *string)
+static int txtfmt_py_find_builtinfunc(const char *string)
{
- int a, i;
- const char *builtinfuncs[] = {
- /* "False", "None", "True", */ /* see find_bool() */
- "and", "as", "assert", "break",
- "class", "continue", "def", "del", "elif", "else", "except",
- "finally", "for", "from", "global", "if", "import", "in",
- "is", "lambda", "nonlocal", "not", "or", "pass", "raise",
- "return", "try", "while", "with", "yield",
- };
-
- for (a = 0; a < sizeof(builtinfuncs) / sizeof(builtinfuncs[0]); a++) {
- i = 0;
- while (1) {
- /* If we hit the end of a keyword... (eg. "def") */
- if (builtinfuncs[a][i] == '\0') {
- /* If we still have identifier chars in the source (eg. "definate") */
- if (text_check_identifier(string[i]))
- i = -1; /* No match */
- break; /* Next keyword if no match, otherwise we're done */
-
- /* If chars mismatch, move on to next keyword */
- }
- else if (string[i] != builtinfuncs[a][i]) {
- i = -1;
- break; /* Break inner loop, start next keyword */
- }
- i++;
- }
- if (i > 0) break; /* If we have a match, we're done */
- }
+ int i, len;
+ /* list is from...
+ * ", ".join(['"%s"' % kw
+ * for kw in __import__("keyword").kwlist
+ * if kw not in {"False", "None", "True", "def", "class"}])
+ *
+ * ... and for this code:
+ * print("\n".join(['else if (STR_LITERAL_STARTSWITH(string, "%s", len)) i = len;' % kw
+ * for kw in __import__("keyword").kwlist
+ * if kw not in {"False", "None", "True", "def", "class"}]))
+ */
+
+ if (STR_LITERAL_STARTSWITH(string, "and", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "as", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "assert", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "continue", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "del", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "elif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "except", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "finally", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "from", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "global", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "import", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "in", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "is", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lambda", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "nonlocal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "not", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "or", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pass", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "raise", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "try", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "with", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "yield", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
return i;
}
@@ -95,25 +109,28 @@ static int txtfmt_py_find_builtinfunc(char *string)
* If a special name is found, the length of the matching name is returned.
* Otherwise, -1 is returned. */
-static int txtfmt_py_find_specialvar(char *string)
+static int txtfmt_py_find_specialvar(const char *string)
{
- int i = 0;
- /* Check for "def" */
- if (string[0] == 'd' && string[1] == 'e' && string[2] == 'f')
- i = 3;
- /* Check for "class" */
- else if (string[0] == 'c' && string[1] == 'l' && string[2] == 'a' && string[3] == 's' && string[4] == 's')
- i = 5;
+ int i, len;
+
+ if (STR_LITERAL_STARTSWITH(string, "def", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "class", len)) i = len;
+ else i = 0;
+
/* If next source char is an identifier (eg. 'i' in "definate") no match */
if (i == 0 || text_check_identifier(string[i]))
return -1;
return i;
}
-static int txtfmt_py_find_decorator(char *string)
+static int txtfmt_py_find_decorator(const char *string)
{
if (string[0] == '@') {
int i = 1;
+ /* Whitespace is ok '@ foo' */
+ while (text_check_whitespace(string[i])) {
+ i++;
+ }
while (text_check_identifier(string[i])) {
i++;
}
@@ -122,46 +139,57 @@ static int txtfmt_py_find_decorator(char *string)
return -1;
}
-static int txtfmt_py_find_bool(char *string)
+static int txtfmt_py_find_bool(const char *string)
{
- int i = 0;
- /* Check for "False" */
- if (string[0] == 'F' && string[1] == 'a' && string[2] == 'l' && string[3] == 's' && string[4] == 'e')
- i = 5;
- /* Check for "True" */
- else if (string[0] == 'T' && string[1] == 'r' && string[2] == 'u' && string[3] == 'e')
- i = 4;
- /* Check for "None" */
- else if (string[0] == 'N' && string[1] == 'o' && string[2] == 'n' && string[3] == 'e')
- i = 4;
- /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ int i, len;
+
+ if (STR_LITERAL_STARTSWITH(string, "None", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "True", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "False", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
if (i == 0 || text_check_identifier(string[i]))
return -1;
return i;
}
-static void txtfmt_py_format_line(SpaceText *st, TextLine *line, int do_next)
+static char txtfmt_py_format_identifier(const char *str)
+{
+ char fmt;
+ if ((txtfmt_py_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
+ else if ((txtfmt_py_find_builtinfunc(str)) != -1) fmt = FMT_TYPE_KEYWORD;
+ else if ((txtfmt_py_find_decorator(str)) != -1) fmt = FMT_TYPE_RESERVED;
+ else fmt = FMT_TYPE_DEFAULT;
+ return fmt;
+}
+
+static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_next)
{
FlattenString fs;
- char *str, *fmt, orig, cont, find, prev = ' ';
+ const char *str;
+ char *fmt;
+ char cont_orig, cont, find, prev = ' ';
int len, i;
/* Get continuation from previous line */
if (line->prev && line->prev->format != NULL) {
fmt = line->prev->format;
cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont) == cont);
}
else {
- cont = 0;
+ cont = FMT_CONT_NOP;
}
/* Get original continuation from this line */
if (line->format != NULL) {
fmt = line->format;
- orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
}
else {
- orig = 0xFF;
+ cont_orig = 0xFF;
}
len = flatten_string(st, &fs, line->line);
@@ -183,93 +211,90 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, int do_next)
/* Handle continuations */
else if (cont) {
/* Triple strings ("""...""" or '''...''') */
- if (cont & TXT_TRISTR) {
- find = (cont & TXT_DBLQUOTSTR) ? '"' : '\'';
+ if (cont & FMT_CONT_TRIPLE) {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
if (*str == find && *(str + 1) == find && *(str + 2) == find) {
- *fmt = 'l'; fmt++; str++;
- *fmt = 'l'; fmt++; str++;
- cont = 0;
+ *fmt = FMT_TYPE_STRING; fmt++; str++;
+ *fmt = FMT_TYPE_STRING; fmt++; str++;
+ cont = FMT_CONT_NOP;
}
/* Handle other strings */
}
else {
- find = (cont & TXT_DBLQUOTSTR) ? '"' : '\'';
- if (*str == find) cont = 0;
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find) cont = FMT_CONT_NOP;
}
- *fmt = 'l';
+ *fmt = FMT_TYPE_STRING;
str += BLI_str_utf8_size_safe(str) - 1;
}
/* Not in a string... */
else {
/* Deal with comments first */
- if (prev == '#' || *str == '#') {
- *fmt = '#';
+ if (prev == FMT_TYPE_COMMENT || *str == '#') {
+ *fmt = FMT_TYPE_COMMENT;
str += BLI_str_utf8_size_safe(str) - 1;
}
else if (*str == '"' || *str == '\'') {
/* Strings */
find = *str;
- cont = (*str == '"') ? TXT_DBLQUOTSTR : TXT_SNGQUOTSTR;
+ cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
if (*(str + 1) == find && *(str + 2) == find) {
- *fmt = 'l'; fmt++; str++;
- *fmt = 'l'; fmt++; str++;
- cont |= TXT_TRISTR;
+ *fmt = FMT_TYPE_STRING; fmt++; str++;
+ *fmt = FMT_TYPE_STRING; fmt++; str++;
+ cont |= FMT_CONT_TRIPLE;
}
- *fmt = 'l';
+ *fmt = FMT_TYPE_STRING;
}
/* Whitespace (all ws. has been converted to spaces) */
- else if (*str == ' ')
- *fmt = '_';
+ else if (*str == ' ') {
+ *fmt = FMT_TYPE_WHITESPACE;
+ }
/* Numbers (digits not part of an identifier and periods followed by digits) */
- else if ((prev != 'q' && text_check_digit(*str)) || (*str == '.' && text_check_digit(*(str + 1))))
- *fmt = 'n';
+ else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+ (*str == '.' && text_check_digit(*(str + 1))))
+ {
+ *fmt = FMT_TYPE_NUMERAL;
+ }
/* Booleans */
- else if (prev != 'q' && (i = txtfmt_py_find_bool(str)) != -1)
+ else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_py_find_bool(str)) != -1) {
if (i > 0) {
- while (i > 1) {
- *fmt = 'n'; fmt++; str++;
- i--;
- }
- *fmt = 'n';
+ memset(fmt, FMT_TYPE_NUMERAL, i);
+ i--; fmt += i; str += i;
}
else {
str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = 'q';
+ *fmt = FMT_TYPE_DEFAULT;
}
+ }
/* Punctuation */
- else if (text_check_delim(*str))
- *fmt = '!';
+ else if ((*str != '@') && text_check_delim(*str)) {
+ *fmt = FMT_TYPE_SYMBOL;
+ }
/* Identifiers and other text (no previous ws. or delims. so text continues) */
- else if (prev == 'q') {
+ else if (prev == FMT_TYPE_DEFAULT) {
str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = 'q';
+ *fmt = FMT_TYPE_DEFAULT;
}
/* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
else {
/* Special vars(v) or built-in keywords(b) */
- if ((i = txtfmt_py_find_specialvar(str)) != -1)
- prev = 'v';
- else if ((i = txtfmt_py_find_builtinfunc(str)) != -1)
- prev = 'b';
- else if ((i = txtfmt_py_find_decorator(str)) != -1)
- prev = 'v'; /* could have a new color for this */
+ /* keep in sync with 'txtfmt_py_format_identifier()' */
+ if ((i = txtfmt_py_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
+ else if ((i = txtfmt_py_find_builtinfunc(str)) != -1) prev = FMT_TYPE_KEYWORD;
+ else if ((i = txtfmt_py_find_decorator(str)) != -1) prev = FMT_TYPE_DIRECTIVE;
+
if (i > 0) {
- while (i > 1) {
- *fmt = prev; fmt++; str++;
- i--;
- }
- *fmt = prev;
+ memset(fmt, prev, i);
+ i--; fmt += i; str += i;
}
else {
str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = 'q';
+ *fmt = FMT_TYPE_DEFAULT;
}
}
}
- prev = *fmt;
- fmt++;
- str++;
+ prev = *fmt; fmt++; str++;
}
/* Terminate and add continuation char */
@@ -277,7 +302,7 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, int do_next)
*fmt = cont;
/* If continuation has changed and we're allowed, process the next line */
- if (cont != orig && do_next && line->next) {
+ if (cont != cont_orig && do_next && line->next) {
txtfmt_py_format_line(st, line->next, do_next);
}
@@ -289,7 +314,8 @@ void ED_text_format_register_py(void)
static TextFormatType tft = {0};
static const char *ext[] = {"py", NULL};
- tft.format_line = txtfmt_py_format_line;
+ tft.format_identifier = txtfmt_py_format_identifier;
+ tft.format_line = txtfmt_py_format_line;
tft.ext = ext;
ED_text_format_register(&tft);
diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h
index c7f9512737f..799bc49b624 100644
--- a/source/blender/editors/space_text/text_intern.h
+++ b/source/blender/editors/space_text/text_intern.h
@@ -143,6 +143,11 @@ void TEXT_OT_to_3d_object(struct wmOperatorType *ot);
void TEXT_OT_resolve_conflict(struct wmOperatorType *ot);
+int text_space_edit_poll(struct bContext *C);
+
+/* text_autocomplete.c */
+void TEXT_OT_autocomplete(struct wmOperatorType *ot);
+
/* space_text.c */
extern const char *text_context_dir[]; /* doc access */
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 01041c0e385..21966ef614c 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -98,7 +98,7 @@ static int text_edit_poll(bContext *C)
return 1;
}
-static int text_space_edit_poll(bContext *C)
+int text_space_edit_poll(bContext *C)
{
SpaceText *st = CTX_wm_space_text(C);
Text *text = CTX_data_edit_text(C);
@@ -1931,6 +1931,8 @@ static int text_jump_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
void TEXT_OT_jump(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Jump";
ot->idname = "TEXT_OT_jump";
@@ -1942,7 +1944,8 @@ void TEXT_OT_jump(wmOperatorType *ot)
ot->poll = text_edit_poll;
/* properties */
- RNA_def_int(ot->srna, "line", 1, 1, INT_MAX, "Line", "Line number to jump to", 1, 10000);
+ prop = RNA_def_int(ot->srna, "line", 1, 1, INT_MAX, "Line", "Line number to jump to", 1, 10000);
+ RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_TEXT);
}
/******************* delete operator **********************/
diff --git a/source/blender/editors/space_text/text_python.c b/source/blender/editors/space_text/text_python.c
deleted file mode 100644
index 1201302dad0..00000000000
--- a/source/blender/editors/space_text/text_python.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * ***** 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) 2008 Blender Foundation.
- * All rights reserved.
- *
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/space_text/text_python.c
- * \ingroup sptext
- */
-
-#include <ctype.h>
-
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-#include "DNA_text_types.h"
-#include "DNA_userdef_types.h"
-
-#include "BKE_suggestions.h"
-#include "BKE_text.h"
-
-#include "BLI_blenlib.h"
-
-#include "WM_types.h"
-
-#include "text_intern.h"
-
-int text_do_suggest_select(SpaceText *st, ARegion *ar)
-{
- SuggItem *item, *first, *last /* , *sel */ /* UNUSED */;
- TextLine *tmp;
- int l, x, y, w, h, i;
- int tgti, *top;
- int mval[2] = {0, 0};
-
- if (!st || !st->text) return 0;
- if (!texttool_text_is_active(st->text)) return 0;
-
- first = texttool_suggest_first();
- last = texttool_suggest_last();
- /* sel = texttool_suggest_selected(); */ /* UNUSED */
- top = texttool_suggest_top();
-
- if (!last || !first)
- return 0;
-
- /* Count the visible lines to the cursor */
- for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ;
- if (l < 0) return 0;
-
- text_update_character_width(st);
-
- if (st->showlinenrs) {
- x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
- }
- else {
- x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
- }
- y = ar->winy - st->lheight_dpi * l - 2;
-
- w = SUGG_LIST_WIDTH * st->cwidth + U.widget_unit;
- h = SUGG_LIST_SIZE * st->lheight_dpi + 0.4f * U.widget_unit;
-
- // XXX getmouseco_areawin(mval);
-
- if (mval[0] < x || x + w < mval[0] || mval[1] < y - h || y < mval[1])
- return 0;
-
- /* Work out which of the items is at the top of the visible list */
- for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ;
-
- /* Work out the target item index in the visible list */
- tgti = (y - mval[1] - 4) / st->lheight_dpi;
- if (tgti < 0 || tgti > SUGG_LIST_SIZE)
- return 1;
-
- for (i = tgti; i > 0 && item->next; i--, item = item->next) ;
- if (item)
- texttool_suggest_select(item);
- return 1;
-}
-
-void text_pop_suggest_list(void)
-{
- SuggItem *item, *sel;
- int *top, i;
-
- item = texttool_suggest_first();
- sel = texttool_suggest_selected();
- top = texttool_suggest_top();
-
- i = 0;
- while (item && item != sel) {
- item = item->next;
- i++;
- }
- if (i > *top + SUGG_LIST_SIZE - 1)
- *top = i - SUGG_LIST_SIZE + 1;
- else if (i < *top)
- *top = i;
-}
-
-static void get_suggest_prefix(Text *text, int offset)
-{
- int i, len;
- char *line, tmp[256];
-
- if (!text) return;
- if (!texttool_text_is_active(text)) return;
-
- line = text->curl->line;
- for (i = text->curc - 1 + offset; i >= 0; i--)
- if (!text_check_identifier(line[i]))
- break;
- i++;
- len = text->curc - i + offset;
- if (len > 255) {
- printf("Suggestion prefix too long\n");
- len = 255;
- }
- BLI_strncpy(tmp, line + i, len);
- tmp[len] = '\0';
- texttool_suggest_prefix(tmp);
-}
-
-static void confirm_suggestion(Text *text, int skipleft)
-{
- SuggItem *sel;
- int i, over = 0;
- char *line;
-
- if (!text) return;
- if (!texttool_text_is_active(text)) return;
-
- sel = texttool_suggest_selected();
- if (!sel) return;
-
- line = text->curl->line;
- i = text->curc - skipleft - 1;
- while (i >= 0) {
- if (!text_check_identifier(line[i]))
- break;
- over++;
- i--;
- }
-
- for (i = 0; i < skipleft; i++)
- txt_move_left(text, 0);
- for (i = 0; i < over; i++)
- txt_move_left(text, 1);
-
- txt_insert_buf(text, sel->name);
-
- for (i = 0; i < skipleft; i++)
- txt_move_right(text, 0);
-
- texttool_text_clear();
-}
-
-// XXX
-#define LR_SHIFTKEY 0
-#define LR_ALTKEY 0
-#define LR_CTRLKEY 0
-
-// XXX
-static int doc_scroll = 0;
-
-static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned short evnt, short val)
-{
- ARegion *ar = NULL; // XXX
- int qual = 0; // XXX
- int draw = 0, tools = 0, swallow = 0, scroll = 1;
- if (!texttool_text_is_active(st->text)) return 0;
- if (!st->text || st->text->id.lib) return 0;
-
- if (st->doplugins && texttool_text_is_active(st->text)) {
- if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST;
- if (texttool_docs_get()) tools |= TOOL_DOCUMENT;
- }
-
- if (ascii) {
- if (tools & TOOL_SUGG_LIST) {
- if ((ascii != '_' && ascii != '*' && ispunct(ascii)) || text_check_whitespace(ascii)) {
- confirm_suggestion(st->text, 0);
- text_update_line_edited(st->text->curl);
- }
- else if ((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) {
- get_suggest_prefix(st->text, 0);
- text_pop_suggest_list();
- swallow = 1;
- draw = 1;
- }
- }
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
-
- }
- else if (val == 1 && evnt) {
- switch (evnt) {
- case LEFTMOUSE:
- if (text_do_suggest_select(st, ar))
- swallow = 1;
- else {
- if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
- }
- draw = 1;
- break;
- case MIDDLEMOUSE:
- if (text_do_suggest_select(st, ar)) {
- confirm_suggestion(st->text, 0);
- text_update_line_edited(st->text->curl);
- swallow = 1;
- }
- else {
- if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
- }
- draw = 1;
- break;
- case ESCKEY:
- draw = swallow = 1;
- if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
- else if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
- else draw = swallow = 0;
- break;
- case RETKEY:
- if (tools & TOOL_SUGG_LIST) {
- confirm_suggestion(st->text, 0);
- text_update_line_edited(st->text->curl);
- swallow = 1;
- draw = 1;
- }
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
- break;
- case LEFTARROWKEY:
- case BACKSPACEKEY:
- if (tools & TOOL_SUGG_LIST) {
- if (qual)
- texttool_suggest_clear();
- else {
- /* Work out which char we are about to delete/pass */
- if (st->text->curl && st->text->curc > 0) {
- char ch = st->text->curl->line[st->text->curc - 1];
- if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
- get_suggest_prefix(st->text, -1);
- text_pop_suggest_list();
- }
- else
- texttool_suggest_clear();
- }
- else
- texttool_suggest_clear();
- }
- }
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
- break;
- case RIGHTARROWKEY:
- if (tools & TOOL_SUGG_LIST) {
- if (qual)
- texttool_suggest_clear();
- else {
- /* Work out which char we are about to pass */
- if (st->text->curl && st->text->curc < st->text->curl->len) {
- char ch = st->text->curl->line[st->text->curc + 1];
- if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
- get_suggest_prefix(st->text, 1);
- text_pop_suggest_list();
- }
- else
- texttool_suggest_clear();
- }
- else
- texttool_suggest_clear();
- }
- }
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
- break;
- case PAGEDOWNKEY:
- scroll = SUGG_LIST_SIZE - 1;
- case WHEELDOWNMOUSE:
- case DOWNARROWKEY:
- if (tools & TOOL_DOCUMENT) {
- doc_scroll++;
- swallow = 1;
- draw = 1;
- break;
- }
- else if (tools & TOOL_SUGG_LIST) {
- SuggItem *sel = texttool_suggest_selected();
- if (!sel) {
- texttool_suggest_select(texttool_suggest_first());
- }
- else {
- while (sel && sel != texttool_suggest_last() && sel->next && scroll--) {
- texttool_suggest_select(sel->next);
- sel = sel->next;
- }
- }
- text_pop_suggest_list();
- swallow = 1;
- draw = 1;
- break;
- }
- case PAGEUPKEY:
- scroll = SUGG_LIST_SIZE - 1;
- case WHEELUPMOUSE:
- case UPARROWKEY:
- if (tools & TOOL_DOCUMENT) {
- if (doc_scroll > 0) doc_scroll--;
- swallow = 1;
- draw = 1;
- break;
- }
- else if (tools & TOOL_SUGG_LIST) {
- SuggItem *sel = texttool_suggest_selected();
- while (sel && sel != texttool_suggest_first() && sel->prev && scroll--) {
- texttool_suggest_select(sel->prev);
- sel = sel->prev;
- }
- text_pop_suggest_list();
- swallow = 1;
- draw = 1;
- break;
- }
- case RIGHTSHIFTKEY:
- case LEFTSHIFTKEY:
- break;
- default:
- if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw = 1;
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
- }
- }
-
- if (draw) {
- // XXX redraw_alltext();
- }
-
- return swallow;
-}
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index 1ea3876f5cc..5ebbebec35b 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -105,14 +105,16 @@ static SpaceLink *userpref_duplicate(SpaceLink *sl)
/* add handlers, stuff you only do once or on area/region changes */
static void userpref_main_area_init(wmWindowManager *wm, ARegion *ar)
{
+ /* do not use here, the properties changed in userprefs do a system-wide refresh, then scroller jumps back */
+ /* ar->v2d.flag &= ~V2D_IS_INITIALISED; */
+
+ ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+
ED_region_panels_init(wm, ar);
}
static void userpref_main_area_draw(const bContext *C, ARegion *ar)
{
- /* this solves "vibrating UI" bug #25422 */
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
-
ED_region_panels(C, ar, 1, NULL, -1);
}
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index e36654323fd..fa72f28cc44 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -396,6 +396,7 @@ static void draw_textured_end(void)
glShadeModel(GL_FLAT);
glDisable(GL_CULL_FACE);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
/* XXX, bad patch - GPU_default_lights() calls
* glLightfv(GL_POSITION, ...) which
@@ -1018,7 +1019,7 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
const short do_light = (v3d->drawtype >= OB_SOLID);
/* hide faces in face select mode */
- if (draw_flags & DRAW_FACE_SELECT)
+ if (me->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL))
facemask = wpaint__setSolidDrawOptions_facemask;
if (ob->mode & OB_MODE_WEIGHT_PAINT) {
@@ -1066,12 +1067,18 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
draw_mesh_face_select(rv3d, me, dm);
}
else if ((do_light == FALSE) || (ob->dtx & OB_DRAWWIRE)) {
+ const int use_depth = (v3d->flag & V3D_ZBUF_SELECT);
/* weight paint in solid mode, special case. focus on making the weights clear
* rather than the shading, this is also forced in wire view */
- bglPolygonOffset(rv3d->dist, 1.0);
- glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
+ if (use_depth) {
+ bglPolygonOffset(rv3d->dist, 1.0);
+ glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
+ }
+ else {
+ glDisable(GL_DEPTH_TEST);
+ }
glEnable(GL_BLEND);
glColor4ub(255, 255, 255, 96);
@@ -1080,8 +1087,14 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
dm->drawEdges(dm, 1, 1);
- bglPolygonOffset(rv3d->dist, 0.0);
- glDepthMask(1);
+ if (use_depth) {
+ bglPolygonOffset(rv3d->dist, 0.0);
+ glDepthMask(1);
+ }
+ else {
+ glEnable(GL_DEPTH_TEST);
+ }
+
glDisable(GL_LINE_STIPPLE);
glDisable(GL_BLEND);
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 3722e6797f8..ebb5fd30666 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -101,7 +101,7 @@ typedef enum eWireDrawMode {
} eWireDrawMode;
typedef struct drawDMVerts_userData {
- BMEditMesh *em; /* BMESH BRANCH ONLY */
+ BMEditMesh *em;
int sel;
BMVert *eve_act;
@@ -119,7 +119,7 @@ typedef struct drawDMVerts_userData {
} drawDMVerts_userData;
typedef struct drawDMEdgesSel_userData {
- BMEditMesh *em; /* BMESH BRANCH ONLY */
+ BMEditMesh *em;
unsigned char *baseCol, *selCol, *actCol;
BMEdge *eed_act;
@@ -132,8 +132,8 @@ typedef struct drawDMFacesSel_userData {
unsigned char *cols[3];
#endif
- DerivedMesh *dm; /* BMESH BRANCH ONLY */
- BMEditMesh *em; /* BMESH BRANCH ONLY */
+ DerivedMesh *dm;
+ BMEditMesh *em;
BMFace *efa_act;
int *orig_index_mf_to_mpoly;
@@ -2629,10 +2629,10 @@ static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitS
/* make the precision of the display value proportionate to the gridsize */
- if (grid < 0.01f) conv_float = "%.6g";
- else if (grid < 0.1f) conv_float = "%.5g";
- else if (grid < 1.0f) conv_float = "%.4g";
- else if (grid < 10.0f) conv_float = "%.3g";
+ if (grid <= 0.01f) conv_float = "%.6g";
+ else if (grid <= 0.1f) conv_float = "%.5g";
+ else if (grid <= 1.0f) conv_float = "%.4g";
+ else if (grid <= 10.0f) conv_float = "%.3g";
else conv_float = "%.2g";
if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
@@ -3312,11 +3312,15 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
}
if (is_obact && paint_vertsel_test(ob)) {
-
+ const int use_depth = (v3d->flag & V3D_ZBUF_SELECT);
glColor3f(0.0f, 0.0f, 0.0f);
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
-
+
+ if (!use_depth) glDisable(GL_DEPTH_TEST);
+ else bglPolygonOffset(rv3d->dist, 1.0);
drawSelectedVertices(dm, ob->data);
+ if (!use_depth) glEnable(GL_DEPTH_TEST);
+ else bglPolygonOffset(rv3d->dist, 0.0);
glPointSize(1.0f);
}
@@ -6949,10 +6953,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
UI_make_axis_color(col1, col2, 'Z');
glColor3ubv(col2);
- cob = constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+ cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
for (curcon = list->first; curcon; curcon = curcon->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(curcon);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -7006,7 +7010,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
}
- constraints_clear_evalob(cob);
+ BKE_constraints_clear_evalob(cob);
}
}
@@ -7167,7 +7171,21 @@ static DMDrawOption bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index)
return DM_DRAW_OPTION_SKIP;
}
}
-static void bbs_mesh_solid(Scene *scene, Object *ob)
+
+static void bbs_mesh_solid_verts(Scene *scene, Object *ob)
+{
+ Mesh *me = ob->data;
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
+ glColor3ub(0, 0, 0);
+
+ dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_enable_material, NULL, me, 0);
+
+ bbs_obmode_mesh_verts(ob, dm, 1);
+ bm_vertoffs = me->totvert + 1;
+ dm->release(dm);
+}
+
+static void bbs_mesh_solid_faces(Scene *scene, Object *ob)
{
DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
Mesh *me = (Mesh *)ob->data;
@@ -7232,18 +7250,10 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
/* currently vertex select only supports weight paint */
(ob->mode & OB_MODE_WEIGHT_PAINT))
{
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
- glColor3ub(0, 0, 0);
-
- dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_enable_material, NULL, me, 0);
-
-
- bbs_obmode_mesh_verts(ob, dm, 1);
- bm_vertoffs = me->totvert + 1;
- dm->release(dm);
+ bbs_mesh_solid_verts(scene, ob);
}
else {
- bbs_mesh_solid(scene, ob);
+ bbs_mesh_solid_faces(scene, ob);
}
}
break;
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 4ade47fbdc7..1d87895d64a 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -520,14 +520,8 @@ static int view3d_ima_ob_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = (ID *)drag->poin;
- PointerRNA ptr;
- /* need to put name in sub-operator in macro */
- ptr = RNA_pointer_get(drop->ptr, "OBJECT_OT_add_named");
- if (ptr.data)
- RNA_string_set(&ptr, "name", id->name + 2);
- else
- RNA_string_set(drop->ptr, "name", id->name + 2);
+ RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
@@ -561,7 +555,7 @@ static void view3d_dropboxes(void)
{
ListBase *lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
- WM_dropbox_add(lb, "OBJECT_OT_add_named_cursor", view3d_ob_drop_poll, view3d_ob_drop_copy);
+ WM_dropbox_add(lb, "OBJECT_OT_add_named", view3d_ob_drop_poll, view3d_ob_drop_copy);
WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy);
WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_ob_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 7475f65317a..4ccf26e12b1 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -2596,10 +2596,10 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr);
}
- glClearColor(backcol[0], backcol[1], backcol[2], 0.0);
+ glClearColor(backcol[0], backcol[1], backcol[2], 0.0f);
}
else {
- UI_ThemeClearColor(TH_BACK);
+ UI_ThemeClearColor(TH_BACK);
}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 78c3f4e4f4a..e984a3f5cfd 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -921,7 +921,8 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
if (event->type == MOUSEPAN) {
- viewrotate_apply(vod, event->prevx, event->prevy);
+ /* invert it, trackpad scroll then follows how you mapped it globally */
+ viewrotate_apply(vod, 2 * event->x - event->prevx, 2 * event->y - event->prevy);
ED_view3d_depth_tag_update(rv3d);
viewops_data_free(C, op);
@@ -1008,17 +1009,20 @@ void ndof_to_quat(struct wmNDOFMotionData *ndof, float q[4])
*/
static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
- ViewOpsData *vod = op->customdata;
if (event->type != NDOF_MOTION)
return OPERATOR_CANCELLED;
else {
View3D *v3d = CTX_wm_view3d(C);
+ ViewOpsData *vod;
RegionView3D *rv3d = CTX_wm_region_view3d(C);
wmNDOFMotionData *ndof = (wmNDOFMotionData *) event->customdata;
ED_view3d_camera_lock_init(v3d, rv3d);
+ viewops_data_create(C, op, event);
+ vod = op->customdata;
+
rv3d->rot_angle = 0.f; /* off by default, until changed later this function */
if (ndof->progress != P_FINISHING) {
@@ -1138,8 +1142,10 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
}
+ viewops_data_free(C, op);
+
ED_view3d_camera_lock_sync(v3d, rv3d);
-
+
ED_region_tag_redraw(CTX_wm_region(C));
return OPERATOR_FINISHED;
@@ -1161,6 +1167,181 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
ot->flag = 0;
}
+
+static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+
+ if (event->type != NDOF_MOTION)
+ return OPERATOR_CANCELLED;
+ else {
+ ViewOpsData *vod;
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ wmNDOFMotionData *ndof = (wmNDOFMotionData *) event->customdata;
+
+ ED_view3d_camera_lock_init(v3d, rv3d);
+
+ rv3d->rot_angle = 0.f; /* off by default, until changed later this function */
+
+ viewops_data_create(C, op, event);
+ vod = op->customdata;
+
+ if (ndof->progress != P_FINISHING) {
+ const float dt = ndof->dt;
+
+ /* tune these until everything feels right */
+ const float rot_sensitivity = 1.f;
+
+ const float zoom_sensitivity = 1.f;
+
+ const float pan_sensitivity = 1.f;
+ const int has_rotation = rv3d->viewlock != RV3D_LOCKED && !is_zero_v3(ndof->rvec);
+
+ float view_inv[4];
+ invert_qt_qt(view_inv, rv3d->viewquat);
+
+ /* #define DEBUG_NDOF_MOTION */
+ #ifdef DEBUG_NDOF_MOTION
+ printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n",
+ ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt);
+ #endif
+
+ if (ndof->tz) {
+ /* Zoom!
+ * velocity should be proportional to the linear velocity attained by rotational motion of same strength
+ * [got that?]
+ * proportional to arclength = radius * angle
+ */
+ float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz;
+
+ if (U.ndof_flag & NDOF_ZOOM_INVERT)
+ zoom_distance = -zoom_distance;
+
+ rv3d->dist += zoom_distance;
+ }
+
+ if (rv3d->viewlock == RV3D_LOCKED) {
+ /* rotation not allowed -- explore panning options instead */
+ float pan_vec[3] = {ndof->tx, ndof->ty, 0.0f};
+ mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt);
+
+ /* transform motion from view to world coordinates */
+ invert_qt_qt(view_inv, rv3d->viewquat);
+ mul_qt_v3(view_inv, pan_vec);
+
+ /* move center of view opposite of hand motion (this is camera mode, not object mode) */
+ sub_v3_v3(rv3d->ofs, pan_vec);
+ }
+
+ if (has_rotation) {
+
+ rv3d->view = RV3D_VIEW_USER;
+
+ if (U.ndof_flag & NDOF_TURNTABLE) {
+
+ /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */
+ float angle, rot[4];
+ float xvec[3] = {1, 0, 0};
+
+ /* Determine the direction of the x vector (for rotating up and down) */
+ mul_qt_v3(view_inv, xvec);
+
+ /* Perform the up/down rotation */
+ angle = rot_sensitivity * dt * ndof->rx;
+ if (U.ndof_flag & NDOF_TILT_INVERT_AXIS)
+ angle = -angle;
+ rot[0] = cos(angle);
+ mul_v3_v3fl(rot + 1, xvec, sin(angle));
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
+
+ /* Perform the orbital rotation */
+ angle = rot_sensitivity * dt * ndof->ry;
+ if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS)
+ angle = -angle;
+
+ /* update the onscreen doo-dad */
+ rv3d->rot_angle = angle;
+ rv3d->rot_axis[0] = 0;
+ rv3d->rot_axis[1] = 0;
+ rv3d->rot_axis[2] = 1;
+
+ rot[0] = cos(angle);
+ rot[1] = rot[2] = 0.0;
+ rot[3] = sin(angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
+
+ }
+ else {
+ float rot[4];
+ float axis[3];
+ float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
+
+ if (U.ndof_flag & NDOF_ROLL_INVERT_AXIS)
+ axis[2] = -axis[2];
+
+ if (U.ndof_flag & NDOF_TILT_INVERT_AXIS)
+ axis[0] = -axis[0];
+
+ if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS)
+ axis[1] = -axis[1];
+
+
+ /* transform rotation axis from view to world coordinates */
+ mul_qt_v3(view_inv, axis);
+
+ /* update the onscreen doo-dad */
+ rv3d->rot_angle = angle;
+ copy_v3_v3(rv3d->rot_axis, axis);
+
+ axis_angle_to_quat(rot, axis, angle);
+
+ /* apply rotation */
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
+
+ }
+
+ /* rotate around custom center */
+ if (vod && vod->use_dyn_ofs) {
+ float q1[4];
+
+ /* compute the post multiplication quat, to rotate the offset correctly */
+ conjugate_qt_qt(q1, vod->oldquat);
+ mul_qt_qtqt(q1, q1, rv3d->viewquat);
+
+ conjugate_qt(q1); /* conj == inv for unit quat */
+ copy_v3_v3(rv3d->ofs, vod->ofs);
+ sub_v3_v3(rv3d->ofs, vod->dyn_ofs);
+ mul_qt_v3(q1, rv3d->ofs);
+ add_v3_v3(rv3d->ofs, vod->dyn_ofs);
+ }
+ }
+ }
+
+ viewops_data_free(C, op);
+
+ ED_view3d_camera_lock_sync(v3d, rv3d);
+
+ ED_region_tag_redraw(CTX_wm_region(C));
+
+ return OPERATOR_FINISHED;
+ }
+}
+
+void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "NDOF Orbit View with zoom";
+ ot->description = "Explore every angle of an object using the 3D mouse";
+ ot->idname = "VIEW3D_OT_ndof_orbit_zoom";
+
+ /* api callbacks */
+ ot->invoke = ndof_orbit_zoom_invoke;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = 0;
+}
+
/* -- "pan" navigation
* -- zoom or dolly?
*/
@@ -1197,8 +1378,7 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt);
#else /* ------------------------------------------------------- dolly with Z */
- float speed = 10.f; /* blender units per second */
- /* ^^ this is ok for default cube scene, but should scale with.. something */
+ float speed = rv3d->dist; /* uses distance from pivot to define dolly */
/* tune these until everything feels right */
const float forward_sensitivity = 1.f;
@@ -1261,8 +1441,9 @@ void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot)
*/
static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
- if (event->type != NDOF_MOTION)
+ if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
+ }
else {
ViewOpsData *vod;
@@ -1282,23 +1463,14 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
const float dt = ndof->dt;
float view_inv[4];
- float speed = 10.f; /* blender units per second */
- /* ^^ this is ok for default cube scene, but should scale with.. something */
+ float speed = rv3d->dist; /* uses distance from pivot to define dolly */
/* tune these until everything feels right */
const float forward_sensitivity = 1.f;
const float vertical_sensitivity = 0.4f;
const float lateral_sensitivity = 0.6f;
-
float pan_vec[3];
const float rot_sensitivity = 1.f;
-#if 0
- const float zoom_sensitivity = 1.f;
- const float pan_sensitivity = 1.f;
- float rot[4];
- float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
- float axis[3];
-#endif
/* inverse view */
invert_qt_qt(view_inv, rv3d->viewquat);
@@ -1389,7 +1561,7 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
/* rotate around custom center */
- if (vod && vod->use_dyn_ofs) {
+ if (vod->use_dyn_ofs) {
float q1[4];
/* compute the post multiplication quat, to rotate the offset correctly */
@@ -1404,10 +1576,13 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
}
+
+ viewops_data_free(C, op);
+
ED_view3d_camera_lock_sync(v3d, rv3d);
ED_region_tag_redraw(CTX_wm_region(C));
- viewops_data_free(C, op);
+
return OPERATOR_FINISHED;
}
}
@@ -3677,17 +3852,21 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot)
/* ***************** 3d cursor cursor op ******************* */
-/* mx my in region coords */
-static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+/* cursor position in vec, result in vec, mval in region coords */
+/* note: cannot use event->mval here (called by object_add() */
+void ED_view3d_cursor3d_position(bContext *C, float *fp, int mx, int my)
{
Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- float *fp = give_cursor(scene, v3d);
float mval_fl[2];
+ int mval[2];
int flip;
+ mval[0] = mx - ar->winrct.xmin;
+ mval[1] = my - ar->winrct.ymin;
+
flip = initgrabz(rv3d, fp[0], fp[1], fp[2]);
/* reset the depth based on the view offset (we _know_ the offset is infront of us) */
@@ -3702,20 +3881,20 @@ static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *
if (U.uiflag & USER_ZBUF_CURSOR) { /* maybe this should be accessed some other way */
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(scene, ar, v3d, event->mval, fp))
+ if (ED_view3d_autodist(scene, ar, v3d, mval, fp))
depth_used = TRUE;
}
if (depth_used == FALSE) {
float dvec[3];
- VECSUB2D(mval_fl, mval_fl, event->mval);
+ VECSUB2D(mval_fl, mval_fl, mval);
ED_view3d_win_to_delta(ar, mval_fl, dvec);
sub_v3_v3(fp, dvec);
}
}
else {
- const float dx = ((float)(event->mval[0] - (ar->winx / 2))) * rv3d->zfac / (ar->winx / 2);
- const float dy = ((float)(event->mval[1] - (ar->winy / 2))) * rv3d->zfac / (ar->winy / 2);
+ const float dx = ((float)(mval[0] - (ar->winx / 2))) * rv3d->zfac / (ar->winx / 2);
+ const float dy = ((float)(mval[1] - (ar->winy / 2))) * rv3d->zfac / (ar->winy / 2);
const float fz = (rv3d->persmat[0][3] * fp[0] +
rv3d->persmat[1][3] * fp[1] +
rv3d->persmat[2][3] * fp[2] +
@@ -3726,11 +3905,21 @@ static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *
fp[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy + rv3d->persinv[2][2] * fz) - rv3d->ofs[2];
}
+}
+
+static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+{
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ float *fp = give_cursor(scene, v3d);
+
+ ED_view3d_cursor3d_position(C, fp, event->x, event->y);
+
if (v3d && v3d->localvd)
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
else
WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
-
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 79bf003a563..2b30e4e6b81 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -487,11 +487,17 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
block = uiLayoutGetBlock(row);
if (v3d->twflag & V3D_USE_MANIPULATOR) {
- but = uiDefIconButBitC(block, TOG, V3D_MANIP_TRANSLATE, B_MAN_TRANS, ICON_MAN_TRANS, 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0, TIP_("Translate manipulator - Shift-Click for multiple modes"));
+ but = uiDefIconButBitC(block, TOG, V3D_MANIP_TRANSLATE, B_MAN_TRANS, ICON_MAN_TRANS,
+ 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0,
+ TIP_("Translate manipulator - Shift-Click for multiple modes"));
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
- but = uiDefIconButBitC(block, TOG, V3D_MANIP_ROTATE, B_MAN_ROT, ICON_MAN_ROT, 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0, TIP_("Rotate manipulator - Shift-Click for multiple modes"));
+ but = uiDefIconButBitC(block, TOG, V3D_MANIP_ROTATE, B_MAN_ROT, ICON_MAN_ROT,
+ 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0,
+ TIP_("Rotate manipulator - Shift-Click for multiple modes"));
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
- but = uiDefIconButBitC(block, TOG, V3D_MANIP_SCALE, B_MAN_SCALE, ICON_MAN_SCALE, 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0, TIP_("Scale manipulator - Shift-Click for multiple modes"));
+ but = uiDefIconButBitC(block, TOG, V3D_MANIP_SCALE, B_MAN_SCALE, ICON_MAN_SCALE,
+ 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0,
+ TIP_("Scale manipulator - Shift-Click for multiple modes"));
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
}
@@ -500,7 +506,8 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
}
str_menu = BIF_menustringTransformOrientation(C, "Orientation");
- but = uiDefButC(block, MENU, B_MAN_MODE, str_menu, 0, 0, 70 * dpi_fac, UI_UNIT_Y, &v3d->twmode, 0, 0, 0, 0, TIP_("Transform Orientation"));
+ but = uiDefButC(block, MENU, B_MAN_MODE, str_menu, 0, 0, 70 * dpi_fac, UI_UNIT_Y, &v3d->twmode, 0, 0, 0, 0,
+ TIP_("Transform Orientation"));
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
MEM_freeN((void *)str_menu);
}
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index f8a7cdde8a5..a6daf610052 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -77,6 +77,7 @@ void VIEW3D_OT_zoom_camera_1_to_1(struct wmOperatorType *ot);
void VIEW3D_OT_move(struct wmOperatorType *ot);
void VIEW3D_OT_rotate(struct wmOperatorType *ot);
void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot);
+void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot);
void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot);
void VIEW3D_OT_ndof_all(struct wmOperatorType *ot);
void VIEW3D_OT_view_all(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index a0b36e57d69..81e890c37ee 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -27,6 +27,7 @@
#include "DNA_curve_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meta_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
@@ -47,6 +48,12 @@
#include "ED_object.h"
#include "ED_view3d.h"
+typedef struct foreachScreenObjectVert_userData {
+ void (*func)(void *userData, MVert *mv, const float screen_co_b[2], int index);
+ void *userData;
+ ViewContext vc;
+ eV3DProjTest clip_flag;
+} foreachScreenObjectVert_userData;
typedef struct foreachScreenVert_userData {
void (*func)(void *userData, BMVert *eve, const float screen_co_b[2], int index);
@@ -79,6 +86,46 @@ typedef struct foreachScreenFace_userData {
/* ------------------------------------------------------------------------ */
+
+static void meshobject_foreachScreenVert__mapFunc(void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+ foreachScreenObjectVert_userData *data = userData;
+ struct MVert *mv = &((Mesh *)(data->vc.obact->data))->mvert[index];
+
+ if (!(mv->flag & ME_HIDE)) {
+ float screen_co[2];
+
+ if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) != V3D_PROJ_RET_OK) {
+ return;
+ }
+
+ data->func(data->userData, mv, screen_co, index);
+ }
+}
+
+void meshobject_foreachScreenVert(
+ ViewContext *vc,
+ void (*func)(void *userData, MVert *eve, const float screen_co[2], int index),
+ void *userData, eV3DProjTest clip_flag)
+{
+ foreachScreenObjectVert_userData data;
+ DerivedMesh *dm = mesh_get_derived_deform(vc->scene, vc->obact, CD_MASK_BAREMESH);
+
+ data.vc = *vc;
+ data.func = func;
+ data.userData = userData;
+ data.clip_flag = clip_flag;
+
+ if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
+ ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
+ }
+
+ dm->foreachMappedVert(dm, meshobject_foreachScreenVert__mapFunc, &data);
+
+ dm->release(dm);
+}
+
static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const float co[3],
const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
{
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 4101ced616a..615ae71cf9b 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -131,6 +131,7 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_zoom);
WM_operatortype_append(VIEW3D_OT_zoom_camera_1_to_1);
WM_operatortype_append(VIEW3D_OT_dolly);
+ WM_operatortype_append(VIEW3D_OT_ndof_orbit_zoom);
WM_operatortype_append(VIEW3D_OT_ndof_orbit);
WM_operatortype_append(VIEW3D_OT_ndof_pan);
WM_operatortype_append(VIEW3D_OT_ndof_all);
@@ -195,34 +196,6 @@ void view3d_keymap(wmKeyConfig *keyconf)
/* only for region 3D window */
keymap = WM_keymap_find(keyconf, "3D View", SPACE_VIEW3D, 0);
-
- /* NDOF: begin */
- /* note: positioned here so keymaps show keyboard keys if assigned */
- /* 3D mouse */
- WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit", NDOF_MOTION, 0, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_pan", NDOF_MOTION, 0, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_all", NDOF_MOTION, 0, 0, 0);
- WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
- RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
- RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BACK, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BACK);
- RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_LEFT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_LEFT);
- RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_RIGHT);
- RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_TOP);
- RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BOTTOM, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BOTTOM);
-
- /* 3D mouse align */
- kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, KM_SHIFT, 0);
- RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_FRONT);
- RNA_boolean_set(kmi->ptr, "align_active", TRUE);
- kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, KM_SHIFT, 0);
- RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_RIGHT);
- RNA_boolean_set(kmi->ptr, "align_active", TRUE);
- kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, KM_SHIFT, 0);
- RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_TOP);
- RNA_boolean_set(kmi->ptr, "align_active", TRUE);
- /* NDOF: end */
-
-
kmi = WM_keymap_verify_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_ANY, 0);
RNA_boolean_set(kmi->ptr, "release_confirm", TRUE);
/*
@@ -248,9 +221,9 @@ void view3d_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0);
- WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEPAN, 0, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEPAN, 0, 0, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEROTATE, 0, 0, 0);
- WM_keymap_add_item(keymap, "VIEW3D_OT_move", MOUSEPAN, 0, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_move", MOUSEPAN, 0, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", MOUSEZOOM, 0, 0, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", MOUSEPAN, 0, KM_CTRL, 0);
@@ -331,6 +304,34 @@ void view3d_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW3D_OT_localview", PADSLASHKEY, KM_PRESS, 0, 0);
+ /* NDOF: begin */
+ /* note: positioned here so keymaps show keyboard keys if assigned */
+ /* 3D mouse */
+ WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit_zoom", NDOF_MOTION, 0, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit", NDOF_MOTION, 0, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_pan", NDOF_MOTION, 0, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_all", NDOF_MOTION, 0, KM_CTRL | KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BACK, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BACK);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_LEFT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_LEFT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_RIGHT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_TOP);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BOTTOM, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BOTTOM);
+
+ /* 3D mouse align */
+ kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_FRONT);
+ RNA_boolean_set(kmi->ptr, "align_active", TRUE);
+ kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_RIGHT);
+ RNA_boolean_set(kmi->ptr, "align_active", TRUE);
+ kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_TOP);
+ RNA_boolean_set(kmi->ptr, "align_active", TRUE);
+ /* NDOF: end */
+
+
/* layers, shift + alt are properties set in invoke() */
RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ACCENTGRAVEKEY, KM_PRESS, 0, 0)->ptr, "nr", 0);
RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ONEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 1);
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index d4bdf6c3177..c428cb02236 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -110,7 +110,7 @@ eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base)
/* perspmat is typically...
* - 'rv3d->perspmat', is_local == FALSE
- * - 'rv3d->perspmatob', is_local == TRUE
+ * - 'rv3d->persmatob', is_local == TRUE
*/
static eV3DProjStatus ed_view3d_project__internal(ARegion *ar,
float perspmat[4][4], const int is_local, /* normally hidden */
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index d37042fa2ec..dac887f7f13 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -70,6 +70,7 @@
#include "BKE_paint.h"
#include "BKE_tessmesh.h"
#include "BKE_tracking.h"
+#include "BKE_utildefines.h"
#include "BIF_gl.h"
@@ -741,67 +742,19 @@ static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short m
mball_foreachScreenElem(vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
-static int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int extend)
+static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
{
- Mesh *me;
- MVert *mvert;
- struct ImBuf *ibuf;
- unsigned int *rt;
- int a, index;
- char *selar;
- int sx = BLI_rcti_size_x(rect) + 1;
- int sy = BLI_rcti_size_y(rect) + 1;
-
- me = vc->obact->data;
-
- if (me == NULL || me->totvert == 0 || sx * sy <= 0)
- return OPERATOR_CANCELLED;
-
- selar = MEM_callocN(me->totvert + 1, "selar");
-
- if (extend == 0 && select)
- paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, FALSE);
-
- view3d_validate_backbuf(vc);
-
- ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect);
- rt = ibuf->rect;
- glReadPixels(rect->xmin + vc->ar->winrct.xmin, rect->ymin + vc->ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
- if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
-
- a = sx * sy;
- while (a--) {
- if (*rt) {
- index = WM_framebuffer_to_index(*rt);
- if (index <= me->totvert) selar[index] = 1;
- }
- rt++;
- }
+ LassoSelectUserData *data = userData;
- mvert = me->mvert;
- for (a = 1; a <= me->totvert; a++, mvert++) {
- if (selar[a]) {
- if ((mvert->flag & ME_HIDE) == 0) {
- if (select) mvert->flag |= SELECT;
- else mvert->flag &= ~SELECT;
- }
- }
+ if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED))
+ {
+ BKE_BIT_TEST_SET(mv->flag, data->select, SELECT);
}
-
- IMB_freeImBuf(ibuf);
- MEM_freeN(selar);
-
-#ifdef __APPLE__
- glReadBuffer(GL_BACK);
-#endif
-
- paintvert_flush_flags(vc->obact);
-
- return OPERATOR_FINISHED;
}
-
static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
{
+ const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
Object *ob = vc->obact;
Mesh *me = ob ? ob->data : NULL;
rcti rect;
@@ -811,14 +764,31 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh
if (extend == 0 && select)
paintvert_deselect_all_visible(ob, SEL_DESELECT, FALSE); /* flush selection at the end */
- bm_vertoffs = me->totvert + 1; /* max index array */
BLI_lasso_boundbox(&rect, mcords, moves);
- EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- edbm_backbuf_check_and_select_verts_obmode(me, select);
+ if (use_zbuf) {
+ bm_vertoffs = me->totvert + 1; /* max index array */
- EDBM_backbuf_free();
+ EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+ edbm_backbuf_check_and_select_verts_obmode(me, select);
+
+ EDBM_backbuf_free();
+ }
+ else {
+ LassoSelectUserData data;
+ rcti rect;
+
+ BLI_lasso_boundbox(&rect, mcords, moves);
+
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
+
+ ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
+
+ meshobject_foreachScreenVert(vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ }
paintvert_flush_flags(ob);
}
@@ -1217,31 +1187,42 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
}
}
+static int selectbuffer_has_bones(const unsigned int *buffer, const unsigned int hits)
+{
+ unsigned int i;
+ for (i = 0; i < hits; i++) {
+ if (buffer[(4 * i) + 3] & 0xFFFF0000) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
/* we want a select buffer with bones, if there are... */
/* so check three selection levels and compare */
static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buffer, const int mval[2])
{
rcti rect;
int offs;
- short a, hits15, hits9 = 0, hits5 = 0;
- short has_bones15 = 0, has_bones9 = 0, has_bones5 = 0;
+ short hits15, hits9 = 0, hits5 = 0;
+ short has_bones15 = FALSE, has_bones9 = FALSE, has_bones5 = FALSE;
BLI_rcti_init(&rect, mval[0] - 14, mval[0] + 14, mval[1] - 14, mval[1] + 14);
hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
if (hits15 > 0) {
- for (a = 0; a < hits15; a++) if (buffer[4 * a + 3] & 0xFFFF0000) has_bones15 = 1;
+ has_bones15 = selectbuffer_has_bones(buffer, hits15);
offs = 4 * hits15;
BLI_rcti_init(&rect, mval[0] - 9, mval[0] + 9, mval[1] - 9, mval[1] + 9);
hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect);
if (hits9 > 0) {
- for (a = 0; a < hits9; a++) if (buffer[offs + 4 * a + 3] & 0xFFFF0000) has_bones9 = 1;
+ has_bones9 = selectbuffer_has_bones(buffer + offs, hits9);
offs += 4 * hits9;
BLI_rcti_init(&rect, mval[0] - 5, mval[0] + 5, mval[1] - 5, mval[1] + 5);
hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect);
if (hits5 > 0) {
- for (a = 0; a < hits5; a++) if (buffer[offs + 4 * a + 3] & 0xFFFF0000) has_bones5 = 1;
+ has_bones5 = selectbuffer_has_bones(buffer + offs, hits5);
}
}
@@ -1383,10 +1364,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
hits = mixed_bones_object_selectbuffer(&vc, buffer, mval);
if (hits > 0) {
- int a, has_bones = 0;
-
- for (a = 0; a < hits; a++) if (buffer[4 * a + 3] & 0xFFFF0000) has_bones = 1;
-
+ const int has_bones = selectbuffer_has_bones(buffer, hits);
basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, vc.scene->base.first, has_bones);
}
@@ -1420,7 +1398,6 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL;
- int a;
float dist = 100.0f;
int retval = 0;
short hits;
@@ -1473,10 +1450,8 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
hits = mixed_bones_object_selectbuffer(&vc, buffer, mval);
if (hits > 0) {
- int has_bones = 0;
-
/* note: bundles are handling in the same way as bones */
- for (a = 0; a < hits; a++) if (buffer[4 * a + 3] & 0xFFFF0000) has_bones = 1;
+ const int has_bones = selectbuffer_has_bones(buffer, hits);
/* note; shift+alt goes to group-flush-selecting */
if (has_bones == 0 && enumerate) {
@@ -1502,7 +1477,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
}
/* index of bundle is 1<<16-based. if there's no "bone" index
- * in height word, this buffer value belongs to camera,. not to bundle */
+ * in height word, this buffer value belongs to camera. not to bundle */
if (buffer[4 * i + 3] & 0xFFFF0000) {
MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, 0);
MovieTracking *tracking = &clip->tracking;
@@ -1670,6 +1645,85 @@ int edge_inside_circle(const float cent[2], float radius, const float screen_co_
return FALSE;
}
+static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
+{
+ BoxSelectUserData *data = userData;
+
+ if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
+ BKE_BIT_TEST_SET(mv->flag, data->select, SELECT);
+ }
+}
+static int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int extend)
+{
+ const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
+ Mesh *me;
+ MVert *mvert;
+ struct ImBuf *ibuf;
+ unsigned int *rt;
+ int a, index;
+ char *selar;
+ int sx = BLI_rcti_size_x(rect) + 1;
+ int sy = BLI_rcti_size_y(rect) + 1;
+
+ me = vc->obact->data;
+
+ if (me == NULL || me->totvert == 0 || sx * sy <= 0)
+ return OPERATOR_CANCELLED;
+
+
+ if (extend == 0 && select)
+ paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, FALSE);
+
+ if (use_zbuf) {
+ selar = MEM_callocN(me->totvert + 1, "selar");
+ view3d_validate_backbuf(vc);
+
+ ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect);
+ rt = ibuf->rect;
+ glReadPixels(rect->xmin + vc->ar->winrct.xmin, rect->ymin + vc->ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
+
+ a = sx * sy;
+ while (a--) {
+ if (*rt) {
+ index = WM_framebuffer_to_index(*rt);
+ if (index <= me->totvert) selar[index] = 1;
+ }
+ rt++;
+ }
+
+ mvert = me->mvert;
+ for (a = 1; a <= me->totvert; a++, mvert++) {
+ if (selar[a]) {
+ if ((mvert->flag & ME_HIDE) == 0) {
+ if (select) mvert->flag |= SELECT;
+ else mvert->flag &= ~SELECT;
+ }
+ }
+ }
+
+ IMB_freeImBuf(ibuf);
+ MEM_freeN(selar);
+
+#ifdef __APPLE__
+ glReadBuffer(GL_BACK);
+#endif
+ }
+ else {
+ BoxSelectUserData data;
+
+ view3d_userdata_boxselect_init(&data, vc, rect, select);
+
+ ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
+
+ meshobject_foreachScreenVert(vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ }
+
+ paintvert_flush_flags(vc->obact);
+
+ return OPERATOR_FINISHED;
+}
+
static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
{
BoxSelectUserData *data = userData;
@@ -2142,11 +2196,14 @@ void VIEW3D_OT_select_border(wmOperatorType *ot)
/* gets called via generic mouse select operator */
static int mouse_weight_paint_vertex_select(bContext *C, const int mval[2], short extend, short deselect, short toggle, Object *obact)
{
+ View3D *v3d = CTX_wm_view3d(C);
+ const int use_zbuf = (v3d->flag & V3D_ZBUF_SELECT);
+
Mesh *me = obact->data; /* already checked for NULL */
unsigned int index = 0;
MVert *mv;
- if (ED_mesh_pick_vert(C, me, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE)) {
+ if (ED_mesh_pick_vert(C, obact, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, use_zbuf)) {
mv = &me->mvert[index];
if (extend) {
mv->flag |= SELECT;
@@ -2366,22 +2423,39 @@ static void paint_facesel_circle_select(ViewContext *vc, int select, const int m
}
}
+static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
+{
+ CircleSelectUserData *data = userData;
+ if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
+ BKE_BIT_TEST_SET(mv->flag, data->select, SELECT);
+ }
+}
static void paint_vertsel_circle_select(ViewContext *vc, int select, const int mval[2], float rad)
{
+ const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
Object *ob = vc->obact;
- Mesh *me = ob ? ob->data : NULL;
+ Mesh *me = ob->data;
/* int bbsel; */ /* UNUSED */
/* CircleSelectUserData data = {NULL}; */ /* UNUSED */
- if (me) {
+
+ if (use_zbuf) {
bm_vertoffs = me->totvert + 1; /* max index array */
/* bbsel = */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
edbm_backbuf_check_and_select_verts_obmode(me, select == LEFTMOUSE);
EDBM_backbuf_free();
+ }
+ else {
+ CircleSelectUserData data;
- paintvert_flush_flags(ob);
+ ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
+
+ view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+ meshobject_foreachScreenVert(vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
+
+ paintvert_flush_flags(ob);
}
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index b2ee17b8a8b..3b443e8bbac 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -686,6 +686,9 @@ static void view_editmove(unsigned short UNUSED(event))
#define TFM_MODAL_EDGESLIDE_UP 24
#define TFM_MODAL_EDGESLIDE_DOWN 25
+/* for analog input, like trackpad */
+#define TFM_MODAL_PROPSIZE 26
+
/* called in transform_ops.c, on each regeneration of keymaps */
wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
{
@@ -715,6 +718,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
{TFM_MODAL_AUTOIK_LEN_DEC, "AUTOIK_CHAIN_LEN_DOWN", 0, "Decrease Max AutoIK Chain Length", ""},
{TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""},
{TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""},
+ {TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -750,6 +754,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN);
WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_UP);
WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN);
+ WM_modalkeymap_add_item(keymap, MOUSEPAN, 0, 0, 0, TFM_MODAL_PROPSIZE);
WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0, TFM_MODAL_EDGESLIDE_UP);
WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_ALT, 0, TFM_MODAL_EDGESLIDE_DOWN);
@@ -1024,6 +1029,19 @@ int transformEvent(TransInfo *t, wmEvent *event)
removeSnapPoint(t);
t->redraw |= TREDRAW_HARD;
break;
+
+ case TFM_MODAL_PROPSIZE:
+ /* MOUSEPAN usage... */
+ if (t->flag & T_PROP_EDIT) {
+ float fac = 1.0f + 0.005f *(event->y - event->prevy);
+ t->prop_size *= fac;
+ if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO)
+ t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far);
+ calculatePropRatio(t);
+ }
+ t->redraw |= TREDRAW_HARD;
+ break;
+
case TFM_MODAL_PROPSIZE_UP:
if (t->flag & T_PROP_EDIT) {
t->prop_size *= 1.1f;
@@ -1500,7 +1518,6 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
glTranslatef(mval[0], mval[1], 0);
glLineWidth(3.0);
- glBegin(GL_LINES);
drawArrow(UP, 5, 10, 5);
drawArrow(DOWN, 5, 10, 5);
glLineWidth(1.0);
@@ -2258,8 +2275,8 @@ static void protectedQuaternionBits(short protectflag, float *quat, float *oldqu
static void constraintTransLim(TransInfo *t, TransData *td)
{
if (td->con) {
- bConstraintTypeInfo *ctiLoc = get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT);
- bConstraintTypeInfo *ctiDist = get_constraint_typeinfo(CONSTRAINT_TYPE_DISTLIMIT);
+ bConstraintTypeInfo *ctiLoc = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT);
+ bConstraintTypeInfo *ctiDist = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_DISTLIMIT);
bConstraintOb cob = {NULL};
bConstraint *con;
@@ -2309,7 +2326,7 @@ static void constraintTransLim(TransInfo *t, TransData *td)
}
/* get constraint targets if needed */
- get_constraint_targets_for_solving(con, &cob, &targets, ctime);
+ BKE_get_constraint_targets_for_solving(con, &cob, &targets, ctime);
/* do constraint */
cti->evaluate_constraint(con, &cob, &targets);
@@ -2361,7 +2378,7 @@ static void constraintob_from_transdata(bConstraintOb *cob, TransData *td)
static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
{
if (td->con) {
- bConstraintTypeInfo *cti = get_constraint_typeinfo(CONSTRAINT_TYPE_ROTLIMIT);
+ bConstraintTypeInfo *cti = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_ROTLIMIT);
bConstraintOb cob;
bConstraint *con;
int do_limit = FALSE;
@@ -2428,7 +2445,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
static void constraintSizeLim(TransInfo *t, TransData *td)
{
if (td->con && td->ext) {
- bConstraintTypeInfo *cti = get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT);
+ bConstraintTypeInfo *cti = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT);
bConstraintOb cob = {NULL};
bConstraint *con;
float size_sign[3], size_abs[3];
@@ -2721,6 +2738,18 @@ int handleEventShear(TransInfo *t, wmEvent *event)
status = 1;
}
+ else if (event->type == XKEY && event->val == KM_PRESS) {
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+ t->customData = NULL;
+
+ status = 1;
+ }
+ else if (event->type == YKEY && event->val == KM_PRESS) {
+ initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+ t->customData = (void *)1;
+
+ status = 1;
+ }
return status;
}
@@ -2754,7 +2783,7 @@ int Shear(TransInfo *t, const int UNUSED(mval[2]))
}
else {
/* default header print */
- sprintf(str, "Shear: %.3f %s", value, t->proptext);
+ sprintf(str, "Shear: %.3f %s (Press X or Y to set shear axis)", value, t->proptext);
}
t->values[0] = value;
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 7da47425370..12b0341d395 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -835,7 +835,7 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan)
}
}
- con = add_pose_constraint(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
+ con = BKE_add_pose_constraint(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
pchan->constflag |= (PCHAN_HAS_IK | PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
data = con->data;
if (targetless) {
@@ -4090,7 +4090,7 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count
/* Meta's can only directly be moved between channels since they
* don't have their start and length set directly (children affect that)
* since this Meta is nested we don't need any of its data in fact.
- * calc_sequence() will update its settings when run on the toplevel meta */
+ * BKE_sequence_calc() will update its settings when run on the toplevel meta */
*flag = 0;
*count = 0;
*recursive = TRUE;
@@ -4268,8 +4268,8 @@ static void freeSeqData(TransInfo *t)
{
int overlap = 0;
+ seq_prev = NULL;
for (a = 0; a < t->total; a++, td++) {
- seq_prev = NULL;
seq = ((TransDataSeq *)td->extra)->seq;
if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) {
overlap = 1;
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 8f1d6a7b46e..2591c61c5ab 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -61,6 +61,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "BIK_api.h"
+
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_armature.h"
@@ -847,6 +849,8 @@ static void recalcData_view3d(TransInfo *t)
/* old optimize trick... this enforces to bypass the depgraph */
if (!(arm->flag & ARM_DELAYDEFORM)) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
+ /* transformation of pose may affect IK tree, make sure it is rebuilt */
+ BIK_clear_data(ob->pose);
}
else
BKE_pose_where_is(t->scene, ob);
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index c9c4f7e2c7b..4bd6496e083 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -764,7 +764,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
EditBone *ebone;
int ok = FALSE;
- /* grr,.but better then duplicate code */
+ /* grr. but better then duplicate code */
#define EBONE_CALC_NORMAL_PLANE { \
float tmat[3][3]; \
float vec[3]; \
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index 1753a564a3c..1dc7e0c90e8 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -162,15 +162,18 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
}
}
else {
- int do_glob_undo = FALSE;
-
+ /* Note: we used to do a fall-through here where if the
+ * mode-specific undo system had no more steps to undo (or
+ * redo), the global undo would run.
+ *
+ * That was inconsistent with editmode, and also makes for
+ * unecessarily tricky interaction with the other undo
+ * systems. */
if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
- if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname))
- do_glob_undo = TRUE;
+ ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname);
}
else if (obact && obact->mode & OB_MODE_SCULPT) {
- if (!ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname))
- do_glob_undo = TRUE;
+ ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname);
}
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
if (step == 1)
@@ -178,24 +181,17 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
else
PE_redo(CTX_data_scene(C));
}
- else {
- do_glob_undo = TRUE;
- }
-
- if (do_glob_undo) {
- if (U.uiflag & USER_GLOBALUNDO) {
- // note python defines not valid here anymore.
- //#ifdef WITH_PYTHON
- // XXX BPY_scripts_clear_pyobjects();
- //#endif
- if (undoname)
- BKE_undo_name(C, undoname);
- else
- BKE_undo_step(C, step);
+ else if (U.uiflag & USER_GLOBALUNDO) {
+ // note python defines not valid here anymore.
+ //#ifdef WITH_PYTHON
+ // XXX BPY_scripts_clear_pyobjects();
+ //#endif
+ if (undoname)
+ BKE_undo_name(C, undoname);
+ else
+ BKE_undo_step(C, step);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
- }
-
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
}
}
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 27bbba11e75..4d52282d540 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -73,6 +73,7 @@ void uv_find_nearest_edge(struct Scene *scene, struct Image *ima, struct BMEditM
/* utility tool functions */
void uvedit_live_unwrap_update(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit);
+void uvedit_get_aspect(struct Scene *scene, struct Object *ob, struct BMEditMesh *em, float *aspx, float *aspy);
/* operators */
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index bd50857c8b8..8c3eaa1192f 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -136,6 +136,7 @@ typedef struct UvEdge {
/* stitch state object */
typedef struct StitchState {
+ float aspect;
/* use limit flag */
char use_limit;
/* limit to operator, same as original operator */
@@ -285,10 +286,12 @@ static int getNumOfIslandUvs(UvElementMap *elementMap, int island)
}
}
-static void stitch_uv_rotate(float rotation, float medianPoint[2], float uv[2])
+static void stitch_uv_rotate(float rotation, float medianPoint[2], float uv[2], float aspect)
{
float uv_rotation_result[2];
+ uv[1] /= aspect;
+
uv[0] -= medianPoint[0];
uv[1] -= medianPoint[1];
@@ -297,6 +300,8 @@ static void stitch_uv_rotate(float rotation, float medianPoint[2], float uv[2])
uv[0] = uv_rotation_result[0] + medianPoint[0];
uv[1] = uv_rotation_result[1] + medianPoint[1];
+
+ uv[1] *= aspect;
}
/* check if two uvelements are stitchable. This should only operate on -different- separate UvElements */
@@ -413,9 +418,11 @@ static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition
island_stitch_data[i].rotation /= island_stitch_data[i].num_rot_elements;
island_stitch_data[i].medianPoint[0] /= island_stitch_data[i].numOfElements;
island_stitch_data[i].medianPoint[1] /= island_stitch_data[i].numOfElements;
+ island_stitch_data[i].medianPoint[1] /= state->aspect;
}
island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements;
island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements;
+
numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
element = &state->element_map->buf[state->element_map->islandIndices[i]];
for (j = 0; j < numOfIslandUVs; j++, element++) {
@@ -429,7 +436,7 @@ static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition
if (final) {
- stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint, luv->uv);
+ stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint, luv->uv, state->aspect);
add_v2_v2(luv->uv, island_stitch_data[i].translation);
}
@@ -438,7 +445,7 @@ static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition
int face_preview_pos = preview_position[BM_elem_index_get(element->l->f)].data_position;
stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint,
- preview->preview_polys + face_preview_pos + 2 * element->tfindex);
+ preview->preview_polys + face_preview_pos + 2 * element->tfindex, state->aspect);
add_v2_v2(preview->preview_polys + face_preview_pos + 2 * element->tfindex,
island_stitch_data[i].translation);
@@ -461,15 +468,12 @@ static void stitch_island_calculate_edge_rotation(UvEdge *edge, StitchState *sta
int index1, index2;
float rotation;
MLoopUV *luv1, *luv2;
- BMLoop *l1, *l2;
element1 = state->uvs[edge->uv1];
element2 = state->uvs[edge->uv2];
- l1 = element1->l;
- luv1 = CustomData_bmesh_get(&state->em->bm->ldata, l1->head.data, CD_MLOOPUV);
- l2 = element2->l;
- luv2 = CustomData_bmesh_get(&state->em->bm->ldata, l2->head.data, CD_MLOOPUV);
+ luv1 = CustomData_bmesh_get(&state->em->bm->ldata, element1->l->head.data, CD_MLOOPUV);
+ luv2 = CustomData_bmesh_get(&state->em->bm->ldata, element2->l->head.data, CD_MLOOPUV);
if (state->mode == STITCH_VERT) {
index1 = uvfinal_map[element1 - state->element_map->buf];
@@ -484,14 +488,18 @@ static void stitch_island_calculate_edge_rotation(UvEdge *edge, StitchState *sta
uv1[0] = luv2->uv[0] - luv1->uv[0];
uv1[1] = luv2->uv[1] - luv1->uv[1];
+ uv1[1] /= state->aspect;
+
uv2[0] = uv_average[index2].uv[0] - uv_average[index1].uv[0];
uv2[1] = uv_average[index2].uv[1] - uv_average[index1].uv[1];
+ uv2[1] /= state->aspect;
+
normalize_v2(uv1);
normalize_v2(uv2);
- edgecos = uv1[0] * uv2[0] + uv1[1] * uv2[1];
- edgesin = uv1[0] * uv2[1] - uv2[0] * uv1[1];
+ edgecos = dot_v2v2(uv1, uv2);
+ edgesin = cross_v2v2(uv1, uv2);
rotation = (edgesin > 0.0f) ?
+acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))) :
@@ -536,7 +544,9 @@ static void stitch_island_calculate_vert_rotation(UvElement *element, StitchStat
negate_v2_v2(normal, state->normals + index_tmp2 * 2);
edgecos = dot_v2v2(normal, state->normals + index_tmp1 * 2);
edgesin = cross_v2v2(normal, state->normals + index_tmp1 * 2);
- rotation += (edgesin > 0.0f) ? acosf(edgecos) : -acosf(edgecos);
+ rotation += (edgesin > 0.0f) ?
+ +acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))) :
+ -acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
}
}
@@ -837,13 +847,13 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
int previous_island = state->static_island;
BMFace *efa;
BMIter iter;
- UVVertAverage *final_position;
+ UVVertAverage *final_position = NULL;
char stitch_midpoints = state->midpoints;
/* used to map uv indices to uvaverage indices for selection */
- unsigned int *uvfinal_map;
+ unsigned int *uvfinal_map = NULL;
/* per face preview position in preview buffer */
- PreviewPosition *preview_position;
+ PreviewPosition *preview_position = NULL;
/* cleanup previous preview */
stitch_preview_delete(state->stitch_preview);
@@ -1157,6 +1167,14 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
}
}
+ /* take mean position here. For edge case, this can't be done inside the loop for shared uvverts */
+ if (state->mode == STITCH_EDGE && stitch_midpoints) {
+ for (i = 0; i < state->total_separate_uvs; i++) {
+ final_position[i].uv[0] /= final_position[i].count;
+ final_position[i].uv[1] /= final_position[i].count;
+ }
+ }
+
/* second pass, calculate island rotation and translation before modifying any uvs */
if (state->snap_islands) {
if (state->mode == STITCH_VERT) {
@@ -1211,11 +1229,6 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
for (i = 0; i < state->total_separate_uvs; i++) {
UvElement *element = state->uvs[i];
- if (stitch_midpoints) {
- final_position[i].uv[0] /= final_position[i].count;
- final_position[i].uv[1] /= final_position[i].count;
- }
-
if (element->flag & STITCH_STITCHABLE) {
BMLoop *l;
MLoopUV *luv;
@@ -1419,18 +1432,19 @@ static void stitch_switch_selection_mode(StitchState *state)
MEM_freeN(old_selection_stack);
}
-static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal)
+static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal, float aspect)
{
BMLoop *l1 = edge->element->l;
- BMLoop *l2 = l1->next;
MLoopUV *luv1, *luv2;
float tangent[2];
luv1 = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, CD_MLOOPUV);
- luv2 = CustomData_bmesh_get(&em->bm->ldata, l2->head.data, CD_MLOOPUV);
+ luv2 = CustomData_bmesh_get(&em->bm->ldata, l1->next->head.data, CD_MLOOPUV);
sub_v2_v2v2(tangent, luv2->uv, luv1->uv);
+ tangent[1] /= aspect;
+
normal[0] = tangent[1];
normal[1] = -tangent[0];
@@ -1447,6 +1461,8 @@ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *ar
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
+ glPointSize(pointsize * 2.0f);
+
glEnable(GL_BLEND);
UI_ThemeColor4(TH_STITCH_PREVIEW_ACTIVE);
@@ -1462,19 +1478,18 @@ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *ar
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
UI_ThemeColor4(TH_STITCH_PREVIEW_EDGE);
glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
+ #if 0
+ glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
+ UI_ThemeColor4(TH_STITCH_PREVIEW_VERT);
+ glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
+ #endif
index += stitch_preview->uvs_per_polygon[i];
}
- glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
-#if 0
- UI_ThemeColor4(TH_STITCH_PREVIEW_VERT);
- glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_tris * 3);
-#endif
glDisable(GL_BLEND);
/* draw vert preview */
if (state->mode == STITCH_VERT) {
- glPointSize(pointsize * 2.0f);
UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
glDrawArrays(GL_POINTS, 0, stitch_preview->num_stitchable);
@@ -1541,7 +1556,7 @@ static int stitch_init(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
ARegion *ar = CTX_wm_region(C);
-
+ float aspx, aspy;
Object *obedit = CTX_data_edit_object(C);
if (!ar)
@@ -1595,6 +1610,9 @@ static int stitch_init(bContext *C, wmOperator *op)
return 0;
}
+ uvedit_get_aspect(scene, obedit, em, &aspx, &aspy);
+ state->aspect = aspx / aspy;
+
/* Entirely possible if redoing last operator that static island is bigger than total number of islands.
* This ensures we get no hang in the island checking code in stitch_stitch_process_data. */
state->static_island %= state->element_map->totalIslands;
@@ -1720,15 +1738,16 @@ static int stitch_init(bContext *C, wmOperator *op)
* the winding of the polygon (assuming counter-clockwise flow). */
for (i = 0; i < total_edges; i++) {
+ UvEdge *edge = edges + i;
float normal[2];
- if (edges[i].flag & STITCH_BOUNDARY) {
- stitch_calculate_edge_normal(em, edges + i, normal);
+ if (edge->flag & STITCH_BOUNDARY) {
+ stitch_calculate_edge_normal(em, edge, normal, state->aspect);
- add_v2_v2(state->normals + edges[i].uv1 * 2, normal);
- add_v2_v2(state->normals + edges[i].uv2 * 2, normal);
+ add_v2_v2(state->normals + edge->uv1 * 2, normal);
+ add_v2_v2(state->normals + edge->uv2 * 2, normal);
- normalize_v2(state->normals + edges[i].uv1 * 2);
- normalize_v2(state->normals + edges[i].uv2 * 2);
+ normalize_v2(state->normals + edge->uv1 * 2);
+ normalize_v2(state->normals + edge->uv2 * 2);
}
}
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 2ca711a4a6a..81f548b2b5d 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -196,7 +196,7 @@ static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit)
return 0;
}
-static void ED_uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, float *aspy)
+void uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, float *aspy)
{
int sloppy = TRUE;
int selected = FALSE;
@@ -238,7 +238,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh
if (correct_aspect) {
float aspx, aspy;
- ED_uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
+ uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
if (aspx != aspy)
param_aspect_ratio(handle, aspx, aspy);
@@ -423,7 +423,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
if (correct_aspect) {
float aspx, aspy;
- ED_uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
+ uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
if (aspx != aspy)
param_aspect_ratio(handle, aspx, aspy);
@@ -1047,7 +1047,7 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em)
BMFace *efa;
float scale, aspx, aspy;
- ED_uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
+ uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
if (aspx == aspy)
return;
@@ -1563,7 +1563,6 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
uv_map_transform(C, op, center, rotmat);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
continue;
@@ -1573,6 +1572,7 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
}
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
uv_map_mirror(em, efa, tf);
}