added an active face for the mesh editmode and normal mesh - this is needed because the TFace flag was not always easy to access from editmode.

using the last selected face was almost good enough however when selecting verts and edges the last selected face would become inactive and the space image would flicker about too much.
The active face is used for getting the space image at the moment and keeps scripts that use this flag working also.

This has 2 commands to get and set, so the variable is not accessed directly.

all "UV Calculate" scripts work now

last commit crashed when in solid draw mode, it seems subsurf modifier is ignoring the displayMask since MTFACE is available. just made it do a null check for now.

uvcalc_follow_active_coords.py - should be done inC and put in the snap menu.
This commit is contained in:
Campbell Barton 2007-09-22 17:54:13 +00:00
parent d5b186ba6b
commit aee06ac0d0
20 changed files with 142 additions and 230 deletions

@ -51,6 +51,11 @@ def extend():
Draw.PupMenu('ERROR: No mesh object.')
return
# Toggle Edit mode
is_editmode = Window.EditMode()
if is_editmode:
Window.EditMode(0)
me = ob.getData(mesh=1)
me_verts = me.verts
@ -233,7 +238,12 @@ def extend():
face_modes[i] = 2 # dont search again
print sys.time() - t
me.update()
if is_editmode:
Window.EditMode(1)
else:
me.update()
Window.RedrawAll()
Window.WaitCursor(0)

@ -1,129 +0,0 @@
#!BPY
"""
Name: 'UVs from unselected adjacent'
Blender: 242
Group: 'UVCalculation'
Tooltip: 'Assign UVs to selected faces from surrounding unselected faces.'
"""
__author__ = "Campbell Barton"
__url__ = ("blender", "elysiun")
__version__ = "1.0 2006/02/07"
__bpydoc__ = """\
This script sets the UV mapping and image of selected faces from adjacent unselected faces.
Use this script in face select mode for texturing between textured faces.
"""
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Campbell J Barton
#
# 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.
#
# 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.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
from Blender import *
import bpy
def mostUsedImage(imageList): # Returns the image most used in the list.
if not imageList:
return None
elif len(imageList) < 3:
return imageList[0]
# 3+ Images, Get the most used image for surrounding faces.
imageCount = {}
for image in imageList:
if image:
image_key= image.name
else:
image_key = None
try:
imageCount[image_key]['imageCount'] +=1 # an extra user of this image
except:
imageCount[image_key] = {'imageCount':1, 'blenderImage':image} # start with 1 user.
# Now a list of tuples, (imageName, {imageCount, image})
imageCount = imageCount.items()
try: imageCount.sort(key=lambda a: a[1])
except: imageCount.sort(lambda a,b: cmp(a[1], b[1]))
return imageCount[-1][1]['blenderImage']
def main():
scn = bpy.data.scenes.active
ob = scn.objects.active
if ob == None or ob.type != 'Mesh':
Draw.PupMenu('ERROR: No mesh object in face select mode.')
return
me = ob.getData(mesh=1)
if not me.faceUV:
Draw.PupMenu('ERROR: No mesh object in face select mode.')
return
selfaces = [f for f in me.faces if f.sel]
unselfaces = [f for f in me.faces if not f.sel if not f.hide]
# Gather per Vert UV and Image, store in vertUvAverage
vertUvAverage = [[[],[]] for i in xrange(len(me.verts))]
for f in unselfaces: # Unselected faces only.
fuv = f.uv
for i,v in enumerate(f):
vertUvAverage[v.index][0].append(fuv[i])
vertUvAverage[v.index][1].append(f.image)
# Average per vectex UV coords
for vertUvData in vertUvAverage:
uvList = vertUvData[0]
if uvList:
# Convert from a list of vectors into 1 vector.
vertUvData[0] = reduce(lambda a,b: a+b, uvList, Mathutils.Vector(0,0)) * (1.0/len(uvList))
else:
vertUvData[0] = None
# Assign to selected faces
TEX_FLAG = Mesh.FaceModes['TEX']
for f in selfaces:
uvlist = []
imageList = []
for i,v in enumerate(f):
uv, vImages = vertUvAverage[v.index]
uvlist.append( uv )
imageList.extend(vImages)
if None not in uvlist:
# all the faces images used by this faces vert. some faces will be added twice but thats ok.
# Get the most used image and assign to the face.
image = mostUsedImage(imageList)
f.uv = uvlist
if image:
f.image = image
f.mode |= TEX_FLAG
Window.RedrawAll()
if __name__ == '__main__':
main()

