WorkSpace: object-mode switching support
When changing workspaces, existing object-mode data is freed the new workspaces mode is entered (if possible).
This commit is contained in:
parent
5b857102fa
commit
4ab002bca3
Notes:
blender-bot
2023-02-14 06:12:23 +01:00
Referenced by issue #54124, Switching workspaces fails to sync object modes Referenced by issue #54027, Object wrongly in edit mode when changing workspaces with different active objects
|
@ -155,6 +155,12 @@ void ED_object_sculptmode_exit_ex(
|
|||
struct WorkSpace *workspace, struct Scene *scene, struct Object *ob);
|
||||
void ED_object_sculptmode_exit(struct bContext *C);
|
||||
|
||||
bool ED_object_mode_generic_enter(
|
||||
struct bContext *C, eObjectMode object_mode);
|
||||
void ED_object_mode_generic_exit(
|
||||
const struct EvaluationContext *eval_ctx,
|
||||
struct WorkSpace *workspace, struct Scene *scene, struct Object *ob);
|
||||
|
||||
void ED_object_location_from_view(struct bContext *C, float loc[3]);
|
||||
void ED_object_rotation_from_view(struct bContext *C, float rot[3], const char align_axis);
|
||||
void ED_object_base_init_transform(struct bContext *C, struct Base *base, const float loc[3], const float rot[3]);
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
#include "BKE_mball.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_pointcache.h"
|
||||
#include "BKE_property.h"
|
||||
#include "BKE_sca.h"
|
||||
|
@ -2068,6 +2069,55 @@ void OBJECT_OT_game_physics_copy(struct wmOperatorType *ot)
|
|||
|
||||
/* generic utility function */
|
||||
|
||||
bool ED_object_mode_generic_enter(
|
||||
struct bContext *C, eObjectMode object_mode)
|
||||
{
|
||||
WorkSpace *workspace = CTX_wm_workspace(C);
|
||||
if (workspace->object_mode == object_mode) {
|
||||
return true;
|
||||
}
|
||||
wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_mode_set", false);
|
||||
PointerRNA ptr;
|
||||
WM_operator_properties_create_ptr(&ptr, ot);
|
||||
RNA_enum_set(&ptr, "mode", object_mode);
|
||||
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
|
||||
WM_operator_properties_free(&ptr);
|
||||
return (workspace->object_mode == object_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use for changing works-paces or changing active object.
|
||||
* Caller can check #OB_MODE_ALL_MODE_DATA to test if this needs to be run.
|
||||
*/
|
||||
void ED_object_mode_generic_exit(
|
||||
const struct EvaluationContext *eval_ctx,
|
||||
struct WorkSpace *workspace, struct Scene *scene, struct Object *ob)
|
||||
{
|
||||
if (eval_ctx->object_mode & OB_MODE_EDIT) {
|
||||
if (BKE_object_is_in_editmode(ob)) {
|
||||
ED_object_editmode_exit_ex(NULL, workspace, scene, ob, EM_FREEDATA);
|
||||
}
|
||||
}
|
||||
else if (eval_ctx->object_mode & OB_MODE_VERTEX_PAINT) {
|
||||
if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT)) {
|
||||
ED_object_vpaintmode_exit_ex(workspace, ob);
|
||||
}
|
||||
}
|
||||
else if (eval_ctx->object_mode & OB_MODE_WEIGHT_PAINT) {
|
||||
if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT)) {
|
||||
ED_object_wpaintmode_exit_ex(workspace, ob);
|
||||
}
|
||||
}
|
||||
else if (eval_ctx->object_mode & OB_MODE_SCULPT) {
|
||||
if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
|
||||
ED_object_sculptmode_exit_ex(eval_ctx, workspace, scene, ob);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BLI_assert((eval_ctx->object_mode & OB_MODE_ALL_MODE_DATA) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool ED_object_editmode_calc_active_center(Object *obedit, const bool select_only, float r_center[3])
|
||||
{
|
||||
switch (obedit->type) {
|
||||
|
|
|
@ -146,40 +146,12 @@ void ED_object_base_activate(bContext *C, Base *base)
|
|||
*
|
||||
* Not correct because it's possible other work-spaces use these.
|
||||
* although that's a corner case. */
|
||||
if (workspace->object_mode & OB_MODE_EDIT) {
|
||||
FOREACH_OBJECT(view_layer, ob) {
|
||||
if (ob != obact) {
|
||||
if (BKE_object_is_in_editmode(ob)) {
|
||||
ED_object_editmode_exit_ex(NULL, workspace, scene, ob, EM_FREEDATA);
|
||||
}
|
||||
}
|
||||
}
|
||||
FOREACH_OBJECT_END;
|
||||
}
|
||||
else if (workspace->object_mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_SCULPT)) {
|
||||
if (workspace->object_mode & OB_MODE_ALL_MODE_DATA) {
|
||||
EvaluationContext eval_ctx;
|
||||
CTX_data_eval_ctx(C, &eval_ctx);
|
||||
FOREACH_OBJECT(view_layer, ob) {
|
||||
if (ob != obact) {
|
||||
if (ob->sculpt) {
|
||||
switch (ob->sculpt->mode_type) {
|
||||
case OB_MODE_VERTEX_PAINT:
|
||||
{
|
||||
ED_object_vpaintmode_exit_ex(workspace, ob);
|
||||
break;
|
||||
}
|
||||
case OB_MODE_WEIGHT_PAINT:
|
||||
{
|
||||
ED_object_wpaintmode_exit_ex(workspace, ob);
|
||||
break;
|
||||
}
|
||||
case OB_MODE_SCULPT:
|
||||
{
|
||||
ED_object_sculptmode_exit_ex(&eval_ctx, workspace, scene, ob);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ED_object_mode_generic_exit(&eval_ctx, workspace, scene, ob);
|
||||
}
|
||||
}
|
||||
FOREACH_OBJECT_END;
|
||||
|
@ -191,12 +163,7 @@ void ED_object_base_activate(bContext *C, Base *base)
|
|||
view_layer->basact = base;
|
||||
|
||||
if (reset == false) {
|
||||
wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_mode_set", false);
|
||||
PointerRNA ptr;
|
||||
WM_operator_properties_create_ptr(&ptr, ot);
|
||||
RNA_enum_set(&ptr, "mode", object_mode);
|
||||
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
|
||||
WM_operator_properties_free(&ptr);
|
||||
ED_object_mode_generic_enter(C, object_mode);
|
||||
}
|
||||
|
||||
if (base) {
|
||||
|
|
|
@ -93,7 +93,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
|
|||
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
|
||||
ViewLayer *view_layer = BKE_view_layer_from_workspace_get(scene, workspace);
|
||||
Object *obact = (view_layer && view_layer->basact) ? view_layer->basact->object : NULL;
|
||||
Object *obedit = BKE_workspace_edit_object(workspace, scene);
|
||||
|
||||
if (CTX_data_dir(member)) {
|
||||
CTX_data_dir_set(result, screen_context_dir);
|
||||
|
@ -204,6 +203,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
|
|||
return 1;
|
||||
}
|
||||
else if (CTX_data_equals(member, "visible_bones") || CTX_data_equals(member, "editable_bones")) {
|
||||
Object *obedit = BKE_workspace_edit_object(workspace, scene);
|
||||
bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL;
|
||||
EditBone *ebone, *flipbone = NULL;
|
||||
const bool editable_bones = CTX_data_equals(member, "editable_bones");
|
||||
|
@ -246,6 +246,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
|
|||
}
|
||||
}
|
||||
else if (CTX_data_equals(member, "selected_bones") || CTX_data_equals(member, "selected_editable_bones")) {
|
||||
Object *obedit = BKE_workspace_edit_object(workspace, scene);
|
||||
bArmature *arm = (obedit && obedit->type == OB_ARMATURE) ? obedit->data : NULL;
|
||||
EditBone *ebone, *flipbone = NULL;
|
||||
const bool selected_editable_bones = CTX_data_equals(member, "selected_editable_bones");
|
||||
|
@ -367,6 +368,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
|
|||
}
|
||||
else if (CTX_data_equals(member, "edit_object")) {
|
||||
/* convenience for now, 1 object per scene in editmode */
|
||||
Object *obedit = BKE_workspace_edit_object(workspace, scene);
|
||||
if (obedit)
|
||||
CTX_data_id_pointer_set(result, &obedit->id);
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
|
@ -166,6 +168,41 @@ bool ED_workspace_change(
|
|||
BLI_assert(BKE_workspace_layout_screen_get(layout_new) == screen_new);
|
||||
|
||||
if (screen_new) {
|
||||
bool object_mode_set = false;
|
||||
|
||||
/* Handle object mode switching */
|
||||
if ((workspace_old->object_mode != OB_MODE_OBJECT) ||
|
||||
(workspace_new->object_mode != OB_MODE_OBJECT))
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer_old = BKE_workspace_view_layer_get(workspace_old, scene);
|
||||
ViewLayer *view_layer_new = BKE_workspace_view_layer_get(workspace_new, scene);
|
||||
Object *obact_old = OBACT(view_layer_old);
|
||||
Object *obact_new = OBACT(view_layer_new);
|
||||
|
||||
if ((workspace_old->object_mode == workspace_new->object_mode) &&
|
||||
(obact_old == obact_new))
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
if (workspace_old->object_mode & OB_MODE_ALL_MODE_DATA) {
|
||||
if (obact_old) {
|
||||
eObjectMode object_mode = workspace_old->object_mode;
|
||||
EvaluationContext eval_ctx;
|
||||
CTX_data_eval_ctx(C, &eval_ctx);
|
||||
ED_object_mode_generic_exit(&eval_ctx, workspace_old, scene, obact_old);
|
||||
/* weak, set it back so it's used when activating again. */
|
||||
workspace_old->object_mode = object_mode;
|
||||
}
|
||||
}
|
||||
|
||||
if (workspace_new->object_mode != OB_MODE_OBJECT) {
|
||||
object_mode_set = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WM_window_set_active_layout(win, workspace_new, layout_new);
|
||||
WM_window_set_active_workspace(win, workspace_new);
|
||||
|
||||
|
@ -179,6 +216,12 @@ bool ED_workspace_change(
|
|||
WM_toolsystem_unlink(C, workspace_old);
|
||||
WM_toolsystem_link(C, workspace_new);
|
||||
|
||||
if (object_mode_set) {
|
||||
eObjectMode object_mode = workspace_new->object_mode;
|
||||
workspace_new->object_mode = OB_MODE_OBJECT;
|
||||
ED_object_mode_generic_enter(C, object_mode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,4 +46,7 @@ typedef enum eObjectMode {
|
|||
/* Any mode that uses Object.sculpt. */
|
||||
#define OB_MODE_ALL_SCULPT (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)
|
||||
|
||||
/* Any mode that has data we need to free when switching modes, see: #ED_object_mode_generic_exit */
|
||||
#define OB_MODE_ALL_MODE_DATA (OB_MODE_EDIT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_SCULPT)
|
||||
|
||||
#endif /* __DNA_OBJECT_ENUMS_H__ */
|
||||
|
|
Loading…
Reference in New Issue