EditMesh refactory + undo recode
The changelog is very long... it's on the web too: http://www.blender3d.org/cms/Mesh_editing_rewrite.425.0.html EditMesh refactor notes (user) **** New selection modes When entering Edit Mode for a Mesh, you now have the choice for three selection modes. These are shown as icons in the 3D header (hotkey is being searched for!). - Vertex Select Select vertices as usual, fully compatible with how previous version work - Edge Select Vertices are not drawn anymore, and selections happen by default on the edges. It is a true edge select, meaning that you can select three out of four edges in a face, without automatic having the 4th edge selected. - Face Select Instead of vertices, now selection 'points' are drawn in the face centers. Selected faces also get a colored outline, like for edges. This also is true face select, for each face individual regardless selection status of its vertices or edges. While holding SHIFT, and press a selection mode, you can also combine the above choices. Now selection becomes mixed, and will behave as expected. For example; in Edge+Face select mode, selecting the 4 edges of a face will select the face too. The selection modes and optional drawing modes (like transparant faces, normals, or solid drawing) all work together. All of Blender's mesh editing tools now react to the correct selection mode as well. Most noticeable it's in: **** Extrude Extruding in Edge or Face Select mode allows much more precise control over what's extruded and what should be excluded. Try for example a checker pattern selection, and extrude it. New is the fixed translation when faces are extruded. This always follows the (averaged) face normal(s) of the old face(s), enabling much easier working in 3D views . A single 'G' (Grab) or 'R' (Rotate) or 'S' (Scale) will change transform modus as usual. **** Other things to note - Hiding edges/faces will also behave different based on Select Mode. - while editing, normals of faces are updated always now - Border select (BKEY) has 2 different rules for edges; when one edge is fully inside of the border, it will only select edges that are fully inside. Otherwise it selects each edge intersecting with the border. - in face mode, adding vertices, edges or a circle is invisible... - "Add monkey" now works as a normal primitive (rotated and on 3d cursor) - Mesh undo was fully recoded, hopefully solving issues now with Vertex Keys and Groups - Going in and out of editmode was fully recoded. Especially on larger models you'll notice substantial speed gain. **** Todo Add 'FaceSelect mode' functionality in EditMode, including zbuffered selection, display and editing of UV texture. EditMesh refactor notes (coder) **** Usage of flags in general The "->f" flags are reserved for the editmesh.c and editmesh_lib.c core functions. Actually only selection status is there now. The "->f1" and "->f2" flags are free to use. They're available in vertex/edge/face structs. Since they're free, check carefully when calling other functions that use these flags... for example extrude() or subdivide() use them. **** Selection flags EditVert: eve->f & SELECT EditEdge: eed->f & SELECT EditFace: efa->f & SELECT - Selection is only possible when not-hidden! - Selection flags are always up-to-date, BUT: if selection mode >= SELECT_EDGE vertex selection flags can be incorrect if selection mode == SELECT_FACE vertex/edge selection flags can be incorrect This because of shared vertices or edges. - use for selecting vertices: eve->f &= SELECT - use for selecting edges always: void EM_select_edge(eed, 1) // 1 = select, 0 = deselect - use for selecting faces always: void EM_select_face(efa, 1) // 1 = select, 0 = deselect - To set the 'f' flags in all of the data: void EM_set_flag_all(int flag); void EM_clear_flag_all(int flag); - the old faceselectedOR() and faceselectedAND() are still there, but only to be used for evaluating its vertices **** Code hints for handling selection If the selectmode is 'face'; vertex or edge selections need to be flushed upward. Same is true for 'edge' selection mode. This means that you'll have to keep track of all selections while coding... selecting the four vertices in a face doesn't automatically select the face anymore. However, by using the above calls, at least selections flush downward (to vertex level). You then can call: void EM_selectmode_flush(void); Which flushes selections back upward, based on the selectmode setting. This function does the following: - if selectmode 'vertex': select edges/faces based on its selected vertices - if selectmode 'edge': select faces based its selected edges This works fine in nice controlled situations. However, only changing the vertex selections then still doesn't select a face in face mode! If you really can't avoid only working with vertex selections, you can use this call: void EM_select_flush(void); Now selection is flushed upward regardless current selectmode. That can be destructive for special cases however, like checkerboard selected faces. So use this only when you know everything else was deselected (or deselect it). Example: adding primitives. **** Hide flags EditVert: eve->h EditEdge: eed->h EditFace: efa->h - all hide flags are always up-to-date - hidden vertices/edges/faces are always deselected. so when you operate on selection only, there's no need to check for hide flag. **** Unified undo for editmode New file: editmode_undo.h A pretty nice function pointer handler style undo. Just code three functions, and your undo will fly! The c file has a good reference. Also note that the old undo system has been replaced. It currently uses minimal dependencies on Meshes themselves (no abuse of going in/out editmode), and is restricted nicely to editmode functions. **** Going in/out editmode As speedup now all vertices/faces/edges are allocated in three big chunks. In vertices/faces/edges now tags are set to denote such data cannot be freed. ALso the hashtable (lookup) for edges uses no mallocs at all anymore, but is part of the EditEdge itself.
This commit is contained in:
@@ -87,7 +87,8 @@ void RE_jitterate2(float *jit1, float *jit2, int num, float rad2);
|
||||
/* exotic.c */
|
||||
void load_editMesh(void);
|
||||
void make_editMesh(void);
|
||||
void free_editMesh(void);
|
||||
struct EditMesh;
|
||||
void free_editMesh(struct EditMesh *);
|
||||
void free_editArmature(void);
|
||||
void docentre_new(void);
|
||||
int saveover(char *str);
|
||||
|
||||
@@ -63,16 +63,6 @@ struct bSoundListener;
|
||||
struct BMF_Font;
|
||||
struct EditMesh;
|
||||
|
||||
#define UNDO_MAX 64
|
||||
#define UNDO_EDIT_MAX 64
|
||||
|
||||
typedef struct UndoBufferEdit {
|
||||
|
||||
void *datablock;
|
||||
char name[64];
|
||||
|
||||
} UndoBufferEdit;
|
||||
|
||||
|
||||
typedef struct Global {
|
||||
|
||||
@@ -153,14 +143,6 @@ typedef struct Global {
|
||||
short special1, special2;
|
||||
|
||||
int flags;
|
||||
|
||||
/* editmode undo - written by intrr, ported by Det. Thorn */
|
||||
struct UndoBufferEdit undo_edit[UNDO_EDIT_MAX+1];/* need one more for undoing first undo */
|
||||
int undo_edit_level; /* index of last undo buffer created */
|
||||
int undo_edit_highest; /* index of highest undo buffer in use */
|
||||
void *undo_last_data; /* pointer to last datablock edited */
|
||||
void (*undo_clear)(void); /* pointer to function to free the undo data */
|
||||
|
||||
|
||||
} Global;
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ void RE_jitterate2(float *jit1, float *jit2, int num, float rad2){}
|
||||
/* exotic.c */
|
||||
void load_editMesh(void){}
|
||||
void make_editMesh(void){}
|
||||
void free_editMesh(void){}
|
||||
void free_editMesh(struct EditMesh *em){}
|
||||
void docentre_new(void){}
|
||||
int saveover(char *str){ return 0;}
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ static void clear_global(void)
|
||||
|
||||
if (G.obedit) {
|
||||
freeNurblist(&editNurb);
|
||||
free_editMesh();
|
||||
free_editMesh(G.editMesh);
|
||||
free_editText();
|
||||
free_editArmature();
|
||||
}
|
||||
|
||||
@@ -307,13 +307,7 @@ static void read_stl_mesh_binary(char *str)
|
||||
me->totvert = totvert;
|
||||
|
||||
mesh_add_normals_flags(me);
|
||||
/*
|
||||
G.obedit= ob;
|
||||
make_editMesh();
|
||||
load_editMesh();
|
||||
free_editMesh();
|
||||
G.obedit= 0;
|
||||
*/
|
||||
|
||||
tex_space_mesh(me);
|
||||
}
|
||||
waitcursor(1);
|
||||
@@ -479,13 +473,7 @@ static void read_stl_mesh_ascii(char *str)
|
||||
free(vertdata);
|
||||
|
||||
mesh_add_normals_flags(me);
|
||||
/*
|
||||
G.obedit= ob;
|
||||
make_editMesh();
|
||||
load_editMesh();
|
||||
free_editMesh();
|
||||
G.obedit= 0;
|
||||
*/
|
||||
|
||||
tex_space_mesh(me);
|
||||
waitcursor(1);
|
||||
}
|
||||
@@ -707,7 +695,7 @@ static void read_videoscape_mesh(char *str)
|
||||
G.obedit= ob;
|
||||
make_editMesh();
|
||||
load_editMesh();
|
||||
free_editMesh();
|
||||
free_editMesh(G.editMesh);
|
||||
G.obedit= 0;
|
||||
tex_space_mesh(me);
|
||||
waitcursor(1);
|
||||
@@ -892,7 +880,7 @@ static void read_radiogour(char *str)
|
||||
G.obedit= ob;
|
||||
make_editMesh();
|
||||
load_editMesh();
|
||||
free_editMesh();
|
||||
free_editMesh(G.editMesh);
|
||||
|
||||
G.obedit= 0;
|
||||
tex_space_mesh(me);
|
||||
@@ -2273,13 +2261,6 @@ static void displist_to_mesh(DispList *dlfirst)
|
||||
dl= dl->next;
|
||||
}
|
||||
|
||||
//G.obedit= ob;
|
||||
//make_editMesh();
|
||||
//load_editMesh();
|
||||
//free_editMesh();
|
||||
|
||||
//G.obedit= 0;
|
||||
|
||||
mesh_add_normals_flags(me);
|
||||
tex_space_mesh(me);
|
||||
|
||||
@@ -3764,7 +3745,7 @@ static void dxf_read_point(int noob) {
|
||||
G.obedit= ob;
|
||||
make_editMesh();
|
||||
load_editMesh();
|
||||
free_editMesh();
|
||||
free_editMesh(G.editMesh);
|
||||
waitcursor(1); /* patch yah... */
|
||||
|
||||
G.obedit= 0;
|
||||
@@ -3789,7 +3770,7 @@ static void dxf_close_line(void)
|
||||
G.obedit= linehold;
|
||||
make_editMesh();
|
||||
load_editMesh();
|
||||
free_editMesh();
|
||||
free_editMesh(G.editMesh);
|
||||
waitcursor(1); /* patch yah... */
|
||||
|
||||
G.obedit= 0;
|
||||
@@ -3938,7 +3919,7 @@ static void dxf_close_2dpoly(void)
|
||||
G.obedit= p2dhold;
|
||||
make_editMesh();
|
||||
load_editMesh();
|
||||
free_editMesh();
|
||||
free_editMesh(G.editMesh);
|
||||
waitcursor(1); /* patch yah... */
|
||||
|
||||
G.obedit= 0;
|
||||
@@ -4219,7 +4200,7 @@ static void dxf_read_polyline(int noob) {
|
||||
G.obedit= ob;
|
||||
make_editMesh();
|
||||
load_editMesh();
|
||||
free_editMesh();
|
||||
free_editMesh(G.editMesh);
|
||||
waitcursor(1); /* patch yah... */
|
||||
G.obedit= 0;
|
||||
}
|
||||
@@ -4241,7 +4222,7 @@ static void dxf_close_3dface(void)
|
||||
G.obedit= f3dhold;
|
||||
make_editMesh();
|
||||
load_editMesh();
|
||||
free_editMesh();
|
||||
free_editMesh(G.editMesh);
|
||||
waitcursor(1); /* patch yah... */
|
||||
G.obedit= 0;
|
||||
tex_space_mesh(f3dhold->data);
|
||||
@@ -4614,7 +4595,7 @@ static void dxf_read(char *filename)
|
||||
G.obedit= ob;
|
||||
make_editMesh();
|
||||
load_editMesh();
|
||||
free_editMesh();
|
||||
free_editMesh(G.editMesh);
|
||||
waitcursor(1); /* patch yah... */
|
||||
G.obedit= 0;
|
||||
tex_space_mesh(ob->data);
|
||||
|
||||
@@ -128,7 +128,6 @@ void free_scene(Scene *sce)
|
||||
BLI_freelistN(&sce->base);
|
||||
free_editing(sce->ed);
|
||||
if(sce->radio) MEM_freeN(sce->radio);
|
||||
if(sce->fcam) MEM_freeN(sce->fcam);
|
||||
sce->radio= 0;
|
||||
|
||||
BPY_free_scriptlink(&sce->scriptlink);
|
||||
@@ -150,7 +149,8 @@ Scene *add_scene(char *name)
|
||||
|
||||
sce= alloc_libblock(&G.main->scene, ID_SCE, name);
|
||||
sce->lay= 1;
|
||||
|
||||
sce->selectmode= SCE_SELECT_VERTEX;
|
||||
|
||||
sce->r.mode= R_GAMMA;
|
||||
sce->r.cfra= 1;
|
||||
sce->r.sfra= 1;
|
||||
|
||||
@@ -44,23 +44,30 @@ typedef struct EditVert
|
||||
float no[3];
|
||||
float co[3];
|
||||
short xs, ys;
|
||||
unsigned char f, h, f1, hash;
|
||||
int totweight; /* __NLA */
|
||||
unsigned char f, h, f1, f2;
|
||||
short fast; /* only 0 or 1, for editmesh_fastmalloc */
|
||||
short totweight; /* __NLA */
|
||||
int hash;
|
||||
struct MDeformWeight *dw; /* __NLA */
|
||||
int keyindex; /* lets hold on to this so that maybe we can have a hope
|
||||
* of restoring any key information if the number/order
|
||||
* of verts change.
|
||||
*/
|
||||
|
||||
int keyindex; /* original index #, for restoring key information */
|
||||
} EditVert;
|
||||
|
||||
struct EditEdge;
|
||||
|
||||
typedef struct HashEdge {
|
||||
struct EditEdge *eed;
|
||||
struct HashEdge *next;
|
||||
} HashEdge;
|
||||
|
||||
typedef struct EditEdge
|
||||
{
|
||||
struct EditEdge *next, *prev;
|
||||
struct EditVert *v1, *v2, *vn;
|
||||
short f, f1;
|
||||
unsigned char h, dir, seam;
|
||||
short f1, f2; /* short, f1 is (ab)used in subdiv */
|
||||
unsigned char f, h, dir, seam;
|
||||
float crease;
|
||||
int fast; /* only 0 or 1, for editmesh_fastmalloc */
|
||||
HashEdge hash;
|
||||
} EditEdge;
|
||||
|
||||
typedef struct EditFace
|
||||
@@ -68,15 +75,24 @@ typedef struct EditFace
|
||||
struct EditFace *next, *prev;
|
||||
struct EditVert *v1, *v2, *v3, *v4;
|
||||
struct EditEdge *e1, *e2, *e3, *e4;
|
||||
float n[3];
|
||||
float n[3], cent[3];
|
||||
short xs, ys; /* selection */
|
||||
struct TFace tf; /* a copy of original tface. */
|
||||
unsigned char mat_nr, flag;
|
||||
unsigned char f, f1;
|
||||
unsigned char f, f1, h, puno;
|
||||
short fast; /* only 0 or 1, for editmesh_fastmalloc */
|
||||
} EditFace;
|
||||
|
||||
typedef struct EditMesh
|
||||
{
|
||||
ListBase verts, edges, faces;
|
||||
HashEdge *hashedgetab;
|
||||
|
||||
/* this is for the editmesh_fastmalloc */
|
||||
EditVert *allverts, *curvert;
|
||||
EditEdge *alledges, *curedge;
|
||||
EditFace *allfaces, *curface;
|
||||
|
||||
} EditMesh;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2439,7 +2439,6 @@ static void direct_link_scene(FileData *fd, Scene *sce)
|
||||
sce->basact= newdataadr(fd, sce->basact);
|
||||
|
||||
sce->radio= newdataadr(fd, sce->radio);
|
||||
sce->fcam= newdataadr(fd, sce->fcam);
|
||||
|
||||
sce->r.avicodecdata = newdataadr(fd, sce->r.avicodecdata);
|
||||
if (sce->r.avicodecdata) {
|
||||
@@ -4471,6 +4470,13 @@ static void do_versions(Main *main)
|
||||
}
|
||||
}
|
||||
}
|
||||
if(main->versionfile <= 234) {
|
||||
Scene *sce;
|
||||
|
||||
for (sce= main->scene.first; sce; sce= sce->id.next) {
|
||||
if(sce->selectmode==0) sce->selectmode= SCE_SELECT_VERTEX;
|
||||
}
|
||||
}
|
||||
|
||||
/* don't forget to set version number in blender.c! */
|
||||
}
|
||||
|
||||
@@ -1078,7 +1078,6 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
|
||||
}
|
||||
|
||||
writestruct(wd, DATA, "Radio", 1, sce->radio);
|
||||
writestruct(wd, DATA, "FreeCamera", 1, sce->fcam);
|
||||
|
||||
ed= sce->ed;
|
||||
if(ed) {
|
||||
|
||||
@@ -49,12 +49,13 @@ void init_draw_rects(void);
|
||||
void helpline(float *vec);
|
||||
void drawaxes(float size);
|
||||
void drawcamera(struct Object *ob);
|
||||
|
||||
void calc_mesh_facedots_ext(void);
|
||||
void calc_lattverts_ext(void);
|
||||
void calc_meshverts(void);
|
||||
void calc_meshverts_ext(void);
|
||||
void calc_meshverts_ext_f2(void);
|
||||
void calc_nurbverts_ext(void);
|
||||
void tekenvertices(short sel);
|
||||
void drawcircball(float *cent, float rad, float tmat[][4]);
|
||||
void get_local_bounds(struct Object *ob, float *centre, float *size);
|
||||
void draw_object(struct Base *base);
|
||||
|
||||
@@ -93,8 +93,6 @@ int bezt_compare (const void *e1, const void *e2);
|
||||
void curve_changes_other_objects(struct Object *ob);
|
||||
|
||||
extern void undo_push_curve(char *name);
|
||||
extern void undo_clear_curve(void);
|
||||
|
||||
|
||||
#endif /* BDR_EDITCURVE_H */
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#ifndef BIF_EDITMESH_H
|
||||
#define BIF_EDITMESH_H
|
||||
|
||||
struct EditMesh;
|
||||
struct EditFace;
|
||||
struct EditEdge;
|
||||
struct EditVert;
|
||||
@@ -45,16 +46,11 @@ struct View3D;
|
||||
/* ******************* editmesh.c */
|
||||
extern void make_editMesh(void);
|
||||
extern void load_editMesh(void);
|
||||
extern void free_editMesh(void);
|
||||
extern void free_editMesh(struct EditMesh *);
|
||||
extern void remake_editMesh(void);
|
||||
|
||||
/* Editmesh Undo code */
|
||||
void undo_free_mesh(struct Mesh *me);
|
||||
void undo_push_mesh(char *name);
|
||||
void undo_pop_mesh(int steps);
|
||||
void undo_redo_mesh(void);
|
||||
void undo_clear_mesh(void);
|
||||
void undo_menu_mesh(void);
|
||||
extern void undo_push_mesh(char *name);
|
||||
|
||||
extern void separatemenu(void);
|
||||
extern void separate_mesh(void);
|
||||
@@ -67,6 +63,20 @@ extern void addvert_mesh(void);
|
||||
extern void addedgeface_mesh(void);
|
||||
|
||||
/* ******************* editmesh_lib.c */
|
||||
|
||||
extern void EM_set_flag_all(int flag);
|
||||
extern void EM_clear_flag_all(int flag);
|
||||
|
||||
extern void EM_select_face(struct EditFace *efa, int sel);
|
||||
extern void EM_select_edge(struct EditEdge *eed, int sel);
|
||||
|
||||
extern void EM_select_flush(void); // vertices to edges/faces (exception!)
|
||||
extern void EM_selectmode_set(void); // when mode changes
|
||||
extern void EM_selectmode_flush(void); // when selection changes
|
||||
|
||||
extern int EM_nfaces_selected(void);
|
||||
extern int EM_nvertices_selected(void);
|
||||
|
||||
extern int faceselectedAND(struct EditFace *efa, int flag);
|
||||
extern void recalc_editnormals(void);
|
||||
extern void flip_editnormals(void);
|
||||
|
||||
55
source/blender/include/BIF_editmode_undo.h
Normal file
55
source/blender/include/BIF_editmode_undo.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* $Id:
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version. The Blender
|
||||
* Foundation also sells licenses for use in proprietary software under
|
||||
* the Blender License. See http://www.blender.org/BL/ for information
|
||||
* about this.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BIF_EDITMODE_UNDO_H
|
||||
#define BIF_EDITMODE_UNDO_H
|
||||
|
||||
// Add this in your local code:
|
||||
|
||||
extern void undo_editmode_push(char *name,
|
||||
void (*freedata)(void *), // pointer to function freeing data
|
||||
void (*to_editmode)(void *), // data to editmode conversion
|
||||
void *(*from_editmode)(void)); // editmode to data conversion
|
||||
|
||||
|
||||
// Further exported for UI is:
|
||||
|
||||
struct uiBlock;
|
||||
|
||||
extern void undo_editmode_step(int step); // undo and redo
|
||||
extern void undo_editmode_clear(void); // free & clear all data
|
||||
extern void undo_editmode_menu(void); // history menu
|
||||
extern struct uiBlock *editmode_undohistorymenu(void *arg_unused);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -161,9 +161,9 @@ typedef enum {
|
||||
ICON_GHOST,
|
||||
ICON_SHARPCURVE,
|
||||
ICON_SMOOTHCURVE,
|
||||
ICON_BLANK23,
|
||||
ICON_BLANK24,
|
||||
ICON_BLANK25,
|
||||
ICON_VERTEXSEL,
|
||||
ICON_EDGESEL,
|
||||
ICON_FACESEL,
|
||||
ICON_BLANK26,
|
||||
ICON_BPIBFOLDER_X,
|
||||
ICON_BPIBFOLDERGREY,
|
||||
@@ -328,6 +328,7 @@ typedef enum {
|
||||
|
||||
} BIFColorID;
|
||||
|
||||
/* XXX WARNING: this is saved in file, so do not change order! */
|
||||
enum {
|
||||
TH_AUTO, /* for buttons, to signal automatic color assignment */
|
||||
|
||||
@@ -381,8 +382,13 @@ enum {
|
||||
TH_EDGE_FACESEL,
|
||||
TH_FACE,
|
||||
TH_FACE_SELECT,
|
||||
TH_NORMAL
|
||||
TH_NORMAL,
|
||||
TH_FACE_DOT,
|
||||
TH_FACEDOT_SIZE,
|
||||
|
||||
};
|
||||
/* XXX WARNING: previous is saved in file, so do not change order! */
|
||||
|
||||
|
||||
/* specific defines per space should have higher define values */
|
||||
|
||||
|
||||
@@ -232,22 +232,25 @@
|
||||
#define B_AUTOKEY 139
|
||||
#define B_SCENELOCK 140
|
||||
#define B_LOCALVIEW 141
|
||||
#define B_U_CAPSLOCK 142
|
||||
#define B_U_CAPSLOCK 142
|
||||
#define B_EDITMODE 143
|
||||
#define B_VPAINT 144
|
||||
#define B_FACESEL 145
|
||||
#define B_VIEWBUT 146
|
||||
#define B_PERSP 147
|
||||
#define B_PROPTOOL 148
|
||||
#define B_VIEWRENDER 149
|
||||
#define B_VIEWRENDER 149
|
||||
#define B_VIEWTRANS 150
|
||||
#define B_VIEWZOOM 151
|
||||
#define B_STARTGAME 152
|
||||
#define B_POSEMODE 153
|
||||
#define B_TEXTUREPAINT 154
|
||||
#define B_TEXTUREPAINT 154
|
||||
#define B_WPAINT 155
|
||||
#define B_MODESELECT 156
|
||||
#define B_MODESELECT 156
|
||||
#define B_AROUND 157
|
||||
#define B_SEL_VERT 158
|
||||
#define B_SEL_EDGE 159
|
||||
#define B_SEL_FACE 160
|
||||
|
||||
/* IPO: 200 */
|
||||
#define B_IPOHOME 201
|
||||
|
||||
@@ -58,12 +58,9 @@ extern struct EditFace *addfacelist(struct EditVert *v1, struct EditVert *v2, st
|
||||
extern struct EditEdge *findedgelist(struct EditVert *v1, struct EditVert *v2);
|
||||
|
||||
/* ******************* editmesh_add.c */
|
||||
extern void adduplicateflag(int flag);
|
||||
|
||||
|
||||
/* ******************* editmesh_lib.c */
|
||||
extern int editmesh_nfaces_selected(void);
|
||||
extern int editmesh_nvertices_selected(void);
|
||||
|
||||
extern int faceselectedOR(EditFace *efa, int flag);
|
||||
extern int faceselectedAND(EditFace *efa, int flag);
|
||||
@@ -72,15 +69,19 @@ extern int exist_face(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4);
|
||||
extern void flipface(EditFace *efa); // flips for normal direction
|
||||
extern int compareface(EditFace *vl1, EditFace *vl2);
|
||||
|
||||
extern short extrudeflag_vert(short flag);
|
||||
extern short extrudeflag(short flag);
|
||||
|
||||
extern void adduplicateflag(int flag);
|
||||
extern void delfaceflag(int flag);
|
||||
extern short extrudeflag(short flag,short type);
|
||||
|
||||
extern void rotateflag(short flag, float *cent, float rotmat[][3]);
|
||||
extern void translateflag(short flag, float *vec);
|
||||
|
||||
extern float convex(float *v1, float *v2, float *v3, float *v4);
|
||||
|
||||
/* ******************* editmesh_mods.c */
|
||||
extern EditEdge *findnearestedge();
|
||||
extern EditEdge *findnearestedge(short *dist);
|
||||
|
||||
/* ******************* editmesh_tools.c */
|
||||
|
||||
|
||||
@@ -99,6 +99,8 @@ typedef struct MSticky {
|
||||
|
||||
/* flag (mface) */
|
||||
#define ME_SMOOTH 1
|
||||
#define ME_FACE_SEL 2
|
||||
/* flag ME_HIDE is used here too */
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,6 @@ extern "C" {
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_scriptlink_types.h"
|
||||
|
||||
struct FreeCamera;
|
||||
struct Radio;
|
||||
struct Object;
|
||||
struct World;
|
||||
@@ -250,10 +249,9 @@ typedef struct Scene {
|
||||
|
||||
float cursor[3];
|
||||
unsigned int lay;
|
||||
short selectmode, pad;
|
||||
int pad1;
|
||||
|
||||
/* some realtime vars */
|
||||
struct FreeCamera *fcam; /* old, can be removed (ton) */
|
||||
|
||||
void *ed;
|
||||
struct Radio *radio;
|
||||
void *sumohandle;
|
||||
@@ -365,6 +363,11 @@ typedef struct Scene {
|
||||
/* sce->flag */
|
||||
#define SCE_ADDSCENAME 1
|
||||
|
||||
/* sce->selectmode */
|
||||
#define SCE_SELECT_VERTEX 1
|
||||
#define SCE_SELECT_EDGE 2
|
||||
#define SCE_SELECT_FACE 4
|
||||
|
||||
/* return flag next_object function */
|
||||
#define F_START 0
|
||||
#define F_SCENE 1
|
||||
|
||||
@@ -63,7 +63,7 @@ typedef struct ThemeUI {
|
||||
|
||||
} ThemeUI;
|
||||
|
||||
// try to put them all in one, if needed a spacial struct can be created as well
|
||||
// try to put them all in one, if needed a special struct can be created as well
|
||||
// for example later on, when we introduce wire colors for ob types or so...
|
||||
typedef struct ThemeSpace {
|
||||
char back[4];
|
||||
@@ -83,11 +83,12 @@ typedef struct ThemeSpace {
|
||||
char vertex[4], vertex_select[4];
|
||||
char edge[4], edge_select[4];
|
||||
char edge_seam[4], edge_facesel[4];
|
||||
char face[4], face_select[4];
|
||||
char face[4], face_select[4]; // solid faces
|
||||
char face_dot[4]; // selected color
|
||||
char normal[4];
|
||||
|
||||
char vertex_size, pad;
|
||||
short pad1[3];
|
||||
char vertex_size, facedot_size;
|
||||
char pad1[2];
|
||||
|
||||
} ThemeSpace;
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ source_files = ['B.blend.c',
|
||||
'editmesh_loop.c',
|
||||
'editmesh_mods.c',
|
||||
'editmesh_tools.c',
|
||||
'editmode_undo.c',
|
||||
'editnla.c',
|
||||
'editobject.c',
|
||||
'editoops.c',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -372,7 +372,7 @@ static void decimate_apply(void)
|
||||
G.obedit= ob;
|
||||
make_editMesh();
|
||||
load_editMesh();
|
||||
free_editMesh();
|
||||
free_editMesh(G.editMesh);
|
||||
G.obedit= NULL;
|
||||
tex_space_mesh(me);
|
||||
|
||||
@@ -449,7 +449,6 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
|
||||
case B_MATASS:
|
||||
if(G.obedit && G.obedit->actcol>0) {
|
||||
if(G.obedit->type == OB_MESH) {
|
||||
undo_push_mesh("Assign material index");
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
if( faceselectedAND(efa, 1) )
|
||||
@@ -458,6 +457,7 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
|
||||
}
|
||||
allqueue(REDRAWVIEW3D_Z, 0);
|
||||
makeDispList(G.obedit);
|
||||
BIF_undo_push("Assign material index");
|
||||
}
|
||||
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
|
||||
nu= editNurb.first;
|
||||
@@ -563,8 +563,6 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
|
||||
if(G.obedit) {
|
||||
if(G.obedit->type == OB_MESH) {
|
||||
efa= em->faces.first;
|
||||
if (event == B_SETSMOOTH) undo_push_mesh("Set Smooth");
|
||||
else if (event==B_SETSOLID) undo_push_mesh("Set Solid");
|
||||
while(efa) {
|
||||
if( faceselectedAND(efa, 1) ) {
|
||||
if(event==B_SETSMOOTH) efa->flag |= ME_SMOOTH;
|
||||
@@ -575,6 +573,8 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
|
||||
|
||||
makeDispList(G.obedit);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
if(event == B_SETSMOOTH) BIF_undo_push("Set Smooth");
|
||||
else BIF_undo_push("Set Solid");
|
||||
}
|
||||
else {
|
||||
nu= editNurb.first;
|
||||
@@ -1834,16 +1834,17 @@ void do_meshbuts(unsigned short event)
|
||||
case B_DELVGROUP:
|
||||
del_defgroup (G.obedit);
|
||||
allqueue (REDRAWVIEW3D, 1);
|
||||
BIF_undo_push("Delete vertex group");
|
||||
break;
|
||||
case B_ASSIGNVGROUP:
|
||||
undo_push_mesh("Assign to vertex group");
|
||||
assign_verts_defgroup ();
|
||||
allqueue (REDRAWVIEW3D, 1);
|
||||
BIF_undo_push("Assign to vertex group");
|
||||
break;
|
||||
case B_REMOVEVGROUP:
|
||||
undo_push_mesh("Remove from vertex group");
|
||||
remove_verts_defgroup (0);
|
||||
allqueue (REDRAWVIEW3D, 1);
|
||||
BIF_undo_push("Remove from vertex group");
|
||||
break;
|
||||
case B_SELVGROUP:
|
||||
sel_verts_defgroup(1);
|
||||
@@ -1961,28 +1962,28 @@ void do_meshbuts(unsigned short event)
|
||||
G.f -= G_DISABLE_OK;
|
||||
break;
|
||||
case B_REMDOUB:
|
||||
undo_push_mesh("Rem Doubles");
|
||||
notice("Removed: %d", removedoublesflag(1, doublimit));
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
BIF_undo_push("Rem Doubles");
|
||||
break;
|
||||
case B_SUBDIV:
|
||||
waitcursor(1);
|
||||
undo_push_mesh("Subdivide");
|
||||
subdivideflag(1, 0.0, editbutflag & B_BEAUTY);
|
||||
countall();
|
||||
waitcursor(0);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
BIF_undo_push("Subdivide");
|
||||
break;
|
||||
case B_FRACSUBDIV:
|
||||
randfac= 10;
|
||||
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
|
||||
waitcursor(1);
|
||||
undo_push_mesh("Fractal Subdivide");
|
||||
fac= -( (float)randfac )/100;
|
||||
subdivideflag(1, fac, editbutflag & B_BEAUTY);
|
||||
countall();
|
||||
waitcursor(0);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
BIF_undo_push("Fractal Subdivide");
|
||||
break;
|
||||
case B_XSORT:
|
||||
if( select_area(SPACE_VIEW3D)) xsortvert_flag(1);
|
||||
|
||||
@@ -958,6 +958,35 @@ static void drawlattice(Object *ob)
|
||||
|
||||
/* ***************** ******************** */
|
||||
|
||||
void calc_mesh_facedots_ext(void)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
EditFace *efa;
|
||||
float mat[4][4];
|
||||
|
||||
if(em->faces.first==NULL) return;
|
||||
efa= em->faces.first;
|
||||
|
||||
areawinset(curarea->win);
|
||||
persp(PERSP_VIEW);
|
||||
|
||||
mymultmatrix(G.obedit->obmat);
|
||||
|
||||
MTC_Mat4SwapMat4(G.vd->persmat, mat);
|
||||
mygetsingmatrix(G.vd->persmat);
|
||||
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
if( efa->h==0) {
|
||||
project_short(efa->cent, &(efa->xs));
|
||||
}
|
||||
efa= efa->next;
|
||||
}
|
||||
MTC_Mat4SwapMat4(G.vd->persmat, mat);
|
||||
|
||||
myloadmatrix(G.vd->viewmat);
|
||||
}
|
||||
|
||||
/* window coord, assuming all matrices are set OK */
|
||||
void calc_meshverts(void)
|
||||
{
|
||||
@@ -1078,46 +1107,89 @@ void calc_nurbverts_ext(void)
|
||||
|
||||
}
|
||||
|
||||
void tekenvertices(short sel)
|
||||
static void draw_vertices(short sel)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
EditVert *eve;
|
||||
float size;
|
||||
char col[3];
|
||||
EditFace *efa;
|
||||
float size, fsize;
|
||||
char col[3], fcol[3];
|
||||
|
||||
/* draws in zbuffer mode twice, to show invisible vertices transparent */
|
||||
|
||||
size= BIF_GetThemeValuef(TH_VERTEX_SIZE);
|
||||
if(sel) BIF_GetThemeColor3ubv(TH_VERTEX_SELECT, col);
|
||||
else BIF_GetThemeColor3ubv(TH_VERTEX, col);
|
||||
fsize= BIF_GetThemeValuef(TH_FACEDOT_SIZE);
|
||||
if(sel) {
|
||||
BIF_GetThemeColor3ubv(TH_VERTEX_SELECT, col);
|
||||
BIF_GetThemeColor3ubv(TH_FACE_DOT, fcol);
|
||||
}
|
||||
else {
|
||||
BIF_GetThemeColor3ubv(TH_VERTEX, col);
|
||||
BIF_GetThemeColor3ubv(TH_WIRE, fcol);
|
||||
}
|
||||
|
||||
if(G.zbuf) {
|
||||
glPointSize(size>2.1?size/2.0: size);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glColor4ub(col[0], col[1], col[2], 100);
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
bglBegin(GL_POINTS);
|
||||
for(eve= em->verts.first; eve; eve= eve->next) {
|
||||
if(eve->h==0 && (eve->f & 1)==sel ) bglVertex3fv(eve->co);
|
||||
|
||||
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
|
||||
glPointSize(size>2.1?size/2.0: size);
|
||||
glColor4ub(col[0], col[1], col[2], 100);
|
||||
|
||||
bglBegin(GL_POINTS);
|
||||
for(eve= em->verts.first; eve; eve= eve->next) {
|
||||
if(eve->h==0 && (eve->f & SELECT)==sel ) bglVertex3fv(eve->co);
|
||||
}
|
||||
bglEnd();
|
||||
}
|
||||
|
||||
if(G.scene->selectmode & SCE_SELECT_FACE) {
|
||||
glPointSize(fsize>2.1?fsize/2.0: fsize);
|
||||
glColor4ub(fcol[0], fcol[1], fcol[2], 100);
|
||||
|
||||
bglBegin(GL_POINTS);
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
if(efa->h==0) {
|
||||
if(sel == (efa->f & SELECT)) {
|
||||
bglVertex3fv(efa->cent);
|
||||
}
|
||||
}
|
||||
}
|
||||
bglEnd();
|
||||
}
|
||||
bglEnd();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
glPointSize(size);
|
||||
glColor3ub(col[0], col[1], col[2]);
|
||||
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
|
||||
glPointSize(size);
|
||||
glColor3ub(col[0], col[1], col[2]);
|
||||
|
||||
bglBegin(GL_POINTS);
|
||||
for(eve= em->verts.first; eve; eve= eve->next) {
|
||||
if(eve->h==0 && (eve->f & 1)==sel ) bglVertex3fv(eve->co);
|
||||
bglBegin(GL_POINTS);
|
||||
for(eve= em->verts.first; eve; eve= eve->next) {
|
||||
if(eve->h==0 && (eve->f & SELECT)==sel ) bglVertex3fv(eve->co);
|
||||
}
|
||||
bglEnd();
|
||||
}
|
||||
|
||||
if(G.scene->selectmode & SCE_SELECT_FACE) {
|
||||
glPointSize(fsize);
|
||||
glColor3ub(fcol[0], fcol[1], fcol[2]);
|
||||
|
||||
bglBegin(GL_POINTS);
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
if(efa->h==0) {
|
||||
if(sel == (efa->f & SELECT)) {
|
||||
bglVertex3fv(efa->cent);
|
||||
}
|
||||
}
|
||||
}
|
||||
bglEnd();
|
||||
}
|
||||
bglEnd();
|
||||
|
||||
glPointSize(1.0);
|
||||
}
|
||||
@@ -1760,14 +1832,14 @@ static void drawmeshsolid(Object *ob, float *nors)
|
||||
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
if(efa->v1->h==0 && efa->v2->h==0 && efa->v3->h==0) {
|
||||
if(efa->h==0) {
|
||||
|
||||
if(efa->mat_nr!=matnr) {
|
||||
matnr= efa->mat_nr;
|
||||
set_gl_material(matnr+1);
|
||||
}
|
||||
|
||||
if(efa->v4 && efa->v4->h==0) {
|
||||
if(efa->v4) {
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glNormal3fv(efa->n);
|
||||
@@ -2381,7 +2453,7 @@ static void drawmeshwire(Object *ob)
|
||||
Material *ma;
|
||||
EditEdge *eed;
|
||||
EditFace *efa;
|
||||
float fvec[3], cent[3], *f1, *f2, *f3, *f4, *extverts=NULL;
|
||||
float fvec[3], *f1, *f2, *f3, *f4, *extverts=NULL;
|
||||
int a, start, end, test, ok, handles=0;
|
||||
|
||||
me= get_mesh(ob);
|
||||
@@ -2390,7 +2462,7 @@ static void drawmeshwire(Object *ob)
|
||||
|
||||
if( (me->flag & ME_OPT_EDGES) && (me->flag & ME_SUBSURF) && me->subdiv) handles= 1;
|
||||
|
||||
if(handles==0 && (G.f & (G_FACESELECT+G_DRAWFACES))) { /* faces */
|
||||
if(handles==0 && (G.f & (G_FACESELECT+G_DRAWFACES))) { /* transp faces */
|
||||
char col1[4], col2[4];
|
||||
|
||||
BIF_GetThemeColor4ubv(TH_FACE, col1);
|
||||
@@ -2402,43 +2474,17 @@ static void drawmeshwire(Object *ob)
|
||||
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
if(efa->v1->h==0 && efa->v2->h==0 && efa->v3->h==0 && (efa->v4==NULL || efa->v4->h==0)) {
|
||||
if(efa->h==0) {
|
||||
|
||||
if(1) {
|
||||
if(faceselectedAND(efa, 1)) glColor4ub(col2[0], col2[1], col2[2], col2[3]);
|
||||
else glColor4ub(col1[0], col1[1], col1[2], col1[3]);
|
||||
|
||||
glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
|
||||
glVertex3fv(efa->v1->co);
|
||||
glVertex3fv(efa->v2->co);
|
||||
glVertex3fv(efa->v3->co);
|
||||
if(efa->v4) glVertex3fv(efa->v4->co);
|
||||
glEnd();
|
||||
|
||||
} else {
|
||||
if(faceselectedAND(efa, 1)) glColor4ub(col2[0], col2[1], col2[2], col2[3]);
|
||||
else glColor4ub(col1[0], col1[1], col1[2], col1[3]);
|
||||
if(efa->f & SELECT) glColor4ub(col2[0], col2[1], col2[2], col2[3]);
|
||||
else glColor4ub(col1[0], col1[1], col1[2], col1[3]);
|
||||
|
||||
if(efa->v4 && efa->v4->h==0) {
|
||||
|
||||
CalcCent4f(cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
|
||||
glBegin(GL_QUADS);
|
||||
VecMidf(fvec, cent, efa->v1->co); glVertex3fv(fvec);
|
||||
VecMidf(fvec, cent, efa->v2->co); glVertex3fv(fvec);
|
||||
VecMidf(fvec, cent, efa->v3->co); glVertex3fv(fvec);
|
||||
VecMidf(fvec, cent, efa->v4->co); glVertex3fv(fvec);
|
||||
glEnd();
|
||||
}
|
||||
else {
|
||||
|
||||
CalcCent3f(cent, efa->v1->co, efa->v2->co, efa->v3->co);
|
||||
glBegin(GL_TRIANGLES);
|
||||
VecMidf(fvec, cent, efa->v1->co); glVertex3fv(fvec);
|
||||
VecMidf(fvec, cent, efa->v2->co); glVertex3fv(fvec);
|
||||
VecMidf(fvec, cent, efa->v3->co); glVertex3fv(fvec);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
|
||||
glVertex3fv(efa->v1->co);
|
||||
glVertex3fv(efa->v2->co);
|
||||
glVertex3fv(efa->v3->co);
|
||||
if(efa->v4) glVertex3fv(efa->v4->co);
|
||||
glEnd();
|
||||
}
|
||||
efa= efa->next;
|
||||
}
|
||||
@@ -2457,7 +2503,8 @@ static void drawmeshwire(Object *ob)
|
||||
}
|
||||
}
|
||||
|
||||
if(handles==0 && (G.f & G_DRAWCREASES)) { /* Use crease edge Highlighting */
|
||||
if(handles); // then no edges draw
|
||||
else if(G.f & G_DRAWCREASES) { /* Use crease edge Highlighting */
|
||||
|
||||
eed= em->edges.first;
|
||||
glBegin(GL_LINES);
|
||||
@@ -2471,35 +2518,77 @@ static void drawmeshwire(Object *ob)
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
else if(handles==0 && (G.f & G_DRAWEDGES)) { /* Use edge Highlighting */
|
||||
else if(G.scene->selectmode == SCE_SELECT_FACE) {
|
||||
/* draw faces twice, to have selected ones on top */
|
||||
BIF_ThemeColor(TH_WIRE);
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
if(efa->h==0 && (efa->f & SELECT)==0) {
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex3fv(efa->v1->co);
|
||||
glVertex3fv(efa->v2->co);
|
||||
glVertex3fv(efa->v3->co);
|
||||
if(efa->v4) glVertex3fv(efa->v4->co);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
BIF_ThemeColor(TH_EDGE_SELECT);
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
if(efa->h==0 && (efa->f & SELECT)) {
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex3fv(efa->v1->co);
|
||||
glVertex3fv(efa->v2->co);
|
||||
glVertex3fv(efa->v3->co);
|
||||
if(efa->v4) glVertex3fv(efa->v4->co);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( (G.f & G_DRAWEDGES) || (G.scene->selectmode & SCE_SELECT_EDGE) ) {
|
||||
/* Use edge highlighting */
|
||||
char col[4], colhi[4];
|
||||
|
||||
BIF_GetThemeColor3ubv(TH_EDGE_SELECT, colhi);
|
||||
BIF_GetThemeColor3ubv(TH_WIRE, col);
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
|
||||
eed= em->edges.first;
|
||||
glBegin(GL_LINES);
|
||||
while(eed) {
|
||||
if(eed->h==0) {
|
||||
|
||||
if(eed->v1->f & 1) glColor3ub(colhi[0], colhi[1], colhi[2]);
|
||||
else glColor3ub(col[0], col[1], col[2]);
|
||||
|
||||
glVertex3fv(eed->v1->co);
|
||||
|
||||
if(eed->v2->f & 1) glColor3ub(colhi[0], colhi[1], colhi[2]);
|
||||
else glColor3ub(col[0], col[1], col[2]);
|
||||
/* (bleeding edges) to illustrate selection is defined on vertex basis */
|
||||
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
glVertex3fv(eed->v2->co);
|
||||
glBegin(GL_LINES);
|
||||
while(eed) {
|
||||
if(eed->h==0) {
|
||||
|
||||
if(eed->v1->f & SELECT) glColor3ub(colhi[0], colhi[1], colhi[2]);
|
||||
else glColor3ub(col[0], col[1], col[2]);
|
||||
|
||||
glVertex3fv(eed->v1->co);
|
||||
|
||||
if(eed->v2->f & SELECT) glColor3ub(colhi[0], colhi[1], colhi[2]);
|
||||
else glColor3ub(col[0], col[1], col[2]);
|
||||
|
||||
glVertex3fv(eed->v2->co);
|
||||
}
|
||||
eed= eed->next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
glBegin(GL_LINES);
|
||||
while(eed) {
|
||||
if(eed->h==0) {
|
||||
if(eed->f & SELECT) glColor3ub(colhi[0], colhi[1], colhi[2]);
|
||||
else glColor3ub(col[0], col[1], col[2]);
|
||||
|
||||
glVertex3fv(eed->v1->co);
|
||||
glVertex3fv(eed->v2->co);
|
||||
}
|
||||
eed= eed->next;
|
||||
}
|
||||
eed= eed->next;
|
||||
}
|
||||
glEnd();
|
||||
glShadeModel(GL_FLAT);
|
||||
}
|
||||
else if(handles==0) {
|
||||
else {
|
||||
BIF_ThemeColor(TH_WIRE);
|
||||
eed= em->edges.first;
|
||||
glBegin(GL_LINES);
|
||||
@@ -2536,8 +2625,8 @@ static void drawmeshwire(Object *ob)
|
||||
|
||||
calc_meshverts();
|
||||
|
||||
tekenvertices(0);
|
||||
tekenvertices(1);
|
||||
draw_vertices(0);
|
||||
draw_vertices(1);
|
||||
|
||||
if(G.f & G_DRAWNORMALS) { /* normals */
|
||||
/*cpack(0xDDDD22);*/
|
||||
@@ -2547,7 +2636,7 @@ static void drawmeshwire(Object *ob)
|
||||
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
if(efa->v1->h==0 && efa->v2->h==0 && efa->v3->h==0) {
|
||||
if(efa->h==0) {
|
||||
if(efa->v4) CalcCent4f(fvec, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
|
||||
else CalcCent3f(fvec, efa->v1->co, efa->v2->co, efa->v3->co);
|
||||
|
||||
@@ -3678,10 +3767,12 @@ static void drawWireExtra(Object *ob, ListBase *lb)
|
||||
else BIF_ThemeColor(TH_WIRE);
|
||||
|
||||
bPolygonOffset(1);
|
||||
glDepthMask(0); // disable write in zbuffer, selected edge wires show better
|
||||
|
||||
if(ob->type==OB_MESH) drawmeshwire(ob);
|
||||
else drawDispListwire(lb);
|
||||
|
||||
glDepthMask(1);
|
||||
bPolygonOffset(0);
|
||||
}
|
||||
|
||||
@@ -3918,7 +4009,7 @@ void draw_object(Base *base)
|
||||
|
||||
/* draw outline for selected solid objects */
|
||||
if(G.vd->flag & V3D_SELECT_OUTLINE) {
|
||||
if(dt>OB_WIRE && ob!=G.obedit && (G.f & G_BACKBUFSEL)==0) {
|
||||
if(dt>OB_WIRE && dt<OB_TEXTURE && ob!=G.obedit && (G.f & G_BACKBUFSEL)==0) {
|
||||
if((G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT))==0)
|
||||
draw_solid_select(ob);
|
||||
}
|
||||
|
||||
@@ -535,24 +535,14 @@ void countall()
|
||||
eve= em->verts.first;
|
||||
while(eve) {
|
||||
G.totvert++;
|
||||
if(eve->f & 1) G.totvertsel++;
|
||||
if(eve->f & SELECT) G.totvertsel++;
|
||||
eve= eve->next;
|
||||
}
|
||||
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
G.totface++;
|
||||
if(efa->v1->f & 1) {
|
||||
if(efa->v2->f & 1) {
|
||||
if(efa->v3->f & 1) {
|
||||
if(efa->v4) {
|
||||
if(efa->v4->f & 1) G.totfacesel++;
|
||||
}
|
||||
else {
|
||||
G.totfacesel++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(efa->f & SELECT) G.totfacesel++;
|
||||
efa= efa->next;
|
||||
}
|
||||
}
|
||||
@@ -1199,8 +1189,6 @@ void mergemenu(void)
|
||||
|
||||
if (event==-1) return; /* Return if the menu is closed without any choices */
|
||||
|
||||
undo_push_mesh("Merge"); /* The action has been confirmed, push the mesh down the undo pipe */
|
||||
|
||||
if (event==1)
|
||||
snap_to_center(); /*Merge at Center*/
|
||||
else
|
||||
@@ -1209,6 +1197,8 @@ void mergemenu(void)
|
||||
notice("Removed %d Vertices", removedoublesflag(1, doublimit));
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
countall();
|
||||
BIF_undo_push("Merge"); /* push the mesh down the undo pipe */
|
||||
|
||||
}
|
||||
|
||||
void delete_context_selected(void) {
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_dynstr.h"
|
||||
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_ipo_types.h"
|
||||
@@ -70,6 +71,7 @@
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_main.h"
|
||||
|
||||
#include "BIF_editmode_undo.h"
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_graphics.h"
|
||||
#include "BIF_screen.h"
|
||||
@@ -281,7 +283,6 @@ void load_editNurb()
|
||||
nu= editNurb.first;
|
||||
while(nu) {
|
||||
newnu= duplicateNurb(nu);
|
||||
newnu->hide= 0;
|
||||
BLI_addtail(&(cu->nurb), newnu);
|
||||
|
||||
if((nu->type & 7)==CU_NURBS) {
|
||||
@@ -303,12 +304,9 @@ void make_editNurb()
|
||||
/* make copy of baseNurb in editNurb */
|
||||
Curve *cu=0;
|
||||
Nurb *nu, *newnu;
|
||||
BezTriple *bezt;
|
||||
BPoint *bp;
|
||||
KeyBlock *actkey=0;
|
||||
int a, tot=0;
|
||||
|
||||
if(G.obedit==0) return;
|
||||
if(G.obedit==NULL) return;
|
||||
|
||||
lastselbp= NULL; /* global for select row */
|
||||
|
||||
@@ -321,26 +319,6 @@ void make_editNurb()
|
||||
while(nu) {
|
||||
newnu= duplicateNurb(nu);
|
||||
BLI_addtail(&editNurb, newnu);
|
||||
/* flags zero */
|
||||
newnu->hide= 0;
|
||||
if((nu->type & 7)==CU_BEZIER) {
|
||||
a= nu->pntsu;
|
||||
bezt= newnu->bezt;
|
||||
while(a--) {
|
||||
bezt->f1= bezt->f2= bezt->f3= bezt->hide= 0;
|
||||
bezt++;
|
||||
tot+= 3;
|
||||
}
|
||||
}
|
||||
else {
|
||||
a= nu->pntsu*nu->pntsv;
|
||||
bp= newnu->bp;
|
||||
while(a--) {
|
||||
bp->f1= bp->hide= 0;
|
||||
bp++;
|
||||
tot++;
|
||||
}
|
||||
}
|
||||
nu= nu->next;
|
||||
}
|
||||
|
||||
@@ -357,7 +335,7 @@ void make_editNurb()
|
||||
}
|
||||
makeDispList(G.obedit);
|
||||
}
|
||||
else G.obedit= 0;
|
||||
else G.obedit= NULL;
|
||||
|
||||
countall();
|
||||
|
||||
@@ -1046,8 +1024,6 @@ void switchdirectionNurb2(void)
|
||||
if(G.obedit->lay & G.vd->lay);
|
||||
else return;
|
||||
|
||||
undo_push_curve("Switch direction");
|
||||
|
||||
nu= editNurb.first;
|
||||
while(nu) {
|
||||
if( isNurbsel(nu) ) switchdirectionNurb(nu);
|
||||
@@ -1058,6 +1034,7 @@ void switchdirectionNurb2(void)
|
||||
curve_changes_other_objects(G.obedit);
|
||||
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
BIF_undo_push("Switch direction");
|
||||
}
|
||||
|
||||
void switchdirection_knots(float *base, int tot)
|
||||
@@ -1113,7 +1090,7 @@ void deselectall_nurb()
|
||||
if(G.obedit->lay & G.vd->lay);
|
||||
else return;
|
||||
|
||||
undo_push_curve("Deselect all");
|
||||
BIF_undo_push("Deselect all");
|
||||
|
||||
a= 0;
|
||||
nu= editNurb.first;
|
||||
@@ -1203,7 +1180,7 @@ void hideNurb(int swap)
|
||||
|
||||
if(G.obedit==0) return;
|
||||
|
||||
undo_push_curve("Hide");
|
||||
BIF_undo_push("Hide");
|
||||
|
||||
nu= editNurb.first;
|
||||
while(nu) {
|
||||
@@ -1260,8 +1237,6 @@ void revealNurb()
|
||||
|
||||
if(G.obedit==0) return;
|
||||
|
||||
undo_push_curve("Reveal");
|
||||
|
||||
nu= editNurb.first;
|
||||
while(nu) {
|
||||
nu->hide= 0;
|
||||
@@ -1295,6 +1270,8 @@ void revealNurb()
|
||||
makeDispList(G.obedit);
|
||||
countall();
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
BIF_undo_push("Reveal");
|
||||
|
||||
}
|
||||
|
||||
void selectswapNurb()
|
||||
@@ -1306,8 +1283,6 @@ void selectswapNurb()
|
||||
|
||||
if(G.obedit==0) return;
|
||||
|
||||
undo_push_curve("Select swap");
|
||||
|
||||
nu= editNurb.first;
|
||||
while(nu) {
|
||||
if((nu->type & 7)==CU_BEZIER) {
|
||||
@@ -1341,6 +1316,8 @@ void selectswapNurb()
|
||||
|
||||
countall();
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
BIF_undo_push("Select swap");
|
||||
|
||||
}
|
||||
|
||||
/** Divide the line segments associated with the currently selected
|
||||
@@ -1361,8 +1338,6 @@ void subdivideNurb()
|
||||
|
||||
// printf("*** subdivideNurb: entering subdivide\n");
|
||||
|
||||
undo_push_curve("Subdivide");
|
||||
|
||||
nu= editNurb.first;
|
||||
while(nu) {
|
||||
amount= 0;
|
||||
@@ -1723,6 +1698,8 @@ void subdivideNurb()
|
||||
countall();
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
BIF_undo_push("Subdivide");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1887,8 +1864,6 @@ void setsplinetype(short type)
|
||||
return;
|
||||
}
|
||||
|
||||
undo_push_curve("Set spline type");
|
||||
|
||||
nu= editNurb.first;
|
||||
while(nu) {
|
||||
if(isNurbsel(nu)) {
|
||||
@@ -2015,6 +1990,8 @@ void setsplinetype(short type)
|
||||
}
|
||||
nu= nu->next;
|
||||
}
|
||||
BIF_undo_push("Set spline type");
|
||||
|
||||
}
|
||||
|
||||
/* ******************** SKINNING LOFTING!!! ******************** */
|
||||
@@ -2269,8 +2246,6 @@ void merge_nurb()
|
||||
return;
|
||||
}
|
||||
|
||||
undo_push_curve("Merge");
|
||||
|
||||
nus1= nsortbase.first;
|
||||
nus2= nus1->next;
|
||||
|
||||
@@ -2310,6 +2285,8 @@ void merge_nurb()
|
||||
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
BIF_undo_push("Merge");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2322,8 +2299,6 @@ void addsegment_nurb()
|
||||
float *fp, offset;
|
||||
int a;
|
||||
|
||||
undo_push_curve("Add segment");
|
||||
|
||||
/* first decide if this is a surface merge! */
|
||||
if(G.obedit->type==OB_SURF) nu= editNurb.first;
|
||||
else nu= NULL;
|
||||
@@ -2469,6 +2444,8 @@ void addsegment_nurb()
|
||||
countall();
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
BIF_undo_push("Add segment");
|
||||
|
||||
}
|
||||
else error("Can't make segment");
|
||||
}
|
||||
@@ -2480,8 +2457,6 @@ void mouse_nurb()
|
||||
BPoint *bp=0;
|
||||
short hand;
|
||||
|
||||
undo_push_curve("Select");
|
||||
|
||||
hand= findnearestNurbvert(1, &nu, &bezt, &bp);
|
||||
|
||||
if(bezt || bp) {
|
||||
@@ -2561,7 +2536,7 @@ void mouse_nurb()
|
||||
|
||||
}
|
||||
|
||||
void spinNurb(float *dvec, short mode)
|
||||
static void spin_nurb(float *dvec, short mode)
|
||||
{
|
||||
Nurb *nu;
|
||||
float *curs, si,phi,n[3],q[4],cmat[3][3],tmat[3][3],imat[3][3];
|
||||
@@ -2572,8 +2547,6 @@ void spinNurb(float *dvec, short mode)
|
||||
if(G.obedit==0 || G.obedit->type!=OB_SURF) return;
|
||||
if( (G.vd->lay & G.obedit->lay)==0 ) return;
|
||||
|
||||
undo_push_curve("Spin");
|
||||
|
||||
Mat3CpyMat4(persmat, G.vd->viewmat);
|
||||
Mat3Inv(persinv, persmat);
|
||||
|
||||
@@ -2662,6 +2635,14 @@ void spinNurb(float *dvec, short mode)
|
||||
nu= nu->next;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* external one, for undo */
|
||||
void spinNurb(float *dvec, short mode)
|
||||
{
|
||||
spin_nurb(dvec, mode);
|
||||
BIF_undo_push("Spin");
|
||||
}
|
||||
|
||||
void curve_changes_other_objects(Object *ob)
|
||||
@@ -2694,8 +2675,6 @@ void addvert_Nurb(int mode)
|
||||
|
||||
if(mode=='e' && okee("Extrude")==0) return;
|
||||
|
||||
undo_push_curve("Add vertex");
|
||||
|
||||
Mat3CpyMat4(mat, G.obedit->obmat);
|
||||
Mat3Inv(imat,mat);
|
||||
|
||||
@@ -2817,6 +2796,8 @@ void addvert_Nurb(int mode)
|
||||
if(mode!='e') {
|
||||
/* dependencies with other objects, should become event */
|
||||
curve_changes_other_objects(G.obedit);
|
||||
BIF_undo_push("Add vertex");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2839,12 +2820,12 @@ void extrude_nurb()
|
||||
else {
|
||||
|
||||
if(okee("Extrude")==0) return;
|
||||
undo_push_curve("Extrude");
|
||||
|
||||
ok= extrudeflagNurb(1); /* '1'= flag */
|
||||
|
||||
if(ok) {
|
||||
makeDispList(G.obedit);
|
||||
BIF_undo_push("Extrude");
|
||||
countall();
|
||||
transform('d');
|
||||
}
|
||||
@@ -2862,8 +2843,6 @@ void makecyclicNurb()
|
||||
float *fp;
|
||||
int a, b, cyclmode=0;
|
||||
|
||||
undo_push_curve("Cyclic");
|
||||
|
||||
nu= editNurb.first;
|
||||
while(nu) {
|
||||
if( nu->pntsu>1 || nu->pntsv>1) {
|
||||
@@ -2961,7 +2940,7 @@ void makecyclicNurb()
|
||||
}
|
||||
makeDispList(G.obedit);
|
||||
curve_changes_other_objects(G.obedit);
|
||||
|
||||
BIF_undo_push("Cyclic");
|
||||
}
|
||||
|
||||
void selectconnected_nurb()
|
||||
@@ -2971,8 +2950,6 @@ void selectconnected_nurb()
|
||||
BPoint *bp;
|
||||
int a;
|
||||
|
||||
undo_push_curve("Select connected");
|
||||
|
||||
findnearestNurbvert(1, &nu, &bezt, &bp);
|
||||
if(bezt) {
|
||||
a= nu->pntsu;
|
||||
@@ -3011,6 +2988,8 @@ void selectconnected_nurb()
|
||||
|
||||
countall();
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
BIF_undo_push("Select connected");
|
||||
|
||||
}
|
||||
|
||||
void selectrow_nurb()
|
||||
@@ -3025,8 +3004,6 @@ void selectrow_nurb()
|
||||
if(G.obedit==NULL || G.obedit->type!=OB_SURF) return;
|
||||
if(lastselbp==NULL) return;
|
||||
|
||||
undo_push_curve("Select Row");
|
||||
|
||||
/* find the correct nurb and toggle with u of v */
|
||||
nu= editNurb.first;
|
||||
while(nu) {
|
||||
@@ -3066,6 +3043,8 @@ void selectrow_nurb()
|
||||
}
|
||||
nu= nu->next;
|
||||
}
|
||||
BIF_undo_push("Select Row");
|
||||
|
||||
}
|
||||
|
||||
void adduplicate_nurb()
|
||||
@@ -3073,8 +3052,6 @@ void adduplicate_nurb()
|
||||
|
||||
if( (G.vd->lay & G.obedit->lay)==0 ) return;
|
||||
|
||||
undo_push_curve("Duplicate");
|
||||
|
||||
adduplicateflagNurb(1);
|
||||
|
||||
countall();
|
||||
@@ -3097,8 +3074,6 @@ void delNurb()
|
||||
|
||||
if(event== -1) return;
|
||||
|
||||
undo_push_curve("Delete");
|
||||
|
||||
if(G.obedit->type==OB_SURF) {
|
||||
if(event==0) deleteflagNurb(1);
|
||||
else freeNurblist(&editNurb);
|
||||
@@ -3107,6 +3082,8 @@ void delNurb()
|
||||
makeDispList(G.obedit);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
BIF_undo_push("Delete");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3222,6 +3199,7 @@ void delNurb()
|
||||
makeDispList(G.obedit);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
BIF_undo_push("Delete");
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -3248,6 +3226,7 @@ void delNurb()
|
||||
makeDispList(G.obedit);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
BIF_undo_push("Delete");
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -3350,6 +3329,8 @@ void delNurb()
|
||||
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
BIF_undo_push("Delete");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -3377,8 +3358,6 @@ void join_curve(int type)
|
||||
}
|
||||
else if(okee("Join selected curves")==0) return;
|
||||
|
||||
undo_push_curve("Join");
|
||||
|
||||
/* trasnform all selected curves inverse in obact */
|
||||
Mat4Invert(imat, ob->obmat);
|
||||
|
||||
@@ -3435,6 +3414,8 @@ void join_curve(int type)
|
||||
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
BIF_undo_push("Join");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -3764,7 +3745,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
|
||||
makeknots(nu, 1, nu->flagu>>1);
|
||||
|
||||
BLI_addtail(&editNurb, nu); /* temporal for spin */
|
||||
spinNurb(0, 0);
|
||||
spin_nurb(0, 0);
|
||||
|
||||
makeknots(nu, 2, nu->flagv>>1);
|
||||
|
||||
@@ -3791,7 +3772,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
|
||||
nu->resolv= 32;
|
||||
nu->flag= CU_SMOOTH;
|
||||
BLI_addtail(&editNurb, nu); /* temporal for extrude and translate */
|
||||
spinNurb(0, 0);
|
||||
spin_nurb(0, 0);
|
||||
|
||||
BLI_remlink(&editNurb, nu);
|
||||
|
||||
@@ -3872,7 +3853,7 @@ void add_primitiveCurve(int stype)
|
||||
check_editmode(OB_CURVE);
|
||||
|
||||
/* if no obedit: new object and enter editmode */
|
||||
if(G.obedit==0) {
|
||||
if(G.obedit==NULL) {
|
||||
add_object_draw(OB_CURVE);
|
||||
base_init_from_view3d(BASACT, G.vd);
|
||||
G.obedit= BASACT->object;
|
||||
@@ -3892,7 +3873,6 @@ void add_primitiveCurve(int stype)
|
||||
}
|
||||
else {
|
||||
cu= G.obedit->data;
|
||||
undo_push_curve("Add primitive");
|
||||
}
|
||||
|
||||
if(cu->flag & CU_3D) type &= ~CU_2D;
|
||||
@@ -3907,6 +3887,10 @@ void add_primitiveCurve(int stype)
|
||||
|
||||
countall();
|
||||
allqueue(REDRAWALL, 0);
|
||||
|
||||
/* if a new object was created, it stores it in Curve, for reload original data and undo */
|
||||
if(newname) load_editNurb();
|
||||
BIF_undo_push("Add primitive");
|
||||
}
|
||||
|
||||
void add_primitiveNurb(int type)
|
||||
@@ -3931,9 +3915,6 @@ void add_primitiveNurb(int type)
|
||||
setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
|
||||
newname= 1;
|
||||
}
|
||||
else {
|
||||
undo_push_curve("Add primitive");
|
||||
}
|
||||
|
||||
nu= addNurbprim(4, type, newname);
|
||||
BLI_addtail(&editNurb,nu);
|
||||
@@ -3941,6 +3922,10 @@ void add_primitiveNurb(int type)
|
||||
|
||||
countall();
|
||||
allqueue(REDRAWALL, 0);
|
||||
|
||||
/* if a new object was created, it stores it in Curve, for reload original data and undo */
|
||||
if(newname) load_editNurb();
|
||||
else BIF_undo_push("Add primitive");
|
||||
}
|
||||
|
||||
|
||||
@@ -3954,8 +3939,6 @@ void clear_tilt()
|
||||
|
||||
if(okee("Clear tilt")==0) return;
|
||||
|
||||
undo_push_curve("Clear tilt");
|
||||
|
||||
nu= editNurb.first;
|
||||
while(nu) {
|
||||
if( nu->bezt ) {
|
||||
@@ -3979,6 +3962,8 @@ void clear_tilt()
|
||||
|
||||
makeBevelList(G.obedit);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
BIF_undo_push("Clear tilt");
|
||||
|
||||
}
|
||||
|
||||
int bezt_compare (const void *e1, const void *e2)
|
||||
@@ -4008,148 +3993,53 @@ int bezt_compare (const void *e1, const void *e2)
|
||||
|
||||
/* **************** undo for curves ************** */
|
||||
|
||||
#define MAXUNDONAME 64
|
||||
typedef struct UndoElem {
|
||||
struct UndoElem *next, *prev;
|
||||
Object *ob;
|
||||
ListBase editnurb;
|
||||
char name[MAXUNDONAME];
|
||||
} UndoElem;
|
||||
|
||||
static ListBase undobase={NULL, NULL};
|
||||
static UndoElem *curundo= NULL;
|
||||
|
||||
static void undo_restore(UndoElem *undo)
|
||||
static void undoCurve_to_editCurve(void *lbv)
|
||||
{
|
||||
ListBase *lb= lbv;
|
||||
Nurb *nu, *newnu;
|
||||
|
||||
|
||||
freeNurblist(&editNurb);
|
||||
|
||||
/* copy */
|
||||
nu= undo->editnurb.first;
|
||||
nu= lb->first;
|
||||
while(nu) {
|
||||
newnu= duplicateNurb(nu);
|
||||
BLI_addtail(&editNurb, newnu);
|
||||
nu= nu->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* name can be a dynamic string */
|
||||
void undo_push_curve(char *name)
|
||||
static void *editCurve_to_undoCurve(void)
|
||||
{
|
||||
ListBase *lb;
|
||||
Nurb *nu, *newnu;
|
||||
UndoElem *uel;
|
||||
int nr;
|
||||
|
||||
/* remove all undos after (also when curundo==NULL) */
|
||||
while(undobase.last != curundo) {
|
||||
uel= undobase.last;
|
||||
BLI_remlink(&undobase, uel);
|
||||
freeNurblist(&uel->editnurb);
|
||||
MEM_freeN(uel);
|
||||
}
|
||||
|
||||
/* make new */
|
||||
curundo= uel= MEM_callocN(sizeof(UndoElem), "undo curve");
|
||||
strncpy(uel->name, name, MAXUNDONAME-1);
|
||||
BLI_addtail(&undobase, uel);
|
||||
|
||||
/* and limit amount to the maximum */
|
||||
nr= 0;
|
||||
uel= undobase.last;
|
||||
while(uel) {
|
||||
nr++;
|
||||
if(nr==U.undosteps) break;
|
||||
uel= uel->prev;
|
||||
}
|
||||
if(uel) {
|
||||
while(undobase.first!=uel) {
|
||||
UndoElem *first= undobase.first;
|
||||
BLI_remlink(&undobase, first);
|
||||
freeNurblist(&first->editnurb);
|
||||
MEM_freeN(first);
|
||||
}
|
||||
}
|
||||
|
||||
/* copy editNurb */
|
||||
lb= MEM_callocN(sizeof(ListBase), "listbase undo");
|
||||
|
||||
/* copy */
|
||||
nu= editNurb.first;
|
||||
while(nu) {
|
||||
newnu= duplicateNurb(nu);
|
||||
BLI_addtail(&curundo->editnurb, newnu);
|
||||
BLI_addtail(lb, newnu);
|
||||
nu= nu->next;
|
||||
}
|
||||
curundo->ob= G.obedit;
|
||||
return lb;
|
||||
}
|
||||
|
||||
/* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at previous step */
|
||||
void undo_curve_step(int step)
|
||||
static void free_undoCurve(void *lbv)
|
||||
{
|
||||
UndoElem *uel, *next;
|
||||
ListBase *lb= lbv;
|
||||
|
||||
/* prevent undo to happen on wrong object */
|
||||
uel= undobase.first;
|
||||
while(uel) {
|
||||
next= uel->next;
|
||||
if(uel->ob!=G.obedit) {
|
||||
if(uel==curundo) curundo= next;
|
||||
BLI_remlink(&undobase, uel);
|
||||
freeNurblist(&uel->editnurb);
|
||||
MEM_freeN(uel);
|
||||
}
|
||||
uel= next;
|
||||
}
|
||||
|
||||
if(step==1) {
|
||||
if(curundo==NULL) error("No undo available");
|
||||
else {
|
||||
|
||||
/* if we undo, the current situation needs saved */
|
||||
if(curundo->next==NULL) {
|
||||
undo_push_curve("Original");
|
||||
curundo= curundo->prev;
|
||||
}
|
||||
undo_restore(curundo);
|
||||
curundo= curundo->prev;
|
||||
}
|
||||
}
|
||||
else {
|
||||
UndoElem *redo;
|
||||
|
||||
/* curundo has to remain the undo step, so we load curundo->next->next! */
|
||||
|
||||
if(curundo==NULL) redo= undobase.first;
|
||||
else redo= curundo->next;
|
||||
|
||||
if(redo==NULL || redo->next==NULL) error("No redo available");
|
||||
else {
|
||||
undo_restore(redo->next);
|
||||
curundo= redo;
|
||||
}
|
||||
}
|
||||
|
||||
lastnu= NULL; /* for selected */
|
||||
|
||||
makeDispList(G.obedit);
|
||||
curve_changes_other_objects(G.obedit);
|
||||
|
||||
countall();
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
freeNurblist(lb);
|
||||
MEM_freeN(lb);
|
||||
}
|
||||
|
||||
void undo_clear_curve(void)
|
||||
/* and this is all the undo system needs to know */
|
||||
void undo_push_curve(char *name)
|
||||
{
|
||||
UndoElem *uel;
|
||||
|
||||
uel= undobase.first;
|
||||
while(uel) {
|
||||
freeNurblist(&uel->editnurb);
|
||||
uel= uel->next;
|
||||
}
|
||||
BLI_freelistN(&undobase);
|
||||
curundo= NULL;
|
||||
undo_editmode_push(name, free_undoCurve, undoCurve_to_editCurve, editCurve_to_undoCurve);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -123,6 +123,9 @@ void addvert_mesh(void)
|
||||
EditVert *eve,*v1=0;
|
||||
float *curs, mat[3][3],imat[3][3];
|
||||
|
||||
// hurms, yah...
|
||||
if(G.scene->selectmode==SCE_SELECT_FACE) return;
|
||||
|
||||
TEST_EDITMESH
|
||||
|
||||
Mat3CpyMat4(mat, G.obedit->obmat);
|
||||
@@ -130,15 +133,14 @@ void addvert_mesh(void)
|
||||
|
||||
v1= em->verts.first;
|
||||
while(v1) {
|
||||
if(v1->f & 1) break;
|
||||
if(v1->f & SELECT) break;
|
||||
v1= v1->next;
|
||||
}
|
||||
eve= v1; /* prevent there are more selected */
|
||||
while(eve) {
|
||||
eve->f&= ~1;
|
||||
eve= eve->next;
|
||||
}
|
||||
eve= v1;
|
||||
|
||||
/* prevent there are more selected */
|
||||
EM_clear_flag_all(SELECT);
|
||||
|
||||
eve= addvertlist(0);
|
||||
|
||||
curs= give_cursor();
|
||||
@@ -148,7 +150,7 @@ void addvert_mesh(void)
|
||||
VecSubf(eve->co, eve->co, G.obedit->obmat[3]);
|
||||
|
||||
Mat3MulVecfl(imat, eve->co);
|
||||
eve->f= 1;
|
||||
eve->f= SELECT;
|
||||
|
||||
if(v1) {
|
||||
addedgelist(v1, eve, NULL);
|
||||
@@ -168,34 +170,34 @@ void addedgeface_mesh(void)
|
||||
EditVert *eve, *neweve[4];
|
||||
EditFace *efa;
|
||||
float con1, con2, con3;
|
||||
short aantal=0;
|
||||
short amount=0;
|
||||
|
||||
if( (G.vd->lay & G.obedit->lay)==0 ) return;
|
||||
|
||||
/* how many selected ? */
|
||||
eve= em->verts.first;
|
||||
while(eve) {
|
||||
if(eve->f & 1) {
|
||||
aantal++;
|
||||
if(aantal>4) break;
|
||||
neweve[aantal-1]= eve;
|
||||
if(eve->f & SELECT) {
|
||||
amount++;
|
||||
if(amount>4) break;
|
||||
neweve[amount-1]= eve;
|
||||
}
|
||||
eve= eve->next;
|
||||
}
|
||||
if(aantal==2) {
|
||||
if(amount==2) {
|
||||
addedgelist(neweve[0], neweve[1], NULL);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
makeDispList(G.obedit);
|
||||
return;
|
||||
}
|
||||
if(aantal<2 || aantal>4) {
|
||||
if(amount<2 || amount>4) {
|
||||
error("Incorrect number of vertices to make edge/face");
|
||||
return;
|
||||
}
|
||||
|
||||
efa= NULL; // check later
|
||||
|
||||
if(aantal==3) {
|
||||
if(amount==3) {
|
||||
if(exist_face(neweve[0], neweve[1], neweve[2], 0)==0) {
|
||||
|
||||
efa= addfacelist(neweve[0], neweve[1], neweve[2], 0, NULL);
|
||||
@@ -203,7 +205,7 @@ void addedgeface_mesh(void)
|
||||
}
|
||||
else error("The selected vertices already form a face");
|
||||
}
|
||||
else if(aantal==4) {
|
||||
else if(amount==4) {
|
||||
if(exist_face(neweve[0], neweve[1], neweve[2], neweve[3])==0) {
|
||||
|
||||
con1= convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co);
|
||||
@@ -227,7 +229,7 @@ void addedgeface_mesh(void)
|
||||
|
||||
CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
|
||||
|
||||
inp= efa->n[0]*G.vd->viewmat[0][2] + efa->n[1]*G.vd->viewmat[1][2] + efa->n[2]*G.vd->viewmat[2][2];
|
||||
inp= efa->n[0]*G.vd->viewmat[0][2] + efa->n[1]*G.vd->viewmat[1][2] + efa->n[2]*G.vd->viewmat[2][2];
|
||||
|
||||
if(inp < 0.0) flipface(efa);
|
||||
}
|
||||
@@ -237,71 +239,6 @@ void addedgeface_mesh(void)
|
||||
makeDispList(G.obedit);
|
||||
}
|
||||
|
||||
void adduplicateflag(int flag)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
/* old verts have flag 128 set, and flag 'flag' cleared
|
||||
new verts have flag 'flag' set */
|
||||
EditVert *eve, *v1, *v2, *v3, *v4;
|
||||
EditEdge *eed;
|
||||
EditFace *efa;
|
||||
|
||||
/* vertices first */
|
||||
eve= em->verts.last;
|
||||
while(eve) {
|
||||
eve->f&= ~128;
|
||||
if(eve->f & flag) {
|
||||
v1= addvertlist(eve->co);
|
||||
v1->f= eve->f;
|
||||
eve->f-= flag;
|
||||
eve->f|= 128;
|
||||
eve->vn= v1;
|
||||
#ifdef __NLA
|
||||
/* >>>>> FIXME: Copy deformation weight ? */
|
||||
v1->totweight = eve->totweight;
|
||||
if (eve->totweight){
|
||||
v1->dw = MEM_mallocN (eve->totweight * sizeof(MDeformWeight), "deformWeight");
|
||||
memcpy (v1->dw, eve->dw, eve->totweight * sizeof(MDeformWeight));
|
||||
}
|
||||
else
|
||||
v1->dw=NULL;
|
||||
#endif
|
||||
}
|
||||
eve= eve->prev;
|
||||
}
|
||||
eed= em->edges.first;
|
||||
while(eed) {
|
||||
if( (eed->v1->f & 128) && (eed->v2->f & 128) ) {
|
||||
v1= eed->v1->vn;
|
||||
v2= eed->v2->vn;
|
||||
addedgelist(v1, v2, eed);
|
||||
}
|
||||
eed= eed->next;
|
||||
}
|
||||
|
||||
/* then dupicate faces */
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
if( (efa->v1->f & 128) && (efa->v2->f & 128) && (efa->v3->f & 128) ) {
|
||||
if(efa->v4) {
|
||||
if(efa->v4->f & 128) {
|
||||
v1= efa->v1->vn;
|
||||
v2= efa->v2->vn;
|
||||
v3= efa->v3->vn;
|
||||
v4= efa->v4->vn;
|
||||
addfacelist(v1, v2, v3, v4, efa);
|
||||
}
|
||||
}
|
||||
else {
|
||||
v1= efa->v1->vn;
|
||||
v2= efa->v2->vn;
|
||||
v3= efa->v3->vn;
|
||||
addfacelist(v1, v2, v3, 0, efa);
|
||||
}
|
||||
}
|
||||
efa= efa->next;
|
||||
}
|
||||
}
|
||||
|
||||
void adduplicate_mesh(void)
|
||||
{
|
||||
@@ -309,8 +246,9 @@ void adduplicate_mesh(void)
|
||||
TEST_EDITMESH
|
||||
|
||||
waitcursor(1);
|
||||
undo_push_mesh("Duplicate");
|
||||
adduplicateflag(1);
|
||||
|
||||
adduplicateflag(SELECT);
|
||||
|
||||
waitcursor(0);
|
||||
countall(); /* for G.totvert in calc_meshverts() */
|
||||
transform('d');
|
||||
@@ -327,6 +265,7 @@ void add_primitiveMesh(int type)
|
||||
float q[4], cmat[3][3];
|
||||
static short tot=32, seg=32, subdiv=2;
|
||||
short a, b, ext=0, fill=0, totoud, newob=0;
|
||||
char *undostr="Add Primitive";
|
||||
|
||||
if(G.scene->id.lib) return;
|
||||
|
||||
@@ -361,11 +300,7 @@ void add_primitiveMesh(int type)
|
||||
me= G.obedit->data;
|
||||
|
||||
/* deselectall */
|
||||
eve= em->verts.first;
|
||||
while(eve) {
|
||||
if(eve->f & 1) eve->f&= ~1;
|
||||
eve= eve->next;
|
||||
}
|
||||
EM_clear_flag_all(SELECT);
|
||||
|
||||
totoud= tot; /* store, and restore when cube/plane */
|
||||
|
||||
@@ -396,6 +331,7 @@ void add_primitiveMesh(int type)
|
||||
fill= 1;
|
||||
if(newob) rename_id((ID *)G.obedit, "Plane");
|
||||
if(newob) rename_id((ID *)me, "Plane");
|
||||
undostr="Add Plane";
|
||||
break;
|
||||
case 1: /* cube */
|
||||
tot= 4;
|
||||
@@ -403,6 +339,7 @@ void add_primitiveMesh(int type)
|
||||
fill= 1;
|
||||
if(newob) rename_id((ID *)G.obedit, "Cube");
|
||||
if(newob) rename_id((ID *)me, "Cube");
|
||||
undostr="Add Cube";
|
||||
break;
|
||||
case 4: /* circle */
|
||||
if(button(&tot,3,100,"Vertices:")==0) return;
|
||||
@@ -410,6 +347,8 @@ void add_primitiveMesh(int type)
|
||||
fill= 0;
|
||||
if(newob) rename_id((ID *)G.obedit, "Circle");
|
||||
if(newob) rename_id((ID *)me, "Circle");
|
||||
if(G.scene->selectmode==SCE_SELECT_FACE) notice("Circle is not visible in face mode");
|
||||
undostr="Add Circle";
|
||||
break;
|
||||
case 5: /* cylinder */
|
||||
if(button(&tot,3,100,"Vertices:")==0) return;
|
||||
@@ -417,6 +356,7 @@ void add_primitiveMesh(int type)
|
||||
fill= 1;
|
||||
if(newob) rename_id((ID *)G.obedit, "Cylinder");
|
||||
if(newob) rename_id((ID *)me, "Cylinder");
|
||||
undostr="Add Cylinder";
|
||||
break;
|
||||
case 6: /* tube */
|
||||
if(button(&tot,3,100,"Vertices:")==0) return;
|
||||
@@ -424,6 +364,7 @@ void add_primitiveMesh(int type)
|
||||
fill= 0;
|
||||
if(newob) rename_id((ID *)G.obedit, "Tube");
|
||||
if(newob) rename_id((ID *)me, "Tube");
|
||||
undostr="Add Tube";
|
||||
break;
|
||||
case 7: /* cone */
|
||||
if(button(&tot,3,100,"Vertices:")==0) return;
|
||||
@@ -431,27 +372,32 @@ void add_primitiveMesh(int type)
|
||||
fill= 1;
|
||||
if(newob) rename_id((ID *)G.obedit, "Cone");
|
||||
if(newob) rename_id((ID *)me, "Cone");
|
||||
undostr="Add Cone";
|
||||
break;
|
||||
case 10: /* grid */
|
||||
if(button(&tot,2,100,"X res:")==0) return;
|
||||
if(button(&seg,2,100,"Y res:")==0) return;
|
||||
if(newob) rename_id((ID *)G.obedit, "Grid");
|
||||
if(newob) rename_id((ID *)me, "Grid");
|
||||
undostr="Add Grid";
|
||||
break;
|
||||
case 11: /* UVsphere */
|
||||
if(button(&seg,3,100,"Segments:")==0) return;
|
||||
if(button(&tot,3,100,"Rings:")==0) return;
|
||||
if(newob) rename_id((ID *)G.obedit, "Sphere");
|
||||
if(newob) rename_id((ID *)me, "Sphere");
|
||||
undostr="Add UV Sphere";
|
||||
break;
|
||||
case 12: /* Icosphere */
|
||||
if(button(&subdiv,1,5,"Subdivision:")==0) return;
|
||||
if(newob) rename_id((ID *)G.obedit, "Sphere");
|
||||
if(newob) rename_id((ID *)me, "Sphere");
|
||||
undostr="Add Ico Sphere";
|
||||
break;
|
||||
case 13: /* Monkey */
|
||||
if(newob) rename_id((ID *)G.obedit, "Suzanne");
|
||||
if(newob) rename_id((ID *)me, "Suzanne");
|
||||
undostr="Add Monkey";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -475,7 +421,7 @@ void add_primitiveMesh(int type)
|
||||
|
||||
Mat3MulVecfl(imat, vec);
|
||||
eve= addvertlist(vec);
|
||||
eve->f= 1;
|
||||
eve->f= SELECT;
|
||||
if(a==0) {
|
||||
if(b==0) v1= eve;
|
||||
else v2= eve;
|
||||
@@ -500,8 +446,8 @@ void add_primitiveMesh(int type)
|
||||
vdown= v1;
|
||||
vtop= v2;
|
||||
}
|
||||
if(vtop) vtop->f= 1;
|
||||
if(vdown) vdown->f= 1;
|
||||
if(vtop) vtop->f= SELECT;
|
||||
if(vdown) vdown->f= SELECT;
|
||||
|
||||
/* top and bottom face */
|
||||
if(fill) {
|
||||
@@ -587,9 +533,10 @@ void add_primitiveMesh(int type)
|
||||
vec[1]= dia*phid;
|
||||
Mat3MulVecfl(imat, vec);
|
||||
for(a=0;a<seg-1;a++) {
|
||||
extrudeflag(2,0);
|
||||
extrudeflag_vert(2);
|
||||
translateflag(2, vec);
|
||||
}
|
||||
recalc_editnormals(); // does face centers too
|
||||
}
|
||||
else if(type==11) { /* UVsphere */
|
||||
float tmat[3][3];
|
||||
@@ -626,7 +573,7 @@ void add_primitiveMesh(int type)
|
||||
Mat3MulMat3(cmat, imat, tmat);
|
||||
|
||||
for(a=0; a<seg; a++) {
|
||||
extrudeflag(2, 0);
|
||||
extrudeflag_vert(2);
|
||||
rotateflag(2, v1->co, cmat);
|
||||
}
|
||||
removedoublesflag(4, 0.0001);
|
||||
@@ -677,7 +624,9 @@ void add_primitiveMesh(int type)
|
||||
float v[3];
|
||||
v[0]= (monkeyv[i][0]+127)/128.0, v[1]= monkeyv[i][1]/128.0, v[2]= monkeyv[i][2]/128.0;
|
||||
tv[i]= addvertlist(v);
|
||||
tv[i]->f |= SELECT;
|
||||
tv[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]:addvertlist(v);
|
||||
tv[monkeynv+i]->f |= SELECT;
|
||||
}
|
||||
for (i=0; i<monkeynf; i++) {
|
||||
addfacelist(tv[monkeyf[i][0]+i-monkeyo], tv[monkeyf[i][1]+i-monkeyo], tv[monkeyf[i][2]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeyf[i][3]+i-monkeyo]:NULL, NULL);
|
||||
@@ -685,15 +634,30 @@ void add_primitiveMesh(int type)
|
||||
}
|
||||
|
||||
MEM_freeN(tv);
|
||||
|
||||
/* and now do imat */
|
||||
eve= em->verts.first;
|
||||
while(eve) {
|
||||
if(eve->f & SELECT) {
|
||||
VecAddf(eve->co,eve->co,cent);
|
||||
Mat3MulVecfl(imat,eve->co);
|
||||
}
|
||||
eve= eve->next;
|
||||
}
|
||||
}
|
||||
|
||||
// simple selection flush OK, based on fact it's a single model
|
||||
EM_select_flush(); // flushes vertex -> edge -> face selection
|
||||
|
||||
if(type!=0 && type!=10) righthandfaces(1);
|
||||
countall();
|
||||
|
||||
allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */
|
||||
allqueue(REDRAWALL, 0);
|
||||
makeDispList(G.obedit);
|
||||
|
||||
if (type==13) notice("Oooh Oooh Oooh");
|
||||
|
||||
/* if a new object was created, it stores it in Mesh, for reload original data and undo */
|
||||
if(newob) load_editMesh();
|
||||
BIF_undo_push(undostr);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
@@ -67,22 +68,89 @@ editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data
|
||||
#include "editmesh.h"
|
||||
|
||||
|
||||
/* ********************* */
|
||||
/* ********* Selection ************ */
|
||||
|
||||
int editmesh_nfaces_selected(void)
|
||||
void EM_select_face(EditFace *efa, int sel)
|
||||
{
|
||||
if(sel) {
|
||||
efa->f |= SELECT;
|
||||
efa->e1->f |= SELECT;
|
||||
efa->e2->f |= SELECT;
|
||||
efa->e3->f |= SELECT;
|
||||
if(efa->e4) efa->e4->f |= SELECT;
|
||||
efa->v1->f |= SELECT;
|
||||
efa->v2->f |= SELECT;
|
||||
efa->v3->f |= SELECT;
|
||||
if(efa->v4) efa->v4->f |= SELECT;
|
||||
}
|
||||
else {
|
||||
efa->f &= ~SELECT;
|
||||
efa->e1->f &= ~SELECT;
|
||||
efa->e2->f &= ~SELECT;
|
||||
efa->e3->f &= ~SELECT;
|
||||
if(efa->e4) efa->e4->f &= ~SELECT;
|
||||
efa->v1->f &= ~SELECT;
|
||||
efa->v2->f &= ~SELECT;
|
||||
efa->v3->f &= ~SELECT;
|
||||
if(efa->v4) efa->v4->f &= ~SELECT;
|
||||
}
|
||||
}
|
||||
|
||||
void EM_select_edge(EditEdge *eed, int sel)
|
||||
{
|
||||
if(sel) {
|
||||
eed->f |= SELECT;
|
||||
eed->v1->f |= SELECT;
|
||||
eed->v2->f |= SELECT;
|
||||
}
|
||||
else {
|
||||
eed->f &= ~SELECT;
|
||||
eed->v1->f &= ~SELECT;
|
||||
eed->v2->f &= ~SELECT;
|
||||
}
|
||||
}
|
||||
|
||||
int faceselectedOR(EditFace *efa, int flag)
|
||||
{
|
||||
|
||||
if(efa->v1->f & flag) return 1;
|
||||
if(efa->v2->f & flag) return 1;
|
||||
if(efa->v3->f & flag) return 1;
|
||||
if(efa->v4 && (efa->v4->f & 1)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// replace with (efa->f & SELECT)
|
||||
int faceselectedAND(EditFace *efa, int flag)
|
||||
{
|
||||
if(efa->v1->f & flag) {
|
||||
if(efa->v2->f & flag) {
|
||||
if(efa->v3->f & flag) {
|
||||
if(efa->v4) {
|
||||
if(efa->v4->f & flag) return 1;
|
||||
}
|
||||
else return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int EM_nfaces_selected(void)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
EditFace *efa;
|
||||
int count= 0;
|
||||
|
||||
for (efa= em->faces.first; efa; efa= efa->next)
|
||||
if (faceselectedAND(efa, SELECT))
|
||||
if (efa->f & SELECT)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int editmesh_nvertices_selected(void)
|
||||
int EM_nvertices_selected(void)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
EditVert *eve;
|
||||
@@ -95,22 +163,353 @@ int editmesh_nvertices_selected(void)
|
||||
return count;
|
||||
}
|
||||
|
||||
/* ***************** */
|
||||
|
||||
short extrudeflag(short flag,short type)
|
||||
void EM_clear_flag_all(int flag)
|
||||
{
|
||||
/* when type=1 old extrusion faces are removed (for spin etc) */
|
||||
/* all verts with (flag & 'flag'): extrude */
|
||||
EditMesh *em = G.editMesh;
|
||||
EditVert *eve;
|
||||
EditEdge *eed;
|
||||
EditFace *efa;
|
||||
|
||||
for (eve= em->verts.first; eve; eve= eve->next) eve->f &= ~flag;
|
||||
for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~flag;
|
||||
for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~flag;
|
||||
|
||||
}
|
||||
|
||||
void EM_set_flag_all(int flag)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
EditVert *eve;
|
||||
EditEdge *eed;
|
||||
EditFace *efa;
|
||||
|
||||
for (eve= em->verts.first; eve; eve= eve->next) eve->f |= flag;
|
||||
for (eed= em->edges.first; eed; eed= eed->next) eed->f |= flag;
|
||||
for (efa= em->faces.first; efa; efa= efa->next) efa->f |= flag;
|
||||
|
||||
}
|
||||
|
||||
/* flush to edges & faces */
|
||||
|
||||
/* this based on coherent selected vertices, for example when adding new
|
||||
objects. call clear_flag_all() before you select vertices to be sure it ends OK!
|
||||
|
||||
*/
|
||||
|
||||
void EM_select_flush(void)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
EditEdge *eed;
|
||||
EditFace *efa;
|
||||
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT;
|
||||
}
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
if(efa->v4) {
|
||||
if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT ) efa->f |= SELECT;
|
||||
}
|
||||
else {
|
||||
if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT ) efa->f |= SELECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* flush to edges & faces */
|
||||
|
||||
/* based on select mode it selects edges/faces
|
||||
assumed is that verts/edges/faces were properly selected themselves
|
||||
with the calls above
|
||||
*/
|
||||
|
||||
void EM_selectmode_flush(void)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
EditEdge *eed;
|
||||
EditFace *efa;
|
||||
|
||||
// flush to edges & faces
|
||||
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT;
|
||||
else eed->f &= ~SELECT;
|
||||
}
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
if(efa->v4) {
|
||||
if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT) efa->f |= SELECT;
|
||||
else efa->f &= ~SELECT;
|
||||
}
|
||||
else {
|
||||
if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT) efa->f |= SELECT;
|
||||
else efa->f &= ~SELECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
// flush to faces
|
||||
else if(G.scene->selectmode & SCE_SELECT_EDGE) {
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
if(efa->e4) {
|
||||
if(efa->e1->f & efa->e2->f & efa->e3->f & efa->e4->f & SELECT) efa->f |= SELECT;
|
||||
else efa->f &= ~SELECT;
|
||||
}
|
||||
else {
|
||||
if(efa->e1->f & efa->e2->f & efa->e3->f & SELECT) efa->f |= SELECT;
|
||||
else efa->f &= ~SELECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make sure selected faces have selected edges too, for extrude (hack?)
|
||||
else if(G.scene->selectmode & SCE_SELECT_FACE) {
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
if(efa->f & SELECT) {
|
||||
efa->e1->f |= SELECT;
|
||||
efa->e2->f |= SELECT;
|
||||
efa->e3->f |= SELECT;
|
||||
if(efa->e4) efa->e4->f |= SELECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* when switching select mode, makes sure selection is consistant for editing */
|
||||
/* also for paranoia checks to make sure edge or face mode works */
|
||||
void EM_selectmode_set(void)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
EditVert *eve;
|
||||
EditEdge *eed;
|
||||
EditFace *efa;
|
||||
|
||||
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
|
||||
/* vertices -> edges -> faces */
|
||||
EM_select_flush();
|
||||
}
|
||||
else if(G.scene->selectmode & SCE_SELECT_EDGE) {
|
||||
/* deselect vertices, and select again based on edge select */
|
||||
for(eve= em->verts.first; eve; eve= eve->next) eve->f &= ~SELECT;
|
||||
for(eed= em->edges.first; eed; eed= eed->next)
|
||||
if(eed->f & SELECT) EM_select_edge(eed, 1);
|
||||
/* selects faces based on edge status */
|
||||
EM_selectmode_flush();
|
||||
}
|
||||
else if(G.scene->selectmode == SCE_SELECT_FACE) {
|
||||
/* deselect eges, and select again based on face select */
|
||||
for(eed= em->edges.first; eed; eed= eed->next) EM_select_edge(eed, 0);
|
||||
for(efa= em->faces.first; efa; efa= efa->next)
|
||||
if(efa->f & SELECT) EM_select_face(efa, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ******** EXTRUDE ********* */
|
||||
|
||||
static void set_edge_directions(void)
|
||||
{
|
||||
EditMesh *em= G.editMesh;
|
||||
EditFace *efa= em->faces.first;
|
||||
|
||||
while(efa) {
|
||||
// non selected face
|
||||
if(efa->f== 0) {
|
||||
if(efa->e1->f) {
|
||||
if(efa->e1->v1 == efa->v1) efa->e1->dir= 0;
|
||||
else efa->e1->dir= 1;
|
||||
}
|
||||
if(efa->e2->f) {
|
||||
if(efa->e2->v1 == efa->v2) efa->e2->dir= 0;
|
||||
else efa->e2->dir= 1;
|
||||
}
|
||||
if(efa->e3->f) {
|
||||
if(efa->e3->v1 == efa->v3) efa->e3->dir= 0;
|
||||
else efa->e3->dir= 1;
|
||||
}
|
||||
if(efa->e4 && efa->e4->f) {
|
||||
if(efa->e4->v1 == efa->v4) efa->e4->dir= 0;
|
||||
else efa->e4->dir= 1;
|
||||
}
|
||||
}
|
||||
efa= efa->next;
|
||||
}
|
||||
}
|
||||
|
||||
static short extrudeflag_edge(short flag)
|
||||
{
|
||||
/* all select edges/faces: extrude */
|
||||
/* old select is cleared, in new ones it is set */
|
||||
EditMesh *em = G.editMesh;
|
||||
EditVert *eve, *nextve;
|
||||
EditEdge *eed, *nexted;
|
||||
EditFace *efa, *nextfa;
|
||||
float nor[3]={0.0, 0.0, 0.0};
|
||||
short del_old= 0;
|
||||
|
||||
if(G.obedit==0 || get_mesh(G.obedit)==0) return 0;
|
||||
|
||||
/* selected edges with 0 or 1 selected face become faces */
|
||||
/* selected faces generate new faces */
|
||||
|
||||
/* if *one* selected face has edge with unselected face; remove old selected faces */
|
||||
|
||||
/* if selected edge is not used anymore; remove */
|
||||
/* if selected vertex is not used anymore: remove */
|
||||
|
||||
/* select the new extrusion, deselect old */
|
||||
|
||||
|
||||
/* step 1; init, count faces in edges */
|
||||
recalc_editnormals();
|
||||
|
||||
for(eve= em->verts.first; eve; eve= eve->next) {
|
||||
eve->vn= NULL;
|
||||
eve->f1= 0;
|
||||
}
|
||||
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
eed->f1= 0; // amount of selected faces
|
||||
eed->f2= 0; // amount of unselected faces
|
||||
if(eed->f & SELECT) {
|
||||
eed->v1->f1= 1; // we call this 'selected vertex' now
|
||||
eed->v2->f1= 1;
|
||||
}
|
||||
}
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
if(efa->f & SELECT) {
|
||||
efa->e1->f1++;
|
||||
efa->e2->f1++;
|
||||
efa->e3->f1++;
|
||||
if(efa->e4) efa->e4->f1++;
|
||||
}
|
||||
else {
|
||||
efa->e1->f2++;
|
||||
efa->e2->f2++;
|
||||
efa->e3->f2++;
|
||||
if(efa->e4) efa->e4->f2++;
|
||||
}
|
||||
}
|
||||
|
||||
set_edge_directions();
|
||||
|
||||
/* step 2: make new faces from edges */
|
||||
for(eed= em->edges.last; eed; eed= eed->prev) {
|
||||
if(eed->f & SELECT) {
|
||||
if(eed->f1<2) {
|
||||
if(eed->v1->vn==NULL)
|
||||
eed->v1->vn= addvertlist(eed->v1->co);
|
||||
if(eed->v2->vn==NULL)
|
||||
eed->v2->vn= addvertlist(eed->v2->co);
|
||||
|
||||
if(eed->dir==1) addfacelist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, NULL);
|
||||
else addfacelist(eed->v2, eed->v1, eed->v1->vn, eed->v2->vn, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* step 3: make new faces from faces */
|
||||
for(efa= em->faces.last; efa; efa= efa->prev) {
|
||||
if(efa->f & SELECT) {
|
||||
if(efa->v1->vn==NULL) efa->v1->vn= addvertlist(efa->v1->co);
|
||||
if(efa->v2->vn==NULL) efa->v2->vn= addvertlist(efa->v2->co);
|
||||
if(efa->v3->vn==NULL) efa->v3->vn= addvertlist(efa->v3->co);
|
||||
if(efa->v4 && efa->v4->vn==NULL) efa->v4->vn= addvertlist(efa->v4->co);
|
||||
|
||||
if(efa->v4)
|
||||
addfacelist(efa->v1->vn, efa->v2->vn, efa->v3->vn, efa->v4->vn, efa);
|
||||
else
|
||||
addfacelist(efa->v1->vn, efa->v2->vn, efa->v3->vn, NULL, efa);
|
||||
|
||||
/* if *one* selected face has edge with unselected face; remove old selected faces */
|
||||
if(efa->e1->f2 || efa->e2->f2 || efa->e3->f2 || (efa->e4 && efa->e4->f2))
|
||||
del_old= 1;
|
||||
|
||||
/* for transform */
|
||||
VecAddf(nor, nor, efa->n);
|
||||
}
|
||||
}
|
||||
|
||||
if(del_old) {
|
||||
/* step 4: remove old faces, if del_old */
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
nextfa= efa->next;
|
||||
if(efa->f & SELECT) {
|
||||
BLI_remlink(&em->faces, efa);
|
||||
free_editface(efa);
|
||||
}
|
||||
efa= nextfa;
|
||||
}
|
||||
|
||||
/* step 5: remove selected unused edges */
|
||||
/* start tagging again */
|
||||
for(eed= em->edges.first; eed; eed= eed->next) eed->f1=0;
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
efa->e1->f1= 1;
|
||||
efa->e2->f1= 1;
|
||||
efa->e3->f1= 1;
|
||||
if(efa->e4) efa->e4->f1= 1;
|
||||
}
|
||||
/* remove */
|
||||
eed= em->edges.first;
|
||||
while(eed) {
|
||||
nexted= eed->next;
|
||||
if(eed->f & SELECT) {
|
||||
if(eed->f1==0) {
|
||||
remedge(eed);
|
||||
free_editedge(eed);
|
||||
}
|
||||
}
|
||||
eed= nexted;
|
||||
}
|
||||
|
||||
/* step 6: remove selected unused vertices */
|
||||
for(eed= em->edges.first; eed; eed= eed->next)
|
||||
eed->v1->f1= eed->v2->f1= 0;
|
||||
|
||||
eve= em->verts.first;
|
||||
while(eve) {
|
||||
nextve= eve->next;
|
||||
if(eve->f1) {
|
||||
// hack... but we need it for step 7, redoing selection
|
||||
if(eve->vn) eve->vn->vn= eve->vn;
|
||||
|
||||
BLI_remlink(&em->verts, eve);
|
||||
free_editvert(eve);
|
||||
}
|
||||
eve= nextve;
|
||||
}
|
||||
}
|
||||
|
||||
/* step 7: redo selection */
|
||||
EM_clear_flag_all(SELECT);
|
||||
|
||||
Normalise(nor); // translation normal grab
|
||||
|
||||
for(eve= em->verts.first; eve; eve= eve->next) {
|
||||
if(eve->vn) {
|
||||
eve->vn->f |= SELECT;
|
||||
VECCOPY(eve->vn->no, nor);
|
||||
}
|
||||
}
|
||||
|
||||
EM_select_flush();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
short extrudeflag_vert(short flag)
|
||||
{
|
||||
/* all verts/edges/faces with (f & 'flag'): extrude */
|
||||
/* from old verts, 'flag' is cleared, in new ones it is set */
|
||||
EditMesh *em = G.editMesh;
|
||||
EditVert *eve, *v1, *v2, *v3, *v4, *nextve;
|
||||
EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
|
||||
EditFace *efa, *efa2, *nextvl;
|
||||
short sel=0, deloud= 0, smooth= 0;
|
||||
float nor[3]={0.0, 0.0, 0.0};
|
||||
short sel=0, del_old= 0, smooth= 0;
|
||||
|
||||
if(G.obedit==0 || get_mesh(G.obedit)==0) return 0;
|
||||
|
||||
/* clear vert flag f1, we use this to detext a loose selected vertice */
|
||||
/* clear vert flag f1, we use this to detect a loose selected vertice */
|
||||
eve= em->verts.first;
|
||||
while(eve) {
|
||||
if(eve->f & flag) eve->f1= 1;
|
||||
@@ -121,11 +520,11 @@ short extrudeflag(short flag,short type)
|
||||
eed= em->edges.first;
|
||||
while(eed) {
|
||||
if( (eed->v1->f & flag) && (eed->v2->f & flag) ) {
|
||||
eed->f= 1;
|
||||
eed->f2= 1;
|
||||
eed->v1->f1= 0;
|
||||
eed->v2->f1= 0;
|
||||
}
|
||||
else eed->f= 0;
|
||||
else eed->f2= 0;
|
||||
|
||||
eed->f1= 1; /* this indicates it is an 'old' edge (in this routine we make new ones) */
|
||||
|
||||
@@ -136,7 +535,7 @@ short extrudeflag(short flag,short type)
|
||||
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
efa->f= 0;
|
||||
efa->f1= 0;
|
||||
|
||||
if (efa->flag & ME_SMOOTH) {
|
||||
if (faceselectedOR(efa, 1)) smooth= 1;
|
||||
@@ -148,11 +547,12 @@ short extrudeflag(short flag,short type)
|
||||
e3= efa->e3;
|
||||
e4= efa->e4;
|
||||
|
||||
if(e1->f < 3) e1->f++;
|
||||
if(e2->f < 3) e2->f++;
|
||||
if(e3->f < 3) e3->f++;
|
||||
if(e4 && e4->f < 3) e4->f++;
|
||||
efa->f= 1;
|
||||
if(e1->f2 < 3) e1->f2++;
|
||||
if(e2->f2 < 3) e2->f2++;
|
||||
if(e3->f2 < 3) e3->f2++;
|
||||
if(e4 && e4->f2 < 3) e4->f2++;
|
||||
|
||||
efa->f1= 1;
|
||||
}
|
||||
else if(faceselectedOR(efa, flag)) {
|
||||
e1= efa->e1;
|
||||
@@ -169,51 +569,28 @@ short extrudeflag(short flag,short type)
|
||||
efa= efa->next;
|
||||
}
|
||||
|
||||
/* set direction of edges */
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
if(efa->f== 0) {
|
||||
if(efa->e1->f==2) {
|
||||
if(efa->e1->v1 == efa->v1) efa->e1->dir= 0;
|
||||
else efa->e1->dir= 1;
|
||||
}
|
||||
if(efa->e2->f==2) {
|
||||
if(efa->e2->v1 == efa->v2) efa->e2->dir= 0;
|
||||
else efa->e2->dir= 1;
|
||||
}
|
||||
if(efa->e3->f==2) {
|
||||
if(efa->e3->v1 == efa->v3) efa->e3->dir= 0;
|
||||
else efa->e3->dir= 1;
|
||||
}
|
||||
if(efa->e4 && efa->e4->f==2) {
|
||||
if(efa->e4->v1 == efa->v4) efa->e4->dir= 0;
|
||||
else efa->e4->dir= 1;
|
||||
}
|
||||
}
|
||||
efa= efa->next;
|
||||
}
|
||||
|
||||
set_edge_directions();
|
||||
|
||||
/* the current state now is:
|
||||
eve->f1==1: loose selected vertex
|
||||
|
||||
eed->f==0 : edge is not selected, no extrude
|
||||
eed->f==1 : edge selected, is not part of a face, extrude
|
||||
eed->f==2 : edge selected, is part of 1 face, extrude
|
||||
eed->f==3 : edge selected, is part of more faces, no extrude
|
||||
eed->f2==0 : edge is not selected, no extrude
|
||||
eed->f2==1 : edge selected, is not part of a face, extrude
|
||||
eed->f2==2 : edge selected, is part of 1 face, extrude
|
||||
eed->f2==3 : edge selected, is part of more faces, no extrude
|
||||
|
||||
eed->f1==0: new edge
|
||||
eed->f1==1: edge selected, is part of selected face, when eed->f==3: remove
|
||||
eed->f1==2: edge selected, is not part of a selected face
|
||||
eed->f1==2: edge selected, part of a partially selected face
|
||||
|
||||
efa->f==1 : duplicate this face
|
||||
efa->f1==1 : duplicate this face
|
||||
*/
|
||||
|
||||
/* copy all selected vertices, */
|
||||
/* write pointer to new vert in old struct at eve->vn */
|
||||
eve= em->verts.last;
|
||||
while(eve) {
|
||||
eve->f&= ~128; /* clear, for later test for loose verts */
|
||||
eve->f &= ~128; /* clear, for later test for loose verts */
|
||||
if(eve->f & flag) {
|
||||
sel= 1;
|
||||
v1= addvertlist(0);
|
||||
@@ -229,17 +606,24 @@ short extrudeflag(short flag,short type)
|
||||
|
||||
if(sel==0) return 0;
|
||||
|
||||
/* all edges with eed->f==1 or eed->f==2 become faces */
|
||||
/* if deloud==1 then edges with eed->f>2 are removed */
|
||||
/* all edges with eed->f2==1 or eed->f2==2 become faces */
|
||||
|
||||
/* if del_old==1 then extrude is in partial geometry, to keep it manifold.
|
||||
verts with f1==0 and (eve->f & 128)==0) are removed
|
||||
edges with eed->f2>2 are removed
|
||||
faces with efa->f1 are removed
|
||||
if del_old==0 the extrude creates a volume.
|
||||
*/
|
||||
|
||||
eed= em->edges.last;
|
||||
while(eed) {
|
||||
nexted= eed->prev;
|
||||
if( eed->f<3) {
|
||||
eed->v1->f|=128; /* = no loose vert! */
|
||||
eed->v2->f|=128;
|
||||
if( eed->f2<3) {
|
||||
eed->v1->f |= 128; /* = no loose vert! */
|
||||
eed->v2->f |= 128;
|
||||
}
|
||||
if( (eed->f==1 || eed->f==2) ) {
|
||||
if(eed->f1==2) deloud=1;
|
||||
if( (eed->f2==1 || eed->f2==2) ) {
|
||||
if(eed->f1==2) del_old= 1;
|
||||
|
||||
if(eed->dir==1) efa2= addfacelist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, NULL);
|
||||
else efa2= addfacelist(eed->v2, eed->v1, eed->v1->vn, eed->v2->vn, NULL);
|
||||
@@ -257,22 +641,22 @@ short extrudeflag(short flag,short type)
|
||||
|
||||
eed= nexted;
|
||||
}
|
||||
if(deloud) {
|
||||
if(del_old) {
|
||||
eed= em->edges.first;
|
||||
while(eed) {
|
||||
nexted= eed->next;
|
||||
if(eed->f==3 && eed->f1==1) {
|
||||
if(eed->f2==3 && eed->f1==1) {
|
||||
remedge(eed);
|
||||
free_editedge(eed);
|
||||
}
|
||||
eed= nexted;
|
||||
}
|
||||
}
|
||||
/* duplicate faces, if necessart remove old ones */
|
||||
/* duplicate faces, if necessary remove old ones */
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
nextvl= efa->next;
|
||||
if(efa->f & 1) {
|
||||
if(efa->f1 & 1) {
|
||||
|
||||
v1= efa->v1->vn;
|
||||
v2= efa->v2->vn;
|
||||
@@ -281,7 +665,10 @@ short extrudeflag(short flag,short type)
|
||||
|
||||
efa2= addfacelist(v1, v2, v3, v4, efa);
|
||||
|
||||
if(deloud) {
|
||||
/* for transform */
|
||||
VecAddf(nor, nor, efa->n);
|
||||
|
||||
if(del_old) {
|
||||
BLI_remlink(&em->faces, efa);
|
||||
free_editface(efa);
|
||||
}
|
||||
@@ -289,9 +676,12 @@ short extrudeflag(short flag,short type)
|
||||
}
|
||||
efa= nextvl;
|
||||
}
|
||||
|
||||
Normalise(nor); // for grab
|
||||
|
||||
/* for all vertices with eve->vn!=0
|
||||
if eve->f1==1: make edge
|
||||
if flag!=128 : if deloud==1: remove
|
||||
if flag!=128 : if del_old==1: remove
|
||||
*/
|
||||
eve= em->verts.last;
|
||||
while(eve) {
|
||||
@@ -299,21 +689,35 @@ short extrudeflag(short flag,short type)
|
||||
if(eve->vn) {
|
||||
if(eve->f1==1) addedgelist(eve, eve->vn, NULL);
|
||||
else if( (eve->f & 128)==0) {
|
||||
if(deloud) {
|
||||
if(del_old) {
|
||||
BLI_remlink(&em->verts,eve);
|
||||
free_editvert(eve);
|
||||
eve= NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(eve) eve->f&= ~128;
|
||||
|
||||
if(eve) {
|
||||
if(eve->f & flag) {
|
||||
VECCOPY(eve->no, nor);
|
||||
}
|
||||
eve->f &= ~128;
|
||||
}
|
||||
eve= nextve;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* generic extrude */
|
||||
short extrudeflag(short flag)
|
||||
{
|
||||
if(G.scene->selectmode & SCE_SELECT_VERTEX)
|
||||
return extrudeflag_vert(flag);
|
||||
else
|
||||
return extrudeflag_edge(flag);
|
||||
|
||||
}
|
||||
|
||||
void rotateflag(short flag, float *cent, float rotmat[][3])
|
||||
{
|
||||
/* all verts with (flag & 'flag') rotate */
|
||||
@@ -352,32 +756,92 @@ void translateflag(short flag, float *vec)
|
||||
}
|
||||
}
|
||||
|
||||
void adduplicateflag(int flag)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
/* old selection has flag 128 set, and flag 'flag' cleared
|
||||
new selection has flag 'flag' set */
|
||||
EditVert *eve, *v1, *v2, *v3, *v4;
|
||||
EditEdge *eed, *newed;
|
||||
EditFace *efa, *newfa;
|
||||
|
||||
EM_clear_flag_all(128);
|
||||
EM_selectmode_set(); // paranoia check, selection now is consistant
|
||||
|
||||
/* vertices first */
|
||||
for(eve= em->verts.last; eve; eve= eve->prev) {
|
||||
|
||||
if(eve->f & flag) {
|
||||
v1= addvertlist(eve->co);
|
||||
|
||||
v1->f= eve->f;
|
||||
eve->f-= flag;
|
||||
eve->f|= 128;
|
||||
|
||||
eve->vn= v1;
|
||||
|
||||
/* >>>>> FIXME: Copy deformation weight ? */
|
||||
v1->totweight = eve->totweight;
|
||||
if (eve->totweight){
|
||||
v1->dw = MEM_mallocN (eve->totweight * sizeof(MDeformWeight), "deformWeight");
|
||||
memcpy (v1->dw, eve->dw, eve->totweight * sizeof(MDeformWeight));
|
||||
}
|
||||
else
|
||||
v1->dw=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* copy edges */
|
||||
for(eed= em->edges.last; eed; eed= eed->prev) {
|
||||
if( eed->f & flag ) {
|
||||
v1= eed->v1->vn;
|
||||
v2= eed->v2->vn;
|
||||
newed= addedgelist(v1, v2, eed);
|
||||
|
||||
newed->f= eed->f;
|
||||
eed->f -= flag;
|
||||
eed->f |= 128;
|
||||
}
|
||||
}
|
||||
|
||||
/* then dupicate faces */
|
||||
for(efa= em->faces.last; efa; efa= efa->prev) {
|
||||
if(efa->f & flag) {
|
||||
v1= efa->v1->vn;
|
||||
v2= efa->v2->vn;
|
||||
v3= efa->v3->vn;
|
||||
if(efa->v4) v4= efa->v4->vn; else v4= NULL;
|
||||
newfa= addfacelist(v1, v2, v3, v4, efa);
|
||||
|
||||
newfa->f= efa->f;
|
||||
efa->f -= flag;
|
||||
efa->f |= 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void delfaceflag(int flag)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
/* delete all faces with 'flag', including edges and loose vertices */
|
||||
/* in vertices the 'flag' is cleared */
|
||||
/* in remaining vertices/edges 'flag' is cleared */
|
||||
EditVert *eve,*nextve;
|
||||
EditEdge *eed, *nexted;
|
||||
EditFace *efa,*nextvl;
|
||||
|
||||
eed= em->edges.first;
|
||||
while(eed) {
|
||||
eed->f= 0;
|
||||
eed= eed->next;
|
||||
}
|
||||
for(eed= em->edges.first; eed; eed= eed->next) eed->f2= 0;
|
||||
|
||||
/* delete faces */
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
nextvl= efa->next;
|
||||
if(faceselectedAND(efa, flag)) {
|
||||
if(efa->f & flag) {
|
||||
|
||||
efa->e1->f= 1;
|
||||
efa->e2->f= 1;
|
||||
efa->e3->f= 1;
|
||||
efa->e1->f2= 1;
|
||||
efa->e2->f2= 1;
|
||||
efa->e3->f2= 1;
|
||||
if(efa->e4) {
|
||||
efa->e4->f= 1;
|
||||
efa->e4->f2= 1;
|
||||
}
|
||||
|
||||
BLI_remlink(&em->faces, efa);
|
||||
@@ -385,33 +849,34 @@ void delfaceflag(int flag)
|
||||
}
|
||||
efa= nextvl;
|
||||
}
|
||||
/* all faces with 1, 2 (3) vertices selected: make sure we keep the edges */
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
efa->e1->f= 0;
|
||||
efa->e2->f= 0;
|
||||
efa->e3->f= 0;
|
||||
|
||||
/* all remaining faces: make sure we keep the edges */
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
efa->e1->f2= 0;
|
||||
efa->e2->f2= 0;
|
||||
efa->e3->f2= 0;
|
||||
if(efa->e4) {
|
||||
efa->e4->f= 0;
|
||||
efa->e4->f2= 0;
|
||||
}
|
||||
|
||||
efa= efa->next;
|
||||
}
|
||||
|
||||
/* test all edges for vertices with 'flag', and clear */
|
||||
/* remove tagged edges, and clear remaining ones */
|
||||
eed= em->edges.first;
|
||||
while(eed) {
|
||||
nexted= eed->next;
|
||||
if(eed->f==1) {
|
||||
|
||||
if(eed->f2==1) {
|
||||
remedge(eed);
|
||||
free_editedge(eed);
|
||||
}
|
||||
else if( (eed->v1->f & flag) || (eed->v2->f & flag) ) {
|
||||
eed->v1->f&= ~flag;
|
||||
eed->v2->f&= ~flag;
|
||||
else {
|
||||
eed->f &= ~flag;
|
||||
eed->v1->f &= ~flag;
|
||||
eed->v2->f &= ~flag;
|
||||
}
|
||||
eed= nexted;
|
||||
}
|
||||
|
||||
/* vertices with 'flag' now are the loose ones, and will be removed */
|
||||
eve= em->verts.first;
|
||||
while(eve) {
|
||||
@@ -547,7 +1012,7 @@ void vertexnormals(int testflip)
|
||||
/* vertex normal flip-flags for shade (render) */
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
efa->f=0;
|
||||
efa->puno=0;
|
||||
|
||||
if(testflip) {
|
||||
f1= efa->v1->no;
|
||||
@@ -556,21 +1021,21 @@ void vertexnormals(int testflip)
|
||||
|
||||
fac1= efa->n[0]*f1[0] + efa->n[1]*f1[1] + efa->n[2]*f1[2];
|
||||
if(fac1<0.0) {
|
||||
efa->f = ME_FLIPV1;
|
||||
efa->puno = ME_FLIPV1;
|
||||
}
|
||||
fac2= efa->n[0]*f2[0] + efa->n[1]*f2[1] + efa->n[2]*f2[2];
|
||||
if(fac2<0.0) {
|
||||
efa->f += ME_FLIPV2;
|
||||
efa->puno += ME_FLIPV2;
|
||||
}
|
||||
fac3= efa->n[0]*f3[0] + efa->n[1]*f3[1] + efa->n[2]*f3[2];
|
||||
if(fac3<0.0) {
|
||||
efa->f += ME_FLIPV3;
|
||||
efa->puno += ME_FLIPV3;
|
||||
}
|
||||
if(efa->v4) {
|
||||
f4= efa->v4->no;
|
||||
fac4= efa->n[0]*f4[0] + efa->n[1]*f4[1] + efa->n[2]*f4[2];
|
||||
if(fac4<0.0) {
|
||||
efa->f += ME_FLIPV4;
|
||||
efa->puno += ME_FLIPV4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -579,9 +1044,9 @@ void vertexnormals(int testflip)
|
||||
yn= fabs(efa->n[1]);
|
||||
zn= fabs(efa->n[2]);
|
||||
|
||||
if(zn>xn && zn>yn) efa->f += ME_PROJXY;
|
||||
else if(yn>xn && yn>zn) efa->f += ME_PROJXZ;
|
||||
else efa->f += ME_PROJYZ;
|
||||
if(zn>xn && zn>yn) efa->puno += ME_PROJXY;
|
||||
else if(yn>xn && yn>zn) efa->puno += ME_PROJXZ;
|
||||
else efa->puno += ME_PROJYZ;
|
||||
|
||||
efa= efa->next;
|
||||
}
|
||||
@@ -624,7 +1089,7 @@ void flip_editnormals(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* does face centers too */
|
||||
void recalc_editnormals(void)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
@@ -632,37 +1097,19 @@ void recalc_editnormals(void)
|
||||
|
||||
efa= em->faces.first;
|
||||
while(efa) {
|
||||
if(efa->v4) CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n);
|
||||
else CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
|
||||
if(efa->v4) {
|
||||
CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n);
|
||||
CalcCent4f(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
|
||||
}
|
||||
else {
|
||||
CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
|
||||
CalcCent3f(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co);
|
||||
}
|
||||
efa= efa->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int faceselectedOR(EditFace *efa, int flag)
|
||||
{
|
||||
|
||||
if(efa->v1->f & flag) return 1;
|
||||
if(efa->v2->f & flag) return 1;
|
||||
if(efa->v3->f & flag) return 1;
|
||||
if(efa->v4 && (efa->v4->f & 1)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int faceselectedAND(EditFace *efa, int flag)
|
||||
{
|
||||
if(efa->v1->f & flag) {
|
||||
if(efa->v2->f & flag) {
|
||||
if(efa->v3->f & flag) {
|
||||
if(efa->v4) {
|
||||
if(efa->v4->f & flag) return 1;
|
||||
}
|
||||
else return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int compareface(EditFace *vl1, EditFace *vl2)
|
||||
{
|
||||
|
||||
@@ -136,7 +136,9 @@ short sharesFace(EditEdge* e1, EditEdge* e2)
|
||||
}
|
||||
/* This function selects a vertex loop based on a each succesive edge having a valance of 4
|
||||
and not sharing a face with the previous edge */
|
||||
|
||||
|
||||
/* It uses ->f flags still, which isn't causing bugs now, but better be put in ->f1 (ton) */
|
||||
|
||||
void vertex_loop_select()
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
@@ -144,10 +146,9 @@ void vertex_loop_select()
|
||||
EditEdge *search=NULL,*startEdge=NULL,*valSearch = NULL,*nearest = NULL,*compEdge;
|
||||
EditEdge *EdgeVal[5] = {NULL,NULL,NULL,NULL,NULL};
|
||||
short numEdges=0,curEdge = 0,looking = 1,edgeValCount = 0,i=0,looped = 0,choosing = 1,event,noloop=0,cancel=0, val;
|
||||
short protect = 0;
|
||||
short protect = 0, dist= 50;
|
||||
short mvalo[2] = {0,0}, mval[2];
|
||||
|
||||
undo_push_mesh("Select Vertex Loop");
|
||||
SetBlenderCursor(BC_VLOOPCURSOR);
|
||||
for(search=em->edges.first;search;search=search->next)
|
||||
numEdges++;
|
||||
@@ -161,7 +162,8 @@ void vertex_loop_select()
|
||||
mvalo[1] = mval[1];
|
||||
|
||||
scrarea_do_windraw(curarea);
|
||||
nearest = findnearestedge();
|
||||
dist= 50;
|
||||
nearest = findnearestedge(&dist); // returns actual distance in dist
|
||||
if (nearest && edgeFaces(nearest)==2) {
|
||||
for(search = em->edges.first;search;search=search->next)
|
||||
search->f &= ~32;
|
||||
@@ -323,11 +325,14 @@ void vertex_loop_select()
|
||||
}
|
||||
if(!cancel){
|
||||
/* If this is a unmodified select, clear the selection */
|
||||
|
||||
/* XXX note that !1 is 0, so it not only clears bit 1 (ton) */
|
||||
if(!(G.qual & LR_SHIFTKEY) && !(G.qual & LR_ALTKEY)){
|
||||
for(search = em->edges.first;search;search= search->next){
|
||||
search->v1->f &= !1;
|
||||
search->v2->f &= !1;
|
||||
}
|
||||
EM_clear_flag_all(SELECT); /* XXX probably that's sufficient */
|
||||
}
|
||||
/* Alt was not pressed, so add to the selection */
|
||||
if(!(G.qual & LR_ALTKEY)){
|
||||
@@ -338,21 +343,26 @@ void vertex_loop_select()
|
||||
}
|
||||
search->f &= ~32;
|
||||
}
|
||||
/* XXX this will correctly flush */
|
||||
}
|
||||
/* alt was pressed, so subtract from the selection */
|
||||
else
|
||||
{
|
||||
/* XXX this doesnt flush correct in face select mode */
|
||||
for(search = em->edges.first;search;search= search->next){
|
||||
if(search->f & 32){
|
||||
search->v1->f &= !1;
|
||||
search->v2->f &= !1;
|
||||
EM_select_edge(search, 0); // the call to deselect edge
|
||||
}
|
||||
search->f &= ~32;
|
||||
}
|
||||
}
|
||||
|
||||
EM_select_flush(); // flushes vertex -> edge -> face selection
|
||||
BIF_undo_push("Select Vertex Loop");
|
||||
}
|
||||
else
|
||||
undo_pop_mesh(1);
|
||||
|
||||
addqueue(curarea->win, REDRAW, 1);
|
||||
SetBlenderCursor(SYSCURSOR);
|
||||
return;
|
||||
@@ -523,7 +533,8 @@ CutCurve *get_mouse_trail(int *len, char mode){
|
||||
/* prototype */
|
||||
short seg_intersect(struct EditEdge * e, CutCurve *c, int len);
|
||||
|
||||
void KnifeSubdivide(char mode){
|
||||
void KnifeSubdivide(char mode)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
int oldcursor, len=0;
|
||||
short isect=0;
|
||||
@@ -533,7 +544,7 @@ void KnifeSubdivide(char mode){
|
||||
|
||||
if (G.obedit==0) return;
|
||||
|
||||
if (editmesh_nvertices_selected() < 2) {
|
||||
if (EM_nvertices_selected() < 2) {
|
||||
error("No edges are selected to operate on");
|
||||
return;
|
||||
}
|
||||
@@ -544,8 +555,6 @@ void KnifeSubdivide(char mode){
|
||||
mode= val; // warning, mode is char, pupmenu returns -1 with ESC
|
||||
}
|
||||
|
||||
undo_push_mesh("Knife");
|
||||
|
||||
calc_meshverts_ext(); /*Update screen coords for current window */
|
||||
|
||||
/* Set a knife cursor here */
|
||||
@@ -560,15 +569,15 @@ void KnifeSubdivide(char mode){
|
||||
if (curve && len && mode){
|
||||
eed= em->edges.first;
|
||||
while(eed) {
|
||||
if((eed->v1->f&1)&&(eed->v2->f&1)){
|
||||
if((eed->v1->f & 1) && (eed->v2->f & 1)){
|
||||
isect=seg_intersect(eed, curve, len);
|
||||
if (isect) eed->f=1;
|
||||
else eed->f=0;
|
||||
eed->f1=isect;
|
||||
if (isect) eed->f2= 1;
|
||||
else eed->f2=0;
|
||||
eed->f1= isect;
|
||||
//printf("isect=%i\n", isect);
|
||||
}
|
||||
else {
|
||||
eed->f=0;
|
||||
eed->f2=0;
|
||||
eed->f1=0;
|
||||
}
|
||||
eed= eed->next;
|
||||
@@ -579,7 +588,7 @@ void KnifeSubdivide(char mode){
|
||||
|
||||
eed=em->edges.first;
|
||||
while(eed){
|
||||
eed->f=0;
|
||||
eed->f2=0;
|
||||
eed->f1=0;
|
||||
eed=eed->next;
|
||||
}
|
||||
@@ -589,6 +598,8 @@ void KnifeSubdivide(char mode){
|
||||
addqueue(curarea->win, REDRAW, 0);
|
||||
window_set_cursor(win, oldcursor);
|
||||
if (curve) MEM_freeN(curve);
|
||||
|
||||
BIF_undo_push("Knife");
|
||||
}
|
||||
|
||||
/* seg_intersect() Determines if and where a mouse trail intersects an EditEdge */
|
||||
@@ -701,9 +712,9 @@ short seg_intersect(EditEdge *e, CutCurve *c, int len){
|
||||
|
||||
/* ******************** LOOP ******************************************* */
|
||||
|
||||
/* BTW: this loop function is totally out of control!
|
||||
/* XXX: this loop function is totally out of control!
|
||||
can be half the code, and using structured functions (ton) */
|
||||
|
||||
|
||||
/*
|
||||
functionality: various loop functions
|
||||
parameters: mode tells the function what it should do with the loop:
|
||||
@@ -792,9 +803,6 @@ void loopoperations(char mode)
|
||||
|
||||
if ((G.obedit==0) || (em->faces.first==0)) return;
|
||||
|
||||
if(mode==LOOP_CUT)undo_push_mesh("Face Loop Subdivide");
|
||||
else if(mode==LOOP_SELECT)undo_push_mesh("Select Face Loop");
|
||||
|
||||
SetBlenderCursor(BC_VLOOPCURSOR);
|
||||
|
||||
start=NULL;
|
||||
@@ -1212,10 +1220,12 @@ void loopoperations(char mode)
|
||||
/* If this is a unmodified select, clear the selection */
|
||||
if(!(G.qual & LR_SHIFTKEY) && !(G.qual & LR_ALTKEY)){
|
||||
for(efa= em->faces.first;efa;efa=efa->next){
|
||||
// note: !1 is zero.... (ton)
|
||||
efa->v1->f &= !1;
|
||||
efa->v2->f &= !1;
|
||||
efa->v3->f &= !1;
|
||||
if(efa->v4)efa->v4->f &= !1;
|
||||
if(efa->v4)efa->v4->f &= !1;
|
||||
EM_select_face(efa, 0); // and this is correct deselect face
|
||||
}
|
||||
}
|
||||
/* Alt was not pressed, so add to the selection */
|
||||
@@ -1225,7 +1235,8 @@ void loopoperations(char mode)
|
||||
efa->v1->f |= 1;
|
||||
efa->v2->f |= 1;
|
||||
efa->v3->f |= 1;
|
||||
if(efa->v4)efa->v4->f |= 1;
|
||||
if(efa->v4) efa->v4->f |= 1;
|
||||
EM_select_face(efa, 1); // and this is correct select face
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,6 +1249,7 @@ void loopoperations(char mode)
|
||||
efa->v2->f &= !1;
|
||||
efa->v3->f &= !1;
|
||||
if(efa->v4)efa->v4->f &= !1;
|
||||
EM_select_face(efa, 0); // this is correct deselect face
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1802,6 +1814,10 @@ void loopoperations(char mode)
|
||||
efa->f &= ~(4|8);
|
||||
}
|
||||
|
||||
// flushes vertex -> edge -> face selection
|
||||
// this actually can be wrong.... but I can't fix above code! (ton)
|
||||
EM_select_flush();
|
||||
|
||||
countall();
|
||||
|
||||
if(tagged)
|
||||
@@ -1814,6 +1830,11 @@ void loopoperations(char mode)
|
||||
/* send event to redraw this window, does header too */
|
||||
SetBlenderCursor(SYSCURSOR);
|
||||
addqueue(curarea->win, REDRAW, 1);
|
||||
|
||||
/* should have check for cancelled (ton) */
|
||||
if(mode==LOOP_CUT) BIF_undo_push("Face Loop Subdivide");
|
||||
else if(mode==LOOP_SELECT) BIF_undo_push("Select Face Loop");
|
||||
|
||||
}
|
||||
|
||||
/* ****************************** END LOOPOPERATIONS ********************** */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
329
source/blender/src/editmode_undo.c
Normal file
329
source/blender/src/editmode_undo.c
Normal file
@@ -0,0 +1,329 @@
|
||||
/**
|
||||
* $Id:
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version. The Blender
|
||||
* Foundation also sells licenses for use in proprietary software under
|
||||
* the Blender License. See http://www.blender.org/BL/ for information
|
||||
* about this.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include "BLI_winstuff.h"
|
||||
#endif
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_global.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_editVert.h"
|
||||
#include "BLI_dynstr.h"
|
||||
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "BIF_editmesh.h"
|
||||
#include "BIF_interface.h"
|
||||
#include "BIF_screen.h"
|
||||
#include "BIF_resources.h"
|
||||
#include "BIF_toolbox.h"
|
||||
#include "BIF_space.h"
|
||||
|
||||
#include "BDR_editcurve.h"
|
||||
|
||||
#include "BSE_edit.h"
|
||||
|
||||
#include "mydevice.h"
|
||||
|
||||
/* ***************** generic editmode undo system ********************* */
|
||||
/*
|
||||
|
||||
Add this in your local code:
|
||||
|
||||
void undo_editmode_push(char *name,
|
||||
void (*freedata)(void *), // pointer to function freeing data
|
||||
void (*to_editmode)(void *), // data to editmode conversion
|
||||
void * (*from_editmode)(void)) // editmode to data conversion
|
||||
|
||||
|
||||
Further exported for UI is:
|
||||
|
||||
void undo_editmode_step(int step); // undo and redo
|
||||
void undo_editmode_clear(void) // free & clear all data
|
||||
void undo_editmode_menu(void) // history menu
|
||||
|
||||
|
||||
*/
|
||||
/* ********************************************************************* */
|
||||
|
||||
|
||||
#define MAXUNDONAME 64
|
||||
typedef struct UndoElem {
|
||||
struct UndoElem *next, *prev;
|
||||
Object *ob;
|
||||
void *undodata;
|
||||
char name[MAXUNDONAME];
|
||||
void (*freedata)(void *);
|
||||
void (*to_editmode)(void *);
|
||||
void * (*from_editmode)(void);
|
||||
} UndoElem;
|
||||
|
||||
static ListBase undobase={NULL, NULL};
|
||||
static UndoElem *curundo= NULL;
|
||||
|
||||
|
||||
/* ********************* xtern api calls ************* */
|
||||
|
||||
static void undo_restore(UndoElem *undo)
|
||||
{
|
||||
if(undo) {
|
||||
waitcursor(1);
|
||||
undo->to_editmode(undo->undodata); // also frees editmode itself
|
||||
waitcursor(0);
|
||||
|
||||
countall();
|
||||
}
|
||||
}
|
||||
|
||||
/* name can be a dynamic string */
|
||||
void undo_editmode_push(char *name, void (*freedata)(void *),
|
||||
void (*to_editmode)(void *), void *(*from_editmode)(void))
|
||||
{
|
||||
UndoElem *uel;
|
||||
int nr;
|
||||
|
||||
/* prevent two same undocalls */
|
||||
if(curundo && strcmp("Original", name)==0) {
|
||||
if(curundo->ob==G.obedit) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* remove all undos after (also when curundo==NULL) */
|
||||
while(undobase.last != curundo) {
|
||||
uel= undobase.last;
|
||||
BLI_remlink(&undobase, uel);
|
||||
uel->freedata(uel->undodata);
|
||||
MEM_freeN(uel);
|
||||
}
|
||||
|
||||
/* make new */
|
||||
curundo= uel= MEM_callocN(sizeof(UndoElem), "undo file");
|
||||
strncpy(uel->name, name, MAXUNDONAME-1);
|
||||
BLI_addtail(&undobase, uel);
|
||||
|
||||
uel->freedata= freedata;
|
||||
uel->to_editmode= to_editmode;
|
||||
uel->from_editmode= from_editmode;
|
||||
|
||||
/* and limit amount to the maximum */
|
||||
nr= 0;
|
||||
uel= undobase.last;
|
||||
while(uel) {
|
||||
nr++;
|
||||
if(nr==U.undosteps) break;
|
||||
uel= uel->prev;
|
||||
}
|
||||
if(uel) {
|
||||
while(undobase.first!=uel) {
|
||||
UndoElem *first= undobase.first;
|
||||
BLI_remlink(&undobase, first);
|
||||
uel->freedata(uel->undodata);
|
||||
MEM_freeN(first);
|
||||
}
|
||||
}
|
||||
|
||||
/* copy */
|
||||
curundo->undodata= curundo->from_editmode();
|
||||
|
||||
curundo->ob= G.obedit;
|
||||
}
|
||||
|
||||
|
||||
/* helper to remove clean other objects from undo stack */
|
||||
static void undo_clean_stack(void)
|
||||
{
|
||||
UndoElem *uel, *next;
|
||||
int mixed= 0;
|
||||
|
||||
uel= undobase.first;
|
||||
while(uel) {
|
||||
next= uel->next;
|
||||
if(uel->ob!=G.obedit) {
|
||||
mixed= 1;
|
||||
BLI_remlink(&undobase, uel);
|
||||
uel->freedata(uel->undodata);
|
||||
MEM_freeN(uel);
|
||||
}
|
||||
uel= next;
|
||||
}
|
||||
|
||||
if(mixed) curundo= undobase.last;
|
||||
}
|
||||
|
||||
/* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */
|
||||
void undo_editmode_step(int step)
|
||||
{
|
||||
|
||||
/* prevent undo to happen on wrong object, stack can be a mix */
|
||||
undo_clean_stack();
|
||||
|
||||
if(step==0) {
|
||||
undo_restore(curundo); // if NULL, reloads editmesh
|
||||
}
|
||||
else if(step==1) {
|
||||
|
||||
if(curundo==NULL || curundo->prev==NULL) error("No more steps to undo");
|
||||
else {
|
||||
printf("undo %s\n", curundo->name);
|
||||
curundo= curundo->prev;
|
||||
undo_restore(curundo); // if NULL, reloads editmesh
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* curundo has to remain current situation! */
|
||||
|
||||
if(curundo==NULL || curundo->next==NULL) error("No more steps to redo");
|
||||
else {
|
||||
undo_restore(curundo->next);
|
||||
curundo= curundo->next;
|
||||
printf("redo %s\n", curundo->name);
|
||||
}
|
||||
}
|
||||
|
||||
makeDispList(G.obedit);
|
||||
// type specific redraw events...
|
||||
if(G.obedit->type==OB_CURVE) curve_changes_other_objects(G.obedit);
|
||||
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWIMAGE, 0);
|
||||
}
|
||||
|
||||
void undo_editmode_clear(void)
|
||||
{
|
||||
UndoElem *uel;
|
||||
|
||||
uel= undobase.first;
|
||||
while(uel) {
|
||||
uel->freedata(uel->undodata);
|
||||
uel= uel->next;
|
||||
}
|
||||
BLI_freelistN(&undobase);
|
||||
curundo= NULL;
|
||||
}
|
||||
|
||||
/* based on index nr it does a restore */
|
||||
static void undo_number(int nr)
|
||||
{
|
||||
UndoElem *uel;
|
||||
int a=1;
|
||||
|
||||
for(uel= undobase.first; uel; uel= uel->next, a++) {
|
||||
if(a==nr) break;
|
||||
}
|
||||
curundo= uel;
|
||||
undo_editmode_step(0);
|
||||
}
|
||||
|
||||
/* ************** for interaction with menu/pullown */
|
||||
|
||||
void undo_editmode_menu(void)
|
||||
{
|
||||
UndoElem *uel;
|
||||
DynStr *ds= BLI_dynstr_new();
|
||||
short event;
|
||||
char *menu;
|
||||
|
||||
undo_clean_stack(); // removes other objects from it
|
||||
|
||||
BLI_dynstr_append(ds, "Undo History %t");
|
||||
|
||||
for(uel= undobase.first; uel; uel= uel->next) {
|
||||
BLI_dynstr_append(ds, "|");
|
||||
BLI_dynstr_append(ds, uel->name);
|
||||
}
|
||||
|
||||
menu= BLI_dynstr_get_cstring(ds);
|
||||
BLI_dynstr_free(ds);
|
||||
|
||||
event= pupmenu_col(menu, 20);
|
||||
MEM_freeN(menu);
|
||||
|
||||
if(event>0) undo_number(event);
|
||||
}
|
||||
|
||||
static void do_editmode_undohistorymenu(void *arg, int event)
|
||||
{
|
||||
|
||||
if(G.obedit==NULL || event<1) return;
|
||||
|
||||
if (event==1) {
|
||||
if(G.obedit->type==OB_MESH) remake_editMesh();
|
||||
}
|
||||
else undo_number(event-1);
|
||||
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
}
|
||||
|
||||
uiBlock *editmode_undohistorymenu(void *arg_unused)
|
||||
{
|
||||
uiBlock *block;
|
||||
UndoElem *uel;
|
||||
short yco = 20, menuwidth = 120;
|
||||
short item=2;
|
||||
|
||||
block= uiNewBlock(&curarea->uiblocks, "view3d_edit_mesh_undohistorymenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
|
||||
uiBlockSetButmFunc(block, do_editmode_undohistorymenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo All Changes|Ctrl U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
|
||||
|
||||
for(uel= undobase.first; uel; uel= uel->next, item++) {
|
||||
if (uel==curundo) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, uel->name, 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, (float)item, "");
|
||||
}
|
||||
|
||||
uiBlockSetDirection(block, UI_RIGHT);
|
||||
uiTextBoundsBlock(block, 60);
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
@@ -1479,7 +1479,7 @@ void exit_editmode(int freedata) /* freedata==0 at render, 1= freedata, 2= do un
|
||||
}
|
||||
load_editMesh(); /* makes new displist */
|
||||
|
||||
if(freedata) free_editMesh();
|
||||
if(freedata) free_editMesh(G.editMesh);
|
||||
|
||||
if(G.f & G_FACESELECT) {
|
||||
set_seamtface();
|
||||
@@ -1982,26 +1982,26 @@ void special_editmenu(void)
|
||||
|
||||
switch(nr) {
|
||||
case 1:
|
||||
undo_push_mesh("Subdivide");
|
||||
subdivideflag(1, 0.0, editbutflag);
|
||||
BIF_undo_push("Subdivide");
|
||||
break;
|
||||
case 2:
|
||||
randfac= 10;
|
||||
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
|
||||
fac= -( (float)randfac )/100;
|
||||
undo_push_mesh("Subdivide Fractal");
|
||||
subdivideflag(1, fac, editbutflag);
|
||||
BIF_undo_push("Subdivide Fractal");
|
||||
break;
|
||||
case 3:
|
||||
undo_push_mesh("Subdivide Smooth");
|
||||
subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
|
||||
BIF_undo_push("Subdivide Smooth");
|
||||
break;
|
||||
case 4:
|
||||
mergemenu();
|
||||
break;
|
||||
case 5:
|
||||
undo_push_mesh("Remove Doubles");
|
||||
notice("Removed %d Vertices", removedoublesflag(1, doublimit));
|
||||
BIF_undo_push("Remove Doubles");
|
||||
break;
|
||||
case 6:
|
||||
hide_mesh(0);
|
||||
@@ -2013,11 +2013,10 @@ void special_editmenu(void)
|
||||
selectswap_mesh();
|
||||
break;
|
||||
case 9:
|
||||
undo_push_mesh("Flip Normals");
|
||||
flip_editnormals();
|
||||
BIF_undo_push("Flip Normals");
|
||||
break;
|
||||
case 10:
|
||||
undo_push_mesh("Smooth");
|
||||
vertexsmooth();
|
||||
break;
|
||||
case 11:
|
||||
@@ -3884,10 +3883,11 @@ void make_trans_verts(float *min, float *max, int mode)
|
||||
eve= em->verts.first;
|
||||
while(eve) {
|
||||
if(eve->h==0) {
|
||||
if(mode==1 || (eve->f & 1)) {
|
||||
if(mode==1 || (eve->f & SELECT)) {
|
||||
VECCOPY(tv->oldloc, eve->co);
|
||||
tv->loc= eve->co;
|
||||
tv->nor= eve->no;
|
||||
if(eve->no[0]!=0.0 || eve->no[1]!=0.0 ||eve->no[2]!=0.0)
|
||||
tv->nor= eve->no;
|
||||
tv->flag= eve->f & 1;
|
||||
tv++;
|
||||
tottrans++;
|
||||
@@ -4081,6 +4081,9 @@ void special_trans_update(int keyflags)
|
||||
IpoCurve *icu;
|
||||
|
||||
if(G.obedit) {
|
||||
if(G.obedit->type==OB_MESH) {
|
||||
recalc_editnormals(); // does face centers too
|
||||
}
|
||||
if(G.obedit->type==OB_CURVE) {
|
||||
cu= G.obedit->data;
|
||||
|
||||
@@ -4887,12 +4890,14 @@ static char *transform_mode_to_string(int mode)
|
||||
case 'N': return("Shrink/Fatten"); break;
|
||||
case 'w': return("Warp"); break;
|
||||
case 'd': return("Duplicate"); break;
|
||||
case 'n': return("Extrude"); break;
|
||||
default: return("Transform");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
'g' 'G' -> Grab / Grab with PET
|
||||
'n' -> Grab with vert normal (after extrude)
|
||||
'r' 'R' -> Rotate / Rotate with PET
|
||||
's' 'C' -> Scale / Scale with PET
|
||||
'S' -> Shear
|
||||
@@ -4916,7 +4921,7 @@ void transform(int mode)
|
||||
int axismode=0, time, fast=0, a, midtog=0, firsttime=1, wrong= 0, cameragrab= 0, gridflag;
|
||||
unsigned short event=0;
|
||||
short mval[2], breakloop=0, doit, xn, yn, xc, yc, xo, yo = 0, val;
|
||||
char str[100];
|
||||
char str[100], *undostr;
|
||||
int keyflags = 0;
|
||||
|
||||
float addvec[3] = {0,0,0}; // for new typing code
|
||||
@@ -4946,7 +4951,10 @@ void transform(int mode)
|
||||
mode = 'r';
|
||||
else if (mode % 's' == 0)
|
||||
mode = 's';
|
||||
|
||||
|
||||
/* used in end of function */
|
||||
undostr= transform_mode_to_string(mode);
|
||||
|
||||
if(G.obedit && (G.f & G_PROPORTIONAL)) {
|
||||
if(mode=='g') mode= 'G';
|
||||
if(mode=='r') mode= 'R';
|
||||
@@ -4966,13 +4974,6 @@ void transform(int mode)
|
||||
}
|
||||
if(mode=='w' && G.obedit==0) return;
|
||||
|
||||
if (G.obedit) {
|
||||
if(G.obedit->type == OB_MESH)
|
||||
undo_push_mesh(transform_mode_to_string(mode));
|
||||
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF)
|
||||
undo_push_curve(transform_mode_to_string(mode));
|
||||
}
|
||||
|
||||
/* what data will be involved? */
|
||||
if(G.obedit) {
|
||||
if(mode=='N') vertexnormals(0);
|
||||
@@ -5170,7 +5171,7 @@ void transform(int mode)
|
||||
}
|
||||
firsttime= 0;
|
||||
|
||||
if(mode=='g' || mode=='G') {
|
||||
if(mode=='g' || mode=='G' || mode=='n') {
|
||||
char gmode[10] = "";
|
||||
|
||||
keyflags |= KEYFLAG_LOC;
|
||||
@@ -5277,6 +5278,14 @@ void transform(int mode)
|
||||
tv->loc[1]= tv->oldloc[1]+tv->fac*dvecp[1];
|
||||
tv->loc[2]= tv->oldloc[2]+tv->fac*dvecp[2];
|
||||
}
|
||||
else if(mode=='n' && tv->nor) {
|
||||
float dot; /* dot product dvec with normal */
|
||||
|
||||
dot= tv->nor[0]*dvecp[0] + tv->nor[1]*dvecp[1] + tv->nor[2]*dvecp[2];
|
||||
tv->loc[0]= tv->oldloc[0]+dot*tv->nor[0];
|
||||
tv->loc[1]= tv->oldloc[1]+dot*tv->nor[1];
|
||||
tv->loc[2]= tv->oldloc[2]+dot*tv->nor[2];
|
||||
}
|
||||
else VecAddf(tv->loc, tv->oldloc, dvecp);
|
||||
}
|
||||
|
||||
@@ -6504,7 +6513,6 @@ void transform(int mode)
|
||||
|
||||
if(event==ESCKEY || event==RIGHTMOUSE) {
|
||||
canceled=1;
|
||||
G.undo_edit_level--;
|
||||
|
||||
if(edge_creases) { // exception case, edges dont fit in Trans structs...
|
||||
EditEdge *ee;
|
||||
@@ -6553,8 +6561,8 @@ void transform(int mode)
|
||||
tottrans= 0;
|
||||
|
||||
/* undo after transform, since it's storing current situations */
|
||||
if(canceled==0 && G.obedit==NULL)
|
||||
BIF_undo_push(transform_mode_to_string(mode));
|
||||
if(canceled==0)
|
||||
BIF_undo_push(undostr);
|
||||
}
|
||||
|
||||
void std_rmouse_transform(void (*xf_func)(int))
|
||||
@@ -6588,8 +6596,8 @@ void std_rmouse_transform(void (*xf_func)(int))
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if gets here it's a select, later on remove obedit check */
|
||||
if(G.obedit==NULL) BIF_undo_push("Select");
|
||||
/* if gets here it's a select */
|
||||
BIF_undo_push("Select");
|
||||
}
|
||||
|
||||
void rightmouse_transform(void)
|
||||
@@ -7824,10 +7832,6 @@ void mirror_edit(short mode)
|
||||
float mat[3][3], imat[3][3], min[3], max[3];
|
||||
TransVert *tv;
|
||||
|
||||
if(G.obedit->type==OB_MESH) undo_push_mesh("Mirror"); /* If it's a mesh, push it down the undo pipe */
|
||||
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF)
|
||||
undo_push_curve("Mirror");
|
||||
|
||||
make_trans_verts(min, max, 0);
|
||||
Mat3CpyMat4(mat, G.obedit->obmat);
|
||||
// Inverting the matrix explicitly, since the inverse is not always correct (then why the heck are we keeping it!)
|
||||
@@ -7947,11 +7951,13 @@ void mirror_edit(short mode)
|
||||
clearbaseflags_for_editing();
|
||||
if(transvmain) MEM_freeN(transvmain);
|
||||
transvmain= 0;
|
||||
|
||||
tottrans= 0;
|
||||
|
||||
BIF_undo_push("Mirror");
|
||||
}
|
||||
|
||||
void mirror_object(short mode) {
|
||||
void mirror_object(short mode)
|
||||
{
|
||||
TransOb *tob;
|
||||
short a, axis;
|
||||
float off[3], imat[3][3];
|
||||
@@ -8011,7 +8017,8 @@ void mirror_object(short mode) {
|
||||
tottrans= 0;
|
||||
}
|
||||
|
||||
void mirrormenu(void){
|
||||
void mirrormenu(void)
|
||||
{
|
||||
short mode = 0;
|
||||
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
#include "BSE_drawview.h"
|
||||
#include "BSE_editaction.h"
|
||||
|
||||
#include "editmesh.h" // borderselect uses it...
|
||||
#include "blendef.h"
|
||||
#include "mydevice.h"
|
||||
|
||||
@@ -670,20 +671,57 @@ void mouse_select(void)
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int edge_fully_inside_rect(rcti rect, short x1, short y1, short x2, short y2)
|
||||
{
|
||||
|
||||
// check points in rect
|
||||
if(rect.xmin<x1 && rect.xmax>x1 && rect.ymin<y1 && rect.ymax>y1)
|
||||
if(rect.xmin<x2 && rect.xmax>x2 && rect.ymin<y2 && rect.ymax>y2) return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int edge_inside_rect(rcti rect, short x1, short y1, short x2, short y2)
|
||||
{
|
||||
int d1, d2, d3, d4;
|
||||
|
||||
// check points in rect
|
||||
if(rect.xmin<x1 && rect.xmax>x1 && rect.ymin<y1 && rect.ymax>y1) return 1;
|
||||
if(rect.xmin<x2 && rect.xmax>x2 && rect.ymin<y2 && rect.ymax>y2) return 1;
|
||||
|
||||
/* check points completely out rect */
|
||||
if(x1<rect.xmin && x2<rect.xmin) return 0;
|
||||
if(x1>rect.xmax && x2>rect.xmax) return 0;
|
||||
if(y1<rect.ymin && y2<rect.ymin) return 0;
|
||||
if(y1>rect.ymax && y2>rect.ymax) return 0;
|
||||
|
||||
// simple check lines intersecting.
|
||||
d1= (y1-y2)*(x1- rect.xmin ) + (x2-x1)*(y1- rect.ymin );
|
||||
d2= (y1-y2)*(x1- rect.xmin ) + (x2-x1)*(y1- rect.ymax );
|
||||
d3= (y1-y2)*(x1- rect.xmax ) + (x2-x1)*(y1- rect.ymax );
|
||||
d4= (y1-y2)*(x1- rect.xmax ) + (x2-x1)*(y1- rect.ymin );
|
||||
|
||||
if(d1<0 && d2<0 && d3<0 && d4<0) return 0;
|
||||
if(d1>0 && d2>0 && d3>0 && d4>0) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the 'borderselect' command. (Select verts based on selecting with a
|
||||
* border: key 'b'). All selecting seems to be done in the get_border part.
|
||||
*/
|
||||
void borderselect(void)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
rcti rect;
|
||||
Base *base;
|
||||
Nurb *nu;
|
||||
BezTriple *bezt;
|
||||
BPoint *bp;
|
||||
MetaElem *ml;
|
||||
struct EditVert *eve;
|
||||
unsigned int buffer[MAXPICKBUF];
|
||||
int a, index;
|
||||
short hits, val, tel;
|
||||
@@ -725,22 +763,61 @@ void borderselect(void)
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
if(G.obedit) {
|
||||
else if(G.obedit) {
|
||||
/* used to be a bigger test, also included sector and life */
|
||||
if(G.obedit->type==OB_MESH) {
|
||||
EditMesh *em = G.editMesh;
|
||||
EditVert *eve;
|
||||
EditEdge *eed;
|
||||
EditFace *efa;
|
||||
|
||||
calc_meshverts_ext(); /* drawobject.c */
|
||||
eve= em->verts.first;
|
||||
while(eve) {
|
||||
if(eve->h==0 && eve->xs>rect.xmin && eve->xs<rect.xmax) {
|
||||
if(eve->ys>rect.ymin && eve->ys<rect.ymax) {
|
||||
if(val==LEFTMOUSE) eve->f|= 1;
|
||||
else eve->f&= 254;
|
||||
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
|
||||
calc_meshverts_ext(); /* clips, drawobject.c */
|
||||
for(eve= em->verts.first; eve; eve= eve->next) {
|
||||
if(eve->h==0 && eve->xs>rect.xmin && eve->xs<rect.xmax) {
|
||||
if(eve->ys>rect.ymin && eve->ys<rect.ymax) {
|
||||
if(val==LEFTMOUSE) eve->f|= 1;
|
||||
else eve->f&= 254;
|
||||
}
|
||||
}
|
||||
}
|
||||
eve= eve->next;
|
||||
}
|
||||
if(G.scene->selectmode & SCE_SELECT_EDGE) {
|
||||
short done= 0;
|
||||
calc_meshverts_ext_f2(); /* doesnt clip, drawobject.c */
|
||||
|
||||
/* two stages, for nice edge select first do 'both points in rect' */
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if(eed->h==0) {
|
||||
if( edge_fully_inside_rect(rect, eed->v1->xs, eed->v1->ys, eed->v2->xs, eed->v2->ys)) {
|
||||
EM_select_edge(eed, val==LEFTMOUSE);
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(done==0) {
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if(eed->h==0) {
|
||||
if( edge_inside_rect(rect, eed->v1->xs, eed->v1->ys, eed->v2->xs, eed->v2->ys))
|
||||
EM_select_edge(eed, val==LEFTMOUSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(G.scene->selectmode & SCE_SELECT_FACE) {
|
||||
calc_mesh_facedots_ext();
|
||||
for(efa= em->faces.first; efa; efa= efa->next) {
|
||||
if(efa->h==0 && efa->xs>rect.xmin && efa->xs<rect.xmax) {
|
||||
if(efa->ys>rect.ymin && efa->ys<rect.ymax) {
|
||||
EM_select_face(efa, val==LEFTMOUSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EM_selectmode_flush();
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
|
||||
}
|
||||
@@ -917,8 +994,8 @@ void borderselect(void)
|
||||
|
||||
allqueue(REDRAWINFO, 0);
|
||||
}
|
||||
/* remove obedit check later */
|
||||
if(G.obedit==NULL) BIF_undo_push("Border select");
|
||||
|
||||
BIF_undo_push("Border select");
|
||||
|
||||
} /* end of borderselect() */
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
#include "BIF_editarmature.h"
|
||||
#include "BIF_editfont.h"
|
||||
#include "BIF_editmesh.h"
|
||||
#include "BIF_editmode_undo.h"
|
||||
#include "BIF_editview.h"
|
||||
#include "BIF_interface.h"
|
||||
#include "BIF_mainqueue.h"
|
||||
@@ -1813,40 +1814,6 @@ static uiBlock *view3d_edit_propfalloffmenu(void *arg_unused)
|
||||
return block;
|
||||
}
|
||||
|
||||
static void do_view3d_edit_mesh_undohistorymenu(void *arg, int event)
|
||||
{
|
||||
TEST_EDITMESH
|
||||
|
||||
if(event<1) return;
|
||||
|
||||
if (event==1) remake_editMesh();
|
||||
else undo_pop_mesh(G.undo_edit_level-event+3);
|
||||
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
}
|
||||
|
||||
static uiBlock *view3d_edit_mesh_undohistorymenu(void *arg_unused)
|
||||
{
|
||||
uiBlock *block;
|
||||
short yco = 20, menuwidth = 120;
|
||||
int i, lasti;
|
||||
|
||||
lasti = (G.undo_edit_level>25) ? G.undo_edit_level-25 : 0;
|
||||
|
||||
block= uiNewBlock(&curarea->uiblocks, "view3d_edit_mesh_undohistorymenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
|
||||
uiBlockSetButmFunc(block, do_view3d_edit_mesh_undohistorymenu, NULL);
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo All Changes|Ctrl U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
|
||||
|
||||
for (i=G.undo_edit_level; i>=lasti; i--) {
|
||||
if (i == G.undo_edit_level) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, G.undo_edit[i].name, 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, (float)i+2, "");
|
||||
}
|
||||
|
||||
uiBlockSetDirection(block, UI_RIGHT);
|
||||
uiTextBoundsBlock(block, 60);
|
||||
return block;
|
||||
}
|
||||
|
||||
void do_view3d_edit_mesh_verticesmenu(void *arg, int event)
|
||||
{
|
||||
@@ -1911,19 +1878,19 @@ void do_view3d_edit_mesh_edgesmenu(void *arg, int event)
|
||||
switch(event) {
|
||||
|
||||
case 0: /* subdivide smooth */
|
||||
undo_push_mesh("Subdivide Smooth");
|
||||
subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
|
||||
BIF_undo_push("Subdivide Smooth");
|
||||
break;
|
||||
case 1: /*subdivide fractal */
|
||||
undo_push_mesh("Subdivide Fractal");
|
||||
randfac= 10;
|
||||
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
|
||||
fac= -( (float)randfac )/100;
|
||||
subdivideflag(1, fac, editbutflag);
|
||||
BIF_undo_push("Subdivide Fractal");
|
||||
break;
|
||||
case 2: /* subdivide */
|
||||
undo_push_mesh("Subdivide");
|
||||
subdivideflag(1, 0.0, editbutflag);
|
||||
BIF_undo_push("Subdivide");
|
||||
break;
|
||||
case 3: /* knife subdivide */
|
||||
KnifeSubdivide(KNIFE_PROMPT);
|
||||
@@ -2196,10 +2163,10 @@ static void do_view3d_edit_meshmenu(void *arg, int event)
|
||||
switch(event) {
|
||||
|
||||
case 0: /* Undo Editing */
|
||||
undo_pop_mesh(1);
|
||||
BIF_undo();
|
||||
break;
|
||||
case 1: /* Redo Editing */
|
||||
undo_redo_mesh();
|
||||
BIF_redo();
|
||||
break;
|
||||
case 2: /* transform properties */
|
||||
add_blockhandler(curarea, VIEW3D_HANDLER_OBJECT, 0);
|
||||
@@ -2249,7 +2216,7 @@ static uiBlock *view3d_edit_meshmenu(void *arg_unused)
|
||||
*/
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo Editing|U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Redo Editing|Shift U", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
|
||||
uiDefIconTextBlockBut(block, view3d_edit_mesh_undohistorymenu, NULL, ICON_RIGHTARROW_THIN, "Undo History", 0, yco-=20, 120, 19, "");
|
||||
uiDefIconTextBlockBut(block, editmode_undohistorymenu, NULL, ICON_RIGHTARROW_THIN, "Undo History", 0, yco-=20, 120, 19, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
@@ -3436,7 +3403,10 @@ void do_view3d_buttons(short event)
|
||||
G.f &= ~G_TEXTUREPAINT;
|
||||
}
|
||||
#endif /* NAN_VPT */
|
||||
if(G.obedit==0) enter_editmode();
|
||||
if(G.obedit==NULL) {
|
||||
enter_editmode();
|
||||
BIF_undo_push("Original"); // here, because all over code enter_editmode is abused
|
||||
}
|
||||
else exit_editmode(2); // freedata, and undo
|
||||
scrarea_queue_headredraw(curarea);
|
||||
break;
|
||||
@@ -3601,6 +3571,7 @@ void do_view3d_buttons(short event)
|
||||
if (G.obpose) exit_posemode(1); /* exit posemode */
|
||||
|
||||
enter_editmode();
|
||||
BIF_undo_push("Original"); // here, because all over code enter_editmode is abused
|
||||
}
|
||||
} else if (G.vd->modeselect == V3D_FACESELECTMODE_SEL) {
|
||||
if ((G.obedit) && (G.f & G_FACESELECT)) {
|
||||
@@ -3661,7 +3632,27 @@ void do_view3d_buttons(short event)
|
||||
break;
|
||||
case B_AROUND:
|
||||
handle_view3d_around();
|
||||
break;
|
||||
break;
|
||||
|
||||
case B_SEL_VERT:
|
||||
if( (G.qual & LR_SHIFTKEY)==0 || G.scene->selectmode==0)
|
||||
G.scene->selectmode= SCE_SELECT_VERTEX;
|
||||
EM_selectmode_set();
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
break;
|
||||
case B_SEL_EDGE:
|
||||
if( (G.qual & LR_SHIFTKEY)==0 || G.scene->selectmode==0)
|
||||
G.scene->selectmode= SCE_SELECT_EDGE;
|
||||
EM_selectmode_set();
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
break;
|
||||
case B_SEL_FACE:
|
||||
if( (G.qual & LR_SHIFTKEY)==0 || G.scene->selectmode==0)
|
||||
G.scene->selectmode= SCE_SELECT_FACE;
|
||||
EM_selectmode_set();
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if(event>=B_LAY && event<B_LAY+31) {
|
||||
@@ -3917,7 +3908,8 @@ void view3d_buttons(void)
|
||||
}
|
||||
else xco+= (10+1)*(XIC/2)+10;
|
||||
|
||||
if(G.obedit && (OBACT->type == OB_MESH || OBACT->type == OB_CURVE || OBACT->type == OB_SURF || OBACT->type == OB_LATTICE)) {
|
||||
/* proportional falloff */
|
||||
if(G.obedit && (G.obedit->type == OB_MESH || G.obedit->type == OB_CURVE || G.obedit->type == OB_SURF || G.obedit->type == OB_LATTICE)) {
|
||||
extern int prop_mode;
|
||||
if(G.f & G_PROPORTIONAL) {
|
||||
uiDefIconTextButI(block, ICONTEXTROW,B_REDR, ICON_SHARPCURVE, propfalloff_pup(), xco,0,XIC+10,YIC, &(prop_mode), 0, 1.0, 0, 0, "Proportional Edit Falloff (Hotkey: Shift O) ");
|
||||
@@ -3925,6 +3917,18 @@ void view3d_buttons(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* selection modus */
|
||||
if(G.obedit && (G.obedit->type == OB_MESH)) {
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefIconButS(block, TOG|BIT|0, B_SEL_VERT, ICON_VERTEXSEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode");
|
||||
xco+= XIC;
|
||||
uiDefIconButS(block, TOG|BIT|1, B_SEL_EDGE, ICON_EDGESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Edge select mode");
|
||||
xco+= XIC;
|
||||
uiDefIconButS(block, TOG|BIT|2, B_SEL_FACE, ICON_FACESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Face select mode");
|
||||
xco+= XIC+20;
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
|
||||
uiDefIconBut(block, BUT, B_VIEWRENDER, ICON_SCENE_DEHLT, xco,0,XIC,YIC, NULL, 0, 1.0, 0, 0, "Render this window (hold CTRL for anim)");
|
||||
|
||||
if (G.obpose){
|
||||
|
||||
@@ -3092,7 +3092,9 @@ static int ui_do_block(uiBlock *block, uiEvent *uevent)
|
||||
butevent= ui_do_button(block, but, uevent);
|
||||
|
||||
if( !(block->flag & UI_BLOCK_LOOP))
|
||||
if(but->type!=BLOCK && but->type!=MENU) BIF_undo_push(but->str);
|
||||
if(but->type!=BLOCK && but->type!=MENU)
|
||||
if(!G.obedit)
|
||||
BIF_undo_push(but->str);
|
||||
|
||||
if(butevent) addqueue(block->winq, UI_BUT_EVENT, (short)butevent);
|
||||
|
||||
|
||||
@@ -461,6 +461,10 @@ char *BIF_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
|
||||
cp= ts->face; break;
|
||||
case TH_FACE_SELECT:
|
||||
cp= ts->face_select; break;
|
||||
case TH_FACE_DOT:
|
||||
cp= ts->face_dot; break;
|
||||
case TH_FACEDOT_SIZE:
|
||||
cp= &ts->facedot_size; break;
|
||||
case TH_NORMAL:
|
||||
cp= ts->normal; break;
|
||||
|
||||
@@ -535,13 +539,15 @@ void BIF_InitTheme(void)
|
||||
SETCOL(btheme->tv3d.vertex_select, 0xff, 0xff, 0x70, 255);
|
||||
btheme->tv3d.vertex_size= 2;
|
||||
SETCOL(btheme->tv3d.edge, 0x0, 0x0, 0x0, 255);
|
||||
SETCOL(btheme->tv3d.edge_select, 0x90, 0x90, 0x30, 255);
|
||||
SETCOL(btheme->tv3d.edge_select, 0xb0, 0xb0, 0x30, 255);
|
||||
SETCOL(btheme->tv3d.edge_seam, 230, 150, 50, 255);
|
||||
SETCOL(btheme->tv3d.edge_facesel, 75, 75, 75, 255);
|
||||
SETCOL(btheme->tv3d.face, 0, 50, 150, 30);
|
||||
SETCOL(btheme->tv3d.face_select, 200, 100, 200, 60);
|
||||
SETCOL(btheme->tv3d.normal, 0x22, 0xDD, 0xDD, 255);
|
||||
|
||||
SETCOL(btheme->tv3d.face_dot, 255, 138, 48, 255);
|
||||
btheme->tv3d.facedot_size= 4;
|
||||
|
||||
/* space buttons */
|
||||
/* to have something initialized */
|
||||
btheme->tbuts= btheme->tv3d;
|
||||
@@ -687,8 +693,10 @@ char *BIF_ThemeColorsPup(int spacetype)
|
||||
sprintf(str, "Edge Selected %%x%d|", TH_EDGE_SELECT); strcat(cp, str);
|
||||
sprintf(str, "Edge Seam %%x%d|", TH_EDGE_SEAM); strcat(cp, str);
|
||||
sprintf(str, "Edge UV Face Select %%x%d|", TH_EDGE_FACESEL); strcat(cp, str);
|
||||
sprintf(str, "Face %%x%d|", TH_FACE); strcat(cp, str);
|
||||
sprintf(str, "Face Selected %%x%d|", TH_FACE_SELECT); strcat(cp, str);
|
||||
sprintf(str, "Face (transp) %%x%d|", TH_FACE); strcat(cp, str);
|
||||
sprintf(str, "Face Selected (transp) %%x%d|", TH_FACE_SELECT); strcat(cp, str);
|
||||
sprintf(str, "Face Dot Selected %%x%d|", TH_FACE_DOT); strcat(cp, str);
|
||||
sprintf(str, "Face Dot Size %%x%d|", TH_FACEDOT_SIZE); strcat(cp, str);
|
||||
sprintf(str, "Normal %%x%d", TH_NORMAL); strcat(cp, str);
|
||||
}
|
||||
else if(spacetype==SPACE_IPO) {
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
#include "BIF_editkey.h"
|
||||
#include "BIF_editlattice.h"
|
||||
#include "BIF_editmesh.h"
|
||||
#include "BIF_editmode_undo.h"
|
||||
#include "BIF_editoops.h"
|
||||
#include "BIF_editseq.h"
|
||||
#include "BIF_editsima.h"
|
||||
@@ -641,9 +642,9 @@ void BIF_undo(void)
|
||||
|
||||
if(G.obedit) {
|
||||
if(G.obedit->type==OB_MESH)
|
||||
undo_pop_mesh(1);
|
||||
undo_editmode_step(1);
|
||||
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF)
|
||||
undo_curve_step(1);
|
||||
undo_editmode_step(1);
|
||||
|
||||
}
|
||||
else {
|
||||
@@ -665,9 +666,9 @@ void BIF_redo(void)
|
||||
|
||||
if(G.obedit) {
|
||||
if(G.obedit->type==OB_MESH)
|
||||
undo_redo_mesh();
|
||||
undo_editmode_step(-1);
|
||||
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF)
|
||||
undo_curve_step(-1);
|
||||
undo_editmode_step(-1);
|
||||
|
||||
}
|
||||
else {
|
||||
@@ -687,9 +688,11 @@ void BIF_undo_menu(void)
|
||||
{
|
||||
if(G.obedit) {
|
||||
if(G.obedit->type==OB_MESH)
|
||||
undo_menu_mesh();
|
||||
undo_editmode_menu();
|
||||
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF)
|
||||
;//undo_menu_curve();
|
||||
undo_editmode_menu();
|
||||
|
||||
allqueue(REDRAWALL, 0);
|
||||
}
|
||||
else {
|
||||
if (G.f & G_FACESELECT)
|
||||
@@ -702,7 +705,6 @@ void BIF_undo_menu(void)
|
||||
if(U.uiflag & USER_GLOBALUNDO) BKE_undo_menu();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* *************** */
|
||||
@@ -1239,7 +1241,6 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
|
||||
if(G.qual==LR_CTRLKEY)
|
||||
add_hook();
|
||||
else {
|
||||
undo_push_curve("Handle change");
|
||||
if(G.qual==LR_CTRLKEY)
|
||||
autocalchandlesNurb_all(1); /* flag=1, selected */
|
||||
else if((G.qual==LR_SHIFTKEY))
|
||||
@@ -1248,7 +1249,7 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
|
||||
sethandlesNurb(3);
|
||||
|
||||
makeDispList(G.obedit);
|
||||
|
||||
BIF_undo_push("Handle change");
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
}
|
||||
}
|
||||
@@ -1384,16 +1385,16 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
|
||||
case OB_MESH:
|
||||
if(G.qual==(LR_SHIFTKEY|LR_CTRLKEY)) {
|
||||
if(okee("Recalculate normals inside")) {
|
||||
undo_push_mesh("Recalculate normals inside");
|
||||
righthandfaces(2);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
BIF_undo_push("Recalculate normals inside");
|
||||
}
|
||||
}
|
||||
else if(G.qual==LR_CTRLKEY){
|
||||
if(okee("Recalculate normals outside")) {
|
||||
undo_push_mesh("Recalculate normals outside");
|
||||
righthandfaces(1);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
BIF_undo_push("Recalculate normals outside");
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1508,25 +1509,13 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
|
||||
break;
|
||||
case UKEY:
|
||||
if(G.obedit) {
|
||||
if(G.obedit->type==OB_MESH){
|
||||
if (G.qual==LR_ALTKEY)
|
||||
undo_menu_mesh();
|
||||
else if (G.qual==LR_SHIFTKEY)
|
||||
undo_redo_mesh();
|
||||
else if((G.qual==0))
|
||||
undo_pop_mesh(1);
|
||||
if(G.obedit->type==OB_MESH) {
|
||||
if(G.qual==0) BIF_undo(); else BIF_redo();
|
||||
}
|
||||
else if(G.obedit->type==OB_ARMATURE)
|
||||
remake_editArmature();
|
||||
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
|
||||
extern void undo_curve_step(int step);
|
||||
if (G.qual==LR_ALTKEY)
|
||||
//undo_menu_curve();
|
||||
;
|
||||
else if (G.qual==LR_SHIFTKEY)
|
||||
undo_curve_step(-1);
|
||||
else if((G.qual==0))
|
||||
undo_curve_step(1);
|
||||
if(G.qual==0) BIF_undo(); else BIF_redo();
|
||||
}
|
||||
else if(G.obedit->type==OB_LATTICE)
|
||||
remake_editLatt();
|
||||
@@ -1542,8 +1531,6 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
|
||||
single_user();
|
||||
}
|
||||
}
|
||||
else if(G.qual==LR_SHIFTKEY)
|
||||
if(U.uiflag & USER_GLOBALUNDO) BIF_redo();
|
||||
|
||||
break;
|
||||
case VKEY:
|
||||
@@ -1561,10 +1548,10 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
|
||||
else if (G.qual==0){
|
||||
if(G.obedit) {
|
||||
if(G.obedit->type==OB_CURVE) {
|
||||
undo_push_curve("Handle change");
|
||||
sethandlesNurb(2);
|
||||
makeDispList(G.obedit);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
BIF_undo_push("Handle change");
|
||||
}
|
||||
}
|
||||
else if(ob && ob->type == OB_MESH)
|
||||
|
||||
@@ -740,8 +740,10 @@ int blenderqread(unsigned short event, short val)
|
||||
enter_meta();
|
||||
else if(G.vd) {
|
||||
/* also when Alt-E */
|
||||
if(G.obedit==0)
|
||||
if(G.obedit==0) {
|
||||
enter_editmode();
|
||||
BIF_undo_push("Original"); // here, because all over code enter_editmode is abused
|
||||
}
|
||||
else
|
||||
exit_editmode(2); // freedata, and undo
|
||||
}
|
||||
@@ -793,8 +795,10 @@ int blenderqread(unsigned short event, short val)
|
||||
case EKEY:
|
||||
if(G.qual==LR_ALTKEY) {
|
||||
if(G.vd && textspace==0) {
|
||||
if(G.obedit==0)
|
||||
if(G.obedit==0) {
|
||||
enter_editmode();
|
||||
BIF_undo_push("Original");
|
||||
}
|
||||
else
|
||||
exit_editmode(2); // freedata, and undo
|
||||
return 0;
|
||||
@@ -936,6 +940,10 @@ int blenderqread(unsigned short event, short val)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if(G.qual==LR_ALTKEY) {
|
||||
BIF_undo_menu();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -974,7 +982,7 @@ int blenderqread(unsigned short event, short val)
|
||||
}
|
||||
break;
|
||||
case ZKEY: // undo
|
||||
if(G.qual & (LR_CTRLKEY|LR_COMMANDKEY)) { // all combos with ctrl/cammandkey are accepted
|
||||
if(G.qual & (LR_CTRLKEY|LR_COMMANDKEY)) { // all combos with ctrl/commandkey are accepted
|
||||
if ELEM(G.qual, LR_CTRLKEY, LR_COMMANDKEY) BIF_undo();
|
||||
else BIF_redo(); // all combos with ctrl is redo
|
||||
return 0;
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
#include "BIF_editlattice.h"
|
||||
#include "BIF_editfont.h"
|
||||
#include "BIF_editmesh.h"
|
||||
#include "BIF_editmode_undo.h"
|
||||
#include "BIF_editsound.h"
|
||||
#include "BIF_renderwin.h"
|
||||
#include "BIF_resources.h"
|
||||
@@ -244,6 +245,13 @@ int BIF_read_homefile(void)
|
||||
btheme->tv3d.normal[2]= 0xDD;
|
||||
btheme->tv3d.normal[3]= 255;
|
||||
}
|
||||
if(btheme->tv3d.face_dot[3]==0) {
|
||||
btheme->tv3d.face_dot[0]= 255;
|
||||
btheme->tv3d.face_dot[1]= 138;
|
||||
btheme->tv3d.face_dot[2]= 48;
|
||||
btheme->tv3d.face_dot[3]= 255;
|
||||
btheme->tv3d.facedot_size= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,7 +564,7 @@ void exit_usiblender(void)
|
||||
free_editText();
|
||||
}
|
||||
else if(G.obedit->type==OB_MBALL) BLI_freelistN(&editelems);
|
||||
free_editMesh();
|
||||
free_editMesh(G.editMesh);
|
||||
}
|
||||
|
||||
free_editLatt();
|
||||
@@ -602,8 +610,8 @@ void exit_usiblender(void)
|
||||
FTF_End();
|
||||
#endif
|
||||
|
||||
if (G.undo_clear) G.undo_clear();
|
||||
undo_clear_curve();
|
||||
/* undo free stuff */
|
||||
undo_editmode_clear();
|
||||
|
||||
BKE_undo_save_quit(); // saves quit.blend if global undo is on
|
||||
BKE_reset_undo();
|
||||
|
||||
Reference in New Issue
Block a user