@ -544,6 +544,12 @@ def main():
Draw.PupMenu('Error%t|No mesh objects selected.')
return
# Toggle Edit mode
is_editmode = Window.EditMode()
if is_editmode:
Window.EditMode(0)
Window.WaitCursor(1)
lightmap_uvpack(meshes,\
PREF_SEL_ONLY.val,\
@ -554,6 +560,9 @@ def main():
PREF_BOX_DIV.val,\
int(1/(PREF_MARGIN_DIV.val/100)))
if is_editmode:
Window.EditMode(1)
Window.WaitCursor(0)
if __name__ == '__main__':

@ -80,6 +80,10 @@ def main():
if not ob or ob.type!='Mesh':
return
is_editmode = Window.EditMode()
if is_editmode:
Window.EditMode(0)
mousedown_wait() # so the menu items clicking dosnt trigger the mouseclick
Window.DrawProgressBar (0.0, '')
@ -100,10 +104,8 @@ def main():
mouse_buttons = Window.GetMouseButtons()
Window.DrawProgressBar (0.2, '(2 of 3 ) Click confirms the U coords')
mousedown_wait()
obmat= ob.matrixWorld
@ -112,7 +114,7 @@ def main():
if not mouseInView or not OriginA:
return
me = ob.getData(mesh=1)
# Get the face under the mouse
@ -255,6 +257,9 @@ def main():
Window.Redraw(Window.Types.VIEW3D)
Window.SetCursorPos(*orig_cursor)
if is_editmode:
Window.EditMode(1)
Window.RedrawAll()
if __name__=='__main__':

@ -1121,6 +1121,9 @@ def main():
print "Smart Projection time: %.2f" % (sys.time() - time1)
# Window.DrawProgressBar(0.9, "Smart Projections done, time: %.2f sec." % (sys.time() - time1))
if is_editmode:
Window.EditMode(1)
Window.DrawProgressBar(1.0, "")
Window.WaitCursor(0)
Window.RedrawAll()

@ -243,6 +243,7 @@ static Image *image_alloc(const char *name, short source, short type)
ima->ok= IMA_OK;
ima->xrep= ima->yrep= 1;
ima->aspx= ima->aspy= 1.0;
ima->gen_x= 256; ima->gen_y= 256;
ima->gen_type= 1; /* no defines yet? */

