Two in one:
[blender.git] / source / blender / src / editmball.c
index 17c669a4048b0b42a65ffc9f21c5e3255f8a1a9c..f92a341c2b32fca9dd63e66ebc810ee9cc74ecfb 100644 (file)
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
  */
 
+#include <string.h>
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
-#ifdef WIN32
-#include "BLI_winstuff.h"
-#endif
 #include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
-#include "BLI_editVert.h"
 
 #include "DNA_screen_types.h"
+#include "DNA_space_types.h"
 #include "DNA_meta_types.h"
 #include "DNA_object_types.h"
+#include "DNA_scene_types.h"
 #include "DNA_view3d_types.h"
 
 #include "BKE_utildefines.h"
-#include "BKE_displist.h"
+#include "BKE_depsgraph.h"
 #include "BKE_global.h"
 #include "BKE_object.h"
 
@@ -58,6 +58,8 @@
 #include "BIF_screen.h"
 #include "BIF_toolbox.h"
 #include "BIF_space.h"
+#include "BIF_editmode_undo.h"
+#include "BIF_transform.h"
 
 #include "BDR_editobject.h"
 #include "BDR_editmball.h"
@@ -65,7 +67,6 @@
 #include "BSE_edit.h"
 #include "BSE_view.h"
 
-#include "render.h"
 #include "blendef.h"
 #include "mydevice.h"
 
@@ -74,6 +75,8 @@ extern short editbutflag;
 ListBase editelems= {0, 0};
 MetaElem *lastelem;
 
+/* this function is called, when MetaBall Object is
+ * switched from object mode to edit mode */
 void make_editMball()
 {
        MetaBall *mb;
@@ -98,13 +101,16 @@ void make_editMball()
        countall();
 }
 
+/* this function is called, when MetaBall Object switched from
+ * edit mode to object mode. List od MetaElements is copied
+ * from editelems to to object->data structure (mb->elems) */
 void load_editMball()
 {
        /* load mball in object */
        MetaBall *mb;
        MetaElem *ml, *newml;
 
-       if(G.obedit==0) return;
+       if(G.obedit==NULL) return;
        
        mb= G.obedit->data;
        BLI_freelistN(&(mb->elems));
@@ -119,6 +125,7 @@ void load_editMball()
        }
 }
 
+/* add new MetaElement primitive */
 void add_primitiveMball(int dummy_argument)
 {
        MetaElem *ml;
@@ -132,13 +139,13 @@ void add_primitiveMball(int dummy_argument)
        check_editmode(OB_MBALL);
 
        /* if no obedit: new object and enter editmode */
-       if(G.obedit==0) {
-               add_object(OB_MBALL);
+       if(G.obedit==NULL) {
+               add_object_draw(OB_MBALL);
                base_init_from_view3d(BASACT, G.vd);
                G.obedit= BASACT->object;
                
-               where_is_object(G.obedit);
-
+               where_is_object(G.obedit);  // need now, for imat
+               
                make_editMball();
                setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
        }
@@ -172,44 +179,51 @@ void add_primitiveMball(int dummy_argument)
        ml->x= cent[0];
        ml->y= cent[1];
        ml->z= cent[2];
+       ml->quat[0]= 1.0;
+       ml->quat[1]= 0.0;
+       ml->quat[2]= 0.0;
+       ml->quat[3]= 0.0;
        ml->rad= 2.0;
-       ml->lay= 1;
        ml->s= 2.0;
-       ml->flag= SELECT;
-
-        switch(dummy_argument) {
-                case 1:
-                        ml->type = MB_BALL;
-                        ml->expx= ml->expy= ml->expz= 1.0;
-                        break;
-                case 2:
-                        ml->type = MB_TUBE;
-                        ml->expx= ml->expy= ml->expz= 1.0;
-                        break;
-                case 3:
-                        ml->type = MB_PLANE;
-                        ml->expx= ml->expy= ml->expz= 1.0;
-                        break;
-                case 4:
-                        ml->type = MB_ELIPSOID;
-                        ml->expx= 1.2f;
-                        ml->expy= 0.8f;
-                        ml->expz= 1.0;
-                        break;
-                case 5:
-                        ml->type = MB_CUBE;
-                        ml->expx= ml->expy= ml->expz= 1.0;
-                        break;
-                default:
-                        break;
-        }
+       ml->flag= SELECT | MB_SCALE_RAD;
+
+       switch(dummy_argument) {
+       case 1:
+               ml->type = MB_BALL;
+               ml->expx= ml->expy= ml->expz= 1.0;
+               break;
+       case 2:
+               ml->type = MB_TUBE;
+               ml->expx= ml->expy= ml->expz= 1.0;
+               break;
+       case 3:
+               ml->type = MB_PLANE;
+               ml->expx= ml->expy= ml->expz= 1.0;
+               break;
+       case 4:
+               ml->type = MB_ELIPSOID;
+               ml->expx= 1.2f;
+               ml->expy= 0.8f;
+               ml->expz= 1.0;
+               break;
+       case 5:
+               ml->type = MB_CUBE;
+               ml->expx= ml->expy= ml->expz= 1.0;
+               break;
+       default:
+               break;
+       }
        
        lastelem= ml;
        
+       DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);  // added ball can influence others
+
+       countall();     
        allqueue(REDRAWALL, 0);
-       makeDispList(G.obedit);
+       BIF_undo_push("Add MetaElem");
 }
 
