[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [13252] branches/blender2.5/blender/source /blender: Operators: Join Areas

Andrea Weikert elubie at gmx.net
Tue Jan 15 21:42:00 CET 2008


Revision: 13252
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=13252
Author:   elubie
Date:     2008-01-15 21:42:00 +0100 (Tue, 15 Jan 2008)

Log Message:
-----------
Operators: Join Areas

add split area to screen manager
- RMB+ALT down on area edge activates
- mouse move interactively to area that is to be removed
- LMB to confirm, ESC to cancel
TODO: 
- notifications for interactive drawing to mark area to remove

Some fixes
- uninitialized var warning.
- exit function of operators need to run before modal handler is removed if operator is used there.
- replaced MEM_mallocN with MEM_callocN to get rid of uninitialized mem for wmOperator.
- respect return value of wm_handler_operator_call() and break out of operator handling.

Modified Paths:
--------------
    branches/blender2.5/blender/source/blender/editors/screen/screen_edit.c
    branches/blender2.5/blender/source/blender/editors/screen/screen_intern.h
    branches/blender2.5/blender/source/blender/editors/screen/screen_ops.c
    branches/blender2.5/blender/source/blender/windowmanager/intern/wm.c
    branches/blender2.5/blender/source/blender/windowmanager/intern/wm_event_system.c
    branches/blender2.5/blender/source/blender/windowmanager/intern/wm_operators.c

Modified: branches/blender2.5/blender/source/blender/editors/screen/screen_edit.c
===================================================================
--- branches/blender2.5/blender/source/blender/editors/screen/screen_edit.c	2008-01-15 20:40:52 UTC (rev 13251)
+++ branches/blender2.5/blender/source/blender/editors/screen/screen_edit.c	2008-01-15 20:42:00 UTC (rev 13252)
@@ -972,6 +972,7 @@
 {
 	
 	/* operator arguments and storage */
+	op->properties = NULL;
 	op->delta= 0;
 	op->veci.x= event->x;
 	op->veci.y= event->y;
@@ -1011,8 +1012,8 @@
 			
 		case LEFTMOUSE:
 			if(event->val==0) {
-				WM_event_remove_modal_handler(&C->window->handlers, op);
 				move_areas_exit(C, op);
+				WM_event_remove_modal_handler(&C->window->handlers, op);				
 			}
 			break;
 			
@@ -1119,18 +1120,18 @@
 		sd->max= sd->aedge->v2->vec.x;
 	}
 	
-	sd->narea= splitarea(C->window, C->screen, sd->sarea, sd->dir, fac);
-	
-	if(sd->narea==NULL) return 0;
+	sd->narea= splitarea(C->window, C->screen, sd->sarea, sd->dir, fac);
 	
+	if(sd->narea==NULL) return 0;
+	
 	sd->nedge= area_findsharededge(C->screen, sd->sarea, sd->narea);
 	
 	printf("split_area_init\n");
 	/* get newly created edge and select it */
-	select_connected_scredge(C->screen, sd->nedge);
-	
+	select_connected_scredge(C->screen, sd->nedge);
+	
 	WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0);
-	
+	
 	return 1;
 }
 
@@ -1155,6 +1156,7 @@
 static int split_area_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
 	/* operator arguments and storage */
+	op->customdata= NULL;
 	op->delta= 0;
 	op->veci.x= event->x;
 	op->veci.y= event->y;
@@ -1255,8 +1257,8 @@
 			
 		case RIGHTMOUSE:
 			if(event->val==0) { /* mouse up */
+				split_area_exit(C, op);
 				WM_event_remove_modal_handler(&C->window->handlers, op);
-				split_area_exit(C, op);
 			}
 			break;
 			
@@ -1286,3 +1288,267 @@
 	ot->poll= ED_operator_screenactive;
 	//ot->poll= ED_operator_screen_mainwinactive;
 }
