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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2016-12-01 12:29:46 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2016-12-01 12:29:46 +0300
commitff2a74906a7b70625a4e941c6a805f7734491204 (patch)
tree562f5ccdd9f4e377d20fe22eadca48201924b4b3 /source/blender/editors
parent73c1c92c0e86ce1b5a8abeaa16be2bf2c259412b (diff)
parent58877d6d082d82185ca611b704364168e5984bd7 (diff)
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c42
-rw-r--r--source/blender/editors/include/ED_gpencil.h2
-rw-r--r--source/blender/editors/include/UI_icons.h9
-rw-r--r--source/blender/editors/include/UI_interface.h2
-rw-r--r--source/blender/editors/interface/interface.c41
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c90
-rw-r--r--source/blender/editors/interface/interface_intern.h2
-rw-r--r--source/blender/editors/interface/interface_layout.c2
-rw-r--r--source/blender/editors/interface/interface_regions.c6
-rw-r--r--source/blender/editors/interface/interface_templates.c5
-rw-r--r--source/blender/editors/interface/interface_utils.c4
-rw-r--r--source/blender/editors/interface/interface_widgets.c10
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c2
-rw-r--r--source/blender/editors/object/object_add.c153
-rw-r--r--source/blender/editors/object/object_relations.c98
-rw-r--r--source/blender/editors/object/object_warp.c3
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c3
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c15
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c15
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c2
24 files changed, 330 insertions, 196 deletions
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 12d837dfb29..15f65b394a9 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -96,7 +96,11 @@ static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
/* Just toggle editmode flag... */
gpd->flag ^= GP_DATA_STROKE_EDITMODE;
-
+ /* recalculate parent matrix */
+ if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
+ ED_gpencil_reset_layers_parent(gpd);
+ }
+
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL);
WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 564ba639983..76e85f20c36 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -915,7 +915,7 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints)
/**
* Add randomness to stroke
* \param gps Stroke data
- * \param brsuh Brush data
+ * \param brush Brush data
*/
void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush)
{
@@ -997,6 +997,46 @@ void ED_gpencil_parent_location(bGPDlayer *gpl, float diff_mat[4][4])
}
}
+/* reset parent matrix for all layers */
+void ED_gpencil_reset_layers_parent(bGPdata *gpd)
+{
+ bGPDspoint *pt;
+ int i;
+ float diff_mat[4][4];
+ float cur_mat[4][4];
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->parent != NULL) {
+ /* calculate new matrix */
+ if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
+ invert_m4_m4(cur_mat, gpl->parent->obmat);
+ }
+ else if (gpl->partype == PARBONE) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr);
+ if (pchan) {
+ float tmp_mat[4][4];
+ mul_m4_m4m4(tmp_mat, gpl->parent->obmat, pchan->pose_mat);
+ invert_m4_m4(cur_mat, tmp_mat);
+ }
+ }
+
+ /* only redo if any change */
+ if (!equals_m4m4(gpl->inverse, cur_mat)) {
+ /* first apply current transformation to all strokes */
+ ED_gpencil_parent_location(gpl, diff_mat);
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ mul_m4_v3(diff_mat, &pt->x);
+ }
+ }
+ }
+ /* set new parent matrix */
+ copy_m4_m4(gpl->inverse, cur_mat);
+ }
+ }
+ }
+}
/* ******************************************************** */
bool ED_gpencil_stroke_minmax(
const bGPDstroke *gps, const bool use_select,
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index bc93b5622cb..74d9ad0886d 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -185,6 +185,8 @@ int ED_undo_gpencil_step(struct bContext *C, int step, const char *name);
/* get difference matrix using parent */
void ED_gpencil_parent_location(struct bGPDlayer *gpl, float diff_mat[4][4]);
+/* reset parent matrix for all layers */
+void ED_gpencil_reset_layers_parent(struct bGPdata *gpd);
#endif /* __ED_GPENCIL_H__ */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index e016e014a1a..8579778ff79 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -1005,15 +1005,6 @@ DEF_ICON(MATCAP_23)
DEF_ICON(MATCAP_24)
/* vector icons, VICO_ prefix added */
-DEF_VICO(VIEW3D_VEC)
-DEF_VICO(EDIT_VEC)
-DEF_VICO(EDITMODE_VEC_DEHLT)
-DEF_VICO(EDITMODE_VEC_HLT)
-DEF_VICO(DISCLOSURE_TRI_RIGHT_VEC)
-DEF_VICO(DISCLOSURE_TRI_DOWN_VEC)
-DEF_VICO(MOVE_UP_VEC)
-DEF_VICO(MOVE_DOWN_VEC)
-DEF_VICO(X_VEC)
DEF_VICO(SMALL_TRI_RIGHT_VEC)
DEF_VICO(KEYTYPE_KEYFRAME_VEC)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index d1f14bf5c1a..d48cfbee413 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -181,7 +181,7 @@ enum {
UI_BUT_HAS_SEP_CHAR = (1 << 27), /* but->str contains UI_SEP_CHAR, used for key shortcuts */
UI_BUT_UPDATE_DELAY = (1 << 28), /* don't run updates while dragging (needed in rare cases). */
UI_BUT_TEXTEDIT_UPDATE = (1 << 29), /* when widget is in textedit mode, update value on each char stroke */
- UI_BUT_SEARCH_UNLINK = (1 << 30), /* show unlink for search button */
+ UI_BUT_VALUE_CLEAR = (1 << 30), /* show 'x' icon to clear/unlink value of text or search button */
};
#define UI_PANEL_WIDTH 340
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 6bba35e821f..a913421d12c 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1987,22 +1987,29 @@ uiBut *ui_but_drag_multi_edit_get(uiBut *but)
/** \name Check to show extra icons
*
* Extra icons are shown on the right hand side of buttons.
+ * This could (should!) definitely become more generic, but for now this is good enough.
* \{ */
+static bool ui_but_icon_extra_is_visible_text_clear(const uiBut *but)
+{
+ BLI_assert(but->type == UI_BTYPE_TEXT);
+ return ((but->flag & UI_BUT_VALUE_CLEAR) && but->drawstr && but->drawstr[0]);
+}
+
static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but)
{
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
return ((but->editstr == NULL) &&
(but->drawstr[0] != '\0') &&
- (but->flag & UI_BUT_SEARCH_UNLINK));
+ (but->flag & UI_BUT_VALUE_CLEAR));
}
-static bool ui_but_icon_extra_is_visible_eyedropper(uiBut *but)
+static bool ui_but_icon_extra_is_visible_search_eyedropper(uiBut *but)
{
StructRNA *type;
short idcode;
- BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_SEARCH_UNLINK));
+ BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_VALUE_CLEAR));
if (but->rnaprop == NULL) {
return false;
@@ -2011,21 +2018,31 @@ static bool ui_but_icon_extra_is_visible_eyedropper(uiBut *but)
type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
idcode = RNA_type_to_ID_code(type);
-
return ((but->editstr == NULL) &&
(idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode)));
}
uiButExtraIconType ui_but_icon_extra_get(uiBut *but)
{
- if ((but->flag & UI_BUT_SEARCH_UNLINK) == 0) {
- /* pass */
- }
- else if (ui_but_icon_extra_is_visible_search_unlink(but)) {
- return UI_BUT_ICONEXTRA_UNLINK;
- }
- else if (ui_but_icon_extra_is_visible_eyedropper(but)) {
- return UI_BUT_ICONEXTRA_EYEDROPPER;
+ switch (but->type) {
+ case UI_BTYPE_TEXT:
+ if (ui_but_icon_extra_is_visible_text_clear(but)) {
+ return UI_BUT_ICONEXTRA_CLEAR;
+ }
+ break;
+ case UI_BTYPE_SEARCH_MENU:
+ if ((but->flag & UI_BUT_VALUE_CLEAR) == 0) {
+ /* pass */
+ }
+ else if (ui_but_icon_extra_is_visible_search_unlink(but)) {
+ return UI_BUT_ICONEXTRA_CLEAR;
+ }
+ else if (ui_but_icon_extra_is_visible_search_eyedropper(but)) {
+ return UI_BUT_ICONEXTRA_EYEDROPPER;
+ }
+ break;
+ default:
+ break;
}
return UI_BUT_ICONEXTRA_NONE;
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 9c808589d26..6efa711a53f 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -748,7 +748,7 @@ static int datadropper_poll(bContext *C)
if ((CTX_wm_window(C) != NULL) &&
(but = UI_context_active_but_prop_get(C, &ptr, &prop, &index_dummy)) &&
(but->type == UI_BTYPE_SEARCH_MENU) &&
- (but->flag & UI_BUT_SEARCH_UNLINK))
+ (but->flag & UI_BUT_VALUE_CLEAR))
{
if (prop && RNA_property_type(prop) == PROP_POINTER) {
StructRNA *type = RNA_property_pointer_type(&ptr, prop);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 09ba666773b..ce67c24f096 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -2554,6 +2554,18 @@ void ui_but_text_password_hide(char password_str[UI_MAX_PASSWORD_STR], uiBut *bu
}
}
+static void ui_but_text_clear(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ /* most likely NULL, but let's check, and give it temp zero string */
+ if (!data->str) {
+ data->str = MEM_callocN(1, "temp str");
+ }
+ data->str[0] = 0;
+
+ ui_apply_but_TEX(C, but, data);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+}
+
/* ************* in-button text selection/editing ************* */
@@ -3820,6 +3832,21 @@ static int ui_do_but_KEYEVT(
return WM_UI_HANDLER_CONTINUE;
}
+static bool ui_but_is_mouse_over_icon_extra(const ARegion *region, uiBut *but, const int mouse_xy[2])
+{
+ int x = mouse_xy[0], y = mouse_xy[1];
+ rcti icon_rect;
+
+ BLI_assert(ui_but_icon_extra_get(but) != UI_BUT_ICONEXTRA_NONE);
+
+ ui_window_to_block(region, but->block, &x, &y);
+
+ BLI_rcti_rctf_copy(&icon_rect, &but->rect);
+ icon_rect.xmin = icon_rect.xmax - (BLI_rcti_size_y(&icon_rect));
+
+ return BLI_rcti_isect_pt(&icon_rect, x, y);
+}
+
static int ui_do_but_TEX(
bContext *C, uiBlock *block, uiBut *but,
uiHandleButtonData *data, const wmEvent *event)
@@ -3833,7 +3860,14 @@ static int ui_do_but_TEX(
/* pass */
}
else {
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ const bool has_icon_extra = ui_but_icon_extra_get(but) == UI_BUT_ICONEXTRA_CLEAR;
+
+ if (has_icon_extra && ui_but_is_mouse_over_icon_extra(data->region, but, &event->x)) {
+ ui_but_text_clear(C, but, data);
+ }
+ else {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ }
return WM_UI_HANDLER_BREAK;
}
}
@@ -3854,47 +3888,29 @@ static int ui_do_but_SEARCH_UNLINK(
bContext *C, uiBlock *block, uiBut *but,
uiHandleButtonData *data, const wmEvent *event)
{
- uiButExtraIconType extra_icon_type;
+ const uiButExtraIconType extra_icon_type = ui_but_icon_extra_get(but);
+ const bool has_icon_extra = (extra_icon_type != UI_BUT_ICONEXTRA_NONE);
/* unlink icon is on right */
if ((ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) &&
- ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE))
+ (has_icon_extra == true) &&
+ (ui_but_is_mouse_over_icon_extra(data->region, but, &event->x) == true))
{
- ARegion *ar = data->region;
- rcti rect;
- int x = event->x, y = event->y;
-
- ui_window_to_block(ar, but->block, &x, &y);
-
- BLI_rcti_rctf_copy(&rect, &but->rect);
-
- rect.xmin = rect.xmax - (BLI_rcti_size_y(&rect));
- /* handle click on unlink/eyedropper icon */
- if (BLI_rcti_isect_pt(&rect, x, y)) {
- /* doing this on KM_PRESS calls eyedropper after clicking unlink icon */
- if (event->val == KM_RELEASE) {
- /* unlink */
- if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) {
- /* most likely NULL, but let's check, and give it temp zero string */
- if (data->str == NULL) {
- data->str = MEM_callocN(1, "temp str");
- }
- data->str[0] = 0;
-
- ui_apply_but_TEX(C, but, data);
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- /* eyedropper */
- else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
- WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL);
- }
- else {
- BLI_assert(0);
- }
+ /* doing this on KM_PRESS calls eyedropper after clicking unlink icon */
+ if (event->val == KM_RELEASE) {
+ /* unlink */
+ if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
+ ui_but_text_clear(C, but, data);
+ }
+ /* eyedropper */
+ else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
+ WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL);
+ }
+ else {
+ BLI_assert(0);
}
-
- return WM_UI_HANDLER_BREAK;
}
+ return WM_UI_HANDLER_BREAK;
}
return ui_do_but_TEX(C, block, but, data, event);
}
@@ -7069,7 +7085,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case UI_BTYPE_TEXT:
case UI_BTYPE_SEARCH_MENU:
if ((but->type == UI_BTYPE_SEARCH_MENU) &&
- (but->flag & UI_BUT_SEARCH_UNLINK))
+ (but->flag & UI_BUT_VALUE_CLEAR))
{
retval = ui_do_but_SEARCH_UNLINK(C, block, but, data, event);
if (retval & WM_UI_HANDLER_BREAK) {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 0f9db6fd9b6..7529f60c6f0 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -127,7 +127,7 @@ enum {
* (e.g. 'x' icon in search menu) - used with ui_but_icon_extra_get */
typedef enum uiButExtraIconType {
UI_BUT_ICONEXTRA_NONE = 1,
- UI_BUT_ICONEXTRA_UNLINK,
+ UI_BUT_ICONEXTRA_CLEAR,
UI_BUT_ICONEXTRA_EYEDROPPER,
} uiButExtraIconType;
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 875522e01c6..b128bf47b5f 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -1659,7 +1659,7 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN
but->rnasearchprop = searchprop;
but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT;
if (RNA_property_is_unlink(prop)) {
- but->flag |= UI_BUT_SEARCH_UNLINK;
+ but->flag |= UI_BUT_VALUE_CLEAR;
}
if (RNA_property_type(prop) == PROP_ENUM) {
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index cdf34642a8d..466978272bc 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -851,7 +851,7 @@ static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step)
}
else {
/* only let users step into an 'unset' state for unlink buttons */
- data->active = (but->flag & UI_BUT_SEARCH_UNLINK) ? -1 : 0;
+ data->active = (but->flag & UI_BUT_VALUE_CLEAR) ? -1 : 0;
}
}
@@ -922,8 +922,8 @@ bool ui_searchbox_apply(uiBut *but, ARegion *ar)
return true;
}
- else if (but->flag & UI_BUT_SEARCH_UNLINK) {
- /* It is valid for _UNLINK flavor to have no active element (it's a valid way to unlink). */
+ else if (but->flag & UI_BUT_VALUE_CLEAR) {
+ /* It is valid for _VALUE_CLEAR flavor to have no active element (it's a valid way to unlink). */
but->editstr[0] = '\0';
return true;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 09c5854fb26..80784e86b1e 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -302,7 +302,10 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
break;
case UI_ID_LOCAL:
if (id) {
- if (id_make_local(CTX_data_main(C), id, false, false)) {
+ Main *bmain = CTX_data_main(C);
+ if (id_make_local(bmain, id, false, false)) {
+ BKE_main_id_clear_newpoins(bmain);
+
/* reassign to get get proper updates/notifiers */
idptr = RNA_property_pointer_get(&template->ptr, template->prop);
RNA_property_pointer_set(&template->ptr, template->prop, idptr);
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 1d51c0588b6..8dfbbdd02eb 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -119,6 +119,10 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
else
but = uiDefButR_prop(block, UI_BTYPE_TEXT, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ PropertySubType subtype = RNA_property_subtype(prop);
+ if (!(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME) || (block->flag & UI_BLOCK_LIST_ITEM))) {
+ UI_but_flag_enable(but, UI_BUT_VALUE_CLEAR);
+ }
if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE);
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 6cb3aa19db3..b75ecf68136 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1513,10 +1513,10 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* draws text and icons for buttons */
static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
{
+ const uiButExtraIconType extra_icon_type = ui_but_icon_extra_get(but);
const bool show_menu_icon = ui_but_draw_menu_icon(but);
float alpha = (float)wcol->text[3] / 255.0f;
char password_str[UI_MAX_DRAW_STR];
- uiButExtraIconType extra_icon_type;
ui_but_text_password_hide(password_str, but, false);
@@ -1582,15 +1582,13 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
rect->xmax -= (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
}
- /* unlink icon for this button type */
- if ((but->type == UI_BTYPE_SEARCH_MENU) &&
- ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE))
- {
+ /* extra icons, e.g. 'x' icon to clear text or icon for eyedropper */
+ if (extra_icon_type != UI_BUT_ICONEXTRA_NONE) {
rcti temp = *rect;
temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
- if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) {
+ if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
widget_draw_icon(but, ICON_X, alpha, &temp, false);
}
else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index a84b8d9dcc8..44453d03ade 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -2140,7 +2140,7 @@ static float snap_v2_angle(float r[2], const float v[2], const float v_ref[2], f
normalize_v2_v2(v_unit, v);
angle = angle_signed_v2v2(v_unit, v_ref);
angle_delta = (roundf(angle / angle_snap) * angle_snap) - angle;
- rotate_m2(m2, angle_delta);
+ angle_to_mat2(m2, angle_delta);
mul_v2_m2v2(r, m2, v);
return angle + angle_delta;
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 6e973740f7c..a6f7388cb49 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1252,10 +1252,10 @@ static void copy_object_set_idnew(bContext *C)
/********************* Make Duplicates Real ************************/
/**
- * \note regarding hashing dupli-objects, skip the first member of #DupliObject.persistent_id
+ * \note regarding hashing dupli-objects when using OB_DUPLIGROUP, skip the first member of #DupliObject.persistent_id
* since its a unique index and we only want to know if the group objects are from the same dupli-group instance.
*/
-static unsigned int dupliobject_hash(const void *ptr)
+static unsigned int dupliobject_group_hash(const void *ptr)
{
const DupliObject *dob = ptr;
unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
@@ -1266,7 +1266,20 @@ static unsigned int dupliobject_hash(const void *ptr)
return hash;
}
-static bool dupliobject_cmp(const void *a_, const void *b_)
+/**
+ * \note regarding hashing dupli-objects when NOT using OB_DUPLIGROUP, include the first member of #DupliObject.persistent_id
+ * since its the index of the vertex/face the object is instantiated on and we want to identify objects on the same vertex/face.
+ */
+static unsigned int dupliobject_hash(const void *ptr)
+{
+ const DupliObject *dob = ptr;
+ unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
+ hash ^= (dob->persistent_id[0] ^ 0);
+ return hash;
+}
+
+/* Compare function that matches dupliobject_group_hash */
+static bool dupliobject_group_cmp(const void *a_, const void *b_)
{
const DupliObject *a = a_;
const DupliObject *b = b_;
@@ -1289,6 +1302,24 @@ static bool dupliobject_cmp(const void *a_, const void *b_)
return false;
}
+/* Compare function that matches dupliobject_hash */
+static bool dupliobject_cmp(const void *a_, const void *b_)
+{
+ const DupliObject *a = a_;
+ const DupliObject *b = b_;
+
+ if (a->ob != b->ob) {
+ return true;
+ }
+
+ if (a->persistent_id[0] != b->persistent_id[0]) {
+ return true;
+ }
+
+ /* matching */
+ return false;
+}
+
static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
const bool use_base_parent,
const bool use_hierarchy)
@@ -1307,13 +1338,18 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (use_hierarchy || use_base_parent) {
dupli_gh = BLI_ghash_ptr_new(__func__);
if (use_hierarchy) {
- parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
+ if (base->object->transflag & OB_DUPLIGROUP) {
+ parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
+ }
+ else {
+ parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
+ }
}
}
for (dob = lb->first; dob; dob = dob->next) {
Base *basen;
- Object *ob = BKE_object_copy(bmain, dob->ob);
+ Object *ob = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, dob->ob));
/* font duplis can have a totcol without material, we get them from parent
* should be implemented better...
@@ -1357,6 +1393,11 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
}
}
+ /* Remap new object to itself, and clear again newid pointer of orig object. */
+ BKE_libblock_relink(&ob->id);
+ set_sca_new_poins_ob(ob);
+ BKE_id_clear_newpoin(&dob->ob->id);
+
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
@@ -1375,9 +1416,14 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
* they won't be read, this is simply for a hash lookup. */
DupliObject dob_key;
dob_key.ob = ob_src_par;
- memcpy(&dob_key.persistent_id[1],
- &dob->persistent_id[1],
- sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
+ if (base->object->transflag & OB_DUPLIGROUP) {
+ memcpy(&dob_key.persistent_id[1],
+ &dob->persistent_id[1],
+ sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
+ }
+ else {
+ dob_key.persistent_id[0] = dob->persistent_id[0];
+ }
ob_dst_par = BLI_ghash_lookup(parent_gh, &dob_key);
}
@@ -1442,8 +1488,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (parent_gh)
BLI_ghash_free(parent_gh, NULL, NULL);
- copy_object_set_idnew(C);
-
free_object_duplilist(lb);
base->object->transflag &= ~OB_DUPLI;
@@ -1918,8 +1962,12 @@ void OBJECT_OT_convert(wmOperatorType *ot)
/* used below, assumes id.new is correct */
/* leaves selection of base/object unaltered */
+/* Does set ID->newid pointers. */
static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base, int dupflag)
{
+#define ID_NEW_REMAP_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; }
+#define ID_NEW_REMAP_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; }
+
Base *basen = NULL;
Material ***matarar;
Object *ob, *obn;
@@ -1931,7 +1979,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
; /* nothing? */
}
else {
- obn = BKE_object_copy(bmain, ob);
+ obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
basen = MEM_mallocN(sizeof(Base), "duplibase");
@@ -1953,20 +2001,21 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
/* duplicates using userflags */
if (dupflag & USER_DUP_ACT) {
- BKE_animdata_copy_id_action(&obn->id);
+ BKE_animdata_copy_id_action(&obn->id, true);
}
if (dupflag & USER_DUP_MAT) {
for (a = 0; a < obn->totcol; a++) {
id = (ID *)obn->mat[a];
if (id) {
- ID_NEW_US(obn->mat[a])
- else
- obn->mat[a] = BKE_material_copy(bmain, obn->mat[a]);
+ ID_NEW_REMAP_US(obn->mat[a])
+ else {
+ obn->mat[a] = ID_NEW_SET(obn->mat[a], BKE_material_copy(bmain, obn->mat[a]));
+ }
id_us_min(id);
if (dupflag & USER_DUP_ACT) {
- BKE_animdata_copy_id_action(&obn->mat[a]->id);
+ BKE_animdata_copy_id_action(&obn->mat[a]->id, true);
}
}
}
@@ -1978,9 +2027,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
switch (obn->type) {
case OB_MESH:
if (dupflag & USER_DUP_MESH) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_mesh_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_mesh_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -1988,9 +2037,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_CURVE:
if (dupflag & USER_DUP_CURVE) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_curve_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -1998,9 +2047,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_SURF:
if (dupflag & USER_DUP_SURF) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_curve_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2008,9 +2057,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_FONT:
if (dupflag & USER_DUP_FONT) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_curve_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2018,9 +2067,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_MBALL:
if (dupflag & USER_DUP_MBALL) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_mball_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_mball_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2028,9 +2077,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_LAMP:
if (dupflag & USER_DUP_LAMP) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_lamp_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_lamp_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2041,9 +2090,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
if (obn->pose)
BKE_pose_tag_recalc(bmain, obn->pose);
if (dupflag & USER_DUP_ARM) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_armature_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_armature_copy(bmain, obn->data));
BKE_pose_rebuild(obn, obn->data);
didit = 1;
}
@@ -2052,9 +2101,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_LATTICE:
if (dupflag != 0) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_lattice_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_lattice_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2062,9 +2111,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_CAMERA:
if (dupflag != 0) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_camera_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_camera_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2072,9 +2121,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_SPEAKER:
if (dupflag != 0) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_speaker_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_speaker_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2089,12 +2138,15 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
if (dupflag & USER_DUP_ACT) {
bActuator *act;
- BKE_animdata_copy_id_action((ID *)obn->data);
+ BKE_animdata_copy_id_action((ID *)obn->data, true);
if (key) {
- BKE_animdata_copy_id_action((ID *)key);
+ BKE_animdata_copy_id_action((ID *)key, true);
}
/* Update the duplicated action in the action actuators */
+ /* XXX TODO this code is all wrong! actact->act is user-refcounted (see readfile.c),
+ * and what about other ID pointers of other BGE logic bricks,
+ * and since this is object-level, why is it only ran if obdata was duplicated??? -mont29 */
for (act = obn->actuators.first; act; act = act->next) {
if (act->type == ACT_ACTION) {
bActionActuator *actact = (bActionActuator *) act->data;
@@ -2111,9 +2163,10 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
for (a = 0; a < obn->totcol; a++) {
id = (ID *)(*matarar)[a];
if (id) {
- ID_NEW_US((*matarar)[a])
- else
- (*matarar)[a] = BKE_material_copy(bmain, (*matarar)[a]);
+ ID_NEW_REMAP_US((*matarar)[a])
+ else {
+ (*matarar)[a] = ID_NEW_SET((*matarar)[a], BKE_material_copy(bmain, (*matarar)[a]));
+ }
id_us_min(id);
}
}
@@ -2122,6 +2175,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
}
}
return basen;
+
+#undef ID_NEW_REMAP_US
+#undef ID_NEW_REMAP_US2
}
/* single object duplicate, if dupflag==0, fully linked, else it uses the flags given */
@@ -2134,8 +2190,7 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag
Base *basen;
Object *ob;
- BKE_main_id_clear_newpoins(bmain);
- clear_sca_new_poins(); /* sensor/contr/act */
+ clear_sca_new_poins(); /* BGE logic */
basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
if (basen == NULL) {
@@ -2154,6 +2209,8 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag
ED_render_id_flush_update(bmain, ob->data);
}
+ BKE_main_id_clear_newpoins(bmain);
+
return basen;
}
@@ -2165,8 +2222,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
const bool linked = RNA_boolean_get(op->ptr, "linked");
int dupflag = (linked) ? 0 : U.dupflag;
- BKE_main_id_clear_newpoins(bmain);
- clear_sca_new_poins(); /* sensor/contr/act */
+ clear_sca_new_poins(); /* BGE logic */
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
@@ -2192,6 +2248,8 @@ static int duplicate_exec(bContext *C, wmOperator *op)
copy_object_set_idnew(C);
+ BKE_main_id_clear_newpoins(bmain);
+
DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -2250,8 +2308,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
base->flag = ob->flag;
/* prepare dupli */
- BKE_main_id_clear_newpoins(bmain);
- clear_sca_new_poins(); /* sensor/contr/act */
+ clear_sca_new_poins(); /* BGE logic */
basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
@@ -2277,6 +2334,8 @@ static int add_named_exec(bContext *C, wmOperator *op)
copy_object_set_idnew(C);
+ BKE_main_id_clear_newpoins(bmain);
+
DAG_relations_tag_update(bmain);
MEM_freeN(base);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index a3ff8dcb676..0bfd4b054eb 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1730,6 +1730,7 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
/**************************** Make Single User ********************************/
+/* Warning, sets ID->newid pointers of objects and groups, but does not clear them. */
static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups)
{
Base *base;
@@ -1737,18 +1738,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
Group *group, *groupn;
GroupObject *go;
- clear_sca_new_poins(); /* sensor/contr/act */
-
- /* newid may still have some trash from Outliner tree building, so clear that first to avoid errors, see T26002.
- * We have to clear whole datablocks, not only Object one may be accessed here, see T49905. */
- ListBase *lbarray[MAX_LIBARRAY];
- int a = set_listbasepointers(bmain, lbarray);
- while (a--) {
- ListBase *lb = lbarray[a];
- for (ID *id = lb->first; id; id = id->next) {
- id->newid = NULL;
- }
- }
+ clear_sca_new_poins(); /* BGE logic */
/* duplicate (must set newid) */
for (base = FIRSTBASE; base; base = base->next) {
@@ -1757,8 +1747,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
if ((base->flag & flag) == flag) {
if (!ID_IS_LINKED_DATABLOCK(ob) && ob->id.us > 1) {
/* base gets copy of object */
- obn = BKE_object_copy(bmain, ob);
- base->object = obn;
+ base->object = obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
if (copy_groups) {
if (ob->flag & OB_FROMGROUP) {
@@ -1788,8 +1777,6 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
/* duplicate groups that consist entirely of duplicated objects */
for (group = bmain->group.first; group; group = group->id.next) {
- group->id.newid = NULL;
-
if (copy_groups && group->gobject.first) {
bool all_duplicated = true;
@@ -1801,10 +1788,11 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
}
if (all_duplicated) {
- groupn = BKE_group_copy(bmain, group);
+ groupn = ID_NEW_SET(group, BKE_group_copy(bmain, group));
- for (go = groupn->gobject.first; go; go = go->next)
+ for (go = groupn->gobject.first; go; go = go->next) {
go->ob = (Object *)go->ob->id.newid;
+ }
}
}
}
@@ -1812,8 +1800,8 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
/* group pointers in scene */
BKE_scene_groups_relink(scene);
- ID_NEW(scene->camera);
- if (v3d) ID_NEW(v3d->camera);
+ ID_NEW_REMAP(scene->camera);
+ if (v3d) ID_NEW_REMAP(v3d->camera);
/* object and group pointers */
for (base = FIRSTBASE; base; base = base->next) {
@@ -1836,6 +1824,8 @@ void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
}
single_object_users(bmain, scene, NULL, OB_DONE, copy_groups);
+
+ BKE_main_id_clear_newpoins(bmain);
}
static void new_id_matar(Main *bmain, Material **matar, const int totcol)
@@ -1852,9 +1842,8 @@ static void new_id_matar(Main *bmain, Material **matar, const int totcol)
id_us_min(id);
}
else if (id->us > 1) {
- matar[a] = BKE_material_copy(bmain, matar[a]);
+ matar[a] = ID_NEW_SET(id, BKE_material_copy(bmain, matar[a]));
id_us_min(id);
- id->newid = (ID *)matar[a];
}
}
}
@@ -1882,45 +1871,46 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
switch (ob->type) {
case OB_LAMP:
- ob->data = la = BKE_lamp_copy(bmain, ob->data);
+ ob->data = la = ID_NEW_SET(ob->data, BKE_lamp_copy(bmain, ob->data));
for (a = 0; a < MAX_MTEX; a++) {
if (la->mtex[a]) {
- ID_NEW(la->mtex[a]->object);
+ ID_NEW_REMAP(la->mtex[a]->object);
}
}
break;
case OB_CAMERA:
- ob->data = BKE_camera_copy(bmain, ob->data);
+ ob->data = ID_NEW_SET(ob->data, BKE_camera_copy(bmain, ob->data));
break;
case OB_MESH:
- ob->data = me = BKE_mesh_copy(bmain, ob->data);
- if (me->key)
- BKE_animdata_copy_id_action((ID *)me->key);
+ /* Needed to remap texcomesh below. */
+ me = ob->data = ID_NEW_SET(ob->data, BKE_mesh_copy(bmain, ob->data));
+ if (me->key) /* We do not need to set me->key->id.newid here... */
+ BKE_animdata_copy_id_action((ID *)me->key, false);
break;
case OB_MBALL:
- ob->data = BKE_mball_copy(bmain, ob->data);
+ ob->data = ID_NEW_SET(ob->data, BKE_mball_copy(bmain, ob->data));
break;
case OB_CURVE:
case OB_SURF:
case OB_FONT:
- ob->data = cu = BKE_curve_copy(bmain, ob->data);
- ID_NEW(cu->bevobj);
- ID_NEW(cu->taperobj);
- if (cu->key)
- BKE_animdata_copy_id_action((ID *)cu->key);
+ ob->data = cu = ID_NEW_SET(ob->data, BKE_curve_copy(bmain, ob->data));
+ ID_NEW_REMAP(cu->bevobj);
+ ID_NEW_REMAP(cu->taperobj);
+ if (cu->key) /* We do not need to set cu->key->id.newid here... */
+ BKE_animdata_copy_id_action((ID *)cu->key, false);
break;
case OB_LATTICE:
- ob->data = lat = BKE_lattice_copy(bmain, ob->data);
- if (lat->key)
- BKE_animdata_copy_id_action((ID *)lat->key);
+ ob->data = lat = ID_NEW_SET(ob->data, BKE_lattice_copy(bmain, ob->data));
+ if (lat->key) /* We do not need to set lat->key->id.newid here... */
+ BKE_animdata_copy_id_action((ID *)lat->key, false);
break;
case OB_ARMATURE:
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- ob->data = BKE_armature_copy(bmain, ob->data);
+ ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data));
BKE_pose_rebuild(ob, ob->data);
break;
case OB_SPEAKER:
- ob->data = BKE_speaker_copy(bmain, ob->data);
+ ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data));
break;
default:
if (G.debug & G_DEBUG)
@@ -1933,17 +1923,16 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
* AnimData structure, which is not what we want.
* (sergey)
*/
- BKE_animdata_copy_id_action((ID *)ob->data);
+ BKE_animdata_copy_id_action((ID *)ob->data, false);
id_us_min(id);
- id->newid = ob->data;
}
}
}
me = bmain->mesh.first;
while (me) {
- ID_NEW(me->texcomesh);
+ ID_NEW_REMAP(me->texcomesh);
me = me->id.next;
}
}
@@ -1957,7 +1946,7 @@ static void single_object_action_users(Scene *scene, const int flag)
ob = base->object;
if (!ID_IS_LINKED_DATABLOCK(ob) && (flag == 0 || (base->flag & SELECT)) ) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- BKE_animdata_copy_id_action(&ob->id);
+ BKE_animdata_copy_id_action(&ob->id, false);
}
}
}
@@ -1976,11 +1965,11 @@ static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bo
for (a = 1; a <= ob->totcol; a++) {
ma = give_current_material(ob, a);
if (ma) {
- /* do not test for LIB_TAG_NEW: this functions guaranteed delivers single_users! */
+ /* do not test for LIB_TAG_NEW or use newid: this functions guaranteed delivers single_users! */
if (ma->id.us > 1) {
man = BKE_material_copy(bmain, ma);
- BKE_animdata_copy_id_action(&man->id);
+ BKE_animdata_copy_id_action(&man->id, false);
man->id.us = 0;
assign_material(ob, man, a, BKE_MAT_ASSIGN_USERPREF);
@@ -1991,7 +1980,7 @@ static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bo
if (tex->id.us > 1) {
id_us_min(&tex->id);
tex = BKE_texture_copy(bmain, tex);
- BKE_animdata_copy_id_action(&tex->id);
+ BKE_animdata_copy_id_action(&tex->id, false);
man->mtex[b]->tex = tex;
}
}
@@ -2017,8 +2006,8 @@ static void do_single_tex_user(Main *bmain, Tex **from)
id_us_min(&tex->id);
}
else if (tex->id.us > 1) {
- texn = BKE_texture_copy(bmain, tex);
- BKE_animdata_copy_id_action(&texn->id);
+ texn = ID_NEW_SET(tex, BKE_texture_copy(bmain, tex));
+ BKE_animdata_copy_id_action(&texn->id, false);
tex->id.newid = (ID *)texn;
id_us_min(&tex->id);
*from = texn;
@@ -2095,7 +2084,7 @@ static void single_mat_users_expand(Main *bmain)
if (ma->id.tag & LIB_TAG_NEW)
for (a = 0; a < MAX_MTEX; a++)
if (ma->mtex[a])
- ID_NEW(ma->mtex[a]->object);
+ ID_NEW_REMAP(ma->mtex[a]->object);
}
/* used for copying scenes */
@@ -2245,7 +2234,6 @@ static int make_local_exec(bContext *C, wmOperator *op)
}
tag_localizable_objects(C, mode);
- BKE_main_id_clear_newpoins(bmain);
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
@@ -2262,7 +2250,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
if (ob->id.lib == NULL) {
- ID_NEW(ob->parent);
+ ID_NEW_REMAP(ob->parent);
}
}
CTX_DATA_END;
@@ -2330,6 +2318,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
}
+ BKE_main_id_clear_newpoins(bmain);
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
@@ -2376,8 +2365,6 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
const bool copy_groups = false;
bool update_deps = false;
- BKE_main_id_clear_newpoins(bmain);
-
if (RNA_boolean_get(op->ptr, "object")) {
single_object_users(bmain, scene, v3d, flag, copy_groups);
@@ -2401,11 +2388,6 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
single_object_action_users(scene, flag);
}
- /* TODO(sergey): This should not be needed, however some tool still could rely
- * on the fact, that id->newid is kept NULL by default.
- * Need to make sure all the guys are learing newid before they're
- * using it, not after.
- */
BKE_main_id_clear_newpoins(bmain);
WM_event_add_notifier(C, NC_WINDOW, NULL);
diff --git a/source/blender/editors/object/object_warp.c b/source/blender/editors/object/object_warp.c
index 9f4da87903d..92b82e2a31b 100644
--- a/source/blender/editors/object/object_warp.c
+++ b/source/blender/editors/object/object_warp.c
@@ -53,8 +53,7 @@ static void object_warp_calc_view_matrix(float r_mat_view[4][4], float r_center_
float viewmat_roll[4][4];
/* apply the rotation offset by rolling the view */
- unit_m4(mat_offset);
- rotate_m4(mat_offset, 'Z', offset_angle);
+ axis_angle_to_mat4_single(mat_offset, 'Z', offset_angle);
mul_m4_m4m4(viewmat_roll, mat_offset, viewmat);
/* apply the view and the object matrix */
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 53434b18d06..ef2f2d36ab7 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -821,10 +821,9 @@ static float calc_overlap(StrokeCache *cache, const char symm, const char axis,
flip_v3_v3(mirror, cache->true_location, symm);
if (axis != 0) {
- float mat[4][4];
- unit_m4(mat);
- rotate_m4(mat, axis, angle);
- mul_m4_v3(mat, mirror);
+ float mat[3][3];
+ axis_angle_to_mat3_single(mat, axis, angle);
+ mul_m3_v3(mat, mirror);
}
/* distsq = len_squared_v3v3(mirror, cache->traced_location); */
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 2c678457025..d6300b74aea 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -442,6 +442,9 @@ static void id_local_cb(
if (id_make_local(bmain, tselem->id, false, false) == false) {
id_clear_lib_data(bmain, tselem->id);
}
+ else {
+ BKE_main_id_clear_newpoins(bmain);
+ }
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 3b499a81831..d1c75b01157 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -1099,8 +1099,12 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
tselem->flag &= ~TSE_CLOSED;
if (TSELEM_OPEN(tselem, soops)) {
- for (a = 0; a < tot; a++)
- outliner_add_element(soops, &te->subtree, (void *)ptr, te, TSE_RNA_PROPERTY, a);
+ for (a = 0; a < tot; a++) {
+ RNA_property_collection_lookup_int(ptr, iterprop, a, &propptr);
+ if (!(RNA_property_flag(propptr.data) & PROP_HIDDEN)) {
+ outliner_add_element(soops, &te->subtree, (void *)ptr, te, TSE_RNA_PROPERTY, a);
+ }
+ }
}
else if (tot)
te->flag |= TE_LAZY_CLOSED;
@@ -1632,11 +1636,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
outliner_free_tree(&soops->tree);
outliner_storage_cleanup(soops);
- /* clear ob id.new flags */
- for (Object *ob = mainvar->object.first; ob; ob = ob->id.next) {
- ob->id.newid = NULL;
- }
-
/* options */
if (soops->outlinevis == SO_LIBRARIES) {
Library *lib;
@@ -1822,6 +1821,8 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
outliner_sort(&soops->tree);
}
outliner_filter_tree(soops, &soops->tree);
+
+ BKE_main_id_clear_newpoins(mainvar);
}
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index b37a6740891..7ac176f82b1 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -2719,6 +2719,11 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
else {
/* Draw Pose */
if (ob->pose && ob->pose->chanbase.first) {
+ /* We can't safely draw non-updated pose, might contain NULL bone pointers... */
+ if (ob->pose->flag & POSE_RECALC) {
+ BKE_pose_rebuild(ob, arm);
+ }
+
/* drawing posemode selection indices or colors only in these cases */
if (!(base->flag & OB_FROMDUPLI)) {
if (G.f & G_PICKSEL) {
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 9184e4723a8..201209789a2 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -125,7 +125,7 @@ static bool use_depth(const bContext *C)
void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
{
RegionView3D *rv3d = ar->regiondata;
- rctf cameraborder;
+
/* setup window matrices */
if (winmat)
@@ -139,7 +139,7 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view
else
view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
- /* update utilitity matrices */
+ /* update utility matrices */
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
invert_m4_m4(rv3d->persinv, rv3d->persmat);
invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
@@ -148,6 +148,7 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view
/* store window coordinates scaling/offset */
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ rctf cameraborder;
ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false);
rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder);
@@ -1447,6 +1448,16 @@ static void view3d_draw_grid(const bContext *C, ARegion *ar)
* Also for now always assume depth is there, so we
* draw on top of it.
*/
+ /**
+ * Calculate pixel-size factor once, is used for lamps and object centers.
+ * Used by #ED_view3d_pixel_size and typically not accessed directly.
+ *
+ * \note #BKE_camera_params_compute_viewplane' also calculates a pixel-size value,
+ * passed to #RE_SetPixelSize, in ortho mode this is compatible with this value,
+ * but in perspective mode its offset by the near-clip.
+ *
+ * 'RegionView3D.pixsize' is used for viewport drawing, not rendering.
+ */
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ar->regiondata;
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 59442e89787..50aec737c8e 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -459,7 +459,7 @@ static void stitch_calculate_island_snapping(
island_stitch_data[i].num_rot_elements_neg) / totelem;
}
- rotate_m2(rotation_mat, rotation);
+ angle_to_mat2(rotation_mat, rotation);
numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
element = &state->element_map->buf[state->element_map->islandIndices[i]];
for (j = 0; j < numOfIslandUVs; j++, element++) {