+/* deselect all MetaElements */
 void deselectall_mball()
 {
        MetaElem *ml;
@@ -229,18 +243,22 @@ void deselectall_mball()
                else ml->flag |= SELECT;
                ml= ml->next;
        }
+
        allqueue(REDRAWVIEW3D, 0);
+       countall();
+       BIF_undo_push("Deselect MetaElem");
 }
 
+/* select MetaElement with mouse click (user can select radius circle or
+ * stiffness circle) */
 void mouse_mball()
 {
        static MetaElem *startelem=0;
        MetaElem *ml, *act=0;
        int a, hits;
-       /* was IGLuint ...  but is stupid */
-       GLuint buffer[MAXPICKBUF];
+       unsigned int buffer[MAXPICKBUF];
        
-       hits= selectprojektie(buffer, 0, 0, 0, 0);
+       hits= view3d_opengl_select(buffer, MAXPICKBUF, 0, 0, 0, 0);
 
        /* does startelem exist? */
        ml= editelems.first;
@@ -248,23 +266,29 @@ void mouse_mball()
                if(ml==startelem) break;
                ml= ml->next;
        }
-       if(ml==0) startelem= editelems.first;
+       if(ml==NULL) startelem= editelems.first;
        
        if(hits>0) {
                ml= startelem;
                while(ml) {
-                       /* if(base->lay & G.vd->lay) { */
                        
-                               for(a=0; a<hits; a++) {
-                                       /* index converted for gl stuff */
-                                       if(ml->selcol==buffer[ 4 * a + 3 ]) act= ml;
+                       for(a=0; a<hits; a++) {
+                               /* index converted for gl stuff */
+                               if(ml->selcol1==buffer[ 4 * a + 3 ]){
+                                       ml->flag |= MB_SCALE_RAD;
+                                       act= ml;
+                               }
+                               if(ml->selcol2==buffer[ 4 * a + 3 ]){
+                                       ml->flag &= ~MB_SCALE_RAD;
+                                       act= ml;
                                }
-                       /* } */
+
+                       }
                        
                        if(act) break;
                        
                        ml= ml->next;
-                       if(ml==0) ml= editelems.first;
+                       if(ml==NULL) ml= editelems.first;
                        if(ml==startelem) break;
                }
                if(act) {
@@ -284,9 +308,13 @@ void mouse_mball()
                        allqueue(REDRAWBUTSEDIT, 0);
                }
        }
+
+       allqueue(REDRAWBUTSOBJECT, 0);
+       countall();
        rightmouse_transform();
 }
 
+/* duplicate selected MetaElements */
 void adduplicate_mball()
 {
        MetaElem *ml, *newml;
@@ -302,10 +330,14 @@ void adduplicate_mball()
                ml= ml->prev;
        }
        
