[Bf-blender-cvs] [e1178266e71] blender2.8: Workspace: support reordering of workspaces from RMB menu.

Brecht Van Lommel noreply at git.blender.org
Tue Sep 11 12:44:39 CEST 2018


Commit: e1178266e713ae7184fc60c3ecb93d42d8b28a53
Author: Brecht Van Lommel
Date:   Thu Aug 23 16:13:52 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBe1178266e713ae7184fc60c3ecb93d42d8b28a53

Workspace: support reordering of workspaces from RMB menu.

Drag and drop will follow later, it's a bit complicated to make this work
reliable in the current UI code.

===================================================================

M	release/scripts/startup/bl_ui/space_topbar.py
M	source/blender/blenkernel/BKE_library.h
M	source/blender/blenkernel/intern/library.c
M	source/blender/blenloader/intern/versioning_defaults.c
M	source/blender/editors/interface/interface_templates.c
M	source/blender/editors/screen/workspace_edit.c
M	source/blender/makesdna/DNA_workspace_types.h

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index 06bdc9ee59e..ce4a1ad8c74 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -613,6 +613,11 @@ class TOPBAR_MT_workspace_menu(Menu):
         if len(bpy.data.workspaces) > 1:
             layout.operator("workspace.delete", text="Delete")
 
+        layout.separator()
+
+        layout.operator("workspace.reorder_to_front", text="Reorder to Front")
+        layout.operator("workspace.reorder_to_back", text="Reorder to Back")
+
 
 class TOPBAR_PT_active_tool(Panel):
     bl_space_type = 'PROPERTIES'
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 50447e02fe5..050e9368a43 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -214,6 +214,9 @@ void BKE_id_tag_clear_atomic(struct ID *id, int tag);
 
 bool BKE_id_is_in_gobal_main(struct ID *id);
 
+void BKE_id_ordered_list(struct ListBase *ordered_lb, const struct ListBase *lb);
+void BKE_id_reorder(const struct ListBase *lb, struct ID *id, struct ID *relative, bool after);
+
 /* use when "" is given to new_id() */
 #define ID_FALLBACK_NAME N_("Untitled")
 
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 04ebaaf80b7..84aa75abc72 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -2596,3 +2596,98 @@ bool BKE_id_is_in_gobal_main(ID *id)
 	/* We do not want to fail when id is NULL here, even though this is a bit strange behavior... */
 	return (id == NULL || BLI_findindex(which_libbase(G_MAIN, GS(id->name)), id) != -1);
 }
+
+/************************* Datablock order in UI **************************/
+
+static int *id_order_get(ID *id)
+{
+	/* Only for workspace tabs currently. */
+	switch (GS(id->name)) {
+		case ID_WS:
+			return &((WorkSpace *)id)->order;
+		default:
+			return NULL;
+	}
+}
+
+static int id_order_compare(const void *a, const void *b)
+{
+	ID *id_a = ((LinkData *)a)->data;
+	ID *id_b = ((LinkData *)b)->data;
+
+	int *order_a = id_order_get(id_a);
+	int *order_b = id_order_get(id_b);
+
+	if (order_a && order_b) {
+		if (*order_a < *order_b) {
+			return -1;
+		}
+		else if (*order_a > *order_b) {
+			return 1;
+		}
+	}
+
+	return strcmp(id_a->name, id_b->name);
+}
+
+/**
+ * Returns ordered list of datablocks for display in the UI.
+ * Result is list of LinkData of IDs that must be freed.
+ */
+void BKE_id_ordered_list(ListBase *ordered_lb, const ListBase *lb)
+{
+	BLI_listbase_clear(ordered_lb);
+
+	for (ID *id = lb->first; id; id = id->next) {
+		BLI_addtail(ordered_lb, BLI_genericNodeN(id));
+	}
+
+	BLI_listbase_sort(ordered_lb, id_order_compare);
+
+	int num = 0;
+	for (LinkData *link = ordered_lb->first; link; link = link->next) {
+		int *order = id_order_get(link->data);
+		if (order) {
+			*order = num++;
+		}
+	}
+}
+
+/**
+ * Reorder ID in the list, before or after the "relative" ID.
+ */
+void BKE_id_reorder(const ListBase *lb, ID *id, ID *relative, bool after)
+{
+	int *id_order = id_order_get(id);
+	int relative_order;
+
+	if (relative) {
+		relative_order = *id_order_get(relative);
+	}
+	else {
+		relative_order = (after) ? BLI_listbase_count(lb) : 0;
+	}
+
+	if (after) {
+		/* Insert after. */
+		for (ID *other = lb->first; other; other = other->next) {
+			int *order = id_order_get(other);
+			if (*order > relative_order) {
+				(*order)++;
+			}
+		}
+
+		*id_order = relative_order + 1;
+	}
+	else {
+		/* Insert before. */
+		for (ID *other = lb->first; other; other = other->next) {
+			int *order = id_order_get(other);
+			if (*order < relative_order) {
+				(*order)--;
+			}
+		}
+
+		*id_order = relative_order - 1;
+	}
+}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 1fd82d01cf5..abbc8f4c4a4 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -79,20 +79,46 @@ void BLO_update_defaults_startup_blend(Main *bmain)
 	for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
 		const char *name = workspace->id.name + 2;
 
