diff options
Diffstat (limited to 'source/blender/editors/space_view3d')
30 files changed, 11000 insertions, 7853 deletions
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index a5c60248bf1..de8380aa8bb 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -25,6 +25,7 @@ set(INC ../../blenlib ../../blentranslation ../../bmesh + ../../draw ../../gpu ../../imbuf ../../makesdna @@ -52,11 +53,18 @@ set(SRC view3d_buttons.c view3d_camera_control.c view3d_draw.c + view3d_draw_legacy.c view3d_edit.c view3d_fly.c view3d_walk.c view3d_header.c view3d_iterators.c + view3d_manipulator_armature.c + view3d_manipulator_camera.c + view3d_manipulator_empty.c + view3d_manipulator_forcefield.c + view3d_manipulator_lamp.c + view3d_manipulator_ruler.c view3d_ops.c view3d_project.c view3d_ruler.c @@ -94,8 +102,4 @@ if(WITH_MOD_SMOKE) add_definitions(-DWITH_SMOKE) endif() -if(WITH_LEGACY_DEPSGRAPH) - add_definitions(-DWITH_LEGACY_DEPSGRAPH) -endif() - blender_add_lib(bf_editor_space_view3d "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c index f0e65f84205..66355a50478 100644 --- a/source/blender/editors/space_view3d/drawanimviz.c +++ b/source/blender/editors/space_view3d/drawanimviz.c @@ -49,7 +49,8 @@ #include "BKE_animsys.h" #include "BKE_action.h" -#include "BIF_gl.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" #include "ED_keyframes_draw.h" @@ -71,8 +72,8 @@ void draw_motion_paths_init(View3D *v3d, ARegion *ar) if (v3d->zbuf) glDisable(GL_DEPTH_TEST); - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); + gpuPushMatrix(); + gpuLoadMatrix(rv3d->viewmat); } /* set color @@ -86,10 +87,11 @@ void draw_motion_paths_init(View3D *v3d, ARegion *ar) * - User selected color for next frames */ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short sel, int sfra, int efra, - float prev_color[3], float frame_color[3], float next_color[3]) + float prev_color[3], float frame_color[3], float next_color[3], unsigned color) { int frame = sfra + i; int blend_base = (abs(frame - CFRA) == 1) ? TH_CFRAME : TH_BACK; /* "bleed" cframe color to ease color blending */ + unsigned char ubcolor[3]; #define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max - min)) + min) float intensity; /* how faint */ @@ -97,7 +99,7 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short if (frame < CFRA) { if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { /* Custom color: previous frames color is darker than current frame */ - glColor3fv(prev_color); + rgb_float_to_uchar(ubcolor, prev_color); } else { /* black - before cfra */ @@ -109,13 +111,14 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short /* intensity = 0.8f; */ intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f); } - UI_ThemeColorBlend(TH_WIRE, blend_base, intensity); + + UI_GetThemeColorBlend3ubv(TH_WIRE, blend_base, intensity, ubcolor); } } else if (frame > CFRA) { if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { /* Custom color: next frames color is equal to user selected color */ - glColor3fv(next_color); + rgb_float_to_uchar(ubcolor, next_color); } else { /* blue - after cfra */ @@ -127,13 +130,14 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short /* intensity = 0.8f; */ intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f); } - UI_ThemeColorBlend(TH_BONE_POSE, blend_base, intensity); + + UI_GetThemeColorBlend3ubv(TH_BONE_POSE, blend_base, intensity, ubcolor); } } else { if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { /* Custom color: current frame color is slightly darker than user selected color */ - glColor3fv(frame_color); + rgb_float_to_uchar(ubcolor, frame_color); } else { /* green - on cfra */ @@ -143,9 +147,12 @@ static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short else { intensity = 0.99f; } - UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10); + UI_GetThemeColorBlendShade3ubv(TH_CFRAME, TH_BACK, intensity, 10, ubcolor); } } + + immAttrib3ubv(color, ubcolor); + #undef SET_INTENSITY } @@ -231,42 +238,65 @@ void draw_motion_path_instance(Scene *scene, /* set line thickness */ glLineWidth(mpath->line_thickness); - glBegin(GL_LINE_STRIP); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); + + immBegin(GWN_PRIM_LINE_STRIP, len); + for (i = 0, mpv = mpv_start; i < len; i++, mpv++) { short sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT); + /* Set color */ - set_motion_path_color(scene, mpath, i, sel, sfra, efra, prev_color, frame_color, next_color); + set_motion_path_color(scene, mpath, i, sel, sfra, efra, prev_color, frame_color, next_color, color); + /* draw a vertex with this color */ - glVertex3fv(mpv->co); + immVertex3fv(pos, mpv->co); } - glEnd(); + immEnd(); + + immUnbindProgram(); + /* back to old line thickness */ glLineWidth(old_width); } + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + /* Point must be bigger than line thickness */ glPointSize(mpath->line_thickness + 1.0); - /* draw little black point at each frame - * NOTE: this is not really visible/noticeable - */ - glBegin(GL_POINTS); - for (i = 0, mpv = mpv_start; i < len; i++, mpv++) - glVertex3fv(mpv->co); - glEnd(); - + /* draw little black point at each frame */ + immUniformColor3ub(0, 0, 0); + + immBegin(GWN_PRIM_POINTS, len); + + for (i = 0, mpv = mpv_start; i < len; i++, mpv++) { + immVertex3fv(pos, mpv->co); + } + + immEnd(); + /* Draw little white dots at each framestep value or replace with custom color */ if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { - glColor4fv(mpath->color); + immUniformColor3fv(mpath->color); } else { - UI_ThemeColor(TH_TEXT_HI); + immUniformThemeColor(TH_TEXT_HI); } - glBegin(GL_POINTS); - for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) - glVertex3fv(mpv->co); - glEnd(); + + immBegin(GWN_PRIM_POINTS, (len + stepsize - 1) / stepsize); + + for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) { + immVertex3fv(pos, mpv->co); + } + + immEnd(); /* Draw big green dot where the current frame is * NOTE: this is only done when keyframes are shown, since this adds similar types of clutter @@ -274,16 +304,18 @@ void draw_motion_path_instance(Scene *scene, if ((avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) && (sfra < CFRA) && (CFRA <= efra)) { - UI_ThemeColor(TH_CFRAME); - glPointSize(mpath->line_thickness + 5.0); - glBegin(GL_POINTS); + immUniformThemeColor(TH_CFRAME); + + immBegin(GWN_PRIM_POINTS, 1); + mpv = mpv_start + (CFRA - sfra); - glVertex3fv(mpv->co); - glEnd(); - - UI_ThemeColor(TH_TEXT_HI); + immVertex3fv(pos, mpv->co); + + immEnd(); } + + immUnbindProgram(); /* XXX, this isn't up to date but probably should be kept so. */ invert_m4_m4(ob->imat, ob->obmat); @@ -353,24 +385,28 @@ void draw_motion_path_instance(Scene *scene, UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col); col[3] = 255; - /* if custom, point must be bigger than line */ - if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) { - glPointSize(mpath->line_thickness + 3.0); - } - else { - glPointSize(4.0f); - } - glColor3ubv(col); + /* point must be bigger than line */ + glPointSize(mpath->line_thickness + 3.0); + + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(col); - glBegin(GL_POINTS); + immBeginAtMost(GWN_PRIM_POINTS, len); + for (i = 0, mpv = mpv_start; i < len; i++, mpv++) { int frame = sfra + i; float mframe = (float)(frame); - if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) - glVertex3fv(mpv->co); + if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) { + immVertex3fv(pos, mpv->co); + } } - glEnd(); + + immEnd(); + + immUnbindProgram(); /* Draw frame numbers of keyframes */ if (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) { @@ -398,5 +434,5 @@ void draw_motion_path_instance(Scene *scene, void draw_motion_paths_cleanup(View3D *v3d) { if (v3d->zbuf) glEnable(GL_DEPTH_TEST); - glPopMatrix(); + gpuPopMatrix(); } diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 5208013b6fe..f04b8c0cdad 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -54,15 +54,20 @@ #include "BKE_modifier.h" #include "BKE_nla.h" #include "BKE_curve.h" +#include "BKE_context.h" +#include "DEG_depsgraph.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "ED_armature.h" #include "ED_keyframes_draw.h" #include "GPU_basic_shader.h" +#include "GPU_batch.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" #include "UI_resources.h" @@ -74,8 +79,10 @@ /* global here is reset before drawing each bone */ static ThemeWireColor *bcolor = NULL; +static float fcolor[4] = {0.0f}; +static bool flat_color; -/* values of colCode for set_pchan_glcolor */ +/* values of colCode for set_pchan_color */ enum { PCHAN_COLOR_NORMAL = 0, /* normal drawing */ PCHAN_COLOR_SOLID, /* specific case where "solid" color is needed */ @@ -128,7 +135,7 @@ static void set_pchan_colorset(Object *ob, bPoseChannel *pchan) } } -/* This function is for brightening/darkening a given color (like UI_ThemeColorShade()) */ +/* This function is for brightening/darkening a given color (like UI_GetThemeColorShade3ubv()) */ static void cp_shade_color3ub(unsigned char cp[3], const int offset) { int r, g, b; @@ -146,13 +153,13 @@ static void cp_shade_color3ub(unsigned char cp[3], const int offset) } /* This function sets the gl-color for coloring a certain bone (based on bcolor) */ -static bool set_pchan_glColor(short colCode, int boneflag, short constflag) +static bool set_pchan_color(short colCode, int boneflag, short constflag) { switch (colCode) { case PCHAN_COLOR_NORMAL: { if (bcolor) { - unsigned char cp[3]; + unsigned char cp[4] = {255}; if (boneflag & BONE_DRAW_ACTIVE) { copy_v3_v3_char((char *)cp, bcolor->active); @@ -169,20 +176,20 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) cp_shade_color3ub(cp, -50); } - glColor3ubv(cp); + rgb_uchar_to_float(fcolor, cp); } else { if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) { - UI_ThemeColor(TH_BONE_POSE_ACTIVE); + UI_GetThemeColor4fv(TH_BONE_POSE_ACTIVE, fcolor); } else if (boneflag & BONE_DRAW_ACTIVE) { - UI_ThemeColorBlend(TH_WIRE, TH_BONE_POSE, 0.15f); /* unselected active */ + UI_GetThemeColorBlendShade4fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, fcolor); } else if (boneflag & BONE_SELECTED) { - UI_ThemeColor(TH_BONE_POSE); + UI_GetThemeColor4fv(TH_BONE_POSE, fcolor); } else { - UI_ThemeColor(TH_WIRE); + UI_GetThemeColor4fv(TH_WIRE, fcolor); } } @@ -191,21 +198,25 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) case PCHAN_COLOR_SOLID: { if (bcolor) { - glColor3ubv((unsigned char *)bcolor->solid); + rgb_uchar_to_float(fcolor, (unsigned char *)bcolor->solid); + } + else { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); } - else - UI_ThemeColor(TH_BONE_SOLID); return true; } case PCHAN_COLOR_CONSTS: { if ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) { - if (constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80); - else if (constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80); - else if (constflag & PCHAN_HAS_SPLINEIK) glColor4ub(200, 255, 0, 80); - else if (constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80); - + unsigned char cp[4]; + if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 80); + else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 80); + else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 80); + else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 80); + + rgba_uchar_to_float(fcolor, cp); + return true; } return false; @@ -213,7 +224,7 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) case PCHAN_COLOR_SPHEREBONE_BASE: { if (bcolor) { - unsigned char cp[3]; + unsigned char cp[4] = {255}; if (boneflag & BONE_DRAW_ACTIVE) { copy_v3_v3_char((char *)cp, bcolor->active); @@ -225,12 +236,18 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) copy_v3_v3_char((char *)cp, bcolor->solid); } - glColor3ubv(cp); + rgb_uchar_to_float(fcolor, cp); } else { - if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40); - else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE); - else UI_ThemeColor(TH_BONE_SOLID); + if (boneflag & BONE_DRAW_ACTIVE) { + UI_GetThemeColorShade4fv(TH_BONE_POSE, 40, fcolor); + } + else if (boneflag & BONE_SELECTED) { + UI_GetThemeColor4fv(TH_BONE_POSE, fcolor); + } + else { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + } } return true; @@ -238,7 +255,7 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) case PCHAN_COLOR_SPHEREBONE_END: { if (bcolor) { - unsigned char cp[3]; + unsigned char cp[4] = {255}; if (boneflag & BONE_DRAW_ACTIVE) { copy_v3_v3_char((char *)cp, bcolor->active); @@ -253,12 +270,18 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) cp_shade_color3ub(cp, -30); } - glColor3ubv(cp); + rgb_uchar_to_float(fcolor, cp); } else { - if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 10); - else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_BONE_POSE, -30); - else UI_ThemeColorShade(TH_BONE_SOLID, -30); + if (boneflag & BONE_DRAW_ACTIVE) { + UI_GetThemeColorShade4fv(TH_BONE_POSE, 10, fcolor); + } + else if (boneflag & BONE_SELECTED) { + UI_GetThemeColorShade4fv(TH_BONE_POSE, -30, fcolor); + } + else { + UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor); + } } break; } @@ -266,19 +289,24 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) { /* inner part in background color or constraint */ if ((constflag) && ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS))) { - if (constflag & PCHAN_HAS_TARGET) glColor3ub(255, 150, 0); - else if (constflag & PCHAN_HAS_IK) glColor3ub(255, 255, 0); - else if (constflag & PCHAN_HAS_SPLINEIK) glColor3ub(200, 255, 0); - else if (constflag & PCHAN_HAS_CONST) glColor3ub(0, 255, 120); - else if (constflag) UI_ThemeColor(TH_BONE_POSE); /* PCHAN_HAS_ACTION */ + unsigned char cp[4]; + if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 255); + else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 255); + else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 255); + else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 255); + else if (constflag) UI_GetThemeColor4ubv(TH_BONE_POSE, cp); /* PCHAN_HAS_ACTION */ + + rgb_uchar_to_float(fcolor, cp); } else { if (bcolor) { const char *cp = bcolor->solid; - glColor4ub(cp[0], cp[1], cp[2], 204); + rgb_uchar_to_float(fcolor, (unsigned char *)cp); + fcolor[3] = 204.f / 255.f; + } + else { + UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor); } - else - UI_ThemeColorShade(TH_BACK, -30); } return true; @@ -288,26 +316,37 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag) return false; } -static void set_ebone_glColor(const unsigned int boneflag) +static void set_ebone_color(const unsigned int boneflag) { if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) { - UI_ThemeColor(TH_EDGE_SELECT); + UI_GetThemeColor4fv(TH_EDGE_SELECT, fcolor); } else if (boneflag & BONE_DRAW_ACTIVE) { - UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f); /* unselected active */ + UI_GetThemeColorBlendShade4fv(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f, 0, fcolor); } else if (boneflag & BONE_SELECTED) { - UI_ThemeColorShade(TH_EDGE_SELECT, -20); + UI_GetThemeColorShade4fv(TH_EDGE_SELECT, -20, fcolor); } else { - UI_ThemeColor(TH_WIRE_EDIT); + UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor); } } /* *************** Armature drawing, helper calls for parts ******************* */ +static void add_solid_flat_triangle(Gwn_VertBuf *vbo, unsigned int *vertex, unsigned int pos, unsigned int nor, + const float p1[3], const float p2[3], const float p3[3], const float n[3]) +{ + GWN_vertbuf_attr_set(vbo, nor, *vertex, n); + GWN_vertbuf_attr_set(vbo, pos, (*vertex)++, p1); + GWN_vertbuf_attr_set(vbo, nor, *vertex, n); + GWN_vertbuf_attr_set(vbo, pos, (*vertex)++, p2); + GWN_vertbuf_attr_set(vbo, nor, *vertex, n); + GWN_vertbuf_attr_set(vbo, pos, (*vertex)++, p3); +} + /* half the cube, in Y */ -static const float cube[8][3] = { +static const float cube_vert[8][3] = { {-1.0, 0.0, -1.0}, {-1.0, 0.0, 1.0}, {-1.0, 1.0, 1.0}, @@ -318,128 +357,184 @@ static const float cube[8][3] = { { 1.0, 1.0, -1.0}, }; +static const float cube_wire[24] = { + 0, 1, 1, 2, 2, 3, 3, 0, + 4, 5, 5, 6, 6, 7, 7, 4, + 0, 4, 1, 5, 2, 6, 3, 7, +}; + static void drawsolidcube_size(float xsize, float ysize, float zsize) { - static GLuint displist = 0; - float n[3] = {0.0f}; - - glScalef(xsize, ysize, zsize); - - if (displist == 0) { - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); + static Gwn_VertFormat format = {0}; + static Gwn_VertBuf vbo = {{0}}; + static Gwn_Batch batch = {{0}}; + const float light_vec[3] = {0.0f, 0.0f, 1.0f}; + + if (format.attrib_ct == 0) { + unsigned int i = 0; + float n[3] = {0.0f}; + /* Vertex format */ + unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + /* Vertices */ + GWN_vertbuf_init_with_format(&vbo, &format); + GWN_vertbuf_data_alloc(&vbo, 36); - glBegin(GL_QUADS); n[0] = -1.0; - glNormal3fv(n); - glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[1], cube_vert[2], n); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[2], cube_vert[3], cube_vert[0], n); n[0] = 0; n[1] = -1.0; - glNormal3fv(n); - glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[4], cube_vert[5], n); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[5], cube_vert[1], cube_vert[0], n); n[1] = 0; n[0] = 1.0; - glNormal3fv(n); - glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[4], cube_vert[7], cube_vert[6], n); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[6], cube_vert[5], cube_vert[4], n); n[0] = 0; n[1] = 1.0; - glNormal3fv(n); - glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[7], cube_vert[3], cube_vert[2], n); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[2], cube_vert[6], cube_vert[7], n); n[1] = 0; n[2] = 1.0; - glNormal3fv(n); - glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[1], cube_vert[5], cube_vert[6], n); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[6], cube_vert[2], cube_vert[1], n); n[2] = -1.0; - glNormal3fv(n); - glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]); - glEnd(); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[7], cube_vert[4], cube_vert[0], n); + add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[3], cube_vert[7], n); - glEndList(); + GWN_batch_init(&batch, GWN_PRIM_TRIS, &vbo, NULL); } - glCallList(displist); + gpuPushMatrix(); + gpuScale3f(xsize, ysize, zsize); + + if (flat_color) { + GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR); + } + else { + /* TODO replace with good default lighting shader ? */ + GWN_batch_program_set_builtin(&batch, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_3fv(&batch, "light", light_vec); + } + GWN_batch_uniform_4fv(&batch, "color", fcolor); + GWN_batch_draw(&batch); + + gpuPopMatrix(); } static void drawcube_size(float xsize, float ysize, float zsize) { - static GLuint displist = 0; - - if (displist == 0) { - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - glBegin(GL_LINE_STRIP); - glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]); - glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); - glVertex3fv(cube[7]); glVertex3fv(cube[4]); - glEnd(); - - glBegin(GL_LINES); - glVertex3fv(cube[1]); glVertex3fv(cube[5]); - glVertex3fv(cube[2]); glVertex3fv(cube[6]); - glVertex3fv(cube[3]); glVertex3fv(cube[7]); - glEnd(); - - glEndList(); + static Gwn_VertFormat format = {0}; + static Gwn_VertBuf vbo = {{0}}; + static Gwn_IndexBufBuilder elb = {0}; + static Gwn_IndexBuf el = {0}; + static Gwn_Batch batch = {{0}}; + + if (format.attrib_ct == 0) { + /* Vertex format */ + unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + /* Elements */ + GWN_indexbuf_init(&elb, GWN_PRIM_LINES, 12, 8); + for (int i = 0; i < 12; ++i) { + GWN_indexbuf_add_line_verts(&elb, cube_wire[i * 2], cube_wire[i * 2 + 1]); + } + GWN_indexbuf_build_in_place(&elb, &el); + + /* Vertices */ + GWN_vertbuf_init_with_format(&vbo, &format); + GWN_vertbuf_data_alloc(&vbo, 8); + for (int i = 0; i < 8; ++i) { + GWN_vertbuf_attr_set(&vbo, pos, i, cube_vert[i]); + } + + GWN_batch_init(&batch, GWN_PRIM_LINES, &vbo, &el); + GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR); } - glScalef(xsize, ysize, zsize); - glCallList(displist); - + gpuPushMatrix(); + gpuScale3f(xsize, ysize, zsize); + + GWN_batch_program_use_begin(&batch); + GWN_batch_uniform_4fv(&batch, "color", fcolor); + GWN_batch_draw(&batch); + + gpuPopMatrix(); } static void draw_bonevert(void) { - static GLuint displist = 0; - - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - glPushMatrix(); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - gluDisk(qobj, 0.0, 0.05, 16, 1); - - glRotatef(90, 0, 1, 0); - gluDisk(qobj, 0.0, 0.05, 16, 1); - - glRotatef(90, 1, 0, 0); - gluDisk(qobj, 0.0, 0.05, 16, 1); - - gluDeleteQuadric(qobj); - - glPopMatrix(); - glEndList(); + static Gwn_VertFormat format = {0}; + static Gwn_VertBuf vbo = {{0}}; + static Gwn_Batch batch = {{0}}; + + if (format.attrib_ct == 0) { + /* Vertex format */ + unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + /* Vertices */ + GWN_vertbuf_init_with_format(&vbo, &format); + GWN_vertbuf_data_alloc(&vbo, 96); + for (int i = 0; i < 16; ++i) { + float vert[3] = {0.f, 0.f, 0.f}; + const float r = 0.05f; + + vert[0] = r * cosf(2 * M_PI * i / 16.f); + vert[1] = r * sinf(2 * M_PI * i / 16.f); + GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 0, vert); + vert[0] = r * cosf(2 * M_PI * (i + 1) / 16.f); + vert[1] = r * sinf(2 * M_PI * (i + 1) / 16.f); + GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 1, vert); + + vert[0] = 0.f; + vert[1] = r * cosf(2 * M_PI * i / 16.f); + vert[2] = r * sinf(2 * M_PI * i / 16.f); + GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 2, vert); + vert[1] = r * cosf(2 * M_PI * (i + 1) / 16.f); + vert[2] = r * sinf(2 * M_PI * (i + 1) / 16.f); + GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 3, vert); + + vert[1] = 0.f; + vert[0] = r * cosf(2 * M_PI * i / 16.f); + vert[2] = r * sinf(2 * M_PI * i / 16.f); + GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 4, vert); + vert[0] = r * cosf(2 * M_PI * (i + 1) / 16.f); + vert[2] = r * sinf(2 * M_PI * (i + 1) / 16.f); + GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 5, vert); + } + + GWN_batch_init(&batch, GWN_PRIM_LINES, &vbo, NULL); + GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR); } - glCallList(displist); + GWN_batch_program_use_begin(&batch); + GWN_batch_uniform_4fv(&batch, "color", fcolor); + GWN_batch_draw(&batch); } static void draw_bonevert_solid(void) { - static GLuint displist = 0; - - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_FILL); - /* Draw tips of a bone */ - gluSphere(qobj, 0.05, 8, 5); - gluDeleteQuadric(qobj); - - glEndList(); + Gwn_Batch *batch = GPU_batch_preset_sphere(0); + const float light_vec[3] = {0.0f, 0.0f, 1.0f}; + + gpuPushMatrix(); + gpuScaleUniform(0.05); + + if (flat_color) { + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); } + else { + /* TODO replace with good default lighting shader ? */ + GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_3fv(batch, "light", light_vec); + } + GWN_batch_uniform_4fv(batch, "color", fcolor); + GWN_batch_draw(batch); - glCallList(displist); + gpuPopMatrix(); } static const float bone_octahedral_verts[6][3] = { @@ -451,8 +546,11 @@ static const float bone_octahedral_verts[6][3] = { { 0.0f, 1.0f, 0.0f} }; -static const unsigned int bone_octahedral_wire_sides[8] = {0, 1, 5, 3, 0, 4, 5, 2}; -static const unsigned int bone_octahedral_wire_square[8] = {1, 2, 3, 4, 1}; +static const unsigned int bone_octahedral_wire[24] = { + 0, 1, 1, 5, 5, 3, 3, 0, + 0, 4, 4, 5, 5, 2, 2, 0, + 1, 2, 2, 3, 3, 4, 4, 1, +}; static const unsigned int bone_octahedral_solid_tris[8][3] = { {2, 1, 0}, /* bottom */ @@ -480,70 +578,78 @@ static const float bone_octahedral_solid_normals[8][3] = { static void draw_bone_octahedral(void) { - static GLuint displist = 0; - - if (displist == 0) { - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - /* Section 1, sides */ - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, bone_octahedral_verts); - glDrawElements(GL_LINE_LOOP, - sizeof(bone_octahedral_wire_sides) / sizeof(*bone_octahedral_wire_sides), - GL_UNSIGNED_INT, - bone_octahedral_wire_sides); - - /* Section 1, square */ - glDrawElements(GL_LINE_LOOP, - sizeof(bone_octahedral_wire_square) / sizeof(*bone_octahedral_wire_square), - GL_UNSIGNED_INT, - bone_octahedral_wire_square); - glDisableClientState(GL_VERTEX_ARRAY); - - glEndList(); + static Gwn_VertFormat format = {0}; + static Gwn_VertBuf vbo = {{0}}; + static Gwn_IndexBufBuilder elb = {0}; + static Gwn_IndexBuf el = {0}; + static Gwn_Batch batch = {{0}}; + + if (format.attrib_ct == 0) { + /* Vertex format */ + unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + /* Elements */ + GWN_indexbuf_init(&elb, GWN_PRIM_LINES, 12, 6); + for (int i = 0; i < 12; ++i) { + GWN_indexbuf_add_line_verts(&elb, bone_octahedral_wire[i * 2], bone_octahedral_wire[i * 2 + 1]); + } + GWN_indexbuf_build_in_place(&elb, &el); + + /* Vertices */ + GWN_vertbuf_init_with_format(&vbo, &format); + GWN_vertbuf_data_alloc(&vbo, 6); + for (int i = 0; i < 6; ++i) { + GWN_vertbuf_attr_set(&vbo, pos, i, bone_octahedral_verts[i]); + } + + GWN_batch_init(&batch, GWN_PRIM_LINES, &vbo, &el); + GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR); } - glCallList(displist); -} + GWN_batch_program_use_begin(&batch); + GWN_batch_uniform_4fv(&batch, "color", fcolor); + GWN_batch_draw(&batch); +} static void draw_bone_solid_octahedral(void) { - static GLuint displist = 0; - - if (displist == 0) { - int i; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - -#if 1 - glBegin(GL_TRIANGLES); - for (i = 0; i < 8; i++) { - glNormal3fv(bone_octahedral_solid_normals[i]); - glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][0]]); - glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][1]]); - glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][2]]); - } - - glEnd(); - -#else /* not working because each vert needs a different normal */ - glEnableClientState(GL_NORMAL_ARRAY); - glEnableClientState(GL_VERTEX_ARRAY); - glNormalPointer(GL_FLOAT, 0, bone_octahedral_solid_normals); - glVertexPointer(3, GL_FLOAT, 0, bone_octahedral_verts); - glDrawElements(GL_TRIANGLES, sizeof(bone_octahedral_solid_tris) / sizeof(unsigned int), - GL_UNSIGNED_INT, bone_octahedral_solid_tris); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); -#endif + static Gwn_VertFormat format = {0}; + static Gwn_VertBuf vbo = {{0}}; + static Gwn_Batch batch = {{0}}; + const float light_vec[3] = {0.0f, 0.0f, 1.0f}; + + if (format.attrib_ct == 0) { + unsigned int v_idx = 0; + /* Vertex format */ + unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + /* Vertices */ + GWN_vertbuf_init_with_format(&vbo, &format); + GWN_vertbuf_data_alloc(&vbo, 24); + + for (int i = 0; i < 8; i++) { + add_solid_flat_triangle(&vbo, &v_idx, pos, nor, + bone_octahedral_verts[bone_octahedral_solid_tris[i][0]], + bone_octahedral_verts[bone_octahedral_solid_tris[i][1]], + bone_octahedral_verts[bone_octahedral_solid_tris[i][2]], + bone_octahedral_solid_normals[i]); + } - glEndList(); + GWN_batch_init(&batch, GWN_PRIM_TRIS, &vbo, NULL); } - glCallList(displist); -} + if (flat_color) { + GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR); + } + else { + /* TODO replace with good default lighting shader ? */ + GWN_batch_program_set_builtin(&batch, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_3fv(&batch, "light", light_vec); + } + GWN_batch_uniform_4fv(&batch, "color", fcolor); + GWN_batch_draw(&batch); +} /* *************** Armature drawing, bones ******************* */ @@ -557,15 +663,20 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag, if (dt <= OB_WIRE) { if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColor(TH_VERTEX); + if (boneflag & BONE_ROOTSEL) { + UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + } + else { + UI_GetThemeColor4fv(TH_VERTEX, fcolor); + } } } else { if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0); - else - UI_ThemeColor(TH_BONE_SOLID); + set_pchan_color(PCHAN_COLOR_SOLID, boneflag, 0); + else { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + } } if (dt > OB_WIRE) @@ -580,24 +691,29 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag, if (dt <= OB_WIRE) { if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColor(TH_VERTEX); + if (boneflag & BONE_TIPSEL) { + UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + } + else { + UI_GetThemeColor4fv(TH_VERTEX, fcolor); + } } } else { if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0); - else - UI_ThemeColor(TH_BONE_SOLID); + set_pchan_color(PCHAN_COLOR_SOLID, boneflag, 0); + else { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + } } - glTranslatef(0.0f, 1.0f, 0.0f); + gpuPushMatrix(); + gpuTranslate2f(0.0f, 1.0f); if (dt > OB_WIRE) draw_bonevert_solid(); else draw_bonevert(); - glTranslatef(0.0f, -1.0f, 0.0f); - + gpuPopMatrix(); } /* 16 values of sin function (still same result!) */ @@ -696,8 +812,13 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann //mul_v3_fl(dirvec, head); cross_v3_v3v3(norvec, dirvec, imat[2]); - - glBegin(GL_QUAD_STRIP); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immBegin(GWN_PRIM_TRI_STRIP, 66); + immUniformColor4ub(255, 255, 255, 50); for (a = 0; a < 16; a++) { vec[0] = -si[a] * dirvec[0] + co[a] * norvec[0]; @@ -707,10 +828,8 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann madd_v3_v3v3fl(vec1, headvec, vec, head); madd_v3_v3v3fl(vec2, headvec, vec, head + dist); - glColor4ub(255, 255, 255, 50); - glVertex3fv(vec1); - //glColor4ub(255, 255, 255, 0); - glVertex3fv(vec2); + immVertex3fv(pos, vec1); + immVertex3fv(pos, vec2); } for (a = 15; a >= 0; a--) { @@ -721,10 +840,8 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann madd_v3_v3v3fl(vec1, tailvec, vec, tail); madd_v3_v3v3fl(vec2, tailvec, vec, tail + dist); - //glColor4ub(255, 255, 255, 50); - glVertex3fv(vec1); - //glColor4ub(255, 255, 255, 0); - glVertex3fv(vec2); + immVertex3fv(pos, vec1); + immVertex3fv(pos, vec2); } /* make it cyclic... */ @@ -735,12 +852,11 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann madd_v3_v3v3fl(vec1, headvec, vec, head); madd_v3_v3v3fl(vec2, headvec, vec, head + dist); - //glColor4ub(255, 255, 255, 50); - glVertex3fv(vec1); - //glColor4ub(255, 255, 255, 0); - glVertex3fv(vec2); + immVertex3fv(pos, vec1); + immVertex3fv(pos, vec2); - glEnd(); + immEnd(); + immUnbindProgram(); } } @@ -752,6 +868,11 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4], { float head, tail /*, length*/; float *headvec, *tailvec, dirvec[3]; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* figure out the sizes of spheres */ if (ebone) { @@ -780,35 +901,49 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4], /* sphere root color */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColor(TH_VERTEX); + if (boneflag & BONE_ROOTSEL) { + UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + } + else { + UI_GetThemeColor4fv(TH_VERTEX, fcolor); + } } else if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); - + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); + + immUniformColor4fv(fcolor); + /* Draw root point if we are not connected */ if ((boneflag & BONE_CONNECTED) == 0) { if (id != -1) GPU_select_load_id(id | BONESEL_ROOT); - drawcircball(GL_LINE_LOOP, headvec, head, imat); + imm_drawcircball(headvec, head, imat, pos); } /* Draw tip point */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColor(TH_VERTEX); + if (boneflag & BONE_TIPSEL) { + UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + } + else { + UI_GetThemeColor4fv(TH_VERTEX, fcolor); + } } if (id != -1) GPU_select_load_id(id | BONESEL_TIP); - drawcircball(GL_LINE_LOOP, tailvec, tail, imat); + imm_drawcircball(tailvec, tail, imat, pos); /* base */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT); - else UI_ThemeColor(TH_WIRE_EDIT); + if (boneflag & BONE_SELECTED) { + UI_GetThemeColor4fv(TH_SELECT, fcolor); + } + else { + UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor); + } } sub_v3_v3v3(dirvec, tailvec, headvec); @@ -834,34 +969,40 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4], if (id != -1) GPU_select_load_id(id | BONESEL_BONE); - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, 4); add_v3_v3v3(vec, headvec, norvech); - glVertex3fv(vec); + immVertex3fv(pos, vec); add_v3_v3v3(vec, tailvec, norvect); - glVertex3fv(vec); + immVertex3fv(pos, vec); sub_v3_v3v3(vec, headvec, norvech); - glVertex3fv(vec); + immVertex3fv(pos, vec); sub_v3_v3v3(vec, tailvec, norvect); - glVertex3fv(vec); + immVertex3fv(pos, vec); - glEnd(); + immEnd(); } + + immUnbindProgram(); } /* does wire only for outline selecting */ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone) { - GLUquadricObj *qobj; + Gwn_Batch *sphere = GPU_batch_preset_sphere(1); float head, tail, length; - float fac1, fac2; - - glPushMatrix(); - qobj = gluNewQuadric(); + float fac1, fac2, size1, size2; + const float light_vec[3] = {0.0f, 0.0f, 1.0f}; + + /* dt is always OB_SOlID */ + GWN_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_3fv(sphere, "light", light_vec); + + gpuPushMatrix(); /* figure out the sizes of spheres */ if (ebone) { @@ -882,110 +1023,124 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co } /* move to z-axis space */ - glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); + gpuRotateAxis(-90.0f, 'X'); - if (dt == OB_SOLID) { - /* set up solid drawing */ - GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); - - gluQuadricDrawStyle(qobj, GLU_FILL); - } - else { - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - } - /* sphere root color */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColorShade(TH_BONE_SOLID, -30); + if (boneflag & BONE_ROOTSEL) + UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + else + UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor); } else if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_END, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_SPHEREBONE_END, boneflag, constflag); else if (dt == OB_SOLID) - UI_ThemeColorShade(TH_BONE_SOLID, -30); + UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor); /* Draw root point if we are not connected */ if ((boneflag & BONE_CONNECTED) == 0) { if (id != -1) GPU_select_load_id(id | BONESEL_ROOT); - gluSphere(qobj, head, 16, 10); + gpuPushMatrix(); + gpuScaleUniform(head); + GWN_batch_uniform_4fv(sphere, "color", fcolor); + GWN_batch_draw(sphere); + gpuPopMatrix(); } /* Draw tip point */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColorShade(TH_BONE_SOLID, -30); + if (boneflag & BONE_TIPSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + else UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor); } if (id != -1) GPU_select_load_id(id | BONESEL_TIP); - glTranslatef(0.0f, 0.0f, length); - gluSphere(qobj, tail, 16, 10); - glTranslatef(0.0f, 0.0f, -length); + gpuTranslate3f(0.0f, 0.0f, length); + + gpuPushMatrix(); + gpuScaleUniform(tail); + GWN_batch_program_use_begin(sphere); /* hack to make the following uniforms stick */ + GWN_batch_uniform_4fv(sphere, "color", fcolor); + GWN_batch_draw(sphere); + gpuPopMatrix(); + + gpuTranslate3f(0.0f, 0.0f, -length); /* base */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT); - else UI_ThemeColor(TH_BONE_SOLID); + if (boneflag & BONE_SELECTED) UI_GetThemeColor4fv(TH_SELECT, fcolor); + else UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); } else if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_BASE, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_SPHEREBONE_BASE, boneflag, constflag); else if (dt == OB_SOLID) - UI_ThemeColor(TH_BONE_SOLID); + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + + GWN_batch_program_use_begin(sphere); /* hack to make the following uniforms stick */ + GWN_batch_uniform_4fv(sphere, "color", fcolor); fac1 = (length - head) / length; fac2 = (length - tail) / length; if (length > (head + tail)) { + size1 = fac2 * tail + (1.0f - fac2) * head; + size2 = fac1 * head + (1.0f - fac1) * tail; + if (id != -1) GPU_select_load_id(id | BONESEL_BONE); + /* draw sphere on extrema */ + gpuPushMatrix(); + gpuTranslate3f(0.0f, 0.0f, length - tail); + gpuScaleUniform(size1); + + GWN_batch_draw(sphere); + gpuPopMatrix(); + + gpuPushMatrix(); + gpuTranslate3f(0.0f, 0.0f, head); + gpuScaleUniform(size2); + + GWN_batch_draw(sphere); + gpuPopMatrix(); + + /* draw cynlinder between spheres */ glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -1.0f); - - glTranslatef(0.0f, 0.0f, head); - gluCylinder(qobj, fac1 * head + (1.0f - fac1) * tail, fac2 * tail + (1.0f - fac2) * head, length - head - tail, 16, 1); - glTranslatef(0.0f, 0.0f, -head); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_SIMPLE_LIGHTING); + immUniformColor4fv(fcolor); + immUniform3fv("light", light_vec); + + gpuTranslate3f(0.0f, 0.0f, head); + imm_draw_cylinder_fill_normal_3d(pos, nor, size2, size1, length - head - tail, 16, 1); + + immUnbindProgram(); glDisable(GL_POLYGON_OFFSET_FILL); - - /* draw sphere on extrema */ - glTranslatef(0.0f, 0.0f, length - tail); - gluSphere(qobj, fac2 * tail + (1.0f - fac2) * head, 16, 10); - glTranslatef(0.0f, 0.0f, -length + tail); - - glTranslatef(0.0f, 0.0f, head); - gluSphere(qobj, fac1 * head + (1.0f - fac1) * tail, 16, 10); } else { + size1 = fac1 * head + (1.0f - fac1) * tail; + /* 1 sphere in center */ - glTranslatef(0.0f, 0.0f, (head + length - tail) / 2.0f); - gluSphere(qobj, fac1 * head + (1.0f - fac1) * tail, 16, 10); - } - - /* restore */ - if (dt == OB_SOLID) { - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + gpuTranslate3f(0.0f, 0.0f, (head + length - tail) / 2.0f); + + gpuScaleUniform(size1); + GWN_batch_draw(sphere); } - glPopMatrix(); - gluDeleteQuadric(qobj); + gpuPopMatrix(); } -static GLubyte bm_dot6[] = {0x0, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x0}; -static GLubyte bm_dot8[] = {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C}; - -static GLubyte bm_dot5[] = {0x0, 0x0, 0x10, 0x38, 0x7c, 0x38, 0x10, 0x0}; -static GLubyte bm_dot7[] = {0x0, 0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38}; - - static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone) { - /* call this once, avoid constant changing */ - BLI_assert(glaGetOneInt(GL_UNPACK_ALIGNMENT) == 1); - float length; if (pchan) @@ -993,103 +1148,119 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned else length = ebone->length; - glPushMatrix(); - glScalef(length, length, length); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + gpuPushMatrix(); + gpuScaleUniform(length); /* this chunk not in object mode */ if (armflag & (ARM_EDITMODE | ARM_POSEMODE)) { glLineWidth(4.0f); - if (G.f & G_PICKSEL) { - /* no bitmap in selection mode, crashes 3d cards... - * instead draw a solid point the same size */ - glPointSize(8.0f); - } + glPointSize(8.0f); if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); else if (armflag & ARM_EDITMODE) { - UI_ThemeColor(TH_WIRE_EDIT); + UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor); } - + + /* line */ + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(fcolor); + + if (id != -1) + GPU_select_load_id(id | BONESEL_BONE); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 1.0f, 0.0f); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR); + immUniformColor4fv(fcolor); + /* Draw root point if we are not connected */ if ((boneflag & BONE_CONNECTED) == 0) { - if (G.f & G_PICKSEL) { + if (G.f & G_PICKSEL) GPU_select_load_id(id | BONESEL_ROOT); - glBegin(GL_POINTS); - glVertex3f(0.0f, 0.0f, 0.0f); - glEnd(); - } - else { - glRasterPos3f(0.0f, 0.0f, 0.0f); - glBitmap(8, 8, 4, 4, 0, 0, bm_dot8); - } + + immBegin(GWN_PRIM_POINTS, 1); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immEnd(); } - - if (id != -1) - GPU_select_load_id((GLuint) id | BONESEL_BONE); - - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, 1.0f, 0.0f); - glEnd(); - + /* tip */ - if (G.f & G_PICKSEL) { - /* no bitmap in selection mode, crashes 3d cards... */ + if (G.f & G_PICKSEL) GPU_select_load_id(id | BONESEL_TIP); - glBegin(GL_POINTS); - glVertex3f(0.0f, 1.0f, 0.0f); - glEnd(); - } - else { - glRasterPos3f(0.0f, 1.0f, 0.0f); - glBitmap(8, 8, 4, 4, 0, 0, bm_dot7); - } - + + immBegin(GWN_PRIM_POINTS, 1); + immVertex3f(pos, 0.0f, 1.0f, 0.0f); + immEnd(); + + immUnbindProgram(); + + /* further we send no names */ if (id != -1) GPU_select_load_id(id & 0xFFFF); /* object tag, for bordersel optim */ if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_LINEBONE, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_LINEBONE, boneflag, constflag); } - - glLineWidth(2.0); - + + /* Now draw the inner color */ + glLineWidth(2.0f); + glPointSize(5.0f); + + /* line */ + if (armflag & ARM_EDITMODE) { + if (boneflag & BONE_SELECTED) UI_GetThemeColor4fv(TH_EDGE_SELECT, fcolor); + else UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor); + } + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(fcolor); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 1.0f, 0.0f); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR); + /*Draw root point if we are not connected */ if ((boneflag & BONE_CONNECTED) == 0) { - if ((G.f & G_PICKSEL) == 0) { - /* no bitmap in selection mode, crashes 3d cards... */ - if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColor(TH_VERTEX); - } - glRasterPos3f(0.0f, 0.0f, 0.0f); - glBitmap(8, 8, 4, 4, 0, 0, bm_dot6); + if (armflag & ARM_EDITMODE) { + if (boneflag & BONE_ROOTSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + else UI_GetThemeColor4fv(TH_VERTEX, fcolor); } + immUniformColor4fv(fcolor); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immEnd(); } - - if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_EDGE_SELECT); - else UI_ThemeColorShade(TH_BACK, -30); - } - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, 1.0f, 0.0f); - glEnd(); - + /* tip */ if ((G.f & G_PICKSEL) == 0) { /* no bitmap in selection mode, crashes 3d cards... */ if (armflag & ARM_EDITMODE) { - if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColor(TH_VERTEX); + if (boneflag & BONE_TIPSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor); + else UI_GetThemeColor4fv(TH_VERTEX, fcolor); } - glRasterPos3f(0.0f, 1.0f, 0.0f); - glBitmap(8, 8, 4, 4, 0, 0, bm_dot5); + immUniformColor4fv(fcolor); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3f(pos, 0.0f, 1.0f, 0.0f); + immEnd(); } - - glPopMatrix(); + + immUnbindProgram(); + + gpuPopMatrix(); } /* A partial copy of b_bone_spline_setup(), with just the parts for previewing editmode curve settings @@ -1188,18 +1359,16 @@ static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, EditBone *ebo } for (a = 0; a < segments; a++) { - glPushMatrix(); - glMultMatrixf(bbone[a].mat); + gpuPushMatrix(); + gpuMultMatrix(bbone[a].mat); if (dt == OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth); else drawcube_size(xwidth, dlen, zwidth); - glPopMatrix(); + gpuPopMatrix(); } } else { - glPushMatrix(); if (dt == OB_SOLID) drawsolidcube_size(xwidth, length, zwidth); else drawcube_size(xwidth, length, zwidth); - glPopMatrix(); } } @@ -1222,26 +1391,27 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl /* draw points only if... */ if (armflag & ARM_EDITMODE) { /* move to unitspace */ - glPushMatrix(); - glScalef(length, length, length); + gpuPushMatrix(); + gpuScaleUniform(length); draw_bone_points(dt, armflag, boneflag, id); - glPopMatrix(); + gpuPopMatrix(); length *= 0.95f; /* make vertices visible */ } /* colors for modes */ if (armflag & ARM_POSEMODE) { if (dt <= OB_WIRE) - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); else - set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag); } else if (armflag & ARM_EDITMODE) { if (dt == OB_WIRE) { - set_ebone_glColor(boneflag); + set_ebone_color(boneflag); + } + else { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); } - else - UI_ThemeColor(TH_BONE_SOLID); } if (id != -1) { @@ -1250,33 +1420,31 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl /* set up solid drawing */ if (dt > OB_WIRE) { - GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); - if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag); - else - UI_ThemeColor(TH_BONE_SOLID); + set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag); + else { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + } + flat_color = false; draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth); - - /* disable solid drawing */ - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); } else { /* wire */ if (armflag & ARM_POSEMODE) { if (constflag && ((G.f & G_PICKSEL) == 0)) { /* set constraint colors */ - if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) { + if (set_pchan_color(PCHAN_COLOR_CONSTS, boneflag, constflag)) { glEnable(GL_BLEND); + flat_color = true; draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth); glDisable(GL_BLEND); } /* restore colors */ - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); } } @@ -1286,33 +1454,41 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float length, int segments) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(fcolor); + if ((segments > 1) && (pchan)) { float dlen = length / (float)segments; Mat4 *bbone = bbones; int a; - + for (a = 0; a < segments; a++, bbone++) { - glPushMatrix(); - glMultMatrixf(bbone->mat); - - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, dlen, 0.0f); - glEnd(); /* GL_LINES */ - - glPopMatrix(); + gpuPushMatrix(); + gpuMultMatrix(bbone->mat); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immVertex3f(pos, 0.0f, dlen, 0.0f); + immEnd(); + + gpuPopMatrix(); } } else { - glPushMatrix(); - - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, length, 0.0f); - glEnd(); - - glPopMatrix(); + gpuPushMatrix(); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immVertex3f(pos, 0.0f, length, 0.0f); + immEnd(); + + gpuPopMatrix(); } + + immUnbindProgram(); } static void draw_wire_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, @@ -1338,10 +1514,11 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons /* draw points only if... */ if (armflag & ARM_EDITMODE) { /* move to unitspace */ - glPushMatrix(); - glScalef(length, length, length); + gpuPushMatrix(); + gpuScaleUniform(length); + flat_color = true; draw_bone_points(dt, armflag, boneflag, id); - glPopMatrix(); + gpuPopMatrix(); length *= 0.95f; /* make vertices visible */ } @@ -1359,10 +1536,10 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons /* colors for modes */ if (armflag & ARM_POSEMODE) { - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); } else if (armflag & ARM_EDITMODE) { - set_ebone_glColor(boneflag); + set_ebone_color(boneflag); } /* draw normal */ @@ -1372,23 +1549,23 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons static void draw_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, float length) { - /* Draw a 3d octahedral bone, we use normalized space based on length, - * for display-lists */ - - glScalef(length, length, length); + /* Draw a 3d octahedral bone, we use normalized space based on length */ + gpuScaleUniform(length); /* set up solid drawing */ if (dt > OB_WIRE) { - GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); - UI_ThemeColor(TH_BONE_SOLID); + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + flat_color = false; } + else + flat_color = true; /* colors for posemode */ if (armflag & ARM_POSEMODE) { if (dt <= OB_WIRE) - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); else - set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag); } @@ -1403,12 +1580,12 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag if (dt <= OB_WIRE) { /* colors */ if (armflag & ARM_EDITMODE) { - set_ebone_glColor(boneflag); + set_ebone_color(boneflag); } else if (armflag & ARM_POSEMODE) { if (constflag && ((G.f & G_PICKSEL) == 0)) { /* draw constraint colors */ - if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) { + if (set_pchan_color(PCHAN_COLOR_CONSTS, boneflag, constflag)) { glEnable(GL_BLEND); draw_bone_solid_octahedral(); @@ -1417,7 +1594,7 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag } /* restore colors */ - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag); } } draw_bone_octahedral(); @@ -1425,35 +1602,33 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag else { /* solid */ if (armflag & ARM_POSEMODE) - set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag); + set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag); else - UI_ThemeColor(TH_BONE_SOLID); - draw_bone_solid_octahedral(); - } + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); - /* disable solid drawing */ - if (dt > OB_WIRE) { - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + draw_bone_solid_octahedral(); } } -static void draw_custom_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, - const short dt, int armflag, int boneflag, unsigned int id, float length) +static void draw_custom_bone( + const struct EvaluationContext *eval_ctx, + Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Object *ob, + const short dt, int armflag, int boneflag, unsigned int id, float length) { if (ob == NULL) return; - glScalef(length, length, length); + gpuScaleUniform(length); /* colors for posemode */ if (armflag & ARM_POSEMODE) { - set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, 0); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, 0); } if (id != -1) { GPU_select_load_id((GLuint) id | BONESEL_BONE); } - - draw_object_instance(scene, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE); + + draw_object_instance(eval_ctx, scene, sl, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE, fcolor); } @@ -1461,7 +1636,20 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp) { bConstraint *con; bPoseChannel *parchan; - + + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniformColor4fv(fcolor); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + for (con = pchan->constraints.first; con; con = con->next) { if (con->enforce == 0.0f) continue; @@ -1471,47 +1659,45 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp) { bKinematicConstraint *data = (bKinematicConstraint *)con->data; int segcount = 0; + float ik_tip[3]; /* if only_temp, only draw if it is a temporary ik-chain */ if ((only_temp) && !(data->flag & CONSTRAINT_IK_TEMP)) continue; - - setlinestyle(3); - glBegin(GL_LINES); - + /* exclude tip from chain? */ if ((data->flag & CONSTRAINT_IK_TIP) == 0) parchan = pchan->parent; else parchan = pchan; - glVertex3fv(parchan->pose_tail); + copy_v3_v3(ik_tip, parchan->pose_tail); /* Find the chain's root */ while (parchan->parent) { segcount++; - if (segcount == data->rootbone || segcount > 255) { - break; /* 255 is weak */ - } + /* FIXME: revise the breaking conditions */ + if (segcount == data->rootbone || segcount > 255) break; /* 255 is weak */ parchan = parchan->parent; } - if (parchan) - glVertex3fv(parchan->pose_head); + + if (parchan) { + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(shdr_pos, ik_tip); + immVertex3fv(shdr_pos, parchan->pose_head); + immEnd(); + } - glEnd(); - setlinestyle(0); break; } case CONSTRAINT_TYPE_SPLINEIK: { bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; int segcount = 0; - - setlinestyle(3); - glBegin(GL_LINES); + float ik_tip[3]; parchan = pchan; - glVertex3fv(parchan->pose_tail); + copy_v3_v3(ik_tip, parchan->pose_tail); /* Find the chain's root */ while (parchan->parent) { @@ -1521,18 +1707,21 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp) parchan = parchan->parent; } /* Only draw line in case our chain is more than one bone long! */ - if (parchan != pchan) /* XXX revise the breaking conditions to only stop at the tail? */ - glVertex3fv(parchan->pose_head); - - glEnd(); - setlinestyle(0); + if (parchan != pchan) { /* XXX revise the breaking conditions to only stop at the tail? */ + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(shdr_pos, ik_tip); + immVertex3fv(shdr_pos, parchan->pose_head); + immEnd(); + } break; } } } + + immUnbindProgram(); } -static void bgl_sphere_project(float ax, float az) +static void imm_sphere_project(unsigned int pos, float ax, float az) { float dir[3], sine, q3; @@ -1543,11 +1732,13 @@ static void bgl_sphere_project(float ax, float az) dir[1] = 1.0f - 2.0f * sine; dir[2] = ax * q3; - glVertex3fv(dir); + immVertex3fv(pos, dir); } -static void draw_dof_ellipse(float ax, float az) +static void draw_dof_ellipse(unsigned int pos, float ax, float az) { + const int n = 16; + const int tri = n * n - 2 * n + 1; /* Yay fancy math ! */ const float staticSine[16] = { 0.0f, 0.104528463268f, 0.207911690818f, 0.309016994375f, 0.406736643076f, 0.5f, 0.587785252292f, 0.669130606359f, @@ -1556,15 +1747,15 @@ static void draw_dof_ellipse(float ax, float az) 0.994521895368f, 1.0f }; - int i, j, n = 16; + int i, j; float x, z, px, pz; glEnable(GL_BLEND); glDepthMask(0); - glColor4ub(70, 70, 70, 50); + immUniformColor4ub(70, 70, 70, 50); - glBegin(GL_QUADS); + immBegin(GWN_PRIM_TRIS, tri * 3); pz = 0.0f; for (i = 1; i < n; i++) { z = staticSine[i]; @@ -1574,36 +1765,35 @@ static void draw_dof_ellipse(float ax, float az) x = staticSine[j]; if (j == n - i) { - glEnd(); - glBegin(GL_TRIANGLES); - bgl_sphere_project(ax * px, az * z); - bgl_sphere_project(ax * px, az * pz); - bgl_sphere_project(ax * x, az * pz); - glEnd(); - glBegin(GL_QUADS); + imm_sphere_project(pos, ax * px, az * z); + imm_sphere_project(pos, ax * px, az * pz); + imm_sphere_project(pos, ax * x, az * pz); } else { - bgl_sphere_project(ax * x, az * z); - bgl_sphere_project(ax * x, az * pz); - bgl_sphere_project(ax * px, az * pz); - bgl_sphere_project(ax * px, az * z); + imm_sphere_project(pos, ax * x, az * z); + imm_sphere_project(pos, ax * x, az * pz); + imm_sphere_project(pos, ax * px, az * pz); + + imm_sphere_project(pos, ax * px, az * pz); + imm_sphere_project(pos, ax * px, az * z); + imm_sphere_project(pos, ax * x, az * z); } px = x; } pz = z; } - glEnd(); + immEnd(); glDisable(GL_BLEND); glDepthMask(1); - glColor3ub(0, 0, 0); + immUniformColor3ub(0, 0, 0); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, n); for (i = 0; i < n; i++) - bgl_sphere_project(staticSine[n - i - 1] * ax, staticSine[i] * az); - glEnd(); + imm_sphere_project(pos, staticSine[n - i - 1] * ax, staticSine[i] * az); + immEnd(); } static void draw_pose_dofs(Object *ob) @@ -1611,7 +1801,12 @@ static void draw_pose_dofs(Object *ob) bArmature *arm = ob->data; bPoseChannel *pchan; Bone *bone; - + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { bone = pchan->bone; @@ -1625,54 +1820,55 @@ static void draw_pose_dofs(Object *ob) int a, i; /* in parent-bone pose, but own restspace */ - glPushMatrix(); + gpuPushMatrix(); copy_v3_v3(posetrans, pchan->pose_mat[3]); - glTranslate3fv(posetrans); + gpuTranslate3fv(posetrans); if (pchan->parent) { copy_m4_m4(mat, pchan->parent->pose_mat); mat[3][0] = mat[3][1] = mat[3][2] = 0.0f; - glMultMatrixf(mat); + gpuMultMatrix(mat); } copy_m4_m3(mat, pchan->bone->bone_mat); - glMultMatrixf(mat); + gpuMultMatrix(mat); scale = bone->length * pchan->size[1]; - glScalef(scale, scale, scale); + gpuScaleUniform(scale); - if (pchan->ikflag & BONE_IK_XLIMIT) { - if (pchan->ikflag & BONE_IK_ZLIMIT) { - float amin[3], amax[3]; - - for (i = 0; i < 3; i++) { - /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */ - amin[i] = sinf(pchan->limitmin[i] * 0.5f); - amax[i] = sinf(pchan->limitmax[i] * 0.5f); - } - - glScalef(1.0f, -1.0f, 1.0f); - if ((amin[0] != 0.0f) && (amin[2] != 0.0f)) - draw_dof_ellipse(amin[0], amin[2]); - if ((amin[0] != 0.0f) && (amax[2] != 0.0f)) - draw_dof_ellipse(amin[0], amax[2]); - if ((amax[0] != 0.0f) && (amin[2] != 0.0f)) - draw_dof_ellipse(amax[0], amin[2]); - if ((amax[0] != 0.0f) && (amax[2] != 0.0f)) - draw_dof_ellipse(amax[0], amax[2]); - glScalef(1.0f, -1.0f, 1.0f); + if (((pchan->ikflag & BONE_IK_XLIMIT) != 0) && + ((pchan->ikflag & BONE_IK_ZLIMIT) != 0)) + { + float amin[3], amax[3]; + + for (i = 0; i < 3; i++) { + /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */ + amin[i] = sinf(pchan->limitmin[i] * 0.5f); + amax[i] = sinf(pchan->limitmax[i] * 0.5f); } + + gpuScale3f(1.0f, -1.0f, 1.0f); + if ((amin[0] != 0.0f) && (amin[2] != 0.0f)) + draw_dof_ellipse(pos, amin[0], amin[2]); + if ((amin[0] != 0.0f) && (amax[2] != 0.0f)) + draw_dof_ellipse(pos, amin[0], amax[2]); + if ((amax[0] != 0.0f) && (amin[2] != 0.0f)) + draw_dof_ellipse(pos, amax[0], amin[2]); + if ((amax[0] != 0.0f) && (amax[2] != 0.0f)) + draw_dof_ellipse(pos, amax[0], amax[2]); + gpuScale3f(1.0f, -1.0f, 1.0f); /* XXX same as above, is this intentional? */ } /* arcs */ if (pchan->ikflag & BONE_IK_ZLIMIT) { /* OpenGL requires rotations in degrees; so we're taking the average angle here */ theta = RAD2DEGF(0.5f * (pchan->limitmin[2] + pchan->limitmax[2])); - glRotatef(theta, 0.0f, 0.0f, 1.0f); + gpuPushMatrix(); + gpuRotateAxis(theta, 'Z'); - glColor3ub(50, 50, 255); /* blue, Z axis limit */ - glBegin(GL_LINE_STRIP); + immUniformColor3ub(50, 50, 255); /* blue, Z axis limit */ + immBegin(GWN_PRIM_LINE_STRIP, 33); for (a = -16; a <= 16; a++) { /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */ float fac = ((float)a) / 16.0f * 0.5f; @@ -1683,20 +1879,21 @@ static void draw_pose_dofs(Object *ob) corner[i][0] = sinf(phi); corner[i][1] = cosf(phi); corner[i][2] = 0.0f; - glVertex3fv(corner[i]); + immVertex3fv(pos, corner[i]); } - glEnd(); + immEnd(); - glRotatef(-theta, 0.0f, 0.0f, 1.0f); + gpuPopMatrix(); } if (pchan->ikflag & BONE_IK_XLIMIT) { /* OpenGL requires rotations in degrees; so we're taking the average angle here */ theta = RAD2DEGF(0.5f * (pchan->limitmin[0] + pchan->limitmax[0])); - glRotatef(theta, 1.0f, 0.0f, 0.0f); + gpuPushMatrix(); + gpuRotateAxis(theta, 'X'); - glColor3ub(255, 50, 50); /* Red, X axis limit */ - glBegin(GL_LINE_STRIP); + immUniformColor3ub(255, 50, 50); /* Red, X axis limit */ + immBegin(GWN_PRIM_LINE_STRIP, 33); for (a = -16; a <= 16; a++) { /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */ float fac = ((float)a) / 16.0f * 0.5f; @@ -1706,21 +1903,23 @@ static void draw_pose_dofs(Object *ob) corner[i][0] = 0.0f; corner[i][1] = sinf(phi); corner[i][2] = cosf(phi); - glVertex3fv(corner[i]); + immVertex3fv(pos, corner[i]); } - glEnd(); + immEnd(); - glRotatef(-theta, 1.0f, 0.0f, 0.0f); + gpuPopMatrix(); } /* out of cone, out of bone */ - glPopMatrix(); + gpuPopMatrix(); } } } } } } + + immUnbindProgram(); } static void bone_matrix_translate_y(float mat[4][4], float y) @@ -1733,9 +1932,10 @@ static void bone_matrix_translate_y(float mat[4][4], float y) } /* assumes object is Armature with pose */ -static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, - const short dt, const unsigned char ob_wire_col[4], - const bool do_const_color, const bool is_outline) +static void draw_pose_bones( + const struct EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, + const short dt, const unsigned char ob_wire_col[4], + const bool do_const_color, const bool is_outline) { RegionView3D *rv3d = ar->regiondata; Object *ob = base->object; @@ -1756,7 +1956,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* being set below */ arm->layer_used = 0; - + + rgba_uchar_to_float(fcolor, ob_wire_col); + /* precalc inverse matrix for drawing screen aligned */ if (arm->drawtype == ARM_ENVELOPE) { /* precalc inverse matrix for drawing screen aligned */ @@ -1805,7 +2007,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* if solid we draw that first, with selection codes, but without names, axes etc */ if (dt > OB_WIRE) { if (arm->flag & ARM_POSEMODE) - index = base->selcol; + index = base->object->select_color; for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { bone = pchan->bone; @@ -1817,13 +2019,13 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, { if (bone->layer & arm->layer) { const bool use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM); - glPushMatrix(); + gpuPushMatrix(); if (use_custom && pchan->custom_tx) { - glMultMatrixf(pchan->custom_tx->pose_mat); + gpuMultMatrix(pchan->custom_tx->pose_mat); } else { - glMultMatrixf(pchan->pose_mat); + gpuMultMatrix(pchan->pose_mat); } /* catch exception for bone with hidden parent */ @@ -1858,7 +2060,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, glDisable(GL_CULL_FACE); } - draw_custom_bone(scene, v3d, rv3d, pchan->custom, + draw_custom_bone(eval_ctx, scene, sl, v3d, rv3d, pchan->custom, OB_SOLID, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan)); } } @@ -1885,7 +2087,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } } - glPopMatrix(); + gpuPopMatrix(); } } @@ -1913,7 +2115,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, (draw_wire || (dt <= OB_WIRE)) ) { if (arm->flag & ARM_POSEMODE) - index = base->selcol; + index = base->object->select_color; /* only draw custom bone shapes that need to be drawn as wires */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { @@ -1926,13 +2128,13 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (bone->layer & arm->layer) { if (pchan->custom) { if ((dt < OB_SOLID) || (bone->flag & BONE_DRAWWIRE)) { - glPushMatrix(); + gpuPushMatrix(); if (pchan->custom_tx) { - glMultMatrixf(pchan->custom_tx->pose_mat); + gpuMultMatrix(pchan->custom_tx->pose_mat); } else { - glMultMatrixf(pchan->pose_mat); + gpuMultMatrix(pchan->pose_mat); } /* prepare colors */ @@ -1942,7 +2144,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, else if (arm->flag & ARM_POSEMODE) set_pchan_colorset(ob, pchan); else { - glColor3ubv(ob_wire_col); + rgba_uchar_to_float(fcolor, ob_wire_col); } /* catch exception for bone with hidden parent */ @@ -1954,10 +2156,10 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (bone == arm->act_bone) flag |= BONE_DRAW_ACTIVE; - draw_custom_bone(scene, v3d, rv3d, pchan->custom, + draw_custom_bone(eval_ctx, scene, sl, v3d, rv3d, pchan->custom, OB_WIRE, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan)); - glPopMatrix(); + gpuPopMatrix(); } } } @@ -1979,7 +2181,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* draw line check first. we do selection indices */ if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) { if (arm->flag & ARM_POSEMODE) - index = base->selcol; + index = base->object->select_color; } /* if solid && posemode, we draw again with polygonoffset */ else if ((dt > OB_WIRE) && (arm->flag & ARM_POSEMODE)) { @@ -1988,7 +2190,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, else { /* and we use selection indices if not done yet */ if (arm->flag & ARM_POSEMODE) - index = base->selcol; + index = base->object->select_color; } if (is_cull_enabled == false) { @@ -2011,16 +2213,30 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, * - only if V3D_HIDE_HELPLINES is enabled... */ if ((do_dashed & DASH_HELP_LINES) && ((bone->flag & BONE_CONNECTED) == 0)) { + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniformColor4fv(fcolor); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + if (arm->flag & ARM_POSEMODE) { GPU_select_load_id(index & 0xFFFF); /* object tag, for bordersel optim */ - UI_ThemeColor(TH_WIRE); + immUniformThemeColor(TH_WIRE); } - setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(pchan->pose_head); - glVertex3fv(pchan->parent->pose_tail); - glEnd(); - setlinestyle(0); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(shdr_pos, pchan->parent->pose_tail); + immVertex3fv(shdr_pos, pchan->pose_head); + immEnd(); + + immUnbindProgram(); } /* Draw a line to IK root bone @@ -2029,8 +2245,11 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (arm->flag & ARM_POSEMODE) { if (constflag & PCHAN_HAS_IK) { if (bone->flag & BONE_SELECTED) { - if (constflag & PCHAN_HAS_TARGET) glColor3ub(200, 120, 0); - else glColor3ub(200, 200, 50); /* add theme! */ + if (constflag & PCHAN_HAS_TARGET) { + rgba_float_args_set(fcolor, 200.f / 255.f, 120.f / 255.f, 0.f / 255.f, 1.0f); + } + /* add theme! */ + else rgba_float_args_set(fcolor, 200.f / 255.f, 200.f / 255.f, 50.f / 255.f, 1.0f); GPU_select_load_id(index & 0xFFFF); pchan_draw_IK_root_lines(pchan, !(do_dashed & DASH_HELP_LINES)); @@ -2038,8 +2257,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } else if (constflag & PCHAN_HAS_SPLINEIK) { if (bone->flag & BONE_SELECTED) { - glColor3ub(150, 200, 50); /* add theme! */ - + /* add theme! */ + rgba_float_args_set(fcolor, 150.f / 255.f, 200.f / 255.f, 50.f / 255.f, 1.0f); + GPU_select_load_id(index & 0xFFFF); pchan_draw_IK_root_lines(pchan, !(do_dashed & DASH_HELP_LINES)); } @@ -2047,9 +2267,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } } - glPushMatrix(); + gpuPushMatrix(); if (arm->drawtype != ARM_ENVELOPE) - glMultMatrixf(pchan->pose_mat); + gpuMultMatrix(pchan->pose_mat); /* catch exception for bone with hidden parent */ flag = bone->flag; @@ -2086,7 +2306,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, else draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->length); - glPopMatrix(); + gpuPopMatrix(); } } @@ -2106,7 +2326,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* draw DoFs */ if (arm->flag & ARM_POSEMODE) { - if (((base->flag & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) { + if (((base->flag_legacy & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) { draw_pose_dofs(ob); } } @@ -2114,26 +2334,17 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* finally names and axes */ if ((arm->flag & (ARM_DRAWNAMES | ARM_DRAWAXES)) && (is_outline == 0) && - ((base->flag & OB_FROMDUPLI) == 0)) + ((base->flag_legacy & OB_FROMDUPLI) == 0)) { /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */ if ((G.f & G_PICKSEL) == 0) { float vec[3]; unsigned char col[4]; - if (do_const_color) { - /* so we can draw bone names in current const color */ - float tcol[4]; - glGetFloatv(GL_CURRENT_COLOR, tcol); - rgb_float_to_uchar(col, tcol); - col[3] = 255; - } - else { - col[0] = ob_wire_col[0]; - col[1] = ob_wire_col[1]; - col[2] = ob_wire_col[2]; - col[3] = 255; - } + col[0] = ob_wire_col[0]; + col[1] = ob_wire_col[1]; + col[2] = ob_wire_col[2]; + col[3] = 255; if (v3d->zbuf) glDisable(GL_DEPTH_TEST); @@ -2156,18 +2367,16 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* Draw additional axes on the bone tail */ if ((arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE)) { - glPushMatrix(); + gpuPushMatrix(); copy_m4_m4(bmat, pchan->pose_mat); bone_matrix_translate_y(bmat, pchan->bone->length); - glMultMatrixf(bmat); + gpuMultMatrix(bmat); - glColor3ubv(col); - float viewmat_pchan[4][4]; mul_m4_m4m4(viewmat_pchan, rv3d->viewmatob, bmat); - drawaxes(viewmat_pchan, pchan->bone->length * 0.25f, OB_ARROWS); + drawaxes(viewmat_pchan, pchan->bone->length * 0.25f, OB_ARROWS, col); - glPopMatrix(); + gpuPopMatrix(); } } } @@ -2233,9 +2442,9 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) for (eBone = arm->edbo->first, index = 0; eBone; eBone = eBone->next, index++) { if (eBone->layer & arm->layer) { if ((eBone->flag & BONE_HIDDEN_A) == 0) { - glPushMatrix(); + gpuPushMatrix(); get_matrix_editbone(eBone, bmat); - glMultMatrixf(bmat); + gpuMultMatrix(bmat); /* catch exception for bone with hidden parent */ flag = eBone->flag; @@ -2257,7 +2466,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length); } - glPopMatrix(); + gpuPopMatrix(); } } } @@ -2295,9 +2504,9 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) draw_sphere_bone_wire(smat, imat, arm->flag, flag, 0, index, NULL, eBone); } else { - glPushMatrix(); + gpuPushMatrix(); get_matrix_editbone(eBone, bmat); - glMultMatrixf(bmat); + gpuMultMatrix(bmat); if (arm->drawtype == ARM_LINE) draw_line_bone(arm->flag, flag, 0, index, NULL, eBone); @@ -2308,21 +2517,32 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) else draw_bone(OB_WIRE, arm->flag, flag, 0, index, eBone->length); - glPopMatrix(); + gpuPopMatrix(); } /* offset to parent */ if (eBone->parent) { - UI_ThemeColor(TH_WIRE_EDIT); + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + GPU_select_load_id(-1); /* -1 here is OK! */ - setlinestyle(3); - - glBegin(GL_LINES); - glVertex3fv(eBone->parent->tail); - glVertex3fv(eBone->head); - glEnd(); - - setlinestyle(0); + + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniformThemeColor(TH_WIRE_EDIT); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(shdr_pos, eBone->parent->tail); + immVertex3fv(shdr_pos, eBone->head); + immEnd(); + + immUnbindProgram(); } } } @@ -2364,18 +2584,16 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) } /* Draw additional axes */ if (arm->flag & ARM_DRAWAXES) { - glPushMatrix(); + gpuPushMatrix(); get_matrix_editbone(eBone, bmat); bone_matrix_translate_y(bmat, eBone->length); - glMultMatrixf(bmat); - - glColor3ubv(col); + gpuMultMatrix(bmat); float viewmat_ebone[4][4]; mul_m4_m4m4(viewmat_ebone, rv3d->viewmatob, bmat); - drawaxes(viewmat_ebone, eBone->length * 0.25f, OB_ARROWS); + drawaxes(viewmat_ebone, eBone->length * 0.25f, OB_ARROWS, col); - glPopMatrix(); + gpuPopMatrix(); } } @@ -2448,7 +2666,8 @@ static void ghost_poses_tag_unselected(Object *ob, short unset) /* draw ghosts that occur within a frame range * note: object should be in posemode */ -static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +static void draw_ghost_poses_range( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base) { Object *ob = base->object; AnimData *adt = BKE_animdata_from_id(&ob->id); @@ -2456,6 +2675,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base bPose *posen, *poseo; float start, end, stepsize, range, colfac; int cfrao, flago; + unsigned char col[4]; start = (float)arm->ghostsf; end = (float)arm->ghostef; @@ -2488,11 +2708,11 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base /* draw from first frame of range to last */ for (CFRA = (int)start; CFRA <= end; CFRA += (int)stepsize) { colfac = (end - (float)CFRA) / range; - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac))); + UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col); BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL); - BKE_pose_where_is(scene, ob); - draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false); + BKE_pose_where_is(eval_ctx, scene, ob); + draw_pose_bones(eval_ctx, scene, sl, v3d, ar, base, OB_WIRE, col, true, false); } glDisable(GL_BLEND); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); @@ -2514,7 +2734,9 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base /* draw ghosts on keyframes in action within range * - object should be in posemode */ -static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +static void draw_ghost_poses_keys( + const struct EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, + View3D *v3d, ARegion *ar, Base *base) { Object *ob = base->object; AnimData *adt = BKE_animdata_from_id(&ob->id); @@ -2525,6 +2747,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base * ActKeyColumn *ak, *akn; float start, end, range, colfac, i; int cfrao, flago; + unsigned char col[4]; start = (float)arm->ghostsf; end = (float)arm->ghostef; @@ -2566,13 +2789,13 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base * /* draw from first frame of range to last */ for (ak = keys.first, i = 0; ak; ak = ak->next, i++) { colfac = i / range; - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac))); + UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col); CFRA = (int)ak->cfra; BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL); - BKE_pose_where_is(scene, ob); - draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false); + BKE_pose_where_is(eval_ctx, scene, ob); + draw_pose_bones(eval_ctx, scene, sl, v3d, ar, base, OB_WIRE, col, true, false); } glDisable(GL_BLEND); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); @@ -2595,7 +2818,9 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base * /* draw ghosts around current frame * - object is supposed to be armature in posemode */ -static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +static void draw_ghost_poses( + const struct EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, + View3D *v3d, ARegion *ar, Base *base) { Object *ob = base->object; AnimData *adt = BKE_animdata_from_id(&ob->id); @@ -2603,7 +2828,8 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) bPose *posen, *poseo; float cur, start, end, stepsize, range, colfac, actframe, ctime; int cfrao, flago; - + unsigned char col[4]; + /* pre conditions, get an action with sufficient frames */ if (ELEM(NULL, adt, adt->action)) return; @@ -2640,7 +2866,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) for (cur = stepsize; cur < range; cur += stepsize) { ctime = cur - (float)fmod(cfrao, stepsize); /* ensures consistent stepping */ colfac = ctime / range; - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac))); + UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col); /* only within action range */ if (actframe + ctime >= start && actframe + ctime <= end) { @@ -2648,14 +2874,14 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) if (CFRA != cfrao) { BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL); - BKE_pose_where_is(scene, ob); - draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false); + BKE_pose_where_is(eval_ctx, scene, ob); + draw_pose_bones(eval_ctx, scene, sl, v3d, ar, base, OB_WIRE, col, true, false); } } ctime = cur + (float)fmod((float)cfrao, stepsize) - stepsize + 1.0f; /* ensures consistent stepping */ colfac = ctime / range; - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac))); + UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col); /* only within action range */ if ((actframe - ctime >= start) && (actframe - ctime <= end)) { @@ -2663,8 +2889,8 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) if (CFRA != cfrao) { BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL); - BKE_pose_where_is(scene, ob); - draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false); + BKE_pose_where_is(eval_ctx, scene, ob); + draw_pose_bones(eval_ctx, scene, sl, v3d, ar, base, OB_WIRE, col, true, false); } } } @@ -2689,9 +2915,10 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) /* called from drawobject.c, return true if nothing was drawn * (ob_wire_col == NULL) when drawing ghost */ -bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4], - const bool is_outline) +bool draw_armature( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, + const short dt, const short dflag, const unsigned char ob_wire_col[4], + const bool is_outline) { Object *ob = base->object; bArmature *arm = ob->data; @@ -2700,11 +2927,7 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (v3d->flag2 & V3D_RENDER_OVERRIDE) return true; - /* needed for 'draw_line_bone' which draws pixel. */ - if (arm->drawtype == ARM_LINE) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - } - +#if 0 /* Not used until lighting is properly reimplemented */ if (dt > OB_WIRE) { /* we use color for solid lighting */ if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) { @@ -2719,7 +2942,8 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); /* only for lighting... */ } } - +#endif + /* arm->flag is being used to detect mode... */ /* editmode? */ if (arm->edbo) { @@ -2736,7 +2960,7 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } /* drawing posemode selection indices or colors only in these cases */ - if (!(base->flag & OB_FROMDUPLI)) { + if (!(base->flag_legacy & OB_FROMDUPLI)) { if (G.f & G_PICKSEL) { #if 0 /* nifty but actually confusing to allow bone selection out of posemode */ @@ -2752,31 +2976,28 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } else if (ob->mode & OB_MODE_POSE) { if (arm->ghosttype == ARM_GHOST_RANGE) { - draw_ghost_poses_range(scene, v3d, ar, base); + draw_ghost_poses_range(eval_ctx, scene, sl, v3d, ar, base); } else if (arm->ghosttype == ARM_GHOST_KEYS) { - draw_ghost_poses_keys(scene, v3d, ar, base); + draw_ghost_poses_keys(eval_ctx, scene, sl, v3d, ar, base); } else if (arm->ghosttype == ARM_GHOST_CUR) { if (arm->ghostep) - draw_ghost_poses(scene, v3d, ar, base); + draw_ghost_poses(eval_ctx, scene, sl, v3d, ar, base); } if ((dflag & DRAW_SCENESET) == 0) { - if (ob == OBACT) + if (ob == OBACT(sl)) arm->flag |= ARM_POSEMODE; - else if (OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) { - if (ob == modifiers_isDeformedByArmature(OBACT)) + else if (OBACT(sl) && (OBACT(sl)->mode & OB_MODE_WEIGHT_PAINT)) { + if (ob == modifiers_isDeformedByArmature(OBACT(sl))) arm->flag |= ARM_POSEMODE; } draw_pose_paths(scene, v3d, ar, ob); } } } - draw_pose_bones(scene, v3d, ar, base, dt, ob_wire_col, (dflag & DRAW_CONSTCOLOR), is_outline); + draw_pose_bones(eval_ctx, scene, sl, v3d, ar, base, dt, ob_wire_col, (dflag & DRAW_CONSTCOLOR), is_outline); arm->flag &= ~ARM_POSEMODE; - - if (ob->mode & OB_MODE_POSE) - UI_ThemeColor(TH_WIRE); /* restore, for extra draw stuff */ } else { retval = true; @@ -2785,9 +3006,5 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* restore */ glFrontFace(GL_CCW); - if (arm->drawtype == ARM_LINE) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - } - return retval; } diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index bbbf8c633bd..719fb6f764f 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -55,7 +55,6 @@ #include "BKE_editmesh.h" #include "BKE_scene.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "UI_resources.h" @@ -64,6 +63,7 @@ #include "GPU_material.h" #include "GPU_basic_shader.h" #include "GPU_shader.h" +#include "GPU_matrix.h" #include "RE_engine.h" @@ -77,20 +77,6 @@ typedef struct drawMeshFaceSelect_userData { BLI_bitmap *edge_flags; /* pairs of edge options (visible, select) */ } drawMeshFaceSelect_userData; -typedef struct drawEMTFMapped_userData { - BMEditMesh *em; - bool has_mcol; - int cd_poly_tex_offset; - const MPoly *mpoly; - const MTexPoly *mtexpoly; -} drawEMTFMapped_userData; - -typedef struct drawTFace_userData { - const Mesh *me; - const MPoly *mpoly; - const MTexPoly *mtexpoly; -} drawTFace_userData; - /**************************** Face Select Mode *******************************/ /* mainly to be less confusing */ @@ -213,562 +199,6 @@ void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm, bool d /***************************** Texture Drawing ******************************/ -static Material *give_current_material_or_def(Object *ob, int matnr) -{ - extern Material defmaterial; /* render module abuse... */ - Material *ma = give_current_material(ob, matnr); - - return ma ? ma : &defmaterial; -} - -/* Icky globals, fix with userdata parameter */ - -static struct TextureDrawState { - Object *ob; - Image *stencil; /* texture painting stencil */ - Image *canvas; /* texture painting canvas, for image mode */ - bool use_game_mat; - int is_lit, is_tex; - int color_profile; - bool use_backface_culling; - bool two_sided_lighting; - unsigned char obcol[4]; - bool is_texpaint; - bool texpaint_material; /* use material slots for texture painting */ -} Gtexdraw = {NULL, NULL, NULL, false, 0, 0, 0, false, false, {0, 0, 0, 0}, false, false}; - -static bool set_draw_settings_cached( - int clearcache, MTexPoly *texface, Material *ma, - const struct TextureDrawState *gtexdraw) -{ - static Material *c_ma; - static int c_textured; - static MTexPoly c_texface; - static int c_backculled; - static bool c_badtex; - static int c_lit; - static int c_has_texface; - - int backculled = 1; - int alphablend = GPU_BLEND_SOLID; - int textured = 0; - int lit = 0; - int has_texface = texface != NULL; - bool need_set_tpage = false; - bool texpaint = ((gtexdraw->ob->mode & OB_MODE_TEXTURE_PAINT) != 0); - - Image *ima = NULL; - - if (ma != NULL) { - if (ma->mode & MA_TRANSP) { - alphablend = GPU_BLEND_ALPHA; - } - } - - if (clearcache) { - c_textured = c_lit = c_backculled = -1; - memset(&c_texface, 0, sizeof(c_texface)); - c_badtex = false; - c_has_texface = -1; - c_ma = NULL; - } - else { - textured = gtexdraw->is_tex; - } - - /* convert number of lights into boolean */ - if (gtexdraw->is_lit) { - lit = 1; - } - - backculled = gtexdraw->use_backface_culling; - if (ma) { - if (ma->mode & MA_SHLESS) lit = 0; - if (gtexdraw->use_game_mat) { - backculled = backculled || (ma->game.flag & GEMAT_BACKCULL); - alphablend = ma->game.alpha_blend; - } - } - - if (texface && !texpaint) { - textured = textured && (texface->tpage); - - /* no material, render alpha if texture has depth=32 */ - if (!ma && BKE_image_has_alpha(texface->tpage)) - alphablend = GPU_BLEND_ALPHA; - } - else if (texpaint) { - if (gtexdraw->texpaint_material) - ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL; - else - ima = gtexdraw->canvas; - } - else - textured = 0; - - if (backculled != c_backculled) { - if (backculled) glEnable(GL_CULL_FACE); - else glDisable(GL_CULL_FACE); - - c_backculled = backculled; - } - - /* need to re-set tpage if textured flag changed or existsment of texface changed.. */ - need_set_tpage = textured != c_textured || has_texface != c_has_texface; - /* ..or if settings inside texface were changed (if texface was used) */ - need_set_tpage |= (texpaint && c_ma != ma) || (texface && memcmp(&c_texface, texface, sizeof(c_texface))); - - if (need_set_tpage) { - if (textured) { - if (texpaint) { - c_badtex = false; - if (GPU_verify_image(ima, NULL, GL_TEXTURE_2D, 0, 1, 0, false)) { - glEnable(GL_TEXTURE_2D); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE); - - glActiveTexture(GL_TEXTURE1); - glEnable(GL_TEXTURE_2D); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); - glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); - glActiveTexture(GL_TEXTURE0); - } - else { - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glActiveTexture(GL_TEXTURE0); - - c_badtex = true; - GPU_clear_tpage(true); - glDisable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } - } - else { - c_badtex = !GPU_set_tpage(texface, !texpaint, alphablend); - } - } - else { - GPU_set_tpage(NULL, 0, 0); - c_badtex = false; - } - c_textured = textured; - c_has_texface = has_texface; - if (texface) - memcpy(&c_texface, texface, sizeof(c_texface)); - } - - if (c_badtex) lit = 0; - if (lit != c_lit || ma != c_ma || textured != c_textured) { - int options = GPU_SHADER_USE_COLOR; - - if (c_textured && !c_badtex) { - options |= GPU_SHADER_TEXTURE_2D; - } - if (gtexdraw->two_sided_lighting) { - options |= GPU_SHADER_TWO_SIDED; - } - - if (lit) { - options |= GPU_SHADER_LIGHTING; - if (!ma) - ma = give_current_material_or_def(NULL, 0); /* default material */ - - float specular[3]; - mul_v3_v3fl(specular, &ma->specr, ma->spec); - - GPU_basic_shader_colors(NULL, specular, ma->har, 1.0f); - } - - GPU_basic_shader_bind(options); - - c_lit = lit; - c_ma = ma; - } - - return c_badtex; -} - -static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) -{ - unsigned char obcol[4]; - bool is_tex, solidtex; - Mesh *me = ob->data; - ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; - - /* XXX scene->obedit warning */ - - /* texture draw is abused for mask selection mode, do this so wire draw - * with face selection in weight paint is not lit. */ - if ((v3d->drawtype <= OB_WIRE) && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT))) { - solidtex = false; - Gtexdraw.is_lit = 0; - } - else if ((ob->mode & OB_MODE_TEXTURE_PAINT) && BKE_scene_use_new_shading_nodes(scene)) { - solidtex = true; - if (v3d->flag2 & V3D_SHADELESS_TEX) - Gtexdraw.is_lit = 0; - else - Gtexdraw.is_lit = -1; - } - else if ((v3d->drawtype == OB_SOLID) || - ((ob->mode & OB_MODE_EDIT) && (v3d->drawtype != OB_TEXTURE))) - { - /* draw with default lights in solid draw mode and edit mode */ - solidtex = true; - Gtexdraw.is_lit = -1; - } - else { - /* draw with lights in the scene otherwise */ - solidtex = false; - if (v3d->flag2 & V3D_SHADELESS_TEX) { - Gtexdraw.is_lit = 0; - } - else { - Gtexdraw.is_lit = GPU_scene_object_lights( - scene, ob, v3d->localvd ? v3d->localvd->lay : v3d->lay, - rv3d->viewmat, !rv3d->is_persp); - } - } - - rgba_float_to_uchar(obcol, ob->col); - - if (solidtex || v3d->drawtype == OB_TEXTURE) is_tex = true; - else is_tex = false; - - Gtexdraw.ob = ob; - Gtexdraw.stencil = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? imapaint->stencil : NULL; - Gtexdraw.is_texpaint = (ob->mode == OB_MODE_TEXTURE_PAINT); - Gtexdraw.texpaint_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL); - Gtexdraw.canvas = (Gtexdraw.texpaint_material) ? NULL : imapaint->canvas; - Gtexdraw.is_tex = is_tex; - - /* naughty multitexturing hacks to quickly support stencil + shading + alpha blending - * in new texpaint code. The better solution here would be to support GLSL */ - if (Gtexdraw.is_texpaint) { - glActiveTexture(GL_TEXTURE1); - glEnable(GL_TEXTURE_2D); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); - - /* load the stencil texture here */ - if (Gtexdraw.stencil != NULL) { - glActiveTexture(GL_TEXTURE2); - if (GPU_verify_image(Gtexdraw.stencil, NULL, GL_TEXTURE_2D, false, false, false, false)) { - float col[4] = {imapaint->stencil_col[0], imapaint->stencil_col[1], imapaint->stencil_col[2], 1.0f}; - glEnable(GL_TEXTURE_2D); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, col); - if ((imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) == 0) { - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_ONE_MINUS_SRC_COLOR); - } - else { - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); - } - } - } - glActiveTexture(GL_TEXTURE0); - } - - Gtexdraw.color_profile = BKE_scene_check_color_management_enabled(scene); - Gtexdraw.use_game_mat = (RE_engines_find(scene->r.engine)->flag & RE_GAME) != 0; - Gtexdraw.use_backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0; - Gtexdraw.two_sided_lighting = (me->flag & ME_TWOSIDED); - - memcpy(Gtexdraw.obcol, obcol, sizeof(obcol)); - set_draw_settings_cached(1, NULL, NULL, &Gtexdraw); - glCullFace(GL_BACK); -} - -static void draw_textured_end(void) -{ - if (Gtexdraw.ob->mode & OB_MODE_TEXTURE_PAINT) { - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glBindTexture(GL_TEXTURE_2D, 0); - - if (Gtexdraw.stencil != NULL) { - glActiveTexture(GL_TEXTURE2); - glDisable(GL_TEXTURE_2D); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glBindTexture(GL_TEXTURE_2D, 0); - } - glActiveTexture(GL_TEXTURE0); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - /* manual reset, since we don't use tpage */ - glBindTexture(GL_TEXTURE_2D, 0); - /* force switch off textures */ - GPU_clear_tpage(true); - } - else { - /* switch off textures */ - GPU_set_tpage(NULL, 0, 0); - } - - glDisable(GL_CULL_FACE); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - - /* XXX, bad patch - GPU_default_lights() calls - * glLightfv(GL_POSITION, ...) which - * is transformed by the current matrix... we - * need to make sure that matrix is identity. - * - * It would be better if drawmesh.c kept track - * of and restored the light settings it changed. - * - zr - */ - glPushMatrix(); - glLoadIdentity(); - GPU_default_lights(); - glPopMatrix(); -} - -static DMDrawOption draw_tface__set_draw_legacy(MTexPoly *mtexpoly, const bool has_mcol, int matnr) -{ - Material *ma = give_current_material(Gtexdraw.ob, matnr + 1); - bool invalidtexture = false; - - if (ma && (ma->game.flag & GEMAT_INVISIBLE)) - return DM_DRAW_OPTION_SKIP; - - invalidtexture = set_draw_settings_cached(0, mtexpoly, ma, &Gtexdraw); - - if (mtexpoly && invalidtexture) { - glColor3ub(0xFF, 0x00, 0xFF); - return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */ - } - else if (!has_mcol) { - if (mtexpoly) { - glColor3f(1.0, 1.0, 1.0); - } - else { - if (ma) { - if (ma->shade_flag & MA_OBCOLOR) { - glColor3ubv(Gtexdraw.obcol); - } - else { - float col[3]; - if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r); - else copy_v3_v3(col, &ma->r); - - glColor3fv(col); - } - } - else { - glColor3f(1.0, 1.0, 1.0); - } - } - return DM_DRAW_OPTION_NORMAL; /* normal drawing (no mcols anyway, no need to turn off) */ - } - else { - return DM_DRAW_OPTION_NORMAL; /* Set color from mcol */ - } -} - -static DMDrawOption draw_tface__set_draw(MTexPoly *mtexpoly, const bool UNUSED(has_mcol), int matnr) -{ - Material *ma = give_current_material(Gtexdraw.ob, matnr + 1); - - if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return DM_DRAW_OPTION_SKIP; - - if (mtexpoly || Gtexdraw.is_texpaint) - set_draw_settings_cached(0, mtexpoly, ma, &Gtexdraw); - - /* always use color from mcol, as set in update_tface_color_layer */ - return DM_DRAW_OPTION_NORMAL; -} - -static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol) -{ - const MPoly *mp = dm->getPolyArray(dm); - const int mpoly_num = dm->getNumPolys(dm); - MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY); - MLoopCol *finalCol; - int i, j; - MLoopCol *mloopcol = NULL; - - /* cache material values to avoid a lot of lookups */ - Material *ma = NULL; - short mat_nr_prev = -1; - enum { - COPY_CALC, - COPY_ORIG, - COPY_PREV, - } copy_mode = COPY_CALC; - - if (use_mcol) { - mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL); - if (!mloopcol) - mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL); - } - - if (CustomData_has_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL)) { - finalCol = CustomData_get_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL); - } - else { - finalCol = MEM_mallocN(sizeof(MLoopCol) * dm->numLoopData, "add_tface_color_layer"); - CustomData_add_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL, CD_ASSIGN, finalCol, dm->numLoopData); - } - - for (i = mpoly_num; i--; mp++) { - const short mat_nr = mp->mat_nr; - - if (UNLIKELY(mat_nr_prev != mat_nr)) { - ma = give_current_material(Gtexdraw.ob, mat_nr + 1); - copy_mode = COPY_CALC; - mat_nr_prev = mat_nr; - } - - /* avoid lookups */ - if (copy_mode == COPY_ORIG) { - memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop); - } - else if (copy_mode == COPY_PREV) { - int loop_index = mp->loopstart; - const MLoopCol *lcol_prev = &finalCol[(mp - 1)->loopstart]; - for (j = 0; j < mp->totloop; j++, loop_index++) { - finalCol[loop_index] = *lcol_prev; - } - } - - /* (copy_mode == COPY_CALC) */ - else if (ma && (ma->game.flag & GEMAT_INVISIBLE)) { - if (mloopcol) { - memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop); - copy_mode = COPY_ORIG; - } - else { - memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop); - copy_mode = COPY_PREV; - } - } - else if (mtexpoly && set_draw_settings_cached(0, mtexpoly, ma, &Gtexdraw)) { - int loop_index = mp->loopstart; - for (j = 0; j < mp->totloop; j++, loop_index++) { - finalCol[loop_index].r = 255; - finalCol[loop_index].g = 0; - finalCol[loop_index].b = 255; - finalCol[loop_index].a = 255; - } - copy_mode = COPY_PREV; - } - else if (ma && (ma->shade_flag & MA_OBCOLOR)) { - int loop_index = mp->loopstart; - for (j = 0; j < mp->totloop; j++, loop_index++) { - copy_v3_v3_uchar(&finalCol[loop_index].r, Gtexdraw.obcol); - finalCol[loop_index].a = 255; - } - copy_mode = COPY_PREV; - } - else { - if (mloopcol) { - memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop); - copy_mode = COPY_ORIG; - } - else if (mtexpoly) { - memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop); - copy_mode = COPY_PREV; - } - else { - float col[3]; - - if (ma) { - int loop_index = mp->loopstart; - MLoopCol lcol; - - if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r); - else copy_v3_v3(col, &ma->r); - rgb_float_to_uchar((unsigned char *)&lcol.r, col); - lcol.a = 255; - - for (j = 0; j < mp->totloop; j++, loop_index++) { - finalCol[loop_index] = lcol; - } - } - else { - memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop); - } - copy_mode = COPY_PREV; - } - } - } - - dm->dirty |= DM_DIRTY_MCOL_UPDATE_DRAW; -} - -static DMDrawOption draw_tface_mapped__set_draw(void *userData, int origindex, int UNUSED(mat_nr)) -{ - const Mesh *me = ((drawTFace_userData *)userData)->me; - - /* array checked for NULL before calling */ - MPoly *mpoly = &me->mpoly[origindex]; - - BLI_assert(origindex >= 0 && origindex < me->totpoly); - - if (mpoly->flag & ME_HIDE) { - return DM_DRAW_OPTION_SKIP; - } - else { - MTexPoly *tpoly = (me->mtpoly) ? &me->mtpoly[origindex] : NULL; - int matnr = mpoly->mat_nr; - - return draw_tface__set_draw(tpoly, (me->mloopcol != NULL), matnr); - } -} - -static DMDrawOption draw_em_tf_mapped__set_draw(void *userData, int origindex, int mat_nr) -{ - drawEMTFMapped_userData *data = userData; - BMEditMesh *em = data->em; - BMFace *efa; - - if (UNLIKELY(origindex >= em->bm->totface)) - return DM_DRAW_OPTION_NORMAL; - - efa = BM_face_at_index(em->bm, origindex); - - if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - return DM_DRAW_OPTION_SKIP; - } - else { - MTexPoly *mtexpoly = (data->cd_poly_tex_offset != -1) ? - BM_ELEM_CD_GET_VOID_P(efa, data->cd_poly_tex_offset) : NULL; - int matnr = (mat_nr != -1) ? mat_nr : efa->mat_nr; - - return draw_tface__set_draw_legacy(mtexpoly, data->has_mcol, matnr); - } -} - /* when face select is on, use face hidden flag */ static DMDrawOption wpaint__setSolidDrawOptions_facemask(void *userData, int index) { @@ -779,288 +209,6 @@ static DMDrawOption wpaint__setSolidDrawOptions_facemask(void *userData, int ind return DM_DRAW_OPTION_NORMAL; } -static void draw_mesh_text(Scene *scene, Object *ob, int glsl) -{ - Mesh *me = ob->data; - DerivedMesh *ddm; - MPoly *mp, *mface = me->mpoly; - MTexPoly *mtpoly = me->mtpoly; - MLoopUV *mloopuv = me->mloopuv; - MLoopUV *luv; - MLoopCol *mloopcol = me->mloopcol; /* why does mcol exist? */ - MLoopCol *lcol; - - bProperty *prop = BKE_bproperty_object_get(ob, "Text"); - GPUVertexAttribs gattribs; - int a, totpoly = me->totpoly; - - /* fake values to pass to GPU_render_text() */ - MCol tmp_mcol[4] = {{0}}; - MCol *tmp_mcol_pt = mloopcol ? tmp_mcol : NULL; - - /* don't draw without tfaces */ - if (!mtpoly || !mloopuv) - return; - - /* don't draw when editing */ - if (ob->mode & OB_MODE_EDIT) - return; - else if (ob == OBACT) - if (BKE_paint_select_elem_test(ob)) - return; - - ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); - - for (a = 0, mp = mface; a < totpoly; a++, mtpoly++, mp++) { - short matnr = mp->mat_nr; - const bool mf_smooth = (mp->flag & ME_SMOOTH) != 0; - Material *mat = (me->mat) ? me->mat[matnr] : NULL; - int mode = mat ? mat->game.flag : GEMAT_INVISIBLE; - - - if (!(mode & GEMAT_INVISIBLE) && (mode & GEMAT_TEXT) && mp->totloop >= 3) { - /* get the polygon as a tri/quad */ - int mp_vi[4]; - float v_quad_data[4][3]; - const float *v_quad[4]; - const float *uv_quad[4]; - char string[MAX_PROPSTRING]; - int characters, i, glattrib = -1, badtex = 0; - - - /* TEXFACE */ - if (glsl) { - GPU_object_material_bind(matnr + 1, &gattribs); - - for (i = 0; i < gattribs.totlayer; i++) { - if (gattribs.layer[i].type == CD_MTFACE) { - glattrib = gattribs.layer[i].glindex; - break; - } - } - } - else { - badtex = set_draw_settings_cached(0, mtpoly, mat, &Gtexdraw); - if (badtex) { - continue; - } - } - - mp_vi[0] = me->mloop[mp->loopstart + 0].v; - mp_vi[1] = me->mloop[mp->loopstart + 1].v; - mp_vi[2] = me->mloop[mp->loopstart + 2].v; - mp_vi[3] = (mp->totloop >= 4) ? me->mloop[mp->loopstart + 3].v : 0; - - /* UV */ - luv = &mloopuv[mp->loopstart]; - uv_quad[0] = luv->uv; luv++; - uv_quad[1] = luv->uv; luv++; - uv_quad[2] = luv->uv; luv++; - if (mp->totloop >= 4) { - uv_quad[3] = luv->uv; - } - else { - uv_quad[3] = NULL; - } - - - /* COLOR */ - if (mloopcol) { - unsigned int totloop_clamp = min_ii(4, mp->totloop); - unsigned int j; - lcol = &mloopcol[mp->loopstart]; - - for (j = 0; j < totloop_clamp; j++, lcol++) { - MESH_MLOOPCOL_TO_MCOL(lcol, &tmp_mcol[j]); - } - } - - /* LOCATION */ - ddm->getVertCo(ddm, mp_vi[0], v_quad_data[0]); - ddm->getVertCo(ddm, mp_vi[1], v_quad_data[1]); - ddm->getVertCo(ddm, mp_vi[2], v_quad_data[2]); - if (mp->totloop >= 4) { - ddm->getVertCo(ddm, mp_vi[3], v_quad_data[3]); - } - - v_quad[0] = v_quad_data[0]; - v_quad[1] = v_quad_data[1]; - v_quad[2] = v_quad_data[2]; - if (mp->totloop >= 4) { - v_quad[3] = v_quad_data[2]; - } - else { - v_quad[3] = NULL; - } - - - /* The BM_FONT handling is in the gpu module, shared with the - * game engine, was duplicated previously */ - - BKE_bproperty_set_valstr(prop, string); - characters = strlen(string); - - if (!BKE_image_has_ibuf(mtpoly->tpage, NULL)) - characters = 0; - - if (!mf_smooth) { - float nor[3]; - - normal_tri_v3(nor, v_quad[0], v_quad[1], v_quad[2]); - - glNormal3fv(nor); - } - - GPU_render_text( - mtpoly, mode, string, characters, - (unsigned int *)tmp_mcol_pt, - v_quad, uv_quad, - glattrib); - } - } - - ddm->release(ddm); -} - -static int compareDrawOptions(void *userData, int cur_index, int next_index) -{ - drawTFace_userData *data = userData; - - if (data->mpoly && data->mpoly[cur_index].mat_nr != data->mpoly[next_index].mat_nr) - return 0; - - if (data->mtexpoly && data->mtexpoly[cur_index].tpage != data->mtexpoly[next_index].tpage) - return 0; - - return 1; -} - - -static int compareDrawOptionsEm(void *userData, int cur_index, int next_index) -{ - drawEMTFMapped_userData *data = userData; - - if (data->mpoly && data->mpoly[cur_index].mat_nr != data->mpoly[next_index].mat_nr) - return 0; - - if (data->mtexpoly && data->mtexpoly[cur_index].tpage != data->mtexpoly[next_index].tpage) - return 0; - - return 1; -} - -static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d, - Object *ob, DerivedMesh *dm, const int draw_flags) -{ - Mesh *me = ob->data; - - /* correct for negative scale */ - if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW); - else glFrontFace(GL_CCW); - - /* draw the textured mesh */ - draw_textured_begin(scene, v3d, rv3d, ob); - - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - - if (ob->mode & OB_MODE_EDIT) { - drawEMTFMapped_userData data; - - data.em = me->edit_btmesh; - data.has_mcol = CustomData_has_layer(&me->edit_btmesh->bm->ldata, CD_MLOOPCOL); - data.cd_poly_tex_offset = CustomData_get_offset(&me->edit_btmesh->bm->pdata, CD_MTEXPOLY); - - data.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY); - data.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY); - - dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data, 0); - } - else { - DMDrawFlag dm_draw_flag; - drawTFace_userData userData; - - if (ob->mode & OB_MODE_TEXTURE_PAINT) { - dm_draw_flag = DM_DRAW_USE_TEXPAINT_UV; - } - else { - dm_draw_flag = DM_DRAW_USE_ACTIVE_UV; - } - - if (ob == OBACT) { - if (ob->mode & OB_MODE_WEIGHT_PAINT) { - dm_draw_flag |= DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH | DM_DRAW_SKIP_HIDDEN; - } - else if (ob->mode & OB_MODE_SCULPT) { - dm_draw_flag |= DM_DRAW_SKIP_HIDDEN | DM_DRAW_USE_COLORS; - } - else if ((ob->mode & OB_MODE_TEXTURE_PAINT) == 0) { - dm_draw_flag |= DM_DRAW_USE_COLORS; - } - } - else { - if ((ob->mode & OB_MODE_TEXTURE_PAINT) == 0) { - dm_draw_flag |= DM_DRAW_USE_COLORS; - } - } - - - userData.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY); - userData.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY); - - if (draw_flags & DRAW_FACE_SELECT) { - userData.me = me; - - dm->drawMappedFacesTex( - dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, compareDrawOptions, - &userData, dm_draw_flag); - } - else { - userData.me = NULL; - - /* if ((ob->mode & OB_MODE_ALL_PAINT) == 0) */ { - - /* Note: this isn't efficient and runs on every redraw, - * its needed so material colors are used for vertex colors. - * In the future we will likely remove 'texface' so, just avoid running this where possible, - * (when vertex paint or weight paint are used). - * - * Note 2: We disable optimization for now since it causes T48788 - * and it is now too close to release to do something smarter. - * - * TODO(sergey): Find some real solution here. - */ - - update_tface_color_layer(dm, !(ob->mode & OB_MODE_TEXTURE_PAINT)); - } - - dm->drawFacesTex( - dm, draw_tface__set_draw, compareDrawOptions, - &userData, dm_draw_flag); - } - } - - /* draw game engine text hack */ - if (rv3d->rflag & RV3D_IS_GAME_ENGINE) { - if (BKE_bproperty_object_get(ob, "Text")) { - draw_mesh_text(scene, ob, 0); - } - } - - draw_textured_end(); - - /* draw edges and selected faces over textured mesh */ - if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT)) { - bool draw_select_edges = (ob->mode & OB_MODE_TEXTURE_PAINT) == 0; - draw_mesh_face_select(rv3d, me, dm, draw_select_edges); - } - - /* reset from negative scale correction */ - glFrontFace(GL_CCW); - - /* in editmode, the blend mode needs to be set in case it was ADD */ - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -} - /************************** NEW SHADING NODES ********************************/ typedef struct TexMatCallback { @@ -1072,187 +220,11 @@ typedef struct TexMatCallback { bool two_sided_lighting; } TexMatCallback; -static void tex_mat_set_material_cb(void *UNUSED(userData), int mat_nr, void *attribs) -{ - /* all we have to do here is simply enable the GLSL material, but note - * that the GLSL code will give different result depending on the drawtype, - * in texture draw mode it will output the active texture node, in material - * draw mode it will show the full material. */ - GPU_object_material_bind(mat_nr, attribs); -} - -static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs) -{ - /* texture draw mode without GLSL */ - TexMatCallback *data = (TexMatCallback *)userData; - GPUVertexAttribs *gattribs = attribs; - Image *ima; - ImageUser *iuser; - bNode *node; - - /* draw image texture if we find one */ - if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node, NULL)) { - /* get openl texture */ - int mipmap = 1; - int bindcode = (ima) ? GPU_verify_image(ima, iuser, GL_TEXTURE_2D, 0, 0, mipmap, false) : 0; - - if (bindcode) { - NodeTexBase *texbase = node->storage; - - /* disable existing material */ - GPU_object_material_unbind(); - - /* bind texture */ - glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); - - glMatrixMode(GL_TEXTURE); - glLoadMatrixf(texbase->tex_mapping.mat); - glMatrixMode(GL_MODELVIEW); - - /* use active UV texture layer */ - memset(gattribs, 0, sizeof(*gattribs)); - - gattribs->layer[0].type = CD_MTFACE; - gattribs->layer[0].name[0] = '\0'; - gattribs->layer[0].gltexco = 1; - gattribs->totlayer = 1; - - /* bind material */ - float diffuse[3] = {1.0f, 1.0f, 1.0f}; - - int options = GPU_SHADER_TEXTURE_2D; - if (!data->shadeless) - options |= GPU_SHADER_LIGHTING; - if (data->two_sided_lighting) - options |= GPU_SHADER_TWO_SIDED; - - GPU_basic_shader_colors(diffuse, NULL, 0, 1.0f); - GPU_basic_shader_bind(options); - - return; - } - } - - /* disable texture material */ - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - - if (data->shadeless) { - glColor3f(1.0f, 1.0f, 1.0f); - memset(gattribs, 0, sizeof(*gattribs)); - } - else { - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - - /* enable solid material */ - GPU_object_material_bind(mat_nr, attribs); - } -} - -static bool tex_mat_set_face_mesh_cb(void *userData, int index) -{ - /* faceselect mode face hiding */ - TexMatCallback *data = (TexMatCallback *)userData; - Mesh *me = (Mesh *)data->me; - MPoly *mp = &me->mpoly[index]; - - return !(mp->flag & ME_HIDE); -} - -static bool tex_mat_set_face_editmesh_cb(void *userData, int index) -{ - /* editmode face hiding */ - TexMatCallback *data = (TexMatCallback *)userData; - Mesh *me = (Mesh *)data->me; - BMEditMesh *em = me->edit_btmesh; - BMFace *efa; - - if (UNLIKELY(index >= em->bm->totface)) - return DM_DRAW_OPTION_NORMAL; - - efa = BM_face_at_index(em->bm, index); - - return !BM_elem_flag_test(efa, BM_ELEM_HIDDEN); -} - -void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, +void draw_mesh_textured(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, const int draw_flags) { - /* if not cycles, or preview-modifiers, or drawing matcaps */ - if ((draw_flags & DRAW_MODIFIERS_PREVIEW) || - (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) || - (BKE_scene_use_new_shading_nodes(scene) == false) || - ((ob->mode & OB_MODE_TEXTURE_PAINT) && ELEM(v3d->drawtype, OB_TEXTURE, OB_SOLID))) - { - draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags); - return; - } - else if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) { - draw_mesh_paint(v3d, rv3d, ob, dm, draw_flags); - return; - } - - /* set opengl state for negative scale & color */ - if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW); - else glFrontFace(GL_CCW); - - Mesh *me = ob->data; - - bool shadeless = ((v3d->flag2 & V3D_SHADELESS_TEX) && - ((v3d->drawtype == OB_TEXTURE) || (ob->mode & OB_MODE_TEXTURE_PAINT))); - bool two_sided_lighting = (me->flag & ME_TWOSIDED) != 0; - - TexMatCallback data = {scene, ob, me, dm, shadeless, two_sided_lighting}; - bool (*set_face_cb)(void *, int); - bool picking = (G.f & G_PICKSEL) != 0; - - /* face hiding callback depending on mode */ - if (ob == scene->obedit) - set_face_cb = tex_mat_set_face_editmesh_cb; - else if (draw_flags & DRAW_FACE_SELECT) - set_face_cb = tex_mat_set_face_mesh_cb; - else - set_face_cb = NULL; - - /* test if we can use glsl */ - const int drawtype = view3d_effective_drawtype(v3d); - bool glsl = (drawtype == OB_MATERIAL) && !picking; - - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); - - if (glsl || picking) { - /* draw glsl or solid */ - dm->drawMappedFacesMat(dm, - tex_mat_set_material_cb, - set_face_cb, &data); - } - else { - /* draw textured */ - dm->drawMappedFacesMat(dm, - tex_mat_set_texture_cb, - set_face_cb, &data); - } - - GPU_end_object_materials(); - - /* reset opengl state */ - GPU_end_object_materials(); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - - glBindTexture(GL_TEXTURE_2D, 0); - - glFrontFace(GL_CCW); - - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - - /* faceselect mode drawing over textured mesh */ - if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT)) { - bool draw_select_edges = (ob->mode & OB_MODE_TEXTURE_PAINT) == 0; - draw_mesh_face_select(rv3d, ob->data, dm, draw_select_edges); - } + UNUSED_VARS(scene, sl, v3d, rv3d, ob, dm, draw_flags); + return; } /* Vertex Paint and Weight Paint */ @@ -1299,13 +271,6 @@ void draw_mesh_paint_vcolor_faces(DerivedMesh *dm, const bool use_light, flags |= DM_DRAW_NEED_NORMALS; } - /* Don't show alpha in wire mode. */ - const bool show_alpha = use_light; - if (show_alpha) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - if (me->mloopcol) { dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data, DM_DRAW_USE_COLORS | flags); @@ -1315,10 +280,6 @@ void draw_mesh_paint_vcolor_faces(DerivedMesh *dm, const bool use_light, dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data, flags); } - if (show_alpha) { - glDisable(GL_BLEND); - } - if (use_light) { draw_mesh_paint_light_end(); } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index d7e3b78cdc3..eaf699d8385 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -54,6 +54,7 @@ #include "BKE_camera.h" #include "BKE_colortools.h" #include "BKE_constraint.h" /* for the get_constraint_target function */ +#include "BKE_context.h" #include "BKE_curve.h" #include "BKE_DerivedMesh.h" #include "BKE_deform.h" @@ -62,6 +63,7 @@ #include "BKE_global.h" #include "BKE_image.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -80,6 +82,8 @@ #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" + #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -90,6 +94,10 @@ #include "GPU_select.h" #include "GPU_basic_shader.h" #include "GPU_shader.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_batch.h" +#include "GPU_matrix.h" #include "ED_mesh.h" #include "ED_particle.h" @@ -105,6 +113,13 @@ #include "view3d_intern.h" /* bad level include */ +#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */ + +/* prototypes */ +static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos); + +// #define USE_MESH_DM_SELECT + /* Workaround for sequencer scene render mode. * * Strips doesn't use DAG to update objects or so, which @@ -129,6 +144,7 @@ typedef struct drawDMVerts_userData { BMVert *eve_act; char sel; + unsigned int pos, color; /* cached theme values */ unsigned char th_editmesh_active[4]; @@ -181,6 +197,7 @@ typedef struct drawDMFacesSel_userData { } drawDMFacesSel_userData; typedef struct drawDMNormal_userData { + unsigned int pos; BMesh *bm; int uniform_scale; float normalsize; @@ -189,6 +206,7 @@ typedef struct drawDMNormal_userData { } drawDMNormal_userData; typedef struct drawMVertOffset_userData { + unsigned int pos, col; MVert *mvert; int offset; } drawMVertOffset_userData; @@ -196,9 +214,11 @@ typedef struct drawMVertOffset_userData { typedef struct drawDMLayer_userData { BMesh *bm; int cd_layer_offset; + unsigned int pos, col; } drawDMLayer_userData; typedef struct drawBMOffset_userData { + unsigned int pos, col; BMesh *bm; int offset; } drawBMOffset_userData; @@ -206,25 +226,23 @@ typedef struct drawBMOffset_userData { typedef struct drawBMSelect_userData { BMesh *bm; bool select; + unsigned int pos; } drawBMSelect_userData; -static void draw_bounding_volume(Object *ob, char type); -static void drawcube_size(float size); -static void drawcircle_size(float size); -static void draw_empty_sphere(float size); -static void draw_empty_cone(float size); -static void draw_box(const float vec[8][3], bool solid); +static void drawcube_size(float size, unsigned pos); +static void drawcircle_size(float size, unsigned pos); +static void draw_empty_sphere(float size, unsigned pos); +static void draw_empty_cone(float size, unsigned pos); -static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac) +static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac, float r_col[3]) { - float col_wire[3], col_bg[3], col[3]; + float col_wire[3], col_bg[3]; rgb_uchar_to_float(col_wire, ob_wire_col); UI_GetThemeColor3fv(theme_id, col_bg); - interp_v3_v3v3(col, col_bg, col_wire, fac); - glColor3fv(col); + interp_v3_v3v3(r_col, col_bg, col_wire, fac); } int view3d_effective_drawtype(const struct View3D *v3d) @@ -296,13 +314,13 @@ static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt) /* check for glsl drawing */ -bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) +bool draw_glsl_material(Scene *scene, SceneLayer *sl, Object *ob, View3D *v3d, const char dt) { if (G.f & G_PICKSEL) return false; if (!check_object_draw_texture(scene, v3d, dt)) return false; - if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT)) + if (ob == OBACT(sl) && (ob && ob->mode & OB_MODE_WEIGHT_PAINT)) return false; if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) @@ -318,7 +336,7 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) static bool check_alpha_pass(Base *base) { - if (base->flag & OB_FROMDUPLI) + if (base->flag_legacy & OB_FROMDUPLI) return false; if (G.f & G_PICKSEL) @@ -414,9 +432,9 @@ static const float cosval[CIRCLE_RESOL] = { * \param viewmat_local_unit is typically the 'rv3d->viewmatob' * copied into a 3x3 matrix and normalized. */ -static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3], float size, int axis) +static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3], float size, int axis, unsigned pos) { - int line_type; + Gwn_PrimType line_type = GWN_PRIM_LINES; float buffer[4][3]; int n = 0; @@ -429,8 +447,6 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3] switch (axis) { case 0: /* x axis */ - line_type = GL_LINES; - /* bottom left to top right */ negate_v3_v3(v1, dx); sub_v3_v3(v1, dy); @@ -450,8 +466,6 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3] break; case 1: /* y axis */ - line_type = GL_LINES; - /* bottom left to top right */ mul_v3_fl(dx, 0.75f); negate_v3_v3(v1, dx); @@ -472,7 +486,7 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3] break; case 2: /* z axis */ - line_type = GL_LINE_STRIP; + line_type = GWN_PRIM_LINE_STRIP; /* start at top left */ negate_v3_v3(v1, dx); @@ -501,54 +515,60 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3] return; } + immBegin(line_type, n); for (int i = 0; i < n; i++) { mul_transposed_m3_v3((float (*)[3])viewmat_local_unit, buffer[i]); add_v3_v3(buffer[i], c); + immVertex3fv(pos, buffer[i]); } + immEnd(); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, buffer); - glDrawArrays(line_type, 0, n); - glDisableClientState(GL_VERTEX_ARRAY); + /* TODO: recode this function for clarity once we're not in a hurry to modernize GL usage */ } -void drawaxes(const float viewmat_local[4][4], float size, char drawtype) +void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const unsigned char color[4]) { int axis; float v1[3] = {0.0, 0.0, 0.0}; float v2[3] = {0.0, 0.0, 0.0}; float v3[3] = {0.0, 0.0, 0.0}; - glLineWidth(1); + glLineWidth(1.0f); - switch (drawtype) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + if (color) { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4ubv(color); + } + else { + immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY); + } + switch (drawtype) { case OB_PLAINAXES: + immBegin(GWN_PRIM_LINES, 6); for (axis = 0; axis < 3; axis++) { - glBegin(GL_LINES); - v1[axis] = size; v2[axis] = -size; - glVertex3fv(v1); - glVertex3fv(v2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); /* reset v1 & v2 to zero */ v1[axis] = v2[axis] = 0.0f; - - glEnd(); } + immEnd(); break; - case OB_SINGLE_ARROW: - glBegin(GL_LINES); + case OB_SINGLE_ARROW: + immBegin(GWN_PRIM_LINES, 2); /* in positive z direction only */ v1[2] = size; - glVertex3fv(v1); - glVertex3fv(v2); - glEnd(); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + immEnd(); /* square pyramid */ - glBegin(GL_TRIANGLES); + immBegin(GWN_PRIM_TRIS, 12); v2[0] = size * 0.035f; v2[1] = size * 0.035f; v3[0] = size * -0.035f; v3[1] = size * 0.035f; @@ -564,28 +584,27 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype) v3[0] = -v3[0]; } - glVertex3fv(v1); - glVertex3fv(v2); - glVertex3fv(v3); - + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + immVertex3fv(pos, v3); } - glEnd(); - + immEnd(); break; + case OB_CUBE: - drawcube_size(size); + drawcube_size(size, pos); break; case OB_CIRCLE: - drawcircle_size(size); + drawcircle_size(size, pos); break; case OB_EMPTY_SPHERE: - draw_empty_sphere(size); + draw_empty_sphere(size, pos); break; case OB_EMPTY_CONE: - draw_empty_cone(size); + draw_empty_cone(size, pos); break; case OB_ARROWS: @@ -599,34 +618,34 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype) for (axis = 0; axis < 3; axis++) { const int arrow_axis = (axis == 0) ? 1 : 0; - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, 6); v2[axis] = size; - glVertex3fv(v1); - glVertex3fv(v2); - + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + v1[axis] = size * 0.85f; v1[arrow_axis] = -size * 0.08f; - glVertex3fv(v1); - glVertex3fv(v2); - + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + v1[arrow_axis] = size * 0.08f; - glVertex3fv(v1); - glVertex3fv(v2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); - glEnd(); - - v2[axis] += size * 0.125f; + immEnd(); - draw_xyz_wire(viewmat_local_unit, v2, size, axis); + v2[axis] += size * 0.125f; + draw_xyz_wire(viewmat_local_unit, v2, size, axis, pos); /* reset v1 & v2 to zero */ v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f; } - break; } } + + immUnbindProgram(); } @@ -634,38 +653,39 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype) static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4], eStereoViews sview) { Image *ima = ob->data; - ImBuf *ibuf; - ImageUser iuser = *ob->iuser; - /* Support multi-view */ - if (ima && (sview == STEREO_RIGHT_ID)) { - iuser.multiview_eye = sview; - iuser.flag |= IMA_SHOW_STEREO; - BKE_image_multiview_index(ima, &iuser); - } + const float ob_alpha = ob->col[3]; + float ima_x, ima_y; - ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); + int bindcode = 0; - if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) { - IMB_rect_from_float(ibuf); - } + if (ima) { + ImageUser iuser = *ob->iuser; + + /* Support multi-view */ + if (ima && (sview == STEREO_RIGHT_ID)) { + iuser.multiview_eye = sview; + iuser.flag |= IMA_SHOW_STEREO; + BKE_image_multiview_index(ima, &iuser); + } - int ima_x, ima_y; + if (ob_alpha > 0.0f) { + bindcode = GPU_verify_image(ima, &iuser, GL_TEXTURE_2D, 0, false, false, false); + /* don't bother drawing the image if alpha = 0 */ + } - /* Get the buffer dimensions so we can fallback to fake ones */ - if (ibuf && ibuf->rect) { - ima_x = ibuf->x; - ima_y = ibuf->y; + int w, h; + BKE_image_get_size(ima, &iuser, &w, &h); + ima_x = w; + ima_y = h; } else { - ima_x = 1; - ima_y = 1; + /* if no image, make it a 1x1 empty square, honor scale & offset */ + ima_x = ima_y = 1.0f; } - float sca_x = 1.0f; - float sca_y = 1.0f; - /* Get the image aspect even if the buffer is invalid */ + float sca_x = 1.0f, sca_y = 1.0f; if (ima) { if (ima->aspx > ima->aspy) { sca_y = ima->aspy / ima->aspx; @@ -675,61 +695,98 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char } } - /* Calculate the scale center based on object's origin */ - float ofs_x = ob->ima_ofs[0] * ima_x; - float ofs_y = ob->ima_ofs[1] * ima_y; + float scale_x; + float scale_y; + { + const float scale_x_inv = ima_x * sca_x; + const float scale_y_inv = ima_y * sca_y; + if (scale_x_inv > scale_y_inv) { + scale_x = ob->empty_drawsize; + scale_y = ob->empty_drawsize * (scale_y_inv / scale_x_inv); + } + else { + scale_x = ob->empty_drawsize * (scale_x_inv / scale_y_inv); + scale_y = ob->empty_drawsize; + } + } - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); + const float ofs_x = ob->ima_ofs[0] * scale_x; + const float ofs_y = ob->ima_ofs[1] * scale_y; - /* Calculate Image scale */ - float scale = ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y); + const rctf rect = { + .xmin = ofs_x, + .xmax = ofs_x + scale_x, + .ymin = ofs_y, + .ymax = ofs_y + scale_y, + }; - /* Set the object scale */ - glScalef(scale * sca_x, scale * sca_y, 1.0f); + bool use_blend = false; - if (ibuf && ibuf->rect) { - const bool use_clip = (U.glalphaclip != 1.0f); - int zoomfilter = (U.gameflags & USER_DISABLE_MIPMAP) ? GL_NEAREST : GL_LINEAR; - /* Setup GL params */ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (bindcode) { + use_blend = ob_alpha < 1.0f || BKE_image_has_alpha(ima); - if (use_clip) { - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, U.glalphaclip); + if (use_blend) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - /* Use the object color and alpha */ - glColor4fv(ob->col); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA); + immUniform1f("alpha", ob_alpha); + immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ - /* Draw the Image on the screen */ - glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_RGBA, GL_UNSIGNED_BYTE, zoomfilter, ibuf->rect); + immBegin(GWN_PRIM_TRI_FAN, 4); + immAttrib2f(texCoord, 0.0f, 0.0f); + immVertex2f(pos, rect.xmin, rect.ymin); - glDisable(GL_BLEND); + immAttrib2f(texCoord, 1.0f, 0.0f); + immVertex2f(pos, rect.xmax, rect.ymin); - if (use_clip) { - glDisable(GL_ALPHA_TEST); - glAlphaFunc(GL_ALWAYS, 0.0f); - } + immAttrib2f(texCoord, 1.0f, 1.0f); + immVertex2f(pos, rect.xmax, rect.ymax); + + immAttrib2f(texCoord, 0.0f, 1.0f); + immVertex2f(pos, rect.xmin, rect.ymax); + immEnd(); + + immUnbindProgram(); + + glBindTexture(GL_TEXTURE_2D, 0); /* necessary? */ } - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(ob_wire_col); + /* Draw the image outline */ + glLineWidth(1.5f); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + const bool picking = dflag & DRAW_CONSTCOLOR; + if (picking) { + /* TODO: deal with picking separately, use this function just to draw */ + immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY); + if (use_blend) { + glDisable(GL_BLEND); + } + + imm_draw_box_wire_2d(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); } + else { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(ob_wire_col); + glEnable(GL_LINE_SMOOTH); - /* Calculate the outline vertex positions */ - glBegin(GL_LINE_LOOP); - glVertex2f(ofs_x, ofs_y); - glVertex2f(ofs_x + ima_x, ofs_y); - glVertex2f(ofs_x + ima_x, ofs_y + ima_y); - glVertex2f(ofs_x, ofs_y + ima_y); - glEnd(); + if (!use_blend) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } - /* Reset GL settings */ - glPopMatrix(); + imm_draw_box_wire_2d(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - BKE_image_release_ibuf(ima, ibuf, NULL); + glDisable(GL_LINE_SMOOTH); + glDisable(GL_BLEND); + } + + immUnbindProgram(); } static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, const float tmat[4][4]) @@ -747,62 +804,65 @@ static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3 } } -void drawcircball(int mode, const float cent[3], float rad, const float tmat[4][4]) +void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos) { float verts[CIRCLE_RESOL][3]; circball_array_fill(verts, cent, rad, tmat); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, verts); - glDrawArrays(mode, 0, CIRCLE_RESOL); - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(GWN_PRIM_LINE_LOOP, CIRCLE_RESOL); + for (int i = 0; i < CIRCLE_RESOL; ++i) { + immVertex3fv(pos, verts[i]); + } + immEnd(); } /* circle for object centers, special_color is for library or ob users */ -static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, bool special_color) +static void drawcentercircle(View3D *v3d, RegionView3D *UNUSED(rv3d), const float co[3], int selstate, bool special_color) { - const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f; - float verts[CIRCLE_RESOL][3]; + const float outlineWidth = 1.0f * U.pixelsize; + const float size = U.obcenter_dia * U.pixelsize + outlineWidth; + + if (v3d->zbuf) { + glDisable(GL_DEPTH_TEST); + /* TODO(merwin): fit things like this into plates/buffers design */ + } - /* using glDepthFunc guarantees that it does write z values, - * but not checks for it, so centers remain visible independent of draw order */ - if (v3d->zbuf) glDepthFunc(GL_ALWAYS); - /* write to near buffer always */ - glDepthRange(0.0, 0.0); glEnable(GL_BLEND); - + GPU_enable_program_point_size(); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); + immUniform1f("size", size); + if (special_color) { - if (selstate == ACTIVE || selstate == SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155); - else glColor4ub(0x55, 0xCC, 0xCC, 155); + if (selstate == ACTIVE || selstate == SELECT) immUniformColor4ub(0x88, 0xFF, 0xFF, 155); + else immUniformColor4ub(0x55, 0xCC, 0xCC, 155); } else { - if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80); - else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80); - else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80); + if (selstate == ACTIVE) immUniformThemeColorShadeAlpha(TH_ACTIVE, 0, -80); + else if (selstate == SELECT) immUniformThemeColorShadeAlpha(TH_SELECT, 0, -80); + else if (selstate == DESELECT) immUniformThemeColorShadeAlpha(TH_TRANSFORM, 0, -80); } - circball_array_fill(verts, co, size, rv3d->viewinv); - - /* enable vertex array */ - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, verts); - - /* 1. draw filled, blended polygon */ - glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL); + /* set up outline */ + float outlineColor[4]; + UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, outlineColor); + immUniform4fv("outlineColor", outlineColor); + immUniform1f("outlineWidth", outlineWidth); - /* 2. draw outline */ - glLineWidth(1); - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30); - glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, co); + immEnd(); - /* finish up */ - glDisableClientState(GL_VERTEX_ARRAY); + immUnbindProgram(); - glDepthRange(0.0, 1.0); + GPU_disable_program_point_size(); glDisable(GL_BLEND); - if (v3d->zbuf) glDepthFunc(GL_LEQUAL); + if (v3d->zbuf) { + glEnable(GL_DEPTH_TEST); + } } /* *********** text drawing for object/particles/armature ************* */ @@ -893,36 +953,30 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write) if (tot) { int col_pack_prev = 0; -#if 0 - bglMats mats; /* ZBuffer depth vars */ - double ux, uy, uz; - float depth; - - if (v3d->zbuf) - bgl_get_mats(&mats); -#endif if (rv3d->rflag & RV3D_CLIPPING) { ED_view3d_clipping_disable(); } - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); + float original_proj[4][4]; + gpuGetProjectionMatrix(original_proj); wmOrtho2_region_pixelspace(ar); - glLoadIdentity(); + + gpuPushMatrix(); + gpuLoadIdentity(); if (depth_write) { if (v3d->zbuf) glDisable(GL_DEPTH_TEST); } else { - glDepthMask(0); + glDepthMask(GL_FALSE); } + const int font_id = BLF_default(); + for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) { if (vos->sco[0] != IS_CLIPPED) { if (col_pack_prev != vos->col.pack) { - glColor3ubv(vos->col.ub); + BLF_color3ubv(font_id, vos->col.ub); col_pack_prev = vos->col.pack; } @@ -941,13 +995,11 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write) if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } else { - glDepthMask(1); + glDepthMask(GL_TRUE); } - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + gpuPopMatrix(); + gpuLoadProjectionMatrix(original_proj); if (rv3d->rflag & RV3D_CLIPPING) { ED_view3d_clipping_enable(); @@ -971,9 +1023,9 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write) /* draws a cube given the scaling of the cube, assuming that * all required matrices have been set (used for drawing empties) */ -static void drawcube_size(float size) +static void drawcube_size(float size, unsigned pos) { - const GLfloat pos[8][3] = { + const float verts[8][3] = { {-size, -size, -size}, {-size, -size, size}, {-size, size, -size}, @@ -986,13 +1038,21 @@ static void drawcube_size(float size) const GLubyte indices[24] = {0,1,1,3,3,2,2,0,0,4,4,5,5,7,7,6,6,4,1,5,3,7,2,6}; +#if 0 glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, pos); + glVertexPointer(3, GL_FLOAT, 0, verts); glDrawRangeElements(GL_LINES, 0, 7, 24, GL_UNSIGNED_BYTE, indices); glDisableClientState(GL_VERTEX_ARRAY); +#else + immBegin(GWN_PRIM_LINES, 24); + for (int i = 0; i < 24; ++i) { + immVertex3fv(pos, verts[indices[i]]); + } + immEnd(); +#endif } -static void drawshadbuflimits(Lamp *la, float mat[4][4]) +static void drawshadbuflimits(const Lamp *la, const float mat[4][4], unsigned pos) { float sta[3], end[3], lavec[3]; @@ -1002,16 +1062,16 @@ static void drawshadbuflimits(Lamp *la, float mat[4][4]) madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta); madd_v3_v3v3fl(end, mat[3], lavec, la->clipend); - glBegin(GL_LINES); - glVertex3fv(sta); - glVertex3fv(end); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, sta); + immVertex3fv(pos, end); + immEnd(); - glPointSize(3.0); - glBegin(GL_POINTS); - glVertex3fv(sta); - glVertex3fv(end); - glEnd(); + glPointSize(3.0f); + immBegin(GWN_PRIM_POINTS, 2); + immVertex3fv(pos, sta); + immVertex3fv(pos, end); + immEnd(); } static void spotvolume(float lvec[3], float vvec[3], const float inp) @@ -1077,62 +1137,63 @@ static void spotvolume(float lvec[3], float vvec[3], const float inp) mul_m3_v3(mat2, vvec); } -static void draw_spot_cone(Lamp *la, float x, float z) +static void draw_spot_cone(Lamp *la, float x, float z, unsigned pos) { z = fabsf(z); - glBegin(GL_TRIANGLE_FAN); - glVertex3f(0.0f, 0.0f, -x); + const bool square = (la->mode & LA_SQUARE); + + immBegin(GWN_PRIM_TRI_FAN, square ? 6 : 34); + immVertex3f(pos, 0.0f, 0.0f, -x); - if (la->mode & LA_SQUARE) { - glVertex3f(z, z, 0); - glVertex3f(-z, z, 0); - glVertex3f(-z, -z, 0); - glVertex3f(z, -z, 0); - glVertex3f(z, z, 0); + if (square) { + immVertex3f(pos, z, z, 0); + immVertex3f(pos, -z, z, 0); + immVertex3f(pos, -z, -z, 0); + immVertex3f(pos, z, -z, 0); + immVertex3f(pos, z, z, 0); } else { for (int a = 0; a < 33; a++) { float angle = a * M_PI * 2 / (33 - 1); - glVertex3f(z * cosf(angle), z * sinf(angle), 0); + immVertex3f(pos, z * cosf(angle), z * sinf(angle), 0.0f); } } - glEnd(); + immEnd(); } -static void draw_transp_spot_volume(Lamp *la, float x, float z) +static void draw_transp_spot_volume(Lamp *la, float x, float z, unsigned pos) { glEnable(GL_CULL_FACE); glEnable(GL_BLEND); - glDepthMask(0); + glDepthMask(GL_FALSE); /* draw backside darkening */ glCullFace(GL_FRONT); glBlendFunc(GL_ZERO, GL_SRC_ALPHA); - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); - draw_spot_cone(la, x, z); + draw_spot_cone(la, x, z, pos); /* draw front side lighting */ glCullFace(GL_BACK); glBlendFunc(GL_ONE, GL_ONE); - glColor4f(0.2f, 0.2f, 0.2f, 1.0f); + immUniformColor3f(0.2f, 0.2f, 0.2f); - draw_spot_cone(la, x, z); + draw_spot_cone(la, x, z, pos); /* restore state */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); - glDepthMask(1); + glDepthMask(GL_TRUE); glDisable(GL_CULL_FACE); - glCullFace(GL_BACK); } #ifdef WITH_GAMEENGINE -static void draw_transp_sun_volume(Lamp *la) +static void draw_transp_sun_volume(Lamp *la, unsigned pos) { float box[8][3]; @@ -1145,50 +1206,46 @@ static void draw_transp_sun_volume(Lamp *la) box[1][2] = box[2][2] = box[5][2] = box[6][2] = -la->clipsta; /* draw edges */ - draw_box(box, false); + imm_draw_box(box, false, pos); /* draw faces */ glEnable(GL_CULL_FACE); glEnable(GL_BLEND); - glDepthMask(0); + glDepthMask(GL_FALSE); /* draw backside darkening */ glCullFace(GL_FRONT); glBlendFunc(GL_ZERO, GL_SRC_ALPHA); - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); - draw_box(box, true); + imm_draw_box(box, true, pos); /* draw front side lighting */ glCullFace(GL_BACK); glBlendFunc(GL_ONE, GL_ONE); - glColor4f(0.2f, 0.2f, 0.2f, 1.0f); + immUniformColor3f(0.2f, 0.2f, 0.2f); - draw_box(box, true); + imm_draw_box(box, true, pos); /* restore state */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); - glDepthMask(1); + glDepthMask(GL_TRUE); glDisable(GL_CULL_FACE); - glCullFace(GL_BACK); } #endif -static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, - const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact) +void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact) { Object *ob = base->object; const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]); Lamp *la = ob->data; float vec[3], lvec[3], vvec[3], circrad; - float lampsize; float imat[4][4]; - unsigned char curcol[4]; - unsigned char col[4]; /* cone can't be drawn for duplicated lamps, because duplilist would be freed */ /* the moment of view3d_draw_transp() call */ const bool is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object); @@ -1196,7 +1253,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, !(G.f & G_PICKSEL) && (la->type == LA_SPOT) && (la->mode & LA_SHOW_CONE) && - !(base->flag & OB_FROMDUPLI) && + !(base->flag_legacy & OB_FROMDUPLI) && !is_view); #ifdef WITH_GAMEENGINE @@ -1208,7 +1265,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, ((la->mode & LA_SHAD_BUF) || (la->mode & LA_SHAD_RAY)) && (la->mode & LA_SHOW_SHADOW_BOX) && - !(base->flag & OB_FROMDUPLI) && + !(base->flag_legacy & OB_FROMDUPLI) && !is_view); #else const bool drawshadowbox = false; @@ -1216,118 +1273,159 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, if ((drawcone || drawshadowbox) && !v3d->transp) { /* in this case we need to draw delayed */ - ED_view3d_after_add(v3d->xray ? &v3d->afterdraw_xraytransp : &v3d->afterdraw_transp, base, dflag); + ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag); return; } - + /* we first draw only the screen aligned & fixed scale stuff */ - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); + gpuPushMatrix(); + gpuLoadMatrix(rv3d->viewmat); /* lets calculate the scale: */ - lampsize = pixsize * ((float)U.obcenter_dia * 0.5f); + const float lampsize_px = U.obcenter_dia; + const float lampsize = pixsize * lampsize_px * 0.5f; /* and view aligned matrix: */ copy_m4_m4(imat, rv3d->viewinv); normalize_v3(imat[0]); normalize_v3(imat[1]); + const unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + /* lamp center */ copy_v3_v3(vec, ob->obmat[3]); + float curcol[4]; if ((dflag & DRAW_CONSTCOLOR) == 0) { /* for AA effects */ - curcol[0] = ob_wire_col[0]; - curcol[1] = ob_wire_col[1]; - curcol[2] = ob_wire_col[2]; - curcol[3] = 154; - glColor4ubv(curcol); + rgb_uchar_to_float(curcol, ob_wire_col); + curcol[3] = 0.6f; + /* TODO: pay attention to GL_BLEND */ } - glLineWidth(1); + glLineWidth(1.0f); + setlinestyle(3); if (lampsize > 0.0f) { + const float outlineWidth = 1.5f * U.pixelsize; + const float lampdot_size = lampsize_px * U.pixelsize + outlineWidth; + /* Inner Circle */ if ((dflag & DRAW_CONSTCOLOR) == 0) { + const float *color = curcol; if (ob->id.us > 1) { - if (is_obact || (ob->flag & SELECT)) { - glColor4ub(0x88, 0xFF, 0xFF, 155); + if (is_obact || ((base->flag & BASE_SELECTED) != 0)) { + static const float active_color[4] = {0.533f, 1.0f, 1.0f, 1.0f}; + color = active_color; } else { - glColor4ub(0x77, 0xCC, 0xCC, 155); + static const float inactive_color[4] = {0.467f, 0.8f, 0.8f, 1.0f}; + color = inactive_color; } } + + GPU_enable_program_point_size(); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); + immUniform1f("size", lampdot_size); + immUniform1f("outlineWidth", outlineWidth); + immUniformColor3fvAlpha(color, 0.3f); + immUniform4fv("outlineColor", color); + + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, vec); + immEnd(); + + immUnbindProgram(); + + glDisable(GL_BLEND); + GPU_disable_program_point_size(); } - - /* Inner Circle */ - glEnable(GL_BLEND); - drawcircball(GL_LINE_LOOP, vec, lampsize, imat); - glDisable(GL_BLEND); - drawcircball(GL_POLYGON, vec, lampsize, imat); - + else { + /* CONSTCOLOR in effect */ + /* TODO: separate picking from drawing */ + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR); + /* color doesn't matter, so don't set */ + glPointSize(lampdot_size); + + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, vec); + immEnd(); + + immUnbindProgram(); + } + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + /* TODO(merwin): short term, use DEPTH_ONLY for picking + * long term, separate picking from drawing + */ + /* restore */ if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (ob->id.us > 1) - glColor4ubv(curcol); + immUniformColor4fv(curcol); } /* Outer circle */ circrad = 3.0f * lampsize; - setlinestyle(3); - drawcircball(GL_LINE_LOOP, vec, circrad, imat); + imm_drawcircball(vec, circrad, imat, pos); /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */ if (la->type != LA_HEMI) { if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) { - drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f * pixsize, imat); + imm_drawcircball(vec, circrad + 3.0f * pixsize, imat, pos); } } } else { - setlinestyle(3); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if ((dflag & DRAW_CONSTCOLOR) == 0) { + immUniformColor4fv(curcol); + } circrad = 0.0f; } - + /* draw the pretty sun rays */ if (la->type == LA_SUN) { float v1[3], v2[3], mat[3][3]; short axis; - + /* setup a 45 degree rotation matrix */ axis_angle_normalized_to_mat3_ex(mat, imat[2], M_SQRT1_2, M_SQRT1_2); /* vectors */ mul_v3_v3fl(v1, imat[0], circrad * 1.2f); mul_v3_v3fl(v2, imat[0], circrad * 2.5f); - + /* center */ - glTranslate3fv(vec); - + gpuPushMatrix(); + gpuTranslate3fv(vec); + setlinestyle(3); - - glBegin(GL_LINES); + + immBegin(GWN_PRIM_LINES, 16); for (axis = 0; axis < 8; axis++) { - glVertex3fv(v1); - glVertex3fv(v2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); mul_m3_v3(mat, v1); mul_m3_v3(mat, v2); } - glEnd(); - - glTranslatef(-vec[0], -vec[1], -vec[2]); + immEnd(); + gpuPopMatrix(); } - + if (la->type == LA_LOCAL) { if (la->mode & LA_SPHERE) { - drawcircball(GL_LINE_LOOP, vec, la->dist, imat); + imm_drawcircball(vec, la->dist, imat, pos); } } - - glPopMatrix(); /* back in object space */ + + gpuPopMatrix(); /* back in object space */ zero_v3(vec); - + if (is_view) { /* skip drawing extra info */ } @@ -1359,24 +1457,18 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, {z_abs, -z_abs, x}, {-z_abs, z_abs, x}, }; - const unsigned char indices[] = { - 0, 1, 3, - 0, 3, 2, - 0, 2, 4, - 0, 1, 4, - }; - /* Draw call: - * activate and specify pointer to vertex array */ - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vertices); - /* draw the pyramid */ - glDrawElements(GL_LINE_STRIP, 12, GL_UNSIGNED_BYTE, indices); - - /* deactivate vertex arrays after drawing */ - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(GWN_PRIM_LINES, 16); + for (int i = 1; i <= 4; ++i) { + immVertex3fv(pos, vertices[0]); /* apex to corner */ + immVertex3fv(pos, vertices[i]); + int next_i = (i == 4) ? 1 : (i + 1); + immVertex3fv(pos, vertices[i]); /* corner to next corner */ + immVertex3fv(pos, vertices[next_i]); + } + immEnd(); - glTranslatef(0.0f, 0.0f, x); + gpuTranslate3f(0.0f, 0.0f, x); /* draw the square representing spotbl */ if (la->type == LA_SPOT) { @@ -1386,22 +1478,21 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, * previously it adjusted to always to show it but that seems * confusing because it doesn't show the actual blend size */ if (blend != 0.0f && blend != z_abs) { - fdrawbox(blend, -blend, -blend, blend); + imm_draw_box_wire_3d(pos, blend, -blend, -blend, blend); } } } else { - /* draw the angled sides of the cone */ - glBegin(GL_LINE_STRIP); - glVertex3fv(vvec); - glVertex3fv(vec); - glVertex3fv(lvec); - glEnd(); + immBegin(GWN_PRIM_LINE_STRIP, 3); + immVertex3fv(pos, vvec); + immVertex3fv(pos, vec); + immVertex3fv(pos, lvec); + immEnd(); /* draw the circle at the end of the cone */ - glTranslatef(0.0f, 0.0f, x); - circ(0.0f, 0.0f, z_abs); + gpuTranslate3f(0.0f, 0.0f, x); + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, z_abs, 32); /* draw the circle representing spotbl */ if (la->type == LA_SPOT) { @@ -1411,17 +1502,17 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, * previously it adjusted to always to show it but that seems * confusing because it doesn't show the actual blend size */ if (blend != 0.0f && blend != z_abs) { - circ(0.0f, 0.0f, blend); + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, blend, 32); } } } if (drawcone) - draw_transp_spot_volume(la, x, z); + draw_transp_spot_volume(la, x, z, pos); /* draw clip start, useful for wide cones where its not obvious where the start is */ - glTranslatef(0.0, 0.0, -x); /* reverse translation above */ - glBegin(GL_LINES); + gpuTranslate3f(0.0f, 0.0f, -x); /* reverse translation above */ + immBegin(GWN_PRIM_LINES, 2); if (la->type == LA_SPOT && (la->mode & LA_SHAD_BUF)) { float lvec_clip[3]; float vvec_clip[3]; @@ -1430,41 +1521,40 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac); interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac); - glVertex3fv(lvec_clip); - glVertex3fv(vvec_clip); + immVertex3fv(pos, lvec_clip); + immVertex3fv(pos, vvec_clip); } /* Else, draw spot direction (using distance as end limit, same as for Area lamp). */ else { - glVertex3f(0.0, 0.0, -circrad); - glVertex3f(0.0, 0.0, -la->dist); + immVertex3f(pos, 0.0f, 0.0f, -circrad); + immVertex3f(pos, 0.0f, 0.0f, -la->dist); } - glEnd(); + immEnd(); } else if (ELEM(la->type, LA_HEMI, LA_SUN)) { - /* draw the line from the circle along the dist */ - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, 2); vec[2] = -circrad; - glVertex3fv(vec); + immVertex3fv(pos, vec); vec[2] = -la->dist; - glVertex3fv(vec); - glEnd(); - + immVertex3fv(pos, vec); + immEnd(); + if (la->type == LA_HEMI) { /* draw the hemisphere curves */ short axis, steps, dir; float outdist, zdist, mul; zero_v3(vec); - outdist = 0.14; mul = 1.4; dir = 1; - + outdist = 0.14f; mul = 1.4f; dir = 1; + setlinestyle(4); /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */ for (axis = 0; axis < 4; axis++) { - float v[3] = {0.0, 0.0, 0.0}; - zdist = 0.02; - - glBegin(GL_LINE_STRIP); - + float v[3] = {0.0f, 0.0f, 0.0f}; + zdist = 0.02f; + + immBegin(GWN_PRIM_LINE_STRIP, 6); + for (steps = 0; steps < 6; steps++) { if (axis == 0 || axis == 1) { /* x axis up, x axis down */ /* make the arcs start at the edge of the energy circle */ @@ -1477,13 +1567,13 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, } v[2] = v[2] - steps * zdist; - - glVertex3fv(v); - + + immVertex3fv(pos, v); + zdist = zdist * mul; } - - glEnd(); + + immEnd(); /* flip the direction */ dir = -dir; } @@ -1491,96 +1581,92 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, #ifdef WITH_GAMEENGINE if (drawshadowbox) { - draw_transp_sun_volume(la); + draw_transp_sun_volume(la, pos); } #endif - } else if (la->type == LA_AREA) { setlinestyle(3); if (la->area_shape == LA_AREA_SQUARE) - fdrawbox(-la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f); + imm_draw_box_wire_3d(pos, -la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f); else if (la->area_shape == LA_AREA_RECT) - fdrawbox(-la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f); + imm_draw_box_wire_3d(pos, -la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f); - glBegin(GL_LINES); - glVertex3f(0.0, 0.0, -circrad); - glVertex3f(0.0, 0.0, -la->dist); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 0.0f, -circrad); + immVertex3f(pos, 0.0f, 0.0f, -la->dist); + immEnd(); } - + /* and back to viewspace */ - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); + gpuPushMatrix(); + gpuLoadMatrix(rv3d->viewmat); copy_v3_v3(vec, ob->obmat[3]); setlinestyle(0); - + if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == false)) { - drawshadbuflimits(la, ob->obmat); + drawshadbuflimits(la, ob->obmat, pos); } - + if ((dflag & DRAW_CONSTCOLOR) == 0) { - UI_GetThemeColor4ubv(TH_LAMP, col); - glColor4ubv(col); + immUniformThemeColor(TH_LAMP); } glEnable(GL_BLEND); - + if (vec[2] > 0) vec[2] -= circrad; else vec[2] += circrad; - - glBegin(GL_LINES); - glVertex3fv(vec); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, vec); vec[2] = 0; - glVertex3fv(vec); - glEnd(); - - glPointSize(2.0); - glBegin(GL_POINTS); - glVertex3fv(vec); - glEnd(); - + immVertex3fv(pos, vec); + immEnd(); + + glPointSize(2.0f); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, vec); + immEnd(); + glDisable(GL_BLEND); - - if ((dflag & DRAW_CONSTCOLOR) == 0) { - /* restore for drawing extra stuff */ - glColor3ubv(ob_wire_col); - } - /* and finally back to org object space! */ - glPopMatrix(); + + immUnbindProgram(); + gpuPopMatrix(); } -static void draw_limit_line(float sta, float end, const short dflag, const unsigned char col[3]) +static void draw_limit_line(float sta, float end, const short dflag, const unsigned char col[3], unsigned pos) { - glBegin(GL_LINES); - glVertex3f(0.0, 0.0, -sta); - glVertex3f(0.0, 0.0, -end); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 0.0f, -sta); + immVertex3f(pos, 0.0f, 0.0f, -end); + immEnd(); if (!(dflag & DRAW_PICKING)) { - glPointSize(3.0); - glBegin(GL_POINTS); + glPointSize(3.0f); + /* would like smooth round points here, but that means binding another shader... + * if it's really desired, pull these points into their own function to be called after */ + immBegin(GWN_PRIM_POINTS, 2); if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(col); + immUniformColor3ubv(col); } - glVertex3f(0.0, 0.0, -sta); - glVertex3f(0.0, 0.0, -end); - glEnd(); + immVertex3f(pos, 0.0f, 0.0f, -sta); + immVertex3f(pos, 0.0f, 0.0f, -end); + immEnd(); } } /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */ /* qdn: now also enabled for Blender to set focus point for defocus composite node */ -static void draw_focus_cross(float dist, float size) +static void draw_focus_cross(float dist, float size, unsigned pos) { - glBegin(GL_LINES); - glVertex3f(-size, 0.0f, -dist); - glVertex3f(size, 0.0f, -dist); - glVertex3f(0.0f, -size, -dist); - glVertex3f(0.0f, size, -dist); - glEnd(); + immBegin(GWN_PRIM_LINES, 4); + immVertex3f(pos, -size, 0.0f, -dist); + immVertex3f(pos, size, 0.0f, -dist); + immVertex3f(pos, 0.0f, -size, -dist); + immVertex3f(pos, 0.0f, size, -dist); + immEnd(); } #ifdef VIEW3D_CAMERA_BORDER_HACK @@ -1590,26 +1676,6 @@ bool view3d_camera_border_hack_test = false; /* ****************** draw clip data *************** */ -static void draw_bundle_sphere(void) -{ - static GLuint displist = 0; - - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_FILL); - gluSphere(qobj, 0.05, 8, 8); - gluDeleteQuadric(qobj); - - glEndList(); - } - - glCallList(displist); -} - static void draw_viewport_object_reconstruction( Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip, MovieTrackingObject *tracking_object, @@ -1635,7 +1701,7 @@ static void draw_viewport_object_reconstruction( if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) mul_v3_fl(camera_size, tracking_object->scale); - glPushMatrix(); + gpuPushMatrix(); if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { /* current ogl matrix is translated in camera space, bundles should @@ -1643,8 +1709,8 @@ static void draw_viewport_object_reconstruction( * from current ogl matrix */ invert_m4_m4(imat, base->object->obmat); - glMultMatrixf(imat); - glMultMatrixf(mat); + gpuMultMatrix(imat); + gpuMultMatrix(mat); } else { float obmat[4][4]; @@ -1653,7 +1719,7 @@ static void draw_viewport_object_reconstruction( BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, obmat); invert_m4_m4(imat, obmat); - glMultMatrixf(imat); + gpuMultMatrix(imat); } for (track = tracksbase->first; track; track = track->next) { @@ -1666,66 +1732,93 @@ static void draw_viewport_object_reconstruction( continue; if (dflag & DRAW_PICKING) - GPU_select_load_id(base->selcol + (tracknr << 16)); + GPU_select_load_id(base->object->select_color + (tracknr << 16)); - glPushMatrix(); - glTranslate3fv(track->bundle_pos); - glScalef(v3d->bundle_size / 0.05f / camera_size[0], - v3d->bundle_size / 0.05f / camera_size[1], - v3d->bundle_size / 0.05f / camera_size[2]); + gpuPushMatrix(); + gpuTranslate3fv(track->bundle_pos); + gpuScale3f(v3d->bundle_size / 0.05f / camera_size[0], + v3d->bundle_size / 0.05f / camera_size[1], + v3d->bundle_size / 0.05f / camera_size[2]); const int v3d_drawtype = view3d_effective_drawtype(v3d); if (v3d_drawtype == OB_WIRE) { + unsigned char color[4]; + const unsigned char *color_ptr = NULL; if ((dflag & DRAW_CONSTCOLOR) == 0) { if (selected && (track->flag & TRACK_CUSTOMCOLOR) == 0) { - glColor3ubv(ob_wire_col); + color_ptr = ob_wire_col; } else { - glColor3fv(track->color); + rgba_float_to_uchar(color, track->color); + color_ptr = color; } } - drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype); + drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype, color_ptr); } else if (v3d_drawtype > OB_WIRE) { if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) { + Gwn_Batch *batch; + + gpuScaleUniform(0.05f); + /* selection outline */ if (selected) { + batch = GPU_batch_preset_sphere_wire(1); + if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(ob_wire_col); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + GWN_batch_uniform_4f(batch, "color", + ob_wire_col[0] / 255.f, + ob_wire_col[1] / 255.f, + ob_wire_col[2] / 255.f, 1.0f); + } + else { + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_DEPTH_ONLY); } - glLineWidth(2.0f); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - draw_bundle_sphere(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + GWN_batch_draw(batch); } + batch = GPU_batch_preset_sphere(0); + if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color); - else UI_ThemeColor(TH_BUNDLE_SOLID); + const float light[3] = {0.0f, 0.0f, 1.0f}; + float col[3]; + GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_3fv(batch, "light", light); + + if (track->flag & TRACK_CUSTOMCOLOR) copy_v3_v3(col, track->color); + else UI_GetThemeColor3fv(TH_BUNDLE_SOLID, col); + GWN_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f); + } + else { + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_DEPTH_ONLY); } - draw_bundle_sphere(); + GWN_batch_draw(batch); } else { + unsigned char color[4]; + const unsigned char *color_ptr = NULL; if ((dflag & DRAW_CONSTCOLOR) == 0) { if (selected) { - glColor3ubv(ob_wire_col); + color_ptr = ob_wire_col; } else { - if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color); - else UI_ThemeColor(TH_WIRE); + if (track->flag & TRACK_CUSTOMCOLOR) rgba_float_to_uchar(color, track->color); + else UI_GetThemeColor4ubv(TH_WIRE, color); + + color_ptr = color; } } - drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype); + drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype, color_ptr); } } - glPopMatrix(); + gpuPopMatrix(); if ((dflag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) { float pos[3]; @@ -1745,22 +1838,27 @@ static void draw_viewport_object_reconstruction( MovieTrackingReconstruction *reconstruction; reconstruction = BKE_tracking_object_get_reconstruction(tracking, tracking_object); - if (reconstruction->camnr) { + if (reconstruction->camnr >= 2) { MovieReconstructedCamera *camera = reconstruction->cameras; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_CAMERA_PATH); - UI_ThemeColor(TH_CAMERA_PATH); glLineWidth(2.0f); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, reconstruction->camnr); for (int a = 0; a < reconstruction->camnr; a++, camera++) { - glVertex3fv(camera->mat[3]); + immVertex3fv(pos, camera->mat[3]); } - glEnd(); + immEnd(); + + immUnbindProgram(); } } } - glPopMatrix(); + gpuPopMatrix(); *global_track_index = tracknr; } @@ -1795,67 +1893,65 @@ static void draw_viewport_reconstruction( /* restore */ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(ob_wire_col); - } - if (dflag & DRAW_PICKING) - GPU_select_load_id(base->selcol); + GPU_select_load_id(base->object->select_color); } -static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], const GLenum mode) +/* camera frame */ +static void drawcamera_frame(float vec[4][3], bool filled, unsigned pos) { - glBegin(mode); - glVertex3fv(near_plane[0]); - glVertex3fv(far_plane[0]); - glVertex3fv(far_plane[1]); - glVertex3fv(near_plane[1]); - glEnd(); - - glBegin(mode); - glVertex3fv(near_plane[1]); - glVertex3fv(far_plane[1]); - glVertex3fv(far_plane[2]); - glVertex3fv(near_plane[2]); - glEnd(); - - glBegin(mode); - glVertex3fv(near_plane[2]); - glVertex3fv(far_plane[2]); - glVertex3fv(far_plane[3]); - glVertex3fv(near_plane[3]); - glEnd(); - - glBegin(mode); - glVertex3fv(far_plane[3]); - glVertex3fv(near_plane[3]); - glVertex3fv(near_plane[0]); - glVertex3fv(far_plane[0]); - glEnd(); + immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, 4); + immVertex3fv(pos, vec[0]); + immVertex3fv(pos, vec[1]); + immVertex3fv(pos, vec[2]); + immVertex3fv(pos, vec[3]); + immEnd(); } -/* camera frame */ -static void drawcamera_frame(float vec[4][3], const GLenum mode) +/* center point to camera frame */ +static void drawcamera_framelines(float vec[4][3], float origin[3], unsigned pos) { - glBegin(mode); - glVertex3fv(vec[0]); - glVertex3fv(vec[1]); - glVertex3fv(vec[2]); - glVertex3fv(vec[3]); - glEnd(); + immBegin(GWN_PRIM_LINES, 8); + immVertex3fv(pos, origin); + immVertex3fv(pos, vec[0]); + immVertex3fv(pos, origin); + immVertex3fv(pos, vec[1]); + immVertex3fv(pos, origin); + immVertex3fv(pos, vec[2]); + immVertex3fv(pos, origin); + immVertex3fv(pos, vec[3]); + immEnd(); } -/* center point to camera frame */ -static void drawcamera_framelines(float vec[4][3], float origin[3]) +static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], bool filled, unsigned pos) { - glBegin(GL_LINE_STRIP); - glVertex3fv(vec[1]); - glVertex3fv(origin); - glVertex3fv(vec[0]); - glVertex3fv(vec[3]); - glVertex3fv(origin); - glVertex3fv(vec[2]); - glEnd(); + drawcamera_frame(near_plane, filled, pos); + drawcamera_frame(far_plane, filled, pos); + + if (filled) { + immBegin(GWN_PRIM_TRI_STRIP, 10); + + immVertex3fv(pos, near_plane[0]); + immVertex3fv(pos, far_plane[0]); + immVertex3fv(pos, near_plane[1]); + immVertex3fv(pos, far_plane[1]); + immVertex3fv(pos, near_plane[2]); + immVertex3fv(pos, far_plane[2]); + immVertex3fv(pos, near_plane[3]); + immVertex3fv(pos, far_plane[3]); + immVertex3fv(pos, near_plane[0]); + immVertex3fv(pos, far_plane[0]); + + immEnd(); + } + else { + immBegin(GWN_PRIM_LINES, 8); + for (int i = 0; i < 4; ++i) { + immVertex3fv(pos, near_plane[i]); + immVertex3fv(pos, far_plane[i]); + } + immEnd(); + } } static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob) @@ -1867,7 +1963,7 @@ static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob) static void drawcamera_stereo3d( Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const Camera *cam, - float vec[4][3], float drawsize, const float scale[3]) + float vec[4][3], float drawsize, const float scale[3], unsigned pos) { float obmat[4][4]; float vec_lr[2][4][3]; @@ -1883,15 +1979,15 @@ static void drawcamera_stereo3d( zero_v3(tvec); - glPushMatrix(); + /* caller bound GPU_SHADER_3D_UNIFORM_COLOR, passed in pos attribute ID */ for (int i = 0; i < 2; i++) { ob = BKE_camera_multiview_render(scene, ob, names[i]); cam_lr[i] = ob->data; - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); BKE_camera_multiview_model_matrix(&scene->r, ob, names[i], obmat); - glMultMatrixf(obmat); + gpuMultMatrix(obmat); copy_m3_m3(vec_lr[i], vec); copy_v3_v3(vec_lr[i][3], vec[3]); @@ -1908,10 +2004,10 @@ static void drawcamera_stereo3d( if (is_stereo3d_cameras) { /* camera frame */ - drawcamera_frame(vec_lr[i], GL_LINE_LOOP); + drawcamera_frame(vec_lr[i], false, pos); /* center point to camera frame */ - drawcamera_framelines(vec_lr[i], tvec); + drawcamera_framelines(vec_lr[i], tvec, pos); } /* connecting line */ @@ -1925,21 +2021,20 @@ static void drawcamera_stereo3d( } } - /* the remaining drawing takes place in the view space */ - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); if (is_stereo3d_cameras) { /* draw connecting lines */ - GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); - GPU_basic_shader_line_stipple(2, 0xAAAA); + glLineStipple(2, 0xAAAA); + glEnable(GL_LINE_STIPPLE); - glBegin(GL_LINES); - glVertex3fv(origin[0]); - glVertex3fv(origin[1]); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, origin[0]); + immVertex3fv(pos, origin[1]); + immEnd(); - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); + glDisable(GL_LINE_STIPPLE); } /* draw convergence plane */ @@ -1964,21 +2059,21 @@ static void drawcamera_stereo3d( add_v3_v3(local_plane[i], axis_center); } - glColor3f(0.0f, 0.0f, 0.0f); + immUniformColor3f(0.0f, 0.0f, 0.0f); /* camera frame */ - drawcamera_frame(local_plane, GL_LINE_LOOP); + drawcamera_frame(local_plane, false, pos); if (v3d->stereo3d_convergence_alpha > 0.0f) { glEnable(GL_BLEND); - glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */ - glColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha); + immUniformColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha); - drawcamera_frame(local_plane, GL_QUADS); + drawcamera_frame(local_plane, true, pos); glDisable(GL_BLEND); - glDepthMask(1); /* restore write in zbuffer */ + glDepthMask(GL_TRUE); /* restore write in zbuffer */ } } @@ -2003,37 +2098,31 @@ static void drawcamera_stereo3d( } /* camera frame */ - glColor3f(0.0f, 0.0f, 0.0f); + immUniformColor3f(0.0f, 0.0f, 0.0f); - drawcamera_frame(near_plane, GL_LINE_LOOP); - drawcamera_frame(far_plane, GL_LINE_LOOP); - drawcamera_volume(near_plane, far_plane, GL_LINE_LOOP); + drawcamera_volume(near_plane, far_plane, false, pos); if (v3d->stereo3d_volume_alpha > 0.0f) { glEnable(GL_BLEND); - glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */ if (i == 0) - glColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha); + immUniformColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha); else - glColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha); + immUniformColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha); - drawcamera_frame(near_plane, GL_QUADS); - drawcamera_frame(far_plane, GL_QUADS); - drawcamera_volume(near_plane, far_plane, GL_QUADS); + drawcamera_volume(near_plane, far_plane, true, pos); glDisable(GL_BLEND); - glDepthMask(1); /* restore write in zbuffer */ + glDepthMask(GL_TRUE); /* restore write in zbuffer */ } } } - - glPopMatrix(); } /* flag similar to draw_object() */ -static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dflag, const unsigned char ob_wire_col[4]) +void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, + const short dflag, const unsigned char ob_wire_col[4]) { /* a standing up pyramid with (0,0,0) as top */ Camera *cam; @@ -2096,8 +2185,12 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale, asp, shift, &drawsize, vec); - glDisable(GL_CULL_FACE); - glLineWidth(1); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) { + immUniformColor3ubv(ob_wire_col); + } + glLineWidth(1.0f); /* camera frame */ if (!is_stereo3d_cameras) { @@ -2106,27 +2199,29 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base float obmat[4][4]; bool is_left = v3d->multiview_eye == STEREO_LEFT_ID; - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); + gpuPushMatrix(); + gpuLoadMatrix(rv3d->viewmat); BKE_camera_multiview_model_matrix(&scene->r, ob, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, obmat); - glMultMatrixf(obmat); + gpuMultMatrix(obmat); - drawcamera_frame(vec, GL_LINE_LOOP); - glPopMatrix(); + drawcamera_frame(vec, false, pos); + gpuPopMatrix(); } else { - drawcamera_frame(vec, GL_LINE_LOOP); + drawcamera_frame(vec, false, pos); } } - if (is_view) + if (is_view) { + immUnbindProgram(); return; + } zero_v3(tvec); /* center point to camera frame */ if (!is_stereo3d_cameras) - drawcamera_framelines(vec, tvec); + drawcamera_framelines(vec, tvec, pos); /* arrow on top */ tvec[2] = vec[1][2]; /* copy the depth */ @@ -2135,22 +2230,25 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base * for active cameras. We actually draw both outline+filled * for active cameras so the wire can be seen side-on */ for (int i = 0; i < 2; i++) { - if (i == 0) glBegin(GL_LINE_LOOP); - else if (i == 1 && is_active) glBegin(GL_TRIANGLES); + if (i == 0) immBegin(GWN_PRIM_LINE_LOOP, 3); + else if (i == 1 && is_active) { + glDisable(GL_CULL_FACE); /* TODO: declarative state tracking */ + immBegin(GWN_PRIM_TRIS, 3); + } else break; tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]); tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]); - glVertex3fv(tvec); /* left */ + immVertex3fv(pos, tvec); /* left */ tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]); - glVertex3fv(tvec); /* right */ + immVertex3fv(pos, tvec); /* right */ tvec[0] = shift[0]; tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]); - glVertex3fv(tvec); /* top */ + immVertex3fv(pos, tvec); /* top */ - glEnd(); + immEnd(); } if ((dflag & DRAW_SCENESET) == 0) { @@ -2161,16 +2259,15 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base copy_m4_m4(nobmat, ob->obmat); normalize_m4(nobmat); - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); - glMultMatrixf(nobmat); + gpuLoadMatrix(rv3d->viewmat); + gpuMultMatrix(nobmat); if (cam->flag & CAM_SHOWLIMITS) { const unsigned char col[3] = {128, 128, 60}, col_hi[3] = {255, 255, 120}; - draw_limit_line(cam->clipsta, cam->clipend, dflag, (is_active ? col_hi : col)); + draw_limit_line(cam->clipsta, cam->clipend, dflag, (is_active ? col_hi : col), pos); /* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */ - draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize); + draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize, pos); } if (cam->flag & CAM_SHOWMIST) { @@ -2179,69 +2276,79 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base if (world) { draw_limit_line(world->miststa, world->miststa + world->mistdist, - dflag, (is_active ? col_hi : col)); + dflag, (is_active ? col_hi : col), pos); } } - glPopMatrix(); } } /* stereo cameras drawing */ if (is_stereo3d) { - drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale); + drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale, pos); } + + immUnbindProgram(); } /* flag similar to draw_object() */ -static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d), - Object *UNUSED(ob), int UNUSED(flag)) +void drawspeaker(const unsigned char ob_wire_col[3]) { - float vec[3]; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); - glEnable(GL_BLEND); - glLineWidth(1); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + if (ob_wire_col) { + immUniformColor3ubv(ob_wire_col); + } + + glLineWidth(1.0f); + + const int segments = 16; for (int j = 0; j < 3; j++) { - vec[2] = 0.25f * j - 0.125f; + float z = 0.25f * j - 0.125f; - glBegin(GL_LINE_LOOP); - for (int i = 0; i < 16; i++) { - vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f); - vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f); - glVertex3fv(vec); + immBegin(GWN_PRIM_LINE_LOOP, segments); + for (int i = 0; i < segments; i++) { + float x = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f); + float y = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f); + immVertex3f(pos, x, y, z); } - glEnd(); + immEnd(); } for (int j = 0; j < 4; j++) { - vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f; - vec[1] = ((j % 2) * (j - 2)) * 0.5f; - glBegin(GL_LINE_STRIP); + float x = (((j + 1) % 2) * (j - 1)) * 0.5f; + float y = ((j % 2) * (j - 2)) * 0.5f; + immBegin(GWN_PRIM_LINE_STRIP, 3); for (int i = 0; i < 3; i++) { if (i == 1) { - vec[0] *= 0.5f; - vec[1] *= 0.5f; + x *= 0.5f; + y *= 0.5f; } - vec[2] = 0.25f * i - 0.125f; - glVertex3fv(vec); + float z = 0.25f * i - 0.125f; + immVertex3f(pos, x, y, z); } - glEnd(); + immEnd(); } - glDisable(GL_BLEND); + immUnbindProgram(); } -static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel) +static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel, + unsigned int pos, unsigned int color) { BPoint *bp = lt->def; const float *co = dl ? dl->verts : NULL; + float active_color[4], draw_color[4]; - const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX; - UI_ThemeColor(color); + UI_GetThemeColor4fv(sel ? TH_VERTEX_SELECT : TH_VERTEX, draw_color); + UI_GetThemeColor4fv(TH_ACTIVE_VERT, active_color); glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - glBegin(GL_POINTS); + immBeginAtMost(GWN_PRIM_POINTS, lt->pntsw * lt->pntsv * lt->pntsu); for (int w = 0; w < lt->pntsw; w++) { int wxt = (w == 0 || w == lt->pntsw - 1); @@ -2253,12 +2360,12 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short s if (bp->hide == 0) { /* check for active BPoint and ensure selected */ if ((bp == actbp) && (bp->f1 & SELECT)) { - UI_ThemeColor(TH_ACTIVE_VERT); - glVertex3fv(dl ? co : bp->vec); - UI_ThemeColor(color); + immAttrib4fv(color, active_color); + immVertex3fv(pos, dl ? co : bp->vec); } else if ((bp->f1 & SELECT) == sel) { - glVertex3fv(dl ? co : bp->vec); + immAttrib4fv(color, draw_color); + immVertex3fv(pos, dl ? co : bp->vec); } } } @@ -2266,32 +2373,32 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short s } } - glEnd(); + immEnd(); } -static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol) +static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol, + unsigned int pos, unsigned int color) { int index = ((w * lt->pntsv + v) * lt->pntsu) + u; if (actdef_wcol) { float col[3]; MDeformWeight *mdw = defvert_find_index(lt->dvert + index, actdef_wcol - 1); - weight_to_rgb(col, mdw ? mdw->weight : 0.0f); - glColor3fv(col); - + immAttrib3fv(color, col); } if (dl) { - glVertex3fv(&dl->verts[index * 3]); + immVertex3fv(pos, &dl->verts[index * 3]); } else { - glVertex3fv(lt->def[index].vec); + immVertex3fv(pos, lt->def[index].vec); } } #ifdef SEQUENCER_DAG_WORKAROUND -static void ensure_curve_cache(Scene *scene, Object *object) +static void ensure_curve_cache( + const EvaluationContext *eval_ctx, Scene *scene, Object *object) { bool need_recalc = object->curve_cache == NULL; /* Render thread might have freed the curve cache if the @@ -2320,13 +2427,13 @@ static void ensure_curve_cache(Scene *scene, Object *object) case OB_CURVE: case OB_SURF: case OB_FONT: - BKE_displist_make_curveTypes(scene, object, false); + BKE_displist_make_curveTypes(eval_ctx, scene, object, false); break; case OB_MBALL: - BKE_displist_make_mball(G.main->eval_ctx, scene, object); + BKE_displist_make_mball(eval_ctx, scene, object); break; case OB_LATTICE: - BKE_lattice_modifiers_calc(scene, object); + BKE_lattice_modifiers_calc(eval_ctx, scene, object); break; } } @@ -2334,7 +2441,7 @@ static void ensure_curve_cache(Scene *scene, Object *object) #endif /* lattice color is hardcoded, now also shows weightgroup values in edit mode */ -static void drawlattice(View3D *v3d, Object *ob) +static void drawlattice(View3D *v3d, Object *ob, const short dflag, const unsigned char ob_wire_col[4]) { Lattice *lt = ob->data; DispList *dl; @@ -2347,15 +2454,37 @@ static void drawlattice(View3D *v3d, Object *ob) if (is_edit) { lt = lt->editlatt->latt; - UI_ThemeColor(TH_WIRE_EDIT); - if (ob->defbase.first && lt->dvert) { actdef_wcol = ob->actdef; } } - glLineWidth(1); - glBegin(GL_LINES); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int color, pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + if (actdef_wcol) { + color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); + } + else { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + if (is_edit) { + immUniformThemeColor(TH_WIRE_EDIT); + } + else { + if ((dflag & DRAW_CONSTCOLOR) == 0) { + immUniformColor3ubv(ob_wire_col); + } + else { + immUniformColor3f(0.0f, 0.0f, 0.0f); + } + } + } + + glLineWidth(1.0f); + immBeginAtMost(GWN_PRIM_LINES, lt->pntsw * lt->pntsv * lt->pntsu * 6); + for (w = 0; w < lt->pntsw; w++) { int wxt = (w == 0 || w == lt->pntsw - 1); for (v = 0; v < lt->pntsv; v++) { @@ -2364,30 +2493,40 @@ static void drawlattice(View3D *v3d, Object *ob) int uxt = (u == 0 || u == lt->pntsu - 1); if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) { - drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol); - drawlattice__point(lt, dl, u, v, w, actdef_wcol); + drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol, pos, color); + drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color); } if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) { - drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol); - drawlattice__point(lt, dl, u, v, w, actdef_wcol); + drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol, pos, color); + drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color); } if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) { - drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol); - drawlattice__point(lt, dl, u, v, w, actdef_wcol); + drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol, pos, color); + drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color); } } } } - glEnd(); + + immEnd(); + immUnbindProgram(); if (is_edit) { BPoint *actbp = BKE_lattice_active_point_get(lt); if (v3d->zbuf) glDisable(GL_DEPTH_TEST); - - lattice_draw_verts(lt, dl, actbp, 0); - lattice_draw_verts(lt, dl, actbp, 1); - + + Gwn_VertFormat *v_format = immVertexFormat(); + unsigned int v_pos = GWN_vertformat_attr_add(v_format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int v_color = GWN_vertformat_attr_add(v_format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); + + lattice_draw_verts(lt, dl, actbp, 0, v_pos, v_color); + lattice_draw_verts(lt, dl, actbp, 1, v_pos, v_color); + + immUnbindProgram(); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } } @@ -2401,6 +2540,7 @@ typedef struct drawDMVertSel_userData { int active; unsigned char *col[3]; /* (base, sel, act) */ char sel_prev; + unsigned int pos, color; } drawDMVertSel_userData; static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3], @@ -2412,17 +2552,18 @@ static void drawSelectedVertices__mapFunc(void *userData, int index, const float if (!(mv->flag & ME_HIDE)) { const char sel = (index == data->active) ? 2 : (mv->flag & SELECT); if (sel != data->sel_prev) { - glColor3ubv(data->col[sel]); + immAttrib3ubv(data->color, data->col[sel]); data->sel_prev = sel; } - glVertex3fv(co); + immVertex3fv(data->pos, co); } } static void drawSelectedVertices(DerivedMesh *dm, Mesh *me) { drawDMVertSel_userData data; + Gwn_VertFormat *format = immVertexFormat(); /* TODO define selected color */ unsigned char base_col[3] = {0x0, 0x0, 0x0}; @@ -2437,9 +2578,18 @@ static void drawSelectedVertices(DerivedMesh *dm, Mesh *me) data.col[1] = sel_col; data.col[2] = act_col; - glBegin(GL_POINTS); + data.color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + if (dm->getNumVerts(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + immBeginAtMost(GWN_PRIM_POINTS, dm->getNumVerts(dm)); dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } /* ************** DRAW MESH ****************** */ @@ -2486,25 +2636,34 @@ static void draw_dm_face_normals__mapFunc(void *userData, int index, const float copy_v3_v3(n, no); } - glVertex3fv(cent); - glVertex3f(cent[0] + n[0] * data->normalsize, - cent[1] + n[1] * data->normalsize, - cent[2] + n[2] * data->normalsize); + immVertex3fv(data->pos, cent); + immVertex3f(data->pos, cent[0] + n[0] * data->normalsize, + cent[1] + n[1] * data->normalsize, + cent[2] + n[2] * data->normalsize); } } -static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm) +static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id) { + Gwn_VertFormat *format = immVertexFormat(); drawDMNormal_userData data; data.bm = em->bm; data.normalsize = scene->toolsettings->normalsize; + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); calcDrawDMNormalScale(ob, &data); - glBegin(GL_LINES); + if (dm->getNumPolys(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(theme_id); + + immBeginAtMost(GWN_PRIM_LINES, dm->getNumPolys(dm) * 2); dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL); - glEnd(); + immEnd(); + + immUnbindProgram(); } static void draw_dm_face_centers__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3])) @@ -2515,16 +2674,28 @@ static void draw_dm_face_centers__mapFunc(void *userData, int index, const float if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && (BM_elem_flag_test(efa, BM_ELEM_SELECT) == data->select)) { - glVertex3fv(cent); + immVertex3fv(data->pos, cent); } } -static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, bool select) +static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, bool select, const unsigned char fcol[3]) { - drawBMSelect_userData data = {em->bm, select}; + Gwn_VertFormat *format = immVertexFormat(); + + drawBMSelect_userData data; + data.bm = em->bm; + data.select = select; + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + if (dm->getNumPolys(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(fcol); - glBegin(GL_POINTS); + immBeginAtMost(GWN_PRIM_POINTS, dm->getNumPolys(dm)); dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]) @@ -2551,71 +2722,83 @@ static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float copy_v3_v3(n, no); } - glVertex3fv(co); - glVertex3f(co[0] + n[0] * data->normalsize, - co[1] + n[1] * data->normalsize, - co[2] + n[2] * data->normalsize); + immVertex3fv(data->pos, co); + immVertex3f(data->pos, co[0] + n[0] * data->normalsize, + co[1] + n[1] * data->normalsize, + co[2] + n[2] * data->normalsize); } } -static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm) +static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id) { drawDMNormal_userData data; + Gwn_VertFormat *format = immVertexFormat(); data.bm = em->bm; data.normalsize = scene->toolsettings->normalsize; + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); calcDrawDMNormalScale(ob, &data); - glBegin(GL_LINES); + if (dm->getNumVerts(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(theme_id); + + immBeginAtMost(GWN_PRIM_LINES, dm->getNumVerts(dm) * 2); dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL); - glEnd(); + immEnd(); + + immUnbindProgram(); } -/* Draw verts with color set based on selection */ -static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3], - const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) +static void draw_dm_verts_skin_root__mapFunc(void *userData, int index, const float co[3], + const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) { drawDMVerts_userData *data = userData; BMVert *eve = BM_vert_at_index(data->bm, index); if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) { /* skin nodes: draw a red circle around the root node(s) */ - if (data->cd_vskin_offset != -1) { - const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset); - if (vs->flag & MVERT_SKIN_ROOT) { - float radius = (vs->radius[0] + vs->radius[1]) * 0.5f; - glEnd(); - - glColor4ubv(data->th_skin_root); - drawcircball(GL_LINES, co, radius, data->imat); - - glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex); - glBegin(GL_POINTS); - } + const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset); + if (vs->flag & MVERT_SKIN_ROOT) { + float radius = (vs->radius[0] + vs->radius[1]) * 0.5f; + imm_drawcircball(co, radius, data->imat, data->pos); } + } +} + +/* Draw verts with color set based on selection */ +static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3], + const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) +{ + drawDMVerts_userData *data = userData; + BMVert *eve = BM_vert_at_index(data->bm, index); + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) { /* draw active in a different color - no need to stop/start point drawing for this :D */ if (eve == data->eve_act) { - glColor4ubv(data->th_editmesh_active); - glVertex3fv(co); - - /* back to regular vertex color */ - glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex); + immAttrib4ubv(data->color, data->th_editmesh_active); + immVertex3fv(data->pos, co); } else { - glVertex3fv(co); + immAttrib4ubv(data->color, data->sel ? data->th_vertex_select : data->th_vertex); + immVertex3fv(data->pos, co); } } } static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVert *eve_act, - RegionView3D *rv3d) + RegionView3D *rv3d, const unsigned char col[4]) { + Gwn_VertFormat *format = immVertexFormat(); + drawDMVerts_userData data; data.sel = sel; data.eve_act = eve_act; data.bm = em->bm; + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); /* Cache theme values */ UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, data.th_editmesh_active); @@ -2623,16 +2806,37 @@ static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVer UI_GetThemeColor4ubv(TH_VERTEX, data.th_vertex); UI_GetThemeColor4ubv(TH_SKIN_ROOT, data.th_skin_root); - /* For skin root drawing */ - data.cd_vskin_offset = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN); + /* Set correct alpha */ + data.th_editmesh_active[3] = data.th_vertex_select[3] = data.th_vertex[3] = data.th_skin_root[3] = col[3]; + /* view-aligned matrix */ mul_m4_m4m4(data.imat, rv3d->viewmat, em->ob->obmat); invert_m4(data.imat); + if (dm->getNumVerts(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - glBegin(GL_POINTS); + + immBeginAtMost(GWN_PRIM_POINTS, dm->getNumVerts(dm)); dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); + + /* For skin root drawing */ + data.cd_vskin_offset = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN); + + if (data.cd_vskin_offset != -1) { + data.pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4ubv(data.th_skin_root); + + dm->foreachMappedVert(dm, draw_dm_verts_skin_root__mapFunc, &data, DM_FOREACH_NOP); + + immUnbindProgram(); + } } /* Draw edges with color set based on selection */ @@ -2938,24 +3142,32 @@ static void draw_dm_loop_normals__mapFunc(void *userData, int vertex_index, int } mul_v3_fl(vec, data->normalsize); add_v3_v3(vec, co); - glVertex3fv(co); - glVertex3fv(vec); + immVertex3fv(data->pos, co); + immVertex3fv(data->pos, vec); } } } -static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm) +static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id) { drawDMNormal_userData data; data.bm = em->bm; data.normalsize = scene->toolsettings->normalsize; + data.pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + if (dm->getNumLoops(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(theme_id); calcDrawDMNormalScale(ob, &data); - glBegin(GL_LINES); + immBeginAtMost(GWN_PRIM_LINES, dm->getNumLoops(dm) * 2); dm->foreachMappedLoop(dm, draw_dm_loop_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL); - glEnd(); + immEnd(); + + immUnbindProgram(); } /* Draw faces with color set based on selection @@ -3072,7 +3284,7 @@ static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm) data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE); if (data.cd_layer_offset != -1) { - glLineWidth(3.0); + glLineWidth(3.0f); dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, &data); } } @@ -3102,8 +3314,10 @@ static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { const float bweight = BM_ELEM_CD_GET_FLOAT(eve, data->cd_layer_offset); if (bweight != 0.0f) { - UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_BEVEL, bweight); - glVertex3fv(co); + unsigned char col[3]; + UI_GetThemeColorBlend3ubv(TH_VERTEX, TH_VERTEX_BEVEL, bweight, col); + immAttrib3ubv(data->col, col); + immVertex3fv(data->pos, co); } } } @@ -3117,11 +3331,21 @@ static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm) data.bm = em->bm; data.cd_layer_offset = CustomData_get_offset(&em->bm->vdata, CD_BWEIGHT); + /* is that ever true? */ if (data.cd_layer_offset != -1) { - glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2); - glBegin(GL_POINTS); + Gwn_VertFormat *format = immVertexFormat(); + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2.0f); + + immBeginAtMost(GWN_PRIM_POINTS, dm->getNumVerts(dm)); dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } } else { @@ -3131,7 +3355,7 @@ static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm) data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT); if (data.cd_layer_offset != -1) { - glLineWidth(3.0); + glLineWidth(3.0f); dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, &data); } } @@ -3152,7 +3376,7 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, { ToolSettings *ts = scene->toolsettings; - if (v3d->zbuf) glDepthMask(0); /* disable write in zbuffer, zbuf select */ + if (v3d->zbuf) glDepthMask(GL_FALSE); /* disable write in zbuffer, zbuf select */ for (int sel = 0; sel < 2; sel++) { unsigned char col[4], fcol[4]; @@ -3182,15 +3406,12 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, } if (ts->selectmode & SCE_SELECT_VERTEX) { - glPointSize(size); - glColor4ubv(col); - draw_dm_verts(em, cageDM, sel, eve_act, rv3d); + draw_dm_verts(em, cageDM, sel, eve_act, rv3d, col); } if (check_ob_drawface_dot(scene, v3d, obedit->dt)) { glPointSize(fsize); - glColor4ubv(fcol); - draw_dm_face_centers(em, cageDM, sel); + draw_dm_face_centers(em, cageDM, sel, fcol); } if (pass == 0) { @@ -3200,7 +3421,7 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, } } - if (v3d->zbuf) glDepthMask(1); + if (v3d->zbuf) glDepthMask(GL_TRUE); } static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d, @@ -3307,11 +3528,9 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe if (me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_EDGEANG)) { BoundBox bb; - bglMats mats = {{0}}; const rcti rect = {0, ar->winx, 0, ar->winy}; - view3d_get_transformation(ar, ar->regiondata, em->ob, &mats); - ED_view3d_clipping_calc(&bb, clip_planes, &mats, &rect); + ED_view3d_clipping_calc(&bb, clip_planes, ar, em->ob, &rect); } if (me->drawflag & ME_DRAWEXTRA_EDGELEN) { @@ -3675,7 +3894,7 @@ static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index) } } -static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, +static void draw_em_fancy(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const char dt) { @@ -3684,7 +3903,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, const bool use_occlude_wire = (dt > OB_WIRE) && (v3d->flag2 & V3D_OCCLUDE_WIRE); bool use_depth_offset = false; - glLineWidth(1); + glLineWidth(1.0f); BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); @@ -3693,7 +3912,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, draw_mesh_paint_weight_faces(finalDM, true, draw_em_fancy__setFaceOpts, me->edit_btmesh); ED_view3d_polygon_offset(rv3d, 1.0); - glDepthMask(0); + glDepthMask(GL_FALSE); use_depth_offset = true; } else { @@ -3713,7 +3932,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } else if (check_object_draw_texture(scene, v3d, dt)) { - if (draw_glsl_material(scene, ob, v3d, dt)) { + if (draw_glsl_material(scene, sl, ob, v3d, dt)) { glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); finalDM->drawMappedFacesGLSL(finalDM, GPU_object_material_bind, @@ -3723,7 +3942,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, glFrontFace(GL_CCW); } else { - draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0); + draw_mesh_textured(scene, sl, v3d, rv3d, ob, finalDM, 0); } } else { @@ -3740,7 +3959,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, UI_ThemeColor(TH_WIRE_EDIT); ED_view3d_polygon_offset(rv3d, 1.0); - glDepthMask(0); + glDepthMask(GL_FALSE); use_depth_offset = true; } else { @@ -3790,7 +4009,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #endif glEnable(GL_BLEND); - glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */ /* don't draw unselected faces, only selected, this is MUCH nicer when texturing */ if (check_object_draw_texture(scene, v3d, dt)) @@ -3806,7 +4025,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #endif glDisable(GL_BLEND); - glDepthMask(1); /* restore write in zbuffer */ + glDepthMask(GL_TRUE); /* restore write in zbuffer */ } else if (efa_act) { /* even if draw faces is off it would be nice to draw the stipple face @@ -3821,7 +4040,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3); glEnable(GL_BLEND); - glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */ #ifdef WITH_FREESTYLE draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act); @@ -3830,7 +4049,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #endif glDisable(GL_BLEND); - glDepthMask(1); /* restore write in zbuffer */ + glDepthMask(GL_TRUE); /* restore write in zbuffer */ } /* here starts all fancy draw-extra over */ @@ -3844,7 +4063,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, else { if (me->drawflag & ME_DRAWSEAMS) { UI_ThemeColor(TH_EDGE_SEAM); - glLineWidth(2); + glLineWidth(2.0f); draw_dm_edges_seams(em, cageDM); @@ -3853,7 +4072,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, if (me->drawflag & ME_DRAWSHARP) { UI_ThemeColor(TH_EDGE_SHARP); - glLineWidth(2); + glLineWidth(2.0f); draw_dm_edges_sharp(em, cageDM); @@ -3863,7 +4082,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #ifdef WITH_FREESTYLE if (me->drawflag & ME_DRAW_FREESTYLE_EDGE && CustomData_has_layer(&em->bm->edata, CD_FREESTYLE_EDGE)) { UI_ThemeColor(TH_FREESTYLE_EDGE_MARK); - glLineWidth(2); + glLineWidth(2.0f); draw_dm_edges_freestyle(em, cageDM); @@ -3878,7 +4097,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, draw_dm_bweights(em, scene, cageDM); } - glLineWidth(1); + glLineWidth(1.0f); draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act); } @@ -3886,16 +4105,13 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act, rv3d); if (me->drawflag & ME_DRAWNORMALS) { - UI_ThemeColor(TH_NORMAL); - draw_dm_face_normals(em, scene, ob, cageDM); + draw_dm_face_normals(em, scene, ob, cageDM, TH_NORMAL); } if (me->drawflag & ME_DRAW_VNORMALS) { - UI_ThemeColor(TH_VNORMAL); - draw_dm_vert_normals(em, scene, ob, cageDM); + draw_dm_vert_normals(em, scene, ob, cageDM, TH_VNORMAL); } if (me->drawflag & ME_DRAW_LNORMALS) { - UI_ThemeColor(TH_LNORMAL); - draw_dm_loop_normals(em, scene, ob, cageDM); + draw_dm_loop_normals(em, scene, ob, cageDM, TH_LNORMAL); } if ((me->drawflag & (ME_DRAWEXTRA_EDGELEN | @@ -3916,7 +4132,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, } if (use_depth_offset) { - glDepthMask(1); + glDepthMask(GL_TRUE); ED_view3d_polygon_offset(rv3d, 0.0); GPU_object_material_unbind(); } @@ -3927,15 +4143,97 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #endif } +static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *UNUSED(ar), View3D *UNUSED(v3d), + Object *UNUSED(ob), Mesh *me, BMEditMesh *UNUSED(em), DerivedMesh *UNUSED(cageDM), DerivedMesh *UNUSED(finalDM), const char UNUSED(dt)) +{ + /* for now... something simple! */ + Gwn_Batch *surface = DRW_mesh_batch_cache_get_all_triangles(me); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + glEnable(GL_BLEND); + + /* disable depth writes for transparent surface, so it doesn't interfere with itself */ + glDepthMask(GL_FALSE); + + GWN_batch_program_set_builtin(surface, GPU_SHADER_3D_UNIFORM_COLOR); + GWN_batch_uniform_4f(surface, "color", 1.0f, 0.5f, 0.0f, 0.5f); + GWN_batch_draw(surface); + +#if 0 /* until I understand finalDM better */ + if (finalDM != cageDM) { + puts("finalDM != cageDM"); + Gwn_Batch *finalSurface = MBC_get_all_triangles(finalDM); + GWN_batch_program_set_builtin(finalSurface, GPU_SHADER_3D_UNIFORM_COLOR); + GWN_batch_uniform_4f(finalSurface, "color", 0.0f, 0.0f, 0.0f, 0.05f); + GWN_batch_draw(finalSurface); + } +#endif + + glDepthMask(GL_TRUE); + + /* now write surface depth so other objects won't poke through + * NOTE: does not help as much as desired + * TODO: draw edit object last to avoid this mess + */ + GWN_batch_program_set_builtin(surface, GPU_SHADER_3D_DEPTH_ONLY); + GWN_batch_draw(surface); + + if (GLEW_VERSION_3_2) { +#if 0 + Gwn_Batch *overlay = DRW_mesh_batch_cache_get_overlay_edges(me); + GWN_batch_program_set_builtin(overlay, GPU_SHADER_EDGES_OVERLAY); + GWN_batch_uniform_2f(overlay, "viewportSize", ar->winx, ar->winy); + GWN_batch_draw(overlay); +#endif + +#if 0 /* TODO: use this SIMPLE variant for pure triangle meshes */ + GWN_batch_program_set_builtin(surface, GPU_SHADER_EDGES_OVERLAY_SIMPLE); + /* use these defaults: + * const float edgeColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + * GWN_batch_uniform_4f(surface, "fillColor", edgeColor[0], edgeColor[1], edgeColor[2], 0.0f); + * GWN_batch_uniform_4fv(surface, "outlineColor", edgeColor); + * GWN_batch_uniform_1f(surface, "outlineWidth", 1.0f); + */ + GWN_batch_uniform_2f(surface, "viewportSize", ar->winx, ar->winy); + GWN_batch_draw(surface); +#endif + } + else { + Gwn_Batch *edges = DRW_mesh_batch_cache_get_all_edges(me); + GWN_batch_program_set_builtin(edges, GPU_SHADER_3D_UNIFORM_COLOR); + GWN_batch_uniform_4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f); + glEnable(GL_LINE_SMOOTH); + glLineWidth(1.5f); + GWN_batch_draw(edges); + glDisable(GL_LINE_SMOOTH); + } + +#if 0 /* looks good even without points */ + Gwn_Batch *verts = MBC_get_all_verts(me); + glEnable(GL_BLEND); + + GWN_batch_program_set_builtin(verts, GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + GWN_batch_uniform_4f(verts, "color", 0.0f, 0.0f, 0.0f, 1.0f); + GWN_batch_uniform_1f(verts, "size", UI_GetThemeValuef(TH_VERTEX_SIZE) * 1.5f); + GWN_batch_draw(verts); + + glDisable(GL_BLEND); +#endif +} + /* Mesh drawing routines */ -static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) +void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm, const unsigned char ob_wire_col[4]) /* LEGACY */ { if ((v3d->transp == false) && /* not when we draw the transparent pass */ (ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */ { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); - glDepthMask(0); + glDepthMask(GL_FALSE); + + if (ob_wire_col) glColor4ubv(ob_wire_col); /* if transparent, we cannot draw the edges for solid select... edges * have no material info. GPU_object_material_visible will skip the @@ -3949,7 +4247,49 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) dm->drawEdges(dm, 0, 1); } - glDepthMask(1); + glDepthMask(GL_TRUE); + } +} + +static void draw_mesh_object_outline_new(View3D *v3d, RegionView3D *rv3d, Object *ob, Mesh *me, const bool is_active) +{ + if ((v3d->transp == false) && /* not when we draw the transparent pass */ + (ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */ + { + glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); + glDepthMask(GL_FALSE); + + float outline_color[4]; + UI_GetThemeColor4fv((is_active ? TH_ACTIVE : TH_SELECT), outline_color); + +#if 1 /* new version that draws only silhouette edges */ + Gwn_Batch *fancy_edges = DRW_mesh_batch_cache_get_fancy_edges(me); + + if (rv3d->persp == RV3D_ORTHO) { + GWN_batch_program_set_builtin(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_ORTHO); + /* set eye vector, transformed to object coords */ + float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */ + mul_m3_v3(gpuGetNormalMatrixInverse(NULL), eye); + GWN_batch_uniform_3fv(fancy_edges, "eye", eye); + } + else { + GWN_batch_program_set_builtin(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_PERSP); + } + + GWN_batch_uniform_1b(fancy_edges, "drawFront", false); + GWN_batch_uniform_1b(fancy_edges, "drawBack", false); + GWN_batch_uniform_1b(fancy_edges, "drawSilhouette", true); + GWN_batch_uniform_4fv(fancy_edges, "silhouetteColor", outline_color); + + GWN_batch_draw(fancy_edges); +#else /* alternate version that matches look of old viewport (but more efficient) */ + Gwn_Batch *batch = MBC_get_all_edges(dm); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + GWN_batch_uniform_4fv(batch, "color", outline_color); + GWN_batch_draw(batch); +#endif + + glDepthMask(GL_TRUE); } } @@ -3959,19 +4299,20 @@ static bool object_is_halo(Scene *scene, Object *ob) return (ma && (ma->material_type == MA_TYPE_HALO) && !BKE_scene_use_new_shading_nodes(scene)); } -static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, - const char dt, const unsigned char ob_wire_col[4], const short dflag) +static void draw_mesh_fancy( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const unsigned char ob_wire_col[4], const short dflag) { #ifdef WITH_GAMEENGINE - Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, scene) : base->object; + Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, sl) : base->object; #else Object *ob = base->object; #endif Mesh *me = ob->data; eWireDrawMode draw_wire = OBDRAW_WIRE_OFF; bool /* no_verts,*/ no_edges, no_faces; - DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); - const bool is_obact = (ob == OBACT); + DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, scene->customdata_mask); + const bool is_obact = (ob == OBACT(sl)); int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0; if (!dm) @@ -4007,12 +4348,12 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if (dt == OB_BOUNDBOX) { if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0) - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } else if ((no_faces && no_edges) || ((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob))) { - glPointSize(1.5); + glPointSize(1.5f); dm->drawVerts(dm); } else if ((dt == OB_WIRE) || no_faces) { @@ -4025,19 +4366,19 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) && (draw_wire == OBDRAW_WIRE_OFF)) { - draw_mesh_object_outline(v3d, ob, dm); + draw_mesh_object_outline(v3d, ob, dm, ob_wire_col); } - if (draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) { + if (draw_glsl_material(scene, sl, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) { Paint *p; glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); - if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene))) { + if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene, sl))) { GPUVertexAttribs gattribs; float planes[4][4]; float (*fpl)[4] = NULL; @@ -4045,7 +4386,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if (ob->sculpt->partial_redraw) { if (ar->do_draw & RGN_DRAW_PARTIAL) { - ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob); + ED_sculpt_redraw_planes_get(planes, ar, ob); fpl = planes; ob->sculpt->partial_redraw = 0; } @@ -4070,7 +4411,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D draw_mesh_face_select(rv3d, me, dm, false); } else { - draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags); + draw_mesh_textured(scene, sl, v3d, rv3d, ob, dm, draw_flags); } if (draw_loose && !(draw_flags & DRAW_FACE_SELECT)) { @@ -4096,11 +4437,11 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D /* draw outline */ if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { - draw_mesh_object_outline(v3d, ob, dm); + draw_mesh_object_outline(v3d, ob, dm, ob_wire_col); } /* materials arent compatible with vertex colors */ @@ -4120,23 +4461,23 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { - draw_mesh_object_outline(v3d, ob, dm); + draw_mesh_object_outline(v3d, ob, dm, ob_wire_col); } glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); - if (ob->sculpt && (p = BKE_paint_get_active(scene))) { + if (ob->sculpt && (p = BKE_paint_get_active(scene, sl))) { float planes[4][4]; float (*fpl)[4] = NULL; const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING); if (ob->sculpt->partial_redraw) { if (ar->do_draw & RGN_DRAW_PARTIAL) { - ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob); + ED_sculpt_redraw_planes_get(planes, ar, ob); fpl = planes; ob->sculpt->partial_redraw = 0; } @@ -4177,7 +4518,9 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if ((dflag & DRAW_CONSTCOLOR) == 0) { if (is_obact && (ob->mode & OB_MODE_PARTICLE_EDIT)) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.15f); + float color[3]; + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.15f, color); + glColor3fv(color); } else { glColor3ubv(ob_wire_col); @@ -4195,14 +4538,14 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D */ if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) { ED_view3d_polygon_offset(rv3d, 1.0); - glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, selected edge wires show better */ } glLineWidth(1.0f); dm->drawEdges(dm, ((dt == OB_WIRE) || no_faces), (ob->dtx & OB_DRAW_ALL_EDGES) != 0); if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) { - glDepthMask(1); + glDepthMask(GL_TRUE); ED_view3d_polygon_offset(rv3d, 0.0); } } @@ -4221,8 +4564,9 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } /* returns true if nothing was drawn, for detecting to draw an object center */ -static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, - const char dt, const unsigned char ob_wire_col[4], const short dflag) +static bool draw_mesh_object( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const unsigned char ob_wire_col[4], const short dflag) { Object *ob = base->object; Object *obedit = scene->obedit; @@ -4233,7 +4577,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 /* If we are drawing shadows and any of the materials don't cast a shadow, * then don't draw the object */ if (v3d->flag2 & V3D_RENDER_SHADOW) { - for (int i = 1; i <= ob->totcol; ++i) { + for (int i = 0; i < ob->totcol; ++i) { Material *ma = give_current_material(ob, i); if (ma && !(ma->mode2 & MA_CASTSHADOW)) { return true; @@ -4262,7 +4606,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 } else { cageDM = editbmesh_get_derived_cage_and_final( - scene, ob, em, scene->customdata_mask, + eval_ctx, scene, ob, em, scene->customdata_mask, &finalDM); } @@ -4275,13 +4619,13 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 if (use_material) { if (dt > OB_WIRE) { - const bool glsl = draw_glsl_material(scene, ob, v3d, dt); + const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL); } } - draw_em_fancy(scene, ar, v3d, ob, em, cageDM, finalDM, dt); + draw_em_fancy(scene, sl, ar, v3d, ob, em, cageDM, finalDM, dt); if (use_material) { GPU_end_object_materials(); @@ -4294,16 +4638,16 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 /* ob->bb was set by derived mesh system, do NULL check just to be sure */ if (me->totpoly <= 4 || (!ob->bb || ED_view3d_boundbox_clip(rv3d, ob->bb))) { if (dt > OB_WIRE) { - const bool glsl = draw_glsl_material(scene, ob, v3d, dt); + const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); if (dt == OB_SOLID || glsl) { const bool check_alpha = check_alpha_pass(base); - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, (check_alpha) ? &do_alpha_after : NULL); } } - draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); + draw_mesh_fancy(eval_ctx, scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); GPU_end_object_materials(); @@ -4311,7 +4655,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 } } - if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag_legacy & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* GPU_begin_object_materials checked if this is needed */ if (do_alpha_after) { if (ob->dtx & OB_DRAWXRAY) { @@ -4335,18 +4679,551 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 return retval; } +static void make_color_variations(const unsigned char base_ubyte[4], float low[4], float med[4], float high[4], const bool other_obedit) +{ + /* original idea: nice variations (lighter & darker shades) of base color + * current implementation uses input color as high; med & low get closer to background color + */ + + float bg[3]; + UI_GetThemeColor3fv(TH_BACK, bg); + + float base[4]; + rgba_uchar_to_float(base, base_ubyte); + + if (other_obedit) { + /* this object should fade away so user can focus on the object being edited */ + interp_v3_v3v3(low, bg, base, 0.1f); + interp_v3_v3v3(med, bg, base, 0.2f); + interp_v3_v3v3(high, bg, base, 0.25f); + } + else { + interp_v3_v3v3(low, bg, base, 0.333f); + interp_v3_v3v3(med, bg, base, 0.667f); + copy_v3_v3(high, base); + } + + /* use original alpha */ + low[3] = base[3]; + med[3] = base[3]; + high[3] = base[3]; +} + +static void draw_mesh_fancy_new(EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const unsigned char ob_wire_col[4], const short dflag, const bool other_obedit) +{ + if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) { + /* too complicated! use existing methods */ + /* TODO: move this into a separate depth pre-pass */ + draw_mesh_fancy(eval_ctx, scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); + return; + } + +#ifdef WITH_GAMEENGINE + Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, sl) : base->object; +#else + Object *ob = base->object; +#endif + Mesh *me = ob->data; + eWireDrawMode draw_wire = OBDRAW_WIRE_OFF; /* could be bool draw_wire_overlay */ + bool no_edges, no_faces; + DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, scene->customdata_mask); + const bool is_obact = (ob == OBACT(sl)); + int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0; + + if (!dm) + return; + + const bool solid = dt >= OB_SOLID; + if (solid) { + DM_update_materials(dm, ob); + } + + /* Check to draw dynamic paint colors (or weights from WeightVG modifiers). + * Note: Last "preview-active" modifier in stack will win! */ + if (DM_get_loop_data_layer(dm, CD_PREVIEW_MLOOPCOL) && modifiers_isPreview(ob)) + draw_flags |= DRAW_MODIFIERS_PREVIEW; + + /* Unwanted combination */ + if (draw_flags & DRAW_FACE_SELECT) { + draw_wire = OBDRAW_WIRE_OFF; + } + else if (ob->dtx & OB_DRAWWIRE) { + draw_wire = OBDRAW_WIRE_ON; + } + + /* check polys instead of tessfaces because of dyntopo where tessfaces don't exist */ + if (dm->type == DM_TYPE_CCGDM) { + no_edges = !subsurf_has_edges(dm); + no_faces = !subsurf_has_faces(dm); + } + else { + no_edges = (dm->getNumEdges(dm) == 0); + no_faces = (dm->getNumPolys(dm) == 0); + } + + if (solid) { + /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */ + glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + } + + if (dt == OB_BOUNDBOX) { + if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0) + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); + } + else if ((no_faces && no_edges) || + ((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob))) + { + glPointSize(1.5f); + // dm->drawVerts(dm); + // TODO: draw smooth round points as a batch + } + else if ((dt == OB_WIRE) || no_faces) { + draw_wire = OBDRAW_WIRE_ON; + + /* enable depth for wireframes */ + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glLineWidth(1.0f); + +#if 1 /* fancy wireframes */ + + Gwn_Batch *fancy_edges = DRW_mesh_batch_cache_get_fancy_edges(me); + + if (rv3d->persp == RV3D_ORTHO) { + GWN_batch_program_set_builtin(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_ORTHO); + /* set eye vector, transformed to object coords */ + float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */ + mul_m3_v3(gpuGetNormalMatrixInverse(NULL), eye); + GWN_batch_uniform_3fv(fancy_edges, "eye", eye); + } + else { + GWN_batch_program_set_builtin(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_PERSP); + } + + float frontColor[4]; + float backColor[4]; + float outlineColor[4]; + make_color_variations(ob_wire_col, backColor, frontColor, outlineColor, other_obedit); + + GWN_batch_uniform_4fv(fancy_edges, "frontColor", frontColor); + GWN_batch_uniform_4fv(fancy_edges, "backColor", backColor); + GWN_batch_uniform_1b(fancy_edges, "drawFront", true); + GWN_batch_uniform_1b(fancy_edges, "drawBack", true); /* false here = backface cull */ + GWN_batch_uniform_1b(fancy_edges, "drawSilhouette", false); + + GWN_batch_draw(fancy_edges); + + /* extra oomph for the silhouette contours */ + glLineWidth(2.0f); + GWN_batch_program_use_begin(fancy_edges); /* hack to make the following uniforms stick */ + GWN_batch_uniform_1b(fancy_edges, "drawFront", false); + GWN_batch_uniform_1b(fancy_edges, "drawBack", false); + GWN_batch_uniform_1b(fancy_edges, "drawSilhouette", true); + GWN_batch_uniform_4fv(fancy_edges, "silhouetteColor", outlineColor); + + GWN_batch_draw(fancy_edges); + +#else /* simple wireframes */ + + Gwn_Batch *batch = MBC_get_all_edges(dm); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + + float color[4]; + rgba_uchar_to_float(color, ob_wire_col); + + GWN_batch_uniform_4fv(batch, "color", color); + + GWN_batch_draw(batch); +#endif + } + else if (((is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) || + check_object_draw_texture(scene, v3d, dt)) + { + bool draw_loose = true; + + if ((v3d->flag & V3D_SELECT_OUTLINE) && + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && + (base->flag & BASE_SELECTED) && + !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) && + (draw_wire == OBDRAW_WIRE_OFF)) + { + draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT(sl))); + } + + if (draw_glsl_material(scene, sl, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) { + Paint *p; + + glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + + if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene, sl))) { + GPUVertexAttribs gattribs; + float planes[4][4]; + float (*fpl)[4] = NULL; + const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING); + + if (ob->sculpt->partial_redraw) { + if (ar->do_draw & RGN_DRAW_PARTIAL) { + ED_sculpt_redraw_planes_get(planes, ar, ob); + fpl = planes; + ob->sculpt->partial_redraw = 0; + } + } + + GPU_object_material_bind(1, &gattribs); + dm->drawFacesSolid(dm, fpl, fast, NULL); + draw_loose = false; + } + else + dm->drawFacesGLSL(dm, GPU_object_material_bind); + + GPU_object_material_unbind(); + + glFrontFace(GL_CCW); + + if (draw_flags & DRAW_FACE_SELECT) + draw_mesh_face_select(rv3d, me, dm, false); + } + else { + draw_mesh_textured(scene, sl, v3d, rv3d, ob, dm, draw_flags); + } + + if (draw_loose && !(draw_flags & DRAW_FACE_SELECT)) { + if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + if ((dflag & DRAW_CONSTCOLOR) == 0) { + glColor3ubv(ob_wire_col); + } + glLineWidth(1.0f); + dm->drawLooseEdges(dm); + } + } + } + else if (dt == OB_SOLID) { + if (draw_flags & DRAW_MODIFIERS_PREVIEW) { + /* for object selection draws no shade */ + if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) { + /* TODO: draw basic faces with GPU_SHADER_3D_DEPTH_ONLY */ + } + else { + const float specular[3] = {0.47f, 0.47f, 0.47f}; + + /* draw outline */ + /* TODO: move this into a separate pass */ + if ((v3d->flag & V3D_SELECT_OUTLINE) && + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && + (base->flag & BASE_SELECTED) && + (draw_wire == OBDRAW_WIRE_OFF) && + (ob->sculpt == NULL)) + { + draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT(sl))); + } + + /* materials arent compatible with vertex colors */ + GPU_end_object_materials(); + + /* set default specular */ + GPU_basic_shader_colors(NULL, specular, 35, 1.0f); + GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); + + dm->drawMappedFaces(dm, NULL, NULL, NULL, NULL, DM_DRAW_USE_COLORS | DM_DRAW_NEED_NORMALS); + + GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + } + } + else { + Paint *p; + + if ((v3d->flag & V3D_SELECT_OUTLINE) && + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && + (base->flag & BASE_SELECTED) && + (draw_wire == OBDRAW_WIRE_OFF) && + (ob->sculpt == NULL)) + { + /* TODO: move this into a separate pass */ + draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT(sl))); + } + + glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + + if (ob->sculpt && (p = BKE_paint_get_active(scene, sl))) { + float planes[4][4]; + float (*fpl)[4] = NULL; + const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING); + + if (ob->sculpt->partial_redraw) { + if (ar->do_draw & RGN_DRAW_PARTIAL) { + ED_sculpt_redraw_planes_get(planes, ar, ob); + fpl = planes; + ob->sculpt->partial_redraw = 0; + } + } + + dm->drawFacesSolid(dm, fpl, fast, GPU_object_material_bind); + } + else + dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind); + + glFrontFace(GL_CCW); + + GPU_object_material_unbind(); + + if (!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + if ((dflag & DRAW_CONSTCOLOR) == 0) { + glColor3ubv(ob_wire_col); + } + glLineWidth(1.0f); + dm->drawLooseEdges(dm); + } + } + } + else if (dt == OB_PAINT) { + draw_mesh_paint(v3d, rv3d, ob, dm, draw_flags); + + /* since we already draw wire as wp guide, don't draw over the top */ + draw_wire = OBDRAW_WIRE_OFF; + } + + if ((draw_wire != OBDRAW_WIRE_OFF) && /* draw extra wire */ + /* when overriding with render only, don't bother */ + (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_SOLID) == 0)) // <-- is this "== 0" in the right spot??? + { + /* When using wireframe object draw in particle edit mode + * the mesh gets in the way of seeing the particles, fade the wire color + * with the background. */ + + if ((dflag & DRAW_CONSTCOLOR) == 0) { + /* TODO: + * Batch_UniformColor4ubv(ob_wire_col); + */ + } + + /* If drawing wire and drawtype is not OB_WIRE then we are + * overlaying the wires. + * + * No need for polygon offset because new technique is AWESOME. + */ +#if 0 + glLineWidth(1.0f); + dm->drawEdges(dm, ((dt == OB_WIRE) || no_faces), (ob->dtx & OB_DRAW_ALL_EDGES) != 0); +#else + /* something */ +#endif + } + +#if 0 // (merwin) what is this for? + if (is_obact && BKE_paint_select_vert_test(ob)) { + const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) != 0; + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + if (!use_depth) glDisable(GL_DEPTH_TEST); + else ED_view3d_polygon_offset(rv3d, 1.0); + drawSelectedVertices(dm, ob->data); + if (!use_depth) glEnable(GL_DEPTH_TEST); + else ED_view3d_polygon_offset(rv3d, 0.0); + } +#endif + + dm->release(dm); +} + +static bool UNUSED_FUNCTION(draw_mesh_object_new)(const bContext *C, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const unsigned char ob_wire_col[4], const short dflag) +{ + EvaluationContext eval_ctx; + Object *ob = base->object; + Object *obedit = scene->obedit; + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + bool do_alpha_after = false, drawlinked = false, retval = false; + + CTX_data_eval_ctx(C, &eval_ctx); + + if (v3d->flag2 & V3D_RENDER_SHADOW) { + /* TODO: handle shadow pass separately */ + return true; + } + + if (obedit && ob != obedit && ob->data == obedit->data) { + if (BKE_key_from_object(ob) || BKE_key_from_object(obedit)) {} + else if (ob->modifiers.first || obedit->modifiers.first) {} + else drawlinked = true; + } + + /* backface culling */ + const bool solid = dt > OB_WIRE; + const bool cullBackface = solid && (v3d->flag2 & V3D_BACKFACE_CULLING); + if (cullBackface) { + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + } + + if (ob == obedit || drawlinked) { + DerivedMesh *finalDM, *cageDM; + + if (obedit != ob) { + /* linked to the edit object */ + finalDM = cageDM = editbmesh_get_derived_base( + ob, em, scene->customdata_mask); + } + else { + cageDM = editbmesh_get_derived_cage_and_final( + &eval_ctx, scene, ob, em, scene->customdata_mask, + &finalDM); + } + + const bool use_material = solid && ((me->drawflag & ME_DRAWEIGHT) == 0); + +#if 0 // why update if not being used? + DM_update_materials(finalDM, ob); + if (cageDM != finalDM) { + DM_update_materials(cageDM, ob); + } +#endif // moved to below + + if (use_material) { + DM_update_materials(finalDM, ob); + if (cageDM != finalDM) { + DM_update_materials(cageDM, ob); + } + + const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); + + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL); + } + + draw_em_fancy_new(scene, ar, v3d, ob, me, em, cageDM, finalDM, dt); + + if (use_material) { + GPU_end_object_materials(); + } + + if (obedit != ob) + finalDM->release(finalDM); + } + else { + /* ob->bb was set by derived mesh system, do NULL check just to be sure */ + if (me->totpoly <= 4 || (!ob->bb || ED_view3d_boundbox_clip(rv3d, ob->bb))) { + if (solid) { + const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); + + if (dt == OB_SOLID || glsl) { + const bool check_alpha = check_alpha_pass(base); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, + (check_alpha) ? &do_alpha_after : NULL); + } + } + + const bool other_obedit = obedit && (obedit != ob); + + draw_mesh_fancy_new(&eval_ctx, scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag, other_obedit); + + GPU_end_object_materials(); + + if (me->totvert == 0) retval = true; + } + } + + if (cullBackface) + glDisable(GL_CULL_FACE); + + return retval; +} + /* ************** DRAW DISPLIST ****************** */ +static void drawDispListVerts(Gwn_PrimType prim_type, const void *data, unsigned int vert_ct, const unsigned char wire_col[3]) +{ + Gwn_VertFormat format = {0}; + unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vert_ct); + + GWN_vertbuf_attr_fill(vbo, pos_id, data); + + Gwn_Batch *batch = GWN_batch_create_ex(prim_type, vbo, NULL, GWN_BATCH_OWNS_VBO); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + if (wire_col) { + GWN_batch_uniform_4f(batch, "color", wire_col[0] / 255.0f, wire_col[1] / 255.0f, wire_col[2] / 255.0f, 1.0f); + } + GWN_batch_draw(batch); + GWN_batch_discard(batch); +} + +/* convert dispList with elem indices to batch, only support triangles and quads + * XXX : This is a huge perf issue. We should cache the resulting batches inside the object instead. + * But new viewport will do it anyway + * TODO implement flat drawing */ +static void drawDispListElem( + bool quads, bool UNUSED(smooth), bool ndata_is_single, + const float *data, const float *ndata, unsigned int data_len, + const int *elem, unsigned int elem_len, const unsigned char wire_col[3]) +{ + Gwn_VertFormat format = {0}; + int i; + const int *idx = elem; + unsigned int pos_id, nor_id; + + pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + if (ndata) { + if (ndata_is_single) { + /* pass */ + } + else { + nor_id = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + } + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, (quads) ? elem_len * 2 : elem_len, 0xffffffff); + + if (quads) { + for (i = elem_len; i; --i, idx += 4) { + GWN_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]); + GWN_indexbuf_add_tri_verts(&elb, idx[0], idx[2], idx[3]); + } + } + else { + for (i = elem_len; i; --i, idx += 3) { + GWN_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]); + } + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, data_len); + + GWN_vertbuf_attr_fill(vbo, pos_id, data); + + if (ndata) { + if (ndata_is_single) { + /* TODO: something like glNormal for a single value */ + } + else { + GWN_vertbuf_attr_fill(vbo, nor_id, ndata); + } + } + + Gwn_Batch *batch = GWN_batch_create_ex( + GWN_PRIM_TRIS, vbo, GWN_indexbuf_build(&elb), GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX); + GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING); + if (wire_col) { + GWN_batch_uniform_4f(batch, "color", wire_col[0] / 255.0f, wire_col[1] / 255.0f, wire_col[2] / 255.0f, 1.0f); + } + GWN_batch_uniform_4f(batch, "color", 0.8f, 0.8f, 0.8f, 1.0f); + GWN_batch_uniform_3f(batch, "light", 0.0f, 0.0f, 1.0f); + GWN_batch_draw(batch); + GWN_batch_discard(batch); +} /** * \param dl_type_mask Only draw types matching this mask. * \return true when nothing was drawn */ -static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask) +static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask, const unsigned char wire_col[3]) { if (dlbase == NULL) return true; - glEnableClientState(GL_VERTEX_ARRAY); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); for (DispList *dl = dlbase->first; dl; dl = dl->next) { @@ -4357,83 +5234,76 @@ static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask) if ((dl_type_mask & (1 << dl->type)) == 0) { continue; } - + const float *data = dl->verts; int parts; switch (dl->type) { case DL_SEGM: - - glVertexPointer(3, GL_FLOAT, 0, data); - for (parts = 0; parts < dl->parts; parts++) - glDrawArrays(GL_LINE_STRIP, parts * dl->nr, dl->nr); - + drawDispListVerts(GWN_PRIM_LINE_STRIP, data + (parts * dl->nr * 3), dl->nr, wire_col); break; - case DL_POLY: - - glVertexPointer(3, GL_FLOAT, 0, data); + case DL_POLY: for (parts = 0; parts < dl->parts; parts++) - glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr); - + drawDispListVerts(GWN_PRIM_LINE_LOOP, data + (parts * dl->nr * 3), dl->nr, wire_col); break; - case DL_SURF: - - glVertexPointer(3, GL_FLOAT, 0, data); + case DL_SURF: for (parts = 0; parts < dl->parts; parts++) { if (dl->flag & DL_CYCL_U) - glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr); + drawDispListVerts(GWN_PRIM_LINE_LOOP, data + (parts * dl->nr * 3), dl->nr, wire_col); else - glDrawArrays(GL_LINE_STRIP, parts * dl->nr, dl->nr); + drawDispListVerts(GWN_PRIM_LINE_STRIP, data + (parts * dl->nr * 3), dl->nr, wire_col); } + float *data_aligned = MEM_mallocN(sizeof(float) * 3 * dl->parts, "aligned data"); for (int nr = 0; nr < dl->nr; nr++) { int ofs = 3 * dl->nr; + int idx = 0; data = (dl->verts) + 3 * nr; parts = dl->parts; - if (dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP); - else glBegin(GL_LINE_STRIP); - while (parts--) { - glVertex3fv(data); + copy_v3_v3(data_aligned + idx, data); data += ofs; + idx += 3; } - glEnd(); -#if 0 - /* (ton) this code crashes for me when resolv is 86 or higher... no clue */ - glVertexPointer(3, GL_FLOAT, sizeof(float) * 3 * dl->nr, data + 3 * nr); - if (dl->flag & DL_CYCL_V) - glDrawArrays(GL_LINE_LOOP, 0, dl->parts); - else - glDrawArrays(GL_LINE_STRIP, 0, dl->parts); -#endif + if (dl->flag & DL_CYCL_V) + drawDispListVerts(GWN_PRIM_LINE_LOOP, data_aligned, dl->parts, wire_col); + else + drawDispListVerts(GWN_PRIM_LINE_STRIP, data_aligned, dl->parts, wire_col); } + + if (data_aligned) + MEM_freeN(data_aligned); + break; case DL_INDEX3: - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index); + drawDispListElem( + false, true, false, + dl->verts, NULL, dl->nr, + dl->index, dl->parts, wire_col); break; case DL_INDEX4: - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - glDrawElements(GL_QUADS, 4 * dl->parts, GL_UNSIGNED_INT, dl->index); + drawDispListElem( + true, true, false, + dl->verts, NULL, dl->nr, + dl->index, dl->parts, wire_col); break; } } - glDisableClientState(GL_VERTEX_ARRAY); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); return false; } -static bool drawDispListwire(ListBase *dlbase, const short ob_type) +static bool drawDispListwire(ListBase *dlbase, const short ob_type, const unsigned char wire_col[3]) { unsigned int dl_mask = 0xffffffff; @@ -4442,27 +5312,25 @@ static bool drawDispListwire(ListBase *dlbase, const short ob_type) dl_mask &= ~((1 << DL_INDEX3) | (1 << DL_INDEX4)); } - return drawDispListwire_ex(dlbase, dl_mask); + return drawDispListwire_ex(dlbase, dl_mask, wire_col); } static bool index3_nors_incr = true; -static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, +static void drawDispListsolid(ListBase *lb, Object *ob, const short UNUSED(dflag), const unsigned char ob_wire_col[4], const bool use_glsl) { GPUVertexAttribs gattribs; if (lb == NULL) return; - glEnableClientState(GL_VERTEX_ARRAY); - /* track current material, -1 for none (needed for lines) */ short col = -1; DispList *dl = lb->first; while (dl) { const float *data = dl->verts; - const float *ndata = dl->nors; + //const float *ndata = dl->nors; switch (dl->type) { case DL_SEGM: @@ -4472,15 +5340,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, col = -1; } - if ((dflag & DRAW_CONSTCOLOR) == 0) - glColor3ubv(ob_wire_col); - - // glVertexPointer(3, GL_FLOAT, 0, dl->verts); - // glDrawArrays(GL_LINE_STRIP, 0, dl->nr); - glBegin(GL_LINE_STRIP); - for (int nr = dl->nr; nr; nr--, data += 3) - glVertex3fv(data); - glEnd(); + drawDispListVerts(GWN_PRIM_LINE_STRIP, data, dl->nr, ob_wire_col); } break; case DL_POLY: @@ -4490,14 +5350,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, col = -1; } - /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */ - //glVertexPointer(3, GL_FLOAT, 0, dl->verts); - //glDrawArrays(GL_LINE_LOOP, 0, dl->nr); - - glBegin(GL_LINE_LOOP); - for (int nr = dl->nr; nr; nr--, data += 3) - glVertex3fv(data); - glEnd(); + drawDispListVerts(GWN_PRIM_LINE_LOOP, data, dl->nr, ob_wire_col); } break; case DL_SURF: @@ -4507,15 +5360,12 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, GPU_object_material_bind(dl->col + 1, use_glsl ? &gattribs : NULL); col = dl->col; } - /* FLAT/SMOOTH shading for surfaces */ - glShadeModel((dl->rt & CU_SMOOTH) ? GL_SMOOTH : GL_FLAT); + const unsigned int verts_len = dl->nr * dl->parts; - glEnableClientState(GL_NORMAL_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - glNormalPointer(GL_FLOAT, 0, dl->nors); - glDrawElements(GL_QUADS, 4 * dl->totindex, GL_UNSIGNED_INT, dl->index); - glDisableClientState(GL_NORMAL_ARRAY); - glShadeModel(GL_SMOOTH); + drawDispListElem( + true, (dl->rt & CU_SMOOTH) != 0, false, + dl->verts, dl->nors, verts_len, + dl->index, dl->totindex, ob_wire_col); } break; @@ -4525,8 +5375,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, col = dl->col; } - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - +#if 0 /* for polys only one normal needed */ if (index3_nors_incr) { glEnableClientState(GL_NORMAL_ARRAY); @@ -4534,11 +5383,17 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, } else glNormal3fv(ndata); +#endif + /* special case, 'nors' is a single value */ + drawDispListElem( + false, (dl->rt & CU_SMOOTH) != 0, true, + dl->verts, dl->nors, dl->nr, + dl->index, dl->parts, ob_wire_col); - glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index); - +#if 0 if (index3_nors_incr) glDisableClientState(GL_NORMAL_ARRAY); +#endif break; @@ -4548,18 +5403,16 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, col = dl->col; } - glEnableClientState(GL_NORMAL_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - glNormalPointer(GL_FLOAT, 0, dl->nors); - glDrawElements(GL_QUADS, 4 * dl->parts, GL_UNSIGNED_INT, dl->index); - glDisableClientState(GL_NORMAL_ARRAY); + drawDispListElem( + true, true, false, + dl->verts, dl->nors, dl->nr, + dl->index, dl->parts, ob_wire_col); break; } dl = dl->next; } - glDisableClientState(GL_VERTEX_ARRAY); glFrontFace(GL_CCW); if (col != -1) { @@ -4574,7 +5427,7 @@ static void drawCurveDMWired(Object *ob) } /* return true when nothing was drawn */ -static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt) +static bool drawCurveDerivedMesh(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt) { Object *ob = base->object; DerivedMesh *dm = ob->derivedFinal; @@ -4588,8 +5441,8 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); if (dt > OB_WIRE && dm->getNumPolys(dm)) { - bool glsl = draw_glsl_material(scene, ob, v3d, dt); - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL); if (!glsl) dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind); @@ -4610,7 +5463,7 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, * Only called by #drawDispList * \return true when nothing was drawn */ -static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool drawDispList_nobackface(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; @@ -4640,10 +5493,10 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 if (!render_only) { /* when we have faces, only draw loose-wire */ if (has_faces) { - drawDispListwire_ex(lb, (1 << DL_SEGM)); + drawDispListwire_ex(lb, (1 << DL_SEGM), ob_wire_col); } else { - drawDispListwire(lb, ob->type); + drawDispListwire(lb, ob->type, ob_wire_col); } } @@ -4651,26 +5504,26 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 /* pass */ } else { - if (draw_glsl_material(scene, ob, v3d, dt)) { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); + if (draw_glsl_material(scene, sl, ob, v3d, dt)) { + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 1, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, true); GPU_end_object_materials(); } else { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 0, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, false); GPU_end_object_materials(); } if (cu->editnurb && cu->bevobj == NULL && cu->taperobj == NULL && cu->ext1 == 0.0f && cu->ext2 == 0.0f) { - cpack(0); - drawDispListwire(lb, ob->type); + unsigned char col[4] = {0, 0, 0, 0}; + drawDispListwire(lb, ob->type, col); } } index3_nors_incr = true; } else { if (!render_only || BKE_displist_has_faces(lb)) { - return drawDispListwire(lb, ob->type); + return drawDispListwire(lb, ob->type, ob_wire_col); } } break; @@ -4686,19 +5539,19 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 if (dl->nors == NULL) BKE_displist_normals_add(lb); - if (draw_glsl_material(scene, ob, v3d, dt)) { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); + if (draw_glsl_material(scene, sl, ob, v3d, dt)) { + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 1, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, true); GPU_end_object_materials(); } else { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 0, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, false); GPU_end_object_materials(); } } else { - return drawDispListwire(lb, ob->type); + return drawDispListwire(lb, ob->type, ob_wire_col); } break; case OB_MBALL: @@ -4711,19 +5564,19 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 if (solid) { - if (draw_glsl_material(scene, ob, v3d, dt)) { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); + if (draw_glsl_material(scene, sl, ob, v3d, dt)) { + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 1, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, true); GPU_end_object_materials(); } else { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 0, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, false); GPU_end_object_materials(); } } else { - return drawDispListwire(lb, ob->type); + return drawDispListwire(lb, ob->type, ob_wire_col); } } break; @@ -4731,8 +5584,9 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 return false; } -static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const char dt, const short dflag, const unsigned char ob_wire_col[4]) +static bool drawDispList( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { bool retval; @@ -4744,10 +5598,10 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba } #ifdef SEQUENCER_DAG_WORKAROUND - ensure_curve_cache(scene, base->object); + ensure_curve_cache(eval_ctx, scene, base->object); #endif - if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == false) { + if (drawCurveDerivedMesh(scene, sl, v3d, rv3d, base, dt) == false) { retval = false; } else { @@ -4763,7 +5617,7 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba glFrontFace(mode); - retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + retval = drawDispList_nobackface(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); if (mode != GL_CCW) { glFrontFace(GL_CCW); @@ -4778,16 +5632,63 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba } /* *********** drawing for particles ************* */ -static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int select) +/* stride : offset size in bytes + * col[4] : the color to use when *color is NULL, can be also NULL */ +static void draw_vertex_array(Gwn_PrimType prim_type, const float *vert, const float *nor, const float *color, int stride, int vert_ct, float col[4]) +{ + Gwn_VertFormat format = {0}; + unsigned int pos_id, nor_id, col_id; + pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + if (nor) nor_id = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + if (color) col_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vert_ct); + + if (stride == 0) { + GWN_vertbuf_attr_fill(vbo, pos_id, vert); + if (nor) GWN_vertbuf_attr_fill(vbo, nor_id, nor); + if (color) GWN_vertbuf_attr_fill(vbo, col_id, color); + } + else { + GWN_vertbuf_attr_fill_stride(vbo, pos_id, stride, vert); + if (nor) GWN_vertbuf_attr_fill_stride(vbo, nor_id, stride, nor); + if (color) GWN_vertbuf_attr_fill_stride(vbo, col_id, stride, color); + } + + Gwn_Batch *batch = GWN_batch_create_ex(prim_type, vbo, NULL, GWN_BATCH_OWNS_VBO); + if (nor && color) { + GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR); + GWN_batch_uniform_3f(batch, "light", 0.0f, 0.0f, 1.0f); + } + else if (nor) { + GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING); + GWN_batch_uniform_3f(batch, "light", 0.0f, 0.0f, 1.0f); + if (col) GWN_batch_uniform_4fv(batch, "color", col); + } + else if (color) { + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_SMOOTH_COLOR); + } + else { + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + if (col) GWN_batch_uniform_4fv(batch, "color", col); + } + GWN_batch_draw(batch); + GWN_batch_discard(batch); +} + +static void draw_particle_arrays_new(int draw_as, int ob_dt, int select, + const float *vert, const float *nor, const float *color, + int totpoint, float col[4]) { /* draw created data arrays */ switch (draw_as) { case PART_DRAW_AXIS: case PART_DRAW_CROSS: - glDrawArrays(GL_LINES, 0, 6 * totpoint); + draw_vertex_array(GWN_PRIM_LINES, vert, nor, color, 0, 6 * totpoint, col); break; case PART_DRAW_LINE: - glDrawArrays(GL_LINES, 0, 2 * totpoint); + draw_vertex_array(GWN_PRIM_LINES, vert, nor, color, 0, 2 * totpoint, col); break; case PART_DRAW_BB: if (ob_dt <= OB_WIRE || select) @@ -4795,15 +5696,16 @@ static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int selec else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glDrawArrays(GL_QUADS, 0, 4 * totpoint); + draw_vertex_array(GWN_PRIM_TRIS, vert, nor, color, 0, 6 * totpoint, col); break; default: - glDrawArrays(GL_POINTS, 0, totpoint); + draw_vertex_array(GWN_PRIM_POINTS, vert, nor, color, 0, totpoint, col); break; } } static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize, - float imat[4][4], const float draw_line[2], ParticleBillboardData *bb, ParticleDrawData *pdd) + float imat[4][4], const float draw_line[2], ParticleBillboardData *bb, ParticleDrawData *pdd, + unsigned int pos) { float vec[3], vec2[3]; float *vd = NULL; @@ -4913,24 +5815,19 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix } case PART_DRAW_CIRC: { - drawcircball(GL_LINE_LOOP, state->co, pixsize, imat); + imm_drawcircball(state->co, pixsize, imat, pos); break; } case PART_DRAW_BB: { float xvec[3], yvec[3], zvec[3], bb_center[3]; - if (cd) { - cd[0] = cd[3] = cd[6] = cd[9] = ma_col[0]; - cd[1] = cd[4] = cd[7] = cd[10] = ma_col[1]; - cd[2] = cd[5] = cd[8] = cd[11] = ma_col[2]; - pdd->cd += 12; - } copy_v3_v3(bb->vec, state->co); copy_v3_v3(bb->vel, state->vel); psys_make_billboard(bb, xvec, yvec, zvec, bb_center); - + + /* First tri */ add_v3_v3v3(pdd->vd, bb_center, xvec); add_v3_v3(pdd->vd, yvec); pdd->vd += 3; @@ -4940,13 +5837,24 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix sub_v3_v3v3(pdd->vd, bb_center, xvec); sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3; + /* Second tri */ + add_v3_v3v3(pdd->vd, bb_center, xvec); + add_v3_v3(pdd->vd, yvec); pdd->vd += 3; + + sub_v3_v3v3(pdd->vd, bb_center, xvec); + sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3; + add_v3_v3v3(pdd->vd, bb_center, xvec); sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3; - copy_v3_v3(pdd->nd, zvec); pdd->nd += 3; - copy_v3_v3(pdd->nd, zvec); pdd->nd += 3; - copy_v3_v3(pdd->nd, zvec); pdd->nd += 3; - copy_v3_v3(pdd->nd, zvec); pdd->nd += 3; + if (cd) { + for (int i = 0; i < 6; i++, cd += 3, pdd->cd += 3) { + copy_v3_v3(cd, ma_col); + } + } + for (int i = 0; i < 6; i++, pdd->nd += 3) { + copy_v3_v3(pdd->nd, zvec); + } break; } } @@ -4954,7 +5862,8 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d, ParticleKey *state, int draw_as, float imat[4][4], ParticleBillboardData *bb, ParticleDrawData *pdd, - const float ct, const float pa_size, const float r_tilt, const float pixsize_scale) + const float ct, const float pa_size, const float r_tilt, const float pixsize_scale, + unsigned int pos) { ParticleSettings *part = psys->part; float pixsize; @@ -4985,7 +5894,7 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d, pixsize = ED_view3d_pixel_size(rv3d, state->co) * pixsize_scale; - draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd); + draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd, pos); } /* unified drawing of all new particle systems draw types except dupli ob & group * mostly tries to use vertex arrays for speed @@ -4998,9 +5907,10 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d, * 6. draw the arrays * 7. clean up */ -static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d, - Base *base, ParticleSystem *psys, - const char ob_dt, const short dflag) +static void draw_new_particle_system( + const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d, + Base *base, ParticleSystem *psys, + const char ob_dt, const short dflag) { Object *ob = base->object; ParticleEditSettings *pset = PE_settings(scene); @@ -5018,10 +5928,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv float cfra; float ma_col[3] = {0.0f, 0.0f, 0.0f}; int a, totpart, totpoint = 0, totve = 0, drawn, draw_as, totchild = 0; - bool select = (ob->flag & SELECT) != 0, create_cdata = false, need_v = false; + bool select = (base->flag & BASE_SELECTED) != 0, create_cdata = false, need_v = false; GLint polygonmode[2]; char numstr[32]; unsigned char tcol[4] = {0, 0, 0, 255}; + unsigned int pos; /* 1. */ if (part == NULL || !psys_check_enabled(ob, psys, G.is_rendering)) @@ -5030,7 +5941,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if (pars == NULL) return; /* don't draw normal paths in edit mode */ - if (psys_in_edit_mode(scene, psys) && (pset->flag & PE_DRAW_PART) == 0) + if (psys_in_edit_mode(eval_ctx->scene_layer, psys) && (pset->flag & PE_DRAW_PART) == 0) return; if (part->draw_as == PART_DRAW_REND) @@ -5048,6 +5959,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv curvemapping_changed_all(psys->part->roughcurve); /* 2. */ + sim.eval_ctx = eval_ctx; sim.scene = scene; sim.ob = ob; sim.psys = psys; @@ -5083,16 +5995,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv copy_v3_v3(ma_col, &ma->r); } - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(tcol); - } - timestep = psys_get_timestep(&sim); - if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) { + if ((ob->flag & OB_FROMGROUP) != 0) { float mat[4][4]; mul_m4_m4m4(mat, ob->obmat, psys->imat); - glMultMatrixf(mat); + gpuMultMatrix(mat); } /* needed for text display */ @@ -5212,7 +6120,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv tot_vec_size *= 2; break; case PART_DRAW_BB: - tot_vec_size *= 4; + tot_vec_size *= 6; /* New OGL only understands tris, no choice here. */ create_ndata = 1; break; } @@ -5266,6 +6174,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv totpoint = pdd->totpoint; /* draw data is up to date */ } else { + if ((draw_as == PART_DRAW_CIRC) || (part->draw & PART_DRAW_SIZE)) { + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + imm_cpack(0xFFFFFF); + } for (a = 0, pa = pars; a < totpart + totchild; a++, pa++) { /* setup per particle individual stuff */ if (a < totpart) { @@ -5336,7 +6249,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv draw_particle_data(psys, rv3d, &state, draw_as, imat, &bb, psys->pdd, - ct, pa_size, r_tilt, pixsize_scale); + ct, pa_size, r_tilt, pixsize_scale, pos); totpoint++; drawn = 1; @@ -5348,7 +6261,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv draw_particle_data(psys, rv3d, &state, draw_as, imat, &bb, psys->pdd, - pa_time, pa_size, r_tilt, pixsize_scale); + pa_time, pa_size, r_tilt, pixsize_scale, pos); totpoint++; drawn = 1; @@ -5370,7 +6283,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if (part->draw & PART_DRAW_SIZE) { setlinestyle(3); - drawcircball(GL_LINE_LOOP, state.co, pa_size, imat); + imm_drawcircball(state.co, pa_size, imat, pos); setlinestyle(0); } @@ -5407,31 +6320,19 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv } } } + if ((draw_as == PART_DRAW_CIRC) || (part->draw & PART_DRAW_SIZE)) { + immUnbindProgram(); + } } } /* 6. */ glGetIntegerv(GL_POLYGON_MODE, polygonmode); - glEnableClientState(GL_VERTEX_ARRAY); if (draw_as == PART_DRAW_PATH) { ParticleCacheKey **cache, *path; float *cdata2 = NULL; - /* setup gl flags */ - if (1) { //ob_dt > OB_WIRE) { - glEnableClientState(GL_NORMAL_ARRAY); - - if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (part->draw_col == PART_DRAW_COL_MAT) - glEnableClientState(GL_COLOR_ARRAY); - } - - // XXX test - GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f); - GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); - } - if (totchild && (part->draw & PART_DRAW_PARENT) == 0) totpart = 0; else if (psys->pathcache == NULL) @@ -5442,41 +6343,28 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { path = cache[a]; if (path->segments > 0) { - glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co); - - if (1) { //ob_dt > OB_WIRE) { - glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel); - if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (part->draw_col == PART_DRAW_COL_MAT) { - glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col); - } - } + if (((dflag & DRAW_CONSTCOLOR) == 0) && (part->draw_col == PART_DRAW_COL_MAT)) { + draw_vertex_array(GWN_PRIM_LINE_STRIP, path->co, path->vel, path->col, sizeof(ParticleCacheKey), path->segments + 1, NULL); + } + else { + float color[4]; + rgba_uchar_to_float(color, tcol); + draw_vertex_array(GWN_PRIM_LINE_STRIP, path->co, path->vel, NULL, sizeof(ParticleCacheKey), path->segments + 1, color); } - - glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1); } } if (part->type == PART_HAIR) { if (part->draw & PART_DRAW_GUIDE_HAIRS) { DerivedMesh *hair_dm = psys->hair_out_dm; - - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - + for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { if (pa->totkey > 1) { HairKey *hkey = pa->hair; - glVertexPointer(3, GL_FLOAT, sizeof(HairKey), hkey->world_co); - -#if 0 /* XXX use proper theme color here */ - UI_ThemeColor(TH_NORMAL); -#else - glColor3f(0.58f, 0.67f, 1.0f); -#endif - - glDrawArrays(GL_LINE_STRIP, 0, pa->totkey); + /* XXX use proper theme color here */ + float color[4] = {0.58f, 0.67f, 1.0f, 1.0f}; + draw_vertex_array(GWN_PRIM_LINE_STRIP, hkey->world_co, NULL, NULL, sizeof(HairKey), pa->totkey, color); } } @@ -5484,30 +6372,36 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv MVert *mvert = hair_dm->getVertArray(hair_dm); int i; - glColor3f(0.9f, 0.4f, 0.4f); - - glBegin(GL_LINES); + unsigned int pos_id = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3f(0.9f, 0.4f, 0.4f); + + unsigned int count = 0; for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { - for (i = 1; i < pa->totkey; ++i) { - float v1[3], v2[3]; - - copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co); - copy_v3_v3(v2, mvert[pa->hair_index + i].co); - - mul_m4_v3(ob->obmat, v1); - mul_m4_v3(ob->obmat, v2); - - glVertex3fv(v1); - glVertex3fv(v2); + count += MAX2(pa->totkey - 1, 0); + } + + if (count > 0) { + immBegin(GWN_PRIM_LINES, count * 2); + for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { + for (i = 1; i < pa->totkey; ++i) { + float v1[3], v2[3]; + + copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co); + copy_v3_v3(v2, mvert[pa->hair_index + i].co); + + mul_m4_v3(ob->obmat, v1); + mul_m4_v3(ob->obmat, v2); + + immVertex3fv(pos_id, v1); + immVertex3fv(pos_id, v2); + } } + immEnd(); } - glEnd(); + + immUnbindProgram(); } - - glEnableClientState(GL_NORMAL_ARRAY); - if ((dflag & DRAW_CONSTCOLOR) == 0) - if (part->draw_col == PART_DRAW_COL_MAT) - glEnableClientState(GL_COLOR_ARRAY); } if (part->draw & PART_DRAW_HAIR_GRID) { @@ -5518,64 +6412,69 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv int *res = clmd->hair_grid_res; int i; - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - + unsigned int pos_id = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); if (select) - UI_ThemeColor(TH_ACTIVE); + immUniformThemeColor(TH_ACTIVE); else - UI_ThemeColor(TH_WIRE); - glBegin(GL_LINES); - glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmin[2]); - glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmin[2]); - glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmin[2]); - glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmin[2]); + immUniformThemeColor(TH_WIRE); + + immBegin(GWN_PRIM_LINES, 24); + immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]); + immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]); + immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]); + immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]); - glVertex3f(gmin[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmin[1], gmax[2]); - glVertex3f(gmax[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmax[1], gmax[2]); - glVertex3f(gmax[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmax[1], gmax[2]); - glVertex3f(gmin[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmin[1], gmax[2]); + immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]); + immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]); + immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]); + immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]); - glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmax[2]); - glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmax[2]); - glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmax[2]); - glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmax[2]); - glEnd(); + immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]); + immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]); + immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]); + immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]); + immEnd(); if (select) - UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -100); + immUniformThemeColorShadeAlpha(TH_ACTIVE, 0, -100); else - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -100); - glEnable(GL_BLEND); - glBegin(GL_LINES); - for (i = 1; i < res[0] - 1; ++i) { - float f = interpf(gmax[0], gmin[0], (float)i / (float)(res[0] - 1)); - glVertex3f(f, gmin[1], gmin[2]); glVertex3f(f, gmax[1], gmin[2]); - glVertex3f(f, gmax[1], gmin[2]); glVertex3f(f, gmax[1], gmax[2]); - glVertex3f(f, gmax[1], gmax[2]); glVertex3f(f, gmin[1], gmax[2]); - glVertex3f(f, gmin[1], gmax[2]); glVertex3f(f, gmin[1], gmin[2]); - } - for (i = 1; i < res[1] - 1; ++i) { - float f = interpf(gmax[1], gmin[1], (float)i / (float)(res[1] - 1)); - glVertex3f(gmin[0], f, gmin[2]); glVertex3f(gmax[0], f, gmin[2]); - glVertex3f(gmax[0], f, gmin[2]); glVertex3f(gmax[0], f, gmax[2]); - glVertex3f(gmax[0], f, gmax[2]); glVertex3f(gmin[0], f, gmax[2]); - glVertex3f(gmin[0], f, gmax[2]); glVertex3f(gmin[0], f, gmin[2]); - } - for (i = 1; i < res[2] - 1; ++i) { - float f = interpf(gmax[2], gmin[2], (float)i / (float)(res[2] - 1)); - glVertex3f(gmin[0], gmin[1], f); glVertex3f(gmax[0], gmin[1], f); - glVertex3f(gmax[0], gmin[1], f); glVertex3f(gmax[0], gmax[1], f); - glVertex3f(gmax[0], gmax[1], f); glVertex3f(gmin[0], gmax[1], f); - glVertex3f(gmin[0], gmax[1], f); glVertex3f(gmin[0], gmin[1], f); + immUniformThemeColorShadeAlpha(TH_WIRE, 0, -100); + + int count = 0; + count += MAX2(0, res[0] - 2) * 8; + count += MAX2(0, res[1] - 2) * 8; + count += MAX2(0, res[2] - 2) * 8; + + if (count >= 2) { + glEnable(GL_BLEND); + immBegin(GWN_PRIM_LINES, count); + for (i = 1; i < res[0] - 1; ++i) { + float f = interpf(gmax[0], gmin[0], (float)i / (float)(res[0] - 1)); + immVertex3f(pos_id, f, gmin[1], gmin[2]); immVertex3f(pos_id, f, gmax[1], gmin[2]); + immVertex3f(pos_id, f, gmax[1], gmin[2]); immVertex3f(pos_id, f, gmax[1], gmax[2]); + immVertex3f(pos_id, f, gmax[1], gmax[2]); immVertex3f(pos_id, f, gmin[1], gmax[2]); + immVertex3f(pos_id, f, gmin[1], gmax[2]); immVertex3f(pos_id, f, gmin[1], gmin[2]); + } + for (i = 1; i < res[1] - 1; ++i) { + float f = interpf(gmax[1], gmin[1], (float)i / (float)(res[1] - 1)); + immVertex3f(pos_id, gmin[0], f, gmin[2]); immVertex3f(pos_id, gmax[0], f, gmin[2]); + immVertex3f(pos_id, gmax[0], f, gmin[2]); immVertex3f(pos_id, gmax[0], f, gmax[2]); + immVertex3f(pos_id, gmax[0], f, gmax[2]); immVertex3f(pos_id, gmin[0], f, gmax[2]); + immVertex3f(pos_id, gmin[0], f, gmax[2]); immVertex3f(pos_id, gmin[0], f, gmin[2]); + } + for (i = 1; i < res[2] - 1; ++i) { + float f = interpf(gmax[2], gmin[2], (float)i / (float)(res[2] - 1)); + immVertex3f(pos_id, gmin[0], gmin[1], f); immVertex3f(pos_id, gmax[0], gmin[1], f); + immVertex3f(pos_id, gmax[0], gmin[1], f); immVertex3f(pos_id, gmax[0], gmax[1], f); + immVertex3f(pos_id, gmax[0], gmax[1], f); immVertex3f(pos_id, gmin[0], gmax[1], f); + immVertex3f(pos_id, gmin[0], gmax[1], f); immVertex3f(pos_id, gmin[0], gmin[1], f); + } + immEnd(); + glDisable(GL_BLEND); } - glEnd(); - glDisable(GL_BLEND); - - glEnableClientState(GL_NORMAL_ARRAY); - if ((dflag & DRAW_CONSTCOLOR) == 0) - if (part->draw_col == PART_DRAW_COL_MAT) - glEnableClientState(GL_COLOR_ARRAY); + + immUnbindProgram(); } } } @@ -5584,27 +6483,17 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv cache = psys->childcache; for (a = 0; a < totchild; a++) { path = cache[a]; - glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co); - if (1) { //ob_dt > OB_WIRE) { - glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel); - if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (part->draw_col == PART_DRAW_COL_MAT) { - glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col); - } - } + if (((dflag & DRAW_CONSTCOLOR) == 0) && (part->draw_col == PART_DRAW_COL_MAT)) { + draw_vertex_array(GWN_PRIM_LINE_STRIP, path->co, path->vel, path->col, sizeof(ParticleCacheKey), path->segments + 1, NULL); + } + else { + float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + draw_vertex_array(GWN_PRIM_LINE_STRIP, path->co, path->vel, NULL, sizeof(ParticleCacheKey), path->segments + 1, color); } - - glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1); } /* restore & clean up */ - if (1) { //ob_dt > OB_WIRE) { - if (part->draw_col == PART_DRAW_COL_MAT) - glDisableClientState(GL_COLOR_ARRAY); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } - if (cdata2) { MEM_freeN(cdata2); cdata2 = NULL; @@ -5624,19 +6513,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv } } else if (pdd && ELEM(draw_as, 0, PART_DRAW_CIRC) == 0) { - glDisableClientState(GL_COLOR_ARRAY); - /* enable point data array */ if (pdd->vdata) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, pdd->vdata); - } - else - glDisableClientState(GL_VERTEX_ARRAY); - - if ((dflag & DRAW_CONSTCOLOR) == 0) { if (select) { - UI_ThemeColor(TH_ACTIVE); + float color[4]; + UI_GetThemeColor4fv(TH_ACTIVE, color); if (part->draw_size) glPointSize(part->draw_size + 2); @@ -5645,48 +6526,39 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glLineWidth(3.0); - draw_particle_arrays(draw_as, totpoint, ob_dt, 1); + draw_particle_arrays_new(draw_as, ob_dt, 1, pdd->vdata, NULL, NULL, totpoint, color); } - /* restore from select */ - glColor3fv(ma_col); - } - - glPointSize(part->draw_size ? part->draw_size : 2.0); - glLineWidth(1.0); + glPointSize(part->draw_size ? part->draw_size : 2.0); + glLineWidth(1.0); - /* enable other data arrays */ - /* billboards are drawn this way */ - if (pdd->ndata && ob_dt > OB_WIRE) { - glEnableClientState(GL_NORMAL_ARRAY); - glNormalPointer(GL_FLOAT, 0, pdd->ndata); - GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f); - GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); - } - - if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (pdd->cdata) { - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(3, GL_FLOAT, 0, pdd->cdata); +#if 0 + /* enable other data arrays */ + /* billboards are drawn this way */ + if (pdd->ndata && ob_dt > OB_WIRE) { + GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f); + GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); } + if ((dflag & DRAW_CONSTCOLOR) == 0) { + if (pdd->cdata) { + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(3, GL_FLOAT, 0, pdd->cdata); + } + } +#endif + + draw_particle_arrays_new(draw_as, ob_dt, 0, pdd->vdata, pdd->ndata, pdd->cdata, totpoint, NULL); } - draw_particle_arrays(draw_as, totpoint, ob_dt, 0); pdd->flag |= PARTICLE_DRAW_DATA_UPDATED; pdd->totpoint = totpoint; } if (pdd && pdd->vedata) { - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glDisableClientState(GL_COLOR_ARRAY); - cpack(0xC0C0C0); - } - - glVertexPointer(3, GL_FLOAT, 0, pdd->vedata); - - glDrawArrays(GL_LINES, 0, 2 * totve); + float color[4] = {0.75f, 0.75f, 0.75f, 1.0f}; + draw_vertex_array(GWN_PRIM_LINES, pdd->vedata, NULL, NULL, 0, 2 * totve, color); } glPolygonMode(GL_FRONT, polygonmode[0]); @@ -5695,9 +6567,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv /* 7. */ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); if (states) MEM_freeN(states); @@ -5720,32 +6589,28 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pdd->ma_col = NULL; } - if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) { - glLoadMatrixf(rv3d->viewmat); + if ((ob->flag & OB_FROMGROUP) != 0) { + gpuLoadMatrix(rv3d->viewmat); } } -static void draw_update_ptcache_edit(Scene *scene, Object *ob, PTCacheEdit *edit) +static void draw_update_ptcache_edit( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, Object *ob, PTCacheEdit *edit) { if (edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED) - PE_update_object(scene, ob, 0); + PE_update_object(eval_ctx, scene, sl, ob, 0); /* create path and child path cache if it doesn't exist already */ - if (edit->pathcache == NULL) - psys_cache_edit_paths(scene, ob, edit, CFRA, G.is_rendering); + if (edit->pathcache == NULL) { + psys_cache_edit_paths(eval_ctx, scene, ob, edit, CFRA, G.is_rendering); + } } static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) { - ParticleCacheKey **cache, *path, *pkey; - PTCacheEditPoint *point; - PTCacheEditKey *key; ParticleEditSettings *pset = PE_settings(scene); - int i, k, totpoint = edit->totpoint, timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : 0; - int totkeys = 1; - float sel_col[3]; - float nosel_col[3]; - float *pathcol = NULL, *pcol; + const int totpoint = edit->totpoint; + const bool timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : false; if (edit->pathcache == NULL) return; @@ -5757,50 +6622,71 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) glDisable(GL_DEPTH_TEST); /* get selection theme colors */ + float sel_col[3], nosel_col[3]; UI_GetThemeColor3fv(TH_VERTEX_SELECT, sel_col); UI_GetThemeColor3fv(TH_VERTEX, nosel_col); /* draw paths */ - totkeys = (*edit->pathcache)->segments + 1; + const int totkeys = (*edit->pathcache)->segments + 1; glEnable(GL_BLEND); - pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data"); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); + float *pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data"); if (pset->brushtype == PE_BRUSH_WEIGHT) glLineWidth(2.0f); - cache = edit->pathcache; + ParticleCacheKey **cache = edit->pathcache; + PTCacheEditPoint *point; + int i; + for (i = 0, point = edit->points; i < totpoint; i++, point++) { - path = cache[i]; - glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co); + ParticleCacheKey *path = cache[i]; + + Gwn_VertFormat format = {0}; + unsigned int pos_id, col_id, col_comp; + + col_comp = ((point->flag & PEP_HIDE) || timed) ? 4 : 3; + + pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + col_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, col_comp, GWN_FETCH_FLOAT); + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, path->segments + 1); + + GWN_vertbuf_attr_fill_stride(vbo, pos_id, sizeof(ParticleCacheKey), path->co); + + float *pcol = pathcol; if (point->flag & PEP_HIDE) { - for (k = 0, pcol = pathcol; k < totkeys; k++, pcol += 4) { + for (int k = 0; k < totkeys; k++, pcol += 4) { copy_v3_v3(pcol, path->col); pcol[3] = 0.25f; } - glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol); + GWN_vertbuf_attr_fill(vbo, col_id, pathcol); } else if (timed) { - for (k = 0, pcol = pathcol, pkey = path; k < totkeys; k++, pkey++, pcol += 4) { + ParticleCacheKey *pkey = path; + for (int k = 0; k < totkeys; k++, pkey++, pcol += 4) { copy_v3_v3(pcol, pkey->col); pcol[3] = 1.0f - fabsf((float)(CFRA) -pkey->time) / (float)pset->fade_frames; } - glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol); + GWN_vertbuf_attr_fill(vbo, col_id, pathcol); + } + else { + /* FIXME: shader wants 4 color components but the cache only contains ParticleCacheKey + * So alpha is random */ + GWN_vertbuf_attr_fill_stride(vbo, col_id, sizeof(ParticleCacheKey), path->col); } - else - glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col); - glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1); + Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_LINE_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_SMOOTH_COLOR); + GWN_batch_draw(batch); + GWN_batch_discard(batch); } - if (pathcol) { MEM_freeN(pathcol); pathcol = pcol = NULL; } - + if (pathcol) { MEM_freeN(pathcol); pathcol = NULL; } /* draw edit vertices */ if (pset->selectmode != SCE_SELECT_PATH) { @@ -5811,6 +6697,10 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) float *cd = NULL, *cdata = NULL; int totkeys_visible = 0; + Gwn_VertFormat format = {0}; + unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int col_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, (timed ? 4 : 3), GWN_FETCH_FLOAT); + for (i = 0, point = edit->points; i < totpoint; i++, point++) if (!(point->flag & PEP_HIDE)) totkeys_visible += point->totkey; @@ -5825,7 +6715,8 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) if (point->flag & PEP_HIDE) continue; - for (k = 0, key = point->keys; k < point->totkey; k++, key++) { + PTCacheEditKey *key = point->keys; + for (int k = 0; k < point->totkey; k++, key++) { if (pd) { copy_v3_v3(pd, key->co); pd += 3; @@ -5850,14 +6741,20 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) if (point->flag & PEP_HIDE || point->totkey == 0) continue; + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, point->totkey); + if (point->keys->flag & PEK_USE_WCO) - glVertexPointer(3, GL_FLOAT, sizeof(PTCacheEditKey), point->keys->world_co); + GWN_vertbuf_attr_fill_stride(vbo, pos_id, sizeof(PTCacheEditKey), point->keys->world_co); else - glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), pd); + GWN_vertbuf_attr_fill(vbo, pos_id, pd); - glColorPointer((timed ? 4 : 3), GL_FLOAT, (timed ? 4 : 3) * sizeof(float), cd); + GWN_vertbuf_attr_fill(vbo, col_id, cd); - glDrawArrays(GL_POINTS, 0, point->totkey); + Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_SMOOTH_COLOR); + GWN_batch_draw(batch); + GWN_batch_discard(batch); pd += pd ? 3 * point->totkey : 0; cd += (timed ? 4 : 3) * point->totkey; @@ -5866,23 +6763,30 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) if (cdata) { MEM_freeN(cdata); cd = cdata = NULL; } } else if (pset->selectmode == SCE_SELECT_END) { - glBegin(GL_POINTS); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int col_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + immBeginAtMost(GWN_PRIM_POINTS, totpoint); for (i = 0, point = edit->points; i < totpoint; i++, point++) { if ((point->flag & PEP_HIDE) == 0 && point->totkey) { - key = point->keys + point->totkey - 1; - glColor3fv((key->flag & PEK_SELECT) ? sel_col : nosel_col); + PTCacheEditKey *key = point->keys + point->totkey - 1; + if ((key->flag & PEK_SELECT) != 0) { + immAttrib3fv(col_id, sel_col); + } + else { + immAttrib3fv(col_id, nosel_col); + } /* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/ - glVertex3fv((key->flag & PEK_USE_WCO) ? key->world_co : key->co); + immVertex3fv(pos_id, (key->flag & PEK_USE_WCO) ? key->world_co : key->co); } } - glEnd(); + immEnd(); + immUnbindProgram(); } } glDisable(GL_BLEND); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } @@ -5895,130 +6799,137 @@ static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, flo float tw = itw * drw_size; float th = ith * drw_size; - glBegin(GL_LINES); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + immBegin(GWN_PRIM_LINES, 30); - glColor4ub(0x7F, 0x00, 0x00, 155); + immAttrib4ub(col, 0x7F, 0x00, 0x00, 155); root[1] = root[2] = 0.0f; root[0] = -drw_size; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); + immVertex3fv(pos, root); tip[1] = tip[2] = 0.0f; tip[0] = drw_size; mul_m3_v3(tr, tip); add_v3_v3(tip, com); - glVertex3fv(tip); + immVertex3fv(pos, tip); root[1] = 0.0f; root[2] = tw; root[0] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[1] = 0.0f; root[2] = -tw; root[0] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[1] = tw; root[2] = 0.0f; root[0] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[1] = -tw; root[2] = 0.0f; root[0] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); - glColor4ub(0x00, 0x7F, 0x00, 155); + immAttrib4ub(col, 0x00, 0x7F, 0x00, 155); root[0] = root[2] = 0.0f; root[1] = -drw_size; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); + immVertex3fv(pos, root); tip[0] = tip[2] = 0.0f; tip[1] = drw_size; mul_m3_v3(tr, tip); add_v3_v3(tip, com); - glVertex3fv(tip); + immVertex3fv(pos, tip); root[0] = 0.0f; root[2] = tw; root[1] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = 0.0f; root[2] = -tw; root[1] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = tw; root[2] = 0.0f; root[1] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = -tw; root[2] = 0.0f; root[1] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); - glColor4ub(0x00, 0x00, 0x7F, 155); + immAttrib4ub(col, 0x00, 0x00, 0x7F, 155); root[0] = root[1] = 0.0f; root[2] = -drw_size; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); + immVertex3fv(pos, root); tip[0] = tip[1] = 0.0f; tip[2] = drw_size; mul_m3_v3(tr, tip); add_v3_v3(tip, com); - glVertex3fv(tip); + immVertex3fv(pos, tip); root[0] = 0.0f; root[1] = tw; root[2] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = 0.0f; root[1] = -tw; root[2] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = tw; root[1] = 0.0f; root[2] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = -tw; root[1] = 0.0f; root[2] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); - glEnd(); + immEnd(); + + immUnbindProgram(); } /* place to add drawers */ @@ -6027,7 +6938,7 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles) { if (nu->hide || hide_handles) return; - if (nu->type == CU_BEZIER) { + if (nu->type == CU_BEZIER && nu->pntsu > 0) { const float *fp; @@ -6040,9 +6951,14 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles) UI_GetThemeColor3ubv(basecol + a, handle_cols[a]); } + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + glLineWidth(1.0f); - glBegin(GL_LINES); + immBeginAtMost(GWN_PRIM_LINES, nu->pntsu * 4); BezTriple *bezt = nu->bezt; int a = nu->pntsu; @@ -6051,33 +6967,35 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles) if ((bezt->f2 & SELECT) == sel) { fp = bezt->vec[0]; - glColor3ubv(handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); - glVertex3fv(fp); - glVertex3fv(fp + 3); + immAttrib3ubv(col, handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); + immVertex3fv(pos, fp); + immVertex3fv(pos, fp + 3); - glColor3ubv(handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]); - glVertex3fv(fp + 3); - glVertex3fv(fp + 6); + immAttrib3ubv(col, handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]); + immVertex3fv(pos, fp + 3); + immVertex3fv(pos, fp + 6); } else if ((bezt->f1 & SELECT) == sel) { fp = bezt->vec[0]; - glColor3ubv(handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); - glVertex3fv(fp); - glVertex3fv(fp + 3); + immAttrib3ubv(col, handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); + immVertex3fv(pos, fp); + immVertex3fv(pos, fp + 3); } else if ((bezt->f3 & SELECT) == sel) { fp = bezt->vec[1]; - glColor3ubv(handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]); - glVertex3fv(fp); - glVertex3fv(fp + 3); + immAttrib3ubv(col, handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]); + immVertex3fv(pos, fp); + immVertex3fv(pos, fp + 3); } } bezt++; } - glEnd(); + immEnd(); + + immUnbindProgram(); #undef TH_HANDLE_COL_TOT @@ -6088,153 +7006,196 @@ static void drawhandlesN_active(Nurb *nu) { if (nu->hide) return; - UI_ThemeColor(TH_ACTIVE_SPLINE); - glLineWidth(2); - - glBegin(GL_LINES); + if (nu->type == CU_BEZIER && nu->pntsu > 0) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_ACTIVE_SPLINE); + glLineWidth(2.0f); - if (nu->type == CU_BEZIER) { + immBeginAtMost(GWN_PRIM_LINES, nu->pntsu * 4); BezTriple *bezt = nu->bezt; int a = nu->pntsu; while (a--) { if (bezt->hide == 0) { const float *fp = bezt->vec[0]; - glVertex3fv(fp); - glVertex3fv(fp + 3); + immVertex3fv(pos, fp); + immVertex3fv(pos, fp + 3); - glVertex3fv(fp + 3); - glVertex3fv(fp + 6); + immVertex3fv(pos, fp + 3); + immVertex3fv(pos, fp + 6); } bezt++; } + immEnd(); + immUnbindProgram(); } - glEnd(); - - glColor3ub(0, 0, 0); } -static void drawvertsN(Nurb *nu, const char sel, const bool hide_handles, const void *vert) +static void drawvertsN(const Nurb *nurb, const bool hide_handles, const void *vert) { - if (nu->hide) return; + const Nurb *nu; + + // just quick guesstimate of how many verts to draw + int count = 0; + for (nu = nurb; nu; nu = nu->next) { + if (!nu->hide) { + if (nu->type == CU_BEZIER) { + count += nu->pntsu * 3; + } + else { + count += nu->pntsu * nu->pntsv; + } + } + } + if (count == 0) return; - const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); - UI_ThemeColor(color); + unsigned char vert_color[3]; + unsigned char vert_color_select[3]; + unsigned char vert_color_active[3]; + UI_GetThemeColor3ubv(TH_VERTEX, vert_color); + UI_GetThemeColor3ubv(TH_VERTEX_SELECT, vert_color_select); + UI_GetThemeColor3ubv(TH_ACTIVE_VERT, vert_color_active); glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + immBeginAtMost(GWN_PRIM_POINTS, count); - glBegin(GL_POINTS); - - if (nu->type == CU_BEZIER) { + for (nu = nurb; nu; nu = nu->next) { - BezTriple *bezt = nu->bezt; - int a = nu->pntsu; - while (a--) { - if (bezt->hide == 0) { - if (sel == 1 && bezt == vert) { - UI_ThemeColor(TH_ACTIVE_VERT); + if (nu->hide) continue; - if (bezt->f2 & SELECT) glVertex3fv(bezt->vec[1]); - if (!hide_handles) { - if (bezt->f1 & SELECT) glVertex3fv(bezt->vec[0]); - if (bezt->f3 & SELECT) glVertex3fv(bezt->vec[2]); - } + if (nu->type == CU_BEZIER) { - UI_ThemeColor(color); - } - else if (hide_handles) { - if ((bezt->f2 & SELECT) == sel) glVertex3fv(bezt->vec[1]); - } - else { - if ((bezt->f1 & SELECT) == sel) glVertex3fv(bezt->vec[0]); - if ((bezt->f2 & SELECT) == sel) glVertex3fv(bezt->vec[1]); - if ((bezt->f3 & SELECT) == sel) glVertex3fv(bezt->vec[2]); + const BezTriple *bezt = nu->bezt; + int a = nu->pntsu; + while (a--) { + if (bezt->hide == 0) { + if (bezt == vert) { + immAttrib3ubv(color, bezt->f2 & SELECT ? vert_color_active : vert_color); + immVertex3fv(pos, bezt->vec[1]); + if (!hide_handles) { + immAttrib3ubv(color, bezt->f1 & SELECT ? vert_color_active : vert_color); + immVertex3fv(pos, bezt->vec[0]); + immAttrib3ubv(color, bezt->f3 & SELECT ? vert_color_active : vert_color); + immVertex3fv(pos, bezt->vec[2]); + } + } + else { + immAttrib3ubv(color, bezt->f2 & SELECT ? vert_color_select : vert_color); + immVertex3fv(pos, bezt->vec[1]); + if (!hide_handles) { + immAttrib3ubv(color, bezt->f1 & SELECT ? vert_color_select : vert_color); + immVertex3fv(pos, bezt->vec[0]); + immAttrib3ubv(color, bezt->f3 & SELECT ? vert_color_select : vert_color); + immVertex3fv(pos, bezt->vec[2]); + } + } } + bezt++; } - bezt++; } - } - else { - BPoint *bp = nu->bp; - int a = nu->pntsu * nu->pntsv; - while (a--) { - if (bp->hide == 0) { - if (bp == vert) { - UI_ThemeColor(TH_ACTIVE_VERT); - glVertex3fv(bp->vec); - UI_ThemeColor(color); - } - else { - if ((bp->f1 & SELECT) == sel) glVertex3fv(bp->vec); + else { + const BPoint *bp = nu->bp; + int a = nu->pntsu * nu->pntsv; + while (a--) { + if (bp->hide == 0) { + if (bp == vert) { + immAttrib3ubv(color, vert_color_active); + } + else { + immAttrib3ubv(color, bp->f1 & SELECT ? vert_color_select : vert_color); + } + immVertex3fv(pos, bp->vec); } + bp++; } - bp++; } } - - glEnd(); + + immEnd(); + immUnbindProgram(); } static void editnurb_draw_active_poly(Nurb *nu) { - UI_ThemeColor(TH_ACTIVE_SPLINE); - glLineWidth(2); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_ACTIVE_SPLINE); + + glLineWidth(2.0f); BPoint *bp = nu->bp; for (int b = 0; b < nu->pntsv; b++) { - if (nu->flagu & 1) glBegin(GL_LINE_LOOP); - else glBegin(GL_LINE_STRIP); + if (nu->pntsu >= 2) { + if (nu->flagu & 1) immBegin(GWN_PRIM_LINE_LOOP, nu->pntsu); + else immBegin(GWN_PRIM_LINE_STRIP, nu->pntsu); - for (int a = 0; a < nu->pntsu; a++, bp++) { - glVertex3fv(bp->vec); - } + for (int a = 0; a < nu->pntsu; a++, bp++) { + immVertex3fv(pos, bp->vec); + } - glEnd(); + immEnd(); + } } - glColor3ub(0, 0, 0); + immUnbindProgram(); } static void editnurb_draw_active_nurbs(Nurb *nu) { - UI_ThemeColor(TH_ACTIVE_SPLINE); - glLineWidth(2); - - glBegin(GL_LINES); - BPoint *bp = nu->bp; - for (int b = 0; b < nu->pntsv; b++) { - BPoint *bp1 = bp; - bp++; + if (nu->pntsv > 0) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_ACTIVE_SPLINE); - for (int a = nu->pntsu - 1; a > 0; a--, bp++) { - if (bp->hide == 0 && bp1->hide == 0) { - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); - } - bp1 = bp; - } - } + glLineWidth(2.0f); + // just quick guesstimate of how many verts to draw + int count = (nu->pntsu - 1) * nu->pntsv * 2; + if (nu->pntsv > 1) count += (nu->pntsv - 1) * nu->pntsu * 2; + if (count < 2) return; - if (nu->pntsv > 1) { /* surface */ + immBeginAtMost(GWN_PRIM_LINES, count); + BPoint *bp = nu->bp; + for (int b = 0; b < nu->pntsv; b++) { + BPoint *bp1 = bp; + bp++; - int ofs = nu->pntsu; - for (int b = 0; b < nu->pntsu; b++) { - BPoint *bp1 = nu->bp + b; - bp = bp1 + ofs; - for (int a = nu->pntsv - 1; a > 0; a--, bp += ofs) { + for (int a = nu->pntsu - 1; a > 0; a--, bp++) { if (bp->hide == 0 && bp1->hide == 0) { - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } bp1 = bp; } } - } - glEnd(); + if (nu->pntsv > 1) { /* surface */ + int ofs = nu->pntsu; + for (int b = 0; b < nu->pntsu; b++) { + BPoint *bp1 = nu->bp + b; + bp = bp1 + ofs; + for (int a = nu->pntsv - 1; a > 0; a--, bp += ofs) { + if (bp->hide == 0 && bp1->hide == 0) { + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); + } + bp1 = bp; + } + } + } + + immEnd(); - glColor3ub(0, 0, 0); + immUnbindProgram(); + } } static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) @@ -6242,6 +7203,9 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) BPoint *bp, *bp1; int a, b; Curve *cu = ob->data; + Gwn_VertFormat *format; + unsigned int pos, col; + unsigned char color[3]; int index = 0; Nurb *nu = nurb; @@ -6249,35 +7213,55 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) if (nu->hide == 0) { switch (nu->type) { case CU_POLY: + { if (!sel && index == cu->actnu) { /* we should draw active spline highlight below everything */ editnurb_draw_active_poly(nu); } - glLineWidth(1); + format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + glLineWidth(1.0f); - UI_ThemeColor(TH_NURB_ULINE); + immUniformThemeColor(TH_NURB_ULINE); bp = nu->bp; for (b = 0; b < nu->pntsv; b++) { - if (nu->flagu & 1) glBegin(GL_LINE_LOOP); - else glBegin(GL_LINE_STRIP); + if (nu->pntsu >= 2) { + if (nu->flagu & 1) immBegin(GWN_PRIM_LINE_LOOP, nu->pntsu); + else immBegin(GWN_PRIM_LINE_STRIP, nu->pntsu); - for (a = 0; a < nu->pntsu; a++, bp++) { - glVertex3fv(bp->vec); - } + for (a = 0; a < nu->pntsu; a++, bp++) { + immVertex3fv(pos, bp->vec); + } - glEnd(); + immEnd(); + } } + immUnbindProgram(); break; + } case CU_NURBS: + { if (!sel && index == cu->actnu) { /* we should draw active spline highlight below everything */ editnurb_draw_active_nurbs(nu); } - glLineWidth(1); + format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + // just quick guesstimate of how many verts to draw + int count = (nu->pntsu - 1) * nu->pntsv * 2; + if (nu->pntsv > 1) count += (nu->pntsv - 1) * nu->pntsu * 2; + if (count < 2) return; - glBegin(GL_LINES); + glLineWidth(1.0f); + + immBeginAtMost(GWN_PRIM_LINES, count); bp = nu->bp; for (b = 0; b < nu->pntsv; b++) { @@ -6287,10 +7271,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) if (bp->hide == 0 && bp1->hide == 0) { if (sel) { if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) { - UI_ThemeColor(TH_NURB_SEL_ULINE); - - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + UI_GetThemeColor3ubv(TH_NURB_SEL_ULINE, color); + immAttrib3ubv(col, color); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } } else { @@ -6298,10 +7282,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) /* pass */ } else { - UI_ThemeColor(TH_NURB_ULINE); - - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + UI_GetThemeColor3ubv(TH_NURB_ULINE, color); + immAttrib3ubv(col, color); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } } } @@ -6318,10 +7302,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) if (bp->hide == 0 && bp1->hide == 0) { if (sel) { if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) { - UI_ThemeColor(TH_NURB_SEL_VLINE); - - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + UI_GetThemeColor3ubv(TH_NURB_SEL_VLINE, color); + immAttrib3ubv(col, color); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } } else { @@ -6329,10 +7313,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) /* pass */ } else { - UI_ThemeColor(TH_NURB_VLINE); - - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + UI_GetThemeColor3ubv(TH_NURB_VLINE, color); + immAttrib3ubv(col, color); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } } } @@ -6340,9 +7324,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) } } } - - glEnd(); + immEnd(); + immUnbindProgram(); break; + } } } @@ -6352,8 +7337,9 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) } static void draw_editnurb( - Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, - const char dt, const short dflag, const unsigned char ob_wire_col[4]) + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, + View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, + const char dt, const short dflag, const unsigned char UNUSED(ob_wire_col[4])) { ToolSettings *ts = scene->toolsettings; Object *ob = base->object; @@ -6365,9 +7351,8 @@ static void draw_editnurb( /* DispList */ UI_GetThemeColor3ubv(TH_WIRE_EDIT, wire_col); - glColor3ubv(wire_col); - drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, wire_col); /* for shadows only show solid faces */ if (v3d->flag2 & V3D_RENDER_SHADOW) @@ -6391,79 +7376,110 @@ static void draw_editnurb( for (nu = nurb; nu; nu = nu->next) { if (nu->type == CU_BEZIER && (cu->drawflag & CU_HIDE_HANDLES) == 0) drawhandlesN(nu, 1, hide_handles); - drawvertsN(nu, 0, hide_handles, NULL); } if (v3d->zbuf) glDepthFunc(GL_LEQUAL); - glColor3ubv(wire_col); - /* direction vectors for 3d curve paths * when at its lowest, don't render normals */ if ((cu->flag & CU_3D) && (ts->normalsize > 0.0015f) && (cu->drawflag & CU_HIDE_NORMALS) == 0) { BevList *bl; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_WIRE_EDIT); + glLineWidth(1.0f); + + int count = 0; + int count_used = 0; for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) { - BevPoint *bevp = bl->bevpoints; int nr = bl->nr; int skip = nu->resolu / 16; - + +#if 0 while (nr-- > 0) { /* accounts for empty bevel lists */ - const float fac = bevp->radius * ts->normalsize; - float vec_a[3]; /* Offset perpendicular to the curve */ - float vec_b[3]; /* Delta along the curve */ + count += 4; + nr -= skip; + } +#else + /* Same as loop above */ + count += 4 * max_ii((nr + max_ii(skip - 1, 0)) / (skip + 1), 0); +#endif + } - vec_a[0] = fac; - vec_a[1] = 0.0f; - vec_a[2] = 0.0f; - - mul_qt_v3(bevp->quat, vec_a); - madd_v3_v3fl(vec_a, bevp->dir, -fac); + if (count > 2) { + immBegin(GWN_PRIM_LINES, count); + for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) { + BevPoint *bevp = bl->bevpoints; + int nr = bl->nr; + int skip = nu->resolu / 16; - reflect_v3_v3v3(vec_b, vec_a, bevp->dir); - negate_v3(vec_b); + while (nr-- > 0) { /* accounts for empty bevel lists */ + const float fac = bevp->radius * ts->normalsize; + float vec_a[3]; /* Offset perpendicular to the curve */ + float vec_b[3]; /* Delta along the curve */ - add_v3_v3(vec_a, bevp->vec); - add_v3_v3(vec_b, bevp->vec); + vec_a[0] = fac; + vec_a[1] = 0.0f; + vec_a[2] = 0.0f; + + mul_qt_v3(bevp->quat, vec_a); + madd_v3_v3fl(vec_a, bevp->dir, -fac); - glBegin(GL_LINE_STRIP); - glVertex3fv(vec_a); - glVertex3fv(bevp->vec); - glVertex3fv(vec_b); - glEnd(); - - bevp += skip + 1; - nr -= skip; + reflect_v3_v3v3(vec_b, vec_a, bevp->dir); + negate_v3(vec_b); + + add_v3_v3(vec_a, bevp->vec); + add_v3_v3(vec_b, bevp->vec); + + immVertex3fv(pos, vec_a); + immVertex3fv(pos, bevp->vec); + immVertex3fv(pos, bevp->vec); + immVertex3fv(pos, vec_b); + + bevp += skip + 1; + nr -= skip; + count_used += 4; + } } + BLI_assert(count == count_used); + UNUSED_VARS_NDEBUG(count_used); + + immEnd(); } + immUnbindProgram(); } - if (v3d->zbuf) glDepthFunc(GL_ALWAYS); - - for (nu = nurb; nu; nu = nu->next) { - drawvertsN(nu, 1, hide_handles, vert); - } - - if (v3d->zbuf) glDepthFunc(GL_LEQUAL); + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); + + drawvertsN(nurb, hide_handles, vert); + + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } static void draw_editfont_textcurs(RegionView3D *rv3d, float textcurs[4][2]) { - cpack(0); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); ED_view3d_polygon_offset(rv3d, -1.0); set_inverted_drawing(1); - glBegin(GL_QUADS); - glVertex2fv(textcurs[0]); - glVertex2fv(textcurs[1]); - glVertex2fv(textcurs[2]); - glVertex2fv(textcurs[3]); - glEnd(); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + imm_cpack(0); + immBegin(GWN_PRIM_TRI_FAN, 4); + immVertex2fv(pos, textcurs[0]); + immVertex2fv(pos, textcurs[1]); + immVertex2fv(pos, textcurs[2]); + immVertex2fv(pos, textcurs[3]); + immEnd(); set_inverted_drawing(0); ED_view3d_polygon_offset(rv3d, 0.0); + immUnbindProgram(); } -static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const char dt, const short dflag, const unsigned char ob_wire_col[4]) +static void draw_editfont( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; Curve *cu = ob->data; @@ -6473,17 +7489,19 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b draw_editfont_textcurs(rv3d, ef->textcurs); if (cu->flag & CU_FAST) { - cpack(0xFFFFFF); + imm_cpack(0xFFFFFF); set_inverted_drawing(1); - drawDispList(scene, v3d, rv3d, base, OB_WIRE, dflag, ob_wire_col); + drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, OB_WIRE, dflag, ob_wire_col); set_inverted_drawing(0); } else { - drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } if (cu->linewidth != 0.0f) { - UI_ThemeColor(TH_WIRE_EDIT); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_WIRE_EDIT); copy_v3_v3(vec1, ob->orig); copy_v3_v3(vec2, ob->orig); vec1[0] += cu->linewidth; @@ -6491,31 +7509,35 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b vec1[1] += cu->linedist * cu->fsize; vec2[1] -= cu->lines * cu->linedist * cu->fsize; setlinestyle(3); - glBegin(GL_LINES); - glVertex2fv(vec1); - glVertex2fv(vec2); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex2fv(pos, vec1); + immVertex2fv(pos, vec2); + immEnd(); setlinestyle(0); + immUnbindProgram(); } setlinestyle(3); for (int i = 0; i < cu->totbox; i++) { if (cu->tb[i].w != 0.0f) { - UI_ThemeColor(i == (cu->actbox - 1) ? TH_ACTIVE : TH_WIRE); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(i == (cu->actbox - 1) ? TH_ACTIVE : TH_WIRE); vec1[0] = cu->xof + cu->tb[i].x; vec1[1] = cu->yof + cu->tb[i].y + cu->fsize; vec1[2] = 0.001; - glBegin(GL_LINE_STRIP); - glVertex3fv(vec1); + immBegin(GWN_PRIM_LINE_STRIP, 5); + immVertex3fv(pos, vec1); vec1[0] += cu->tb[i].w; - glVertex3fv(vec1); + immVertex3fv(pos, vec1); vec1[1] -= cu->tb[i].h; - glVertex3fv(vec1); + immVertex3fv(pos, vec1); vec1[0] -= cu->tb[i].w; - glVertex3fv(vec1); + immVertex3fv(pos, vec1); vec1[1] += cu->tb[i].h; - glVertex3fv(vec1); - glEnd(); + immVertex3fv(pos, vec1); + immEnd(); + immUnbindProgram(); } } setlinestyle(0); @@ -6524,7 +7546,9 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b if (ef->selboxes && ef->selboxes_len) { float selboxw; - cpack(0xffffff); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + imm_cpack(0xffffff); set_inverted_drawing(1); for (int i = 0; i < ef->selboxes_len; i++) { EditFontSelBox *sb = &ef->selboxes[i]; @@ -6543,20 +7567,20 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b /* fill in xy below */ tvec[2] = 0.001; - glBegin(GL_QUADS); + immBegin(GWN_PRIM_TRI_FAN, 4); if (sb->rot == 0.0f) { copy_v2_fl2(tvec, sb->x, sb->y); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, sb->x + selboxw, sb->y); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, sb->x + selboxw, sb->y + sb->h); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, sb->x, sb->y + sb->h); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); } else { float mat[2][2]; @@ -6564,84 +7588,87 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b angle_to_mat2(mat, sb->rot); copy_v2_fl2(tvec, sb->x, sb->y); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, selboxw, 0.0f); mul_m2v2(mat, tvec); add_v2_v2(tvec, &sb->x); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, selboxw, sb->h); mul_m2v2(mat, tvec); add_v2_v2(tvec, &sb->x); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, 0.0f, sb->h); mul_m2v2(mat, tvec); add_v2_v2(tvec, &sb->x); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); } - glEnd(); + immEnd(); } set_inverted_drawing(0); + immUnbindProgram(); } } /* draw a sphere for use as an empty drawtype */ -static void draw_empty_sphere(float size) -{ - static GLuint displist = 0; - - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - glPushMatrix(); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - gluDisk(qobj, 0.0, 1, 16, 1); - - glRotatef(90, 0, 1, 0); - gluDisk(qobj, 0.0, 1, 16, 1); - - glRotatef(90, 1, 0, 0); - gluDisk(qobj, 0.0, 1, 16, 1); - - gluDeleteQuadric(qobj); - - glPopMatrix(); - glEndList(); - } - - glScalef(size, size, size); - glCallList(displist); - glScalef(1.0f / size, 1.0f / size, 1.0f / size); +static void draw_empty_sphere(float size, unsigned pos) +{ +#define NSEGMENTS 16 + /* a single ring of vertices */ + float p[NSEGMENTS][2]; + for (int i = 0; i < NSEGMENTS; ++i) { + float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); + p[i][0] = size * cosf(angle); + p[i][1] = size * sinf(angle); + } + + immBegin(GWN_PRIM_LINE_LOOP, NSEGMENTS); + for (int i = 0; i < NSEGMENTS; ++i) + immVertex3f(pos, p[i][0], p[i][1], 0.0f); + immEnd(); + immBegin(GWN_PRIM_LINE_LOOP, NSEGMENTS); + for (int i = 0; i < NSEGMENTS; ++i) + immVertex3f(pos, p[i][0], 0.0f, p[i][1]); + immEnd(); + immBegin(GWN_PRIM_LINE_LOOP, NSEGMENTS); + for (int i = 0; i < NSEGMENTS; ++i) + immVertex3f(pos, 0.0f, p[i][0], p[i][1]); + immEnd(); +#undef NSEGMENTS } /* draw a cone for use as an empty drawtype */ -static void draw_empty_cone(float size) +static void draw_empty_cone(float size, unsigned pos) { - const float radius = size; +#define NSEGMENTS 8 + /* a single ring of vertices */ + float p[NSEGMENTS][2]; + for (int i = 0; i < NSEGMENTS; ++i) { + float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); + p[i][0] = size * cosf(angle); + p[i][1] = size * sinf(angle); + } - GLUquadricObj *qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - - glPushMatrix(); - - glScalef(radius, size * 2.0f, radius); - glRotatef(-90.0, 1.0, 0.0, 0.0); - gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1); + /* cone sides */ + immBegin(GWN_PRIM_LINES, NSEGMENTS * 2); + for (int i = 0; i < NSEGMENTS; ++i) { + immVertex3f(pos, 0.0f, 2.0f * size, 0.0f); + immVertex3f(pos, p[i][0], 0.0f, p[i][1]); + } + immEnd(); - glPopMatrix(); - - gluDeleteQuadric(qobj); + /* end ring */ + immBegin(GWN_PRIM_LINE_LOOP, NSEGMENTS); + for (int i = 0; i < NSEGMENTS; ++i) + immVertex3f(pos, p[i][0], 0.0f, p[i][1]); + immEnd(); +#undef NSEGMENTS } -static void drawspiral(const float cent[3], float rad, float tmat[4][4], int start) +static void drawspiral(unsigned int pos, const float cent[3], float rad, float tmat[4][4], int start) { float vec[3], vx[3], vy[3]; const float tot_inv = 1.0f / (float)CIRCLE_RESOL; @@ -6657,11 +7684,11 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta mul_v3_v3fl(vx, tmat[0], rad); mul_v3_v3fl(vy, tmat[1], rad); - glBegin(GL_LINE_STRIP); + immBegin(GWN_PRIM_LINE_STRIP, CIRCLE_RESOL + 1); if (inverse == 0) { copy_v3_v3(vec, cent); - glVertex3fv(vec); + immVertex3fv(pos, vec); for (a = 0; a < CIRCLE_RESOL; a++) { if (a + start >= CIRCLE_RESOL) @@ -6675,7 +7702,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta vec[1] = cent[1] + (x * vx[1] + y * vy[1]); vec[2] = cent[2] + (x * vx[2] + y * vy[2]); - glVertex3fv(vec); + immVertex3fv(pos, vec); } } else { @@ -6687,7 +7714,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta vec[1] = cent[1] + (x * vx[1] + y * vy[1]); vec[2] = cent[2] + (x * vx[2] + y * vy[2]); - glVertex3fv(vec); + immVertex3fv(pos, vec); for (a = 0; a < CIRCLE_RESOL; a++) { if (a + start >= CIRCLE_RESOL) @@ -6700,79 +7727,79 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta vec[0] = cent[0] + (x * vx[0] + y * vy[0]); vec[1] = cent[1] + (x * vx[1] + y * vy[1]); vec[2] = cent[2] + (x * vx[2] + y * vy[2]); - glVertex3fv(vec); + immVertex3fv(pos, vec); } } - glEnd(); + immEnd(); } /* draws a circle on x-z plane given the scaling of the circle, assuming that * all required matrices have been set (used for drawing empties) */ -static void drawcircle_size(float size) +static void drawcircle_size(float size, unsigned pos) { - glBegin(GL_LINE_LOOP); + immBegin(GWN_PRIM_LINE_LOOP, CIRCLE_RESOL); /* coordinates are: cos(degrees * 11.25) = x, sin(degrees * 11.25) = y, 0.0f = z */ for (short degrees = 0; degrees < CIRCLE_RESOL; degrees++) { float x = cosval[degrees]; float y = sinval[degrees]; - - glVertex3f(x * size, 0.0f, y * size); + + immVertex3f(pos, x * size, 0.0f, y * size); } - - glEnd(); + immEnd(); } /* needs fixing if non-identity matrix used */ -static void drawtube(const float vec[3], float radius, float height, float tmat[4][4]) +static void imm_drawtube(const float vec[3], float radius, float height, float tmat[4][4], unsigned pos) { float cur[3]; - drawcircball(GL_LINE_LOOP, vec, radius, tmat); + imm_drawcircball(vec, radius, tmat, pos); copy_v3_v3(cur, vec); cur[2] += height; - drawcircball(GL_LINE_LOOP, cur, radius, tmat); + imm_drawcircball(cur, radius, tmat, pos); - glBegin(GL_LINES); - glVertex3f(vec[0] + radius, vec[1], vec[2]); - glVertex3f(cur[0] + radius, cur[1], cur[2]); - glVertex3f(vec[0] - radius, vec[1], vec[2]); - glVertex3f(cur[0] - radius, cur[1], cur[2]); - glVertex3f(vec[0], vec[1] + radius, vec[2]); - glVertex3f(cur[0], cur[1] + radius, cur[2]); - glVertex3f(vec[0], vec[1] - radius, vec[2]); - glVertex3f(cur[0], cur[1] - radius, cur[2]); - glEnd(); + immBegin(GWN_PRIM_LINES, 8); + immVertex3f(pos, vec[0] + radius, vec[1], vec[2]); + immVertex3f(pos, cur[0] + radius, cur[1], cur[2]); + immVertex3f(pos, vec[0] - radius, vec[1], vec[2]); + immVertex3f(pos, cur[0] - radius, cur[1], cur[2]); + immVertex3f(pos, vec[0], vec[1] + radius, vec[2]); + immVertex3f(pos, cur[0], cur[1] + radius, cur[2]); + immVertex3f(pos, vec[0], vec[1] - radius, vec[2]); + immVertex3f(pos, cur[0], cur[1] - radius, cur[2]); + immEnd(); } /* needs fixing if non-identity matrix used */ -static void drawcone(const float vec[3], float radius, float height, float tmat[4][4]) +static void imm_drawcone(const float vec[3], float radius, float height, float tmat[4][4], unsigned pos) { float cur[3]; copy_v3_v3(cur, vec); cur[2] += height; - drawcircball(GL_LINE_LOOP, cur, radius, tmat); + imm_drawcircball(cur, radius, tmat, pos); - glBegin(GL_LINES); - glVertex3f(vec[0], vec[1], vec[2]); - glVertex3f(cur[0] + radius, cur[1], cur[2]); - glVertex3f(vec[0], vec[1], vec[2]); - glVertex3f(cur[0] - radius, cur[1], cur[2]); - glVertex3f(vec[0], vec[1], vec[2]); - glVertex3f(cur[0], cur[1] + radius, cur[2]); - glVertex3f(vec[0], vec[1], vec[2]); - glVertex3f(cur[0], cur[1] - radius, cur[2]); - glEnd(); + immBegin(GWN_PRIM_LINES, 8); + immVertex3f(pos, vec[0], vec[1], vec[2]); + immVertex3f(pos, cur[0] + radius, cur[1], cur[2]); + immVertex3f(pos, vec[0], vec[1], vec[2]); + immVertex3f(pos, cur[0] - radius, cur[1], cur[2]); + immVertex3f(pos, vec[0], vec[1], vec[2]); + immVertex3f(pos, cur[0], cur[1] + radius, cur[2]); + immVertex3f(pos, vec[0], vec[1], vec[2]); + immVertex3f(pos, cur[0], cur[1] - radius, cur[2]); + immEnd(); } /* return true if nothing was drawn */ -static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const char dt, const short dflag, const unsigned char ob_wire_col[4]) +static bool drawmball( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; MetaElem *ml; @@ -6785,15 +7812,13 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, if ((G.f & G_PICKSEL) == 0) { unsigned char wire_col[4]; UI_GetThemeColor4ubv(TH_WIRE_EDIT, wire_col); - glColor3ubv(wire_col); - - drawDispList(scene, v3d, rv3d, base, dt, dflag, wire_col); + drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, wire_col); } ml = mb->editelems->first; } else { - if ((base->flag & OB_FROMDUPLI) == 0) { - drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + if ((base->flag_legacy & OB_FROMDUPLI) == 0) { + drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } ml = mb->elems.first; } @@ -6810,20 +7835,25 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, normalize_v3(imat[0]); normalize_v3(imat[1]); +#if 0 /* no purpose? */ if (mb->editelems == NULL) { if ((dflag & DRAW_CONSTCOLOR) == 0) { glColor3ubv(ob_wire_col); } } - +#endif + glLineWidth(1.0f); + const unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + while (ml) { /* draw radius */ if (mb->editelems) { if ((dflag & DRAW_CONSTCOLOR) == 0) { - if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) cpack(0xA0A0F0); - else cpack(0x3030A0); + if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) imm_cpack(0xA0A0F0); + else imm_cpack(0x3030A0); } if (G.f & G_PICKSEL) { @@ -6831,24 +7861,26 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, GPU_select_load_id(code++); } } - drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat); + imm_drawcircball(&(ml->x), ml->rad, imat, pos); /* draw stiffness */ if (mb->editelems) { if ((dflag & DRAW_CONSTCOLOR) == 0) { - if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) cpack(0xA0F0A0); - else cpack(0x30A030); + if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) imm_cpack(0xA0F0A0); + else imm_cpack(0x30A030); } if (G.f & G_PICKSEL) { ml->selcol2 = code; GPU_select_load_id(code++); } - drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad * atanf(ml->s) / (float)M_PI_2, imat); + imm_drawcircball(&(ml->x), ml->rad * atanf(ml->s) / (float)M_PI_2, imat, pos); } ml = ml->next; } + + immUnbindProgram(); return false; } @@ -6858,6 +7890,7 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, PartDeflect *pd = ob->pd; float imat[4][4], tmat[4][4]; float vec[3] = {0.0, 0.0, 0.0}; + float draw_color[3] = {0.0f, 0.0f, 0.0f}; /* scale size of circle etc with the empty drawsize */ const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f; @@ -6867,35 +7900,53 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, normalize_v3(imat[0]); /* we don't do this because field doesnt scale either... apart from wind! */ normalize_v3(imat[1]); #endif + + const unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3fv(draw_color); if (pd->forcefield == PFIELD_WIND) { float force_val = pd->f_strength; if ((dflag & DRAW_CONSTCOLOR) == 0) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color); + immUniformColor3fv(draw_color); } unit_m4(tmat); force_val *= 0.1f; - drawcircball(GL_LINE_LOOP, vec, size, tmat); + imm_drawcircball(vec, size, tmat, pos); vec[2] = 0.5f * force_val; - drawcircball(GL_LINE_LOOP, vec, size, tmat); + imm_drawcircball(vec, size, tmat, pos); vec[2] = 1.0f * force_val; - drawcircball(GL_LINE_LOOP, vec, size, tmat); + imm_drawcircball(vec, size, tmat, pos); vec[2] = 1.5f * force_val; - drawcircball(GL_LINE_LOOP, vec, size, tmat); + imm_drawcircball(vec, size, tmat, pos); vec[2] = 0.0f; /* reset vec for max dist circle */ - } else if (pd->forcefield == PFIELD_FORCE) { float ffall_val = pd->f_power; - if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); - drawcircball(GL_LINE_LOOP, vec, size, imat); - if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(1.5f, ffall_val)); - drawcircball(GL_LINE_LOOP, vec, size * 1.5f, imat); - if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(2.0f, ffall_val)); - drawcircball(GL_LINE_LOOP, vec, size * 2.0f, imat); + if ((dflag & DRAW_CONSTCOLOR) == 0) { + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color); + immUniformColor3fv(draw_color); + } + + imm_drawcircball(vec, size, imat, pos); + + if ((dflag & DRAW_CONSTCOLOR) == 0) { + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(1.5f, ffall_val), draw_color); + immUniformColor3fv(draw_color); + } + + imm_drawcircball(vec, size * 1.5f, imat, pos); + + if ((dflag & DRAW_CONSTCOLOR) == 0) { + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(2.0f, ffall_val), draw_color); + immUniformColor3fv(draw_color); + } + + imm_drawcircball(vec, size * 2.0f, imat, pos); } else if (pd->forcefield == PFIELD_VORTEX) { float force_val = pd->f_strength; @@ -6903,16 +7954,17 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, unit_m4(tmat); if ((dflag & DRAW_CONSTCOLOR) == 0) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f); + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f, draw_color); + immUniformColor3fv(draw_color); } if (force_val < 0) { - drawspiral(vec, size, tmat, 1); - drawspiral(vec, size, tmat, 16); + drawspiral(pos, vec, size, tmat, 1); + drawspiral(pos, vec, size, tmat, 16); } else { - drawspiral(vec, size, tmat, -1); - drawspiral(vec, size, tmat, -16); + drawspiral(pos, vec, size, tmat, -1); + drawspiral(pos, vec, size, tmat, -16); } } else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) { @@ -6922,18 +7974,19 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, float mindist = pd->f_strength; if ((dflag & DRAW_CONSTCOLOR) == 0) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color); + immUniformColor3fv(draw_color); } /* path end */ setlinestyle(3); where_on_path(ob, 1.0f, guidevec1, guidevec2, NULL, NULL, NULL); - drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat); + imm_drawcircball(guidevec1, mindist, imat, pos); /* path beginning */ setlinestyle(0); where_on_path(ob, 0.0f, guidevec1, guidevec2, NULL, NULL, NULL); - drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat); + imm_drawcircball(guidevec1, mindist, imat, pos); copy_v3_v3(vec, guidevec1); /* max center */ } @@ -6942,16 +7995,19 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, setlinestyle(3); if ((dflag & DRAW_CONSTCOLOR) == 0) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color); + immUniformColor3fv(draw_color); } if (pd->falloff == PFIELD_FALL_SPHERE) { /* as last, guide curve alters it */ - if (pd->flag & PFIELD_USEMAX) - drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat); + if ((pd->flag & PFIELD_USEMAX) != 0) { + imm_drawcircball(vec, pd->maxdist, imat, pos); + } - if (pd->flag & PFIELD_USEMIN) - drawcircball(GL_LINE_LOOP, vec, pd->mindist, imat); + if ((pd->flag & PFIELD_USEMIN) != 0) { + imm_drawcircball(vec, pd->mindist, imat, pos); + } } else if (pd->falloff == PFIELD_FALL_TUBE) { float radius, distance; @@ -6964,16 +8020,18 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, vec[2] = distance; distance = (pd->flag & PFIELD_POSZ) ? -distance : -2.0f * distance; - if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) - drawtube(vec, radius, distance, tmat); + if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { + imm_drawtube(vec, radius, distance, tmat, pos); + } radius = (pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f; distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f; vec[2] = distance; distance = (pd->flag & PFIELD_POSZ) ? -distance : -2.0f * distance; - if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) - drawtube(vec, radius, distance, tmat); + if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { + imm_drawtube(vec, radius, distance, tmat, pos); + } } else if (pd->falloff == PFIELD_FALL_CONE) { float radius, distance; @@ -6984,46 +8042,54 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f; if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { - drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat); + imm_drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat, pos); if ((pd->flag & PFIELD_POSZ) == 0) - drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat); + imm_drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat, pos); } radius = DEG2RADF((pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f); distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f; if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { - drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat); + imm_drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat, pos); if ((pd->flag & PFIELD_POSZ) == 0) - drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat); + imm_drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat, pos); } } setlinestyle(0); + + immUnbindProgram(); } -static void draw_box(const float vec[8][3], bool solid) +static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vec); - if (solid) { - const GLubyte indices[24] = {0,1,2,3,7,6,5,4,4,5,1,0,3,2,6,7,3,7,4,0,1,5,6,2}; - glDrawRangeElements(GL_QUADS, 0, 7, 24, GL_UNSIGNED_BYTE, indices); + /* Adpated from "Optimizing Triangle Strips for Fast Rendering" by F. Evans, S. Skiena and A. Varshney + * (http://www.cs.umd.edu/gvil/papers/av_ts.pdf). */ + static const GLubyte tris_strip_indices[14] = {0,1,3,2,6,1,5,0,4,3,7,6,4,5}; + immBegin(GWN_PRIM_TRI_STRIP, 14); + for (int i = 0; i < 14; ++i) { + immVertex3fv(pos, vec[tris_strip_indices[i]]); + } + immEnd(); } else { - const GLubyte indices[24] = {0,1,1,2,2,3,3,0,0,4,4,5,5,6,6,7,7,4,1,5,2,6,3,7}; - glDrawRangeElements(GL_LINES, 0, 7, 24, GL_UNSIGNED_BYTE, indices); + static const GLubyte line_indices[24] = {0,1,1,2,2,3,3,0,0,4,4,5,5,6,6,7,7,4,1,5,2,6,3,7}; + immBegin(GWN_PRIM_LINES, 24); + for (int i = 0; i < 24; ++i) { + immVertex3fv(pos, vec[line_indices[i]]); + } + immEnd(); } - glDisableClientState(GL_VERTEX_ARRAY); } -static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin) +static void imm_draw_bb(BoundBox *bb, char type, bool around_origin, const unsigned char ob_wire_col[4]) { float size[3], cent[3]; - GLUquadricObj *qobj = gluNewQuadric(); - - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); + Gwn_Batch *sphere = GPU_batch_preset_sphere_wire(0); + GWN_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) GWN_batch_uniform_4f(sphere, "color", ob_wire_col[0] / 255.0f, ob_wire_col[1] / 255.0f, ob_wire_col[2] / 255.0f, 1.0f); BKE_boundbox_calc_size_aabb(bb, size); @@ -7034,40 +8100,51 @@ static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin) BKE_boundbox_calc_center_aabb(bb, cent); } - glPushMatrix(); + gpuPushMatrix(); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + if (type == OB_BOUND_SPHERE) { float scale = MAX3(size[0], size[1], size[2]); - glTranslate3fv(cent); - glScalef(scale, scale, scale); - gluSphere(qobj, 1.0, 8, 5); + gpuTranslate3fv(cent); + gpuRotateAxis(90, 'X'); + gpuScaleUniform(scale); + GWN_batch_draw(sphere); } else if (type == OB_BOUND_CYLINDER) { float radius = size[0] > size[1] ? size[0] : size[1]; - glTranslatef(cent[0], cent[1], cent[2] - size[2]); - glScalef(radius, radius, 2.0f * size[2]); - gluCylinder(qobj, 1.0, 1.0, 1.0, 8, 1); + gpuTranslate3f(cent[0], cent[1], cent[2] - size[2]); + gpuScale3f(radius, radius, 2.0f * size[2]); + imm_draw_cylinder_wire_3d(pos, 1.0f, 1.0f, 1.0f, 8, 1); } else if (type == OB_BOUND_CONE) { float radius = size[0] > size[1] ? size[0] : size[1]; - glTranslatef(cent[0], cent[1], cent[2] - size[2]); - glScalef(radius, radius, 2.0f * size[2]); - gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1); + gpuTranslate3f(cent[0], cent[1], cent[2] - size[2]); + gpuScale3f(radius, radius, 2.0f * size[2]); + imm_draw_cylinder_wire_3d(pos, 1.0f, 0.0f, 1.0f, 8, 1); + } else if (type == OB_BOUND_CAPSULE) { float radius = size[0] > size[1] ? size[0] : size[1]; float length = size[2] > radius ? 2.0f * (size[2] - radius) : 0.0f; - glTranslatef(cent[0], cent[1], cent[2] - length * 0.5f); - gluCylinder(qobj, radius, radius, length, 8, 1); - gluSphere(qobj, radius, 8, 4); - glTranslatef(0.0, 0.0, length); - gluSphere(qobj, radius, 8, 4); + gpuTranslate3f(cent[0], cent[1], cent[2] - length * 0.5f); + imm_draw_cylinder_wire_3d(pos, radius, radius, length, 8, 1); + + gpuRotateAxis(90, 'X'); + gpuScaleUniform(radius); + GWN_batch_draw(sphere); + + gpuTranslate3f(0.0f, length / radius, 0.0f); + GWN_batch_draw(sphere); } - glPopMatrix(); - - gluDeleteQuadric(qobj); + + gpuPopMatrix(); + immUnbindProgram(); } -static void draw_bounding_volume(Object *ob, char type) +void draw_bounding_volume(Object *ob, char type, const unsigned char ob_wire_col[4]) { BoundBox bb_local; BoundBox *bb = NULL; @@ -7097,12 +8174,16 @@ static void draw_bounding_volume(Object *ob, char type) if (bb == NULL) return; - + if (ob->gameflag & OB_BOUNDS) { /* bounds need to be drawn around origin for game engine */ if (type == OB_BOUND_BOX) { float vec[8][3], size[3]; - + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + BKE_boundbox_calc_size_aabb(bb, size); vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = -size[0]; @@ -7112,21 +8193,31 @@ static void draw_bounding_volume(Object *ob, char type) vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2]; vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2]; - draw_box(vec, false); + imm_draw_box(vec, false, pos); + + immUnbindProgram(); } else { - draw_bb_quadric(bb, type, true); + imm_draw_bb(bb, type, true, ob_wire_col); } } else { - if (type == OB_BOUND_BOX) - draw_box(bb->vec, false); + if (type == OB_BOUND_BOX) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + + imm_draw_box(bb->vec, false, pos); + + immUnbindProgram(); + } else - draw_bb_quadric(bb, type, false); + imm_draw_bb(bb, type, false, ob_wire_col); } + } -static void drawtexspace(Object *ob) +static void drawtexspace(Object *ob, const unsigned char ob_wire_col[3]) { float vec[8][3], loc[3], size[3]; @@ -7156,26 +8247,38 @@ static void drawtexspace(Object *ob) setlinestyle(2); - draw_box(vec, false); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + if (ob_wire_col) { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(ob_wire_col); + } + else { + immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY); + } + + imm_draw_box(vec, false, pos); + + immUnbindProgram(); setlinestyle(0); } /* draws wire outline */ static void draw_object_selected_outline( - Scene *scene, View3D *v3d, ARegion *ar, Base *base, + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, const unsigned char ob_wire_col[4]) { RegionView3D *rv3d = ar->regiondata; Object *ob = base->object; - glDepthMask(0); + glDepthMask(GL_FALSE); if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { bool has_faces = false; #ifdef SEQUENCER_DAG_WORKAROUND - ensure_curve_cache(scene, ob); + ensure_curve_cache(eval_ctx, scene, ob); #endif DerivedMesh *dm = ob->derivedFinal; @@ -7193,46 +8296,41 @@ static void draw_object_selected_outline( if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->bb)) { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); if (dm) { - draw_mesh_object_outline(v3d, ob, dm); + draw_mesh_object_outline(v3d, ob, dm, ob_wire_col); } else { /* only draw 'solid' parts of the display list as wire. */ - drawDispListwire_ex(&ob->curve_cache->disp, (DL_INDEX3 | DL_INDEX4 | DL_SURF)); + drawDispListwire_ex(&ob->curve_cache->disp, (DL_INDEX3 | DL_INDEX4 | DL_SURF), ob_wire_col); } } } else if (ob->type == OB_MBALL) { if (BKE_mball_is_basis(ob)) { - if ((base->flag & OB_FROMDUPLI) == 0) { + if ((base->flag_legacy & OB_FROMDUPLI) == 0) { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); - drawDispListwire(&ob->curve_cache->disp, ob->type); + drawDispListwire(&ob->curve_cache->disp, ob->type, ob_wire_col); } } } else if (ob->type == OB_ARMATURE) { - if (!(ob->mode & OB_MODE_POSE && base == scene->basact)) { + if (!(ob->mode & OB_MODE_POSE && base == sl->basact)) { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); - draw_armature(scene, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true); + draw_armature(eval_ctx, scene, sl, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true); } } - glDepthMask(1); + glDepthMask(GL_TRUE); } static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const unsigned char ob_wire_col[4]) { if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL)) { - - if (scene->obedit == ob) { - UI_ThemeColor(TH_WIRE_EDIT); - } - else { - glColor3ubv(ob_wire_col); - } + unsigned char wire_edit_col[4]; + UI_GetThemeColor4ubv(TH_WIRE_EDIT, wire_edit_col); ED_view3d_polygon_offset(rv3d, 1.0); - glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */ - glLineWidth(1); + glDepthMask(GL_FALSE); /* disable write in zbuffer, selected edge wires show better */ + glLineWidth(1.0f); if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { if (ED_view3d_boundbox_clip(rv3d, ob->bb)) { @@ -7241,23 +8339,23 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const drawCurveDMWired(ob); } else { - drawDispListwire(&ob->curve_cache->disp, ob->type); + drawDispListwire(&ob->curve_cache->disp, ob->type, (scene->obedit == ob) ? wire_edit_col : ob_wire_col); } } } else if (ob->type == OB_MBALL) { if (BKE_mball_is_basis(ob)) { - drawDispListwire(&ob->curve_cache->disp, ob->type); + drawDispListwire(&ob->curve_cache->disp, ob->type, (scene->obedit == ob) ? wire_edit_col : ob_wire_col); } } - glDepthMask(1); + glDepthMask(GL_TRUE); ED_view3d_polygon_offset(rv3d, 0.0); } } /* should be called in view space */ -static void draw_hooks(Object *ob) +static void draw_hooks(Object *ob, unsigned int pos) { for (ModifierData *md = ob->modifiers.first; md; md = md->next) { if (md->type == eModifierType_Hook) { @@ -7268,17 +8366,17 @@ static void draw_hooks(Object *ob) if (hmd->object) { setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(hmd->object->obmat[3]); - glVertex3fv(vec); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, hmd->object->obmat[3]); + immVertex3fv(pos, vec); + immEnd(); setlinestyle(0); } - glPointSize(3.0); - glBegin(GL_POINTS); - glVertex3fv(vec); - glEnd(); + glPointSize(3.0f); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, vec); + immEnd(); } } } @@ -7289,9 +8387,16 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data, const char *axis_str[3] = {"px", "py", "pz"}; float mat[4][4]; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + eul_to_mat4(mat, &data->axX); glLineWidth(4.0f); setlinestyle(2); + + immBegin(GWN_PRIM_LINES, 6); for (int axis = 0; axis < 3; axis++) { float dir[3] = {0, 0, 0}; float v[3]; @@ -7299,12 +8404,10 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data, copy_v3_v3(v, &data->pivX); dir[axis] = 1.0f; - glBegin(GL_LINES); mul_m4_v3(mat, dir); add_v3_v3(v, dir); - glVertex3fv(&data->pivX); - glVertex3fv(v); - glEnd(); + immVertex3fv(pos, &data->pivX); + immVertex3fv(pos, v); /* when const color is set wirecolor is NULL - we could get the current color but * with selection and group instancing its not needed to draw the text */ @@ -7312,11 +8415,15 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data, view3d_cached_text_draw_add(v, axis_str[axis], 2, 0, V3D_CACHE_TEXT_ASCII, ob_wire_col); } } + immEnd(); setlinestyle(0); + glLineWidth(1.0f); + + immUnbindProgram(); } -static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_col[4]) +void draw_object_wire_color(Scene *scene, SceneLayer *sl, Base *base, unsigned char r_ob_wire_col[4]) { Object *ob = base->object; int colindex = 0; @@ -7330,23 +8437,23 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_ if ((scene->obedit == NULL) && (G.moving & G_TRANSFORM_OBJ) && - (base->flag & (SELECT + BA_WAS_SEL))) + ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) { theme_id = TH_TRANSFORM; } else { /* Sets the 'colindex' */ if (ID_IS_LINKED(ob)) { - colindex = (base->flag & (SELECT + BA_WAS_SEL)) ? 2 : 1; + colindex = ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) ? 2 : 1; } /* Sets the 'theme_id' or fallback to wire */ else { - if (ob->flag & OB_FROMGROUP) { - if (base->flag & (SELECT + BA_WAS_SEL)) { + if ((ob->flag & OB_FROMGROUP) != 0) { + if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) { /* uses darker active color for non-active + selected */ theme_id = TH_GROUP_ACTIVE; - if (scene->basact != base) { + if (sl->basact != base) { theme_shade = -32; } } @@ -7355,8 +8462,8 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_ } } else { - if (base->flag & (SELECT + BA_WAS_SEL)) { - theme_id = scene->basact == base ? TH_ACTIVE : TH_SELECT; + if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) { + theme_id = sl->basact == base ? TH_ACTIVE : TH_SELECT; } else { if (ob->type == OB_LAMP) theme_id = TH_LAMP; @@ -7410,10 +8517,11 @@ static void draw_object_matcap_check(View3D *v3d, Object *ob) v3d->flag2 |= V3D_SHOW_SOLID_MATCAP; } -static void draw_rigidbody_shape(Object *ob) +void draw_rigidbody_shape(Object *ob, const unsigned char ob_wire_col[4]) { BoundBox *bb = NULL; float size[3], vec[8][3]; + unsigned int pos; if (ob->type == OB_MESH) { bb = BKE_mesh_boundbox_get(ob); @@ -7426,6 +8534,10 @@ static void draw_rigidbody_shape(Object *ob) case RB_SHAPE_BOX: BKE_boundbox_calc_size_aabb(bb, size); + pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = -size[0]; vec[4][0] = vec[5][0] = vec[6][0] = vec[7][0] = +size[0]; vec[0][1] = vec[1][1] = vec[4][1] = vec[5][1] = -size[1]; @@ -7433,19 +8545,20 @@ static void draw_rigidbody_shape(Object *ob) vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2]; vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2]; - draw_box(vec, false); + imm_draw_box(vec, false, pos); + immUnbindProgram(); break; case RB_SHAPE_SPHERE: - draw_bb_quadric(bb, OB_BOUND_SPHERE, true); + imm_draw_bb(bb, OB_BOUND_SPHERE, true, ob_wire_col); break; case RB_SHAPE_CONE: - draw_bb_quadric(bb, OB_BOUND_CONE, true); + imm_draw_bb(bb, OB_BOUND_CONE, true, ob_wire_col); break; case RB_SHAPE_CYLINDER: - draw_bb_quadric(bb, OB_BOUND_CYLINDER, true); + imm_draw_bb(bb, OB_BOUND_CYLINDER, true, ob_wire_col); break; case RB_SHAPE_CAPSULE: - draw_bb_quadric(bb, OB_BOUND_CAPSULE, true); + imm_draw_bb(bb, OB_BOUND_CAPSULE, true, ob_wire_col); break; } } @@ -7454,17 +8567,18 @@ static void draw_rigidbody_shape(Object *ob) * main object drawing function, draws in selection * \param dflag (draw flag) can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET */ -void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag) +void draw_object( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, + Base *base, const short dflag) { ModifierData *md = NULL; Object *ob = base->object; Curve *cu; RegionView3D *rv3d = ar->regiondata; - unsigned int col = 0; unsigned char _ob_wire_col[4]; /* dont initialize this */ const unsigned char *ob_wire_col = NULL; /* dont initialize this, use NULL crashes as a way to find invalid use */ bool zbufoff = false, is_paint = false, empty_object = false; - const bool is_obact = (ob == OBACT); + const bool is_obact = (ob == OBACT(sl)); const bool render_override = (v3d->flag2 & V3D_RENDER_OVERRIDE) != 0; const bool is_picking = (G.f & G_PICKSEL) != 0; const bool has_particles = (ob->particlesystem.first != NULL); @@ -7504,7 +8618,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } } - if (((base->flag & OB_FROMDUPLI) == 0) && + if (((base->flag_legacy & OB_FROMDUPLI) == 0) && (md = modifiers_findByType(ob, eModifierType_Smoke)) && (modifier_isEnabled(scene, md, eModifierMode_Realtime))) { @@ -7528,7 +8642,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* xray delay? */ - if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag_legacy & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* don't do xray in particle mode, need the z-buffer */ if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) { /* xray and transp are set when it is drawing the 2nd/3rd pass */ @@ -7581,10 +8695,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short ED_view3d_project_base(ar, base); - draw_object_wire_color(scene, base, _ob_wire_col); + draw_object_wire_color(scene, sl, base, _ob_wire_col); ob_wire_col = _ob_wire_col; - glColor3ubv(ob_wire_col); + //glColor3ubv(ob_wire_col); } /* maximum drawtype */ @@ -7636,15 +8750,22 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* draw outline for selected objects, mesh does itself */ if ((v3d->flag & V3D_SELECT_OUTLINE) && !render_override && ob->type != OB_MESH) { if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (dflag & DRAW_SCENESET) == 0) { - if (!(ob->dtx & OB_DRAWWIRE) && (ob->flag & SELECT) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) { - draw_object_selected_outline(scene, v3d, ar, base, ob_wire_col); + if (!(ob->dtx & OB_DRAWWIRE) && (base->flag & BASE_SELECTED) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) { + draw_object_selected_outline(eval_ctx, scene, sl, v3d, ar, base, ob_wire_col); } } } + /* TODO Viewport: draw only for selection */ + if ((dflag & DRAW_PICKING) == 0) { + if ((dt == OB_BOUNDBOX) || ELEM(ob->type, OB_EMPTY, OB_LAMP, OB_CAMERA, OB_SPEAKER)) { + goto afterdraw; + } + } + switch (ob->type) { case OB_MESH: - empty_object = draw_mesh_object(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); + empty_object = draw_mesh_object(eval_ctx, scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); if ((dflag & DRAW_CONSTCOLOR) == 0) { /* mesh draws wire itself */ dtx &= ~OB_DRAWWIRE; @@ -7654,18 +8775,18 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short case OB_FONT: cu = ob->data; if (cu->editfont) { - draw_editfont(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + draw_editfont(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } else if (dt == OB_BOUNDBOX) { if ((render_override && v3d->drawtype >= OB_WIRE) == 0) { #ifdef SEQUENCER_DAG_WORKAROUND - ensure_curve_cache(scene, base->object); + ensure_curve_cache(eval_ctx, scene, base->object); #endif - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } } else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) { - empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + empty_object = drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } break; @@ -7675,18 +8796,18 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (cu->editnurb) { ListBase *nurbs = BKE_curve_editNurbs_get(cu); - draw_editnurb(scene, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col); + draw_editnurb(eval_ctx, scene, sl, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col); } else if (dt == OB_BOUNDBOX) { if ((render_override && (v3d->drawtype >= OB_WIRE)) == 0) { #ifdef SEQUENCER_DAG_WORKAROUND - ensure_curve_cache(scene, base->object); + ensure_curve_cache(eval_ctx, scene, base->object); #endif - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } } else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) { - empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + empty_object = drawDispList(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } break; case OB_MBALL: @@ -7694,17 +8815,17 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short MetaBall *mb = ob->data; if (mb->editelems) - drawmball(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + drawmball(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); else if (dt == OB_BOUNDBOX) { if ((render_override && (v3d->drawtype >= OB_WIRE)) == 0) { #ifdef SEQUENCER_DAG_WORKAROUND - ensure_curve_cache(scene, base->object); + ensure_curve_cache(eval_ctx, scene, base->object); #endif - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } } else - empty_object = drawmball(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + empty_object = drawmball(eval_ctx, scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); break; } case OB_EMPTY: @@ -7713,7 +8834,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short draw_empty_image(ob, dflag, ob_wire_col, v3d->multiview_eye); } else { - drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype); + drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, ob_wire_col); } } break; @@ -7731,7 +8852,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short break; case OB_SPEAKER: if (!render_override) - drawspeaker(scene, v3d, rv3d, ob, dflag); + drawspeaker(ob_wire_col); break; case OB_LATTICE: if (!render_override) { @@ -7739,13 +8860,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((dt == OB_BOUNDBOX) && (ob->mode & OB_MODE_EDIT)) dt = OB_WIRE; if (dt == OB_BOUNDBOX) { - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } else { #ifdef SEQUENCER_DAG_WORKAROUND - ensure_curve_cache(scene, ob); + ensure_curve_cache(eval_ctx, scene, ob); #endif - drawlattice(v3d, ob); + drawlattice(v3d, ob, dflag, ob_wire_col); } } break; @@ -7755,21 +8876,33 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((dt == OB_BOUNDBOX) && (ob->mode & (OB_MODE_EDIT | OB_MODE_POSE))) dt = OB_WIRE; if (dt == OB_BOUNDBOX) { - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } else { + unsigned char arm_col[4]; glLineWidth(1.0f); - empty_object = draw_armature(scene, v3d, ar, base, dt, dflag, ob_wire_col, false); + + if (ob_wire_col == NULL) { + float fcol[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + rgba_float_to_uchar(arm_col, fcol); + } + else + copy_v4_v4_uchar(arm_col, ob_wire_col); + + empty_object = draw_armature(eval_ctx, scene, sl, v3d, ar, base, dt, dflag, arm_col, false); } } break; default: if (!render_override) { - drawaxes(rv3d->viewmatob, 1.0, OB_ARROWS); + drawaxes(rv3d->viewmatob, 1.0, OB_ARROWS, ob_wire_col); } break; } + /* TODO Viewport: some elements are being drawn for object selection only */ +afterdraw: + if (!render_override) { if (ob->soft /*&& dflag & OB_SBMOTION*/) { float mrt[3][3], msc[3][3], mtr[3][3]; @@ -7778,12 +8911,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((sb = ob->soft)) { if (sb->solverflags & SBSO_ESTIMATEIPO) { - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); copy_m3_m3(msc, sb->lscale); copy_m3_m3(mrt, sb->lrot); mul_m3_m3m3(mtr, mrt, msc); ob_draw_RE_motion(sb->lcom, mtr, tipw, tiph, drawsize); - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); } } } @@ -7800,35 +8933,28 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short { ParticleSystem *psys; - if ((dflag & DRAW_CONSTCOLOR) == 0) { - /* for visibility, also while wpaint */ - if (col || (ob->flag & SELECT)) { - cpack(0xFFFFFF); - } - } //glDepthMask(GL_FALSE); - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); view3d_cached_text_draw_begin(); for (psys = ob->particlesystem.first; psys; psys = psys->next) { /* run this so that possible child particles get cached */ if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) { - PTCacheEdit *edit = PE_create_current(scene, ob); + PTCacheEdit *edit = PE_create_current(eval_ctx, scene, ob); if (edit && edit->psys == psys) - draw_update_ptcache_edit(scene, ob, edit); + draw_update_ptcache_edit(eval_ctx, scene, sl, ob, edit); } - draw_new_particle_system(scene, v3d, rv3d, base, psys, dt, dflag); + draw_new_particle_system(eval_ctx, scene, v3d, rv3d, base, psys, dt, dflag); } invert_m4_m4(ob->imat, ob->obmat); view3d_cached_text_draw_end(v3d, ar, 0); - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); //glDepthMask(GL_TRUE); - if (col) cpack(col); } /* draw edit particles last so that they can draw over child particles */ @@ -7837,12 +8963,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short { if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) { - PTCacheEdit *edit = PE_create_current(scene, ob); + PTCacheEdit *edit = PE_create_current(eval_ctx, scene, ob); if (edit) { - glLoadMatrixf(rv3d->viewmat); - draw_update_ptcache_edit(scene, ob, edit); + gpuLoadMatrix(rv3d->viewmat); + draw_update_ptcache_edit(eval_ctx, scene, sl, ob, edit); draw_ptcache_edit(scene, v3d, edit); - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); } } } @@ -7850,21 +8976,25 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* draw code for smoke, only draw domains */ if (smd && smd->domain) { SmokeDomainSettings *sds = smd->domain; + const bool show_smoke = (CFRA >= sds->point_cache[0]->startframe); float viewnormal[3]; - glLoadMatrixf(rv3d->viewmat); - glMultMatrixf(ob->obmat); + gpuLoadMatrix(rv3d->viewmat); + gpuMultMatrix(ob->obmat); if (!render_override) { BoundBox bb; float p0[3], p1[3]; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); /* draw max domain bounds */ if ((sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN)) { VECSUBFAC(p0, sds->p0, sds->cell_size, sds->adapt_res); VECADDFAC(p1, sds->p1, sds->cell_size, sds->adapt_res); BKE_boundbox_init_from_minmax(&bb, p0, p1); - draw_box(bb.vec, false); + imm_draw_box(bb.vec, false, pos); } /* draw a single voxel to hint the user about the resolution of the fluid */ @@ -7878,11 +9008,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } BKE_boundbox_init_from_minmax(&bb, p0, p1); - draw_box(bb.vec, false); + imm_draw_box(bb.vec, false, pos); + + immUnbindProgram(); } /* don't show smoke before simulation starts, this could be made an option in the future */ - if (sds->fluid && CFRA >= sds->point_cache[0]->startframe) { + if (sds->fluid && show_smoke) { float p0[3], p1[3]; /* get view vector */ @@ -7934,29 +9066,37 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((ob->gameflag & OB_BOUNDS) && (ob->mode == OB_MODE_OBJECT)) { if (ob->boundtype != ob->collision_boundtype || (dtx & OB_DRAWBOUNDOX) == 0) { setlinestyle(2); - draw_bounding_volume(ob, ob->collision_boundtype); + draw_bounding_volume(ob, ob->collision_boundtype, ob_wire_col); setlinestyle(0); } } if (ob->rigidbody_object) { - draw_rigidbody_shape(ob); + draw_rigidbody_shape(ob, ob_wire_col); } /* draw extra: after normal draw because of makeDispList */ if (dtx && (G.f & G_RENDER_OGL) == 0) { if (dtx & OB_AXIS) { - drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS); + if ((dflag & DRAW_CONSTCOLOR) == 0) { + /* prevent random colors being used */ + drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS, ob_wire_col); + } + else { + drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS, NULL); + } } if (dtx & OB_DRAWBOUNDOX) { - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } if (dtx & OB_TEXSPACE) { if ((dflag & DRAW_CONSTCOLOR) == 0) { /* prevent random colors being used */ - glColor3ubv(ob_wire_col); + drawtexspace(ob, ob_wire_col); + } + else { + drawtexspace(ob, NULL); } - drawtexspace(ob); } if (dtx & OB_DRAWNAME) { /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */ @@ -7983,16 +9123,21 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short { float imat[4][4], vec[3] = {0.0f, 0.0f, 0.0f}; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + invert_m4_m4(imat, rv3d->viewmatob); if ((dflag & DRAW_CONSTCOLOR) == 0) { /* prevent random colors being used */ - glColor3ubv(ob_wire_col); + immUniformColor3ubv(ob_wire_col); } setlinestyle(2); - drawcircball(GL_LINE_LOOP, vec, ob->inertia, imat); + imm_drawcircball(vec, ob->inertia, imat, pos); setlinestyle(0); + + immUnbindProgram(); } } @@ -8002,13 +9147,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* return warning, clear temp flag */ v3d->flag2 &= ~V3D_SHOW_SOLID_MATCAP; - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); if (zbufoff) { glDisable(GL_DEPTH_TEST); } - if ((base->flag & OB_FROMDUPLI) || render_override) { + if ((base->flag_legacy & OB_FROMDUPLI) || render_override) { ED_view3d_clear_mats_rv3d(rv3d); return; } @@ -8022,7 +9167,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } else if (is_obact) do_draw_center = ACTIVE; - else if (base->flag & SELECT) + else if (base->flag & BASE_SELECTED) do_draw_center = SELECT; else if (empty_object || (v3d->flag & V3D_DRAW_CENTERS)) do_draw_center = DESELECT; @@ -8033,10 +9178,15 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((base->sx != IS_CLIPPED) && (U.obcenter_dia != 0.0)) { + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR); + /* TODO: short term, use DEPTH_ONLY shader or set appropriate color */ + /* TODO: long term, solve picking & selection problem better */ glPointSize(U.obcenter_dia); - glBegin(GL_POINTS); - glVertex3fv(ob->obmat[3]); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, ob->obmat[3]); + immEnd(); + immUnbindProgram(); } } else if ((dflag & DRAW_CONSTCOLOR) == 0) { @@ -8057,18 +9207,24 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short ListBase *list; RigidBodyCon *rbc = ob->rigidbody_constraint; + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(ob_wire_col); + /* draw hook center and offset line */ if (ob != scene->obedit) - draw_hooks(ob); + draw_hooks(ob, pos); /* help lines and so */ - if (ob != scene->obedit && ob->parent && (ob->parent->lay & v3d->lay)) { - setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(ob->obmat[3]); - glVertex3fv(ob->orig); - glEnd(); - setlinestyle(0); + if (ob != scene->obedit && ob->parent) { + if (BKE_object_is_visible(ob->parent)) { + setlinestyle(3); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, ob->obmat[3]); + immVertex3fv(pos, ob->orig); + immEnd(); + setlinestyle(0); + } } /* Drawing the constraint lines */ @@ -8081,7 +9237,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short UI_GetThemeColor3ubv(TH_GRID, col1); UI_make_axis_color(col1, col2, 'Z'); - glColor3ubv(col2); + immUniformColor3ubv(col2); cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); @@ -8106,10 +9262,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (camob) { setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(camob->obmat[3]); - glVertex3fv(ob->obmat[3]); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, camob->obmat[3]); + immVertex3fv(pos, ob->obmat[3]); + immEnd(); setlinestyle(0); } } @@ -8125,15 +9281,15 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short for (ct = targets.first; ct; ct = ct->next) { /* calculate target's matrix */ if (cti->get_target_matrix) - cti->get_target_matrix(curcon, cob, ct, BKE_scene_frame_get(scene)); + cti->get_target_matrix(eval_ctx, curcon, cob, ct, BKE_scene_frame_get(scene)); else unit_m4(ct->matrix); setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(ct->matrix[3]); - glVertex3fv(ob->obmat[3]); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, ct->matrix[3]); + immVertex3fv(pos, ob->obmat[3]); + immEnd(); setlinestyle(0); } @@ -8146,21 +9302,24 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short BKE_constraints_clear_evalob(cob); } /* draw rigid body constraint lines */ - if (rbc) { - UI_ThemeColor(TH_WIRE); + if (rbc && (rbc->ob1 || rbc->ob2)) { + immUniformThemeColor(TH_WIRE); + setlinestyle(3); - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, ((int)((bool)rbc->ob1) + (int)((bool)rbc->ob2)) * 2); if (rbc->ob1) { - glVertex3fv(ob->obmat[3]); - glVertex3fv(rbc->ob1->obmat[3]); + immVertex3fv(pos, ob->obmat[3]); + immVertex3fv(pos, rbc->ob1->obmat[3]); } if (rbc->ob2) { - glVertex3fv(ob->obmat[3]); - glVertex3fv(rbc->ob2->obmat[3]); + immVertex3fv(pos, ob->obmat[3]); + immVertex3fv(pos, rbc->ob2->obmat[3]); } - glEnd(); + immEnd(); setlinestyle(0); } + + immUnbindProgram(); } ED_view3d_clear_mats_rv3d(rv3d); @@ -8171,10 +9330,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short * Drawing for selection picking, * caller must have called 'GPU_select_load_id(base->selcode)' first. */ -void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag) +void draw_object_select( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, + Base *base, const short dflag) { BLI_assert(dflag & DRAW_PICKING && dflag & DRAW_CONSTCOLOR); - draw_object(scene, ar, v3d, base, dflag); + draw_object(eval_ctx, scene, sl, ar, v3d, base, dflag); /* we draw duplicators for selection too */ if ((base->object->transflag & OB_DUPLI)) { @@ -8182,13 +9343,11 @@ void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, cons DupliObject *dob; Base tbase; - tbase.flag = OB_FROMDUPLI; - lb = object_duplilist(G.main->eval_ctx, scene, base->object); + tbase.flag_legacy = OB_FROMDUPLI; + lb = object_duplilist(eval_ctx, scene, base->object); for (dob = lb->first; dob; dob = dob->next) { float omat[4][4]; - char dt; - short dtx; tbase.object = dob->ob; copy_m4_m4(omat, dob->ob->obmat); @@ -8196,10 +9355,10 @@ void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, cons /* extra service: draw the duplicator in drawtype of parent */ /* MIN2 for the drawtype to allow bounding box objects in groups for lods */ - dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); - dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx; + char dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); + short dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx; - draw_object(scene, ar, v3d, &tbase, dflag); + draw_object(eval_ctx, scene, sl, ar, v3d, &tbase, dflag); tbase.object->dt = dt; tbase.object->dtx = dtx; @@ -8212,6 +9371,7 @@ void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, cons /* ***************** BACKBUF SEL (BBS) ********* */ +#ifdef USE_MESH_DM_SELECT static void bbs_obmode_mesh_verts__mapFunc(void *userData, int index, const float co[3], const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) { @@ -8219,8 +9379,10 @@ static void bbs_obmode_mesh_verts__mapFunc(void *userData, int index, const floa MVert *mv = &data->mvert[index]; if (!(mv->flag & ME_HIDE)) { - GPU_select_index_set(data->offset + index); - glVertex3fv(co); + int selcol; + GPU_select_index_get(data->offset + index, &selcol); + immAttrib1u(data->col, selcol); + immVertex3fv(data->pos, co); } } @@ -8231,12 +9393,36 @@ static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *dm, int offset) MVert *mvert = me->mvert; data.mvert = mvert; data.offset = offset; + + const int imm_len = dm->getNumVerts(dm); + + if (imm_len == 0) return; + + Gwn_VertFormat *format = immVertexFormat(); + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - glBegin(GL_POINTS); + + immBeginAtMost(GWN_PRIM_POINTS, imm_len); dm->foreachMappedVert(dm, bbs_obmode_mesh_verts__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } +#else +static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *UNUSED(dm), int offset) +{ + Mesh *me = ob->data; + Gwn_Batch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); +} +#endif +#ifdef USE_MESH_DM_SELECT static void bbs_mesh_verts__mapFunc(void *userData, int index, const float co[3], const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) { @@ -8244,97 +9430,223 @@ static void bbs_mesh_verts__mapFunc(void *userData, int index, const float co[3] BMVert *eve = BM_vert_at_index(data->bm, index); if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - GPU_select_index_set(data->offset + index); - glVertex3fv(co); + int selcol; + GPU_select_index_get(data->offset + index, &selcol); + immAttrib1u(data->col, selcol); + immVertex3fv(data->pos, co); } } static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset) { - drawBMOffset_userData data = {em->bm, offset}; + drawBMOffset_userData data; + data.bm = em->bm; + data.offset = offset; + Gwn_VertFormat *format = immVertexFormat(); + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - glBegin(GL_POINTS); + + immBeginAtMost(GWN_PRIM_POINTS, em->bm->totvert); dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } +#else +static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset) +{ + Mesh *me = em->ob->data; + Gwn_Batch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); +} +#endif -static DMDrawOption bbs_mesh_wire__setDrawOptions(void *userData, int index) +#ifdef USE_MESH_DM_SELECT +static void bbs_mesh_wire__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3]) { drawBMOffset_userData *data = userData; BMEdge *eed = BM_edge_at_index(data->bm, index); if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { - GPU_select_index_set(data->offset + index); - return DM_DRAW_OPTION_NORMAL; - } - else { - return DM_DRAW_OPTION_SKIP; + int selcol; + GPU_select_index_get(data->offset + index, &selcol); + immAttrib1u(data->col, selcol); + immVertex3fv(data->pos, v0co); + immVertex3fv(data->pos, v1co); } } + static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset) { - drawBMOffset_userData data = {em->bm, offset}; - dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, &data); + drawBMOffset_userData data; + data.bm = em->bm; + data.offset = offset; + + Gwn_VertFormat *format = immVertexFormat(); + + const int imm_len = dm->getNumEdges(dm) * 2; + + if (imm_len == 0) return; + + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + immBeginAtMost(GWN_PRIM_LINES, imm_len); + dm->foreachMappedEdge(dm, bbs_mesh_wire__mapFunc, &data); + immEnd(); + + immUnbindProgram(); } +#else +static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset) +{ + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); -/** - * dont set #GPU_framebuffer_index_set. just use to mask other - */ -static DMDrawOption bbs_mesh_mask__setSolidDrawOptions(void *userData, int index) + Mesh *me = em->ob->data; + Gwn_Batch *batch = DRW_mesh_batch_cache_get_edges_with_select_id(me, offset); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); +} +#endif + +#ifdef USE_MESH_DM_SELECT +static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *dm, const bool use_select) { - BMFace *efa = BM_face_at_index(userData, index); - - if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - return DM_DRAW_OPTION_NORMAL; + UNUSED_VARS(dm); + + drawBMOffset_userData data; + data.bm = em->bm; + + const int tri_len = em->tottri; + const int imm_len = tri_len * 3; + const char hflag_skip = use_select ? BM_ELEM_HIDDEN : (BM_ELEM_HIDDEN | BM_ELEM_SELECT); + + if (imm_len == 0) return; + + Gwn_VertFormat *format = immVertexFormat(); + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + + immBeginAtMost(GWN_PRIM_TRIS, imm_len); + + if (use_select == false) { + int selcol; + GPU_select_index_get(0, &selcol); + immAttrib1u(data.col, selcol); } - else { - return DM_DRAW_OPTION_SKIP; + + int index = 0; + while (index < tri_len) { + const BMFace *f = em->looptris[index][0]->f; + const int ntris = f->len - 2; + if (!BM_elem_flag_test(f, hflag_skip)) { + if (use_select) { + int selcol; + GPU_select_index_get(BM_elem_index_get(f) + 1, &selcol); + immAttrib1u(data.col, selcol); + } + for (int t = 0; t < ntris; t++) { + immVertex3fv(data.pos, em->looptris[index][0]->v->co); + immVertex3fv(data.pos, em->looptris[index][1]->v->co); + immVertex3fv(data.pos, em->looptris[index][2]->v->co); + index++; + } + } + else { + index += ntris; + } } -} + immEnd(); -static DMDrawOption bbs_mesh_solid__setSolidDrawOptions(void *userData, int index) + immUnbindProgram(); +} +#else +static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *UNUSED(dm), const bool use_select) { - BMFace *efa = BM_face_at_index(userData, index); + Mesh *me = em->ob->data; + Gwn_Batch *batch; - if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - GPU_select_index_set(index + 1); - return DM_DRAW_OPTION_NORMAL; + if (use_select) { + batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true, 1); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); } else { - return DM_DRAW_OPTION_SKIP; + int selcol; + GPU_select_index_get(0, &selcol); + batch = DRW_mesh_batch_cache_get_triangles_with_select_mask(me, true); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32); + GWN_batch_uniform_1i(batch, "color", selcol); + GWN_batch_draw(batch); } } +#endif +#ifdef USE_MESH_DM_SELECT static void bbs_mesh_solid__drawCenter(void *userData, int index, const float cent[3], const float UNUSED(no[3])) { + drawBMOffset_userData *data = (drawBMOffset_userData *)userData; BMFace *efa = BM_face_at_index(userData, index); if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - GPU_select_index_set(index + 1); - - glVertex3fv(cent); + int selcol; + GPU_select_index_get(index + 1, &selcol); + immAttrib1u(data->col, selcol); + immVertex3fv(data->pos, cent); } } +static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *dm) +{ + drawBMOffset_userData data; /* don't use offset */ + data.bm = em->bm; + Gwn_VertFormat *format = immVertexFormat(); + data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + + glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE)); + + immBeginAtMost(GWN_PRIM_POINTS, em->bm->totface); + dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, &data, DM_FOREACH_NOP); + immEnd(); + + immUnbindProgram(); +} +#else +static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *UNUSED(dm)) +{ + Mesh *me = em->ob->data; + Gwn_Batch *batch = DRW_mesh_batch_cache_get_facedots_with_select_id(me, 1); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); +} +#endif + /* two options, facecolors or black */ static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob, DerivedMesh *dm, bool use_faceselect) { - cpack(0); - if (use_faceselect) { - dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, NULL, NULL, em->bm, DM_DRAW_SKIP_HIDDEN | DM_DRAW_SELECT_USE_EDITMODE); + bbs_mesh_face(em, dm, true); if (check_ob_drawface_dot(scene, v3d, ob->dt)) { - glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE)); - - glBegin(GL_POINTS); - dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, em->bm, DM_FOREACH_NOP); - glEnd(); + bbs_mesh_face_dot(em, dm); } - } else { - dm->drawMappedFaces(dm, bbs_mesh_mask__setSolidDrawOptions, NULL, NULL, em->bm, DM_DRAW_SKIP_SELECT | DM_DRAW_SKIP_HIDDEN | DM_DRAW_SELECT_USE_EDITMODE); + bbs_mesh_face(em, dm, false); } } @@ -8349,7 +9661,6 @@ static DMDrawOption bbs_mesh_solid_hide__setDrawOpts(void *userData, int index) Mesh *me = userData; if (!(me->mpoly[index].flag & ME_HIDE)) { - GPU_select_index_set(index + 1); return DM_DRAW_OPTION_NORMAL; } else { @@ -8357,6 +9668,7 @@ static DMDrawOption bbs_mesh_solid_hide__setDrawOpts(void *userData, int index) } } +#ifdef USE_MESH_DM_SELECT /* must have called GPU_framebuffer_index_set beforehand */ static DMDrawOption bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index) { @@ -8370,11 +9682,10 @@ static DMDrawOption bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index) } } -static void bbs_mesh_solid_verts(Scene *scene, Object *ob) +static void bbs_mesh_solid_verts(const EvaluationContext *eval_ctx, Scene *scene, Object *ob) { Mesh *me = ob->data; - DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); - glColor3ub(0, 0, 0); + DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, scene->customdata_mask); DM_update_materials(dm, ob); @@ -8390,29 +9701,53 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob) bm_vertoffs = me->totvert + 1; dm->release(dm); } - -static void bbs_mesh_solid_faces(Scene *scene, Object *ob) +#else +static void bbs_mesh_solid_verts(const EvaluationContext *UNUSED(eval_ctx), Scene *UNUSED(scene), Object *ob) { - DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); Mesh *me = ob->data; - - glColor3ub(0, 0, 0); - DM_update_materials(dm, ob); + /* Only draw faces to mask out verts, we don't want their selection ID's. */ + const int G_f_orig = G.f; + G.f &= ~G_BACKBUFSEL; - if ((me->editflag & ME_EDIT_PAINT_FACE_SEL)) - dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, NULL, NULL, me, DM_DRAW_SKIP_HIDDEN); - else - dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, NULL, NULL, me, 0); + { + int selcol; + Gwn_Batch *batch; + GPU_select_index_get(0, &selcol); + batch = DRW_mesh_batch_cache_get_triangles_with_select_mask(me, true); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32); + GWN_batch_uniform_1i(batch, "color", selcol); + GWN_batch_draw(batch); + } - dm->release(dm); + G.f |= (G_f_orig & G_BACKBUFSEL); + + bbs_obmode_mesh_verts(ob, NULL, 1); + bm_vertoffs = me->totvert + 1; } +#endif -void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) +static void bbs_mesh_solid_faces(Scene *scene, Object *ob) +{ + Mesh *me = ob->data; + UNUSED_VARS(scene, bbs_mesh_solid_hide__setDrawOpts, bbs_mesh_solid__setDrawOpts); + Gwn_Batch *batch; + if ((me->editflag & ME_EDIT_PAINT_FACE_SEL)) { + batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true, 1); + } + else { + batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, false, 1); + } + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); +} + +void draw_object_backbufsel( + const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) { ToolSettings *ts = scene->toolsettings; - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); @@ -8423,7 +9758,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec Mesh *me = ob->data; BMEditMesh *em = me->edit_btmesh; - DerivedMesh *dm = editbmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH); + DerivedMesh *dm = editbmesh_get_derived_cage(eval_ctx, scene, ob, em, CD_MASK_BAREMESH); BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); @@ -8460,7 +9795,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec /* currently vertex select supports weight paint and vertex paint*/ ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) { - bbs_mesh_solid_verts(scene, ob); + bbs_mesh_solid_verts(eval_ctx, scene, ob); } else { bbs_mesh_solid_faces(scene, ob); @@ -8472,7 +9807,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec break; } - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); } @@ -8480,8 +9815,9 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec /* assumes all matrices/etc set OK */ /* helper function for drawing object instances - meshes */ -static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, - Object *ob, const short dt, int outline) +static void draw_object_mesh_instance( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, + Object *ob, const short dt, int outline, const unsigned char ob_wire_col[4]) { Mesh *me = ob->data; DerivedMesh *dm = NULL, *edm = NULL; @@ -8491,11 +9827,12 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r DM_update_materials(edm, ob); } else { - dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH); DM_update_materials(dm, ob); } if (dt <= OB_WIRE) { + glColor4ubv(ob_wire_col); if (dm) dm->drawEdges(dm, 1, 0); else if (edm) @@ -8503,11 +9840,11 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r } else { if (outline) - draw_mesh_object_outline(v3d, ob, dm ? dm : edm); + draw_mesh_object_outline(v3d, ob, dm ? dm : edm, ob_wire_col); if (dm) { - bool glsl = draw_glsl_material(scene, ob, v3d, dt); - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL); } glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); @@ -8526,23 +9863,153 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r if (dm) dm->release(dm); } -void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline) +void draw_object_instance(const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline, const float wire_col[4]) { if (ob == NULL) return; + unsigned char bcol[4]; + rgba_float_to_uchar(bcol, wire_col); + switch (ob->type) { case OB_MESH: - draw_object_mesh_instance(scene, v3d, rv3d, ob, dt, outline); + draw_object_mesh_instance(eval_ctx, scene, sl, v3d, rv3d, ob, dt, outline, bcol); break; case OB_EMPTY: if (ob->empty_drawtype == OB_EMPTY_IMAGE) { - /* CONSTCOLOR == no wire outline */ - draw_empty_image(ob, DRAW_CONSTCOLOR, NULL, v3d->multiview_eye); + draw_empty_image(ob, 0, bcol, v3d->multiview_eye); } else { - drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype); + drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, bcol); } break; } } + +void ED_draw_object_facemap( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, const float col[4], const int facemap) +{ + DerivedMesh *dm = NULL; + + /* happens on undo */ + if (ob->type != OB_MESH || !ob->data) + return; + + /* Temporary, happens on undo, would resolve but will eventually move away from DM. */ + if (ob->derivedFinal == NULL) { + return; + } + + dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH); + if (!dm || !CustomData_has_layer(&dm->polyData, CD_FACEMAP)) + return; + + + glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + +#if 0 + DM_update_materials(dm, ob); + + /* add polygon offset so we draw above the original surface */ + glPolygonOffset(1.0, 1.0); + + GPU_facemap_setup(dm); + + glColor4fv(col); + + gpuPushAttrib(GL_ENABLE_BIT); + glEnable(GL_BLEND); + glDisable(GL_LIGHTING); + + /* always draw using backface culling */ + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + if (dm->drawObject->facemapindices) { + glDrawElements(GL_TRIANGLES, dm->drawObject->facemap_count[facemap] * 3, GL_UNSIGNED_INT, + (int *)NULL + dm->drawObject->facemap_start[facemap] * 3); + } + gpuPopAttrib(); + + GPU_buffers_unbind(); + + glPolygonOffset(0.0, 0.0); + +#else + + /* Just to create the data to pass to immediate mode, grr! */ + Mesh *me = ob->data; + const int *facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP); + if (facemap_data) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(col); + + /* XXX, alpha isn't working yet, not sure why. */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + MVert *mvert; + + MPoly *mpoly; + int mpoly_len; + + MLoop *mloop; + int mloop_len; + + if (dm && CustomData_has_layer(&dm->polyData, CD_FACEMAP)) { + mvert = dm->getVertArray(dm); + mpoly = dm->getPolyArray(dm); + mloop = dm->getLoopArray(dm); + + mpoly_len = dm->getNumPolys(dm); + mloop_len = dm->getNumLoops(dm); + + facemap_data = CustomData_get_layer(&dm->polyData, CD_FACEMAP); + } + else { + mvert = me->mvert; + mpoly = me->mpoly; + mloop = me->mloop; + + mpoly_len = me->totpoly; + mloop_len = me->totloop; + + facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP); + } + + /* use gawain immediate mode fore now */ + const int looptris_len = poly_to_tri_count(mpoly_len, mloop_len); + immBeginAtMost(GWN_PRIM_TRIS, looptris_len * 3); + + MPoly *mp; + int i; + for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) { + if (facemap_data[i] == facemap) { + /* Weak, fan-fill, use until we have derived-mesh replaced. */ + const MLoop *ml_start = &mloop[mp->loopstart]; + const MLoop *ml_a = ml_start + 1; + const MLoop *ml_b = ml_start + 2; + for (int j = 2; j < mp->totloop; j++) { + immVertex3fv(pos, mvert[ml_start->v].co); + immVertex3fv(pos, mvert[ml_a->v].co); + immVertex3fv(pos, mvert[ml_b->v].co); + + ml_a++; + ml_b++; + } + } + } + immEnd(); + + immUnbindProgram(); + + glDisable(GL_BLEND); + } +#endif + + dm->release(dm); +} + diff --git a/source/blender/editors/space_view3d/drawsimdebug.c b/source/blender/editors/space_view3d/drawsimdebug.c index 3f23d4aa09a..14708ca67bc 100644 --- a/source/blender/editors/space_view3d/drawsimdebug.c +++ b/source/blender/editors/space_view3d/drawsimdebug.c @@ -40,102 +40,137 @@ #include "BKE_effect.h" -#include "view3d_intern.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" -#include "BIF_gl.h" +#include "view3d_intern.h" static void draw_sim_debug_elements(SimDebugData *debug_data, float imat[4][4]) { + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + /* count element types */ GHashIterator iter; + int num_dots = 0; + int num_circles = 0; + int num_lines = 0; + int num_vectors = 0; + for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { + SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); + switch (elem->type) { + case SIM_DEBUG_ELEM_DOT: ++num_dots; break; + case SIM_DEBUG_ELEM_CIRCLE: ++num_circles; break; + case SIM_DEBUG_ELEM_LINE: ++num_lines; break; + case SIM_DEBUG_ELEM_VECTOR: ++num_vectors; break; + } + } /**** dots ****/ glPointSize(3.0f); - glBegin(GL_POINTS); + immBegin(GWN_PRIM_POINTS, num_dots); for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); if (elem->type != SIM_DEBUG_ELEM_DOT) continue; - glColor3f(elem->color[0], elem->color[1], elem->color[2]); - glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]); + immAttrib3fv(color, elem->color); + immVertex3fv(pos, elem->v1); } - glEnd(); + immEnd(); /**** circles ****/ { - float circle[16][2] = { +#define CIRCLERES 16 + float circle[CIRCLERES][2] = { {0.000000, 1.000000}, {0.382683, 0.923880}, {0.707107, 0.707107}, {0.923880, 0.382683}, {1.000000, -0.000000}, {0.923880, -0.382683}, {0.707107, -0.707107}, {0.382683, -0.923880}, {-0.000000, -1.000000}, {-0.382683, -0.923880}, {-0.707107, -0.707107}, {-0.923879, -0.382684}, {-1.000000, 0.000000}, {-0.923879, 0.382684}, {-0.707107, 0.707107}, {-0.382683, 0.923880} }; + + immBegin(GWN_PRIM_LINES, num_circles * CIRCLERES * 2); + for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); float radius = elem->v2[0]; - float co[3]; + float co[3], nco[3]; int i; if (elem->type != SIM_DEBUG_ELEM_CIRCLE) continue; - glColor3f(elem->color[0], elem->color[1], elem->color[2]); - glBegin(GL_LINE_LOOP); - for (i = 0; i < 16; ++i) { - co[0] = radius * circle[i][0]; - co[1] = radius * circle[i][1]; - co[2] = 0.0f; - mul_mat3_m4_v3(imat, co); - add_v3_v3(co, elem->v1); + immAttrib3fv(color, elem->color); + zero_v3(co); + for (i = 0; i <= CIRCLERES; ++i) { + int ni = i % CIRCLERES; + nco[0] = radius * circle[ni][0]; + nco[1] = radius * circle[ni][1]; + nco[2] = 0.0f; + mul_mat3_m4_v3(imat, nco); + add_v3_v3(nco, elem->v1); - glVertex3f(co[0], co[1], co[2]); + if (i > 0) { + immVertex3fv(pos, co); + immVertex3fv(pos, nco); + } + + copy_v3_v3(co, nco); } - glEnd(); } + + immEnd(); +#undef CIRCLERES } /**** lines ****/ - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, num_lines * 2); for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); if (elem->type != SIM_DEBUG_ELEM_LINE) continue; - glColor3f(elem->color[0], elem->color[1], elem->color[2]); - glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]); - glVertex3f(elem->v2[0], elem->v2[1], elem->v2[2]); + immAttrib3fv(color, elem->color); + immVertex3fv(pos, elem->v1); + immVertex3fv(pos, elem->v2); } - glEnd(); + immEnd(); /**** vectors ****/ glPointSize(2.0f); - glBegin(GL_POINTS); + immBegin(GWN_PRIM_POINTS, num_vectors); for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); if (elem->type != SIM_DEBUG_ELEM_VECTOR) continue; - glColor3f(elem->color[0], elem->color[1], elem->color[2]); - glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]); + immAttrib3fv(color, elem->color); + immVertex3fv(pos, elem->v1); } - glEnd(); + immEnd(); - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, num_vectors * 2); for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); float t[3]; if (elem->type != SIM_DEBUG_ELEM_VECTOR) continue; - glColor3f(elem->color[0], elem->color[1], elem->color[2]); - glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]); + immAttrib3fv(color, elem->color); + immVertex3fv(pos, elem->v1); add_v3_v3v3(t, elem->v1, elem->v2); - glVertex3f(t[0], t[1], t[2]); + immVertex3fv(pos, t); } - glEnd(); + immEnd(); + + immUnbindProgram(); /**** strings ****/ @@ -163,18 +198,12 @@ void draw_sim_debug_data(Scene *UNUSED(scene), View3D *v3d, ARegion *ar) invert_m4_m4(imat, rv3d->viewmatob); -// glDepthMask(GL_FALSE); -// glEnable(GL_BLEND); - - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); + gpuPushMatrix(); + gpuLoadMatrix(rv3d->viewmat); view3d_cached_text_draw_begin(); draw_sim_debug_elements(_sim_debug_data, imat); view3d_cached_text_draw_end(v3d, ar, false); - glPopMatrix(); - -// glDepthMask(GL_TRUE); -// glDisable(GL_BLEND); + gpuPopMatrix(); } diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index c076bfb4aa4..3a80624acd9 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -48,7 +48,6 @@ #include "BIF_gl.h" -#include "GPU_debug.h" #include "GPU_shader.h" #include "GPU_texture.h" @@ -160,7 +159,7 @@ static GPUTexture *create_field_texture(SmokeDomainSettings *sds) default: return NULL; } - return GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, field); + return GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1, GPU_R8, field, NULL); } typedef struct VolumeSlicer { diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 996506a9cf7..e1e78fd8ff1 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -43,22 +43,27 @@ #include "BLI_utildefines.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" +#include "BKE_curve.h" #include "BKE_icons.h" +#include "BKE_lattice.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_mball.h" +#include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_workspace.h" #include "ED_space_api.h" #include "ED_screen.h" +#include "ED_transform.h" #include "GPU_compositing.h" #include "GPU_framebuffer.h" #include "GPU_material.h" - -#include "BIF_gl.h" +#include "GPU_viewport.h" +#include "GPU_matrix.h" #include "WM_api.h" #include "WM_types.h" @@ -250,7 +255,7 @@ void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d) /* we have to multiply instead of loading viewmatob to make * it work with duplis using displists, otherwise it will * override the dupli-matrix */ - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); } #ifdef DEBUG @@ -304,7 +309,7 @@ void ED_view3d_shade_update(Main *bmain, Scene *scene, View3D *v3d, ScrArea *sa) } else if (scene->obedit != NULL && scene->obedit->type == OB_MESH) { /* Tag mesh to load edit data. */ - DAG_id_tag_update(scene->obedit->data, 0); + DEG_id_tag_update(scene->obedit->data, 0); } } @@ -340,9 +345,10 @@ static SpaceLink *view3d_new(const bContext *C) v3d->near = 0.01f; v3d->far = 1000.0f; - v3d->twflag |= U.tw_flag & V3D_USE_MANIPULATOR; + v3d->twflag |= U.manipulator_flag & V3D_MANIPULATOR_DRAW; v3d->twtype = V3D_MANIP_TRANSLATE; v3d->around = V3D_AROUND_CENTER_MEAN; + v3d->custom_orientation_index = -1; v3d->bundle_size = 0.2f; v3d->bundle_drawtype = OB_PLAINAXES; @@ -404,17 +410,6 @@ static SpaceLink *view3d_new(const bContext *C) static void view3d_free(SpaceLink *sl) { View3D *vd = (View3D *) sl; - BGpic *bgpic; - - for (bgpic = vd->bgpicbase.first; bgpic; bgpic = bgpic->next) { - if (bgpic->source == V3D_BGPIC_IMAGE) { - id_us_min((ID *)bgpic->ima); - } - else if (bgpic->source == V3D_BGPIC_MOVIE) { - id_us_min((ID *)bgpic->clip); - } - } - BLI_freelistN(&vd->bgpicbase); if (vd->localvd) MEM_freeN(vd->localvd); @@ -445,7 +440,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) { View3D *v3do = (View3D *)sl; View3D *v3dn = MEM_dupallocN(sl); - BGpic *bgpic; /* clear or remove stuff from old */ @@ -462,16 +456,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) v3dn->defmaterial = NULL; - BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase); - for (bgpic = v3dn->bgpicbase.first; bgpic; bgpic = bgpic->next) { - if (bgpic->source == V3D_BGPIC_IMAGE) { - id_us_plus((ID *)bgpic->ima); - } - else if (bgpic->source == V3D_BGPIC_MOVIE) { - id_us_plus((ID *)bgpic->clip); - } - } - v3dn->properties_storage = NULL; if (v3dn->fx_settings.dof) v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof); @@ -487,6 +471,13 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar) ListBase *lb; wmKeyMap *keymap; + if (ar->manipulator_map == NULL) { + ar->manipulator_map = WM_manipulatormap_new_from_type( + &(const struct wmManipulatorMapType_Params) {SPACE_VIEW3D, RGN_TYPE_WINDOW}); + } + + WM_manipulatormap_add_handlers(ar, ar->manipulator_map); + /* object ops. */ /* important to be before Pose keymap since they can both be enabled at once */ @@ -582,6 +573,12 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar) GPU_fx_compositor_destroy(rv3d->compositor); rv3d->compositor = NULL; } + + if (rv3d->viewport) { + GPU_viewport_free(rv3d->viewport); + MEM_freeN(rv3d->viewport); + rv3d->viewport = NULL; + } } static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) @@ -712,6 +709,26 @@ static void view3d_dropboxes(void) WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy); } +static void view3d_widgets(void) +{ + wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure( + &(const struct wmManipulatorMapType_Params){SPACE_VIEW3D, RGN_TYPE_WINDOW}); + + WM_manipulatorgrouptype_append_and_link(mmap_type, TRANSFORM_WGT_manipulator); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_spot); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_area); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_target); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_force_field); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera_view); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_empty_image); + WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_armature_spline); + + WM_manipulatorgrouptype_append(VIEW3D_WGT_xform_cage); + + WM_manipulatorgrouptype_append(VIEW3D_WGT_ruler); + WM_manipulatortype_append(VIEW3D_WT_ruler_item); +} /* type callback, not region itself */ @@ -739,6 +756,10 @@ static void view3d_main_region_free(ARegion *ar) if (rv3d->compositor) { GPU_fx_compositor_destroy(rv3d->compositor); } + if (rv3d->viewport) { + GPU_viewport_free(rv3d->viewport); + MEM_freeN(rv3d->viewport); + } MEM_freeN(rv3d); ar->regiondata = NULL; @@ -763,32 +784,22 @@ static void *view3d_main_region_duplicate(void *poin) new->sms = NULL; new->smooth_timer = NULL; new->compositor = NULL; + new->viewport = NULL; return new; } return NULL; } -static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene) +static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene)) { wmWindow *win = wmn->wm->winactive; - ScrArea *sa; unsigned int lay_used = 0; - Base *base; if (!win) return; - base = scene->base.first; - while (base) { - lay_used |= base->lay & ((1 << 20) - 1); /* ignore localview */ - - if (lay_used == (1 << 20) - 1) - break; - - base = base->next; - } - - for (sa = win->screen->areabase.first; sa; sa = sa->next) { + const bScreen *screen = WM_window_get_active_screen(win); + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { if (sa->spacetype == SPACE_VIEW3D) { if (BLI_findindex(&sa->regionbase, ar) != -1) { View3D *v3d = sa->spacedata.first; @@ -799,13 +810,21 @@ static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene } } -static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *wmn) +static void view3d_main_region_listener( + bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar, + wmNotifier *wmn, const Scene *scene) { - Scene *scene = sc->scene; View3D *v3d = sa->spacedata.first; - + RegionView3D *rv3d = ar->regiondata; + wmManipulatorMap *mmap = ar->manipulator_map; + /* context changes */ switch (wmn->category) { + case NC_WM: + if (ELEM(wmn->data, ND_UNDO)) { + WM_manipulatormap_tag_refresh(mmap); + } + break; case NC_ANIMATION: switch (wmn->data) { case ND_KEYFRAME_PROP: @@ -825,21 +844,32 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w break; case NC_SCENE: switch (wmn->data) { + case ND_SCENEBROWSE: case ND_LAYER_CONTENT: if (wmn->reference) view3d_recalc_used_layers(ar, wmn, wmn->reference); ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); + break; + case ND_LAYER: + if (wmn->reference) { + BKE_screen_view3d_sync(v3d, wmn->reference); + } + ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); break; - case ND_FRAME: - case ND_TRANSFORM: case ND_OB_ACTIVE: case ND_OB_SELECT: + DEG_id_tag_update((ID *)&scene->id, DEG_TAG_COPY_ON_WRITE); + ATTR_FALLTHROUGH; + case ND_FRAME: + case ND_TRANSFORM: case ND_OB_VISIBLE: - case ND_LAYER: case ND_RENDER_OPTIONS: case ND_MARKERS: case ND_MODE: ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); break; case ND_WORLD: /* handled by space_view3d_listener() for v3d access */ @@ -847,7 +877,6 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_DRAW_RENDER_VIEWPORT: { if (v3d->camera && (scene == wmn->reference)) { - RegionView3D *rv3d = ar->regiondata; if (rv3d->persp == RV3D_CAMOB) { ED_region_tag_redraw(ar); } @@ -872,6 +901,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_POINTCACHE: case ND_LOD: ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); break; } switch (wmn->action) { @@ -882,9 +912,30 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w break; case NC_GEOM: switch (wmn->data) { + case ND_SELECT: + { + WM_manipulatormap_tag_refresh(mmap); + + if (scene->obedit) { + Object *ob = scene->obedit; + switch (ob->type) { + case OB_MESH: + BKE_mesh_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_SELECT); + break; + // case OB_FONT: /* handled by text_update_edited */ + case OB_CURVE: + case OB_SURF: + BKE_curve_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_SELECT); + break; + case OB_LATTICE: + BKE_lattice_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_SELECT); + break; + } + } + ATTR_FALLTHROUGH; + } case ND_DATA: case ND_VERTEX_GROUP: - case ND_SELECT: ED_region_tag_redraw(ar); break; } @@ -899,7 +950,6 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_DRAW_RENDER_VIEWPORT: { if (v3d->camera && (v3d->camera->data == wmn->reference)) { - RegionView3D *rv3d = ar->regiondata; if (rv3d->persp == RV3D_CAMOB) { ED_region_tag_redraw(ar); } @@ -928,21 +978,13 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w switch (wmn->data) { case ND_SHADING: case ND_NODES: - { -#ifdef WITH_LEGACY_DEPSGRAPH - Object *ob = OBACT; - if ((v3d->drawtype == OB_MATERIAL) || - (ob && (ob->mode == OB_MODE_TEXTURE_PAINT)) || - (v3d->drawtype == OB_TEXTURE && - (scene->gm.matmode == GAME_MAT_GLSL || - BKE_scene_use_new_shading_nodes(scene))) || - !DEG_depsgraph_use_legacy()) -#endif - { - ED_region_tag_redraw(ar); - } + /* TODO(sergey) This is a bit too much updates, but needed to + * have proper material drivers update in the viewport. + * + * How to solve? + */ + ED_region_tag_redraw(ar); break; - } case ND_SHADING_DRAW: case ND_SHADING_LINKS: ED_region_tag_redraw(ar); @@ -954,20 +996,23 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_WORLD_DRAW: /* handled by space_view3d_listener() for v3d access */ break; + case ND_WORLD: + /* Needed for updating world materials */ + ED_region_tag_redraw(ar); + break; } break; case NC_LAMP: switch (wmn->data) { case ND_LIGHTING: - if ((v3d->drawtype == OB_MATERIAL) || - (v3d->drawtype == OB_TEXTURE && (scene->gm.matmode == GAME_MAT_GLSL)) || - !DEG_depsgraph_use_legacy()) - { - ED_region_tag_redraw(ar); - } + /* TODO(sergey): This is a bit too much, but needed to + * handle updates from new depsgraph. + */ + ED_region_tag_redraw(ar); break; case ND_LIGHTING_DRAW: ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); break; } break; @@ -987,10 +1032,10 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case NC_SPACE: if (wmn->data == ND_SPACE_VIEW3D) { if (wmn->subtype == NS_VIEW3D_GPU) { - RegionView3D *rv3d = ar->regiondata; rv3d->rflag |= RV3D_GPULIGHT_UPDATE; } ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); } break; case NC_ID: @@ -1003,15 +1048,13 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_SKETCH: ED_region_tag_redraw(ar); break; - case ND_SCREENBROWSE: - case ND_SCREENDELETE: - case ND_SCREENSET: - /* screen was changed, need to update used layers due to NC_SCENE|ND_LAYER_CONTENT */ - /* updates used layers only for View3D in active screen */ - if (wmn->reference) { - bScreen *sc_ref = wmn->reference; - view3d_recalc_used_layers(ar, wmn, sc_ref->scene); - } + case ND_LAYOUTBROWSE: + case ND_LAYOUTDELETE: + case ND_LAYOUTSET: + WM_manipulatormap_tag_refresh(mmap); + ED_region_tag_redraw(ar); + break; + case ND_LAYER: ED_region_tag_redraw(ar); break; } @@ -1028,7 +1071,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w /* concept is to retrieve cursor type context-less */ static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar)) { - Scene *scene = win->screen->scene; + const Scene *scene = WM_window_get_active_scene(win); if (scene->obedit) { WM_cursor_set(win, CURSOR_EDIT); @@ -1053,7 +1096,9 @@ static void view3d_header_region_draw(const bContext *C, ARegion *ar) ED_region_header(C, ar); } -static void view3d_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void view3d_header_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -1099,7 +1144,9 @@ static void view3d_buttons_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, NULL, -1, true); } -static void view3d_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void view3d_buttons_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -1205,7 +1252,9 @@ static void view3d_tools_region_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, CTX_data_mode_string(C), -1, true); } -static void view3d_props_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +static void view3d_props_region_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, + wmNotifier *wmn, const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { @@ -1225,7 +1274,9 @@ static void view3d_props_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa } /* area (not region) level listener */ -static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNotifier *wmn) +static void space_view3d_listener( + bScreen *UNUSED(sc), ScrArea *sa, struct wmNotifier *wmn, Scene *UNUSED(scene), + WorkSpace *UNUSED(workspace)) { View3D *v3d = sa->spacedata.first; @@ -1260,8 +1311,6 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot } const char *view3d_context_dir[] = { - "selected_objects", "selected_bases", "selected_editable_objects", - "selected_editable_bases", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases", "active_base", "active_object", NULL }; @@ -1272,109 +1321,27 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes if (CTX_data_dir(member)) { CTX_data_dir_set(result, view3d_context_dir); } - else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool selected_objects = CTX_data_equals(member, "selected_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (selected_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if ((base->flag & SELECT) && (base->lay & lay)) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (0 == BKE_object_is_libdata(base->object)) { - if (selected_editable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool visible_objects = CTX_data_equals(member, "visible_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (base->lay & lay) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) { - if (visible_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - Base *base; - const bool selectable_objects = CTX_data_equals(member, "selectable_objects"); - - for (base = scene->base.first; base; base = base->next) { - if (base->lay & lay) { - if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) { - if (selectable_objects) - CTX_data_id_list_add(result, &base->object->id); - else - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } else if (CTX_data_equals(member, "active_base")) { - View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - if (scene->basact && (scene->basact->lay & lay)) { - Object *ob = scene->basact->object; + SceneLayer *sl = CTX_data_scene_layer(C); + if (sl->basact) { + Object *ob = sl->basact->object; /* if hidden but in edit mode, we still display, can happen with animation */ - if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) - CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact); + if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT)) { + CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, sl->basact); + } } return 1; } else if (CTX_data_equals(member, "active_object")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const unsigned int lay = v3d ? v3d->lay : scene->lay; - if (scene->basact && (scene->basact->lay & lay)) { - Object *ob = scene->basact->object; - if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) - CTX_data_id_pointer_set(result, &scene->basact->object->id); + SceneLayer *sl = CTX_data_scene_layer(C); + if (sl->basact) { + Object *ob = sl->basact->object; + /* if hidden but in edit mode, we still display, can happen with animation */ + if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) { + CTX_data_id_pointer_set(result, &ob->id); + } } return 1; @@ -1424,21 +1391,6 @@ static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_i v3d->ob_centre_bone[0] = '\0'; } } - - if (ELEM(GS(old_id->name), ID_IM, ID_MC)) { - for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { - if ((ID *)bgpic->ima == old_id) { - bgpic->ima = (Image *)new_id; - id_us_min(old_id); - id_us_plus(new_id); - } - if ((ID *)bgpic->clip == old_id) { - bgpic->clip = (MovieClip *)new_id; - id_us_min(old_id); - id_us_plus(new_id); - } - } - } } if (is_local) { @@ -1464,6 +1416,7 @@ void ED_spacetype_view3d(void) st->operatortypes = view3d_operatortypes; st->keymap = view3d_keymap; st->dropboxes = view3d_dropboxes; + st->manipulators = view3d_widgets; st->context = view3d_context; st->id_remap = view3d_id_remap; diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 0c67776693d..ac808487dd2 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -55,13 +55,14 @@ #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_customdata.h" -#include "BKE_depsgraph.h" #include "BKE_screen.h" #include "BKE_editmesh.h" #include "BKE_deform.h" #include "BKE_object.h" #include "BKE_object_deform.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -776,18 +777,18 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event) return; } else { - Scene *scene = CTX_data_scene(C); - Object *ob = scene->basact->object; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = sl->basact->object; ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); } } static int view3d_panel_vgroup_poll(const bContext *C, PanelType *UNUSED(pt)) { - Scene *scene = CTX_data_scene(C); - Object *ob = OBACT; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = OBACT(sl); if (ob && (BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob))) { @@ -805,7 +806,8 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) { uiBlock *block = uiLayoutAbsoluteBlock(pa->layout); Scene *scene = CTX_data_scene(C); - Object *ob = scene->basact->object; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = sl->basact->object; MDeformVert *dv; @@ -1095,9 +1097,9 @@ static void v3d_editmetaball_buts(uiLayout *layout, Object *ob) static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event) { - Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); View3D *v3d = CTX_wm_view3d(C); - Object *ob = OBACT; + Object *ob = OBACT(sl); switch (event) { @@ -1108,7 +1110,7 @@ static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event case B_OBJECTPANELMEDIAN: if (ob) { v3d_editvertex_buts(NULL, v3d, ob, 1.0); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } break; } @@ -1119,16 +1121,17 @@ static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event static int view3d_panel_transform_poll(const bContext *C, PanelType *UNUSED(pt)) { - Scene *scene = CTX_data_scene(C); - return (scene->basact != NULL); + SceneLayer *sl = CTX_data_scene_layer(C); + return (sl->basact != NULL); } static void view3d_panel_transform(const bContext *C, Panel *pa) { uiBlock *block; Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Object *obedit = CTX_data_edit_object(C); - Object *ob = scene->basact->object; + Object *ob = sl->basact->object; uiLayout *col; block = uiLayoutGetBlock(pa->layout); diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c index f717f1c0a43..9b07593e576 100644 --- a/source/blender/editors/space_view3d/view3d_camera_control.c +++ b/source/blender/editors/space_view3d/view3d_camera_control.c @@ -54,8 +54,9 @@ #include "BLI_utildefines.h" #include "BKE_object.h" +#include "BKE_context.h" -#include "BKE_depsgraph.h" /* for object updating */ +#include "DEG_depsgraph.h" #include "ED_screen.h" @@ -137,10 +138,13 @@ Object *ED_view3d_cameracontrol_object_get(View3DCameraControl *vctrl) * the view for first-person style navigation. */ struct View3DCameraControl *ED_view3d_cameracontrol_acquire( - Scene *scene, View3D *v3d, RegionView3D *rv3d, + const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d, const bool use_parent_root) { View3DCameraControl *vctrl; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); vctrl = MEM_callocN(sizeof(View3DCameraControl), __func__); @@ -177,7 +181,7 @@ struct View3DCameraControl *ED_view3d_cameracontrol_acquire( /* store the original camera loc and rot */ vctrl->obtfm = BKE_object_tfm_backup(ob_back); - BKE_object_where_is_calc(scene, v3d->camera); + BKE_object_where_is_calc(&eval_ctx, scene, v3d->camera); negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]); rv3d->dist = 0.0; @@ -242,7 +246,7 @@ void ED_view3d_cameracontrol_update( ob_update = v3d->camera->parent; while (ob_update) { - DAG_id_tag_update(&ob_update->id, OB_RECALC_OB); + DEG_id_tag_update(&ob_update->id, OB_RECALC_OB); ob_update = ob_update->parent; } @@ -264,7 +268,7 @@ void ED_view3d_cameracontrol_update( BKE_object_apply_mat4(v3d->camera, view_mat, true, true); - DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); + DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); copy_v3_v3(v3d->camera->size, size_back); @@ -299,7 +303,7 @@ void ED_view3d_cameracontrol_release( /* store the original camera loc and rot */ BKE_object_tfm_restore(ob_back, vctrl->obtfm); - DAG_id_tag_update(&ob_back->id, OB_RECALC_OB); + DEG_id_tag_update(&ob_back->id, OB_RECALC_OB); } else { /* Non Camera we need to reset the view back to the original location bacause the user canceled*/ @@ -311,7 +315,7 @@ void ED_view3d_cameracontrol_release( rv3d->dist = vctrl->dist_backup; } else if (vctrl->persp_backup == RV3D_CAMOB) { /* camera */ - DAG_id_tag_update((ID *)view3d_cameracontrol_object(vctrl), OB_RECALC_OB); + DEG_id_tag_update((ID *)view3d_cameracontrol_object(vctrl), OB_RECALC_OB); /* always, is set to zero otherwise */ copy_v3_v3(rv3d->ofs, vctrl->ofs_backup); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 56508ea989a..475e9cd07bf 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -28,948 +28,282 @@ * \ingroup spview3d */ -#include <string.h> -#include <stdio.h> #include <math.h> -#include "DNA_armature_types.h" -#include "DNA_camera_types.h" -#include "DNA_customdata_types.h" -#include "DNA_object_types.h" -#include "DNA_group_types.h" -#include "DNA_mesh_types.h" -#include "DNA_key_types.h" -#include "DNA_lamp_types.h" -#include "DNA_scene_types.h" -#include "DNA_world_types.h" -#include "DNA_brush_types.h" - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" +#include "BLI_listbase.h" #include "BLI_math.h" -#include "BLI_jitter.h" -#include "BLI_utildefines.h" -#include "BLI_endian_switch.h" +#include "BLI_rect.h" +#include "BLI_string.h" #include "BLI_threads.h" +#include "BLI_jitter.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" -#include "BKE_anim.h" #include "BKE_camera.h" #include "BKE_context.h" -#include "BKE_customdata.h" -#include "BKE_DerivedMesh.h" -#include "BKE_image.h" +#include "BKE_global.h" #include "BKE_key.h" -#include "BKE_main.h" +#include "BKE_scene.h" #include "BKE_object.h" -#include "BKE_global.h" #include "BKE_paint.h" -#include "BKE_scene.h" -#include "BKE_screen.h" #include "BKE_unit.h" -#include "BKE_movieclip.h" - -#include "RE_engine.h" -#include "IMB_imbuf_types.h" -#include "IMB_imbuf.h" -#include "IMB_colormanagement.h" +#include "BLF_api.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" +#include "BLT_translation.h" -#include "WM_api.h" +#include "DNA_armature_types.h" +#include "DNA_brush_types.h" +#include "DNA_camera_types.h" +#include "DNA_key_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_view3d_types.h" +#include "DNA_windowmanager_types.h" -#include "BLF_api.h" -#include "BLT_translation.h" +#include "DRW_engine.h" #include "ED_armature.h" #include "ED_keyframing.h" #include "ED_gpencil.h" #include "ED_screen.h" -#include "ED_space_api.h" -#include "ED_screen_types.h" #include "ED_transform.h" -#include "UI_interface.h" -#include "UI_interface_icons.h" -#include "UI_resources.h" +#include "DEG_depsgraph_query.h" #include "GPU_draw.h" -#include "GPU_framebuffer.h" +#include "GPU_matrix.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" #include "GPU_material.h" +#include "GPU_viewport.h" #include "GPU_compositing.h" -#include "GPU_extensions.h" -#include "GPU_select.h" - -#include "view3d_intern.h" /* own include */ - -/* prototypes */ -static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d); -static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect); -static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar, - float winmat[4][4], const char *viewname); - -/* handy utility for drawing shapes in the viewport for arbitrary code. - * could add lines and points too */ -// #define DEBUG_DRAW -#ifdef DEBUG_DRAW -static void bl_debug_draw(void); -/* add these locally when using these functions for testing */ -extern void bl_debug_draw_quad_clear(void); -extern void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]); -extern void bl_debug_draw_edge_add(const float v0[3], const float v1[3]); -extern void bl_debug_color_set(const unsigned int col); -#endif - -void circf(float x, float y, float rad) -{ - GLUquadricObj *qobj = gluNewQuadric(); - - gluQuadricDrawStyle(qobj, GLU_FILL); - - glPushMatrix(); - - glTranslatef(x, y, 0.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.0); - - gluDisk(qobj, 0.0, rad, 32, 1); - - glPopMatrix(); - - gluDeleteQuadric(qobj); -} - -/* ********* custom clipping *********** */ - -static void view3d_draw_clipping(RegionView3D *rv3d) -{ - BoundBox *bb = rv3d->clipbb; - - if (bb) { - const unsigned int clipping_index[6][4] = { - {0, 1, 2, 3}, - {0, 4, 5, 1}, - {4, 7, 6, 5}, - {7, 3, 2, 6}, - {1, 5, 6, 2}, - {7, 4, 0, 3} - }; - - /* fill in zero alpha for rendering & re-projection [#31530] */ - unsigned char col[4]; - UI_GetThemeColor4ubv(TH_V3D_CLIPPING_BORDER, col); - glColor4ubv(col); - - glEnable(GL_BLEND); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, bb->vec); - glDrawElements(GL_QUADS, sizeof(clipping_index) / sizeof(unsigned int), GL_UNSIGNED_INT, clipping_index); - glDisableClientState(GL_VERTEX_ARRAY); - glDisable(GL_BLEND); - } -} +#include "MEM_guardedalloc.h" -void ED_view3d_clipping_set(RegionView3D *rv3d) -{ - double plane[4]; - const unsigned int tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6; - unsigned int a; - - for (a = 0; a < tot; a++) { - copy_v4db_v4fl(plane, rv3d->clip[a]); - glClipPlane(GL_CLIP_PLANE0 + a, plane); - glEnable(GL_CLIP_PLANE0 + a); - } -} +#include "UI_interface.h" +#include "UI_resources.h" -/* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */ -void ED_view3d_clipping_disable(void) -{ - unsigned int a; +#include "RE_engine.h" - for (a = 0; a < 6; a++) { - glDisable(GL_CLIP_PLANE0 + a); - } -} -void ED_view3d_clipping_enable(void) -{ - unsigned int a; +#include "WM_api.h" +#include "WM_types.h" - for (a = 0; a < 6; a++) { - glEnable(GL_CLIP_PLANE0 + a); - } -} +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" -static bool view3d_clipping_test(const float co[3], const float clip[6][4]) -{ - if (plane_point_side_v3(clip[0], co) > 0.0f) - if (plane_point_side_v3(clip[1], co) > 0.0f) - if (plane_point_side_v3(clip[2], co) > 0.0f) - if (plane_point_side_v3(clip[3], co) > 0.0f) - return false; +#include "view3d_intern.h" /* own include */ - return true; -} +/* ******************** general functions ***************** */ -/* for 'local' ED_view3d_clipping_local must run first - * then all comparisons can be done in localspace */ -bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local) +static bool use_depth_doit(Scene *scene, View3D *v3d) { - return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip); -} - -/* ********* end custom clipping *********** */ - - -static void drawgrid_draw(ARegion *ar, double wx, double wy, double x, double y, double dx) -{ - double verts[2][2]; - - x += (wx); - y += (wy); - - /* set fixed 'Y' */ - verts[0][1] = 0.0f; - verts[1][1] = (double)ar->winy; + if (v3d->drawtype > OB_WIRE) + return true; - /* iter over 'X' */ - verts[0][0] = verts[1][0] = x - dx * floor(x / dx); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_DOUBLE, 0, verts); - - while (verts[0][0] < ar->winx) { - glDrawArrays(GL_LINES, 0, 2); - verts[0][0] = verts[1][0] = verts[0][0] + dx; - } - - /* set fixed 'X' */ - verts[0][0] = 0.0f; - verts[1][0] = (double)ar->winx; - - /* iter over 'Y' */ - verts[0][1] = verts[1][1] = y - dx * floor(y / dx); - while (verts[0][1] < ar->winy) { - glDrawArrays(GL_LINES, 0, 2); - verts[0][1] = verts[1][1] = verts[0][1] + dx; + /* special case (depth for wire color) */ + if (v3d->drawtype <= OB_WIRE) { + if (scene->obedit && scene->obedit->type == OB_MESH) { + Mesh *me = scene->obedit->data; + if (me->drawflag & ME_DRAWEIGHT) { + return true; + } + } } - - glDisableClientState(GL_VERTEX_ARRAY); + return false; } -#define GRID_MIN_PX_D 6.0 -#define GRID_MIN_PX_F 6.0f - -static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit) +/** + * \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore + */ +void ED_view3d_update_viewmat( + const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar, + float viewmat[4][4], float winmat[4][4], const rcti *rect) { - /* extern short bgpicmode; */ RegionView3D *rv3d = ar->regiondata; - double wx, wy, x, y, fw, fx, fy, dx; - double vec4[4]; - unsigned char col[3], col2[3]; - - fx = rv3d->persmat[3][0]; - fy = rv3d->persmat[3][1]; - fw = rv3d->persmat[3][3]; - - wx = (ar->winx / 2.0); /* because of rounding errors, grid at wrong location */ - wy = (ar->winy / 2.0); - - x = (wx) * fx / fw; - y = (wy) * fy / fw; - - vec4[0] = vec4[1] = v3d->grid; - - vec4[2] = 0.0; - vec4[3] = 1.0; - mul_m4_v4d(rv3d->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); - - glLineWidth(1.0f); - glDepthMask(GL_FALSE); /* disable write in zbuffer */ - - /* check zoom out */ - UI_ThemeColor(TH_GRID); - - if (unit->system) { - /* Use GRID_MIN_PX * 2 for units because very very small grid - * items are less useful when dealing with units */ - const void *usys; - int len, i; - double dx_scalar; - float blend_fac; - bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len); - - if (usys) { - i = len; - while (i--) { - double scalar = bUnit_GetScaler(usys, i); - - dx_scalar = dx * scalar / (double)unit->scale_length; - if (dx_scalar < (GRID_MIN_PX_D * 2.0)) - continue; + /* setup window matrices */ + if (winmat) + copy_m4_m4(rv3d->winmat, winmat); + else + view3d_winmatrix_set(ar, v3d, rect); - /* Store the smallest drawn grid size units name so users know how big each grid cell is */ - if (*grid_unit == NULL) { - *grid_unit = bUnit_GetNameDisplay(usys, i); - rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length); - } - blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar); + /* setup view matrix */ + if (viewmat) + copy_m4_m4(rv3d->viewmat, viewmat); + else + view3d_viewmatrix_set(eval_ctx, scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */ - /* tweak to have the fade a bit nicer */ - blend_fac = (blend_fac * blend_fac) * 2.0f; - CLAMP(blend_fac, 0.3f, 1.0f); + /* update utility matrices */ + mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); + invert_m4_m4(rv3d->persinv, rv3d->persmat); + invert_m4_m4(rv3d->viewinv, rv3d->viewmat); + /* calculate GLSL view dependent values */ - UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, blend_fac); + /* store window coordinates scaling/offset */ + if (rv3d->persp == RV3D_CAMOB && v3d->camera) { + rctf cameraborder; + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false); + rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder); + rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder); - drawgrid_draw(ar, wx, wy, x, y, dx_scalar); - } - } + rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx; + rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy; } else { - const double sublines = v3d->gridsubdiv; - const float sublines_fl = v3d->gridsubdiv; - - if (dx < GRID_MIN_PX_D) { - rv3d->gridview *= sublines_fl; - dx *= sublines; - - if (dx < GRID_MIN_PX_D) { - rv3d->gridview *= sublines_fl; - dx *= sublines; - - if (dx < GRID_MIN_PX_D) { - rv3d->gridview *= sublines_fl; - dx *= sublines; - if (dx < GRID_MIN_PX_D) { - /* pass */ - } - else { - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, dx); - } - } - else { /* start blending out */ - UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); - drawgrid_draw(ar, wx, wy, x, y, dx); - - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, sublines * dx); - } - } - else { /* start blending out (GRID_MIN_PX < dx < (GRID_MIN_PX * 10)) */ - UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); - drawgrid_draw(ar, wx, wy, x, y, dx); - - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, sublines * dx); - } - } - else { - if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */ - rv3d->gridview /= sublines_fl; - dx /= sublines; - if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */ - rv3d->gridview /= sublines_fl; - dx /= sublines; - if (dx > (GRID_MIN_PX_D * 10.0)) { - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, dx); - } - else { - UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); - drawgrid_draw(ar, wx, wy, x, y, dx); - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, dx * sublines); - } - } - else { - UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); - drawgrid_draw(ar, wx, wy, x, y, dx); - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, dx * sublines); - } - } - else { - UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0)); - drawgrid_draw(ar, wx, wy, x, y, dx); - UI_ThemeColor(TH_GRID); - drawgrid_draw(ar, wx, wy, x, y, dx * sublines); - } - } + rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f; + rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f; } + /* calculate pixelsize factor once, is used for lamps and obcenters */ + { + /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' + * because of float point precision problems at large values [#23908] */ + float v1[3], v2[3]; + float len_px, len_sc; - x += (wx); - y += (wy); - UI_GetThemeColor3ubv(TH_GRID, col); - - setlinestyle(0); - - /* center cross */ - /* horizontal line */ - if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) - UI_make_axis_color(col, col2, 'Y'); - else UI_make_axis_color(col, col2, 'X'); - glColor3ubv(col2); - - fdrawline(0.0, y, (float)ar->winx, y); - - /* vertical line */ - if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) - UI_make_axis_color(col, col2, 'Y'); - else UI_make_axis_color(col, col2, 'Z'); - glColor3ubv(col2); - - fdrawline(x, 0.0, x, (float)ar->winy); - - glDepthMask(GL_TRUE); /* enable write in zbuffer */ -} -#undef GRID_MIN_PX + v1[0] = rv3d->persmat[0][0]; + v1[1] = rv3d->persmat[1][0]; + v1[2] = rv3d->persmat[2][0]; -/** could move this elsewhere, but tied into #ED_view3d_grid_scale */ -float ED_scene_grid_scale(Scene *scene, const char **grid_unit) -{ - /* apply units */ - if (scene->unit.system) { - const void *usys; - int len; + v2[0] = rv3d->persmat[0][1]; + v2[1] = rv3d->persmat[1][1]; + v2[2] = rv3d->persmat[2][1]; - bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len); + len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2))); + len_sc = (float)MAX2(ar->winx, ar->winy); - if (usys) { - int i = bUnit_GetBaseUnit(usys); - if (grid_unit) - *grid_unit = bUnit_GetNameDisplay(usys, i); - return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length; - } + rv3d->pixsize = len_px / len_sc; } - - return 1.0f; -} - -float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) -{ - return v3d->grid * ED_scene_grid_scale(scene, grid_unit); } -static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth) +static void view3d_main_region_setup_view( + const EvaluationContext *eval_ctx, Scene *scene, + View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect) { - float grid, grid_scale; - unsigned char col_grid[3]; - const int gridlines = v3d->gridlines / 2; - - if (v3d->gridlines < 3) return; - - /* use 'grid_scale' instead of 'v3d->grid' from now on */ - grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit); - grid = gridlines * grid_scale; - - if (!write_depth) - glDepthMask(GL_FALSE); - - UI_GetThemeColor3ubv(TH_GRID, col_grid); - - glLineWidth(1); - - /* draw the Y axis and/or grid lines */ - if (v3d->gridflag & V3D_SHOW_FLOOR) { - const int sublines = v3d->gridsubdiv; - float vert[4][3] = {{0.0f}}; - unsigned char col_bg[3]; - unsigned char col_grid_emphasise[3], col_grid_light[3]; - int a; - int prev_emphasise = -1; - - UI_GetThemeColor3ubv(TH_BACK, col_bg); - - /* emphasise division lines lighter instead of darker, if background is darker than grid */ - UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10); - UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise, - (((col_grid[0] + col_grid[1] + col_grid[2]) + 30) > - (col_bg[0] + col_bg[1] + col_bg[2])) ? 20 : -10); - - /* set fixed axis */ - vert[0][0] = vert[2][1] = grid; - vert[1][0] = vert[3][1] = -grid; - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vert); - - for (a = -gridlines; a <= gridlines; a++) { - const float line = a * grid_scale; - const int is_emphasise = (a % sublines) == 0; - - if (is_emphasise != prev_emphasise) { - glColor3ubv(is_emphasise ? col_grid_emphasise : col_grid_light); - prev_emphasise = is_emphasise; - } - - /* set variable axis */ - vert[0][1] = vert[1][1] = vert[2][0] = vert[3][0] = line; + RegionView3D *rv3d = ar->regiondata; - glDrawArrays(GL_LINES, 0, 4); - } + ED_view3d_update_viewmat(eval_ctx, scene, v3d, ar, viewmat, winmat, rect); - glDisableClientState(GL_VERTEX_ARRAY); - } - - /* draw the Z axis line */ - /* check for the 'show Z axis' preference */ - if (v3d->gridflag & (V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) { - glBegin(GL_LINES); - int axis; - for (axis = 0; axis < 3; axis++) { - if (v3d->gridflag & (V3D_SHOW_X << axis)) { - float vert[3]; - unsigned char tcol[3]; - - UI_make_axis_color(col_grid, tcol, 'X' + axis); - glColor3ubv(tcol); - - zero_v3(vert); - vert[axis] = grid; - glVertex3fv(vert); - vert[axis] = -grid; - glVertex3fv(vert); - } - } - glEnd(); - } - - glDepthMask(GL_TRUE); + /* set for opengl */ + gpuLoadProjectionMatrix(rv3d->winmat); + gpuLoadMatrix(rv3d->viewmat); } - -static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d) +static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d) { - int co[2]; - - /* we don't want the clipping for cursor */ - if (ED_view3d_project_int_global(ar, ED_view3d_cursor3d_get(scene, v3d), co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - const float f5 = 0.25f * U.widget_unit; - const float f10 = 0.5f * U.widget_unit; - const float f20 = U.widget_unit; - - glLineWidth(1); - setlinestyle(0); - cpack(0xFF); - circ((float)co[0], (float)co[1], f10); - setlinestyle(4); - cpack(0xFFFFFF); - circ((float)co[0], (float)co[1], f10); - setlinestyle(0); - - UI_ThemeColor(TH_VIEW_OVERLAY); - sdrawline(co[0] - f20, co[1], co[0] - f5, co[1]); - sdrawline(co[0] + f5, co[1], co[0] + f20, co[1]); - sdrawline(co[0], co[1] - f20, co[0], co[1] - f5); - sdrawline(co[0], co[1] + f5, co[0], co[1] + f20); + if ((scene->r.scemode & R_MULTIVIEW) == 0) { + return false; } -} - -/* Draw a live substitute of the view icon, which is always shown - * colors copied from transform_manipulator.c, we should keep these matching. */ -static void draw_view_axis(RegionView3D *rv3d, rcti *rect) -{ - const float k = U.rvisize * U.pixelsize; /* axis size */ - const float toll = 0.5; /* used to see when view is quasi-orthogonal */ - float startx = k + 1.0f; /* axis center in screen coordinates, x=y */ - float starty = k + 1.0f; - float ydisp = 0.0; /* vertical displacement to allow obj info text */ - int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */ - float vec[3]; - float dx, dy; - - int axis_order[3] = {0, 1, 2}; - int axis_i; - startx += rect->xmin; - starty += rect->ymin; - - axis_sort_v3(rv3d->viewinv[2], axis_order); - - /* thickness of lines is proportional to k */ - glLineWidth(2); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - for (axis_i = 0; axis_i < 3; axis_i++) { - int i = axis_order[axis_i]; - const char axis_text[2] = {'x' + i, '\0'}; - - zero_v3(vec); - vec[i] = 1.0f; - mul_qt_v3(rv3d->viewquat, vec); - dx = vec[0] * k; - dy = vec[1] * k; - - UI_ThemeColorShadeAlpha(TH_AXIS_X + i, 0, bright); - glBegin(GL_LINES); - glVertex2f(startx, starty + ydisp); - glVertex2f(startx + dx, starty + dy + ydisp); - glEnd(); - - if (fabsf(dx) > toll || fabsf(dy) > toll) { - BLF_draw_default_ascii(startx + dx + 2, starty + dy + ydisp + 2, 0.0f, axis_text, 1); - - /* BLF_draw_default disables blending */ - glEnable(GL_BLEND); - } + if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) { + return false; } - glDisable(GL_BLEND); -} - -#ifdef WITH_INPUT_NDOF -/* draw center and axis of rotation for ongoing 3D mouse navigation */ -static void draw_rotation_guide(RegionView3D *rv3d) -{ - float o[3]; /* center of rotation */ - float end[3]; /* endpoints for drawing */ - - float color[4] = {0.0f, 0.4235f, 1.0f, 1.0f}; /* bright blue so it matches device LEDs */ - - negate_v3_v3(o, rv3d->ofs); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glPointSize(5); - glEnable(GL_POINT_SMOOTH); - glDepthMask(0); /* don't overwrite zbuf */ - - if (rv3d->rot_angle != 0.0f) { - /* -- draw rotation axis -- */ - float scaled_axis[3]; - const float scale = rv3d->dist; - mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale); - - - glBegin(GL_LINE_STRIP); - color[3] = 0.0f; /* more transparent toward the ends */ - glColor4fv(color); - add_v3_v3v3(end, o, scaled_axis); - glVertex3fv(end); - -#if 0 - color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */ - /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */ -#endif - - color[3] = 0.5f; /* more opaque toward the center */ - glColor4fv(color); - glVertex3fv(o); - - color[3] = 0.0f; - glColor4fv(color); - sub_v3_v3v3(end, o, scaled_axis); - glVertex3fv(end); - glEnd(); - - /* -- draw ring around rotation center -- */ - { -#define ROT_AXIS_DETAIL 13 - - const float s = 0.05f * scale; - const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL); - float angle; - int i; - - float q[4]; /* rotate ring so it's perpendicular to axis */ - const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f; - if (!upright) { - const float up[3] = {0.0f, 0.0f, 1.0f}; - float vis_angle, vis_axis[3]; - - cross_v3_v3v3(vis_axis, up, rv3d->rot_axis); - vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis)); - axis_angle_to_quat(q, vis_axis, vis_angle); + switch (v3d->stereo3d_camera) { + case STEREO_MONO_ID: + return false; + break; + case STEREO_3D_ID: + /* win will be NULL when calling this from the selection or draw loop. */ + if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) { + return false; } - - color[3] = 0.25f; /* somewhat faint */ - glColor4fv(color); - glBegin(GL_LINE_LOOP); - for (i = 0, angle = 0.0f; i < ROT_AXIS_DETAIL; ++i, angle += step) { - float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f}; - - if (!upright) { - mul_qt_v3(q, p); - } - - add_v3_v3(p, o); - glVertex3fv(p); + if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) && + !BKE_scene_multiview_is_stereo3d(&scene->r)) + { + return false; } - glEnd(); - -#undef ROT_AXIS_DETAIL - } - - color[3] = 1.0f; /* solid dot */ - } - else - color[3] = 0.5f; /* see-through dot */ - - /* -- draw rotation center -- */ - glColor4fv(color); - glBegin(GL_POINTS); - glVertex3fv(o); - glEnd(); - -#if 0 - /* find screen coordinates for rotation center, then draw pretty icon */ - mul_m4_v3(rv3d->persinv, rot_center); - UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN); - /* ^^ just playing around, does not work */ -#endif - - glDisable(GL_BLEND); - glDisable(GL_POINT_SMOOTH); - glDepthMask(1); -} -#endif /* WITH_INPUT_NDOF */ - -static void draw_view_icon(RegionView3D *rv3d, rcti *rect) -{ - BIFIconID icon; - - if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) - icon = ICON_AXIS_TOP; - else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) - icon = ICON_AXIS_FRONT; - else if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) - icon = ICON_AXIS_SIDE; - else return; - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - UI_icon_draw(5.0 + rect->xmin, 5.0 + rect->ymin, icon); - - glDisable(GL_BLEND); -} - -static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d) -{ - const char *name = NULL; - - switch (rv3d->view) { - case RV3D_VIEW_FRONT: - if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho"); - else name = IFACE_("Front Persp"); - break; - case RV3D_VIEW_BACK: - if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho"); - else name = IFACE_("Back Persp"); - break; - case RV3D_VIEW_TOP: - if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho"); - else name = IFACE_("Top Persp"); - break; - case RV3D_VIEW_BOTTOM: - if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho"); - else name = IFACE_("Bottom Persp"); - break; - case RV3D_VIEW_RIGHT: - if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho"); - else name = IFACE_("Right Persp"); break; - case RV3D_VIEW_LEFT: - if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho"); - else name = IFACE_("Left Persp"); - break; - + /* We always need the stereo calculation for left and right cameras. */ + case STEREO_LEFT_ID: + case STEREO_RIGHT_ID: default: - if (rv3d->persp == RV3D_CAMOB) { - if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) { - Camera *cam; - cam = v3d->camera->data; - if (cam->type == CAM_PERSP) { - name = IFACE_("Camera Persp"); - } - else if (cam->type == CAM_ORTHO) { - name = IFACE_("Camera Ortho"); - } - else { - BLI_assert(cam->type == CAM_PANO); - name = IFACE_("Camera Pano"); - } - } - else { - name = IFACE_("Object as Camera"); - } - } - else { - name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp"); - } break; } - - return name; + return true; } -static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect) -{ - RegionView3D *rv3d = ar->regiondata; - const char *name = view3d_get_name(v3d, rv3d); - /* increase size for unicode languages (Chinese in utf-8...) */ -#ifdef WITH_INTERNATIONAL - char tmpstr[96]; -#else - char tmpstr[32]; -#endif - if (v3d->localvd) { - BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name); - name = tmpstr; - } +/* setup the view and win matrices for the multiview cameras + * + * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called + * we have no winmatrix (i.e., projection matrix) defined at that time. + * Since the camera and the camera shift are needed for the winmat calculation + * we do a small hack to replace it temporarily so we don't need to change the + * view3d)main_region_setup_view() code to account for that. + */ +static void view3d_stereo3d_setup( + const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect) +{ + bool is_left; + const char *names[2] = { STEREO_LEFT_NAME, STEREO_RIGHT_NAME }; + const char *viewname; - UI_ThemeColor(TH_TEXT_HI); -#ifdef WITH_INTERNATIONAL - BLF_draw_default(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr)); -#else - BLF_draw_default_ascii(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr)); -#endif -} + /* show only left or right camera */ + if (v3d->stereo3d_camera != STEREO_3D_ID) + v3d->multiview_eye = v3d->stereo3d_camera; -/* draw info beside axes in bottom left-corner: - * framenum, object name, bone name (if available), marker name (if available) - */ + is_left = v3d->multiview_eye == STEREO_LEFT_ID; + viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID]; -static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) -{ - const int cfra = CFRA; - const char *msg_pin = " (Pinned)"; - const char *msg_sep = " : "; + /* update the viewport matrices with the new camera */ + if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { + Camera *data; + float viewmat[4][4]; + float shiftx; - char info[300]; - const char *markern; - char *s = info; - short offset = 1.5f * UI_UNIT_X + rect->xmin; + data = (Camera *)v3d->camera->data; + shiftx = data->shiftx; - s += sprintf(s, "(%d)", cfra); + BLI_lock_thread(LOCK_VIEW3D); + data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname); - /* - * info can contain: - * - a frame (7 + 2) - * - 3 object names (MAX_NAME) - * - 2 BREAD_CRUMB_SEPARATORs (6) - * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room! - * - a marker name (MAX_NAME + 3) - */ + BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, NULL, rect); - /* get name of marker on current frame (if available) */ - markern = BKE_scene_find_marker_name(scene, cfra); - - /* check if there is an object */ - if (ob) { - *s++ = ' '; - s += BLI_strcpy_rlen(s, ob->id.name + 2); + data->shiftx = shiftx; + BLI_unlock_thread(LOCK_VIEW3D); + } + else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ + float viewmat[4][4]; + Object *view_ob = v3d->camera; + Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); - /* name(s) to display depends on type of object */ - if (ob->type == OB_ARMATURE) { - bArmature *arm = ob->data; - - /* show name of active bone too (if possible) */ - if (arm->edbo) { - if (arm->act_edbone) { - s += BLI_strcpy_rlen(s, msg_sep); - s += BLI_strcpy_rlen(s, arm->act_edbone->name); - } - } - else if (ob->mode & OB_MODE_POSE) { - if (arm->act_bone) { + BLI_lock_thread(LOCK_VIEW3D); + v3d->camera = camera; - if (arm->act_bone->layer & arm->layer) { - s += BLI_strcpy_rlen(s, msg_sep); - s += BLI_strcpy_rlen(s, arm->act_bone->name); - } - } - } - } - else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) { - Key *key = NULL; - KeyBlock *kb = NULL; + BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, NULL, rect); - /* try to display active bone and active shapekey too (if they exist) */ + v3d->camera = view_ob; + BLI_unlock_thread(LOCK_VIEW3D); + } +} - if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) { - Object *armobj = BKE_object_pose_armature_get(ob); - if (armobj && armobj->mode & OB_MODE_POSE) { - bArmature *arm = armobj->data; - if (arm->act_bone) { - if (arm->act_bone->layer & arm->layer) { - s += BLI_strcpy_rlen(s, msg_sep); - s += BLI_strcpy_rlen(s, arm->act_bone->name); - } - } - } - } +/** + * Set the correct matrices + */ +void ED_view3d_draw_setup_view( + wmWindow *win, const EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d, + float viewmat[4][4], float winmat[4][4], const rcti *rect) +{ + RegionView3D *rv3d = ar->regiondata; - key = BKE_key_from_object(ob); - if (key) { - kb = BLI_findlink(&key->block, ob->shapenr - 1); - if (kb) { - s += BLI_strcpy_rlen(s, msg_sep); - s += BLI_strcpy_rlen(s, kb->name); - if (ob->shapeflag & OB_SHAPE_LOCK) { - s += BLI_strcpy_rlen(s, IFACE_(msg_pin)); - } - } - } - } - - /* color depends on whether there is a keyframe */ - if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) - UI_ThemeColor(TH_TIME_KEYFRAME); - else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) - UI_ThemeColor(TH_TIME_GP_KEYFRAME); - else - UI_ThemeColor(TH_TEXT_HI); + /* Setup the view matrix. */ + if (view3d_stereo3d_active(win, scene, v3d, rv3d)) { + view3d_stereo3d_setup(eval_ctx, scene, v3d, ar, rect); } else { - /* no object */ - if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra)) - UI_ThemeColor(TH_TIME_GP_KEYFRAME); - else - UI_ThemeColor(TH_TEXT_HI); + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, rect); } - - if (markern) { - s += sprintf(s, " <%s>", markern); - } - - if (U.uiflag & USER_SHOW_ROTVIEWICON) - offset = U.widget_unit + (U.rvisize * 2) + rect->xmin; - - BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info)); } +/* ******************** view border ***************** */ + static void view3d_camera_border( const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d, rctf *r_viewborder, const bool no_shift, const bool no_zoom) @@ -1023,7 +357,7 @@ void ED_view3d_calc_camera_border( view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, no_shift, false); } -static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float fac) +static void drawviewborder_grid3(uint shdr_pos, float x1, float x2, float y1, float y2, float fac) { float x3, y3, x4, y4; @@ -1032,29 +366,33 @@ static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float f x4 = x1 + (1.0f - fac) * (x2 - x1); y4 = y1 + (1.0f - fac) * (y2 - y1); - glBegin(GL_LINES); - glVertex2f(x1, y3); - glVertex2f(x2, y3); + immBegin(GWN_PRIM_LINES, 8); + + immVertex2f(shdr_pos, x1, y3); + immVertex2f(shdr_pos, x2, y3); - glVertex2f(x1, y4); - glVertex2f(x2, y4); + immVertex2f(shdr_pos, x1, y4); + immVertex2f(shdr_pos, x2, y4); - glVertex2f(x3, y1); - glVertex2f(x3, y2); + immVertex2f(shdr_pos, x3, y1); + immVertex2f(shdr_pos, x3, y2); - glVertex2f(x4, y1); - glVertex2f(x4, y2); - glEnd(); + immVertex2f(shdr_pos, x4, y1); + immVertex2f(shdr_pos, x4, y2); + + immEnd(); } /* harmonious triangle */ -static void drawviewborder_triangle(float x1, float x2, float y1, float y2, const char golden, const char dir) +static void drawviewborder_triangle( + uint shdr_pos, float x1, float x2, float y1, float y2, const char golden, const char dir) { float ofs; float w = x2 - x1; float h = y2 - y1; - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, 6); + if (w > h) { if (golden) { ofs = w * (1.0f - (1.0f / 1.61803399f)); @@ -1064,14 +402,14 @@ static void drawviewborder_triangle(float x1, float x2, float y1, float y2, cons } if (dir == 'B') SWAP(float, y1, y2); - glVertex2f(x1, y1); - glVertex2f(x2, y2); + immVertex2f(shdr_pos, x1, y1); + immVertex2f(shdr_pos, x2, y2); - glVertex2f(x2, y1); - glVertex2f(x1 + (w - ofs), y2); + immVertex2f(shdr_pos, x2, y1); + immVertex2f(shdr_pos, x1 + (w - ofs), y2); - glVertex2f(x1, y2); - glVertex2f(x1 + ofs, y1); + immVertex2f(shdr_pos, x1, y2); + immVertex2f(shdr_pos, x1 + ofs, y1); } else { if (golden) { @@ -1082,16 +420,17 @@ static void drawviewborder_triangle(float x1, float x2, float y1, float y2, cons } if (dir == 'B') SWAP(float, x1, x2); - glVertex2f(x1, y1); - glVertex2f(x2, y2); + immVertex2f(shdr_pos, x1, y1); + immVertex2f(shdr_pos, x2, y2); - glVertex2f(x2, y1); - glVertex2f(x1, y1 + ofs); + immVertex2f(shdr_pos, x2, y1); + immVertex2f(shdr_pos, x1, y1 + ofs); - glVertex2f(x1, y2); - glVertex2f(x2, y1 + (h - ofs)); + immVertex2f(shdr_pos, x1, y2); + immVertex2f(shdr_pos, x2, y1 + (h - ofs)); } - glEnd(); + + immEnd(); } static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) @@ -1128,58 +467,76 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) y1i = (int)(y1 - 1.0001f); x2i = (int)(x2 + (1.0f - 0.0001f)); y2i = (int)(y2 + (1.0f - 0.0001f)); - - /* passepartout, specified in camera edit buttons */ - if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) { - const float winx = (ar->winx + 1); - const float winy = (ar->winy + 1); - if (ca->passepartalpha == 1.0f) { - glColor3f(0, 0, 0); + uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + /* First, solid lines. */ + { + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* passepartout, specified in camera edit buttons */ + if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) { + const float winx = (ar->winx + 1); + const float winy = (ar->winy + 1); + + float alpha = 1.0f; + + if (ca->passepartalpha != 1.0f) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + alpha = ca->passepartalpha; + } + + immUniformColor4f(0.0f, 0.0f, 0.0f, alpha); + + if (x1i > 0.0f) + immRectf(shdr_pos, 0.0f, winy, x1i, 0.0f); + if (x2i < winx) + immRectf(shdr_pos, x2i, winy, winx, 0.0f); + if (y2i < winy) + immRectf(shdr_pos, x1i, winy, x2i, y2i); + if (y2i > 0.0f) + immRectf(shdr_pos, x1i, y1i, x2i, 0.0f); + + glDisable(GL_BLEND); } - else { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glColor4f(0, 0, 0, ca->passepartalpha); + + immUniformThemeColor(TH_BACK); + imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i); + +#ifdef VIEW3D_CAMERA_BORDER_HACK + if (view3d_camera_border_hack_test == true) { + immUniformColor3ubv(view3d_camera_border_hack_col); + imm_draw_box_wire_2d(shdr_pos, x1i + 1, y1i + 1, x2i - 1, y2i - 1); + view3d_camera_border_hack_test = false; } +#endif - if (x1i > 0.0f) - glRectf(0.0, winy, x1i, 0.0); - if (x2i < winx) - glRectf(x2i, winy, winx, 0.0); - if (y2i < winy) - glRectf(x1i, winy, x2i, y2i); - if (y2i > 0.0f) - glRectf(x1i, y1i, x2i, 0.0); - - glDisable(GL_BLEND); + immUnbindProgram(); } - setlinestyle(0); + /* And now, the dashed lines! */ + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - UI_ThemeColor(TH_BACK); - - fdrawbox(x1i, y1i, x2i, y2i); + { + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); -#ifdef VIEW3D_CAMERA_BORDER_HACK - if (view3d_camera_border_hack_test == true) { - glColor3ubv(view3d_camera_border_hack_col); - fdrawbox(x1i + 1, y1i + 1, x2i - 1, y2i - 1); - view3d_camera_border_hack_test = false; - } -#endif + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); - setlinestyle(3); + /* outer line not to confuse with object selection */ + if (v3d->flag2 & V3D_LOCK_CAMERA) { + immUniformThemeColor(TH_REDALERT); + imm_draw_box_wire_2d(shdr_pos, x1i - 1, y1i - 1, x2i + 1, y2i + 1); + } - /* outer line not to confuse with object selecton */ - if (v3d->flag2 & V3D_LOCK_CAMERA) { - UI_ThemeColor(TH_REDALERT); - fdrawbox(x1i - 1, y1i - 1, x2i + 1, y2i + 1); + immUniformThemeColor(TH_VIEW_OVERLAY); + imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i); } - UI_ThemeColor(TH_VIEW_OVERLAY); - fdrawbox(x1i, y1i, x2i, y2i); - /* border */ if (scene->r.mode & R_BORDER) { float x3, y3, x4, y4; @@ -1189,82 +546,76 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) x4 = floorf(x1 + (scene->r.border.xmax * (x2 - x1))) + (U.pixelsize - 1); y4 = floorf(y1 + (scene->r.border.ymax * (y2 - y1))) + (U.pixelsize - 1); - cpack(0x4040FF); - sdrawbox(x3, y3, x4, y4); + immUniformColor3f(1.0f, 0.25f, 0.25f); + imm_draw_box_wire_2d(shdr_pos, x3, y3, x4, y4); } /* safety border */ if (ca) { + immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f); + if (ca->dtx & CAM_DTX_CENTER) { float x3, y3; - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - x3 = x1 + 0.5f * (x2 - x1); y3 = y1 + 0.5f * (y2 - y1); - glBegin(GL_LINES); - glVertex2f(x1, y3); - glVertex2f(x2, y3); + immBegin(GWN_PRIM_LINES, 4); - glVertex2f(x3, y1); - glVertex2f(x3, y2); - glEnd(); + immVertex2f(shdr_pos, x1, y3); + immVertex2f(shdr_pos, x2, y3); + + immVertex2f(shdr_pos, x3, y1); + immVertex2f(shdr_pos, x3, y2); + + immEnd(); } if (ca->dtx & CAM_DTX_CENTER_DIAG) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); + immBegin(GWN_PRIM_LINES, 4); - glBegin(GL_LINES); - glVertex2f(x1, y1); - glVertex2f(x2, y2); + immVertex2f(shdr_pos, x1, y1); + immVertex2f(shdr_pos, x2, y2); - glVertex2f(x1, y2); - glVertex2f(x2, y1); - glEnd(); + immVertex2f(shdr_pos, x1, y2); + immVertex2f(shdr_pos, x2, y1); + + immEnd(); } if (ca->dtx & CAM_DTX_THIRDS) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_grid3(x1, x2, y1, y2, 1.0f / 3.0f); + drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f / 3.0f); } if (ca->dtx & CAM_DTX_GOLDEN) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_grid3(x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f)); + drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f)); } if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_triangle(x1, x2, y1, y2, 0, 'A'); + drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'A'); } if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_triangle(x1, x2, y1, y2, 0, 'B'); + drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'B'); } if (ca->dtx & CAM_DTX_HARMONY_TRI_A) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_triangle(x1, x2, y1, y2, 1, 'A'); + drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'A'); } if (ca->dtx & CAM_DTX_HARMONY_TRI_B) { - UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0); - drawviewborder_triangle(x1, x2, y1, y2, 1, 'B'); + drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'B'); } if (ca->flag & CAM_SHOW_SAFE_MARGINS) { UI_draw_safe_areas( - x1, x2, y1, y2, - scene->safe_areas.title, - scene->safe_areas.action); + shdr_pos, x1, x2, y1, y2, + scene->safe_areas.title, scene->safe_areas.action); if (ca->flag & CAM_SHOW_SAFE_CENTER) { UI_draw_safe_areas( - x1, x2, y1, y2, - scene->safe_areas.title_center, - scene->safe_areas.action_center); + shdr_pos, x1, x2, y1, y2, + scene->safe_areas.title_center, scene->safe_areas.action_center); } } @@ -1300,1776 +651,1294 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) } /* draw */ - UI_ThemeColorShade(TH_VIEW_OVERLAY, 100); - UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f); + immUniformThemeColorShade(TH_VIEW_OVERLAY, 100); + + /* TODO Was using UI_draw_roundbox_4fv(false, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color). + * We'll probably need a new imm_draw_line_roundbox_dashed dor that - though in practice the + * 2.0f round corner effect was nearly not visible anyway... */ + imm_draw_box_wire_2d(shdr_pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); } } - setlinestyle(0); + immUnbindProgram(); + /* end dashed lines */ /* camera name - draw in highlighted text color */ if (ca && (ca->flag & CAM_SHOWNAME)) { - UI_ThemeColor(TH_TEXT_HI); + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); BLF_draw_default( x1i, y1i - (0.7f * U.widget_unit), 0.0f, v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2); } } -/* *********************** backdraw for selection *************** */ +static void drawrenderborder(ARegion *ar, View3D *v3d) +{ + /* use the same program for everything */ + uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + glLineWidth(1.0f); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 0); /* "simple" mode */ + immUniform4f("color", 1.0f, 0.25f, 0.25f, 1.0f); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + + imm_draw_box_wire_2d(shdr_pos, + v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy, + v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy); + + immUnbindProgram(); +} -static void backdrawview3d(Scene *scene, wmWindow *win, ARegion *ar, View3D *v3d) +void ED_view3d_draw_depth( + const EvaluationContext *eval_ctx, struct Depsgraph *graph, + ARegion *ar, View3D *v3d, bool alphaoverride) { + struct bThemeState theme_state; + Scene *scene = DEG_get_evaluated_scene(graph); RegionView3D *rv3d = ar->regiondata; - struct Base *base = scene->basact; - int multisample_enabled; - BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); + short zbuf = v3d->zbuf; + short flag = v3d->flag; + float glalphaclip = U.glalphaclip; + int obcenter_dia = U.obcenter_dia; + /* temp set drawtype to solid */ + /* Setting these temporarily is not nice */ + v3d->flag &= ~V3D_SELECT_OUTLINE; + U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */ + U.obcenter_dia = 0; - if (base && (base->object->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) || - BKE_paint_select_face_test(base->object))) - { - /* do nothing */ - } - /* texture paint mode sampling */ - else if (base && (base->object->mode & OB_MODE_TEXTURE_PAINT) && - (v3d->drawtype > OB_WIRE)) - { - /* do nothing */ - } - else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) && - V3D_IS_ZBUF(v3d)) - { - /* do nothing */ - } - else if (scene->obedit && - V3D_IS_ZBUF(v3d)) - { - /* do nothing */ - } - else { - v3d->flag &= ~V3D_INVALID_BACKBUF; - return; - } + /* Tools may request depth outside of regular drawing code. */ + UI_Theme_Store(&theme_state); + UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); - if (!(v3d->flag & V3D_INVALID_BACKBUF)) - return; + ED_view3d_draw_setup_view(NULL, eval_ctx, scene, ar, v3d, NULL, NULL, NULL); -#if 0 - if (test) { - if (qtest()) { - addafterqueue(ar->win, BACKBUFDRAW, 1); - return; - } - } -#endif + glClear(GL_DEPTH_BUFFER_BIT); - if (v3d->drawtype > OB_WIRE) v3d->zbuf = true; - - /* dithering and AA break color coding, so disable */ - glDisable(GL_DITHER); - - multisample_enabled = glIsEnabled(GL_MULTISAMPLE); - if (multisample_enabled) - glDisable(GL_MULTISAMPLE); - - if (win->multisamples != USER_MULTISAMPLE_NONE) { - /* for multisample we use an offscreen FBO. multisample drawing can fail - * with color coded selection drawing, and reading back depths from such - * a buffer can also cause a few seconds freeze on OS X / NVidia. */ - int w = BLI_rcti_size_x(&ar->winrct); - int h = BLI_rcti_size_y(&ar->winrct); - char error[256]; - - if (rv3d->gpuoffscreen) { - if (GPU_offscreen_width(rv3d->gpuoffscreen) != w || - GPU_offscreen_height(rv3d->gpuoffscreen) != h) - { - GPU_offscreen_free(rv3d->gpuoffscreen); - rv3d->gpuoffscreen = NULL; - } - } + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_set(rv3d); + } + /* get surface depth without bias */ + rv3d->rflag |= RV3D_ZOFFSET_DISABLED; - if (!rv3d->gpuoffscreen) { - rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error); + v3d->zbuf = true; + glEnable(GL_DEPTH_TEST); - if (!rv3d->gpuoffscreen) - fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error); - } +#ifdef WITH_OPENGL_LEGACY + if (IS_VIEWPORT_LEGACY(vc->v3d)) { + /* temp, calls into view3d_draw_legacy.c */ + ED_view3d_draw_depth_loop(scene, ar, v3d); } - - if (rv3d->gpuoffscreen) - GPU_offscreen_bind(rv3d->gpuoffscreen, true); else - glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct)); - - glClearColor(0.0, 0.0, 0.0, 0.0); - if (v3d->zbuf) { - glEnable(GL_DEPTH_TEST); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +#endif /* WITH_OPENGL_LEGACY */ + { + DRW_draw_depth_loop(graph, ar, v3d); } - else { - glClear(GL_COLOR_BUFFER_BIT); - glDisable(GL_DEPTH_TEST); + + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_disable(); } - - if (rv3d->rflag & RV3D_CLIPPING) - ED_view3d_clipping_set(rv3d); - - G.f |= G_BACKBUFSEL; - - if (base && (base->lay & v3d->lay)) - draw_object_backbufsel(scene, v3d, rv3d, base->object); - - if (rv3d->gpuoffscreen) - GPU_offscreen_unbind(rv3d->gpuoffscreen, true); - else - ar->swap = 0; /* mark invalid backbuf for wm draw */ + rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED; - v3d->flag &= ~V3D_INVALID_BACKBUF; + v3d->zbuf = zbuf; + if (!v3d->zbuf) glDisable(GL_DEPTH_TEST); - G.f &= ~G_BACKBUFSEL; - v3d->zbuf = false; - glDisable(GL_DEPTH_TEST); - glEnable(GL_DITHER); - if (multisample_enabled) - glEnable(GL_MULTISAMPLE); + U.glalphaclip = glalphaclip; + v3d->flag = flag; + U.obcenter_dia = obcenter_dia; - if (rv3d->rflag & RV3D_CLIPPING) - ED_view3d_clipping_disable(); + UI_Theme_Restore(&theme_state); } -void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data) +/* ******************** background plates ***************** */ + +static void view3d_draw_background_gradient(void) { - RegionView3D *rv3d = ar->regiondata; + /* TODO: finish 2D API & draw background with that */ - if (rv3d->gpuoffscreen) { - GPU_offscreen_bind(rv3d->gpuoffscreen, true); - glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); - glReadPixels(x, y, w, h, format, type, data); - GPU_offscreen_unbind(rv3d->gpuoffscreen, true); - } - else { - glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); - } -} + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + unsigned char col_hi[3], col_lo[3]; -/* XXX depth reading exception, for code not using gpu offscreen */ -static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data) -{ + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); - glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); -} + UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo); + UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi); -void ED_view3d_backbuf_validate(ViewContext *vc) -{ - if (vc->v3d->flag & V3D_INVALID_BACKBUF) - backdrawview3d(vc->scene, vc->win, vc->ar, vc->v3d); + immBegin(GWN_PRIM_TRI_FAN, 4); + immAttrib3ubv(color, col_lo); + immVertex2f(pos, -1.0f, -1.0f); + immVertex2f(pos, 1.0f, -1.0f); + + immAttrib3ubv(color, col_hi); + immVertex2f(pos, 1.0f, 1.0f); + immVertex2f(pos, -1.0f, 1.0f); + immEnd(); + + immUnbindProgram(); } -/** - * allow for small values [0.5 - 2.5], - * and large values, FLT_MAX by clamping by the area size - */ -int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) +static void view3d_draw_background_none(void) { - return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); + UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); } -/* samples a single pixel (copied from vpaint) */ -unsigned int ED_view3d_backbuf_sample(ViewContext *vc, int x, int y) +static void view3d_draw_background_world(Scene *scene, RegionView3D *rv3d) { - unsigned int col; - - if (x >= vc->ar->winx || y >= vc->ar->winy) { - return 0; - } + if (scene->world) { + GPUMaterial *gpumat = GPU_material_world(scene, scene->world); - ED_view3d_backbuf_validate(vc); + /* calculate full shader for background */ + GPU_material_bind(gpumat, 1, 1, 1.0f, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac); + + if (GPU_material_bound(gpumat)) { + /* TODO viewport (dfelinto): GPU_material_bind relies on immediate mode, + * we can't get rid of the following code without a bigger refactor + * or we dropping this functionality. */ + + glBegin(GL_TRIANGLE_STRIP); + glVertex2f(-1.0f, -1.0f); + glVertex2f(1.0f, -1.0f); + glVertex2f(-1.0f, 1.0f); + glVertex2f(1.0f, 1.0f); + glEnd(); - view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); - glReadBuffer(GL_BACK); - - if (ENDIAN_ORDER == B_ENDIAN) { - BLI_endian_switch_uint32(&col); + GPU_material_unbind(gpumat); + return; + } } - - return GPU_select_to_index(col); -} -/* reads full rect, converts indices */ -ImBuf *ED_view3d_backbuf_read(ViewContext *vc, int xmin, int ymin, int xmax, int ymax) -{ - struct ImBuf *ibuf_clip; - /* clip */ - const rcti clip = { - max_ii(xmin, 0), min_ii(xmax, vc->ar->winx - 1), - max_ii(ymin, 0), min_ii(ymax, vc->ar->winy - 1)}; - const int size_clip[2] = { - BLI_rcti_size_x(&clip) + 1, - BLI_rcti_size_y(&clip) + 1}; - - if (UNLIKELY((clip.xmin > clip.xmax) || - (clip.ymin > clip.ymax))) - { - return NULL; - } + /* if any of the above fails */ + view3d_draw_background_none(); +} - ibuf_clip = IMB_allocImBuf(size_clip[0], size_clip[1], 32, IB_rect); +/* ******************** other elements ***************** */ - ED_view3d_backbuf_validate(vc); - view3d_opengl_read_pixels(vc->ar, clip.xmin, clip.ymin, size_clip[0], size_clip[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf_clip->rect); +#define DEBUG_GRID 0 - glReadBuffer(GL_BACK); +static void gridline_range(double x0, double dx, double max, int *r_first, int *r_count) +{ + /* determine range of gridlines that appear in this Area -- similar calc but separate ranges for x & y + * x0 is gridline 0, the axis in screen space + * Area covers [0 .. max) pixels */ - if (ENDIAN_ORDER == B_ENDIAN) { - IMB_convert_rgba_to_abgr(ibuf_clip); - } + int first = (int)ceil(-x0 / dx); + int last = (int)floor((max - x0) / dx); - GPU_select_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]); - - if ((clip.xmin == xmin) && - (clip.xmax == xmax) && - (clip.ymin == ymin) && - (clip.ymax == ymax)) - { - return ibuf_clip; + if (first <= last) { + *r_first = first; + *r_count = last - first + 1; } else { - /* put clipped result into a non-clipped buffer */ - struct ImBuf *ibuf_full; - const int size[2] = { - (xmax - xmin + 1), - (ymax - ymin + 1)}; - - ibuf_full = IMB_allocImBuf(size[0], size[1], 32, IB_rect); - - IMB_rectcpy( - ibuf_full, ibuf_clip, - clip.xmin - xmin, clip.ymin - ymin, - 0, 0, - size_clip[0], size_clip[1]); - IMB_freeImBuf(ibuf_clip); - return ibuf_full; + *r_first = 0; + *r_count = 0; } + +#if DEBUG_GRID + printf(" first %d * dx = %f\n", first, x0 + first * dx); + printf(" last %d * dx = %f\n", last, x0 + last * dx); + printf(" count = %d\n", *count_out); +#endif } -/* smart function to sample a rect spiralling outside, nice for backbuf selection */ -unsigned int ED_view3d_backbuf_sample_rect( - ViewContext *vc, const int mval[2], int size, - unsigned int min, unsigned int max, float *r_dist) +static int gridline_count(ARegion *ar, double x0, double y0, double dx) { - struct ImBuf *buf; - const unsigned int *bufmin, *bufmax, *tbuf; - int minx, miny; - int a, b, rc, nr, amount, dirvec[4][2]; - unsigned int index = 0; + /* x0 & y0 establish the "phase" of the grid within this 2D region + * dx is the frequency, shared by x & y directions + * pass in dx of smallest (highest precision) grid we want to draw */ - amount = (size - 1) / 2; +#if DEBUG_GRID + printf(" %s(%f, %f, dx:%f)\n", __FUNCTION__, x0, y0, dx); +#endif - minx = mval[0] - (amount + 1); - miny = mval[1] - (amount + 1); - buf = ED_view3d_backbuf_read(vc, minx, miny, minx + size - 1, miny + size - 1); - if (!buf) return 0; + int first, x_ct, y_ct; - 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++) { - if (*tbuf && *tbuf >= min && *tbuf < max) { - /* we got a hit */ - - /* get x,y pixel coords from the offset - * (manhatten distance in keeping with other screen-based selection) */ - *r_dist = (float)( - abs(((int)(tbuf - buf->rect) % size) - (size / 2)) + - abs(((int)(tbuf - buf->rect) / size) - (size / 2))); - - /* indices start at 1 here */ - index = (*tbuf - min) + 1; - goto exit; - } - - tbuf += (dirvec[rc][0] + dirvec[rc][1]); - - if (tbuf < bufmin || tbuf >= bufmax) { - goto exit; - } - } - rc++; - rc &= 3; - } - } + gridline_range(x0, dx, ar->winx, &first, &x_ct); + gridline_range(y0, dx, ar->winy, &first, &y_ct); -exit: - IMB_freeImBuf(buf); - return index; -} + int total_ct = x_ct + y_ct; +#if DEBUG_GRID + printf(" %d + %d = %d gridlines\n", x_ct, y_ct, total_ct); +#endif -/* ************************************************************* */ + return total_ct; +} -static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser) +static bool drawgrid_draw(ARegion *ar, double x0, double y0, double dx, int skip_mod, unsigned pos, unsigned col, GLubyte col_value[3]) { - if (BKE_image_is_stereo(ima)) { - iuser->flag |= IMA_SHOW_STEREO; + /* skip every skip_mod lines relative to each axis; they will be overlaid by another drawgrid_draw + * always skip exact x0 & y0 axes; they will be drawn later in color + * + * set grid color once, just before the first line is drawn + * it's harmless to set same color for every line, or every vertex + * but if no lines are drawn, color must not be set! */ - if ((scene->r.scemode & R_MULTIVIEW) == 0) { - iuser->multiview_eye = STEREO_LEFT_ID; - } - else if (v3d->stereo3d_camera != STEREO_3D_ID) { - /* show only left or right camera */ - iuser->multiview_eye = v3d->stereo3d_camera; - } +#if DEBUG_GRID + printf(" %s(%f, %f, dx:%f, skip_mod:%d)\n", __FUNCTION__, x0, y0, dx, skip_mod); +#endif - BKE_image_multiview_index(ima, iuser); - } - else { - iuser->flag &= ~IMA_SHOW_STEREO; - } -} + const float x_max = (float)ar->winx; + const float y_max = (float)ar->winy; -static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, - const bool do_foreground, const bool do_camera_frame) -{ - RegionView3D *rv3d = ar->regiondata; - BGpic *bgpic; - int fg_flag = do_foreground ? V3D_BGPIC_FOREGROUND : 0; + int first, ct; + int x_ct = 0, y_ct = 0; /* count of lines actually drawn */ + int lines_skipped_for_next_unit = 0; - for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { - bgpic->iuser.scene = scene; /* Needed for render results. */ + /* draw vertical lines */ + gridline_range(x0, dx, x_max, &first, &ct); - if ((bgpic->flag & V3D_BGPIC_FOREGROUND) != fg_flag) + for (int i = first; i < first + ct; ++i) { + if (i == 0) + continue; + else if (skip_mod && (i % skip_mod) == 0) { + ++lines_skipped_for_next_unit; continue; + } - if ((bgpic->view == 0) || /* zero for any */ - (bgpic->view & (1 << rv3d->view)) || /* check agaist flags */ - (rv3d->persp == RV3D_CAMOB && bgpic->view == (1 << RV3D_VIEW_CAMERA))) - { - float image_aspect[2]; - float fac, asp, zoomx, zoomy; - float x1, y1, x2, y2, centx, centy; - - ImBuf *ibuf = NULL, *freeibuf, *releaseibuf; - void *lock; - rctf clip_rect; - - Image *ima = NULL; - MovieClip *clip = NULL; - - /* disable individual images */ - if ((bgpic->flag & V3D_BGPIC_DISABLED)) - continue; - - freeibuf = NULL; - releaseibuf = NULL; - if (bgpic->source == V3D_BGPIC_IMAGE) { - ima = bgpic->ima; - if (ima == NULL) - continue; - BKE_image_user_frame_calc(&bgpic->iuser, CFRA, 0); - if (ima->source == IMA_SRC_SEQUENCE && !(bgpic->iuser.flag & IMA_USER_FRAME_IN_RANGE)) { - ibuf = NULL; /* frame is out of range, dont show */ - } - else { - view3d_stereo_bgpic_setup(scene, v3d, ima, &bgpic->iuser); - ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, &lock); - releaseibuf = ibuf; - } + if (x_ct == 0) + immAttrib3ub(col, col_value[0], col_value[1], col_value[2]); - image_aspect[0] = ima->aspx; - image_aspect[1] = ima->aspy; - } - else if (bgpic->source == V3D_BGPIC_MOVIE) { - /* TODO: skip drawing when out of frame range (as image sequences do above) */ + float x = (float)(x0 + i * dx); + immVertex2f(pos, x, 0.0f); + immVertex2f(pos, x, y_max); + ++x_ct; + } - if (bgpic->flag & V3D_BGPIC_CAMERACLIP) { - if (scene->camera) - clip = BKE_object_movieclip_get(scene, scene->camera, true); - } - else { - clip = bgpic->clip; - } + /* draw horizontal lines */ + gridline_range(y0, dx, y_max, &first, &ct); - if (clip == NULL) - continue; + for (int i = first; i < first + ct; ++i) { + if (i == 0) + continue; + else if (skip_mod && (i % skip_mod) == 0) { + ++lines_skipped_for_next_unit; + continue; + } - BKE_movieclip_user_set_frame(&bgpic->cuser, CFRA); - ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser); + if (x_ct + y_ct == 0) + immAttrib3ub(col, col_value[0], col_value[1], col_value[2]); - image_aspect[0] = clip->aspx; - image_aspect[1] = clip->aspy; + float y = (float)(y0 + i * dx); + immVertex2f(pos, 0.0f, y); + immVertex2f(pos, x_max, y); + ++y_ct; + } - /* working with ibuf from image and clip has got different workflow now. - * ibuf acquired from clip is referenced by cache system and should - * be dereferenced after usage. */ - freeibuf = ibuf; - } - else { - /* perhaps when loading future files... */ - BLI_assert(0); - copy_v2_fl(image_aspect, 1.0f); - } +#if DEBUG_GRID + int total_ct = x_ct + y_ct; + printf(" %d + %d = %d gridlines drawn, %d skipped for next unit\n", x_ct, y_ct, total_ct, lines_skipped_for_next_unit); +#endif - if (ibuf == NULL) - continue; + return lines_skipped_for_next_unit > 0; +} - if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */ - if (freeibuf) - IMB_freeImBuf(freeibuf); - if (releaseibuf) - BKE_image_release_ibuf(ima, releaseibuf, lock); +#define GRID_MIN_PX_D 6.0 +#define GRID_MIN_PX_F 6.0f - continue; - } +static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit) +{ + RegionView3D *rv3d = ar->regiondata; - if (ibuf->rect == NULL) - IMB_rect_from_float(ibuf); +#if DEBUG_GRID + printf("%s width %d, height %d\n", __FUNCTION__, ar->winx, ar->winy); +#endif - if (rv3d->persp == RV3D_CAMOB) { + double fx = rv3d->persmat[3][0]; + double fy = rv3d->persmat[3][1]; + double fw = rv3d->persmat[3][3]; - if (do_camera_frame) { - rctf vb; - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false); - x1 = vb.xmin; - y1 = vb.ymin; - x2 = vb.xmax; - y2 = vb.ymax; - } - else { - x1 = ar->winrct.xmin; - y1 = ar->winrct.ymin; - x2 = ar->winrct.xmax; - y2 = ar->winrct.ymax; - } + const double wx = 0.5 * ar->winx; /* use double precision to avoid rounding errors */ + const double wy = 0.5 * ar->winy; - /* apply offset last - camera offset is different to offset in blender units */ - /* so this has some sane way of working - this matches camera's shift _exactly_ */ - { - const float max_dim = max_ff(x2 - x1, y2 - y1); - const float xof_scale = bgpic->xof * max_dim; - const float yof_scale = bgpic->yof * max_dim; - - x1 += xof_scale; - y1 += yof_scale; - x2 += xof_scale; - y2 += yof_scale; - } + double x = wx * fx / fw; + double y = wy * fy / fw; - centx = (x1 + x2) / 2.0f; - centy = (y1 + y2) / 2.0f; + double vec4[4] = { v3d->grid, v3d->grid, 0.0, 1.0 }; + mul_m4_v4d(rv3d->persmat, vec4); + fx = vec4[0]; + fy = vec4[1]; + fw = vec4[3]; - /* aspect correction */ - if (bgpic->flag & V3D_BGPIC_CAMERA_ASPECT) { - /* apply aspect from clip */ - const float w_src = ibuf->x * image_aspect[0]; - const float h_src = ibuf->y * image_aspect[1]; + double dx = fabs(x - wx * fx / fw); + if (dx == 0) dx = fabs(y - wy * fy / fw); - /* destination aspect is already applied from the camera frame */ - const float w_dst = x1 - x2; - const float h_dst = y1 - y2; + x += wx; + y += wy; - const float asp_src = w_src / h_src; - const float asp_dst = w_dst / h_dst; + /* now x, y, and dx have their final values + * (x,y) is the world origin (0,0,0) mapped to Area-relative screen space + * dx is the distance in pixels between grid lines -- same for horiz or vert grid lines */ - if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) { - if ((asp_src > asp_dst) == ((bgpic->flag & V3D_BGPIC_CAMERA_CROP) != 0)) { - /* fit X */ - const float div = asp_src / asp_dst; - x1 = ((x1 - centx) * div) + centx; - x2 = ((x2 - centx) * div) + centx; - } - else { - /* fit Y */ - const float div = asp_dst / asp_src; - y1 = ((y1 - centy) * div) + centy; - y2 = ((y2 - centy) * div) + centy; - } - } - } - } - else { - float tvec[3]; - float sco[2]; - const float mval_f[2] = {1.0f, 0.0f}; - const float co_zero[3] = {0}; - float zfac; - - /* calc window coord */ - zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL); - ED_view3d_win_to_delta(ar, mval_f, tvec, zfac); - fac = max_ff(fabsf(tvec[0]), max_ff(fabsf(tvec[1]), fabsf(tvec[2]))); /* largest abs axis */ - fac = 1.0f / fac; - - asp = (float)ibuf->y / (float)ibuf->x; - - zero_v3(tvec); - ED_view3d_project_float_v2_m4(ar, tvec, sco, rv3d->persmat); - - x1 = sco[0] + fac * (bgpic->xof - bgpic->size); - y1 = sco[1] + asp * fac * (bgpic->yof - bgpic->size); - x2 = sco[0] + fac * (bgpic->xof + bgpic->size); - y2 = sco[1] + asp * fac * (bgpic->yof + bgpic->size); - - centx = (x1 + x2) / 2.0f; - centy = (y1 + y2) / 2.0f; - } - - /* complete clip? */ - BLI_rctf_init(&clip_rect, x1, x2, y1, y2); - if (bgpic->rotation) { - BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation); - } + glLineWidth(1.0f); - if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) { - if (freeibuf) - IMB_freeImBuf(freeibuf); - if (releaseibuf) - BKE_image_release_ibuf(ima, releaseibuf, lock); +#if 0 /* TODO: write to UI/widget depth buffer, not scene depth */ + glDepthMask(GL_FALSE); /* disable write in zbuffer */ +#endif - continue; - } + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); - zoomx = (x2 - x1) / ibuf->x; - zoomy = (y2 - y1) / ibuf->y; + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); - /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */ - if (zoomx < 1.0f || zoomy < 1.0f) { - float tzoom = min_ff(zoomx, zoomy); - int mip = 0; + unsigned char col[3], col2[3]; + UI_GetThemeColor3ubv(TH_GRID, col); - if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) { - IMB_remakemipmap(ibuf, 0); - ibuf->userflags &= ~IB_MIPMAP_INVALID; - } - else if (ibuf->mipmap[0] == NULL) - IMB_makemipmap(ibuf, 0); - - while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) { - tzoom *= 2.0f; - zoomx *= 2.0f; - zoomy *= 2.0f; - mip++; - } - if (mip > 0) - ibuf = ibuf->mipmap[mip - 1]; - } + if (unit->system) { + const void *usys; + int len; - if (v3d->zbuf) glDisable(GL_DEPTH_TEST); - glDepthMask(0); + bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + bool first = true; - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - ED_region_pixelspace(ar); + if (usys) { + int i = len; + while (i--) { + double scalar = bUnit_GetScaler(usys, i); - glTranslatef(centx, centy, 0.0); - glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f); + double dx_scalar = dx * scalar / (double)unit->scale_length; + if (dx_scalar < (GRID_MIN_PX_D * 2.0)) { + /* very very small grid items are less useful when dealing with units */ + continue; + } - if (bgpic->flag & V3D_BGPIC_FLIP_X) { - zoomx *= -1.0f; - x1 = x2; - } - if (bgpic->flag & V3D_BGPIC_FLIP_Y) { - zoomy *= -1.0f; - y1 = y2; - } - glPixelZoom(zoomx, zoomy); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend); + if (first) { + first = false; - /* could not use glaDrawPixelsAuto because it could fallback to - * glaDrawPixelsSafe in some cases, which will end up in missing - * alpha transparency for the background image (sergey) - */ - glaDrawPixelsTex(x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect); + /* Store the smallest drawn grid size units name so users know how big each grid cell is */ + *grid_unit = bUnit_GetNameDisplay(usys, i); + rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length); - glPixelZoom(1.0, 1.0); - glPixelTransferf(GL_ALPHA_SCALE, 1.0f); + int gridline_ct = gridline_count(ar, x, y, dx_scalar); + if (gridline_ct == 0) + goto drawgrid_cleanup; /* nothing to draw */ - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + immBegin(GWN_PRIM_LINES, gridline_ct * 2); + } - glDisable(GL_BLEND); + float blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar); + /* tweak to have the fade a bit nicer */ + blend_fac = (blend_fac * blend_fac) * 2.0f; + CLAMP(blend_fac, 0.3f, 1.0f); - glDepthMask(1); - if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, blend_fac, col2); - if (freeibuf) - IMB_freeImBuf(freeibuf); - if (releaseibuf) - BKE_image_release_ibuf(ima, releaseibuf, lock); + const int skip_mod = (i == 0) ? 0 : (int)round(bUnit_GetScaler(usys, i - 1) / scalar); +#if DEBUG_GRID + printf("%s %f, ", bUnit_GetNameDisplay(usys, i), scalar); + if (i > 0) + printf("next unit is %d times larger\n", skip_mod); + else + printf("largest unit\n"); +#endif + if (!drawgrid_draw(ar, x, y, dx_scalar, skip_mod, pos, color, col2)) + break; + } } } -} + else { + const double sublines = v3d->gridsubdiv; + const float sublines_fl = v3d->gridsubdiv; -static void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d, - const bool do_foreground, const bool do_camera_frame) -{ - RegionView3D *rv3d = ar->regiondata; + int grids_to_draw = 2; /* first the faint fine grid, then the bold coarse grid */ - if ((v3d->flag & V3D_DISPBGPICS) == 0) - return; + if (dx < GRID_MIN_PX_D) { + rv3d->gridview *= sublines_fl; + dx *= sublines; + if (dx < GRID_MIN_PX_D) { + rv3d->gridview *= sublines_fl; + dx *= sublines; + if (dx < GRID_MIN_PX_D) { + rv3d->gridview *= sublines_fl; + dx *= sublines; + grids_to_draw = (dx < GRID_MIN_PX_D) ? 0 : 1; + } + } + } + else { + if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */ + rv3d->gridview /= sublines_fl; + dx /= sublines; + if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */ + rv3d->gridview /= sublines_fl; + dx /= sublines; + if (dx > (GRID_MIN_PX_D * 10.0)) { + grids_to_draw = 1; + } + } + } + } - /* disabled - mango request, since footage /w only render is quite useful - * and this option is easy to disable all background images at once */ -#if 0 - if (v3d->flag2 & V3D_RENDER_OVERRIDE) - return; -#endif + int gridline_ct = gridline_count(ar, x, y, dx); + if (gridline_ct == 0) + goto drawgrid_cleanup; /* nothing to draw */ - if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) { - if (rv3d->persp == RV3D_CAMOB) { - view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame); + immBegin(GWN_PRIM_LINES, gridline_ct * 2); + + if (grids_to_draw == 2) { + UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0), col2); + if (drawgrid_draw(ar, x, y, dx, v3d->gridsubdiv, pos, color, col2)) + drawgrid_draw(ar, x, y, dx * sublines, 0, pos, color, col); + } + else if (grids_to_draw == 1) { + drawgrid_draw(ar, x, y, dx, 0, pos, color, col); } } - else { - view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame); + + /* draw visible axes */ + /* horizontal line */ + if (0 <= y && y < ar->winy) { + UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT) ? 'Y' : 'X'); + immAttrib3ub(color, col2[0], col2[1], col2[2]); + immVertex2f(pos, 0.0f, y); + immVertex2f(pos, (float)ar->winx, y); + } + + /* vertical line */ + if (0 <= x && x < ar->winx) { + UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM) ? 'Y' : 'Z'); + immAttrib3ub(color, col2[0], col2[1], col2[2]); + immVertex2f(pos, x, 0.0f); + immVertex2f(pos, x, (float)ar->winy); } -} -/* ****************** View3d afterdraw *************** */ + immEnd(); -typedef struct View3DAfter { - struct View3DAfter *next, *prev; - struct Base *base; - short dflag; -} View3DAfter; +drawgrid_cleanup: + immUnbindProgram(); -/* temp storage of Objects that need to be drawn as last */ -void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag) -{ - View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after"); - BLI_assert((base->flag & OB_FROMDUPLI) == 0); - BLI_addtail(lb, v3da); - v3da->base = base; - v3da->dflag = dflag; +#if 0 /* depth write is left enabled above */ + glDepthMask(GL_TRUE); /* enable write in zbuffer */ +#endif } -/* disables write in zbuffer and draws it over */ -static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d) -{ - View3DAfter *v3da; - - glDepthMask(GL_FALSE); - v3d->transp = true; - - while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) { - draw_object(scene, ar, v3d, v3da->base, v3da->dflag); - MEM_freeN(v3da); - } - v3d->transp = false; - - glDepthMask(GL_TRUE); - -} +#undef DEBUG_GRID +#undef GRID_MIN_PX_D +#undef GRID_MIN_PX_F -/* clears zbuffer and draws it over */ -static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear) +static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth) { - View3DAfter *v3da; + /* draw only if there is something to draw */ + if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) { + /* draw how many lines? + * trunc(v3d->gridlines / 2) * 4 + * + 2 for xy axes (possibly with special colors) + * + 1 for z axis (the only line not in xy plane) + * even v3d->gridlines are honored, odd rounded down */ + const int gridlines = v3d->gridlines / 2; + const float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit); + const float grid = gridlines * grid_scale; - if (*clear && v3d->zbuf) { - glClear(GL_DEPTH_BUFFER_BIT); - *clear = false; - } + const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) && gridlines >= 1; - v3d->xray = true; - while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { - draw_object(scene, ar, v3d, v3da->base, v3da->dflag); - MEM_freeN(v3da); - } - v3d->xray = false; -} + bool show_axis_x = v3d->gridflag & V3D_SHOW_X; + bool show_axis_y = v3d->gridflag & V3D_SHOW_Y; + bool show_axis_z = v3d->gridflag & V3D_SHOW_Z; + unsigned char col_grid[3], col_axis[3]; -/* clears zbuffer and draws it over */ -static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, const bool clear) -{ - View3DAfter *v3da; + glLineWidth(1.0f); - if (clear && v3d->zbuf) - glClear(GL_DEPTH_BUFFER_BIT); + UI_GetThemeColor3ubv(TH_GRID, col_grid); - v3d->xray = true; - v3d->transp = true; - - glDepthMask(GL_FALSE); + if (!write_depth) + glDepthMask(GL_FALSE); - while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) { - draw_object(scene, ar, v3d, v3da->base, v3da->dflag); - MEM_freeN(v3da); - } + if (show_floor) { + const unsigned vertex_ct = 2 * (gridlines * 4 + 2); + const int sublines = v3d->gridsubdiv; - v3d->transp = false; - v3d->xray = false; + unsigned char col_bg[3], col_grid_emphasise[3], col_grid_light[3]; - glDepthMask(GL_TRUE); -} + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); -/* clears zbuffer and draws it over, - * note that in the select version we don't care about transparent flag as with regular drawing */ -static void view3d_draw_xray_select(Scene *scene, ARegion *ar, View3D *v3d, bool *clear) -{ - /* Not ideal, but we need to read from the previous depths before clearing - * otherwise we could have a function to load the depths after drawing. - * - * Clearing the depth buffer isn't all that common between drawing objects so accept this for now. - */ - if (U.gpu_select_pick_deph) { - GPU_select_load_id(-1); - } + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); - View3DAfter *v3da; - if (*clear && v3d->zbuf) { - glClear(GL_DEPTH_BUFFER_BIT); - *clear = false; - } + immBegin(GWN_PRIM_LINES, vertex_ct); - v3d->xray = true; - while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { - if (GPU_select_load_id(v3da->base->selcol)) { - draw_object_select(scene, ar, v3d, v3da->base, v3da->dflag); - } - MEM_freeN(v3da); - } - v3d->xray = false; -} + /* draw normal grid lines */ + UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10); -/* *********************** */ + for (int a = 1; a <= gridlines; a++) { + /* skip emphasised divider lines */ + if (a % sublines != 0) { + const float line = a * grid_scale; -/* - * In most cases call draw_dupli_objects, - * draw_dupli_objects_color was added because when drawing set dupli's - * we need to force the color - */ + immAttrib3ubv(color, col_grid_light); -#if 0 -int dupli_ob_sort(void *arg1, void *arg2) -{ - void *p1 = ((DupliObject *)arg1)->ob; - void *p2 = ((DupliObject *)arg2)->ob; - int val = 0; - if (p1 < p2) val = -1; - else if (p1 > p2) val = 1; - return val; -} -#endif + immVertex2f(pos, -grid, -line); + immVertex2f(pos, +grid, -line); + immVertex2f(pos, -grid, +line); + immVertex2f(pos, +grid, +line); + immVertex2f(pos, -line, -grid); + immVertex2f(pos, -line, +grid); + immVertex2f(pos, +line, -grid); + immVertex2f(pos, +line, +grid); + } + } -static DupliObject *dupli_step(DupliObject *dob) -{ - while (dob && dob->no_draw) - dob = dob->next; - return dob; -} + /* draw emphasised grid lines */ + UI_GetThemeColor3ubv(TH_BACK, col_bg); + /* emphasise division lines lighter instead of darker, if background is darker than grid */ + UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise, + (col_grid[0] + col_grid[1] + col_grid[2] + 30 > + col_bg[0] + col_bg[1] + col_bg[2]) ? 20 : -10); -static void draw_dupli_objects_color( - Scene *scene, ARegion *ar, View3D *v3d, Base *base, - const short dflag, const int color) -{ - RegionView3D *rv3d = ar->regiondata; - ListBase *lb; - LodLevel *savedlod; - DupliObject *dob_prev = NULL, *dob, *dob_next = NULL; - Base tbase = {NULL}; - BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */ - GLuint displist = 0; - unsigned char color_rgb[3]; - const short dflag_dupli = dflag | DRAW_CONSTCOLOR; - short transflag; - bool use_displist = false; /* -1 is initialize */ - char dt; - short dtx; - DupliApplyData *apply_data; - - if (base->object->restrictflag & OB_RESTRICT_VIEW) return; - if ((base->object->restrictflag & OB_RESTRICT_RENDER) && (v3d->flag2 & V3D_RENDER_OVERRIDE)) return; - - if (dflag & DRAW_CONSTCOLOR) { - BLI_assert(color == TH_UNDEFINED); - } - else { - UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb); - } + if (sublines <= gridlines) { + immAttrib3ubv(color, col_grid_emphasise); + + for (int a = sublines; a <= gridlines; a += sublines) { + const float line = a * grid_scale; + + immVertex2f(pos, -grid, -line); + immVertex2f(pos, +grid, -line); + immVertex2f(pos, -grid, +line); + immVertex2f(pos, +grid, +line); - tbase.flag = OB_FROMDUPLI | base->flag; - lb = object_duplilist(G.main->eval_ctx, scene, base->object); - // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */ + immVertex2f(pos, -line, -grid); + immVertex2f(pos, -line, +grid); + immVertex2f(pos, +line, -grid); + immVertex2f(pos, +line, +grid); + } + } - apply_data = duplilist_apply(base->object, scene, lb); + /* draw X axis */ + if (show_axis_x) { + show_axis_x = false; /* drawing now, won't need to draw later */ + UI_make_axis_color(col_grid, col_axis, 'X'); + immAttrib3ubv(color, col_axis); + } + else + immAttrib3ubv(color, col_grid_emphasise); - dob = dupli_step(lb->first); - if (dob) dob_next = dupli_step(dob->next); + immVertex2f(pos, -grid, 0.0f); + immVertex2f(pos, +grid, 0.0f); - for (; dob; dob_prev = dob, dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) { - bool testbb = false; + /* draw Y axis */ + if (show_axis_y) { + show_axis_y = false; /* drawing now, won't need to draw later */ + UI_make_axis_color(col_grid, col_axis, 'Y'); + immAttrib3ubv(color, col_axis); + } + else + immAttrib3ubv(color, col_grid_emphasise); - tbase.object = dob->ob; + immVertex2f(pos, 0.0f, -grid); + immVertex2f(pos, 0.0f, +grid); - /* Make sure lod is updated from dupli's position */ - savedlod = dob->ob->currentlod; + immEnd(); + immUnbindProgram(); -#ifdef WITH_GAMEENGINE - if (rv3d->rflag & RV3D_IS_GAME_ENGINE) { - BKE_object_lod_update(dob->ob, rv3d->viewinv[3]); + /* done with XY plane */ } -#endif - /* extra service: draw the duplicator in drawtype of parent, minimum taken - * to allow e.g. boundbox box objects in groups for LOD */ - dt = tbase.object->dt; - tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); + if (show_axis_x || show_axis_y || show_axis_z) { + /* draw axis lines -- sometimes grid floor is off, other times we still need to draw the Z axis */ - /* inherit draw extra, but not if a boundbox under the assumption that this - * is intended to speed up drawing, and drawing extra (especially wire) can - * slow it down too much */ - dtx = tbase.object->dtx; - if (tbase.object->dt != OB_BOUNDBOX) - tbase.object->dtx = base->object->dtx; + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); - /* negative scale flag has to propagate */ - transflag = tbase.object->transflag; + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + immBegin(GWN_PRIM_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2); - if (is_negative_m4(dob->mat)) - tbase.object->transflag |= OB_NEG_SCALE; - else - tbase.object->transflag &= ~OB_NEG_SCALE; - - /* should move outside the loop but possible color is set in draw_object still */ - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(color_rgb); - } - - /* generate displist, test for new object */ - if (dob_prev && dob_prev->ob != dob->ob) { - if (use_displist == true) - glDeleteLists(displist, 1); - - use_displist = false; - } - - if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) { - bb = *bb_tmp; /* must make a copy */ - testbb = true; - } + if (show_axis_x) { + UI_make_axis_color(col_grid, col_axis, 'X'); + immAttrib3ubv(color, col_axis); + immVertex3f(pos, -grid, 0.0f, 0.0f); + immVertex3f(pos, +grid, 0.0f, 0.0f); + } - if (!testbb || ED_view3d_boundbox_clip_ex(rv3d, &bb, dob->mat)) { - /* generate displist */ - if (use_displist == false) { - - /* note, since this was added, its checked (dob->type == OB_DUPLIGROUP) - * however this is very slow, it was probably needed for the NLA - * offset feature (used in group-duplicate.blend but no longer works in 2.5) - * so for now it should be ok to - campbell */ - - if ( /* if this is the last no need to make a displist */ - (dob_next == NULL || dob_next->ob != dob->ob) || - /* lamp drawing messes with matrices, could be handled smarter... but this works */ - (dob->ob->type == OB_LAMP) || - (dob->type == OB_DUPLIGROUP && dob->animated) || - !bb_tmp || - draw_glsl_material(scene, dob->ob, v3d, dt) || - check_object_draw_texture(scene, v3d, dt) || - (v3d->flag2 & V3D_SOLID_MATCAP) != 0) - { - // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2); - use_displist = false; - } - else { - // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name + 2); - - /* disable boundbox check for list creation */ - BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 1); - /* need this for next part of code */ - unit_m4(dob->ob->obmat); /* obmat gets restored */ - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - draw_object(scene, ar, v3d, &tbase, dflag_dupli); - glEndList(); - - use_displist = true; - BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 0); - } + if (show_axis_y) { + UI_make_axis_color(col_grid, col_axis, 'Y'); + immAttrib3ubv(color, col_axis); + immVertex3f(pos, 0.0f, -grid, 0.0f); + immVertex3f(pos, 0.0f, +grid, 0.0f); } - - if (use_displist) { - glPushMatrix(); - glMultMatrixf(dob->mat); - glCallList(displist); - glPopMatrix(); - } - else { - copy_m4_m4(dob->ob->obmat, dob->mat); - GPU_begin_dupli_object(dob); - draw_object(scene, ar, v3d, &tbase, dflag_dupli); - GPU_end_dupli_object(); + + if (show_axis_z) { + UI_make_axis_color(col_grid, col_axis, 'Z'); + immAttrib3ubv(color, col_axis); + immVertex3f(pos, 0.0f, 0.0f, -grid); + immVertex3f(pos, 0.0f, 0.0f, +grid); } + + immEnd(); + immUnbindProgram(); } - - tbase.object->dt = dt; - tbase.object->dtx = dtx; - tbase.object->transflag = transflag; - tbase.object->currentlod = savedlod; + + if (!write_depth) + glDepthMask(GL_TRUE); } +} + +/** could move this elsewhere, but tied into #ED_view3d_grid_scale */ +float ED_scene_grid_scale(Scene *scene, const char **grid_unit) +{ + /* apply units */ + if (scene->unit.system) { + const void *usys; + int len; + + bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len); - if (apply_data) { - duplilist_restore(lb, apply_data); - duplilist_free_apply_data(apply_data); + if (usys) { + int i = bUnit_GetBaseUnit(usys); + if (grid_unit) + *grid_unit = bUnit_GetNameDisplay(usys, i); + return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length; + } } - free_object_duplilist(lb); - - if (use_displist) - glDeleteLists(displist, 1); + return 1.0f; } -static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base) +float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) { - /* define the color here so draw_dupli_objects_color can be called - * from the set loop */ - - int color = (base->flag & SELECT) ? TH_SELECT : TH_WIRE; - /* debug */ - if (base->object->dup_group && base->object->dup_group->id.us < 1) - color = TH_REDALERT; - - draw_dupli_objects_color(scene, ar, v3d, base, 0, color); + return v3d->grid * ED_scene_grid_scale(scene, grid_unit); } -/* XXX warning, not using gpu offscreen here */ -void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) +static bool is_cursor_visible(Scene *scene, SceneLayer *sl) { - int x, y, w, h; - rcti r; - /* clamp rect by region */ + Object *ob = OBACT(sl); - r.xmin = 0; - r.xmax = ar->winx - 1; - r.ymin = 0; - r.ymax = ar->winy - 1; + /* don't draw cursor in paint modes, but with a few exceptions */ + if (ob && ob->mode & OB_MODE_ALL_PAINT) { + /* exception: object is in weight paint and has deforming armature in pose mode */ + if (ob->mode & OB_MODE_WEIGHT_PAINT) { + if (BKE_object_pose_armature_get(ob) != NULL) { + return true; + } + } + /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */ + else if (ob->mode & OB_MODE_TEXTURE_PAINT) { + const Paint *p = BKE_paint_get_active(scene, sl); - /* Constrain rect to depth bounds */ - BLI_rcti_isect(&r, rect, rect); + if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) { + if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) { + return true; + } + } + } - /* assign values to compare with the ViewDepths */ - x = rect->xmin; - y = rect->ymin; + /* no exception met? then don't draw cursor! */ + return false; + } - w = BLI_rcti_size_x(rect); - h = BLI_rcti_size_y(rect); + return true; +} - if (w <= 0 || h <= 0) { - if (d->depths) - MEM_freeN(d->depths); - d->depths = NULL; +static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d) +{ + int co[2]; - d->damaged = false; - } - else if (d->w != w || - d->h != h || - d->x != x || - d->y != y || - d->depths == NULL - ) - { - d->x = x; - d->y = y; - d->w = w; - d->h = h; + /* we don't want the clipping for cursor */ + if (ED_view3d_project_int_global(ar, ED_view3d_cursor3d_get(scene, v3d), co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + const float f5 = 0.25f * U.widget_unit; + const float f10 = 0.5f * U.widget_unit; + const float f20 = U.widget_unit; + + glLineWidth(1.0f); - if (d->depths) - MEM_freeN(d->depths); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); - d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset"); - - d->damaged = true; - } + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); - if (d->damaged) { - /* XXX using special function here, it doesn't use the gpu offscreen system */ - view3d_opengl_read_Z_pixels(ar, d->x, d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); - glGetDoublev(GL_DEPTH_RANGE, d->depth_range); - d->damaged = false; - } -} + const int segments = 16; -/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */ -void ED_view3d_depth_update(ARegion *ar) -{ - RegionView3D *rv3d = ar->regiondata; - - /* Create storage for, and, if necessary, copy depth buffer */ - if (!rv3d->depths) rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); - if (rv3d->depths) { - ViewDepths *d = rv3d->depths; - if (d->w != ar->winx || - d->h != ar->winy || - !d->depths) - { - d->w = ar->winx; - d->h = ar->winy; - if (d->depths) - MEM_freeN(d->depths); - d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); - d->damaged = true; - } - - if (d->damaged) { - view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); - glGetDoublev(GL_DEPTH_RANGE, d->depth_range); - - d->damaged = false; - } - } -} + immBegin(GWN_PRIM_LINE_LOOP, segments); -/* utility function to find the closest Z value, use for autodepth */ -float view3d_depth_near(ViewDepths *d) -{ - /* convert to float for comparisons */ - const float near = (float)d->depth_range[0]; - const float far_real = (float)d->depth_range[1]; - float far = far_real; - - const float *depths = d->depths; - float depth = FLT_MAX; - int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */ - - /* far is both the starting 'far' value - * and the closest value found. */ - while (i--) { - depth = *depths++; - if ((depth < far) && (depth > near)) { - far = depth; + for (int i = 0; i < segments; ++i) { + float angle = 2 * M_PI * ((float)i / (float)segments); + float x = co[0] + f10 * cosf(angle); + float y = co[1] + f10 * sinf(angle); + + if (i % 2 == 0) + immAttrib3ub(color, 255, 0, 0); + else + immAttrib3ub(color, 255, 255, 255); + + immVertex2f(pos, x, y); } - } + immEnd(); - return far == far_real ? FLT_MAX : far; -} + immUnbindProgram(); -void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d) -{ - short zbuf = v3d->zbuf; - RegionView3D *rv3d = ar->regiondata; + GWN_vertformat_clear(format); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - /* Setup view matrix. */ - ED_view3d_draw_setup_view(NULL, scene, ar, v3d, rv3d->viewmat, rv3d->winmat, NULL); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - glClear(GL_DEPTH_BUFFER_BIT); + unsigned char crosshair_color[3]; + UI_GetThemeColor3ubv(TH_VIEW_OVERLAY, crosshair_color); + immUniformColor3ubv(crosshair_color); - v3d->zbuf = true; - glEnable(GL_DEPTH_TEST); + immBegin(GWN_PRIM_LINES, 8); + immVertex2f(pos, co[0] - f20, co[1]); + immVertex2f(pos, co[0] - f5, co[1]); + immVertex2f(pos, co[0] + f5, co[1]); + immVertex2f(pos, co[0] + f20, co[1]); + immVertex2f(pos, co[0], co[1] - f20); + immVertex2f(pos, co[0], co[1] - f5); + immVertex2f(pos, co[0], co[1] + f5); + immVertex2f(pos, co[0], co[1] + f20); + immEnd(); - if (v3d->flag2 & V3D_SHOW_GPENCIL) { - ED_gpencil_draw_view3d(NULL, scene, v3d, ar, true); + immUnbindProgram(); } - - v3d->zbuf = zbuf; } -static void view3d_draw_depth_loop(Scene *scene, ARegion *ar, View3D *v3d) +static void draw_view_axis(RegionView3D *rv3d, rcti *rect) { - Base *base; - - /* no need for color when drawing depth buffer */ - const short dflag_depth = DRAW_CONSTCOLOR; - - /* draw set first */ - if (scene->set) { - Scene *sce_iter; - for (SETLOOPER(scene->set, sce_iter, base)) { - if (v3d->lay & base->lay) { - draw_object(scene, ar, v3d, base, 0); - if (base->object->transflag & OB_DUPLI) { - draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED); - } - } - } - } - - for (base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { - /* dupli drawing */ - if (base->object->transflag & OB_DUPLI) { - draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED); - } - draw_object(scene, ar, v3d, base, dflag_depth); - } + const float k = U.rvisize * U.pixelsize; /* axis size */ + const int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */ + + const float startx = rect->xmin + k + 1.0f; /* axis center in screen coordinates, x=y */ + const float starty = rect->ymin + k + 1.0f; + + float axis_pos[3][2]; + unsigned char axis_col[3][4]; + + int axis_order[3] = {0, 1, 2}; + axis_sort_v3(rv3d->viewinv[2], axis_order); + + for (int axis_i = 0; axis_i < 3; axis_i++) { + int i = axis_order[axis_i]; + + /* get position of each axis tip on screen */ + float vec[3] = { 0.0f }; + vec[i] = 1.0f; + mul_qt_v3(rv3d->viewquat, vec); + axis_pos[i][0] = startx + vec[0] * k; + axis_pos[i][1] = starty + vec[1] * k; + + /* get color of each axis */ + UI_GetThemeColorShade3ubv(TH_AXIS_X + i, bright, axis_col[i]); /* rgb */ + axis_col[i][3] = 255 * hypotf(vec[0], vec[1]); /* alpha */ } - - /* this isn't that nice, draw xray objects as if they are normal */ - if (v3d->afterdraw_transp.first || - v3d->afterdraw_xray.first || - v3d->afterdraw_xraytransp.first) - { - View3DAfter *v3da; - int mask_orig; - v3d->xray = true; - - /* transp materials can change the depth mask, see #21388 */ - glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig); + /* draw axis lines */ + glLineWidth(2.0f); + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); - if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) { - glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */ - for (v3da = v3d->afterdraw_xray.first; v3da; v3da = v3da->next) { - draw_object(scene, ar, v3d, v3da->base, dflag_depth); - } - glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */ - } + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBegin(GWN_PRIM_LINES, 6); - /* draw 3 passes, transp/xray/xraytransp */ - v3d->xray = false; - v3d->transp = true; - while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) { - draw_object(scene, ar, v3d, v3da->base, dflag_depth); - MEM_freeN(v3da); - } + for (int axis_i = 0; axis_i < 3; axis_i++) { + int i = axis_order[axis_i]; - v3d->xray = true; - v3d->transp = false; - while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { - draw_object(scene, ar, v3d, v3da->base, dflag_depth); - MEM_freeN(v3da); - } + immAttrib4ubv(col, axis_col[i]); + immVertex2f(pos, startx, starty); + immVertex2fv(pos, axis_pos[i]); + } - v3d->xray = true; - v3d->transp = true; - while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) { - draw_object(scene, ar, v3d, v3da->base, dflag_depth); - MEM_freeN(v3da); - } + immEnd(); + immUnbindProgram(); + glDisable(GL_LINE_SMOOTH); - - v3d->xray = false; - v3d->transp = false; + /* draw axis names */ + for (int axis_i = 0; axis_i < 3; axis_i++) { + int i = axis_order[axis_i]; - glDepthMask(mask_orig); + const char axis_text[2] = {'x' + i, '\0'}; + BLF_color4ubv(BLF_default(), axis_col[i]); + BLF_draw_default_ascii(axis_pos[i][0] + 2, axis_pos[i][1] + 2, 0.0f, axis_text, 1); } } -void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride) +#ifdef WITH_INPUT_NDOF +/* draw center and axis of rotation for ongoing 3D mouse navigation */ +static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d) { - struct bThemeState theme_state; - RegionView3D *rv3d = ar->regiondata; - short zbuf = v3d->zbuf; - short flag = v3d->flag; - float glalphaclip = U.glalphaclip; - int obcenter_dia = U.obcenter_dia; - /* temp set drawtype to solid */ - - /* Setting these temporarily is not nice */ - v3d->flag &= ~V3D_SELECT_OUTLINE; - U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */ - U.obcenter_dia = 0; - - /* Tools may request depth outside of regular drawing code. */ - UI_Theme_Store(&theme_state); - UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); + float o[3]; /* center of rotation */ + float end[3]; /* endpoints for drawing */ - /* Setup view matrix. */ - ED_view3d_draw_setup_view(NULL, scene, ar, v3d, rv3d->viewmat, rv3d->winmat, NULL); - - glClear(GL_DEPTH_BUFFER_BIT); - - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_set(rv3d); - } - /* get surface depth without bias */ - rv3d->rflag |= RV3D_ZOFFSET_DISABLED; + GLubyte color[4] = {0, 108, 255, 255}; /* bright blue so it matches device LEDs */ - v3d->zbuf = true; - glEnable(GL_DEPTH_TEST); + negate_v3_v3(o, rv3d->ofs); - view3d_draw_depth_loop(scene, ar, v3d); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(GL_FALSE); /* don't overwrite zbuf */ - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_disable(); - } - rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED; - - v3d->zbuf = zbuf; - if (!v3d->zbuf) glDisable(GL_DEPTH_TEST); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); - U.glalphaclip = glalphaclip; - v3d->flag = flag; - U.obcenter_dia = obcenter_dia; + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); - UI_Theme_Restore(&theme_state); -} + if (rv3d->rot_angle != 0.0f) { + /* -- draw rotation axis -- */ + float scaled_axis[3]; + const float scale = rv3d->dist; + mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale); -void ED_view3d_draw_select_loop( - ViewContext *vc, Scene *scene, View3D *v3d, ARegion *ar, - bool use_obedit_skip, bool use_nearest) -{ - short code = 1; - const short dflag = DRAW_PICKING | DRAW_CONSTCOLOR; - if (vc->obedit && vc->obedit->type == OB_MBALL) { - draw_object(scene, ar, v3d, BASACT, dflag); - } - else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) { - /* if not drawing sketch, draw bones */ - if (!BDR_drawSketchNames(vc)) { - draw_object(scene, ar, v3d, BASACT, dflag); - } - } - else { - Base *base; + immBegin(GWN_PRIM_LINE_STRIP, 3); + color[3] = 0; /* more transparent toward the ends */ + immAttrib4ubv(col, color); + add_v3_v3v3(end, o, scaled_axis); + immVertex3fv(pos, end); - for (base = scene->base.first; base; base = base->next) { - if (base->lay & v3d->lay) { +#if 0 + color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */ + /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */ +#endif - if ((base->object->restrictflag & OB_RESTRICT_SELECT) || - (use_obedit_skip && (scene->obedit->data == base->object->data))) - { - base->selcol = 0; - } - else { - base->selcol = code; + color[3] = 127; /* more opaque toward the center */ + immAttrib4ubv(col, color); + immVertex3fv(pos, o); - if (use_nearest && (base->object->dtx & OB_DRAWXRAY)) { - ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag); - } - else { - if (GPU_select_load_id(code)) { - draw_object_select(scene, ar, v3d, base, dflag); - } - } - code++; - } + color[3] = 0; + immAttrib4ubv(col, color); + sub_v3_v3v3(end, o, scaled_axis); + immVertex3fv(pos, end); + immEnd(); + + /* -- draw ring around rotation center -- */ + { +#define ROT_AXIS_DETAIL 13 + + const float s = 0.05f * scale; + const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL); + + float q[4]; /* rotate ring so it's perpendicular to axis */ + const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f; + if (!upright) { + const float up[3] = {0.0f, 0.0f, 1.0f}; + float vis_angle, vis_axis[3]; + + cross_v3_v3v3(vis_axis, up, rv3d->rot_axis); + vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis)); + axis_angle_to_quat(q, vis_axis, vis_angle); } - } - if (use_nearest) { - bool xrayclear = true; - if (v3d->afterdraw_xray.first) { - view3d_draw_xray_select(scene, ar, v3d, &xrayclear); + immBegin(GWN_PRIM_LINE_LOOP, ROT_AXIS_DETAIL); + color[3] = 63; /* somewhat faint */ + immAttrib4ubv(col, color); + float angle = 0.0f; + for (int i = 0; i < ROT_AXIS_DETAIL; ++i, angle += step) { + float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f}; + + if (!upright) { + mul_qt_v3(q, p); + } + + add_v3_v3(p, o); + immVertex3fv(pos, p); } + immEnd(); + +#undef ROT_AXIS_DETAIL } + + color[3] = 255; /* solid dot */ } + else + color[3] = 127; /* see-through dot */ + + immUnbindProgram(); + + /* -- draw rotation center -- */ + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); + glPointSize(5.0f); + immBegin(GWN_PRIM_POINTS, 1); + immAttrib4ubv(col, color); + immVertex3fv(pos, o); + immEnd(); + immUnbindProgram(); + +#if 0 + /* find screen coordinates for rotation center, then draw pretty icon */ + mul_m4_v3(rv3d->persinv, rot_center); + UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN); + /* ^^ just playing around, does not work */ +#endif + + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); } +#endif /* WITH_INPUT_NDOF */ -typedef struct View3DShadow { - struct View3DShadow *next, *prev; - GPULamp *lamp; -} View3DShadow; +/* ******************** info ***************** */ -static void gpu_render_lamp_update(Scene *scene, View3D *v3d, - Object *ob, Object *par, - float obmat[4][4], unsigned int lay, - ListBase *shadows, SceneRenderLayer *srl) +/** +* Render and camera border +*/ +static void view3d_draw_border(const bContext *C, ARegion *ar) { - GPULamp *lamp; - Lamp *la = (Lamp *)ob->data; - View3DShadow *shadow; - unsigned int layers; - - lamp = GPU_lamp_from_blender(scene, ob, par); - - if (lamp) { - GPU_lamp_update(lamp, lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat); - GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy); - - layers = lay & v3d->lay; - if (srl) - layers &= srl->lay; - - if (layers && - GPU_lamp_has_shadow_buffer(lamp) && - /* keep last, may do string lookup */ - GPU_lamp_visible(lamp, srl, NULL)) - { - shadow = MEM_callocN(sizeof(View3DShadow), "View3DShadow"); - shadow->lamp = lamp; - BLI_addtail(shadows, shadow); - } + Scene *scene = CTX_data_scene(C); + RegionView3D *rv3d = ar->regiondata; + View3D *v3d = CTX_wm_view3d(C); + + if (rv3d->persp == RV3D_CAMOB) { + drawviewborder(scene, ar, v3d); + } + else if (v3d->flag2 & V3D_RENDER_BORDER) { + drawrenderborder(ar, v3d); } } -static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d) +/** +* Grease Pencil +*/ +static void view3d_draw_grease_pencil(const bContext *UNUSED(C)) { - ListBase shadows; - View3DShadow *shadow; - Scene *sce_iter; - Base *base; - Object *ob; - World *world = scene->world; - SceneRenderLayer *srl = v3d->scenelock ? BLI_findlink(&scene->r.layers, scene->r.actlay) : NULL; - - BLI_listbase_clear(&shadows); - - /* update lamp transform and gather shadow lamps */ - for (SETLOOPER(scene, sce_iter, base)) { - ob = base->object; - - if (ob->type == OB_LAMP) - gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, ob->lay, &shadows, srl); - - if (ob->transflag & OB_DUPLI) { - DupliObject *dob; - ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob); - - for (dob = lb->first; dob; dob = dob->next) - if (dob->ob->type == OB_LAMP) - gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, ob->lay, &shadows, srl); - - free_object_duplilist(lb); - } - } - - /* render shadows after updating all lamps, nested object_duplilist - * don't work correct since it's replacing object matrices */ - for (shadow = shadows.first; shadow; shadow = shadow->next) { - /* this needs to be done better .. */ - float viewmat[4][4], winmat[4][4]; - int drawtype, lay, winsize, flag2 = v3d->flag2; - ARegion ar = {NULL}; - RegionView3D rv3d = {{{0}}}; - - drawtype = v3d->drawtype; - lay = v3d->lay; - - v3d->drawtype = OB_SOLID; - v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp); - v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP); - v3d->flag2 |= V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW; - - GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat); - - ar.regiondata = &rv3d; - ar.regiontype = RGN_TYPE_WINDOW; - rv3d.persp = RV3D_CAMOB; - copy_m4_m4(rv3d.winmat, winmat); - copy_m4_m4(rv3d.viewmat, viewmat); - invert_m4_m4(rv3d.viewinv, rv3d.viewmat); - mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat); - invert_m4_m4(rv3d.persinv, rv3d.viewinv); - - /* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */ - ED_view3d_draw_offscreen( - scene, v3d, &ar, winsize, winsize, viewmat, winmat, - false, false, true, - NULL, NULL, NULL, NULL); - GPU_lamp_shadow_buffer_unbind(shadow->lamp); - - v3d->drawtype = drawtype; - v3d->lay = lay; - v3d->flag2 = flag2; - } - - BLI_freelistN(&shadows); - - /* update world values */ - if (world) { - GPU_mist_update_enable(world->mode & WO_MIST); - GPU_mist_update_values(world->mistype, world->miststa, world->mistdist, world->misi, &world->horr); - GPU_horizon_update_color(&world->horr); - GPU_ambient_update_color(&world->ambr); - GPU_zenith_update_color(&world->zenr); - } + /* TODO viewport */ } -/* *********************** customdata **************** */ -CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d) +/** +* Viewport Name +*/ +static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d) { - CustomDataMask mask = 0; - const int drawtype = view3d_effective_drawtype(v3d); + const char *name = NULL; - if (ELEM(drawtype, OB_TEXTURE, OB_MATERIAL) || - ((drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX))) - { - mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; + switch (rv3d->view) { + case RV3D_VIEW_FRONT: + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho"); + else name = IFACE_("Front Persp"); + break; + case RV3D_VIEW_BACK: + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho"); + else name = IFACE_("Back Persp"); + break; + case RV3D_VIEW_TOP: + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho"); + else name = IFACE_("Top Persp"); + break; + case RV3D_VIEW_BOTTOM: + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho"); + else name = IFACE_("Bottom Persp"); + break; + case RV3D_VIEW_RIGHT: + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho"); + else name = IFACE_("Right Persp"); + break; + case RV3D_VIEW_LEFT: + if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho"); + else name = IFACE_("Left Persp"); + break; - if (BKE_scene_use_new_shading_nodes(scene)) { - if (drawtype == OB_MATERIAL) - mask |= CD_MASK_ORCO; - } - else { - if ((scene->gm.matmode == GAME_MAT_GLSL && drawtype == OB_TEXTURE) || - (drawtype == OB_MATERIAL)) - { - mask |= CD_MASK_ORCO; + default: + if (rv3d->persp == RV3D_CAMOB) { + if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) { + Camera *cam; + cam = v3d->camera->data; + if (cam->type == CAM_PERSP) { + name = IFACE_("Camera Persp"); + } + else if (cam->type == CAM_ORTHO) { + name = IFACE_("Camera Ortho"); + } + else { + BLI_assert(cam->type == CAM_PANO); + name = IFACE_("Camera Pano"); + } + } + else { + name = IFACE_("Object as Camera"); + } + } + else { + name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp"); } - } } - return mask; + return name; } -/* goes over all modes and view3d settings */ -CustomDataMask ED_view3d_screen_datamask(const bScreen *screen) +static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect) { - const Scene *scene = screen->scene; - CustomDataMask mask = CD_MASK_BAREMESH; - const ScrArea *sa; - - /* check if we need tfaces & mcols due to view mode */ - for (sa = screen->areabase.first; sa; sa = sa->next) { - if (sa->spacetype == SPACE_VIEW3D) { - mask |= ED_view3d_datamask(scene, sa->spacedata.first); - } + RegionView3D *rv3d = ar->regiondata; + const char *name = view3d_get_name(v3d, rv3d); + /* increase size for unicode languages (Chinese in utf-8...) */ +#ifdef WITH_INTERNATIONAL + char tmpstr[96]; +#else + char tmpstr[32]; +#endif + + if (v3d->localvd) { + BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name); + name = tmpstr; } - return mask; + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); +#ifdef WITH_INTERNATIONAL + BLF_draw_default(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr)); +#else + BLF_draw_default_ascii(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr)); +#endif } /** - * \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore + * draw info beside axes in bottom left-corner: + * framenum, object name, bone name (if available), marker name (if available) */ -void ED_view3d_update_viewmat( - Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect) -{ - RegionView3D *rv3d = ar->regiondata; - /* setup window matrices */ - if (winmat) - copy_m4_m4(rv3d->winmat, winmat); - else - view3d_winmatrix_set(ar, v3d, rect); +static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) +{ + const int cfra = CFRA; + const char *msg_pin = " (Pinned)"; + const char *msg_sep = " : "; - /* setup view matrix */ - if (viewmat) - copy_m4_m4(rv3d->viewmat, viewmat); - else - view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */ + const int font_id = BLF_default(); - /* update utility matrices */ - mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); - invert_m4_m4(rv3d->persinv, rv3d->persmat); - invert_m4_m4(rv3d->viewinv, rv3d->viewmat); - - /* calculate GLSL view dependent values */ + char info[300]; + char *s = info; + short offset = 1.5f * UI_UNIT_X + rect->xmin; - /* store window coordinates scaling/offset */ - if (rv3d->persp == RV3D_CAMOB && v3d->camera) { - rctf cameraborder; - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false); - rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder); - rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder); - - rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx; - rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy; - } - else { - rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f; - rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f; - } + s += sprintf(s, "(%d)", cfra); - /** - * Calculate pixel-size factor once, is used for lamps and object centers. - * Used by #ED_view3d_pixel_size and typically not accessed directly. - * - * \note #BKE_camera_params_compute_viewplane' also calculates a pixel-size value, - * passed to #RE_SetPixelSize, in ortho mode this is compatible with this value, - * but in perspective mode its offset by the near-clip. - * - * 'RegionView3D.pixsize' is used for viewport drawing, not rendering. + /* + * info can contain: + * - a frame (7 + 2) + * - 3 object names (MAX_NAME) + * - 2 BREAD_CRUMB_SEPARATORs (6) + * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room! + * - a marker name (MAX_NAME + 3) */ - { - /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' - * because of float point precision problems at large values [#23908] */ - float v1[3], v2[3]; - float len_px, len_sc; - - v1[0] = rv3d->persmat[0][0]; - v1[1] = rv3d->persmat[1][0]; - v1[2] = rv3d->persmat[2][0]; - v2[0] = rv3d->persmat[0][1]; - v2[1] = rv3d->persmat[1][1]; - v2[2] = rv3d->persmat[2][1]; - - len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2))); - len_sc = (float)MAX2(ar->winx, ar->winy); - - rv3d->pixsize = len_px / len_sc; - } -} + /* get name of marker on current frame (if available) */ + const char *markern = BKE_scene_find_marker_name(scene, cfra); -/** - * Shared by #ED_view3d_draw_offscreen and #view3d_main_region_draw_objects - * - * \note \a C and \a grid_unit will be NULL when \a draw_offscreen is set. - * \note Drawing lamps and opengl render uses this, so dont do grease pencil or view widgets here. - */ -static void view3d_draw_objects( - const bContext *C, - Scene *scene, View3D *v3d, ARegion *ar, - const char **grid_unit, - const bool do_bgpic, const bool draw_offscreen, GPUFX *fx) -{ - RegionView3D *rv3d = ar->regiondata; - Base *base; - const bool do_camera_frame = !draw_offscreen; - const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0; - const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO); - /* only draw grids after in solid modes, else it hovers over mesh wires */ - const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx; - bool do_composite_xray = false; - bool xrayclear = true; - - if (!draw_offscreen) { - ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); - } + /* check if there is an object */ + if (ob) { + *s++ = ' '; + s += BLI_strcpy_rlen(s, ob->id.name + 2); - if (rv3d->rflag & RV3D_CLIPPING) - view3d_draw_clipping(rv3d); + /* name(s) to display depends on type of object */ + if (ob->type == OB_ARMATURE) { + bArmature *arm = ob->data; - /* set zbuffer after we draw clipping region */ - if (v3d->drawtype > OB_WIRE) { - v3d->zbuf = true; - } - else { - v3d->zbuf = false; - } + /* show name of active bone too (if possible) */ + if (arm->edbo) { + if (arm->act_edbone) { + s += BLI_strcpy_rlen(s, msg_sep); + s += BLI_strcpy_rlen(s, arm->act_edbone->name); + } + } + else if (ob->mode & OB_MODE_POSE) { + if (arm->act_bone) { - /* special case (depth for wire color) */ - if (v3d->drawtype <= OB_WIRE) { - if (scene->obedit && scene->obedit->type == OB_MESH) { - Mesh *me = scene->obedit->data; - if (me->drawflag & ME_DRAWEIGHT) { - v3d->zbuf = true; + if (arm->act_bone->layer & arm->layer) { + s += BLI_strcpy_rlen(s, msg_sep); + s += BLI_strcpy_rlen(s, arm->act_bone->name); + } + } } } - } - - if (v3d->zbuf) { - glEnable(GL_DEPTH_TEST); - } + else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) { + /* try to display active bone and active shapekey too (if they exist) */ - /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override - * objects if done last */ - if (draw_grids) { - /* needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views. */ - rv3d->gridview = ED_view3d_grid_scale(scene, v3d, grid_unit); + if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) { + Object *armobj = BKE_object_pose_armature_get(ob); + if (armobj && armobj->mode & OB_MODE_POSE) { + bArmature *arm = armobj->data; + if (arm->act_bone) { + if (arm->act_bone->layer & arm->layer) { + s += BLI_strcpy_rlen(s, msg_sep); + s += BLI_strcpy_rlen(s, arm->act_bone->name); + } + } + } + } - if (!draw_floor) { - ED_region_pixelspace(ar); - *grid_unit = NULL; /* drawgrid need this to detect/affect smallest valid unit... */ - drawgrid(&scene->unit, ar, v3d, grid_unit); - /* XXX make function? replaces persp(1) */ - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(rv3d->winmat); - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(rv3d->viewmat); - } - else if (!draw_grids_after) { - drawfloor(scene, v3d, grid_unit, true); + Key *key = BKE_key_from_object(ob); + if (key) { + KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1); + if (kb) { + s += BLI_strcpy_rlen(s, msg_sep); + s += BLI_strcpy_rlen(s, kb->name); + if (ob->shapeflag & OB_SHAPE_LOCK) { + s += BLI_strcpy_rlen(s, IFACE_(msg_pin)); + } + } + } } - } - /* important to do before clipping */ - if (do_bgpic) { - view3d_draw_bgpic_test(scene, ar, v3d, false, do_camera_frame); + /* color depends on whether there is a keyframe */ + if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) + UI_FontThemeColor(font_id, TH_TIME_KEYFRAME); + else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) + UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME); + else + UI_FontThemeColor(font_id, TH_TEXT_HI); } - - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_set(rv3d); + else { + /* no object */ + if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra)) + UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME); + else + UI_FontThemeColor(font_id, TH_TEXT_HI); } - /* draw set first */ - if (scene->set) { - const short dflag = DRAW_CONSTCOLOR | DRAW_SCENESET; - Scene *sce_iter; - for (SETLOOPER(scene->set, sce_iter, base)) { - if (v3d->lay & base->lay) { - UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f); - draw_object(scene, ar, v3d, base, dflag); - - if (base->object->transflag & OB_DUPLI) { - draw_dupli_objects_color(scene, ar, v3d, base, dflag, TH_UNDEFINED); - } - } - } - - /* Transp and X-ray afterdraw stuff for sets is done later */ + if (markern) { + s += sprintf(s, " <%s>", markern); } + if (U.uiflag & USER_SHOW_ROTVIEWICON) + offset = U.widget_unit + (U.rvisize * 2) + rect->xmin; - if (draw_offscreen) { - for (base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { - /* dupli drawing */ - if (base->object->transflag & OB_DUPLI) - draw_dupli_objects(scene, ar, v3d, base); + BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info)); +} - draw_object(scene, ar, v3d, base, 0); - } - } - } - else { - unsigned int lay_used = 0; +/* ******************** view loop ***************** */ - /* then draw not selected and the duplis, but skip editmode object */ - for (base = scene->base.first; base; base = base->next) { - lay_used |= base->lay; +/** +* Information drawn on top of the solid plates and composed data +*/ +void view3d_draw_region_info(const bContext *C, ARegion *ar, const int offset) +{ + RegionView3D *rv3d = ar->regiondata; + View3D *v3d = CTX_wm_view3d(C); + Scene *scene = CTX_data_scene(C); + wmWindowManager *wm = CTX_wm_manager(C); - if (v3d->lay & base->lay) { + /* correct projection matrix */ + ED_region_pixelspace(ar); - /* dupli drawing */ - if (base->object->transflag & OB_DUPLI) { - draw_dupli_objects(scene, ar, v3d, base); - } - if ((base->flag & SELECT) == 0) { - if (base->object != scene->obedit) - draw_object(scene, ar, v3d, base, 0); - } - } - } + /* local coordinate visible rect inside region, to accomodate overlapping ui */ + rcti rect; + ED_region_visible_rect(ar, &rect); - /* mask out localview */ - v3d->lay_used = lay_used & ((1 << 20) - 1); + /* Leave room for previously drawn info. */ + rect.ymax -= offset; - /* draw selected and editmode */ - for (base = scene->base.first; base; base = base->next) { - if (v3d->lay & base->lay) { - if (base->object == scene->obedit || (base->flag & SELECT)) { - draw_object(scene, ar, v3d, base, 0); - } - } - } + view3d_draw_border(C, ar); + view3d_draw_grease_pencil(C); + + if (U.uiflag & USER_SHOW_ROTVIEWICON) { + draw_view_axis(rv3d, &rect); } - /* perspective floor goes last to use scene depth and avoid writing to depth buffer */ - if (draw_grids_after) { - drawfloor(scene, v3d, grid_unit, false); + if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) { + ED_scene_draw_fps(scene, &rect); + } + else if (U.uiflag & USER_SHOW_VIEWPORTNAME) { + draw_viewport_name(ar, v3d, &rect); } - /* must be before xray draw which clears the depth buffer */ - if (v3d->flag2 & V3D_SHOW_GPENCIL) { - wmWindowManager *wm = (C != NULL) ? CTX_wm_manager(C) : NULL; - - /* must be before xray draw which clears the depth buffer */ - if (v3d->zbuf) glDisable(GL_DEPTH_TEST); - ED_gpencil_draw_view3d(wm, scene, v3d, ar, true); - if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + if (U.uiflag & USER_DRAWVIEWINFO) { + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = OBACT(sl); + draw_selected_name(scene, ob, &rect); } +#if 0 /* TODO */ + if (grid_unit) { /* draw below the viewport name */ + char numstr[32] = ""; - /* transp and X-ray afterdraw stuff */ - if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d); + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); + if (v3d->grid != 1.0f) { + BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); + } - /* always do that here to cleanup depth buffers if none needed */ - if (fx) { - do_composite_xray = v3d->zbuf && (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first); - GPU_fx_compositor_setup_XRay_pass(fx, do_composite_xray); + BLF_draw_default_ascii(rect.xmin + U.widget_unit, + rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f, + numstr[0] ? numstr : grid_unit, sizeof(numstr)); } +#endif +} - if (v3d->afterdraw_xray.first) view3d_draw_xray(scene, ar, v3d, &xrayclear); - if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, xrayclear); +static void view3d_draw_view(const bContext *C, ARegion *ar) +{ + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); - if (fx && do_composite_xray) { - GPU_fx_compositor_XRay_resolve(fx); - } + ED_view3d_draw_setup_view(CTX_wm_window(C), &eval_ctx, CTX_data_scene(C), ar, CTX_wm_view3d(C), NULL, NULL, NULL); - if (!draw_offscreen) { - ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); - } + /* Only 100% compliant on new spec goes bellow */ + DRW_draw_view(C); +} - if (rv3d->rflag & RV3D_CLIPPING) - ED_view3d_clipping_disable(); +void view3d_main_region_draw(const bContext *C, ARegion *ar) +{ + Scene *scene = CTX_data_scene(C); + WorkSpace *workspace = CTX_wm_workspace(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = ar->regiondata; + ViewRender *view_render = BKE_viewrender_get(scene, workspace); + RenderEngineType *type = RE_engines_find(view_render->engine_id); - /* important to do after clipping */ - if (do_bgpic) { - view3d_draw_bgpic_test(scene, ar, v3d, true, do_camera_frame); + /* Provisory Blender Internal drawing */ + if (type->flag & RE_USE_LEGACY_PIPELINE) { + view3d_main_region_draw_legacy(C, ar); + return; } - if (!draw_offscreen) { - BIF_draw_manipulator(C); + if (!rv3d->viewport) { + rv3d->viewport = GPU_viewport_create(); } - /* cleanup */ - if (v3d->zbuf) { - v3d->zbuf = false; - glDisable(GL_DEPTH_TEST); - } + GPU_viewport_bind(rv3d->viewport, &ar->winrct); + view3d_draw_view(C, ar); + GPU_viewport_unbind(rv3d->viewport); - if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) { - GPU_free_images_old(); - } + v3d->flag |= V3D_INVALID_BACKBUF; } -static void view3d_main_region_setup_view( - Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect) -{ - RegionView3D *rv3d = ar->regiondata; - ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat, rect); +/* -------------------------------------------------------------------- */ - /* set for opengl */ - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(rv3d->winmat); - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(rv3d->viewmat); -} +/** \name Offscreen Drawing + * \{ */ -/** - * Store values from #RegionView3D, set when drawing. - * This is needed when we draw with to a viewport using a different matrix (offscreen drawing for example). - * - * Values set by #ED_view3d_update_viewmat should be handled here. - */ -struct RV3DMatrixStore { - float winmat[4][4]; - float viewmat[4][4]; - float viewinv[4][4]; - float persmat[4][4]; - float persinv[4][4]; - float viewcamtexcofac[4]; - float pixsize; -}; - -struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d) +static void view3d_stereo3d_setup_offscreen( + const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar, + float winmat[4][4], const char *viewname) { - struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__); - copy_m4_m4(rv3dmat->winmat, rv3d->winmat); - copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat); - copy_m4_m4(rv3dmat->persmat, rv3d->persmat); - copy_m4_m4(rv3dmat->persinv, rv3d->persinv); - copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv); - copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac); - rv3dmat->pixsize = rv3d->pixsize; - return (void *)rv3dmat; -} + /* update the viewport matrices with the new camera */ + if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { + float viewmat[4][4]; + const bool is_left = STREQ(viewname, STEREO_LEFT_NAME); -void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat) -{ - copy_m4_m4(rv3d->winmat, rv3dmat->winmat); - copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat); - copy_m4_m4(rv3d->persmat, rv3dmat->persmat); - copy_m4_m4(rv3d->persinv, rv3dmat->persinv); - copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv); - copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac); - rv3d->pixsize = rv3dmat->pixsize; + BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL); + } + else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ + float viewmat[4][4]; + Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); + + BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL); + } } -void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d) +void ED_view3d_draw_offscreen_init(const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, View3D *v3d) { - /* shadow buffers, before we setup matrices */ - if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) - gpu_update_lamps_shadows_world(scene, v3d); + RenderEngineType *type = eval_ctx->engine; + if (type->flag & RE_USE_LEGACY_PIPELINE) { + /* shadow buffers, before we setup matrices */ + if (draw_glsl_material(scene, sl, NULL, v3d, v3d->drawtype)) { + VP_deprecated_gpu_update_lamps_shadows_world(eval_ctx, scene, v3d); + } + } } /* @@ -3077,79 +1946,13 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d) */ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar) { - if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) { - RegionView3D *rv3d = ar->regiondata; - GPUMaterial *gpumat = GPU_material_world(scene, scene->world); - - /* calculate full shader for background */ - GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0)); - - bool material_not_bound = !GPU_material_bound(gpumat); - - if (material_not_bound) { - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glColor4f(0.0f, 0.0f, 0.0f, 1.0f); - } - - /* Draw world */ - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); - glBegin(GL_TRIANGLE_STRIP); - glVertex3f(-1.0, -1.0, 1.0); - glVertex3f(1.0, -1.0, 1.0); - glVertex3f(-1.0, 1.0, 1.0); - glVertex3f(1.0, 1.0, 1.0); - glEnd(); - - if (material_not_bound) { - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - } + glClear(GL_DEPTH_BUFFER_BIT); - GPU_material_unbind(gpumat); - - glDepthFunc(GL_LEQUAL); - glDisable(GL_DEPTH_TEST); + if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) { + VP_view3d_draw_background_world(scene, ar->regiondata); } else { - if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) { - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); - glBegin(GL_QUADS); - UI_ThemeColor(TH_LOW_GRAD); - glVertex3f(-1.0, -1.0, 1.0); - glVertex3f(1.0, -1.0, 1.0); - UI_ThemeColor(TH_HIGH_GRAD); - glVertex3f(1.0, 1.0, 1.0); - glVertex3f(-1.0, 1.0, 1.0); - glEnd(); - glDepthFunc(GL_LEQUAL); - glDisable(GL_DEPTH_TEST); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - } - else { - UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } + VP_view3d_draw_background_none(); } } @@ -3157,24 +1960,20 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar) * stuff like shadow buffers */ void ED_view3d_draw_offscreen( - Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy, + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *scene_layer, + View3D *v3d, ARegion *ar, int winx, int winy, float viewmat[4][4], float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, const char *viewname, GPUFX *fx, GPUFXSettings *fx_settings, GPUOffScreen *ofs) { - struct bThemeState theme_state; - int bwinx, bwiny; - rcti brect; bool do_compositing = false; RegionView3D *rv3d = ar->regiondata; - glPushMatrix(); - /* set temporary new size */ - bwinx = ar->winx; - bwiny = ar->winy; - brect = ar->winrct; + int bwinx = ar->winx; + int bwiny = ar->winy; + rcti brect = ar->winrct; ar->winx = winx; ar->winy = winy; @@ -3183,6 +1982,7 @@ void ED_view3d_draw_offscreen( ar->winrct.xmax = winx; ar->winrct.ymax = winy; + struct bThemeState theme_state; UI_Theme_Store(&theme_state); UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); @@ -3195,26 +1995,10 @@ void ED_view3d_draw_offscreen( GPU_free_images_anim(); } - /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */ - if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera) - view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname); - else - view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL); - - /* framebuffer fx needed, we need to draw offscreen first */ - if (v3d->fx_settings.fx_flag && fx) { - GPUSSAOSettings *ssao = NULL; - - if (v3d->drawtype < OB_SOLID) { - ssao = v3d->fx_settings.ssao; - v3d->fx_settings.ssao = NULL; - } - - do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings); - - if (ssao) - v3d->fx_settings.ssao = ssao; - } + gpuPushProjectionMatrix(); + gpuLoadIdentity(); + gpuPushMatrix(); + gpuLoadIdentity(); /* clear opengl buffers */ if (do_sky) { @@ -3225,28 +2009,57 @@ void ED_view3d_draw_offscreen( glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } + if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera) + view3d_stereo3d_setup_offscreen(eval_ctx, scene, v3d, ar, winmat, viewname); + else + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL); + /* main drawing call */ - view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL); + RenderEngineType *type = eval_ctx->engine; + if (type->flag & RE_USE_LEGACY_PIPELINE) { - /* post process */ - if (do_compositing) { - if (!winmat) - is_persp = rv3d->is_persp; - GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs); - } + /* framebuffer fx needed, we need to draw offscreen first */ + if (v3d->fx_settings.fx_flag && fx) { + GPUSSAOSettings *ssao = NULL; - if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) { - /* draw grease-pencil stuff */ - ED_region_pixelspace(ar); + if (v3d->drawtype < OB_SOLID) { + ssao = v3d->fx_settings.ssao; + v3d->fx_settings.ssao = NULL; + } + do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings); - if (v3d->flag2 & V3D_SHOW_GPENCIL) { - /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */ - ED_gpencil_draw_view3d(NULL, scene, v3d, ar, false); + if (ssao) + v3d->fx_settings.ssao = ssao; } - /* freeing the images again here could be done after the operator runs, leaving for now */ - GPU_free_images_anim(); + VP_deprecated_view3d_draw_objects(NULL, eval_ctx, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL); + + /* post process */ + if (do_compositing) { + if (!winmat) + is_persp = rv3d->is_persp; + GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs); + } + + if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + /* draw grease-pencil stuff */ + ED_region_pixelspace(ar); + + if (v3d->flag2 & V3D_SHOW_GPENCIL) { + /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */ + ED_gpencil_draw_view3d(NULL, scene, scene_layer, v3d, ar, false); + } + + /* freeing the images again here could be done after the operator runs, leaving for now */ + GPU_free_images_anim(); + } + } + else { + /* XXX, should take depsgraph as arg */ + Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, scene_layer, false); + BLI_assert(depsgraph != NULL); + DRW_draw_render_loop_offscreen(depsgraph, eval_ctx->engine, ar, v3d, ofs); } /* restore size */ @@ -3254,7 +2067,8 @@ void ED_view3d_draw_offscreen( ar->winy = bwiny; ar->winrct = brect; - glPopMatrix(); + gpuPopProjectionMatrix(); + gpuPopMatrix(); UI_Theme_Restore(&theme_state); @@ -3262,37 +2076,20 @@ void ED_view3d_draw_offscreen( } /** - * Set the correct matrices - */ -void ED_view3d_draw_setup_view( - wmWindow *win, Scene *scene, ARegion *ar, View3D *v3d, float viewmat[4][4], float winmat[4][4], const rcti *rect) -{ - RegionView3D *rv3d = ar->regiondata; - - /* Setup the view matrix. */ - if (view3d_stereo3d_active(win, scene, v3d, rv3d)) { - view3d_stereo3d_setup(scene, v3d, ar, rect); - } - else { - view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, rect); - } -} - -/** * Utility func for ED_view3d_draw_offscreen * * \param ofs: Optional off-screen buffer, can be NULL. * (avoids re-creating when doing multiple GL renders). */ ImBuf *ED_view3d_draw_offscreen_imbuf( - Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey, + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *scene_layer, + View3D *v3d, ARegion *ar, int sizex, int sizey, unsigned int flag, bool draw_background, int alpha_mode, int samples, bool full_samples, const char *viewname, /* output vars */ GPUFX *fx, GPUOffScreen *ofs, char err_out[256]) { RegionView3D *rv3d = ar->regiondata; - ImBuf *ibuf; const bool draw_sky = (alpha_mode == R_ADDSKY); /* view state */ @@ -3315,12 +2112,12 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( } } - ED_view3d_draw_offscreen_init(scene, v3d); + ED_view3d_draw_offscreen_init(eval_ctx, scene, scene_layer, v3d); GPU_offscreen_bind(ofs, true); /* read in pixels & stamp */ - ibuf = IMB_allocImBuf(sizex, sizey, 32, flag); + ImBuf *ibuf = IMB_allocImBuf(sizex, sizey, 32, flag); /* render 3d view */ if (rv3d->persp == RV3D_CAMOB && v3d->camera) { @@ -3357,7 +2154,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( if ((samples && full_samples) == 0) { /* Single-pass render, common case */ ED_view3d_draw_offscreen( - scene, v3d, ar, sizex, sizey, NULL, winmat, + eval_ctx, scene, scene_layer, v3d, ar, sizex, sizey, NULL, winmat, draw_background, draw_sky, !is_ortho, viewname, fx, &fx_settings, ofs); @@ -3376,25 +2173,23 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( /* use imbuf as temp storage, before writing into it from accumulation buffer */ unsigned char *rect_temp = ibuf->rect ? (void *)ibuf->rect : (void *)ibuf->rect_float; unsigned int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int[4]), "accum1"); - unsigned int i; - int j; BLI_jitter_init(jit_ofs, samples); /* first sample buffer, also initializes 'rv3d->persmat' */ ED_view3d_draw_offscreen( - scene, v3d, ar, sizex, sizey, NULL, winmat, + eval_ctx, scene, scene_layer, v3d, ar, sizex, sizey, NULL, winmat, draw_background, draw_sky, !is_ortho, viewname, fx, &fx_settings, ofs); GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp); - i = sizex * sizey * 4; + unsigned i = sizex * sizey * 4; while (i--) { accum_buffer[i] = rect_temp[i]; } /* skip the first sample */ - for (j = 1; j < samples; j++) { + for (int j = 1; j < samples; j++) { copy_m4_m4(winmat_jitter, winmat); window_translate_m4( winmat_jitter, rv3d->persmat, @@ -3402,7 +2197,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( (jit_ofs[j][1] * 2.0f) / sizey); ED_view3d_draw_offscreen( - scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, + eval_ctx, scene, scene_layer, v3d, ar, sizex, sizey, NULL, winmat_jitter, draw_background, draw_sky, !is_ortho, viewname, fx, &fx_settings, ofs); GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp); @@ -3453,7 +2248,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( * \note used by the sequencer */ ImBuf *ED_view3d_draw_offscreen_imbuf_simple( - Scene *scene, Object *camera, int width, int height, + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *scene_layer, + Object *camera, int width, int height, unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, int samples, bool full_samples, const char *viewname, GPUFX *fx, GPUOffScreen *ofs, char err_out[256]) @@ -3471,13 +2267,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple( v3d.lay = scene->lay; v3d.drawtype = drawtype; v3d.flag2 = V3D_RENDER_OVERRIDE; - + if (use_gpencil) v3d.flag2 |= V3D_SHOW_GPENCIL; if (use_solid_tex) v3d.flag2 |= V3D_SOLID_TEX; - + if (draw_background) v3d.flag3 |= V3D_SHOW_WORLD; @@ -3507,665 +2303,105 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple( invert_m4_m4(rv3d.persinv, rv3d.viewinv); return ED_view3d_draw_offscreen_imbuf( - scene, &v3d, &ar, width, height, flag, + eval_ctx, scene, scene_layer, &v3d, &ar, width, height, flag, draw_background, alpha_mode, samples, full_samples, viewname, fx, ofs, err_out); } +/** \} */ -/** - * \note The info that this uses is updated in #ED_refresh_viewport_fps, - * which currently gets called during #SCREEN_OT_animation_step. - */ -void ED_scene_draw_fps(Scene *scene, const rcti *rect) -{ - ScreenFrameRateInfo *fpsi = scene->fps_info; - float fps; - char printable[16]; - int i, tot; - - if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) - return; - - printable[0] = '\0'; - -#if 0 - /* this is too simple, better do an average */ - fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime)) -#else - fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime)); - - for (i = 0, tot = 0, fps = 0.0f; i < REDRAW_FRAME_AVERAGE; i++) { - if (fpsi->redrawtimes_fps[i]) { - fps += fpsi->redrawtimes_fps[i]; - tot++; - } - } - if (tot) { - fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE; - - //fpsi->redrawtime_index++; - //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE) - // fpsi->redrawtime = 0; - - fps = fps / tot; - } -#endif - - /* is this more than half a frame behind? */ - if (fps + 0.5f < (float)(FPS)) { - UI_ThemeColor(TH_REDALERT); - BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps); - } - else { - UI_ThemeColor(TH_TEXT_HI); - BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f)); - } - -#ifdef WITH_INTERNATIONAL - BLF_draw_default(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable)); -#else - BLF_draw_default_ascii(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable)); -#endif -} -static bool view3d_main_region_do_render_draw(Scene *scene) -{ - RenderEngineType *type = RE_engines_find(scene->r.engine); +/* -------------------------------------------------------------------- */ - return (type && type->view_update && type->view_draw); -} +/** \name Legacy Interface + * + * This will be removed once the viewport gets replaced + * meanwhile it should keep the old viewport working. + * + * \{ */ -bool ED_view3d_calc_render_border(Scene *scene, View3D *v3d, ARegion *ar, rcti *rect) +void VP_legacy_drawcursor(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d) { - RegionView3D *rv3d = ar->regiondata; - rctf viewborder; - bool use_border; - - /* test if there is a 3d view rendering */ - if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene)) - return false; - - /* test if there is a border render */ - if (rv3d->persp == RV3D_CAMOB) - use_border = (scene->r.mode & R_BORDER) != 0; - else - use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0; - - if (!use_border) - return false; - - /* compute border */ - if (rv3d->persp == RV3D_CAMOB) { - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false); - - rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); - rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); - rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); - rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); + if (is_cursor_visible(scene, sl)) { + drawcursor(scene, ar, v3d); } - else { - rect->xmin = v3d->render_border.xmin * ar->winx; - rect->xmax = v3d->render_border.xmax * ar->winx; - rect->ymin = v3d->render_border.ymin * ar->winy; - rect->ymax = v3d->render_border.ymax * ar->winy; - } - - BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin); - BLI_rcti_isect(&ar->winrct, rect, rect); - - return true; } -static bool view3d_main_region_draw_engine(const bContext *C, Scene *scene, - ARegion *ar, View3D *v3d, - bool clip_border, const rcti *border_rect) +void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect) { - RegionView3D *rv3d = ar->regiondata; - RenderEngineType *type; - GLint scissor[4]; - - /* create render engine */ - if (!rv3d->render_engine) { - RenderEngine *engine; - - type = RE_engines_find(scene->r.engine); - - if (!(type->view_update && type->view_draw)) - return false; - - engine = RE_engine_create_ex(type, true); - - engine->tile_x = scene->r.tilex; - engine->tile_y = scene->r.tiley; - - type->view_update(engine, C); - - rv3d->render_engine = engine; - } - - /* setup view matrices */ - view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL, NULL); - - /* background draw */ - ED_region_pixelspace(ar); - - if (clip_border) { - /* for border draw, we only need to clear a subset of the 3d view */ - if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) { - glGetIntegerv(GL_SCISSOR_BOX, scissor); - glScissor(border_rect->xmin, border_rect->ymin, - BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect)); - } - else { - return false; - } - } - - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - if (v3d->flag & V3D_DISPBGPICS) - view3d_draw_bgpic_test(scene, ar, v3d, false, true); - else - fdrawcheckerboard(0, 0, ar->winx, ar->winy); - - /* render result draw */ - type = rv3d->render_engine->type; - type->view_draw(rv3d->render_engine, C); - - if (v3d->flag & V3D_DISPBGPICS) - view3d_draw_bgpic_test(scene, ar, v3d, true, true); - - if (clip_border) { - /* restore scissor as it was before */ - glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); - } - - return true; + draw_view_axis(rv3d, rect); } -static void view3d_main_region_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ARegion *ar, bool render_border) +void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect) { - float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f}; - - if (!rv3d->render_engine || !rv3d->render_engine->text[0]) - return; - - if (render_border) { - /* draw darkened background color. no alpha because border render does - * partial redraw and will not redraw the region behind this info bar */ - float alpha = 1.0f - fill_color[3]; - Camera *camera = ED_view3d_camera_data_get(v3d, rv3d); - - if (camera) { - if (camera->flag & CAM_SHOWPASSEPARTOUT) { - alpha *= (1.0f - camera->passepartalpha); - } - } - - UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color); - mul_v3_fl(fill_color, alpha); - fill_color[3] = 1.0f; - } - - ED_region_info_draw(ar, rv3d->render_engine->text, fill_color, true); + draw_viewport_name(ar, v3d, rect); } -static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d) +void VP_legacy_draw_selected_name(Scene *scene, Object *ob, rcti *rect) { - if ((scene->r.scemode & R_MULTIVIEW) == 0) { - return false; - } - - if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) { - return false; - } - - switch (v3d->stereo3d_camera) { - case STEREO_MONO_ID: - return false; - break; - case STEREO_3D_ID: - /* win will be NULL when calling this from the selection or draw loop. */ - if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) { - return false; - } - if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) && - !BKE_scene_multiview_is_stereo3d(&scene->r)) - { - return false; - } - break; - /* We always need the stereo calculation for left and right cameras. */ - case STEREO_LEFT_ID: - case STEREO_RIGHT_ID: - default: - break; - } - return true; + draw_selected_name(scene, ob, rect); } -/* setup the view and win matrices for the multiview cameras - * - * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called - * we have no winmatrix (i.e., projection matrix) defined at that time. - * Since the camera and the camera shift are needed for the winmat calculation - * we do a small hack to replace it temporarily so we don't need to change the - * view3d)main_region_setup_view() code to account for that. - */ -static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect) +void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit) { - bool is_left; - const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; - const char *viewname; - - /* show only left or right camera */ - if (v3d->stereo3d_camera != STEREO_3D_ID) - v3d->multiview_eye = v3d->stereo3d_camera; - - is_left = v3d->multiview_eye == STEREO_LEFT_ID; - viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID]; - - /* update the viewport matrices with the new camera */ - if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { - Camera *data; - float viewmat[4][4]; - float shiftx; - - data = (Camera *)v3d->camera->data; - shiftx = data->shiftx; - - BLI_lock_thread(LOCK_VIEW3D); - data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname); - - BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); - view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL, rect); - - data->shiftx = shiftx; - BLI_unlock_thread(LOCK_VIEW3D); - } - else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ - float viewmat[4][4]; - Object *view_ob = v3d->camera; - Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); - - BLI_lock_thread(LOCK_VIEW3D); - v3d->camera = camera; - - BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); - view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL, rect); - - v3d->camera = view_ob; - BLI_unlock_thread(LOCK_VIEW3D); - } + drawgrid(unit, ar, v3d, grid_unit); } -static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar, - float winmat[4][4], const char *viewname) +void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth) { - /* update the viewport matrices with the new camera */ - if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { - float viewmat[4][4]; - const bool is_left = STREQ(viewname, STEREO_LEFT_NAME); - - BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); - view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL); - } - else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ - float viewmat[4][4]; - Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); - - BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); - view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL); - } + drawfloor(scene, v3d, grid_unit, write_depth); } -#ifdef WITH_GAMEENGINE -static void update_lods(Scene *scene, float camera_pos[3]) +void VP_legacy_view3d_main_region_setup_view( + const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, + ARegion *ar, float viewmat[4][4], float winmat[4][4]) { - Scene *sce_iter; - Base *base; - Object *ob; - - for (SETLOOPER(scene, sce_iter, base)) { - ob = base->object; - BKE_object_lod_update(ob, camera_pos); - } + view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL); } -#endif -static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, View3D *v3d, - ARegion *ar, const char **grid_unit) +bool VP_legacy_view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d) { - wmWindow *win = CTX_wm_window(C); - RegionView3D *rv3d = ar->regiondata; - unsigned int lay_used = v3d->lay_used; - - /* post processing */ - bool do_compositing = false; - - /* shadow buffers, before we setup matrices */ - if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) - gpu_update_lamps_shadows_world(scene, v3d); - - /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */ - if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) { - rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE; - GPU_default_lights(); - } - - /* Setup the view matrix. */ - ED_view3d_draw_setup_view(CTX_wm_window(C), scene, ar, v3d, NULL, NULL, NULL); - - rv3d->rflag &= ~RV3D_IS_GAME_ENGINE; -#ifdef WITH_GAMEENGINE - if (STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME)) { - rv3d->rflag |= RV3D_IS_GAME_ENGINE; - - /* Make sure LoDs are up to date */ - update_lods(scene, rv3d->viewinv[3]); - } -#endif - - /* framebuffer fx needed, we need to draw offscreen first */ - if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) { - GPUFXSettings fx_settings; - BKE_screen_gpu_fx_validate(&v3d->fx_settings); - fx_settings = v3d->fx_settings; - if (!rv3d->compositor) - rv3d->compositor = GPU_fx_compositor_create(); - - if (rv3d->persp == RV3D_CAMOB && v3d->camera) - BKE_camera_to_gpu_dof(v3d->camera, &fx_settings); - else { - fx_settings.dof = NULL; - } - - do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings); - } - - /* clear the background */ - view3d_main_region_clear(scene, v3d, ar); - - /* enables anti-aliasing for 3D view drawing */ - if (win->multisamples != USER_MULTISAMPLE_NONE) { - glEnable(GL_MULTISAMPLE); - } - - /* main drawing call */ - view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL); - - /* post process */ - if (do_compositing) { - GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL); - } - - /* Disable back anti-aliasing */ - if (win->multisamples != USER_MULTISAMPLE_NONE) { - glDisable(GL_MULTISAMPLE); - } - - if (v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */ - /* find header and force tag redraw */ - ScrArea *sa = CTX_wm_area(C); - ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER); - ED_region_tag_redraw(ar_header); /* can be NULL */ - } - - if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { - BDR_drawSketch(C); - } - -#ifdef WITH_INPUT_NDOF - if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((rv3d->viewlock & RV3D_LOCKED) == 0) && (rv3d->persp != RV3D_CAMOB)) - /* TODO: draw something else (but not this) during fly mode */ - draw_rotation_guide(rv3d); -#endif + return view3d_stereo3d_active(win, scene, v3d, rv3d); } -static bool is_cursor_visible(Scene *scene) +void VP_legacy_view3d_stereo3d_setup(const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar) { - Object *ob = OBACT; - - /* don't draw cursor in paint modes, but with a few exceptions */ - if (ob && ob->mode & OB_MODE_ALL_PAINT) { - /* exception: object is in weight paint and has deforming armature in pose mode */ - if (ob->mode & OB_MODE_WEIGHT_PAINT) { - if (BKE_object_pose_armature_get(ob) != NULL) { - return true; - } - } - /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */ - else if (ob->mode & OB_MODE_TEXTURE_PAINT) { - const Paint *p = BKE_paint_get_active(scene); - - if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) { - if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) { - return true; - } - } - } - - /* no exception met? then don't draw cursor! */ - return false; - } - - return true; + view3d_stereo3d_setup(eval_ctx, scene, v3d, ar, NULL); } -static void view3d_main_region_draw_info(const bContext *C, Scene *scene, - ARegion *ar, View3D *v3d, - const char *grid_unit, bool render_border) +bool VP_legacy_use_depth(Scene *scene, View3D *v3d) { - wmWindowManager *wm = CTX_wm_manager(C); - RegionView3D *rv3d = ar->regiondata; - rcti rect; - - /* local coordinate visible rect inside region, to accomodate overlapping ui */ - ED_region_visible_rect(ar, &rect); - - if (rv3d->persp == RV3D_CAMOB) { - drawviewborder(scene, ar, v3d); - } - else if (v3d->flag2 & V3D_RENDER_BORDER) { - glLineWidth(1.0f); - setlinestyle(3); - cpack(0x4040FF); - - sdrawbox(v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy, - v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy); - - setlinestyle(0); - } - - if (v3d->flag2 & V3D_SHOW_GPENCIL) { - /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */ - ED_gpencil_draw_view3d(wm, scene, v3d, ar, false); - } - - if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { - Object *ob; - - /* 3d cursor */ - if (is_cursor_visible(scene)) { - drawcursor(scene, ar, v3d); - } - - if (U.uiflag & USER_SHOW_ROTVIEWICON) - draw_view_axis(rv3d, &rect); - else - draw_view_icon(rv3d, &rect); - - ob = OBACT; - if (U.uiflag & USER_DRAWVIEWINFO) - draw_selected_name(scene, ob, &rect); - } - - if (rv3d->render_engine) { - view3d_main_region_draw_engine_info(v3d, rv3d, ar, render_border); - return; - } - - if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { - if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) { - ED_scene_draw_fps(scene, &rect); - } - else if (U.uiflag & USER_SHOW_VIEWPORTNAME) { - draw_viewport_name(ar, v3d, &rect); - } - - if (grid_unit) { /* draw below the viewport name */ - char numstr[32] = ""; - - UI_ThemeColor(TH_TEXT_HI); - if (v3d->grid != 1.0f) { - BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); - } - - BLF_draw_default_ascii(rect.xmin + U.widget_unit, - rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f, - numstr[0] ? numstr : grid_unit, sizeof(numstr)); - } - } + return use_depth_doit(scene, v3d); } -void view3d_main_region_draw(const bContext *C, ARegion *ar) +void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) { - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - const char *grid_unit = NULL; - rcti border_rect; - bool render_border, clip_border; - - /* if we only redraw render border area, skip opengl draw and also - * don't do scissor because it's already set */ - render_border = ED_view3d_calc_render_border(scene, v3d, ar, &border_rect); - clip_border = (render_border && !BLI_rcti_compare(&ar->drawrct, &border_rect)); - - /* draw viewport using opengl */ - if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene) || clip_border) { - view3d_main_region_draw_objects(C, scene, v3d, ar, &grid_unit); - -#ifdef DEBUG_DRAW - bl_debug_draw(); -#endif - if (G.debug & G_DEBUG_SIMDATA) - draw_sim_debug_data(scene, v3d, ar); - - ED_region_pixelspace(ar); - } - - /* draw viewport using external renderer */ - if (v3d->drawtype == OB_RENDER) - view3d_main_region_draw_engine(C, scene, ar, v3d, clip_border, &border_rect); - - view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border); - - v3d->flag |= V3D_INVALID_BACKBUF; - - BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_transp)); - BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xray)); - BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xraytransp)); + drawviewborder(scene, ar, v3d); } -#ifdef DEBUG_DRAW -/* debug drawing */ -#define _DEBUG_DRAW_QUAD_TOT 1024 -#define _DEBUG_DRAW_EDGE_TOT 1024 -static float _bl_debug_draw_quads[_DEBUG_DRAW_QUAD_TOT][4][3]; -static int _bl_debug_draw_quads_tot = 0; -static float _bl_debug_draw_edges[_DEBUG_DRAW_QUAD_TOT][2][3]; -static int _bl_debug_draw_edges_tot = 0; -static unsigned int _bl_debug_draw_quads_color[_DEBUG_DRAW_QUAD_TOT]; -static unsigned int _bl_debug_draw_edges_color[_DEBUG_DRAW_EDGE_TOT]; -static unsigned int _bl_debug_draw_color; - -void bl_debug_draw_quad_clear(void) -{ - _bl_debug_draw_quads_tot = 0; - _bl_debug_draw_edges_tot = 0; - _bl_debug_draw_color = 0x00FF0000; -} -void bl_debug_color_set(const unsigned int color) +void VP_drawrenderborder(ARegion *ar, View3D *v3d) { - _bl_debug_draw_color = color; + drawrenderborder(ar, v3d); } -void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]) + +void VP_view3d_draw_background_none(void) { - if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_QUAD_TOT) { - printf("%s: max quad count hit %d!", __func__, _bl_debug_draw_quads_tot); + if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) { + view3d_draw_background_gradient(); } else { - float *pt = &_bl_debug_draw_quads[_bl_debug_draw_quads_tot][0][0]; - copy_v3_v3(pt, v0); pt += 3; - copy_v3_v3(pt, v1); pt += 3; - copy_v3_v3(pt, v2); pt += 3; - copy_v3_v3(pt, v3); pt += 3; - _bl_debug_draw_quads_color[_bl_debug_draw_quads_tot] = _bl_debug_draw_color; - _bl_debug_draw_quads_tot++; + view3d_draw_background_none(); } } -void bl_debug_draw_edge_add(const float v0[3], const float v1[3]) + +void VP_view3d_draw_background_world(Scene *scene, RegionView3D *rv3d) { - if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_EDGE_TOT) { - printf("%s: max edge count hit %d!", __func__, _bl_debug_draw_edges_tot); - } - else { - float *pt = &_bl_debug_draw_edges[_bl_debug_draw_edges_tot][0][0]; - copy_v3_v3(pt, v0); pt += 3; - copy_v3_v3(pt, v1); pt += 3; - _bl_debug_draw_edges_color[_bl_debug_draw_edges_tot] = _bl_debug_draw_color; - _bl_debug_draw_edges_tot++; - } + view3d_draw_background_world(scene, rv3d); } -static void bl_debug_draw(void) + +void VP_view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar) { - unsigned int color; - if (_bl_debug_draw_quads_tot) { - int i; - color = _bl_debug_draw_quads_color[0]; - cpack(color); - for (i = 0; i < _bl_debug_draw_quads_tot; i ++) { - if (_bl_debug_draw_quads_color[i] != color) { - color = _bl_debug_draw_quads_color[i]; - cpack(color); - } - glBegin(GL_LINE_LOOP); - glVertex3fv(_bl_debug_draw_quads[i][0]); - glVertex3fv(_bl_debug_draw_quads[i][1]); - glVertex3fv(_bl_debug_draw_quads[i][2]); - glVertex3fv(_bl_debug_draw_quads[i][3]); - glEnd(); - } - } - if (_bl_debug_draw_edges_tot) { - int i; - color = _bl_debug_draw_edges_color[0]; - cpack(color); - glBegin(GL_LINES); - for (i = 0; i < _bl_debug_draw_edges_tot; i ++) { - if (_bl_debug_draw_edges_color[i] != color) { - color = _bl_debug_draw_edges_color[i]; - cpack(color); - } - glVertex3fv(_bl_debug_draw_edges[i][0]); - glVertex3fv(_bl_debug_draw_edges[i][1]); - } - glEnd(); - color = _bl_debug_draw_edges_color[0]; - cpack(color); - glPointSize(4.0); - glBegin(GL_POINTS); - for (i = 0; i < _bl_debug_draw_edges_tot; i ++) { - if (_bl_debug_draw_edges_color[i] != color) { - color = _bl_debug_draw_edges_color[i]; - cpack(color); - } - glVertex3fv(_bl_debug_draw_edges[i][0]); - glVertex3fv(_bl_debug_draw_edges[i][1]); - } - glEnd(); - } + view3d_main_region_clear(scene, v3d, ar); } -#endif + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c new file mode 100644 index 00000000000..9f1c27a09e7 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -0,0 +1,2186 @@ +/* + * ***** BEGIN GPL 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_draw_legacy.c + * \ingroup spview3d + */ + +#include <string.h> +#include <stdio.h> +#include <math.h> + +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_customdata_types.h" +#include "DNA_object_types.h" +#include "DNA_group_types.h" +#include "DNA_mesh_types.h" +#include "DNA_key_types.h" +#include "DNA_lamp_types.h" +#include "DNA_scene_types.h" +#include "DNA_world_types.h" +#include "DNA_brush_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_jitter.h" +#include "BLI_utildefines.h" +#include "BLI_endian_switch.h" +#include "BLI_threads.h" + +#include "BKE_anim.h" +#include "BKE_camera.h" +#include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_DerivedMesh.h" +#include "BKE_image.h" +#include "BKE_key.h" +#include "BKE_layer.h" +#include "BKE_main.h" +#include "BKE_object.h" +#include "BKE_global.h" +#include "BKE_paint.h" +#include "BKE_scene.h" +#include "BKE_screen.h" +#include "BKE_unit.h" +#include "BKE_movieclip.h" + +#include "DEG_depsgraph.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "IMB_colormanagement.h" + +#include "BIF_glutil.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "BLF_api.h" +#include "BLT_translation.h" + +#include "ED_armature.h" +#include "ED_keyframing.h" +#include "ED_gpencil.h" +#include "ED_screen.h" +#include "ED_space_api.h" +#include "ED_screen_types.h" +#include "ED_transform.h" + +#include "UI_interface.h" +#include "UI_interface_icons.h" +#include "UI_resources.h" + +#include "GPU_draw.h" +#include "GPU_framebuffer.h" +#include "GPU_lamp.h" +#include "GPU_material.h" +#include "GPU_compositing.h" +#include "GPU_extensions.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_select.h" +#include "GPU_matrix.h" + +#include "RE_engine.h" + +#include "DRW_engine.h" + +#include "view3d_intern.h" /* own include */ + +/* ********* custom clipping *********** */ + +static void view3d_draw_clipping(RegionView3D *rv3d) +{ + BoundBox *bb = rv3d->clipbb; + + if (bb) { + const unsigned int clipping_index[6][4] = { + {0, 1, 2, 3}, + {0, 4, 5, 1}, + {4, 7, 6, 5}, + {7, 3, 2, 6}, + {1, 5, 6, 2}, + {7, 4, 0, 3} + }; + + /* fill in zero alpha for rendering & re-projection [#31530] */ + unsigned char col[4]; + UI_GetThemeColor4ubv(TH_V3D_CLIPPING_BORDER, col); + glColor4ubv(col); + + glEnable(GL_BLEND); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, bb->vec); + glDrawElements(GL_QUADS, sizeof(clipping_index) / sizeof(unsigned int), GL_UNSIGNED_INT, clipping_index); + glDisableClientState(GL_VERTEX_ARRAY); + glDisable(GL_BLEND); + } +} + +void ED_view3d_clipping_set(RegionView3D *rv3d) +{ + double plane[4]; + const unsigned int tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6; + + for (unsigned a = 0; a < tot; a++) { + copy_v4db_v4fl(plane, rv3d->clip[a]); + glClipPlane(GL_CLIP_PLANE0 + a, plane); + glEnable(GL_CLIP_PLANE0 + a); + } +} + +/* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */ +void ED_view3d_clipping_disable(void) +{ + for (unsigned a = 0; a < 6; a++) { + glDisable(GL_CLIP_PLANE0 + a); + } +} +void ED_view3d_clipping_enable(void) +{ + for (unsigned a = 0; a < 6; a++) { + glEnable(GL_CLIP_PLANE0 + a); + } +} + +static bool view3d_clipping_test(const float co[3], const float clip[6][4]) +{ + if (plane_point_side_v3(clip[0], co) > 0.0f) + if (plane_point_side_v3(clip[1], co) > 0.0f) + if (plane_point_side_v3(clip[2], co) > 0.0f) + if (plane_point_side_v3(clip[3], co) > 0.0f) + return false; + + return true; +} + +/* for 'local' ED_view3d_clipping_local must run first + * then all comparisons can be done in localspace */ +bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local) +{ + return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip); +} + +/* ********* end custom clipping *********** */ + +static void draw_view_icon(RegionView3D *rv3d, rcti *rect) +{ + BIFIconID icon; + + if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) + icon = ICON_AXIS_TOP; + else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) + icon = ICON_AXIS_FRONT; + else if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) + icon = ICON_AXIS_SIDE; + else return; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + UI_icon_draw(5.0 + rect->xmin, 5.0 + rect->ymin, icon); + + glDisable(GL_BLEND); +} + +/* *********************** backdraw for selection *************** */ + +static void backdrawview3d(const struct EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, wmWindow *win, ARegion *ar, View3D *v3d) +{ + RegionView3D *rv3d = ar->regiondata; + struct Base *base = sl->basact; + int multisample_enabled; + + BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); + + if (base && (base->object->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) || + BKE_paint_select_face_test(base->object))) + { + /* do nothing */ + } + /* texture paint mode sampling */ + else if (base && (base->object->mode & OB_MODE_TEXTURE_PAINT) && + (v3d->drawtype > OB_WIRE)) + { + /* do nothing */ + } + else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) && + V3D_IS_ZBUF(v3d)) + { + /* do nothing */ + } + else if (scene->obedit && + V3D_IS_ZBUF(v3d)) + { + /* do nothing */ + } + else { + v3d->flag &= ~V3D_INVALID_BACKBUF; + return; + } + + if (!(v3d->flag & V3D_INVALID_BACKBUF)) + return; + +#if 0 + if (test) { + if (qtest()) { + addafterqueue(ar->win, BACKBUFDRAW, 1); + return; + } + } +#endif + + if (v3d->drawtype > OB_WIRE) v3d->zbuf = true; + + /* dithering and AA break color coding, so disable */ + glDisable(GL_DITHER); + + multisample_enabled = glIsEnabled(GL_MULTISAMPLE); + if (multisample_enabled) + glDisable(GL_MULTISAMPLE); + + if (win->multisamples != USER_MULTISAMPLE_NONE) { + /* for multisample we use an offscreen FBO. multisample drawing can fail + * with color coded selection drawing, and reading back depths from such + * a buffer can also cause a few seconds freeze on OS X / NVidia. */ + int w = BLI_rcti_size_x(&ar->winrct); + int h = BLI_rcti_size_y(&ar->winrct); + char error[256]; + + if (rv3d->gpuoffscreen) { + if (GPU_offscreen_width(rv3d->gpuoffscreen) != w || + GPU_offscreen_height(rv3d->gpuoffscreen) != h) + { + GPU_offscreen_free(rv3d->gpuoffscreen); + rv3d->gpuoffscreen = NULL; + } + } + + if (!rv3d->gpuoffscreen) { + rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error); + + if (!rv3d->gpuoffscreen) + fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error); + } + } + + if (rv3d->gpuoffscreen) + GPU_offscreen_bind(rv3d->gpuoffscreen, true); + else + glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct)); + + glClearColor(0.0, 0.0, 0.0, 0.0); + if (v3d->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 (rv3d->rflag & RV3D_CLIPPING) + ED_view3d_clipping_set(rv3d); + + G.f |= G_BACKBUFSEL; + + if (base && ((base->flag & BASE_VISIBLED) != 0)) + draw_object_backbufsel(eval_ctx, scene, v3d, rv3d, base->object); + + if (rv3d->gpuoffscreen) + GPU_offscreen_unbind(rv3d->gpuoffscreen, true); + else + ar->swap = 0; /* mark invalid backbuf for wm draw */ + + v3d->flag &= ~V3D_INVALID_BACKBUF; + + G.f &= ~G_BACKBUFSEL; + v3d->zbuf = false; + glDisable(GL_DEPTH_TEST); + glEnable(GL_DITHER); + if (multisample_enabled) + glEnable(GL_MULTISAMPLE); + + if (rv3d->rflag & RV3D_CLIPPING) + ED_view3d_clipping_disable(); +} + +void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data) +{ + RegionView3D *rv3d = ar->regiondata; + + if (rv3d->gpuoffscreen) { + GPU_offscreen_bind(rv3d->gpuoffscreen, true); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glReadPixels(x, y, w, h, format, type, data); + GPU_offscreen_unbind(rv3d->gpuoffscreen, true); + } + else { + glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); + } +} + +/* XXX depth reading exception, for code not using gpu offscreen */ +static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data) +{ + glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); +} + +void ED_view3d_backbuf_validate(const struct EvaluationContext *eval_ctx, ViewContext *vc) +{ + if (vc->v3d->flag & V3D_INVALID_BACKBUF) { + backdrawview3d(eval_ctx, vc->scene, vc->scene_layer, vc->win, vc->ar, vc->v3d); + } +} + +/** + * allow for small values [0.5 - 2.5], + * and large values, FLT_MAX by clamping by the area size + */ +int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) +{ + return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); +} + +/* samples a single pixel (copied from vpaint) */ +unsigned int ED_view3d_backbuf_sample( + const EvaluationContext *eval_ctx, ViewContext *vc, int x, int y) +{ + if (x >= vc->ar->winx || y >= vc->ar->winy) { + return 0; + } + + ED_view3d_backbuf_validate(eval_ctx, vc); + + unsigned int col; + view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); + glReadBuffer(GL_BACK); + + if (ENDIAN_ORDER == B_ENDIAN) { + BLI_endian_switch_uint32(&col); + } + + return GPU_select_to_index(col); +} + +/* reads full rect, converts indices */ +ImBuf *ED_view3d_backbuf_read( + const EvaluationContext *eval_ctx, ViewContext *vc, int xmin, int ymin, int xmax, int ymax) +{ + /* clip */ + const rcti clip = { + max_ii(xmin, 0), min_ii(xmax, vc->ar->winx - 1), + max_ii(ymin, 0), min_ii(ymax, vc->ar->winy - 1)}; + const int size_clip[2] = { + BLI_rcti_size_x(&clip) + 1, + BLI_rcti_size_y(&clip) + 1}; + + if (UNLIKELY((clip.xmin > clip.xmax) || + (clip.ymin > clip.ymax))) + { + return NULL; + } + + ImBuf *ibuf_clip = IMB_allocImBuf(size_clip[0], size_clip[1], 32, IB_rect); + + ED_view3d_backbuf_validate(eval_ctx, vc); + + view3d_opengl_read_pixels(vc->ar, clip.xmin, clip.ymin, size_clip[0], size_clip[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf_clip->rect); + + glReadBuffer(GL_BACK); + + if (ENDIAN_ORDER == B_ENDIAN) { + IMB_convert_rgba_to_abgr(ibuf_clip); + } + + GPU_select_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]); + + if ((clip.xmin == xmin) && + (clip.xmax == xmax) && + (clip.ymin == ymin) && + (clip.ymax == ymax)) + { + return ibuf_clip; + } + else { + /* put clipped result into a non-clipped buffer */ + const int size[2] = { + (xmax - xmin + 1), + (ymax - ymin + 1)}; + + ImBuf *ibuf_full = IMB_allocImBuf(size[0], size[1], 32, IB_rect); + + IMB_rectcpy( + ibuf_full, ibuf_clip, + clip.xmin - xmin, clip.ymin - ymin, + 0, 0, + size_clip[0], size_clip[1]); + IMB_freeImBuf(ibuf_clip); + return ibuf_full; + } +} + +/* smart function to sample a rect spiralling outside, nice for backbuf selection */ +unsigned int ED_view3d_backbuf_sample_rect( + const EvaluationContext *eval_ctx, ViewContext *vc, const int mval[2], int size, + unsigned int min, unsigned int max, float *r_dist) +{ + int dirvec[4][2]; + + const int amount = (size - 1) / 2; + + const int minx = mval[0] - (amount + 1); + const int miny = mval[1] - (amount + 1); + ImBuf *buf = ED_view3d_backbuf_read(eval_ctx, vc, minx, miny, minx + size - 1, miny + size - 1); + if (!buf) return 0; + + unsigned index = 0; + int 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; + + const unsigned *bufmin = buf->rect; + const unsigned *tbuf = buf->rect; + const unsigned *bufmax = buf->rect + size * size; + tbuf += amount * size + amount; + + for (int nr = 1; nr <= size; nr++) { + for (int a = 0; a < 2; a++) { + for (int b = 0; b < nr; b++) { + if (*tbuf && *tbuf >= min && *tbuf < max) { + /* we got a hit */ + + /* get x,y pixel coords from the offset + * (manhatten distance in keeping with other screen-based selection) */ + *r_dist = (float)( + abs(((int)(tbuf - buf->rect) % size) - (size / 2)) + + abs(((int)(tbuf - buf->rect) / size) - (size / 2))); + + /* indices start at 1 here */ + index = (*tbuf - min) + 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; +} + + +/* ************************************************************* */ + +static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser) +{ + if (BKE_image_is_stereo(ima)) { + iuser->flag |= IMA_SHOW_STEREO; + + if ((scene->r.scemode & R_MULTIVIEW) == 0) { + iuser->multiview_eye = STEREO_LEFT_ID; + } + else if (v3d->stereo3d_camera != STEREO_3D_ID) { + /* show only left or right camera */ + iuser->multiview_eye = v3d->stereo3d_camera; + } + + BKE_image_multiview_index(ima, iuser); + } + else { + iuser->flag &= ~IMA_SHOW_STEREO; + } +} + +static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, + const bool do_foreground, const bool do_camera_frame) +{ + RegionView3D *rv3d = ar->regiondata; + int fg_flag = do_foreground ? CAM_BGIMG_FLAG_FOREGROUND : 0; + if (v3d->camera == NULL || v3d->camera->type != OB_CAMERA) { + return; + } + Camera *cam = v3d->camera->data; + + for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) { + bgpic->iuser.scene = scene; /* Needed for render results. */ + + if ((bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != fg_flag) + continue; + + { + float image_aspect[2]; + float x1, y1, x2, y2, centx, centy; + + void *lock; + + Image *ima = NULL; + + /* disable individual images */ + if ((bgpic->flag & CAM_BGIMG_FLAG_DISABLED)) + continue; + + ImBuf *ibuf = NULL; + ImBuf *freeibuf = NULL; + ImBuf *releaseibuf = NULL; + if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) { + ima = bgpic->ima; + if (ima == NULL) + continue; + BKE_image_user_frame_calc(&bgpic->iuser, CFRA, 0); + if (ima->source == IMA_SRC_SEQUENCE && !(bgpic->iuser.flag & IMA_USER_FRAME_IN_RANGE)) { + ibuf = NULL; /* frame is out of range, dont show */ + } + else { + view3d_stereo_bgpic_setup(scene, v3d, ima, &bgpic->iuser); + ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, &lock); + releaseibuf = ibuf; + } + + image_aspect[0] = ima->aspx; + image_aspect[1] = ima->aspy; + } + else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) { + /* TODO: skip drawing when out of frame range (as image sequences do above) */ + MovieClip *clip = NULL; + + if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) { + if (scene->camera) + clip = BKE_object_movieclip_get(scene, scene->camera, true); + } + else { + clip = bgpic->clip; + } + + if (clip == NULL) + continue; + + BKE_movieclip_user_set_frame(&bgpic->cuser, CFRA); + ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser); + + image_aspect[0] = clip->aspx; + image_aspect[1] = clip->aspy; + + /* working with ibuf from image and clip has got different workflow now. + * ibuf acquired from clip is referenced by cache system and should + * be dereferenced after usage. */ + freeibuf = ibuf; + } + else { + /* perhaps when loading future files... */ + BLI_assert(0); + copy_v2_fl(image_aspect, 1.0f); + } + + if (ibuf == NULL) + continue; + + if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */ + if (freeibuf) + IMB_freeImBuf(freeibuf); + if (releaseibuf) + BKE_image_release_ibuf(ima, releaseibuf, lock); + + continue; + } + + if (ibuf->rect == NULL) + IMB_rect_from_float(ibuf); + + BLI_assert(rv3d->persp == RV3D_CAMOB); + { + if (do_camera_frame) { + rctf vb; + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false); + x1 = vb.xmin; + y1 = vb.ymin; + x2 = vb.xmax; + y2 = vb.ymax; + } + else { + x1 = ar->winrct.xmin; + y1 = ar->winrct.ymin; + x2 = ar->winrct.xmax; + y2 = ar->winrct.ymax; + } + + /* apply offset last - camera offset is different to offset in blender units */ + /* so this has some sane way of working - this matches camera's shift _exactly_ */ + { + const float max_dim = max_ff(x2 - x1, y2 - y1); + const float xof_scale = bgpic->offset[0] * max_dim; + const float yof_scale = bgpic->offset[1] * max_dim; + + x1 += xof_scale; + y1 += yof_scale; + x2 += xof_scale; + y2 += yof_scale; + } + + centx = (x1 + x2) * 0.5f; + centy = (y1 + y2) * 0.5f; + + /* aspect correction */ + if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_ASPECT) { + /* apply aspect from clip */ + const float w_src = ibuf->x * image_aspect[0]; + const float h_src = ibuf->y * image_aspect[1]; + + /* destination aspect is already applied from the camera frame */ + const float w_dst = x1 - x2; + const float h_dst = y1 - y2; + + const float asp_src = w_src / h_src; + const float asp_dst = w_dst / h_dst; + + if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) { + if ((asp_src > asp_dst) == ((bgpic->flag & CAM_BGIMG_FLAG_CAMERA_CROP) != 0)) { + /* fit X */ + const float div = asp_src / asp_dst; + x1 = ((x1 - centx) * div) + centx; + x2 = ((x2 - centx) * div) + centx; + } + else { + /* fit Y */ + const float div = asp_dst / asp_src; + y1 = ((y1 - centy) * div) + centy; + y2 = ((y2 - centy) * div) + centy; + } + } + } + } + + /* complete clip? */ + rctf clip_rect; + BLI_rctf_init(&clip_rect, x1, x2, y1, y2); + if (bgpic->rotation) { + BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation); + } + + if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) { + if (freeibuf) + IMB_freeImBuf(freeibuf); + if (releaseibuf) + BKE_image_release_ibuf(ima, releaseibuf, lock); + + continue; + } + + float zoomx = (x2 - x1) / ibuf->x; + float zoomy = (y2 - y1) / ibuf->y; + + /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */ + if (zoomx < 1.0f || zoomy < 1.0f) { + float tzoom = min_ff(zoomx, zoomy); + int mip = 0; + + if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) { + IMB_remakemipmap(ibuf, 0); + ibuf->userflags &= ~IB_MIPMAP_INVALID; + } + else if (ibuf->mipmap[0] == NULL) + IMB_makemipmap(ibuf, 0); + + while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) { + tzoom *= 2.0f; + zoomx *= 2.0f; + zoomy *= 2.0f; + mip++; + } + if (mip > 0) + ibuf = ibuf->mipmap[mip - 1]; + } + + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + gpuPushProjectionMatrix(); + gpuPushMatrix(); + ED_region_pixelspace(ar); + + gpuTranslate2f(centx, centy); + gpuScaleUniform(bgpic->scale); + gpuRotate2D(RAD2DEGF(-bgpic->rotation)); + + if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) { + zoomx *= -1.0f; + x1 = x2; + } + if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) { + zoomy *= -1.0f; + y1 = y2; + } + + float col[4] = {1.0f, 1.0f, 1.0f, bgpic->alpha}; + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect, + zoomx, zoomy, col); + + gpuPopProjectionMatrix(); + gpuPopMatrix(); + + glDisable(GL_BLEND); + + glDepthMask(GL_TRUE); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + + if (freeibuf) + IMB_freeImBuf(freeibuf); + if (releaseibuf) + BKE_image_release_ibuf(ima, releaseibuf, lock); + } + } +} + +void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d, + const bool do_foreground, const bool do_camera_frame) +{ + RegionView3D *rv3d = ar->regiondata; + + if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) { + Camera *cam = v3d->camera->data; + if ((cam->flag & CAM_SHOW_BG_IMAGE) == 0) { + return; + } + } + else { + return; + } + + /* disabled - mango request, since footage /w only render is quite useful + * and this option is easy to disable all background images at once */ +#if 0 + if (v3d->flag2 & V3D_RENDER_OVERRIDE) + return; +#endif + + if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) { + if (rv3d->persp == RV3D_CAMOB) { + view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame); + } + } + else { + view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame); + } +} + +/* ****************** View3d afterdraw *************** */ + +typedef struct View3DAfter { + struct View3DAfter *next, *prev; + struct Base *base; + short dflag; +} View3DAfter; + +/* temp storage of Objects that need to be drawn as last */ +void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag) +{ + View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after"); + BLI_assert((base->flag_legacy & OB_FROMDUPLI) == 0); + BLI_addtail(lb, v3da); + v3da->base = base; + v3da->dflag = dflag; +} + +/* disables write in zbuffer and draws it over */ +static void view3d_draw_transp( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d) +{ + View3DAfter *v3da; + + glDepthMask(GL_FALSE); + v3d->transp = true; + + while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, v3da->dflag); + MEM_freeN(v3da); + } + v3d->transp = false; + + glDepthMask(GL_TRUE); + +} + +/* clears zbuffer and draws it over */ +static void view3d_draw_xray( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, bool *clear) +{ + if (*clear && v3d->zbuf) { + glClear(GL_DEPTH_BUFFER_BIT); + *clear = false; + } + + v3d->xray = true; + View3DAfter *v3da; + while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, v3da->dflag); + MEM_freeN(v3da); + } + v3d->xray = false; +} + + +/* clears zbuffer and draws it over */ +static void view3d_draw_xraytransp( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, const bool clear) +{ + if (clear && v3d->zbuf) + glClear(GL_DEPTH_BUFFER_BIT); + + v3d->xray = true; + v3d->transp = true; + + glDepthMask(GL_FALSE); + + View3DAfter *v3da; + while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, v3da->dflag); + MEM_freeN(v3da); + } + + v3d->transp = false; + v3d->xray = false; + + glDepthMask(GL_TRUE); +} + +/* clears zbuffer and draws it over, + * note that in the select version we don't care about transparent flag as with regular drawing */ +static void view3d_draw_xray_select( + const struct EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, bool *clear) +{ + /* Not ideal, but we need to read from the previous depths before clearing + * otherwise we could have a function to load the depths after drawing. + * + * Clearing the depth buffer isn't all that common between drawing objects so accept this for now. + */ + if (U.gpu_select_pick_deph) { + GPU_select_load_id(-1); + } + + View3DAfter *v3da; + if (*clear && v3d->zbuf) { + glClear(GL_DEPTH_BUFFER_BIT); + *clear = false; + } + + v3d->xray = true; + while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { + if (GPU_select_load_id(v3da->base->object->select_color)) { + draw_object_select(eval_ctx, scene, sl, ar, v3d, v3da->base, v3da->dflag); + } + MEM_freeN(v3da); + } + v3d->xray = false; +} + +/* *********************** */ + +/* + * In most cases call draw_dupli_objects, + * draw_dupli_objects_color was added because when drawing set dupli's + * we need to force the color + */ + +#if 0 +int dupli_ob_sort(void *arg1, void *arg2) +{ + void *p1 = ((DupliObject *)arg1)->ob; + void *p2 = ((DupliObject *)arg2)->ob; + int val = 0; + if (p1 < p2) val = -1; + else if (p1 > p2) val = 1; + return val; +} +#endif + + +static DupliObject *dupli_step(DupliObject *dob) +{ + while (dob && dob->no_draw) + dob = dob->next; + return dob; +} + +static void draw_dupli_objects_color( + const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *base, + const short dflag, const int color) +{ + RegionView3D *rv3d = ar->regiondata; + ListBase *lb; + LodLevel *savedlod; + Base tbase = {NULL}; + BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */ + unsigned char color_rgb[3]; + const short dflag_dupli = dflag | DRAW_CONSTCOLOR; + short transflag; + char dt; + short dtx; + DupliApplyData *apply_data; + + if ((base->flag & BASE_VISIBLED) == 0) return; + if ((base->object->restrictflag & OB_RESTRICT_RENDER) && (v3d->flag2 & V3D_RENDER_OVERRIDE)) return; + + if (dflag & DRAW_CONSTCOLOR) { + BLI_assert(color == TH_UNDEFINED); + } + else { + UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb); + } + + tbase.flag_legacy = OB_FROMDUPLI | base->flag_legacy; + tbase.flag = base->flag; + lb = object_duplilist(eval_ctx, scene, base->object); + // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */ + + apply_data = duplilist_apply(eval_ctx, base->object, scene, lb); + + DupliObject *dob_next = NULL; + DupliObject *dob = dupli_step(lb->first); + if (dob) dob_next = dupli_step(dob->next); + + for (; dob; dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) { + bool testbb = false; + + tbase.object = dob->ob; + + /* Make sure lod is updated from dupli's position */ + savedlod = dob->ob->currentlod; + +#ifdef WITH_GAMEENGINE + if (rv3d->rflag & RV3D_IS_GAME_ENGINE) { + BKE_object_lod_update(dob->ob, rv3d->viewinv[3]); + } +#endif + + /* extra service: draw the duplicator in drawtype of parent, minimum taken + * to allow e.g. boundbox box objects in groups for LOD */ + dt = tbase.object->dt; + tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); + + /* inherit draw extra, but not if a boundbox under the assumption that this + * is intended to speed up drawing, and drawing extra (especially wire) can + * slow it down too much */ + dtx = tbase.object->dtx; + if (tbase.object->dt != OB_BOUNDBOX) + tbase.object->dtx = base->object->dtx; + + /* negative scale flag has to propagate */ + transflag = tbase.object->transflag; + + if (is_negative_m4(dob->mat)) + tbase.object->transflag |= OB_NEG_SCALE; + else + tbase.object->transflag &= ~OB_NEG_SCALE; + + /* should move outside the loop but possible color is set in draw_object still */ + if ((dflag & DRAW_CONSTCOLOR) == 0) { + glColor3ubv(color_rgb); + } + + if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) { + bb = *bb_tmp; /* must make a copy */ + testbb = true; + } + + if (!testbb || ED_view3d_boundbox_clip_ex(rv3d, &bb, dob->mat)) { + copy_m4_m4(dob->ob->obmat, dob->mat); + GPU_begin_dupli_object(dob); + draw_object(eval_ctx, scene, sl, ar, v3d, &tbase, dflag_dupli); + GPU_end_dupli_object(); + } + + tbase.object->dt = dt; + tbase.object->dtx = dtx; + tbase.object->transflag = transflag; + tbase.object->currentlod = savedlod; + } + + if (apply_data) { + duplilist_restore(lb, apply_data); + duplilist_free_apply_data(apply_data); + } + + free_object_duplilist(lb); +} + +void draw_dupli_objects(const EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *base) +{ + /* define the color here so draw_dupli_objects_color can be called + * from the set loop */ + + int color = (base->flag & BASE_SELECTED) ? TH_SELECT : TH_WIRE; + /* debug */ + if (base->object->dup_group && base->object->dup_group->id.us < 1) + color = TH_REDALERT; + + draw_dupli_objects_color(eval_ctx, scene, sl, ar, v3d, base, 0, color); +} + +/* XXX warning, not using gpu offscreen here */ +void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) +{ + /* clamp rect by region */ + rcti r = { + .xmin = 0, + .xmax = ar->winx - 1, + .ymin = 0, + .ymax = ar->winy - 1 + }; + + /* Constrain rect to depth bounds */ + BLI_rcti_isect(&r, rect, rect); + + /* assign values to compare with the ViewDepths */ + int x = rect->xmin; + int y = rect->ymin; + + int w = BLI_rcti_size_x(rect); + int h = BLI_rcti_size_y(rect); + + if (w <= 0 || h <= 0) { + if (d->depths) + MEM_freeN(d->depths); + d->depths = NULL; + + d->damaged = false; + } + else if (d->w != w || + d->h != h || + d->x != x || + d->y != y || + d->depths == NULL + ) + { + d->x = x; + d->y = y; + d->w = w; + d->h = h; + + if (d->depths) + MEM_freeN(d->depths); + + d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset"); + + d->damaged = true; + } + + if (d->damaged) { + /* XXX using special function here, it doesn't use the gpu offscreen system */ + view3d_opengl_read_Z_pixels(ar, d->x, d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); + glGetDoublev(GL_DEPTH_RANGE, d->depth_range); + d->damaged = false; + } +} + +/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */ +void ED_view3d_depth_update(ARegion *ar) +{ + RegionView3D *rv3d = ar->regiondata; + + /* Create storage for, and, if necessary, copy depth buffer */ + if (!rv3d->depths) rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); + if (rv3d->depths) { + ViewDepths *d = rv3d->depths; + if (d->w != ar->winx || + d->h != ar->winy || + !d->depths) + { + d->w = ar->winx; + d->h = ar->winy; + if (d->depths) + MEM_freeN(d->depths); + d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); + d->damaged = true; + } + + if (d->damaged) { + view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); + glGetDoublev(GL_DEPTH_RANGE, d->depth_range); + + d->damaged = false; + } + } +} + +/* utility function to find the closest Z value, use for autodepth */ +float view3d_depth_near(ViewDepths *d) +{ + /* convert to float for comparisons */ + const float near = (float)d->depth_range[0]; + const float far_real = (float)d->depth_range[1]; + float far = far_real; + + const float *depths = d->depths; + float depth = FLT_MAX; + int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */ + + /* far is both the starting 'far' value + * and the closest value found. */ + while (i--) { + depth = *depths++; + if ((depth < far) && (depth > near)) { + far = depth; + } + } + + return far == far_real ? FLT_MAX : far; +} + +void ED_view3d_draw_depth_gpencil( + const EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d) +{ + bool zbuf = v3d->zbuf; + + /* Setup view matrix. */ + ED_view3d_draw_setup_view(NULL, eval_ctx, scene, ar, v3d, NULL, NULL, NULL); + + glClear(GL_DEPTH_BUFFER_BIT); + + v3d->zbuf = true; + glEnable(GL_DEPTH_TEST); + + if (v3d->flag2 & V3D_SHOW_GPENCIL) { + ED_gpencil_draw_view3d(NULL, scene, eval_ctx->scene_layer, v3d, ar, true); + } + + v3d->zbuf = zbuf; + if (!zbuf) glDisable(GL_DEPTH_TEST); +} + +void ED_view3d_draw_depth_loop(const EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d) +{ + Base *base; + SceneLayer *sl = eval_ctx->scene_layer; + /* no need for color when drawing depth buffer */ + const short dflag_depth = DRAW_CONSTCOLOR; + + /* draw set first */ + if (scene->set) { + Scene *sce_iter; + for (SETLOOPER(scene->set, sce_iter, base)) { + if ((base->flag & BASE_VISIBLED) != 0) { + draw_object(eval_ctx, scene, sl, ar, v3d, base, 0); + if (base->object->transflag & OB_DUPLI) { + draw_dupli_objects_color(eval_ctx, scene, sl, ar, v3d, base, dflag_depth, TH_UNDEFINED); + } + } + } + } + + for (base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { + /* dupli drawing */ + if (base->object->transflag & OB_DUPLI) { + draw_dupli_objects_color(eval_ctx, scene, sl, ar, v3d, base, dflag_depth, TH_UNDEFINED); + } + draw_object(eval_ctx, scene, sl, ar, v3d, base, dflag_depth); + } + } + + /* this isn't that nice, draw xray objects as if they are normal */ + if (v3d->afterdraw_transp.first || + v3d->afterdraw_xray.first || + v3d->afterdraw_xraytransp.first) + { + View3DAfter *v3da; + int mask_orig; + + v3d->xray = true; + + /* transp materials can change the depth mask, see #21388 */ + glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig); + + + if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) { + glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */ + for (v3da = v3d->afterdraw_xray.first; v3da; v3da = v3da->next) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, dflag_depth); + } + glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */ + } + + /* draw 3 passes, transp/xray/xraytransp */ + v3d->xray = false; + v3d->transp = true; + while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, dflag_depth); + MEM_freeN(v3da); + } + + v3d->xray = true; + v3d->transp = false; + while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, dflag_depth); + MEM_freeN(v3da); + } + + v3d->xray = true; + v3d->transp = true; + while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) { + draw_object(eval_ctx, scene, sl, ar, v3d, v3da->base, dflag_depth); + MEM_freeN(v3da); + } + + + v3d->xray = false; + v3d->transp = false; + + glDepthMask(mask_orig); + } +} + +void ED_view3d_draw_select_loop( + const struct EvaluationContext *eval_ctx, ViewContext *vc, Scene *scene, SceneLayer *sl, + View3D *v3d, ARegion *ar, bool use_obedit_skip, bool use_nearest) +{ + struct bThemeState theme_state; + + short code = 1; + const short dflag = DRAW_PICKING | DRAW_CONSTCOLOR; + + /* Tools may request depth outside of regular drawing code. */ + UI_Theme_Store(&theme_state); + UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); + + if (vc->obedit && vc->obedit->type == OB_MBALL) { + draw_object(eval_ctx, scene, sl, ar, v3d, BASACT(sl), dflag); + } + else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) { + /* if not drawing sketch, draw bones */ + if (!BDR_drawSketchNames(vc)) { + draw_object(eval_ctx, scene, sl, ar, v3d, BASACT(sl), dflag); + } + } + else { + Base *base; + + for (base = sl->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { + if (((base->flag & BASE_SELECTABLED) == 0) || + (use_obedit_skip && (scene->obedit->data == base->object->data))) + { + base->object->select_color = 0; + } + else { + base->object->select_color = code; + + if (use_nearest && (base->object->dtx & OB_DRAWXRAY)) { + ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag); + } + else { + if (GPU_select_load_id(code)) { + draw_object(eval_ctx, scene, sl, ar, v3d, base, dflag); + } + } + code++; + } + } + } + + if (use_nearest) { + bool xrayclear = true; + if (v3d->afterdraw_xray.first) { + view3d_draw_xray_select(eval_ctx, scene, sl, ar, v3d, &xrayclear); + } + } + } + + UI_Theme_Restore(&theme_state); +} + +typedef struct View3DShadow { + struct View3DShadow *next, *prev; + GPULamp *lamp; +} View3DShadow; + +static void gpu_render_lamp_update(Scene *scene, View3D *v3d, + Object *ob, Object *par, + float obmat[4][4], unsigned int lay, + ListBase *shadows) +{ + GPULamp *lamp = GPU_lamp_from_blender(scene, ob, par); + + if (lamp) { + Lamp *la = (Lamp *)ob->data; + + GPU_lamp_update(lamp, lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat); + GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy); + + unsigned int layers = lay & v3d->lay; + + if (layers && + GPU_lamp_has_shadow_buffer(lamp) && + /* keep last, may do string lookup */ + GPU_lamp_visible(lamp, NULL)) + { + View3DShadow *shadow = MEM_callocN(sizeof(View3DShadow), "View3DShadow"); + shadow->lamp = lamp; + BLI_addtail(shadows, shadow); + } + } +} + +static void gpu_update_lamps_shadows_world(const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d) +{ + ListBase shadows; + Scene *sce_iter; + Base *base; + World *world = scene->world; + + BLI_listbase_clear(&shadows); + + /* update lamp transform and gather shadow lamps */ + for (SETLOOPER(scene, sce_iter, base)) { + Object *ob = base->object; + + if (ob->type == OB_LAMP) + gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, ob->lay, &shadows); + + if (ob->transflag & OB_DUPLI) { + DupliObject *dob; + ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob); + + for (dob = lb->first; dob; dob = dob->next) + if (dob->ob->type == OB_LAMP) + gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, ob->lay, &shadows); + + free_object_duplilist(lb); + } + } + + /* render shadows after updating all lamps, nested object_duplilist + * don't work correct since it's replacing object matrices */ + for (View3DShadow *shadow = shadows.first; shadow; shadow = shadow->next) { + /* this needs to be done better .. */ + float viewmat[4][4], winmat[4][4]; + ARegion ar = {NULL}; + RegionView3D rv3d = {{{0}}}; + + int drawtype = v3d->drawtype; + int lay = v3d->lay; + int flag2 = v3d->flag2; + + v3d->drawtype = OB_SOLID; + v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp); + v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP); + v3d->flag2 |= V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW; + + int winsize; + GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat); + + ar.regiondata = &rv3d; + ar.regiontype = RGN_TYPE_WINDOW; + rv3d.persp = RV3D_CAMOB; + copy_m4_m4(rv3d.winmat, winmat); + copy_m4_m4(rv3d.viewmat, viewmat); + invert_m4_m4(rv3d.viewinv, rv3d.viewmat); + mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat); + invert_m4_m4(rv3d.persinv, rv3d.viewinv); + + /* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */ + ED_view3d_draw_offscreen( + eval_ctx, scene, eval_ctx->scene_layer, v3d, &ar, winsize, winsize, viewmat, winmat, + false, false, true, + NULL, NULL, NULL, NULL); + GPU_lamp_shadow_buffer_unbind(shadow->lamp); + + v3d->drawtype = drawtype; + v3d->lay = lay; + v3d->flag2 = flag2; + } + + BLI_freelistN(&shadows); + + /* update world values */ + if (world) { + GPU_mist_update_enable(world->mode & WO_MIST); + GPU_mist_update_values(world->mistype, world->miststa, world->mistdist, world->misi, &world->horr); + GPU_horizon_update_color(&world->horr); + GPU_ambient_update_color(&world->ambr); + GPU_zenith_update_color(&world->zenr); + } +} + +/* *********************** customdata **************** */ + +CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d) +{ + CustomDataMask mask = 0; + const int drawtype = view3d_effective_drawtype(v3d); + + if (ELEM(drawtype, OB_TEXTURE, OB_MATERIAL) || + ((drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX))) + { + mask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; + + if (BKE_scene_use_new_shading_nodes(scene)) { + if (drawtype == OB_MATERIAL) + mask |= CD_MASK_ORCO; + } + else { + if ((scene->gm.matmode == GAME_MAT_GLSL && drawtype == OB_TEXTURE) || + (drawtype == OB_MATERIAL)) + { + mask |= CD_MASK_ORCO; + } + } + } + + return mask; +} + +/* goes over all modes and view3d settings */ +CustomDataMask ED_view3d_screen_datamask(const Scene *scene, const bScreen *screen) +{ + CustomDataMask mask = CD_MASK_BAREMESH; + + /* check if we need tfaces & mcols due to view mode */ + for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_VIEW3D) { + mask |= ED_view3d_datamask(scene, sa->spacedata.first); + } + } + + return mask; +} + +/** + * Shared by #ED_view3d_draw_offscreen and #view3d_main_region_draw_objects + * + * \note \a C and \a grid_unit will be NULL when \a draw_offscreen is set. + * \note Drawing lamps and opengl render uses this, so dont do grease pencil or view widgets here. + */ +static void view3d_draw_objects( + const bContext *C, + const EvaluationContext *eval_ctx, + Scene *scene, View3D *v3d, ARegion *ar, + const char **grid_unit, + const bool do_bgpic, const bool draw_offscreen, GPUFX *fx) +{ + SceneLayer *scene_layer = C ? CTX_data_scene_layer(C) : BKE_scene_layer_from_scene_get(scene); + RegionView3D *rv3d = ar->regiondata; + Base *base; + const bool do_camera_frame = !draw_offscreen; + const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0; + const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO); + /* only draw grids after in solid modes, else it hovers over mesh wires */ + const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx; + bool do_composite_xray = false; + bool xrayclear = true; + + if (!draw_offscreen) { + ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); + } + + if (rv3d->rflag & RV3D_CLIPPING) + view3d_draw_clipping(rv3d); + + /* set zbuffer after we draw clipping region */ + v3d->zbuf = VP_legacy_use_depth(scene, v3d); + + if (v3d->zbuf) { + glEnable(GL_DEPTH_TEST); + } + + /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override + * objects if done last */ + if (draw_grids) { + /* needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views. */ + rv3d->gridview = ED_view3d_grid_scale(scene, v3d, grid_unit); + + if (!draw_floor) { + ED_region_pixelspace(ar); + *grid_unit = NULL; /* drawgrid need this to detect/affect smallest valid unit... */ + VP_legacy_drawgrid(&scene->unit, ar, v3d, grid_unit); + gpuLoadProjectionMatrix(rv3d->winmat); + gpuLoadMatrix(rv3d->viewmat); + } + else if (!draw_grids_after) { + VP_legacy_drawfloor(scene, v3d, grid_unit, true); + } + } + + /* important to do before clipping */ + if (do_bgpic) { + view3d_draw_bgpic_test(scene, ar, v3d, false, do_camera_frame); + } + + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_set(rv3d); + } + + /* draw set first */ + if (scene->set) { + const short dflag = DRAW_CONSTCOLOR | DRAW_SCENESET; + Scene *sce_iter; + for (SETLOOPER(scene->set, sce_iter, base)) { + if ((base->flag & BASE_VISIBLED) != 0) { + UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f); + draw_object(eval_ctx, scene, scene_layer, ar, v3d, base, dflag); + + if (base->object->transflag & OB_DUPLI) { + draw_dupli_objects_color(eval_ctx, scene, scene_layer, ar, v3d, base, dflag, TH_UNDEFINED); + } + } + } + + /* Transp and X-ray afterdraw stuff for sets is done later */ + } + + if (draw_offscreen) { + for (base = scene_layer->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { + /* dupli drawing */ + if (base->object->transflag & OB_DUPLI) { + draw_dupli_objects(eval_ctx, scene, scene_layer, ar, v3d, base); + } + + draw_object(eval_ctx, scene, scene_layer, ar, v3d, base, 0); + } + } + } + else { + unsigned int lay_used = 0; + + /* then draw not selected and the duplis, but skip editmode object */ + for (base = scene_layer->object_bases.first; base; base = base->next) { + lay_used |= base->lay; + + if ((base->flag & BASE_VISIBLED) != 0) { + + /* dupli drawing */ + if (base->object->transflag & OB_DUPLI) { + draw_dupli_objects(eval_ctx, scene, scene_layer, ar, v3d, base); + } + if ((base->flag & BASE_SELECTED) == 0) { + if (base->object != scene->obedit) + draw_object(eval_ctx, scene, scene_layer, ar, v3d, base, 0); + } + } + } + + /* mask out localview */ + v3d->lay_used = lay_used & ((1 << 20) - 1); + + /* draw selected and editmode */ + for (base = scene_layer->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_VISIBLED) != 0) { + if (base->object == scene->obedit || (base->flag & BASE_SELECTED)) { + draw_object(eval_ctx, scene, scene_layer, ar, v3d, base, 0); + } + } + } + } + + /* perspective floor goes last to use scene depth and avoid writing to depth buffer */ + if (draw_grids_after) { + VP_legacy_drawfloor(scene, v3d, grid_unit, false); + } + + /* must be before xray draw which clears the depth buffer */ + if (v3d->flag2 & V3D_SHOW_GPENCIL) { + wmWindowManager *wm = (C != NULL) ? CTX_wm_manager(C) : NULL; + + /* must be before xray draw which clears the depth buffer */ + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); + ED_gpencil_draw_view3d(wm, scene, scene_layer, v3d, ar, true); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + } + + /* transp and X-ray afterdraw stuff */ + if (v3d->afterdraw_transp.first) view3d_draw_transp(eval_ctx, scene, scene_layer, ar, v3d); + + /* always do that here to cleanup depth buffers if none needed */ + if (fx) { + do_composite_xray = v3d->zbuf && (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first); + GPU_fx_compositor_setup_XRay_pass(fx, do_composite_xray); + } + + if (v3d->afterdraw_xray.first) view3d_draw_xray(eval_ctx, scene, scene_layer, ar, v3d, &xrayclear); + if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(eval_ctx, scene, scene_layer, ar, v3d, xrayclear); + + if (fx && do_composite_xray) { + GPU_fx_compositor_XRay_resolve(fx); + } + + if (!draw_offscreen) { + ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); + } + + if (rv3d->rflag & RV3D_CLIPPING) + ED_view3d_clipping_disable(); + + /* important to do after clipping */ + if (do_bgpic) { + view3d_draw_bgpic_test(scene, ar, v3d, true, do_camera_frame); + } + + /* cleanup */ + if (v3d->zbuf) { + v3d->zbuf = false; + glDisable(GL_DEPTH_TEST); + } + + if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + GPU_free_images_old(); + } +} + +/** + * Store values from #RegionView3D, set when drawing. + * This is needed when we draw with to a viewport using a different matrix (offscreen drawing for example). + * + * Values set by #ED_view3d_update_viewmat should be handled here. + */ +struct RV3DMatrixStore { + float winmat[4][4]; + float viewmat[4][4]; + float viewinv[4][4]; + float persmat[4][4]; + float persinv[4][4]; + float viewcamtexcofac[4]; + float pixsize; +}; + +struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d) +{ + struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__); + copy_m4_m4(rv3dmat->winmat, rv3d->winmat); + copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat); + copy_m4_m4(rv3dmat->persmat, rv3d->persmat); + copy_m4_m4(rv3dmat->persinv, rv3d->persinv); + copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv); + copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac); + rv3dmat->pixsize = rv3d->pixsize; + return (void *)rv3dmat; +} + +void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat_pt) +{ + struct RV3DMatrixStore *rv3dmat = rv3dmat_pt; + copy_m4_m4(rv3d->winmat, rv3dmat->winmat); + copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat); + copy_m4_m4(rv3d->persmat, rv3dmat->persmat); + copy_m4_m4(rv3d->persinv, rv3dmat->persinv); + copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv); + copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac); + rv3d->pixsize = rv3dmat->pixsize; +} + +/** + * \note The info that this uses is updated in #ED_refresh_viewport_fps, + * which currently gets called during #SCREEN_OT_animation_step. + */ +void ED_scene_draw_fps(Scene *scene, const rcti *rect) +{ + ScreenFrameRateInfo *fpsi = scene->fps_info; + char printable[16]; + + if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) + return; + + printable[0] = '\0'; + +#if 0 + /* this is too simple, better do an average */ + fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime)) +#else + fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime)); + + float fps = 0.0f; + int tot = 0; + for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) { + if (fpsi->redrawtimes_fps[i]) { + fps += fpsi->redrawtimes_fps[i]; + tot++; + } + } + if (tot) { + fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE; + + //fpsi->redrawtime_index++; + //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE) + // fpsi->redrawtime = 0; + + fps = fps / tot; + } +#endif + + const int font_id = BLF_default(); + + /* is this more than half a frame behind? */ + if (fps + 0.5f < (float)(FPS)) { + UI_FontThemeColor(font_id, TH_REDALERT); + BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps); + } + else { + UI_FontThemeColor(font_id, TH_TEXT_HI); + BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f)); + } + +#ifdef WITH_INTERNATIONAL + BLF_draw_default(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable)); +#else + BLF_draw_default_ascii(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable)); +#endif +} + +static bool view3d_main_region_do_render_draw(const Scene *scene) +{ + RenderEngineType *type = RE_engines_find(scene->view_render.engine_id); + return (type && type->view_update && type->render_to_view); +} + +bool ED_view3d_calc_render_border(const Scene *scene, View3D *v3d, ARegion *ar, rcti *rect) +{ + RegionView3D *rv3d = ar->regiondata; + bool use_border; + + /* test if there is a 3d view rendering */ + if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene)) + return false; + + /* test if there is a border render */ + if (rv3d->persp == RV3D_CAMOB) + use_border = (scene->r.mode & R_BORDER) != 0; + else + use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0; + + if (!use_border) + return false; + + /* compute border */ + if (rv3d->persp == RV3D_CAMOB) { + rctf viewborder; + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false); + + rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); + rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); + rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); + rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); + } + else { + rect->xmin = v3d->render_border.xmin * ar->winx; + rect->xmax = v3d->render_border.xmax * ar->winx; + rect->ymin = v3d->render_border.ymin * ar->winy; + rect->ymax = v3d->render_border.ymax * ar->winy; + } + + BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin); + BLI_rcti_isect(&ar->winrct, rect, rect); + + return true; +} + +/** + * IMPORTANT: this is deprecated, any changes made in this function should + * be mirrored in view3d_draw_render_draw() in view3d_draw.c + */ +static bool view3d_main_region_draw_engine( + const bContext *C, const EvaluationContext *eval_ctx, Scene *scene, + ARegion *ar, View3D *v3d, + bool clip_border, const rcti *border_rect) +{ + RegionView3D *rv3d = ar->regiondata; + RenderEngineType *type; + GLint scissor[4]; + + + /* create render engine */ + if (!rv3d->render_engine) { + RenderEngine *engine; + type = RE_engines_find(scene->view_render.engine_id); + + if (!(type->view_update && type->render_to_view)) + return false; + + engine = RE_engine_create_ex(type, true); + + engine->tile_x = scene->r.tilex; + engine->tile_y = scene->r.tiley; + + type->view_update(engine, C); + + rv3d->render_engine = engine; + } + + /* setup view matrices */ + VP_legacy_view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, NULL, NULL); + + /* background draw */ + ED_region_pixelspace(ar); + + if (clip_border) { + /* for border draw, we only need to clear a subset of the 3d view */ + if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) { + glGetIntegerv(GL_SCISSOR_BOX, scissor); + glScissor(border_rect->xmin, border_rect->ymin, + BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect)); + } + else { + return false; + } + } + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + bool show_image = false; + { + Camera *cam = ED_view3d_camera_data_get(v3d, rv3d); + if (cam->flag & CAM_SHOW_BG_IMAGE) { + show_image = true; + view3d_draw_bgpic_test(scene, ar, v3d, false, true); + } + else { + imm_draw_box_checker_2d(0, 0, ar->winx, ar->winy); + } + } + + if (show_image) { + view3d_draw_bgpic_test(scene, ar, v3d, false, true); + } + else { + imm_draw_box_checker_2d(0, 0, ar->winx, ar->winy); + } + + /* render result draw */ + type = rv3d->render_engine->type; + type->render_to_view(rv3d->render_engine, C); + + if (show_image) { + view3d_draw_bgpic_test(scene, ar, v3d, true, true); + } + + if (clip_border) { + /* restore scissor as it was before */ + glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); + } + + return true; +} + +static void view3d_main_region_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ARegion *ar, bool render_border) +{ + float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f}; + + if (!rv3d->render_engine || !rv3d->render_engine->text[0]) + return; + + if (render_border) { + /* draw darkened background color. no alpha because border render does + * partial redraw and will not redraw the region behind this info bar */ + float alpha = 1.0f - fill_color[3]; + Camera *camera = ED_view3d_camera_data_get(v3d, rv3d); + + if (camera) { + if (camera->flag & CAM_SHOWPASSEPARTOUT) { + alpha *= (1.0f - camera->passepartalpha); + } + } + + UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color); + mul_v3_fl(fill_color, alpha); + fill_color[3] = 1.0f; + } + + ED_region_info_draw(ar, rv3d->render_engine->text, fill_color, true); +} + +#ifdef WITH_GAMEENGINE +static void update_lods(Scene *scene, float camera_pos[3]) +{ + Scene *sce_iter; + Base *base; + + for (SETLOOPER(scene, sce_iter, base)) { + Object *ob = base->object; + BKE_object_lod_update(ob, camera_pos); + } +} +#endif + +static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, SceneLayer *sl, View3D *v3d, + ARegion *ar, const char **grid_unit) +{ + wmWindow *win = CTX_wm_window(C); + EvaluationContext eval_ctx; + RegionView3D *rv3d = ar->regiondata; + unsigned int lay_used = v3d->lay_used; + + CTX_data_eval_ctx(C, &eval_ctx); + + /* post processing */ + bool do_compositing = false; + + /* shadow buffers, before we setup matrices */ + if (draw_glsl_material(scene, sl, NULL, v3d, v3d->drawtype)) + gpu_update_lamps_shadows_world(&eval_ctx, scene, v3d); + + /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */ + if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) { + rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE; + GPU_default_lights(); + } + + /* setup the view matrix */ + if (VP_legacy_view3d_stereo3d_active(win, scene, v3d, rv3d)) { + VP_legacy_view3d_stereo3d_setup(&eval_ctx, scene, v3d, ar); + } + else { + VP_legacy_view3d_main_region_setup_view(&eval_ctx, scene, v3d, ar, NULL, NULL); + } + + rv3d->rflag &= ~RV3D_IS_GAME_ENGINE; +#ifdef WITH_GAMEENGINE + if (STREQ(scene->view_render.engine_id, RE_engine_id_BLENDER_GAME)) { + rv3d->rflag |= RV3D_IS_GAME_ENGINE; + + /* Make sure LoDs are up to date */ + update_lods(scene, rv3d->viewinv[3]); + } +#endif + + /* framebuffer fx needed, we need to draw offscreen first */ + if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) { + BKE_screen_gpu_fx_validate(&v3d->fx_settings); + GPUFXSettings fx_settings = v3d->fx_settings; + if (!rv3d->compositor) + rv3d->compositor = GPU_fx_compositor_create(); + + if (rv3d->persp == RV3D_CAMOB && v3d->camera) + BKE_camera_to_gpu_dof(v3d->camera, &fx_settings); + else { + fx_settings.dof = NULL; + } + + do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings); + } + + /* enables anti-aliasing for 3D view drawing */ + if (win->multisamples != USER_MULTISAMPLE_NONE) { + glEnable(GL_MULTISAMPLE); + } + + /* main drawing call */ + view3d_draw_objects(C, &eval_ctx, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL); + + /* draw depth culled manipulators - manipulators need to be updated *after* view matrix was set up */ + /* TODO depth culling manipulators is not yet supported, just drawing _3D here, should + * later become _IN_SCENE (and draw _3D separate) */ + WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_3D); + + /* post process */ + if (do_compositing) { + GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL); + } + + /* Disable back anti-aliasing */ + if (win->multisamples != USER_MULTISAMPLE_NONE) { + glDisable(GL_MULTISAMPLE); + } + + if (v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */ + /* find header and force tag redraw */ + ScrArea *sa = CTX_wm_area(C); + ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER); + ED_region_tag_redraw(ar_header); /* can be NULL */ + } + + if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + BDR_drawSketch(C); + } +} + +static void view3d_main_region_draw_info(const bContext *C, Scene *scene, + ARegion *ar, View3D *v3d, + const char *grid_unit, bool render_border) +{ + SceneLayer *scene_layer = CTX_data_scene_layer(C); + wmWindowManager *wm = CTX_wm_manager(C); + RegionView3D *rv3d = ar->regiondata; + rcti rect; + + /* local coordinate visible rect inside region, to accomodate overlapping ui */ + ED_region_visible_rect(ar, &rect); + + if (rv3d->persp == RV3D_CAMOB) { + VP_drawviewborder(scene, ar, v3d); + } + else if (v3d->flag2 & V3D_RENDER_BORDER) { + VP_drawrenderborder(ar, v3d); + } + + if (v3d->flag2 & V3D_SHOW_GPENCIL) { + /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */ + ED_gpencil_draw_view3d(wm, scene, scene_layer, v3d, ar, false); + } + + if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + VP_legacy_drawcursor(scene, scene_layer, ar, v3d); /* 3D cursor */ + + if (U.uiflag & USER_SHOW_ROTVIEWICON) + VP_legacy_draw_view_axis(rv3d, &rect); + else + draw_view_icon(rv3d, &rect); + + if (U.uiflag & USER_DRAWVIEWINFO) { + Object *ob = OBACT(scene_layer); + VP_legacy_draw_selected_name(scene, ob, &rect); + } + } + + if (rv3d->render_engine) { + view3d_main_region_draw_engine_info(v3d, rv3d, ar, render_border); + return; + } + + if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) { + ED_scene_draw_fps(scene, &rect); + } + else if (U.uiflag & USER_SHOW_VIEWPORTNAME) { + VP_legacy_draw_viewport_name(ar, v3d, &rect); + } + + if (grid_unit) { /* draw below the viewport name */ + char numstr[32] = ""; + + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); + if (v3d->grid != 1.0f) { + BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); + } + + BLF_draw_default_ascii(rect.xmin + U.widget_unit, + rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f, + numstr[0] ? numstr : grid_unit, sizeof(numstr)); + } + } +} + +void view3d_main_region_draw_legacy(const bContext *C, ARegion *ar) +{ + EvaluationContext eval_ctx; + Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); + View3D *v3d = CTX_wm_view3d(C); + const char *grid_unit = NULL; + rcti border_rect; + + /* if we only redraw render border area, skip opengl draw and also + * don't do scissor because it's already set */ + bool render_border = ED_view3d_calc_render_border(scene, v3d, ar, &border_rect); + bool clip_border = (render_border && !BLI_rcti_compare(&ar->drawrct, &border_rect)); + + gpuPushProjectionMatrix(); + gpuLoadIdentityProjectionMatrix(); + gpuPushMatrix(); + gpuLoadIdentity(); + + CTX_data_eval_ctx(C, &eval_ctx); + + /* draw viewport using opengl */ + if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene) || clip_border) { + VP_view3d_main_region_clear(scene, v3d, ar); /* background */ + view3d_main_region_draw_objects(C, scene, sl, v3d, ar, &grid_unit); + + if (G.debug & G_DEBUG_SIMDATA) + draw_sim_debug_data(scene, v3d, ar); + + glDisable(GL_DEPTH_TEST); + ED_region_pixelspace(ar); + } + + /* draw viewport using external renderer */ + if (v3d->drawtype == OB_RENDER) { + view3d_main_region_draw_engine(C, &eval_ctx, scene, ar, v3d, clip_border, &border_rect); + } + + VP_legacy_view3d_main_region_setup_view(&eval_ctx, scene, v3d, ar, NULL, NULL); + glClear(GL_DEPTH_BUFFER_BIT); + + ED_region_pixelspace(ar); + + WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_2D); + + view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border); + + gpuPopProjectionMatrix(); + gpuPopMatrix(); + + v3d->flag |= V3D_INVALID_BACKBUF; + + BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_transp)); + BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xray)); + BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xraytransp)); +} + + +/* -------------------------------------------------------------------- */ + +/** \name Deprecated Interface + * + * New viewport sometimes has a check for new/old viewport code. + * Use these functions so new viewport can *optionally* call. + * + * \{ */ + + +void VP_deprecated_view3d_draw_objects( + const bContext *C, + const EvaluationContext *eval_ctx, + Scene *scene, View3D *v3d, ARegion *ar, + const char **grid_unit, + const bool do_bgpic, const bool draw_offscreen, GPUFX *fx) +{ + view3d_draw_objects(C, eval_ctx, scene, v3d, ar, grid_unit, do_bgpic, draw_offscreen, fx); +} + +void VP_deprecated_gpu_update_lamps_shadows_world(const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d) +{ + gpu_update_lamps_shadows_world(eval_ctx, scene, v3d); +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 5203e0617ee..dc6d6382d37 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -34,6 +34,7 @@ #include <float.h> #include "DNA_armature_types.h" +#include "DNA_camera_types.h" #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -51,6 +52,7 @@ #include "BKE_camera.h" #include "BKE_context.h" #include "BKE_font.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_object.h" #include "BKE_paint.h" @@ -58,11 +60,10 @@ #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_action.h" -#include "BKE_depsgraph.h" /* for ED_view3d_camera_lock_sync */ +#include "DEG_depsgraph.h" #include "BIF_gl.h" -#include "BIF_glutil.h" #include "WM_api.h" #include "WM_types.h" @@ -79,6 +80,8 @@ #include "ED_gpencil.h" #include "ED_view3d.h" +#include "DEG_depsgraph_query.h" + #include "UI_resources.h" #include "PIL_time.h" /* smoothview */ @@ -163,7 +166,7 @@ bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d) ob_update = v3d->camera; while (ob_update) { - DAG_id_tag_update(&ob_update->id, OB_RECALC_OB); + DEG_id_tag_update(&ob_update->id, OB_RECALC_OB); WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, ob_update); ob_update = ob_update->parent; } @@ -175,7 +178,7 @@ bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d) ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist); BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag | protect_scale_all); - DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); + DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->camera); } @@ -621,7 +624,8 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) bool is_set = false; Scene *scene = CTX_data_scene(C); - Object *ob_act = OBACT; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob_act = OBACT(sl); if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) && /* with weight-paint + pose-mode, fall through to using calculateTransformCenter */ @@ -658,14 +662,13 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) } else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) { /* object mode use boundbox centers */ - View3D *v3d = CTX_wm_view3d(C); Base *base; unsigned int tot = 0; float select_center[3]; zero_v3(select_center); - for (base = FIRSTBASE; base; base = base->next) { - if (TESTBASE(v3d, base)) { + for (base = FIRSTBASE(sl); base; base = base->next) { + if (TESTBASE(base)) { /* use the boundbox if we can */ Object *ob = base->object; @@ -741,14 +744,18 @@ static void viewops_data_create_ex( /* we need the depth info before changing any viewport options */ if (orbit_mode & VIEWOPS_ORBIT_DEPTH) { + EvaluationContext eval_ctx; + struct Depsgraph *graph = CTX_data_depsgraph(C); float fallback_depth_pt[3]; + CTX_data_eval_ctx(C, &eval_ctx); + view3d_operator_needs_opengl(C); /* needed for zbuf drawing */ negate_v3_v3(fallback_depth_pt, rv3d->ofs); vod->use_dyn_ofs = ED_view3d_autodist( - vod->scene, vod->ar, vod->v3d, + &eval_ctx, graph, vod->ar, vod->v3d, event->mval, vod->dyn_ofs, true, fallback_depth_pt); } else { @@ -866,8 +873,9 @@ static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *even static void viewops_data_free(bContext *C, wmOperator *op) { ARegion *ar; +#if 0 Paint *p = BKE_paint_get_active_from_context(C); - +#endif if (op->customdata) { ViewOpsData *vod = op->customdata; ar = vod->ar; @@ -883,7 +891,9 @@ static void viewops_data_free(bContext *C, wmOperator *op) ar = CTX_wm_region(C); } +#if 0 if (p && (p->flags & PAINT_FAST_NAVIGATE)) +#endif ED_region_tag_redraw(ar); } /** \} */ @@ -2980,6 +2990,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Base *base; float *curs; const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions"); @@ -3003,8 +3014,8 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in INIT_MINMAX(min, max); } - for (base = scene->base.first; base; base = base->next) { - if (BASE_VISIBLE(v3d, base)) { + for (base = sl->object_bases.first; base; base = base->next) { + if (BASE_VISIBLE(base)) { changed = true; if (skip_camera && base->object == v3d->camera) { @@ -3064,9 +3075,12 @@ static int viewselected_exec(bContext *C, wmOperator *op) ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); bGPdata *gpd = CTX_data_gpencil_data(C); const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)); - Object *ob = OBACT; + const bool is_face_map = ((is_gp_edit == false) && ar->manipulator_map && + WM_manipulatormap_is_any_selected(ar->manipulator_map)); + Object *ob = OBACT(sl); Object *obedit = CTX_data_edit_object(C); float min[3], max[3]; bool ok = false, ok_dist = true; @@ -3077,8 +3091,7 @@ static int viewselected_exec(bContext *C, wmOperator *op) const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); INIT_MINMAX(min, max); - - if (is_gp_edit) { + if (is_gp_edit || is_face_map) { ob = NULL; } @@ -3086,8 +3099,8 @@ static int viewselected_exec(bContext *C, wmOperator *op) /* hard-coded exception, we look for the one selected armature */ /* this is weak code this way, we should make a generic active/selection callback interface once... */ Base *base; - for (base = scene->base.first; base; base = base->next) { - if (TESTBASELIB(v3d, base)) { + for (base = sl->object_bases.first; base; base = base->next) { + if (TESTBASELIB(base)) { if (base->object->type == OB_ARMATURE) if (base->object->mode & OB_MODE_POSE) break; @@ -3110,6 +3123,9 @@ static int viewselected_exec(bContext *C, wmOperator *op) } CTX_DATA_END; } + else if (is_face_map) { + ok = WM_manipulatormap_minmax(ar->manipulator_map, true, true, min, max); + } else if (obedit) { ok = ED_view3d_minmax_verts(obedit, min, max); /* only selected */ } @@ -3120,7 +3136,7 @@ static int viewselected_exec(bContext *C, wmOperator *op) ok = paintface_minmax(ob, min, max); } else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { - ok = PE_minmax(scene, min, max); + ok = PE_minmax(scene, sl, min, max); } else if (ob && (ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) @@ -3132,8 +3148,8 @@ static int viewselected_exec(bContext *C, wmOperator *op) } else { Base *base; - for (base = FIRSTBASE; base; base = base->next) { - if (TESTBASE(v3d, base)) { + for (base = FIRSTBASE(sl); base; base = base->next) { + if (TESTBASE(base)) { if (skip_camera && base->object == v3d->camera) { continue; @@ -3310,18 +3326,21 @@ static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *ev { View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); - Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); if (rv3d) { + EvaluationContext eval_ctx; + struct Depsgraph *graph = CTX_data_depsgraph(C); float new_ofs[3]; const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + CTX_data_eval_ctx(C, &eval_ctx); + ED_view3d_smooth_view_force_finish(C, v3d, ar); view3d_operator_needs_opengl(C); - if (ED_view3d_autodist(scene, ar, v3d, event->mval, new_ofs, false, NULL)) { + if (ED_view3d_autodist(&eval_ctx, graph, ar, v3d, event->mval, new_ofs, false, NULL)) { /* pass */ } else { @@ -3576,10 +3595,10 @@ void VIEW3D_OT_clear_render_border(wmOperatorType *ot) static int view3d_zoom_border_exec(bContext *C, wmOperator *op) { + EvaluationContext eval_ctx; ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); - Scene *scene = CTX_data_scene(C); const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); /* Zooms in on a border drawn by the user */ @@ -3592,13 +3611,14 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) float new_ofs[3]; /* ZBuffer depth vars */ - bglMats mats; float depth_close = FLT_MAX; - double cent[2], p[3]; + float p[3]; /* note; otherwise opengl won't work */ view3d_operator_needs_opengl(C); + CTX_data_eval_ctx(C, &eval_ctx); + /* get border select values using rna */ WM_operator_properties_border_to_rcti(op, &rect); @@ -3608,8 +3628,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) ED_view3d_dist_range_get(v3d, dist_range); /* Get Z Depths, needed for perspective, nice for ortho */ - bgl_get_mats(&mats); - ED_view3d_draw_depth(scene, ar, v3d, true); + ED_view3d_draw_depth(&eval_ctx, CTX_data_depsgraph(C), ar, v3d, true); { /* avoid allocating the whole depth buffer */ @@ -3624,11 +3643,11 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) MEM_SAFE_FREE(depth_temp.depths); } - cent[0] = (((double)rect.xmin) + ((double)rect.xmax)) / 2; - cent[1] = (((double)rect.ymin) + ((double)rect.ymax)) / 2; + float centx = (((float)rect.xmin) + ((float)rect.xmax)) / 2; + float centy = (((float)rect.ymin) + ((float)rect.ymax)) / 2; if (rv3d->is_persp) { - double p_corner[3]; + float p_corner[3]; /* no depths to use, we cant do anything! */ if (depth_close == FLT_MAX) { @@ -3636,23 +3655,14 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } /* convert border to 3d coordinates */ - if ((!gluUnProject(cent[0], cent[1], depth_close, - mats.modelview, mats.projection, (GLint *)mats.viewport, - &p[0], &p[1], &p[2])) || - (!gluUnProject((double)rect.xmin, (double)rect.ymin, depth_close, - mats.modelview, mats.projection, (GLint *)mats.viewport, - &p_corner[0], &p_corner[1], &p_corner[2]))) + if ((!ED_view3d_unproject(ar, centx, centy, depth_close, p)) || + (!ED_view3d_unproject(ar, rect.xmin, rect.ymin, depth_close, p_corner))) { return OPERATOR_CANCELLED; } - dvec[0] = p[0] - p_corner[0]; - dvec[1] = p[1] - p_corner[1]; - dvec[2] = p[2] - p_corner[2]; - - new_ofs[0] = -p[0]; - new_ofs[1] = -p[1]; - new_ofs[2] = -p[2]; + sub_v3_v3v3(dvec, p, p_corner); + negate_v3_v3(new_ofs, p); new_dist = len_v3(dvec); @@ -3667,13 +3677,8 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) new_dist = rv3d->dist; /* convert the drawn rectangle into 3d space */ - if (depth_close != FLT_MAX && gluUnProject(cent[0], cent[1], depth_close, - mats.modelview, mats.projection, (GLint *)mats.viewport, - &p[0], &p[1], &p[2])) - { - new_ofs[0] = -p[0]; - new_ofs[1] = -p[1]; - new_ofs[2] = -p[2]; + if (depth_close != FLT_MAX && ED_view3d_unproject(ar, centx, centy, depth_close, p)) { + negate_v3_v3(new_ofs, p); } else { float mval_f[2]; @@ -3910,6 +3915,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op) ARegion *ar; RegionView3D *rv3d; Scene *scene = CTX_data_scene(C); + SceneLayer *scene_layer = CTX_data_scene_layer(C); static int perspo = RV3D_PERSP; int viewnum, nextperspo; bool align_active; @@ -3944,7 +3950,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op) /* lastview - */ if (rv3d->persp != RV3D_CAMOB) { - Object *ob = OBACT; + Object *ob = OBACT(scene_layer); if (!rv3d->smooth_timer) { /* store settings of current view before allowing overwriting with camera view @@ -3979,7 +3985,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op) v3d->camera = ob; if (v3d->camera == NULL) - v3d->camera = BKE_scene_camera_find(scene); + v3d->camera = BKE_scene_layer_camera_find(scene_layer); /* couldnt find any useful camera, bail out */ if (v3d->camera == NULL) @@ -4511,11 +4517,11 @@ void VIEW3D_OT_navigate(wmOperatorType *ot) /* ******************** add background image operator **************** */ -static BGpic *background_image_add(bContext *C) +static CameraBGImage *background_image_add(bContext *C) { - View3D *v3d = CTX_wm_view3d(C); + Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; - return ED_view3D_background_image_new(v3d); + return BKE_camera_background_image_new(cam); } static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op)) @@ -4527,9 +4533,9 @@ static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op)) static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - View3D *v3d = CTX_wm_view3d(C); + Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; Image *ima; - BGpic *bgpic; + CameraBGImage *bgpic; ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM); /* may be NULL, continue anyway */ @@ -4537,10 +4543,10 @@ static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEven bgpic = background_image_add(C); bgpic->ima = ima; - v3d->flag |= V3D_DISPBGPICS; - - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); - + cam->flag |= CAM_SHOW_BG_IMAGE; + + WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam); + return OPERATOR_FINISHED; } @@ -4556,7 +4562,7 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot) /* api callbacks */ ot->invoke = background_image_add_invoke; ot->exec = background_image_add_exec; - ot->poll = ED_operator_view3d_active; + ot->poll = ED_operator_camera; /* flags */ ot->flag = OPTYPE_UNDO; @@ -4572,21 +4578,22 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot) /* ***** remove image operator ******* */ static int background_image_remove_exec(bContext *C, wmOperator *op) { - View3D *v3d = CTX_wm_view3d(C); + Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; const int index = RNA_int_get(op->ptr, "index"); - BGpic *bgpic_rem = BLI_findlink(&v3d->bgpicbase, index); + CameraBGImage *bgpic_rem = BLI_findlink(&cam->bg_images, index); if (bgpic_rem) { - if (bgpic_rem->source == V3D_BGPIC_IMAGE) { + if (bgpic_rem->source == CAM_BGIMG_SOURCE_IMAGE) { id_us_min((ID *)bgpic_rem->ima); } - else if (bgpic_rem->source == V3D_BGPIC_MOVIE) { + else if (bgpic_rem->source == CAM_BGIMG_SOURCE_MOVIE) { id_us_min((ID *)bgpic_rem->clip); } - ED_view3D_background_image_remove(v3d, bgpic_rem); + BKE_camera_background_image_remove(cam, bgpic_rem); + + WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); return OPERATOR_FINISHED; } else { @@ -4604,7 +4611,7 @@ void VIEW3D_OT_background_image_remove(wmOperatorType *ot) /* api callbacks */ ot->exec = background_image_remove_exec; - ot->poll = ED_operator_view3d_active; + ot->poll = ED_operator_camera; /* flags */ ot->flag = 0; @@ -4638,9 +4645,8 @@ void ED_view3d_clipping_local(RegionView3D *rv3d, float mat[4][4]) static int view3d_clipping_exec(bContext *C, wmOperator *op) { + ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); - ViewContext vc; - bglMats mats; rcti rect; WM_operator_properties_border_to_rcti(op, &rect); @@ -4648,12 +4654,8 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op) rv3d->rflag |= RV3D_CLIPPING; rv3d->clipbb = MEM_callocN(sizeof(BoundBox), "clipbb"); - /* note; otherwise opengl won't work */ - view3d_operator_needs_opengl(C); - - view3d_set_viewcontext(C, &vc); - view3d_get_transformation(vc.ar, vc.rv3d, NULL, &mats); /* NULL because we don't want it in object space */ - ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, &mats, &rect); + /* NULL object because we don't want it in object space */ + ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, ar, NULL, &rect); return OPERATOR_FINISHED; } @@ -4705,7 +4707,6 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot) /* note: cannot use event->mval here (called by object_add() */ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2]) { - Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = ar->regiondata; @@ -4727,9 +4728,15 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2]) } if (U.uiflag & USER_ZBUF_CURSOR) { /* maybe this should be accessed some other way */ + EvaluationContext eval_ctx; + struct Depsgraph *graph = CTX_data_depsgraph(C); + + CTX_data_eval_ctx(C, &eval_ctx); + view3d_operator_needs_opengl(C); - if (ED_view3d_autodist(scene, ar, v3d, mval, fp, true, NULL)) + if (ED_view3d_autodist(&eval_ctx, graph, ar, v3d, mval, fp, true, NULL)) { depth_used = true; + } } if (depth_used == false) { @@ -4808,45 +4815,6 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot) /* ***************** manipulator op ******************* */ - -static int manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - View3D *v3d = CTX_wm_view3d(C); - - if (!(v3d->twflag & V3D_USE_MANIPULATOR)) return OPERATOR_PASS_THROUGH; - if (!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return OPERATOR_PASS_THROUGH; - - /* note; otherwise opengl won't work */ - view3d_operator_needs_opengl(C); - - if (BIF_do_manipulator(C, event, op) == 0) - return OPERATOR_PASS_THROUGH; - - return OPERATOR_FINISHED; -} - -void VIEW3D_OT_manipulator(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name = "3D Manipulator"; - ot->description = "Manipulate selected item by axis"; - ot->idname = "VIEW3D_OT_manipulator"; - - /* api callbacks */ - ot->invoke = manipulator_invoke; - - ot->poll = ED_operator_view3d_active; - - /* properties to pass to transform */ - Transform_Properties(ot, P_CONSTRAINT); - - prop = RNA_def_boolean(ot->srna, "use_planar_constraint", false, "Planar Constraint", "Limit the transformation to the " - "two axes that have not been clicked (translate/scale only)"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); -} - static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { View3D *v3d = CTX_wm_view3d(C); @@ -4950,22 +4918,17 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg * \param fallback_depth_pt: Use this points depth when no depth can be found. */ bool ED_view3d_autodist( - Scene *scene, ARegion *ar, View3D *v3d, + const EvaluationContext *eval_ctx, struct Depsgraph *graph, ARegion *ar, View3D *v3d, const int mval[2], float mouse_worldloc[3], const bool alphaoverride, const float fallback_depth_pt[3]) { - bglMats mats; /* ZBuffer depth vars */ float depth_close; - double cent[2], p[3]; int margin_arr[] = {0, 2, 4}; int i; bool depth_ok = false; /* Get Z Depths, needed for perspective, nice for ortho */ - ED_view3d_draw_depth(scene, ar, v3d, alphaoverride); - - /* call after in case settings have been modified since last drawing, see: T47089 */ - bgl_get_mats(&mats); + ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, alphaoverride); /* Attempt with low margin's first */ i = 0; @@ -4975,15 +4938,10 @@ bool ED_view3d_autodist( } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr))); if (depth_ok) { - cent[0] = (double)mval[0] + 0.5; - cent[1] = (double)mval[1] + 0.5; + float centx = (float)mval[0] + 0.5f; + float centy = (float)mval[1] + 0.5f; - if (gluUnProject(cent[0], cent[1], depth_close, - mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) - { - mouse_worldloc[0] = (float)p[0]; - mouse_worldloc[1] = (float)p[1]; - mouse_worldloc[2] = (float)p[2]; + if (ED_view3d_unproject(ar, centx, centy, depth_close, mouse_worldloc)) { return true; } } @@ -4997,16 +4955,21 @@ bool ED_view3d_autodist( } } -void ED_view3d_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) +void ED_view3d_autodist_init( + const EvaluationContext *eval_ctx, struct Depsgraph *graph, + ARegion *ar, View3D *v3d, int mode) { /* Get Z Depths, needed for perspective, nice for ortho */ switch (mode) { case 0: - ED_view3d_draw_depth(scene, ar, v3d, true); + ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, true); break; case 1: - ED_view3d_draw_depth_gpencil(scene, ar, v3d); + { + Scene *scene = DEG_get_evaluated_scene(graph); + ED_view3d_draw_depth_gpencil(eval_ctx, scene, ar, v3d); break; + } } } @@ -5014,9 +4977,7 @@ void ED_view3d_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth) { - bglMats mats; /* ZBuffer depth vars, could cache? */ float depth; - double cent[2], p[3]; /* Get Z Depths, needed for perspective, nice for ortho */ if (force_depth) @@ -5027,21 +4988,9 @@ bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_world if (depth == FLT_MAX) return false; - cent[0] = (double)mval[0] + 0.5; - cent[1] = (double)mval[1] + 0.5; - - bgl_get_mats(&mats); - - if (!gluUnProject(cent[0], cent[1], depth, - mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) - { - return false; - } - - mouse_worldloc[0] = (float)p[0]; - mouse_worldloc[1] = (float)p[1]; - mouse_worldloc[2] = (float)p[2]; - return true; + float centx = (float)mval[0] + 0.5f; + float centy = (float)mval[1] + 0.5f; + return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc); } bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth) @@ -5223,6 +5172,7 @@ void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], const float dist) { float mat[4][4]; + ED_view3d_to_m4(mat, ofs, quat, dist); BKE_object_apply_mat4(ob, mat, true, true); } @@ -5239,43 +5189,6 @@ void ED_view3d_lastview_store(RegionView3D *rv3d) } } -BGpic *ED_view3D_background_image_new(View3D *v3d) -{ - BGpic *bgpic = MEM_callocN(sizeof(BGpic), "Background Image"); - - bgpic->rotation = 0.0f; - bgpic->size = 5.0f; - bgpic->blend = 0.5f; - bgpic->iuser.fie_ima = 2; - bgpic->iuser.ok = 1; - bgpic->view = 0; /* 0 for all */ - bgpic->flag |= V3D_BGPIC_EXPANDED; - - BLI_addtail(&v3d->bgpicbase, bgpic); - - return bgpic; -} - -void ED_view3D_background_image_remove(View3D *v3d, BGpic *bgpic) -{ - BLI_remlink(&v3d->bgpicbase, bgpic); - - MEM_freeN(bgpic); -} - -void ED_view3D_background_image_clear(View3D *v3d) -{ - BGpic *bgpic = v3d->bgpicbase.first; - - while (bgpic) { - BGpic *next_bgpic = bgpic->next; - - ED_view3D_background_image_remove(v3d, bgpic); - - bgpic = next_bgpic; - } -} - void ED_view3D_lock_clear(View3D *v3d) { v3d->ob_centre = NULL; diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index eda780d01a7..5e7eddb1c22 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -56,6 +56,8 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "GPU_immediate.h" + #include "view3d_intern.h" /* own include */ /* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ @@ -257,36 +259,45 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), x2 = xoff + 0.55f * fly->width; y2 = yoff + 0.55f * fly->height; - UI_ThemeColor(TH_VIEW_OVERLAY); - glBegin(GL_LINES); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColor(TH_VIEW_OVERLAY); + + immBegin(GWN_PRIM_LINES, 16); + /* bottom left */ - glVertex2f(x1, y1); - glVertex2f(x1, y1 + 5); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x1, y1 + 5); - glVertex2f(x1, y1); - glVertex2f(x1 + 5, y1); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x1 + 5, y1); /* top right */ - glVertex2f(x2, y2); - glVertex2f(x2, y2 - 5); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x2, y2 - 5); - glVertex2f(x2, y2); - glVertex2f(x2 - 5, y2); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x2 - 5, y2); /* top left */ - glVertex2f(x1, y2); - glVertex2f(x1, y2 - 5); + immVertex2f(pos, x1, y2); + immVertex2f(pos, x1, y2 - 5); - glVertex2f(x1, y2); - glVertex2f(x1 + 5, y2); + immVertex2f(pos, x1, y2); + immVertex2f(pos, x1 + 5, y2); /* bottom right */ - glVertex2f(x2, y1); - glVertex2f(x2, y1 + 5); + immVertex2f(pos, x2, y1); + immVertex2f(pos, x2, y1 + 5); + + immVertex2f(pos, x2, y1); + immVertex2f(pos, x2 - 5, y1); - glVertex2f(x2, y1); - glVertex2f(x2 - 5, y1); - glEnd(); + immEnd(); + immUnbindProgram(); } static void fly_update_header(bContext *C, wmOperator *op, FlyInfo *fly) @@ -406,7 +417,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent } fly->v3d_camera_control = ED_view3d_cameracontrol_acquire( - fly->scene, fly->v3d, fly->rv3d, + C, fly->scene, fly->v3d, fly->rv3d, (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); /* calculate center */ diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 11dc4d10f2a..4f322b8519d 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -41,11 +41,12 @@ #include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_screen.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -71,11 +72,10 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event); /* XXX quickly ported across */ static void handle_view3d_lock(bContext *C) { - Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ScrArea *sa = CTX_wm_area(C); View3D *v3d = CTX_wm_view3d(C); - + if (v3d != NULL && sa != NULL) { if (v3d->localvd == NULL && v3d->scenelock && sa->spacetype == SPACE_VIEW3D) { /* copy to scene */ @@ -83,10 +83,6 @@ static void handle_view3d_lock(bContext *C) scene->layact = v3d->layact; scene->camera = v3d->camera; - /* not through notifier, listener don't have context - * and non-open screens or spaces need to be updated too */ - BKE_screen_view3d_main_sync(&bmain->screen, scene); - /* notifiers for scene update */ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); } @@ -172,7 +168,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op) if (v3d->scenelock) handle_view3d_lock(C); - DAG_on_visible_update(CTX_data_main(C), false); + DEG_on_visible_update(CTX_data_main(C), false); ED_area_tag_redraw(sa); @@ -284,15 +280,16 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); ToolSettings *ts = CTX_data_tool_settings(C); PointerRNA v3dptr, toolsptr, sceneptr; - Object *ob = OBACT; + Object *ob = OBACT(sl); Object *obedit = CTX_data_edit_object(C); bGPdata *gpd = CTX_data_gpencil_data(C); uiBlock *block; uiLayout *row; - bool is_paint = false; - int modeselect; + bool is_paint = ob && !(gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) && + ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT); RNA_pointer_create(&screen->id, &RNA_SpaceView3D, v3d, &v3dptr); RNA_pointer_create(&scene->id, &RNA_ToolSettings, ts, &toolsptr); @@ -303,39 +300,6 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) /* other buttons: */ UI_block_emboss_set(block, UI_EMBOSS); - - /* mode */ - if ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)) { - modeselect = OB_MODE_GPENCIL; - } - else if (ob) { - modeselect = ob->mode; - is_paint = ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT); - } - else { - modeselect = OB_MODE_OBJECT; - } - - row = uiLayoutRow(layout, false); - { - const EnumPropertyItem *item = rna_enum_object_mode_items; - const char *name = ""; - int icon = ICON_OBJECT_DATAMODE; - - while (item->identifier) { - if (item->value == modeselect && item->identifier[0]) { - name = IFACE_(item->name); - icon = item->icon; - break; - } - item++; - } - - uiItemMenuEnumO(row, C, "OBJECT_OT_mode_set", "mode", name, icon); - } - - /* Draw type */ - uiItemR(layout, &v3dptr, "viewport_shade", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); row = uiLayoutRow(layout, true); uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); @@ -364,18 +328,13 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) /* Transform widget / manipulators */ row = uiLayoutRow(layout, true); uiItemR(row, &v3dptr, "show_manipulator", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); - if (v3d->twflag & V3D_USE_MANIPULATOR) { + if (v3d->twflag & V3D_MANIPULATOR_DRAW) { uiItemR(row, &v3dptr, "transform_manipulators", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); } uiItemR(row, &v3dptr, "transform_orientation", 0, "", ICON_NONE); } if (obedit == NULL && v3d->localvd == NULL) { - unsigned int ob_lay = ob ? ob->lay : 0; - - /* Layers */ - uiTemplateLayers(layout, v3d->scenelock ? &sceneptr : &v3dptr, "layers", &v3dptr, "layers_used", ob_lay); - /* Scene lock */ uiItemR(layout, &v3dptr, "lock_camera_and_layers", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 7a106a27833..189e22a04d7 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -37,7 +37,9 @@ struct ARegion; struct ARegionType; +struct Base; struct BoundBox; +struct Gwn_Batch; struct DerivedMesh; struct Object; struct SmokeDomainSettings; @@ -46,9 +48,12 @@ struct bContext; struct bMotionPath; struct bPoseChannel; struct Mesh; +struct SceneLayer; struct wmOperatorType; -struct wmWindowManager; struct wmKeyConfig; +struct wmManipulatorGroupType; +struct wmManipulatorType; +struct wmWindowManager; /* drawing flags: */ enum { @@ -99,7 +104,6 @@ void VIEW3D_OT_view_orbit(struct wmOperatorType *ot); void VIEW3D_OT_view_roll(struct wmOperatorType *ot); void VIEW3D_OT_clip_border(struct wmOperatorType *ot); void VIEW3D_OT_cursor3d(struct wmOperatorType *ot); -void VIEW3D_OT_manipulator(struct wmOperatorType *ot); void VIEW3D_OT_enable_manipulator(struct wmOperatorType *ot); void VIEW3D_OT_render_border(struct wmOperatorType *ot); void VIEW3D_OT_clear_render_border(struct wmOperatorType *ot); @@ -142,13 +146,29 @@ void draw_motion_paths_cleanup(View3D *v3d); /* drawobject.c */ -void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, const short dflag); -void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag); - -bool draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const char dt); -void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline); -void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob); -void drawaxes(const float viewmat_local[4][4], float size, char drawtype); +void draw_object( + const struct EvaluationContext *eval_ctx, Scene *scene, struct SceneLayer *sl, struct ARegion *ar, View3D *v3d, + struct Base *base, const short dflag); +void draw_object_select( + const struct EvaluationContext *eval_ctx, Scene *scene, struct SceneLayer *sl, struct ARegion *ar, View3D *v3d, + Base *base, const short dflag); + +void draw_mesh_object_outline(View3D *v3d, Object *ob, struct DerivedMesh *dm, const unsigned char ob_wire_col[4]); + +bool draw_glsl_material(Scene *scene, struct SceneLayer *sl, struct Object *ob, View3D *v3d, const char dt); +void draw_object_instance(const struct EvaluationContext *eval_ctx, Scene *scene, struct SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline, const float wire_col[4]); +void draw_object_backbufsel(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob); + +void draw_object_wire_color(Scene *scene, struct SceneLayer *, Base *base, unsigned char r_ob_wire_col[4]); +void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const unsigned char color[4]); +void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const short dflag, const unsigned char ob_wire_col[4], + const bool is_obact); +void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, + const short dflag, const unsigned char ob_wire_col[4]); +void drawspeaker(const unsigned char ob_wire_col[3]); +void draw_bounding_volume(struct Object *ob, char type, const unsigned char ob_wire_col[4]); +void draw_rigidbody_shape(struct Object *ob, const unsigned char ob_wire_col[4]); void view3d_cached_text_draw_begin(void); void view3d_cached_text_draw_add(const float co[3], @@ -169,12 +189,13 @@ enum { int view3d_effective_drawtype(const struct View3D *v3d); /* drawarmature.c */ -bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4], - const bool is_outline); +bool draw_armature( + const struct EvaluationContext *eval_ctx, Scene *scene, struct SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, + const short dt, const short dflag, const unsigned char ob_wire_col[4], + const bool is_outline); /* drawmesh.c */ -void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, +void draw_mesh_textured(Scene *scene, struct SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, struct Object *ob, struct DerivedMesh *dm, const int draw_flags); void draw_mesh_face_select( struct RegionView3D *rv3d, struct Mesh *me, struct DerivedMesh *dm, @@ -195,16 +216,28 @@ void draw_sim_debug_data(Scene *scene, View3D *v3d, ARegion *ar); /* view3d_draw.c */ void view3d_main_region_draw(const struct bContext *C, struct ARegion *ar); -void ED_view3d_draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, bool alphaoverride); -void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d); +void view3d_draw_region_info(const struct bContext *C, struct ARegion *ar, const int offset); + +void ED_view3d_draw_depth( + const struct EvaluationContext *eval_ctx, struct Depsgraph *graph, + struct ARegion *ar, View3D *v3d, bool alphaoverride); + +/* view3d_draw_legacy.c */ +void view3d_main_region_draw_legacy(const struct bContext *C, struct ARegion *ar); +void ED_view3d_draw_depth_gpencil(const struct EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d); + void ED_view3d_draw_select_loop( - ViewContext *vc, Scene *scene, View3D *v3d, ARegion *ar, + const struct EvaluationContext *eval_ctx, ViewContext *vc, Scene *scene, struct SceneLayer *sl, View3D *v3d, ARegion *ar, bool use_obedit_skip, bool use_nearest); -void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag);\ +void ED_view3d_draw_depth_loop( + const struct EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d); + +void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d, + const bool do_foreground, const bool do_camera_frame); + +void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag); -void circf(float x, float y, float rad); -void circ(float x, float y, float rad); void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect); float view3d_depth_near(struct ViewDepths *d); @@ -219,7 +252,6 @@ void VIEW3D_OT_smoothview(struct wmOperatorType *ot); void VIEW3D_OT_camera_to_view(struct wmOperatorType *ot); void VIEW3D_OT_camera_to_view_selected(struct wmOperatorType *ot); void VIEW3D_OT_object_as_camera(struct wmOperatorType *ot); -void VIEW3D_OT_localview(struct wmOperatorType *ot); void VIEW3D_OT_game_start(struct wmOperatorType *ot); @@ -248,7 +280,7 @@ void ED_view3d_smooth_view_force_finish( struct View3D *v3d, struct ARegion *ar); void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect); -void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d); +void view3d_viewmatrix_set(const struct EvaluationContext *eval_ctx, Scene *scene, const View3D *v3d, RegionView3D *rv3d); void fly_modal_keymap(struct wmKeyConfig *keyconf); void walk_modal_keymap(struct wmKeyConfig *keyconf); @@ -263,7 +295,7 @@ void view3d_buttons_register(struct ARegionType *art); /* view3d_camera_control.c */ struct View3DCameraControl *ED_view3d_cameracontrol_acquire( - Scene *scene, View3D *v3d, RegionView3D *rv3d, + const struct bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d, const bool use_parent_root); void ED_view3d_cameracontrol_update( struct View3DCameraControl *vctrl, @@ -297,6 +329,20 @@ ARegion *view3d_has_tools_region(ScrArea *sa); extern const char *view3d_context_dir[]; /* doc access */ +/* view3d_widgets.c */ +void VIEW3D_WGT_lamp_spot(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_lamp_area(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_lamp_target(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_camera(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_camera_view(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_force_field(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_empty_image(struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_armature_spline(struct wmManipulatorGroupType *wgt); + +void VIEW3D_WGT_ruler(struct wmManipulatorGroupType *wgt); +void VIEW3D_WT_ruler_item(struct wmManipulatorType *wt); +void VIEW3D_OT_ruler_add(struct wmOperatorType *ot); + /* draw_volume.c */ void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob, const float min[3], const float max[3], @@ -315,5 +361,31 @@ extern unsigned char view3d_camera_border_hack_col[3]; extern bool view3d_camera_border_hack_test; #endif -#endif /* __VIEW3D_INTERN_H__ */ +/* temporary for legacy viewport to work */ +void VP_legacy_drawcursor(Scene *scene, struct SceneLayer *sl, ARegion *ar, View3D *v3d); +void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect); +void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect); +void VP_legacy_draw_selected_name(Scene *scene, Object *ob, rcti *rect); +void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit); +void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth); +void VP_legacy_view3d_main_region_setup_view(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4]); +bool VP_legacy_view3d_stereo3d_active(struct wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d); +void VP_legacy_view3d_stereo3d_setup(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar); +void draw_dupli_objects(const struct EvaluationContext *eval_ctx, Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *base); +bool VP_legacy_use_depth(Scene *scene, View3D *v3d); +void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d); +void VP_drawrenderborder(ARegion *ar, View3D *v3d); +void VP_view3d_draw_background_none(void); +void VP_view3d_draw_background_world(Scene *scene, RegionView3D *rv3d); +void VP_view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar); + +/* temporary legacy calls, only when there is a switch between new/old draw calls */ +void VP_deprecated_gpu_update_lamps_shadows_world(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d); +void VP_deprecated_view3d_draw_objects( + const struct bContext *C, + const struct EvaluationContext *eval_ctx, + Scene *scene, View3D *v3d, ARegion *ar, + const char **grid_unit, + const bool do_bgpic, const bool draw_offscreen, struct GPUFX *fx); +#endif /* __VIEW3D_INTERN_H__ */ diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index ef7b01f7a21..4f80270e1e7 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -40,6 +40,9 @@ #include "BKE_DerivedMesh.h" #include "BKE_displist.h" #include "BKE_editmesh.h" +#include "BKE_context.h" + +#include "DEG_depsgraph.h" #include "bmesh.h" @@ -104,12 +107,14 @@ static void meshobject_foreachScreenVert__mapFunc(void *userData, int index, con } void meshobject_foreachScreenVert( - ViewContext *vc, + const EvaluationContext *eval_ctx, ViewContext *vc, void (*func)(void *userData, MVert *eve, const float screen_co[2], int index), void *userData, eV3DProjTest clip_flag) { foreachScreenObjectVert_userData data; - DerivedMesh *dm = mesh_get_derived_deform(vc->scene, vc->obact, CD_MASK_BAREMESH); + DerivedMesh *dm; + + dm = mesh_get_derived_deform(eval_ctx, vc->scene, vc->obact, CD_MASK_BAREMESH); ED_view3d_check_mats_rv3d(vc->rv3d); @@ -145,12 +150,14 @@ static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const flo } void mesh_foreachScreenVert( - ViewContext *vc, + const EvaluationContext *eval_ctx, ViewContext *vc, void (*func)(void *userData, BMVert *eve, const float screen_co[2], int index), void *userData, eV3DProjTest clip_flag) { foreachScreenVert_userData data; - DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); + DerivedMesh *dm; + + dm = editbmesh_get_derived_cage(eval_ctx, vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); ED_view3d_check_mats_rv3d(vc->rv3d); @@ -199,12 +206,14 @@ static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, const flo } void mesh_foreachScreenEdge( - ViewContext *vc, + const EvaluationContext *eval_ctx, ViewContext *vc, void (*func)(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index), void *userData, eV3DProjTest clip_flag) { foreachScreenEdge_userData data; - DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); + DerivedMesh *dm; + + dm = editbmesh_get_derived_cage(eval_ctx, vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); ED_view3d_check_mats_rv3d(vc->rv3d); @@ -245,12 +254,14 @@ static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const flo } void mesh_foreachScreenFace( - ViewContext *vc, + const EvaluationContext *eval_ctx, ViewContext *vc, void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index), void *userData, const eV3DProjTest clip_flag) { foreachScreenFace_userData data; - DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); + DerivedMesh *dm; + + dm = editbmesh_get_derived_cage(eval_ctx, vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); ED_view3d_check_mats_rv3d(vc->rv3d); diff --git a/source/blender/editors/space_view3d/view3d_manipulator_armature.c b/source/blender/editors/space_view3d/view3d_manipulator_armature.c new file mode 100644 index 00000000000..5d3d88ff2a2 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_armature.c @@ -0,0 +1,220 @@ +/* + * ***** BEGIN GPL 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_manipulator_armature.c + * \ingroup spview3d + */ + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_armature.h" +#include "BKE_action.h" +#include "BKE_context.h" +#include "BKE_object.h" + +#include "DNA_object_types.h" +#include "DNA_armature_types.h" + +#include "ED_armature.h" +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +#include "UI_resources.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "view3d_intern.h" /* own include */ + + +/* -------------------------------------------------------------------- */ + +/** \name Armature Spline Manipulator + * + * \{ */ + +/* + * TODO(campbell): Current conversion is a approximation (usable not correct), + * we'll need to take the next/previous bones into account to get the tangent directions. + * First last matrices from 'b_bone_spline_setup' are close but also not quite accurate + * since they're not at either end-points on the curve. + * + * Likely we'll need a function especially to get the first/last orientations. + */ + +#define BBONE_SCALE_Y 3.0f + +struct BoneSplineHandle { + wmManipulator *manipulator; + bPoseChannel *pchan; + /* We could remove, keep since at the moment for checking the conversion. */ + float co[3]; + int index; +}; + +struct BoneSplineWidgetGroup { + struct BoneSplineHandle handles[2]; +}; + +static void manipulator_bbone_offset_get( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + void *value_p) +{ + struct BoneSplineHandle *bh = mpr_prop->custom_func.user_data; + bPoseChannel *pchan = bh->pchan; + + float *value = value_p; + BLI_assert(mpr_prop->type->array_length == 3); + + if (bh->index == 0) { + bh->co[1] = pchan->bone->ease1 / BBONE_SCALE_Y; + bh->co[0] = pchan->curveInX; + bh->co[2] = pchan->curveInY; + } + else { + bh->co[1] = -pchan->bone->ease2 / BBONE_SCALE_Y; + bh->co[0] = pchan->curveOutX; + bh->co[2] = pchan->curveOutY; + } + copy_v3_v3(value, bh->co); +} + +static void manipulator_bbone_offset_set( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + struct BoneSplineHandle *bh = mpr_prop->custom_func.user_data; + bPoseChannel *pchan = bh->pchan; + + const float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 3); + copy_v3_v3(bh->co, value); + + if (bh->index == 0) { + pchan->bone->ease1 = max_ff(0.0f, bh->co[1] * BBONE_SCALE_Y); + pchan->curveInX = bh->co[0]; + pchan->curveInY = bh->co[2]; + } + else { + pchan->bone->ease2 = max_ff(0.0f, -bh->co[1] * BBONE_SCALE_Y); + pchan->curveOutX = bh->co[0]; + pchan->curveOutY = bh->co[2]; + } + +} + +static bool WIDGETGROUP_armature_spline_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); + if (ob != NULL) { + const bArmature *arm = ob->data; + if (arm->drawtype == ARM_B_BONE) { + if (arm->act_bone && arm->act_bone->segments > 1) { + return true; + } + } + } + return false; +} + + +static void WIDGETGROUP_armature_spline_setup(const bContext *C, wmManipulatorGroup *mgroup) +{ + Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); + bPoseChannel *pchan = BKE_pose_channel_active(ob); + + const wmManipulatorType *wt_grab = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", true); + + struct BoneSplineWidgetGroup *bspline_group = MEM_callocN(sizeof(struct BoneSplineWidgetGroup), __func__); + mgroup->customdata = bspline_group; + + /* Handles */ + for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) { + wmManipulator *mpr; + mpr = bspline_group->handles[i].manipulator = WM_manipulator_new_ptr(wt_grab, mgroup, NULL); + RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_RING_2D); + RNA_enum_set(mpr->ptr, "draw_options", + ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL | ED_MANIPULATOR_GRAB_DRAW_FLAG_ALIGN_VIEW); + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_VALUE, true); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); + + mpr->scale_basis = 0.06f; + + if (i == 0) { + copy_v3_v3(mpr->matrix_basis[3], pchan->loc); + } + } +} + +static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); + + if (!mgroup->customdata) + return; + + struct BoneSplineWidgetGroup *bspline_group = mgroup->customdata; + bPoseChannel *pchan = BKE_pose_channel_active(ob); + + /* Handles */ + for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) { + wmManipulator *mpr = bspline_group->handles[i].manipulator; + bspline_group->handles[i].pchan = pchan; + bspline_group->handles[i].index = i; + + float mat[4][4]; + mul_m4_m4m4(mat, ob->obmat, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat); + copy_m4_m4(mpr->matrix_space, mat); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + WM_manipulator_target_property_def_func( + mpr, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_bbone_offset_get, + .value_set_fn = manipulator_bbone_offset_set, + .range_get_fn = NULL, + .user_data = &bspline_group->handles[i], + }); + } +} + +void VIEW3D_WGT_armature_spline(wmManipulatorGroupType *wgt) +{ + wgt->name = "Armature Spline Widgets"; + wgt->idname = "VIEW3D_WGT_armature_spline"; + + wgt->flag = (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D); + + wgt->poll = WIDGETGROUP_armature_spline_poll; + wgt->setup = WIDGETGROUP_armature_spline_setup; + wgt->refresh = WIDGETGROUP_armature_spline_refresh; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_manipulator_camera.c b/source/blender/editors/space_view3d/view3d_manipulator_camera.c new file mode 100644 index 00000000000..e8a1b5cea89 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c @@ -0,0 +1,401 @@ +/* + * ***** BEGIN GPL 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_manipulator_camera.c + * \ingroup spview3d + */ + + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_camera.h" +#include "BKE_context.h" + +#include "DNA_object_types.h" +#include "DNA_camera_types.h" + +#include "ED_armature.h" +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +#include "UI_resources.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "view3d_intern.h" /* own include */ + + +/* -------------------------------------------------------------------- */ + +/** \name Camera Manipulators + * \{ */ + +struct CameraWidgetGroup { + wmManipulator *dop_dist; + wmManipulator *focal_len; + wmManipulator *ortho_scale; +}; + +static bool WIDGETGROUP_camera_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = CTX_data_active_object(C); + + return (ob && ob->type == OB_CAMERA); +} + +static void cameragroup_property_setup(wmManipulator *widget, Object *ob, Camera *ca, const bool is_ortho) +{ + const float scale[3] = {1.0f / len_v3(ob->obmat[0]), 1.0f / len_v3(ob->obmat[1]), 1.0f / len_v3(ob->obmat[2])}; + const float scale_fac = ca->drawsize; + const float drawsize = is_ortho ? + (0.5f * ca->ortho_scale) : + (scale_fac / ((scale[0] + scale[1] + scale[2]) / 3.0f)); + const float half_sensor = 0.5f * ((ca->sensor_fit == CAMERA_SENSOR_FIT_VERT) ? ca->sensor_y : ca->sensor_x); + const char *propname = is_ortho ? "ortho_scale" : "lens"; + + PointerRNA camera_ptr; + float min, max, range; + float step, precision; + + RNA_pointer_create(&ca->id, &RNA_Camera, ca, &camera_ptr); + + /* get property range */ + PropertyRNA *prop = RNA_struct_find_property(&camera_ptr, propname); + RNA_property_float_ui_range(&camera_ptr, prop, &min, &max, &step, &precision); + range = max - min; + + ED_manipulator_arrow3d_set_range_fac(widget, is_ortho ? (scale_fac * range) : (drawsize * range / half_sensor)); +} + +static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgroup) +{ + Object *ob = CTX_data_active_object(C); + Camera *ca = ob->data; + float dir[3]; + + const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true); + + struct CameraWidgetGroup *camgroup = MEM_callocN(sizeof(struct CameraWidgetGroup), __func__); + mgroup->customdata = camgroup; + + negate_v3_v3(dir, ob->obmat[2]); + + /* dof distance */ + { + wmManipulator *mpr; + mpr = camgroup->dop_dist = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); + RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CROSS); + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_HOVER, true); + + UI_GetThemeColor3fv(TH_MANIPULATOR_A, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); + } + + /* focal length + * - logic/calculations are similar to BKE_camera_view_frame_ex, better keep in sync */ + { + wmManipulator *mpr; + mpr = camgroup->focal_len = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); + mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE; + RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE); + RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); + cameragroup_property_setup(mpr, ob, ca, false); + + mpr = camgroup->ortho_scale = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); + mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE; + RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE); + RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); + cameragroup_property_setup(mpr, ob, ca, true); + } +} + +static void WIDGETGROUP_camera_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + if (!mgroup->customdata) + return; + + struct CameraWidgetGroup *camgroup = mgroup->customdata; + Object *ob = CTX_data_active_object(C); + Camera *ca = ob->data; + PointerRNA camera_ptr; + float dir[3]; + + RNA_pointer_create(&ca->id, &RNA_Camera, ca, &camera_ptr); + + negate_v3_v3(dir, ob->obmat[2]); + + if (ca->flag & CAM_SHOWLIMITS) { + WM_manipulator_set_matrix_location(camgroup->dop_dist, ob->obmat[3]); + WM_manipulator_set_matrix_rotation_from_yz_axis(camgroup->dop_dist, ob->obmat[1], dir); + WM_manipulator_set_scale(camgroup->dop_dist, ca->drawsize); + WM_manipulator_set_flag(camgroup->dop_dist, WM_MANIPULATOR_HIDDEN, false); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + WM_manipulator_target_property_def_rna(camgroup->dop_dist, "offset", &camera_ptr, "dof_distance", -1); + } + else { + WM_manipulator_set_flag(camgroup->dop_dist, WM_MANIPULATOR_HIDDEN, true); + } + + /* TODO - make focal length/ortho scale widget optional */ + if (true) { + const bool is_ortho = (ca->type == CAM_ORTHO); + float offset[3]; + float aspect[2]; + + wmManipulator *widget = is_ortho ? camgroup->ortho_scale : camgroup->focal_len; + WM_manipulator_set_flag(widget, WM_MANIPULATOR_HIDDEN, false); + WM_manipulator_set_flag(is_ortho ? camgroup->focal_len : camgroup->ortho_scale, WM_MANIPULATOR_HIDDEN, true); + + + /* account for lens shifting */ + offset[0] = ((ob->size[0] > 0.0f) ? -2.0f : 2.0f) * ca->shiftx; + offset[1] = 2.0f * ca->shifty; + offset[2] = 0.0f; + + /* get aspect */ + const Scene *scene = CTX_data_scene(C); + const float aspx = (float)scene->r.xsch * scene->r.xasp; + const float aspy = (float)scene->r.ysch * scene->r.yasp; + const int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, aspx, aspy); + aspect[0] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? 1.0f : aspx / aspy; + aspect[1] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? aspy / aspx : 1.0f; + + unit_m4(widget->matrix_basis); + WM_manipulator_set_matrix_location(widget, ob->obmat[3]); + WM_manipulator_set_matrix_rotation_from_yz_axis(widget, ob->obmat[1], dir); + + { + float scale_matrix; + if (is_ortho) { + scale_matrix = ca->ortho_scale * 0.5f; + } + else { + const float scale[3] = { + 1.0f / len_v3(ob->obmat[0]), + 1.0f / len_v3(ob->obmat[1]), + 1.0f / len_v3(ob->obmat[2]), + }; + scale_matrix = ca->drawsize / ((scale[0] + scale[1] + scale[2]) / 3.0f); + } + mul_v3_fl(widget->matrix_basis[0], scale_matrix); + mul_v3_fl(widget->matrix_basis[1], scale_matrix); + } + + RNA_float_set_array(widget->ptr, "aspect", aspect); + + WM_manipulator_set_matrix_offset_location(widget, offset); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + WM_manipulator_target_property_def_rna(camgroup->focal_len, "offset", &camera_ptr, "lens", -1); + WM_manipulator_target_property_def_rna(camgroup->ortho_scale, "offset", &camera_ptr, "ortho_scale", -1); + } +} + +void VIEW3D_WGT_camera(wmManipulatorGroupType *wgt) +{ + wgt->name = "Camera Widgets"; + wgt->idname = "VIEW3D_WGT_camera"; + + wgt->flag = (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D | + WM_MANIPULATORGROUPTYPE_DEPTH_3D); + + wgt->poll = WIDGETGROUP_camera_poll; + wgt->setup = WIDGETGROUP_camera_setup; + wgt->refresh = WIDGETGROUP_camera_refresh; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name CameraView Manipulators + * \{ */ + +struct CameraViewWidgetGroup { + wmManipulator *border; + + struct { + rctf *edit_border; + rctf view_border; + } state; +}; + +/* scale callbacks */ +static void manipulator_render_border_prop_matrix_get( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + void *value_p) +{ + float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + struct CameraViewWidgetGroup *viewgroup = mpr_prop->custom_func.user_data; + const rctf *border = viewgroup->state.edit_border; + + unit_m4(matrix); + matrix[0][0] = BLI_rctf_size_x(border); + matrix[1][1] = BLI_rctf_size_y(border); + matrix[3][0] = BLI_rctf_cent_x(border); + matrix[3][1] = BLI_rctf_cent_y(border); +} + +static void manipulator_render_border_prop_matrix_set( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + const float (*matrix)[4] = value_p; + struct CameraViewWidgetGroup *viewgroup = mpr_prop->custom_func.user_data; + rctf *border = viewgroup->state.edit_border; + BLI_assert(mpr_prop->type->array_length == 16); + + BLI_rctf_resize(border, len_v3(matrix[0]), len_v3(matrix[1])); + BLI_rctf_recenter(border, matrix[3][0], matrix[3][1]); + BLI_rctf_isect(&(rctf){.xmin = 0, .ymin = 0, .xmax = 1, .ymax = 1}, border, border); +} + +static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + + /* This is just so the border isn't always in the way, + * stealing mouse clicks from regular usage. + * We could change the rules for when to show. */ + { + SceneLayer *sl = CTX_data_scene_layer(C); + if (scene->camera != OBACT(sl)) { + return false; + } + } + + if (rv3d->persp == RV3D_CAMOB) { + if (scene->r.mode & R_BORDER) { + return true; + } + } + else if (v3d->flag2 & V3D_RENDER_BORDER) { + return true; + } + return false; +} + +static void WIDGETGROUP_camera_view_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + struct CameraViewWidgetGroup *viewgroup = MEM_mallocN(sizeof(struct CameraViewWidgetGroup), __func__); + + viewgroup->border = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL); + + RNA_enum_set(viewgroup->border->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE); + /* Box style is more subtle in this case. */ + RNA_enum_set(viewgroup->border->ptr, "draw_style", ED_MANIPULATOR_CAGE2D_STYLE_BOX); + + + mgroup->customdata = viewgroup; +} + +static void WIDGETGROUP_camera_view_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct CameraViewWidgetGroup *viewgroup = mgroup->customdata; + + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + if (rv3d->persp == RV3D_CAMOB) { + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewgroup->state.view_border, false); + } + else { + viewgroup->state.view_border = (rctf){.xmin = 0, .ymin = 0, .xmax = ar->winx, .ymax = ar->winy}; + } + + wmManipulator *mpr = viewgroup->border; + unit_m4(mpr->matrix_space); + mul_v3_fl(mpr->matrix_space[0], BLI_rctf_size_x(&viewgroup->state.view_border)); + mul_v3_fl(mpr->matrix_space[1], BLI_rctf_size_y(&viewgroup->state.view_border)); + mpr->matrix_space[3][0] = viewgroup->state.view_border.xmin; + mpr->matrix_space[3][1] = viewgroup->state.view_border.ymin; +} + +static void WIDGETGROUP_camera_view_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct CameraViewWidgetGroup *viewgroup = mgroup->customdata; + + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + Scene *scene = CTX_data_scene(C); + + { + wmManipulator *mpr = viewgroup->border; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + + RNA_enum_set(viewgroup->border->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE); + + if (rv3d->persp == RV3D_CAMOB) { + viewgroup->state.edit_border = &scene->r.border; + } + else { + viewgroup->state.edit_border = &v3d->render_border; + } + + WM_manipulator_target_property_def_func( + mpr, "matrix", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_render_border_prop_matrix_get, + .value_set_fn = manipulator_render_border_prop_matrix_set, + .range_get_fn = NULL, + .user_data = viewgroup, + }); + } + +} + +void VIEW3D_WGT_camera_view(wmManipulatorGroupType *wgt) +{ + wgt->name = "Camera View Widgets"; + wgt->idname = "VIEW3D_WGT_camera_view"; + + wgt->flag = (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_SCALE); + + wgt->poll = WIDGETGROUP_camera_view_poll; + wgt->setup = WIDGETGROUP_camera_view_setup; + wgt->draw_prepare = WIDGETGROUP_camera_view_draw_prepare; + wgt->refresh = WIDGETGROUP_camera_view_refresh; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_manipulator_empty.c b/source/blender/editors/space_view3d/view3d_manipulator_empty.c new file mode 100644 index 00000000000..1d56c5ee7f4 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_empty.c @@ -0,0 +1,196 @@ +/* + * ***** BEGIN GPL 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_manipulator_empty.c + * \ingroup spview3d + */ + + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_object.h" +#include "BKE_image.h" + +#include "DNA_object_types.h" +#include "DNA_lamp_types.h" + +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +#include "UI_resources.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "view3d_intern.h" /* own include */ + +/* -------------------------------------------------------------------- */ + +/** \name Empty Image Manipulators + * \{ */ + +struct EmptyImageWidgetGroup { + wmManipulator *manipulator; + struct { + Object *ob; + float dims[2]; + } state; +}; + +/* translate callbacks */ +static void manipulator_empty_image_prop_matrix_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + struct EmptyImageWidgetGroup *imgroup = mpr_prop->custom_func.user_data; + const Object *ob = imgroup->state.ob; + + unit_m4(matrix); + matrix[0][0] = ob->empty_drawsize; + matrix[1][1] = ob->empty_drawsize; + + float dims[2] = {0.0f, 0.0f}; + RNA_float_get_array(mpr->ptr, "dimensions", dims); + dims[0] *= ob->empty_drawsize; + dims[1] *= ob->empty_drawsize; + + matrix[3][0] = (ob->ima_ofs[0] * dims[0]) + (0.5f * dims[0]); + matrix[3][1] = (ob->ima_ofs[1] * dims[1]) + (0.5f * dims[1]); +} + +static void manipulator_empty_image_prop_matrix_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + const float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + struct EmptyImageWidgetGroup *imgroup = mpr_prop->custom_func.user_data; + Object *ob = imgroup->state.ob; + + ob->empty_drawsize = matrix[0][0]; + + float dims[2]; + RNA_float_get_array(mpr->ptr, "dimensions", dims); + dims[0] *= ob->empty_drawsize; + dims[1] *= ob->empty_drawsize; + + ob->ima_ofs[0] = (matrix[3][0] - (0.5f * dims[0])) / dims[0]; + ob->ima_ofs[1] = (matrix[3][1] - (0.5f * dims[1])) / dims[1]; +} + +static bool WIDGETGROUP_empty_image_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = CTX_data_active_object(C); + + if (ob && ob->type == OB_EMPTY) { + return (ob->empty_drawtype == OB_EMPTY_IMAGE); + } + return false; +} + +static void WIDGETGROUP_empty_image_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + struct EmptyImageWidgetGroup *imgroup = MEM_mallocN(sizeof(struct EmptyImageWidgetGroup), __func__); + imgroup->manipulator = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL); + wmManipulator *mpr = imgroup->manipulator; + RNA_enum_set(mpr->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE); + + mgroup->customdata = imgroup; + + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_HOVER, true); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); +} + +static void WIDGETGROUP_empty_image_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct EmptyImageWidgetGroup *imgroup = mgroup->customdata; + Object *ob = CTX_data_active_object(C); + wmManipulator *mpr = imgroup->manipulator; + + copy_m4_m4(mpr->matrix_basis, ob->obmat); + + RNA_enum_set(mpr->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE | + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM); + + imgroup->state.ob = ob; + + /* Use dimensions for aspect. */ + if (ob->data != NULL) { + const Image *image = ob->data; + ImageUser iuser = *ob->iuser; + float size[2]; + BKE_image_get_size_fl(ob->data, &iuser, size); + + /* Get the image aspect even if the buffer is invalid */ + if (image->aspx > image->aspy) { + size[1] *= image->aspy / image->aspx; + } + else if (image->aspx < image->aspy) { + size[0] *= image->aspx / image->aspy; + } + + const float dims_max = max_ff(size[0], size[1]); + imgroup->state.dims[0] = size[0] / dims_max; + imgroup->state.dims[1] = size[1] / dims_max; + } + else { + copy_v2_fl(imgroup->state.dims, 1.0f); + } + RNA_float_set_array(mpr->ptr, "dimensions", imgroup->state.dims); + + WM_manipulator_target_property_def_func( + mpr, "matrix", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_empty_image_prop_matrix_get, + .value_set_fn = manipulator_empty_image_prop_matrix_set, + .range_get_fn = NULL, + .user_data = imgroup, + }); +} + +void VIEW3D_WGT_empty_image(wmManipulatorGroupType *wgt) +{ + wgt->name = "Area Lamp Widgets"; + wgt->idname = "VIEW3D_WGT_empty_image"; + + wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D | + WM_MANIPULATORGROUPTYPE_DEPTH_3D); + + wgt->poll = WIDGETGROUP_empty_image_poll; + wgt->setup = WIDGETGROUP_empty_image_setup; + wgt->refresh = WIDGETGROUP_empty_image_refresh; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c new file mode 100644 index 00000000000..6a34f493caf --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c @@ -0,0 +1,118 @@ +/* + * ***** BEGIN GPL 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_manipulator_forcefield.c + * \ingroup spview3d + */ + + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_object.h" + +#include "DNA_object_types.h" +#include "DNA_object_force.h" + +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +#include "UI_resources.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "view3d_intern.h" /* own include */ + +/* -------------------------------------------------------------------- */ + +/** \name Force Field Manipulators + * \{ */ + +static bool WIDGETGROUP_forcefield_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = CTX_data_active_object(C); + + return (ob && ob->pd && ob->pd->forcefield); +} + +static void WIDGETGROUP_forcefield_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + /* only wind effector for now */ + wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__); + mgroup->customdata = wwrapper; + + wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL); + wmManipulator *mpr = wwrapper->manipulator; + RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED); + ED_manipulator_arrow3d_set_ui_range(mpr, -200.0f, 200.0f); + ED_manipulator_arrow3d_set_range_fac(mpr, 6.0f); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); +} + +static void WIDGETGROUP_forcefield_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = mgroup->customdata; + wmManipulator *mpr = wwrapper->manipulator; + Object *ob = CTX_data_active_object(C); + PartDeflect *pd = ob->pd; + + if (pd->forcefield == PFIELD_WIND) { + const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f; + const float ofs[3] = {0.0f, -size, 0.0f}; + PointerRNA field_ptr; + + RNA_pointer_create(&ob->id, &RNA_FieldSettings, pd, &field_ptr); + WM_manipulator_set_matrix_location(mpr, ob->obmat[3]); + WM_manipulator_set_matrix_rotation_from_z_axis(mpr, ob->obmat[2]); + WM_manipulator_set_matrix_offset_location(mpr, ofs); + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + WM_manipulator_target_property_def_rna(mpr, "offset", &field_ptr, "strength", -1); + } + else { + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); + } +} + +void VIEW3D_WGT_force_field(wmManipulatorGroupType *wgt) +{ + wgt->name = "Force Field Widgets"; + wgt->idname = "VIEW3D_WGT_force_field"; + + wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D | + WM_MANIPULATORGROUPTYPE_SCALE | + WM_MANIPULATORGROUPTYPE_DEPTH_3D); + + wgt->poll = WIDGETGROUP_forcefield_poll; + wgt->setup = WIDGETGROUP_forcefield_setup; + wgt->refresh = WIDGETGROUP_forcefield_refresh; +} + +/** \} */ + diff --git a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c new file mode 100644 index 00000000000..93b6b69a105 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c @@ -0,0 +1,289 @@ +/* + * ***** BEGIN GPL 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_manipulator_lamp.c + * \ingroup spview3d + */ + + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_object.h" + +#include "DNA_object_types.h" +#include "DNA_lamp_types.h" + +#include "ED_screen.h" +#include "ED_manipulator_library.h" + +#include "UI_resources.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "view3d_intern.h" /* own include */ + +/* -------------------------------------------------------------------- */ + +/** \name Spot Lamp Manipulators + * \{ */ + +static bool WIDGETGROUP_lamp_spot_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = CTX_data_active_object(C); + + if (ob && ob->type == OB_LAMP) { + Lamp *la = ob->data; + return (la->type == LA_SPOT); + } + return false; +} + +static void WIDGETGROUP_lamp_spot_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__); + + wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL); + wmManipulator *mpr = wwrapper->manipulator; + RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_INVERTED); + + mgroup->customdata = wwrapper; + + ED_manipulator_arrow3d_set_range_fac(mpr, 4.0f); + + UI_GetThemeColor3fv(TH_MANIPULATOR_SECONDARY, mpr->color); +} + +static void WIDGETGROUP_lamp_spot_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = mgroup->customdata; + wmManipulator *mpr = wwrapper->manipulator; + Object *ob = CTX_data_active_object(C); + Lamp *la = ob->data; + float dir[3]; + + negate_v3_v3(dir, ob->obmat[2]); + + WM_manipulator_set_matrix_rotation_from_z_axis(mpr, dir); + WM_manipulator_set_matrix_location(mpr, ob->obmat[3]); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + PointerRNA lamp_ptr; + const char *propname = "spot_size"; + RNA_pointer_create(&la->id, &RNA_Lamp, la, &lamp_ptr); + WM_manipulator_target_property_def_rna(mpr, "offset", &lamp_ptr, propname, -1); +} + +void VIEW3D_WGT_lamp_spot(wmManipulatorGroupType *wgt) +{ + wgt->name = "Spot Lamp Widgets"; + wgt->idname = "VIEW3D_WGT_lamp_spot"; + + wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D | + WM_MANIPULATORGROUPTYPE_DEPTH_3D); + + wgt->poll = WIDGETGROUP_lamp_spot_poll; + wgt->setup = WIDGETGROUP_lamp_spot_setup; + wgt->refresh = WIDGETGROUP_lamp_spot_refresh; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Area Lamp Manipulators + * \{ */ + +/* scale callbacks */ +static void manipulator_area_lamp_prop_matrix_get( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + void *value_p) +{ + BLI_assert(mpr_prop->type->array_length == 16); + float (*matrix)[4] = value_p; + const Lamp *la = mpr_prop->custom_func.user_data; + + matrix[0][0] = la->area_size; + matrix[1][1] = (la->area_shape == LA_AREA_RECT) ? la->area_sizey : la->area_size; +} + +static void manipulator_area_lamp_prop_matrix_set( + const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + const float (*matrix)[4] = value_p; + BLI_assert(mpr_prop->type->array_length == 16); + Lamp *la = mpr_prop->custom_func.user_data; + + if (la->area_shape == LA_AREA_RECT) { + la->area_size = len_v3(matrix[0]); + la->area_sizey = len_v3(matrix[1]); + } + else { + la->area_size = len_v3(matrix[0]); + } +} + +static bool WIDGETGROUP_lamp_area_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = CTX_data_active_object(C); + + if (ob && ob->type == OB_LAMP) { + Lamp *la = ob->data; + return (la->type == LA_AREA); + } + return false; +} + +static void WIDGETGROUP_lamp_area_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__); + wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL); + wmManipulator *mpr = wwrapper->manipulator; + RNA_enum_set(mpr->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE); + + mgroup->customdata = wwrapper; + + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_HOVER, true); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); +} + +static void WIDGETGROUP_lamp_area_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = mgroup->customdata; + Object *ob = CTX_data_active_object(C); + Lamp *la = ob->data; + wmManipulator *mpr = wwrapper->manipulator; + + copy_m4_m4(mpr->matrix_basis, ob->obmat); + + RNA_enum_set(mpr->ptr, "transform", + ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE | + ((la->area_shape == LA_AREA_SQUARE) ? ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM : 0)); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + WM_manipulator_target_property_def_func( + mpr, "matrix", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_area_lamp_prop_matrix_get, + .value_set_fn = manipulator_area_lamp_prop_matrix_set, + .range_get_fn = NULL, + .user_data = la, + }); +} + +void VIEW3D_WGT_lamp_area(wmManipulatorGroupType *wgt) +{ + wgt->name = "Area Lamp Widgets"; + wgt->idname = "VIEW3D_WGT_lamp_area"; + + wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D | + WM_MANIPULATORGROUPTYPE_DEPTH_3D); + + wgt->poll = WIDGETGROUP_lamp_area_poll; + wgt->setup = WIDGETGROUP_lamp_area_setup; + wgt->refresh = WIDGETGROUP_lamp_area_refresh; +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Lamp Target Manipulator + * \{ */ + +static bool WIDGETGROUP_lamp_target_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + Object *ob = CTX_data_active_object(C); + + if (ob != NULL) { + if (ob->type == OB_LAMP) { + Lamp *la = ob->data; + return (ELEM(la->type, LA_SUN, LA_SPOT, LA_HEMI, LA_AREA)); + } +#if 0 + else if (ob->type == OB_CAMERA) { + return true; + } +#endif + } + return false; +} + +static void WIDGETGROUP_lamp_target_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__); + wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_grab_3d", mgroup, NULL); + wmManipulator *mpr = wwrapper->manipulator; + + mgroup->customdata = wwrapper; + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi); + + mpr->scale_basis = 0.06f; + + wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_transform_axis_target", true); + + RNA_enum_set(mpr->ptr, "draw_options", + ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL | ED_MANIPULATOR_GRAB_DRAW_FLAG_ALIGN_VIEW); + + WM_manipulator_operator_set(mpr, 0, ot, NULL); +} + +static void WIDGETGROUP_lamp_target_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmManipulatorWrapper *wwrapper = mgroup->customdata; + Object *ob = CTX_data_active_object(C); + wmManipulator *mpr = wwrapper->manipulator; + + copy_m4_m4(mpr->matrix_basis, ob->obmat); + unit_m4(mpr->matrix_offset); + mpr->matrix_offset[3][2] = -2.4f / mpr->scale_basis; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true); +} + +void VIEW3D_WGT_lamp_target(wmManipulatorGroupType *wgt) +{ + wgt->name = "Target Lamp Widgets"; + wgt->idname = "VIEW3D_WGT_lamp_target"; + + wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT | + WM_MANIPULATORGROUPTYPE_3D); + + wgt->poll = WIDGETGROUP_lamp_target_poll; + wgt->setup = WIDGETGROUP_lamp_target_setup; + wgt->draw_prepare = WIDGETGROUP_lamp_target_draw_prepare; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c new file mode 100644 index 00000000000..01cf67259a4 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c @@ -0,0 +1,1079 @@ +/* + * ***** BEGIN GPL 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_manipulator_ruler.c + * \ingroup spview3d + */ + +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_rect.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "BKE_context.h" +#include "BKE_object.h" +#include "BKE_gpencil.h" +#include "BKE_unit.h" + +#include "DNA_object_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_view3d_types.h" + +#include "BIF_gl.h" + +#include "ED_screen.h" +#include "ED_transform_snap_object_context.h" +#include "ED_view3d.h" + +#include "UI_resources.h" +#include "UI_interface.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "view3d_intern.h" /* own include */ + +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_select.h" + +#include "BLF_api.h" + + +static const char *view3d_wgt_ruler_id = "VIEW3D_WGT_ruler"; + + +#define MVAL_MAX_PX_DIST 12.0f + +/* -------------------------------------------------------------------- */ +/* Ruler Item (we can have many) */ +enum { + RULERITEM_USE_ANGLE = (1 << 0), /* use protractor */ + RULERITEM_USE_RAYCAST = (1 << 1) +}; + +enum { + RULERITEM_DIRECTION_IN = 0, + RULERITEM_DIRECTION_OUT +}; + +/* keep smaller then selection, since we may want click elsewhere without selecting a ruler */ +#define RULER_PICK_DIST 12.0f +#define RULER_PICK_DIST_SQ (RULER_PICK_DIST * RULER_PICK_DIST) + +/* not clicking on a point */ +#define PART_LINE 0xff + +/* -------------------------------------------------------------------- */ +/* Ruler Info (wmManipulatorGroup customdata) */ + +enum { + RULER_STATE_NORMAL = 0, + RULER_STATE_DRAG +}; + +enum { + RULER_SNAP_OK = (1 << 0), +}; + +typedef struct RulerInfo { + // ListBase items; + int item_active; + int flag; + int snap_flag; + int state; + + struct SnapObjectContext *snap_context; + + /* wm state */ + wmWindow *win; + ScrArea *sa; + ARegion *ar; /* re-assigned every modal update */ +} RulerInfo; + +/* -------------------------------------------------------------------- */ +/* Ruler Item (two or three points) */ + +typedef struct RulerItem { + wmManipulator mpr; + + /* worldspace coords, middle being optional */ + float co[3][3]; + + int flag; + int raycast_dir; /* RULER_DIRECTION_* */ +} RulerItem; + +typedef struct RulerInteraction { + /* selected coord */ + char co_index; /* 0 -> 2 */ + float drag_start_co[3]; + uint inside_region : 1; +} RulerInteraction; + +/* -------------------------------------------------------------------- */ +/** \name Internal Ruler Utilities + * \{ */ + +static RulerItem *ruler_item_add(wmManipulatorGroup *mgroup) +{ + /* could pass this as an arg */ + const wmManipulatorType *wt_ruler = WM_manipulatortype_find("VIEW3D_WT_ruler_item", true); + RulerItem *ruler_item = (RulerItem *)WM_manipulator_new_ptr(wt_ruler, mgroup, NULL); + WM_manipulator_set_flag(&ruler_item->mpr, WM_MANIPULATOR_DRAW_MODAL, true); + return ruler_item; +} + +static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit, + char *numstr, size_t numstr_size, int prec) +{ + const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0; + + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + const float ruler_angle = angle_v3v3v3(ruler_item->co[0], + ruler_item->co[1], + ruler_item->co[2]); + + if (unit->system == USER_UNIT_NONE) { + BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle)); + } + else { + bUnit_AsString(numstr, numstr_size, + (double)ruler_angle, + prec, unit->system, B_UNIT_ROTATION, do_split, false); + } + } + else { + const float ruler_len = len_v3v3(ruler_item->co[0], + ruler_item->co[2]); + + if (unit->system == USER_UNIT_NONE) { + BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len); + } + else { + bUnit_AsString(numstr, numstr_size, + (double)(ruler_len * unit->scale_length), + prec, unit->system, B_UNIT_LENGTH, do_split, false); + } + } +} + +static bool view3d_ruler_pick( + wmManipulatorGroup *mgroup, RulerItem *ruler_item, const float mval[2], + int *r_co_index) +{ + RulerInfo *ruler_info = mgroup->customdata; + ARegion *ar = ruler_info->ar; + bool found = false; + + float dist_best = RULER_PICK_DIST_SQ; + int co_index_best = -1; + + { + float co_ss[3][2]; + float dist; + int j; + + /* should these be checked? - ok for now not to */ + for (j = 0; j < 3; j++) { + ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP); + } + + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + dist = min_ff(dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[1]), + dist_squared_to_line_segment_v2(mval, co_ss[1], co_ss[2])); + if (dist < dist_best) { + dist_best = dist; + found = true; + + { + const float dist_points[3] = { + len_squared_v2v2(co_ss[0], mval), + len_squared_v2v2(co_ss[1], mval), + len_squared_v2v2(co_ss[2], mval), + }; + if (min_fff(UNPACK3(dist_points)) < RULER_PICK_DIST_SQ) { + co_index_best = min_axis_v3(dist_points); + } + else { + co_index_best = -1; + } + } + } + } + else { + dist = dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[2]); + if (dist < dist_best) { + dist_best = dist; + found = true; + + { + const float dist_points[2] = { + len_squared_v2v2(co_ss[0], mval), + len_squared_v2v2(co_ss[2], mval), + }; + if (min_ff(UNPACK2(dist_points)) < RULER_PICK_DIST_SQ) { + co_index_best = (dist_points[0] < dist_points[1]) ? 0 : 2; + } + else { + co_index_best = -1; + } + } + } + } + } + + *r_co_index = co_index_best; + return found; +} + +/** + * Ensure the 'snap_context' is only cached while dragging, + * needed since the user may toggle modes between tool use. + */ +static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) +{ + if (state == ruler_info->state) { + return; + } + + /* always remove */ + if (ruler_info->snap_context) { + ED_transform_snap_object_context_destroy(ruler_info->snap_context); + ruler_info->snap_context = NULL; + } + + if (state == RULER_STATE_NORMAL) { + /* pass */ + } + else if (state == RULER_STATE_DRAG) { + ruler_info->snap_context = ED_transform_snap_object_context_create_view3d( + CTX_data_main(C), CTX_data_scene(C), CTX_data_scene_layer(C), CTX_data_engine(C), 0, + ruler_info->ar, CTX_wm_view3d(C)); + } + else { + BLI_assert(0); + } + + ruler_info->state = state; +} + +static void view3d_ruler_item_project( + RulerInfo *ruler_info, float r_co[3], + const int xy[2]) +{ + ED_view3d_win_to_3d_int(ruler_info->sa->spacedata.first, ruler_info->ar, r_co, xy, r_co); +} + +/* use for mousemove events */ +static bool view3d_ruler_item_mousemove( + RulerInfo *ruler_info, RulerItem *ruler_item, const int mval[2], + const bool do_thickness, const bool do_snap) +{ + RulerInteraction *inter = ruler_item->mpr.interaction_data; + const float eps_bias = 0.0002f; + float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */ + + ruler_info->snap_flag &= ~RULER_SNAP_OK; + + if (ruler_item) { + float *co = ruler_item->co[inter->co_index]; + /* restore the initial depth */ + copy_v3_v3(co, inter->drag_start_co); + view3d_ruler_item_project(ruler_info, co, mval); + if (do_thickness && inter->co_index != 1) { + // Scene *scene = CTX_data_scene(C); + // View3D *v3d = ruler_info->sa->spacedata.first; + const float mval_fl[2] = {UNPACK2(mval)}; + float ray_normal[3]; + float ray_start[3]; + float *co_other; + + co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0]; + + if (ED_transform_snap_object_project_view3d_mixed( + ruler_info->snap_context, + SCE_SELECT_FACE, + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + .use_object_edit_cage = true, + }, + mval_fl, &dist_px, true, + co, ray_normal)) + { + negate_v3(ray_normal); + /* add some bias */ + madd_v3_v3v3fl(ray_start, co, ray_normal, eps_bias); + ED_transform_snap_object_project_ray( + ruler_info->snap_context, + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + .use_object_edit_cage = true, + }, + ray_start, ray_normal, NULL, + co_other, NULL); + } + } + else if (do_snap) { + // Scene *scene = CTX_data_scene(C); + View3D *v3d = ruler_info->sa->spacedata.first; + const float mval_fl[2] = {UNPACK2(mval)}; + bool use_depth = (v3d->drawtype >= OB_SOLID); + + if (ED_transform_snap_object_project_view3d_mixed( + ruler_info->snap_context, + (SCE_SELECT_VERTEX | SCE_SELECT_EDGE) | (use_depth ? SCE_SELECT_FACE : 0), + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + .use_object_edit_cage = true, + }, + mval_fl, &dist_px, use_depth, + co, NULL)) + { + ruler_info->snap_flag |= RULER_SNAP_OK; + } + } + return true; + } + else { + return false; + } +} + + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Ruler/Grease Pencil Conversion + * \{ */ + +#define RULER_ID "RulerData3D" +static bool view3d_ruler_to_gpencil(bContext *C, wmManipulatorGroup *mgroup) +{ + // RulerInfo *ruler_info = mgroup->customdata; + Scene *scene = CTX_data_scene(C); + bGPDlayer *gpl; + bGPDframe *gpf; + bGPDstroke *gps; + bGPDpalette *palette; + bGPDpalettecolor *palcolor; + RulerItem *ruler_item; + const char *ruler_name = RULER_ID; + bool changed = false; + + if (scene->gpd == NULL) { + scene->gpd = BKE_gpencil_data_addnew("GPencil"); + } + + gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); + if (gpl == NULL) { + gpl = BKE_gpencil_layer_addnew(scene->gpd, ruler_name, false); + gpl->thickness = 1; + gpl->flag |= GP_LAYER_HIDE; + } + + /* try to get active palette or create a new one */ + palette = BKE_gpencil_palette_getactive(scene->gpd); + if (palette == NULL) { + palette = BKE_gpencil_palette_addnew(scene->gpd, DATA_("GP_Palette"), true); + } + /* try to get color with the ruler name or create a new one */ + palcolor = BKE_gpencil_palettecolor_getbyname(palette, (char *)ruler_name); + if (palcolor == NULL) { + palcolor = BKE_gpencil_palettecolor_addnew(palette, (char *)ruler_name, true); + } + + gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true); + BKE_gpencil_free_strokes(gpf); + + for (ruler_item = mgroup->manipulators.first; ruler_item; ruler_item = (RulerItem *)ruler_item->mpr.next) { + bGPDspoint *pt; + int j; + + /* allocate memory for a new stroke */ + gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + gps->totpoints = 3; + pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + for (j = 0; j < 3; j++) { + copy_v3_v3(&pt->x, ruler_item->co[j]); + pt->pressure = 1.0f; + pt->strength = 1.0f; + pt++; + } + } + else { + gps->totpoints = 2; + pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + for (j = 0; j < 3; j += 2) { + copy_v3_v3(&pt->x, ruler_item->co[j]); + pt->pressure = 1.0f; + pt->strength = 1.0f; + pt++; + } + } + gps->flag = GP_STROKE_3DSPACE; + gps->thickness = 3; + /* assign color to stroke */ + BLI_strncpy(gps->colorname, palcolor->info, sizeof(gps->colorname)); + gps->palcolor = palcolor; + BLI_addtail(&gpf->strokes, gps); + changed = true; + } + + return changed; +} + +static bool view3d_ruler_from_gpencil(const bContext *C, wmManipulatorGroup *mgroup) +{ + Scene *scene = CTX_data_scene(C); + bool changed = false; + + if (scene->gpd) { + bGPDlayer *gpl; + const char *ruler_name = RULER_ID; + gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); + if (gpl) { + bGPDframe *gpf; + gpf = BKE_gpencil_layer_getframe(gpl, CFRA, false); + if (gpf) { + bGPDstroke *gps; + for (gps = gpf->strokes.first; gps; gps = gps->next) { + bGPDspoint *pt = gps->points; + int j; + RulerItem *ruler_item = NULL; + if (gps->totpoints == 3) { + ruler_item = ruler_item_add(mgroup); + for (j = 0; j < 3; j++) { + copy_v3_v3(ruler_item->co[j], &pt->x); + pt++; + } + ruler_item->flag |= RULERITEM_USE_ANGLE; + changed = true; + } + else if (gps->totpoints == 2) { + ruler_item = ruler_item_add(mgroup); + for (j = 0; j < 3; j += 2) { + copy_v3_v3(ruler_item->co[j], &pt->x); + pt++; + } + changed = true; + } + } + } + } + } + + return changed; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Ruler Item Manipulator Type + * \{ */ + +static void manipulator_ruler_draw(const bContext *C, wmManipulator *mpr) +{ + Scene *scene = CTX_data_scene(C); + UnitSettings *unit = &scene->unit; + RulerInfo *ruler_info = mpr->parent_mgroup->customdata; + RulerItem *ruler_item = (RulerItem *)mpr; + ARegion *ar = ruler_info->ar; + RegionView3D *rv3d = ar->regiondata; + const float cap_size = 4.0f; + const float bg_margin = 4.0f * U.pixelsize; + const float bg_radius = 4.0f * U.pixelsize; + const float arc_size = 64.0f * U.pixelsize; +#define ARC_STEPS 24 + const int arc_steps = ARC_STEPS; + const float color_act[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const float color_base[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + unsigned char color_text[3]; + unsigned char color_wire[3]; + float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f}; + + /* anti-aliased lines for more consistent appearance */ + glEnable(GL_LINE_SMOOTH); + + BLF_enable(blf_mono_font, BLF_ROTATION); + BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi); + BLF_rotation(blf_mono_font, 0.0f); + + UI_GetThemeColor3ubv(TH_TEXT, color_text); + UI_GetThemeColor3ubv(TH_WIRE, color_wire); + + const bool is_act = (mpr->flag & WM_MANIPULATOR_DRAW_HOVER); + float dir_ruler[2]; + float co_ss[3][2]; + int j; + + /* should these be checked? - ok for now not to */ + for (j = 0; j < 3; j++) { + ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP); + } + + glEnable(GL_BLEND); + + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 2); /* "advanced" mode */ + const float *col = is_act ? color_act : color_base; + immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2); + immUniform1f("dash_width", 6.0f); + + immBegin(GWN_PRIM_LINE_STRIP, 3); + + immVertex2fv(shdr_pos, co_ss[0]); + immVertex2fv(shdr_pos, co_ss[1]); + immVertex2fv(shdr_pos, co_ss[2]); + + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* arc */ + { + float dir_tmp[3]; + float co_tmp[3]; + float arc_ss_coord[2]; + + float dir_a[3]; + float dir_b[3]; + float quat[4]; + float axis[3]; + float angle; + const float px_scale = (ED_view3d_pixel_size(rv3d, ruler_item->co[1]) * + min_fff(arc_size, + len_v2v2(co_ss[0], co_ss[1]) / 2.0f, + len_v2v2(co_ss[2], co_ss[1]) / 2.0f)); + + sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]); + sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]); + normalize_v3(dir_a); + normalize_v3(dir_b); + + cross_v3_v3v3(axis, dir_a, dir_b); + angle = angle_normalized_v3v3(dir_a, dir_b); + + axis_angle_to_quat(quat, axis, angle / arc_steps); + + copy_v3_v3(dir_tmp, dir_a); + + immUniformColor3ubv(color_wire); + + immBegin(GWN_PRIM_LINE_STRIP, arc_steps + 1); + + for (j = 0; j <= arc_steps; j++) { + madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale); + ED_view3d_project_float_global(ar, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP); + mul_qt_v3(quat, dir_tmp); + + immVertex2fv(shdr_pos, arc_ss_coord); + } + + immEnd(); + } + + /* capping */ + { + float rot_90_vec_a[2]; + float rot_90_vec_b[2]; + float cap[2]; + + sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]); + rot_90_vec_a[0] = -dir_ruler[1]; + rot_90_vec_a[1] = dir_ruler[0]; + normalize_v2(rot_90_vec_a); + + sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]); + rot_90_vec_b[0] = -dir_ruler[1]; + rot_90_vec_b[1] = dir_ruler[0]; + normalize_v2(rot_90_vec_b); + + glEnable(GL_BLEND); + + immUniformColor3ubv(color_wire); + + immBegin(GWN_PRIM_LINES, 8); + + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size); + immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size); + immVertex2fv(shdr_pos, cap); + + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size); + immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size); + immVertex2fv(shdr_pos, cap); + + /* angle vertex */ + immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); + immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); + immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); + immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); + + immEnd(); + + glDisable(GL_BLEND); + } + + immUnbindProgram(); + + /* text */ + { + char numstr[256]; + float numstr_size[2]; + float posit[2]; + const int prec = 2; /* XXX, todo, make optional */ + + ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); + + BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); + + posit[0] = co_ss[1][0] + (cap_size * 2.0f); + posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f); + + /* draw text (bg) */ + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_aa( + true, + posit[0] - bg_margin, posit[1] - bg_margin, + posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1], + bg_radius, color_back); + /* draw text */ + BLF_color3ubv(blf_mono_font, color_text); + BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); + BLF_rotation(blf_mono_font, 0.0f); + BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + } + } + else { + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 2); /* "advanced" mode */ + const float *col = is_act ? color_act : color_base; + immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2); + immUniform1f("dash_width", 6.0f); + + immBegin(GWN_PRIM_LINES, 2); + + immVertex2fv(shdr_pos, co_ss[0]); + immVertex2fv(shdr_pos, co_ss[2]); + + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); + + /* capping */ + { + float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]}; + float cap[2]; + + normalize_v2(rot_90_vec); + + glEnable(GL_BLEND); + + immUniformColor3ubv(color_wire); + + immBegin(GWN_PRIM_LINES, 4); + + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size); + immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size); + immVertex2fv(shdr_pos, cap); + + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size); + immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size); + immVertex2fv(shdr_pos, cap); + + immEnd(); + + glDisable(GL_BLEND); + } + + immUnbindProgram(); + + /* text */ + { + char numstr[256]; + float numstr_size[2]; + const int prec = 6; /* XXX, todo, make optional */ + float posit[2]; + + ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); + + BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); + + mid_v2_v2v2(posit, co_ss[0], co_ss[2]); + + /* center text */ + posit[0] -= numstr_size[0] / 2.0f; + posit[1] -= numstr_size[1] / 2.0f; + + /* draw text (bg) */ + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_aa( + true, + posit[0] - bg_margin, posit[1] - bg_margin, + posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1], + bg_radius, color_back); + /* draw text */ + BLF_color3ubv(blf_mono_font, color_text); + BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); + BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + } + } + + glDisable(GL_LINE_SMOOTH); + + BLF_disable(blf_mono_font, BLF_ROTATION); + +#undef ARC_STEPS + + /* draw snap */ + if ((ruler_info->snap_flag & RULER_SNAP_OK) && + (ruler_info->state == RULER_STATE_DRAG) && + (ruler_item->mpr.interaction_data != NULL)) + { + RulerInteraction *inter = ruler_item->mpr.interaction_data; + /* size from drawSnapping */ + const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); + float co_ss_snap[3]; + ED_view3d_project_float_global(ar, ruler_item->co[inter->co_index], co_ss_snap, V3D_PROJ_TEST_NOP); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv(color_act); + + imm_draw_circle_wire_2d(pos, co_ss_snap[0], co_ss_snap[1], size * U.pixelsize, 32); + + immUnbindProgram(); + } +} + +static int manipulator_ruler_test_select( + bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event) +{ + RulerItem *ruler_item_pick = (RulerItem *)mpr; + float mval_fl[2] = {UNPACK2(event->mval)}; + int co_index; + + /* select and drag */ + if (view3d_ruler_pick(mpr->parent_mgroup, ruler_item_pick, mval_fl, &co_index)) { + if (co_index == -1) { + if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) { + return PART_LINE; + } + } + else { + return co_index; + } + } + return -1; +} + +static int manipulator_ruler_modal( + bContext *C, wmManipulator *mpr, const wmEvent *event, + eWM_ManipulatorTweak UNUSED(tweak_flag)) +{ + bool do_draw = false; + int exit_code = OPERATOR_RUNNING_MODAL; + RulerInfo *ruler_info = mpr->parent_mgroup->customdata; + RulerItem *ruler_item = (RulerItem *)mpr; + RulerInteraction *inter = ruler_item->mpr.interaction_data; + ARegion *ar = CTX_wm_region(C); + + ruler_info->ar = ar; + + switch (event->type) { + case MOUSEMOVE: + { + if (ruler_info->state == RULER_STATE_DRAG) { + if (view3d_ruler_item_mousemove( + ruler_info, ruler_item, event->mval, + event->shift != 0, event->ctrl != 0)) + { + do_draw = true; + } + inter->inside_region = BLI_rcti_isect_pt_v(&ar->winrct, &event->x); + } + break; + } + } + if (do_draw) { + ED_region_tag_redraw(ar); + } + return exit_code; +} + +static int manipulator_ruler_invoke( + bContext *C, wmManipulator *mpr, const wmEvent *event) +{ + wmManipulatorGroup *mgroup = mpr->parent_mgroup; + RulerInfo *ruler_info = mgroup->customdata; + RulerItem *ruler_item_pick = (RulerItem *)mpr; + RulerInteraction *inter = MEM_callocN(sizeof(RulerInteraction), __func__); + mpr->interaction_data = inter; + + ARegion *ar = ruler_info->ar; + + const float mval_fl[2] = {UNPACK2(event->mval)}; + + /* select and drag */ + if (mpr->highlight_part == PART_LINE) { + if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) { + /* Add Center Point */ + ruler_item_pick->flag |= RULERITEM_USE_ANGLE; + inter->co_index = 1; + ruler_state_set(C, ruler_info, RULER_STATE_DRAG); + + /* find the factor */ + { + float co_ss[2][2]; + float fac; + + ED_view3d_project_float_global(ar, ruler_item_pick->co[0], co_ss[0], V3D_PROJ_TEST_NOP); + ED_view3d_project_float_global(ar, ruler_item_pick->co[2], co_ss[1], V3D_PROJ_TEST_NOP); + + fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]); + CLAMP(fac, 0.0f, 1.0f); + + interp_v3_v3v3(ruler_item_pick->co[1], + ruler_item_pick->co[0], + ruler_item_pick->co[2], fac); + } + + /* update the new location */ + view3d_ruler_item_mousemove( + ruler_info, ruler_item_pick, event->mval, + event->shift != 0, event->ctrl != 0); + } + } + else { + inter->co_index = mpr->highlight_part; + ruler_state_set(C, ruler_info, RULER_STATE_DRAG); + + /* store the initial depth */ + copy_v3_v3(inter->drag_start_co, ruler_item_pick->co[inter->co_index]); + } + + return OPERATOR_RUNNING_MODAL; +} + +static void manipulator_ruler_exit(bContext *C, wmManipulator *mpr, const bool cancel) +{ + wmManipulatorGroup *mgroup = mpr->parent_mgroup; + RulerInfo *ruler_info = mgroup->customdata; + RulerItem *ruler_item = (RulerItem *)mpr; + RulerInteraction *inter = mpr->interaction_data; + + if (!cancel) { + if (ruler_info->state == RULER_STATE_DRAG) { + /* rubber-band angle removal */ + if (ruler_item && (inter->co_index == 1) && (ruler_item->flag & RULERITEM_USE_ANGLE)) { + if (!inter->inside_region) { + ruler_item->flag &= ~RULERITEM_USE_ANGLE; + } + } + if (ruler_info->snap_flag & RULER_SNAP_OK) { + ruler_info->snap_flag &= ~RULER_SNAP_OK; + } + ruler_state_set(C, ruler_info, RULER_STATE_NORMAL); + } + /* We could convert only the current manipulator, for now just re-generate. */ + view3d_ruler_to_gpencil(C, mgroup); + } + + MEM_SAFE_FREE(mpr->interaction_data); + + ruler_state_set(C, ruler_info, RULER_STATE_NORMAL); +} + +static int manipulator_ruler_cursor_get(wmManipulator *mpr) +{ + if (mpr->highlight_part == PART_LINE) { + return BC_CROSSCURSOR; + } + return BC_NSEW_SCROLLCURSOR; +} + +void VIEW3D_WT_ruler_item(wmManipulatorType *wt) +{ + /* identifiers */ + wt->idname = "VIEW3D_WT_ruler_item"; + + /* api callbacks */ + wt->draw = manipulator_ruler_draw; + wt->test_select = manipulator_ruler_test_select; + wt->modal = manipulator_ruler_modal; + wt->invoke = manipulator_ruler_invoke; + wt->exit = manipulator_ruler_exit; + wt->cursor_get = manipulator_ruler_cursor_get; + + wt->struct_size = sizeof(RulerItem); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Ruler Manipulator Group + * \{ */ + +static bool WIDGETGROUP_ruler_poll(const bContext *C, wmManipulatorGroupType *wgt) +{ + WorkSpace *workspace = CTX_wm_workspace(C); + if (!STREQ(wgt->idname, workspace->tool.manipulator_group)) { + WM_manipulator_group_type_unlink_delayed_ptr(wgt); + return false; + } + return true; +} + +static void WIDGETGROUP_ruler_setup(const bContext *C, wmManipulatorGroup *mgroup) +{ + RulerInfo *ruler_info = MEM_callocN(sizeof(RulerInfo), __func__); + + if (view3d_ruler_from_gpencil(C, mgroup)) { + /* nop */ + } + + wmWindow *win = CTX_wm_window(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + ruler_info->win = win; + ruler_info->sa = sa; + ruler_info->ar = ar; + + mgroup->customdata = ruler_info; +} + +void VIEW3D_WGT_ruler(wmManipulatorGroupType *wgt) +{ + wgt->name = "Ruler Widgets"; + wgt->idname = view3d_wgt_ruler_id; + + wgt->flag |= WM_MANIPULATORGROUPTYPE_SCALE; + + wgt->mmap_params.spaceid = SPACE_VIEW3D; + wgt->mmap_params.regionid = RGN_TYPE_WINDOW; + + wgt->poll = WIDGETGROUP_ruler_poll; + wgt->setup = WIDGETGROUP_ruler_setup; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Add Ruler Operator + * \{ */ + +static int view3d_ruler_poll(bContext *C) +{ + WorkSpace *workspace = CTX_wm_workspace(C); + if (!STREQ(view3d_wgt_ruler_id, workspace->tool.manipulator_group) || + CTX_wm_region_view3d(C) == NULL) + { + return false; + } + return true; +} + +static int view3d_ruler_add_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = ar->regiondata; + + wmManipulatorMap *mmap = ar->manipulator_map; + wmManipulatorGroup *mgroup = WM_manipulatormap_group_find(mmap, view3d_wgt_ruler_id); + const bool use_depth = (v3d->drawtype >= OB_SOLID); + + /* Create new line */ + RulerItem *ruler_item; + ruler_item = ruler_item_add(mgroup); + + /* This is a little weak, but there is no real good way to tweak directly. */ + WM_manipulator_highlight_set(mmap, &ruler_item->mpr); + if (WM_operator_name_call( + C, "MANIPULATORGROUP_OT_manipulator_tweak", + WM_OP_INVOKE_REGION_WIN, NULL) == OPERATOR_RUNNING_MODAL) + { + RulerInfo *ruler_info = mgroup->customdata; + RulerInteraction *inter = ruler_item->mpr.interaction_data; + if (use_depth) { + /* snap the first point added, not essential but handy */ + inter->co_index = 0; + view3d_ruler_item_mousemove(ruler_info, ruler_item, event->mval, false, true); + copy_v3_v3(inter->drag_start_co, ruler_item->co[inter->co_index]); + } + else { + negate_v3_v3(inter->drag_start_co, rv3d->ofs); + copy_v3_v3(ruler_item->co[0], inter->drag_start_co); + view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval); + } + + copy_v3_v3(ruler_item->co[2], ruler_item->co[0]); + ruler_item->mpr.highlight_part = inter->co_index = 2; + } + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_ruler_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Ruler Add"; + ot->idname = "VIEW3D_OT_ruler_add"; + ot->description = ""; + + ot->invoke = view3d_ruler_add_invoke; + ot->poll = view3d_ruler_poll; + + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index d71639c35d2..568343f8ec8 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -119,8 +119,8 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op) if (RNA_boolean_get(op->ptr, "autoselect")) flag |= FILE_AUTOSELECT; - if (RNA_boolean_get(op->ptr, "active_layer")) - flag |= FILE_ACTIVELAY; + if (RNA_boolean_get(op->ptr, "active_collection")) + flag |= FILE_ACTIVE_COLLECTION; BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend"); if (BKE_copybuffer_paste(C, str, flag, op->reports)) { @@ -152,7 +152,7 @@ static void VIEW3D_OT_pastebuffer(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select pasted objects"); - RNA_def_boolean(ot->srna, "active_layer", true, "Active Layer", "Put pasted objects on the active layer"); + RNA_def_boolean(ot->srna, "active_collection", true, "Active Collection", "Put pasted objects on the active collection"); } /* ************************** registration **********************************/ @@ -193,7 +193,6 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_render_border); WM_operatortype_append(VIEW3D_OT_clear_render_border); WM_operatortype_append(VIEW3D_OT_zoom_border); - WM_operatortype_append(VIEW3D_OT_manipulator); WM_operatortype_append(VIEW3D_OT_enable_manipulator); WM_operatortype_append(VIEW3D_OT_cursor3d); WM_operatortype_append(VIEW3D_OT_select_lasso); @@ -201,7 +200,6 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_camera_to_view); WM_operatortype_append(VIEW3D_OT_camera_to_view_selected); WM_operatortype_append(VIEW3D_OT_object_as_camera); - WM_operatortype_append(VIEW3D_OT_localview); WM_operatortype_append(VIEW3D_OT_game_start); WM_operatortype_append(VIEW3D_OT_fly); WM_operatortype_append(VIEW3D_OT_walk); @@ -224,6 +222,8 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_toggle_render); + WM_operatortype_append(VIEW3D_OT_ruler_add); + transform_operatortypes(); } @@ -240,24 +240,7 @@ void view3d_keymap(wmKeyConfig *keyconf) /* only for region 3D window */ keymap = WM_keymap_find(keyconf, "3D View", SPACE_VIEW3D, 0); - /* Shift+LMB behavior first, so it has priority over KM_ANY item below. */ - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", true); - RNA_boolean_set(kmi->ptr, "use_accurate", false); - - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", false); - RNA_boolean_set(kmi->ptr, "use_accurate", true); - - /* Using KM_ANY here to allow holding modifiers before starting to transform. */ - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_ANY, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", false); - RNA_boolean_set(kmi->ptr, "use_accurate", false); - - WM_keymap_verify_item(keymap, "VIEW3D_OT_cursor3d", ACTIONMOUSE, KM_PRESS, 0, 0); + WM_keymap_verify_item(keymap, "VIEW3D_OT_cursor3d", ACTIONMOUSE, KM_CLICK, 0, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_rotate", MIDDLEMOUSE, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_move", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0); @@ -372,8 +355,6 @@ void view3d_keymap(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD7, KM_PRESS, KM_SHIFT | KM_CTRL, 0); RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_BOTTOM); RNA_boolean_set(kmi->ptr, "align_active", true); - - WM_keymap_add_item(keymap, "VIEW3D_OT_localview", PADSLASHKEY, KM_PRESS, 0, 0); #ifdef WITH_INPUT_NDOF /* note: positioned here so keymaps show keyboard keys if assigned */ diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 65a6dee2f6c..f8b02f0b405 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -36,14 +36,13 @@ #include "BLI_sys_types.h" /* int64_t */ -#include "BIF_gl.h" /* bglMats */ -#include "BIF_glutil.h" /* bglMats */ - #include "BLI_math_vector.h" #include "BKE_camera.h" #include "BKE_screen.h" +#include "GPU_matrix.h" + #include "ED_view3d.h" /* own include */ #define BL_NEAR_CLIP 0.001 @@ -656,16 +655,22 @@ void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, float obm } /** - * Uses window coordinates (x,y) and depth component z to find a point in - * modelspace */ -void ED_view3d_unproject(bglMats *mats, float out[3], const float x, const float y, const float z) + * Convert between region relative coordinates (x,y) and depth component z and + * a point in world space. */ +void ED_view3d_project(const struct ARegion *ar, const float world[3], float region[3]) { - double ux, uy, uz; + // viewport is set up to make coordinates relative to the region, not window + RegionView3D *rv3d = ar->regiondata; + int viewport[4] = {0, 0, ar->winx, ar->winy}; - gluUnProject(x, y, z, mats->modelview, mats->projection, - (GLint *)mats->viewport, &ux, &uy, &uz); + gpuProject(world, rv3d->viewmat, rv3d->winmat, viewport, region); +} + +bool ED_view3d_unproject(const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3]) +{ + RegionView3D *rv3d = ar->regiondata; + int viewport[4] = {0, 0, ar->winx, ar->winy}; + float region[3] = {regionx, regiony, regionz}; - out[0] = ux; - out[1] = uy; - out[2] = uz; + return gpuUnProject(region, rv3d->viewmat, rv3d->winmat, viewport, world); } diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index f2c87953302..03f4f506c13 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -43,6 +43,9 @@ #include "BIF_gl.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" + #include "WM_api.h" #include "WM_types.h" @@ -279,7 +282,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) } else if (state == RULER_STATE_DRAG) { ruler_info->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), 0, + CTX_data_main(C), CTX_data_scene(C), CTX_data_scene_layer(C), CTX_data_engine(C), 0, ruler_info->ar, CTX_wm_view3d(C)); } else { @@ -425,12 +428,11 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a #define ARC_STEPS 24 const int arc_steps = ARC_STEPS; int i; - //unsigned int color_act = 0x666600; - unsigned int color_act = 0xffffff; - unsigned int color_base = 0x0; - unsigned char color_back[4] = {0xff, 0xff, 0xff, 0x80}; + const float color_act[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const float color_base[4] = {0.0f, 0.0f, 0.0f, 1.0f}; unsigned char color_text[3]; unsigned char color_wire[3]; + float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f}; /* anti-aliased lines for more consistent appearance */ glEnable(GL_LINE_SMOOTH); @@ -455,28 +457,37 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a glEnable(GL_BLEND); - cpack(is_act ? color_act : color_base); + const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); if (ruler_item->flag & RULERITEM_USE_ANGLE) { - glBegin(GL_LINE_STRIP); - for (j = 0; j < 3; j++) { - glVertex2fv(co_ss[j]); - } - glEnd(); - cpack(0xaaaaaa); - setlinestyle(3); - glBegin(GL_LINE_STRIP); - for (j = 0; j < 3; j++) { - glVertex2fv(co_ss[j]); - } - glEnd(); - setlinestyle(0); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 2); /* "advanced" mode */ + const float *col = is_act ? color_act : color_base; + immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2); + immUniform1f("dash_width", 6.0f); + + immBegin(GWN_PRIM_LINE_STRIP, 3); + + immVertex2fv(shdr_pos, co_ss[0]); + immVertex2fv(shdr_pos, co_ss[1]); + immVertex2fv(shdr_pos, co_ss[2]); + + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* arc */ { float dir_tmp[3]; float co_tmp[3]; - float arc_ss_coords[ARC_STEPS + 1][2]; + float arc_ss_coord[2]; float dir_a[3]; float dir_b[3]; @@ -500,46 +511,19 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a copy_v3_v3(dir_tmp, dir_a); - glColor3ubv(color_wire); + immUniformColor3ubv(color_wire); + + immBegin(GWN_PRIM_LINE_STRIP, arc_steps + 1); for (j = 0; j <= arc_steps; j++) { madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale); - ED_view3d_project_float_global(ar, co_tmp, arc_ss_coords[j], V3D_PROJ_TEST_NOP); + ED_view3d_project_float_global(ar, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP); mul_qt_v3(quat, dir_tmp); - } - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, arc_ss_coords); - glDrawArrays(GL_LINE_STRIP, 0, arc_steps + 1); - glDisableClientState(GL_VERTEX_ARRAY); - } - /* text */ - { - char numstr[256]; - float numstr_size[2]; - float pos[2]; - const int prec = 2; /* XXX, todo, make optional */ - - ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); - - BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); - - pos[0] = co_ss[1][0] + (cap_size * 2.0f); - pos[1] = co_ss[1][1] - (numstr_size[1] / 2.0f); + immVertex2fv(shdr_pos, arc_ss_coord); + } - /* draw text (bg) */ - glColor4ubv(color_back); - UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox( - pos[0] - bg_margin, pos[1] - bg_margin, - pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1], - bg_radius); - /* draw text */ - glColor3ubv(color_text); - BLF_position(blf_mono_font, pos[0], pos[1], 0.0f); - BLF_rotation(blf_mono_font, 0.0f); - BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + immEnd(); } /* capping */ @@ -560,75 +544,84 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a glEnable(GL_BLEND); - glColor3ubv(color_wire); + immUniformColor3ubv(color_wire); - glBegin(GL_LINES); + immBegin(GWN_PRIM_LINES, 8); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); /* angle vertex */ - glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); - glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); - glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); - glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); - glEnd(); + immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); + immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); + immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); + immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); + + immEnd(); glDisable(GL_BLEND); } - } - else { - glBegin(GL_LINE_STRIP); - for (j = 0; j < 3; j += 2) { - glVertex2fv(co_ss[j]); - } - glEnd(); - cpack(0xaaaaaa); - setlinestyle(3); - glBegin(GL_LINE_STRIP); - for (j = 0; j < 3; j += 2) { - glVertex2fv(co_ss[j]); - } - glEnd(); - setlinestyle(0); - sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); + immUnbindProgram(); /* text */ { char numstr[256]; float numstr_size[2]; - const int prec = 6; /* XXX, todo, make optional */ - float pos[2]; + float posit[2]; + const int prec = 2; /* XXX, todo, make optional */ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); - mid_v2_v2v2(pos, co_ss[0], co_ss[2]); - - /* center text */ - pos[0] -= numstr_size[0] / 2.0f; - pos[1] -= numstr_size[1] / 2.0f; + posit[0] = co_ss[1][0] + (cap_size * 2.0f); + posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f); /* draw text (bg) */ - glColor4ubv(color_back); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox(pos[0] - bg_margin, pos[1] - bg_margin, - pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1], - bg_radius); + UI_draw_roundbox_aa(true, + posit[0] - bg_margin, posit[1] - bg_margin, + posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1], + bg_radius, color_back); /* draw text */ - glColor3ubv(color_text); - BLF_position(blf_mono_font, pos[0], pos[1], 0.0f); + BLF_color3ubv(blf_mono_font, color_text); + BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); + BLF_rotation(blf_mono_font, 0.0f); BLF_draw(blf_mono_font, numstr, sizeof(numstr)); } + } + else { + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + + immUniform1i("num_colors", 2); /* "advanced" mode */ + const float *col = is_act ? color_act : color_base; + immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2); + immUniform1f("dash_width", 6.0f); + + immBegin(GWN_PRIM_LINES, 2); + + immVertex2fv(shdr_pos, co_ss[0]); + immVertex2fv(shdr_pos, co_ss[2]); + + immEnd(); + + immUnbindProgram(); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); /* capping */ { @@ -638,22 +631,56 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a normalize_v2(rot_90_vec); glEnable(GL_BLEND); - glColor3ubv(color_wire); - glBegin(GL_LINES); + immUniformColor3ubv(color_wire); + + immBegin(GWN_PRIM_LINES, 4); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size); - glVertex2fv(cap); + immVertex2fv(shdr_pos, cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size); - glVertex2fv(cap); - glEnd(); + immVertex2fv(shdr_pos, cap); + + immEnd(); glDisable(GL_BLEND); } + + immUnbindProgram(); + + /* text */ + { + char numstr[256]; + float numstr_size[2]; + const int prec = 6; /* XXX, todo, make optional */ + float posit[2]; + + ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); + + BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); + + mid_v2_v2v2(posit, co_ss[0], co_ss[2]); + + /* center text */ + posit[0] -= numstr_size[0] / 2.0f; + posit[1] -= numstr_size[1] / 2.0f; + + /* draw text (bg) */ + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_aa(true, + posit[0] - bg_margin, posit[1] - bg_margin, + posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1], + bg_radius, color_back); + /* draw text */ + BLF_color3ubv(blf_mono_font, color_text); + BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); + BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + } } } @@ -672,8 +699,14 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a float co_ss[3]; ED_view3d_project_float_global(ar, ruler_item->co[ruler_item->co_index], co_ss, V3D_PROJ_TEST_NOP); - cpack(color_act); - circ(co_ss[0], co_ss[1], size * U.pixelsize); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv(color_act); + + imm_draw_circle_wire_2d(pos, co_ss[0], co_ss[1], size * U.pixelsize, 32); + + immUnbindProgram(); } } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 05cf552e5cc..297bd5c4aa1 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -63,16 +63,16 @@ #include "BKE_armature.h" #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" +#include "BKE_layer.h" #include "BKE_mball.h" #include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_editmesh.h" +#include "BKE_scene.h" #include "BKE_tracking.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" +#include "DEG_depsgraph.h" #include "WM_api.h" #include "WM_types.h" @@ -93,6 +93,8 @@ #include "UI_interface.h" #include "GPU_draw.h" +#include "GPU_glew.h" +#include "GPU_matrix.h" #include "view3d_intern.h" /* own include */ @@ -108,7 +110,10 @@ void view3d_set_viewcontext(bContext *C, ViewContext *vc) { memset(vc, 0, sizeof(ViewContext)); vc->ar = CTX_wm_region(C); + vc->depsgraph = CTX_data_depsgraph(C); vc->scene = CTX_data_scene(C); + vc->scene_layer = CTX_data_scene_layer(C); + vc->engine = CTX_data_engine(C); vc->v3d = CTX_wm_view3d(C); vc->win = CTX_wm_window(C); vc->rv3d = CTX_wm_region_view3d(C); @@ -116,34 +121,6 @@ void view3d_set_viewcontext(bContext *C, ViewContext *vc) vc->obedit = CTX_data_edit_object(C); } -/* - * ob == NULL if you want global matrices - * */ -void view3d_get_transformation(const ARegion *ar, RegionView3D *rv3d, Object *ob, bglMats *mats) -{ - float cpy[4][4]; - int i, j; - - if (ob) { - mul_m4_m4m4(cpy, rv3d->viewmat, ob->obmat); - } - else { - copy_m4_m4(cpy, rv3d->viewmat); - } - - for (i = 0; i < 4; ++i) { - for (j = 0; j < 4; ++j) { - mats->projection[i * 4 + j] = rv3d->winmat[i][j]; - mats->modelview[i * 4 + j] = cpy[i][j]; - } - } - - mats->viewport[0] = ar->winrct.xmin; - mats->viewport[1] = ar->winrct.ymin; - mats->viewport[2] = ar->winx; - mats->viewport[3] = ar->winy; -} - /* ********************** view3d_select: selection manipulations ********************* */ /* local prototypes */ @@ -394,18 +371,18 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[] bArmature *arm = ob->data; if (arm->flag & ARM_HAS_VIZ_DEPS) { /* mask modifier ('armature' mode), etc. */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } } -static void object_deselect_all_visible(Scene *scene, View3D *v3d) +static void object_deselect_all_visible(SceneLayer *sl) { Base *base; - for (base = scene->base.first; base; base = base->next) { - if (BASE_SELECTABLE(v3d, base)) { - ED_base_object_select(base, BA_DESELECT); + for (base = sl->object_bases.first; base; base = base->next) { + if (BASE_SELECTABLE(base)) { + ED_object_base_select(base, BA_DESELECT); } } } @@ -416,15 +393,14 @@ static void do_lasso_select_objects(ViewContext *vc, const int mcords[][2], cons Base *base; if (extend == false && select) - object_deselect_all_visible(vc->scene, vc->v3d); + object_deselect_all_visible(vc->scene_layer); - for (base = vc->scene->base.first; base; base = base->next) { - if (BASE_SELECTABLE(vc->v3d, base)) { /* use this to avoid un-needed lasso lookups */ + for (base = vc->scene_layer->object_bases.first; base; base = base->next) { + if (BASE_SELECTABLE(base)) { /* use this to avoid un-needed lasso lookups */ if (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) { if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) { - ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT); - base->object->flag = base->flag; + ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); } } if (vc->obact == base->object && (base->object->mode & OB_MODE_POSE)) { @@ -481,7 +457,9 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, cons } } -static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) +static void do_lasso_select_mesh( + const struct EvaluationContext *eval_ctx, ViewContext *vc, + const int mcords[][2], short moves, bool extend, bool select) { LassoSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; @@ -501,25 +479,25 @@ static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short m /* for non zbuf projections, don't change the GL state */ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - glLoadMatrixf(vc->rv3d->viewmat); - bbsel = EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + gpuLoadMatrix(vc->rv3d->viewmat); + bbsel = EDBM_backbuf_border_mask_init(eval_ctx, vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); if (ts->selectmode & SCE_SELECT_VERTEX) { if (bbsel) { edbm_backbuf_check_and_select_verts(vc->em, select); } else { - mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenVert(eval_ctx, vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } if (ts->selectmode & SCE_SELECT_EDGE) { /* Does both bbsel and non-bbsel versions (need screen cos for both) */ data.pass = 0; - mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); + mesh_foreachScreenEdge(eval_ctx, vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); if (data.is_done == false) { data.pass = 1; - mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); + mesh_foreachScreenEdge(eval_ctx, vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); } } @@ -528,7 +506,7 @@ static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short m edbm_backbuf_check_and_select_faces(vc->em, select); } else { - mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenFace(eval_ctx, vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -727,7 +705,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); } } -static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) +static void do_lasso_select_paintvert(const struct EvaluationContext *eval_ctx, ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) { const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Object *ob = vc->obact; @@ -745,7 +723,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh if (use_zbuf) { bm_vertoffs = me->totvert + 1; /* max index array */ - EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + EDBM_backbuf_border_mask_init(eval_ctx, vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); edbm_backbuf_check_and_select_verts_obmode(me, select); @@ -758,7 +736,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); - meshobject_foreachScreenVert(vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + meshobject_foreachScreenVert(eval_ctx, vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } @@ -767,7 +745,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh } paintvert_flush_flags(ob); } -static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) +static void do_lasso_select_paintface(const struct EvaluationContext *eval_ctx, ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) { Object *ob = vc->obact; Mesh *me = ob->data; @@ -782,7 +760,7 @@ static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], sh bm_vertoffs = me->totpoly + 1; /* max index array */ BLI_lasso_boundbox(&rect, mcords, moves); - EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + EDBM_backbuf_border_mask_init(eval_ctx, vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); edbm_backbuf_check_and_select_tfaces(me, select); @@ -828,16 +806,22 @@ static void view3d_lasso_select(bContext *C, ViewContext *vc, { Object *ob = CTX_data_active_object(C); + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + if (vc->obedit == NULL) { /* Object Mode */ - if (BKE_paint_select_face_test(ob)) - do_lasso_select_paintface(vc, mcords, moves, extend, select); - else if (BKE_paint_select_vert_test(ob)) - do_lasso_select_paintvert(vc, mcords, moves, extend, select); + if (BKE_paint_select_face_test(ob)) { + do_lasso_select_paintface(&eval_ctx, vc, mcords, moves, extend, select); + } + else if (BKE_paint_select_vert_test(ob)) { + do_lasso_select_paintvert(&eval_ctx, vc, mcords, moves, extend, select); + } else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { /* pass */ } - else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) + else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { PE_lasso_select(C, mcords, moves, extend, select); + } else { do_lasso_select_objects(vc, mcords, moves, extend, select); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); @@ -846,7 +830,7 @@ static void view3d_lasso_select(bContext *C, ViewContext *vc, else { /* Edit Mode */ switch (vc->obedit->type) { case OB_MESH: - do_lasso_select_mesh(vc, mcords, moves, extend, select); + do_lasso_select_mesh(&eval_ctx, vc, mcords, moves, extend, select); break; case OB_CURVE: case OB_SURF: @@ -930,7 +914,7 @@ static unsigned int samplerect(unsigned int *buf, int size, unsigned int dontdo) base = LASTBASE; if (base == 0) return 0; - maxob = base->selcol; + maxob = base->object->select_color; len = (size - 1) / 2; rc = 0; @@ -1016,8 +1000,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) if (!toggle) { CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { - if (base->flag & SELECT) { - ED_base_object_select(base, BA_DESELECT); + if ((base->flag & BASE_SELECTED) != 0) { + ED_object_base_select(base, BA_DESELECT); changed = true; } } @@ -1028,8 +1012,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) { /* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */ if (STREQ(name, base->object->id.name + 2)) { - ED_base_object_activate(C, base); - ED_base_object_select(base, BA_SELECT); + ED_object_base_activate(C, base); + ED_object_base_select(base, BA_SELECT); changed = true; } } @@ -1073,14 +1057,12 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot) RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first"); } -static void deselectall_except(Scene *scene, Base *b) /* deselect all except b */ +static void deselectall_except(SceneLayer *sl, Base *b) /* deselect all except b */ { - Base *base; - - for (base = FIRSTBASE; base; base = base->next) { - if (base->flag & SELECT) { + for (Base *base = sl->object_bases.first; base; base = base->next) { + if (base->flag & BASE_SELECTED) { if (b != base) { - ED_base_object_select(base, BA_DESELECT); + ED_object_base_select(base, BA_DESELECT); } } } @@ -1093,7 +1075,8 @@ static Base *object_mouse_select_menu( short baseCount = 0; bool ok; LinkNode *linklist = NULL; - + + /* handle base->object->select_color */ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { ok = false; @@ -1102,7 +1085,7 @@ static Base *object_mouse_select_menu( if (buffer) { for (int a = 0; a < hits; a++) { /* index was converted */ - if (base->selcol == (buffer[(4 * a) + 3] & ~0xFFFF0000)) { + if (base->object->select_color == (buffer[(4 * a) + 3] & ~0xFFFF0000)) { ok = true; break; } @@ -1201,7 +1184,7 @@ static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits15, const /* we want a select buffer with bones, if there are... */ /* so check three selection levels and compare */ static int mixed_bones_object_selectbuffer( - ViewContext *vc, unsigned int *buffer, const int mval[2], + const EvaluationContext *eval_ctx, ViewContext *vc, unsigned int *buffer, const int mval[2], bool use_cycle, bool enumerate, bool *r_do_nearest) { @@ -1241,7 +1224,7 @@ static int mixed_bones_object_selectbuffer( view3d_opengl_select_cache_begin(); BLI_rcti_init_pt_radius(&rect, mval, 14); - hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode); + hits15 = view3d_opengl_select(eval_ctx, vc, buffer, MAXPICKBUF, &rect, select_mode); if (hits15 == 1) { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; @@ -1252,7 +1235,7 @@ static int mixed_bones_object_selectbuffer( offs = 4 * hits15; BLI_rcti_init_pt_radius(&rect, mval, 9); - hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); + hits9 = view3d_opengl_select(eval_ctx, vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); if (hits9 == 1) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; @@ -1262,7 +1245,7 @@ static int mixed_bones_object_selectbuffer( offs += 4 * hits9; BLI_rcti_init_pt_radius(&rect, mval, 5); - hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); + hits5 = view3d_opengl_select(eval_ctx, vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode); if (hits5 == 1) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; @@ -1291,8 +1274,7 @@ finally: static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits, Base *startbase, bool has_bones, bool do_nearest) { - Scene *scene = vc->scene; - View3D *v3d = vc->v3d; + SceneLayer *sl = vc->scene_layer; Base *base, *basact = NULL; int a; @@ -1312,7 +1294,9 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int } else { /* only exclude active object when it is selected... */ - if (BASACT && (BASACT->flag & SELECT) && hits > 1) notcol = BASACT->selcol; + if (BASACT(sl) && (BASACT(sl)->flag & BASE_SELECTED) && hits > 1) { + notcol = BASACT(sl)->object->select_color; + } for (a = 0; a < hits; a++) { if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) { @@ -1322,10 +1306,10 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int } } - base = FIRSTBASE; + base = FIRSTBASE(sl); while (base) { - if (BASE_SELECTABLE(v3d, base)) { - if (base->selcol == selcol) break; + if (BASE_SELECTABLE(base)) { + if (base->object->select_color == selcol) break; } base = base->next; } @@ -1337,23 +1321,23 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int while (base) { /* skip objects with select restriction, to prevent prematurely ending this loop * with an un-selectable choice */ - if (base->object->restrictflag & OB_RESTRICT_SELECT) { + if ((base->flag & BASE_SELECTABLED) == 0) { base = base->next; - if (base == NULL) base = FIRSTBASE; + if (base == NULL) base = FIRSTBASE(sl); if (base == startbase) break; } - if (BASE_SELECTABLE(v3d, base)) { + if (BASE_SELECTABLE(base)) { for (a = 0; a < hits; a++) { if (has_bones) { /* skip non-bone objects */ if ((buffer[4 * a + 3] & 0xFFFF0000)) { - if (base->selcol == (buffer[(4 * a) + 3] & 0xFFFF)) + if (base->object->select_color == (buffer[(4 * a) + 3] & 0xFFFF)) basact = base; } } else { - if (base->selcol == (buffer[(4 * a) + 3] & 0xFFFF)) + if (base->object->select_color == (buffer[(4 * a) + 3] & 0xFFFF)) basact = base; } } @@ -1362,7 +1346,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int if (basact) break; base = base->next; - if (base == NULL) base = FIRSTBASE; + if (base == NULL) base = FIRSTBASE(sl); if (base == startbase) break; } } @@ -1373,6 +1357,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int /* mval comes from event->mval, only use within region handlers */ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) { + EvaluationContext eval_ctx; ViewContext vc; Base *basact = NULL; unsigned int buffer[MAXPICKBUF]; @@ -1381,13 +1366,15 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) /* setup view context for argument to callbacks */ view3d_operator_needs_opengl(C); + + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); - hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, false, false, &do_nearest); + hits = mixed_bones_object_selectbuffer(&eval_ctx, &vc, buffer, mval, false, false, &do_nearest); if (hits > 0) { const bool has_bones = selectbuffer_has_bones(buffer, hits); - basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.scene->base.first, has_bones, do_nearest); + basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.scene_layer->object_bases.first, has_bones, do_nearest); } return basact; @@ -1417,10 +1404,11 @@ static bool ed_object_select_pick( bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool obcenter, bool enumerate, bool object) { + EvaluationContext eval_ctx; ViewContext vc; ARegion *ar = CTX_wm_region(C); - View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL; bool is_obedit; float dist = ED_view3d_select_dist_px() * 1.3333f; @@ -1430,6 +1418,7 @@ static bool ed_object_select_pick( /* setup view context for argument to callbacks */ + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); is_obedit = (vc.obedit != NULL); @@ -1439,8 +1428,8 @@ static bool ed_object_select_pick( } /* always start list from basact in wire mode */ - startbase = FIRSTBASE; - if (BASACT && BASACT->next) startbase = BASACT->next; + startbase = FIRSTBASE(sl); + if (BASACT(sl) && BASACT(sl)->next) startbase = BASACT(sl)->next; /* This block uses the control key to make the object selected by its center point rather than its contents */ /* in editmode do not activate */ @@ -1453,13 +1442,13 @@ static bool ed_object_select_pick( else { base = startbase; while (base) { - if (BASE_SELECTABLE(v3d, base)) { + if (BASE_SELECTABLE(base)) { float screen_co[2]; if (ED_view3d_project_float_global(ar, base->object->obmat[3], screen_co, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { float dist_temp = len_manhattan_v2v2(mval_fl, screen_co); - if (base == BASACT) dist_temp += 10.0f; + if (base == BASACT(sl)) dist_temp += 10.0f; if (dist_temp < dist) { dist = dist_temp; basact = base; @@ -1468,7 +1457,7 @@ static bool ed_object_select_pick( } base = base->next; - if (base == NULL) base = FIRSTBASE; + if (base == NULL) base = FIRSTBASE(sl); if (base == startbase) break; } } @@ -1480,7 +1469,7 @@ static bool ed_object_select_pick( // TIMEIT_START(select_time); /* if objects have posemode set, the bones are in the same selection buffer */ - hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, true, enumerate, &do_nearest); + hits = mixed_bones_object_selectbuffer(&eval_ctx, &vc, buffer, mval, true, enumerate, &do_nearest); // TIMEIT_END(select_time); @@ -1498,7 +1487,7 @@ static bool ed_object_select_pick( if (has_bones && basact) { if (basact->object->type == OB_CAMERA) { - if (BASACT == basact) { + if (BASACT(sl) == basact) { int i, hitresult; bool changed = false; @@ -1507,7 +1496,7 @@ static bool ed_object_select_pick( /* if there's bundles in buffer select bundles first, * so non-camera elements should be ignored in buffer */ - if (basact->selcol != (hitresult & 0xFFFF)) { + if (basact->object->select_color != (hitresult & 0xFFFF)) { continue; } @@ -1536,8 +1525,8 @@ static bool ed_object_select_pick( changed = true; } - basact->flag |= SELECT; - basact->object->flag = basact->flag; + basact->flag |= BASE_SELECTED; + BKE_scene_object_base_flag_sync_from_base(basact); retval = true; @@ -1555,27 +1544,27 @@ static bool ed_object_select_pick( } } } - else if (ED_do_pose_selectbuffer(scene, basact, buffer, hits, extend, deselect, toggle, do_nearest)) { + else if (ED_do_pose_selectbuffer(scene, sl, basact, buffer, hits, extend, deselect, toggle, do_nearest)) { /* then bone is found */ /* we make the armature selected: * not-selected active object in posemode won't work well for tools */ - basact->flag |= SELECT; - basact->object->flag = basact->flag; + basact->flag |= BASE_SELECTED; + BKE_scene_object_base_flag_sync_from_base(basact); retval = true; WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object); WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object); /* in weightpaint, we use selected bone to select vertexgroup, so no switch to new active object */ - if (BASACT && (BASACT->object->mode & OB_MODE_WEIGHT_PAINT)) { + if (BASACT(sl) && (BASACT(sl)->object->mode & OB_MODE_WEIGHT_PAINT)) { /* prevent activating */ basact = NULL; } } /* prevent bone selecting to pass on to object selecting */ - if (basact == BASACT) + if (basact == BASACT(sl)) basact = NULL; } } @@ -1587,37 +1576,37 @@ static bool ed_object_select_pick( if (vc.obedit) { /* only do select */ - deselectall_except(scene, basact); - ED_base_object_select(basact, BA_SELECT); + deselectall_except(sl, basact); + ED_object_base_select(basact, BA_SELECT); } /* also prevent making it active on mouse selection */ - else if (BASE_SELECTABLE(v3d, basact)) { + else if (BASE_SELECTABLE(basact)) { - oldbasact = BASACT; + oldbasact = BASACT(sl); if (extend) { - ED_base_object_select(basact, BA_SELECT); + ED_object_base_select(basact, BA_SELECT); } else if (deselect) { - ED_base_object_select(basact, BA_DESELECT); + ED_object_base_select(basact, BA_DESELECT); } else if (toggle) { - if (basact->flag & SELECT) { + if (basact->flag & BASE_SELECTED) { if (basact == oldbasact) { - ED_base_object_select(basact, BA_DESELECT); + ED_object_base_select(basact, BA_DESELECT); } } else { - ED_base_object_select(basact, BA_SELECT); + ED_object_base_select(basact, BA_SELECT); } } else { - deselectall_except(scene, basact); - ED_base_object_select(basact, BA_SELECT); + deselectall_except(sl, basact); + ED_object_base_select(basact, BA_SELECT); } if ((oldbasact != basact) && (is_obedit == false)) { - ED_base_object_activate(C, basact); /* adds notifier */ + ED_object_base_activate(C, basact); /* adds notifier */ } } @@ -1673,7 +1662,8 @@ static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, con SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); } } -static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) +static int do_paintvert_box_select( + const EvaluationContext *eval_ctx, ViewContext *vc, rcti *rect, bool select, bool extend) { const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Mesh *me; @@ -1697,7 +1687,7 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo if (use_zbuf) { selar = MEM_callocN(me->totvert + 1, "selar"); - ED_view3d_backbuf_validate(vc); + ED_view3d_backbuf_validate(eval_ctx, vc); ibuf = IMB_allocImBuf(size[0], size[1], 32, IB_rect); rt = ibuf->rect; @@ -1745,7 +1735,7 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); - meshobject_foreachScreenVert(vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + meshobject_foreachScreenVert(eval_ctx, vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } if (select == false) { @@ -1860,7 +1850,8 @@ static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, const BM_face_select_set(data->vc->em->bm, efa, data->select); } } -static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) +static int do_mesh_box_select( + const struct EvaluationContext *eval_ctx, ViewContext *vc, rcti *rect, bool select, bool extend) { BoxSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; @@ -1874,26 +1865,26 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool ext /* for non zbuf projections, don't change the GL state */ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - glLoadMatrixf(vc->rv3d->viewmat); - bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + gpuLoadMatrix(vc->rv3d->viewmat); + bbsel = EDBM_backbuf_border_init(eval_ctx, vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax); if (ts->selectmode & SCE_SELECT_VERTEX) { if (bbsel) { edbm_backbuf_check_and_select_verts(vc->em, select); } else { - mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenVert(eval_ctx, vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } if (ts->selectmode & SCE_SELECT_EDGE) { /* Does both bbsel and non-bbsel versions (need screen cos for both) */ data.pass = 0; - mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); + mesh_foreachScreenEdge(eval_ctx, vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); if (data.is_done == 0) { data.pass = 1; - mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); + mesh_foreachScreenEdge(eval_ctx, vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); } } @@ -1902,7 +1893,7 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool ext edbm_backbuf_check_and_select_faces(vc->em, select); } else { - mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenFace(eval_ctx, vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -1913,7 +1904,9 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool ext return OPERATOR_FINISHED; } -static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) +static int do_meta_box_select( + const struct EvaluationContext *eval_ctx, ViewContext *vc, + const rcti *rect, bool select, bool extend) { MetaBall *mb = (MetaBall *)vc->obedit->data; MetaElem *ml; @@ -1922,7 +1915,7 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool ext unsigned int buffer[MAXPICKBUF]; int hits; - hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); + hits = view3d_opengl_select(eval_ctx, vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); if (extend == false && select) BKE_mball_deselect_all(mb); @@ -1947,7 +1940,9 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool ext return OPERATOR_FINISHED; } -static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) +static int do_armature_box_select( + const struct EvaluationContext *eval_ctx, ViewContext *vc, + const rcti *rect, bool select, bool extend) { bArmature *arm = vc->obedit->data; EditBone *ebone; @@ -1956,7 +1951,7 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool unsigned int buffer[MAXPICKBUF]; int hits; - hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); + hits = view3d_opengl_select(eval_ctx, vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL); /* clear flag we use to detect point was affected */ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) @@ -2020,8 +2015,30 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool return hits > 0 ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } +/** + * Compare result of 'GPU_select': 'uint[4]', + * needed for when we need to align with object draw-order. + */ +static int opengl_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p) +{ + /* 4th element is select id */ + const uint sel_a = ((uint *)sel_a_p)[3]; + const uint sel_b = ((uint *)sel_b_p)[3]; + + if (sel_a < sel_b) { + return -1; + } + else if (sel_a > sel_b) { + return 1; + } + else { + return 0; + } +} + static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, bool select, bool extend) { + EvaluationContext eval_ctx; Bone *bone; Object *ob = vc->obact; unsigned int *vbuffer = NULL; /* selection buffer */ @@ -2031,6 +2048,8 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b int totobj = MAXPICKBUF; /* XXX solve later */ int hits; + CTX_data_eval_ctx(C, &eval_ctx); + if ((ob) && (ob->mode & OB_MODE_POSE)) bone_only = 1; else @@ -2047,13 +2066,13 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b CTX_DATA_END; } else { - object_deselect_all_visible(vc->scene, vc->v3d); + object_deselect_all_visible(vc->scene_layer); } } /* selection buffer now has bones potentially too, so we add MAXPICKBUF */ vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(unsigned int), "selection buffer"); - hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL); + hits = view3d_opengl_select(&eval_ctx, vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL); /* * LOGIC NOTES (theeth): * The buffer and ListBase have the same relative order, which makes the selection @@ -2061,18 +2080,22 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b * is the same as the object, we have a hit and can move to the next color * and object pair, if not, just move to the next object, * keeping the same color until we have a hit. - * - * The buffer order is defined by OGL standard, hopefully no stupid GFX card - * does it incorrectly. */ if (hits > 0) { /* no need to loop if there's no hit */ Base *base; col = vbuffer + 3; - - for (base = vc->scene->base.first; base && hits; base = base->next) { - if (BASE_SELECTABLE(vc->v3d, base)) { - while (base->selcol == (*col & 0xFFFF)) { /* we got an object */ + + /* The draw order doesn't always match the order we populate the engine, see: T51695. */ + qsort(vbuffer, hits, sizeof(uint[4]), opengl_select_buffer_cmp); + + /* + * Even though 'DRW_draw_select_loop' uses 'DEG_OBJECT_ITER', + * we can be sure the order remains the same between both. + */ + for (base = vc->scene_layer->object_bases.first; base && hits; base = base->next) { + if (BASE_SELECTABLE(base)) { + while (base->object->select_color == (*col & 0xFFFF)) { /* we got an object */ if (*col & 0xFFFF0000) { /* we got a bone */ bone = get_indexed_bone(base->object, *col & ~(BONESEL_ANY)); if (bone) { @@ -2091,7 +2114,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b } } else if (!bone_only) { - ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT); + ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); } col += 4; /* next color */ @@ -2108,7 +2131,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b if (arm && (arm->flag & ARM_HAS_VIZ_DEPS)) { /* mask modifier ('armature' mode), etc. */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } } @@ -2123,6 +2146,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b static int view3d_borderselect_exec(bContext *C, wmOperator *op) { + EvaluationContext eval_ctx; ViewContext vc; rcti rect; bool extend; @@ -2133,6 +2157,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) view3d_operator_needs_opengl(C); /* setup view context for argument to callbacks */ + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); select = !RNA_boolean_get(op->ptr, "deselect"); @@ -2143,7 +2168,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) switch (vc.obedit->type) { case OB_MESH: vc.em = BKE_editmesh_from_object(vc.obedit); - ret = do_mesh_box_select(&vc, &rect, select, extend); + ret = do_mesh_box_select(&eval_ctx, &vc, &rect, select, extend); // if (EM_texFaceCheck()) if (ret & OPERATOR_FINISHED) { WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); @@ -2157,13 +2182,13 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) } break; case OB_MBALL: - ret = do_meta_box_select(&vc, &rect, select, extend); + ret = do_meta_box_select(&eval_ctx, &vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; case OB_ARMATURE: - ret = do_armature_box_select(&vc, &rect, select, extend); + ret = do_armature_box_select(&eval_ctx, &vc, &rect, select, extend); if (ret & OPERATOR_FINISHED) { WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit); } @@ -2184,10 +2209,10 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) ret = ED_sculpt_mask_box_select(C, &vc, &rect, select, extend); } else if (vc.obact && BKE_paint_select_face_test(vc.obact)) { - ret = do_paintface_box_select(&vc, &rect, select, extend); + ret = do_paintface_box_select(&eval_ctx, &vc, &rect, select, extend); } else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) { - ret = do_paintvert_box_select(&vc, &rect, select, extend); + ret = do_paintvert_box_select(&eval_ctx, &vc, &rect, select, extend); } else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) { ret = PE_border_select(C, &rect, select, extend); @@ -2431,13 +2456,13 @@ static void mesh_circle_doSelectFace(void *userData, BMFace *efa, const float sc } } -static void mesh_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) +static void mesh_circle_select(const struct EvaluationContext *eval_ctx, ViewContext *vc, const bool select, const int mval[2], float rad) { ToolSettings *ts = vc->scene->toolsettings; int bbsel; CircleSelectUserData data; - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + bbsel = EDBM_backbuf_circle_init(eval_ctx, vc, mval[0], mval[1], (short)(rad + 1.0f)); ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ vc->em = BKE_editmesh_from_object(vc->obedit); @@ -2449,7 +2474,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva edbm_backbuf_check_and_select_verts(vc->em, select); } else { - mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenVert(eval_ctx, vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -2458,7 +2483,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva edbm_backbuf_check_and_select_edges(vc->em, select); } else { - mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); + mesh_foreachScreenEdge(eval_ctx, vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); } } @@ -2467,7 +2492,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva edbm_backbuf_check_and_select_faces(vc->em, select); } else { - mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenFace(eval_ctx, vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -2475,7 +2500,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva EDBM_selectmode_flush(vc->em); } -static void paint_facesel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) +static void paint_facesel_circle_select(const struct EvaluationContext *eval_ctx, ViewContext *vc, const bool select, const int mval[2], float rad) { Object *ob = vc->obact; Mesh *me = ob->data; @@ -2483,7 +2508,7 @@ static void paint_facesel_circle_select(ViewContext *vc, const bool select, cons bm_vertoffs = me->totpoly + 1; /* max index array */ - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + bbsel = EDBM_backbuf_circle_init(eval_ctx, vc, mval[0], mval[1], (short)(rad + 1.0f)); if (bbsel) { edbm_backbuf_check_and_select_tfaces(me, select); EDBM_backbuf_free(); @@ -2499,7 +2524,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); } } -static void paint_vertsel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) +static void paint_vertsel_circle_select(const struct EvaluationContext *eval_ctx, ViewContext *vc, const bool select, const int mval[2], float rad) { const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Object *ob = vc->obact; @@ -2510,7 +2535,7 @@ static void paint_vertsel_circle_select(ViewContext *vc, const bool select, cons if (use_zbuf) { bm_vertoffs = me->totvert + 1; /* max index array */ - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + bbsel = EDBM_backbuf_circle_init(eval_ctx, vc, mval[0], mval[1], (short)(rad + 1.0f)); if (bbsel) { edbm_backbuf_check_and_select_verts_obmode(me, select); EDBM_backbuf_free(); @@ -2522,7 +2547,7 @@ static void paint_vertsel_circle_select(ViewContext *vc, const bool select, cons ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ view3d_userdata_circleselect_init(&data, vc, select, mval, rad); - meshobject_foreachScreenVert(vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + meshobject_foreachScreenVert(eval_ctx, vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } if (select != LEFTMOUSE) { @@ -2666,7 +2691,7 @@ static void pose_circle_select(ViewContext *vc, const bool select, const int mva if (arm->flag & ARM_HAS_VIZ_DEPS) { /* mask modifier ('armature' mode), etc. */ - DAG_id_tag_update(&vc->obact->id, OB_RECALC_DATA); + DEG_id_tag_update(&vc->obact->id, OB_RECALC_DATA); } } } @@ -2776,11 +2801,12 @@ static void mball_circle_select(ViewContext *vc, const bool select, const int mv /** Callbacks for circle selection in Editmode */ -static void obedit_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) +static void obedit_circle_select( + const struct EvaluationContext *eval_ctx, ViewContext *vc, const bool select, const int mval[2], float rad) { switch (vc->obedit->type) { case OB_MESH: - mesh_circle_select(vc, select, mval, rad); + mesh_circle_select(eval_ctx, vc, select, mval, rad); break; case OB_CURVE: case OB_SURF: @@ -2802,22 +2828,22 @@ static void obedit_circle_select(ViewContext *vc, const bool select, const int m static bool object_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) { - Scene *scene = vc->scene; + SceneLayer *sl = vc->scene_layer; const float radius_squared = rad * rad; const float mval_fl[2] = {mval[0], mval[1]}; bool changed = false; - const int select_flag = select ? SELECT : 0; + const int select_flag = select ? BASE_SELECTED : 0; Base *base; - for (base = FIRSTBASE; base; base = base->next) { - if (BASE_SELECTABLE(vc->v3d, base) && ((base->flag & SELECT) != select_flag)) { + for (base = FIRSTBASE(sl); base; base = base->next) { + if (BASE_SELECTABLE(base) && ((base->flag & BASE_SELECTED) != select_flag)) { float screen_co[2]; if (ED_view3d_project_float_global(vc->ar, base->object->obmat[3], screen_co, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) { - ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT); + ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); changed = true; } } @@ -2840,22 +2866,24 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) if (CTX_data_edit_object(C) || BKE_paint_select_elem_test(obact) || (obact && (obact->mode & (OB_MODE_PARTICLE_EDIT | OB_MODE_POSE))) ) { + EvaluationContext eval_ctx; ViewContext vc; view3d_operator_needs_opengl(C); + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); if (CTX_data_edit_object(C)) { - obedit_circle_select(&vc, select, mval, (float)radius); + obedit_circle_select(&eval_ctx, &vc, select, mval, (float)radius); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); } else if (BKE_paint_select_face_test(obact)) { - paint_facesel_circle_select(&vc, select, mval, (float)radius); + paint_facesel_circle_select(&eval_ctx, &vc, select, mval, (float)radius); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); } else if (BKE_paint_select_vert_test(obact)) { - paint_vertsel_circle_select(&vc, select, mval, (float)radius); + paint_vertsel_circle_select(&eval_ctx, &vc, select, mval, (float)radius); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); } else if (obact->mode & OB_MODE_POSE) diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 5dd69cc66eb..1df29201bf6 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -40,13 +40,14 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_mball.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_tracking.h" +#include "DEG_depsgraph.h" + #include "WM_api.h" #include "WM_types.h" @@ -73,9 +74,12 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) RegionView3D *rv3d = CTX_wm_region_data(C); TransVertStore tvs = {NULL}; TransVert *tv; + EvaluationContext eval_ctx; float gridf, imat[3][3], bmat[3][3], vec[3]; int a; + CTX_data_eval_ctx(C, &eval_ctx); + gridf = rv3d->gridview; if (obedit) { @@ -153,7 +157,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) } ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } else { vec[0] = -ob->obmat[3][0] + gridf * floorf(0.5f + ob->obmat[3][0] / gridf); @@ -162,7 +166,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) if (ob->parent) { float originmat[3][3]; - BKE_object_where_is_calc_ex(scene, NULL, ob, originmat); + BKE_object_where_is_calc_ex(&eval_ctx, scene, NULL, ob, originmat); invert_m3_m3(imat, originmat); mul_m3_v3(imat, vec); @@ -177,7 +181,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) /* auto-keyframing */ ED_autokeyframe_object(C, scene, ob, ks); - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } } CTX_DATA_END; @@ -213,11 +217,14 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global View3D *v3d = CTX_wm_view3d(C); TransVertStore tvs = {NULL}; TransVert *tv; + EvaluationContext eval_ctx; float imat[3][3], bmat[3][3]; float center_global[3]; float offset_global[3]; int a; + CTX_data_eval_ctx(C, &eval_ctx); + if (use_offset) { if ((v3d && v3d->around == V3D_AROUND_ACTIVE) && snap_calc_active_center(C, true, center_global)) @@ -329,7 +336,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global obact->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); - DAG_id_tag_update(&obact->id, OB_RECALC_DATA); + DEG_id_tag_update(&obact->id, OB_RECALC_DATA); } else { struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); @@ -370,7 +377,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global if (ob->parent) { float originmat[3][3]; - BKE_object_where_is_calc_ex(scene, NULL, ob, originmat); + BKE_object_where_is_calc_ex(&eval_ctx, scene, NULL, ob, originmat); invert_m3_m3(imat, originmat); mul_m3_v3(imat, cursor_parent); @@ -385,7 +392,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global /* auto-keyframing */ ED_autokeyframe_object(C, scene, ob, ks); - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DEG_id_tag_update(&ob->id, OB_RECALC_OB); } } diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 0bccab626e6..4e98386be97 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -43,7 +43,6 @@ #include "BKE_action.h" #include "BKE_camera.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_object.h" #include "BKE_global.h" #include "BKE_main.h" @@ -51,12 +50,15 @@ #include "BKE_scene.h" #include "BKE_screen.h" -#include "BIF_gl.h" +#include "DEG_depsgraph.h" + #include "BIF_glutil.h" #include "UI_resources.h" +#include "GPU_glew.h" #include "GPU_select.h" +#include "GPU_matrix.h" #include "WM_api.h" #include "WM_types.h" @@ -64,6 +66,8 @@ #include "ED_screen.h" #include "ED_armature.h" +#include "DRW_engine.h" + #ifdef WITH_GAMEENGINE # include "BLI_listbase.h" @@ -98,10 +102,8 @@ void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar) RegionView3D *rv3d = ar->regiondata; wmSubWindowSet(win, ar->swinid); - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(rv3d->winmat); - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(rv3d->viewmat); + gpuLoadProjectionMatrix(rv3d->winmat); + gpuLoadMatrix(rv3d->viewmat); } } @@ -443,6 +445,9 @@ void ED_view3d_smooth_view_force_finish( View3D *v3d, ARegion *ar) { RegionView3D *rv3d = ar->regiondata; + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); if (rv3d && rv3d->sms) { rv3d->sms->time_allowed = 0.0; /* force finishing */ @@ -451,7 +456,7 @@ void ED_view3d_smooth_view_force_finish( /* force update of view matrix so tools that run immediately after * can use them without redrawing first */ Scene *scene = CTX_data_scene(C); - ED_view3d_update_viewmat(scene, v3d, ar, NULL, NULL, NULL); + ED_view3d_update_viewmat(&eval_ctx, scene, v3d, ar, NULL, NULL, NULL); } } @@ -493,7 +498,7 @@ static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op)) BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag); - DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); + DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); rv3d->persp = RV3D_CAMOB; WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, v3d->camera); @@ -541,6 +546,7 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot) static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); View3D *v3d = CTX_wm_view3d(C); /* can be NULL */ Object *camera_ob = v3d ? v3d->camera : scene->camera; @@ -553,7 +559,7 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op) } /* this function does all the important stuff */ - if (BKE_camera_view_frame_fit_to_scene(scene, v3d, camera_ob, r_co, &r_scale)) { + if (BKE_camera_view_frame_fit_to_scene(scene, sl, camera_ob, r_co, &r_scale)) { ObjectTfmProtectedChannels obtfm; float obmat_new[4][4]; @@ -570,7 +576,7 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op) BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D); /* notifiers */ - DAG_id_tag_update(&camera_ob->id, OB_RECALC_OB); + DEG_id_tag_update(&camera_ob->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, camera_ob); return OPERATOR_FINISHED; } @@ -727,40 +733,35 @@ void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, } } -void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], bglMats *mats, const rcti *rect) +void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect) { - float modelview[4][4]; - double xs, ys, p[3]; - int val, flip_sign, a; - - /* near zero floating point values can give issues with gluUnProject - * in side view on some implementations */ - if (fabs(mats->modelview[0]) < 1e-6) mats->modelview[0] = 0.0; - if (fabs(mats->modelview[5]) < 1e-6) mats->modelview[5] = 0.0; - - /* Set up viewport so that gluUnProject will give correct values */ - mats->viewport[0] = 0; - mats->viewport[1] = 0; + /* init in case unproject fails */ + memset(bb->vec, 0, sizeof(bb->vec)); /* four clipping planes and bounding volume */ /* first do the bounding volume */ - for (val = 0; val < 4; val++) { - xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax; - ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax; + for (int val = 0; val < 4; val++) { + float xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax; + float ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax; - gluUnProject(xs, ys, 0.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]); - copy_v3fl_v3db(bb->vec[val], p); + ED_view3d_unproject(ar, xs, ys, 0.0, bb->vec[val]); + ED_view3d_unproject(ar, xs, ys, 1.0, bb->vec[4 + val]); + } - gluUnProject(xs, ys, 1.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]); - copy_v3fl_v3db(bb->vec[4 + val], p); + /* optionally transform to object space */ + if (ob) { + float imat[4][4]; + invert_m4_m4(imat, ob->obmat); + + for (int val = 0; val < 8; val++) { + mul_m4_v3(imat, bb->vec[val]); + } } /* verify if we have negative scale. doing the transform before cross * product flips the sign of the vector compared to doing cross product * before transform then, so we correct for that. */ - for (a = 0; a < 16; a++) - ((float *)modelview)[a] = mats->modelview[a]; - flip_sign = is_negative_m4(modelview); + int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false; ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign); } @@ -836,7 +837,7 @@ float ED_view3d_depth_read_cached(const ViewContext *vc, const int mval[2]) } bool ED_view3d_depth_read_cached_normal( - const ViewContext *vc, const bglMats *mats, const int mval[2], + const ViewContext *vc, const int mval[2], float r_normal[3]) { /* Note: we could support passing in a radius. @@ -855,7 +856,7 @@ bool ED_view3d_depth_read_cached_normal( const double depth = (double)ED_view3d_depth_read_cached(vc, mval_ofs); if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) { - if (ED_view3d_depth_unproject(ar, mats, mval_ofs, depth, coords[i])) { + if (ED_view3d_depth_unproject(ar, mval_ofs, depth, coords[i])) { depths_valid[i] = true; } } @@ -897,21 +898,13 @@ bool ED_view3d_depth_read_cached_normal( } bool ED_view3d_depth_unproject( - const ARegion *ar, const bglMats *mats, + const ARegion *ar, const int mval[2], const double depth, float r_location_world[3]) { - double p[3]; - if (gluUnProject( - (double)ar->winrct.xmin + mval[0] + 0.5, - (double)ar->winrct.ymin + mval[1] + 0.5, - depth, mats->modelview, mats->projection, (const GLint *)mats->viewport, - &p[0], &p[1], &p[2])) - { - copy_v3fl_v3db(r_location_world, p); - return true; - } - return false; + float centx = (float)mval[0] + 0.5f; + float centy = (float)mval[1] + 0.5f; + return ED_view3d_unproject(ar, centx, centy, depth, r_location_world); } /** \} */ @@ -1025,14 +1018,14 @@ void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect) } if (is_ortho) { - wmOrtho(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); + gpuOrtho(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); } else { - wmFrustum(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); + gpuFrustum(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); } /* update matrix in 3d view region */ - glGetFloatv(GL_PROJECTION_MATRIX, (float *)rv3d->winmat); + gpuGetProjectionMatrix(rv3d->winmat); } static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob) @@ -1116,11 +1109,11 @@ bool ED_view3d_lock(RegionView3D *rv3d) } /* don't set windows active in here, is used by renderwin too */ -void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d) +void view3d_viewmatrix_set(const EvaluationContext *eval_ctx, Scene *scene, const View3D *v3d, RegionView3D *rv3d) { if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */ if (v3d->camera) { - BKE_object_where_is_calc(scene, v3d->camera); + BKE_object_where_is_calc(eval_ctx, scene, v3d->camera); obmat_to_viewmat(rv3d, v3d->camera); } else { @@ -1205,10 +1198,11 @@ void view3d_opengl_select_cache_end(void) * \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection. */ int view3d_opengl_select( - ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input, + const EvaluationContext *eval_ctx, ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input, eV3DSelectMode select_mode) { struct bThemeState theme_state; + Depsgraph *graph = vc->depsgraph; Scene *scene = vc->scene; View3D *v3d = vc->v3d; ARegion *ar = vc->ar; @@ -1270,7 +1264,7 @@ int view3d_opengl_select( /* Important we use the 'viewmat' and don't re-calculate since * the object & bone view locking takes 'rect' into account, see: T51629. */ - ED_view3d_draw_setup_view(vc->win, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect); + ED_view3d_draw_setup_view(vc->win, eval_ctx, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect); if (v3d->drawtype > OB_WIRE) { v3d->zbuf = true; @@ -1282,7 +1276,16 @@ int view3d_opengl_select( GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0); - ED_view3d_draw_select_loop(vc, scene, v3d, ar, use_obedit_skip, use_nearest); +#ifdef WITH_OPENGL_LEGACY + if (IS_VIEWPORT_LEGACY(vc->v3d)) { + ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest); + } + else +#else + { + DRW_draw_select_loop(graph, ar, v3d, use_obedit_skip, use_nearest, &rect); + } +#endif /* WITH_OPENGL_LEGACY */ hits = GPU_select_end(); @@ -1290,13 +1293,22 @@ int view3d_opengl_select( if (do_passes && (hits > 0)) { GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits); - ED_view3d_draw_select_loop(vc, scene, v3d, ar, use_obedit_skip, use_nearest); +#ifdef WITH_OPENGL_LEGACY + if (IS_VIEWPORT_LEGACY(vc->v3d)) { + ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest); + } + else +#else + { + DRW_draw_select_loop(graph, ar, v3d, use_obedit_skip, use_nearest, &rect); + } +#endif /* WITH_OPENGL_LEGACY */ GPU_select_end(); } G.f &= ~G_PICKSEL; - ED_view3d_draw_setup_view(vc->win, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL); + ED_view3d_draw_setup_view(vc->win, eval_ctx, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL); if (v3d->drawtype > OB_WIRE) { v3d->zbuf = 0; @@ -1314,42 +1326,6 @@ finally: return hits; } -/* ********************** local view operator ******************** */ - -static unsigned int free_localbit(Main *bmain) -{ - unsigned int lay; - ScrArea *sa; - bScreen *sc; - - lay = 0; - - /* sometimes we loose a localview: when an area is closed */ - /* check all areas: which localviews are in use? */ - for (sc = bmain->screen.first; sc; sc = sc->id.next) { - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl = sa->spacedata.first; - for (; sl; sl = sl->next) { - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *) sl; - lay |= v3d->lay; - } - } - } - } - - if ((lay & 0x01000000) == 0) return 0x01000000; - if ((lay & 0x02000000) == 0) return 0x02000000; - if ((lay & 0x04000000) == 0) return 0x04000000; - if ((lay & 0x08000000) == 0) return 0x08000000; - if ((lay & 0x10000000) == 0) return 0x10000000; - if ((lay & 0x20000000) == 0) return 0x20000000; - if ((lay & 0x40000000) == 0) return 0x40000000; - if ((lay & 0x80000000) == 0) return 0x80000000; - - return 0; -} - int ED_view3d_scene_layer_set(int lay, const int *values, int *active) { int i, tot = 0; @@ -1388,267 +1364,6 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active) return lay; } -static bool view3d_localview_init( - wmWindowManager *wm, wmWindow *win, - Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx, - ReportList *reports) -{ - View3D *v3d = sa->spacedata.first; - Base *base; - float min[3], max[3], box[3], mid[3]; - float size = 0.0f; - unsigned int locallay; - bool ok = false; - - if (v3d->localvd) { - return ok; - } - - INIT_MINMAX(min, max); - - locallay = free_localbit(bmain); - - if (locallay == 0) { - BKE_report(reports, RPT_ERROR, "No more than 8 local views"); - ok = false; - } - else { - if (scene->obedit) { - BKE_object_minmax(scene->obedit, min, max, false); - - ok = true; - - BASACT->lay |= locallay; - scene->obedit->lay = BASACT->lay; - } - else { - for (base = FIRSTBASE; base; base = base->next) { - if (TESTBASE(v3d, base)) { - BKE_object_minmax(base->object, min, max, false); - base->lay |= locallay; - base->object->lay = base->lay; - ok = true; - } - } - } - - sub_v3_v3v3(box, max, min); - size = max_fff(box[0], box[1], box[2]); - } - - if (ok == true) { - ARegion *ar; - - v3d->localvd = MEM_mallocN(sizeof(View3D), "localview"); - - memcpy(v3d->localvd, v3d, sizeof(View3D)); - - mid_v3_v3v3(mid, min, max); - - copy_v3_v3(v3d->cursor, mid); - - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = ar->regiondata; - bool ok_dist = true; - - /* new view values */ - Object *camera_old = NULL; - float dist_new, ofs_new[3]; - - rv3d->localvd = MEM_mallocN(sizeof(RegionView3D), "localview region"); - memcpy(rv3d->localvd, rv3d, sizeof(RegionView3D)); - - negate_v3_v3(ofs_new, mid); - - if (rv3d->persp == RV3D_CAMOB) { - rv3d->persp = RV3D_PERSP; - camera_old = v3d->camera; - } - - if (rv3d->persp == RV3D_ORTHO) { - if (size < 0.0001f) { - ok_dist = false; - } - } - - if (ok_dist) { - dist_new = ED_view3d_radius_to_dist(v3d, ar, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN); - if (rv3d->persp == RV3D_PERSP) { - /* don't zoom closer than the near clipping plane */ - dist_new = max_ff(dist_new, v3d->near * 1.5f); - } - } - - ED_view3d_smooth_view_ex( - wm, win, sa, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { - .camera_old = camera_old, - .ofs = ofs_new, .quat = rv3d->viewquat, - .dist = ok_dist ? &dist_new : NULL, .lens = &v3d->lens}); - } - } - - v3d->lay = locallay; - } - else { - /* clear flags */ - for (base = FIRSTBASE; base; base = base->next) { - if (base->lay & locallay) { - base->lay -= locallay; - if (base->lay == 0) base->lay = v3d->layact; - if (base->object != scene->obedit) base->flag |= SELECT; - base->object->lay = base->lay; - } - } - } - - DAG_on_visible_update(bmain, false); - - return ok; -} - -static void restore_localviewdata(wmWindowManager *wm, wmWindow *win, Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx) -{ - const bool free = true; - ARegion *ar; - View3D *v3d = sa->spacedata.first; - Object *camera_old, *camera_new; - - if (v3d->localvd == NULL) return; - - camera_old = v3d->camera; - camera_new = v3d->localvd->camera; - - v3d->lay = v3d->localvd->lay; - v3d->layact = v3d->localvd->layact; - v3d->drawtype = v3d->localvd->drawtype; - v3d->camera = v3d->localvd->camera; - - if (free) { - MEM_freeN(v3d->localvd); - v3d->localvd = NULL; - } - - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = ar->regiondata; - - if (rv3d->localvd) { - Object *camera_old_rv3d, *camera_new_rv3d; - - camera_old_rv3d = (rv3d->persp == RV3D_CAMOB) ? camera_old : NULL; - camera_new_rv3d = (rv3d->localvd->persp == RV3D_CAMOB) ? camera_new : NULL; - - rv3d->view = rv3d->localvd->view; - rv3d->persp = rv3d->localvd->persp; - rv3d->camzoom = rv3d->localvd->camzoom; - - ED_view3d_smooth_view_ex( - wm, win, sa, - v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { - .camera_old = camera_old_rv3d, .camera = camera_new_rv3d, - .ofs = rv3d->localvd->ofs, .quat = rv3d->localvd->viewquat, - .dist = &rv3d->localvd->dist}); - - if (free) { - MEM_freeN(rv3d->localvd); - rv3d->localvd = NULL; - } - } - - ED_view3d_shade_update(bmain, scene, v3d, sa); - } - } -} - -static bool view3d_localview_exit( - wmWindowManager *wm, wmWindow *win, - Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx) -{ - View3D *v3d = sa->spacedata.first; - struct Base *base; - unsigned int locallay; - - if (v3d->localvd) { - - locallay = v3d->lay & 0xFF000000; - - restore_localviewdata(wm, win, bmain, scene, sa, smooth_viewtx); - - /* for when in other window the layers have changed */ - if (v3d->scenelock) v3d->lay = scene->lay; - - for (base = FIRSTBASE; base; base = base->next) { - if (base->lay & locallay) { - base->lay -= locallay; - if (base->lay == 0) base->lay = v3d->layact; - if (base->object != scene->obedit) { - base->flag |= SELECT; - base->object->flag |= SELECT; - } - base->object->lay = base->lay; - } - } - - DAG_on_visible_update(bmain, false); - - return true; - } - else { - return false; - } -} - -static int localview_exec(bContext *C, wmOperator *op) -{ - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ScrArea *sa = CTX_wm_area(C); - View3D *v3d = CTX_wm_view3d(C); - bool changed; - - if (v3d->localvd) { - changed = view3d_localview_exit(wm, win, bmain, scene, sa, smooth_viewtx); - } - else { - changed = view3d_localview_init(wm, win, bmain, scene, sa, smooth_viewtx, op->reports); - } - - if (changed) { - DAG_id_type_tag(bmain, ID_OB); - ED_area_tag_redraw(sa); - - /* unselected objects become selected when exiting */ - if (v3d->localvd == NULL) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - } - - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } -} - -void VIEW3D_OT_localview(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Local View"; - ot->description = "Toggle display of selected object(s) separately and centered in view"; - ot->idname = "VIEW3D_OT_localview"; - - /* api callbacks */ - ot->exec = localview_exec; - ot->flag = OPTYPE_UNDO; /* localview changes object layer bitflags */ - - ot->poll = ED_operator_view3d_active; -} - #ifdef WITH_GAMEENGINE static ListBase queue_back; @@ -1687,7 +1402,6 @@ static void RestoreState(bContext *C, wmWindow *win) win->queue = queue_back; GPU_state_init(); - GPU_set_tpage(NULL, 0, 0); glPopAttrib(); } @@ -1730,10 +1444,6 @@ static void game_set_commmandline_options(GameData *gm) SYS_WriteCommandLineInt(syshandle, "blender_material", test); test = (gm->matmode == GAME_MAT_GLSL); SYS_WriteCommandLineInt(syshandle, "blender_glsl_material", test); - test = (gm->flag & GAME_DISPLAY_LISTS); - SYS_WriteCommandLineInt(syshandle, "displaylists", test); - - } } @@ -1741,19 +1451,21 @@ static void game_set_commmandline_options(GameData *gm) static int game_engine_poll(bContext *C) { - bScreen *screen; + const wmWindow *win = CTX_wm_window(C); + const Scene *scene = WM_window_get_active_scene(win); + /* we need a context and area to launch BGE * it's a temporary solution to avoid crash at load time * if we try to auto run the BGE. Ideally we want the * context to be set as soon as we load the file. */ - if (CTX_wm_window(C) == NULL) return 0; - if ((screen = CTX_wm_screen(C)) == NULL) return 0; + if (win == NULL) return 0; + if (CTX_wm_screen(C) == NULL) return 0; if (CTX_data_mode_enum(C) != CTX_MODE_OBJECT) return 0; - if (!BKE_scene_uses_blender_game(screen->scene)) + if (!BKE_scene_uses_blender_game(scene)) return 0; return 1; @@ -1862,7 +1574,7 @@ static int game_engine_exec(bContext *C, wmOperator *op) //XXX restore_all_scene_cfra(scene_cfra_store); BKE_scene_set_background(CTX_data_main(C), startscene); - //XXX BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay); + //XXX BKE_scene_graph_update_for_newframe(bmain->eval_ctx, bmain, scene, depsgraph); BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_POST); diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 9464f332d39..95390fe9065 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -56,6 +56,10 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "GPU_immediate.h" + +#include "RE_engine.h" + #include "view3d_intern.h" /* own include */ #ifdef WITH_INPUT_NDOF @@ -246,6 +250,8 @@ typedef struct WalkInfo { View3D *v3d; ARegion *ar; Scene *scene; + SceneLayer *scene_layer; + RenderEngineType *engine; wmTimer *timer; /* needed for redraws */ @@ -337,24 +343,33 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *a yoff = walk->ar->winy / 2; } - UI_ThemeColor(TH_VIEW_OVERLAY); - glBegin(GL_LINES); + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColor(TH_VIEW_OVERLAY); + + immBegin(GWN_PRIM_LINES, 8); + /* North */ - glVertex2i(xoff, yoff + inner_length); - glVertex2i(xoff, yoff + outter_length); + immVertex2i(pos, xoff, yoff + inner_length); + immVertex2i(pos, xoff, yoff + outter_length); /* East */ - glVertex2i(xoff + inner_length, yoff); - glVertex2i(xoff + outter_length, yoff); + immVertex2i(pos, xoff + inner_length, yoff); + immVertex2i(pos, xoff + outter_length, yoff); /* South */ - glVertex2i(xoff, yoff - inner_length); - glVertex2i(xoff, yoff - outter_length); + immVertex2i(pos, xoff, yoff - inner_length); + immVertex2i(pos, xoff, yoff - outter_length); /* West */ - glVertex2i(xoff - inner_length, yoff); - glVertex2i(xoff - outter_length, yoff); - glEnd(); + immVertex2i(pos, xoff - inner_length, yoff); + immVertex2i(pos, xoff - outter_length, yoff); + + immEnd(); + immUnbindProgram(); } static void walk_update_header(bContext *C, wmOperator *op, WalkInfo *walk) @@ -499,6 +514,8 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->v3d = CTX_wm_view3d(C); walk->ar = CTX_wm_region(C); walk->scene = CTX_data_scene(C); + walk->scene_layer = CTX_data_scene_layer(C); + walk->engine = CTX_data_engine(C); #ifdef NDOF_WALK_DEBUG puts("\n-- walk begin --"); @@ -587,11 +604,11 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->rv3d->rflag |= RV3D_NAVIGATING; walk->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), walk->scene, 0, + CTX_data_main(C), walk->scene, walk->scene_layer, walk->engine, 0, walk->ar, walk->v3d); walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( - walk->scene, walk->v3d, walk->rv3d, + C, walk->scene, walk->v3d, walk->rv3d, (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); /* center the mouse */ |