-       transform('g');
+       BIF_TransformSetUndo("Add Duplicate");
+       countall();
+       initTransform(TFM_TRANSLATION, CTX_NO_PET);
+       Transform();
        allqueue(REDRAWBUTSEDIT, 0);
 }
 
+/* Delete all selected MetaElems (not MetaBall) */
 void delete_mball()
 {
        MetaElem *ml, *next;
@@ -323,7 +355,138 @@ void delete_mball()
                ml= next;
        }
        
-       makeDispList(G.obedit);
+       DAG_scene_sort(G.scene);
+       DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWBUTSEDIT, 0);
+       countall();
+       BIF_undo_push("Delete MetaElem");
+}
+
+/* free all MetaElems from ListBase */
+void freeMetaElemlist(ListBase *lb)
+{
+       MetaElem *ml, *next;
+
+       if(lb==NULL) return;
+
+       ml= lb->first;
+       while(ml){
+               next= ml->next;
+               BLI_remlink(lb, ml);
+               MEM_freeN(ml);
+               ml= next;
+       }
+
+       lb->first= lb->last= NULL;
+       
+}
+
+/*  ************* undo for MetaBalls ************* */
+
+static void undoMball_to_editMball(void *lbv)
+{
+       ListBase *lb= lbv;
+       MetaElem *ml, *newml;
+       unsigned int nr, lastmlnr= 0;
+
+       /* we try to restore lastelem, which used in for example in button window */
+       for(ml= editelems.first; ml; ml= ml->next, lastmlnr++)
+               if(lastelem==ml) break;
+
+       freeMetaElemlist(&editelems);
+
+       /* copy 'undo' MetaElems to 'edit' MetaElems */
+       ml= lb->first;
+       while(ml){
+               newml= MEM_dupallocN(ml);
+               BLI_addtail(&editelems, newml);
+               ml= ml->next;
+       }
+       
+       for(nr=0, lastelem= editelems.first; lastelem; lastelem= lastelem->next, nr++)
+               if(nr==lastmlnr) break;
+       
+       countall();
 }
+
+static void *editMball_to_undoMball(void)
+{
+       ListBase *lb;
+       MetaElem *ml, *newml;
+
+       /* allocate memory for undo ListBase */
+       lb= MEM_callocN(sizeof(ListBase), "listbase undo");
+       lb->first= lb->last= NULL;
+       
+       /* copy contents of current ListBase to the undo ListBase */
+       ml= editelems.first;
+       while(ml){
+               newml= MEM_dupallocN(ml);
+               BLI_addtail(lb, newml);
+               ml= ml->next;
+       }
+       
+       return lb;
+}
+
+/* free undo ListBase of MetaElems */
+static void free_undoMball(void *lbv)
+{
+       ListBase *lb= lbv;
+       
+       freeMetaElemlist(lb);
+       MEM_freeN(lb);
+}
+
+/* this is undo system for MetaBalls */
+void undo_push_mball(char *name)
+{
+       undo_editmode_push(name, free_undoMball, undoMball_to_editMball, editMball_to_undoMball);
+}
+
+/* Hide selected/unselected MetaElems */
+void hide_mball(char hide)
+{
+       MetaElem *ml;
+
+       ml= editelems.first;
+
+       while(ml){
+               if(hide){
+                       if(!(ml->flag & SELECT))
+                               ml->flag |= MB_HIDE;
+               }
+               else{
+                       if(ml->flag & SELECT)
+                               ml->flag |= MB_HIDE;
+               }
+               ml= ml->next;
+       }
+
+       DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
+       allqueue(REDRAWVIEW3D, 0);
+       allqueue(REDRAWBUTSEDIT, 0);
+       countall();
+       BIF_undo_push("Hide MetaElems");
+}
+
+/* Unhide all edited MetaElems */
+void reveal_mball(void)
+{
+       MetaElem *ml;
+
+       ml= editelems.first;
+
+       while(ml){
+               ml->flag &= ~MB_HIDE;
+               ml= ml->next;
+       }
+
+       DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
+       allqueue(REDRAWVIEW3D, 0);
+       allqueue(REDRAWBUTSEDIT, 0);
+       countall();
+       BIF_undo_push("Unhide MetaElems");
+}
+