-		if (STREQ(name, "2D Animation")) {
-			workspace->object_mode = OB_MODE_GPENCIL_PAINT;
-		}
-		if (STREQ(name, "3D Animation")) {
-			workspace->object_mode = OB_MODE_POSE;
-		}
-		else if (STREQ(name, "Texture Paint")) {
-			workspace->object_mode = OB_MODE_TEXTURE_PAINT;
+		if (STREQ(name, "Modeling")) {
+			workspace->order = 0;
 		}
 		else if (STREQ(name, "Sculpting")) {
 			workspace->object_mode = OB_MODE_SCULPT;
+			workspace->order = 1;
 		}
 		else if (STREQ(name, "UV Editing")) {
 			workspace->object_mode = OB_MODE_EDIT;
+			workspace->order = 2;
+		}
+		else if (STREQ(name, "Texture Paint")) {
+			workspace->object_mode = OB_MODE_TEXTURE_PAINT;
+			workspace->order = 3;
+		}
+		else if (STREQ(name, "Shading")) {
+			workspace->order = 4;
+		}
+		else if (STREQ(name, "3D Animation")) {
+			workspace->object_mode = OB_MODE_POSE;
+			workspace->order = 5;
+		}
+		else if (STREQ(name, "Rendering")) {
+			workspace->order = 6;
+		}
+		else if (STREQ(name, "Compositing")) {
+			workspace->order = 7;
+		}
+		else if (STREQ(name, "2D Animation")) {
+			workspace->object_mode = OB_MODE_GPENCIL_PAINT;
+			workspace->order = 8;
+		}
+		else if (STREQ(name, "Video Editing")) {
+			workspace->order = 9;
+		}
+		else if (STREQ(name, "Motion Tracking")) {
+			workspace->order = 10;
+		}
+		else if (STREQ(name, "Scripting")) {
+			workspace->order = 11;
 		}
 	}
 
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index a72d1df019a..f39f26e0d00 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -850,7 +850,11 @@ static void template_ID_tabs(
 	uiBlock *block = uiLayoutGetBlock(layout);
 	uiStyle *style = UI_style_get_dpi();
 
-	for (ID *id = template->idlb->first; id; id = id->next) {
+	ListBase ordered;
+	BKE_id_ordered_list(&ordered, template->idlb);
+
+	for (LinkData *link = ordered.first; link; link = link->next) {
+		ID *id = link->data;
 		const int name_width = UI_fontstyle_string_width(&style->widgetlabel, id->name + 2);
 		const int but_width = name_width + UI_UNIT_X;
 
@@ -860,11 +864,14 @@ static void template_ID_tabs(
 		        sizeof(id->name) - 2, 0.0f, 0.0f, "");
 		UI_but_funcN_set(&tab->but, template_ID_set_property_cb, MEM_dupallocN(template), id);
 		tab->but.custom_data = (void *)id;
+		tab->but.dragpoin = id;
 		tab->menu = mt;
 
 		UI_but_drawflag_enable(&tab->but, but_align);
 	}
 
+	BLI_freelistN(&ordered);
+
 	if (flag & UI_ID_ADD_NEW) {
 		const bool editable = RNA_property_editable(&template->ptr, template->prop);
 		uiBut *but;
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index 77fc20a98a5..db60bfc9fb6 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -272,6 +272,11 @@ static WorkSpace *workspace_context_get(bContext *C)
 	return WM_window_get_active_workspace(win);
 }
 
+static bool workspace_context_poll(bContext *C)
+{
+	return workspace_context_get(C) != NULL;
+}
+
 static int workspace_new_exec(bContext *C, wmOperator *UNUSED(op))
 {
 	Main *bmain = CTX_data_main(C);
@@ -293,8 +298,8 @@ static void WORKSPACE_OT_duplicate(wmOperatorType *ot)
 	ot->idname = "WORKSPACE_OT_duplicate";
 
 	/* api callbacks */
+	ot->poll = workspace_context_poll;
 	ot->exec = workspace_new_exec;
-	ot->poll = WM_operator_winactive;
 }
 
 static int workspace_delete_exec(bContext *C, wmOperator *UNUSED(op))
@@ -313,6 +318,7 @@ static void WORKSPACE_OT_delete(wmOperatorType *ot)
 	ot->idname = "WORKSPACE_OT_delete";
 
 	/* api callbacks */
+	ot->poll = workspace_context_poll;
 	ot->exec = workspace_delete_exec;
 }
 
@@ -519,12 +525,60 @@ static void WORKSPACE_OT_add_menu(wmOperatorType *ot)
 	ot->invoke = workspace_add_invoke;
 }
 
