This is a much faster and easier way to give a bevelled curve a taper, without using taper curves. Each point on a curve now has a 'radius' value that you can shrink and fatten using Alt S, which will influence the taper when the curve is bevelled (either with a bevob, or with front/back turned off and a bevel dept set). Alt S shrinks and fattens the selected points in an interactive transform, and you can set an absolute radius for selected points with 'Set Radius' in the curve specials menu. See demo: http://mke3.net/blender/etc/curve_shrinkfatten-h264.mov This can be a quick way to create revolved surfaces (eg. http://mke3.net/blender/etc/wineglass-h264.mov ) and it would be very interesting to use this radius value in other tools, such as a 'freehand curve' tool that would let you draw a curve freehand, with the radius affected by pen pressure, or even using the radius at each point to control curve guides for particles more precisely, rather than the continous maxdist.
3117 lines
82 KiB
C
3117 lines
82 KiB
C
/**
|
|
* $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 *****
|
|
*/
|
|
|
|
//#define NAN_LINEAR_PHYSICS
|
|
|
|
#include <math.h>
|
|
#include <string.h>
|
|
|
|
#ifndef WIN32
|
|
#include <unistd.h>
|
|
#include <sys/times.h>
|
|
#else
|
|
#include <io.h>
|
|
#endif
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "PIL_time.h"
|
|
|
|
#include "BMF_Api.h"
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
#include "IMB_imbuf.h"
|
|
|
|
#include "DNA_action_types.h"
|
|
#include "DNA_armature_types.h"
|
|
#include "DNA_camera_types.h"
|
|
#include "DNA_constraint_types.h"
|
|
#include "DNA_curve_types.h"
|
|
#include "DNA_group_types.h"
|
|
#include "DNA_image_types.h"
|
|
#include "DNA_lattice_types.h"
|
|
#include "DNA_mesh_types.h"
|
|
#include "DNA_meshdata_types.h"
|
|
#include "DNA_meta_types.h"
|
|
#include "DNA_object_types.h"
|
|
#include "DNA_screen_types.h"
|
|
#include "DNA_scene_types.h"
|
|
#include "DNA_space_types.h"
|
|
#include "DNA_texture_types.h"
|
|
#include "DNA_userdef_types.h"
|
|
#include "DNA_view3d_types.h"
|
|
#include "DNA_world_types.h"
|
|
|
|
#include "BLI_blenlib.h"
|
|
#include "BLI_arithb.h"
|
|
#include "BLI_editVert.h"
|
|
|
|
#include "BKE_action.h"
|
|
#include "BKE_armature.h"
|
|
#include "BKE_anim.h"
|
|
#include "BKE_constraint.h"
|
|
#include "BKE_curve.h"
|
|
#include "BKE_displist.h"
|
|
#include "BKE_depsgraph.h"
|
|
#include "BKE_DerivedMesh.h"
|
|
#include "BKE_global.h"
|
|
#include "BKE_lattice.h"
|
|
#include "BKE_library.h"
|
|
#include "BKE_image.h"
|
|
#include "BKE_ipo.h"
|
|
#include "BKE_key.h"
|
|
#include "BKE_main.h"
|
|
#include "BKE_mesh.h"
|
|
#include "BKE_object.h"
|
|
#include "BKE_scene.h"
|
|
#include "BKE_texture.h"
|
|
#include "BKE_utildefines.h"
|
|
|
|
#include "BIF_butspace.h"
|
|
#include "BIF_drawimage.h"
|
|
#include "BIF_editgroup.h"
|
|
#include "BIF_editarmature.h"
|
|
#include "BIF_editmesh.h"
|
|
#include "BIF_gl.h"
|
|
#include "BIF_glutil.h"
|
|
#include "BIF_interface.h"
|
|
#include "BIF_interface_icons.h"
|
|
#include "BIF_mywindow.h"
|
|
#include "BIF_poseobject.h"
|
|
#include "BIF_previewrender.h"
|
|
#include "BIF_resources.h"
|
|
#include "BIF_screen.h"
|
|
#include "BIF_space.h"
|
|
|
|
#include "BDR_drawmesh.h"
|
|
#include "BDR_drawobject.h"
|
|
#include "BDR_editobject.h"
|
|
#include "BDR_vpaint.h"
|
|
|
|
#include "BSE_drawview.h"
|
|
#include "BSE_filesel.h"
|
|
#include "BSE_headerbuttons.h"
|
|
#include "BSE_seqaudio.h"
|
|
#include "BSE_trans_types.h"
|
|
#include "BSE_time.h"
|
|
#include "BSE_view.h"
|
|
|
|
#include "BPY_extern.h"
|
|
|
|
#include "RE_render_ext.h"
|
|
|
|
#include "blendef.h"
|
|
#include "mydevice.h"
|
|
#include "butspace.h" // event codes
|
|
|
|
#include "BIF_transform.h"
|
|
|
|
#include "RE_pipeline.h" // make_stars
|
|
|
|
/* Modules used */
|
|
#include "radio.h"
|
|
|
|
/* locals */
|
|
void drawname(Object *ob);
|
|
|
|
static void star_stuff_init_func(void)
|
|
{
|
|
cpack(-1);
|
|
glPointSize(1.0);
|
|
glBegin(GL_POINTS);
|
|
}
|
|
static void star_stuff_vertex_func(float* i)
|
|
{
|
|
glVertex3fv(i);
|
|
}
|
|
static void star_stuff_term_func(void)
|
|
{
|
|
glEnd();
|
|
}
|
|
|
|
static void setalpha_bgpic(BGpic *bgpic)
|
|
{
|
|
int x, y, alph;
|
|
char *rect;
|
|
|
|
alph= (int)(255.0*(1.0-bgpic->blend));
|
|
|
|
rect= (char *)bgpic->rect;
|
|
for(y=0; y< bgpic->yim; y++) {
|
|
for(x= bgpic->xim; x>0; x--, rect+=4) {
|
|
rect[3]= alph;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void default_gl_light(void)
|
|
{
|
|
int a;
|
|
|
|
/* initialize */
|
|
if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) {
|
|
U.light[0].flag= 1;
|
|
U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9;
|
|
U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8;
|
|
U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5;
|
|
U.light[0].spec[3]= 1.0;
|
|
|
|
U.light[1].flag= 0;
|
|
U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1;
|
|
U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8;
|
|
U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5;
|
|
U.light[1].spec[3]= 1.0;
|
|
|
|
U.light[2].flag= 0;
|
|
U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2;
|
|
U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4;
|
|
U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3;
|
|
U.light[2].spec[3]= 1.0;
|
|
}
|
|
|
|
|
|
glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec);
|
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col);
|
|
glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec);
|
|
|
|
glLightfv(GL_LIGHT1, GL_POSITION, U.light[1].vec);
|
|
glLightfv(GL_LIGHT1, GL_DIFFUSE, U.light[1].col);
|
|
glLightfv(GL_LIGHT1, GL_SPECULAR, U.light[1].spec);
|
|
|
|
glLightfv(GL_LIGHT2, GL_POSITION, U.light[2].vec);
|
|
glLightfv(GL_LIGHT2, GL_DIFFUSE, U.light[2].col);
|
|
glLightfv(GL_LIGHT2, GL_SPECULAR, U.light[2].spec);
|
|
|
|
for(a=0; a<8; a++) {
|
|
if(a<3) {
|
|
if(U.light[a].flag) glEnable(GL_LIGHT0+a);
|
|
else glDisable(GL_LIGHT0+a);
|
|
|
|
// clear stuff from other opengl lamp usage
|
|
glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0);
|
|
glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0);
|
|
glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0);
|
|
}
|
|
else glDisable(GL_LIGHT0+a);
|
|
}
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glDisable(GL_COLOR_MATERIAL);
|
|
}
|
|
|
|
/* also called when render 'ogl' */
|
|
void init_gl_stuff(void)
|
|
{
|
|
float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 };
|
|
float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
|
|
float mat_shininess[] = { 35.0 };
|
|
int a, x, y;
|
|
GLubyte pat[32*32];
|
|
const GLubyte *patc= pat;
|
|
|
|
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
|
|
|
|
default_gl_light();
|
|
|
|
/* no local viewer, looks ugly in ortho mode */
|
|
/* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */
|
|
|
|
glDepthFunc(GL_LEQUAL);
|
|
/* scaling matrices */
|
|
glEnable(GL_NORMALIZE);
|
|
|
|
glShadeModel(GL_FLAT);
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
glDisable(GL_BLEND);
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDisable(GL_FOG);
|
|
glDisable(GL_LIGHTING);
|
|
glDisable(GL_LOGIC_OP);
|
|
glDisable(GL_STENCIL_TEST);
|
|
glDisable(GL_TEXTURE_1D);
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
|
|
glPixelTransferi(GL_RED_SCALE, 1);
|
|
glPixelTransferi(GL_RED_BIAS, 0);
|
|
glPixelTransferi(GL_GREEN_SCALE, 1);
|
|
glPixelTransferi(GL_GREEN_BIAS, 0);
|
|
glPixelTransferi(GL_BLUE_SCALE, 1);
|
|
glPixelTransferi(GL_BLUE_BIAS, 0);
|
|
glPixelTransferi(GL_ALPHA_SCALE, 1);
|
|
glPixelTransferi(GL_ALPHA_BIAS, 0);
|
|
|
|
glPixelTransferi(GL_DEPTH_BIAS, 0);
|
|
glPixelTransferi(GL_DEPTH_SCALE, 1);
|
|
glDepthRange(0.0, 1.0);
|
|
|
|
a= 0;
|
|
for(x=0; x<32; x++) {
|
|
for(y=0; y<4; y++) {
|
|
if( (x) & 1) pat[a++]= 0x88;
|
|
else pat[a++]= 0x22;
|
|
}
|
|
}
|
|
|
|
glPolygonStipple(patc);
|
|
|
|
|
|
init_realtime_GL();
|
|
}
|
|
|
|
void circf(float x, float y, float rad)
|
|
{
|
|
GLUquadricObj *qobj = gluNewQuadric();
|
|
|
|
gluQuadricDrawStyle(qobj, GLU_FILL);
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(x, y, 0.);
|
|
|
|
gluDisk( qobj, 0.0, rad, 32, 1);
|
|
|
|
glPopMatrix();
|
|
|
|
gluDeleteQuadric(qobj);
|
|
}
|
|
|
|
void circ(float x, float y, float rad)
|
|
{
|
|
GLUquadricObj *qobj = gluNewQuadric();
|
|
|
|
gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(x, y, 0.);
|
|
|
|
gluDisk( qobj, 0.0, rad, 32, 1);
|
|
|
|
glPopMatrix();
|
|
|
|
gluDeleteQuadric(qobj);
|
|
}
|
|
|
|
/* ********** ********** */
|
|
|
|
static void draw_bgpic(void)
|
|
{
|
|
BGpic *bgpic;
|
|
Image *ima;
|
|
float vec[4], fac, asp, zoomx, zoomy;
|
|
float x1, y1, x2, y2, cx, cy;
|
|
|
|
bgpic= G.vd->bgpic;
|
|
if(bgpic==NULL) return;
|
|
|
|
if(bgpic->tex) {
|
|
extern void init_render_texture(struct Render *re, Tex *tex);
|
|
/* note; bad call, this has to be recoded to move to blenkernel */
|
|
init_render_texture(NULL, bgpic->tex);
|
|
free_unused_animimages();
|
|
ima= bgpic->tex->ima;
|
|
}
|
|
else {
|
|
ima= bgpic->ima;
|
|
}
|
|
|
|
if(ima==NULL) return;
|
|
if(ima->ok==0) return;
|
|
|
|
tag_image_time(ima);
|
|
|
|
/* test for image */
|
|
if(ima->ibuf==NULL) {
|
|
|
|
if(bgpic->rect) MEM_freeN(bgpic->rect);
|
|
bgpic->rect= NULL;
|
|
|
|
if(bgpic->tex) {
|
|
ima_ibuf_is_nul(bgpic->tex, bgpic->tex->ima);
|
|
}
|
|
else {
|
|
waitcursor(1);
|
|
load_image(ima, IB_rect, G.sce, G.scene->r.cfra);
|
|
waitcursor(0);
|
|
}
|
|
if(ima->ibuf==NULL) {
|
|
ima->ok= 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* this ensures that when ibuf changed (reloaded) the backbuf changes too */
|
|
if(bgpic->ibuf!=ima->ibuf) {
|
|
if(bgpic->rect) MEM_freeN(bgpic->rect);
|
|
bgpic->rect= NULL;
|
|
}
|
|
bgpic->ibuf= ima->ibuf;
|
|
|
|
if(bgpic->rect==NULL) {
|
|
|
|
bgpic->rect= MEM_dupallocN(ima->ibuf->rect);
|
|
bgpic->xim= ima->ibuf->x;
|
|
bgpic->yim= ima->ibuf->y;
|
|
setalpha_bgpic(bgpic);
|
|
}
|
|
|
|
if(G.vd->persp==2) {
|
|
rctf vb;
|
|
|
|
calc_viewborder(G.vd, &vb);
|
|
|
|
x1= vb.xmin;
|
|
y1= vb.ymin;
|
|
x2= vb.xmax;
|
|
y2= vb.ymax;
|
|
}
|
|
else {
|
|
float sco[2];
|
|
|
|
/* calc window coord */
|
|
initgrabz(0.0, 0.0, 0.0);
|
|
window_to_3d(vec, 1, 0);
|
|
fac= MAX3( fabs(vec[0]), fabs(vec[1]), fabs(vec[1]) );
|
|
fac= 1.0/fac;
|
|
|
|
asp= ( (float)ima->ibuf->y)/(float)ima->ibuf->x;
|
|
|
|
vec[0] = vec[1] = vec[2] = 0.0;
|
|
view3d_project_float(curarea, vec, sco, G.vd->persmat);
|
|
cx = sco[0];
|
|
cy = sco[1];
|
|
|
|
x1= cx+ fac*(bgpic->xof-bgpic->size);
|
|
y1= cy+ asp*fac*(bgpic->yof-bgpic->size);
|
|
x2= cx+ fac*(bgpic->xof+bgpic->size);
|
|
y2= cy+ asp*fac*(bgpic->yof+bgpic->size);
|
|
}
|
|
|
|
/* complete clip? */
|
|
|
|
if(x2 < 0 ) return;
|
|
if(y2 < 0 ) return;
|
|
if(x1 > curarea->winx ) return;
|
|
if(y1 > curarea->winy ) return;
|
|
|
|
zoomx= (x2-x1)/ima->ibuf->x;
|
|
zoomy= (y2-y1)/ima->ibuf->y;
|
|
|
|
glEnable(GL_BLEND);
|
|
if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
|
|
glaDefine2DArea(&curarea->winrct);
|
|
glPixelZoom(zoomx, zoomy);
|
|
glaDrawPixelsSafe(x1, y1, ima->ibuf->x, ima->ibuf->y, ima->ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, bgpic->rect);
|
|
glPixelZoom(1.0, 1.0);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();
|
|
|
|
glBlendFunc(GL_ONE, GL_ZERO);
|
|
glDisable(GL_BLEND);
|
|
if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
|
|
|
|
areawinset(curarea->win); // restore viewport / scissor
|
|
}
|
|
|
|
static void drawgrid_draw(float wx, float wy, float x, float y, float dx)
|
|
{
|
|
float fx, fy;
|
|
|
|
x+= (wx);
|
|
y+= (wy);
|
|
fx= x/dx;
|
|
fx= x-dx*floor(fx);
|
|
|
|
while(fx< curarea->winx) {
|
|
fdrawline(fx, 0.0, fx, (float)curarea->winy);
|
|
fx+= dx;
|
|
}
|
|
|
|
fy= y/dx;
|
|
fy= y-dx*floor(fy);
|
|
|
|
|
|
while(fy< curarea->winy) {
|
|
fdrawline(0.0, fy, (float)curarea->winx, fy);
|
|
fy+= dx;
|
|
}
|
|
|
|
}
|
|
|
|
// not intern, called in editobject for constraint axis too
|
|
void make_axis_color(char *col, char *col2, char axis)
|
|
{
|
|
if(axis=='x') {
|
|
col2[0]= col[0]>219?255:col[0]+36;
|
|
col2[1]= col[1]<26?0:col[1]-26;
|
|
col2[2]= col[2]<26?0:col[2]-26;
|
|
}
|
|
else if(axis=='y') {
|
|
col2[0]= col[0]<46?0:col[0]-36;
|
|
col2[1]= col[1]>189?255:col[1]+66;
|
|
col2[2]= col[2]<46?0:col[2]-36;
|
|
}
|
|
else {
|
|
col2[0]= col[0]<26?0:col[0]-26;
|
|
col2[1]= col[1]<26?0:col[1]-26;
|
|
col2[2]= col[2]>209?255:col[2]+46;
|
|
}
|
|
|
|
}
|
|
|
|
static void drawgrid(void)
|
|
{
|
|
/* extern short bgpicmode; */
|
|
float wx, wy, x, y, fw, fx, fy, dx;
|
|
float vec4[4];
|
|
char col[3], col2[3];
|
|
|
|
vec4[0]=vec4[1]=vec4[2]=0.0;
|
|
vec4[3]= 1.0;
|
|
Mat4MulVec4fl(G.vd->persmat, vec4);
|
|
fx= vec4[0];
|
|
fy= vec4[1];
|
|
fw= vec4[3];
|
|
|
|
wx= (curarea->winx/2.0); /* because of rounding errors, grid at wrong location */
|
|
wy= (curarea->winy/2.0);
|
|
|
|
x= (wx)*fx/fw;
|
|
y= (wy)*fy/fw;
|
|
|
|
vec4[0]=vec4[1]=G.vd->grid;
|
|
vec4[2]= 0.0;
|
|
vec4[3]= 1.0;
|
|
Mat4MulVec4fl(G.vd->persmat, vec4);
|
|
fx= vec4[0];
|
|
fy= vec4[1];
|
|
fw= vec4[3];
|
|
|
|
dx= fabs(x-(wx)*fx/fw);
|
|
if(dx==0) dx= fabs(y-(wy)*fy/fw);
|
|
|
|
glDepthMask(0); // disable write in zbuffer
|
|
|
|
/* check zoom out */
|
|
BIF_ThemeColor(TH_GRID);
|
|
persp(PERSP_WIN);
|
|
|
|
if(dx<6.0) {
|
|
G.vd->gridview*= 10.0;
|
|
dx*= 10.0;
|
|
|
|
if(dx<6.0) {
|
|
G.vd->gridview*= 10.0;
|
|
dx*= 10.0;
|
|
|
|
if(dx<6.0) {
|
|
G.vd->gridview*= 10.0;
|
|
dx*=10;
|
|
if(dx<6.0);
|
|
else {
|
|
BIF_ThemeColor(TH_GRID);
|
|
drawgrid_draw(wx, wy, x, y, dx);
|
|
}
|
|
}
|
|
else { // start blending out
|
|
BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
|
|
drawgrid_draw(wx, wy, x, y, dx);
|
|
|
|
BIF_ThemeColor(TH_GRID);
|
|
drawgrid_draw(wx, wy, x, y, 10*dx);
|
|
}
|
|
}
|
|
else { // start blending out (6 < dx < 60)
|
|
BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
|
|
drawgrid_draw(wx, wy, x, y, dx);
|
|
|
|
BIF_ThemeColor(TH_GRID);
|
|
drawgrid_draw(wx, wy, x, y, 10*dx);
|
|
}
|
|
}
|
|
else {
|
|
if(dx>60.0) { // start blending in
|
|
G.vd->gridview/= 10.0;
|
|
dx/= 10.0;
|
|
if(dx>60.0) { // start blending in
|
|
G.vd->gridview/= 10.0;
|
|
dx/= 10.0;
|
|
if(dx>60.0) {
|
|
BIF_ThemeColor(TH_GRID);
|
|
drawgrid_draw(wx, wy, x, y, dx);
|
|
}
|
|
else {
|
|
BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
|
|
drawgrid_draw(wx, wy, x, y, dx);
|
|
BIF_ThemeColor(TH_GRID);
|
|
drawgrid_draw(wx, wy, x, y, dx*10);
|
|
}
|
|
}
|
|
else {
|
|
BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
|
|
drawgrid_draw(wx, wy, x, y, dx);
|
|
BIF_ThemeColor(TH_GRID);
|
|
drawgrid_draw(wx, wy, x, y, dx*10);
|
|
}
|
|
}
|
|
else {
|
|
BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
|
|
drawgrid_draw(wx, wy, x, y, dx);
|
|
BIF_ThemeColor(TH_GRID);
|
|
drawgrid_draw(wx, wy, x, y, dx*10);
|
|
}
|
|
}
|
|
|
|
x+= (wx);
|
|
y+= (wy);
|
|
BIF_GetThemeColor3ubv(TH_GRID, col);
|
|
|
|
setlinestyle(0);
|
|
|
|
/* center cross */
|
|
if(G.vd->view==3) make_axis_color(col, col2, 'y');
|
|
else make_axis_color(col, col2, 'x');
|
|
glColor3ubv(col2);
|
|
|
|
fdrawline(0.0, y, (float)curarea->winx, y);
|
|
|
|
if(G.vd->view==7) make_axis_color(col, col2, 'y');
|
|
else make_axis_color(col, col2, 'z');
|
|
glColor3ubv(col2);
|
|
|
|
fdrawline(x, 0.0, x, (float)curarea->winy);
|
|
|
|
glDepthMask(1); // enable write in zbuffer
|
|
persp(PERSP_VIEW);
|
|
}
|
|
|
|
|
|
static void drawfloor(void)
|
|
{
|
|
View3D *vd;
|
|
float vert[3], grid;
|
|
int a, gridlines, emphasise;
|
|
char col[3], col2[3];
|
|
short draw_line = 0;
|
|
|
|
vd= curarea->spacedata.first;
|
|
|
|
vert[2]= 0.0;
|
|
|
|
if(vd->gridlines<3) return;
|
|
|
|
if(G.vd->zbuf && G.obedit) glDepthMask(0); // for zbuffer-select
|
|
|
|
gridlines= vd->gridlines/2;
|
|
grid= gridlines*vd->grid;
|
|
|
|
BIF_GetThemeColor3ubv(TH_GRID, col);
|
|
BIF_GetThemeColor3ubv(TH_BACK, col2);
|
|
|
|
/* emphasise division lines lighter instead of darker, if background is darker than grid */
|
|
if ( ((col[0]+col[1]+col[2])/3+10) > (col2[0]+col2[1]+col2[2])/3 )
|
|
emphasise = 20;
|
|
else
|
|
emphasise = -10;
|
|
|
|
/* draw the Y axis and/or grid lines */
|
|
for(a= -gridlines;a<=gridlines;a++) {
|
|
if(a==0) {
|
|
/* check for the 'show Y axis' preference */
|
|
if (vd->gridflag & V3D_SHOW_Y) {
|
|
make_axis_color(col, col2, 'y');
|
|
glColor3ubv(col2);
|
|
|
|
draw_line = 1;
|
|
} else if (vd->gridflag & V3D_SHOW_FLOOR) {
|
|
BIF_ThemeColorShade(TH_GRID, emphasise);
|
|
} else {
|
|
draw_line = 0;
|
|
}
|
|
} else {
|
|
/* check for the 'show grid floor' preference */
|
|
if (vd->gridflag & V3D_SHOW_FLOOR) {
|
|
if( (a % 10)==0) {
|
|
BIF_ThemeColorShade(TH_GRID, emphasise);
|
|
}
|
|
else BIF_ThemeColorShade(TH_GRID, 10);
|
|
|
|
draw_line = 1;
|
|
} else {
|
|
draw_line = 0;
|
|
}
|
|
}
|
|
|
|
if (draw_line) {
|
|
glBegin(GL_LINE_STRIP);
|
|
vert[0]= a*vd->grid;
|
|
vert[1]= grid;
|
|
glVertex3fv(vert);
|
|
vert[1]= -grid;
|
|
glVertex3fv(vert);
|
|
glEnd();
|
|
}
|
|
}
|
|
|
|
/* draw the X axis and/or grid lines */
|
|
for(a= -gridlines;a<=gridlines;a++) {
|
|
if(a==0) {
|
|
/* check for the 'show X axis' preference */
|
|
if (vd->gridflag & V3D_SHOW_X) {
|
|
make_axis_color(col, col2, 'x');
|
|
glColor3ubv(col2);
|
|
|
|
draw_line = 1;
|
|
} else if (vd->gridflag & V3D_SHOW_FLOOR) {
|
|
BIF_ThemeColorShade(TH_GRID, emphasise);
|
|
} else {
|
|
draw_line = 0;
|
|
}
|
|
} else {
|
|
/* check for the 'show grid floor' preference */
|
|
if (vd->gridflag & V3D_SHOW_FLOOR) {
|
|
if( (a % 10)==0) {
|
|
BIF_ThemeColorShade(TH_GRID, emphasise);
|
|
}
|
|
else BIF_ThemeColorShade(TH_GRID, 10);
|
|
|
|
draw_line = 1;
|
|
} else {
|
|
draw_line = 0;
|
|
}
|
|
}
|
|
|
|
if (draw_line) {
|
|
glBegin(GL_LINE_STRIP);
|
|
vert[1]= a*vd->grid;
|
|
vert[0]= grid;
|
|
glVertex3fv(vert );
|
|
vert[0]= -grid;
|
|
glVertex3fv(vert);
|
|
glEnd();
|
|
}
|
|
}
|
|
|
|
/* draw the Z axis line */
|
|
/* check for the 'show Z axis' preference */
|
|
if (vd->gridflag & V3D_SHOW_Z) {
|
|
make_axis_color(col, col2, 'z');
|
|
glColor3ubv(col2);
|
|
|
|
glBegin(GL_LINE_STRIP);
|
|
vert[0]= 0;
|
|
vert[1]= 0;
|
|
vert[2]= grid;
|
|
glVertex3fv(vert );
|
|
vert[2]= -grid;
|
|
glVertex3fv(vert);
|
|
glEnd();
|
|
}
|
|
|
|
if(G.vd->zbuf && G.obedit) glDepthMask(1);
|
|
|
|
}
|
|
|
|
static void drawcursor(View3D *v3d)
|
|
{
|
|
short mx,my,co[2];
|
|
int flag;
|
|
|
|
/* we dont want the clipping for cursor */
|
|
flag= v3d->flag;
|
|
v3d->flag= 0;
|
|
project_short( give_cursor(), co);
|
|
v3d->flag= flag;
|
|
|
|
mx = co[0];
|
|
my = co[1];
|
|
|
|
if(mx!=IS_CLIPPED) {
|
|
setlinestyle(0);
|
|
cpack(0xFF);
|
|
circ((float)mx, (float)my, 10.0);
|
|
setlinestyle(4);
|
|
cpack(0xFFFFFF);
|
|
circ((float)mx, (float)my, 10.0);
|
|
setlinestyle(0);
|
|
cpack(0x0);
|
|
|
|
sdrawline(mx-20, my, mx-5, my);
|
|
sdrawline(mx+5, my, mx+20, my);
|
|
sdrawline(mx, my-20, mx, my-5);
|
|
sdrawline(mx, my+5, mx, my+20);
|
|
}
|
|
}
|
|
|
|
/* ********* custom clipping *********** */
|
|
|
|
static void view3d_draw_clipping(View3D *v3d)
|
|
{
|
|
BoundBox *bb= v3d->clipbb;
|
|
|
|
BIF_ThemeColorShade(TH_BACK, -8);
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[3]);
|
|
glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[1]);
|
|
glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[5]);
|
|
glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[3]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[6]);
|
|
glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[2]);
|
|
glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[3]);
|
|
|
|
glEnd();
|
|
}
|
|
|
|
void view3d_set_clipping(View3D *v3d)
|
|
{
|
|
double plane[4];
|
|
int a;
|
|
|
|
for(a=0; a<4; a++) {
|
|
QUATCOPY(plane, v3d->clip[a]);
|
|
glClipPlane(GL_CLIP_PLANE0+a, plane);
|
|
glEnable(GL_CLIP_PLANE0+a);
|
|
}
|
|
}
|
|
|
|
void view3d_clr_clipping(void)
|
|
{
|
|
int a;
|
|
|
|
for(a=0; a<4; a++) {
|
|
glDisable(GL_CLIP_PLANE0+a);
|
|
}
|
|
}
|
|
|
|
int view3d_test_clipping(View3D *v3d, float *vec)
|
|
{
|
|
/* vec in world coordinates, returns 1 if clipped */
|
|
float view[3];
|
|
|
|
VECCOPY(view, vec);
|
|
|
|
if(0.0f < v3d->clip[0][3] + INPR(view, v3d->clip[0]))
|
|
if(0.0f < v3d->clip[1][3] + INPR(view, v3d->clip[1]))
|
|
if(0.0f < v3d->clip[2][3] + INPR(view, v3d->clip[2]))
|
|
if(0.0f < v3d->clip[3][3] + INPR(view, v3d->clip[3]))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* ********* end custom clipping *********** */
|
|
|
|
static void view3d_get_viewborder_size(View3D *v3d, float size_r[2])
|
|
{
|
|
float winmax= MAX2(v3d->area->winx, v3d->area->winy);
|
|
float aspect= (float) (G.scene->r.xsch*G.scene->r.xasp)/(G.scene->r.ysch*G.scene->r.yasp);
|
|
|
|
if(aspect>1.0) {
|
|
size_r[0]= winmax;
|
|
size_r[1]= winmax/aspect;
|
|
} else {
|
|
size_r[0]= winmax*aspect;
|
|
size_r[1]= winmax;
|
|
}
|
|
}
|
|
|
|
void calc_viewborder(struct View3D *v3d, rctf *viewborder_r)
|
|
{
|
|
float zoomfac, size[2];
|
|
float dx= 0.0f, dy= 0.0f;
|
|
|
|
view3d_get_viewborder_size(v3d, size);
|
|
|
|
/* magic zoom calculation, no idea what
|
|
* it signifies, if you find out, tell me! -zr
|
|
*/
|
|
/* simple, its magic dude!
|
|
* well, to be honest, this gives a natural feeling zooming
|
|
* with multiple keypad presses (ton)
|
|
*/
|
|
|
|
zoomfac= (M_SQRT2 + v3d->camzoom/50.0);
|
|
zoomfac= (zoomfac*zoomfac)*0.25;
|
|
|
|
size[0]= size[0]*zoomfac;
|
|
size[1]= size[1]*zoomfac;
|
|
|
|
/* center in window */
|
|
viewborder_r->xmin= 0.5*v3d->area->winx - 0.5*size[0];
|
|
viewborder_r->ymin= 0.5*v3d->area->winy - 0.5*size[1];
|
|
viewborder_r->xmax= viewborder_r->xmin + size[0];
|
|
viewborder_r->ymax= viewborder_r->ymin + size[1];
|
|
|
|
dx= v3d->area->winx*G.vd->camdx;
|
|
dy= v3d->area->winy*G.vd->camdy;
|
|
|
|
/* apply offset */
|
|
viewborder_r->xmin-= dx;
|
|
viewborder_r->ymin-= dy;
|
|
viewborder_r->xmax-= dx;
|
|
viewborder_r->ymax-= dy;
|
|
}
|
|
|
|
void view3d_set_1_to_1_viewborder(View3D *v3d)
|
|
{
|
|
float size[2];
|
|
int im_width= (G.scene->r.size*G.scene->r.xsch)/100;
|
|
|
|
view3d_get_viewborder_size(v3d, size);
|
|
|
|
v3d->camzoom= (sqrt(4.0*im_width/size[0]) - M_SQRT2)*50.0;
|
|
v3d->camzoom= CLAMPIS(v3d->camzoom, -30, 300);
|
|
}
|
|
|
|
|
|
static void drawviewborder_flymode(void)
|
|
{
|
|
/* draws 4 edge brackets that frame the safe area where the
|
|
mouse can move during fly mode without spinning the view */
|
|
float x1, x2, y1, y2;
|
|
|
|
x1= 0.45*(float)curarea->winx;
|
|
y1= 0.45*(float)curarea->winy;
|
|
x2= 0.55*(float)curarea->winx;
|
|
y2= 0.55*(float)curarea->winy;
|
|
cpack(0);
|
|
|
|
|
|
glBegin(GL_LINES);
|
|
/* bottom left */
|
|
glVertex2f(x1,y1);
|
|
glVertex2f(x1,y1+5);
|
|
|
|
glVertex2f(x1,y1);
|
|
glVertex2f(x1+5,y1);
|
|
|
|
/* top right */
|
|
glVertex2f(x2,y2);
|
|
glVertex2f(x2,y2-5);
|
|
|
|
glVertex2f(x2,y2);
|
|
glVertex2f(x2-5,y2);
|
|
|
|
/* top left */
|
|
glVertex2f(x1,y2);
|
|
glVertex2f(x1,y2-5);
|
|
|
|
glVertex2f(x1,y2);
|
|
glVertex2f(x1+5,y2);
|
|
|
|
/* bottom right */
|
|
glVertex2f(x2,y1);
|
|
glVertex2f(x2,y1+5);
|
|
|
|
glVertex2f(x2,y1);
|
|
glVertex2f(x2-5,y1);
|
|
glEnd();
|
|
}
|
|
|
|
|
|
static void drawviewborder(void)
|
|
{
|
|
extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad); // interface_panel.c
|
|
float fac, a;
|
|
float x1, x2, y1, y2;
|
|
float x3, y3, x4, y4;
|
|
rctf viewborder;
|
|
Camera *ca= NULL;
|
|
|
|
if(G.vd->camera==NULL)
|
|
return;
|
|
if(G.vd->camera->type==OB_CAMERA)
|
|
ca = G.vd->camera->data;
|
|
|
|
calc_viewborder(G.vd, &viewborder);
|
|
x1= viewborder.xmin;
|
|
y1= viewborder.ymin;
|
|
x2= viewborder.xmax;
|
|
y2= viewborder.ymax;
|
|
|
|
/* passepartout, specified in camera edit buttons */
|
|
if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT)) {
|
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
|
glEnable(GL_BLEND);
|
|
glColor4f(0, 0, 0, ca->passepartalpha);
|
|
|
|
if (x1 > 0.0)
|
|
glRectf(0.0, (float)curarea->winy, x1, 0.0);
|
|
if (x2 < (float)curarea->winx)
|
|
glRectf(x2, (float)curarea->winy, (float)curarea->winx, 0.0);
|
|
if (y2 < (float)curarea->winy)
|
|
glRectf(x1, (float)curarea->winy, x2, y2);
|
|
if (y2 > 0.0)
|
|
glRectf(x1, y1, x2, 0.0);
|
|
|
|
glDisable(GL_BLEND);
|
|
}
|
|
|
|
/* edge */
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
|
|
setlinestyle(0);
|
|
BIF_ThemeColor(TH_BACK);
|
|
glRectf(x1, y1, x2, y2);
|
|
|
|
setlinestyle(3);
|
|
BIF_ThemeColor(TH_WIRE);
|
|
glRectf(x1, y1, x2, y2);
|
|
|
|
/* camera name */
|
|
if (ca && (ca->flag & CAM_SHOWNAME)) {
|
|
glRasterPos2f(x1, y1-15);
|
|
|
|
BMF_DrawString(G.font, G.vd->camera->id.name+2);
|
|
}
|
|
|
|
|
|
/* border */
|
|
if(G.scene->r.mode & R_BORDER) {
|
|
|
|
cpack(0);
|
|
x3= x1+ G.scene->r.border.xmin*(x2-x1);
|
|
y3= y1+ G.scene->r.border.ymin*(y2-y1);
|
|
x4= x1+ G.scene->r.border.xmax*(x2-x1);
|
|
y4= y1+ G.scene->r.border.ymax*(y2-y1);
|
|
|
|
cpack(0x4040FF);
|
|
glRectf(x3, y3, x4, y4);
|
|
}
|
|
|
|
/* safety border */
|
|
if (ca && (ca->flag & CAM_SHOWTITLESAFE)) {
|
|
fac= 0.1;
|
|
|
|
a= fac*(x2-x1);
|
|
x1+= a;
|
|
x2-= a;
|
|
|
|
a= fac*(y2-y1);
|
|
y1+= a;
|
|
y2-= a;
|
|
|
|
BIF_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
|
|
|
|
uiSetRoundBox(15);
|
|
gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
|
|
}
|
|
|
|
setlinestyle(0);
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
}
|
|
|
|
|
|
void backdrawview3d(int test)
|
|
{
|
|
struct Base *base;
|
|
|
|
if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT));
|
|
else if(G.obedit && G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT));
|
|
else {
|
|
G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
|
|
return;
|
|
}
|
|
|
|
if( !(G.vd->flag & V3D_NEEDBACKBUFDRAW) ) return;
|
|
|
|
if(test) {
|
|
if(qtest()) {
|
|
addafterqueue(curarea->win, BACKBUFDRAW, 1);
|
|
return;
|
|
}
|
|
}
|
|
persp(PERSP_VIEW);
|
|
|
|
#ifdef __APPLE__
|
|
glDrawBuffer(GL_AUX0);
|
|
#endif
|
|
if(G.vd->drawtype > OB_WIRE) G.vd->zbuf= TRUE;
|
|
curarea->win_swap &= ~WIN_BACK_OK;
|
|
|
|
glDisable(GL_DITHER);
|
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
|
if(G.vd->zbuf) {
|
|
glEnable(GL_DEPTH_TEST);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
else {
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
glDisable(GL_DEPTH_TEST);
|
|
}
|
|
|
|
if(G.vd->flag & V3D_CLIPPING)
|
|
view3d_set_clipping(G.vd);
|
|
|
|
G.f |= G_BACKBUFSEL;
|
|
|
|
base= (G.scene->basact);
|
|
if(base && (base->lay & G.vd->lay)) {
|
|
draw_object_backbufsel(base->object);
|
|
}
|
|
|
|
G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
|
|
|
|
G.f &= ~G_BACKBUFSEL;
|
|
G.vd->zbuf= FALSE;
|
|
glDisable(GL_DEPTH_TEST);
|
|
glEnable(GL_DITHER);
|
|
|
|
#ifdef __APPLE__
|
|
glDrawBuffer(GL_BACK); /* we were in aux buffers */
|
|
#endif
|
|
|
|
if(G.vd->flag & V3D_CLIPPING)
|
|
view3d_clr_clipping();
|
|
|
|
/* it is important to end a view in a transform compatible with buttons */
|
|
persp(PERSP_WIN); // set ortho
|
|
bwin_scalematrix(curarea->win, G.vd->blockscale, G.vd->blockscale, G.vd->blockscale);
|
|
|
|
}
|
|
|
|
void check_backbuf(void)
|
|
{
|
|
if(G.vd->flag & V3D_NEEDBACKBUFDRAW)
|
|
backdrawview3d(0);
|
|
}
|
|
|
|
/* samples a single pixel (copied from vpaint) */
|
|
unsigned int sample_backbuf(int x, int y)
|
|
{
|
|
unsigned int col;
|
|
|
|
if(x>=curarea->winx || y>=curarea->winy) return 0;
|
|
x+= curarea->winrct.xmin;
|
|
y+= curarea->winrct.ymin;
|
|
|
|
check_backbuf(); // actually not needed for apple
|
|
|
|
#ifdef __APPLE__
|
|
glReadBuffer(GL_AUX0);
|
|
#endif
|
|
glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
|
|
glReadBuffer(GL_BACK);
|
|
|
|
if(G.order==B_ENDIAN) SWITCH_INT(col);
|
|
|
|
return framebuffer_to_index(col);
|
|
}
|
|
|
|
/* reads full rect, converts indices */
|
|
ImBuf *read_backbuf(short xmin, short ymin, short xmax, short ymax)
|
|
{
|
|
unsigned int *dr, *rd;
|
|
struct ImBuf *ibuf, *ibuf1;
|
|
int a;
|
|
short xminc, yminc, xmaxc, ymaxc, xs, ys;
|
|
|
|
/* clip */
|
|
if(xmin<0) xminc= 0; else xminc= xmin;
|
|
if(xmax>=curarea->winx) xmaxc= curarea->winx-1; else xmaxc= xmax;
|
|
if(xminc > xmaxc) return NULL;
|
|
|
|
if(ymin<0) yminc= 0; else yminc= ymin;
|
|
if(ymax>=curarea->winy) ymaxc= curarea->winy-1; else ymaxc= ymax;
|
|
if(yminc > ymaxc) return NULL;
|
|
|
|
ibuf= IMB_allocImBuf((xmaxc-xminc+1), (ymaxc-yminc+1), 32, IB_rect,0);
|
|
|
|
check_backbuf(); // actually not needed for apple
|
|
|
|
#ifdef __APPLE__
|
|
glReadBuffer(GL_AUX0);
|
|
#endif
|
|
glReadPixels(curarea->winrct.xmin+xminc, curarea->winrct.ymin+yminc, (xmaxc-xminc+1), (ymaxc-yminc+1), GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
|
|
glReadBuffer(GL_BACK);
|
|
|
|
if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
|
|
|
|
a= (xmaxc-xminc+1)*(ymaxc-yminc+1);
|
|
dr= ibuf->rect;
|
|
while(a--) {
|
|
if(*dr) *dr= framebuffer_to_index(*dr);
|
|
dr++;
|
|
}
|
|
|
|
ibuf->ftype= PNG;
|
|
IMB_saveiff(ibuf, "/tmp/rt.png", IB_rect);
|
|
|
|
/* put clipped result back, if needed */
|
|
if(xminc==xmin && xmaxc==xmax && yminc==ymin && ymaxc==ymax)
|
|
return ibuf;
|
|
|
|
ibuf1= IMB_allocImBuf( (xmax-xmin+1),(ymax-ymin+1),32,IB_rect,0);
|
|
rd= ibuf->rect;
|
|
dr= ibuf1->rect;
|
|
|
|
for(ys= ymin; ys<=ymax; ys++) {
|
|
for(xs= xmin; xs<=xmax; xs++, dr++) {
|
|
if( xs>=xminc && xs<=xmaxc && ys>=yminc && ys<=ymaxc) {
|
|
*dr= *rd;
|
|
rd++;
|
|
}
|
|
}
|
|
}
|
|
IMB_freeImBuf(ibuf);
|
|
return ibuf1;
|
|
}
|
|
|
|
/* smart function to sample a rect spiralling outside, nice for backbuf selection */
|
|
unsigned int sample_backbuf_rect(short mval[2], int size, unsigned int min, unsigned int max, short *dist)
|
|
{
|
|
struct ImBuf *buf;
|
|
unsigned int *bufmin, *bufmax, *tbuf;
|
|
int minx, miny;
|
|
int a, b, rc, nr, amount, dirvec[4][2];
|
|
short distance=0;
|
|
unsigned int index = 0;
|
|
|
|
amount= (size-1)/2;
|
|
|
|
minx = mval[0]-(amount+1);
|
|
miny = mval[1]-(amount+1);
|
|
buf = read_backbuf(minx, miny, minx+size-1, miny+size-1);
|
|
if (!buf) return 0;
|
|
|
|
rc= 0;
|
|
|
|
dirvec[0][0]= 1; dirvec[0][1]= 0;
|
|
dirvec[1][0]= 0; dirvec[1][1]= -size;
|
|
dirvec[2][0]= -1; dirvec[2][1]= 0;
|
|
dirvec[3][0]= 0; dirvec[3][1]= size;
|
|
|
|
bufmin = buf->rect;
|
|
tbuf = buf->rect;
|
|
bufmax = buf->rect + size*size;
|
|
tbuf+= amount*size+ amount;
|
|
|
|
for(nr=1; nr<=size; nr++) {
|
|
|
|
for(a=0; a<2; a++) {
|
|
for(b=0; b<nr; b++, distance++) {
|
|
if (*tbuf && *tbuf>=min && *tbuf<max) {
|
|
*dist= (short) sqrt( (float)distance ); // XXX, this distance is wrong - zr
|
|
index = *tbuf - min+1; // messy yah, but indices start at 1
|
|
goto exit;
|
|
}
|
|
|
|
tbuf+= (dirvec[rc][0]+dirvec[rc][1]);
|
|
|
|
if(tbuf<bufmin || tbuf>=bufmax) {
|
|
goto exit;
|
|
}
|
|
}
|
|
rc++;
|
|
rc &= 3;
|
|
}
|
|
}
|
|
|
|
exit:
|
|
IMB_freeImBuf(buf);
|
|
return index;
|
|
}
|
|
|
|
void drawname(Object *ob)
|
|
{
|
|
cpack(0x404040);
|
|
glRasterPos3f(0.0, 0.0, 0.0);
|
|
|
|
BMF_DrawString(G.font, " ");
|
|
BMF_DrawString(G.font, ob->id.name+2);
|
|
}
|
|
|
|
|
|
static void draw_selected_name(Object *ob)
|
|
{
|
|
char info[128];
|
|
short offset=30;
|
|
|
|
if(ob->type==OB_ARMATURE) {
|
|
bArmature *arm= ob->data;
|
|
char *name= NULL;
|
|
|
|
if(ob==G.obedit) {
|
|
EditBone *ebo;
|
|
for (ebo=G.edbo.first; ebo; ebo=ebo->next){
|
|
if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) {
|
|
name= ebo->name;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if(ob->pose && (ob->flag & OB_POSEMODE)) {
|
|
bPoseChannel *pchan;
|
|
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
|
if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) {
|
|
name= pchan->name;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(name)
|
|
sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name);
|
|
else
|
|
sprintf(info, "(%d) %s", CFRA, ob->id.name+2);
|
|
}
|
|
else sprintf(info, "(%d) %s", CFRA, ob->id.name+2);
|
|
|
|
BIF_ThemeColor(TH_TEXT_HI);
|
|
if (U.uiflag & USER_SHOW_ROTVIEWICON)
|
|
offset = 14 + (U.rvisize * 2);
|
|
|
|
glRasterPos2i(offset, 10);
|
|
BMF_DrawString(G.fonts, info);
|
|
}
|
|
|
|
|
|
/* Draw a live substitute of the view icon, which is always shown */
|
|
static void draw_view_axis(void)
|
|
{
|
|
const float k = U.rvisize; /* axis size */
|
|
const float toll = 0.5; /* used to see when view is quasi-orthogonal */
|
|
const float start = k + 1.0; /* axis center in screen coordinates, x=y */
|
|
float ydisp = 0.0; /* vertical displacement to allow obj info text */
|
|
|
|
/* rvibright ranges approx. from original axis icon color to gizmo color */
|
|
float bright = U.rvibright / 15.0f;
|
|
|
|
unsigned char col[3];
|
|
unsigned char gridcol[3];
|
|
float colf[3];
|
|
|
|
float vec[4];
|
|
float dx, dy;
|
|
float h, s, v;
|
|
|
|
BIF_GetThemeColor3ubv(TH_GRID, gridcol);
|
|
|
|
/* X */
|
|
vec[0] = vec[3] = 1;
|
|
vec[1] = vec[2] = 0;
|
|
QuatMulVecf(G.vd->viewquat, vec);
|
|
|
|
make_axis_color(gridcol, col, 'x');
|
|
rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
|
|
s = s<0.5 ? s+0.5 : 1.0;
|
|
v = 0.3;
|
|
v = (v<1.0-(bright) ? v+bright : 1.0);
|
|
hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
|
|
glColor3fv(colf);
|
|
|
|
dx = vec[0] * k;
|
|
dy = vec[1] * k;
|
|
fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
|
|
if (fabs(dx) > toll || fabs(dy) > toll) {
|
|
glRasterPos2i(start + dx + 2, start + dy + ydisp + 2);
|
|
BMF_DrawString(G.fonts, "x");
|
|
}
|
|
|
|
/* Y */
|
|
vec[1] = vec[3] = 1;
|
|
vec[0] = vec[2] = 0;
|
|
QuatMulVecf(G.vd->viewquat, vec);
|
|
|
|
make_axis_color(gridcol, col, 'y');
|
|
rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
|
|
s = s<0.5 ? s+0.5 : 1.0;
|
|
v = 0.3;
|
|
v = (v<1.0-(bright) ? v+bright : 1.0);
|
|
hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
|
|
glColor3fv(colf);
|
|
|
|
dx = vec[0] * k;
|
|
dy = vec[1] * k;
|
|
fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
|
|
if (fabs(dx) > toll || fabs(dy) > toll) {
|
|
glRasterPos2i(start + dx + 2, start + dy + ydisp + 2);
|
|
BMF_DrawString(G.fonts, "y");
|
|
}
|
|
|
|
/* Z */
|
|
vec[2] = vec[3] = 1;
|
|
vec[1] = vec[0] = 0;
|
|
QuatMulVecf(G.vd->viewquat, vec);
|
|
|
|
make_axis_color(gridcol, col, 'z');
|
|
rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
|
|
s = s<0.5 ? s+0.5 : 1.0;
|
|
v = 0.5;
|
|
v = (v<1.0-(bright) ? v+bright : 1.0);
|
|
hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
|
|
glColor3fv(colf);
|
|
|
|
dx = vec[0] * k;
|
|
dy = vec[1] * k;
|
|
fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
|
|
if (fabs(dx) > toll || fabs(dy) > toll) {
|
|
glRasterPos2i(start + dx + 2, start + dy + ydisp + 2);
|
|
BMF_DrawString(G.fonts, "z");
|
|
}
|
|
}
|
|
|
|
|
|
static void draw_view_icon(void)
|
|
{
|
|
BIFIconID icon;
|
|
|
|
if(G.vd->view==7) icon= ICON_AXIS_TOP;
|
|
else if(G.vd->view==1) icon= ICON_AXIS_FRONT;
|
|
else if(G.vd->view==3) icon= ICON_AXIS_SIDE;
|
|
else return ;
|
|
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
BIF_icon_draw(5.0, 5.0, icon);
|
|
|
|
glBlendFunc(GL_ONE, GL_ZERO);
|
|
glDisable(GL_BLEND);
|
|
}
|
|
|
|
static void draw_viewport_name(ScrArea *sa)
|
|
{
|
|
char *name = NULL;
|
|
|
|
switch(G.vd->view) {
|
|
case 1:
|
|
name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Back" : "Front";
|
|
break;
|
|
case 3:
|
|
name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Left" : "Right";
|
|
break;
|
|
case 7:
|
|
name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Bottom" : "Top";
|
|
break;
|
|
default:
|
|
name = G.vd->persp==V3D_PERSP_USE_THE_CAMERA ? "Camera" : "User";
|
|
}
|
|
|
|
if (name) {
|
|
BIF_ThemeColor(TH_TEXT_HI);
|
|
glRasterPos2i(10, sa->winy-20);
|
|
BMF_DrawString(G.fonts, name);
|
|
}
|
|
}
|
|
|
|
/* ******************* view3d space & buttons ************** */
|
|
|
|
static void view3d_change_bgpic_ima(View3D *v3d, Image *newima) {
|
|
if (v3d->bgpic && v3d->bgpic->ima!=newima) {
|
|
if (newima)
|
|
id_us_plus((ID*) newima);
|
|
if (v3d->bgpic->ima)
|
|
v3d->bgpic->ima->id.us--;
|
|
v3d->bgpic->ima= newima;
|
|
|
|
if(v3d->bgpic->rect) MEM_freeN(v3d->bgpic->rect);
|
|
v3d->bgpic->rect= NULL;
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
}
|
|
static void view3d_change_bgpic_tex(View3D *v3d, Tex *newtex) {
|
|
if (v3d->bgpic && v3d->bgpic->tex!=newtex) {
|
|
if (newtex)
|
|
id_us_plus((ID*) newtex);
|
|
if (v3d->bgpic->tex)
|
|
v3d->bgpic->tex->id.us--;
|
|
v3d->bgpic->tex= newtex;
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
}
|
|
}
|
|
|
|
static void load_bgpic_image(char *name)
|
|
{
|
|
Image *ima;
|
|
View3D *vd;
|
|
|
|
areawinset(curarea->win);
|
|
vd= G.vd;
|
|
if(vd==0 || vd->bgpic==0) return;
|
|
|
|
ima= add_image(name);
|
|
if(ima) {
|
|
if(vd->bgpic->ima) {
|
|
vd->bgpic->ima->id.us--;
|
|
}
|
|
vd->bgpic->ima= ima;
|
|
|
|
free_image_buffers(ima); /* force read again */
|
|
ima->ok= 1;
|
|
}
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
}
|
|
|
|
/* this one assumes there is only one global active object in blender... (for object panel) */
|
|
static float ob_eul[4]; // used for quat too....
|
|
static float ob_scale[3]; // need temp space due to linked values
|
|
static float ob_dims[3];
|
|
static short link_scale = 0;
|
|
|
|
/* this one assumes there is only one editmode in blender... (for object panel) */
|
|
static float ve_median[5];
|
|
|
|
/* is used for both read and write... */
|
|
static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
|
|
{
|
|
static int curdef=0;
|
|
static float *defweightp= NULL;
|
|
EditMesh *em = G.editMesh;
|
|
EditVert *eve, *evedef=NULL;
|
|
EditEdge *eed;
|
|
float median[5];
|
|
int tot, totw, totweight, totedge;
|
|
char defstr[320];
|
|
|
|
median[0]= median[1]= median[2]= median[3]= median[4]= 0.0;
|
|
tot= totw= totweight= totedge= 0;
|
|
defstr[0]= 0;
|
|
|
|
if(ob->type==OB_MESH) {
|
|
eve= em->verts.first;
|
|
while(eve) {
|
|
if(eve->f & 1) {
|
|
evedef= eve;
|
|
tot++;
|
|
VecAddf(median, median, eve->co);
|
|
}
|
|
eve= eve->next;
|
|
}
|
|
eed= em->edges.first;
|
|
while(eed) {
|
|
if((eed->f & SELECT)) {
|
|
totedge++;
|
|
median[3]+= eed->crease;
|
|
}
|
|
eed= eed->next;
|
|
}
|
|
/* check for defgroups */
|
|
if(tot==1 && evedef->totweight) {
|
|
bDeformGroup *dg;
|
|
int i, max=1, init=1;
|
|
char str[32];
|
|
|
|
for (i=0; i<evedef->totweight; i++){
|
|
dg = BLI_findlink (&ob->defbase, evedef->dw[i].def_nr);
|
|
if(dg) {
|
|
max+= sprintf(str, "%s %%x%d|", dg->name, evedef->dw[i].def_nr);
|
|
if(max<320) strcat(defstr, str);
|
|
}
|
|
else printf("oh no!\n");
|
|
if(curdef==evedef->dw[i].def_nr) {
|
|
init= 0;
|
|
defweightp= &evedef->dw[i].weight;
|
|
}
|
|
}
|
|
|
|
if(init) { // needs new initialized
|
|
curdef= evedef->dw[0].def_nr;
|
|
defweightp= &evedef->dw[0].weight;
|
|
}
|
|
}
|
|
}
|
|
else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
|
|
extern ListBase editNurb; /* editcurve.c */
|
|
Nurb *nu;
|
|
BPoint *bp;
|
|
BezTriple *bezt;
|
|
int a;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
bezt= nu->bezt;
|
|
a= nu->pntsu;
|
|
while(a--) {
|
|
if(bezt->f2 & 1) {
|
|
VecAddf(median, median, bezt->vec[1]);
|
|
tot++;
|
|
median[4]+= bezt->weight;
|
|
totweight++;
|
|
}
|
|
else {
|
|
if(bezt->f1 & 1) {
|
|
VecAddf(median, median, bezt->vec[0]);
|
|
tot++;
|
|
}
|
|
if(bezt->f3 & 1) {
|
|
VecAddf(median, median, bezt->vec[2]);
|
|
tot++;
|
|
}
|
|
}
|
|
bezt++;
|
|
}
|
|
}
|
|
else {
|
|
bp= nu->bp;
|
|
a= nu->pntsu*nu->pntsv;
|
|
while(a--) {
|
|
if(bp->f1 & 1) {
|
|
VecAddf(median, median, bp->vec);
|
|
median[3]+= bp->vec[3];
|
|
totw++;
|
|
tot++;
|
|
median[4]+= bp->weight;
|
|
totweight++;
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
nu= nu->next;
|
|
}
|
|
}
|
|
else if(ob->type==OB_LATTICE) {
|
|
BPoint *bp;
|
|
int a;
|
|
|
|
a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
|
bp= editLatt->def;
|
|
while(a--) {
|
|
if(bp->f1 & SELECT) {
|
|
VecAddf(median, median, bp->vec);
|
|
tot++;
|
|
median[4]+= bp->weight;
|
|
totweight++;
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
|
|
if(tot==0) return;
|
|
|
|
median[0] /= (float)tot;
|
|
median[1] /= (float)tot;
|
|
median[2] /= (float)tot;
|
|
if(totedge) median[3] /= (float)totedge;
|
|
else if(totw) median[3] /= (float)totw;
|
|
if(totweight) median[4] /= (float)totweight;
|
|
|
|
if(G.vd->flag & V3D_GLOBAL_STATS)
|
|
Mat4MulVecfl(ob->obmat, median);
|
|
|
|
if(block) { // buttons
|
|
|
|
uiBlockBeginAlign(block);
|
|
uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, REDRAWVIEW3D, "Global", 160, 150, 70, 19, &G.vd->flag, 0, 0, 0, 0, "Displays global values");
|
|
uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, REDRAWVIEW3D, "Local", 230, 150, 70, 19, &G.vd->flag, 0, 0, 0, 0, "Displays local values");
|
|
|
|
memcpy(ve_median, median, sizeof(ve_median));
|
|
|
|
uiBlockBeginAlign(block);
|
|
if(tot==1) {
|
|
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex X:", 10, 110, 290, 19, &(ve_median[0]), -lim, lim, 10, 3, "");
|
|
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex Y:", 10, 90, 290, 19, &(ve_median[1]), -lim, lim, 10, 3, "");
|
|
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex Z:", 10, 70, 290, 19, &(ve_median[2]), -lim, lim, 10, 3, "");
|
|
if(totw==1)
|
|
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex W:", 10, 50, 290, 19, &(ve_median[3]), 0.01, 100.0, 10, 3, "");
|
|
uiBlockEndAlign(block);
|
|
|
|
if(defstr[0]) {
|
|
uiDefBut(block, LABEL, 1, "Vertex Deform Groups", 10, 40, 290, 20, NULL, 0.0, 0.0, 0, 0, "");
|
|
|
|
uiBlockBeginAlign(block);
|
|
uiDefButF(block, NUM, B_NOP, "Weight:", 10, 20, 150, 19, defweightp, 0.0f, 1.0f, 10, 3, "Weight value");
|
|
uiDefButI(block, MENU, REDRAWVIEW3D, defstr, 160, 20, 140, 19, &curdef, 0.0, 0.0, 0, 0, "Current Vertex Group");
|
|
uiBlockEndAlign(block);
|
|
}
|
|
else if(totweight)
|
|
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 10, 20, 290, 19, &(ve_median[4]), 0.0, 1.0, 10, 3, "");
|
|
|
|
}
|
|
else {
|
|
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median X:", 10, 110, 290, 19, &(ve_median[0]), -lim, lim, 10, 3, "");
|
|
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Y:", 10, 90, 290, 19, &(ve_median[1]), -lim, lim, 10, 3, "");
|
|
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Z:", 10, 70, 290, 19, &(ve_median[2]), -lim, lim, 10, 3, "");
|
|
if(totw==tot)
|
|
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median W:", 10, 50, 290, 19, &(ve_median[3]), 0.01, 100.0, 10, 3, "");
|
|
uiBlockEndAlign(block);
|
|
if(totweight)
|
|
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 10, 20, 290, 19, &(ve_median[4]), 0.0, 1.0, 10, 3, "Weight is used for SoftBody Goal");
|
|
}
|
|
|
|
if(totedge==1)
|
|
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Crease W:", 10, 30, 290, 19, &(ve_median[3]), 0.0, 1.0, 10, 3, "");
|
|
else if(totedge>1)
|
|
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Crease W:", 10, 30, 290, 19, &(ve_median[3]), 0.0, 1.0, 10, 3, "");
|
|
|
|
}
|
|
else { // apply
|
|
|
|
if(G.vd->flag & V3D_GLOBAL_STATS) {
|
|
Mat4Invert(ob->imat, ob->obmat);
|
|
Mat4MulVecfl(ob->imat, median);
|
|
Mat4MulVecfl(ob->imat, ve_median);
|
|
}
|
|
VecSubf(median, ve_median, median);
|
|
median[3]= ve_median[3]-median[3];
|
|
median[4]= ve_median[4]-median[4];
|
|
|
|
if(ob->type==OB_MESH) {
|
|
float diffac= 1.0;
|
|
|
|
eve= em->verts.first;
|
|
while(eve) {
|
|
if(eve->f & 1) {
|
|
VecAddf(eve->co, eve->co, median);
|
|
}
|
|
eve= eve->next;
|
|
}
|
|
|
|
/* calculate the differences to squeeze a range smaller when values are close to 1 or 0 */
|
|
/* this way you can edit a median value which is applied on clipped values :) */
|
|
if(totedge>1) {
|
|
float max= 0.0;
|
|
for(eed= em->edges.first; eed; eed= eed->next) {
|
|
if(eed->f & SELECT) {
|
|
if(max < ABS(eed->crease-ve_median[3])) max= ABS(eed->crease-ve_median[3]);
|
|
}
|
|
}
|
|
if(max>0.0) {
|
|
if(ve_median[3]> 0.5) diffac= (1.0-ve_median[3])/max;
|
|
else diffac= (ve_median[3])/max;
|
|
if(diffac>1.0) diffac= 1.0;
|
|
}
|
|
}
|
|
|
|
for(eed= em->edges.first; eed; eed= eed->next) {
|
|
if(eed->f & SELECT) {
|
|
eed->crease+= median[3];
|
|
eed->crease= ve_median[3] + diffac*(eed->crease-ve_median[3]);
|
|
|
|
CLAMP(eed->crease, 0.0, 1.0);
|
|
}
|
|
}
|
|
|
|
recalc_editnormals();
|
|
}
|
|
else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
|
|
extern ListBase editNurb; /* editcurve.c */
|
|
Nurb *nu;
|
|
BPoint *bp;
|
|
BezTriple *bezt;
|
|
int a;
|
|
|
|
nu= editNurb.first;
|
|
while(nu) {
|
|
if((nu->type & 7)==1) {
|
|
bezt= nu->bezt;
|
|
a= nu->pntsu;
|
|
while(a--) {
|
|
if(bezt->f2 & 1) {
|
|
VecAddf(bezt->vec[0], bezt->vec[0], median);
|
|
VecAddf(bezt->vec[1], bezt->vec[1], median);
|
|
VecAddf(bezt->vec[2], bezt->vec[2], median);
|
|
bezt->weight+= median[4];
|
|
}
|
|
else {
|
|
if(bezt->f1 & 1) {
|
|
VecAddf(bezt->vec[0], bezt->vec[0], median);
|
|
}
|
|
if(bezt->f3 & 1) {
|
|
VecAddf(bezt->vec[2], bezt->vec[2], median);
|
|
}
|
|
}
|
|
bezt++;
|
|
}
|
|
}
|
|
else {
|
|
bp= nu->bp;
|
|
a= nu->pntsu*nu->pntsv;
|
|
while(a--) {
|
|
if(bp->f1 & 1) {
|
|
VecAddf(bp->vec, bp->vec, median);
|
|
bp->vec[3]+= median[3];
|
|
bp->weight+= median[4];
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
test2DNurb(nu);
|
|
testhandlesNurb(nu); /* test for bezier too */
|
|
|
|
nu= nu->next;
|
|
}
|
|
}
|
|
else if(ob->type==OB_LATTICE) {
|
|
BPoint *bp;
|
|
int a;
|
|
|
|
a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
|
bp= editLatt->def;
|
|
while(a--) {
|
|
if(bp->f1 & SELECT) {
|
|
VecAddf(bp->vec, bp->vec, median);
|
|
bp->weight+= median[4];
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
|
|
BIF_undo_push("Transform properties");
|
|
}
|
|
}
|
|
|
|
/* assumes armature active */
|
|
static void validate_bonebutton_cb(void *bonev, void *namev)
|
|
{
|
|
Object *ob= OBACT;
|
|
|
|
if(ob && ob->type==OB_ARMATURE) {
|
|
Bone *bone= bonev;
|
|
char oldname[32], newname[32];
|
|
|
|
/* need to be on the stack */
|
|
BLI_strncpy(newname, bone->name, 32);
|
|
BLI_strncpy(oldname, (char *)namev, 32);
|
|
/* restore */
|
|
BLI_strncpy(bone->name, oldname, 32);
|
|
|
|
armature_bone_rename(ob->data, oldname, newname); // editarmature.c
|
|
allqueue(REDRAWALL, 0);
|
|
}
|
|
}
|
|
|
|
|
|
static void v3d_posearmature_buts(uiBlock *block, Object *ob, float lim)
|
|
{
|
|
uiBut *but;
|
|
bArmature *arm;
|
|
bPoseChannel *pchan;
|
|
Bone *bone;
|
|
|
|
arm = get_armature(OBACT);
|
|
if (!arm || !ob->pose) return;
|
|
|
|
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
|
bone = pchan->bone;
|
|
if(bone && (bone->flag & BONE_ACTIVE) && (bone->layer & arm->layer))
|
|
break;
|
|
}
|
|
if (!pchan) return;
|
|
|
|
but= uiDefBut(block, TEX, B_DIFF, "Bone:", 160, 140, 140, 19, bone->name, 1, 31, 0, 0, "");
|
|
uiButSetFunc(but, validate_bonebutton_cb, bone, NULL);
|
|
|
|
QuatToEul(pchan->quat, ob_eul);
|
|
ob_eul[0]*= 180.0/M_PI;
|
|
ob_eul[1]*= 180.0/M_PI;
|
|
ob_eul[2]*= 180.0/M_PI;
|
|
|
|
uiBlockBeginAlign(block);
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCX, REDRAWVIEW3D, ICON_UNLOCKED, 10,140,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocX:", 30, 140, 120, 19, pchan->loc, -lim, lim, 100, 3, "");
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCY, REDRAWVIEW3D, ICON_UNLOCKED, 10,120,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocY:", 30, 120, 120, 19, pchan->loc+1, -lim, lim, 100, 3, "");
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCZ, REDRAWVIEW3D, ICON_UNLOCKED, 10,100,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL2, "locZ:", 30, 100, 120, 19, pchan->loc+2, -lim, lim, 100, 3, "");
|
|
|
|
uiBlockBeginAlign(block);
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, REDRAWVIEW3D, ICON_UNLOCKED, 10,70,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotX:", 30, 70, 120, 19, ob_eul, -1000.0, 1000.0, 100, 3, "");
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, REDRAWVIEW3D, ICON_UNLOCKED, 10,50,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotY:", 30, 50, 120, 19, ob_eul+1, -1000.0, 1000.0, 100, 3, "");
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, REDRAWVIEW3D, ICON_UNLOCKED, 10,30,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotZ:", 30, 30, 120, 19, ob_eul+2, -1000.0, 1000.0, 100, 3, "");
|
|
|
|
uiBlockBeginAlign(block);
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEX, REDRAWVIEW3D, ICON_UNLOCKED, 160,70,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleX:", 180, 70, 120, 19, pchan->size, -lim, lim, 10, 3, "");
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEY, REDRAWVIEW3D, ICON_UNLOCKED, 160,50,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleY:", 180, 50, 120, 19, pchan->size+1, -lim, lim, 10, 3, "");
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEZ, REDRAWVIEW3D, ICON_UNLOCKED, 160,30,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleZ:", 180, 30, 120, 19, pchan->size+2, -lim, lim, 10, 3, "");
|
|
uiBlockEndAlign(block);
|
|
}
|
|
|
|
static void v3d_editarmature_buts(uiBlock *block, Object *ob, float lim)
|
|
{
|
|
bArmature *arm= G.obedit->data;
|
|
EditBone *ebone;
|
|
uiBut *but;
|
|
|
|
ebone= G.edbo.first;
|
|
|
|
for (ebone = G.edbo.first; ebone; ebone=ebone->next){
|
|
if ((ebone->flag & BONE_ACTIVE) && (ebone->layer & arm->layer))
|
|
break;
|
|
}
|
|
|
|
if (!ebone)
|
|
return;
|
|
|
|
but= uiDefBut(block, TEX, B_DIFF, "Bone:", 160, 150, 140, 19, ebone->name, 1, 31, 0, 0, "");
|
|
uiButSetFunc(but, validate_editbonebutton_cb, ebone, NULL);
|
|
|
|
uiBlockBeginAlign(block);
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL1, "RootX:", 10, 70, 140, 19, ebone->head, -lim, lim, 10, 3, "");
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL1, "RootY:", 10, 50, 140, 19, ebone->head+1, -lim, lim, 10, 3, "");
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL1, "RootZ:", 10, 30, 140, 19, ebone->head+2, -lim, lim, 10, 3, "");
|
|
uiBlockBeginAlign(block);
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL1, "TipX:", 160, 70, 140, 19, ebone->tail, -lim, lim, 10, 3, "");
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL1, "TipY:", 160, 50, 140, 19, ebone->tail+1, -lim, lim, 10, 3, "");
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL1, "TipZ:", 160, 30, 140, 19, ebone->tail+2, -lim, lim, 10, 3, "");
|
|
uiBlockEndAlign(block);
|
|
ob_eul[0]= 180.0*ebone->roll/M_PI;
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL1, "Roll:", 10, 100, 140, 19, ob_eul, -lim, lim, 1000, 3, "");
|
|
|
|
|
|
uiBlockBeginAlign(block);
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL1, "TipRadius:", 10, 150, 140, 19, &ebone->rad_tail, 0, lim, 10, 3, "");
|
|
if (ebone->parent && ebone->flag & BONE_CONNECTED )
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadRadius:", 10, 130, 140, 19, &ebone->parent->rad_tail, 0, lim, 10, 3, "");
|
|
else
|
|
uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadRadius:", 10, 130, 140, 19, &ebone->rad_head, 0, lim, 10, 3, "");
|
|
uiBlockEndAlign(block);
|
|
}
|
|
|
|
static void v3d_editmetaball_buts(uiBlock *block, Object *ob, float lim)
|
|
{
|
|
extern MetaElem *lastelem;
|
|
|
|
if(lastelem) {
|
|
uiBlockBeginAlign(block);
|
|
uiDefButF(block, NUM, B_RECALCMBALL, "LocX:", 10, 70, 140, 19, &lastelem->x, -lim, lim, 100, 3, "");
|
|
uiDefButF(block, NUM, B_RECALCMBALL, "LocY:", 10, 50, 140, 19, &lastelem->y, -lim, lim, 100, 3, "");
|
|
uiDefButF(block, NUM, B_RECALCMBALL, "LocZ:", 10, 30, 140, 19, &lastelem->z, -lim, lim, 100, 3, "");
|
|
|
|
uiBlockBeginAlign(block);
|
|
if(lastelem->type!=MB_BALL)
|
|
uiDefButF(block, NUM, B_RECALCMBALL, "dx:", 160, 70, 140, 19, &lastelem->expx, 0, lim, 100, 3, "");
|
|
if((lastelem->type!=MB_BALL) && (lastelem->type!=MB_TUBE))
|
|
uiDefButF(block, NUM, B_RECALCMBALL, "dy:", 160, 50, 140, 19, &lastelem->expy, 0, lim, 100, 3, "");
|
|
if((lastelem->type==MB_ELIPSOID) || (lastelem->type==MB_CUBE))
|
|
uiDefButF(block, NUM, B_RECALCMBALL, "dz:", 160, 30, 140, 19, &lastelem->expz, 0, lim, 100, 3, "");
|
|
|
|
uiBlockEndAlign(block);
|
|
|
|
uiDefButF(block, NUM, B_RECALCMBALL, "Stiffness:", 10, 100, 140, 19, &lastelem->s, 0, lim, 100, 3, "");
|
|
}
|
|
}
|
|
|
|
void do_viewbuts(unsigned short event)
|
|
{
|
|
BoundBox *bb;
|
|
View3D *vd;
|
|
Object *ob= OBACT;
|
|
char *name;
|
|
|
|
vd= G.vd;
|
|
if(vd==0) return;
|
|
|
|
switch(event) {
|
|
case B_LOADBGPIC:
|
|
if(vd->bgpic && vd->bgpic->ima) name= vd->bgpic->ima->name;
|
|
else name= G.ima;
|
|
|
|
if(G.qual==LR_CTRLKEY)
|
|
activate_imageselect(FILE_SPECIAL, "Select Image", name, load_bgpic_image);
|
|
else
|
|
activate_fileselect(FILE_SPECIAL, "Select Image", name, load_bgpic_image);
|
|
break;
|
|
|
|
case B_BLENDBGPIC:
|
|
if(vd->bgpic && vd->bgpic->rect) setalpha_bgpic(vd->bgpic);
|
|
addqueue(curarea->win, REDRAW, 1);
|
|
break;
|
|
|
|
case B_BGPICBROWSE:
|
|
if(vd->bgpic) {
|
|
if (vd->menunr==-2) {
|
|
activate_databrowse((ID*) vd->bgpic->ima, ID_IM, 0, B_BGPICBROWSE, &vd->menunr, do_viewbuts);
|
|
} else if (vd->menunr>0) {
|
|
Image *newima= (Image*) BLI_findlink(&G.main->image, vd->menunr-1);
|
|
|
|
if (newima)
|
|
view3d_change_bgpic_ima(vd, newima);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case B_BGPICCLEAR:
|
|
if (vd->bgpic)
|
|
view3d_change_bgpic_ima(vd, NULL);
|
|
break;
|
|
|
|
case B_BGPICTEX:
|
|
if (vd->bgpic) {
|
|
if (vd->texnr==-2) {
|
|
activate_databrowse((ID*) vd->bgpic->tex, ID_TE, 0, B_BGPICTEX, &vd->texnr, do_viewbuts);
|
|
} else if (vd->texnr>0) {
|
|
Tex *newtex= (Tex*) BLI_findlink(&G.main->tex, vd->texnr-1);
|
|
|
|
if (newtex)
|
|
view3d_change_bgpic_tex(vd, newtex);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case B_BGPICTEXCLEAR:
|
|
if (vd->bgpic)
|
|
view3d_change_bgpic_tex(vd, NULL);
|
|
break;
|
|
|
|
case B_OBJECTPANEL:
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
|
|
allqueue(REDRAWVIEW3D, 1);
|
|
break;
|
|
|
|
case B_OBJECTPANELROT:
|
|
if(ob) {
|
|
ob->rot[0]= M_PI*ob_eul[0]/180.0;
|
|
ob->rot[1]= M_PI*ob_eul[1]/180.0;
|
|
ob->rot[2]= M_PI*ob_eul[2]/180.0;
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
|
|
allqueue(REDRAWVIEW3D, 1);
|
|
}
|
|
break;
|
|
|
|
case B_OBJECTPANELSCALE:
|
|
if(ob) {
|
|
float ratio, tmp, max = 0.0;
|
|
int axis;
|
|
|
|
/* figure out which axis changed */
|
|
axis = 0;
|
|
max = fabs(ob_scale[0] - ob->size[0]);
|
|
tmp = fabs(ob_scale[1] - ob->size[1]);
|
|
if (tmp > max) {
|
|
axis = 1;
|
|
max = tmp;
|
|
}
|
|
tmp = fabs(ob_scale[2] - ob->size[2]);
|
|
if (tmp > max) {
|
|
axis = 2;
|
|
max = tmp;
|
|
}
|
|
|
|
if (ob->size[axis] != ob_scale[axis]) {
|
|
if (link_scale) {
|
|
if (fabs(ob->size[axis]) > FLT_EPSILON) {
|
|
ratio = ob_scale[axis] / ob->size[axis];
|
|
ob->size[0] *= ratio;
|
|
ob->size[1] *= ratio;
|
|
ob->size[2] *= ratio;
|
|
}
|
|
}
|
|
ob->size[axis] = ob_scale[axis];
|
|
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
|
|
allqueue(REDRAWVIEW3D, 1);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case B_OBJECTPANELDIMS:
|
|
bb= object_get_boundbox(ob);
|
|
if(bb) {
|
|
float old_dims[3], scale[3], ratio, len[3];
|
|
int axis;
|
|
|
|
Mat4ToSize(ob->obmat, scale);
|
|
|
|
len[0] = bb->vec[4][0] - bb->vec[0][0];
|
|
len[1] = bb->vec[2][1] - bb->vec[0][1];
|
|
len[2] = bb->vec[1][2] - bb->vec[0][2];
|
|
|
|
old_dims[0] = fabs(scale[0]) * len[0];
|
|
old_dims[1] = fabs(scale[1]) * len[1];
|
|
old_dims[2] = fabs(scale[2]) * len[2];
|
|
|
|
/* for each axis changed */
|
|
for (axis = 0; axis<3; axis++) {
|
|
if (fabs(old_dims[axis] - ob_dims[axis]) > 0.0001) {
|
|
if (old_dims[axis] > 0.0) {
|
|
ratio = ob_dims[axis] / old_dims[axis];
|
|
if (link_scale) {
|
|
ob->size[0] *= ratio;
|
|
ob->size[1] *= ratio;
|
|
ob->size[2] *= ratio;
|
|
break;
|
|
}
|
|
else {
|
|
ob->size[axis] *= ratio;
|
|
}
|
|
}
|
|
else {
|
|
if (len[axis] > 0) {
|
|
ob->size[axis] = ob_dims[axis] / len[axis];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* prevent multiple B_OBJECTPANELDIMS events to keep scaling, cycling with TAB on buttons can cause that */
|
|
VECCOPY(ob_dims, old_dims);
|
|
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
|
|
allqueue(REDRAWVIEW3D, 1);
|
|
}
|
|
break;
|
|
|
|
case B_OBJECTPANELMEDIAN:
|
|
if(ob) {
|
|
v3d_editvertex_buts(NULL, ob, 1.0);
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
|
allqueue(REDRAWVIEW3D, 1);
|
|
}
|
|
break;
|
|
case B_OBJECTPANELPARENT:
|
|
if(ob) {
|
|
if(ob->id.lib || test_parent_loop(ob->parent, ob) )
|
|
ob->parent= NULL;
|
|
else {
|
|
DAG_scene_sort(G.scene);
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
|
|
}
|
|
allqueue(REDRAWVIEW3D, 1);
|
|
allqueue(REDRAWBUTSOBJECT, 0);
|
|
}
|
|
break;
|
|
|
|
case B_ARMATUREPANEL1:
|
|
{
|
|
bArmature *arm= G.obedit->data;
|
|
EditBone *ebone, *child;
|
|
|
|
for (ebone = G.edbo.first; ebone; ebone=ebone->next){
|
|
if ((ebone->flag & BONE_ACTIVE) && (ebone->layer & arm->layer))
|
|
break;
|
|
}
|
|
if (ebone) {
|
|
ebone->roll= M_PI*ob_eul[0]/180.0;
|
|
// Update our parent
|
|
if (ebone->parent && ebone->flag & BONE_CONNECTED){
|
|
VECCOPY (ebone->parent->tail, ebone->head);
|
|
}
|
|
|
|
// Update our children if necessary
|
|
for (child = G.edbo.first; child; child=child->next){
|
|
if (child->parent == ebone && (child->flag & BONE_CONNECTED)){
|
|
VECCOPY (child->head, ebone->tail);
|
|
}
|
|
}
|
|
if(arm->flag & ARM_MIRROR_EDIT) {
|
|
EditBone *eboflip= armature_bone_get_mirrored(ebone);
|
|
if(eboflip) {
|
|
eboflip->roll= -ebone->roll;
|
|
eboflip->head[0]= -ebone->head[0];
|
|
eboflip->tail[0]= -ebone->tail[0];
|
|
|
|
// Update our parent
|
|
if (eboflip->parent && eboflip->flag & BONE_CONNECTED){
|
|
VECCOPY (eboflip->parent->tail, eboflip->head);
|
|
}
|
|
|
|
// Update our children if necessary
|
|
for (child = G.edbo.first; child; child=child->next){
|
|
if (child->parent == eboflip && (child->flag & BONE_CONNECTED)){
|
|
VECCOPY (child->head, eboflip->tail);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
allqueue(REDRAWVIEW3D, 1);
|
|
}
|
|
}
|
|
break;
|
|
case B_ARMATUREPANEL3: // rotate button on channel
|
|
{
|
|
bArmature *arm;
|
|
bPoseChannel *pchan;
|
|
Bone *bone;
|
|
|
|
arm = get_armature(OBACT);
|
|
if (!arm || !ob->pose) return;
|
|
|
|
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
|
bone = pchan->bone;
|
|
if(bone && (bone->flag & BONE_ACTIVE) && (bone->layer & arm->layer))
|
|
break;
|
|
}
|
|
if (!pchan) return;
|
|
|
|
ob_eul[0]*= M_PI/180.0;
|
|
ob_eul[1]*= M_PI/180.0;
|
|
ob_eul[2]*= M_PI/180.0;
|
|
EulToQuat(ob_eul, pchan->quat);
|
|
}
|
|
/* no break, pass on */
|
|
case B_ARMATUREPANEL2:
|
|
{
|
|
ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
|
allqueue(REDRAWVIEW3D, 1);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void view3d_panel_object(short cntrl) // VIEW3D_HANDLER_OBJECT
|
|
{
|
|
uiBlock *block;
|
|
uiBut *bt;
|
|
Object *ob= OBACT;
|
|
float lim;
|
|
static char hexcol[128];
|
|
|
|
if(ob==NULL) return;
|
|
|
|
block= uiNewBlock(&curarea->uiblocks, "view3d_panel_object", UI_EMBOSS, UI_HELV, curarea->win);
|
|
uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
|
|
uiSetPanelHandler(VIEW3D_HANDLER_OBJECT); // for close and esc
|
|
|
|
/* (ton) can't use the rename trick for paint... panel names and settings are stored in the files and
|
|
used to find previous locations when re-open. This causes flipping */
|
|
|
|
if(uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 318, 204)==0) return;
|
|
|
|
if(ob->id.lib) uiSetButLock(1, "Can't edit library data");
|
|
|
|
if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
|
|
uiBlockSetFlag(block, UI_BLOCK_FRONTBUFFER); // force old style frontbuffer draw
|
|
}
|
|
else {
|
|
bt= uiDefBut(block, TEX, B_IDNAME, "OB: ", 10,180,140,20, ob->id.name+2, 0.0, 19.0, 0, 0, "");
|
|
uiButSetFunc(bt, test_idbutton_cb, ob->id.name, NULL);
|
|
|
|
uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_OBJECTPANELPARENT, "Par:", 160, 180, 140, 20, &ob->parent, "Parent Object");
|
|
}
|
|
|
|
lim= 10000.0f*MAX2(1.0, G.vd->grid);
|
|
|
|
if(ob==G.obedit) {
|
|
if(ob->type==OB_ARMATURE) v3d_editarmature_buts(block, ob, lim);
|
|
if(ob->type==OB_MBALL) v3d_editmetaball_buts(block, ob, lim);
|
|
else v3d_editvertex_buts(block, ob, lim);
|
|
}
|
|
else if(ob->flag & OB_POSEMODE) {
|
|
v3d_posearmature_buts(block, ob, lim);
|
|
}
|
|
else if(G.f & (G_VERTEXPAINT|G_TEXTUREPAINT)) {
|
|
extern VPaint Gvp; /* from vpaint */
|
|
static float hsv[3], old[3]; // used as temp mem for picker
|
|
uiBlockPickerButtons(block, &Gvp.r, hsv, old, hexcol, 'f', REDRAWBUTSEDIT); /* 'f' is for floating panel */
|
|
}
|
|
else {
|
|
BoundBox *bb = NULL;
|
|
|
|
uiBlockBeginAlign(block);
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCX, REDRAWVIEW3D, ICON_UNLOCKED, 10,150,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_OBJECTPANEL, "LocX:", 30, 150, 120, 19, &(ob->loc[0]), -lim, lim, 100, 3, "");
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCY, REDRAWVIEW3D, ICON_UNLOCKED, 10,130,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_OBJECTPANEL, "LocY:", 30, 130, 120, 19, &(ob->loc[1]), -lim, lim, 100, 3, "");
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCZ, REDRAWVIEW3D, ICON_UNLOCKED, 10,110,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_OBJECTPANEL, "LocZ:", 30, 110, 120, 19, &(ob->loc[2]), -lim, lim, 100, 3, "");
|
|
|
|
ob_eul[0]= 180.0*ob->rot[0]/M_PI;
|
|
ob_eul[1]= 180.0*ob->rot[1]/M_PI;
|
|
ob_eul[2]= 180.0*ob->rot[2]/M_PI;
|
|
|
|
uiBlockBeginAlign(block);
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, REDRAWVIEW3D, ICON_UNLOCKED, 160,150,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_OBJECTPANELROT, "RotX:", 180, 150, 120, 19, &(ob_eul[0]), -lim, lim, 1000, 3, "");
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, REDRAWVIEW3D, ICON_UNLOCKED, 160,130,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_OBJECTPANELROT, "RotY:", 180, 130, 120, 19, &(ob_eul[1]), -lim, lim, 1000, 3, "");
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, REDRAWVIEW3D, ICON_UNLOCKED, 160,110,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_OBJECTPANELROT, "RotZ:", 180, 110, 120, 19, &(ob_eul[2]), -lim, lim, 1000, 3, "");
|
|
|
|
ob_scale[0]= ob->size[0];
|
|
ob_scale[1]= ob->size[1];
|
|
ob_scale[2]= ob->size[2];
|
|
|
|
uiBlockBeginAlign(block);
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEX, REDRAWVIEW3D, ICON_UNLOCKED, 10,80,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_OBJECTPANELSCALE, "ScaleX:", 30, 80, 120, 19, &(ob_scale[0]), -lim, lim, 10, 3, "");
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEY, REDRAWVIEW3D, ICON_UNLOCKED, 10,60,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_OBJECTPANELSCALE, "ScaleY:", 30, 60, 120, 19, &(ob_scale[1]), -lim, lim, 10, 3, "");
|
|
uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEZ, REDRAWVIEW3D, ICON_UNLOCKED, 10,40,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
|
|
uiDefButF(block, NUM, B_OBJECTPANELSCALE, "ScaleZ:", 30, 40, 120, 19, &(ob_scale[2]), -lim, lim, 10, 3, "");
|
|
uiBlockEndAlign(block);
|
|
|
|
uiDefButS(block, TOG, REDRAWVIEW3D, "Link Scale", 10, 10, 140, 19, &(link_scale), 0, 1, 0, 0, "Scale values vary proportionally in all directions");
|
|
|
|
bb= object_get_boundbox(ob);
|
|
if (bb) {
|
|
float scale[3];
|
|
|
|
Mat4ToSize(ob->obmat, scale);
|
|
|
|
ob_dims[0] = fabs(scale[0]) * (bb->vec[4][0] - bb->vec[0][0]);
|
|
ob_dims[1] = fabs(scale[1]) * (bb->vec[2][1] - bb->vec[0][1]);
|
|
ob_dims[2] = fabs(scale[2]) * (bb->vec[1][2] - bb->vec[0][2]);
|
|
|
|
uiBlockBeginAlign(block);
|
|
uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimX:", 160, 80, 140, 19, &(ob_dims[0]), 0.0, lim, 10, 3, "Manipulate bounding box size");
|
|
uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimY:", 160, 60, 140, 19, &(ob_dims[1]), 0.0, lim, 10, 3, "Manipulate bounding box size");
|
|
uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimZ:", 160, 40, 140, 19, &(ob_dims[2]), 0.0, lim, 10, 3, "Manipulate bounding box size");
|
|
|
|
uiBlockEndAlign(block);
|
|
}
|
|
}
|
|
uiClearButLock();
|
|
}
|
|
|
|
static void view3d_panel_background(short cntrl) // VIEW3D_HANDLER_BACKGROUND
|
|
{
|
|
uiBlock *block;
|
|
View3D *vd;
|
|
ID *id;
|
|
char *strp;
|
|
|
|
vd= G.vd;
|
|
|
|
block= uiNewBlock(&curarea->uiblocks, "view3d_panel_background", UI_EMBOSS, UI_HELV, curarea->win);
|
|
uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
|
|
uiSetPanelHandler(VIEW3D_HANDLER_BACKGROUND); // for close and esc
|
|
if(uiNewPanel(curarea, block, "Background Image", "View3d", 340, 10, 318, 204)==0) return;
|
|
|
|
if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
|
|
uiBlockSetFlag(block, UI_BLOCK_FRONTBUFFER); // force old style frontbuffer draw
|
|
}
|
|
|
|
if(vd->flag & V3D_DISPBGPIC) {
|
|
if(vd->bgpic==0) {
|
|
vd->bgpic= MEM_callocN(sizeof(BGpic), "bgpic");
|
|
vd->bgpic->size= 5.0;
|
|
vd->bgpic->blend= 0.5;
|
|
}
|
|
}
|
|
|
|
uiDefButBitS(block, TOG, V3D_DISPBGPIC, REDRAWVIEW3D, "Use Background Image", 0, 162, 200, 20, &vd->flag, 0, 0, 0, 0, "Display an image in the background of the 3D View");
|
|
|
|
uiDefBut(block, LABEL, 1, " ", 206, 162, 84, 20, NULL, 0.0, 0.0, 0, 0, "");
|
|
|
|
|
|
if(vd->flag & V3D_DISPBGPIC) {
|
|
|
|
/* Background Image */
|
|
uiDefBut(block, LABEL, 1, "Image:", 0, 128, 76, 19, NULL, 0.0, 0.0, 0, 0, "");
|
|
|
|
uiBlockBeginAlign(block);
|
|
uiDefIconBut(block, BUT, B_LOADBGPIC, ICON_FILESEL, 90, 128, 20, 20, 0, 0, 0, 0, 0, "Open a new background image");
|
|
|
|
id= (ID *)vd->bgpic->ima;
|
|
IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->image), id, &(vd->menunr));
|
|
if(strp[0]) {
|
|
|
|
uiDefButS(block, MENU, B_BGPICBROWSE, strp, 110, 128, 20, 20, &(vd->menunr), 0, 0, 0, 0, "Select a background image");
|
|
|
|
if(vd->bgpic->ima) {
|
|
uiDefBut(block, TEX, 0,"BG: ", 130, 128, 140, 20, &vd->bgpic->ima->name,0.0,100.0, 0, 0, "The currently selected background image");
|
|
uiDefIconBut(block, BUT, B_BGPICCLEAR, ICON_X, 270, 128, 20, 20, 0, 0, 0, 0, 0, "Remove background image link");
|
|
}
|
|
uiBlockEndAlign(block);
|
|
} else {
|
|
uiBlockEndAlign(block);
|
|
}
|
|
MEM_freeN(strp);
|
|
|
|
|
|
/* Background texture */
|
|
uiDefBut(block, LABEL, 1, "Texture:", 0, 100, 76, 19, NULL, 0.0, 0.0, 0, 0, "");
|
|
|
|
id= (ID *)vd->bgpic->tex;
|
|
IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->tex), id, &(vd->texnr));
|
|
if (strp[0])
|
|
uiBlockBeginAlign(block);
|
|
uiDefButS(block, MENU, B_BGPICTEX, strp, 90, 100, 20,20, &(vd->texnr), 0, 0, 0, 0, "Select a texture to use as an animated background image");
|
|
MEM_freeN(strp);
|
|
|
|
if (id) {
|
|
uiDefBut(block, TEX, B_IDNAME, "TE:", 110, 100, 160, 20, id->name+2, 0.0, 18.0, 0, 0, "");
|
|
uiDefIconBut(block, BUT, B_BGPICTEXCLEAR, ICON_X, 270, 100, 20, 20, 0, 0, 0, 0, 0, "Remove background texture link");
|
|
uiBlockEndAlign(block);
|
|
} else {
|
|
uiBlockEndAlign(block);
|
|
}
|
|
|
|
uiDefButF(block, NUMSLI, B_BLENDBGPIC, "Blend:", 0, 60 , 290, 19, &vd->bgpic->blend, 0.0,1.0, 0, 0, "Set the transparency of the background image");
|
|
|
|
uiDefButF(block, NUM, REDRAWVIEW3D, "Size:", 0, 28, 140, 19, &vd->bgpic->size, 0.1, 250.0*vd->grid, 100, 0, "Set the size (width) of the background image");
|
|
|
|
uiDefButF(block, NUM, REDRAWVIEW3D, "X Offset:", 0, 6, 140, 19, &vd->bgpic->xof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the horizontal offset of the background image");
|
|
uiDefButF(block, NUM, REDRAWVIEW3D, "Y Offset:", 150, 6, 140, 19, &vd->bgpic->yof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the vertical offset of the background image");
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static void view3d_panel_properties(short cntrl) // VIEW3D_HANDLER_SETTINGS
|
|
{
|
|
uiBlock *block;
|
|
View3D *vd;
|
|
float *curs;
|
|
|
|
vd= G.vd;
|
|
|
|
block= uiNewBlock(&curarea->uiblocks, "view3d_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
|
|
uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
|
|
uiSetPanelHandler(VIEW3D_HANDLER_PROPERTIES); // for close and esc
|
|
if(uiNewPanel(curarea, block, "View Properties", "View3d", 340, 30, 318, 254)==0) return;
|
|
|
|
/* to force height */
|
|
uiNewPanelHeight(block, 254);
|
|
|
|
if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
|
|
uiBlockSetFlag(block, UI_BLOCK_FRONTBUFFER); // force old style frontbuffer draw
|
|
}
|
|
|
|
uiDefBut(block, LABEL, 1, "Grid:", 10, 220, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
|
|
uiDefButF(block, NUM, REDRAWVIEW3D, "Spacing:", 10, 200, 140, 19, &vd->grid, 0.001, 100.0, 10, 0, "Set the distance between grid lines");
|
|
uiDefButS(block, NUM, REDRAWVIEW3D, "Lines:", 10, 176, 140, 19, &vd->gridlines, 0.0, 100.0, 100, 0, "Set the number of grid lines");
|
|
|
|
uiDefBut(block, LABEL, 1, "3D Display:", 160, 220, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
|
|
uiDefButBitS(block, TOG, V3D_SHOW_FLOOR, REDRAWVIEW3D, "Grid Floor",160, 200, 150, 19, &vd->gridflag, 0, 0, 0, 0, "Show the grid floor in free camera mode");
|
|
uiDefButBitS(block, TOG, V3D_SHOW_X, REDRAWVIEW3D, "X Axis", 160, 176, 48, 19, &vd->gridflag, 0, 0, 0, 0, "Show the X Axis line");
|
|
uiDefButBitS(block, TOG, V3D_SHOW_Y, REDRAWVIEW3D, "Y Axis", 212, 176, 48, 19, &vd->gridflag, 0, 0, 0, 0, "Show the Y Axis line");
|
|
uiDefButBitS(block, TOG, V3D_SHOW_Z, REDRAWVIEW3D, "Z Axis", 262, 176, 48, 19, &vd->gridflag, 0, 0, 0, 0, "Show the Z Axis line");
|
|
|
|
uiDefBut(block, LABEL, 1, "View Camera:", 10, 150, 140, 19, NULL, 0.0, 0.0, 0, 0, "");
|
|
|
|
uiDefButF(block, NUM, REDRAWVIEW3D, "Lens:", 10, 130, 140, 19, &vd->lens, 10.0, 120.0, 100, 0, "The lens angle in perspective view");
|
|
uiBlockBeginAlign(block);
|
|
uiDefButF(block, NUM, REDRAWVIEW3D, "Clip Start:", 10, 106, 140, 19, &vd->near, vd->grid/10.0, 100.0, 10, 0, "Set the beginning of the range in which 3D objects are displayed (perspective view)");
|
|
uiDefButF(block, NUM, REDRAWVIEW3D, "Clip End:", 10, 86, 140, 19, &vd->far, 1.0, 1000.0*vd->grid, 100, 0, "Set the end of the range in which 3D objects are displayed (perspective view)");
|
|
uiBlockEndAlign(block);
|
|
|
|
uiDefBut(block, LABEL, 1, "3D Cursor:", 160, 150, 140, 19, NULL, 0.0, 0.0, 0, 0, "");
|
|
|
|
uiBlockBeginAlign(block);
|
|
curs= give_cursor();
|
|
uiDefButF(block, NUM, REDRAWVIEW3D, "X:", 160, 130, 150, 22, curs, -1000.0*vd->grid, 1000.0*vd->grid, 10, 0, "X co-ordinate of the 3D cursor");
|
|
uiDefButF(block, NUM, REDRAWVIEW3D, "Y:", 160, 108, 150, 22, curs+1, -1000.0*vd->grid, 1000.0*vd->grid, 10, 0, "Y co-ordinate of the 3D cursor");
|
|
uiDefButF(block, NUM, REDRAWVIEW3D, "Z:", 160, 86, 150, 22, curs+2, -1000.0*vd->grid, 1000.0*vd->grid, 10, 0, "Z co-ordinate of the 3D cursor");
|
|
uiBlockEndAlign(block);
|
|
|
|
uiDefBut(block, LABEL, 1, "Display:", 10, 50, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
|
|
|
|
uiDefButBitS(block, TOG, V3D_SELECT_OUTLINE, REDRAWVIEW3D, "Outline Selected", 10, 30, 140, 19, &vd->flag, 0, 0, 0, 0, "Highlight selected objects with an outline, in Solid, Shaded or Textured viewport shading modes");
|
|
uiDefButBitS(block, TOG, V3D_DRAW_CENTERS, REDRAWVIEW3D, "All Object Centers", 160, 30, 150, 19, &vd->flag, 0, 0, 0, 0, "Draw the center points on all objects");
|
|
|
|
uiDefButBitS(block, TOGN, V3D_HIDE_HELPLINES, REDRAWVIEW3D, "Relationship Lines", 10, 6, 140, 19, &vd->flag, 0, 0, 0, 0, "Draw dashed lines indicating Parent, Constraint, or Hook relationships");
|
|
|
|
}
|
|
|
|
static void view3d_panel_preview(ScrArea *sa, short cntrl) // VIEW3D_HANDLER_PREVIEW
|
|
{
|
|
uiBlock *block;
|
|
View3D *v3d= sa->spacedata.first;
|
|
int ofsx, ofsy;
|
|
|
|
block= uiNewBlock(&sa->uiblocks, "view3d_panel_preview", UI_EMBOSS, UI_HELV, sa->win);
|
|
uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
|
|
uiSetPanelHandler(VIEW3D_HANDLER_PREVIEW); // for close and esc
|
|
|
|
ofsx= -150+(sa->winx/2)/v3d->blockscale;
|
|
ofsy= -100+(sa->winy/2)/v3d->blockscale;
|
|
if(uiNewPanel(sa, block, "Preview", "View3d", ofsx, ofsy, 300, 200)==0) return;
|
|
|
|
uiBlockSetDrawExtraFunc(block, BIF_view3d_previewdraw);
|
|
|
|
if(G.scene->recalc & SCE_PRV_CHANGED) {
|
|
G.scene->recalc &= ~SCE_PRV_CHANGED;
|
|
//printf("found recalc\n");
|
|
BIF_view3d_previewrender_free(sa->spacedata.first);
|
|
BIF_preview_changed(0);
|
|
}
|
|
}
|
|
|
|
|
|
static void view3d_blockhandlers(ScrArea *sa)
|
|
{
|
|
View3D *v3d= sa->spacedata.first;
|
|
short a;
|
|
|
|
/* warning; blocks need to be freed each time, handlers dont remove */
|
|
uiFreeBlocksWin(&sa->uiblocks, sa->win);
|
|
|
|
/*uv face-sel and wp mode when mixed with wire leave depth enabled causing
|
|
models to draw over the UI */
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
for(a=0; a<SPACE_MAXHANDLER; a+=2) {
|
|
|
|
switch(v3d->blockhandler[a]) {
|
|
|
|
case VIEW3D_HANDLER_PROPERTIES:
|
|
view3d_panel_properties(v3d->blockhandler[a+1]);
|
|
break;
|
|
case VIEW3D_HANDLER_BACKGROUND:
|
|
view3d_panel_background(v3d->blockhandler[a+1]);
|
|
break;
|
|
case VIEW3D_HANDLER_OBJECT:
|
|
view3d_panel_object(v3d->blockhandler[a+1]);
|
|
break;
|
|
case VIEW3D_HANDLER_PREVIEW:
|
|
view3d_panel_preview(sa, v3d->blockhandler[a+1]);
|
|
break;
|
|
|
|
}
|
|
/* clear action value for event */
|
|
v3d->blockhandler[a+1]= 0;
|
|
}
|
|
uiDrawBlocksPanels(sa, 0);
|
|
|
|
}
|
|
|
|
/* ****************** View3d afterdraw *************** */
|
|
|
|
typedef struct View3DAfter {
|
|
struct View3DAfter *next, *prev;
|
|
struct Base *base;
|
|
int type;
|
|
} View3DAfter;
|
|
|
|
/* temp storage of Objects that need to be drawn as last */
|
|
void add_view3d_after(View3D *v3d, Base *base, int type)
|
|
{
|
|
View3DAfter *v3da= MEM_callocN(sizeof(View3DAfter), "View 3d after");
|
|
|
|
BLI_addtail(&v3d->afterdraw, v3da);
|
|
v3da->base= base;
|
|
v3da->type= type;
|
|
}
|
|
|
|
/* clears zbuffer and draws it over */
|
|
static void view3d_draw_xray(View3D *v3d, int flag)
|
|
{
|
|
View3DAfter *v3da, *next;
|
|
int doit= 0;
|
|
|
|
for(v3da= v3d->afterdraw.first; v3da; v3da= v3da->next)
|
|
if(v3da->type==V3D_XRAY) doit= 1;
|
|
|
|
if(doit) {
|
|
if(v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT);
|
|
v3d->xray= TRUE;
|
|
|
|
for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
|
|
next= v3da->next;
|
|
if(v3da->type==V3D_XRAY) {
|
|
draw_object(v3da->base, flag);
|
|
BLI_remlink(&v3d->afterdraw, v3da);
|
|
MEM_freeN(v3da);
|
|
}
|
|
}
|
|
v3d->xray= FALSE;
|
|
}
|
|
}
|
|
|
|
/* disables write in zbuffer and draws it over */
|
|
static void view3d_draw_transp(View3D *v3d, int flag)
|
|
{
|
|
View3DAfter *v3da, *next;
|
|
|
|
glDepthMask(0);
|
|
v3d->transp= TRUE;
|
|
|
|
for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
|
|
next= v3da->next;
|
|
if(v3da->type==V3D_TRANSP) {
|
|
draw_object(v3da->base, flag);
|
|
BLI_remlink(&v3d->afterdraw, v3da);
|
|
MEM_freeN(v3da);
|
|
}
|
|
}
|
|
v3d->transp= FALSE;
|
|
|
|
glDepthMask(1);
|
|
|
|
}
|
|
|
|
/* *********************** */
|
|
|
|
static void draw_dupli_objects(View3D *v3d, Base *base)
|
|
{
|
|
ListBase *lb;
|
|
DupliObject *dob;
|
|
Base tbase;
|
|
int color= (base->flag & SELECT)?TH_SELECT:TH_WIRE;
|
|
short transflag;
|
|
char dt, dtx;
|
|
|
|
/* debug */
|
|
if(base->object->dup_group && base->object->dup_group->id.us<1)
|
|
color= TH_REDALERT;
|
|
|
|
tbase.flag= OB_FROMDUPLI|base->flag;
|
|
lb= object_duplilist(G.scene, base->object);
|
|
|
|
for(dob= lb->first; dob; dob= dob->next) {
|
|
tbase.object= dob->ob;
|
|
|
|
Mat4CpyMat4(dob->ob->obmat, dob->mat);
|
|
|
|
/* extra service: draw the duplicator in drawtype of parent */
|
|
dt= tbase.object->dt; tbase.object->dt= base->object->dt;
|
|
dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx;
|
|
|
|
/* negative scale flag has to propagate */
|
|
transflag= tbase.object->transflag;
|
|
if(base->object->transflag & OB_NEG_SCALE)
|
|
tbase.object->transflag ^= OB_NEG_SCALE;
|
|
|
|
BIF_ThemeColorBlend(color, TH_BACK, 0.5);
|
|
draw_object(&tbase, DRAW_CONSTCOLOR);
|
|
|
|
tbase.object->dt= dt;
|
|
tbase.object->dtx= dtx;
|
|
tbase.object->transflag= transflag;
|
|
}
|
|
|
|
/* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */
|
|
|
|
free_object_duplilist(lb); /* does restore */
|
|
|
|
}
|
|
|
|
void drawview3dspace(ScrArea *sa, void *spacedata)
|
|
{
|
|
View3D *v3d= spacedata;
|
|
Base *base;
|
|
Object *ob;
|
|
Scene *sce;
|
|
|
|
/* update all objects, ipos, matrices, displists, etc. Flags set by depgraph or manual,
|
|
no layer check here, gets correct flushed */
|
|
for(base= G.scene->base.first; base; base= base->next) {
|
|
object_handle_update(base->object); // bke_object.h
|
|
}
|
|
|
|
setwinmatrixview3d(sa->winx, sa->winy, NULL); /* 0= no pick rect */
|
|
setviewmatrixview3d(); /* note: calls where_is_object for camera... */
|
|
|
|
Mat4MulMat4(v3d->persmat, v3d->viewmat, sa->winmat);
|
|
Mat4Invert(v3d->persinv, v3d->persmat);
|
|
Mat4Invert(v3d->viewinv, v3d->viewmat);
|
|
|
|
/* calculate pixelsize factor once, is used for lamps and obcenters */
|
|
{
|
|
float len1, len2, vec[3];
|
|
|
|
VECCOPY(vec, v3d->persinv[0]);
|
|
len1= Normalise(vec);
|
|
VECCOPY(vec, v3d->persinv[1]);
|
|
len2= Normalise(vec);
|
|
|
|
v3d->pixsize= 2.0f*(len1>len2?len1:len2);
|
|
|
|
/* correct for window size */
|
|
if(sa->winx > sa->winy) v3d->pixsize/= (float)sa->winx;
|
|
else v3d->pixsize/= (float)sa->winy;
|
|
}
|
|
|
|
if(v3d->drawtype > OB_WIRE) {
|
|
if(G.f & G_SIMULATION)
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
|
else {
|
|
float col[3];
|
|
BIF_GetThemeColor3fv(TH_BACK, col);
|
|
glClearColor(col[0], col[1], col[2], 0.0);
|
|
}
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
glLoadIdentity();
|
|
}
|
|
else {
|
|
float col[3];
|
|
BIF_GetThemeColor3fv(TH_BACK, col);
|
|
glClearColor(col[0], col[1], col[2], 0.0);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
}
|
|
|
|
myloadmatrix(v3d->viewmat);
|
|
persp(PERSP_STORE); // store correct view for persp(PERSP_VIEW) calls
|
|
|
|
if(v3d->flag & V3D_CLIPPING)
|
|
view3d_draw_clipping(v3d);
|
|
|
|
/* set zbuffer after we draw clipping region */
|
|
if(v3d->drawtype > OB_WIRE) {
|
|
v3d->zbuf= TRUE;
|
|
glEnable(GL_DEPTH_TEST);
|
|
}
|
|
|
|
// needs to be done always, gridview is adjusted in drawgrid() now
|
|
v3d->gridview= v3d->grid;
|
|
|
|
if(v3d->view==0 || v3d->persp!=0) {
|
|
drawfloor();
|
|
if(v3d->persp==2) {
|
|
if(G.scene->world) {
|
|
if(G.scene->world->mode & WO_STARS) {
|
|
RE_make_stars(NULL, star_stuff_init_func, star_stuff_vertex_func,
|
|
star_stuff_term_func);
|
|
}
|
|
}
|
|
if(v3d->flag & V3D_DISPBGPIC) draw_bgpic();
|
|
}
|
|
}
|
|
else {
|
|
drawgrid();
|
|
|
|
if(v3d->flag & V3D_DISPBGPIC) {
|
|
draw_bgpic();
|
|
}
|
|
}
|
|
|
|
if(v3d->flag & V3D_CLIPPING)
|
|
view3d_set_clipping(v3d);
|
|
|
|
/* draw set first */
|
|
if(G.scene->set) {
|
|
for(SETLOOPER(G.scene->set, base)) {
|
|
|
|
if(v3d->lay & base->lay) {
|
|
|
|
object_handle_update(base->object);
|
|
|
|
BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
|
|
draw_object(base, DRAW_CONSTCOLOR);
|
|
|
|
if(base->object->transflag & OB_DUPLI) {
|
|
draw_dupli_objects(v3d, base);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Transp and X-ray afterdraw stuff */
|
|
view3d_draw_xray(v3d, DRAW_CONSTCOLOR); // clears zbuffer if it is used!
|
|
view3d_draw_transp(v3d, DRAW_CONSTCOLOR);
|
|
}
|
|
|
|
/* then draw not selected and the duplis, but skip editmode object */
|
|
for(base= G.scene->base.first; base; base= base->next) {
|
|
if(v3d->lay & base->lay) {
|
|
|
|
/* dupli drawing */
|
|
if(base->object->transflag & OB_DUPLI) {
|
|
draw_dupli_objects(v3d, base);
|
|
}
|
|
if((base->flag & SELECT)==0) {
|
|
if(base->object!=G.obedit) draw_object(base, 0);
|
|
}
|
|
}
|
|
}
|
|
/* draw selected and editmode */
|
|
for(base= G.scene->base.first; base; base= base->next) {
|
|
if(v3d->lay & base->lay) {
|
|
if (base->object==G.obedit || ( base->flag & SELECT) )
|
|
draw_object(base, 0);
|
|
}
|
|
}
|
|
|
|
if(G.moving) {
|
|
BIF_drawConstraint();
|
|
if(G.obedit) BIF_drawPropCircle(); // only editmode has proportional edit
|
|
}
|
|
|
|
if(G.scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID);
|
|
|
|
/* Transp and X-ray afterdraw stuff */
|
|
view3d_draw_xray(v3d, 0); // clears zbuffer if it is used!
|
|
view3d_draw_transp(v3d, 0);
|
|
|
|
if(v3d->flag & V3D_CLIPPING)
|
|
view3d_clr_clipping();
|
|
|
|
BIF_draw_manipulator(sa);
|
|
|
|
if(v3d->zbuf) {
|
|
v3d->zbuf= FALSE;
|
|
glDisable(GL_DEPTH_TEST);
|
|
}
|
|
|
|
persp(PERSP_WIN); // set ortho
|
|
|
|
if(v3d->persp>1) drawviewborder();
|
|
if(v3d->flag2 & V3D_FLYMODE) drawviewborder_flymode();
|
|
if(!(G.f & G_PLAYANIM)) drawcursor(v3d);
|
|
if(U.uiflag & USER_SHOW_ROTVIEWICON)
|
|
draw_view_axis();
|
|
else
|
|
draw_view_icon();
|
|
if(U.uiflag & USER_SHOW_VIEWPORTNAME)
|
|
draw_viewport_name(sa);
|
|
|
|
ob= OBACT;
|
|
if(ob && (U.uiflag & USER_DRAWVIEWINFO))
|
|
draw_selected_name(ob);
|
|
|
|
draw_area_emboss(sa);
|
|
|
|
/* it is important to end a view in a transform compatible with buttons */
|
|
|
|
bwin_scalematrix(sa->win, v3d->blockscale, v3d->blockscale, v3d->blockscale);
|
|
view3d_blockhandlers(sa);
|
|
|
|
sa->win_swap= WIN_BACK_OK;
|
|
|
|
if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
|
|
v3d->flag |= V3D_NEEDBACKBUFDRAW;
|
|
addafterqueue(sa->win, BACKBUFDRAW, 1);
|
|
}
|
|
// test for backbuf select
|
|
if(G.obedit && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT)) {
|
|
extern int afterqtest(short win, unsigned short evt); //editscreen.c
|
|
|
|
v3d->flag |= V3D_NEEDBACKBUFDRAW;
|
|
if(afterqtest(sa->win, BACKBUFDRAW)==0) {
|
|
addafterqueue(sa->win, BACKBUFDRAW, 1);
|
|
}
|
|
}
|
|
|
|
/* run any view3d draw handler script links */
|
|
if (sa->scriptlink.totscript)
|
|
BPY_do_spacehandlers(sa, 0, SPACEHANDLER_VIEW3D_DRAW);
|
|
|
|
/* run scene redraw script links */
|
|
if((G.f & G_DOSCRIPTLINKS) && G.scene->scriptlink.totscript &&
|
|
!during_script()) {
|
|
BPY_do_pyscript((ID *)G.scene, SCRIPT_REDRAW);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void drawview3d_render(struct View3D *v3d, int winx, int winy)
|
|
{
|
|
Base *base;
|
|
Scene *sce;
|
|
float winmat[4][4];
|
|
|
|
update_for_newframe_muted(); /* first, since camera can be animated */
|
|
|
|
setwinmatrixview3d(winx, winy, NULL);
|
|
|
|
setviewmatrixview3d();
|
|
myloadmatrix(v3d->viewmat);
|
|
glMatrixMode(GL_PROJECTION);
|
|
mygetmatrix(winmat);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
Mat4MulMat4(v3d->persmat, v3d->viewmat, winmat);
|
|
Mat4Invert(v3d->persinv, v3d->persmat);
|
|
Mat4Invert(v3d->viewinv, v3d->viewmat);
|
|
|
|
free_all_realtime_images();
|
|
reshadeall_displist();
|
|
|
|
if(v3d->drawtype > OB_WIRE) {
|
|
v3d->zbuf= TRUE;
|
|
glEnable(GL_DEPTH_TEST);
|
|
}
|
|
|
|
if(v3d->flag & V3D_CLIPPING)
|
|
view3d_set_clipping(v3d);
|
|
|
|
if (v3d->drawtype==OB_TEXTURE && G.scene->world) {
|
|
glClearColor(G.scene->world->horr, G.scene->world->horg, G.scene->world->horb, 0.0);
|
|
} else {
|
|
float col[3];
|
|
BIF_GetThemeColor3fv(TH_BACK, col);
|
|
glClearColor(col[0], col[1], col[2], 0.0);
|
|
}
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
/* abuse! to make sure it doesnt draw the helpstuff */
|
|
G.f |= G_SIMULATION;
|
|
|
|
/* first draw set */
|
|
if(G.scene->set) {
|
|
|
|
for(SETLOOPER(G.scene->set, base)) {
|
|
if(v3d->lay & base->lay) {
|
|
if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
|
|
else {
|
|
where_is_object(base->object);
|
|
|
|
BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
|
|
draw_object(base, DRAW_CONSTCOLOR);
|
|
|
|
if(base->object->transflag & OB_DUPLI) {
|
|
draw_dupli_objects(v3d, base);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Transp and X-ray afterdraw stuff */
|
|
view3d_draw_xray(v3d, DRAW_CONSTCOLOR); // clears zbuffer if it is used!
|
|
view3d_draw_transp(v3d, DRAW_CONSTCOLOR);
|
|
}
|
|
|
|
/* first not selected and duplis */
|
|
base= G.scene->base.first;
|
|
while(base) {
|
|
|
|
if(v3d->lay & base->lay) {
|
|
if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
|
|
else {
|
|
|
|
if(base->object->transflag & OB_DUPLI) {
|
|
draw_dupli_objects(v3d, base);
|
|
}
|
|
else if((base->flag & SELECT)==0) {
|
|
draw_object(base, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
base= base->next;
|
|
}
|
|
|
|
/* draw selected */
|
|
base= G.scene->base.first;
|
|
while(base) {
|
|
|
|
if ( ((base)->flag & SELECT) && ((base)->lay & v3d->lay) ) {
|
|
if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
|
|
else draw_object(base, 0);
|
|
}
|
|
|
|
base= base->next;
|
|
}
|
|
|
|
if(G.scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID);
|
|
|
|
/* Transp and X-ray afterdraw stuff */
|
|
view3d_draw_xray(v3d, 0); // clears zbuffer if it is used!
|
|
view3d_draw_transp(v3d, 0);
|
|
|
|
if(v3d->flag & V3D_CLIPPING)
|
|
view3d_clr_clipping();
|
|
|
|
if(v3d->zbuf) {
|
|
v3d->zbuf= FALSE;
|
|
glDisable(GL_DEPTH_TEST);
|
|
}
|
|
|
|
G.f &= ~G_SIMULATION;
|
|
|
|
glFlush();
|
|
|
|
glLoadIdentity();
|
|
|
|
free_all_realtime_images();
|
|
}
|
|
|
|
|
|
double tottime = 0.0;
|
|
|
|
int update_time(void)
|
|
{
|
|
static double ltime;
|
|
double time;
|
|
|
|
if ((U.mixbufsize)&&(audiostream_pos() != CFRA)&&(G.scene->audio.flag & AUDIO_SYNC)) return 0;
|
|
|
|
time = PIL_check_seconds_timer();
|
|
|
|
tottime += (time - ltime);
|
|
ltime = time;
|
|
return (tottime < 0.0);
|
|
}
|
|
|
|
void inner_play_anim_loop(int init, int mode)
|
|
{
|
|
ScrArea *sa;
|
|
static ScrArea *oldsa;
|
|
static double swaptime;
|
|
static int curmode;
|
|
|
|
/* init */
|
|
if(init) {
|
|
oldsa= curarea;
|
|
swaptime= 1.0/(float)G.scene->r.frs_sec;
|
|
tottime= 0.0;
|
|
curmode= mode;
|
|
|
|
return;
|
|
}
|
|
|
|
set_timecursor(CFRA);
|
|
|
|
update_for_newframe_nodraw(1); /* adds no events in UI */
|
|
|
|
sa= G.curscreen->areabase.first;
|
|
while(sa) {
|
|
if(sa==oldsa) {
|
|
scrarea_do_windraw(sa);
|
|
}
|
|
else if(curmode & 1) { /* catch modes 1 and 3 */
|
|
if ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_SEQ) {
|
|
scrarea_do_windraw(sa);
|
|
}
|
|
}
|
|
|
|
sa= sa->next;
|
|
}
|
|
|
|
/* make sure that swaptime passed by */
|
|
tottime -= swaptime;
|
|
while (update_time()) PIL_sleep_ms(1);
|
|
|
|
if(CFRA>=EFRA) {
|
|
if (tottime > 0.0) tottime = 0.0;
|
|
CFRA= SFRA;
|
|
audiostream_stop();
|
|
audiostream_start( CFRA );
|
|
}
|
|
else {
|
|
if (U.mixbufsize && (G.scene->audio.flag & AUDIO_SYNC)) CFRA = audiostream_pos();
|
|
else CFRA++;
|
|
}
|
|
}
|
|
|
|
/* play_anim: 'mode' defines where to play and if repeat is on:
|
|
* - 0: current area
|
|
* - 1: all view3d and seq areas
|
|
* - 2: current area, no replay
|
|
* - 3: all view3d and seq areas, no replay */
|
|
int play_anim(int mode)
|
|
{
|
|
ScrArea *sa, *oldsa;
|
|
int cfraont;
|
|
unsigned short event=0;
|
|
short val;
|
|
|
|
/* patch for very very old scenes */
|
|
if(SFRA==0) SFRA= 1;
|
|
if(EFRA==0) EFRA= 250;
|
|
|
|
if(SFRA>EFRA) return 0;
|
|
|
|
update_time();
|
|
|
|
/* waitcursor(1); */
|
|
G.f |= G_PLAYANIM; /* in sequence.c and view.c this is handled */
|
|
|
|
cfraont= CFRA;
|
|
oldsa= curarea;
|
|
|
|
audiostream_start( CFRA );
|
|
|
|
inner_play_anim_loop(1, mode); /* 1==init */
|
|
|
|
/* forces all buffers to be OK for current frame (otherwise other windows get redrawn with CFRA+1) */
|
|
curarea->win_swap= WIN_BACK_OK;
|
|
screen_swapbuffers();
|
|
|
|
while(TRUE) {
|
|
|
|
while(qtest()) {
|
|
|
|
/* we test events first because of MKEY event */
|
|
|
|
event= extern_qread(&val);
|
|
if(event==ESCKEY) break;
|
|
else if(event==MIDDLEMOUSE) {
|
|
if(U.flag & USER_VIEWMOVE) {
|
|
if(G.qual & LR_SHIFTKEY) viewmove(0);
|
|
else if(G.qual & LR_CTRLKEY) viewmove(2);
|
|
else viewmove(1);
|
|
}
|
|
else {
|
|
if(G.qual & LR_SHIFTKEY) viewmove(1);
|
|
else if(G.qual & LR_CTRLKEY) viewmove(2);
|
|
else viewmove(0);
|
|
}
|
|
}
|
|
else if(event==MKEY) {
|
|
if(val) add_timeline_marker(CFRA-1);
|
|
}
|
|
}
|
|
if(ELEM3(event, ESCKEY, SPACEKEY, RIGHTMOUSE)) break;
|
|
|
|
inner_play_anim_loop(0, 0);
|
|
screen_swapbuffers();
|
|
|
|
if((mode > 1) && CFRA==EFRA) break; /* no replay */
|
|
}
|
|
|
|
if(event==SPACEKEY);
|
|
else CFRA= cfraont;
|
|
|
|
audiostream_stop();
|
|
|
|
if(oldsa!=curarea) areawinset(oldsa->win);
|
|
|
|
/* restore all areas */
|
|
sa= G.curscreen->areabase.first;
|
|
while(sa) {
|
|
if( (mode && sa->spacetype==SPACE_VIEW3D) || sa==curarea) addqueue(sa->win, REDRAW, 1);
|
|
sa= sa->next;
|
|
}
|
|
|
|
/* groups could have changed ipo */
|
|
allspace(REMAKEIPO, 0);
|
|
allqueue(REDRAWIPO, 0);
|
|
allqueue(REDRAWNLA, 0);
|
|
allqueue (REDRAWACTION, 0);
|
|
|
|
/* restore for cfra */
|
|
update_for_newframe_muted();
|
|
|
|
waitcursor(0);
|
|
G.f &= ~G_PLAYANIM;
|
|
|
|
if (event==ESCKEY || event==SPACEKEY) return 1;
|
|
else return 0;
|
|
}
|