+
+/* ************** join area operator ********************************************** */
+
+/* operator state vars used:  
+           op->veci   mouse coord near edge
+           op->delta  movement of edge
+
+   callbacks:
+
+   init()   find edge based on op->veci, 
+			test if the edge divides two areas, 
+			store active and nonactive area,
+            
+
+   exec()	remove active window, 
+			recalc size,
+			make nonactive window active, 
+			add notifier for redraw.
+   
+   invoke() handler gets called on Alt+RMB near edge
+            call init()
+            add handler
+
+   modal()	accept modal events while doing it
+			call exec() with active window and nonactive window
+            call exit() and remove handler when LMB confirm
+
+   exit()	cleanup, send notifier
+
+*/
+
+typedef struct sAreaJoinData
+{
+	int dir;
+	ScrArea *up;
+	ScrArea *down;
+	ScrArea *left;
+	ScrArea *right;
+	ScrArea *sa1; /* first area to be considered */
+	ScrArea *sa2; /* second area to be considered */
+	ScrArea *scr; /* designed for removal */
+
+} sAreaJoinData;
+
+
+/* validate selection inside screen, set variables OK */
+/* return 0: init failed */
+static int join_areas_init (bContext *C, wmOperator *op)
+{
+	ScrEdge *actedge= screen_find_active_scredge(C->screen, op->veci.x, op->veci.y);
+	ScrArea *sa = C->curarea;
+	ScrEdge *se;
+	sAreaJoinData* jd= NULL;
+	short val = 0;
+
+	if(actedge==NULL) return 0;
+	
+	jd = (sAreaJoinData*)MEM_callocN(sizeof (sAreaJoinData), "op_join_areas");
+	jd->dir= scredge_is_horizontal(actedge) ? 'h':'v';
+	op->customdata = jd;
+	
+	select_connected_scredge(C->screen, actedge);
+
+	jd->sa1 = screen_test_edge_area(C->screen, sa, actedge);
+	if(jd->sa1==0) return 0;
+
+	/* find directions with same edge */
+	jd->sa2= C->screen->areabase.first;
+	while(jd->sa2) {
+		if(jd->sa2 != jd->sa1) {
+			se= screen_findedge(C->screen, jd->sa2->v1, jd->sa2->v2);
+			if(actedge==se) jd->right= jd->sa2;
+			se= screen_findedge(C->screen, jd->sa2->v2, jd->sa2->v3);
+			if(actedge==se) jd->down= jd->sa2;
+			se= screen_findedge(C->screen, jd->sa2->v3, jd->sa2->v4);
+			if(actedge==se) jd->left= jd->sa2;
+			se= screen_findedge(C->screen, jd->sa2->v4, jd->sa2->v1);
+			if(actedge==se) jd->up= jd->sa2;
+		}
+		jd->sa2= jd->sa2->next;
+	}
+
+	if(jd->left) val++;
+	if(jd->up) val++;
+	if(jd->right) val++;
+	if(jd->down) val++;
+	
+	if(val==0) return 0;
+	else if(val==1) {
+		if(jd->left) {
+			jd->right = jd->sa1;
+			jd->sa2 = jd->left;
+			jd->dir = 'h';
+		}
+		else if(jd->right) {
+			jd->left = jd->sa1;
+			jd->sa2 = jd->right;
+			jd->dir = 'h';
+		}
+		else if(jd->up) {
+			jd->down = jd->sa1;
+			jd->sa2= jd->up;
+			jd->dir = 'v';
+		}
+		else if(jd->down) {
+			jd->up = jd->sa1;
+			jd->sa2 = jd->down;
+			jd->dir = 'v';
+		}
+	}
+
+	/* initial set up screen area asigned for destroying */
+	jd->scr = jd->sa2;
+
+	return 1;
+}
+
+/* apply the join of the areas (space types) */
+static int join_areas_exec(bContext *C, wmOperator *op)
+{
+	sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
+	if (!jd) return 0;
+
+	if(jd->sa2!=jd->scr) {
+		jd->sa1 = jd->sa2;
+		jd->sa2 = jd->scr;
+	}
+
+	if(jd->sa2==jd->left) {
+		jd->sa1->v1= jd->sa2->v1;
+		jd->sa1->v2= jd->sa2->v2;
+		screen_addedge(C->screen, jd->sa1->v2, jd->sa1->v3);
+		screen_addedge(C->screen, jd->sa1->v1, jd->sa1->v4);
+	}
+	else if(jd->sa2==jd->up) {
+		jd->sa1->v2= jd->sa2->v2;
+		jd->sa1->v3= jd->sa2->v3;
+		screen_addedge(C->screen, jd->sa1->v1, jd->sa1->v2);
+		screen_addedge(C->screen, jd->sa1->v3, jd->sa1->v4);
+	}
+	else if(jd->sa2==jd->right) {
+		jd->sa1->v3= jd->sa2->v3;
+		jd->sa1->v4= jd->sa2->v4;
+		screen_addedge(C->screen, jd->sa1->v2,jd-> sa1->v3);
+		screen_addedge(C->screen, jd->sa1->v1, jd->sa1->v4);
+	}
+	else if(jd->sa2==jd->down) {
+		jd->sa1->v1= jd->sa2->v1;
+		jd->sa1->v4= jd->sa2->v4;
+		screen_addedge(C->screen, jd->sa1->v1, jd->sa1->v2);
+		screen_addedge(C->screen, jd->sa1->v3, jd->sa1->v4);
+	}
+
+	if (C->curarea == jd->sa2) {
+		C->curarea = NULL;
+	}
+	screen_delarea(C->screen, jd->sa2);
+	jd->sa2 = NULL;
+	return 1;
+}
+
+/* interaction callback */
+/* return 0 = stop evaluating for next handlers */
+static int join_areas_invoke (bContext *C, wmOperator *op, wmEvent *event)
+{
+	/* operator arguments and storage */
+	op->delta= 0;
+	op->veci.x= event->x;
+	op->veci.y= event->y;
+	op->customdata = NULL;
+
+	if(0==join_areas_init(C, op)) 
+		return 1;
+	
+	/* add temp handler */
+	WM_event_add_modal_handler(&C->window->handlers, op);
+	
+	return 0;
+}
+
+static int is_inside_area(ScrArea *ar, short x, short y)
+{
+	int is_inside = 0;
+	if ( (ar->v1->vec.x < x) && (x < ar->v3->vec.x) ) {
+		if ( (y<ar->v3->vec.y) && (ar->v1->vec.y<y) ) {
+			is_inside = 1;
+		}
+	}
+	return is_inside;
+}
+
+
+/* finish operation */
+static int join_areas_exit(bContext *C, wmOperator *op)
+{
+	if (op->customdata) {
+		MEM_freeN(op->customdata);
+		op->customdata = NULL;
+	}
+
+	/* this makes sure aligned edges will result in aligned grabbing */
+	removedouble_scredges(C->screen);
+	removenotused_scredges(C->screen);
+	removenotused_scrverts(C->screen);
+
+	return 1;
+}
+
+/* modal callback while selecting area (space) that will be removed */
+/* return 0 = stop evaluating for next handlers */
+static int join_areas_modal (bContext *C, wmOperator *op, wmEvent *event)
+{
+	/* execute the events */
+	switch(event->type) {
+			
+		case MOUSEMOVE:
+			{
+				sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
+				ScrArea *sa = screen_areahascursor(C->screen, event->x, event->y);
+				if (sa && sa != jd->sa2) {
+					if (sa == jd->sa1) {
+						jd->scr = jd->sa1;
+						jd->sa1 = jd->sa2;
+						jd->sa2 = jd->scr;
+						printf("Changed area\n");
+					} 
+				}
+				break;
+			}
+		case LEFTMOUSE:
+			if(event->val==0) {
+				join_areas_exec(C, op);
+				WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0);				
+				join_areas_exit(C, op);
+				WM_event_remove_modal_handler(&C->window->handlers, op);
+			}
+			break;
+			
+		case ESCKEY:
+			op->delta= 0;
+			join_areas_exit(C, op);
+			WM_event_remove_modal_handler(&C->window->handlers, op);			
+			break;
+	}
+	return 1;
+}
+
+/* Operator for joining two areas (space types) */
+void ED_SCR_OT_join_areas(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Join area";
+	ot->idname= "ED_SCR_OT_join_areas";
+
+	/* api callbacks */
+	ot->init= join_areas_init;
+	ot->invoke= join_areas_invoke;
+	ot->modal= join_areas_modal;
+	ot->exec= join_areas_exec;
+	ot->exit= join_areas_exit;
+
+	ot->poll= ED_operator_screen_mainwinactive;
+}
+