+static int workspace_reorder_to_back_exec(bContext *C, wmOperator *UNUSED(op))
+{
+	Main *bmain = CTX_data_main(C);
+	WorkSpace *workspace = workspace_context_get(C);
+
+	BKE_id_reorder(&bmain->workspaces, &workspace->id, NULL, true);
+	WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+	return OPERATOR_INTERFACE;
+}
+
+static void WORKSPACE_OT_reorder_to_back(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Workspace Reorder to Back";
+	ot->description = "Reorder workspace to be first in the list";
+	ot->idname = "WORKSPACE_OT_reorder_to_back";
+
+	/* api callbacks */
+	ot->poll = workspace_context_poll;
+	ot->exec = workspace_reorder_to_back_exec;
+}
+
+static int workspace_reorder_to_front_exec(bContext *C, wmOperator *UNUSED(op))
+{
+	Main *bmain = CTX_data_main(C);
+	WorkSpace *workspace = workspace_context_get(C);
+
+	BKE_id_reorder(&bmain->workspaces, &workspace->id, NULL, false);
+	WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+	return OPERATOR_INTERFACE;
+}
+
+static void WORKSPACE_OT_reorder_to_front(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Workspace Reorder to Front";
+	ot->description = "Reorder workspace to be first in the list";
+	ot->idname = "WORKSPACE_OT_reorder_to_front";
+
+	/* api callbacks */
+	ot->poll = workspace_context_poll;
+	ot->exec = workspace_reorder_to_front_exec;
+}
+
 void ED_operatortypes_workspace(void)
 {
 	WM_operatortype_append(WORKSPACE_OT_duplicate);
 	WM_operatortype_append(WORKSPACE_OT_delete);
 	WM_operatortype_append(WORKSPACE_OT_add_menu);
 	WM_operatortype_append(WORKSPACE_OT_append_activate);
+	WM_operatortype_append(WORKSPACE_OT_reorder_to_back);
+	WM_operatortype_append(WORKSPACE_OT_reorder_to_front);
 }
 
 /** \} Workspace Operators */
diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h
index fd56c246c96..ad047a85c18 100644
--- a/source/blender/makesdna/DNA_workspace_types.h
+++ b/source/blender/makesdna/DNA_workspace_types.h
@@ -14

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list