@ -1881,28 +1881,30 @@ static void ccgDM_drawUVEdges(DerivedMesh *dm)
MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
int i;
glBegin(GL_LINES);
for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
if(!(mf->flag&ME_HIDE)) {
glVertex2fv(tf->uv[0]);
glVertex2fv(tf->uv[1]);
glVertex2fv(tf->uv[1]);
glVertex2fv(tf->uv[2]);
if(!mf->v4) {
glVertex2fv(tf->uv[2]);
if (tf) {
glBegin(GL_LINES);
for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
if(!(mf->flag&ME_HIDE)) {
glVertex2fv(tf->uv[0]);
} else {
glVertex2fv(tf->uv[1]);
glVertex2fv(tf->uv[1]);
glVertex2fv(tf->uv[2]);
glVertex2fv(tf->uv[3]);
glVertex2fv(tf->uv[3]);
glVertex2fv(tf->uv[0]);
if(!mf->v4) {
glVertex2fv(tf->uv[2]);
glVertex2fv(tf->uv[0]);
} else {
glVertex2fv(tf->uv[2]);
glVertex2fv(tf->uv[3]);
glVertex2fv(tf->uv[3]);
glVertex2fv(tf->uv[0]);
}
}
}
glEnd();
}
glEnd();
}
static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) {

@ -164,6 +164,13 @@ typedef struct EditMesh
/* DerivedMesh caches... note that derived cage can be equivalent
* to derived final, care should be taken on release.
*/
/* used for keeping track of the last clicked on face - so the space image
* when using the last selected face - (EditSelection) the space image flickered too much
*
* never access this directly, use EM_set_actFace and EM_get_actFace */
EditFace *act_face;
struct DerivedMesh *derivedCage, *derivedFinal;
/* the custom data layer mask that was last used to calculate
* derivedCage and derivedFinal

@ -259,4 +259,7 @@ void free_uv_vert_map_EM(UvVertMap *vmap);
int EM_texFaceCheck(void); /* can we edit UV's for this mesh?*/
int EM_vertColorCheck(void); /* can we edit colors for this mesh?*/
void EM_set_actFace(struct EditFace *efa);
struct EditFace * EM_get_actFace(void);
#endif

@ -74,7 +74,14 @@ typedef struct Mesh {
struct CustomData vdata, edata, fdata;
int totvert, totedge, totface, totselect, pad2;
int totvert, totedge, totface, totselect;
/* the last selected vertex/edge/face are used for the active face however
* this means the active face must always be selected, this is to keep track
* of the last selected face and is similar to the old active face flag where
* the face does not need to be selected, -1 is inactive */
int act_face;
int texflag;
/* texture space, copied as one block in editobject.c */

@ -204,7 +204,7 @@ typedef struct PartialVisibility {
/* mtface->flag */
#define TF_SELECT 1 /* use MFace hide flag (after 2.43), should be able to reuse after 2.44 */
#define TF_ACTIVE 2
#define TF_ACTIVE 2 /* deprecated! */
#define TF_SEL1 4
#define TF_SEL2 8
#define TF_SEL3 16

@ -4077,7 +4077,7 @@ static int MFace_setImage( BPy_MFace *self, PyObject *value )
return 0;
}
#define MFACE_FLAG_BITMASK ( TF_SELECT | TF_ACTIVE | TF_SEL1 | \
#define MFACE_FLAG_BITMASK ( TF_SELECT | TF_SEL1 | \
TF_SEL2 | TF_SEL3 | TF_SEL4 | TF_HIDE )
/*
@ -4086,6 +4086,7 @@ static int MFace_setImage( BPy_MFace *self, PyObject *value )
static PyObject *MFace_getFlag( BPy_MFace *self )
{
int flag;
if( !self->mesh->mtface )
return EXPP_ReturnPyObjError( PyExc_ValueError,
"face has no texture values" );
@ -4093,8 +4094,13 @@ static PyObject *MFace_getFlag( BPy_MFace *self )
if( !MFace_get_pointer( self ) )
return NULL;
return PyInt_FromLong( (long) ( self->mesh->mtface[self->index].flag
& MFACE_FLAG_BITMASK ) );
flag = self->mesh->mtface[self->index].flag & MFACE_FLAG_BITMASK;
/* so old scripts still work */
if (self->index == self->mesh->act_face)
flag |= TF_ACTIVE;
return PyInt_FromLong( (long)( flag ) );
}
/*
@ -4128,7 +4134,7 @@ static int MFace_setFlag( BPy_MFace *self, PyObject *value )
"invalid bit(s) set in mask" );
/* merge active setting with other new params */
param |= (self->mesh->mtface[self->index].flag & TF_ACTIVE);
param |= (self->mesh->mtface[self->index].flag);
self->mesh->mtface[self->index].flag = (char)param;
return 0;
@ -7869,27 +7875,19 @@ static PyObject *Mesh_getKey( BPy_Mesh * self )
static PyObject *Mesh_getActiveFace( BPy_Mesh * self )
{
MTFace *face;
int i, totface;
/* not needed but keep incase exceptions make use of it */
if( !self->mesh->mtface )
return EXPP_ReturnPyObjError( PyExc_ValueError,
"face has no texture values" );
face = self->mesh->mtface;
totface = self->mesh->totface;
for( i = 0; i < totface; ++face, ++i )
if( face->flag & TF_ACTIVE ) {
return PyInt_FromLong( i );
}
if (self->mesh->act_face != -1 && self->mesh->act_face <= self->mesh->totface)
return PyInt_FromLong( self->mesh->act_face );
Py_RETURN_NONE;
}
static int Mesh_setActiveFace( BPy_Mesh * self, PyObject * value )
{
MTFace *face;
int param;
/* if no texture faces, error */
@ -7910,18 +7908,8 @@ static int Mesh_setActiveFace( BPy_Mesh * self, PyObject * value )
if( param < 0 || param > self->mesh->totface )
return EXPP_ReturnIntError( PyExc_TypeError,
"face index out of range" );
face = self->mesh->mtface;
/* if requested face isn't already active, then inactivate all
* faces and activate the requested one */
if( !( face[param].flag & TF_ACTIVE ) ) {
int i;
for( i = self->mesh->totface; i > 0; ++face, --i )
face->flag &= ~TF_ACTIVE;
self->mesh->mtface[param].flag |= TF_ACTIVE;
}
self->mesh->act_face = param;
return 0;
}
@ -8500,7 +8488,7 @@ static PyObject *M_Mesh_FaceFlagsDict( void )
PyConstant_Insert( d, "SELECT", PyInt_FromLong( TF_SELECT ) );
PyConstant_Insert( d, "HIDE", PyInt_FromLong( TF_HIDE ) );
PyConstant_Insert( d, "ACTIVE", PyInt_FromLong( TF_ACTIVE ) );
PyConstant_Insert( d, "ACTIVE", PyInt_FromLong( TF_ACTIVE ) ); /* deprecated */
}
return FF;