Modified: branches/blender2.5/blender/source/blender/editors/screen/screen_intern.h
===================================================================
--- branches/blender2.5/blender/source/blender/editors/screen/screen_intern.h	2008-01-15 20:40:52 UTC (rev 13251)
+++ branches/blender2.5/blender/source/blender/editors/screen/screen_intern.h	2008-01-15 20:42:00 UTC (rev 13252)
@@ -41,8 +41,8 @@
 
 void ED_SCR_OT_move_areas(wmOperatorType *ot);
 void ED_SCR_OT_split_area(wmOperatorType *ot);
+void ED_SCR_OT_join_areas(wmOperatorType *ot);
 
-
 #endif /* ED_SCREEN_INTERN_H */
 
 

Modified: branches/blender2.5/blender/source/blender/editors/screen/screen_ops.c
===================================================================
--- branches/blender2.5/blender/source/blender/editors/screen/screen_ops.c	2008-01-15 20:40:52 UTC (rev 13251)
+++ branches/blender2.5/blender/source/blender/editors/screen/screen_ops.c	2008-01-15 20:42:00 UTC (rev 13252)
@@ -87,6 +87,7 @@
 	ADD_OPTYPE( ED_SCR_OT_move_areas );
 	ADD_OPTYPE( ED_SCR_OT_cursor_type );
 	ADD_OPTYPE( ED_SCR_OT_split_area );
+	ADD_OPTYPE( ED_SCR_OT_join_areas );
 	
 	WM_operatortypelist_append(&local_ops);
 }
@@ -97,6 +98,7 @@
 	WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_cursor_type", MOUSEMOVE, 0, 0, 0);
 	WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_move_areas", LEFTMOUSE, KM_PRESS, 0, 0);
 	WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_split_area", RIGHTMOUSE, KM_PRESS, 0, 0);
+	WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_join_areas", RIGHTMOUSE, KM_PRESS, KM_ALT, 0); 
 }
 
 

Modified: branches/blender2.5/blender/source/blender/windowmanager/intern/wm.c
===================================================================
--- branches/blender2.5/blender/source/blender/windowmanager/intern/wm.c	2008-01-15 20:40:52 UTC (rev 13251)
+++ branches/blender2.5/blender/source/blender/windowmanager/intern/wm.c	2008-01-15 20:42:00 UTC (rev 13252)
@@ -53,7 +53,7 @@
 /* called on event handling by event_system.c */

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list