2.5 / Area management
* Add Area Swap: hold alt and drag with LMB from either actionzone. Release LMB on area you want to swap with. I added a matching cute cursor for this (and to make it a politically delicate issue, it's white on black). Note, there are still some error totblocks that I haven't been able to track down properly yet, so that's still a bit WIP.
This commit is contained in:
@@ -139,6 +139,7 @@ void BKE_spacetypes_free(void); /* only for quitting blender */
|
||||
/* spacedata */
|
||||
void BKE_spacedata_freelist(ListBase *lb);
|
||||
void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2);
|
||||
void BKE_spacedata_copyfirst(ListBase *lb1, ListBase *lb2);
|
||||
|
||||
/* area/regions */
|
||||
struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar);
|
||||
|
||||
@@ -214,6 +214,27 @@ void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2)
|
||||
}
|
||||
}
|
||||
|
||||
/* lb1 should be empty */
|
||||
void BKE_spacedata_copyfirst(ListBase *lb1, ListBase *lb2)
|
||||
{
|
||||
SpaceLink *sl;
|
||||
|
||||
lb1->first= lb2->last= NULL; /* to be sure */
|
||||
|
||||
sl= lb2->first;
|
||||
if(sl) {
|
||||
SpaceType *st= BKE_spacetype_from_id(sl->spacetype);
|
||||
|
||||
if(st && st->duplicate) {
|
||||
SpaceLink *slnew= st->duplicate(sl);
|
||||
|
||||
BLI_addtail(lb1, slnew);
|
||||
|
||||
region_copylist(st, &slnew->regionbase, &sl->regionbase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* not region itself */
|
||||
void BKE_area_region_free(SpaceType *st, ARegion *ar)
|
||||
{
|
||||
|
||||
@@ -73,6 +73,7 @@ void ED_area_do_refresh(struct bContext *C, ScrArea *sa);
|
||||
void ED_area_headerprint(ScrArea *sa, const char *str);
|
||||
void ED_area_newspace(struct bContext *C, ScrArea *sa, int type);
|
||||
void ED_area_prevspace(struct bContext *C);
|
||||
void ED_area_swapspace(struct bContext *C, ScrArea *sa1, ScrArea *sa2);
|
||||
|
||||
/* screens */
|
||||
void ED_screens_initialize(struct wmWindowManager *wm);
|
||||
|
||||
@@ -660,12 +660,15 @@ void area_copy_data(ScrArea *sa1, ScrArea *sa2, int swap_space)
|
||||
sa1->spacetype= sa2->spacetype;
|
||||
sa1->butspacetype= sa2->butspacetype;
|
||||
|
||||
if(swap_space) {
|
||||
if(swap_space == 1) {
|
||||
SWAP(ListBase, sa1->spacedata, sa2->spacedata);
|
||||
/* exception: ensure preview is reset */
|
||||
// if(sa1->spacetype==SPACE_VIEW3D)
|
||||
// XXX BIF_view3d_previewrender_free(sa1->spacedata.first);
|
||||
}
|
||||
else if (swap_space == 2) {
|
||||
BKE_spacedata_copylist(&sa1->spacedata, &sa2->spacedata);
|
||||
}
|
||||
else {
|
||||
BKE_spacedata_freelist(&sa1->spacedata);
|
||||
BKE_spacedata_copylist(&sa1->spacedata, &sa2->spacedata);
|
||||
@@ -674,10 +677,12 @@ void area_copy_data(ScrArea *sa1, ScrArea *sa2, int swap_space)
|
||||
/* Note; SPACE_EMPTY is possible on new screens */
|
||||
|
||||
/* regions */
|
||||
st= BKE_spacetype_from_id(sa1->spacetype);
|
||||
for(ar= sa1->regionbase.first; ar; ar= ar->next)
|
||||
BKE_area_region_free(st, ar);
|
||||
BLI_freelistN(&sa1->regionbase);
|
||||
if(swap_space<2) {
|
||||
st= BKE_spacetype_from_id(sa1->spacetype);
|
||||
for(ar= sa1->regionbase.first; ar; ar= ar->next)
|
||||
BKE_area_region_free(st, ar);
|
||||
BLI_freelistN(&sa1->regionbase);
|
||||
}
|
||||
|
||||
st= BKE_spacetype_from_id(sa2->spacetype);
|
||||
for(ar= sa2->regionbase.first; ar; ar= ar->next) {
|
||||
@@ -695,6 +700,38 @@ void area_copy_data(ScrArea *sa1, ScrArea *sa2, int swap_space)
|
||||
|
||||
/* *********** Space switching code *********** */
|
||||
|
||||
void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2)
|
||||
{
|
||||
SpaceType *st;
|
||||
SpaceLink *sl;
|
||||
SpaceLink *slold;
|
||||
ScrArea *tmp= MEM_callocN(sizeof(ScrArea), "addscrarea");
|
||||
|
||||
ED_area_exit(C, sa1);
|
||||
ED_area_exit(C, sa2);
|
||||
|
||||
tmp->spacetype= sa1->spacetype;
|
||||
tmp->butspacetype= sa1->butspacetype;
|
||||
BKE_spacedata_copyfirst(&tmp->spacedata, &sa1->spacedata);
|
||||
|
||||
area_copy_data(tmp, sa1, 2);
|
||||
area_copy_data(sa1, sa2, 0);
|
||||
area_copy_data(sa2, tmp, 0);
|
||||
ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa1);
|
||||
ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa2);
|
||||
|
||||
BKE_screen_area_free(tmp);
|
||||
MEM_freeN(tmp);
|
||||
|
||||
/* tell WM to refresh, cursor types etc */
|
||||
WM_event_add_mousemove(C);
|
||||
|
||||
ED_area_tag_redraw(sa1);
|
||||
ED_area_tag_refresh(sa1);
|
||||
ED_area_tag_redraw(sa2);
|
||||
ED_area_tag_refresh(sa2);
|
||||
}
|
||||
|
||||
void ED_area_newspace(bContext *C, ScrArea *sa, int type)
|
||||
{
|
||||
if(sa->spacetype != type) {
|
||||
|
||||
@@ -438,14 +438,122 @@ void SCREEN_OT_actionzone(wmOperatorType *ot)
|
||||
RNA_def_int(ot->srna, "modifier", 0, 0, 2, "modifier", "modifier state", 0, 2);
|
||||
}
|
||||
|
||||
/* ************** swap area operator *********************************** */
|
||||
|
||||
/* operator state vars used:
|
||||
sa1 start area
|
||||
sa2 area to swap with
|
||||
|
||||
functions:
|
||||
|
||||
init() set custom data for operator, based on actionzone event custom data
|
||||
|
||||
cancel() cancel the operator
|
||||
|
||||
exit() cleanup, send notifier
|
||||
|
||||
callbacks:
|
||||
|
||||
invoke() gets called on shift+lmb drag in actionzone
|
||||
call init(), add handler
|
||||
|
||||
modal() accept modal events while doing it
|
||||
|
||||
*/
|
||||
|
||||
typedef struct sAreaSwapData {
|
||||
ScrArea *sa1, *sa2;
|
||||
} sAreaSwapData;
|
||||
|
||||
static int area_swap_init(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
sAreaSwapData *sd= NULL;
|
||||
sActionzoneData *sad= event->customdata;
|
||||
|
||||
if(sad==NULL || sad->sa1==NULL)
|
||||
return 0;
|
||||
|
||||
sd= MEM_callocN(sizeof(sAreaSwapData), "sAreaSwapData");
|
||||
sd->sa1= sad->sa1;
|
||||
sd->sa2= sad->sa2;
|
||||
op->customdata= sd;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void area_swap_exit(bContext *C, wmOperator *op)
|
||||
{
|
||||
if(op->customdata)
|
||||
MEM_freeN(op->customdata);
|
||||
op->customdata= NULL;
|
||||
}
|
||||
|
||||
static int area_swap_cancel(bContext *C, wmOperator *op)
|
||||
{
|
||||
area_swap_exit(C, op);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
static int area_swap_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
|
||||
if(!area_swap_init(C, op, event))
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
|
||||
/* add modal handler */
|
||||
WM_cursor_modal(CTX_wm_window(C), BC_SWAPAREA_CURSOR);
|
||||
WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
|
||||
}
|
||||
|
||||
static int area_swap_modal(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
sActionzoneData *sad= op->customdata;
|
||||
|
||||
switch(event->type) {
|
||||
case MOUSEMOVE:
|
||||
/* second area, for join */
|
||||
sad->sa2= screen_areahascursor(CTX_wm_screen(C), event->x, event->y);
|
||||
break;
|
||||
case LEFTMOUSE: /* release LMB */
|
||||
if(event->val==0) {
|
||||
if(sad->sa1 == sad->sa2) {
|
||||
|
||||
return area_swap_cancel(C, op);
|
||||
}
|
||||
ED_area_swapspace(C, sad->sa1, sad->sa2);
|
||||
|
||||
area_swap_exit(C, op);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
break;
|
||||
|
||||
case ESCKEY:
|
||||
return area_swap_cancel(C, op);
|
||||
}
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
void SCREEN_OT_area_swap(wmOperatorType *ot)
|
||||
{
|
||||
ot->name= "Swap areas";
|
||||
ot->idname= "SCREEN_OT_area_swap";
|
||||
|
||||
ot->invoke= area_swap_invoke;
|
||||
ot->modal= area_swap_modal;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
}
|
||||
|
||||
/* *********** Duplicate area as new window operator ****************** */
|
||||
|
||||
|
||||
/* operator callback */
|
||||
/* (ton) removed attempt to merge ripped area with another, don't think this is desired functionality.
|
||||
conventions: 'atomic' and 'dont think for user' :) */
|
||||
static int screen_area_dupli_new_op(bContext *C, wmOperator *op, wmEvent *event)
|
||||
static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
wmWindow *newwin, *win;
|
||||
bScreen *newsc, *sc;
|
||||
@@ -454,15 +562,17 @@ static int screen_area_dupli_new_op(bContext *C, wmOperator *op, wmEvent *event)
|
||||
sActionzoneData *sad= event->customdata;
|
||||
|
||||
if(sad==NULL)
|
||||
return OPERATOR_CANCELLED;
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
|
||||
win= CTX_wm_window(C);
|
||||
sc= CTX_wm_screen(C);
|
||||
sa= sad->sa1;
|
||||
|
||||
/* poll() checks area context, but we don't accept full-area windows */
|
||||
if(sc->full != SCREENNORMAL)
|
||||
if(sc->full != SCREENNORMAL) {
|
||||
actionzone_exit(C, op);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* adds window to WM */
|
||||
rect= sa->totrct;
|
||||
@@ -478,16 +588,18 @@ static int screen_area_dupli_new_op(bContext *C, wmOperator *op, wmEvent *event)
|
||||
|
||||
/* screen, areas init */
|
||||
WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
|
||||
|
||||
actionzone_exit(C, op);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void SCREEN_OT_area_dupli_new(wmOperatorType *ot)
|
||||
void SCREEN_OT_area_dupli(wmOperatorType *ot)
|
||||
{
|
||||
ot->name= "Duplicate Area into New Window";
|
||||
ot->idname= "SCREEN_OT_area_dupli_new";
|
||||
ot->idname= "SCREEN_OT_area_dupli";
|
||||
|
||||
ot->invoke= screen_area_dupli_new_op;
|
||||
ot->invoke= area_dupli_invoke;
|
||||
ot->poll= ED_operator_areaactive;
|
||||
}
|
||||
|
||||
@@ -2308,7 +2420,8 @@ void ED_operatortypes_screen(void)
|
||||
WM_operatortype_append(SCREEN_OT_area_move);
|
||||
WM_operatortype_append(SCREEN_OT_area_split);
|
||||
WM_operatortype_append(SCREEN_OT_area_join);
|
||||
WM_operatortype_append(SCREEN_OT_area_dupli_new);
|
||||
WM_operatortype_append(SCREEN_OT_area_dupli);
|
||||
WM_operatortype_append(SCREEN_OT_area_swap);
|
||||
WM_operatortype_append(SCREEN_OT_region_split);
|
||||
WM_operatortype_append(SCREEN_OT_region_foursplit);
|
||||
WM_operatortype_append(SCREEN_OT_region_flip);
|
||||
@@ -2339,16 +2452,16 @@ void ED_keymap_screen(wmWindowManager *wm)
|
||||
/* standard timers */
|
||||
WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", TIMER0, KM_ANY, KM_ANY, 0);
|
||||
|
||||
/*WM_keymap_verify_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, 0, 0);*/
|
||||
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "modifier", 0);
|
||||
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "modifier", 1);
|
||||
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "modifier", 2);
|
||||
|
||||
/* screen tools */
|
||||
WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0);
|
||||
WM_keymap_verify_item(keymap, "SCREEN_OT_area_split", EVT_ACTIONZONE, 0, KM_ANY, 0);
|
||||
WM_keymap_verify_item(keymap, "SCREEN_OT_area_join", EVT_ACTIONZONE, 0, KM_ANY, 0);
|
||||
WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli_new", EVT_ACTIONZONE, 0, KM_ANY, 0);
|
||||
WM_keymap_verify_item(keymap, "SCREEN_OT_area_split", EVT_ACTIONZONE, 0, 0, 0);
|
||||
WM_keymap_verify_item(keymap, "SCREEN_OT_area_join", EVT_ACTIONZONE, 0, 0, 0);
|
||||
WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli", EVT_ACTIONZONE, 0, KM_SHIFT, 0);
|
||||
WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE, 0, KM_ALT, 0);
|
||||
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1);
|
||||
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1);
|
||||
WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", UPARROWKEY, KM_PRESS, KM_CTRL, 0);
|
||||
|
||||
@@ -935,6 +935,38 @@ BlenderCursor[BC_EYEDROPPER_CURSOR]=&EyedropperCursor;
|
||||
|
||||
END_CURSOR_BLOCK
|
||||
|
||||
/********************** Swap Area Cursor ***********************/
|
||||
BEGIN_CURSOR_BLOCK
|
||||
static char swap_sbm[]={
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0xff, 0x07,
|
||||
0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07,
|
||||
0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07,
|
||||
};
|
||||
|
||||
static char swap_smsk[]={
|
||||
0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff,
|
||||
0xc0, 0xff, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0x07,
|
||||
0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07,
|
||||
};
|
||||
|
||||
static BCursor SwapCursor = {
|
||||
/*small*/
|
||||
swap_sbm, swap_smsk,
|
||||
16, 16,
|
||||
8, 8,
|
||||
/*big*/
|
||||
NULL, NULL,
|
||||
32,32,
|
||||
15, 15,
|
||||
/*color*/
|
||||
BC_YELLOW, BC_BLUE
|
||||
};
|
||||
|
||||
BlenderCursor[BC_SWAPAREA_CURSOR]=&SwapCursor;
|
||||
|
||||
END_CURSOR_BLOCK
|
||||
/********************** Put the cursors in the array ***********************/
|
||||
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ enum {
|
||||
BC_NS_SCROLLCURSOR,
|
||||
BC_EW_SCROLLCURSOR,
|
||||
BC_EYEDROPPER_CURSOR,
|
||||
BC_SWAPAREA_CURSOR,
|
||||
/* --- ALWAYS LAST ----- */
|
||||
BC_NUMCURSORS,
|
||||
};
|
||||
|
||||
@@ -52,13 +52,11 @@ void wm_window_set_title (wmWindow *win, char *title);
|
||||
void wm_window_swap_buffers (wmWindow *win);
|
||||
|
||||
wmWindow *wm_window_copy (bContext *C, wmWindow *winorig);
|
||||
wmWindow *wm_window_rip (bContext *C, wmWindow *winorig);
|
||||
|
||||
void wm_window_testbreak (void);
|
||||
|
||||
/* *************** window operators ************** */
|
||||
int wm_window_duplicate_op (bContext *C, wmOperator *op);
|
||||
int wm_window_rip_op (bContext *C, wmOperator *op, struct wmEvent *event);
|
||||
int wm_window_fullscreen_toggle_op(bContext *C, wmOperator *op);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user