@ -1978,20 +1978,11 @@ static BPy_NMVert *nmvert_from_data( MVert * vert, MSticky * st, float *co,
static int get_active_faceindex( Mesh * me )
{
MTFace *tf;
int i;
if( me == NULL )
return -1;
tf = me->mtface;
if( tf == 0 )
return -1;
for( i = 0; i < me->totface; i++ )
if( tf[i].flag & TF_ACTIVE )
return i;
if (me->act_face != -1 && me->act_face < me->totface)
return me->act_face;
return -1;
}

@ -490,6 +490,7 @@ void draw_uvs_sima(void)
cageDM = editmesh_get_derived_cage_and_final(&finalDM, CD_MASK_BAREMESH | CD_MASK_MTFACE);
if (finalDM->drawUVEdges &&
DM_get_face_data_layer(finalDM, CD_MTFACE) &&
/* When sync selection is enabled, all faces are drawn (except for hidden)
* so if cage is the same as the final, theres no point in drawing the shadowmesh. */
!((G.sima->flag & SI_SYNC_UVSEL && cageDM==finalDM))

@ -634,7 +634,7 @@ EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me)
if (!(mf->flag&ME_HIDE)) {
unsigned int flags = eEdge_Visible;
if (mf->flag&ME_FACE_SEL) flags |= eEdge_Select;
if (tf && tf->flag&TF_ACTIVE) {
if (i==me->act_face) {
flags |= eEdge_Active;
if (mf->flag&ME_FACE_SEL) flags |= eEdge_SelectAndActive;
}
@ -647,8 +647,8 @@ EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me)
} else {
get_marked_edge_info__orFlags(eh, mf->v3, mf->v1, flags);
}
if (tf && tf->flag&TF_ACTIVE) {
if (i==me->act_face) {
get_marked_edge_info__orFlags(eh, mf->v1, mf->v2, eEdge_ActiveFirst);
get_marked_edge_info__orFlags(eh, mf->v1, mf->v4?mf->v4:mf->v3, eEdge_ActiveLast);
}

@ -569,13 +569,18 @@ MTFace *get_active_mtface(EditFace **act_efa, MCol **mcol, short partsel)
if(!EM_texFaceCheck())
return NULL;
for (ese = em->selected.last; ese; ese=ese->prev){
if(ese->type == EDITFACE) {
efa = (EditFace *)ese->data;
if (efa->h) efa= NULL;
else break;
/* first check the active face */
if (em->act_face) {
efa = em->act_face;
} else {
for (ese = em->selected.last; ese; ese=ese->prev){
if(ese->type == EDITFACE) {
efa = (EditFace *)ese->data;
if (efa->h) efa= NULL;
else break;
}
}
}
@ -1107,7 +1112,6 @@ void face_select()
{
Object *ob;
Mesh *me;
MTFace *tface, *tsel;
MFace *mface, *msel;
short mval[2];
unsigned int a, index;
@ -1127,33 +1131,20 @@ void face_select()
if (!facesel_face_pick(me, mval, &index, 1)) return;
tsel= (((MTFace*)me->mtface)+index); /* check me->mtface before using */
msel= (((MFace*)me->mface)+index);
if (msel->flag & ME_HIDE) return;
/* clear flags */
tface = me->mtface;
mface = me->mface;
a = me->totface;
while (a--) {
if (G.qual & LR_SHIFTKEY) {
if (me->mtface) {
tface->flag &= ~TF_ACTIVE;
}
} else {
if (me->mtface) {
tface->flag &= ~TF_ACTIVE;
}
if ((G.qual & LR_SHIFTKEY)==0) {
while (a--) {
mface->flag &= ~ME_FACE_SEL;
mface++;
}
if (me->mtface) {
tface++;
}
mface++;
}
if (me->mtface)
tsel->flag |= TF_ACTIVE;
me->act_face = (int)index;
if (G.qual & LR_SHIFTKEY) {
if (msel->flag & ME_FACE_SEL)

@ -333,6 +333,10 @@ void free_editface(EditFace *efa)
}
#endif
EM_remove_selection(efa, EDITFACE);
if (G.editMesh->act_face==efa)
EM_set_actFace(NULL);
CustomData_em_free_block(&G.editMesh->fdata, &efa->data);
if(efa->fast==0)
free(efa);
@ -809,10 +813,11 @@ void make_editMesh()
/* because of reload */
free_editMesh(em);
em->act_face = NULL;
G.totvert= tot= me->totvert;
G.totedge= me->totedge;
G.totface= me->totface;
if(tot==0) {
countall();
return;
@ -906,6 +911,9 @@ void make_editMesh()
if((FACESEL_PAINT_TEST) && (efa->f & SELECT))
EM_select_face(efa, 1); /* flush down */
if (a==me->act_face)
em->act_face = efa;
}
}
}
@ -1140,6 +1148,9 @@ void load_editMesh(void)
/* no index '0' at location 3 or 4 */
test_index_face(mface, &me->fdata, i, efa->v4?4:3);
if (a==me->act_face)
EM_set_actFace(efa);
#ifdef WITH_VERSE
if(efa->vface) {

@ -72,6 +72,17 @@ editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data
#include "editmesh.h"
/* this replaces the active flag used in uv/face mode */
void EM_set_actFace(EditFace *efa)
{
G.editMesh->act_face = efa;
}
EditFace * EM_get_actFace(void)
{
return G.editMesh->act_face;
}
/* ********* Selection History ************ */
static int EM_check_selection(void *data)
{

@ -2067,6 +2067,8 @@ void mouse_mesh(void)
if((G.qual & LR_SHIFTKEY)==0) EM_clear_flag_all(SELECT);
if(efa) {
/* set the last selected face */
EM_set_actFace(efa);
if( (efa->f & SELECT)==0 ) {
EM_store_selection(efa, EDITFACE);

@ -575,8 +575,8 @@ void mouse_select_sima(void) /* TODO - SYNCSEL */
find_nearest_tface(&nearesttf, &nearestefa);
if(nearesttf==NULL)
return;
nearesttf->flag |= TF_ACTIVE;
EM_set_actFace(nearestefa);
for (i=0; i<4; i++)
hituv[i]= nearesttf->uv[i];
@ -660,10 +660,7 @@ void mouse_select_sima(void) /* TODO - SYNCSEL */
for (efa= em->faces.first; efa; efa= efa->next) {
tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
if (SIMA_FACEDRAW_CHECK(efa, tf)) {
if(nearesttf && tf!=nearesttf)
tf->flag &=~ TF_ACTIVE;
if (!sticky) continue;
if(msel_hit(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
SIMA_UVSEL_SET(efa, tf, 0);
if(msel_hit(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
@ -675,6 +672,7 @@ void mouse_select_sima(void) /* TODO - SYNCSEL */
SIMA_UVSEL_SET(efa, tf, 3);
}
}
EM_set_actFace(nearestefa);
flush = 1;
}
}
@ -685,11 +683,12 @@ void mouse_select_sima(void) /* TODO - SYNCSEL */
for (efa= em->faces.first; efa; efa= efa->next) {
tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
SIMA_FACESEL_UNSET(efa, tf);
//if(nearesttf && tf!=nearesttf) /* TODO - deal with editmesh active face */
// tf->flag &= ~TF_ACTIVE;
}
if(nearesttf)
if(nearesttf) {
SIMA_FACESEL_SET(nearestefa, nearesttf);
EM_set_actFace(nearestefa);
}
}
/* deselect uvs, and select sticky uvs */