Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_view3d')
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt25
-rw-r--r--source/blender/editors/space_view3d/drawanimviz.c402
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c2793
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c1406
-rw-r--r--source/blender/editors/space_view3d/drawobject.c8424
-rw-r--r--source/blender/editors/space_view3d/drawsimdebug.c180
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c5
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c611
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c46
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c15
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c4274
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c1077
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c564
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c60
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c215
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h132
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c32
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_armature.c223
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_camera.c469
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_empty.c201
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_forcefield.c123
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_lamp.c305
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate.c372
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c309
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_ruler.c1100
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c96
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c43
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c256
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c749
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c195
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c209
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c258
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c732
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c45
34 files changed, 7414 insertions, 18532 deletions
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index e25a9c04f15..f8e38587117 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
@@ -42,21 +43,26 @@ set(INC_SYS
)
set(SRC
- drawanimviz.c
- drawarmature.c
- drawmesh.c
drawobject.c
- drawsimdebug.c
drawvolume.c
space_view3d.c
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_navigate.c
+ view3d_manipulator_navigate_type.c
+ view3d_manipulator_ruler.c
view3d_ops.c
view3d_project.c
view3d_ruler.c
@@ -74,13 +80,6 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
-if(WITH_GAMEENGINE)
- list(APPEND INC
- ../../../gameengine/BlenderRoutines
- )
- add_definitions(-DWITH_GAMEENGINE)
-endif()
-
add_definitions(${GL_DEFINITIONS})
if(WITH_INTERNATIONAL)
@@ -95,8 +94,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
deleted file mode 100644
index ba75ae6f766..00000000000
--- a/source/blender/editors/space_view3d/drawanimviz.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * ***** 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) 2009 by the Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Joshua Leung
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/space_view3d/drawanimviz.c
- * \ingroup spview3d
- */
-
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "BLI_sys_types.h"
-
-#include "DNA_anim_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_view3d_types.h"
-#include "DNA_object_types.h"
-
-#include "BLI_math.h"
-#include "BLI_dlrbTree.h"
-
-#include "BKE_animsys.h"
-#include "BKE_action.h"
-
-#include "BIF_gl.h"
-
-#include "ED_keyframes_draw.h"
-
-
-#include "UI_resources.h"
-
-#include "view3d_intern.h"
-
-/* ************************************ Motion Paths ************************************* */
-
-/* TODO:
- * - options to draw paths with lines
- * - include support for editing the path verts */
-
-/* Set up drawing environment for drawing motion paths */
-void draw_motion_paths_init(View3D *v3d, ARegion *ar)
-{
- RegionView3D *rv3d = ar->regiondata;
-
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
-
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
-}
-
-/* set color
- * - more intense for active/selected bones, less intense for unselected bones
- * - black for before current frame, green for current frame, blue for after current frame
- * - intensity decreases as distance from current frame increases
- *
- * If the user select custom color, the color is replaced for the color selected in UI panel
- * - 75% Darker color is used for previous frames
- * - 50% Darker color for current frame
- * - 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])
-{
- int frame = sfra + i;
- int blend_base = (abs(frame - CFRA) == 1) ? TH_CFRAME : TH_BACK; /* "bleed" cframe color to ease color blending */
-
-#define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max - min)) + min)
- float intensity; /* how faint */
-
- if (frame < CFRA) {
- if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
- /* Custom color: previous frames color is darker than current frame */
- glColor3fv(prev_color);
- }
- else {
- /* black - before cfra */
- if (sel) {
- /* intensity = 0.5f; */
- intensity = SET_INTENSITY(sfra, i, CFRA, 0.25f, 0.75f);
- }
- else {
- /* intensity = 0.8f; */
- intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f);
- }
- UI_ThemeColorBlend(TH_WIRE, blend_base, intensity);
- }
- }
- else if (frame > CFRA) {
- if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
- /* Custom color: next frames color is equal to user selected color */
- glColor3fv(next_color);
- }
- else {
- /* blue - after cfra */
- if (sel) {
- /* intensity = 0.5f; */
- intensity = SET_INTENSITY(CFRA, i, efra, 0.25f, 0.75f);
- }
- else {
- /* intensity = 0.8f; */
- intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f);
- }
- UI_ThemeColorBlend(TH_BONE_POSE, blend_base, intensity);
- }
- }
- else {
- if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
- /* Custom color: current frame color is slightly darker than user selected color */
- glColor3fv(frame_color);
- }
- else {
- /* green - on cfra */
- if (sel) {
- intensity = 0.5f;
- }
- else {
- intensity = 0.99f;
- }
- UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10);
- }
- }
-#undef SET_INTENSITY
-}
-
-/* Draw the given motion path for an Object or a Bone
- * - assumes that the viewport has already been initialized properly
- * i.e. draw_motion_paths_init() has been called
- */
-void draw_motion_path_instance(Scene *scene,
- Object *ob, bPoseChannel *pchan, bAnimVizSettings *avs, bMotionPath *mpath)
-{
- //RegionView3D *rv3d = ar->regiondata;
- bMotionPathVert *mpv, *mpv_start;
- int i, stepsize = avs->path_step;
- int sfra, efra, sind, len;
- float prev_color[3];
- float frame_color[3];
- float next_color[3];
-
- /* Custom color - Previous frames: color is darker than current frame */
- prev_color[0] = mpath->color[0] * 0.25f;
- prev_color[1] = mpath->color[1] * 0.25f;
- prev_color[2] = mpath->color[2] * 0.25f;
-
- /* Custom color - Current frame: color is slightly darker than user selected color */
- frame_color[0] = mpath->color[0] * 0.50f;
- frame_color[1] = mpath->color[1] * 0.50f;
- frame_color[2] = mpath->color[2] * 0.50f;
-
- /* Custom color - Next frames: color is equal to user selection */
- next_color[0] = mpath->color[0];
- next_color[1] = mpath->color[1];
- next_color[2] = mpath->color[2];
-
- /* Save old line width */
- GLfloat old_width;
- glGetFloatv(GL_LINE_WIDTH, &old_width);
-
- /* get frame ranges */
- if (avs->path_type == MOTIONPATH_TYPE_ACFRA) {
- /* With "Around Current", we only choose frames from around
- * the current frame to draw.
- */
- sfra = CFRA - avs->path_bc;
- efra = CFRA + avs->path_ac;
- }
- else {
- /* Use the current display range */
- sfra = avs->path_sf;
- efra = avs->path_ef;
- }
-
- /* no matter what, we can only show what is in the cache and no more
- * - abort if whole range is past ends of path
- * - otherwise clamp endpoints to extents of path
- */
- if (sfra < mpath->start_frame) {
- /* start clamp */
- sfra = mpath->start_frame;
- }
- if (efra > mpath->end_frame) {
- /* end clamp */
- efra = mpath->end_frame;
- }
-
- if ((sfra > mpath->end_frame) || (efra < mpath->start_frame)) {
- /* whole path is out of bounds */
- return;
- }
-
- len = efra - sfra;
-
- if ((len <= 0) || (mpath->points == NULL)) {
- return;
- }
-
- /* get pointers to parts of path */
- sind = sfra - mpath->start_frame;
- mpv_start = (mpath->points + sind);
-
- /* draw curve-line of path */
- /* Draw lines only if line drawing option is enabled */
- if (mpath->flag & MOTIONPATH_FLAG_LINES) {
- /* set line thickness */
- glLineWidth(mpath->line_thickness);
-
- glBegin(GL_LINE_STRIP);
- 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);
- /* draw a vertex with this color */
- glVertex3fv(mpv->co);
- }
-
- glEnd();
- /* back to old line thickness */
- glLineWidth(old_width);
- }
-
- /* 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 white dots at each framestep value or replace with custom color */
- if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
- glColor4fv(mpath->color);
- }
- else {
- UI_ThemeColor(TH_TEXT_HI);
- }
- glBegin(GL_POINTS);
- for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize)
- glVertex3fv(mpv->co);
- glEnd();
-
- /* 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
- */
- if ((avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) &&
- (sfra < CFRA) && (CFRA <= efra))
- {
- UI_ThemeColor(TH_CFRAME);
-
- glPointSize(mpath->line_thickness + 5.0);
- glBegin(GL_POINTS);
- mpv = mpv_start + (CFRA - sfra);
- glVertex3fv(mpv->co);
- glEnd();
-
- UI_ThemeColor(TH_TEXT_HI);
- }
-
- /* XXX, this isn't up to date but probably should be kept so. */
- invert_m4_m4(ob->imat, ob->obmat);
-
- /* Draw frame numbers at each framestep value */
- if (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) {
- unsigned char col[4];
- UI_GetThemeColor3ubv(TH_TEXT_HI, col);
- col[3] = 255;
-
- for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) {
- int frame = sfra + i;
- char numstr[32];
- size_t numstr_len;
- float co[3];
-
- /* only draw framenum if several consecutive highlighted points don't occur on same point */
- if (i == 0) {
- numstr_len = sprintf(numstr, " %d", frame);
- mul_v3_m4v3(co, ob->imat, mpv->co);
- view3d_cached_text_draw_add(co, numstr, numstr_len,
- 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
- }
- else if ((i >= stepsize) && (i < len - stepsize)) {
- bMotionPathVert *mpvP = (mpv - stepsize);
- bMotionPathVert *mpvN = (mpv + stepsize);
-
- if ((equals_v3v3(mpv->co, mpvP->co) == 0) || (equals_v3v3(mpv->co, mpvN->co) == 0)) {
- numstr_len = sprintf(numstr, " %d", frame);
- mul_v3_m4v3(co, ob->imat, mpv->co);
- view3d_cached_text_draw_add(co, numstr, numstr_len,
- 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
- }
- }
- }
- }
-
- /* Keyframes - dots and numbers */
- if (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) {
- unsigned char col[4];
-
- AnimData *adt = BKE_animdata_from_id(&ob->id);
- DLRBT_Tree keys;
-
- /* build list of all keyframes in active action for object or pchan */
- BLI_dlrbTree_init(&keys);
-
- if (adt) {
- /* it is assumed that keyframes for bones are all grouped in a single group
- * unless an option is set to always use the whole action
- */
- if ((pchan) && (avs->path_viewflag & MOTIONPATH_VIEW_KFACT) == 0) {
- bActionGroup *agrp = BKE_action_group_find_name(adt->action, pchan->name);
-
- if (agrp) {
- agroup_to_keylist(adt, agrp, &keys, NULL);
- BLI_dlrbTree_linkedlist_sync(&keys);
- }
- }
- else {
- action_to_keylist(adt, adt->action, &keys, NULL);
- BLI_dlrbTree_linkedlist_sync(&keys);
- }
- }
-
- /* Draw slightly-larger yellow dots at each keyframe */
- 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);
-
- glBegin(GL_POINTS);
- 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);
- }
- glEnd();
-
- /* Draw frame numbers of keyframes */
- if (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) {
- float co[3];
- for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
- float mframe = (float)(sfra + i);
-
- if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) {
- char numstr[32];
- size_t numstr_len;
-
- numstr_len = sprintf(numstr, " %d", (sfra + i));
- mul_v3_m4v3(co, ob->imat, mpv->co);
- view3d_cached_text_draw_add(co, numstr, numstr_len,
- 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
- }
- }
- }
-
- BLI_dlrbTree_free(&keys);
- }
-}
-
-/* Clean up drawing environment after drawing motion paths */
-void draw_motion_paths_cleanup(View3D *v3d)
-{
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- glPopMatrix();
-}
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
deleted file mode 100644
index bbda002eb8d..00000000000
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ /dev/null
@@ -1,2793 +0,0 @@
-/*
- * ***** 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) 2005 by the Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/space_view3d/drawarmature.c
- * \ingroup spview3d
- */
-
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "DNA_anim_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_view3d_types.h"
-#include "DNA_object_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_dlrbTree.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_animsys.h"
-#include "BKE_action.h"
-#include "BKE_armature.h"
-#include "BKE_global.h"
-#include "BKE_modifier.h"
-#include "BKE_nla.h"
-#include "BKE_curve.h"
-
-
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
-#include "ED_armature.h"
-#include "ED_keyframes_draw.h"
-
-#include "GPU_basic_shader.h"
-
-#include "UI_resources.h"
-
-#include "view3d_intern.h"
-
-#include "GPU_select.h"
-
-/* *************** Armature Drawing - Coloring API ***************************** */
-
-/* global here is reset before drawing each bone */
-static ThemeWireColor *bcolor = NULL;
-
-/* values of colCode for set_pchan_glcolor */
-enum {
- PCHAN_COLOR_NORMAL = 0, /* normal drawing */
- PCHAN_COLOR_SOLID, /* specific case where "solid" color is needed */
- PCHAN_COLOR_CONSTS, /* "constraint" colors (which may/may-not be suppressed) */
-
- PCHAN_COLOR_SPHEREBONE_BASE, /* for the 'stick' of sphere (envelope) bones */
- PCHAN_COLOR_SPHEREBONE_END, /* for the ends of sphere (envelope) bones */
- PCHAN_COLOR_LINEBONE /* for the middle of line-bones */
-};
-
-/* This function sets the color-set for coloring a certain bone */
-static void set_pchan_colorset(Object *ob, bPoseChannel *pchan)
-{
- bPose *pose = (ob) ? ob->pose : NULL;
- bArmature *arm = (ob) ? ob->data : NULL;
- bActionGroup *grp = NULL;
- short color_index = 0;
-
- /* sanity check */
- if (ELEM(NULL, ob, arm, pose, pchan)) {
- bcolor = NULL;
- return;
- }
-
- /* only try to set custom color if enabled for armature */
- if (arm->flag & ARM_COL_CUSTOM) {
- /* currently, a bone can only use a custom color set if it's group (if it has one),
- * has been set to use one
- */
- if (pchan->agrp_index) {
- grp = (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
- if (grp)
- color_index = grp->customCol;
- }
- }
-
- /* bcolor is a pointer to the color set to use. If NULL, then the default
- * color set (based on the theme colors for 3d-view) is used.
- */
- if (color_index > 0) {
- bTheme *btheme = UI_GetTheme();
- bcolor = &btheme->tarm[(color_index - 1)];
- }
- else if (color_index == -1) {
- /* use the group's own custom color set (grp is always != NULL here) */
- bcolor = &grp->cs;
- }
- else {
- bcolor = NULL;
- }
-}
-
-/* This function is for brightening/darkening a given color (like UI_ThemeColorShade()) */
-static void cp_shade_color3ub(unsigned char cp[3], const int offset)
-{
- int r, g, b;
-
- r = offset + (int) cp[0];
- CLAMP(r, 0, 255);
- g = offset + (int) cp[1];
- CLAMP(g, 0, 255);
- b = offset + (int) cp[2];
- CLAMP(b, 0, 255);
-
- cp[0] = r;
- cp[1] = g;
- cp[2] = b;
-}
-
-/* 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)
-{
- switch (colCode) {
- case PCHAN_COLOR_NORMAL:
- {
- if (bcolor) {
- unsigned char cp[3];
-
- if (boneflag & BONE_DRAW_ACTIVE) {
- copy_v3_v3_char((char *)cp, bcolor->active);
- if (!(boneflag & BONE_SELECTED)) {
- cp_shade_color3ub(cp, -80);
- }
- }
- else if (boneflag & BONE_SELECTED) {
- copy_v3_v3_char((char *)cp, bcolor->select);
- }
- else {
- /* a bit darker than solid */
- copy_v3_v3_char((char *)cp, bcolor->solid);
- cp_shade_color3ub(cp, -50);
- }
-
- glColor3ubv(cp);
- }
- else {
- if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) {
- UI_ThemeColor(TH_BONE_POSE_ACTIVE);
- }
- else if (boneflag & BONE_DRAW_ACTIVE) {
- UI_ThemeColorBlend(TH_WIRE, TH_BONE_POSE, 0.15f); /* unselected active */
- }
- else if (boneflag & BONE_SELECTED) {
- UI_ThemeColor(TH_BONE_POSE);
- }
- else {
- UI_ThemeColor(TH_WIRE);
- }
- }
-
- return true;
- }
- case PCHAN_COLOR_SOLID:
- {
- if (bcolor) {
- glColor3ubv((unsigned char *)bcolor->solid);
- }
- 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);
-
- return true;
- }
- return false;
- }
- case PCHAN_COLOR_SPHEREBONE_BASE:
- {
- if (bcolor) {
- unsigned char cp[3];
-
- if (boneflag & BONE_DRAW_ACTIVE) {
- copy_v3_v3_char((char *)cp, bcolor->active);
- }
- else if (boneflag & BONE_SELECTED) {
- copy_v3_v3_char((char *)cp, bcolor->select);
- }
- else {
- copy_v3_v3_char((char *)cp, bcolor->solid);
- }
-
- glColor3ubv(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);
- }
-
- return true;
- }
- case PCHAN_COLOR_SPHEREBONE_END:
- {
- if (bcolor) {
- unsigned char cp[3];
-
- if (boneflag & BONE_DRAW_ACTIVE) {
- copy_v3_v3_char((char *)cp, bcolor->active);
- cp_shade_color3ub(cp, 10);
- }
- else if (boneflag & BONE_SELECTED) {
- copy_v3_v3_char((char *)cp, bcolor->select);
- cp_shade_color3ub(cp, -30);
- }
- else {
- copy_v3_v3_char((char *)cp, bcolor->solid);
- cp_shade_color3ub(cp, -30);
- }
-
- glColor3ubv(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);
- }
- break;
- }
- case PCHAN_COLOR_LINEBONE:
- {
- /* 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 */
- }
- else {
- if (bcolor) {
- const char *cp = bcolor->solid;
- glColor4ub(cp[0], cp[1], cp[2], 204);
- }
- else
- UI_ThemeColorShade(TH_BACK, -30);
- }
-
- return true;
- }
- }
-
- return false;
-}
-
-static void set_ebone_glColor(const unsigned int boneflag)
-{
- if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) {
- UI_ThemeColor(TH_EDGE_SELECT);
- }
- else if (boneflag & BONE_DRAW_ACTIVE) {
- UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f); /* unselected active */
- }
- else if (boneflag & BONE_SELECTED) {
- UI_ThemeColorShade(TH_EDGE_SELECT, -20);
- }
- else {
- UI_ThemeColor(TH_WIRE_EDIT);
- }
-}
-
-/* *************** Armature drawing, helper calls for parts ******************* */
-
-/* half the cube, in Y */
-static const float cube[8][3] = {
- {-1.0, 0.0, -1.0},
- {-1.0, 0.0, 1.0},
- {-1.0, 1.0, 1.0},
- {-1.0, 1.0, -1.0},
- { 1.0, 0.0, -1.0},
- { 1.0, 0.0, 1.0},
- { 1.0, 1.0, 1.0},
- { 1.0, 1.0, -1.0},
-};
-
-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);
-
- glBegin(GL_QUADS);
- n[0] = -1.0;
- glNormal3fv(n);
- glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
- n[0] = 0;
- n[1] = -1.0;
- glNormal3fv(n);
- glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
- n[1] = 0;
- n[0] = 1.0;
- glNormal3fv(n);
- glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
- n[0] = 0;
- n[1] = 1.0;
- glNormal3fv(n);
- glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
- n[1] = 0;
- n[2] = 1.0;
- glNormal3fv(n);
- glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
- n[2] = -1.0;
- glNormal3fv(n);
- glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
- glEnd();
-
- glEndList();
- }
-
- glCallList(displist);
-}
-
-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();
- }
-
- glScalef(xsize, ysize, zsize);
- glCallList(displist);
-
-}
-
-
-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();
- }
-
- glCallList(displist);
-}
-
-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();
- }
-
- glCallList(displist);
-}
-
-static const float bone_octahedral_verts[6][3] = {
- { 0.0f, 0.0f, 0.0f},
- { 0.1f, 0.1f, 0.1f},
- { 0.1f, 0.1f, -0.1f},
- {-0.1f, 0.1f, -0.1f},
- {-0.1f, 0.1f, 0.1f},
- { 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_solid_tris[8][3] = {
- {2, 1, 0}, /* bottom */
- {3, 2, 0},
- {4, 3, 0},
- {1, 4, 0},
-
- {5, 1, 2}, /* top */
- {5, 2, 3},
- {5, 3, 4},
- {5, 4, 1}
-};
-
-/* aligned with bone_octahedral_solid_tris */
-static const float bone_octahedral_solid_normals[8][3] = {
- { M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
- {-0.00000000f, -M_SQRT1_2, -M_SQRT1_2},
- {-M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
- { 0.00000000f, -M_SQRT1_2, M_SQRT1_2},
- { 0.99388373f, 0.11043154f, -0.00000000f},
- { 0.00000000f, 0.11043154f, -0.99388373f},
- {-0.99388373f, 0.11043154f, 0.00000000f},
- { 0.00000000f, 0.11043154f, 0.99388373f}
-};
-
-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();
- }
-
- glCallList(displist);
-}
-
-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
-
- glEndList();
- }
-
- glCallList(displist);
-}
-
-/* *************** Armature drawing, bones ******************* */
-
-
-static void draw_bone_points(const short dt, int armflag, unsigned int boneflag, int id)
-{
- /* Draw root point if we are not connected */
- if ((boneflag & BONE_CONNECTED) == 0) {
- if (id != -1)
- GPU_select_load_id(id | BONESEL_ROOT);
-
- if (dt <= OB_WIRE) {
- if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
- }
- }
- else {
- if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0);
- else
- UI_ThemeColor(TH_BONE_SOLID);
- }
-
- if (dt > OB_WIRE)
- draw_bonevert_solid();
- else
- draw_bonevert();
- }
-
- /* Draw tip point */
- if (id != -1)
- GPU_select_load_id(id | BONESEL_TIP);
-
- if (dt <= OB_WIRE) {
- if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
- }
- }
- else {
- if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0);
- else
- UI_ThemeColor(TH_BONE_SOLID);
- }
-
- glTranslatef(0.0f, 1.0f, 0.0f);
- if (dt > OB_WIRE)
- draw_bonevert_solid();
- else
- draw_bonevert();
- glTranslatef(0.0f, -1.0f, 0.0f);
-
-}
-
-/* 16 values of sin function (still same result!) */
-static const float si[16] = {
- 0.00000000f,
- 0.20129852f, 0.39435585f,
- 0.57126821f, 0.72479278f,
- 0.84864425f, 0.93775213f,
- 0.98846832f, 0.99871650f,
- 0.96807711f, 0.89780453f,
- 0.79077573f, 0.65137248f,
- 0.48530196f, 0.29936312f,
- 0.10116832f
-};
-/* 16 values of cos function (still same result!) */
-static const float co[16] = {
- 1.00000000f,
- 0.97952994f, 0.91895781f,
- 0.82076344f, 0.68896691f,
- 0.52896401f, 0.34730525f,
- 0.15142777f, -0.05064916f,
- -0.25065253f, -0.44039415f,
- -0.61210598f, -0.75875812f,
- -0.87434661f, -0.95413925f,
- -0.99486932f
-};
-
-
-
-/* smat, imat = mat & imat to draw screenaligned */
-static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChannel *pchan, EditBone *ebone)
-{
- float head, tail, dist /*, length*/;
- float *headvec, *tailvec, dirvec[3];
-
- /* figure out the sizes of spheres */
- if (ebone) {
- /* this routine doesn't call get_matrix_editbone() that calculates it */
- ebone->length = len_v3v3(ebone->head, ebone->tail);
-
- /*length = ebone->length;*/ /*UNUSED*/
- tail = ebone->rad_tail;
- dist = ebone->dist;
- if (ebone->parent && (ebone->flag & BONE_CONNECTED))
- head = ebone->parent->rad_tail;
- else
- head = ebone->rad_head;
- headvec = ebone->head;
- tailvec = ebone->tail;
- }
- else {
- /*length = pchan->bone->length;*/ /*UNUSED*/
- tail = pchan->bone->rad_tail;
- dist = pchan->bone->dist;
- if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED))
- head = pchan->parent->bone->rad_tail;
- else
- head = pchan->bone->rad_head;
- headvec = pchan->pose_head;
- tailvec = pchan->pose_tail;
- }
-
- /* ***** draw it ***** */
-
- /* move vector to viewspace */
- sub_v3_v3v3(dirvec, tailvec, headvec);
- mul_mat3_m4_v3(smat, dirvec);
- /* clear zcomp */
- dirvec[2] = 0.0f;
-
- if (head != tail) {
- /* correction when viewing along the bones axis
- * it pops in and out but better then artifacts, [#23841] */
- float view_dist = len_v2(dirvec);
-
- if (head - view_dist > tail) {
- tailvec = headvec;
- tail = head;
- zero_v3(dirvec);
- dirvec[0] = 0.00001; /* XXX. weak but ok */
- }
- else if (tail - view_dist > head) {
- headvec = tailvec;
- head = tail;
- zero_v3(dirvec);
- dirvec[0] = 0.00001; /* XXX. weak but ok */
- }
- }
-
- /* move vector back */
- mul_mat3_m4_v3(imat, dirvec);
-
- if (0.0f != normalize_v3(dirvec)) {
- float norvec[3], vec1[3], vec2[3], vec[3];
- int a;
-
- //mul_v3_fl(dirvec, head);
- cross_v3_v3v3(norvec, dirvec, imat[2]);
-
- glBegin(GL_QUAD_STRIP);
-
- for (a = 0; a < 16; a++) {
- vec[0] = -si[a] * dirvec[0] + co[a] * norvec[0];
- vec[1] = -si[a] * dirvec[1] + co[a] * norvec[1];
- vec[2] = -si[a] * dirvec[2] + co[a] * norvec[2];
-
- 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);
- }
-
- for (a = 15; a >= 0; a--) {
- vec[0] = si[a] * dirvec[0] + co[a] * norvec[0];
- vec[1] = si[a] * dirvec[1] + co[a] * norvec[1];
- vec[2] = si[a] * dirvec[2] + co[a] * norvec[2];
-
- 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);
- }
- /* make it cyclic... */
-
- vec[0] = -si[0] * dirvec[0] + co[0] * norvec[0];
- vec[1] = -si[0] * dirvec[1] + co[0] * norvec[1];
- vec[2] = -si[0] * dirvec[2] + co[0] * norvec[2];
-
- 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);
-
- glEnd();
- }
-}
-
-
-/* smat, imat = mat & imat to draw screenaligned */
-static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
- int armflag, int boneflag, short constflag, unsigned int id,
- bPoseChannel *pchan, EditBone *ebone)
-{
- float head, tail /*, length*/;
- float *headvec, *tailvec, dirvec[3];
-
- /* figure out the sizes of spheres */
- if (ebone) {
- /* this routine doesn't call get_matrix_editbone() that calculates it */
- ebone->length = len_v3v3(ebone->head, ebone->tail);
-
- /*length = ebone->length;*/ /*UNUSED*/
- tail = ebone->rad_tail;
- if (ebone->parent && (boneflag & BONE_CONNECTED))
- head = ebone->parent->rad_tail;
- else
- head = ebone->rad_head;
- headvec = ebone->head;
- tailvec = ebone->tail;
- }
- else {
- /*length = pchan->bone->length;*/ /*UNUSED*/
- tail = pchan->bone->rad_tail;
- if ((pchan->parent) && (boneflag & BONE_CONNECTED))
- head = pchan->parent->bone->rad_tail;
- else
- head = pchan->bone->rad_head;
- headvec = pchan->pose_head;
- tailvec = pchan->pose_tail;
- }
-
- /* sphere root color */
- if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
- }
- else if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
-
- /* 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);
- }
-
- /* Draw tip point */
- if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
- }
-
- if (id != -1)
- GPU_select_load_id(id | BONESEL_TIP);
-
- drawcircball(GL_LINE_LOOP, tailvec, tail, imat);
-
- /* base */
- if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
- else UI_ThemeColor(TH_WIRE_EDIT);
- }
-
- sub_v3_v3v3(dirvec, tailvec, headvec);
-
- /* move vector to viewspace */
- mul_mat3_m4_v3(smat, dirvec);
- /* clear zcomp */
- dirvec[2] = 0.0f;
- /* move vector back */
- mul_mat3_m4_v3(imat, dirvec);
-
- if (0.0f != normalize_v3(dirvec)) {
- float norvech[3], norvect[3], vec[3];
-
- copy_v3_v3(vec, dirvec);
-
- mul_v3_fl(dirvec, head);
- cross_v3_v3v3(norvech, dirvec, imat[2]);
-
- mul_v3_fl(vec, tail);
- cross_v3_v3v3(norvect, vec, imat[2]);
-
- if (id != -1)
- GPU_select_load_id(id | BONESEL_BONE);
-
- glBegin(GL_LINES);
-
- add_v3_v3v3(vec, headvec, norvech);
- glVertex3fv(vec);
-
- add_v3_v3v3(vec, tailvec, norvect);
- glVertex3fv(vec);
-
- sub_v3_v3v3(vec, headvec, norvech);
- glVertex3fv(vec);
-
- sub_v3_v3v3(vec, tailvec, norvect);
- glVertex3fv(vec);
-
- glEnd();
- }
-}
-
-/* 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;
- float head, tail, length;
- float fac1, fac2;
-
- glPushMatrix();
- qobj = gluNewQuadric();
-
- /* figure out the sizes of spheres */
- if (ebone) {
- length = ebone->length;
- tail = ebone->rad_tail;
- if (ebone->parent && (boneflag & BONE_CONNECTED))
- head = ebone->parent->rad_tail;
- else
- head = ebone->rad_head;
- }
- else {
- length = pchan->bone->length;
- tail = pchan->bone->rad_tail;
- if (pchan->parent && (boneflag & BONE_CONNECTED))
- head = pchan->parent->bone->rad_tail;
- else
- head = pchan->bone->rad_head;
- }
-
- /* move to z-axis space */
- glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
-
- 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);
- }
- else if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_END, boneflag, constflag);
- else if (dt == OB_SOLID)
- UI_ThemeColorShade(TH_BONE_SOLID, -30);
-
- /* 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);
- }
-
- /* Draw tip point */
- if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColorShade(TH_BONE_SOLID, -30);
- }
-
- 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);
-
- /* base */
- if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
- else UI_ThemeColor(TH_BONE_SOLID);
- }
- else if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_BASE, boneflag, constflag);
- else if (dt == OB_SOLID)
- UI_ThemeColor(TH_BONE_SOLID);
-
- fac1 = (length - head) / length;
- fac2 = (length - tail) / length;
-
- if (length > (head + tail)) {
- if (id != -1)
- GPU_select_load_id(id | BONESEL_BONE);
-
- 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);
-
- 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 {
- /* 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);
- }
-
- glPopMatrix();
- gluDeleteQuadric(qobj);
-}
-
-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)
- length = pchan->bone->length;
- else
- length = ebone->length;
-
- glPushMatrix();
- glScalef(length, length, 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);
- }
-
- if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
- else if (armflag & ARM_EDITMODE) {
- UI_ThemeColor(TH_WIRE_EDIT);
- }
-
- /* Draw root point if we are not connected */
- if ((boneflag & BONE_CONNECTED) == 0) {
- 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);
- }
- }
-
- 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... */
- 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);
- }
-
- /* 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);
- }
-
- glLineWidth(2.0);
-
- /*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_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);
- }
- glRasterPos3f(0.0f, 1.0f, 0.0f);
- glBitmap(8, 8, 4, 4, 0, 0, bm_dot5);
- }
-
- glPopMatrix();
-}
-
-/* A partial copy of b_bone_spline_setup(), with just the parts for previewing editmode curve settings
- *
- * This assumes that prev/next bones don't have any impact (since they should all still be in the "straight"
- * position here anyway), and that we can simply apply the bbone settings to get the desired effect...
- */
-static void ebone_spline_preview(EditBone *ebone, Mat4 result_array[MAX_BBONE_SUBDIV])
-{
- float h1[3], h2[3], length, hlength1, hlength2, roll1 = 0.0f, roll2 = 0.0f;
- float mat3[3][3];
- float data[MAX_BBONE_SUBDIV + 1][4], *fp;
- int a;
-
- length = ebone->length;
-
- hlength1 = ebone->ease1 * length * 0.390464f; /* 0.5f * sqrt(2) * kappa, the handle length for near-perfect circles */
- hlength2 = ebone->ease2 * length * 0.390464f;
-
- /* find the handle points, since this is inside bone space, the
- * first point = (0, 0, 0)
- * last point = (0, length, 0)
- *
- * we also just apply all the "extra effects", since they're the whole reason we're doing this...
- */
- h1[0] = ebone->curveInX;
- h1[1] = hlength1;
- h1[2] = ebone->curveInY;
- roll1 = ebone->roll1;
-
- h2[0] = ebone->curveOutX;
- h2[1] = -hlength2;
- h2[2] = ebone->curveOutY;
- roll2 = ebone->roll2;
-
- /* make curve */
- if (ebone->segments > MAX_BBONE_SUBDIV)
- ebone->segments = MAX_BBONE_SUBDIV;
-
- BKE_curve_forward_diff_bezier(0.0f, h1[0], h2[0], 0.0f, data[0], MAX_BBONE_SUBDIV, 4 * sizeof(float));
- BKE_curve_forward_diff_bezier(0.0f, h1[1], length + h2[1], length, data[0] + 1, MAX_BBONE_SUBDIV, 4 * sizeof(float));
- BKE_curve_forward_diff_bezier(0.0f, h1[2], h2[2], 0.0f, data[0] + 2, MAX_BBONE_SUBDIV, 4 * sizeof(float));
- BKE_curve_forward_diff_bezier(roll1, roll1 + 0.390464f * (roll2 - roll1), roll2 - 0.390464f * (roll2 - roll1), roll2, data[0] + 3, MAX_BBONE_SUBDIV, 4 * sizeof(float));
-
- equalize_bbone_bezier(data[0], ebone->segments); /* note: does stride 4! */
-
- /* make transformation matrices for the segments for drawing */
- for (a = 0, fp = data[0]; a < ebone->segments; a++, fp += 4) {
- sub_v3_v3v3(h1, fp + 4, fp);
- vec_roll_to_mat3(h1, fp[3], mat3); /* fp[3] is roll */
-
- copy_m4_m3(result_array[a].mat, mat3);
- copy_v3_v3(result_array[a].mat[3], fp);
-
- /* "extra" scale facs... */
- {
- const int num_segments = ebone->segments;
-
- const float scaleFactorIn = 1.0f + (ebone->scaleIn - 1.0f) * ((float)(num_segments - a) / (float)num_segments);
- const float scaleFactorOut = 1.0f + (ebone->scaleOut - 1.0f) * ((float)(a + 1) / (float)num_segments);
-
- const float scalefac = scaleFactorIn * scaleFactorOut;
- float bscalemat[4][4], bscale[3];
-
- bscale[0] = scalefac;
- bscale[1] = 1.0f;
- bscale[2] = scalefac;
-
- size_to_mat4(bscalemat, bscale);
-
- /* Note: don't multiply by inverse scale mat here, as it causes problems with scaling shearing and breaking segment chains */
- mul_m4_series(result_array[a].mat, result_array[a].mat, bscalemat);
- }
- }
-}
-
-static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, EditBone *ebone, float xwidth, float length, float zwidth)
-{
- int segments = 0;
-
- if (pchan)
- segments = pchan->bone->segments;
- else if (ebone)
- segments = ebone->segments;
-
- if (segments > 1) {
- float dlen = length / (float)segments;
- Mat4 bbone[MAX_BBONE_SUBDIV];
- int a;
-
- if (pchan) {
- b_bone_spline_setup(pchan, 0, bbone);
- }
- else if (ebone) {
- ebone_spline_preview(ebone, bbone);
- }
-
- for (a = 0; a < segments; a++) {
- glPushMatrix();
- glMultMatrixf(bbone[a].mat);
- if (dt == OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
- else drawcube_size(xwidth, dlen, zwidth);
- glPopMatrix();
- }
- }
- else {
- glPushMatrix();
- if (dt == OB_SOLID) drawsolidcube_size(xwidth, length, zwidth);
- else drawcube_size(xwidth, length, zwidth);
- glPopMatrix();
- }
-}
-
-static void draw_b_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id,
- bPoseChannel *pchan, EditBone *ebone)
-{
- float xwidth, length, zwidth;
-
- if (pchan) {
- xwidth = pchan->bone->xwidth;
- length = pchan->bone->length;
- zwidth = pchan->bone->zwidth;
- }
- else {
- xwidth = ebone->xwidth;
- length = ebone->length;
- zwidth = ebone->zwidth;
- }
-
- /* draw points only if... */
- if (armflag & ARM_EDITMODE) {
- /* move to unitspace */
- glPushMatrix();
- glScalef(length, length, length);
- draw_bone_points(dt, armflag, boneflag, id);
- glPopMatrix();
- 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);
- else
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
- }
- else if (armflag & ARM_EDITMODE) {
- if (dt == OB_WIRE) {
- set_ebone_glColor(boneflag);
- }
- else
- UI_ThemeColor(TH_BONE_SOLID);
- }
-
- if (id != -1) {
- GPU_select_load_id((GLuint) id | BONESEL_BONE);
- }
-
- /* 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);
-
- 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)) {
- glEnable(GL_BLEND);
-
- draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth);
-
- glDisable(GL_BLEND);
- }
-
- /* restore colors */
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
- }
- }
-
- draw_b_bone_boxes(OB_WIRE, pchan, ebone, xwidth, length, zwidth);
- }
-}
-
-static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float length, int segments)
-{
- 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();
- }
- }
- else {
- glPushMatrix();
-
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3f(0.0f, length, 0.0f);
- glEnd();
-
- glPopMatrix();
- }
-}
-
-static void draw_wire_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id,
- bPoseChannel *pchan, EditBone *ebone)
-{
- Mat4 bbones_array[MAX_BBONE_SUBDIV];
- Mat4 *bbones = NULL;
- int segments = 0;
- float length;
-
- if (pchan) {
- segments = pchan->bone->segments;
- length = pchan->bone->length;
-
- if (segments > 1) {
- b_bone_spline_setup(pchan, 0, bbones_array);
- bbones = bbones_array;
- }
- }
- else
- length = ebone->length;
-
- /* draw points only if... */
- if (armflag & ARM_EDITMODE) {
- /* move to unitspace */
- glPushMatrix();
- glScalef(length, length, length);
- draw_bone_points(dt, armflag, boneflag, id);
- glPopMatrix();
- length *= 0.95f; /* make vertices visible */
- }
-
- /* this chunk not in object mode */
- if (armflag & (ARM_EDITMODE | ARM_POSEMODE)) {
- if (id != -1)
- GPU_select_load_id((GLuint) id | BONESEL_BONE);
-
- draw_wire_bone_segments(pchan, bbones, length, segments);
-
- /* further we send no names */
- if (id != -1)
- GPU_select_load_id(id & 0xFFFF); /* object tag, for bordersel optim */
- }
-
- /* colors for modes */
- if (armflag & ARM_POSEMODE) {
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
- }
- else if (armflag & ARM_EDITMODE) {
- set_ebone_glColor(boneflag);
- }
-
- /* draw normal */
- draw_wire_bone_segments(pchan, bbones, length, segments);
-}
-
-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);
-
- /* set up solid drawing */
- if (dt > OB_WIRE) {
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
- UI_ThemeColor(TH_BONE_SOLID);
- }
-
- /* colors for posemode */
- if (armflag & ARM_POSEMODE) {
- if (dt <= OB_WIRE)
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
- else
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
- }
-
-
- draw_bone_points(dt, armflag, boneflag, id);
-
- /* now draw the bone itself */
- if (id != -1) {
- GPU_select_load_id((GLuint) id | BONESEL_BONE);
- }
-
- /* wire? */
- if (dt <= OB_WIRE) {
- /* colors */
- if (armflag & ARM_EDITMODE) {
- set_ebone_glColor(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)) {
- glEnable(GL_BLEND);
-
- draw_bone_solid_octahedral();
-
- glDisable(GL_BLEND);
- }
-
- /* restore colors */
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
- }
- }
- draw_bone_octahedral();
- }
- else {
- /* solid */
- if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
- else
- UI_ThemeColor(TH_BONE_SOLID);
- draw_bone_solid_octahedral();
- }
-
- /* disable solid drawing */
- if (dt > OB_WIRE) {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- }
-}
-
-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)
-{
- if (ob == NULL) return;
-
- glScalef(length, length, length);
-
- /* colors for posemode */
- if (armflag & ARM_POSEMODE) {
- set_pchan_glColor(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);
-}
-
-
-static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp)
-{
- bConstraint *con;
- bPoseChannel *parchan;
-
- for (con = pchan->constraints.first; con; con = con->next) {
- if (con->enforce == 0.0f)
- continue;
-
- switch (con->type) {
- case CONSTRAINT_TYPE_KINEMATIC:
- {
- bKinematicConstraint *data = (bKinematicConstraint *)con->data;
- int segcount = 0;
-
- /* 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);
-
- /* Find the chain's root */
- while (parchan->parent) {
- segcount++;
- if (segcount == data->rootbone || segcount > 255) {
- break; /* 255 is weak */
- }
- parchan = parchan->parent;
- }
- if (parchan)
- glVertex3fv(parchan->pose_head);
-
- glEnd();
- setlinestyle(0);
- break;
- }
- case CONSTRAINT_TYPE_SPLINEIK:
- {
- bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
- int segcount = 0;
-
- setlinestyle(3);
- glBegin(GL_LINES);
-
- parchan = pchan;
- glVertex3fv(parchan->pose_tail);
-
- /* Find the chain's root */
- while (parchan->parent) {
- segcount++;
- /* FIXME: revise the breaking conditions */
- if (segcount == data->chainlen || segcount > 255) break; /* 255 is weak */
- 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);
- break;
- }
- }
- }
-}
-
-static void bgl_sphere_project(float ax, float az)
-{
- float dir[3], sine, q3;
-
- sine = 1.0f - ax * ax - az * az;
- q3 = (sine < 0.0f) ? 0.0f : (2.0f * sqrtf(sine));
-
- dir[0] = -az * q3;
- dir[1] = 1.0f - 2.0f * sine;
- dir[2] = ax * q3;
-
- glVertex3fv(dir);
-}
-
-static void draw_dof_ellipse(float ax, float az)
-{
- const float staticSine[16] = {
- 0.0f, 0.104528463268f, 0.207911690818f, 0.309016994375f,
- 0.406736643076f, 0.5f, 0.587785252292f, 0.669130606359f,
- 0.743144825477f, 0.809016994375f, 0.866025403784f,
- 0.913545457643f, 0.951056516295f, 0.978147600734f,
- 0.994521895368f, 1.0f
- };
-
- int i, j, n = 16;
- float x, z, px, pz;
-
- glEnable(GL_BLEND);
- glDepthMask(0);
-
- glColor4ub(70, 70, 70, 50);
-
- glBegin(GL_QUADS);
- pz = 0.0f;
- for (i = 1; i < n; i++) {
- z = staticSine[i];
-
- px = 0.0f;
- for (j = 1; j <= (n - i); j++) {
- 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);
- }
- 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);
- }
-
- px = x;
- }
- pz = z;
- }
- glEnd();
-
- glDisable(GL_BLEND);
- glDepthMask(1);
-
- glColor3ub(0, 0, 0);
-
- glBegin(GL_LINE_STRIP);
- for (i = 0; i < n; i++)
- bgl_sphere_project(staticSine[n - i - 1] * ax, staticSine[i] * az);
- glEnd();
-}
-
-static void draw_pose_dofs(Object *ob)
-{
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
- Bone *bone;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bone = pchan->bone;
-
- if ((bone != NULL) && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
- if (bone->flag & BONE_SELECTED) {
- if (bone->layer & arm->layer) {
- if (pchan->ikflag & (BONE_IK_XLIMIT | BONE_IK_ZLIMIT)) {
- if (BKE_pose_channel_in_IK_chain(ob, pchan)) {
- float corner[4][3], posetrans[3], mat[4][4];
- float phi = 0.0f, theta = 0.0f, scale;
- int a, i;
-
- /* in parent-bone pose, but own restspace */
- glPushMatrix();
-
- copy_v3_v3(posetrans, pchan->pose_mat[3]);
- glTranslate3fv(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);
- }
-
- copy_m4_m3(mat, pchan->bone->bone_mat);
- glMultMatrixf(mat);
-
- scale = bone->length * pchan->size[1];
- glScalef(scale, scale, 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);
- }
- }
-
- /* 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);
-
- glColor3ub(50, 50, 255); /* blue, Z axis limit */
- glBegin(GL_LINE_STRIP);
- 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;
-
- phi = fac * (pchan->limitmax[2] - pchan->limitmin[2]);
-
- i = (a == -16) ? 0 : 1;
- corner[i][0] = sinf(phi);
- corner[i][1] = cosf(phi);
- corner[i][2] = 0.0f;
- glVertex3fv(corner[i]);
- }
- glEnd();
-
- glRotatef(-theta, 0.0f, 0.0f, 1.0f);
- }
-
- 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);
-
- glColor3ub(255, 50, 50); /* Red, X axis limit */
- glBegin(GL_LINE_STRIP);
- 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;
- phi = (float)M_PI_2 + fac * (pchan->limitmax[0] - pchan->limitmin[0]);
-
- i = (a == -16) ? 2 : 3;
- corner[i][0] = 0.0f;
- corner[i][1] = sinf(phi);
- corner[i][2] = cosf(phi);
- glVertex3fv(corner[i]);
- }
- glEnd();
-
- glRotatef(-theta, 1.0f, 0.0f, 0.0f);
- }
-
- /* out of cone, out of bone */
- glPopMatrix();
- }
- }
- }
- }
- }
- }
-}
-
-static void bone_matrix_translate_y(float mat[4][4], float y)
-{
- float trans[3];
-
- copy_v3_v3(trans, mat[1]);
- mul_v3_fl(trans, y);
- add_v3_v3(mat[3], trans);
-}
-
-/* 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)
-{
- RegionView3D *rv3d = ar->regiondata;
- Object *ob = base->object;
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
- Bone *bone;
- float smat[4][4], imat[4][4], bmat[4][4];
- int index = -1;
- const enum {
- DASH_RELATIONSHIP_LINES = 1,
- DASH_HELP_LINES = 2,
- } do_dashed = (
- (is_outline ? 0 : DASH_RELATIONSHIP_LINES) |
- ((v3d->flag & V3D_HIDE_HELPLINES) ? 0 : DASH_HELP_LINES));
- bool draw_wire = false;
- int flag;
- bool is_cull_enabled;
-
- /* being set below */
- arm->layer_used = 0;
-
- /* precalc inverse matrix for drawing screen aligned */
- if (arm->drawtype == ARM_ENVELOPE) {
- /* precalc inverse matrix for drawing screen aligned */
- copy_m4_m4(smat, rv3d->viewmatob);
- mul_mat3_m4_fl(smat, 1.0f / len_v3(ob->obmat[0]));
- invert_m4_m4(imat, smat);
-
- /* and draw blended distances */
- if (arm->flag & ARM_POSEMODE) {
- glEnable(GL_BLEND);
-
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bone = pchan->bone;
- if (bone) {
- /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194]
- * NOTE: this is the only case with (NO_DEFORM == 0) flag, as this is for envelope influence drawing
- */
- if (((bone->flag & (BONE_HIDDEN_P | BONE_NO_DEFORM | BONE_HIDDEN_PG)) == 0) &&
- ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0))
- {
- if (bone->flag & (BONE_SELECTED)) {
- if (bone->layer & arm->layer)
- draw_sphere_bone_dist(smat, imat, pchan, NULL);
- }
- }
- }
- }
-
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- glDisable(GL_BLEND);
- }
- }
-
- /* little speedup, also make sure transparent only draws once */
- glCullFace(GL_BACK);
- if (v3d->flag2 & V3D_BACKFACE_CULLING) {
- glEnable(GL_CULL_FACE);
- is_cull_enabled = true;
- }
- else {
- is_cull_enabled = false;
- }
-
- /* 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;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bone = pchan->bone;
- arm->layer_used |= bone->layer;
-
- /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
- if (((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) &&
- ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0))
- {
- if (bone->layer & arm->layer) {
- const bool use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM);
- glPushMatrix();
-
- if (use_custom && pchan->custom_tx) {
- glMultMatrixf(pchan->custom_tx->pose_mat);
- }
- else {
- glMultMatrixf(pchan->pose_mat);
- }
-
- /* catch exception for bone with hidden parent */
- flag = bone->flag;
- if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
- flag &= ~BONE_CONNECTED;
- }
-
- /* set temporary flag for drawing bone as active, but only if selected */
- if (bone == arm->act_bone)
- flag |= BONE_DRAW_ACTIVE;
-
- if (do_const_color) {
- /* keep color */
- }
- else {
- /* set color-set to use */
- set_pchan_colorset(ob, pchan);
- }
-
- /* may be 2x width from custom bone's outline option */
- glLineWidth(1.0f);
-
- if (use_custom) {
- /* if drawwire, don't try to draw in solid */
- if (pchan->bone->flag & BONE_DRAWWIRE) {
- draw_wire = true;
- }
- else {
- if (is_cull_enabled && (v3d->flag2 & V3D_BACKFACE_CULLING) == 0) {
- is_cull_enabled = false;
- glDisable(GL_CULL_FACE);
- }
-
- draw_custom_bone(scene, v3d, rv3d, pchan->custom,
- OB_SOLID, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan));
- }
- }
- else {
- if (is_cull_enabled == false) {
- is_cull_enabled = true;
- glEnable(GL_CULL_FACE);
- }
-
- if (arm->drawtype == ARM_LINE) {
- /* nothing in solid */
- }
- else if (arm->drawtype == ARM_WIRE) {
- /* nothing in solid */
- }
- else if (arm->drawtype == ARM_ENVELOPE) {
- draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
- }
- else if (arm->drawtype == ARM_B_BONE) {
- draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
- }
- else {
- draw_bone(OB_SOLID, arm->flag, flag, 0, index, bone->length);
- }
- }
-
- glPopMatrix();
- }
- }
-
- if (index != -1)
- index += 0x10000; /* pose bones count in higher 2 bytes only */
- }
-
- /* very very confusing... but in object mode, solid draw, we cannot do GPU_select_load_id yet,
- * stick bones and/or wire custom-shapes are drawn in next loop
- */
- if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && (draw_wire == false) && index != -1) {
- /* object tag, for bordersel optim */
- GPU_select_load_id(index & 0xFFFF);
- index = -1;
- }
- }
-
- /* custom bone may draw outline double-width */
- if (arm->flag & ARM_POSEMODE) {
- glLineWidth(1.0f);
- }
-
- /* draw custom bone shapes as wireframes */
- if (!(arm->flag & ARM_NO_CUSTOM) &&
- (draw_wire || (dt <= OB_WIRE)) )
- {
- if (arm->flag & ARM_POSEMODE)
- index = base->selcol;
-
- /* only draw custom bone shapes that need to be drawn as wires */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bone = pchan->bone;
-
- /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
- if (((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) &&
- ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0) )
- {
- if (bone->layer & arm->layer) {
- if (pchan->custom) {
- if ((dt < OB_SOLID) || (bone->flag & BONE_DRAWWIRE)) {
- glPushMatrix();
-
- if (pchan->custom_tx) {
- glMultMatrixf(pchan->custom_tx->pose_mat);
- }
- else {
- glMultMatrixf(pchan->pose_mat);
- }
-
- /* prepare colors */
- if (do_const_color) {
- /* 13 October 2009, Disabled this to make ghosting show the right colors (Aligorith) */
- }
- else if (arm->flag & ARM_POSEMODE)
- set_pchan_colorset(ob, pchan);
- else {
- glColor3ubv(ob_wire_col);
- }
-
- /* catch exception for bone with hidden parent */
- flag = bone->flag;
- if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))
- flag &= ~BONE_CONNECTED;
-
- /* set temporary flag for drawing bone as active, but only if selected */
- if (bone == arm->act_bone)
- flag |= BONE_DRAW_ACTIVE;
-
- draw_custom_bone(scene, v3d, rv3d, pchan->custom,
- OB_WIRE, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan));
-
- glPopMatrix();
- }
- }
- }
- }
-
- if (index != -1)
- index += 0x10000; /* pose bones count in higher 2 bytes only */
- }
- /* stick or wire bones have not been drawn yet so don't clear object selection in this case */
- if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && draw_wire && index != -1) {
- /* object tag, for bordersel optim */
- GPU_select_load_id(index & 0xFFFF);
- index = -1;
- }
- }
-
- /* wire draw over solid only in posemode */
- if ((dt <= OB_WIRE) || (arm->flag & ARM_POSEMODE) || ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
- /* draw line check first. we do selection indices */
- if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
- if (arm->flag & ARM_POSEMODE)
- index = base->selcol;
- }
- /* if solid && posemode, we draw again with polygonoffset */
- else if ((dt > OB_WIRE) && (arm->flag & ARM_POSEMODE)) {
- ED_view3d_polygon_offset(rv3d, 1.0);
- }
- else {
- /* and we use selection indices if not done yet */
- if (arm->flag & ARM_POSEMODE)
- index = base->selcol;
- }
-
- if (is_cull_enabled == false) {
- is_cull_enabled = true;
- glEnable(GL_CULL_FACE);
- }
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bone = pchan->bone;
- arm->layer_used |= bone->layer;
-
- /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
- if (((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) &&
- ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0))
- {
- if (bone->layer & arm->layer) {
- const short constflag = pchan->constflag;
- if ((do_dashed & DASH_RELATIONSHIP_LINES) && (pchan->parent)) {
- /* Draw a line from our root to the parent's tip
- * - only if V3D_HIDE_HELPLINES is enabled...
- */
- if ((do_dashed & DASH_HELP_LINES) && ((bone->flag & BONE_CONNECTED) == 0)) {
- if (arm->flag & ARM_POSEMODE) {
- GPU_select_load_id(index & 0xFFFF); /* object tag, for bordersel optim */
- UI_ThemeColor(TH_WIRE);
- }
- setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(pchan->pose_head);
- glVertex3fv(pchan->parent->pose_tail);
- glEnd();
- setlinestyle(0);
- }
-
- /* Draw a line to IK root bone
- * - only if temporary chain (i.e. "autoik")
- */
- 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! */
-
- GPU_select_load_id(index & 0xFFFF);
- pchan_draw_IK_root_lines(pchan, !(do_dashed & DASH_HELP_LINES));
- }
- }
- else if (constflag & PCHAN_HAS_SPLINEIK) {
- if (bone->flag & BONE_SELECTED) {
- glColor3ub(150, 200, 50); /* add theme! */
-
- GPU_select_load_id(index & 0xFFFF);
- pchan_draw_IK_root_lines(pchan, !(do_dashed & DASH_HELP_LINES));
- }
- }
- }
- }
-
- glPushMatrix();
- if (arm->drawtype != ARM_ENVELOPE)
- glMultMatrixf(pchan->pose_mat);
-
- /* catch exception for bone with hidden parent */
- flag = bone->flag;
- if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))
- flag &= ~BONE_CONNECTED;
-
- /* set temporary flag for drawing bone as active, but only if selected */
- if (bone == arm->act_bone)
- flag |= BONE_DRAW_ACTIVE;
-
- /* extra draw service for pose mode */
-
- /* set color-set to use */
- if (do_const_color) {
- /* keep color */
- }
- else {
- set_pchan_colorset(ob, pchan);
- }
-
- if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) {
- /* custom bone shapes should not be drawn here! */
- }
- else if (arm->drawtype == ARM_ENVELOPE) {
- if (dt < OB_SOLID)
- draw_sphere_bone_wire(smat, imat, arm->flag, flag, constflag, index, pchan, NULL);
- }
- else if (arm->drawtype == ARM_LINE)
- draw_line_bone(arm->flag, flag, constflag, index, pchan, NULL);
- else if (arm->drawtype == ARM_WIRE)
- draw_wire_bone(dt, arm->flag, flag, constflag, index, pchan, NULL);
- else if (arm->drawtype == ARM_B_BONE)
- draw_b_bone(OB_WIRE, arm->flag, flag, constflag, index, pchan, NULL);
- else
- draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->length);
-
- glPopMatrix();
- }
- }
-
- /* pose bones count in higher 2 bytes only */
- if (index != -1)
- index += 0x10000;
- }
- /* restore things */
- if (!ELEM(arm->drawtype, ARM_WIRE, ARM_LINE) && (dt > OB_WIRE) && (arm->flag & ARM_POSEMODE))
- ED_view3d_polygon_offset(rv3d, 0.0);
- }
-
- /* restore */
- if (is_cull_enabled) {
- glDisable(GL_CULL_FACE);
- }
-
- /* draw DoFs */
- if (arm->flag & ARM_POSEMODE) {
- if (((base->flag & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) {
- draw_pose_dofs(ob);
- }
- }
-
- /* finally names and axes */
- if ((arm->flag & (ARM_DRAWNAMES | ARM_DRAWAXES)) &&
- (is_outline == 0) &&
- ((base->flag & 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;
- }
-
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if ((pchan->bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) {
- if (pchan->bone->layer & arm->layer) {
- if (arm->flag & (ARM_EDITMODE | ARM_POSEMODE)) {
- bone = pchan->bone;
- UI_GetThemeColor3ubv((bone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, col);
- }
- else if (dt > OB_WIRE) {
- UI_GetThemeColor3ubv(TH_TEXT, col);
- }
-
- /* Draw names of bone */
- if (arm->flag & ARM_DRAWNAMES) {
- mid_v3_v3v3(vec, pchan->pose_head, pchan->pose_tail);
- view3d_cached_text_draw_add(vec, pchan->name, strlen(pchan->name), 10, 0, col);
- }
-
- /* Draw additional axes on the bone tail */
- if ((arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE)) {
- glPushMatrix();
- copy_m4_m4(bmat, pchan->pose_mat);
- bone_matrix_translate_y(bmat, pchan->bone->length);
- glMultMatrixf(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);
-
- glPopMatrix();
- }
- }
- }
- }
-
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- }
- }
-
- if (index != -1) {
- GPU_select_load_id(-1);
- }
-}
-
-/* in editmode, we don't store the bone matrix... */
-static void get_matrix_editbone(EditBone *ebone, float bmat[4][4])
-{
- ebone->length = len_v3v3(ebone->tail, ebone->head);
- ED_armature_ebone_to_mat4(ebone, bmat);
-}
-
-static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
-{
- RegionView3D *rv3d = ar->regiondata;
- EditBone *eBone;
- bArmature *arm = ob->data;
- float smat[4][4], imat[4][4], bmat[4][4];
- unsigned int index;
- int flag;
-
- /* being set in code below */
- arm->layer_used = 0;
-
- ED_view3d_check_mats_rv3d(rv3d);
-
- /* envelope (deform distance) */
- if (arm->drawtype == ARM_ENVELOPE) {
- /* precalc inverse matrix for drawing screen aligned */
- copy_m4_m4(smat, rv3d->viewmatob);
- mul_mat3_m4_fl(smat, 1.0f / len_v3(ob->obmat[0]));
- invert_m4_m4(imat, smat);
-
- /* and draw blended distances */
- glEnable(GL_BLEND);
-
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
-
- for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- if (eBone->layer & arm->layer) {
- if ((eBone->flag & (BONE_HIDDEN_A | BONE_NO_DEFORM)) == 0) {
- if (eBone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL))
- draw_sphere_bone_dist(smat, imat, NULL, eBone);
- }
- }
- }
-
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- glDisable(GL_BLEND);
- }
-
- /* if solid we draw it first */
- if ((dt > OB_WIRE) && (arm->drawtype != ARM_LINE)) {
- 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();
- get_matrix_editbone(eBone, bmat);
- glMultMatrixf(bmat);
-
- /* catch exception for bone with hidden parent */
- flag = eBone->flag;
- if ((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent)) {
- flag &= ~BONE_CONNECTED;
- }
-
- /* set temporary flag for drawing bone as active, but only if selected */
- if (eBone == arm->act_edbone)
- flag |= BONE_DRAW_ACTIVE;
-
- if (arm->drawtype == ARM_ENVELOPE)
- draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
- else if (arm->drawtype == ARM_B_BONE)
- draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
- else if (arm->drawtype == ARM_WIRE)
- draw_wire_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
- else {
- draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length);
- }
-
- glPopMatrix();
- }
- }
- }
- }
-
- /* if wire over solid, set offset */
- index = -1;
- GPU_select_load_id(-1);
- if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
- if (G.f & G_PICKSEL)
- index = 0;
- }
- else if (dt > OB_WIRE)
- ED_view3d_polygon_offset(rv3d, 1.0);
- else if (arm->flag & ARM_EDITMODE)
- index = 0; /* do selection codes */
-
- for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- arm->layer_used |= eBone->layer;
- if (eBone->layer & arm->layer) {
- if ((eBone->flag & BONE_HIDDEN_A) == 0) {
-
- /* catch exception for bone with hidden parent */
- flag = eBone->flag;
- if ((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent)) {
- flag &= ~BONE_CONNECTED;
- }
-
- /* set temporary flag for drawing bone as active, but only if selected */
- if (eBone == arm->act_edbone)
- flag |= BONE_DRAW_ACTIVE;
-
- if (arm->drawtype == ARM_ENVELOPE) {
- if (dt < OB_SOLID)
- draw_sphere_bone_wire(smat, imat, arm->flag, flag, 0, index, NULL, eBone);
- }
- else {
- glPushMatrix();
- get_matrix_editbone(eBone, bmat);
- glMultMatrixf(bmat);
-
- if (arm->drawtype == ARM_LINE)
- draw_line_bone(arm->flag, flag, 0, index, NULL, eBone);
- else if (arm->drawtype == ARM_WIRE)
- draw_wire_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
- else if (arm->drawtype == ARM_B_BONE)
- draw_b_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
- else
- draw_bone(OB_WIRE, arm->flag, flag, 0, index, eBone->length);
-
- glPopMatrix();
- }
-
- /* offset to parent */
- if (eBone->parent) {
- UI_ThemeColor(TH_WIRE_EDIT);
- GPU_select_load_id(-1); /* -1 here is OK! */
- setlinestyle(3);
-
- glBegin(GL_LINES);
- glVertex3fv(eBone->parent->tail);
- glVertex3fv(eBone->head);
- glEnd();
-
- setlinestyle(0);
- }
- }
- }
- if (index != -1) index++;
- }
-
- /* restore */
- if (index != -1) {
- GPU_select_load_id(-1);
- }
-
- if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
- /* pass */
- }
- else if (dt > OB_WIRE) {
- ED_view3d_polygon_offset(rv3d, 0.0);
- }
-
- /* finally names and axes */
- if (arm->flag & (ARM_DRAWNAMES | ARM_DRAWAXES)) {
- /* 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];
- col[3] = 255;
-
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
-
- for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- if (eBone->layer & arm->layer) {
- if ((eBone->flag & BONE_HIDDEN_A) == 0) {
-
- UI_GetThemeColor3ubv((eBone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, col);
-
- /* Draw name */
- if (arm->flag & ARM_DRAWNAMES) {
- mid_v3_v3v3(vec, eBone->head, eBone->tail);
- view3d_cached_text_draw_add(vec, eBone->name, strlen(eBone->name), 10, 0, col);
- }
- /* Draw additional axes */
- if (arm->flag & ARM_DRAWAXES) {
- glPushMatrix();
- get_matrix_editbone(eBone, bmat);
- bone_matrix_translate_y(bmat, eBone->length);
- glMultMatrixf(bmat);
-
- glColor3ubv(col);
-
- float viewmat_ebone[4][4];
- mul_m4_m4m4(viewmat_ebone, rv3d->viewmatob, bmat);
- drawaxes(viewmat_ebone, eBone->length * 0.25f, OB_ARROWS);
-
- glPopMatrix();
- }
-
- }
- }
- }
-
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- }
- }
-}
-
-/* ****************************** Armature Visualization ******************************** */
-
-/* ---------- Paths --------- */
-
-/* draw bone paths
- * - in view space
- */
-static void draw_pose_paths(Scene *scene, View3D *v3d, ARegion *ar, Object *ob)
-{
- bAnimVizSettings *avs = &ob->pose->avs;
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
-
- /* setup drawing environment for paths */
- draw_motion_paths_init(v3d, ar);
-
- /* draw paths where they exist and they releated bone is visible */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if ((pchan->bone->layer & arm->layer) && (pchan->mpath))
- draw_motion_path_instance(scene, ob, pchan, avs, pchan->mpath);
- }
-
- /* cleanup after drawing */
- draw_motion_paths_cleanup(v3d);
-}
-
-
-/* ---------- Ghosts --------- */
-
-/* helper function for ghost drawing - sets/removes flags for temporarily
- * hiding unselected bones while drawing ghosts
- */
-static void ghost_poses_tag_unselected(Object *ob, short unset)
-{
- bArmature *arm = ob->data;
- bPose *pose = ob->pose;
- bPoseChannel *pchan;
-
- /* don't do anything if no hiding any bones */
- if ((arm->flag & ARM_GHOST_ONLYSEL) == 0)
- return;
-
- /* loop over all pchans, adding/removing tags as appropriate */
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
- if (unset) {
- /* remove tags from all pchans if cleaning up */
- pchan->bone->flag &= ~BONE_HIDDEN_PG;
- }
- else {
- /* set tags on unselected pchans only */
- if ((pchan->bone->flag & BONE_SELECTED) == 0)
- pchan->bone->flag |= BONE_HIDDEN_PG;
- }
- }
- }
-}
-
-/* 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)
-{
- Object *ob = base->object;
- AnimData *adt = BKE_animdata_from_id(&ob->id);
- bArmature *arm = ob->data;
- bPose *posen, *poseo;
- float start, end, stepsize, range, colfac;
- int cfrao, flago;
-
- start = (float)arm->ghostsf;
- end = (float)arm->ghostef;
- if (end <= start)
- return;
-
- /* prevent infinite loops if this is set to 0 - T49527 */
- if (arm->ghostsize < 1)
- arm->ghostsize = 1;
-
- stepsize = (float)(arm->ghostsize);
- range = (float)(end - start);
-
- /* store values */
- ob->mode &= ~OB_MODE_POSE;
- cfrao = CFRA;
- flago = arm->flag;
- arm->flag &= ~(ARM_DRAWNAMES | ARM_DRAWAXES);
-
- /* copy the pose */
- poseo = ob->pose;
- BKE_pose_copy_data(&posen, ob->pose, 1);
- ob->pose = posen;
- BKE_pose_rebuild(ob, ob->data); /* child pointers for IK */
- ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */
-
- glEnable(GL_BLEND);
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
-
- /* 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)));
-
- 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);
- }
- glDisable(GL_BLEND);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
-
- /* before disposing of temp pose, use it to restore object to a sane state */
- BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)cfrao, ADT_RECALC_ALL);
-
- /* clean up temporary pose */
- ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */
- BKE_pose_free(posen);
-
- /* restore */
- CFRA = cfrao;
- ob->pose = poseo;
- arm->flag = flago;
- ob->mode |= OB_MODE_POSE;
-}
-
-/* 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)
-{
- Object *ob = base->object;
- AnimData *adt = BKE_animdata_from_id(&ob->id);
- bAction *act = (adt) ? adt->action : NULL;
- bArmature *arm = ob->data;
- bPose *posen, *poseo;
- DLRBT_Tree keys;
- ActKeyColumn *ak, *akn;
- float start, end, range, colfac, i;
- int cfrao, flago;
-
- start = (float)arm->ghostsf;
- end = (float)arm->ghostef;
- if (end <= start)
- return;
-
- /* get keyframes - then clip to only within range */
- BLI_dlrbTree_init(&keys);
- action_to_keylist(adt, act, &keys, NULL);
- BLI_dlrbTree_linkedlist_sync(&keys);
-
- range = 0;
- for (ak = keys.first; ak; ak = akn) {
- akn = ak->next;
-
- if ((ak->cfra < start) || (ak->cfra > end))
- BLI_freelinkN((ListBase *)&keys, ak);
- else
- range++;
- }
- if (range == 0) return;
-
- /* store values */
- ob->mode &= ~OB_MODE_POSE;
- cfrao = CFRA;
- flago = arm->flag;
- arm->flag &= ~(ARM_DRAWNAMES | ARM_DRAWAXES);
-
- /* copy the pose */
- poseo = ob->pose;
- BKE_pose_copy_data(&posen, ob->pose, 1);
- ob->pose = posen;
- BKE_pose_rebuild(ob, ob->data); /* child pointers for IK */
- ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */
-
- glEnable(GL_BLEND);
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
-
- /* 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)));
-
- 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);
- }
- glDisable(GL_BLEND);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
-
- /* before disposing of temp pose, use it to restore object to a sane state */
- BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)cfrao, ADT_RECALC_ALL);
-
- /* clean up temporary pose */
- ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */
- BLI_dlrbTree_free(&keys);
- BKE_pose_free(posen);
-
- /* restore */
- CFRA = cfrao;
- ob->pose = poseo;
- arm->flag = flago;
- ob->mode |= OB_MODE_POSE;
-}
-
-/* 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)
-{
- Object *ob = base->object;
- AnimData *adt = BKE_animdata_from_id(&ob->id);
- bArmature *arm = ob->data;
- bPose *posen, *poseo;
- float cur, start, end, stepsize, range, colfac, actframe, ctime;
- int cfrao, flago;
-
- /* pre conditions, get an action with sufficient frames */
- if (ELEM(NULL, adt, adt->action))
- return;
-
- calc_action_range(adt->action, &start, &end, 0);
- if (start == end)
- return;
-
- /* prevent infinite loops if this is set to 0 - T49527 */
- if (arm->ghostsize < 1)
- arm->ghostsize = 1;
-
- stepsize = (float)(arm->ghostsize);
- range = (float)(arm->ghostep) * stepsize + 0.5f; /* plus half to make the for loop end correct */
-
- /* store values */
- ob->mode &= ~OB_MODE_POSE;
- cfrao = CFRA;
- actframe = BKE_nla_tweakedit_remap(adt, (float)CFRA, 0);
- flago = arm->flag;
- arm->flag &= ~(ARM_DRAWNAMES | ARM_DRAWAXES);
-
- /* copy the pose */
- poseo = ob->pose;
- BKE_pose_copy_data(&posen, ob->pose, 1);
- ob->pose = posen;
- BKE_pose_rebuild(ob, ob->data); /* child pointers for IK */
- ghost_poses_tag_unselected(ob, 0); /* hide unselected bones if need be */
-
- glEnable(GL_BLEND);
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
-
- /* draw from darkest blend to lowest */
- 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)));
-
- /* only within action range */
- if (actframe + ctime >= start && actframe + ctime <= end) {
- CFRA = (int)BKE_nla_tweakedit_remap(adt, actframe + ctime, NLATIME_CONVERT_MAP);
-
- 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);
- }
- }
-
- 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)));
-
- /* only within action range */
- if ((actframe - ctime >= start) && (actframe - ctime <= end)) {
- CFRA = (int)BKE_nla_tweakedit_remap(adt, actframe - ctime, NLATIME_CONVERT_MAP);
-
- 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);
- }
- }
- }
- glDisable(GL_BLEND);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
-
- /* before disposing of temp pose, use it to restore object to a sane state */
- BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)cfrao, ADT_RECALC_ALL);
-
- /* clean up temporary pose */
- ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */
- BKE_pose_free(posen);
-
- /* restore */
- CFRA = cfrao;
- ob->pose = poseo;
- arm->flag = flago;
- ob->mode |= OB_MODE_POSE;
-}
-
-/* ********************************** Armature Drawing - Main ************************* */
-
-/* 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)
-{
- Object *ob = base->object;
- bArmature *arm = ob->data;
- bool retval = false;
-
- 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 (dt > OB_WIRE) {
- /* we use color for solid lighting */
- if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
- const float diffuse[3] = {0.64f, 0.64f, 0.64f};
- const float specular[3] = {0.5f, 0.5f, 0.5f};
- GPU_basic_shader_colors(diffuse, specular, 35, 1.0f);
- }
- else {
- const float diffuse[3] = {1.0f, 1.0f, 1.0f};
- const float specular[3] = {1.0f, 1.0f, 1.0f};
- GPU_basic_shader_colors(diffuse, specular, 35, 1.0f);
- glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); /* only for lighting... */
- }
- }
-
- /* arm->flag is being used to detect mode... */
- /* editmode? */
- if (arm->edbo) {
- arm->flag |= ARM_EDITMODE;
- draw_ebones(v3d, ar, ob, dt);
- arm->flag &= ~ARM_EDITMODE;
- }
- else {
- /* Draw Pose */
- if (ob->pose && ob->pose->chanbase.first) {
- /* We can't safely draw non-updated pose, might contain NULL bone pointers... */
- if (ob->pose->flag & POSE_RECALC) {
- BKE_pose_rebuild(ob, arm);
- }
-
- /* drawing posemode selection indices or colors only in these cases */
- if (!(base->flag & OB_FROMDUPLI)) {
- if (G.f & G_PICKSEL) {
-#if 0
- /* nifty but actually confusing to allow bone selection out of posemode */
- if (OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) {
- if (ob == modifiers_isDeformedByArmature(OBACT))
- arm->flag |= ARM_POSEMODE;
- }
- else
-#endif
- if (ob->mode & OB_MODE_POSE) {
- arm->flag |= ARM_POSEMODE;
- }
- }
- else if (ob->mode & OB_MODE_POSE) {
- if (arm->ghosttype == ARM_GHOST_RANGE) {
- draw_ghost_poses_range(scene, v3d, ar, base);
- }
- else if (arm->ghosttype == ARM_GHOST_KEYS) {
- draw_ghost_poses_keys(scene, v3d, ar, base);
- }
- else if (arm->ghosttype == ARM_GHOST_CUR) {
- if (arm->ghostep)
- draw_ghost_poses(scene, v3d, ar, base);
- }
- if ((dflag & DRAW_SCENESET) == 0) {
- if (ob == OBACT)
- arm->flag |= ARM_POSEMODE;
- else if (OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) {
- if (ob == modifiers_isDeformedByArmature(OBACT))
- 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);
- arm->flag &= ~ARM_POSEMODE;
-
- if (ob->mode & OB_MODE_POSE)
- UI_ThemeColor(TH_WIRE); /* restore, for extra draw stuff */
- }
- else {
- retval = true;
- }
- }
- /* 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
deleted file mode 100644
index 27180097107..00000000000
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ /dev/null
@@ -1,1406 +0,0 @@
-/*
- * ***** 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) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * Contributor(s): Blender Foundation, full update, glsl support
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/space_view3d/drawmesh.c
- * \ingroup spview3d
- */
-
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_utildefines.h"
-#include "BLI_bitmap.h"
-#include "BLI_math.h"
-
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_node_types.h"
-#include "DNA_object_types.h"
-#include "DNA_property_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_view3d_types.h"
-
-#include "BKE_DerivedMesh.h"
-#include "BKE_global.h"
-#include "BKE_image.h"
-#include "BKE_material.h"
-#include "BKE_paint.h"
-#include "BKE_property.h"
-#include "BKE_editmesh.h"
-#include "BKE_scene.h"
-
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
-#include "UI_resources.h"
-
-#include "GPU_draw.h"
-#include "GPU_material.h"
-#include "GPU_basic_shader.h"
-#include "GPU_shader.h"
-
-#include "RE_engine.h"
-
-#include "ED_uvedit.h"
-
-#include "view3d_intern.h" /* own include */
-
-/* user data structures for derived mesh callbacks */
-typedef struct drawMeshFaceSelect_userData {
- Mesh *me;
- 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 */
-BLI_INLINE int edge_vis_index(const int index) { return index * 2; }
-BLI_INLINE int edge_sel_index(const int index) { return index * 2 + 1; }
-
-static BLI_bitmap *get_tface_mesh_marked_edge_info(Mesh *me, bool draw_select_edges)
-{
- BLI_bitmap *bitmap_edge_flags = BLI_BITMAP_NEW(me->totedge * 2, __func__);
- MPoly *mp;
- MLoop *ml;
- int i, j;
- bool select_set;
-
- for (i = 0; i < me->totpoly; i++) {
- mp = &me->mpoly[i];
-
- if (!(mp->flag & ME_HIDE)) {
- select_set = (mp->flag & ME_FACE_SEL) != 0;
-
- ml = me->mloop + mp->loopstart;
- for (j = 0; j < mp->totloop; j++, ml++) {
- if ((draw_select_edges == false) &&
- (select_set && BLI_BITMAP_TEST(bitmap_edge_flags, edge_sel_index(ml->e))))
- {
- BLI_BITMAP_DISABLE(bitmap_edge_flags, edge_vis_index(ml->e));
- }
- else {
- BLI_BITMAP_ENABLE(bitmap_edge_flags, edge_vis_index(ml->e));
- if (select_set) {
- BLI_BITMAP_ENABLE(bitmap_edge_flags, edge_sel_index(ml->e));
- }
- }
- }
- }
- }
-
- return bitmap_edge_flags;
-}
-
-
-static DMDrawOption draw_mesh_face_select__setHiddenOpts(void *userData, int index)
-{
- drawMeshFaceSelect_userData *data = userData;
- Mesh *me = data->me;
-
- if (me->drawflag & ME_DRAWEDGES) {
- if ((BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index))))
- return DM_DRAW_OPTION_NORMAL;
- else
- return DM_DRAW_OPTION_SKIP;
- }
- else if (BLI_BITMAP_TEST(data->edge_flags, edge_sel_index(index)) &&
- BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index)))
- {
- return DM_DRAW_OPTION_NORMAL;
- }
- else {
- return DM_DRAW_OPTION_SKIP;
- }
-}
-
-static DMDrawOption draw_mesh_face_select__setSelectOpts(void *userData, int index)
-{
- drawMeshFaceSelect_userData *data = userData;
- return (BLI_BITMAP_TEST(data->edge_flags, edge_sel_index(index)) &&
- BLI_BITMAP_TEST(data->edge_flags, edge_vis_index(index))) ? DM_DRAW_OPTION_NORMAL : DM_DRAW_OPTION_SKIP;
-}
-
-/* draws unselected */
-static DMDrawOption draw_mesh_face_select__drawFaceOptsInv(void *userData, int index)
-{
- Mesh *me = (Mesh *)userData;
-
- MPoly *mpoly = &me->mpoly[index];
- if (!(mpoly->flag & ME_HIDE) && !(mpoly->flag & ME_FACE_SEL))
- return DM_DRAW_OPTION_NORMAL;
- else
- return DM_DRAW_OPTION_SKIP;
-}
-
-void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm, bool draw_select_edges)
-{
- drawMeshFaceSelect_userData data;
-
- data.me = me;
- data.edge_flags = get_tface_mesh_marked_edge_info(me, draw_select_edges);
-
- glEnable(GL_DEPTH_TEST);
- ED_view3d_polygon_offset(rv3d, 1.0);
-
- /* Draw (Hidden) Edges */
- setlinestyle(1);
- UI_ThemeColor(TH_EDGE_FACESEL);
- dm->drawMappedEdges(dm, draw_mesh_face_select__setHiddenOpts, &data);
- setlinestyle(0);
-
- /* Draw Selected Faces */
- if (me->drawflag & ME_DRAWFACES) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- /* dull unselected faces so as not to get in the way of seeing color */
- glColor4ub(96, 96, 96, 64);
- dm->drawMappedFaces(dm, draw_mesh_face_select__drawFaceOptsInv, NULL, NULL, (void *)me, DM_DRAW_SKIP_HIDDEN);
- glDisable(GL_BLEND);
- }
-
- ED_view3d_polygon_offset(rv3d, 1.0);
-
- /* Draw Stippled Outline for selected faces */
- glColor3ub(255, 255, 255);
- setlinestyle(1);
- dm->drawMappedEdges(dm, draw_mesh_face_select__setSelectOpts, &data);
- setlinestyle(0);
-
- ED_view3d_polygon_offset(rv3d, 0.0); /* resets correctly now, even after calling accumulated offsets */
-
- MEM_freeN(data.edge_flags);
-}
-
-/***************************** 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)
-{
- Mesh *me = (Mesh *)userData;
- MPoly *mp = &me->mpoly[index];
- if (mp->flag & ME_HIDE)
- return DM_DRAW_OPTION_SKIP;
- 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 {
- Scene *scene;
- Object *ob;
- Mesh *me;
- DerivedMesh *dm;
- bool shadeless;
- 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->layer[0].glinfoindoex = -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,
- 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);
- }
-}
-
-/* Vertex Paint and Weight Paint */
-static void draw_mesh_paint_light_begin(void)
-{
- /* get material diffuse color from vertex colors but set default spec */
- const float specular[3] = {0.47f, 0.47f, 0.47f};
- GPU_basic_shader_colors(NULL, specular, 35, 1.0f);
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
-}
-
-static void draw_mesh_paint_light_end(void)
-{
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-}
-
-void draw_mesh_paint_weight_faces(DerivedMesh *dm, const bool use_light,
- void *facemask_cb, void *user_data)
-{
- DMSetMaterial setMaterial = GPU_object_materials_check() ? GPU_object_material_bind : NULL;
- int flags = DM_DRAW_USE_COLORS;
-
- if (use_light) {
- draw_mesh_paint_light_begin();
- flags |= DM_DRAW_NEED_NORMALS;
- }
-
- dm->drawMappedFaces(dm, (DMSetDrawOptions)facemask_cb, setMaterial, NULL, user_data, flags);
-
- if (use_light) {
- draw_mesh_paint_light_end();
- }
-}
-
-void draw_mesh_paint_vcolor_faces(DerivedMesh *dm, const bool use_light,
- void *facemask_cb, void *user_data,
- const Mesh *me)
-{
- DMSetMaterial setMaterial = GPU_object_materials_check() ? GPU_object_material_bind : NULL;
- int flags = 0;
-
- if (use_light) {
- draw_mesh_paint_light_begin();
- 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);
- }
- else {
- glColor3f(1.0f, 1.0f, 1.0f);
- dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data, flags);
- }
-
- if (show_alpha) {
- glDisable(GL_BLEND);
- }
-
- if (use_light) {
- draw_mesh_paint_light_end();
- }
-}
-
-void draw_mesh_paint_weight_edges(RegionView3D *rv3d, DerivedMesh *dm,
- const bool use_depth, const bool use_alpha,
- void *edgemask_cb, void *user_data)
-{
- /* weight paint in solid mode, special case. focus on making the weights clear
- * rather than the shading, this is also forced in wire view */
-
- if (use_depth) {
- ED_view3d_polygon_offset(rv3d, 1.0);
- glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
- }
- else {
- glDisable(GL_DEPTH_TEST);
- }
-
- if (use_alpha) {
- glEnable(GL_BLEND);
- }
-
- glColor4ub(255, 255, 255, 96);
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(1, 0xAAAA);
-
- dm->drawMappedEdges(dm, (DMSetDrawOptions)edgemask_cb, user_data);
-
- if (use_depth) {
- ED_view3d_polygon_offset(rv3d, 0.0);
- glDepthMask(1);
- }
- else {
- glEnable(GL_DEPTH_TEST);
- }
-
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
-
- if (use_alpha) {
- glDisable(GL_BLEND);
- }
-}
-
-void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
- Object *ob, DerivedMesh *dm, const int draw_flags)
-{
- DMSetDrawOptions facemask = NULL;
- Mesh *me = ob->data;
- const bool use_light = (v3d->drawtype >= OB_SOLID);
-
- /* hide faces in face select mode */
- if (me->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL))
- facemask = wpaint__setSolidDrawOptions_facemask;
-
- if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- draw_mesh_paint_weight_faces(dm, use_light, facemask, me);
- }
- else if (ob->mode & OB_MODE_VERTEX_PAINT) {
- draw_mesh_paint_vcolor_faces(dm, use_light, facemask, me, me);
- }
-
- /* draw face selection on top */
- if (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);
- }
- else if ((use_light == false) || (ob->dtx & OB_DRAWWIRE)) {
- const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) || !(ob->mode & OB_MODE_WEIGHT_PAINT);
- const bool use_alpha = (ob->mode & OB_MODE_VERTEX_PAINT) == 0;
-
- if (use_alpha == false) {
- set_inverted_drawing(1);
- }
-
- draw_mesh_paint_weight_edges(rv3d, dm, use_depth, use_alpha, NULL, NULL);
-
- if (use_alpha == false) {
- set_inverted_drawing(0);
- }
- }
-}
-
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index c10f8f0ce16..1224c284d5f 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,9 +63,11 @@
#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"
+#include "BKE_mesh_runtime.h"
#include "BKE_material.h"
#include "BKE_mball.h"
#include "BKE_modifier.h"
@@ -80,6 +83,9 @@
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -90,6 +96,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,127 +115,7 @@
#include "view3d_intern.h" /* bad level include */
-/* Workaround for sequencer scene render mode.
- *
- * Strips doesn't use DAG to update objects or so, which
- * might lead to situations when object is drawing without
- * curve cache ready.
- *
- * Ideally we don't want to evaluate objects from drawing,
- * but it'll require some major sequencer re-design. So
- * for now just fallback to legacy behavior with calling
- * display ist creating from draw().
- */
-#define SEQUENCER_DAG_WORKAROUND
-
-typedef enum eWireDrawMode {
- OBDRAW_WIRE_OFF = 0,
- OBDRAW_WIRE_ON = 1,
- OBDRAW_WIRE_ON_DEPTH = 2
-} eWireDrawMode;
-
-typedef struct drawDMVerts_userData {
- BMesh *bm;
-
- BMVert *eve_act;
- char sel;
-
- /* cached theme values */
- unsigned char th_editmesh_active[4];
- unsigned char th_vertex_select[4];
- unsigned char th_vertex[4];
- unsigned char th_skin_root[4];
-
- /* for skin node drawing */
- int cd_vskin_offset;
- float imat[4][4];
-} drawDMVerts_userData;
-
-typedef struct drawDMEdgesSel_userData {
- BMesh *bm;
-
- unsigned char *baseCol, *selCol, *actCol;
- BMEdge *eed_act;
-} drawDMEdgesSel_userData;
-
-typedef struct drawDMEdgesSelInterp_userData {
- BMesh *bm;
-
- unsigned char *baseCol, *selCol;
- unsigned char *lastCol;
-} drawDMEdgesSelInterp_userData;
-
-typedef struct drawDMEdgesWeightInterp_userData {
- BMesh *bm;
-
- int cd_dvert_offset;
- int defgroup_tot;
- int vgroup_index;
- char weight_user;
- float alert_color[3];
-
-} drawDMEdgesWeightInterp_userData;
-
-typedef struct drawDMFacesSel_userData {
-#ifdef WITH_FREESTYLE
- unsigned char *cols[4];
-#else
- unsigned char *cols[3];
-#endif
-
- DerivedMesh *dm;
- BMesh *bm;
-
- BMFace *efa_act;
- const int *orig_index_mp_to_orig;
-} drawDMFacesSel_userData;
-
-typedef struct drawDMNormal_userData {
- BMesh *bm;
- int uniform_scale;
- float normalsize;
- float tmat[3][3];
- float imat[3][3];
-} drawDMNormal_userData;
-
-typedef struct drawMVertOffset_userData {
- MVert *mvert;
- int offset;
-} drawMVertOffset_userData;
-
-typedef struct drawDMLayer_userData {
- BMesh *bm;
- int cd_layer_offset;
-} drawDMLayer_userData;
-
-typedef struct drawBMOffset_userData {
- BMesh *bm;
- int offset;
-} drawBMOffset_userData;
-
-typedef struct drawBMSelect_userData {
- BMesh *bm;
- bool select;
-} 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 ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac)
-{
- float col_wire[3], col_bg[3], col[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);
-}
+#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */
int view3d_effective_drawtype(const struct View3D *v3d)
{
@@ -235,42 +125,6 @@ int view3d_effective_drawtype(const struct View3D *v3d)
return v3d->drawtype;
}
-/* this condition has been made more complex since editmode can draw textures */
-bool check_object_draw_texture(Scene *scene, View3D *v3d, const char drawtype)
-{
- const int v3d_drawtype = view3d_effective_drawtype(v3d);
- /* texture and material draw modes */
- if (ELEM(v3d_drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID) {
- return true;
- }
-
- /* textured solid */
- if ((v3d_drawtype == OB_SOLID) &&
- (v3d->flag2 & V3D_SOLID_TEX) &&
- (BKE_scene_use_new_shading_nodes(scene) == false))
- {
- return true;
- }
-
- if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) {
- return true;
- }
-
- return false;
-}
-
-static bool check_object_draw_editweight(Mesh *me, DerivedMesh *finalDM)
-{
- if (me->drawflag & ME_DRAWEIGHT) {
- /* editmesh handles its own weight drawing */
- if (finalDM->type != DM_TYPE_EDITBMESH) {
- return true;
- }
- }
-
- return false;
-}
-
static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
{
if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
@@ -292,49 +146,6 @@ static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
return true;
}
-/* ************************ */
-
-/* check for glsl drawing */
-
-bool draw_glsl_material(Scene *scene, 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))
- return false;
-
- if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP)
- return true;
-
- if (v3d->drawtype == OB_TEXTURE)
- return (scene->gm.matmode == GAME_MAT_GLSL && !BKE_scene_use_new_shading_nodes(scene));
- else if (v3d->drawtype == OB_MATERIAL && dt > OB_SOLID)
- return true;
- else
- return false;
-}
-
-static bool check_alpha_pass(Base *base)
-{
- if (base->flag & OB_FROMDUPLI)
- return false;
-
- if (G.f & G_PICKSEL)
- return false;
-
- if (base->object->mode & OB_MODE_ALL_PAINT)
- return false;
-
- return (base->object->dtx & OB_DRAWTRANSP);
-}
-
-/***/
-static const unsigned int colortab[] = {
- 0x0, 0x403000, 0xFFFF88
-};
-
/* ----------------- OpenGL Circle Drawing - Tables for Optimized Drawing Speed ------------------ */
/* 32 values of sin function (still same result!) */
#define CIRCLE_RESOL 32
@@ -410,328 +221,6 @@ static const float cosval[CIRCLE_RESOL] = {
1.00000000
};
-/**
- * \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)
-{
- int line_type;
- float buffer[4][3];
- int n = 0;
-
- float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3] = {0.0f, 0.0f, 0.0f};
- float dim = size * 0.1f;
- float dx[3], dy[3];
-
- dx[0] = dim; dx[1] = 0.0f; dx[2] = 0.0f;
- dy[0] = 0.0f; dy[1] = dim; dy[2] = 0.0f;
-
- 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);
- copy_v3_v3(v2, dx);
- add_v3_v3(v2, dy);
-
- copy_v3_v3(buffer[n++], v1);
- copy_v3_v3(buffer[n++], v2);
-
- /* top left to bottom right */
- mul_v3_fl(dy, 2.0f);
- add_v3_v3(v1, dy);
- sub_v3_v3(v2, dy);
-
- copy_v3_v3(buffer[n++], v1);
- copy_v3_v3(buffer[n++], v2);
-
- 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);
- sub_v3_v3(v1, dy);
- copy_v3_v3(v2, dx);
- add_v3_v3(v2, dy);
-
- copy_v3_v3(buffer[n++], v1);
- copy_v3_v3(buffer[n++], v2);
-
- /* top left to center */
- mul_v3_fl(dy, 2.0f);
- add_v3_v3(v1, dy);
- zero_v3(v2);
-
- copy_v3_v3(buffer[n++], v1);
- copy_v3_v3(buffer[n++], v2);
-
- break;
- case 2: /* z axis */
- line_type = GL_LINE_STRIP;
-
- /* start at top left */
- negate_v3_v3(v1, dx);
- add_v3_v3(v1, dy);
-
- copy_v3_v3(buffer[n++], v1);
-
- mul_v3_fl(dx, 2.0f);
- add_v3_v3(v1, dx);
-
- copy_v3_v3(buffer[n++], v1);
-
- mul_v3_fl(dy, 2.0f);
- sub_v3_v3(v1, dx);
- sub_v3_v3(v1, dy);
-
- copy_v3_v3(buffer[n++], v1);
-
- add_v3_v3(v1, dx);
-
- copy_v3_v3(buffer[n++], v1);
-
- break;
- default:
- BLI_assert(0);
- return;
- }
-
- for (int i = 0; i < n; i++) {
- mul_transposed_m3_v3((float (*)[3])viewmat_local_unit, buffer[i]);
- add_v3_v3(buffer[i], c);
- }
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, buffer);
- glDrawArrays(line_type, 0, n);
- glDisableClientState(GL_VERTEX_ARRAY);
-}
-
-void drawaxes(const float viewmat_local[4][4], float size, char drawtype)
-{
- 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);
-
- switch (drawtype) {
-
- case OB_PLAINAXES:
- for (axis = 0; axis < 3; axis++) {
- glBegin(GL_LINES);
-
- v1[axis] = size;
- v2[axis] = -size;
- glVertex3fv(v1);
- glVertex3fv(v2);
-
- /* reset v1 & v2 to zero */
- v1[axis] = v2[axis] = 0.0f;
-
- glEnd();
- }
- break;
- case OB_SINGLE_ARROW:
-
- glBegin(GL_LINES);
- /* in positive z direction only */
- v1[2] = size;
- glVertex3fv(v1);
- glVertex3fv(v2);
- glEnd();
-
- /* square pyramid */
- glBegin(GL_TRIANGLES);
-
- v2[0] = size * 0.035f; v2[1] = size * 0.035f;
- v3[0] = size * -0.035f; v3[1] = size * 0.035f;
- v2[2] = v3[2] = size * 0.75f;
-
- for (axis = 0; axis < 4; axis++) {
- if (axis % 2 == 1) {
- v2[0] = -v2[0];
- v3[1] = -v3[1];
- }
- else {
- v2[1] = -v2[1];
- v3[0] = -v3[0];
- }
-
- glVertex3fv(v1);
- glVertex3fv(v2);
- glVertex3fv(v3);
-
- }
- glEnd();
-
- break;
- case OB_CUBE:
- drawcube_size(size);
- break;
-
- case OB_CIRCLE:
- drawcircle_size(size);
- break;
-
- case OB_EMPTY_SPHERE:
- draw_empty_sphere(size);
- break;
-
- case OB_EMPTY_CONE:
- draw_empty_cone(size);
- break;
-
- case OB_ARROWS:
- default:
- {
- float viewmat_local_unit[3][3];
-
- copy_m3_m4(viewmat_local_unit, (float (*)[4])viewmat_local);
- normalize_m3(viewmat_local_unit);
-
- for (axis = 0; axis < 3; axis++) {
- const int arrow_axis = (axis == 0) ? 1 : 0;
-
- glBegin(GL_LINES);
-
- v2[axis] = size;
- glVertex3fv(v1);
- glVertex3fv(v2);
-
- v1[axis] = size * 0.85f;
- v1[arrow_axis] = -size * 0.08f;
- glVertex3fv(v1);
- glVertex3fv(v2);
-
- v1[arrow_axis] = size * 0.08f;
- glVertex3fv(v1);
- glVertex3fv(v2);
-
- glEnd();
-
- v2[axis] += size * 0.125f;
-
- draw_xyz_wire(viewmat_local_unit, v2, size, axis);
-
-
- /* reset v1 & v2 to zero */
- v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
- }
- break;
- }
- }
-}
-
-
-/* Function to draw an Image on an empty Object */
-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);
- }
-
- ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
-
- if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
- IMB_rect_from_float(ibuf);
- }
-
- int ima_x, ima_y;
-
- /* Get the buffer dimensions so we can fallback to fake ones */
- if (ibuf && ibuf->rect) {
- ima_x = ibuf->x;
- ima_y = ibuf->y;
- }
- else {
- ima_x = 1;
- ima_y = 1;
- }
-
- float sca_x = 1.0f;
- float sca_y = 1.0f;
-
- /* Get the image aspect even if the buffer is invalid */
- if (ima) {
- if (ima->aspx > ima->aspy) {
- sca_y = ima->aspy / ima->aspx;
- }
- else if (ima->aspx < ima->aspy) {
- sca_x = ima->aspx / ima->aspy;
- }
- }
-
- /* 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;
-
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
-
- /* Calculate Image scale */
- float scale = ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y);
-
- /* Set the object scale */
- glScalef(scale * sca_x, scale * sca_y, 1.0f);
-
- 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 (use_clip) {
- glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_GREATER, U.glalphaclip);
- }
-
- /* Use the object color and alpha */
- glColor4fv(ob->col);
-
- /* Draw the Image on the screen */
- glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_RGBA, GL_UNSIGNED_BYTE, zoomfilter, ibuf->rect);
-
- glDisable(GL_BLEND);
-
- if (use_clip) {
- glDisable(GL_ALPHA_TEST);
- glAlphaFunc(GL_ALWAYS, 0.0f);
- }
- }
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
- }
-
- /* 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();
-
- /* Reset GL settings */
- glPopMatrix();
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
-}
-
static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, const float tmat[4][4])
{
float vx[3], vy[3];
@@ -747,838 +236,17 @@ 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);
-}
-
-/* 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)
-{
- const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
- float verts[CIRCLE_RESOL][3];
-
- /* 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);
-
- if (special_color) {
- if (selstate == ACTIVE || selstate == SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
- else glColor4ub(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);
- }
-
- 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);
-
- /* 2. draw outline */
- glLineWidth(1);
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
- glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL);
-
- /* finish up */
- glDisableClientState(GL_VERTEX_ARRAY);
-
- glDepthRange(0.0, 1.0);
- glDisable(GL_BLEND);
-
- if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
-}
-
-/* *********** text drawing for object/particles/armature ************* */
-
-typedef struct ViewCachedString {
- struct ViewCachedString *next;
- float vec[3];
- union {
- unsigned char ub[4];
- int pack;
- } col;
- short sco[2];
- short xoffs;
- short flag;
- int str_len;
-
- /* str is allocated past the end */
- char str[0];
-} ViewCachedString;
-
-/* one arena for all 3 string lists */
-static MemArena *g_v3d_strings_arena = NULL;
-static ViewCachedString *g_v3d_strings[3] = {NULL, NULL, NULL};
-static int g_v3d_string_level = -1;
-
-void view3d_cached_text_draw_begin(void)
-{
- g_v3d_string_level++;
-
- BLI_assert(g_v3d_string_level >= 0);
-
- if (g_v3d_string_level == 0) {
- BLI_assert(g_v3d_strings_arena == NULL);
- }
-}
-
-void view3d_cached_text_draw_add(const float co[3],
- const char *str, const size_t str_len,
- short xoffs, short flag,
- const unsigned char col[4])
-{
- int alloc_len = str_len + 1;
- ViewCachedString *vos;
-
- BLI_assert(str_len == strlen(str));
-
- if (g_v3d_strings_arena == NULL) {
- g_v3d_strings_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 14), __func__);
- }
-
- vos = BLI_memarena_alloc(g_v3d_strings_arena, sizeof(ViewCachedString) + alloc_len);
-
- BLI_LINKS_PREPEND(g_v3d_strings[g_v3d_string_level], vos);
-
- copy_v3_v3(vos->vec, co);
- copy_v4_v4_uchar(vos->col.ub, col);
- vos->xoffs = xoffs;
- vos->flag = flag;
- vos->str_len = str_len;
-
- /* allocate past the end */
- memcpy(vos->str, str, alloc_len);
-}
-
-void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write)
-{
- RegionView3D *rv3d = ar->regiondata;
- ViewCachedString *vos;
- int tot = 0;
-
- BLI_assert(g_v3d_string_level >= 0 && g_v3d_string_level <= 2);
-
- /* project first and test */
- for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) {
- if (ED_view3d_project_short_ex(ar,
- (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
- (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0,
- vos->vec, vos->sco,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
- {
- tot++;
- }
- else {
- vos->sco[0] = IS_CLIPPED;
- }
- }
-
- 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();
- wmOrtho2_region_pixelspace(ar);
- glLoadIdentity();
-
- if (depth_write) {
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
- }
- else {
- glDepthMask(0);
- }
-
- 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);
- col_pack_prev = vos->col.pack;
- }
-
- ((vos->flag & V3D_CACHE_TEXT_ASCII) ? BLF_draw_default_ascii : BLF_draw_default)(
- (float)(vos->sco[0] + vos->xoffs),
- (float)(vos->sco[1]),
- (depth_write) ? 0.0f : 2.0f,
- vos->str,
- vos->str_len);
- }
- }
-
- if (depth_write) {
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- }
- else {
- glDepthMask(1);
- }
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_enable();
- }
- }
-
- g_v3d_strings[g_v3d_string_level] = NULL;
-
- if (g_v3d_string_level == 0) {
- if (g_v3d_strings_arena) {
- BLI_memarena_free(g_v3d_strings_arena);
- g_v3d_strings_arena = NULL;
- }
- }
-
- g_v3d_string_level--;
-}
-
-/* ******************** primitive drawing ******************* */
-
-/* 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)
-{
- const GLfloat pos[8][3] = {
- {-size, -size, -size},
- {-size, -size, size},
- {-size, size, -size},
- {-size, size, size},
- { size, -size, -size},
- { size, -size, size},
- { size, size, -size},
- { size, size, 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};
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, pos);
- glDrawRangeElements(GL_LINES, 0, 7, 24, GL_UNSIGNED_BYTE, indices);
- glDisableClientState(GL_VERTEX_ARRAY);
-}
-
-static void drawshadbuflimits(Lamp *la, float mat[4][4])
-{
- float sta[3], end[3], lavec[3];
-
- negate_v3_v3(lavec, mat[2]);
- normalize_v3(lavec);
-
- 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();
-
- glPointSize(3.0);
- glBegin(GL_POINTS);
- glVertex3fv(sta);
- glVertex3fv(end);
- glEnd();
-}
-
-static void spotvolume(float lvec[3], float vvec[3], const float inp)
-{
- /* camera is at 0,0,0 */
- float temp[3], plane[3], mat1[3][3], mat2[3][3], mat3[3][3], mat4[3][3], q[4], co, si, angle;
-
- normalize_v3(lvec);
- normalize_v3(vvec); /* is this the correct vector ? */
-
- cross_v3_v3v3(temp, vvec, lvec); /* equation for a plane through vvec and lvec */
- cross_v3_v3v3(plane, lvec, temp); /* a plane perpendicular to this, parallel with lvec */
-
- /* vectors are exactly aligned, use the X axis, this is arbitrary */
- if (normalize_v3(plane) == 0.0f)
- plane[1] = 1.0f;
-
- /* now we've got two equations: one of a cone and one of a plane, but we have
- * three unknowns. We remove one unknown by rotating the plane to z=0 (the plane normal) */
-
- /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
- /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
-
- /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
-
- q[1] = plane[1];
- q[2] = -plane[0];
- q[3] = 0;
- normalize_v3(&q[1]);
-
- angle = saacos(plane[2]) / 2.0f;
- co = cosf(angle);
- si = sqrtf(1 - co * co);
-
- q[0] = co;
- q[1] *= si;
- q[2] *= si;
- q[3] = 0;
-
- quat_to_mat3(mat1, q);
-
- /* rotate lamp vector now over acos(inp) degrees */
- copy_v3_v3(vvec, lvec);
-
- unit_m3(mat2);
- co = inp;
- si = sqrtf(1.0f - inp * inp);
-
- mat2[0][0] = co;
- mat2[1][0] = -si;
- mat2[0][1] = si;
- mat2[1][1] = co;
- mul_m3_m3m3(mat3, mat2, mat1);
-
- mat2[1][0] = si;
- mat2[0][1] = -si;
- mul_m3_m3m3(mat4, mat2, mat1);
- transpose_m3(mat1);
-
- mul_m3_m3m3(mat2, mat1, mat3);
- mul_m3_v3(mat2, lvec);
- mul_m3_m3m3(mat2, mat1, mat4);
- mul_m3_v3(mat2, vvec);
-}
-
-static void draw_spot_cone(Lamp *la, float x, float z)
-{
- z = fabsf(z);
-
- glBegin(GL_TRIANGLE_FAN);
- glVertex3f(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);
- }
- else {
- for (int a = 0; a < 33; a++) {
- float angle = a * M_PI * 2 / (33 - 1);
- glVertex3f(z * cosf(angle), z * sinf(angle), 0);
- }
- }
-
- glEnd();
-}
-
-static void draw_transp_spot_volume(Lamp *la, float x, float z)
-{
- glEnable(GL_CULL_FACE);
- glEnable(GL_BLEND);
- glDepthMask(0);
-
- /* draw backside darkening */
- glCullFace(GL_FRONT);
-
- glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
- glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
-
- draw_spot_cone(la, x, z);
-
- /* draw front side lighting */
- glCullFace(GL_BACK);
-
- glBlendFunc(GL_ONE, GL_ONE);
- glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
-
- draw_spot_cone(la, x, z);
-
- /* restore state */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glDisable(GL_BLEND);
- glDepthMask(1);
- glDisable(GL_CULL_FACE);
- glCullFace(GL_BACK);
-}
-
-#ifdef WITH_GAMEENGINE
-static void draw_transp_sun_volume(Lamp *la)
-{
- float box[8][3];
-
- /* construct box */
- box[0][0] = box[1][0] = box[2][0] = box[3][0] = -la->shadow_frustum_size;
- box[4][0] = box[5][0] = box[6][0] = box[7][0] = +la->shadow_frustum_size;
- box[0][1] = box[1][1] = box[4][1] = box[5][1] = -la->shadow_frustum_size;
- box[2][1] = box[3][1] = box[6][1] = box[7][1] = +la->shadow_frustum_size;
- box[0][2] = box[3][2] = box[4][2] = box[7][2] = -la->clipend;
- box[1][2] = box[2][2] = box[5][2] = box[6][2] = -la->clipsta;
-
- /* draw edges */
- draw_box(box, false);
-
- /* draw faces */
- glEnable(GL_CULL_FACE);
- glEnable(GL_BLEND);
- glDepthMask(0);
-
- /* draw backside darkening */
- glCullFace(GL_FRONT);
-
- glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
- glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
-
- draw_box(box, true);
-
- /* draw front side lighting */
- glCullFace(GL_BACK);
-
- glBlendFunc(GL_ONE, GL_ONE);
- glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
-
- draw_box(box, true);
-
- /* restore state */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glDisable(GL_BLEND);
- glDepthMask(1);
- 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)
-{
- 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);
- const bool drawcone = ((dt > OB_WIRE) &&
- !(G.f & G_PICKSEL) &&
- (la->type == LA_SPOT) &&
- (la->mode & LA_SHOW_CONE) &&
- !(base->flag & OB_FROMDUPLI) &&
- !is_view);
-
-#ifdef WITH_GAMEENGINE
- const bool drawshadowbox = (
- (rv3d->rflag & RV3D_IS_GAME_ENGINE) &&
- (dt > OB_WIRE) &&
- !(G.f & G_PICKSEL) &&
- (la->type == LA_SUN) &&
- ((la->mode & LA_SHAD_BUF) ||
- (la->mode & LA_SHAD_RAY)) &&
- (la->mode & LA_SHOW_SHADOW_BOX) &&
- !(base->flag & OB_FROMDUPLI) &&
- !is_view);
-#else
- const bool drawshadowbox = false;
-#endif
-
- 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);
- return;
- }
-
- /* we first draw only the screen aligned & fixed scale stuff */
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
-
- /* lets calculate the scale: */
- lampsize = pixsize * ((float)U.obcenter_dia * 0.5f);
-
- /* and view aligned matrix: */
- copy_m4_m4(imat, rv3d->viewinv);
- normalize_v3(imat[0]);
- normalize_v3(imat[1]);
-
- /* lamp center */
- copy_v3_v3(vec, ob->obmat[3]);
-
- 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);
- }
-
- glLineWidth(1);
-
- if (lampsize > 0.0f) {
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (ob->id.us > 1) {
- if (is_obact || (ob->flag & SELECT)) {
- glColor4ub(0x88, 0xFF, 0xFF, 155);
- }
- else {
- glColor4ub(0x77, 0xCC, 0xCC, 155);
- }
- }
- }
-
- /* Inner Circle */
- glEnable(GL_BLEND);
- drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
- glDisable(GL_BLEND);
- drawcircball(GL_POLYGON, vec, lampsize, imat);
-
- /* restore */
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (ob->id.us > 1)
- glColor4ubv(curcol);
- }
-
- /* Outer circle */
- circrad = 3.0f * lampsize;
- setlinestyle(3);
-
- drawcircball(GL_LINE_LOOP, vec, circrad, imat);
-
- /* 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);
- }
- }
- }
- else {
- setlinestyle(3);
- 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);
-
- setlinestyle(3);
-
- glBegin(GL_LINES);
- for (axis = 0; axis < 8; axis++) {
- glVertex3fv(v1);
- glVertex3fv(v2);
- mul_m3_v3(mat, v1);
- mul_m3_v3(mat, v2);
- }
- glEnd();
-
- glTranslatef(-vec[0], -vec[1], -vec[2]);
-
- }
-
- if (la->type == LA_LOCAL) {
- if (la->mode & LA_SPHERE) {
- drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
- }
- }
-
- glPopMatrix(); /* back in object space */
- zero_v3(vec);
-
- if (is_view) {
- /* skip drawing extra info */
- }
- else if (la->type == LA_SPOT) {
- float x, y, z, z_abs;
- copy_v3_fl3(lvec, 0.0f, 0.0f, 1.0f);
- copy_v3_fl3(vvec, rv3d->persmat[0][2], rv3d->persmat[1][2], rv3d->persmat[2][2]);
- mul_transposed_mat3_m4_v3(ob->obmat, vvec);
-
- x = -la->dist;
- y = cosf(la->spotsize * 0.5f);
- z = x * sqrtf(1.0f - y * y);
-
- spotvolume(lvec, vvec, y);
- mul_v3_fl(lvec, x);
- mul_v3_fl(vvec, x);
-
- x *= y;
-
- z_abs = fabsf(z);
-
- if (la->mode & LA_SQUARE) {
- /* draw pyramid */
- const float vertices[5][3] = {
- /* 5 of vertex coords of pyramid */
- {0.0f, 0.0f, 0.0f},
- {z_abs, z_abs, x},
- {-z_abs, -z_abs, x},
- {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);
-
- glTranslatef(0.0f, 0.0f, x);
-
- /* draw the square representing spotbl */
- if (la->type == LA_SPOT) {
- float blend = z_abs * (1.0f - pow2f(la->spotblend));
-
- /* hide line if it is zero size or overlaps with outer border,
- * 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);
- }
- }
- }
- else {
-
- /* draw the angled sides of the cone */
- glBegin(GL_LINE_STRIP);
- glVertex3fv(vvec);
- glVertex3fv(vec);
- glVertex3fv(lvec);
- glEnd();
-
- /* draw the circle at the end of the cone */
- glTranslatef(0.0f, 0.0f, x);
- circ(0.0f, 0.0f, z_abs);
-
- /* draw the circle representing spotbl */
- if (la->type == LA_SPOT) {
- float blend = z_abs * (1.0f - pow2f(la->spotblend));
-
- /* hide line if it is zero size or overlaps with outer border,
- * 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);
- }
- }
- }
-
- if (drawcone)
- draw_transp_spot_volume(la, x, z);
-
- /* 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);
- if (la->type == LA_SPOT && (la->mode & LA_SHAD_BUF)) {
- float lvec_clip[3];
- float vvec_clip[3];
- float clipsta_fac = la->clipsta / -x;
-
- interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
- interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
-
- glVertex3fv(lvec_clip);
- glVertex3fv(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);
- }
- glEnd();
- }
- else if (ELEM(la->type, LA_HEMI, LA_SUN)) {
-
- /* draw the line from the circle along the dist */
- glBegin(GL_LINES);
- vec[2] = -circrad;
- glVertex3fv(vec);
- vec[2] = -la->dist;
- glVertex3fv(vec);
- glEnd();
-
- 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;
-
- 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);
-
- 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 */
- if (steps == 0) v[0] = dir * circrad;
- else v[0] = v[0] + dir * (steps * outdist);
- }
- else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
- /* make the arcs start at the edge of the energy circle */
- v[1] = (steps == 0) ? (dir * circrad) : (v[1] + dir * (steps * outdist));
- }
-
- v[2] = v[2] - steps * zdist;
-
- glVertex3fv(v);
-
- zdist = zdist * mul;
- }
-
- glEnd();
- /* flip the direction */
- dir = -dir;
- }
- }
-
-#ifdef WITH_GAMEENGINE
- if (drawshadowbox) {
- draw_transp_sun_volume(la);
- }
-#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);
- 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);
-
- glBegin(GL_LINES);
- glVertex3f(0.0, 0.0, -circrad);
- glVertex3f(0.0, 0.0, -la->dist);
- glEnd();
- }
-
- /* and back to viewspace */
- glPushMatrix();
- glLoadMatrixf(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);
- }
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- UI_GetThemeColor4ubv(TH_LAMP, col);
- glColor4ubv(col);
- }
-
- glEnable(GL_BLEND);
-
- if (vec[2] > 0) vec[2] -= circrad;
- else vec[2] += circrad;
-
- glBegin(GL_LINES);
- glVertex3fv(vec);
- vec[2] = 0;
- glVertex3fv(vec);
- glEnd();
-
- glPointSize(2.0);
- glBegin(GL_POINTS);
- glVertex3fv(vec);
- glEnd();
-
- 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();
-}
-
-static void draw_limit_line(float sta, float end, const short dflag, const unsigned char col[3])
-{
- glBegin(GL_LINES);
- glVertex3f(0.0, 0.0, -sta);
- glVertex3f(0.0, 0.0, -end);
- glEnd();
-
- if (!(dflag & DRAW_PICKING)) {
- glPointSize(3.0);
- glBegin(GL_POINTS);
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(col);
- }
- glVertex3f(0.0, 0.0, -sta);
- glVertex3f(0.0, 0.0, -end);
- glEnd();
+ immBegin(GWN_PRIM_LINE_LOOP, CIRCLE_RESOL);
+ for (int i = 0; i < CIRCLE_RESOL; ++i) {
+ immVertex3fv(pos, verts[i]);
}
-}
-
-
-/* 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)
-{
- glBegin(GL_LINES);
- glVertex3f(-size, 0.0f, -dist);
- glVertex3f(size, 0.0f, -dist);
- glVertex3f(0.0f, -size, -dist);
- glVertex3f(0.0f, size, -dist);
- glEnd();
+ immEnd();
}
#ifdef VIEW3D_CAMERA_BORDER_HACK
@@ -1586,6781 +254,290 @@ unsigned char view3d_camera_border_hack_col[3];
bool view3d_camera_border_hack_test = false;
#endif
-/* ****************** 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,
- const short dflag, const unsigned char ob_wire_col[4],
- int *global_track_index, bool draw_selected)
-{
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *track;
- float mat[4][4], imat[4][4];
- unsigned char col_unsel[4], col_sel[4];
- int tracknr = *global_track_index;
- ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
- float camera_size[3];
-
- UI_GetThemeColor4ubv(TH_TEXT, col_unsel);
- UI_GetThemeColor4ubv(TH_SELECT, col_sel);
-
- BKE_tracking_get_camera_object_matrix(scene, base->object, mat);
-
- /* we're compensating camera size for bundles size,
- * to make it so bundles are always displayed with the same size */
- copy_v3_v3(camera_size, base->object->size);
- if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0)
- mul_v3_fl(camera_size, tracking_object->scale);
-
- glPushMatrix();
-
- if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- /* current ogl matrix is translated in camera space, bundles should
- * be rendered in world space, so camera matrix should be "removed"
- * from current ogl matrix */
- invert_m4_m4(imat, base->object->obmat);
-
- glMultMatrixf(imat);
- glMultMatrixf(mat);
- }
- else {
- float obmat[4][4];
- int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra);
-
- BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, obmat);
-
- invert_m4_m4(imat, obmat);
- glMultMatrixf(imat);
- }
-
- for (track = tracksbase->first; track; track = track->next) {
- bool selected = TRACK_SELECTED(track);
-
- if (draw_selected && !selected)
- continue;
-
- if ((track->flag & TRACK_HAS_BUNDLE) == 0)
- continue;
-
- if (dflag & DRAW_PICKING)
- GPU_select_load_id(base->selcol + (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]);
-
- const int v3d_drawtype = view3d_effective_drawtype(v3d);
- if (v3d_drawtype == OB_WIRE) {
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (selected && (track->flag & TRACK_CUSTOMCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
- }
- else {
- glColor3fv(track->color);
- }
- }
-
- drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype);
- }
- else if (v3d_drawtype > OB_WIRE) {
- if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) {
- /* selection outline */
- if (selected) {
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
- }
-
- glLineWidth(2.0f);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-
- draw_bundle_sphere();
-
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- }
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
- else UI_ThemeColor(TH_BUNDLE_SOLID);
- }
-
- draw_bundle_sphere();
- }
- else {
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (selected) {
- glColor3ubv(ob_wire_col);
- }
- else {
- if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
- else UI_ThemeColor(TH_WIRE);
- }
- }
-
- drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype);
- }
- }
-
- glPopMatrix();
-
- if ((dflag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) {
- float pos[3];
-
- mul_v3_m4v3(pos, mat, track->bundle_pos);
- view3d_cached_text_draw_add(pos,
- track->name, strlen(track->name),
- 10, V3D_CACHE_TEXT_GLOBALSPACE,
- selected ? col_sel : col_unsel);
- }
-
- tracknr++;
- }
-
- if ((dflag & DRAW_PICKING) == 0) {
- if ((v3d->flag2 & V3D_SHOW_CAMERAPATH) && (tracking_object->flag & TRACKING_OBJECT_CAMERA)) {
- MovieTrackingReconstruction *reconstruction;
- reconstruction = BKE_tracking_object_get_reconstruction(tracking, tracking_object);
-
- if (reconstruction->camnr) {
- MovieReconstructedCamera *camera = reconstruction->cameras;
-
- UI_ThemeColor(TH_CAMERA_PATH);
- glLineWidth(2.0f);
-
- glBegin(GL_LINE_STRIP);
- for (int a = 0; a < reconstruction->camnr; a++, camera++) {
- glVertex3fv(camera->mat[3]);
- }
- glEnd();
- }
- }
- }
-
- glPopMatrix();
-
- *global_track_index = tracknr;
-}
-
-static void draw_viewport_reconstruction(
- Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip,
- const short dflag, const unsigned char ob_wire_col[4],
- const bool draw_selected)
-{
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *tracking_object;
- int global_track_index = 1;
-
- if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) == 0)
- return;
-
- if (v3d->flag2 & V3D_RENDER_OVERRIDE)
- return;
-
- GPU_basic_shader_colors(NULL, NULL, 0, 1.0f);
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
-
- tracking_object = tracking->objects.first;
- while (tracking_object) {
- draw_viewport_object_reconstruction(
- scene, base, v3d, rv3d, clip, tracking_object,
- dflag, ob_wire_col, &global_track_index, draw_selected);
-
- tracking_object = tracking_object->next;
- }
-
- /* 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);
-}
-
-static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], const GLenum mode)
-{
- 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();
-}
-
-/* camera frame */
-static void drawcamera_frame(float vec[4][3], const GLenum mode)
-{
- glBegin(mode);
- glVertex3fv(vec[0]);
- glVertex3fv(vec[1]);
- glVertex3fv(vec[2]);
- glVertex3fv(vec[3]);
- glEnd();
-}
-
-/* center point to camera frame */
-static void drawcamera_framelines(float vec[4][3], float origin[3])
-{
- glBegin(GL_LINE_STRIP);
- glVertex3fv(vec[1]);
- glVertex3fv(origin);
- glVertex3fv(vec[0]);
- glVertex3fv(vec[3]);
- glVertex3fv(origin);
- glVertex3fv(vec[2]);
- glEnd();
-}
-
-static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob)
-{
- return (ob == v3d->camera) &&
- (scene->r.scemode & R_MULTIVIEW) != 0 &&
- (v3d->stereo3d_flag);
-}
-
-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 obmat[4][4];
- float vec_lr[2][4][3];
- const float fac = (cam->stereo.pivot == CAM_S3D_PIVOT_CENTER) ? 2.0f : 1.0f;
- float origin[2][3] = {{0}};
- float tvec[3];
- const Camera *cam_lr[2];
- const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
-
- const bool is_stereo3d_cameras = (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS) && (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D);
- const bool is_stereo3d_plane = (v3d->stereo3d_flag & V3D_S3D_DISPPLANE) && (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D);
- const bool is_stereo3d_volume = (v3d->stereo3d_flag & V3D_S3D_DISPVOLUME);
-
- zero_v3(tvec);
-
- glPushMatrix();
-
- for (int i = 0; i < 2; i++) {
- ob = BKE_camera_multiview_render(scene, ob, names[i]);
- cam_lr[i] = ob->data;
-
- glLoadMatrixf(rv3d->viewmat);
- BKE_camera_multiview_model_matrix(&scene->r, ob, names[i], obmat);
- glMultMatrixf(obmat);
-
- copy_m3_m3(vec_lr[i], vec);
- copy_v3_v3(vec_lr[i][3], vec[3]);
-
- if (cam->stereo.convergence_mode == CAM_S3D_OFFAXIS) {
- const float shift_x =
- ((BKE_camera_multiview_shift_x(&scene->r, ob, names[i]) - cam->shiftx) *
- (drawsize * scale[0] * fac));
-
- for (int j = 0; j < 4; j++) {
- vec_lr[i][j][0] += shift_x;
- }
- }
-
- if (is_stereo3d_cameras) {
- /* camera frame */
- drawcamera_frame(vec_lr[i], GL_LINE_LOOP);
-
- /* center point to camera frame */
- drawcamera_framelines(vec_lr[i], tvec);
- }
-
- /* connecting line */
- mul_m4_v3(obmat, origin[i]);
-
- /* convergence plane */
- if (is_stereo3d_plane || is_stereo3d_volume) {
- for (int j = 0; j < 4; j++) {
- mul_m4_v3(obmat, vec_lr[i][j]);
- }
- }
- }
-
-
- /* the remaining drawing takes place in the view space */
- glLoadMatrixf(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);
-
- glBegin(GL_LINES);
- glVertex3fv(origin[0]);
- glVertex3fv(origin[1]);
- glEnd();
-
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- }
-
- /* draw convergence plane */
- if (is_stereo3d_plane) {
- float axis_center[3], screen_center[3];
- float world_plane[4][3];
- float local_plane[4][3];
- float offset;
-
- mid_v3_v3v3(axis_center, origin[0], origin[1]);
-
- for (int i = 0; i < 4; i++) {
- mid_v3_v3v3(world_plane[i], vec_lr[0][i], vec_lr[1][i]);
- sub_v3_v3v3(local_plane[i], world_plane[i], axis_center);
- }
-
- mid_v3_v3v3(screen_center, world_plane[0], world_plane[2]);
- offset = cam->stereo.convergence_distance / len_v3v3(screen_center, axis_center);
-
- for (int i = 0; i < 4; i++) {
- mul_v3_fl(local_plane[i], offset);
- add_v3_v3(local_plane[i], axis_center);
- }
-
- glColor3f(0.0f, 0.0f, 0.0f);
-
- /* camera frame */
- drawcamera_frame(local_plane, GL_LINE_LOOP);
-
- if (v3d->stereo3d_convergence_alpha > 0.0f) {
- glEnable(GL_BLEND);
- glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
-
- glColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha);
-
- drawcamera_frame(local_plane, GL_QUADS);
-
- glDisable(GL_BLEND);
- glDepthMask(1); /* restore write in zbuffer */
- }
- }
-
- /* draw convergence plane */
- if (is_stereo3d_volume) {
- float screen_center[3];
- float near_plane[4][3], far_plane[4][3];
-
- for (int i = 0; i < 2; i++) {
- mid_v3_v3v3(screen_center, vec_lr[i][0], vec_lr[i][2]);
-
- float offset = len_v3v3(screen_center, origin[i]);
-
- for (int j = 0; j < 4; j++) {
- sub_v3_v3v3(near_plane[j], vec_lr[i][j], origin[i]);
- mul_v3_fl(near_plane[j], cam_lr[i]->clipsta / offset);
- add_v3_v3(near_plane[j], origin[i]);
-
- sub_v3_v3v3(far_plane[j], vec_lr[i][j], origin[i]);
- mul_v3_fl(far_plane[j], cam_lr[i]->clipend / offset);
- add_v3_v3(far_plane[j], origin[i]);
- }
-
- /* camera frame */
- glColor3f(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);
-
- if (v3d->stereo3d_volume_alpha > 0.0f) {
- glEnable(GL_BLEND);
- glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
-
- if (i == 0)
- glColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha);
- else
- glColor4f(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);
-
- glDisable(GL_BLEND);
- glDepthMask(1); /* 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])
-{
- /* a standing up pyramid with (0,0,0) as top */
- Camera *cam;
- Object *ob = base->object;
- float tvec[3];
- float vec[4][3], asp[2], shift[2], scale[3];
- MovieClip *clip = BKE_object_movieclip_get(scene, base->object, false);
-
- const bool is_active = (ob == v3d->camera);
- const bool is_view = (rv3d->persp == RV3D_CAMOB && is_active);
- const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
- const bool is_stereo3d = drawcamera_is_stereo3d(scene, v3d, ob);
- const bool is_stereo3d_view = (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D);
- const bool is_stereo3d_cameras = (ob == scene->camera) &&
- is_multiview &&
- is_stereo3d_view &&
- (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS);
- const bool is_selection_camera_stereo = (G.f & G_PICKSEL) &&
- is_view && is_multiview &&
- is_stereo3d_view;
-
- /* draw data for movie clip set as active for scene */
- if (clip) {
- draw_viewport_reconstruction(scene, base, v3d, rv3d, clip, dflag, ob_wire_col, false);
- draw_viewport_reconstruction(scene, base, v3d, rv3d, clip, dflag, ob_wire_col, true);
- }
-
-#ifdef VIEW3D_CAMERA_BORDER_HACK
- if (is_view && !(G.f & G_PICKSEL)) {
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- view3d_camera_border_hack_col[0] = ob_wire_col[0];
- view3d_camera_border_hack_col[1] = ob_wire_col[1];
- view3d_camera_border_hack_col[2] = ob_wire_col[2];
- }
- else {
- float col[4];
- glGetFloatv(GL_CURRENT_COLOR, col);
- rgb_float_to_uchar(view3d_camera_border_hack_col, col);
- }
- view3d_camera_border_hack_test = true;
- return;
- }
-#endif
-
- cam = ob->data;
-
- /* BKE_camera_multiview_model_matrix already accounts for scale, don't do it here */
- if (is_selection_camera_stereo) {
- scale[0] = 1.0f;
- scale[1] = 1.0f;
- scale[2] = 1.0f;
- }
- else {
- scale[0] = 1.0f / len_v3(ob->obmat[0]);
- scale[1] = 1.0f / len_v3(ob->obmat[1]);
- scale[2] = 1.0f / len_v3(ob->obmat[2]);
- }
-
- float drawsize;
- BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
- asp, shift, &drawsize, vec);
-
- glDisable(GL_CULL_FACE);
- glLineWidth(1);
-
- /* camera frame */
- if (!is_stereo3d_cameras) {
- /* make sure selection uses the same matrix for camera as the one used while viewing */
- if (is_selection_camera_stereo) {
- float obmat[4][4];
- bool is_left = v3d->multiview_eye == STEREO_LEFT_ID;
-
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
- BKE_camera_multiview_model_matrix(&scene->r, ob, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, obmat);
- glMultMatrixf(obmat);
-
- drawcamera_frame(vec, GL_LINE_LOOP);
- glPopMatrix();
- }
- else {
- drawcamera_frame(vec, GL_LINE_LOOP);
- }
- }
-
- if (is_view)
- return;
-
- zero_v3(tvec);
-
- /* center point to camera frame */
- if (!is_stereo3d_cameras)
- drawcamera_framelines(vec, tvec);
-
- /* arrow on top */
- tvec[2] = vec[1][2]; /* copy the depth */
-
- /* draw an outline arrow for inactive cameras and filled
- * 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);
- 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 */
-
- tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]);
- glVertex3fv(tvec); /* right */
-
- tvec[0] = shift[0];
- tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
- glVertex3fv(tvec); /* top */
-
- glEnd();
- }
-
- if ((dflag & DRAW_SCENESET) == 0) {
- if (cam->flag & (CAM_SHOWLIMITS | CAM_SHOWMIST)) {
- float nobmat[4][4];
-
- /* draw in normalized object matrix space */
- copy_m4_m4(nobmat, ob->obmat);
- normalize_m4(nobmat);
-
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
- glMultMatrixf(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));
- /* 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);
- }
-
- if (cam->flag & CAM_SHOWMIST) {
- World *world = scene->world;
- const unsigned char col[3] = {128, 128, 128}, col_hi[3] = {255, 255, 255};
-
- if (world) {
- draw_limit_line(world->miststa, world->miststa + world->mistdist,
- dflag, (is_active ? col_hi : col));
- }
- }
- glPopMatrix();
- }
- }
-
- /* stereo cameras drawing */
- if (is_stereo3d) {
- drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale);
- }
-}
-
-/* flag similar to draw_object() */
-static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
- Object *UNUSED(ob), int UNUSED(flag))
-{
- float vec[3];
-
- glEnable(GL_BLEND);
- glLineWidth(1);
-
- for (int j = 0; j < 3; j++) {
- vec[2] = 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);
- }
- glEnd();
- }
-
- 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);
- for (int i = 0; i < 3; i++) {
- if (i == 1) {
- vec[0] *= 0.5f;
- vec[1] *= 0.5f;
- }
-
- vec[2] = 0.25f * i - 0.125f;
- glVertex3fv(vec);
- }
- glEnd();
- }
-
- glDisable(GL_BLEND);
-}
-
-static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel)
-{
- BPoint *bp = lt->def;
- const float *co = dl ? dl->verts : NULL;
-
- const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX;
- UI_ThemeColor(color);
-
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- glBegin(GL_POINTS);
-
- for (int w = 0; w < lt->pntsw; w++) {
- int wxt = (w == 0 || w == lt->pntsw - 1);
- for (int v = 0; v < lt->pntsv; v++) {
- int vxt = (v == 0 || v == lt->pntsv - 1);
- for (int u = 0; u < lt->pntsu; u++, bp++, co += 3) {
- int uxt = (u == 0 || u == lt->pntsu - 1);
- if (!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
- 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);
- }
- else if ((bp->f1 & SELECT) == sel) {
- glVertex3fv(dl ? co : bp->vec);
- }
- }
- }
- }
- }
- }
-
- glEnd();
-}
-
-static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol)
-{
- 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);
-
- }
-
- if (dl) {
- glVertex3fv(&dl->verts[index * 3]);
- }
- else {
- glVertex3fv(lt->def[index].vec);
- }
-}
-
-#ifdef SEQUENCER_DAG_WORKAROUND
-static void ensure_curve_cache(Main *bmain, Scene *scene, Object *object)
-{
- bool need_recalc = object->curve_cache == NULL;
- /* Render thread might have freed the curve cache if the
- * object is not visible. If the object is also used for
- * particles duplication, then render thread might have
- * also created curve_cache with only bevel and path
- * filled in.
- *
- * So check for curve_cache != NULL is not fully correct
- * here, we also need to check whether display list is
- * empty or not.
- *
- * The trick below tries to optimize calls to displist
- * creation for cases curve is empty. Meaning, if the curve
- * is empty (without splines) bevel list would also be empty.
- * And the thing is, render thread always leaves bevel list
- * in a proper state. So if bevel list is here and display
- * list is not we need to make display list.
- */
- if (need_recalc == false) {
- need_recalc = object->curve_cache->disp.first == NULL &&
- object->curve_cache->bev.first != NULL;
- }
- if (need_recalc) {
- switch (object->type) {
- case OB_CURVE:
- case OB_SURF:
- case OB_FONT:
- BKE_displist_make_curveTypes(scene, object, false);
- break;
- case OB_MBALL:
- BKE_displist_make_mball(bmain, bmain->eval_ctx, scene, object);
- break;
- case OB_LATTICE:
- BKE_lattice_modifiers_calc(scene, object);
- break;
- }
- }
-}
-#endif
-
-/* lattice color is hardcoded, now also shows weightgroup values in edit mode */
-static void drawlattice(View3D *v3d, Object *ob)
-{
- Lattice *lt = ob->data;
- DispList *dl;
- int u, v, w;
- int actdef_wcol = 0;
- const bool is_edit = (lt->editlatt != NULL);
-
- dl = BKE_displist_find(&ob->curve_cache->disp, DL_VERTS);
-
- 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);
- for (w = 0; w < lt->pntsw; w++) {
- int wxt = (w == 0 || w == lt->pntsw - 1);
- for (v = 0; v < lt->pntsv; v++) {
- int vxt = (v == 0 || v == lt->pntsv - 1);
- for (u = 0; u < lt->pntsu; u++) {
- 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);
- }
- 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);
- }
- 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);
- }
- }
- }
- }
- glEnd();
-
- 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);
-
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- }
-}
-
-/* ***************** ******************** */
-
-/* draw callback */
-
-typedef struct drawDMVertSel_userData {
- MVert *mvert;
- int active;
- unsigned char *col[3]; /* (base, sel, act) */
- char sel_prev;
-} drawDMVertSel_userData;
+/* ***************** BACKBUF SEL (BBS) ********* */
-static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+#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]))
{
- drawDMVertSel_userData *data = userData;
+ drawMVertOffset_userData *data = userData;
MVert *mv = &data->mvert[index];
if (!(mv->flag & ME_HIDE)) {
- const char sel = (index == data->active) ? 2 : (mv->flag & SELECT);
- if (sel != data->sel_prev) {
- glColor3ubv(data->col[sel]);
- data->sel_prev = sel;
- }
-
- glVertex3fv(co);
+ int selcol;
+ GPU_select_index_get(data->offset + index, &selcol);
+ immAttrib1u(data->col, selcol);
+ immVertex3fv(data->pos, co);
}
}
-static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
-{
- drawDMVertSel_userData data;
-
- /* TODO define selected color */
- unsigned char base_col[3] = {0x0, 0x0, 0x0};
- unsigned char sel_col[3] = {0xd8, 0xb8, 0x0};
- unsigned char act_col[3] = {0xff, 0xff, 0xff};
-
- data.mvert = me->mvert;
- data.active = BKE_mesh_mselect_active_get(me, ME_VSEL);
- data.sel_prev = 0xff;
-
- data.col[0] = base_col;
- data.col[1] = sel_col;
- data.col[2] = act_col;
-
- glBegin(GL_POINTS);
- dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
-}
-
-/* ************** DRAW MESH ****************** */
-
-/* First section is all the "simple" draw routines,
- * ones that just pass some sort of primitive to GL,
- * with perhaps various options to control lighting,
- * color, etc.
- *
- * These routines should not have user interface related
- * logic!!!
- */
-
-static void calcDrawDMNormalScale(Object *ob, drawDMNormal_userData *data)
-{
- float obmat[3][3];
-
- copy_m3_m4(obmat, ob->obmat);
-
- data->uniform_scale = is_uniform_scaled_m3(obmat);
-
- if (!data->uniform_scale) {
- /* inverted matrix */
- invert_m3_m3(data->imat, obmat);
-
- /* transposed inverted matrix */
- transpose_m3_m3(data->tmat, data->imat);
- }
-}
-
-static void draw_dm_face_normals__mapFunc(void *userData, int index, const float cent[3], const float no[3])
+static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *dm, int offset)
{
- drawDMNormal_userData *data = userData;
- BMFace *efa = BM_face_at_index(data->bm, index);
- float n[3];
-
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- if (!data->uniform_scale) {
- mul_v3_m3v3(n, data->tmat, no);
- normalize_v3(n);
- mul_m3_v3(data->imat, n);
- }
- else {
- copy_v3_v3(n, no);
- }
+ drawMVertOffset_userData data;
+ Mesh *me = ob->data;
+ MVert *mvert = me->mvert;
+ data.mvert = mvert;
+ data.offset = offset;
- glVertex3fv(cent);
- glVertex3f(cent[0] + n[0] * data->normalsize,
- cent[1] + n[1] * data->normalsize,
- cent[2] + n[2] * data->normalsize);
- }
-}
+ const int imm_len = dm->getNumVerts(dm);
-static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
-{
- drawDMNormal_userData data;
+ if (imm_len == 0) return;
- data.bm = em->bm;
- data.normalsize = scene->toolsettings->normalsize;
+ 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);
- calcDrawDMNormalScale(ob, &data);
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
- glBegin(GL_LINES);
- dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
- glEnd();
-}
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
-static void draw_dm_face_centers__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
-{
- drawBMSelect_userData *data = userData;
- BMFace *efa = BM_face_at_index(data->bm, index);
+ immBeginAtMost(GWN_PRIM_POINTS, imm_len);
+ dm->foreachMappedVert(dm, bbs_obmode_mesh_verts__mapFunc, &data, DM_FOREACH_NOP);
+ immEnd();
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) &&
- (BM_elem_flag_test(efa, BM_ELEM_SELECT) == data->select))
- {
- glVertex3fv(cent);
- }
+ immUnbindProgram();
}
-static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, bool select)
+#else
+static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *UNUSED(dm), int offset)
{
- drawBMSelect_userData data = {em->bm, select};
-
- glBegin(GL_POINTS);
- dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
+ 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
-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])
+#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]))
{
- drawDMNormal_userData *data = userData;
+ drawBMOffset_userData *data = userData;
BMVert *eve = BM_vert_at_index(data->bm, index);
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- float no[3], n[3];
-
- if (no_f) {
- copy_v3_v3(no, no_f);
- }
- else {
- normal_short_to_float_v3(no, no_s);
- }
-
- if (!data->uniform_scale) {
- mul_v3_m3v3(n, data->tmat, no);
- normalize_v3(n);
- mul_m3_v3(data->imat, n);
- }
- else {
- 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);
- }
-}
-
-static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
-{
- drawDMNormal_userData data;
-
- data.bm = em->bm;
- data.normalsize = scene->toolsettings->normalsize;
-
- calcDrawDMNormalScale(ob, &data);
-
- glBegin(GL_LINES);
- dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
- glEnd();
-}
-
-/* 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) {
- /* 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);
- }
- }
-
- /* 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);
- }
- else {
- glVertex3fv(co);
- }
+ int selcol;
+ GPU_select_index_get(data->offset + index, &selcol);
+ immAttrib1u(data->col, selcol);
+ immVertex3fv(data->pos, co);
}
}
-
-static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVert *eve_act,
- RegionView3D *rv3d)
+static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset)
{
- drawDMVerts_userData data;
- data.sel = sel;
- data.eve_act = eve_act;
+ 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);
- /* Cache theme values */
- UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, data.th_editmesh_active);
- UI_GetThemeColor4ubv(TH_VERTEX_SELECT, data.th_vertex_select);
- 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);
- /* view-aligned matrix */
- mul_m4_m4m4(data.imat, rv3d->viewmat, em->ob->obmat);
- invert_m4(data.imat);
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- glBegin(GL_POINTS);
- dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
-}
-
-/* Draw edges with color set based on selection */
-static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index)
-{
- BMEdge *eed;
- drawDMEdgesSel_userData *data = userData;
- unsigned char *col;
- eed = BM_edge_at_index(data->bm, index);
-
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- if (eed == data->eed_act) {
- glColor4ubv(data->actCol);
- }
- else {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- col = data->selCol;
- }
- else {
- col = data->baseCol;
- }
- /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
- if (col[3] == 0)
- return DM_DRAW_OPTION_SKIP;
-
- glColor4ubv(col);
- }
- return DM_DRAW_OPTION_NORMAL;
- }
- else {
- return DM_DRAW_OPTION_SKIP;
- }
-}
-
-static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
- unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act)
-{
- drawDMEdgesSel_userData data;
-
- data.baseCol = baseCol;
- data.selCol = selCol;
- data.actCol = actCol;
- data.bm = em->bm;
- data.eed_act = eed_act;
- dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
-}
-
-/* Draw edges */
-static DMDrawOption draw_dm_edges__setDrawOptions(void *userData, int index)
-{
- if (BM_elem_flag_test(BM_edge_at_index(userData, index), BM_ELEM_HIDDEN))
- return DM_DRAW_OPTION_SKIP;
- else
- return DM_DRAW_OPTION_NORMAL;
-}
-
-static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm)
-{
- dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em->bm);
-}
-
-/* Draw edges with color interpolated based on selection */
-static DMDrawOption draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
-{
- drawDMEdgesSelInterp_userData *data = userData;
- if (BM_elem_flag_test(BM_edge_at_index(data->bm, index), BM_ELEM_HIDDEN))
- return DM_DRAW_OPTION_SKIP;
- else
- return DM_DRAW_OPTION_NORMAL;
-}
-static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
-{
- drawDMEdgesSelInterp_userData *data = userData;
- BMEdge *eed = BM_edge_at_index(data->bm, index);
- unsigned char **cols = userData;
- unsigned int col0_id = (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT)) ? 2 : 1;
- unsigned int col1_id = (BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)) ? 2 : 1;
- unsigned char *col0 = cols[col0_id];
- unsigned char *col1 = cols[col1_id];
- unsigned char *col_pt;
-
- if (col0_id == col1_id) {
- col_pt = col0;
- }
- else if (t == 0.0f) {
- col_pt = col0;
- }
- else if (t == 1.0f) {
- col_pt = col1;
- }
- else {
- unsigned char col_blend[4];
- interp_v4_v4v4_uchar(col_blend, col0, col1, t);
- glColor4ubv(col_blend);
- data->lastCol = NULL;
- return;
- }
-
- if (data->lastCol != col_pt) {
- data->lastCol = col_pt;
- glColor4ubv(col_pt);
- }
-}
-
-static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
-{
- drawDMEdgesSelInterp_userData data;
- data.bm = em->bm;
- data.baseCol = baseCol;
- data.selCol = selCol;
- data.lastCol = NULL;
+ immBeginAtMost(GWN_PRIM_POINTS, em->bm->totvert);
+ dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, &data, DM_FOREACH_NOP);
+ immEnd();
- dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, &data);
+ immUnbindProgram();
}
-
-static void bm_color_from_weight(float col[3], BMVert *vert, drawDMEdgesWeightInterp_userData *data)
+#else
+static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset)
{
- MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(vert, data->cd_dvert_offset);
- float weight = defvert_find_weight(dvert, data->vgroup_index);
-
- if ((weight == 0.0f) &&
- ((data->weight_user == OB_DRAW_GROUPUSER_ACTIVE) ||
- ((data->weight_user == OB_DRAW_GROUPUSER_ALL) && defvert_is_weight_zero(dvert, data->defgroup_tot))))
- {
- copy_v3_v3(col, data->alert_color);
- }
- else {
- weight_to_rgb(col, weight);
- }
-}
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
-static void draw_dm_edges_nop_interp__setDrawInterpOptions(void *UNUSED(userData), int UNUSED(index), float UNUSED(t))
-{
- /* pass */
+ 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 void draw_dm_edges_weight_interp__setDrawInterpOptions(void *userData, int index, float t)
+#ifdef USE_MESH_DM_SELECT
+static void bbs_mesh_wire__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3])
{
- drawDMEdgesWeightInterp_userData *data = userData;
+ drawBMOffset_userData *data = userData;
BMEdge *eed = BM_edge_at_index(data->bm, index);
- float col[3];
- if (t == 0.0f) {
- bm_color_from_weight(col, eed->v1, data);
- }
- else if (t == 1.0f) {
- bm_color_from_weight(col, eed->v2, data);
- }
- else {
- float col_v1[3];
- float col_v2[3];
-
- bm_color_from_weight(col_v1, eed->v1, data);
- bm_color_from_weight(col_v2, eed->v2, data);
- interp_v3_v3v3(col, col_v1, col_v2, t);
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ int selcol;
+ GPU_select_index_get(data->offset + index, &selcol);
+ immAttrib1u(data->col, selcol);
+ immVertex3fv(data->pos, v0co);
+ immVertex3fv(data->pos, v1co);
}
-
- glColor3fv(col);
}
-static void draw_dm_edges_weight_interp(BMEditMesh *em, DerivedMesh *dm, const char weight_user)
+static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
{
- drawDMEdgesWeightInterp_userData data;
- Object *ob = em->ob;
-
+ drawBMOffset_userData data;
data.bm = em->bm;
- data.cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
- data.defgroup_tot = BLI_listbase_count(&ob->defbase);
- data.vgroup_index = ob->actdef - 1;
- data.weight_user = weight_user;
- UI_GetThemeColor3fv(TH_VERTEX_UNREFERENCED, data.alert_color);
-
- if ((data.vgroup_index != -1) && (data.cd_dvert_offset != -1)) {
- glEnable(GL_BLEND);
- dm->drawMappedEdgesInterp(
- dm,
- draw_dm_edges_sel_interp__setDrawOptions,
- draw_dm_edges_weight_interp__setDrawInterpOptions,
- &data);
- glDisable(GL_BLEND);
- }
- else {
- float col[3];
-
- if (data.weight_user == OB_DRAW_GROUPUSER_NONE) {
- weight_to_rgb(col, 0.0f);
- }
- else {
- copy_v3_v3(col, data.alert_color);
- }
- glColor3fv(col);
-
- dm->drawMappedEdgesInterp(
- dm,
- draw_dm_edges_sel_interp__setDrawOptions,
- draw_dm_edges_nop_interp__setDrawInterpOptions,
- &data);
- }
-
-}
-
-static bool draw_dm_edges_weight_check(Mesh *me, View3D *v3d)
-{
- if (me->drawflag & ME_DRAWEIGHT) {
- if ((v3d->drawtype == OB_WIRE) ||
- (v3d->flag2 & V3D_SOLID_MATCAP) ||
- ((v3d->flag2 & V3D_OCCLUDE_WIRE) && (v3d->drawtype > OB_WIRE)))
- {
- return true;
- }
- }
-
- return false;
-}
-
-/* Draw only seam edges */
-static DMDrawOption draw_dm_edges_seams__setDrawOptions(void *userData, int index)
-{
- BMEdge *eed = BM_edge_at_index(userData, index);
-
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SEAM))
- return DM_DRAW_OPTION_NORMAL;
- else
- return DM_DRAW_OPTION_SKIP;
-}
-
-static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
-{
- dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em->bm);
-}
-
-/* Draw only sharp edges */
-static DMDrawOption draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
-{
- BMEdge *eed = BM_edge_at_index(userData, index);
+ data.offset = offset;
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && !BM_elem_flag_test(eed, BM_ELEM_SMOOTH))
- return DM_DRAW_OPTION_NORMAL;
- else
- return DM_DRAW_OPTION_SKIP;
-}
+ Gwn_VertFormat *format = immVertexFormat();
-static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
-{
- dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em->bm);
-}
+ const int imm_len = dm->getNumEdges(dm) * 2;
-#ifdef WITH_FREESTYLE
+ if (imm_len == 0) return;
-static bool draw_dm_test_freestyle_edge_mark(BMesh *bm, BMEdge *eed)
-{
- FreestyleEdge *fed = CustomData_bmesh_get(&bm->edata, eed->head.data, CD_FREESTYLE_EDGE);
- if (!fed)
- return false;
- return (fed->flag & FREESTYLE_EDGE_MARK) != 0;
-}
-
-/* Draw only Freestyle feature edges */
-static DMDrawOption draw_dm_edges_freestyle__setDrawOptions(void *userData, int index)
-{
- BMEdge *eed = BM_edge_at_index(userData, index);
+ 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);
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && draw_dm_test_freestyle_edge_mark(userData, eed))
- return DM_DRAW_OPTION_NORMAL;
- else
- return DM_DRAW_OPTION_SKIP;
-}
-
-static void draw_dm_edges_freestyle(BMEditMesh *em, DerivedMesh *dm)
-{
- dm->drawMappedEdges(dm, draw_dm_edges_freestyle__setDrawOptions, em->bm);
-}
-
-static bool draw_dm_test_freestyle_face_mark(BMesh *bm, BMFace *efa)
-{
- FreestyleFace *ffa = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_FREESTYLE_FACE);
- if (!ffa)
- return false;
- return (ffa->flag & FREESTYLE_FACE_MARK) != 0;
-}
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
-#endif
-
-/* Draw loop normals. */
-static void draw_dm_loop_normals__mapFunc(void *userData, int vertex_index, int face_index,
- const float co[3], const float no[3])
-{
- if (no) {
- const drawDMNormal_userData *data = userData;
- const BMVert *eve = BM_vert_at_index(data->bm, vertex_index);
- const BMFace *efa = BM_face_at_index(data->bm, face_index);
- float vec[3];
-
- if (!(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN))) {
- if (!data->uniform_scale) {
- mul_v3_m3v3(vec, (float(*)[3])data->tmat, no);
- normalize_v3(vec);
- mul_m3_v3((float(*)[3])data->imat, vec);
- }
- else {
- copy_v3_v3(vec, no);
- }
- mul_v3_fl(vec, data->normalsize);
- add_v3_v3(vec, co);
- glVertex3fv(co);
- glVertex3fv(vec);
- }
- }
-}
-
-static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
-{
- drawDMNormal_userData data;
-
- data.bm = em->bm;
- data.normalsize = scene->toolsettings->normalsize;
+ glLineWidth(1.0f);
- calcDrawDMNormalScale(ob, &data);
+ immBeginAtMost(GWN_PRIM_LINES, imm_len);
+ dm->foreachMappedEdge(dm, bbs_mesh_wire__mapFunc, &data);
+ immEnd();
- glBegin(GL_LINES);
- dm->foreachMappedLoop(dm, draw_dm_loop_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
- glEnd();
+ immUnbindProgram();
}
-
-/* Draw faces with color set based on selection
- * return 2 for the active face so it renders with stipple enabled */
-static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
-{
- drawDMFacesSel_userData *data = userData;
- BMFace *efa = BM_face_at_index(data->bm, index);
- unsigned char *col;
-
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- if (efa == data->efa_act) {
- glColor4ubv(data->cols[2]);
- return DM_DRAW_OPTION_STIPPLE;
- }
- else {
-#ifdef WITH_FREESTYLE
- col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->bm, efa) ? 3 : 0];
#else
- col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
-#endif
- if (col[3] == 0)
- return DM_DRAW_OPTION_SKIP;
- glColor4ubv(col);
- return DM_DRAW_OPTION_NORMAL;
- }
- }
- return DM_DRAW_OPTION_SKIP;
-}
-
-static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
+static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset)
{
+ glLineWidth(1.0f);
- drawDMFacesSel_userData *data = userData;
- int i;
- BMFace *efa;
- BMFace *next_efa;
-
- unsigned char *col, *next_col;
-
- i = data->orig_index_mp_to_orig ? data->orig_index_mp_to_orig[index] : index;
- efa = (i != ORIGINDEX_NONE) ? BM_face_at_index(data->bm, i) : NULL;
- i = data->orig_index_mp_to_orig ? data->orig_index_mp_to_orig[next_index] : next_index;
- next_efa = (i != ORIGINDEX_NONE) ? BM_face_at_index(data->bm, i) : NULL;
-
- if (ELEM(NULL, efa, next_efa))
- return 0;
-
- if (efa == next_efa)
- return 1;
-
- if (efa == data->efa_act || next_efa == data->efa_act)
- return 0;
-
-#ifdef WITH_FREESTYLE
- col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->bm, efa) ? 3 : 0];
- next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->bm, efa) ? 3 : 0];
-#else
- col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
- next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : 0];
-#endif
-
- if (col[3] == 0 || next_col[3] == 0)
- return 0;
-
- return col == next_col;
+ 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);
}
-
-/* also draws the active face */
-#ifdef WITH_FREESTYLE
-static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
- unsigned char *selCol, unsigned char *actCol, unsigned char *markCol, BMFace *efa_act)
-#else
-static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
- unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
-#endif
-{
- drawDMFacesSel_userData data;
- data.dm = dm;
- data.cols[0] = baseCol;
- data.bm = em->bm;
- data.cols[1] = selCol;
- data.cols[2] = actCol;
-#ifdef WITH_FREESTYLE
- data.cols[3] = markCol;
#endif
- data.efa_act = efa_act;
- /* double lookup */
- data.orig_index_mp_to_orig = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
- dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, NULL, draw_dm_faces_sel__compareDrawOptions, &data, DM_DRAW_SKIP_HIDDEN);
-}
-
-static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index)
-{
- drawDMLayer_userData *data = userData;
- BMesh *bm = data->bm;
- BMEdge *eed = BM_edge_at_index(bm, index);
-
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- const float crease = BM_ELEM_CD_GET_FLOAT(eed, data->cd_layer_offset);
- if (crease != 0.0f) {
- UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_CREASE, crease);
- return DM_DRAW_OPTION_NORMAL;
- }
- }
- return DM_DRAW_OPTION_SKIP;
-}
-static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
+#ifdef USE_MESH_DM_SELECT
+static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *dm, const bool use_select)
{
- drawDMLayer_userData data;
+ UNUSED_VARS(dm);
+ drawBMOffset_userData data;
data.bm = em->bm;
- data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE);
-
- if (data.cd_layer_offset != -1) {
- glLineWidth(3.0);
- dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, &data);
- }
-}
-
-static DMDrawOption draw_dm_bweights__setDrawOptions(void *userData, int index)
-{
- drawDMLayer_userData *data = userData;
- BMesh *bm = data->bm;
- BMEdge *eed = BM_edge_at_index(bm, index);
-
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- const float bweight = BM_ELEM_CD_GET_FLOAT(eed, data->cd_layer_offset);
- if (bweight != 0.0f) {
- UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_BEVEL, bweight);
- return DM_DRAW_OPTION_NORMAL;
- }
- }
- return DM_DRAW_OPTION_SKIP;
-}
-static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
-{
- drawDMLayer_userData *data = userData;
- BMesh *bm = data->bm;
- BMVert *eve = BM_vert_at_index(bm, index);
-
- 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);
- }
- }
-}
-static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
-{
- ToolSettings *ts = scene->toolsettings;
-
- if (ts->selectmode & SCE_SELECT_VERTEX) {
- drawDMLayer_userData data;
-
- data.bm = em->bm;
- data.cd_layer_offset = CustomData_get_offset(&em->bm->vdata, CD_BWEIGHT);
-
- if (data.cd_layer_offset != -1) {
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
- glBegin(GL_POINTS);
- dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
- }
- }
- else {
- drawDMLayer_userData data;
-
- data.bm = em->bm;
- data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT);
-
- if (data.cd_layer_offset != -1) {
- glLineWidth(3.0);
- dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, &data);
- }
- }
-}
-
-/* Second section of routines: Combine first sets to form fancy
- * drawing routines (for example rendering twice to get overlays).
- *
- * Also includes routines that are basic drawing but are too
- * specialized to be split out (like drawing creases or measurements).
- */
-
-/* EditMesh drawing routines */
-
-static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
- BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act,
- RegionView3D *rv3d)
-{
- ToolSettings *ts = scene->toolsettings;
-
- if (v3d->zbuf) glDepthMask(0); /* disable write in zbuffer, zbuf select */
-
- for (int sel = 0; sel < 2; sel++) {
- unsigned char col[4], fcol[4];
-
- UI_GetThemeColor3ubv(sel ? TH_VERTEX_SELECT : TH_VERTEX, col);
- UI_GetThemeColor3ubv(sel ? TH_FACE_DOT : TH_WIRE_EDIT, fcol);
-
- for (int pass = 0; pass < 2; pass++) {
- float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
- float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
-
- if (pass == 0) {
- if (v3d->zbuf && !(v3d->flag & V3D_ZBUF_SELECT)) {
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_BLEND);
- }
- else {
- continue;
- }
-
- size = (size > 2.1f ? size / 2.0f : size);
- fsize = (fsize > 2.1f ? fsize / 2.0f : fsize);
- col[3] = fcol[3] = 100;
- }
- else {
- col[3] = fcol[3] = 255;
- }
-
- if (ts->selectmode & SCE_SELECT_VERTEX) {
- glPointSize(size);
- glColor4ubv(col);
- draw_dm_verts(em, cageDM, sel, eve_act, rv3d);
- }
-
- if (check_ob_drawface_dot(scene, v3d, obedit->dt)) {
- glPointSize(fsize);
- glColor4ubv(fcol);
- draw_dm_face_centers(em, cageDM, sel);
- }
-
- if (pass == 0) {
- glDisable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
- }
- }
- }
-
- if (v3d->zbuf) glDepthMask(1);
-}
-
-static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
- Mesh *me, DerivedMesh *cageDM, short sel_only,
- BMEdge *eed_act)
-{
- ToolSettings *ts = scene->toolsettings;
- unsigned char wireCol[4], selCol[4], actCol[4];
-
- /* since this function does transparent... */
- UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
- UI_GetThemeColor4ubv(TH_WIRE_EDIT, wireCol);
- UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
-
- /* when sel only is used, don't render wire, only selected, this is used for
- * textured draw mode when the 'edges' option is disabled */
- if (sel_only)
- wireCol[3] = 0;
-
- for (int pass = 0; pass < 2; pass++) {
- /* show wires in transparent when no zbuf clipping for select */
- if (pass == 0) {
- if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT) == 0) {
- glEnable(GL_BLEND);
- glDisable(GL_DEPTH_TEST);
- selCol[3] = 85;
- if (!sel_only) wireCol[3] = 85;
- }
- else {
- continue;
- }
- }
- else {
- selCol[3] = 255;
- if (!sel_only) wireCol[3] = 255;
- }
-
- if ((me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE)) {
- if (cageDM->drawMappedEdgesInterp &&
- ((ts->selectmode & SCE_SELECT_VERTEX) || (me->drawflag & ME_DRAWEIGHT)))
- {
- if (draw_dm_edges_weight_check(me, v3d)) {
- // Interpolate vertex weights
- draw_dm_edges_weight_interp(em, cageDM, ts->weightuser);
- }
- else if (ts->selectmode == SCE_SELECT_FACE) {
- draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
- }
- else {
- // Interpolate vertex selection
- draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
- }
- }
- else {
- draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
- }
- }
- else {
- if (!sel_only) {
- glColor4ubv(wireCol);
- draw_dm_edges(em, cageDM);
- }
- }
-
- if (pass == 0) {
- glDisable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
- }
- }
-}
-
-static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMesh *em, UnitSettings *unit)
-{
- /* Do not use ascii when using non-default unit system, some unit chars are utf8 (micro, square, etc.).
- * See bug #36090.
- */
- const short txt_flag = V3D_CACHE_TEXT_LOCALCLIP | (unit->system ? 0 : V3D_CACHE_TEXT_ASCII);
- Mesh *me = ob->data;
- float v1[3], v2[3], v3[3], vmid[3], fvec[3];
- char numstr[32]; /* Stores the measurement display text here */
- size_t numstr_len;
- const char *conv_float; /* Use a float conversion matching the grid size */
- unsigned char col[4] = {0, 0, 0, 255}; /* color of the text to draw */
- float area; /* area of the face */
- float grid = unit->system ? unit->scale_length : v3d->grid;
- const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
- const bool do_global = (v3d->flag & V3D_GLOBAL_STATS) != 0;
- const bool do_moving = (G.moving & G_TRANSFORM_EDIT) != 0;
- /* when 2 edge-info options are enabled, space apart */
- const bool do_edge_textpair = (me->drawflag & ME_DRAWEXTRA_EDGELEN) && (me->drawflag & ME_DRAWEXTRA_EDGEANG);
- const float edge_texpair_sep = 0.4f;
- float clip_planes[4][4];
- /* allow for displaying shape keys and deform mods */
- DerivedMesh *dm = EDBM_mesh_deform_dm_get(em);
- BMIter iter;
-
- /* make the precision of the display value proportionate to the gridsize */
-
- if (grid <= 0.01f) conv_float = "%.6g";
- else if (grid <= 0.1f) conv_float = "%.5g";
- else if (grid <= 1.0f) conv_float = "%.4g";
- else if (grid <= 10.0f) conv_float = "%.3g";
- else conv_float = "%.2g";
-
- 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);
- }
-
- if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
- BMEdge *eed;
-
- UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
-
- if (dm) {
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
- }
-
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- /* draw selected edges, or edges next to selected verts while dragging */
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
- (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
- BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))))
- {
- float v1_clip[3], v2_clip[3];
-
- if (dm) {
- dm->getVertCo(dm, BM_elem_index_get(eed->v1), v1);
- dm->getVertCo(dm, BM_elem_index_get(eed->v2), v2);
- }
- else {
- copy_v3_v3(v1, eed->v1->co);
- copy_v3_v3(v2, eed->v2->co);
- }
-
- if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) {
-
- if (do_edge_textpair) {
- interp_v3_v3v3(vmid, v1, v2, edge_texpair_sep);
- }
- else {
- mid_v3_v3v3(vmid, v1_clip, v2_clip);
- }
-
- if (do_global) {
- mul_mat3_m4_v3(ob->obmat, v1);
- mul_mat3_m4_v3(ob->obmat, v2);
- }
-
- if (unit->system) {
- numstr_len = bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
- unit->system, B_UNIT_LENGTH, do_split, false);
- }
- else {
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2));
- }
-
- view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col);
- }
- }
- }
- }
-
- if (me->drawflag & ME_DRAWEXTRA_EDGEANG) {
- const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS);
- BMEdge *eed;
-
- UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGEANG, col);
-
- if (dm) {
- BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
- }
-
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- BMLoop *l_a, *l_b;
- if (BM_edge_loop_pair(eed, &l_a, &l_b)) {
- /* draw selected edges, or edges next to selected verts while dragging */
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
- (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
- BM_elem_flag_test(eed->v2, BM_ELEM_SELECT) ||
- /* special case, this is useful to show when verts connected to
- * this edge via a face are being transformed */
- BM_elem_flag_test(l_a->next->next->v, BM_ELEM_SELECT) ||
- BM_elem_flag_test(l_a->prev->v, BM_ELEM_SELECT) ||
- BM_elem_flag_test(l_b->next->next->v, BM_ELEM_SELECT) ||
- BM_elem_flag_test(l_b->prev->v, BM_ELEM_SELECT)
- )))
- {
- float v1_clip[3], v2_clip[3];
-
- if (dm) {
- dm->getVertCo(dm, BM_elem_index_get(eed->v1), v1);
- dm->getVertCo(dm, BM_elem_index_get(eed->v2), v2);
- }
- else {
- copy_v3_v3(v1, eed->v1->co);
- copy_v3_v3(v2, eed->v2->co);
- }
-
- if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) {
- float no_a[3], no_b[3];
- float angle;
-
- if (do_edge_textpair) {
- interp_v3_v3v3(vmid, v2_clip, v1_clip, edge_texpair_sep);
- }
- else {
- mid_v3_v3v3(vmid, v1_clip, v2_clip);
- }
-
- if (dm) {
- dm->getPolyNo(dm, BM_elem_index_get(l_a->f), no_a);
- dm->getPolyNo(dm, BM_elem_index_get(l_b->f), no_b);
- }
- else {
- copy_v3_v3(no_a, l_a->f->no);
- copy_v3_v3(no_b, l_b->f->no);
- }
-
- if (do_global) {
- mul_mat3_m4_v3(ob->imat, no_a);
- mul_mat3_m4_v3(ob->imat, no_b);
- normalize_v3(no_a);
- normalize_v3(no_b);
- }
-
- angle = angle_normalized_v3v3(no_a, no_b);
-
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
-
- view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col);
- }
- }
- }
- }
- }
-
- if (me->drawflag & ME_DRAWEXTRA_FACEAREA) {
- /* would be nice to use BM_face_calc_area, but that is for 2d faces
- * so instead add up tessellation triangle areas */
- BMFace *f = NULL;
-
-#define DRAW_EM_MEASURE_STATS_FACEAREA() \
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { \
- mul_v3_fl(vmid, 1.0f / (float)n); \
- if (unit->system) { \
- numstr_len = bUnit_AsString( \
- numstr, sizeof(numstr), \
- (double)(area * unit->scale_length * unit->scale_length), \
- 3, unit->system, B_UNIT_AREA, do_split, false); \
- } \
- else { \
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, area); \
- } \
- view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); \
- } (void)0
-
- UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
-
- if (dm) {
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
- }
-
- area = 0.0;
- zero_v3(vmid);
- int n = 0;
- for (int i = 0; i < em->tottri; i++) {
- BMLoop **l = em->looptris[i];
- if (f && l[0]->f != f) {
- DRAW_EM_MEASURE_STATS_FACEAREA();
- zero_v3(vmid);
- area = 0.0;
- n = 0;
- }
-
- f = l[0]->f;
-
- if (dm) {
- dm->getVertCo(dm, BM_elem_index_get(l[0]->v), v1);
- dm->getVertCo(dm, BM_elem_index_get(l[1]->v), v2);
- dm->getVertCo(dm, BM_elem_index_get(l[2]->v), v3);
- }
- else {
- copy_v3_v3(v1, l[0]->v->co);
- copy_v3_v3(v2, l[1]->v->co);
- copy_v3_v3(v3, l[2]->v->co);
- }
-
- add_v3_v3(vmid, v1);
- add_v3_v3(vmid, v2);
- add_v3_v3(vmid, v3);
- n += 3;
- if (do_global) {
- mul_mat3_m4_v3(ob->obmat, v1);
- mul_mat3_m4_v3(ob->obmat, v2);
- mul_mat3_m4_v3(ob->obmat, v3);
- }
- area += area_tri_v3(v1, v2, v3);
- }
-
- if (f) {
- DRAW_EM_MEASURE_STATS_FACEAREA();
- }
-#undef DRAW_EM_MEASURE_STATS_FACEAREA
- }
-
- if (me->drawflag & ME_DRAWEXTRA_FACEANG) {
- BMFace *efa;
- const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS);
-
- UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
-
- if (dm) {
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
- }
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- const bool is_face_sel = BM_elem_flag_test_bool(efa, BM_ELEM_SELECT);
-
- if (is_face_sel || do_moving) {
- BMIter liter;
- BMLoop *loop;
- bool is_first = true;
-
- BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
- if (is_face_sel ||
- (do_moving &&
- (BM_elem_flag_test(loop->v, BM_ELEM_SELECT) ||
- BM_elem_flag_test(loop->prev->v, BM_ELEM_SELECT) ||
- BM_elem_flag_test(loop->next->v, BM_ELEM_SELECT))))
- {
- float v2_local[3];
-
- /* lazy init center calc */
- if (is_first) {
- if (dm) {
- BMLoop *l_iter, *l_first;
- float tvec[3];
- zero_v3(vmid);
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- do {
- dm->getVertCo(dm, BM_elem_index_get(l_iter->v), tvec);
- add_v3_v3(vmid, tvec);
- } while ((l_iter = l_iter->next) != l_first);
- mul_v3_fl(vmid, 1.0f / (float)efa->len);
- }
- else {
- BM_face_calc_center_bounds(efa, vmid);
- }
- is_first = false;
- }
-
- if (dm) {
- dm->getVertCo(dm, BM_elem_index_get(loop->prev->v), v1);
- dm->getVertCo(dm, BM_elem_index_get(loop->v), v2);
- dm->getVertCo(dm, BM_elem_index_get(loop->next->v), v3);
- }
- else {
- copy_v3_v3(v1, loop->prev->v->co);
- copy_v3_v3(v2, loop->v->co);
- copy_v3_v3(v3, loop->next->v->co);
- }
-
- copy_v3_v3(v2_local, v2);
-
- if (do_global) {
- mul_mat3_m4_v3(ob->obmat, v1);
- mul_mat3_m4_v3(ob->obmat, v2);
- mul_mat3_m4_v3(ob->obmat, v3);
- }
-
- float angle = angle_v3v3v3(v1, v2, v3);
-
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
- interp_v3_v3v3(fvec, vmid, v2_local, 0.8f);
- view3d_cached_text_draw_add(fvec, numstr, numstr_len, 0, txt_flag, col);
- }
- }
- }
- }
- }
-}
-
-static void draw_em_indices(BMEditMesh *em)
-{
- const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
- BMEdge *e;
- BMFace *f;
- BMVert *v;
- char numstr[32];
- size_t numstr_len;
- float pos[3];
- unsigned char col[4];
-
- BMIter iter;
- BMesh *bm = em->bm;
-
- /* For now, reuse appropriate theme colors from stats text colors */
- int i = 0;
- if (em->selectmode & SCE_SELECT_VERTEX) {
- UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i);
- view3d_cached_text_draw_add(v->co, numstr, numstr_len, 0, txt_flag, col);
- }
- i++;
- }
- }
- if (em->selectmode & SCE_SELECT_EDGE) {
- i = 0;
- UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i);
- mid_v3_v3v3(pos, e->v1->co, e->v2->co);
- view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col);
- }
- i++;
- }
- }
+ 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 (em->selectmode & SCE_SELECT_FACE) {
- i = 0;
- UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_face_calc_center_mean(f, pos);
- numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i);
- view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col);
- }
- i++;
- }
- }
-}
-
-static DMDrawOption draw_em_fancy__setFaceOpts(void *userData, int index)
-{
- BMEditMesh *em = userData;
-
- if (UNLIKELY(index >= em->bm->totface))
- return DM_DRAW_OPTION_NORMAL;
-
- BMFace *efa = BM_face_at_index(em->bm, index);
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- return DM_DRAW_OPTION_NORMAL;
- }
- else {
- return DM_DRAW_OPTION_SKIP;
- }
-}
+ if (imm_len == 0) return;
-static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
-{
- BMEditMesh *em = userData;
+ 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);
- if (UNLIKELY(index >= em->bm->totface))
- return DM_DRAW_OPTION_NORMAL;
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
- BMFace *efa = BM_face_at_index(em->bm, index);
+ immBeginAtMost(GWN_PRIM_TRIS, imm_len);
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- return DM_DRAW_OPTION_NORMAL;
+ if (use_select == false) {
+ int selcol;
+ GPU_select_index_get(0, &selcol);
+ immAttrib1u(data.col, selcol);
}
- else {
- return DM_DRAW_OPTION_SKIP;
- }
-}
-
-static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
- Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const char dt)
-
-{
- RegionView3D *rv3d = ar->regiondata;
- Mesh *me = ob->data;
- const bool use_occlude_wire = (dt > OB_WIRE) && (v3d->flag2 & V3D_OCCLUDE_WIRE);
- bool use_depth_offset = false;
-
- glLineWidth(1);
-
- BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
-
- if (check_object_draw_editweight(me, finalDM)) {
- if (dt > OB_WIRE) {
- draw_mesh_paint_weight_faces(finalDM, true, draw_em_fancy__setFaceOpts, me->edit_btmesh);
-
- ED_view3d_polygon_offset(rv3d, 1.0);
- glDepthMask(0);
- use_depth_offset = true;
- }
- else {
- glEnable(GL_DEPTH_TEST);
- draw_mesh_paint_weight_faces(finalDM, false, draw_em_fancy__setFaceOpts, me->edit_btmesh);
- draw_mesh_paint_weight_edges(rv3d, finalDM, true, true, draw_dm_edges__setDrawOptions, me->edit_btmesh->bm);
- glDisable(GL_DEPTH_TEST);
- }
- }
- else if (dt > OB_WIRE) {
- if (use_occlude_wire) {
- /* use the cageDM since it always overlaps the editmesh faces */
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- cageDM->drawMappedFaces(cageDM, draw_em_fancy__setFaceOpts,
- GPU_object_material_bind, NULL, me->edit_btmesh, DM_DRAW_SKIP_HIDDEN | DM_DRAW_NEED_NORMALS);
- GPU_object_material_unbind();
- 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)) {
- glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
-
- finalDM->drawMappedFacesGLSL(finalDM, GPU_object_material_bind,
- draw_em_fancy__setGLSLFaceOpts, em);
- GPU_object_material_unbind();
-
- glFrontFace(GL_CCW);
- }
- else {
- draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
- }
- }
- else {
- glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
- finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_object_material_bind, NULL, me->edit_btmesh, DM_DRAW_SKIP_HIDDEN | DM_DRAW_NEED_NORMALS);
-
- glFrontFace(GL_CCW);
-
- GPU_object_material_unbind();
- }
-
- /* Setup for drawing wire over, disable zbuffer
- * write to show selected edge wires better */
- UI_ThemeColor(TH_WIRE_EDIT);
-
- ED_view3d_polygon_offset(rv3d, 1.0);
- glDepthMask(0);
- use_depth_offset = true;
- }
- else {
- if (cageDM != finalDM) {
- UI_ThemeColorBlend(TH_WIRE_EDIT, TH_BACK, 0.7);
- finalDM->drawEdges(finalDM, 1, 0);
- }
- }
-
- if ((dt > OB_WIRE) && (v3d->flag2 & V3D_RENDER_SHADOW)) {
- /* pass */
- }
- else {
- /* annoying but active faces is stored differently */
- BMFace *efa_act = BM_mesh_active_face_get(em->bm, false, true);
- BMEdge *eed_act = NULL;
- BMVert *eve_act = NULL;
-
- if (em->bm->selected.last) {
- BMEditSelection *ese = em->bm->selected.last;
- /* face is handled above */
-#if 0
- if (ese->type == BM_FACE) {
- efa_act = (BMFace *)ese->data;
- }
- else
-#endif
- if (ese->htype == BM_EDGE) {
- eed_act = (BMEdge *)ese->ele;
- }
- else if (ese->htype == BM_VERT) {
- eve_act = (BMVert *)ese->ele;
- }
- }
-
- if ((me->drawflag & ME_DRAWFACES) && (use_occlude_wire == false)) { /* transp faces */
- unsigned char col1[4], col2[4], col3[4];
-#ifdef WITH_FREESTYLE
- unsigned char col4[4];
-#endif
-
- UI_GetThemeColor4ubv(TH_FACE, col1);
- UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
- UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
-#ifdef WITH_FREESTYLE
- UI_GetThemeColor4ubv(TH_FREESTYLE_FACE_MARK, col4);
-#endif
-
- glEnable(GL_BLEND);
- glDepthMask(0); /* 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))
- col1[3] = 0;
-
-#ifdef WITH_FREESTYLE
- if (!(me->drawflag & ME_DRAW_FREESTYLE_FACE) || !CustomData_has_layer(&em->bm->pdata, CD_FREESTYLE_FACE))
- col4[3] = 0;
-
- draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act);
-#else
- draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
-#endif
-
- glDisable(GL_BLEND);
- glDepthMask(1); /* restore write in zbuffer */
- }
- else if (efa_act) {
- /* even if draw faces is off it would be nice to draw the stipple face
- * Make all other faces zero alpha except for the active */
- unsigned char col1[4], col2[4], col3[4];
-#ifdef WITH_FREESTYLE
- unsigned char col4[4];
- col4[3] = 0; /* don't draw */
-#endif
- col1[3] = col2[3] = 0; /* don't draw */
-
- UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
- glEnable(GL_BLEND);
- glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
-
-#ifdef WITH_FREESTYLE
- draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act);
-#else
- draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
-#endif
-
- glDisable(GL_BLEND);
- glDepthMask(1); /* restore write in zbuffer */
- }
-
- /* here starts all fancy draw-extra over */
- if ((me->drawflag & ME_DRAWEDGES) == 0 && check_object_draw_texture(scene, v3d, dt)) {
- /* we are drawing textures and 'ME_DRAWEDGES' is disabled, don't draw any edges */
-
- /* only draw selected edges otherwise there is no way of telling if a face is selected */
- draw_em_fancy_edges(em, scene, v3d, me, cageDM, 1, eed_act);
-
- }
- else {
- if (me->drawflag & ME_DRAWSEAMS) {
- UI_ThemeColor(TH_EDGE_SEAM);
- glLineWidth(2);
-
- draw_dm_edges_seams(em, cageDM);
-
- glColor3ub(0, 0, 0);
- }
-
- if (me->drawflag & ME_DRAWSHARP) {
- UI_ThemeColor(TH_EDGE_SHARP);
- glLineWidth(2);
-
- draw_dm_edges_sharp(em, cageDM);
-
- glColor3ub(0, 0, 0);
- }
-
-#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);
-
- draw_dm_edges_freestyle(em, cageDM);
-
- glColor3ub(0, 0, 0);
- }
-#endif
-
- if (me->drawflag & ME_DRAWCREASES) {
- draw_dm_creases(em, cageDM);
- }
- if (me->drawflag & ME_DRAWBWEIGHTS) {
- draw_dm_bweights(em, scene, cageDM);
- }
-
- glLineWidth(1);
- draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act);
- }
-
- {
- 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);
- }
- if (me->drawflag & ME_DRAW_VNORMALS) {
- UI_ThemeColor(TH_VNORMAL);
- draw_dm_vert_normals(em, scene, ob, cageDM);
- }
- if (me->drawflag & ME_DRAW_LNORMALS) {
- UI_ThemeColor(TH_LNORMAL);
- draw_dm_loop_normals(em, scene, ob, cageDM);
- }
-
- if ((me->drawflag & (ME_DRAWEXTRA_EDGELEN |
- ME_DRAWEXTRA_FACEAREA |
- ME_DRAWEXTRA_FACEANG |
- ME_DRAWEXTRA_EDGEANG)) &&
- !(v3d->flag2 & V3D_RENDER_OVERRIDE))
- {
- draw_em_measure_stats(ar, v3d, ob, em, &scene->unit);
- }
-
- if ((G.debug & G_DEBUG) && (me->drawflag & ME_DRAWEXTRA_INDICES) &&
- !(v3d->flag2 & V3D_RENDER_OVERRIDE))
- {
- draw_em_indices(em);
+ 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++;
}
}
- }
-
- if (use_depth_offset) {
- glDepthMask(1);
- ED_view3d_polygon_offset(rv3d, 0.0);
- GPU_object_material_unbind();
- }
-#if 0 /* currently not needed */
- else if (use_occlude_wire) {
- ED_view3d_polygon_offset(rv3d, 0.0);
- }
-#endif
-}
-
-/* Mesh drawing routines */
-
-static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
-{
- 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);
-
- /* if transparent, we cannot draw the edges for solid select... edges
- * have no material info. GPU_object_material_visible will skip the
- * transparent faces */
- if (ob->dtx & OB_DRAWTRANSP) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_visible);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- }
else {
- dm->drawEdges(dm, 0, 1);
+ index += ntris;
}
-
- glDepthMask(1);
}
-}
+ immEnd();
-static bool object_is_halo(Scene *scene, Object *ob)
-{
- const Material *ma = give_current_material(ob, 1);
- return (ma && (ma->material_type == MA_TYPE_HALO) && !BKE_scene_use_new_shading_nodes(scene));
+ immUnbindProgram();
}
-
-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)
-{
-#ifdef WITH_GAMEENGINE
- Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, scene) : 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);
- int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0;
-
- if (!dm)
- return;
-
- 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_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */
- }
-
- /* 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);
- }
-
- /* 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);
- }
- else if ((no_faces && no_edges) ||
- ((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob)))
- {
- glPointSize(1.5);
- dm->drawVerts(dm);
- }
- else if ((dt == OB_WIRE) || no_faces) {
- draw_wire = OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff */
- }
- 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 & SELECT) &&
- !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
- (draw_wire == OBDRAW_WIRE_OFF))
- {
- draw_mesh_object_outline(v3d, ob, dm);
- }
-
- if (draw_glsl_material(scene, 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))) {
- 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, rv3d, 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);
-
-#if 0 /* XXX */
- if (BKE_bproperty_object_get(ob, "Text"))
- draw_mesh_text(ob, 1);
-#endif
- 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, 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)) {
- dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind);
- GPU_object_material_unbind();
- }
- else {
- const float specular[3] = {0.47f, 0.47f, 0.47f};
-
- /* draw outline */
- if ((v3d->flag & V3D_SELECT_OUTLINE) &&
- ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
- (base->flag & SELECT) &&
- (draw_wire == OBDRAW_WIRE_OFF) &&
- (ob->sculpt == NULL))
- {
- draw_mesh_object_outline(v3d, ob, dm);
- }
-
- /* 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 & SELECT) &&
- (draw_wire == OBDRAW_WIRE_OFF) &&
- (ob->sculpt == NULL))
- {
- draw_mesh_object_outline(v3d, ob, dm);
- }
-
- glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
-
- if (ob->sculpt && (p = BKE_paint_get_active(scene))) {
- 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);
- 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))
- {
- /* 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) {
- if (is_obact && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.15f);
- }
- else {
- glColor3ubv(ob_wire_col);
- }
- }
-
- /* If drawing wire and drawtype is not OB_WIRE then we are
- * overlaying the wires.
- *
- * UPDATE bug #10290 - With this wire-only objects can draw
- * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
- *
- * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
- * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
- */
- 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 */
- }
-
- 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);
- ED_view3d_polygon_offset(rv3d, 0.0);
- }
- }
-
- 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);
- }
- dm->release(dm);
-}
-
-/* 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 void bbs_mesh_face(BMEditMesh *em, DerivedMesh *UNUSED(dm), const bool use_select)
{
- 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;
-
- /* 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) {
- Material *ma = give_current_material(ob, i);
- if (ma && !(ma->mode2 & MA_CASTSHADOW)) {
- return true;
- }
- }
- }
+ Mesh *me = em->ob->data;
+ Gwn_Batch *batch;
- 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 */
- if (v3d->flag2 & V3D_BACKFACE_CULLING) {
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
- }
-
- if (ob == obedit || drawlinked) {
- DerivedMesh *finalDM, *cageDM;
-
- if (obedit != ob) {
- finalDM = cageDM = editbmesh_get_derived_base(
- ob, em, scene->customdata_mask);
- }
- else {
- cageDM = editbmesh_get_derived_cage_and_final(
- scene, ob, em, scene->customdata_mask,
- &finalDM);
- }
-
- const bool use_material = ((me->drawflag & ME_DRAWEIGHT) == 0);
-
- DM_update_materials(finalDM, ob);
- if (cageDM != finalDM) {
- DM_update_materials(cageDM, ob);
- }
-
- if (use_material) {
- if (dt > OB_WIRE) {
- const bool glsl = draw_glsl_material(scene, ob, v3d, dt);
-
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
- }
- }
-
- draw_em_fancy(scene, ar, v3d, ob, em, cageDM, finalDM, dt);
-
- if (use_material) {
- GPU_end_object_materials();
- }
-
- if (obedit != ob)
- finalDM->release(finalDM);
+ 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 {
- /* 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);
-
- if (dt == OB_SOLID || glsl) {
- const bool check_alpha = check_alpha_pass(base);
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
- (check_alpha) ? &do_alpha_after : NULL);
- }
- }
-
- draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
-
- GPU_end_object_materials();
-
- if (me->totvert == 0) retval = true;
- }
+ 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_1ui(batch, "color", selcol);
+ GWN_batch_draw(batch);
}
-
- if ((dflag & DRAW_PICKING) == 0 && (base->flag & 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) {
- ED_view3d_after_add(&v3d->afterdraw_xraytransp, base, dflag);
- }
- else {
- ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag);
- }
- }
- else if (ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) {
- /* special case xray+transp when alpha is 1.0, without this the object vanishes */
- if (v3d->xray == 0 && v3d->transp == 0) {
- ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag);
- }
- }
- }
-
- if (v3d->flag2 & V3D_BACKFACE_CULLING)
- glDisable(GL_CULL_FACE);
-
- return retval;
}
-
-/* ************** DRAW DISPLIST ****************** */
-
-
-/**
- * \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)
-{
- 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) {
- if (dl->parts == 0 || dl->nr == 0) {
- continue;
- }
-
- 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);
-
- break;
- case DL_POLY:
-
- glVertexPointer(3, GL_FLOAT, 0, data);
-
- for (parts = 0; parts < dl->parts; parts++)
- glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr);
-
- break;
- case DL_SURF:
-
- glVertexPointer(3, GL_FLOAT, 0, data);
-
- for (parts = 0; parts < dl->parts; parts++) {
- if (dl->flag & DL_CYCL_U)
- glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr);
- else
- glDrawArrays(GL_LINE_STRIP, parts * dl->nr, dl->nr);
- }
-
- for (int nr = 0; nr < dl->nr; nr++) {
- int ofs = 3 * dl->nr;
-
- 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);
- data += ofs;
- }
- 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
- }
- break;
-
- case DL_INDEX3:
- glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index);
- break;
-
- case DL_INDEX4:
- glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- glDrawElements(GL_QUADS, 4 * dl->parts, GL_UNSIGNED_INT, dl->index);
- break;
- }
- }
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
- return false;
-}
-
-static bool drawDispListwire(ListBase *dlbase, const short ob_type)
-{
- unsigned int dl_mask = 0xffffffff;
-
- /* skip fill-faces for curves & fonts */
- if (ELEM(ob_type, OB_FONT, OB_CURVE)) {
- dl_mask &= ~((1 << DL_INDEX3) | (1 << DL_INDEX4));
- }
-
- return drawDispListwire_ex(dlbase, dl_mask);
-}
-
-static bool index3_nors_incr = true;
-
-static void drawDispListsolid(ListBase *lb, Object *ob, const short 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;
-
- switch (dl->type) {
- case DL_SEGM:
- if (ob->type == OB_SURF) {
- if (col != -1) {
- GPU_object_material_unbind();
- 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();
- }
- break;
- case DL_POLY:
- if (ob->type == OB_SURF) {
- if (col != -1) {
- GPU_object_material_unbind();
- 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();
- }
- break;
- case DL_SURF:
-
- if (dl->index) {
- if (col != dl->col) {
- 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);
-
- 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);
- }
- break;
-
- case DL_INDEX3:
- if (col != dl->col) {
- GPU_object_material_bind(dl->col + 1, use_glsl ? &gattribs : NULL);
- col = dl->col;
- }
-
- glVertexPointer(3, GL_FLOAT, 0, dl->verts);
-
- /* for polys only one normal needed */
- if (index3_nors_incr) {
- glEnableClientState(GL_NORMAL_ARRAY);
- glNormalPointer(GL_FLOAT, 0, dl->nors);
- }
- else
- glNormal3fv(ndata);
-
- glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index);
-
- if (index3_nors_incr)
- glDisableClientState(GL_NORMAL_ARRAY);
-
- break;
-
- case DL_INDEX4:
- if (col != dl->col) {
- GPU_object_material_bind(dl->col + 1, use_glsl ? &gattribs : NULL);
- 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);
-
- break;
- }
- dl = dl->next;
- }
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glFrontFace(GL_CCW);
- if (col != -1) {
- GPU_object_material_unbind();
- }
-}
-
-static void drawCurveDMWired(Object *ob)
-{
- DerivedMesh *dm = ob->derivedFinal;
- dm->drawEdges(dm, 1, 0);
-}
-
-/* return true when nothing was drawn */
-static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt)
-{
- Object *ob = base->object;
- DerivedMesh *dm = ob->derivedFinal;
-
- if (!dm) {
- return true;
- }
-
- DM_update_materials(dm, ob);
-
- 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);
-
- if (!glsl)
- dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind);
- else
- dm->drawFacesGLSL(dm, GPU_object_material_bind);
-
- GPU_end_object_materials();
- }
- else {
- if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_SOLID) == 0)
- drawCurveDMWired(ob);
- }
-
- return false;
-}
-
-/**
- * Only called by #drawDispList
- * \return true when nothing was drawn
- */
-static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
- const char dt, const short dflag, const unsigned char ob_wire_col[4])
-{
- Object *ob = base->object;
- ListBase *lb = NULL;
- DispList *dl;
- Curve *cu;
- const bool render_only = (v3d->flag2 & V3D_RENDER_OVERRIDE) != 0;
- const bool solid = (dt > OB_WIRE);
-
- switch (ob->type) {
- case OB_FONT:
- case OB_CURVE:
- cu = ob->data;
-
- lb = &ob->curve_cache->disp;
-
- if (solid) {
- const bool has_faces = BKE_displist_has_faces(lb);
- dl = lb->first;
- if (dl == NULL) {
- return true;
- }
-
- if (dl->nors == NULL) BKE_displist_normals_add(lb);
- index3_nors_incr = false;
-
- if (!render_only) {
- /* when we have faces, only draw loose-wire */
- if (has_faces) {
- drawDispListwire_ex(lb, (1 << DL_SEGM));
- }
- else {
- drawDispListwire(lb, ob->type);
- }
- }
-
- if (has_faces == false) {
- /* pass */
- }
- else {
- if (draw_glsl_material(scene, ob, v3d, dt)) {
- GPU_begin_object_materials(v3d, rv3d, scene, 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);
- 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);
- }
- }
- index3_nors_incr = true;
- }
- else {
- if (!render_only || BKE_displist_has_faces(lb)) {
- return drawDispListwire(lb, ob->type);
- }
- }
- break;
- case OB_SURF:
-
- lb = &ob->curve_cache->disp;
-
- if (solid) {
- dl = lb->first;
- if (dl == NULL) {
- return true;
- }
-
- 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);
- drawDispListsolid(lb, ob, dflag, ob_wire_col, true);
- GPU_end_object_materials();
- }
- else {
- GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
- drawDispListsolid(lb, ob, dflag, ob_wire_col, false);
- GPU_end_object_materials();
- }
- }
- else {
- return drawDispListwire(lb, ob->type);
- }
- break;
- case OB_MBALL:
-
- if (BKE_mball_is_basis(ob)) {
- lb = &ob->curve_cache->disp;
- if (BLI_listbase_is_empty(lb)) {
- return true;
- }
-
- if (solid) {
-
- if (draw_glsl_material(scene, ob, v3d, dt)) {
- GPU_begin_object_materials(v3d, rv3d, scene, 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);
- drawDispListsolid(lb, ob, dflag, ob_wire_col, false);
- GPU_end_object_materials();
- }
- }
- else {
- return drawDispListwire(lb, ob->type);
- }
- }
- break;
- }
-
- return false;
-}
-static bool drawDispList(Main *bmain, Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
- const char dt, const short dflag, const unsigned char ob_wire_col[4])
+#ifdef USE_MESH_DM_SELECT
+static void bbs_mesh_solid__drawCenter(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
{
- bool retval;
-
- /* backface culling */
- if (v3d->flag2 & V3D_BACKFACE_CULLING) {
- /* not all displists use same in/out normal direction convention */
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
- }
-
-#ifdef SEQUENCER_DAG_WORKAROUND
- ensure_curve_cache(bmain, scene, base->object);
-#endif
-
- if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == false) {
- retval = false;
- }
- else {
- Object *ob = base->object;
- GLenum mode;
-
- if (ob->type == OB_MBALL) {
- mode = (ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW;
- }
- else {
- mode = (ob->transflag & OB_NEG_SCALE) ? GL_CCW : GL_CW;
- }
-
- glFrontFace(mode);
-
- retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
-
- if (mode != GL_CCW) {
- glFrontFace(GL_CCW);
- }
- }
+ drawBMOffset_userData *data = (drawBMOffset_userData *)userData;
+ BMFace *efa = BM_face_at_index(userData, index);
- if (v3d->flag2 & V3D_BACKFACE_CULLING) {
- glDisable(GL_CULL_FACE);
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ int selcol;
+ GPU_select_index_get(index + 1, &selcol);
+ immAttrib1u(data->col, selcol);
+ immVertex3fv(data->pos, cent);
}
-
- return retval;
}
-/* *********** drawing for particles ************* */
-static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int select)
-{
- /* draw created data arrays */
- switch (draw_as) {
- case PART_DRAW_AXIS:
- case PART_DRAW_CROSS:
- glDrawArrays(GL_LINES, 0, 6 * totpoint);
- break;
- case PART_DRAW_LINE:
- glDrawArrays(GL_LINES, 0, 2 * totpoint);
- break;
- case PART_DRAW_BB:
- if (ob_dt <= OB_WIRE || select)
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- else
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
- glDrawArrays(GL_QUADS, 0, 4 * totpoint);
- break;
- default:
- glDrawArrays(GL_POINTS, 0, totpoint);
- 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)
+static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *dm)
{
- float vec[3], vec2[3];
- float *vd = NULL;
- float *cd = NULL;
- float ma_col[3] = {0.0f, 0.0f, 0.0f};
-
- /* null only for PART_DRAW_CIRC */
- if (pdd) {
- vd = pdd->vd;
- cd = pdd->cd;
-
- if (pdd->ma_col) {
- copy_v3_v3(ma_col, pdd->ma_col);
- }
- }
-
- switch (draw_as) {
- case PART_DRAW_DOT:
- {
- if (vd) {
- copy_v3_v3(vd, state->co); pdd->vd += 3;
- }
- if (cd) {
- copy_v3_v3(cd, pdd->ma_col);
- pdd->cd += 3;
- }
- break;
- }
- case PART_DRAW_CROSS:
- case PART_DRAW_AXIS:
- {
- vec[0] = 2.0f * pixsize;
- vec[1] = vec[2] = 0.0;
- mul_qt_v3(state->rot, vec);
- if (draw_as == PART_DRAW_AXIS) {
- if (cd) {
- cd[1] = cd[2] = cd[4] = cd[5] = 0.0;
- cd[0] = cd[3] = 1.0;
- cd[6] = cd[8] = cd[9] = cd[11] = 0.0;
- cd[7] = cd[10] = 1.0;
- cd[13] = cd[12] = cd[15] = cd[16] = 0.0;
- cd[14] = cd[17] = 1.0;
- pdd->cd += 18;
- }
-
- copy_v3_v3(vec2, state->co);
- }
- else {
- if (cd) {
- cd[0] = cd[3] = cd[6] = cd[9] = cd[12] = cd[15] = ma_col[0];
- cd[1] = cd[4] = cd[7] = cd[10] = cd[13] = cd[16] = ma_col[1];
- cd[2] = cd[5] = cd[8] = cd[11] = cd[14] = cd[17] = ma_col[2];
- pdd->cd += 18;
- }
- sub_v3_v3v3(vec2, state->co, vec);
- }
-
- add_v3_v3(vec, state->co);
- copy_v3_v3(pdd->vd, vec); pdd->vd += 3;
- copy_v3_v3(pdd->vd, vec2); pdd->vd += 3;
-
- vec[1] = 2.0f * pixsize;
- vec[0] = vec[2] = 0.0;
- mul_qt_v3(state->rot, vec);
- if (draw_as == PART_DRAW_AXIS) {
- copy_v3_v3(vec2, state->co);
- }
- else {
- sub_v3_v3v3(vec2, state->co, vec);
- }
-
- add_v3_v3(vec, state->co);
- copy_v3_v3(pdd->vd, vec); pdd->vd += 3;
- copy_v3_v3(pdd->vd, vec2); pdd->vd += 3;
-
- vec[2] = 2.0f * pixsize;
- vec[0] = vec[1] = 0.0f;
- mul_qt_v3(state->rot, vec);
- if (draw_as == PART_DRAW_AXIS) {
- copy_v3_v3(vec2, state->co);
- }
- else {
- sub_v3_v3v3(vec2, state->co, vec);
- }
-
- add_v3_v3(vec, state->co);
-
- copy_v3_v3(pdd->vd, vec); pdd->vd += 3;
- copy_v3_v3(pdd->vd, vec2); pdd->vd += 3;
- break;
- }
- case PART_DRAW_LINE:
- {
- copy_v3_v3(vec, state->vel);
- normalize_v3(vec);
- if (draw & PART_DRAW_VEL_LENGTH)
- mul_v3_fl(vec, len_v3(state->vel));
- madd_v3_v3v3fl(pdd->vd, state->co, vec, -draw_line[0]); pdd->vd += 3;
- madd_v3_v3v3fl(pdd->vd, state->co, vec, draw_line[1]); pdd->vd += 3;
- if (cd) {
- cd[0] = cd[3] = ma_col[0];
- cd[1] = cd[4] = ma_col[1];
- cd[2] = cd[5] = ma_col[2];
- pdd->cd += 6;
- }
- break;
- }
- case PART_DRAW_CIRC:
- {
- drawcircball(GL_LINE_LOOP, state->co, pixsize, imat);
- 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);
-
- add_v3_v3v3(pdd->vd, bb_center, xvec);
- add_v3_v3(pdd->vd, yvec); pdd->vd += 3;
+ 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);
- sub_v3_v3v3(pdd->vd, bb_center, xvec);
- add_v3_v3(pdd->vd, yvec); pdd->vd += 3;
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
- sub_v3_v3v3(pdd->vd, bb_center, xvec);
- sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3;
+ glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
- add_v3_v3v3(pdd->vd, bb_center, xvec);
- sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3;
+ immBeginAtMost(GWN_PRIM_POINTS, em->bm->totface);
+ dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, &data, DM_FOREACH_NOP);
+ immEnd();
- 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;
- break;
- }
- }
+ immUnbindProgram();
}
-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)
-{
- ParticleSettings *part = psys->part;
- float pixsize;
-
- if (psys->parent)
- mul_m4_v3(psys->parent->obmat, state->co);
-
- /* create actual particle data */
- if (draw_as == PART_DRAW_BB) {
- bb->offset[0] = part->bb_offset[0];
- bb->offset[1] = part->bb_offset[1];
- bb->size[0] = part->bb_size[0] * pa_size;
- if (part->bb_align == PART_BB_VEL) {
- float pa_vel = len_v3(state->vel);
- float head = part->bb_vel_head * pa_vel;
- float tail = part->bb_vel_tail * pa_vel;
- bb->size[1] = part->bb_size[1] * pa_size + head + tail;
- /* use offset to adjust the particle center. this is relative to size, so need to divide! */
- if (bb->size[1] > 0.0f)
- bb->offset[1] += (head - tail) / bb->size[1];
- }
- else {
- bb->size[1] = part->bb_size[1] * pa_size;
- }
- bb->tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
- bb->time = ct;
- }
-
- pixsize = ED_view3d_pixel_size(rv3d, state->co) * pixsize_scale;
-
- draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd);
-}
-/* unified drawing of all new particle systems draw types except dupli ob & group
- * mostly tries to use vertex arrays for speed
- *
- * 1. check that everything is ok & updated
- * 2. start initializing things
- * 3. initialize according to draw type
- * 4. allocate drawing data arrays
- * 5. start filling the arrays
- * 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)
-{
- Object *ob = base->object;
- ParticleEditSettings *pset = PE_settings(scene);
- ParticleSettings *part = psys->part;
- ParticleData *pars = psys->particles;
- ParticleData *pa;
- ParticleKey state, *states = NULL;
- ParticleBillboardData bb;
- ParticleSimulationData sim = {NULL};
- ParticleDrawData *pdd = psys->pdd;
- Material *ma;
- float vel[3], imat[4][4];
- float timestep, pixsize_scale = 1.0f, pa_size, r_tilt, r_length;
- float pa_time, pa_birthtime, pa_dietime, pa_health, intensity;
- 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;
- GLint polygonmode[2];
- char numstr[32];
- unsigned char tcol[4] = {0, 0, 0, 255};
-
-/* 1. */
- if (part == NULL || !psys_check_enabled(ob, psys, G.is_rendering))
- return;
-
- 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)
- return;
-
- if (part->draw_as == PART_DRAW_REND)
- draw_as = part->ren_as;
- else
- draw_as = part->draw_as;
-
- if (draw_as == PART_DRAW_NOT)
- return;
-
- /* prepare curvemapping tables */
- if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve)
- curvemapping_changed_all(psys->part->clumpcurve);
- if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve)
- curvemapping_changed_all(psys->part->roughcurve);
- if ((psys->part->child_flag & PART_CHILD_USE_TWIST_CURVE) && psys->part->twistcurve)
- curvemapping_changed_all(psys->part->twistcurve);
-
-/* 2. */
- sim.scene = scene;
- sim.ob = ob;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(ob, psys);
-
- if (part->phystype == PART_PHYS_KEYED) {
- if (psys->flag & PSYS_KEYED) {
- psys_count_keyed_targets(&sim);
- if (psys->totkeyed == 0)
- return;
- }
- }
-
- if (select) {
- select = false;
- if (psys_get_current(ob) == psys)
- select = true;
- }
-
- psys->flag |= PSYS_DRAWING;
-
- if (part->type == PART_HAIR && !psys->childcache)
- totchild = 0;
- else
- totchild = psys->totchild * part->disp / 100;
-
- ma = give_current_material(ob, part->omat);
-
- if (v3d->zbuf) glDepthMask(1);
-
- if ((ma) && (part->draw_col == PART_DRAW_COL_MAT)) {
- rgb_float_to_uchar(tcol, &(ma->r));
- 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)) {
- float mat[4][4];
- mul_m4_m4m4(mat, ob->obmat, psys->imat);
- glMultMatrixf(mat);
- }
-
- /* needed for text display */
- invert_m4_m4(ob->imat, ob->obmat);
-
- totpart = psys->totpart;
-
- cfra = BKE_scene_frame_get(scene);
-
- if (draw_as == PART_DRAW_PATH && psys->pathcache == NULL && psys->childcache == NULL)
- draw_as = PART_DRAW_DOT;
-
-/* 3. */
- glLineWidth(1.0f);
-
- switch (draw_as) {
- case PART_DRAW_DOT:
- if (part->draw_size)
- glPointSize(part->draw_size);
- else
- glPointSize(2.0); /* default dot size */
- break;
- case PART_DRAW_CIRC:
- /* calculate view aligned matrix: */
- copy_m4_m4(imat, rv3d->viewinv);
- normalize_v3(imat[0]);
- normalize_v3(imat[1]);
- ATTR_FALLTHROUGH;
- case PART_DRAW_CROSS:
- case PART_DRAW_AXIS:
- /* lets calculate the scale: */
-
- if (part->draw_size == 0.0)
- pixsize_scale = 2.0f;
- else
- pixsize_scale = part->draw_size;
-
- if (draw_as == PART_DRAW_AXIS)
- create_cdata = 1;
- break;
- case PART_DRAW_OB:
- if (part->dup_ob == NULL)
- draw_as = PART_DRAW_DOT;
- else
- draw_as = 0;
- break;
- case PART_DRAW_GR:
- if (part->dup_group == NULL)
- draw_as = PART_DRAW_DOT;
- else
- draw_as = 0;
- break;
- case PART_DRAW_BB:
- if (v3d->camera == NULL && part->bb_ob == NULL) {
- printf("Billboards need an active camera or a target object!\n");
-
- draw_as = part->draw_as = PART_DRAW_DOT;
-
- if (part->draw_size)
- glPointSize(part->draw_size);
- else
- glPointSize(2.0); /* default dot size */
- }
- else if (part->bb_ob)
- bb.ob = part->bb_ob;
- else
- bb.ob = v3d->camera;
-
- bb.align = part->bb_align;
- bb.anim = part->bb_anim;
- bb.lock = part->draw & PART_DRAW_BB_LOCK;
- break;
- case PART_DRAW_PATH:
- break;
- case PART_DRAW_LINE:
- need_v = 1;
- break;
- }
- if (part->draw & PART_DRAW_SIZE && part->draw_as != PART_DRAW_CIRC) {
- copy_m4_m4(imat, rv3d->viewinv);
- normalize_v3(imat[0]);
- normalize_v3(imat[1]);
- }
-
- if (ELEM(draw_as, PART_DRAW_DOT, PART_DRAW_CROSS, PART_DRAW_LINE) &&
- (part->draw_col > PART_DRAW_COL_MAT))
- {
- create_cdata = 1;
- }
-
- if (!create_cdata && pdd && pdd->cdata) {
- MEM_freeN(pdd->cdata);
- pdd->cdata = pdd->cd = NULL;
- }
-
-/* 4. */
- if (draw_as && ELEM(draw_as, PART_DRAW_PATH, PART_DRAW_CIRC) == 0) {
- int partsize = 3 * sizeof(float);
- int create_ndata = 0;
-
- if (!pdd)
- pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticleDrawData");
-
- if (part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
- partsize *= part->trail_count;
- psys_make_temp_pointcache(ob, psys);
- }
-
- switch (draw_as) {
- case PART_DRAW_AXIS:
- case PART_DRAW_CROSS:
- partsize *= 6;
- if (draw_as != PART_DRAW_CROSS)
- create_cdata = 1;
- break;
- case PART_DRAW_LINE:
- partsize *= 2;
- break;
- case PART_DRAW_BB:
- partsize *= 4;
- create_ndata = 1;
- break;
- }
-
- if (pdd->totpart != totpart + totchild || pdd->partsize != partsize)
- psys_free_pdd(psys);
-
- if (!pdd->vdata)
- pdd->vdata = MEM_calloc_arrayN(totpart + totchild, partsize, "particle_vdata");
- if (create_cdata && !pdd->cdata)
- pdd->cdata = MEM_calloc_arrayN(totpart + totchild, partsize, "particle_cdata");
- if (create_ndata && !pdd->ndata)
- pdd->ndata = MEM_calloc_arrayN(totpart + totchild, partsize, "particle_ndata");
-
- if (part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE) {
- if (!pdd->vedata)
- pdd->vedata = MEM_calloc_arrayN(totpart + totchild, 2 * 3 * sizeof(float), "particle_vedata");
-
- need_v = 1;
- }
- else if (pdd->vedata) {
- /* velocity data not needed, so free it */
- MEM_freeN(pdd->vedata);
- pdd->vedata = NULL;
- }
-
- pdd->vd = pdd->vdata;
- pdd->ved = pdd->vedata;
- pdd->cd = pdd->cdata;
- pdd->nd = pdd->ndata;
- pdd->totpart = totpart + totchild;
- pdd->partsize = partsize;
- }
- else if (psys->pdd) {
- psys_free_pdd(psys);
- MEM_freeN(psys->pdd);
- pdd = psys->pdd = NULL;
- }
-
- if (pdd) {
- pdd->ma_col = ma_col;
- }
-
- psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- /* circles don't use drawdata, so have to add a special case here */
- if ((pdd || draw_as == PART_DRAW_CIRC) && draw_as != PART_DRAW_PATH) {
- /* 5. */
- if (pdd && (pdd->flag & PARTICLE_DRAW_DATA_UPDATED) &&
- (pdd->vedata || part->draw & (PART_DRAW_SIZE | PART_DRAW_NUM | PART_DRAW_HEALTH)) == 0)
- {
- totpoint = pdd->totpoint; /* draw data is up to date */
- }
- else {
- for (a = 0, pa = pars; a < totpart + totchild; a++, pa++) {
- /* setup per particle individual stuff */
- if (a < totpart) {
- if (totchild && (part->draw & PART_DRAW_PARENT) == 0) continue;
- if (pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue;
-
- pa_time = (cfra - pa->time) / pa->lifetime;
- pa_birthtime = pa->time;
- pa_dietime = pa->dietime;
- pa_size = pa->size;
- if (part->phystype == PART_PHYS_BOIDS)
- pa_health = pa->boid->data.health;
- else
- pa_health = -1.0;
-
- r_tilt = 2.0f * (psys_frand(psys, a + 21) - 0.5f);
- r_length = psys_frand(psys, a + 22);
-
- if (part->draw_col > PART_DRAW_COL_MAT) {
- switch (part->draw_col) {
- case PART_DRAW_COL_VEL:
- intensity = len_v3(pa->state.vel) / part->color_vec_max;
- break;
- case PART_DRAW_COL_ACC:
- intensity = len_v3v3(pa->state.vel, pa->prev_state.vel) / ((pa->state.time - pa->prev_state.time) * part->color_vec_max);
- break;
- default:
- intensity = 1.0f; /* should never happen */
- BLI_assert(0);
- break;
- }
- CLAMP(intensity, 0.0f, 1.0f);
- weight_to_rgb(ma_col, intensity);
- }
- }
- else {
- ChildParticle *cpa = &psys->child[a - totpart];
-
- pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
- pa_size = psys_get_child_size(psys, cpa, cfra, NULL);
-
- pa_health = -1.0;
-
- r_tilt = 2.0f * (psys_frand(psys, a + 21) - 0.5f);
- r_length = psys_frand(psys, a + 22);
- }
-
- drawn = 0;
- if (part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
- float length = part->path_end * (1.0f - part->randlength * r_length);
- int trail_count = part->trail_count * (1.0f - part->randlength * r_length);
- float ct = ((part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time) - length;
- float dt = length / (trail_count ? (float)trail_count : 1.0f);
- int i = 0;
-
- ct += dt;
- for (i = 0; i < trail_count; i++, ct += dt) {
-
- if (part->draw & PART_ABS_PATH_TIME) {
- if (ct < pa_birthtime || ct > pa_dietime)
- continue;
- }
- else if (ct < 0.0f || ct > 1.0f)
- continue;
-
- state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime));
- psys_get_particle_on_path(&sim, a, &state, need_v);
-
- draw_particle_data(psys, rv3d,
- &state, draw_as, imat, &bb, psys->pdd,
- ct, pa_size, r_tilt, pixsize_scale);
-
- totpoint++;
- drawn = 1;
- }
- }
- else {
- state.time = cfra;
- if (psys_get_particle_state(&sim, a, &state, 0)) {
-
- draw_particle_data(psys, rv3d,
- &state, draw_as, imat, &bb, psys->pdd,
- pa_time, pa_size, r_tilt, pixsize_scale);
-
- totpoint++;
- drawn = 1;
- }
- }
-
- if (drawn) {
- /* additional things to draw for each particle
- * (velocity, size and number) */
- if ((part->draw & PART_DRAW_VEL) && pdd && pdd->vedata) {
- copy_v3_v3(pdd->ved, state.co);
- pdd->ved += 3;
- mul_v3_v3fl(vel, state.vel, timestep);
- add_v3_v3v3(pdd->ved, state.co, vel);
- pdd->ved += 3;
-
- totve++;
- }
-
- if (part->draw & PART_DRAW_SIZE) {
- setlinestyle(3);
- drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
- setlinestyle(0);
- }
-
-
- if ((part->draw & PART_DRAW_NUM || part->draw & PART_DRAW_HEALTH) &&
- (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0)
- {
- size_t numstr_len;
- float vec_txt[3];
- char *val_pos = numstr;
- numstr[0] = '\0';
-
- if (part->draw & PART_DRAW_NUM) {
- if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) {
- numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health);
- }
- else {
- numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d", a);
- }
- }
- else {
- if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) {
- numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%.2f", pa_health);
- }
- }
-
- if (numstr[0]) {
- /* in path drawing state.co is the end point
- * use worldspace because object matrix is already applied */
- mul_v3_m4v3(vec_txt, ob->imat, state.co);
- view3d_cached_text_draw_add(vec_txt, numstr, numstr_len,
- 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol);
- }
- }
- }
- }
- }
- }
-/* 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)
- totpart = 0;
-
- /* draw actual/parent particles */
- cache = psys->pathcache;
- 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);
- }
- }
- }
-
- 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);
- }
- }
-
- if (hair_dm) {
- MVert *mvert = hair_dm->getVertArray(hair_dm);
- int i;
-
- glColor3f(0.9f, 0.4f, 0.4f);
-
- glBegin(GL_LINES);
- 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);
- }
- }
- glEnd();
- }
-
- 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) {
- ClothModifierData *clmd = psys->clmd;
- if (clmd) {
- float *gmin = clmd->hair_grid_min;
- float *gmax = clmd->hair_grid_max;
- int *res = clmd->hair_grid_res;
- int i;
-
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
-
- if (select)
- UI_ThemeColor(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]);
-
- 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]);
-
- 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();
-
- if (select)
- UI_ThemeColorShadeAlpha(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);
- }
- 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);
- }
- }
- }
-
- /* draw child particles */
- 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);
- }
- }
- }
-
- 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;
- }
-
- if ((part->draw & PART_DRAW_NUM) && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
- cache = psys->pathcache;
-
- for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
- float vec_txt[3];
- size_t numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%i", a);
- /* use worldspace because object matrix is already applied */
- mul_v3_m4v3(vec_txt, ob->imat, cache[a]->co);
- view3d_cached_text_draw_add(vec_txt, numstr, numstr_len,
- 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol);
- }
- }
- }
- 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);
-
- if (part->draw_size)
- glPointSize(part->draw_size + 2);
- else
- glPointSize(4.0);
-
- glLineWidth(3.0);
-
- draw_particle_arrays(draw_as, totpoint, ob_dt, 1);
- }
-
- /* restore from select */
- glColor3fv(ma_col);
- }
-
- 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);
- }
- }
-
- 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);
- }
-
- glPolygonMode(GL_FRONT, polygonmode[0]);
- glPolygonMode(GL_BACK, polygonmode[1]);
-
-/* 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);
-
- psys->flag &= ~PSYS_DRAWING;
-
- /* draw data can't be saved for billboards as they must update to target changes */
- if (draw_as == PART_DRAW_BB) {
- psys_free_pdd(psys);
- pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED;
- }
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-
- if (pdd) {
- /* drop references to stack memory */
- pdd->ma_col = NULL;
- }
-
- if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) {
- glLoadMatrixf(rv3d->viewmat);
- }
-}
-
-static void draw_update_ptcache_edit(Main *bmain, Scene *scene, Object *ob, PTCacheEdit *edit)
-{
- if (edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED)
- PE_update_object(bmain, scene, 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);
-}
-
-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;
-
- if (edit->pathcache == NULL)
- return;
-
- PE_hide_keys_time(scene, edit, CFRA);
-
- /* opengl setup */
- if ((v3d->flag & V3D_ZBUF_SELECT) == 0)
- glDisable(GL_DEPTH_TEST);
-
- /* get selection theme colors */
- UI_GetThemeColor3fv(TH_VERTEX_SELECT, sel_col);
- UI_GetThemeColor3fv(TH_VERTEX, nosel_col);
-
- /* draw paths */
- totkeys = (*edit->pathcache)->segments + 1;
-
- glEnable(GL_BLEND);
- pathcol = MEM_calloc_arrayN(totkeys, 4 * sizeof(float), "particle path color data");
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
-
- if (pset->brushtype == PE_BRUSH_WEIGHT)
- glLineWidth(2.0f);
-
- cache = edit->pathcache;
- for (i = 0, point = edit->points; i < totpoint; i++, point++) {
- path = cache[i];
- glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
-
- if (point->flag & PEP_HIDE) {
- for (k = 0, pcol = pathcol; k < totkeys; k++, pcol += 4) {
- copy_v3_v3(pcol, path->col);
- pcol[3] = 0.25f;
- }
-
- glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol);
- }
- else if (timed) {
- for (k = 0, pcol = pathcol, pkey = path; 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);
- }
- else
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
-
- glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
- }
-
- if (pathcol) { MEM_freeN(pathcol); pathcol = pcol = NULL; }
-
-
- /* draw edit vertices */
- if (pset->selectmode != SCE_SELECT_PATH) {
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
-
- if (pset->selectmode == SCE_SELECT_POINT) {
- float *pd = NULL, *pdata = NULL;
- float *cd = NULL, *cdata = NULL;
- int totkeys_visible = 0;
-
- for (i = 0, point = edit->points; i < totpoint; i++, point++)
- if (!(point->flag & PEP_HIDE))
- totkeys_visible += point->totkey;
-
- if (totkeys_visible) {
- if (edit->points && !(edit->points->keys->flag & PEK_USE_WCO))
- pd = pdata = MEM_calloc_arrayN(totkeys_visible, 3 * sizeof(float), "particle edit point data");
- cd = cdata = MEM_calloc_arrayN(totkeys_visible, (timed ? 4 : 3) * sizeof(float), "particle edit color data");
- }
-
- for (i = 0, point = edit->points; i < totpoint; i++, point++) {
- if (point->flag & PEP_HIDE)
- continue;
-
- for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
- if (pd) {
- copy_v3_v3(pd, key->co);
- pd += 3;
- }
-
- if (key->flag & PEK_SELECT) {
- copy_v3_v3(cd, sel_col);
- }
- else {
- copy_v3_v3(cd, nosel_col);
- }
-
- if (timed)
- *(cd + 3) = 1.0f - fabsf((float)CFRA - *key->time) / (float)pset->fade_frames;
-
- cd += (timed ? 4 : 3);
- }
- }
- cd = cdata;
- pd = pdata;
- for (i = 0, point = edit->points; i < totpoint; i++, point++) {
- if (point->flag & PEP_HIDE || point->totkey == 0)
- continue;
-
- if (point->keys->flag & PEK_USE_WCO)
- glVertexPointer(3, GL_FLOAT, sizeof(PTCacheEditKey), point->keys->world_co);
- else
- glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), pd);
-
- glColorPointer((timed ? 4 : 3), GL_FLOAT, (timed ? 4 : 3) * sizeof(float), cd);
-
- glDrawArrays(GL_POINTS, 0, point->totkey);
-
- pd += pd ? 3 * point->totkey : 0;
- cd += (timed ? 4 : 3) * point->totkey;
- }
- if (pdata) { MEM_freeN(pdata); pd = pdata = NULL; }
- if (cdata) { MEM_freeN(cdata); cd = cdata = NULL; }
- }
- else if (pset->selectmode == SCE_SELECT_END) {
- glBegin(GL_POINTS);
- 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);
- /* 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);
- }
- }
- glEnd();
- }
- }
-
- glDisable(GL_BLEND);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
-}
-
-static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, float ith, float drw_size)
-{
- float tr[3][3];
- float root[3], tip[3];
- /* take a copy for not spoiling original */
- copy_m3_m3(tr, rotscale);
- float tw = itw * drw_size;
- float th = ith * drw_size;
-
- glBegin(GL_LINES);
-
- glColor4ub(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);
- tip[1] = tip[2] = 0.0f;
- tip[0] = drw_size;
- mul_m3_v3(tr, tip);
- add_v3_v3(tip, com);
- glVertex3fv(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);
-
- root[1] = 0.0f; root[2] = -tw;
- root[0] = th;
- mul_m3_v3(tr, root);
- add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(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);
-
- root[1] = -tw; root[2] = 0.0f;
- root[0] = th;
- mul_m3_v3(tr, root);
- add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
-
- glColor4ub(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);
- tip[0] = tip[2] = 0.0f;
- tip[1] = drw_size;
- mul_m3_v3(tr, tip);
- add_v3_v3(tip, com);
- glVertex3fv(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);
-
- root[0] = 0.0f; root[2] = -tw;
- root[1] = th;
- mul_m3_v3(tr, root);
- add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(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);
-
- root[0] = -tw; root[2] = 0.0f;
- root[1] = th;
- mul_m3_v3(tr, root);
- add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
-
- glColor4ub(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);
- tip[0] = tip[1] = 0.0f;
- tip[2] = drw_size;
- mul_m3_v3(tr, tip);
- add_v3_v3(tip, com);
- glVertex3fv(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);
-
- root[0] = 0.0f; root[1] = -tw;
- root[2] = th;
- mul_m3_v3(tr, root);
- add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(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);
-
- root[0] = -tw; root[1] = 0.0f;
- root[2] = th;
- mul_m3_v3(tr, root);
- add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
-
- glEnd();
-}
-
-/* place to add drawers */
-
-static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles)
-{
- if (nu->hide || hide_handles) return;
-
- if (nu->type == CU_BEZIER) {
-
- const float *fp;
-
-#define TH_HANDLE_COL_TOT ((TH_HANDLE_SEL_FREE - TH_HANDLE_FREE) + 1)
- /* use MIN2 when indexing to ensure newer files don't read outside the array */
- unsigned char handle_cols[TH_HANDLE_COL_TOT][3];
- const int basecol = sel ? TH_HANDLE_SEL_FREE : TH_HANDLE_FREE;
-
- for (int a = 0; a < TH_HANDLE_COL_TOT; a++) {
- UI_GetThemeColor3ubv(basecol + a, handle_cols[a]);
- }
-
- glLineWidth(1.0f);
-
- glBegin(GL_LINES);
-
- BezTriple *bezt = nu->bezt;
- int a = nu->pntsu;
- while (a--) {
- if (bezt->hide == 0) {
- 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);
-
- glColor3ubv(handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]);
- glVertex3fv(fp + 3);
- glVertex3fv(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);
- }
- 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);
- }
- }
- bezt++;
- }
-
- glEnd();
-
-#undef TH_HANDLE_COL_TOT
-
- }
-}
-
-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) {
- 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);
-
- glVertex3fv(fp + 3);
- glVertex3fv(fp + 6);
- }
- bezt++;
- }
- }
- glEnd();
-
- glColor3ub(0, 0, 0);
-}
-
-static void drawvertsN(Nurb *nu, const char sel, const bool hide_handles, const void *vert)
-{
- if (nu->hide) return;
-
- const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX;
-
- UI_ThemeColor(color);
-
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
-
- glBegin(GL_POINTS);
-
- if (nu->type == CU_BEZIER) {
-
- 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 (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]);
- }
-
- 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]);
- }
- }
- 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);
- }
- }
- bp++;
- }
- }
-
- glEnd();
-}
-
-static void editnurb_draw_active_poly(Nurb *nu)
-{
- UI_ThemeColor(TH_ACTIVE_SPLINE);
- glLineWidth(2);
-
- 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);
-
- for (int a = 0; a < nu->pntsu; a++, bp++) {
- glVertex3fv(bp->vec);
- }
-
- glEnd();
- }
-
- glColor3ub(0, 0, 0);
-}
-
-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++;
-
- 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;
- }
- }
-
- 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) {
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
- }
- bp1 = bp;
- }
- }
- }
-
- glEnd();
-
- glColor3ub(0, 0, 0);
-}
-
-static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
-{
- BPoint *bp, *bp1;
- int a, b;
- Curve *cu = ob->data;
-
- int index = 0;
- Nurb *nu = nurb;
- while (nu) {
- 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);
-
- UI_ThemeColor(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);
-
- for (a = 0; a < nu->pntsu; a++, bp++) {
- glVertex3fv(bp->vec);
- }
-
- glEnd();
- }
- break;
- case CU_NURBS:
- if (!sel && index == cu->actnu) {
- /* we should draw active spline highlight below everything */
- editnurb_draw_active_nurbs(nu);
- }
-
- glLineWidth(1);
-
- glBegin(GL_LINES);
-
- bp = nu->bp;
- for (b = 0; b < nu->pntsv; b++) {
- bp1 = bp;
- bp++;
- for (a = nu->pntsu - 1; a > 0; a--, bp++) {
- 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);
- }
- }
- else {
- if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) {
- /* pass */
- }
- else {
- UI_ThemeColor(TH_NURB_ULINE);
-
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
- }
- }
- }
- bp1 = bp;
- }
- }
-
- if (nu->pntsv > 1) { /* surface */
- int ofs = nu->pntsu;
- for (b = 0; b < nu->pntsu; b++) {
- bp1 = nu->bp + b;
- bp = bp1 + ofs;
- for (a = nu->pntsv - 1; a > 0; a--, bp += ofs) {
- 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);
- }
- }
- else {
- if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) {
- /* pass */
- }
- else {
- UI_ThemeColor(TH_NURB_VLINE);
-
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
- }
- }
- }
- bp1 = bp;
- }
- }
- }
-
- glEnd();
- break;
- }
- }
-
- index++;
- nu = nu->next;
- }
-}
-
-static void draw_editnurb(
- Main *bmain, Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb,
- const char dt, const short dflag, const unsigned char ob_wire_col[4])
-{
- ToolSettings *ts = scene->toolsettings;
- Object *ob = base->object;
- Curve *cu = ob->data;
- Nurb *nu;
- const void *vert = BKE_curve_vert_active_get(cu);
- const bool hide_handles = (cu->drawflag & CU_HIDE_HANDLES) != 0;
- unsigned char wire_col[3];
-
- /* DispList */
- UI_GetThemeColor3ubv(TH_WIRE_EDIT, wire_col);
- glColor3ubv(wire_col);
-
- drawDispList(bmain, scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
-
- /* for shadows only show solid faces */
- if (v3d->flag2 & V3D_RENDER_SHADOW)
- return;
-
- if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
-
- /* first non-selected and active handles */
- int index = 0;
- for (nu = nurb; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- if (index == cu->actnu && !hide_handles)
- drawhandlesN_active(nu);
- drawhandlesN(nu, 0, hide_handles);
- }
- index++;
- }
- draw_editnurb_splines(ob, nurb, false);
- draw_editnurb_splines(ob, nurb, true);
- /* selected handles */
- 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;
- glLineWidth(1.0f);
- 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;
-
- 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 */
-
- 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);
-
- 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);
-
- glBegin(GL_LINE_STRIP);
- glVertex3fv(vec_a);
- glVertex3fv(bevp->vec);
- glVertex3fv(vec_b);
- glEnd();
-
- bevp += skip + 1;
- nr -= skip;
- }
- }
- }
-
- 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);
-}
-
-static void draw_editfont_textcurs(RegionView3D *rv3d, float textcurs[4][2])
-{
- cpack(0);
- 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();
- set_inverted_drawing(0);
- ED_view3d_polygon_offset(rv3d, 0.0);
-}
-
-static void draw_editfont(
- Main *bmain, Scene *scene, 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;
- EditFont *ef = cu->editfont;
- float vec1[3], vec2[3];
-
- draw_editfont_textcurs(rv3d, ef->textcurs);
-
- if (cu->flag & CU_FAST) {
- cpack(0xFFFFFF);
- set_inverted_drawing(1);
- drawDispList(bmain, scene, v3d, rv3d, base, OB_WIRE, dflag, ob_wire_col);
- set_inverted_drawing(0);
- }
- else {
- drawDispList(bmain, scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
- }
-
- if (cu->linewidth != 0.0f) {
- UI_ThemeColor(TH_WIRE_EDIT);
- copy_v3_v3(vec1, ob->orig);
- copy_v3_v3(vec2, ob->orig);
- vec1[0] += cu->linewidth;
- vec2[0] += cu->linewidth;
- vec1[1] += cu->linedist * cu->fsize;
- vec2[1] -= cu->lines * cu->linedist * cu->fsize;
- setlinestyle(3);
- glBegin(GL_LINES);
- glVertex2fv(vec1);
- glVertex2fv(vec2);
- glEnd();
- setlinestyle(0);
- }
-
- 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);
- 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);
- vec1[0] += cu->tb[i].w;
- glVertex3fv(vec1);
- vec1[1] -= cu->tb[i].h;
- glVertex3fv(vec1);
- vec1[0] -= cu->tb[i].w;
- glVertex3fv(vec1);
- vec1[1] += cu->tb[i].h;
- glVertex3fv(vec1);
- glEnd();
- }
- }
- setlinestyle(0);
-
-
- if (ef->selboxes && ef->selboxes_len) {
- float selboxw;
-
- cpack(0xffffff);
- set_inverted_drawing(1);
- for (int i = 0; i < ef->selboxes_len; i++) {
- EditFontSelBox *sb = &ef->selboxes[i];
- float tvec[3];
-
- if (i + 1 != ef->selboxes_len) {
- if (ef->selboxes[i + 1].y == sb->y)
- selboxw = ef->selboxes[i + 1].x - sb->x;
- else
- selboxw = sb->w;
- }
- else {
- selboxw = sb->w;
- }
-
- /* fill in xy below */
- tvec[2] = 0.001;
-
- glBegin(GL_QUADS);
-
- if (sb->rot == 0.0f) {
- copy_v2_fl2(tvec, sb->x, sb->y);
- glVertex3fv(tvec);
-
- copy_v2_fl2(tvec, sb->x + selboxw, sb->y);
- glVertex3fv(tvec);
-
- copy_v2_fl2(tvec, sb->x + selboxw, sb->y + sb->h);
- glVertex3fv(tvec);
-
- copy_v2_fl2(tvec, sb->x, sb->y + sb->h);
- glVertex3fv(tvec);
- }
- else {
- float mat[2][2];
-
- angle_to_mat2(mat, sb->rot);
-
- copy_v2_fl2(tvec, sb->x, sb->y);
- glVertex3fv(tvec);
-
- copy_v2_fl2(tvec, selboxw, 0.0f);
- mul_m2v2(mat, tvec);
- add_v2_v2(tvec, &sb->x);
- glVertex3fv(tvec);
-
- copy_v2_fl2(tvec, selboxw, sb->h);
- mul_m2v2(mat, tvec);
- add_v2_v2(tvec, &sb->x);
- glVertex3fv(tvec);
-
- copy_v2_fl2(tvec, 0.0f, sb->h);
- mul_m2v2(mat, tvec);
- add_v2_v2(tvec, &sb->x);
- glVertex3fv(tvec);
- }
-
- glEnd();
- }
- set_inverted_drawing(0);
- }
-}
-
-/* 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);
-}
-
-/* draw a cone for use as an empty drawtype */
-static void draw_empty_cone(float size)
-{
- const float radius = size;
-
- 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);
-
- glPopMatrix();
-
- gluDeleteQuadric(qobj);
-}
-
-static void drawspiral(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;
- int a;
- bool inverse = false;
- float x, y, fac;
-
- if (start < 0) {
- inverse = true;
- start = -start;
- }
-
- mul_v3_v3fl(vx, tmat[0], rad);
- mul_v3_v3fl(vy, tmat[1], rad);
-
- glBegin(GL_LINE_STRIP);
-
- if (inverse == 0) {
- copy_v3_v3(vec, cent);
- glVertex3fv(vec);
-
- for (a = 0; a < CIRCLE_RESOL; a++) {
- if (a + start >= CIRCLE_RESOL)
- start = -a + 1;
-
- fac = (float)a * tot_inv;
- x = sinval[a + start] * fac;
- y = cosval[a + start] * fac;
-
- 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);
- }
- }
- else {
- fac = (float)(CIRCLE_RESOL - 1) * tot_inv;
- x = sinval[start] * fac;
- y = cosval[start] * fac;
-
- 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);
-
- for (a = 0; a < CIRCLE_RESOL; a++) {
- if (a + start >= CIRCLE_RESOL)
- start = -a + 1;
-
- fac = (float)(-a + (CIRCLE_RESOL - 1)) * tot_inv;
- x = sinval[a + start] * fac;
- y = cosval[a + start] * fac;
-
- 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);
- }
- }
-
- glEnd();
-}
-
-/* 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)
-{
- glBegin(GL_LINE_LOOP);
-
- /* 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);
- }
-
- glEnd();
-
-}
-
-/* needs fixing if non-identity matrix used */
-static void drawtube(const float vec[3], float radius, float height, float tmat[4][4])
-{
- float cur[3];
- drawcircball(GL_LINE_LOOP, vec, radius, tmat);
-
- copy_v3_v3(cur, vec);
- cur[2] += height;
-
- drawcircball(GL_LINE_LOOP, cur, radius, tmat);
-
- 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();
-}
-
-/* needs fixing if non-identity matrix used */
-static void drawcone(const float vec[3], float radius, float height, float tmat[4][4])
-{
- float cur[3];
-
- copy_v3_v3(cur, vec);
- cur[2] += height;
-
- drawcircball(GL_LINE_LOOP, cur, radius, tmat);
-
- 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();
-}
-
-/* return true if nothing was drawn */
-static bool drawmball(
- Main *bmain, Scene *scene, 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;
- float imat[4][4];
- int code = 1;
-
- MetaBall *mb = ob->data;
-
- if (mb->editelems) {
- if ((G.f & G_PICKSEL) == 0) {
- unsigned char wire_col[4];
- UI_GetThemeColor4ubv(TH_WIRE_EDIT, wire_col);
- glColor3ubv(wire_col);
-
- drawDispList(bmain, scene, v3d, rv3d, base, dt, dflag, wire_col);
- }
- ml = mb->editelems->first;
- }
- else {
- if ((base->flag & OB_FROMDUPLI) == 0) {
- drawDispList(bmain, scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
- }
- ml = mb->elems.first;
- }
-
- if (ml == NULL) {
- return true;
- }
-
- if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
- return false;
- }
-
- invert_m4_m4(imat, rv3d->viewmatob);
- normalize_v3(imat[0]);
- normalize_v3(imat[1]);
-
- if (mb->editelems == NULL) {
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
- }
- }
-
- glLineWidth(1.0f);
-
- 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 (G.f & G_PICKSEL) {
- ml->selcol1 = code;
- GPU_select_load_id(code++);
- }
- }
- drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat);
-
- /* 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 (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);
- }
-
- ml = ml->next;
- }
- return false;
-}
-
-static void draw_forcefield(Object *ob, RegionView3D *rv3d,
- const short dflag, const unsigned char ob_wire_col[4])
-{
- PartDeflect *pd = ob->pd;
- float imat[4][4], tmat[4][4];
- float vec[3] = {0.0, 0.0, 0.0};
- /* scale size of circle etc with the empty drawsize */
- const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f;
-
- /* calculus here, is reused in PFIELD_FORCE */
- invert_m4_m4(imat, rv3d->viewmatob);
-#if 0
- normalize_v3(imat[0]); /* we don't do this because field doesnt scale either... apart from wind! */
- normalize_v3(imat[1]);
-#endif
-
- 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);
- }
-
- unit_m4(tmat);
- force_val *= 0.1f;
- drawcircball(GL_LINE_LOOP, vec, size, tmat);
- vec[2] = 0.5f * force_val;
- drawcircball(GL_LINE_LOOP, vec, size, tmat);
- vec[2] = 1.0f * force_val;
- drawcircball(GL_LINE_LOOP, vec, size, tmat);
- vec[2] = 1.5f * force_val;
- drawcircball(GL_LINE_LOOP, vec, size, tmat);
- 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);
- }
- else if (pd->forcefield == PFIELD_VORTEX) {
- float force_val = pd->f_strength;
-
- unit_m4(tmat);
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f);
- }
-
- if (force_val < 0) {
- drawspiral(vec, size, tmat, 1);
- drawspiral(vec, size, tmat, 16);
- }
- else {
- drawspiral(vec, size, tmat, -1);
- drawspiral(vec, size, tmat, -16);
- }
- }
- else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) {
- Curve *cu = ob->data;
- if ((cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) {
- float guidevec1[4], guidevec2[3];
- float mindist = pd->f_strength;
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f);
- }
-
- /* path end */
- setlinestyle(3);
- where_on_path(ob, 1.0f, guidevec1, guidevec2, NULL, NULL, NULL);
- drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
-
- /* path beginning */
- setlinestyle(0);
- where_on_path(ob, 0.0f, guidevec1, guidevec2, NULL, NULL, NULL);
- drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
-
- copy_v3_v3(vec, guidevec1); /* max center */
- }
- }
-
- setlinestyle(3);
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f);
- }
-
- 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_USEMIN)
- drawcircball(GL_LINE_LOOP, vec, pd->mindist, imat);
- }
- else if (pd->falloff == PFIELD_FALL_TUBE) {
- float radius, distance;
-
- unit_m4(tmat);
-
- vec[0] = vec[1] = 0.0f;
- radius = (pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f;
- distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f;
- vec[2] = distance;
- distance = (pd->flag & PFIELD_POSZ) ? -distance : -2.0f * distance;
-
- if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR))
- drawtube(vec, radius, distance, tmat);
-
- 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);
- }
- else if (pd->falloff == PFIELD_FALL_CONE) {
- float radius, distance;
-
- unit_m4(tmat);
-
- radius = DEG2RADF((pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f);
- 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);
- if ((pd->flag & PFIELD_POSZ) == 0)
- drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat);
- }
-
- 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);
- if ((pd->flag & PFIELD_POSZ) == 0)
- drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat);
- }
- }
- setlinestyle(0);
-}
-
-static void draw_box(const float vec[8][3], bool solid)
-{
- 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);
- }
- 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);
- }
-
- glDisableClientState(GL_VERTEX_ARRAY);
-}
-
-static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin)
+static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *UNUSED(dm))
{
- float size[3], cent[3];
- GLUquadricObj *qobj = gluNewQuadric();
-
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
-
- BKE_boundbox_calc_size_aabb(bb, size);
-
- if (around_origin) {
- zero_v3(cent);
- }
- else {
- BKE_boundbox_calc_center_aabb(bb, cent);
- }
-
- glPushMatrix();
- 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);
- }
- 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);
- }
- 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);
- }
- 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);
- }
- glPopMatrix();
-
- gluDeleteQuadric(qobj);
+ 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);
}
-
-static void draw_bounding_volume(Object *ob, char type)
-{
- BoundBox bb_local;
- BoundBox *bb = NULL;
-
- if (ob->type == OB_MESH) {
- bb = BKE_mesh_boundbox_get(ob);
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- bb = BKE_curve_boundbox_get(ob);
- }
- else if (ob->type == OB_MBALL) {
- if (BKE_mball_is_basis(ob)) {
- bb = ob->bb;
- }
- }
- else if (ob->type == OB_ARMATURE) {
- bb = BKE_armature_boundbox_get(ob);
- }
- else if (ob->type == OB_LATTICE) {
- bb = BKE_lattice_boundbox_get(ob);
- }
- else {
- const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f};
- bb = &bb_local;
- BKE_boundbox_init_from_minmax(bb, min, max);
- }
-
- 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];
-
- BKE_boundbox_calc_size_aabb(bb, size);
-
- 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];
- vec[2][1] = vec[3][1] = vec[6][1] = vec[7][1] = +size[1];
- 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);
- }
- else {
- draw_bb_quadric(bb, type, true);
- }
- }
- else {
- if (type == OB_BOUND_BOX)
- draw_box(bb->vec, false);
- else
- draw_bb_quadric(bb, type, false);
- }
-}
-
-static void drawtexspace(Object *ob)
-{
- float vec[8][3], loc[3], size[3];
-
- if (ob->type == OB_MESH) {
- BKE_mesh_texspace_get(ob->data, loc, NULL, size);
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- BKE_curve_texspace_get(ob->data, loc, NULL, size);
- }
- else if (ob->type == OB_MBALL) {
- MetaBall *mb = ob->data;
- copy_v3_v3(size, mb->size);
- copy_v3_v3(loc, mb->loc);
- }
- else {
- return;
- }
-
- vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = loc[0] - size[0];
- vec[4][0] = vec[5][0] = vec[6][0] = vec[7][0] = loc[0] + size[0];
-
- vec[0][1] = vec[1][1] = vec[4][1] = vec[5][1] = loc[1] - size[1];
- vec[2][1] = vec[3][1] = vec[6][1] = vec[7][1] = loc[1] + size[1];
-
- vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = loc[2] - size[2];
- vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = loc[2] + size[2];
-
- setlinestyle(2);
-
- draw_box(vec, false);
-
- setlinestyle(0);
-}
-
-/* draws wire outline */
-static void draw_object_selected_outline(
- Main *bmain, Scene *scene, View3D *v3d, ARegion *ar, Base *base,
- const unsigned char ob_wire_col[4])
-{
- RegionView3D *rv3d = ar->regiondata;
- Object *ob = base->object;
-
- glDepthMask(0);
-
- if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
- bool has_faces = false;
-
-#ifdef SEQUENCER_DAG_WORKAROUND
- ensure_curve_cache(bmain, scene, ob);
-#endif
-
- DerivedMesh *dm = ob->derivedFinal;
- if (dm) {
- DM_update_materials(dm, ob);
- }
-
- if (dm) {
- has_faces = (dm->getNumPolys(dm) != 0);
- }
- else {
- has_faces = BKE_displist_has_faces(&ob->curve_cache->disp);
- }
-
- 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);
- }
- else {
- /* only draw 'solid' parts of the display list as wire. */
- drawDispListwire_ex(&ob->curve_cache->disp, (DL_INDEX3 | DL_INDEX4 | DL_SURF));
- }
- }
- }
- else if (ob->type == OB_MBALL) {
- if (BKE_mball_is_basis(ob)) {
- if ((base->flag & OB_FROMDUPLI) == 0) {
- glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
- drawDispListwire(&ob->curve_cache->disp, ob->type);
- }
- }
- }
- else if (ob->type == OB_ARMATURE) {
- if (!(ob->mode & OB_MODE_POSE && base == scene->basact)) {
- glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
- draw_armature(scene, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true);
- }
- }
-
- glDepthMask(1);
-}
-
-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);
- }
-
- ED_view3d_polygon_offset(rv3d, 1.0);
- glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
- glLineWidth(1);
-
- if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
- if (ED_view3d_boundbox_clip(rv3d, ob->bb)) {
-
- if (ob->derivedFinal) {
- drawCurveDMWired(ob);
- }
- else {
- drawDispListwire(&ob->curve_cache->disp, ob->type);
- }
- }
- }
- else if (ob->type == OB_MBALL) {
- if (BKE_mball_is_basis(ob)) {
- drawDispListwire(&ob->curve_cache->disp, ob->type);
- }
- }
-
- glDepthMask(1);
- ED_view3d_polygon_offset(rv3d, 0.0);
- }
-}
-
-/* should be called in view space */
-static void draw_hooks(Object *ob)
-{
- for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Hook) {
- HookModifierData *hmd = (HookModifierData *) md;
- float vec[3];
-
- mul_v3_m4v3(vec, ob->obmat, hmd->cent);
-
- if (hmd->object) {
- setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(hmd->object->obmat[3]);
- glVertex3fv(vec);
- glEnd();
- setlinestyle(0);
- }
-
- glPointSize(3.0);
- glBegin(GL_POINTS);
- glVertex3fv(vec);
- glEnd();
- }
- }
-}
-
-static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data,
- const short dflag, const unsigned char ob_wire_col[4])
-{
- const char *axis_str[3] = {"px", "py", "pz"};
- float mat[4][4];
-
- eul_to_mat4(mat, &data->axX);
- glLineWidth(4.0f);
- setlinestyle(2);
- for (int axis = 0; axis < 3; axis++) {
- float dir[3] = {0, 0, 0};
- float v[3];
-
- 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();
-
- /* 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 */
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- view3d_cached_text_draw_add(v, axis_str[axis], 2, 0, V3D_CACHE_TEXT_ASCII, ob_wire_col);
- }
- }
-
- setlinestyle(0);
-}
-
-static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_col[4])
-{
- Object *ob = base->object;
- int colindex = 0;
- const bool is_edit = (ob->mode & OB_MODE_EDIT) != 0;
- /* confusing logic here, there are 2 methods of setting the color
- * 'colortab[colindex]' and 'theme_id', colindex overrides theme_id.
- *
- * note: no theme yet for 'colindex' */
- int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE;
- int theme_shade = 0;
-
- if ((scene->obedit == NULL) &&
- (G.moving & G_TRANSFORM_OBJ) &&
- (base->flag & (SELECT + 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;
- }
- /* Sets the 'theme_id' or fallback to wire */
- else {
- if (ob->flag & OB_FROMGROUP) {
- if (base->flag & (SELECT + BA_WAS_SEL)) {
- /* uses darker active color for non-active + selected */
- theme_id = TH_GROUP_ACTIVE;
-
- if (scene->basact != base) {
- theme_shade = -32;
- }
- }
- else {
- theme_id = TH_GROUP;
- }
- }
- else {
- if (base->flag & (SELECT + BA_WAS_SEL)) {
- theme_id = scene->basact == base ? TH_ACTIVE : TH_SELECT;
- }
- else {
- if (ob->type == OB_LAMP) theme_id = TH_LAMP;
- else if (ob->type == OB_SPEAKER) theme_id = TH_SPEAKER;
- else if (ob->type == OB_CAMERA) theme_id = TH_CAMERA;
- else if (ob->type == OB_EMPTY) theme_id = TH_EMPTY;
- /* fallback to TH_WIRE */
- }
- }
- }
- }
-
- /* finally set the color */
- if (colindex == 0) {
- if (theme_shade == 0) UI_GetThemeColor3ubv(theme_id, r_ob_wire_col);
- else UI_GetThemeColorShade3ubv(theme_id, theme_shade, r_ob_wire_col);
- }
- else {
- cpack_cpy_3ub(r_ob_wire_col, colortab[colindex]);
- }
-
- /* no reason to use this but some functions take col[4] */
- r_ob_wire_col[3] = 255;
-}
-
-static void draw_object_matcap_check(View3D *v3d, Object *ob)
-{
- /* fixed rule, active object draws as matcap */
- BLI_assert((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) == 0);
- (void)ob;
-
- if (v3d->defmaterial == NULL) {
- extern Material defmaterial;
-
- v3d->defmaterial = MEM_mallocN(sizeof(Material), "matcap material");
- *(v3d->defmaterial) = defmaterial;
- BLI_listbase_clear(&v3d->defmaterial->gpumaterial);
- v3d->defmaterial->preview = NULL;
- }
- /* first time users */
- if (v3d->matcap_icon < ICON_MATCAP_01 ||
- v3d->matcap_icon > ICON_MATCAP_24)
- {
- v3d->matcap_icon = ICON_MATCAP_01;
- }
-
- if (v3d->defmaterial->preview == NULL)
- v3d->defmaterial->preview = UI_icon_to_preview(v3d->matcap_icon);
-
- /* signal to all material checks, gets cleared below */
- v3d->flag2 |= V3D_SHOW_SOLID_MATCAP;
-}
-
-static void draw_rigidbody_shape(Object *ob)
-{
- BoundBox *bb = NULL;
- float size[3], vec[8][3];
-
- if (ob->type == OB_MESH) {
- bb = BKE_mesh_boundbox_get(ob);
- }
-
- if (bb == NULL)
- return;
-
- switch (ob->rigidbody_object->shape) {
- case RB_SHAPE_BOX:
- BKE_boundbox_calc_size_aabb(bb, size);
-
- 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];
- vec[2][1] = vec[3][1] = vec[6][1] = vec[7][1] = +size[1];
- 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);
- break;
- case RB_SHAPE_SPHERE:
- draw_bb_quadric(bb, OB_BOUND_SPHERE, true);
- break;
- case RB_SHAPE_CONE:
- draw_bb_quadric(bb, OB_BOUND_CONE, true);
- break;
- case RB_SHAPE_CYLINDER:
- draw_bb_quadric(bb, OB_BOUND_CYLINDER, true);
- break;
- case RB_SHAPE_CAPSULE:
- draw_bb_quadric(bb, OB_BOUND_CAPSULE, true);
- break;
- }
-}
-
-/**
- * main object drawing function, draws in selection
- * \param dflag (draw flag) can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET
- */
-void draw_object(Main *bmain, Scene *scene, 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 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);
- bool skip_object = false; /* Draw particles but not their emitter object. */
- SmokeModifierData *smd = NULL;
-
- if (ob != scene->obedit) {
- if (ob->restrictflag & OB_RESTRICT_VIEW)
- return;
-
- if (render_override) {
- if (ob->restrictflag & OB_RESTRICT_RENDER)
- return;
-
- if (!has_particles && (ob->transflag & (OB_DUPLI & ~OB_DUPLIFRAMES)))
- return;
- }
- }
-
- if (has_particles) {
- /* XXX particles are not safe for simultaneous threaded render */
- if (G.is_rendering) {
- return;
- }
-
- if (ob->mode == OB_MODE_OBJECT) {
- ParticleSystem *psys;
-
- skip_object = render_override;
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- /* Once we have found a psys which renders its emitter object, we are done. */
- if (psys->part->draw & PART_DRAW_EMITTER) {
- skip_object = false;
- break;
- }
- }
- }
- }
-
- if (((base->flag & OB_FROMDUPLI) == 0) &&
- (md = modifiers_findByType(ob, eModifierType_Smoke)) &&
- (modifier_isEnabled(scene, md, eModifierMode_Realtime)))
- {
- smd = (SmokeModifierData *)md;
-
- if (smd->domain) {
- if (!v3d->transp && (dflag & DRAW_PICKING) == 0) {
- if (!v3d->xray && !(ob->dtx & OB_DRAWXRAY)) {
- /* object has already been drawn so skip drawing it */
- ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag);
- return;
- }
- else if (v3d->xray) {
- /* object has already been drawn so skip drawing it */
- ED_view3d_after_add(&v3d->afterdraw_xraytransp, base, dflag);
- return;
- }
- }
- }
- }
-
-
- /* xray delay? */
- if ((dflag & DRAW_PICKING) == 0 && (base->flag & 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 */
- if (!v3d->xray && !v3d->transp && (ob->dtx & OB_DRAWXRAY) && !(ob->dtx & OB_DRAWTRANSP)) {
- ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag);
- return;
- }
-
- /* allow transp option for empty images */
- if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
- if (!v3d->xray && !v3d->transp && !(ob->dtx & OB_DRAWXRAY) && (ob->dtx & OB_DRAWTRANSP)) {
- ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag);
- return;
- }
- }
- }
- }
-
-
- /* -------------------------------------------------------------------- */
- /* no return after this point, otherwise leaks */
-
- /* only once set now, will be removed too, should become a global standard */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- /* reset here to avoid having to call all over */
- glLineWidth(1.0f);
-
- view3d_cached_text_draw_begin();
-
- /* draw motion paths (in view space) */
- if (ob->mpath && !render_override) {
- bAnimVizSettings *avs = &ob->avs;
-
- /* setup drawing environment for paths */
- draw_motion_paths_init(v3d, ar);
-
- /* draw motion path for object */
- draw_motion_path_instance(scene, ob, NULL, avs, ob->mpath);
-
- /* cleanup after drawing */
- draw_motion_paths_cleanup(v3d);
- }
-
- /* multiply view with object matrix.
- * local viewmat and persmat, to calculate projections */
- ED_view3d_init_mats_rv3d_gl(ob, rv3d);
-
- /* which wire color */
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
-
- ED_view3d_project_base(ar, base);
-
- draw_object_wire_color(scene, base, _ob_wire_col);
- ob_wire_col = _ob_wire_col;
-
- glColor3ubv(ob_wire_col);
- }
-
- /* maximum drawtype */
- char dt = v3d->drawtype;
- if (dt == OB_RENDER) dt = v3d->prev_drawtype;
- dt = MIN2(dt, ob->dt);
- if (v3d->zbuf == 0 && dt > OB_WIRE) dt = OB_WIRE;
- short dtx = 0;
-
-
- /* faceselect exception: also draw solid when (dt == wire), except in editmode */
- if (is_obact) {
- if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) {
- if (ob->type == OB_MESH) {
- if (dt < OB_SOLID) {
- zbufoff = true;
- dt = OB_SOLID;
- }
-
- if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
- dt = OB_PAINT;
- }
-
- is_paint = true;
- glEnable(GL_DEPTH_TEST);
- }
- }
- }
-
- /* matcap check - only when not painting color */
- if ((v3d->flag2 & V3D_SOLID_MATCAP) &&
- (dt == OB_SOLID) &&
- (is_paint == false && is_picking == false) &&
- ((v3d->flag2 & V3D_RENDER_SHADOW) == 0))
- {
- draw_object_matcap_check(v3d, ob);
- }
-
- /* draw-extra supported for boundbox drawmode too */
- if (dt >= OB_BOUNDBOX) {
- dtx = ob->dtx;
- if (ob->mode & OB_MODE_EDIT) {
- /* the only 2 extra drawtypes alowed in editmode */
- dtx = dtx & (OB_DRAWWIRE | OB_TEXSPACE);
- }
- }
-
- if (!skip_object) {
- /* 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(bmain, scene, v3d, ar, base, ob_wire_col);
- }
- }
- }
-
- switch (ob->type) {
- case OB_MESH:
- empty_object = draw_mesh_object(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- /* mesh draws wire itself */
- dtx &= ~OB_DRAWWIRE;
- }
-
- break;
- case OB_FONT:
- cu = ob->data;
- if (cu->editfont) {
- draw_editfont(bmain, scene, 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(bmain, scene, base->object);
-#endif
- draw_bounding_volume(ob, ob->boundtype);
- }
- }
- else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) {
- empty_object = drawDispList(bmain, scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
- }
-
- break;
- case OB_CURVE:
- case OB_SURF:
- cu = ob->data;
-
- if (cu->editnurb) {
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- draw_editnurb(bmain, scene, 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(bmain, scene, base->object);
#endif
- draw_bounding_volume(ob, ob->boundtype);
- }
- }
- else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) {
- empty_object = drawDispList(bmain, scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
- }
- break;
- case OB_MBALL:
- {
- MetaBall *mb = ob->data;
-
- if (mb->editelems)
- drawmball(bmain, scene, 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(bmain, scene, base->object);
-#endif
- draw_bounding_volume(ob, ob->boundtype);
- }
- }
- else
- empty_object = drawmball(bmain, scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
- break;
- }
- case OB_EMPTY:
- if (!render_override) {
- if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
- draw_empty_image(ob, dflag, ob_wire_col, v3d->multiview_eye);
- }
- else {
- drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype);
- }
- }
- break;
- case OB_LAMP:
- if (!render_override) {
- drawlamp(v3d, rv3d, base, dt, dflag, ob_wire_col, is_obact);
- }
- break;
- case OB_CAMERA:
- if (!render_override ||
- (rv3d->persp == RV3D_CAMOB && v3d->camera == ob)) /* special exception for active camera */
- {
- drawcamera(scene, v3d, rv3d, base, dflag, ob_wire_col);
- }
- break;
- case OB_SPEAKER:
- if (!render_override)
- drawspeaker(scene, v3d, rv3d, ob, dflag);
- break;
- case OB_LATTICE:
- if (!render_override) {
- /* Do not allow boundbox in edit nor pose mode! */
- if ((dt == OB_BOUNDBOX) && (ob->mode & OB_MODE_EDIT))
- dt = OB_WIRE;
- if (dt == OB_BOUNDBOX) {
- draw_bounding_volume(ob, ob->boundtype);
- }
- else {
-#ifdef SEQUENCER_DAG_WORKAROUND
- ensure_curve_cache(bmain, scene, ob);
-#endif
- drawlattice(v3d, ob);
- }
- }
- break;
- case OB_ARMATURE:
- if (!render_override) {
- /* Do not allow boundbox in edit nor pose mode! */
- 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);
- }
- else {
- glLineWidth(1.0f);
- empty_object = draw_armature(scene, v3d, ar, base, dt, dflag, ob_wire_col, false);
- }
- }
- break;
- default:
- if (!render_override) {
- drawaxes(rv3d->viewmatob, 1.0, OB_ARROWS);
- }
- break;
- }
-
- if (!render_override) {
- if (ob->soft /*&& dflag & OB_SBMOTION*/) {
- float mrt[3][3], msc[3][3], mtr[3][3];
- SoftBody *sb = NULL;
- float tipw = 0.5f, tiph = 0.5f, drawsize = 4.0f;
- if ((sb = ob->soft)) {
- if (sb->solverflags & SBSO_ESTIMATEIPO) {
-
- glLoadMatrixf(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);
- }
- }
- }
-
- if (ob->pd && ob->pd->forcefield) {
- draw_forcefield(ob, rv3d, dflag, ob_wire_col);
- }
- }
- }
-
- /* code for new particle system */
- if ((ob->particlesystem.first) &&
- (ob != scene->obedit))
- {
- 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);
-
- 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(bmain, scene, ob);
- if (edit && edit->psys == psys)
- draw_update_ptcache_edit(bmain, scene, ob, edit);
- }
-
- draw_new_particle_system(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);
-
- //glDepthMask(GL_TRUE);
- if (col) cpack(col);
- }
-
- /* draw edit particles last so that they can draw over child particles */
- if ((dflag & DRAW_PICKING) == 0 &&
- (!scene->obedit))
- {
-
- if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) {
- PTCacheEdit *edit = PE_create_current(bmain, scene, ob);
- if (edit) {
- glLoadMatrixf(rv3d->viewmat);
- draw_update_ptcache_edit(bmain, scene, ob, edit);
- draw_ptcache_edit(scene, v3d, edit);
- glMultMatrixf(ob->obmat);
- }
- }
- }
-
- /* draw code for smoke, only draw domains */
- if (smd && smd->domain) {
- SmokeDomainSettings *sds = smd->domain;
- float viewnormal[3];
-
- glLoadMatrixf(rv3d->viewmat);
- glMultMatrixf(ob->obmat);
-
- if (!render_override) {
- BoundBox bb;
- float p0[3], p1[3];
-
- /* 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);
- }
-
- /* draw a single voxel to hint the user about the resolution of the fluid */
- copy_v3_v3(p0, sds->p0);
-
- if (sds->flags & MOD_SMOKE_HIGHRES) {
- madd_v3_v3v3fl(p1, p0, sds->cell_size, 1.0f / (sds->amplify + 1));
- }
- else {
- add_v3_v3v3(p1, p0, sds->cell_size);
- }
-
- BKE_boundbox_init_from_minmax(&bb, p0, p1);
- draw_box(bb.vec, false);
- }
-
- /* 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) {
- float p0[3], p1[3];
-
- /* get view vector */
- invert_m4_m4(ob->imat, ob->obmat);
- mul_v3_mat3_m4v3(viewnormal, ob->imat, rv3d->viewinv[2]);
- normalize_v3(viewnormal);
-
- /* set dynamic boundaries to draw the volume
- * also scale cube to global space to equalize volume slicing on all axes
- * (it's scaled back before drawing) */
- p0[0] = (sds->p0[0] + sds->cell_size[0] * sds->res_min[0] + sds->obj_shift_f[0]) * fabsf(ob->size[0]);
- p0[1] = (sds->p0[1] + sds->cell_size[1] * sds->res_min[1] + sds->obj_shift_f[1]) * fabsf(ob->size[1]);
- p0[2] = (sds->p0[2] + sds->cell_size[2] * sds->res_min[2] + sds->obj_shift_f[2]) * fabsf(ob->size[2]);
- p1[0] = (sds->p0[0] + sds->cell_size[0] * sds->res_max[0] + sds->obj_shift_f[0]) * fabsf(ob->size[0]);
- p1[1] = (sds->p0[1] + sds->cell_size[1] * sds->res_max[1] + sds->obj_shift_f[1]) * fabsf(ob->size[1]);
- p1[2] = (sds->p0[2] + sds->cell_size[2] * sds->res_max[2] + sds->obj_shift_f[2]) * fabsf(ob->size[2]);
-
- if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
- sds->tex = NULL;
- GPU_create_smoke(smd, 0);
- draw_smoke_volume(sds, ob, p0, p1, viewnormal);
- GPU_free_smoke(smd);
- }
- else if (sds->wt && (sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
- sds->tex = NULL;
- GPU_create_smoke(smd, 1);
- draw_smoke_volume(sds, ob, p0, p1, viewnormal);
- GPU_free_smoke(smd);
- }
-
- /* smoke debug render */
- if (!render_override && sds->draw_velocity) {
- draw_smoke_velocity(sds, viewnormal);
- }
- }
- }
-
- if (!render_override) {
- bConstraint *con;
-
- for (con = ob->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_RIGIDBODYJOINT) {
- bRigidBodyJointConstraint *data = (bRigidBodyJointConstraint *)con->data;
- if (data->flag & CONSTRAINT_DRAW_PIVOT)
- draw_rigid_body_pivot(data, dflag, ob_wire_col);
- }
- }
-
- 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);
- setlinestyle(0);
- }
- }
- if (ob->rigidbody_object) {
- draw_rigidbody_shape(ob);
- }
-
- /* 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 (dtx & OB_DRAWBOUNDOX) {
- draw_bounding_volume(ob, ob->boundtype);
- }
- if (dtx & OB_TEXSPACE) {
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- /* prevent random colors being used */
- glColor3ubv(ob_wire_col);
- }
- drawtexspace(ob);
- }
- if (dtx & OB_DRAWNAME) {
- /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */
- /* but, we also don't draw names for sets or duplicators */
- if (dflag == 0) {
- const float zero[3] = {0, 0, 0};
- view3d_cached_text_draw_add(zero, ob->id.name + 2, strlen(ob->id.name + 2), 10, 0, ob_wire_col);
- }
- }
- if ((dtx & OB_DRAWWIRE) && dt >= OB_SOLID) {
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- draw_wire_extra(scene, rv3d, ob, ob_wire_col);
- }
- }
- }
- }
-
- if ((dt <= OB_SOLID) && !render_override) {
- if (((ob->gameflag & OB_DYNAMIC) &&
- ((ob->gameflag & OB_BOUNDS) == 0)) ||
-
- ((ob->gameflag & OB_BOUNDS) &&
- (ob->collision_boundtype == OB_BOUND_SPHERE)))
- {
- float imat[4][4], vec[3] = {0.0f, 0.0f, 0.0f};
-
- invert_m4_m4(imat, rv3d->viewmatob);
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- /* prevent random colors being used */
- glColor3ubv(ob_wire_col);
- }
-
- setlinestyle(2);
- drawcircball(GL_LINE_LOOP, vec, ob->inertia, imat);
- setlinestyle(0);
- }
- }
-
- /* return warning, this is cached text draw */
- invert_m4_m4(ob->imat, ob->obmat);
- view3d_cached_text_draw_end(v3d, ar, 1);
- /* return warning, clear temp flag */
- v3d->flag2 &= ~V3D_SHOW_SOLID_MATCAP;
-
- glLoadMatrixf(rv3d->viewmat);
-
- if (zbufoff) {
- glDisable(GL_DEPTH_TEST);
- }
-
- if ((base->flag & OB_FROMDUPLI) || render_override) {
- ED_view3d_clear_mats_rv3d(rv3d);
- return;
- }
-
- /* object centers, need to be drawn in viewmat space for speed, but OK for picking select */
- if (!is_obact || !(ob->mode & OB_MODE_ALL_PAINT)) {
- int do_draw_center = -1; /* defines below are zero or positive... */
-
- if (render_override) {
- /* don't draw */
- }
- else if (is_obact)
- do_draw_center = ACTIVE;
- else if (base->flag & SELECT)
- do_draw_center = SELECT;
- else if (empty_object || (v3d->flag & V3D_DRAW_CENTERS))
- do_draw_center = DESELECT;
-
- if (do_draw_center != -1) {
- if (dflag & DRAW_PICKING) {
- /* draw a single point for opengl selection */
- if ((base->sx != IS_CLIPPED) &&
- (U.obcenter_dia != 0.0))
- {
- glPointSize(U.obcenter_dia);
- glBegin(GL_POINTS);
- glVertex3fv(ob->obmat[3]);
- glEnd();
- }
- }
- else if ((dflag & DRAW_CONSTCOLOR) == 0) {
- /* we don't draw centers for duplicators and sets */
- if ((base->sx != IS_CLIPPED) &&
- (U.obcenter_dia != 0.0) &&
- !(G.f & G_RENDER_OGL))
- {
- /* check > 0 otherwise grease pencil can draw into the circle select which is annoying. */
- drawcentercircle(v3d, rv3d, ob->obmat[3], do_draw_center, ID_IS_LINKED(ob) || ob->id.us > 1);
- }
- }
- }
- }
-
- /* not for sets, duplicators or picking */
- if (dflag == 0 && (v3d->flag & V3D_HIDE_HELPLINES) == 0 && !render_override) {
- ListBase *list;
- RigidBodyCon *rbc = ob->rigidbody_constraint;
-
- /* draw hook center and offset line */
- if (ob != scene->obedit)
- draw_hooks(ob);
-
- /* 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);
- }
-
- /* Drawing the constraint lines */
- if (ob->constraints.first) {
- bConstraint *curcon;
- bConstraintOb *cob;
- unsigned char col1[4], col2[4];
-
- list = &ob->constraints;
-
- UI_GetThemeColor3ubv(TH_GRID, col1);
- UI_make_axis_color(col1, col2, 'Z');
- glColor3ubv(col2);
-
- cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
-
- for (curcon = list->first; curcon; curcon = curcon->next) {
- if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_OBJECTSOLVER)) {
- /* special case for object solver and follow track constraints because they don't fill
- * constraint targets properly (design limitation -- scene is needed for their target
- * but it can't be accessed from get_targets callback) */
-
- Object *camob = NULL;
-
- if (curcon->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
- bFollowTrackConstraint *data = (bFollowTrackConstraint *)curcon->data;
-
- camob = data->camera ? data->camera : scene->camera;
- }
- else if (curcon->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
- bObjectSolverConstraint *data = (bObjectSolverConstraint *)curcon->data;
-
- camob = data->camera ? data->camera : scene->camera;
- }
-
- if (camob) {
- setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(camob->obmat[3]);
- glVertex3fv(ob->obmat[3]);
- glEnd();
- setlinestyle(0);
- }
- }
- else {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon);
-
- if ((cti && cti->get_constraint_targets) && (curcon->flag & CONSTRAINT_EXPAND)) {
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- cti->get_constraint_targets(curcon, &targets);
-
- 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));
- else
- unit_m4(ct->matrix);
-
- setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(ct->matrix[3]);
- glVertex3fv(ob->obmat[3]);
- glEnd();
- setlinestyle(0);
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(curcon, &targets, 1);
- }
- }
- }
-
- BKE_constraints_clear_evalob(cob);
- }
- /* draw rigid body constraint lines */
- if (rbc) {
- UI_ThemeColor(TH_WIRE);
- setlinestyle(3);
- glBegin(GL_LINES);
- if (rbc->ob1) {
- glVertex3fv(ob->obmat[3]);
- glVertex3fv(rbc->ob1->obmat[3]);
- }
- if (rbc->ob2) {
- glVertex3fv(ob->obmat[3]);
- glVertex3fv(rbc->ob2->obmat[3]);
- }
- glEnd();
- setlinestyle(0);
- }
- }
-
- ED_view3d_clear_mats_rv3d(rv3d);
-}
-
-
-/**
- * Drawing for selection picking,
- * caller must have called 'GPU_select_load_id(base->selcode)' first.
- */
-void draw_object_select(Main *bmain, Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag)
-{
- BLI_assert(dflag & DRAW_PICKING && dflag & DRAW_CONSTCOLOR);
- draw_object(bmain, scene, ar, v3d, base, dflag);
-
- /* we draw duplicators for selection too */
- if ((base->object->transflag & OB_DUPLI)) {
- ListBase *lb;
- DupliObject *dob;
- Base tbase;
-
- tbase.flag = OB_FROMDUPLI;
- lb = object_duplilist(bmain, bmain->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);
- copy_m4_m4(dob->ob->obmat, dob->mat);
-
- /* 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;
-
- draw_object(bmain, scene, ar, v3d, &tbase, dflag);
-
- tbase.object->dt = dt;
- tbase.object->dtx = dtx;
-
- copy_m4_m4(dob->ob->obmat, omat);
- }
- free_object_duplilist(lb);
- }
-}
-
-/* ***************** BACKBUF SEL (BBS) ********* */
-
-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]))
-{
- drawMVertOffset_userData *data = userData;
- MVert *mv = &data->mvert[index];
-
- if (!(mv->flag & ME_HIDE)) {
- GPU_select_index_set(data->offset + index);
- glVertex3fv(co);
- }
-}
-
-static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *dm, int offset)
-{
- drawMVertOffset_userData data;
- Mesh *me = ob->data;
- MVert *mvert = me->mvert;
- data.mvert = mvert;
- data.offset = offset;
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- glBegin(GL_POINTS);
- dm->foreachMappedVert(dm, bbs_obmode_mesh_verts__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
-}
-
-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]))
-{
- drawBMOffset_userData *data = userData;
- 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);
- }
-}
-static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset)
-{
- drawBMOffset_userData data = {em->bm, offset};
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- glBegin(GL_POINTS);
- dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
-}
-
-static DMDrawOption bbs_mesh_wire__setDrawOptions(void *userData, int index)
-{
- 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;
- }
-}
-static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
-{
- drawBMOffset_userData data = {em->bm, offset};
- glLineWidth(1);
- dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, &data);
-}
-
-/**
- * dont set #GPU_framebuffer_index_set. just use to mask other
- */
-static DMDrawOption bbs_mesh_mask__setSolidDrawOptions(void *userData, int index)
-{
- BMFace *efa = BM_face_at_index(userData, index);
-
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- return DM_DRAW_OPTION_NORMAL;
- }
- else {
- return DM_DRAW_OPTION_SKIP;
- }
-}
-
-static DMDrawOption bbs_mesh_solid__setSolidDrawOptions(void *userData, int index)
-{
- BMFace *efa = BM_face_at_index(userData, index);
-
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- GPU_select_index_set(index + 1);
- return DM_DRAW_OPTION_NORMAL;
- }
- else {
- return DM_DRAW_OPTION_SKIP;
- }
-}
-
-static void bbs_mesh_solid__drawCenter(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
-{
- 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);
- }
-}
/* 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);
- }
-}
-
-static DMDrawOption bbs_mesh_solid__setDrawOpts(void *UNUSED(userData), int index)
-{
- GPU_select_index_set(index + 1);
- return DM_DRAW_OPTION_NORMAL;
-}
-
-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 {
- return DM_DRAW_OPTION_SKIP;
+ bbs_mesh_face(em, dm, false);
}
}
+#ifdef USE_MESH_DM_SELECT
/* must have called GPU_framebuffer_index_set beforehand */
static DMDrawOption bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index)
{
@@ -8374,11 +551,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(Depsgraph *depsgraph, 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(depsgraph, scene, ob, scene->customdata_mask);
DM_update_materials(dm, ob);
@@ -8394,29 +570,56 @@ 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(Depsgraph *UNUSED(depsgraph), Scene *UNUSED(scene), Object *ob)
{
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
Mesh *me = ob->data;
- glColor3ub(0, 0, 0);
+ /* 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;
- DM_update_materials(dm, ob);
+ {
+ 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_1ui(batch, "color", selcol);
+ GWN_batch_draw(batch);
+ }
- 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);
+ G.f |= (G_f_orig & G_BACKBUFSEL);
- dm->release(dm);
+ 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 *UNUSED(scene), Object *ob)
+{
+ Mesh *me = ob->data;
+ 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(
+ Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob,
+ short select_mode)
{
ToolSettings *ts = scene->toolsettings;
+ if (select_mode == -1) {
+ select_mode = ts->selectmode;
+ }
- glMultMatrixf(ob->obmat);
+ gpuMultMatrix(ob->obmat);
glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
@@ -8427,14 +630,14 @@ 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(depsgraph, scene, ob, em, CD_MASK_BAREMESH);
BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
DM_update_materials(dm, ob);
- bbs_mesh_solid_EM(em, scene, v3d, ob, dm, (ts->selectmode & SCE_SELECT_FACE) != 0);
- if (ts->selectmode & SCE_SELECT_FACE)
+ bbs_mesh_solid_EM(em, scene, v3d, ob, dm, (select_mode & SCE_SELECT_FACE) != 0);
+ if (select_mode & SCE_SELECT_FACE)
bm_solidoffs = 1 + em->bm->totface;
else {
bm_solidoffs = 1;
@@ -8443,7 +646,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
ED_view3d_polygon_offset(rv3d, 1.0);
/* we draw edges if edge select mode */
- if (ts->selectmode & SCE_SELECT_EDGE) {
+ if (select_mode & SCE_SELECT_EDGE) {
bbs_mesh_wire(em, dm, bm_solidoffs);
bm_wireoffs = bm_solidoffs + em->bm->totedge;
}
@@ -8453,7 +656,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
}
/* we draw verts if vert select mode. */
- if (ts->selectmode & SCE_SELECT_VERTEX) {
+ if (select_mode & SCE_SELECT_VERTEX) {
bbs_mesh_verts(em, dm, bm_wireoffs);
bm_vertoffs = bm_wireoffs + em->bm->totvert;
}
@@ -8471,7 +674,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(depsgraph, scene, ob);
}
else {
bbs_mesh_solid_faces(scene, ob);
@@ -8483,77 +686,134 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
break;
}
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix(rv3d->viewmat);
}
-/* ************* draw object instances for bones, for example ****************** */
-/* 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)
+void ED_draw_object_facemap(
+ Depsgraph *depsgraph, Scene *scene, Object *ob, const float col[4], const int facemap)
{
- Mesh *me = ob->data;
- DerivedMesh *dm = NULL, *edm = NULL;
+ DerivedMesh *dm = NULL;
- if (ob->mode & OB_MODE_EDIT) {
- edm = editbmesh_get_derived_base(ob, me->edit_btmesh, CD_MASK_BAREMESH);
- DM_update_materials(edm, ob);
- }
- else {
- dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
- DM_update_materials(dm, ob);
+ /* 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;
}
- if (dt <= OB_WIRE) {
- if (dm)
- dm->drawEdges(dm, 1, 0);
- else if (edm)
- edm->drawEdges(edm, 1, 0);
+ dm = mesh_get_derived_final(depsgraph, 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);
}
- else {
- if (outline)
- draw_mesh_object_outline(v3d, ob, dm ? dm : edm);
+ gpuPopAttrib();
- if (dm) {
- bool glsl = draw_glsl_material(scene, ob, v3d, dt);
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
- }
+ GPU_buffers_unbind();
+
+ glPolygonOffset(0.0, 0.0);
- glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
+#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);
- if (dm) {
- dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind);
- GPU_end_object_materials();
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(col);
+
+ /* XXX, alpha isn't working yet, not sure why. */
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, 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 if (edm)
- edm->drawMappedFaces(edm, NULL, GPU_object_material_bind, NULL, NULL, DM_DRAW_NEED_NORMALS);
+ else {
+ mvert = me->mvert;
+ mpoly = me->mpoly;
+ mloop = me->mloop;
- GPU_object_material_unbind();
- }
+ mpoly_len = me->totpoly;
+ mloop_len = me->totloop;
- if (edm) edm->release(edm);
- if (dm) dm->release(dm);
-}
+ facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP);
+ }
-void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline)
-{
- if (ob == NULL)
- return;
+ /* 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);
- switch (ob->type) {
- case OB_MESH:
- draw_object_mesh_instance(scene, v3d, rv3d, ob, dt, outline);
- 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);
- }
- else {
- drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype);
+ 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++;
+ }
}
- break;
+ }
+ 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
deleted file mode 100644
index 9165147736a..00000000000
--- a/source/blender/editors/space_view3d/drawsimdebug.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * ***** 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) 2014 by the Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Lukas Toenne
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/space_view3d/drawsimdebug.c
- * \ingroup spview3d
- */
-
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_view3d_types.h"
-#include "DNA_object_types.h"
-
-#include "BLI_math.h"
-#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
-
-#include "BKE_effect.h"
-
-#include "view3d_intern.h"
-
-#include "BIF_gl.h"
-
-
-static void draw_sim_debug_elements(SimDebugData *debug_data, float imat[4][4])
-{
- GHashIterator iter;
-
- /**** dots ****/
-
- glPointSize(3.0f);
- glBegin(GL_POINTS);
- 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]);
- }
- glEnd();
-
- /**** circles ****/
-
- {
- float circle[16][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} };
- 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];
- 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);
-
- glVertex3f(co[0], co[1], co[2]);
- }
- glEnd();
- }
- }
-
- /**** lines ****/
-
- glBegin(GL_LINES);
- 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]);
- }
- glEnd();
-
- /**** vectors ****/
-
- glPointSize(2.0f);
- glBegin(GL_POINTS);
- 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]);
- }
- glEnd();
-
- glBegin(GL_LINES);
- 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]);
- add_v3_v3v3(t, elem->v1, elem->v2);
- glVertex3f(t[0], t[1], t[2]);
- }
- glEnd();
-
- /**** strings ****/
-
- 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_STRING)
- continue;
-
- unsigned char col[4];
- rgb_float_to_uchar(col, elem->color);
- col[3] = 255;
- view3d_cached_text_draw_add(elem->v1, elem->str, strlen(elem->str),
- 0, V3D_CACHE_TEXT_GLOBALSPACE, col);
- }
-}
-
-void draw_sim_debug_data(Scene *UNUSED(scene), View3D *v3d, ARegion *ar)
-{
- RegionView3D *rv3d = ar->regiondata;
- /*Object *ob = base->object;*/
- float imat[4][4];
-
- if (!_sim_debug_data)
- return;
-
- invert_m4_m4(imat, rv3d->viewmatob);
-
-// glDepthMask(GL_FALSE);
-// glEnable(GL_BLEND);
-
- glPushMatrix();
- glLoadMatrixf(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);
-}
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index cf118404183..3b648e3b13a 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"
@@ -129,7 +128,7 @@ static GPUTexture *create_transfer_function(int type, const ColorBand *coba)
break;
}
- GPUTexture *tex = GPU_texture_create_1D(TFUNC_WIDTH, data, NULL);
+ GPUTexture *tex = GPU_texture_create_1D(TFUNC_WIDTH, GPU_RGBA8, data, NULL);
MEM_freeN(data);
@@ -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(sds->res[0], sds->res[1], sds->res[2], 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 833d54efd75..4f960959abf 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -43,31 +43,40 @@
#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 "GPU_viewport.h"
+#include "GPU_matrix.h"
-#include "BIF_gl.h"
+#include "DRW_engine.h"
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
#include "RE_engine.h"
#include "RE_pipeline.h"
#include "RNA_access.h"
+#include "UI_interface.h"
#include "UI_resources.h"
#ifdef WITH_PYTHON
@@ -106,17 +115,17 @@ ARegion *view3d_has_buttons_region(ScrArea *sa)
ARegion *view3d_has_tools_region(ScrArea *sa)
{
- ARegion *ar, *artool = NULL, *arprops = NULL, *arhead;
+ ARegion *ar, *artool = NULL, *arhead;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->regiontype == RGN_TYPE_TOOLS)
artool = ar;
- if (ar->regiontype == RGN_TYPE_TOOL_PROPS)
- arprops = ar;
}
/* tool region hide/unhide also hides props */
- if (arprops && artool) return artool;
+ if (artool) {
+ return artool;
+ }
if (artool == NULL) {
/* add subdiv level; after header */
@@ -135,15 +144,6 @@ ARegion *view3d_has_tools_region(ScrArea *sa)
artool->flag = RGN_FLAG_HIDDEN;
}
- if (arprops == NULL) {
- /* add extra subdivided region for tool properties */
- arprops = MEM_callocN(sizeof(ARegion), "tool props for view3d");
-
- BLI_insertlinkafter(&sa->regionbase, artool, arprops);
- arprops->regiontype = RGN_TYPE_TOOL_PROPS;
- arprops->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
- }
-
return artool;
}
@@ -250,7 +250,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
@@ -283,8 +283,6 @@ void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
BPy_END_ALLOW_THREADS;
#endif
- if (rv3d->render_engine->re)
- RE_Database_Free(rv3d->render_engine->re);
RE_engine_free(rv3d->render_engine);
rv3d->render_engine = NULL;
}
@@ -298,17 +296,18 @@ void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
ARegion *ar;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiondata)
+ if ((ar->regiontype == RGN_TYPE_WINDOW) && ar->regiondata) {
ED_view3d_stop_render_preview(wm, ar);
+ break;
+ }
}
}
}
/* ******************** default callbacks for view3d space ***************** */
-static SpaceLink *view3d_new(const bContext *C)
+static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
{
- Scene *scene = CTX_data_scene(C);
ARegion *ar;
View3D *v3d;
RegionView3D *rv3d;
@@ -325,19 +324,31 @@ static SpaceLink *view3d_new(const bContext *C)
v3d->gridlines = 16;
v3d->gridsubdiv = 10;
v3d->drawtype = OB_SOLID;
+ v3d->shading.flag = V3D_SHADING_SPECULAR_HIGHLIGHT;
+ v3d->shading.light = V3D_LIGHTING_STUDIO;
+ v3d->shading.shadow_intensity = 0.5f;
+ v3d->shading.xray_alpha = 0.5f;
+ v3d->shading.cavity_valley_factor = 1.0f;
+ v3d->shading.cavity_ridge_factor = 1.0f;
+ copy_v3_fl(v3d->shading.single_color, 0.8f);
+
+ v3d->overlay.flag = V3D_OVERLAY_LOOK_DEV;
+ v3d->overlay.wireframe_threshold = 0.5f;
+ v3d->overlay.bone_selection_alpha = 0.5f;
+ v3d->overlay.texture_paint_mode_opacity = 0.8;
+ v3d->overlay.weight_paint_mode_opacity = 0.8;
+ v3d->overlay.vertex_paint_mode_opacity = 0.8;
v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR;
v3d->flag = V3D_SELECT_OUTLINE;
v3d->flag2 = V3D_SHOW_RECONSTRUCTION | V3D_SHOW_GPENCIL;
- v3d->lens = 35.0f;
+ v3d->lens = 50.0f;
v3d->near = 0.01f;
v3d->far = 1000.0f;
- v3d->twflag |= U.tw_flag & V3D_USE_MANIPULATOR;
- v3d->twtype = V3D_MANIP_TRANSLATE;
- v3d->around = V3D_AROUND_CENTER_MEAN;
+ v3d->twflag |= U.manipulator_flag & V3D_MANIPULATOR_DRAW;
v3d->bundle_size = 0.2f;
v3d->bundle_drawtype = OB_PLAINAXES;
@@ -353,7 +364,7 @@ static SpaceLink *view3d_new(const bContext *C)
BLI_addtail(&v3d->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
+ ar->alignment = RGN_ALIGN_TOP;
/* tool shelf */
ar = MEM_callocN(sizeof(ARegion), "toolshelf for view3d");
@@ -363,14 +374,6 @@ static SpaceLink *view3d_new(const bContext *C)
ar->alignment = RGN_ALIGN_LEFT;
ar->flag = RGN_FLAG_HIDDEN;
- /* tool properties */
- ar = MEM_callocN(sizeof(ARegion), "tool properties for view3d");
-
- BLI_addtail(&v3d->regionbase, ar);
- ar->regiontype = RGN_TYPE_TOOL_PROPS;
- ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
- ar->flag = RGN_FLAG_HIDDEN;
-
/* buttons/list view */
ar = MEM_callocN(sizeof(ARegion), "buttons for view3d");
@@ -399,30 +402,11 @@ 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);
if (vd->properties_storage) MEM_freeN(vd->properties_storage);
- /* matcap material, its preview rect gets freed via icons */
- if (vd->defmaterial) {
- if (vd->defmaterial->gpumaterial.first)
- GPU_material_free(&vd->defmaterial->gpumaterial);
- BKE_previewimg_free(&vd->defmaterial->preview);
- MEM_freeN(vd->defmaterial);
- }
-
if (vd->fx_settings.ssao)
MEM_freeN(vd->fx_settings.ssao);
if (vd->fx_settings.dof)
@@ -440,7 +424,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
{
View3D *v3do = (View3D *)sl;
View3D *v3dn = MEM_dupallocN(sl);
- BGpic *bgpic;
/* clear or remove stuff from old */
@@ -455,18 +438,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
/* copy or clear inside new stuff */
- 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);
@@ -482,6 +453,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 */
@@ -572,11 +550,6 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
GPU_offscreen_free(rv3d->gpuoffscreen);
rv3d->gpuoffscreen = NULL;
}
-
- if (rv3d->compositor) {
- GPU_fx_compositor_destroy(rv3d->compositor);
- rv3d->compositor = NULL;
- }
}
static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
@@ -589,7 +562,7 @@ static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
return 0;
}
-static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static int view3d_collection_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
ID *id = drag->poin;
@@ -664,7 +637,7 @@ static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
RNA_string_set(drop->ptr, "name", id->name + 2);
}
-static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = drag->poin;
@@ -704,9 +677,32 @@ static void view3d_dropboxes(void)
WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_mesh_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
- WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
+ WM_dropbox_add(lb, "OBJECT_OT_collection_instance_add", view3d_collection_drop_poll, view3d_collection_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, 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(TRANSFORM_WGT_manipulator);
+ WM_manipulatorgrouptype_append(VIEW3D_WGT_xform_cage);
+
+ WM_manipulatorgrouptype_append(VIEW3D_WGT_ruler);
+ WM_manipulatortype_append(VIEW3D_WT_ruler_item);
+
+ WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_navigate);
+ WM_manipulatortype_append(VIEW3D_WT_navigate_rotate);
+}
/* type callback, not region itself */
@@ -731,9 +727,6 @@ static void view3d_main_region_free(ARegion *ar)
if (rv3d->gpuoffscreen) {
GPU_offscreen_free(rv3d->gpuoffscreen);
}
- if (rv3d->compositor) {
- GPU_fx_compositor_destroy(rv3d->compositor);
- }
MEM_freeN(rv3d);
ar->regiondata = NULL;
@@ -757,33 +750,21 @@ static void *view3d_main_region_duplicate(void *poin)
new->render_engine = NULL;
new->sms = NULL;
new->smooth_timer = NULL;
- new->compositor = 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;
@@ -794,13 +775,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:
@@ -820,21 +809,31 @@ 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:
+ 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 */
@@ -842,7 +841,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);
}
@@ -867,6 +865,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) {
@@ -877,9 +876,13 @@ 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);
+ ATTR_FALLTHROUGH;
+ }
case ND_DATA:
case ND_VERTEX_GROUP:
- case ND_SELECT:
ED_region_tag_redraw(ar);
break;
}
@@ -894,7 +897,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);
}
@@ -923,21 +925,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);
@@ -949,20 +943,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;
@@ -982,10 +979,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:
@@ -998,15 +995,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;
}
@@ -1020,12 +1015,118 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
}
}
+static void view3d_main_region_message_subscribe(
+ const struct bContext *C,
+ struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
+ struct bScreen *UNUSED(screen), struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ /* Developer note: there are many properties that impact 3D view drawing,
+ * so instead of subscribing to individual properties, just subscribe to types
+ * accepting some redundant redraws.
+ *
+ * For other space types we might try avoid this, keep the 3D view as an exceptional case! */
+ wmMsgParams_RNA msg_key_params = {{{0}}};
+
+ /* Only subscribe to types. */
+ StructRNA *type_array[] = {
+ &RNA_Window,
+
+ /* These object have properties that impact drawing. */
+ &RNA_AreaLamp,
+ &RNA_Camera,
+ &RNA_Lamp,
+ &RNA_Speaker,
+ &RNA_SunLamp,
+
+ /* General types the 3D view depends on. */
+ &RNA_Object,
+ &RNA_UnitSettings, /* grid-floor */
+
+ &RNA_View3DOverlay,
+ &RNA_View3DShading,
+ &RNA_World,
+ };
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
+ msg_key_params.ptr.type = type_array[i];
+ WM_msg_subscribe_rna_params(
+ mbus,
+ &msg_key_params,
+ &msg_sub_value_region_tag_redraw,
+ __func__);
+ }
+
+ /* Subscribe to a handful of other properties. */
+ RegionView3D *rv3d = ar->regiondata;
+
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, engine, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_region_tag_redraw);
+ if (rv3d->persp == RV3D_CAMOB) {
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, use_border, &msg_sub_value_region_tag_redraw);
+ }
+
+ WM_msg_subscribe_rna_anon_type(mbus, SceneEEVEE, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_type(mbus, SceneDisplay, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_type(mbus, ObjectDisplay, &msg_sub_value_region_tag_redraw);
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obact = OBACT(view_layer);
+ if (obact != NULL) {
+ switch (obact->mode) {
+ case OB_MODE_PARTICLE_EDIT:
+ WM_msg_subscribe_rna_anon_type(mbus, ParticleEdit, &msg_sub_value_region_tag_redraw);
+ break;
+ default:
+ break;
+ }
+ }
+
+ {
+ wmMsgSubscribeValue msg_sub_value_region_tag_refresh = {
+ .owner = ar,
+ .user_data = sa,
+ .notify = WM_toolsystem_do_msg_notify_tag_refresh,
+ };
+ WM_msg_subscribe_rna_anon_prop(
+ mbus, Object, mode,
+ &msg_sub_value_region_tag_refresh);
+ }
+}
+
+static void view3d_tools_region_message_subscribe(
+ const struct bContext *UNUSED(C),
+ struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
+ struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+ WM_msg_subscribe_rna_anon_prop(mbus, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
+}
+
/* concept is to retrieve cursor type context-less */
-static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
+static void view3d_main_region_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
{
- Scene *scene = win->screen->scene;
+ if (WM_cursor_set_from_tool(win, sa, ar)) {
+ return;
+ }
- if (scene->obedit) {
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+ if (obedit) {
WM_cursor_set(win, CURSOR_EDIT);
}
else {
@@ -1048,7 +1149,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) {
@@ -1078,6 +1181,36 @@ static void view3d_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(s
}
}
+static void view3d_header_region_message_subscribe(
+ const struct bContext *UNUSED(C),
+ struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
+ struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ wmMsgParams_RNA msg_key_params = {{{0}}};
+
+ /* Only subscribe to types. */
+ StructRNA *type_array[] = {
+ &RNA_View3DShading,
+ };
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
+ msg_key_params.ptr.type = type_array[i];
+ WM_msg_subscribe_rna_params(
+ mbus,
+ &msg_key_params,
+ &msg_sub_value_region_tag_redraw,
+ __func__);
+ }
+}
+
+
/* add handlers, stuff you only do once or on area/region changes */
static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar)
{
@@ -1091,10 +1224,12 @@ static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar)
static void view3d_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
-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) {
@@ -1184,6 +1319,27 @@ static void view3d_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(
}
}
+static int view3d_tools_region_snap_size(const ARegion *ar, int size, int axis)
+{
+ if (axis == 0) {
+ /* Note, this depends on the icon size: see #ICON_DEFAULT_HEIGHT_TOOLBAR. */
+ const float snap_units[] = {2 + 0.8f, 4 + 0.8f};
+ const float aspect = BLI_rctf_size_x(&ar->v2d.cur) / (BLI_rcti_size_x(&ar->v2d.mask) + 1);
+ int best_diff = INT_MAX;
+ int best_size = size;
+ for (uint i = 0; i < ARRAY_SIZE(snap_units); i += 1) {
+ const int test_size = (snap_units[i] * U.widget_unit) / (UI_DPI_FAC * aspect);
+ const int test_diff = ABS(test_size - size);
+ if (test_diff < best_diff) {
+ best_size = test_size;
+ best_diff = test_diff;
+ }
+ }
+ return best_size;
+ }
+ return size;
+}
+
/* add handlers, stuff you only do once or on area/region changes */
static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar)
{
@@ -1197,30 +1353,13 @@ static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar)
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)
-{
- /* context changes */
- switch (wmn->category) {
- case NC_WM:
- if (wmn->data == ND_HISTORY)
- ED_region_tag_redraw(ar);
- break;
- case NC_SCENE:
- if (wmn->data == ND_MODE)
- ED_region_tag_redraw(ar);
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_VIEW3D)
- ED_region_tag_redraw(ar);
- break;
- }
+ ED_region_panels_ex(C, ar, (const char * []){CTX_data_mode_string(C), NULL}, -1, true);
}
/* 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;
@@ -1255,8 +1394,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
};
@@ -1267,109 +1404,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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ if (view_layer->basact) {
+ Object *ob = view_layer->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 ((view_layer->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT)) {
+ CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ if (view_layer->basact) {
+ Object *ob = view_layer->basact->object;
+ /* if hidden but in edit mode, we still display, can happen with animation */
+ if ((view_layer->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) {
+ CTX_data_id_pointer_set(result, &ob->id);
+ }
}
return 1;
@@ -1410,8 +1465,6 @@ static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_i
/* Values in local-view aren't used, see: T52663 */
if (is_local == false) {
- /* Skip 'v3d->defmaterial', it's not library data. */
-
if ((ID *)v3d->ob_centre == old_id) {
v3d->ob_centre = (Object *)new_id;
/* Otherwise, bonename may remain valid... We could be smart and check this, too? */
@@ -1419,21 +1472,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) {
@@ -1459,6 +1497,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;
@@ -1472,6 +1511,7 @@ void ED_spacetype_view3d(void)
art->free = view3d_main_region_free;
art->duplicate = view3d_main_region_duplicate;
art->listener = view3d_main_region_listener;
+ art->message_subscribe = view3d_main_region_message_subscribe;
art->cursor = view3d_main_region_cursor;
art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */
BLI_addhead(&st->regiontypes, art);
@@ -1495,29 +1535,12 @@ void ED_spacetype_view3d(void)
art->prefsizey = 50; /* XXX */
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = view3d_buttons_region_listener;
+ art->message_subscribe = view3d_tools_region_message_subscribe;
+ art->snap_size = view3d_tools_region_snap_size;
art->init = view3d_tools_region_init;
art->draw = view3d_tools_region_draw;
BLI_addhead(&st->regiontypes, art);
-#if 0
- /* unfinished still */
- view3d_toolshelf_register(art);
-#endif
-
- /* regions: tool properties */
- art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tool properties region");
- art->regionid = RGN_TYPE_TOOL_PROPS;
- art->prefsizex = 0;
- art->prefsizey = 120;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
- art->listener = view3d_props_region_listener;
- art->init = view3d_tools_region_init;
- art->draw = view3d_tools_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- view3d_tool_props_register(art);
-
-
/* regions: header */
art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region");
art->regionid = RGN_TYPE_HEADER;
@@ -1526,8 +1549,12 @@ void ED_spacetype_view3d(void)
art->listener = view3d_header_region_listener;
art->init = view3d_header_region_init;
art->draw = view3d_header_region_draw;
+ art->message_subscribe = view3d_header_region_message_subscribe;
+ BLI_addhead(&st->regiontypes, art);
+
+ /* regions: hud */
+ art = ED_area_type_hud(st->spaceid);
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
}
-
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index fbbc5bd7bb9..6ebed88728e 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -55,19 +55,21 @@
#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"
#include "RNA_access.h"
#include "ED_armature.h"
+#include "ED_object.h"
#include "ED_mesh.h"
#include "ED_screen.h"
@@ -776,18 +778,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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = view_layer->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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
if (ob && (BKE_object_is_in_editmode_vgroup(ob) ||
BKE_object_is_in_wpaint_select_vert(ob)))
{
@@ -805,7 +807,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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = view_layer->basact->object;
MDeformVert *dv;
@@ -1095,9 +1098,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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C);
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
switch (event) {
@@ -1108,7 +1111,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 +1122,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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ return (view_layer->basact != NULL);
}
static void view3d_panel_transform(const bContext *C, Panel *pa)
{
uiBlock *block;
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *obedit = CTX_data_edit_object(C);
- Object *ob = scene->basact->object;
+ Object *ob = view_layer->basact->object;
uiLayout *col;
block = uiLayoutGetBlock(pa->layout);
@@ -1160,6 +1164,11 @@ static void view3d_panel_transform(const bContext *C, Panel *pa)
}
}
+static void hide_collections_menu_draw(const bContext *C, Menu *menu)
+{
+ ED_hide_collections_menu_draw(C, menu->layout);
+}
+
void view3d_buttons_register(ARegionType *art)
{
PanelType *pt;
@@ -1179,6 +1188,15 @@ void view3d_buttons_register(ARegionType *art)
pt->draw = view3d_panel_vgroup;
pt->poll = view3d_panel_vgroup_poll;
BLI_addtail(&art->paneltypes, pt);
+
+ MenuType *mt;
+
+ mt = MEM_callocN(sizeof(MenuType), "spacetype view3d menu collections");
+ strcpy(mt->idname, "VIEW3D_MT_collection");
+ strcpy(mt->label, N_("Collection"));
+ strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ mt->draw = hide_collections_menu_draw;
+ WM_menutype_add(mt);
}
static int view3d_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
@@ -1194,7 +1212,7 @@ static int view3d_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void VIEW3D_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ ot->name = "Toggle Sidebar";
ot->description = "Toggle the properties region visibility";
ot->idname = "VIEW3D_OT_properties";
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
index e27b3fe13f9..d0475684262 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,7 +138,7 @@ 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,
+ Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d,
const bool use_parent_root)
{
View3DCameraControl *vctrl;
@@ -177,7 +178,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(depsgraph, scene, v3d->camera);
negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]);
rv3d->dist = 0.0;
@@ -242,7 +243,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 +265,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 +300,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 +312,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 fbf2bd33638..964317f695e 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -28,958 +28,286 @@
* \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_2d.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_2d.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_batch.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_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);
+#include "GPU_viewport.h"
- 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);
- }
-}
-
-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);
- }
-}
-
-/* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */
-void ED_view3d_clipping_disable(void)
-{
- unsigned int a;
-
- for (a = 0; a < 6; a++) {
- glDisable(GL_CLIP_PLANE0 + a);
- }
-}
-void ED_view3d_clipping_enable(void)
-{
- unsigned int a;
-
- for (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 drawgrid_draw(ARegion *ar, double wx, double wy, double x, double y, double dx)
-{
- double verts[2][2];
-
- x += (wx);
- y += (wy);
+#include "MEM_guardedalloc.h"
- /* set fixed 'Y' */
- verts[0][1] = 0.0f;
- verts[1][1] = (double)ar->winy;
+#include "UI_interface.h"
+#include "UI_resources.h"
- /* iter over 'X' */
- verts[0][0] = verts[1][0] = x - dx * floor(x / dx);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_DOUBLE, 0, verts);
+#include "RE_engine.h"
- while (verts[0][0] < ar->winx) {
- glDrawArrays(GL_LINES, 0, 2);
- verts[0][0] = verts[1][0] = verts[0][0] + dx;
- }
+#include "WM_api.h"
+#include "WM_types.h"
- /* set fixed 'X' */
- verts[0][0] = 0.0f;
- verts[1][0] = (double)ar->winx;
+#include "RNA_access.h"
- /* 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;
- }
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
- glDisableClientState(GL_VERTEX_ARRAY);
-}
+#include "view3d_intern.h" /* own include */
-#define GRID_MIN_PX_D 6.0
-#define GRID_MIN_PX_F 6.0f
+/* ******************** general functions ***************** */
-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(
+ Depsgraph *depsgraph, 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;
-
- /* 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);
-
- /* tweak to have the fade a bit nicer */
- blend_fac = (blend_fac * blend_fac) * 2.0f;
- CLAMP(blend_fac, 0.3f, 1.0f);
-
- UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, blend_fac);
+ /* setup window matrices */
+ if (winmat)
+ copy_m4_m4(rv3d->winmat, winmat);
+ else
+ view3d_winmatrix_set(depsgraph, ar, v3d, rect);
- drawgrid_draw(ar, wx, wy, x, y, dx_scalar);
- }
- }
+ /* setup view matrix */
+ if (viewmat) {
+ copy_m4_m4(rv3d->viewmat, viewmat);
}
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);
- }
+ float rect_scale[2];
+ if (rect) {
+ rect_scale[0] = (float)BLI_rcti_size_x(rect) / (float)ar->winx;
+ rect_scale[1] = (float)BLI_rcti_size_y(rect) / (float)ar->winy;
}
+ /* note: calls BKE_object_where_is_calc for camera... */
+ view3d_viewmatrix_set(depsgraph, scene, v3d, rv3d, rect ? rect_scale : NULL);
}
+ /* 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 */
- 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);
+ /* store window coordinates scaling/offset */
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ rctf cameraborder;
+ ED_view3d_calc_camera_border(scene, depsgraph, 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);
- /* 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);
+ 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;
+ }
- fdrawline(x, 0.0, x, (float)ar->winy);
+ /* 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;
- 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(
+ Depsgraph *depsgraph, 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;
-
- glDrawArrays(GL_LINES, 0, 4);
- }
-
- glDisableClientState(GL_VERTEX_ARRAY);
- }
+ RegionView3D *rv3d = ar->regiondata;
- /* 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();
- }
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect);
- 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;
- }
-
- 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
-}
-
-/* draw info beside axes in bottom left-corner:
- * framenum, object name, bone name (if available), marker name (if available)
+/* 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 draw_selected_name(Scene *scene, Object *ob, const rcti *rect)
+static void view3d_stereo3d_setup(
+ Depsgraph *depsgraph, Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect)
{
- const int cfra = CFRA;
- const char *msg_pin = " (Pinned)";
- const char *msg_sep = " : ";
+ bool is_left;
+ const char *names[2] = { STEREO_LEFT_NAME, STEREO_RIGHT_NAME };
+ const char *viewname;
- char info[300];
- const char *markern;
- char *s = info;
- short offset = 1.5f * UI_UNIT_X + rect->xmin;
+ /* show only left or right camera */
+ if (v3d->stereo3d_camera != STEREO_3D_ID)
+ v3d->multiview_eye = v3d->stereo3d_camera;
- s += sprintf(s, "(%d)", cfra);
+ is_left = v3d->multiview_eye == STEREO_LEFT_ID;
+ viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID];
- /*
- * 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)
- */
+ /* 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;
- /* get name of marker on current frame (if available) */
- markern = BKE_scene_find_marker_name(scene, cfra);
+ data = (Camera *)v3d->camera->data;
+ shiftx = data->shiftx;
- /* check if there is an object */
- if (ob) {
- *s++ = ' ';
- s += BLI_strcpy_rlen(s, ob->id.name + 2);
+ BLI_thread_lock(LOCK_VIEW3D);
+ data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
- /* name(s) to display depends on type of object */
- if (ob->type == OB_ARMATURE) {
- bArmature *arm = ob->data;
+ BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
+ view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, NULL, rect);
- /* 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) {
+ data->shiftx = shiftx;
+ BLI_thread_unlock(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);
- 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;
+ BLI_thread_lock(LOCK_VIEW3D);
+ v3d->camera = camera;
- /* try to display active bone and active shapekey too (if they exist) */
+ BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
+ view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, NULL, rect);
- 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);
- }
- }
- }
- }
+ v3d->camera = view_ob;
+ BLI_thread_unlock(LOCK_VIEW3D);
+ }
+}
- 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));
- }
- }
- }
- }
+/**
+ * Set the correct matrices
+ */
+void ED_view3d_draw_setup_view(
+ wmWindow *win, Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d,
+ float viewmat[4][4], float winmat[4][4], const rcti *rect)
+{
+ RegionView3D *rv3d = ar->regiondata;
- /* 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(depsgraph, 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(depsgraph, 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,
+ const Scene *scene, struct Depsgraph *depsgraph,
+ const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
rctf *r_viewborder, const bool no_shift, const bool no_zoom)
{
CameraParams params;
rctf rect_view, rect_camera;
+ Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
/* get viewport viewplane */
BKE_camera_params_init(&params);
- BKE_camera_params_from_view3d(&params, v3d, rv3d);
+ BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
if (no_zoom)
params.zoom = 1.0f;
BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
@@ -990,7 +318,7 @@ static void view3d_camera_border(
/* fallback for non camera objects */
params.clipsta = v3d->near;
params.clipend = v3d->far;
- BKE_camera_params_from_object(&params, v3d->camera);
+ BKE_camera_params_from_object(&params, camera_eval);
if (no_shift) {
params.shiftx = 0.0f;
params.shifty = 0.0f;
@@ -1006,24 +334,26 @@ static void view3d_camera_border(
}
void ED_view3d_calc_camera_border_size(
- const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
+ const Scene *scene, Depsgraph *depsgraph,
+ const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
float r_size[2])
{
rctf viewborder;
- view3d_camera_border(scene, ar, v3d, rv3d, &viewborder, true, true);
+ view3d_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, true, true);
r_size[0] = BLI_rctf_size_x(&viewborder);
r_size[1] = BLI_rctf_size_y(&viewborder);
}
void ED_view3d_calc_camera_border(
- const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
+ const Scene *scene, Depsgraph *depsgraph,
+ const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
rctf *r_viewborder, const bool no_shift)
{
- view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, no_shift, false);
+ view3d_camera_border(scene, depsgraph, 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 +362,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);
+
+ immVertex2f(shdr_pos, x1, y4);
+ immVertex2f(shdr_pos, x2, y4);
- glVertex2f(x1, y4);
- glVertex2f(x2, y4);
+ immVertex2f(shdr_pos, x3, y1);
+ immVertex2f(shdr_pos, x3, y2);
- glVertex2f(x3, y1);
- glVertex2f(x3, y2);
+ immVertex2f(shdr_pos, x4, y1);
+ immVertex2f(shdr_pos, x4, y2);
- glVertex2f(x4, y1);
- glVertex2f(x4, y2);
- glEnd();
+ 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 +398,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,19 +416,20 @@ 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)
+static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View3D *v3d)
{
float x1, x2, y1, y2;
float x1i, x2i, y1i, y2i;
@@ -1108,7 +443,7 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
if (v3d->camera->type == OB_CAMERA)
ca = v3d->camera->data;
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false);
/* the offsets */
x1 = viewborder.xmin;
y1 = viewborder.ymin;
@@ -1129,56 +464,74 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
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);
+ uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- if (ca->passepartalpha == 1.0f) {
- glColor3f(0, 0, 0);
- }
- else {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
- glColor4f(0, 0, 0, ca->passepartalpha);
- }
+ /* First, solid lines. */
+ {
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- 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);
+ /* 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);
- glDisable(GL_BLEND);
- }
+ float alpha = 1.0f;
- setlinestyle(0);
+ if (ca->passepartalpha != 1.0f) {
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ alpha = ca->passepartalpha;
+ }
+
+ immUniformColor4f(0.0f, 0.0f, 0.0f, alpha);
- UI_ThemeColor(TH_BACK);
+ 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);
- fdrawbox(x1i, y1i, x2i, y2i);
+ glDisable(GL_BLEND);
+ }
+
+ 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) {
- glColor3ubv(view3d_camera_border_hack_col);
- fdrawbox(x1i + 1, y1i + 1, x2i - 1, y2i - 1);
- view3d_camera_border_hack_test = false;
- }
+ 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
- setlinestyle(3);
-
- /* 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);
+ immUnbindProgram();
}
- UI_ThemeColor(TH_VIEW_OVERLAY);
- fdrawbox(x1i, y1i, x2i, y2i);
+ /* And now, the dashed lines! */
+ 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 */
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ /* 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);
+ }
+
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+ imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i);
+ }
/* border */
if (scene->r.mode & R_BORDER) {
@@ -1189,82 +542,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);
+
+ immVertex2f(shdr_pos, x1, y3);
+ immVertex2f(shdr_pos, x2, y3);
- glVertex2f(x3, y1);
- glVertex2f(x3, y2);
- glEnd();
+ 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);
+
+ immVertex2f(shdr_pos, x1, y1);
+ immVertex2f(shdr_pos, x2, y2);
- glBegin(GL_LINES);
- glVertex2f(x1, y1);
- glVertex2f(x2, y2);
+ immVertex2f(shdr_pos, x1, y2);
+ immVertex2f(shdr_pos, x2, y1);
- glVertex2f(x1, y2);
- glVertex2f(x2, y1);
- glEnd();
+ 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,1895 +647,689 @@ 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 backdrawview3d(Scene *scene, wmWindow *win, ARegion *ar, View3D *v3d, Object *obact, Object *obedit)
+static void drawrenderborder(ARegion *ar, View3D *v3d)
{
- RegionView3D *rv3d = ar->regiondata;
- int multisample_enabled;
-
- BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
-
- if (obact && (obact->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
- BKE_paint_select_face_test(obact)))
- {
- /* do nothing */
- }
- /* texture paint mode sampling */
- else if (obact && (obact->mode & OB_MODE_TEXTURE_PAINT) &&
- (v3d->drawtype > OB_WIRE))
- {
- /* do nothing */
- }
- else if ((obact && (obact->mode & OB_MODE_PARTICLE_EDIT)) &&
- V3D_IS_ZBUF(v3d))
- {
- /* do nothing */
- }
- else if (obedit &&
- V3D_IS_ZBUF(v3d))
- {
- /* do nothing */
- }
- else {
- v3d->flag &= ~V3D_INVALID_BACKBUF;
- return;
- }
+ /* use the same program for everything */
+ uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- if (!(v3d->flag & V3D_INVALID_BACKBUF))
- return;
+ glLineWidth(1.0f);
-#if 0
- if (test) {
- if (qtest()) {
- addafterqueue(ar->win, BACKBUFDRAW, 1);
- return;
- }
- }
-#endif
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- if (v3d->drawtype > OB_WIRE) v3d->zbuf = true;
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
- /* dithering and AA break color coding, so disable */
- glDisable(GL_DITHER);
+ 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);
- multisample_enabled = glIsEnabled(GL_MULTISAMPLE);
- if (multisample_enabled)
- glDisable(GL_MULTISAMPLE);
+ 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);
- 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];
+ immUnbindProgram();
+}
- if (rv3d->gpuoffscreen) {
- if (GPU_offscreen_width(rv3d->gpuoffscreen) != w ||
- GPU_offscreen_height(rv3d->gpuoffscreen) != h)
- {
- GPU_offscreen_free(rv3d->gpuoffscreen);
- rv3d->gpuoffscreen = NULL;
- }
- }
+void ED_view3d_draw_depth(
+ Depsgraph *depsgraph,
+ ARegion *ar, View3D *v3d, bool alphaoverride)
+{
+ struct bThemeState theme_state;
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ RegionView3D *rv3d = ar->regiondata;
- if (!rv3d->gpuoffscreen) {
- rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error);
+ 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 (!rv3d->gpuoffscreen)
- fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
- }
- }
+ /* Tools may request depth outside of regular drawing code. */
+ UI_Theme_Store(&theme_state);
+ UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
- 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));
+ ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL);
- 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);
- }
+ glClear(GL_DEPTH_BUFFER_BIT);
- if (rv3d->rflag & RV3D_CLIPPING)
+ if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_set(rv3d);
-
- G.f |= G_BACKBUFSEL;
-
- if (obact && (obact->lay & v3d->lay)) {
- draw_object_backbufsel(scene, v3d, rv3d, obact);
}
+ /* get surface depth without bias */
+ rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
- if (rv3d->gpuoffscreen)
- GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
- else
- ar->swap = 0; /* mark invalid backbuf for wm draw */
-
- v3d->flag &= ~V3D_INVALID_BACKBUF;
+ v3d->zbuf = true;
+ glEnable(GL_DEPTH_TEST);
- G.f &= ~G_BACKBUFSEL;
- v3d->zbuf = false;
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_DITHER);
- if (multisample_enabled)
- glEnable(GL_MULTISAMPLE);
+ DRW_draw_depth_loop(depsgraph, ar, v3d);
- if (rv3d->rflag & RV3D_CLIPPING)
+ 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_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);
- }
-}
+ rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
-/* 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)
-{
+ v3d->zbuf = zbuf;
+ if (!v3d->zbuf) glDisable(GL_DEPTH_TEST);
- glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
-}
+ U.glalphaclip = glalphaclip;
+ v3d->flag = flag;
+ U.obcenter_dia = obcenter_dia;
-void ED_view3d_backbuf_validate(ViewContext *vc)
-{
- if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
- backdrawview3d(vc->scene, vc->win, vc->ar, vc->v3d, vc->obact, vc->obedit);
- }
+ UI_Theme_Restore(&theme_state);
}
-/**
- * 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));
-}
+/* ******************** other elements ***************** */
-/* samples a single pixel (copied from vpaint) */
-unsigned int ED_view3d_backbuf_sample(ViewContext *vc, int x, int y)
+/** could move this elsewhere, but tied into #ED_view3d_grid_scale */
+float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
{
- unsigned int col;
-
- if (x >= vc->ar->winx || y >= vc->ar->winy) {
- return 0;
- }
-
- ED_view3d_backbuf_validate(vc);
+ /* apply units */
+ if (scene->unit.system) {
+ const void *usys;
+ int len;
- view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
- glReadBuffer(GL_BACK);
+ bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
- if (ENDIAN_ORDER == B_ENDIAN) {
- BLI_endian_switch_uint32(&col);
+ 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;
+ }
}
- return GPU_select_to_index(col);
+ return 1.0f;
}
-/* reads full rect, converts indices */
-ImBuf *ED_view3d_backbuf_read(ViewContext *vc, int xmin, int ymin, int xmax, int ymax)
+float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
{
- 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;
- }
+ return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
+}
- ibuf_clip = IMB_allocImBuf(size_clip[0], size_clip[1], 32, IB_rect);
+static void draw_view_axis(RegionView3D *rv3d, const rcti *rect)
+{
+ const float k = U.rvisize * U.pixelsize; /* axis size */
+ const int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */
- ED_view3d_backbuf_validate(vc);
+ /* Axis center in screen coordinates.
+ *
+ * - Unit size offset so small text doesn't draw outside the screen
+ * - Extra X offset because of the panel expander.
+ */
+ const float startx = rect->xmax - (k + UI_UNIT_X * 1.5);
+ const float starty = rect->ymax - (k + UI_UNIT_Y);
- view3d_opengl_read_pixels(vc->ar, clip.xmin, clip.ymin, size_clip[0], size_clip[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf_clip->rect);
+ float axis_pos[3][2];
+ unsigned char axis_col[3][4];
- glReadBuffer(GL_BACK);
+ int axis_order[3] = {0, 1, 2};
+ axis_sort_v3(rv3d->viewinv[2], axis_order);
- if (ENDIAN_ORDER == B_ENDIAN) {
- IMB_convert_rgba_to_abgr(ibuf_clip);
- }
+ for (int axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
- GPU_select_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]);
+ /* 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;
- 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 */
- 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;
+ /* 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 */
}
-}
-
-/**
- * Smart function to sample a rectangle spiral ling outside, nice for backbuf selection
- */
-uint ED_view3d_backbuf_sample_rect(
- ViewContext *vc, const int mval[2], int size,
- unsigned int min, unsigned int max, float *r_dist)
-{
- 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;
-
- amount = (size - 1) / 2;
-
- 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;
-
- 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]);
+ /* draw axis lines */
+ glLineWidth(2.0f);
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- if (tbuf < bufmin || tbuf >= bufmax) {
- goto exit;
- }
- }
- rc++;
- rc &= 3;
- }
- }
+ 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);
-exit:
- IMB_freeImBuf(buf);
- return index;
-}
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GWN_PRIM_LINES, 6);
+ for (int axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
-/* ************************************************************* */
+ immAttrib4ubv(col, axis_col[i]);
+ immVertex2f(pos, startx, starty);
+ immAttrib4ubv(col, axis_col[i]);
+ immVertex2fv(pos, axis_pos[i]);
+ }
-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;
+ immEnd();
+ immUnbindProgram();
+ glDisable(GL_LINE_SMOOTH);
- 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;
- }
+ /* draw axis names */
+ for (int axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
- BKE_image_multiview_index(ima, iuser);
- }
- else {
- iuser->flag &= ~IMA_SHOW_STEREO;
+ 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);
}
}
-static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
- const bool do_foreground, const bool do_camera_frame)
+#ifdef WITH_INPUT_NDOF
+/* draw center and axis of rotation for ongoing 3D mouse navigation */
+static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d)
{
- RegionView3D *rv3d = ar->regiondata;
- BGpic *bgpic;
- int fg_flag = do_foreground ? V3D_BGPIC_FOREGROUND : 0;
-
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- bgpic->iuser.scene = scene; /* Needed for render results. */
-
- if ((bgpic->flag & V3D_BGPIC_FOREGROUND) != fg_flag)
- 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;
- }
-
- 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) */
-
- if (bgpic->flag & V3D_BGPIC_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);
- }
+ float o[3]; /* center of rotation */
+ float end[3]; /* endpoints for drawing */
- if (ibuf == NULL)
- continue;
+ GLubyte color[4] = {0, 108, 255, 255}; /* bright blue so it matches device LEDs */
- 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);
+ negate_v3_v3(o, rv3d->ofs);
- continue;
- }
+ glEnable(GL_BLEND);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glDepthMask(GL_FALSE); /* don't overwrite zbuf */
- if (ibuf->rect == NULL)
- IMB_rect_from_float(ibuf);
+ 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);
- if (rv3d->persp == RV3D_CAMOB) {
+ immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
- 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;
- }
+ 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);
- /* 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;
- }
- centx = (x1 + x2) / 2.0f;
- centy = (y1 + y2) / 2.0f;
+ 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);
- /* 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];
+#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
- /* destination aspect is already applied from the camera frame */
- const float w_dst = x1 - x2;
- const float h_dst = y1 - y2;
+ color[3] = 127; /* more opaque toward the center */
+ immAttrib4ubv(col, color);
+ immVertex3fv(pos, o);
- const float asp_src = w_src / h_src;
- const float asp_dst = w_dst / h_dst;
+ color[3] = 0;
+ immAttrib4ubv(col, color);
+ sub_v3_v3v3(end, o, scaled_axis);
+ immVertex3fv(pos, end);
+ immEnd();
- 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;
- }
+ /* -- draw ring around rotation center -- */
+ {
+#define ROT_AXIS_DETAIL 13
- /* complete clip? */
- BLI_rctf_init(&clip_rect, x1, x2, y1, y2);
- if (bgpic->rotation) {
- BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation);
- }
+ const float s = 0.05f * scale;
+ const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL);
- 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);
+ 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];
- continue;
+ 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);
}
- zoomx = (x2 - x1) / ibuf->x;
- 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;
+ 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 ((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 (!upright) {
+ mul_qt_v3(q, p);
}
- if (mip > 0)
- ibuf = ibuf->mipmap[mip - 1];
- }
-
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
- glDepthMask(0);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- ED_region_pixelspace(ar);
-
- glTranslatef(centx, centy, 0.0);
- glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f);
-
- if (bgpic->flag & V3D_BGPIC_FLIP_X) {
- zoomx *= -1.0f;
- x1 = x2;
- }
- if (bgpic->flag & V3D_BGPIC_FLIP_Y) {
- zoomy *= -1.0f;
- y1 = y2;
+ add_v3_v3(p, o);
+ immVertex3fv(pos, p);
}
- glPixelZoom(zoomx, zoomy);
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend);
-
- /* 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);
-
- glPixelZoom(1.0, 1.0);
- glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ immEnd();
- glDisable(GL_BLEND);
-
- glDepthMask(1);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
-
- if (freeibuf)
- IMB_freeImBuf(freeibuf);
- if (releaseibuf)
- BKE_image_release_ibuf(ima, releaseibuf, lock);
+#undef ROT_AXIS_DETAIL
}
+
+ color[3] = 255; /* solid dot */
}
-}
+ else
+ color[3] = 127; /* see-through dot */
-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;
+ immUnbindProgram();
- if ((v3d->flag & V3D_DISPBGPICS) == 0)
- return;
+ /* -- 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();
- /* 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;
+ /* 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
- 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 & 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(Main *bmain, Scene *scene, ARegion *ar, View3D *v3d)
-{
- View3DAfter *v3da;
-
- glDepthMask(GL_FALSE);
- v3d->transp = true;
-
- while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
- draw_object(bmain, scene, ar, v3d, v3da->base, v3da->dflag);
- MEM_freeN(v3da);
- }
- v3d->transp = false;
-
+ glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
-
-}
-
-/* clears zbuffer and draws it over */
-static void view3d_draw_xray(Main *bmain, Scene *scene, ARegion *ar, View3D *v3d, bool *clear)
-{
- View3DAfter *v3da;
-
- if (*clear && v3d->zbuf) {
- glClear(GL_DEPTH_BUFFER_BIT);
- *clear = false;
- }
-
- v3d->xray = true;
- while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
- draw_object(bmain, scene, ar, v3d, v3da->base, v3da->dflag);
- MEM_freeN(v3da);
- }
- v3d->xray = false;
}
+#endif /* WITH_INPUT_NDOF */
+/* ******************** info ***************** */
-/* clears zbuffer and draws it over */
-static void view3d_draw_xraytransp(Main *bmain, Scene *scene, ARegion *ar, View3D *v3d, const bool clear)
-{
- View3DAfter *v3da;
-
- if (clear && v3d->zbuf)
- glClear(GL_DEPTH_BUFFER_BIT);
-
- v3d->xray = true;
- v3d->transp = true;
-
- glDepthMask(GL_FALSE);
-
- while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
- draw_object(bmain, scene, 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(Main *bmain, Scene *scene, ARegion *ar, View3D *v3d, bool *clear)
+/**
+* Render and camera border
+*/
+static void view3d_draw_border(const bContext *C, ARegion *ar)
{
- /* 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);
- }
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ RegionView3D *rv3d = ar->regiondata;
+ View3D *v3d = CTX_wm_view3d(C);
- View3DAfter *v3da;
- if (*clear && v3d->zbuf) {
- glClear(GL_DEPTH_BUFFER_BIT);
- *clear = false;
+ if (rv3d->persp == RV3D_CAMOB) {
+ drawviewborder(scene, depsgraph, ar, v3d);
}
-
- v3d->xray = true;
- while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
- if (GPU_select_load_id(v3da->base->selcol)) {
- draw_object_select(bmain, scene, ar, v3d, v3da->base, v3da->dflag);
- }
- MEM_freeN(v3da);
+ else if (v3d->flag2 & V3D_RENDER_BORDER) {
+ drawrenderborder(ar, v3d);
}
- 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)
+/**
+* Grease Pencil
+*/
+static void view3d_draw_grease_pencil(const bContext *UNUSED(C))
{
- while (dob && dob->no_draw)
- dob = dob->next;
- return dob;
+ /* TODO viewport */
}
-static void draw_dupli_objects_color(
- Main *bmain, Scene *scene, ARegion *ar, View3D *v3d, Base *base,
- const short dflag, const int color)
+/**
+* Viewport Name
+*/
+static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
{
- 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);
- }
-
- tbase.flag = OB_FROMDUPLI | base->flag;
- lb = object_duplilist(bmain, bmain->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(base->object, scene, lb);
-
- dob = dupli_step(lb->first);
- if (dob) dob_next = dupli_step(dob->next);
-
- for (; dob; dob_prev = 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);
- }
-
- /* generate displist, test for new object */
- if (dob_prev && dob_prev->ob != dob->ob) {
- if (use_displist == true)
- glDeleteLists(displist, 1);
-
- use_displist = false;
- }
+ const char *name = NULL;
- if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) {
- bb = *bb_tmp; /* must make a copy */
- testbb = true;
- }
+ 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 (!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;
+ 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 {
- // 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(bmain, scene, ar, v3d, &tbase, dflag_dupli);
- glEndList();
-
- use_displist = true;
- BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 0);
+ name = IFACE_("Object as Camera");
}
}
-
- 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(bmain, scene, ar, v3d, &tbase, dflag_dupli);
- GPU_end_dupli_object();
+ name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp");
}
- }
-
- 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);
-
- if (use_displist)
- glDeleteLists(displist, 1);
-}
-
-static void draw_dupli_objects(Main *bmain, Scene *scene, 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 & 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(bmain, scene, ar, v3d, base, 0, color);
+ return name;
}
-/* XXX warning, not using gpu offscreen here */
-void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
+static void draw_viewport_name(ARegion *ar, View3D *v3d, const rcti *rect)
{
- int x, y, w, h;
- rcti r;
- /* clamp rect by region */
-
- r.xmin = 0;
- r.xmax = ar->winx - 1;
- r.ymin = 0;
- r.ymax = ar->winy - 1;
-
- /* Constrain rect to depth bounds */
- BLI_rcti_isect(&r, rect, rect);
-
- /* assign values to compare with the ViewDepths */
- x = rect->xmin;
- y = rect->ymin;
-
- w = BLI_rcti_size_x(rect);
- 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");
+ 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
- d->damaged = true;
+ if (v3d->localvd) {
+ BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
+ name = tmpstr;
}
- 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;
- }
+ 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, 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;
- }
- }
-}
+/**
+ * draw info beside axes in bottom left-corner:
+ * framenum, object name, bone name (if available), marker name (if available)
+ */
-/* utility function to find the closest Z value, use for autodepth */
-float view3d_depth_near(ViewDepths *d)
+static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
{
- /* 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;
- }
- }
+ const int cfra = CFRA;
+ const char *msg_pin = " (Pinned)";
+ const char *msg_sep = " : ";
- return far == far_real ? FLT_MAX : far;
-}
+ const int font_id = BLF_default();
-void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
-{
- short zbuf = v3d->zbuf;
- RegionView3D *rv3d = ar->regiondata;
+ char info[300];
+ char *s = info;
- /* Setup view matrix. */
- ED_view3d_draw_setup_view(NULL, scene, ar, v3d, rv3d->viewmat, rv3d->winmat, NULL);
+ s += sprintf(s, "(%d)", cfra);
- glClear(GL_DEPTH_BUFFER_BIT);
+ /*
+ * 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)
+ */
- v3d->zbuf = true;
- glEnable(GL_DEPTH_TEST);
+ /* get name of marker on current frame (if available) */
+ const char *markern = BKE_scene_find_marker_name(scene, cfra);
- if (v3d->flag2 & V3D_SHOW_GPENCIL) {
- ED_gpencil_draw_view3d(NULL, scene, v3d, ar, true);
- }
+ /* check if there is an object */
+ if (ob) {
+ *s++ = ' ';
+ s += BLI_strcpy_rlen(s, ob->id.name + 2);
- v3d->zbuf = zbuf;
-}
+ /* name(s) to display depends on type of object */
+ if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
-static void view3d_draw_depth_loop(Main *bmain, Scene *scene, ARegion *ar, View3D *v3d)
-{
- 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(bmain, scene, ar, v3d, base, 0);
- if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects_color(bmain, scene, ar, v3d, base, dflag_depth, TH_UNDEFINED);
+ /* 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);
}
}
- }
- }
-
- 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(bmain, scene, ar, v3d, base, dflag_depth, TH_UNDEFINED);
- }
- draw_object(bmain, scene, 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);
-
+ else if (ob->mode & OB_MODE_POSE) {
+ if (arm->act_bone) {
- 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(bmain, scene, ar, v3d, v3da->base, dflag_depth);
+ if (arm->act_bone->layer & arm->layer) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, arm->act_bone->name);
+ }
+ }
}
- 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(bmain, scene, ar, v3d, v3da->base, dflag_depth);
- MEM_freeN(v3da);
- }
-
- v3d->xray = true;
- v3d->transp = false;
- while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
- draw_object(bmain, scene, ar, v3d, v3da->base, dflag_depth);
- MEM_freeN(v3da);
- }
-
- v3d->xray = true;
- v3d->transp = true;
- while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
- draw_object(bmain, scene, ar, v3d, v3da->base, dflag_depth);
- MEM_freeN(v3da);
- }
-
-
- v3d->xray = false;
- v3d->transp = false;
-
- glDepthMask(mask_orig);
- }
-}
-
-void ED_view3d_draw_depth(Main *bmain, Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride)
-{
- 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);
-
- /* 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;
-
- v3d->zbuf = true;
- glEnable(GL_DEPTH_TEST);
-
- view3d_draw_depth_loop(bmain, scene, ar, v3d);
-
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_disable();
- }
- rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
-
- v3d->zbuf = zbuf;
- if (!v3d->zbuf) glDisable(GL_DEPTH_TEST);
-
- U.glalphaclip = glalphaclip;
- v3d->flag = flag;
- U.obcenter_dia = obcenter_dia;
-
- UI_Theme_Restore(&theme_state);
-}
-
-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(vc->bmain, 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(vc->bmain, scene, ar, v3d, BASACT, dflag);
}
- }
- else {
- Base *base;
-
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & v3d->lay) {
-
- if ((base->object->restrictflag & OB_RESTRICT_SELECT) ||
- (use_obedit_skip && (scene->obedit->data == base->object->data)))
- {
- base->selcol = 0;
- }
- else {
- base->selcol = code;
+ else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
+ /* try to display active bone and active shapekey too (if they exist) */
- 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(vc->bmain, scene, ar, v3d, base, dflag);
+ 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);
}
}
- code++;
}
}
- }
- if (use_nearest) {
- bool xrayclear = true;
- if (v3d->afterdraw_xray.first) {
- view3d_draw_xray_select(vc->bmain, scene, ar, v3d, &xrayclear);
+ 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));
+ }
+ }
}
}
- }
-}
-
-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, SceneRenderLayer *srl)
-{
- 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);
- }
- }
-}
-
-static void gpu_update_lamps_shadows_world(Main *bmain, Scene *scene, View3D *v3d)
-{
- 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(bmain, bmain->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(
- bmain, 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;
+ /* 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);
}
-
- 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);
+ 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);
}
-}
-
-/* *********************** 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_MTEXPOLY | 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;
- }
- }
+ if (markern) {
+ s += sprintf(s, " <%s>", markern);
}
- return mask;
+ BLF_draw_default(rect->xmin + UI_UNIT_X, rect->ymax - (2 * U.widget_unit), 0.0f, info, sizeof(info));
}
-/* goes over all modes and view3d settings */
-CustomDataMask ED_view3d_screen_datamask(const bScreen *screen)
-{
- 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);
- }
- }
-
- return mask;
-}
+/* ******************** view loop ***************** */
/**
- * \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore
- */
-void ED_view3d_update_viewmat(
- Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect)
+* 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);
- /* setup window matrices */
- if (winmat)
- copy_m4_m4(rv3d->winmat, winmat);
- else
- view3d_winmatrix_set(ar, v3d, rect);
-
- /* setup view matrix */
- if (viewmat) {
- copy_m4_m4(rv3d->viewmat, viewmat);
- }
- else {
- float rect_scale[2];
- if (rect) {
- rect_scale[0] = (float)BLI_rcti_size_x(rect) / (float)ar->winx;
- rect_scale[1] = (float)BLI_rcti_size_y(rect) / (float)ar->winy;
- }
- view3d_viewmatrix_set(scene, v3d, rv3d, rect ? rect_scale : NULL); /* note: calls BKE_object_where_is_calc for camera... */
- }
+ /* correct projection matrix */
+ ED_region_pixelspace(ar);
- /* 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);
+ /* local coordinate visible rect inside region, to accomodate overlapping ui */
+ rcti rect;
+ ED_region_visible_rect(ar, &rect);
- /* calculate GLSL view dependent values */
- /* 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);
+ view3d_draw_border(C, ar);
+ view3d_draw_grease_pencil(C);
- 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;
- }
+ BLF_batch_draw_begin();
- /**
- * 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.
- */
+ if (((U.uiflag & USER_SHOW_ROTVIEWICON) != 0) &&
+ ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
+ /* No need to display manipulator and this info. */
+ ((U.manipulator_flag & USER_MANIPULATOR_DRAW_NAVIGATE) == 0))
{
- /* 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;
- }
-}
-
-/**
- * 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,
- Main *bmain,
- Scene *scene, View3D *v3d, ARegion *ar,
- const char **grid_unit,
- const bool do_bgpic, const bool draw_offscreen, GPUFX *fx)
-{
- if (bmain == NULL) {
- bmain = CTX_data_main(C);
- }
- 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);
+ draw_view_axis(rv3d, &rect);
}
- if (rv3d->rflag & RV3D_CLIPPING)
- view3d_draw_clipping(rv3d);
-
- /* set zbuffer after we draw clipping region */
- if (v3d->drawtype > OB_WIRE) {
- v3d->zbuf = true;
- }
- else {
- v3d->zbuf = false;
- }
-
- /* 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 (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... */
- 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);
+ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0 &&
+ (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0)
+ {
+ if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
+ ED_scene_draw_fps(scene, &rect);
}
- }
-
- /* 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 (v3d->lay & base->lay) {
- UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
- draw_object(bmain, scene, ar, v3d, base, dflag);
-
- if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects_color(bmain, scene, ar, v3d, base, dflag, TH_UNDEFINED);
- }
- }
+ else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
+ draw_viewport_name(ar, v3d, &rect);
}
- /* Transp and X-ray afterdraw stuff for sets is done later */
- }
-
-
- 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(bmain, scene, ar, v3d, base);
-
- draw_object(bmain, scene, ar, v3d, base, 0);
- }
+ if (U.uiflag & USER_DRAWVIEWINFO) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ draw_selected_name(scene, ob, &rect);
}
- }
- else {
- unsigned int lay_used = 0;
- /* then draw not selected and the duplis, but skip editmode object */
- for (base = scene->base.first; base; base = base->next) {
- lay_used |= base->lay;
-
- if (v3d->lay & base->lay) {
+#if 0 /* TODO */
+ if (grid_unit) { /* draw below the viewport name */
+ char numstr[32] = "";
- /* dupli drawing */
- if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects(bmain, scene, ar, v3d, base);
- }
- if ((base->flag & SELECT) == 0) {
- if (base->object != scene->obedit)
- draw_object(bmain, scene, ar, v3d, base, 0);
- }
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+ if (v3d->grid != 1.0f) {
+ BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
}
- }
-
- /* mask out localview */
- v3d->lay_used = lay_used & ((1 << 20) - 1);
- /* 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(bmain, scene, ar, v3d, base, 0);
- }
- }
+ 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
}
- /* perspective floor goes last to use scene depth and avoid writing to depth buffer */
- if (draw_grids_after) {
- 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, v3d, ar, true);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- }
-
- /* transp and X-ray afterdraw stuff */
- if (v3d->afterdraw_transp.first) view3d_draw_transp(bmain, scene, 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(bmain, scene, ar, v3d, &xrayclear);
- if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(bmain, scene, 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);
- }
+ BLF_batch_draw_end();
+}
- if (!draw_offscreen) {
- BIF_draw_manipulator(C);
- }
+static void view3d_draw_view(const bContext *C, ARegion *ar)
+{
+ ED_view3d_draw_setup_view(CTX_wm_window(C), CTX_data_depsgraph(C), CTX_data_scene(C), ar, CTX_wm_view3d(C), NULL, NULL, NULL);
- /* cleanup */
- if (v3d->zbuf) {
- v3d->zbuf = false;
- glDisable(GL_DEPTH_TEST);
- }
+ /* Only 100% compliant on new spec goes bellow */
+ DRW_draw_view(C);
+}
- if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
- GPU_free_images_old(bmain);
+RenderEngineType *ED_view3d_engine_type(Scene *scene, int drawtype)
+{
+ /*
+ * Tempory viewport draw modes until we have a proper system.
+ * all modes are done in the draw manager, except
+ * cycles material as it is an external render engine.
+ */
+ if (strcmp(scene->r.engine, RE_engine_id_CYCLES) == 0 && drawtype == OB_MATERIAL) {
+ return RE_engines_find(RE_engine_id_BLENDER_EEVEE);
}
+ return RE_engines_find(scene->r.engine);
}
-static void view3d_main_region_setup_view(
- Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect)
+void view3d_main_region_draw(const bContext *C, ARegion *ar)
{
- RegionView3D *rv3d = ar->regiondata;
+ Main *bmain = CTX_data_main(C);
+ View3D *v3d = CTX_wm_view3d(C);
- ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat, rect);
+ view3d_draw_view(C, ar);
- /* set for opengl */
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(rv3d->winmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(rv3d->viewmat);
-}
+ GPU_free_images_old(bmain);
+ GPU_pass_cache_garbage_collect();
-/**
- * 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;
-}
+ /* XXX This is in order to draw UI batches with the DRW
+ * olg context since we now use it for drawing the entire area */
+ gpu_batch_presets_reset();
-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;
-}
+ /* No depth test for drawing action zones afterwards. */
+ glDisable(GL_DEPTH_TEST);
-void ED_view3d_draw_offscreen_init(Main *bmain, Scene *scene, View3D *v3d)
-{
- /* shadow buffers, before we setup matrices */
- if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
- gpu_update_lamps_shadows_world(bmain, scene, v3d);
+ v3d->flag |= V3D_INVALID_BACKBUF;
}
-/*
- * Function to clear the view
- */
-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();
- }
+/** \name Offscreen Drawing
+ * \{ */
- GPU_material_unbind(gpumat);
+static void view3d_stereo3d_setup_offscreen(
+ Depsgraph *depsgraph, Scene *scene, View3D *v3d, ARegion *ar,
+ float winmat[4][4], const char *viewname)
+{
+ /* 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);
- glDepthFunc(GL_LEQUAL);
- glDisable(GL_DEPTH_TEST);
+ BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
+ view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
}
- 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);
- }
+ 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(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
}
}
-/* ED_view3d_draw_offscreen_init should be called before this to initialize
- * stuff like shadow buffers
- */
void ED_view3d_draw_offscreen(
- Main *bmain, Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
+ Depsgraph *depsgraph, Scene *scene,
+ int drawtype,
+ 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)
+ bool do_sky, bool UNUSED(is_persp), const char *viewname,
+ GPUFXSettings *UNUSED(fx_settings),
+ GPUOffScreen *ofs, GPUViewport *viewport)
{
- struct bThemeState theme_state;
- int bwinx, bwiny;
- rcti brect;
- bool do_compositing = false;
RegionView3D *rv3d = ar->regiondata;
-
- glPushMatrix();
+ RenderEngineType *engine_type = ED_view3d_engine_type(scene, drawtype);
/* 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;
@@ -3197,6 +1338,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);
@@ -3206,69 +1348,31 @@ void ED_view3d_draw_offscreen(
if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
/* free images which can have changed on frame-change
* warning! can be slow so only free animated images - campbell */
- GPU_free_images_anim(bmain);
+ GPU_free_images_anim(G.main); /* XXX :((( */
}
- /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */
+ gpuPushProjectionMatrix();
+ gpuLoadIdentity();
+ gpuPushMatrix();
+ gpuLoadIdentity();
+
if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
- view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname);
+ view3d_stereo3d_setup_offscreen(depsgraph, 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;
- }
-
- /* clear opengl buffers */
- if (do_sky) {
- view3d_main_region_clear(scene, v3d, ar);
- }
- else {
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
+ view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
/* main drawing call */
- view3d_draw_objects(NULL, bmain, 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, v3d, ar, false);
- }
-
- /* freeing the images again here could be done after the operator runs, leaving for now */
- GPU_free_images_anim(bmain);
- }
+ DRW_draw_render_loop_offscreen(
+ depsgraph, engine_type, ar, v3d,
+ do_sky, ofs, viewport);
/* restore size */
ar->winx = bwinx;
ar->winy = bwiny;
ar->winrct = brect;
- glPopMatrix();
+ gpuPopProjectionMatrix();
+ gpuPopMatrix();
UI_Theme_Restore(&theme_state);
@@ -3276,40 +1380,22 @@ 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(
- Main *bmain, Scene *scene,
+ Depsgraph *depsgraph, Scene *scene,
+ int drawtype,
View3D *v3d, ARegion *ar, int sizex, int sizey,
unsigned int flag, unsigned int draw_flags,
int alpha_mode, int samples, const char *viewname,
/* output vars */
- GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
+ GPUOffScreen *ofs, char err_out[256])
{
RegionView3D *rv3d = ar->regiondata;
- ImBuf *ibuf;
const bool draw_sky = (alpha_mode == R_ADDSKY);
- const bool draw_background = (draw_flags & V3D_OFSDRAW_USE_BACKGROUND);
const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE);
/* view state */
@@ -3323,33 +1409,36 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
}
const bool own_ofs = (ofs == NULL);
+ DRW_opengl_context_enable();
if (own_ofs) {
/* bind */
- ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, err_out);
+ ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, true, false, err_out);
if (ofs == NULL) {
+ DRW_opengl_context_disable();
return NULL;
}
}
- ED_view3d_draw_offscreen_init(bmain, scene, 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) {
CameraParams params;
Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
+ const Object *camera_eval = DEG_get_evaluated_object(
+ depsgraph,
+ camera);
BKE_camera_params_init(&params);
/* fallback for non camera objects */
params.clipsta = v3d->near;
params.clipend = v3d->far;
- BKE_camera_params_from_object(&params, camera);
- BKE_camera_multiview_params(&scene->r, &params, camera, viewname);
+ BKE_camera_params_from_object(&params, camera_eval);
+ BKE_camera_multiview_params(&scene->r, &params, camera_eval, viewname);
BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
BKE_camera_params_compute_matrix(&params);
@@ -3362,7 +1451,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
rctf viewplane;
float clipsta, clipend;
- is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
+ is_ortho = ED_view3d_viewplane_get(depsgraph, v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
if (is_ortho) {
orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
}
@@ -3374,9 +1463,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
if ((samples && use_full_sample) == 0) {
/* Single-pass render, common case */
ED_view3d_draw_offscreen(
- bmain, scene, v3d, ar, sizex, sizey, NULL, winmat,
- draw_background, draw_sky, !is_ortho, viewname,
- fx, &fx_settings, ofs);
+ depsgraph, scene, drawtype,
+ v3d, ar, sizex, sizey, NULL, winmat,
+ draw_sky, !is_ortho, viewname,
+ &fx_settings, ofs, NULL);
if (ibuf->rect_float) {
GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
@@ -3390,28 +1480,22 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
* Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */
static float jit_ofs[32][2];
float winmat_jitter[4][4];
- /* 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;
+ float *rect_temp = (ibuf->rect_float) ? ibuf->rect_float : MEM_mallocN(sizex * sizey * sizeof(float[4]), "rect_temp");
+ float *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(float[4]), "accum_buffer");
+ GPUViewport *viewport = GPU_viewport_create_from_offscreen(ofs);
BLI_jitter_init(jit_ofs, samples);
/* first sample buffer, also initializes 'rv3d->persmat' */
ED_view3d_draw_offscreen(
- bmain, scene, 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;
- while (i--) {
- accum_buffer[i] = rect_temp[i];
- }
+ depsgraph, scene, drawtype,
+ v3d, ar, sizex, sizey, NULL, winmat,
+ draw_sky, !is_ortho, viewname,
+ &fx_settings, ofs, viewport);
+ GPU_offscreen_read_pixels(ofs, GL_FLOAT, accum_buffer);
/* 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,
@@ -3419,29 +1503,40 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
(jit_ofs[j][1] * 2.0f) / sizey);
ED_view3d_draw_offscreen(
- bmain, scene, 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);
+ depsgraph, scene, drawtype,
+ v3d, ar, sizex, sizey, NULL, winmat_jitter,
+ draw_sky, !is_ortho, viewname,
+ &fx_settings, ofs, viewport);
+ GPU_offscreen_read_pixels(ofs, GL_FLOAT, rect_temp);
- i = sizex * sizey * 4;
+ unsigned int i = sizex * sizey * 4;
while (i--) {
accum_buffer[i] += rect_temp[i];
}
}
+ {
+ /* don't free data owned by 'ofs' */
+ GPU_viewport_clear_from_offscreen(viewport);
+ GPU_viewport_free(viewport);
+ }
+
+ if (ibuf->rect_float == NULL) {
+ MEM_freeN(rect_temp);
+ }
+
if (ibuf->rect_float) {
float *rect_float = ibuf->rect_float;
- i = sizex * sizey * 4;
+ unsigned int i = sizex * sizey * 4;
while (i--) {
- rect_float[i] = (float)(accum_buffer[i] / samples) * (1.0f / 255.0f);
+ rect_float[i] = accum_buffer[i] / samples;
}
}
else {
unsigned char *rect_ub = (unsigned char *)ibuf->rect;
- i = sizex * sizey * 4;
+ unsigned int i = sizex * sizey * 4;
while (i--) {
- rect_ub[i] = accum_buffer[i] / samples;
+ rect_ub[i] = (unsigned char)(255.0f * accum_buffer[i] / samples);
}
}
@@ -3455,6 +1550,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
GPU_offscreen_free(ofs);
}
+ DRW_opengl_context_disable();
+
if (ibuf->rect_float && ibuf->rect)
IMB_rect_from_float(ibuf);
@@ -3470,11 +1567,12 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
* \note used by the sequencer
*/
ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
- Main *bmain, Scene *scene,
+ Depsgraph *depsgraph, Scene *scene,
+ int drawtype,
Object *camera, int width, int height,
- unsigned int flag, unsigned int draw_flags, int drawtype,
+ unsigned int flag, unsigned int draw_flags,
int alpha_mode, int samples, const char *viewname,
- GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
+ GPUOffScreen *ofs, char err_out[256])
{
View3D v3d = {NULL};
ARegion ar = {NULL};
@@ -3496,9 +1594,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
if (draw_flags & V3D_OFSDRAW_USE_SOLID_TEX) {
v3d.flag2 |= V3D_SOLID_TEX;
}
- if (draw_flags & V3D_OFSDRAW_USE_BACKGROUND) {
- v3d.flag3 |= V3D_SHOW_WORLD;
- }
+
+ v3d.flag3 |= V3D_SHOW_WORLD;
+
if (draw_flags & V3D_OFSDRAW_USE_CAMERA_DOF) {
if (camera->type == OB_CAMERA) {
v3d.fx_settings.dof = &((Camera *)camera->data)->gpu_dof;
@@ -3514,11 +1612,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
{
CameraParams params;
- Object *view_camera = BKE_camera_multiview_render(scene, v3d.camera, viewname);
+ const Object *view_camera_eval = DEG_get_evaluated_object(
+ depsgraph,
+ BKE_camera_multiview_render(scene, v3d.camera, viewname));
BKE_camera_params_init(&params);
- BKE_camera_params_from_object(&params, view_camera);
- BKE_camera_multiview_params(&scene->r, &params, view_camera, viewname);
+ BKE_camera_params_from_object(&params, view_camera_eval);
+ BKE_camera_multiview_params(&scene->r, &params, view_camera_eval, viewname);
BKE_camera_params_compute_viewplane(&params, width, height, scene->r.xasp, scene->r.yasp);
BKE_camera_params_compute_matrix(&params);
@@ -3532,671 +1632,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
invert_m4_m4(rv3d.persinv, rv3d.viewinv);
return ED_view3d_draw_offscreen_imbuf(
- bmain, scene, &v3d, &ar, width, height, flag, draw_flags,
- alpha_mode, 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(const Scene *scene)
-{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
-
- return (type && type->view_update && type->view_draw);
-}
-
-bool ED_view3d_calc_render_border(
- const Scene *scene, const View3D *v3d, const ARegion *ar,
- rcti *rect)
-{
- 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);
- }
- 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)
-{
- 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;
-}
-
-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);
-}
-
-static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d)
-{
- 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;
-}
-
-/* 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)
-{
- 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_thread_lock(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_thread_unlock(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_thread_lock(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_thread_unlock(LOCK_VIEW3D);
- }
-}
-
-static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
- float winmat[4][4], const char *viewname)
-{
- /* 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);
- }
-}
-
-#ifdef WITH_GAMEENGINE
-static void update_lods(Scene *scene, float camera_pos[3])
-{
- Scene *sce_iter;
- Base *base;
- Object *ob;
-
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
- BKE_object_lod_update(ob, camera_pos);
- }
+ depsgraph, scene, drawtype,
+ &v3d, &ar, width, height, flag,
+ draw_flags, alpha_mode, samples, viewname, ofs, err_out);
}
-#endif
-
-static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, View3D *v3d,
- ARegion *ar, const char **grid_unit)
-{
- Main *bmain = CTX_data_main(C);
- 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(bmain, 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, bmain, 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
-}
-
-static bool is_cursor_visible(Scene *scene)
-{
- if (U.app_flag & USER_APP_VIEW3D_HIDE_CURSOR) {
- return false;
- }
-
- 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;
-}
-
-static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
- ARegion *ar, View3D *v3d,
- const char *grid_unit, bool render_border)
-{
- 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));
- }
- }
-}
-
-void view3d_main_region_draw(const bContext *C, ARegion *ar)
-{
- 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));
-}
-
-#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)
-{
- _bl_debug_draw_color = color;
-}
-void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3])
-{
- if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_QUAD_TOT) {
- printf("%s: max quad count hit %d!", __func__, _bl_debug_draw_quads_tot);
- }
- 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++;
- }
-}
-void bl_debug_draw_edge_add(const float v0[3], const float v1[3])
-{
- 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++;
- }
-}
-static void bl_debug_draw(void)
-{
- 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();
- }
-}
-#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..3a89c910ea8
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -0,0 +1,1077 @@
+/*
+ * ***** 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_2d.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 "DEG_depsgraph_query.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_material.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 *********** */
+
+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);
+}
+
+/* *********************** backdraw for selection *************** */
+
+static void backdrawview3d(
+ struct Depsgraph *depsgraph, Scene *scene,
+ ARegion *ar, View3D *v3d,
+ Object *obact, Object *obedit,
+ short select_mode)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
+ Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
+
+ BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
+
+ if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
+ BKE_paint_select_face_test(obact_eval)))
+ {
+ /* do nothing */
+ }
+ /* texture paint mode sampling */
+ else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) &&
+ (v3d->drawtype > OB_WIRE))
+ {
+ /* do nothing */
+ }
+ else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) &&
+ V3D_IS_ZBUF(v3d))
+ {
+ /* do nothing */
+ }
+ else if ((obedit && (obedit->mode & OB_MODE_EDIT)) &&
+ 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);
+
+ if (false) {
+ /* 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.
+ *
+ * NOTE: code is no longer used now, but offscreen drawing is likely
+ * what we will always want to do for the new viewport. */
+ 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, true, false, 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 (obact_eval && ((obact_eval->base_flag & BASE_VISIBLED) != 0)) {
+ draw_object_backbufsel(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode);
+ }
+
+ if (rv3d->gpuoffscreen)
+ GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
+
+ v3d->flag &= ~V3D_INVALID_BACKBUF;
+
+ G.f &= ~G_BACKBUFSEL;
+ v3d->zbuf = false;
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_DITHER);
+
+ 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_with_select_mode(ViewContext *vc, short select_mode)
+{
+ if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
+ backdrawview3d(vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit, select_mode);
+ }
+}
+
+void ED_view3d_backbuf_validate(ViewContext *vc)
+{
+ ED_view3d_backbuf_validate_with_select_mode(vc, -1);
+}
+
+/**
+ * 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(
+ ViewContext *vc, int x, int y)
+{
+ if (x >= vc->ar->winx || y >= vc->ar->winy) {
+ return 0;
+ }
+
+ ED_view3d_backbuf_validate(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(
+ 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(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(
+ 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(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, Depsgraph *depsgraph,
+ 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, depsgraph, 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);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, 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 ED_view3d_draw_bgpic_test(
+ Scene *scene, Depsgraph *depsgraph,
+ 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, depsgraph, ar, v3d, do_foreground, do_camera_frame);
+ }
+ }
+ else {
+ view3d_draw_bgpic(scene, depsgraph, ar, v3d, do_foreground, do_camera_frame);
+ }
+}
+
+/* *********************** */
+
+/* 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(
+ Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d)
+{
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ bool zbuf = v3d->zbuf;
+
+ /* Setup view matrix. */
+ ED_view3d_draw_setup_view(NULL, depsgraph, 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, view_layer, depsgraph, v3d, ar, true);
+ }
+
+ v3d->zbuf = zbuf;
+ if (!zbuf) glDisable(GL_DEPTH_TEST);
+}
+
+/* *********************** customdata **************** */
+
+CustomDataMask ED_view3d_datamask(const Scene *UNUSED(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 (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;
+}
+
+/**
+ * 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->r.engine);
+ return (type && type->view_update && type->view_draw);
+}
+
+bool ED_view3d_calc_render_border(const Scene *scene, Depsgraph *depsgraph, 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, depsgraph, 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;
+}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 5cf167165cd..88c7eabc62f 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -36,6 +36,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"
@@ -48,8 +49,10 @@
#include "BLI_utildefines.h"
#include "BKE_armature.h"
+#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_font.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_object.h"
@@ -59,12 +62,12 @@
#include "BKE_screen.h"
#include "BKE_action.h"
-
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -76,6 +79,7 @@
#include "ED_mesh.h"
#include "ED_gpencil.h"
#include "ED_view3d.h"
+#include "ED_transform_snap_object_context.h"
#include "UI_resources.h"
@@ -133,6 +137,7 @@ typedef struct ViewOpsData {
ARegion *ar;
View3D *v3d;
RegionView3D *rv3d;
+ Depsgraph *depsgraph;
/** Needed for continuous zoom. */
wmTimer *timer;
@@ -218,6 +223,7 @@ static void viewops_data_alloc(bContext *C, wmOperator *op)
/* store data */
op->customdata = vod;
vod->bmain = CTX_data_main(C);
+ vod->depsgraph = CTX_data_depsgraph(C);
vod->scene = CTX_data_scene(C);
vod->sa = CTX_wm_area(C);
vod->ar = CTX_wm_region(C);
@@ -245,8 +251,11 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
static float lastofs[3] = {0, 0, 0};
bool is_set = false;
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
- Object *ob_act = OBACT;
+ ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
+ Object *ob_act_eval = OBACT(view_layer_eval);
+ Object *ob_act = DEG_get_original_object(ob_act_eval);
if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) &&
/* with weight-paint + pose-mode, fall through to using calculateTransformCenter */
@@ -258,16 +267,16 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
*/
if (ob_act->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
float stroke[3];
- BKE_paint_stroke_get_average(scene, ob_act, stroke);
+ BKE_paint_stroke_get_average(scene, ob_act_eval, stroke);
copy_v3_v3(lastofs, stroke);
}
else {
- copy_v3_v3(lastofs, ob_act->obmat[3]);
+ copy_v3_v3(lastofs, ob_act_eval->obmat[3]);
}
is_set = true;
}
else if (ob_act && (ob_act->mode & OB_MODE_EDIT) && (ob_act->type == OB_FONT)) {
- Curve *cu = ob_act->data;
+ Curve *cu = ob_act_eval->data;
EditFont *ef = cu->editfont;
int i;
@@ -277,33 +286,32 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
}
mul_v2_fl(lastofs, 1.0f / 4.0f);
- mul_m4_v3(ob_act->obmat, lastofs);
+ mul_m4_v3(ob_act_eval->obmat, lastofs);
is_set = true;
}
else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) {
/* object mode use boundbox centers */
- View3D *v3d = CTX_wm_view3d(C);
- Base *base;
+ Base *base_eval;
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_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
+ if (TESTBASE(base_eval)) {
/* use the boundbox if we can */
- Object *ob = base->object;
+ Object *ob_eval = base_eval->object;
- if (ob->bb && !(ob->bb->flag & BOUNDBOX_DIRTY)) {
+ if (ob_eval->bb && !(ob_eval->bb->flag & BOUNDBOX_DIRTY)) {
float cent[3];
- BKE_boundbox_calc_center_aabb(ob->bb, cent);
+ BKE_boundbox_calc_center_aabb(ob_eval->bb, cent);
- mul_m4_v3(ob->obmat, cent);
+ mul_m4_v3(ob_eval->obmat, cent);
add_v3_v3(select_center, cent);
}
else {
- add_v3_v3(select_center, ob->obmat[3]);
+ add_v3_v3(select_center, ob_eval->obmat[3]);
}
tot++;
}
@@ -366,6 +374,7 @@ static void viewops_data_create(
bContext *C, wmOperator *op, const wmEvent *event,
enum eViewOpsFlag viewops_flag)
{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
ViewOpsData *vod = op->customdata;
RegionView3D *rv3d = vod->rv3d;
@@ -383,7 +392,7 @@ static void viewops_data_create(
negate_v3_v3(fallback_depth_pt, rv3d->ofs);
vod->use_dyn_ofs = ED_view3d_autodist(
- vod->bmain, vod->scene, vod->ar, vod->v3d,
+ depsgraph, vod->ar, vod->v3d,
event->mval, vod->dyn_ofs, true, fallback_depth_pt);
}
else {
@@ -391,7 +400,7 @@ static void viewops_data_create(
}
if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
- if (ED_view3d_persp_ensure(vod->v3d, vod->ar)) {
+ if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->ar)) {
/* If we're switching from camera view to the perspective one,
* need to tag viewport update, so camera vuew and borders
* are properly updated.
@@ -402,7 +411,7 @@ static void viewops_data_create(
/* set the view from the camera, if view locking is enabled.
* we may want to make this optional but for now its needed always */
- ED_view3d_camera_lock_init(vod->v3d, vod->rv3d);
+ ED_view3d_camera_lock_init(depsgraph, vod->v3d, vod->rv3d);
vod->init.dist = rv3d->dist;
vod->init.camzoom = rv3d->camzoom;
@@ -506,8 +515,9 @@ static void viewops_data_create(
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;
@@ -523,7 +533,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);
}
@@ -802,7 +814,7 @@ static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
vod->prev.event_xy[0] = event_xy[0];
vod->prev.event_xy[1] = event_xy[1];
- ED_view3d_camera_lock_sync(vod->v3d, rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, rv3d);
ED_region_tag_redraw(vod->ar);
}
@@ -1100,7 +1112,6 @@ static void view3d_ndof_pan_zoom(
static void view3d_ndof_orbit(
const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
- /* optional, can be NULL*/
ViewOpsData *vod, const bool apply_dyn_ofs)
{
View3D *v3d = sa->spacedata.first;
@@ -1110,7 +1121,7 @@ static void view3d_ndof_orbit(
BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
- ED_view3d_persp_ensure(v3d, ar);
+ ED_view3d_persp_ensure(vod->depsgraph, v3d, ar);
rv3d->view = RV3D_VIEW_USER;
@@ -1299,6 +1310,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
else {
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
ViewOpsData *vod;
View3D *v3d;
RegionView3D *rv3d;
@@ -1319,7 +1331,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* off by default, until changed later this function */
rv3d->rot_angle = 0.0f;
- ED_view3d_camera_lock_init_ex(v3d, rv3d, false);
+ ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
if (ndof->progress != P_FINISHING) {
const bool has_rotation = NDOF_HAS_ROTATE;
@@ -1336,7 +1348,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
}
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
ED_region_tag_redraw(vod->ar);
@@ -1367,6 +1379,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
return OPERATOR_CANCELLED;
}
else {
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
ViewOpsData *vod;
View3D *v3d;
RegionView3D *rv3d;
@@ -1388,7 +1401,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
/* off by default, until changed later this function */
rv3d->rot_angle = 0.0f;
- ED_view3d_camera_lock_init_ex(v3d, rv3d, false);
+ ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
if (ndof->progress == P_FINISHING) {
/* pass */
@@ -1431,13 +1444,13 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
ED_view3d_distance_set(rv3d, 0.0f);
if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL, false);
+ view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, false);
}
ED_view3d_distance_set(rv3d, dist_backup);
}
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
ED_region_tag_redraw(vod->ar);
@@ -1471,6 +1484,7 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *e
return OPERATOR_CANCELLED;
}
else {
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
const wmNDOFMotionData *ndof = event->customdata;
@@ -1484,7 +1498,7 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *e
if (!(has_translate || has_zoom))
return OPERATOR_CANCELLED;
- ED_view3d_camera_lock_init_ex(v3d, rv3d, false);
+ ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
if (ndof->progress != P_FINISHING) {
ScrArea *sa = CTX_wm_area(C);
@@ -1495,7 +1509,7 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *e
}
}
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
ED_region_tag_redraw(CTX_wm_region(C));
@@ -1628,7 +1642,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
vod->prev.event_xy[0] = x;
vod->prev.event_xy[1] = y;
- ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ED_region_tag_redraw(vod->ar);
}
@@ -1792,7 +1806,7 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf)
* \param zoom_xy: Optionally zoom to window location (coords compatible w/ #wmEvent.x, y). Use when not NULL.
*/
static void view_zoom_to_window_xy_camera(
- Scene *scene, View3D *v3d,
+ Scene *scene, Depsgraph *depsgraph, View3D *v3d,
ARegion *ar, float dfac, const int zoom_xy[2])
{
RegionView3D *rv3d = ar->regiondata;
@@ -1810,13 +1824,13 @@ static void view_zoom_to_window_xy_camera(
float pt_dst[2];
float delta_px[2];
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_old, false);
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_old, false);
BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin);
rv3d->camzoom = camzoom_new;
CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_new, false);
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_new, false);
BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->winrct.ymin);
BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src);
@@ -1989,7 +2003,7 @@ static void viewzoom_apply_camera(
/* calculate inverted, then invert again (needed because of camera zoom scaling) */
zfac = 1.0f / zfac;
view_zoom_to_window_xy_camera(
- vod->scene, vod->v3d,
+ vod->scene, vod->depsgraph, vod->v3d,
vod->ar, zfac, zoom_to_pos ? vod->prev.event_xy : NULL);
}
@@ -2027,7 +2041,7 @@ static void viewzoom_apply_3d(
view3d_boxview_sync(vod->sa, vod->ar);
}
- ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ED_region_tag_redraw(vod->ar);
}
@@ -2109,6 +2123,7 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int viewzoom_exec(bContext *C, wmOperator *op)
{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d;
RegionView3D *rv3d;
@@ -2151,7 +2166,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
const float step = 1.2f;
/* this min and max is also in viewmove() */
if (use_cam_zoom) {
- view_zoom_to_window_xy_camera(scene, v3d, ar, step, zoom_xy);
+ view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy);
}
else {
if (rv3d->dist < dist_range[1]) {
@@ -2162,7 +2177,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
else {
const float step = 1.0f / 1.2f;
if (use_cam_zoom) {
- view_zoom_to_window_xy_camera(scene, v3d, ar, step, zoom_xy);
+ view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy);
}
else {
if (rv3d->dist > dist_range[0]) {
@@ -2177,7 +2192,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
ED_view3d_depth_tag_update(rv3d);
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
ED_region_tag_redraw(ar);
@@ -2371,7 +2386,7 @@ static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const short zoom_
view3d_boxview_sync(vod->sa, vod->ar);
}
- ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ED_region_tag_redraw(vod->ar);
}
@@ -2472,7 +2487,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
ED_view3d_depth_tag_update(rv3d);
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(CTX_data_depsgraph(C), v3d, rv3d);
ED_region_tag_redraw(ar);
@@ -2506,7 +2521,8 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (vod->rv3d->persp != RV3D_PERSP) {
if (vod->rv3d->persp == RV3D_CAMOB) {
/* ignore rv3d->lpersp because dolly only makes sense in perspective mode */
- ED_view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, RV3D_PERSP);
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ED_view3d_persp_switch_from_camera(depsgraph, vod->v3d, vod->rv3d, RV3D_PERSP);
}
else {
vod->rv3d->persp = RV3D_PERSP;
@@ -2640,7 +2656,7 @@ static void view3d_from_minmax(
}
if (ok_dist) {
- new_dist = ED_view3d_radius_to_dist(v3d, ar, persp, true, (size / 2) * VIEW3D_MARGIN);
+ new_dist = ED_view3d_radius_to_dist(v3d, ar, CTX_data_depsgraph(C), persp, true, (size / 2) * VIEW3D_MARGIN);
if (rv3d->is_persp) {
/* don't zoom closer than the near clipping plane */
new_dist = max_ff(new_dist, v3d->near * 1.5f);
@@ -2695,8 +2711,9 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
- Base *base;
- float *curs;
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
+ Base *base_eval;
const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) ||
/* any one of the regions may be locked */
@@ -2709,24 +2726,26 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
if (center) {
/* in 2.4x this also move the cursor to (0, 0, 0) (with shift+c). */
- curs = ED_view3d_cursor3d_get(scene, v3d);
+ View3DCursor *cursor = ED_view3d_cursor3d_get(scene, v3d);
zero_v3(min);
zero_v3(max);
- zero_v3(curs);
+ zero_v3(cursor->location);
+ unit_qt(cursor->rotation);
}
else {
INIT_MINMAX(min, max);
}
- for (base = scene->base.first; base; base = base->next) {
- if (BASE_VISIBLE(v3d, base)) {
+ for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
+ if (BASE_VISIBLE(base_eval)) {
changed = true;
- if (skip_camera && base->object == v3d->camera) {
+ Object *ob = DEG_get_original_object(base_eval->object);
+ if (skip_camera && ob == v3d->camera) {
continue;
}
- BKE_object_minmax(base->object, min, max, false);
+ BKE_object_minmax(base_eval->object, min, max, false);
}
}
if (!changed) {
@@ -2748,6 +2767,10 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
view3d_from_minmax(C, v3d, ar, min, max, true, smooth_viewtx);
}
+ if (center) {
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
+ }
+
return OPERATOR_FINISHED;
}
@@ -2782,13 +2805,16 @@ void VIEW3D_OT_view_all(wmOperatorType *ot)
/* like a localview without local!, was centerview() in 2.4x */
static int viewselected_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
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_eval = OBACT(view_layer_eval);
Object *obedit = CTX_data_edit_object(C);
float min[3], max[3];
bool ok = false, ok_dist = true;
@@ -2799,28 +2825,27 @@ 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) {
- ob = NULL;
+ if (is_gp_edit || is_face_map) {
+ ob_eval = NULL;
}
- if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
+ if (ob_eval && (ob_eval->mode & OB_MODE_WEIGHT_PAINT)) {
/* 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)) {
- if (base->object->type == OB_ARMATURE)
- if (base->object->mode & OB_MODE_POSE)
+ Base *base_eval;
+ for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
+ if (TESTBASELIB(base_eval)) {
+ if (base_eval->object->type == OB_ARMATURE)
+ if (base_eval->object->mode & OB_MODE_POSE)
break;
}
}
- if (base)
- ob = base->object;
+ if (base_eval)
+ ob_eval = base_eval->object;
}
-
if (is_gp_edit) {
+ /* TODO(sergey): Check on this after gpencil merge. */
CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
{
/* we're only interested in selected points here... */
@@ -2832,38 +2857,48 @@ 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 */
+ /* only selected */
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, obedit->mode, ob_eval_iter) {
+ ok |= ED_view3d_minmax_verts(ob_eval_iter, min, max);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
}
- else if (ob && (ob->mode & OB_MODE_POSE)) {
- ok = BKE_pose_minmax(ob, min, max, true, true);
+ else if (ob_eval && (ob_eval->mode & OB_MODE_POSE)) {
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, ob_eval->mode, ob_eval_iter) {
+ ok |= BKE_pose_minmax(ob_eval_iter, min, max, true, true);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
}
- else if (BKE_paint_select_face_test(ob)) {
- ok = paintface_minmax(ob, min, max);
+ else if (BKE_paint_select_face_test(ob_eval)) {
+ ok = paintface_minmax(ob_eval, min, max);
}
- else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
- ok = PE_minmax(bmain, scene, min, max);
+ else if (ob_eval && (ob_eval->mode & OB_MODE_PARTICLE_EDIT)) {
+ ok = PE_minmax(scene, view_layer_eval, min, max);
}
- else if (ob &&
- (ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
+ else if (ob_eval &&
+ (ob_eval->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
{
- BKE_paint_stroke_get_average(scene, ob, min);
+ BKE_paint_stroke_get_average(scene, ob_eval, min);
copy_v3_v3(max, min);
ok = true;
ok_dist = 0; /* don't zoom */
}
else {
- Base *base;
- for (base = FIRSTBASE; base; base = base->next) {
- if (TESTBASE(v3d, base)) {
+ Base *base_eval;
+ for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
+ if (TESTBASE(base_eval)) {
- if (skip_camera && base->object == v3d->camera) {
+ if (skip_camera && base_eval->object == v3d->camera) {
continue;
}
/* account for duplis */
- if (BKE_object_minmax_dupli(bmain, scene, base->object, min, max, false) == 0)
- BKE_object_minmax(base->object, min, max, false); /* use if duplis not found */
+ if (BKE_object_minmax_dupli(depsgraph, scene, base_eval->object, min, max, false) == 0)
+ BKE_object_minmax(base_eval->object, min, max, false); /* use if duplis not found */
ok = 1;
}
@@ -2952,14 +2987,14 @@ static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op))
Object *obact = CTX_data_active_object(C);
if (v3d) {
-
ED_view3d_lock_clear(v3d);
v3d->ob_centre = obact; /* can be NULL */
if (obact && obact->type == OB_ARMATURE) {
if (obact->mode & OB_MODE_POSE) {
- bPoseChannel *pcham_act = BKE_pose_channel_active(obact);
+ Object *obact_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), obact);
+ bPoseChannel *pcham_act = BKE_pose_channel_active(obact_eval);
if (pcham_act) {
BLI_strncpy(v3d->ob_centre_bone, pcham_act->name, sizeof(v3d->ob_centre_bone));
}
@@ -3017,7 +3052,7 @@ static int viewcenter_cursor_exec(bContext *C, wmOperator *op)
/* non camera center */
float new_ofs[3];
- negate_v3_v3(new_ofs, ED_view3d_cursor3d_get(scene, v3d));
+ negate_v3_v3(new_ofs, ED_view3d_cursor3d_get(scene, v3d)->location);
ED_view3d_smooth_view(
C, v3d, ar, smooth_viewtx,
&(const V3D_SmoothParams) {.ofs = new_ofs});
@@ -3051,13 +3086,12 @@ void VIEW3D_OT_view_center_cursor(wmOperatorType *ot)
static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Main *bmain = CTX_data_main(C);
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) {
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
float new_ofs[3];
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
@@ -3065,7 +3099,7 @@ static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *ev
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(bmain, scene, ar, v3d, event->mval, new_ofs, false, NULL)) {
+ if (ED_view3d_autodist(depsgraph, ar, v3d, event->mval, new_ofs, false, NULL)) {
/* pass */
}
else {
@@ -3105,6 +3139,7 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot)
static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) /* was view3d_home() in 2.4x */
{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
float xfac, yfac;
float size[2];
@@ -3119,7 +3154,7 @@ static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) /* was
rv3d->camdx = rv3d->camdy = 0.0f;
- ED_view3d_calc_camera_border_size(scene, ar, v3d, rv3d, size);
+ ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size);
/* 4px is just a little room from the edge of the area */
xfac = (float)ar->winx / (float)(size[0] + 4);
@@ -3188,6 +3223,7 @@ void VIEW3D_OT_view_center_lock(wmOperatorType *ot)
static int render_border_exec(bContext *C, wmOperator *op)
{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = ED_view3d_context_rv3d(C);
@@ -3208,7 +3244,7 @@ static int render_border_exec(bContext *C, wmOperator *op)
/* calculate range */
if (rv3d->persp == RV3D_CAMOB) {
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false);
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false);
}
else {
vb.xmin = 0;
@@ -3253,6 +3289,9 @@ static int render_border_exec(bContext *C, wmOperator *op)
v3d->flag2 |= V3D_RENDER_BORDER;
}
+ if (rv3d->persp == RV3D_CAMOB) {
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
+ }
return OPERATOR_FINISHED;
}
@@ -3316,6 +3355,9 @@ static int clear_render_border_exec(bContext *C, wmOperator *UNUSED(op))
border->xmax = 1.0f;
border->ymax = 1.0f;
+ if (rv3d->persp == RV3D_CAMOB) {
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
+ }
return OPERATOR_FINISHED;
}
@@ -3342,11 +3384,9 @@ void VIEW3D_OT_clear_render_border(wmOperatorType *ot)
static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
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 */
@@ -3359,9 +3399,8 @@ 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 cent[2], p[3];
/* note; otherwise opengl won't work */
view3d_operator_needs_opengl(C);
@@ -3375,8 +3414,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(bmain, scene, ar, v3d, true);
+ ED_view3d_draw_depth(CTX_data_depsgraph(C), ar, v3d, true);
{
/* avoid allocating the whole depth buffer */
@@ -3391,11 +3429,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;
+ cent[0] = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
+ cent[1] = (((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) {
@@ -3403,23 +3441,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, cent[0], cent[1], 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);
@@ -3434,13 +3463,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, cent[0], cent[1], depth_close, p)) {
+ negate_v3_v3(new_ofs, p);
}
else {
float mval_f[2];
@@ -3530,13 +3554,13 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot)
* Sets the view to 1:1 camera/render-pixel.
* \{ */
-static void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar, View3D *v3d)
+static void view3d_set_1_to_1_viewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View3D *v3d)
{
RegionView3D *rv3d = ar->regiondata;
float size[2];
int im_width = (scene->r.size * scene->r.xsch) / 100;
- ED_view3d_calc_camera_border_size(scene, ar, v3d, rv3d, size);
+ ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size);
rv3d->camzoom = BKE_screen_view3d_zoom_from_fac((float)im_width / size[0]);
CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
@@ -3544,6 +3568,7 @@ static void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar, View3D *v3d)
static int view3d_zoom_1_to_1_camera_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d;
@@ -3552,7 +3577,7 @@ static int view3d_zoom_1_to_1_camera_exec(bContext *C, wmOperator *UNUSED(op))
/* no NULL check is needed, poll checks */
ED_view3d_context_user_region(C, &v3d, &ar);
- view3d_set_1_to_1_viewborder(scene, ar, v3d);
+ view3d_set_1_to_1_viewborder(scene, depsgraph, ar, v3d);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
@@ -3659,7 +3684,8 @@ static void axis_set_view(
dist = rv3d->dist;
/* so we animate _from_ the camera location */
- ED_view3d_from_object(v3d->camera, rv3d->ofs, NULL, &rv3d->dist, NULL);
+ Object *camera_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), v3d->camera);
+ ED_view3d_from_object(camera_eval, rv3d->ofs, NULL, &rv3d->dist, NULL);
ED_view3d_smooth_view(
C, v3d, ar, smooth_viewtx,
@@ -3689,7 +3715,6 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
View3D *v3d;
ARegion *ar;
RegionView3D *rv3d;
- Scene *scene = CTX_data_scene(C);
static int perspo = RV3D_PERSP;
int viewnum, nextperspo;
bool align_active;
@@ -3723,8 +3748,11 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
/* lastview - */
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Scene *scene = CTX_data_scene(C);
+
if (rv3d->persp != RV3D_CAMOB) {
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
if (!rv3d->smooth_timer) {
/* store settings of current view before allowing overwriting with camera view
@@ -3759,7 +3787,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_view_layer_camera_find(view_layer);
/* couldnt find any useful camera, bail out */
if (v3d->camera == NULL)
@@ -3867,7 +3895,8 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
float quat_new[4];
if (view_opposite == RV3D_VIEW_USER) {
- ED_view3d_persp_ensure(v3d, ar);
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ED_view3d_persp_ensure(depsgraph, v3d, ar);
}
if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) {
@@ -3992,7 +4021,7 @@ static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y))
view3d_boxview_sync(vod->sa, vod->ar);
}
- ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
+ ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ED_region_tag_redraw(vod->ar);
}
@@ -4325,11 +4354,11 @@ void VIEW3D_OT_navigate(wmOperatorType *ot)
/** \name Background Image Add 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))
@@ -4341,9 +4370,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 */
@@ -4351,9 +4380,9 @@ static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEven
bgpic = background_image_add(C);
bgpic->ima = ima;
- v3d->flag |= V3D_DISPBGPICS;
+ cam->flag |= CAM_SHOW_BG_IMAGE;
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
return OPERATOR_FINISHED;
}
@@ -4370,7 +4399,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;
@@ -4390,21 +4419,21 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot)
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_SPACE | ND_SPACE_VIEW3D, v3d);
+ WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
return OPERATOR_FINISHED;
}
else {
@@ -4421,7 +4450,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;
@@ -4461,9 +4490,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);
@@ -4471,12 +4499,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);
-
- ED_view3d_viewcontext_init(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;
}
@@ -4529,10 +4553,8 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot)
/* cursor position in vec, result in vec, mval in region coords */
/* note: cannot use event->mval here (called by object_add() */
-void ED_view3d_cursor3d_position(bContext *C, const int mval[2], float cursor_co[3])
+void ED_view3d_cursor3d_position(bContext *C, const int mval[2], bool use_depth, float cursor_co[3])
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ar->regiondata;
@@ -4553,10 +4575,13 @@ void ED_view3d_cursor3d_position(bContext *C, const int mval[2], float cursor_co
ED_view3d_calc_zfac(rv3d, cursor_co, NULL /* &flip */ );
}
- if (U.uiflag & USER_DEPTH_CURSOR) { /* maybe this should be accessed some other way */
+ if (use_depth) { /* maybe this should be accessed some other way */
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(bmain, scene, ar, v3d, mval, cursor_co, true, NULL))
+ if (ED_view3d_autodist(depsgraph, ar, v3d, mval, cursor_co, true, NULL)) {
depth_used = true;
+ }
}
if (depth_used == false) {
@@ -4566,31 +4591,117 @@ void ED_view3d_cursor3d_position(bContext *C, const int mval[2], float cursor_co
}
}
-void ED_view3d_cursor3d_update(bContext *C, const int mval[2])
+void ED_view3d_cursor3d_position_rotation(
+ bContext *C, const int mval[2],
+ const bool use_depth, enum eV3DCursorOrient orientation,
+ float cursor_co[3], float cursor_quat[4])
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* XXX, caller should check. */
+ if (rv3d == NULL)
+ return;
+
+ ED_view3d_cursor3d_position(C, mval, use_depth, cursor_co);
+
+ if (orientation == V3D_CURSOR_ORIENT_NONE) {
+ /* pass */
+ }
+ else if (orientation == V3D_CURSOR_ORIENT_VIEW) {
+ copy_qt_qt(cursor_quat, rv3d->viewquat);
+ cursor_quat[0] *= -1.0f;
+ }
+ else if (orientation == V3D_CURSOR_ORIENT_GEOM) {
+ copy_qt_qt(cursor_quat, rv3d->viewquat);
+ cursor_quat[0] *= -1.0f;
+
+ const float mval_fl[2] = {UNPACK2(mval)};
+ float ray_no[3];
+ float ray_co[3];
+
+ struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
+ bmain, scene, CTX_data_depsgraph(C), 0, ar, v3d);
+
+ float obmat[4][4];
+ Object *ob_dummy = NULL;
+ float dist_px = 0;
+ if (ED_transform_snap_object_project_view3d_ex(
+ snap_context,
+ SCE_SNAP_MODE_FACE,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = false,
+ },
+ mval_fl, &dist_px,
+ ray_co, ray_no, NULL,
+ &ob_dummy, obmat))
+ {
+ if (use_depth) {
+ copy_v3_v3(cursor_co, ray_co);
+ }
- float *cursor_co_curr = ED_view3d_cursor3d_get(scene, v3d);
- float cursor_co_prev[3];
+ float tquat[4];
- copy_v3_v3(cursor_co_prev, cursor_co_curr);
+ /* Math normal (Z). */
+ {
+ float z_src[3] = {0, 0, 1};
+ mul_qt_v3(cursor_quat, z_src);
+ rotation_between_vecs_to_quat(tquat, z_src, ray_no);
+ mul_qt_qtqt(cursor_quat, tquat, cursor_quat);
+ }
- ED_view3d_cursor3d_position(C, mval, cursor_co_curr);
+ /* Match object matrix (X). */
+ {
+ const float ortho_axis_dot[3] = {
+ dot_v3v3(ray_no, obmat[0]),
+ dot_v3v3(ray_no, obmat[1]),
+ dot_v3v3(ray_no, obmat[2]),
+ };
+ const int ortho_axis = axis_dominant_v3_ortho_single(ortho_axis_dot);
+ float x_src[3] = {1, 0, 0};
+ float x_dst[3];
+ mul_qt_v3(cursor_quat, x_src);
+ project_plane_v3_v3v3(x_dst, obmat[ortho_axis], ray_no);
+ normalize_v3(x_dst);
+ rotation_between_vecs_to_quat(tquat, x_src, x_dst);
+ mul_qt_qtqt(cursor_quat, tquat, cursor_quat);
+ }
+ }
+ ED_transform_snap_object_context_destroy(snap_context);
+ }
+}
+
+void ED_view3d_cursor3d_update(
+ bContext *C, const int mval[2],
+ const bool use_depth, enum eV3DCursorOrient orientation)
+{
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ View3DCursor *cursor_curr = ED_view3d_cursor3d_get(scene, v3d);
+ View3DCursor cursor_prev = *cursor_curr;
+
+ ED_view3d_cursor3d_position_rotation(
+ C, mval,
+ use_depth, orientation,
+ cursor_curr->location, cursor_curr->rotation);
/* offset the cursor lock to avoid jumping to new offset */
if (v3d->ob_centre_cursor) {
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
-
if (U.uiflag & USER_LOCK_CURSOR_ADJUST) {
float co_2d_curr[2], co_2d_prev[2];
if ((ED_view3d_project_float_global(
- ar, cursor_co_prev, co_2d_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
+ ar, cursor_prev.location, co_2d_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
(ED_view3d_project_float_global(
- ar, cursor_co_curr, co_2d_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
+ ar, cursor_curr->location, co_2d_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
{
rv3d->ofs_lock[0] += (co_2d_curr[0] - co_2d_prev[0]) / (ar->winx * 0.5f);
rv3d->ofs_lock[1] += (co_2d_curr[1] - co_2d_prev[1]) / (ar->winy * 0.5f);
@@ -4606,11 +4717,30 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[2])
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
else
WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
+
+ {
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ WM_msg_publish_rna_prop(
+ mbus, &scene->id, scene, Scene, cursor_location);
+ }
+
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
}
-static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int view3d_cursor3d_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ED_view3d_cursor3d_update(C, event->mval);
+ bool use_depth = (U.uiflag & USER_DEPTH_CURSOR);
+ {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_depth");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ use_depth = RNA_property_boolean_get(op->ptr, prop);
+ }
+ else {
+ RNA_property_boolean_set(op->ptr, prop, use_depth);
+ }
+ }
+ const enum eV3DCursorOrient orientation = RNA_enum_get(op->ptr, "orientation");
+ ED_view3d_cursor3d_update(C, event->mval, use_depth, orientation);
return OPERATOR_FINISHED;
}
@@ -4630,95 +4760,23 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot)
/* flags */
// ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Transform Manipulator Operator
- * \{ */
-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;
+ static const EnumPropertyItem orientation_items[] = {
+ {V3D_CURSOR_ORIENT_NONE, "NONE", 0, "None", "Leave orientation unchanged"},
+ {V3D_CURSOR_ORIENT_VIEW, "VIEW", 0, "View", "Orient to the viewport"},
+ {V3D_CURSOR_ORIENT_GEOM, "GEOM", 0, "Geometry", "Match the surface normal"},
+ {0, NULL, 0, NULL, NULL}
+ };
- /* 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);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Enable Transform Manipulator Operator
- * \{ */
-
-static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- View3D *v3d = CTX_wm_view3d(C);
-
- v3d->twtype = 0;
-
- if (RNA_boolean_get(op->ptr, "translate"))
- v3d->twtype |= V3D_MANIP_TRANSLATE;
- if (RNA_boolean_get(op->ptr, "rotate"))
- v3d->twtype |= V3D_MANIP_ROTATE;
- if (RNA_boolean_get(op->ptr, "scale"))
- v3d->twtype |= V3D_MANIP_SCALE;
-
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
-
- return OPERATOR_FINISHED;
-}
-
-void VIEW3D_OT_enable_manipulator(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Enable 3D Manipulator";
- ot->description = "Enable the transform manipulator for use";
- ot->idname = "VIEW3D_OT_enable_manipulator";
-
- /* api callbacks */
- ot->invoke = enable_manipulator_invoke;
- ot->poll = ED_operator_view3d_active;
-
- /* properties */
- prop = RNA_def_boolean(ot->srna, "translate", 0, "Translate", "Enable the translate manipulator");
+ prop = RNA_def_boolean(
+ ot->srna, "use_depth", true, "Surface Project",
+ "Project onto the surface");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "rotate", 0, "Rotate", "Enable the rotate manipulator");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "scale", 0, "Scale", "Enable the scale manipulator");
+
+ prop = RNA_def_enum(
+ ot->srna, "orientation", orientation_items, V3D_CURSOR_ORIENT_VIEW,
+ "Orientation", "Preset viewpoint to use");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index 65d66df4824..d8cc9ab9828 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -56,6 +56,10 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_immediate.h"
+
+#include "DEG_depsgraph.h"
+
#include "view3d_intern.h" /* own include */
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
@@ -191,6 +195,7 @@ typedef struct FlyInfo {
RegionView3D *rv3d;
View3D *v3d;
ARegion *ar;
+ struct Depsgraph *depsgraph;
Scene *scene;
wmTimer *timer; /* needed for redraws */
@@ -240,7 +245,7 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar),
float x1, x2, y1, y2;
if (fly->scene->camera) {
- ED_view3d_calc_camera_border(fly->scene, fly->ar, fly->v3d, fly->rv3d, &viewborder, false);
+ ED_view3d_calc_camera_border(fly->scene, fly->depsgraph, fly->ar, fly->v3d, fly->rv3d, &viewborder, false);
xoff = viewborder.xmin;
yoff = viewborder.ymin;
}
@@ -257,36 +262,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);
- glVertex2f(x2, y1);
- glVertex2f(x2 - 5, y1);
- glEnd();
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2 - 5, y1);
+
+ immEnd();
+ immUnbindProgram();
}
static void fly_update_header(bContext *C, wmOperator *op, FlyInfo *fly)
@@ -332,6 +346,7 @@ enum {
static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
+
rctf viewborder;
float upvec[3]; /* tmp */
@@ -340,6 +355,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
fly->rv3d = CTX_wm_region_view3d(C);
fly->v3d = CTX_wm_view3d(C);
fly->ar = CTX_wm_region(C);
+ fly->depsgraph = CTX_data_depsgraph(C);
fly->scene = CTX_data_scene(C);
#ifdef NDOF_FLY_DEBUG
@@ -406,12 +422,12 @@ 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,
+ CTX_data_depsgraph(C), fly->scene, fly->v3d, fly->rv3d,
(U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
/* calculate center */
if (fly->scene->camera) {
- ED_view3d_calc_camera_border(fly->scene, fly->ar, fly->v3d, fly->rv3d, &viewborder, false);
+ ED_view3d_calc_camera_border(fly->scene, fly->depsgraph, fly->ar, fly->v3d, fly->rv3d, &viewborder, false);
fly->width = BLI_rctf_size_x(&viewborder);
fly->height = BLI_rctf_size_y(&viewborder);
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 124bd33f227..4f81fa7585c 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,7 +72,6 @@ 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);
@@ -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);
}
@@ -97,16 +93,16 @@ static void handle_view3d_lock(bContext *C)
* layer code is on three levels actually:
* - here for operator
* - uiTemplateLayers in interface/ code for buttons
- * - ED_view3d_scene_layer_set for RNA
+ * - ED_view3d_view_layer_set for RNA
*/
-static void view3d_layers_editmode_ensure(Scene *scene, View3D *v3d)
+static void view3d_layers_editmode_ensure(View3D *v3d, Object *obedit)
{
/* sanity check - when in editmode disallow switching the editmode layer off since its confusing
* an alternative would be to always draw the editmode object. */
- if (scene->obedit && (scene->obedit->lay & v3d->lay) == 0) {
+ if (obedit && (obedit->lay & v3d->lay) == 0) {
int bit;
for (bit = 0; bit < 32; bit++) {
- if (scene->obedit->lay & (1u << bit)) {
+ if (obedit->lay & (1u << bit)) {
v3d->lay |= (1u << bit);
break;
}
@@ -116,9 +112,9 @@ static void view3d_layers_editmode_ensure(Scene *scene, View3D *v3d)
static int view3d_layers_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
+ Object *obedit = CTX_data_edit_object(C);
int nr = RNA_int_get(op->ptr, "nr");
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
@@ -134,7 +130,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op)
/* return to active layer only */
v3d->lay = v3d->lay_prev;
- view3d_layers_editmode_ensure(scene, v3d);
+ view3d_layers_editmode_ensure(v3d, obedit);
}
else {
v3d->lay_prev = v3d->lay;
@@ -155,7 +151,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op)
v3d->lay = (1 << nr);
}
- view3d_layers_editmode_ensure(scene, v3d);
+ view3d_layers_editmode_ensure(v3d, obedit);
/* set active layer, ensure to always have one */
if (v3d->lay & (1 << nr))
@@ -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);
@@ -225,6 +221,72 @@ void VIEW3D_OT_layers(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "toggle", 1, "Toggle", "Toggle the layer");
}
+/* -------------------------------------------------------------------- */
+/** \name Toggle Bone selection Overlay Operator
+ * \{ */
+
+static int toggle_show_xray(bContext *C, wmOperator *UNUSED(op))
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ v3d->shading.flag ^= V3D_SHADING_XRAY;
+ ED_view3d_shade_update(CTX_data_main(C), v3d, CTX_wm_area(C));
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ return OPERATOR_FINISHED;
+}
+
+static int toggle_show_xray_poll(bContext *C)
+{
+ bool result = (ED_operator_view3d_active(C) && !ED_operator_posemode(C) && !ED_operator_editmesh(C));
+ if (result) {
+ // Additional test for SOLID or TEXTURE mode
+ View3D *v3d = CTX_wm_view3d(C);
+ result = (v3d->drawtype & (OB_SOLID | OB_TEXTURE)) > 0;
+ }
+ return result;
+}
+
+void VIEW3D_OT_toggle_xray_draw_option(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Toggle Show X-Ray";
+ ot->description = "Toggle show X-Ray";
+ ot->idname = "VIEW3D_OT_toggle_xray_draw_option";
+
+ /* api callbacks */
+ ot->exec = toggle_show_xray;
+ ot->poll = toggle_show_xray_poll;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Bone selection Overlay Operator
+ * \{ */
+
+static int toggle_matcap_flip(bContext *C, wmOperator *UNUSED(op))
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ v3d->shading.flag ^= V3D_SHADING_MATCAP_FLIP_X;
+ ED_view3d_shade_update(CTX_data_main(C), v3d, CTX_wm_area(C));
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_toggle_matcap_flip(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Flip MatCap";
+ ot->description = "Flip MatCap";
+ ot->idname = "VIEW3D_OT_toggle_matcap_flip";
+
+ /* api callbacks */
+ ot->exec = toggle_matcap_flip;
+ // ot->poll = toggle_show_xray_poll;
+}
+
+/** \} */
+
+
static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event)
{
wmWindow *win = CTX_wm_window(C);
@@ -278,21 +340,64 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
}
}
+static void uiTemplatePaintModeSelection(uiLayout *layout, struct bContext *C)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+
+ /* Manipulators aren't used in paint modes */
+ if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) {
+ /* masks aren't used for sculpt and particle painting */
+ PointerRNA meshptr;
+
+ RNA_pointer_create(ob->data, &RNA_Mesh, ob->data, &meshptr);
+ if (ob->mode & (OB_MODE_TEXTURE_PAINT)) {
+ uiItemR(layout, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ }
+ else {
+ uiLayout *row = uiLayoutRow(layout, true);
+ uiItemR(row, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ uiItemR(row, &meshptr, "use_paint_mask_vertex", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ }
+ }
+}
+
+void uiTemplateHeader3D_mode(uiLayout *layout, struct bContext *C)
+{
+ /* Extracted from: uiTemplateHeader3D */
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ Object *obedit = CTX_data_edit_object(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+
+ 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));
+
+ uiTemplateEditModeSelection(layout, C);
+ if ((obedit == NULL) && is_paint) {
+ uiTemplatePaintModeSelection(layout, C);
+ }
+}
+
void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
{
bScreen *screen = CTX_wm_screen(C);
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
ToolSettings *ts = CTX_data_tool_settings(C);
PointerRNA v3dptr, toolsptr, sceneptr;
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
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);
@@ -304,81 +409,39 @@ 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);
+ /* moved to topbar */
+#if 0
+ uiLayout *row = uiLayoutRow(layout, true);
uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
if (!ob || ELEM(ob->mode, OB_MODE_OBJECT, OB_MODE_POSE, OB_MODE_WEIGHT_PAINT)) {
uiItemR(row, &v3dptr, "use_pivot_point_align", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
}
+#endif
if (obedit == NULL && is_paint) {
- /* Manipulators aren't used in paint modes */
- if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) {
- /* masks aren't used for sculpt and particle painting */
- PointerRNA meshptr;
-
- RNA_pointer_create(ob->data, &RNA_Mesh, ob->data, &meshptr);
- if (ob->mode & (OB_MODE_TEXTURE_PAINT)) {
- uiItemR(layout, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- }
- else {
- row = uiLayoutRow(layout, true);
- uiItemR(row, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- uiItemR(row, &meshptr, "use_paint_mask_vertex", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- }
- }
+ /* Currently Python calls this directly. */
+#if 0
+ uiTemplatePaintModeSelection(layout, C);
+#endif
+
}
else {
+ /* Moved to popover and topbar. */
+#if 0
/* 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) {
- uiItemR(row, &v3dptr, "transform_manipulators", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- }
- uiItemR(row, &v3dptr, "transform_orientation", 0, "", ICON_NONE);
+ uiItemR(row, &sceneptr, "transform_orientation", 0, "", ICON_NONE);
+#endif
}
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);
}
+ /* Currently Python calls this directly. */
+#if 0
uiTemplateEditModeSelection(layout, C);
+#endif
}
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index cfcded70fc9..4eb2a016b94 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -37,7 +37,10 @@
struct ARegion;
struct ARegionType;
+struct Base;
struct BoundBox;
+struct Gwn_Batch;
+struct Depsgraph;
struct DerivedMesh;
struct Object;
struct SmokeDomainSettings;
@@ -46,9 +49,12 @@ struct bContext;
struct bMotionPath;
struct bPoseChannel;
struct Mesh;
+struct ViewLayer;
struct wmOperatorType;
-struct wmWindowManager;
struct wmKeyConfig;
+struct wmManipulatorGroupType;
+struct wmManipulatorType;
+struct wmWindowManager;
/* drawing flags: */
enum {
@@ -57,14 +63,10 @@ enum {
DRAW_SCENESET = (1 << 2)
};
-/* draw_mesh_fancy/draw_mesh_textured draw_flags */
-enum {
- DRAW_MODIFIERS_PREVIEW = (1 << 0),
- DRAW_FACE_SELECT = (1 << 1)
-};
-
/* view3d_header.c */
void VIEW3D_OT_layers(struct wmOperatorType *ot);
+void VIEW3D_OT_toggle_xray_draw_option(struct wmOperatorType *ot);
+void VIEW3D_OT_toggle_matcap_flip(struct wmOperatorType *ot);
/* view3d_ops.c */
void view3d_operatortypes(void);
@@ -99,8 +101,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);
void VIEW3D_OT_zoom_border(struct wmOperatorType *ot);
@@ -133,87 +133,34 @@ void VIEW3D_OT_walk(struct wmOperatorType *ot);
/* view3d_ruler.c */
void VIEW3D_OT_ruler(struct wmOperatorType *ot);
-/* drawanim.c */
-void draw_motion_paths_init(View3D *v3d, struct ARegion *ar);
-void draw_motion_path_instance(Scene *scene,
- struct Object *ob, struct bPoseChannel *pchan,
- struct bAnimVizSettings *avs, struct bMotionPath *mpath);
-void draw_motion_paths_cleanup(View3D *v3d);
-
-
-
/* drawobject.c */
-void draw_object(
- struct Main *bmain, Scene *scene, struct ARegion *ar, View3D *v3d,
- Base *base, const short dflag);
-void draw_object_select(
- struct Main *bmain, 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 view3d_cached_text_draw_begin(void);
-void view3d_cached_text_draw_add(const float co[3],
- const char *str, const size_t str_len,
- short xoffs, short flag, const unsigned char col[4]);
-void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write);
-
-bool check_object_draw_texture(struct Scene *scene, struct View3D *v3d, const char drawtype);
-
-enum {
- V3D_CACHE_TEXT_ZBUF = (1 << 0),
- V3D_CACHE_TEXT_WORLDSPACE = (1 << 1),
- V3D_CACHE_TEXT_ASCII = (1 << 2),
- V3D_CACHE_TEXT_GLOBALSPACE = (1 << 3),
- V3D_CACHE_TEXT_LOCALCLIP = (1 << 4)
-};
+void draw_object_backbufsel(
+ struct Depsgraph *depsgraph, Scene *scene,
+ View3D *v3d, RegionView3D *rv3d, struct Object *ob,
+ short select_mode);
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);
-
-/* drawmesh.c */
-void draw_mesh_textured(Scene *scene, 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,
- bool draw_select_edges);
-void draw_mesh_paint_weight_faces(struct DerivedMesh *dm, const bool do_light,
- void *facemask_cb, void *user_data);
-void draw_mesh_paint_vcolor_faces(struct DerivedMesh *dm, const bool use_light,
- void *facemask_cb, void *user_data,
- const struct Mesh *me);
-void draw_mesh_paint_weight_edges(RegionView3D *rv3d, struct DerivedMesh *dm,
- const bool use_depth, const bool use_alpha,
- void *edgemask_cb, void *user_data);
-void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
- struct Object *ob, struct DerivedMesh *dm, const int draw_flags);
-
-/* drawsimdebug.c */
-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 view3d_draw_region_info(const struct bContext *C, struct ARegion *ar, const int offset);
void ED_view3d_draw_depth(
- struct Main *bmain, struct Scene *scene,
+ struct Depsgraph *depsgraph,
struct ARegion *ar, View3D *v3d, bool alphaoverride);
-void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d);
+
+/* view3d_draw_legacy.c */
+void ED_view3d_draw_depth_gpencil(struct Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d);
+
void ED_view3d_draw_select_loop(
- ViewContext *vc, Scene *scene, View3D *v3d, ARegion *ar,
+ struct Depsgraph *depsgraph, ViewContext *vc, Scene *scene, struct ViewLayer *view_layer, 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(
+ struct Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d);
+
+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);
@@ -228,9 +175,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);
-
bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const struct BoundBox *bb, float obmat[4][4]);
bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const struct BoundBox *bb);
@@ -243,6 +187,7 @@ typedef struct V3D_SmoothParams {
} V3D_SmoothParams;
void ED_view3d_smooth_view_ex(
+ const struct Depsgraph *depsgraph,
struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa,
struct View3D *v3d, struct ARegion *ar, const int smooth_viewtx,
const V3D_SmoothParams *sview);
@@ -257,9 +202,10 @@ void ED_view3d_smooth_view_force_finish(
struct View3D *v3d, struct ARegion *ar);
void view3d_winmatrix_set(
+ struct Depsgraph *depsgraph,
ARegion *ar, const View3D *v3d, const rcti *rect);
void view3d_viewmatrix_set(
- Scene *scene,
+ struct Depsgraph *depsgraph, Scene *scene,
const View3D *v3d, RegionView3D *rv3d, const float rect_scale[2]);
void fly_modal_keymap(struct wmKeyConfig *keyconf);
@@ -275,7 +221,7 @@ void view3d_buttons_register(struct ARegionType *art);
/* view3d_camera_control.c */
struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
- Scene *scene, View3D *v3d, RegionView3D *rv3d,
+ struct Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d,
const bool use_parent_root);
void ED_view3d_cameracontrol_update(
struct View3DCameraControl *vctrl,
@@ -284,13 +230,11 @@ void ED_view3d_cameracontrol_update(
void ED_view3d_cameracontrol_release(
struct View3DCameraControl *vctrl,
const bool restore);
-Object *ED_view3d_cameracontrol_object_get(
+struct Object *ED_view3d_cameracontrol_object_get(
struct View3DCameraControl *vctrl);
/* view3d_toolbar.c */
void VIEW3D_OT_toolshelf(struct wmOperatorType *ot);
-void view3d_toolshelf_register(struct ARegionType *art);
-void view3d_tool_props_register(struct ARegionType *art);
/* view3d_snap.c */
bool ED_view3d_minmax_verts(struct Object *obedit, float min[3], float max[3]);
@@ -309,6 +253,23 @@ 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_navigate(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);
+
+void VIEW3D_WT_navigate_rotate(struct wmManipulatorType *wt);
+
/* draw_volume.c */
void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob,
const float min[3], const float max[3],
@@ -328,4 +289,3 @@ extern bool view3d_camera_border_hack_test;
#endif
#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..eae0cf8e459 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -35,11 +35,17 @@
#include "BLI_utildefines.h"
#include "BLI_rect.h"
+#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_curve.h"
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
+#include "BKE_context.h"
+#include "BKE_mesh_runtime.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "bmesh.h"
@@ -109,7 +115,9 @@ void meshobject_foreachScreenVert(
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(vc->depsgraph, vc->scene, vc->obact, CD_MASK_BAREMESH);
ED_view3d_check_mats_rv3d(vc->rv3d);
@@ -150,7 +158,9 @@ void mesh_foreachScreenVert(
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(vc->depsgraph, vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
ED_view3d_check_mats_rv3d(vc->rv3d);
@@ -204,7 +214,9 @@ void mesh_foreachScreenEdge(
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(vc->depsgraph, vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
ED_view3d_check_mats_rv3d(vc->rv3d);
@@ -250,7 +262,9 @@ void mesh_foreachScreenFace(
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(vc->depsgraph, vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
ED_view3d_check_mats_rv3d(vc->rv3d);
@@ -438,19 +452,21 @@ void pose_foreachScreenBone(
void (*func)(void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]),
void *userData, const eV3DProjTest clip_flag)
{
- bArmature *arm = vc->obact->data;
+ const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
+ const bArmature *arm_eval = ob_eval->data;
bPose *pose = vc->obact->pose;
bPoseChannel *pchan;
ED_view3d_check_mats_rv3d(vc->rv3d);
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (PBONE_VISIBLE(arm, pchan->bone)) {
+ if (PBONE_VISIBLE(arm_eval, pchan->bone)) {
+ bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
float screen_co_a[2], screen_co_b[2];
int points_proj_tot = 0;
/* project head location to screenspace */
- if (ED_view3d_project_float_object(vc->ar, pchan->pose_head, screen_co_a, clip_flag) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(vc->ar, pchan_eval->pose_head, screen_co_a, clip_flag) == V3D_PROJ_RET_OK) {
points_proj_tot++;
}
else {
@@ -459,7 +475,7 @@ void pose_foreachScreenBone(
}
/* project tail location to screenspace */
- if (ED_view3d_project_float_object(vc->ar, pchan->pose_tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(vc->ar, pchan_eval->pose_tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) {
points_proj_tot++;
}
else {
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..abbd6c888b2
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_armature.c
@@ -0,0 +1,223 @@
+/*
+ * ***** 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) {
+ View3D *v3d = CTX_wm_view3d(C);
+ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
+ 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..023e16c070e
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c
@@ -0,0 +1,469 @@
+/*
+ * ***** 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 "WM_message.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))
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
+ Object *ob = CTX_data_active_object(C);
+ if (ob && ob->type == OB_CAMERA) {
+ Camera *camera = ob->data;
+ /* TODO: support overrides. */
+ if (camera->id.lib == NULL) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ Object *ob = CTX_data_active_object(C);
+ 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, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED);
+
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
+
+ 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, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED);
+
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
+ }
+}
+
+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];
+
+ const float ob_scale_inv[3] = {
+ 1.0f / len_v3(ob->obmat[0]),
+ 1.0f / len_v3(ob->obmat[1]),
+ 1.0f / len_v3(ob->obmat[2]),
+ };
+ const float ob_scale_uniform_inv = (ob_scale_inv[0] + ob_scale_inv[1] + ob_scale_inv[2]) / 3.0f;
+
+ 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 ob_scale_inv widget optional */
+ 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 bool is_ortho = (ca->type == CAM_ORTHO);
+ const int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, aspx, aspy);
+ wmManipulator *widget = is_ortho ? camgroup->ortho_scale : camgroup->focal_len;
+ float scale_matrix;
+ if (true) {
+ float offset[3];
+ float aspect[2];
+
+ 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 */
+ 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);
+
+ if (is_ortho) {
+ scale_matrix = ca->ortho_scale * 0.5f;
+ }
+ else {
+ scale_matrix = ca->drawsize / ob_scale_uniform_inv;
+ }
+ 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);
+ }
+
+ /* define & update properties */
+ {
+ const char *propname = is_ortho ? "ortho_scale" : "lens";
+ PropertyRNA *prop = RNA_struct_find_property(&camera_ptr, propname);
+ const wmManipulatorPropertyType *mpr_prop_type = WM_manipulatortype_target_property_find(widget->type, "offset");
+
+ WM_manipulator_target_property_clear_rna_ptr(widget, mpr_prop_type);
+
+ float min, max, range;
+ float step, precision;
+
+ /* get property range */
+ RNA_property_float_ui_range(&camera_ptr, prop, &min, &max, &step, &precision);
+ range = max - min;
+
+ ED_manipulator_arrow3d_set_range_fac(
+ widget, is_ortho ?
+ (ca->drawsize * range) :
+ (scale_matrix * range /
+ /* Half sensor, intentionally use sensor from camera and not calculated above. */
+ (0.5f * ((ca->sensor_fit == CAMERA_SENSOR_FIT_HOR) ? ca->sensor_x : ca->sensor_x))));
+
+ WM_manipulator_target_property_def_rna_ptr(widget, mpr_prop_type, &camera_ptr, prop, -1);
+ }
+
+}
+
+static void WIDGETGROUP_camera_message_subscribe(
+ const bContext *C, wmManipulatorGroup *mgroup, struct wmMsgBus *mbus)
+{
+ ARegion *ar = CTX_wm_region(C);
+ Object *ob = CTX_data_active_object(C);
+ Camera *ca = ob->data;
+
+ wmMsgSubscribeValue msg_sub_value_mpr_tag_refresh = {
+ .owner = ar,
+ .user_data = mgroup->parent_mmap,
+ .notify = WM_manipulator_do_msg_notify_tag_refresh,
+ };
+
+ {
+ extern PropertyRNA rna_Camera_dof_distance;
+ extern PropertyRNA rna_Camera_draw_size;
+ extern PropertyRNA rna_Camera_ortho_scale;
+ extern PropertyRNA rna_Camera_sensor_fit;
+ extern PropertyRNA rna_Camera_sensor_width;
+ extern PropertyRNA rna_Camera_shift_x;
+ extern PropertyRNA rna_Camera_shift_y;
+ extern PropertyRNA rna_Camera_type;
+ extern PropertyRNA rna_Camera_lens;
+ const PropertyRNA *props[] = {
+ &rna_Camera_dof_distance,
+ &rna_Camera_draw_size,
+ &rna_Camera_ortho_scale,
+ &rna_Camera_sensor_fit,
+ &rna_Camera_sensor_width,
+ &rna_Camera_shift_x,
+ &rna_Camera_shift_y,
+ &rna_Camera_type,
+ &rna_Camera_lens,
+ };
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&ca->id, &idptr);
+
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__);
+ }
+ }
+
+ /* Subscribe to render settings */
+ {
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_mpr_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_mpr_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_mpr_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_mpr_tag_refresh);
+ }
+}
+
+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;
+ wgt->message_subscribe = WIDGETGROUP_camera_message_subscribe;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \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))
+{
+ Scene *scene = CTX_data_scene(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. */
+ {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ if (scene->camera != OBACT(view_layer)) {
+ return false;
+ }
+ }
+
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ if (rv3d->persp == RV3D_CAMOB) {
+ if (scene->r.mode & R_BORDER) {
+ /* TODO: support overrides. */
+ if (scene->id.lib == NULL) {
+ 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);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(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, depsgraph, 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..75e4a9e3314
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_empty.c
@@ -0,0 +1,201 @@
+/*
+ * ***** 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))
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
+ 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..305085be370
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c
@@ -0,0 +1,123 @@
+/*
+ * ***** 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_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 Force Field Manipulators
+ * \{ */
+
+static bool WIDGETGROUP_forcefield_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
+ 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, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_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..f98a2f336bc
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c
@@ -0,0 +1,305 @@
+/*
+ * ***** 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))
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
+ 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, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_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] = ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE) ? 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 (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) {
+ 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))
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
+ 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);
+
+ int flag = ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE;
+ if (ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_DISK)) {
+ flag |= ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM;
+ }
+ RNA_enum_set(mpr->ptr, "transform", flag);
+
+ /* 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))
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
+ 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_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
new file mode 100644
index 00000000000..22b7af48de6
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
@@ -0,0 +1,372 @@
+/*
+ * ***** 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_navigate.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 "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+#include "UI_interface.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 View3D Navigation Manipulator Group
+ * \{ */
+
+/* Offset from screen edge. */
+#define MANIPULATOR_OFFSET_FAC 1.5f
+/* Size of main icon. */
+#define MANIPULATOR_SIZE 64
+/* Factor for size of smaller button. */
+#define MANIPULATOR_MINI_FAC 0.35f
+/* How much mini buttons offset from the primary. */
+#define MANIPULATOR_MINI_OFFSET_FAC 0.42f
+
+
+enum {
+ MPR_MOVE = 0,
+ MPR_ROTATE = 1,
+ MPR_ZOOM = 2,
+
+ /* just buttons */
+ /* overlaps MPR_ORTHO (switch between) */
+ MPR_PERSP = 3,
+ MPR_ORTHO = 4,
+ MPR_CAMERA = 5,
+
+ MPR_TOTAL = 6,
+};
+
+/* Vector icons compatible with 'GPU_batch_from_poly_2d_encoded' */
+static const uchar shape_camera[] = {
+ 0xa3, 0x19, 0x78, 0x55, 0x4d, 0x19, 0x4f, 0x0a, 0x7f, 0x00, 0xb0, 0x0a, 0xa9, 0x19,
+ 0xa9, 0x19, 0x25, 0xda, 0x0a, 0xb0, 0x00, 0x7f, 0x0a, 0x4f, 0x25, 0x25, 0x4f, 0x0a,
+ 0x4d, 0x19, 0x47, 0x19, 0x65, 0x55, 0x41, 0x55, 0x41, 0x9e, 0x43, 0xa8, 0x38, 0xb3,
+ 0x34, 0xc3, 0x38, 0xd2, 0x43, 0xdd, 0x53, 0xe1, 0x62, 0xdd, 0x6d, 0xd2, 0x72, 0xc3,
+ 0x78, 0xc3, 0x7c, 0xd2, 0x87, 0xdd, 0x96, 0xe1, 0xa6, 0xdd, 0xb1, 0xd2, 0xb5, 0xc3,
+ 0xb1, 0xb3, 0xa6, 0xa8, 0xa9, 0x9e, 0xa9, 0x8c, 0xbb, 0x8c, 0xbb, 0x86, 0xc7, 0x86,
+ 0xe0, 0x9e, 0xe0, 0x55, 0xc7, 0x6d, 0xbb, 0x6d, 0xbb, 0x67, 0xa9, 0x67, 0xa9, 0x55,
+ 0x8a, 0x55, 0xa9, 0x19, 0xb0, 0x0a, 0xda, 0x25, 0xf5, 0x4f, 0xff, 0x80, 0xf5, 0xb0,
+ 0xda, 0xda, 0xb0, 0xf5, 0x80, 0xff, 0x4f, 0xf5, 0x4f, 0xf5, 0x7c, 0xb3, 0x78, 0xc3,
+ 0x72, 0xc3, 0x6d, 0xb3, 0x62, 0xa8, 0x53, 0xa4, 0x43, 0xa8, 0x41, 0x9e, 0xa9, 0x9e,
+ 0xa6, 0xa8, 0x96, 0xa4, 0x87, 0xa8, 0x87, 0xa8,
+};
+static const uchar shape_ortho[] = {
+ 0x85, 0x15, 0x85, 0x7c, 0xde, 0xb3, 0xde, 0xb8, 0xd9, 0xba, 0x80, 0x85, 0x27, 0xba,
+ 0x22, 0xb8, 0x22, 0xb3, 0x7b, 0x7c, 0x7b, 0x15, 0x80, 0x12, 0x80, 0x12, 0x1d, 0xba,
+ 0x80, 0xf2, 0x80, 0xff, 0x4f, 0xf5, 0x25, 0xda, 0x0a, 0xb0, 0x00, 0x7f, 0x0a, 0x4f,
+ 0x25, 0x25, 0x4f, 0x0a, 0x7f, 0x00, 0x80, 0x0d, 0x1d, 0x45, 0x1d, 0x45, 0xb0, 0x0a,
+ 0xda, 0x25, 0xf5, 0x4f, 0xff, 0x80, 0xf5, 0xb0, 0xda, 0xda, 0xb0, 0xf5, 0x80, 0xff,
+ 0x80, 0xf2, 0xe3, 0xba, 0xe3, 0x45, 0x80, 0x0d, 0x7f, 0x00, 0x7f, 0x00,
+};
+static const uchar shape_pan[] = {
+ 0xbf, 0x4c, 0xbf, 0x66, 0x99, 0x66, 0x99, 0x40, 0xb2, 0x40, 0x7f, 0x0d, 0x7f, 0x00,
+ 0xb0, 0x0a, 0xda, 0x25, 0xf5, 0x4f, 0xff, 0x80, 0xf5, 0xb0, 0xda, 0xda, 0xb0, 0xf5,
+ 0x80, 0xff, 0x80, 0xf2, 0xb3, 0xbf, 0x99, 0xbf, 0x99, 0x99, 0xbf, 0x99, 0xbf, 0xb2,
+ 0xf2, 0x7f, 0xf2, 0x7f, 0x40, 0xb3, 0x40, 0x99, 0x66, 0x99, 0x66, 0xbf, 0x4d, 0xbf,
+ 0x80, 0xf2, 0x80, 0xff, 0x4f, 0xf5, 0x25, 0xda, 0x0a, 0xb0, 0x00, 0x7f, 0x0a, 0x4f,
+ 0x25, 0x25, 0x4f, 0x0a, 0x7f, 0x00, 0x7f, 0x0d, 0x4c, 0x40, 0x66, 0x40, 0x66, 0x66,
+ 0x40, 0x66, 0x40, 0x4d, 0x0d, 0x80, 0x0d, 0x80,
+};
+static const uchar shape_persp[] = {
+ 0xda, 0xda, 0xb0, 0xf5, 0x80, 0xff, 0x4f, 0xf5, 0x25, 0xda, 0x0a, 0xb0, 0x00, 0x7f,
+ 0x0a, 0x4f, 0x25, 0x25, 0x4f, 0x0a, 0x7f, 0x00, 0x80, 0x07, 0x30, 0x50, 0x18, 0xbd,
+ 0x80, 0xdb, 0xe8, 0xbd, 0xf5, 0xb0, 0xf5, 0xb0, 0x83, 0x0f, 0x87, 0x7b, 0xe2, 0xb7,
+ 0xe3, 0xba, 0xe0, 0xbb, 0x80, 0x87, 0x20, 0xbb, 0x1d, 0xba, 0x1d, 0xb7, 0x78, 0x7b,
+ 0x7d, 0x0f, 0x80, 0x0c, 0x80, 0x0c, 0xd0, 0x50, 0x80, 0x07, 0x7f, 0x00, 0xb0, 0x0a,
+ 0xda, 0x25, 0xf5, 0x4f, 0xff, 0x80, 0xf5, 0xb0, 0xe8, 0xbd, 0xe8, 0xbd,
+};
+static const uchar shape_zoom[] = {
+ 0xad, 0x7f, 0xf1, 0x7f, 0xff, 0x80, 0xf5, 0xb0, 0xda, 0xda, 0xb0, 0xf5, 0x80, 0xff,
+ 0x4f, 0xf5, 0x25, 0xda, 0x0a, 0xb0, 0x00, 0x7f, 0x0d, 0x7f, 0x52, 0x7f, 0x69, 0xb7,
+ 0x48, 0xb7, 0x80, 0xd8, 0xb8, 0xb7, 0x96, 0xb7, 0x96, 0xb7, 0x7f, 0x2f, 0x0d, 0x7f,
+ 0x00, 0x7f, 0x0a, 0x4f, 0x25, 0x25, 0x4f, 0x0a, 0x7f, 0x00, 0xb0, 0x0a, 0xda, 0x25,
+ 0xf5, 0x4f, 0xff, 0x80, 0xf1, 0x7f, 0xf1, 0x7f,
+};
+
+
+struct NavigateManipulatorInfo {
+ const char *opname;
+ const char *manipulator;
+ const unsigned char *shape;
+ uint shape_size;
+};
+
+#define SHAPE_VARS(shape_id) shape = shape_id, .shape_size = ARRAY_SIZE(shape_id)
+
+struct NavigateManipulatorInfo g_navigate_params[MPR_TOTAL] = {
+ {
+ .opname = "VIEW3D_OT_move",
+ .manipulator = "MANIPULATOR_WT_button_2d",
+ .SHAPE_VARS(shape_pan),
+ }, {
+ .opname = "VIEW3D_OT_rotate",
+ .manipulator = "VIEW3D_WT_navigate_rotate",
+ .shape = NULL,
+ .shape_size = 0,
+ }, {
+ .opname = "VIEW3D_OT_zoom",
+ .manipulator = "MANIPULATOR_WT_button_2d",
+ .SHAPE_VARS(shape_zoom),
+ }, {
+ .opname = "VIEW3D_OT_view_persportho",
+ .manipulator = "MANIPULATOR_WT_button_2d",
+ .SHAPE_VARS(shape_persp),
+ }, {
+ .opname = "VIEW3D_OT_view_persportho",
+ .manipulator = "MANIPULATOR_WT_button_2d",
+ .SHAPE_VARS(shape_ortho),
+ }, {
+ .opname = "VIEW3D_OT_viewnumpad",
+ .manipulator = "MANIPULATOR_WT_button_2d",
+ .SHAPE_VARS(shape_camera),
+ },
+};
+
+#undef SHAPE_VARS
+
+struct NavigateWidgetGroup {
+ wmManipulator *mpr_array[MPR_TOTAL];
+ /* Store the view state to check for changes. */
+ struct {
+ rcti rect_visible;
+ struct {
+ char is_persp;
+ char is_camera;
+ char viewlock;
+ } rv3d;
+ } state;
+ int region_size[2];
+};
+
+static bool WIDGETGROUP_navigate_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
+ return false;
+ }
+
+ if (U.manipulator_flag & USER_MANIPULATOR_DRAW_NAVIGATE) {
+ return true;
+ }
+ return false;
+
+}
+
+static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__);
+
+ navgroup->region_size[0] = -1;
+ navgroup->region_size[1] = -1;
+
+ wmOperatorType *ot_viewnumpad = WM_operatortype_find("VIEW3D_OT_viewnumpad", true);
+
+ for (int i = 0; i < MPR_TOTAL; i++) {
+ const struct NavigateManipulatorInfo *info = &g_navigate_params[i];
+ navgroup->mpr_array[i] = WM_manipulator_new(info->manipulator, mgroup, NULL);
+ wmManipulator *mpr = navgroup->mpr_array[i];
+ mpr->flag |= WM_MANIPULATOR_GRAB_CURSOR | WM_MANIPULATOR_DRAW_MODAL;
+ mpr->color[3] = 0.2f;
+ mpr->color_hi[3] = 0.4f;
+
+ /* may be overwritten later */
+ mpr->scale_basis = (MANIPULATOR_SIZE * MANIPULATOR_MINI_FAC) / 2;
+ if (info->shape != NULL) {
+ PropertyRNA *prop = RNA_struct_find_property(mpr->ptr, "shape");
+ RNA_property_string_set_bytes(
+ mpr->ptr, prop,
+ (const char *)info->shape, info->shape_size);
+ RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_BUTTON_SHOW_OUTLINE);
+ }
+
+ wmOperatorType *ot = WM_operatortype_find(info->opname, true);
+ WM_manipulator_operator_set(mpr, 0, ot, NULL);
+ }
+
+ {
+ wmManipulator *mpr = navgroup->mpr_array[MPR_CAMERA];
+ PointerRNA *ptr = WM_manipulator_operator_set(mpr, 0, ot_viewnumpad, NULL);
+ RNA_enum_set(ptr, "type", RV3D_VIEW_CAMERA);
+ }
+
+ /* Click only buttons (not modal). */
+ {
+ int mpr_ids[] = {MPR_PERSP, MPR_ORTHO, MPR_CAMERA};
+ for (int i = 0; i < ARRAY_SIZE(mpr_ids); i++) {
+ wmManipulator *mpr = navgroup->mpr_array[mpr_ids[i]];
+ RNA_boolean_set(mpr->ptr, "show_drag", false);
+ }
+ }
+
+ /* Modal operators, don't use initial mouse location since we're clicking on a button. */
+ {
+ int mpr_ids[] = {MPR_MOVE, MPR_ROTATE, MPR_ZOOM};
+ for (int i = 0; i < ARRAY_SIZE(mpr_ids); i++) {
+ wmManipulator *mpr = navgroup->mpr_array[mpr_ids[i]];
+ wmManipulatorOpElem *mpop = WM_manipulator_operator_get(mpr, 0);
+ RNA_boolean_set(&mpop->ptr, "use_mouse_init", false);
+ }
+ }
+
+ {
+ wmManipulator *mpr = navgroup->mpr_array[MPR_ROTATE];
+ mpr->scale_basis = MANIPULATOR_SIZE / 2;
+ char mapping[6] = {
+ RV3D_VIEW_LEFT,
+ RV3D_VIEW_RIGHT,
+ RV3D_VIEW_FRONT,
+ RV3D_VIEW_BACK,
+ RV3D_VIEW_BOTTOM,
+ RV3D_VIEW_TOP,
+ };
+
+ for (int part_index = 0; part_index < 6; part_index += 1) {
+ PointerRNA *ptr = WM_manipulator_operator_set(mpr, part_index + 1, ot_viewnumpad, NULL);
+ RNA_enum_set(ptr, "type", mapping[part_index]);
+ }
+
+ /* When dragging an axis, use this instead. */
+ mpr->drag_part = 0;
+ }
+
+ mgroup->customdata = navgroup;
+}
+
+static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ struct NavigateWidgetGroup *navgroup = mgroup->customdata;
+ ARegion *ar = CTX_wm_region(C);
+ const RegionView3D *rv3d = ar->regiondata;
+
+ for (int i = 0; i < 3; i++) {
+ copy_v3_v3(navgroup->mpr_array[MPR_ROTATE]->matrix_offset[i], rv3d->viewmat[i]);
+ }
+
+ rcti rect_visible;
+ ED_region_visible_rect(ar, &rect_visible);
+
+ if ((navgroup->state.rect_visible.xmax == rect_visible.xmax) &&
+ (navgroup->state.rect_visible.ymax == rect_visible.ymax) &&
+ (navgroup->state.rv3d.is_persp == rv3d->is_persp) &&
+ (navgroup->state.rv3d.is_camera == (rv3d->persp == RV3D_CAMOB)) &&
+ (navgroup->state.rv3d.viewlock == rv3d->viewlock))
+ {
+ return;
+ }
+
+ navgroup->state.rect_visible = rect_visible;
+ navgroup->state.rv3d.is_persp = rv3d->is_persp;
+ navgroup->state.rv3d.is_camera = (rv3d->persp == RV3D_CAMOB);
+ navgroup->state.rv3d.viewlock = rv3d->viewlock;
+
+ const bool show_rotate = (
+ ((rv3d->viewlock & RV3D_LOCKED) == 0) &&
+ (navgroup->state.rv3d.is_camera == false));
+ const bool show_fixed_offset = navgroup->state.rv3d.is_camera;
+ const float icon_size = MANIPULATOR_SIZE;
+ const float icon_offset = (icon_size * 0.52f) * MANIPULATOR_OFFSET_FAC * UI_DPI_FAC;
+ const float icon_offset_mini = icon_size * MANIPULATOR_MINI_OFFSET_FAC * UI_DPI_FAC;
+ const float co_rotate[2] = {
+ rect_visible.xmax - icon_offset,
+ rect_visible.ymax - icon_offset,
+ };
+ const float co[2] = {
+ rect_visible.xmax - ((show_rotate || show_fixed_offset) ? (icon_offset * 2.0f) : (icon_offset_mini * 0.75f)),
+ rect_visible.ymax - icon_offset_mini * 0.75f,
+ };
+
+ wmManipulator *mpr;
+
+ for (uint i = 0; i < ARRAY_SIZE(navgroup->mpr_array); i++) {
+ mpr = navgroup->mpr_array[i];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true);
+ }
+
+ /* RV3D_LOCKED or Camera: only show supported buttons. */
+ if (show_rotate) {
+ mpr = navgroup->mpr_array[MPR_ROTATE];
+ mpr->matrix_basis[3][0] = co_rotate[0];
+ mpr->matrix_basis[3][1] = co_rotate[1];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ }
+
+ int icon_mini_slot = 0;
+
+ mpr = navgroup->mpr_array[MPR_ZOOM];
+ mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ mpr->matrix_basis[3][1] = co[1];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ mpr = navgroup->mpr_array[MPR_MOVE];
+ mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ mpr->matrix_basis[3][1] = co[1];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ mpr = navgroup->mpr_array[MPR_CAMERA];
+ mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ mpr->matrix_basis[3][1] = co[1];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ if (navgroup->state.rv3d.is_camera == false) {
+ mpr = navgroup->mpr_array[rv3d->is_persp ? MPR_PERSP : MPR_ORTHO];
+ mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ mpr->matrix_basis[3][1] = co[1];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ }
+ }
+}
+
+void VIEW3D_WGT_navigate(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "View3D Navigate";
+ wgt->idname = "VIEW3D_WGT_navigate";
+
+ wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
+ WM_MANIPULATORGROUPTYPE_SCALE |
+ WM_MANIPULATORGROUPTYPE_DRAW_MODAL_ALL);
+
+ wgt->poll = WIDGETGROUP_navigate_poll;
+ wgt->setup = WIDGETGROUP_navigate_setup;
+ wgt->draw_prepare = WIDGETGROUP_navigate_draw_prepare;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
new file mode 100644
index 00000000000..b232be35462
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
@@ -0,0 +1,309 @@
+/*
+ * ***** 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 view3d_manipulator_navigate_type.c
+ * \ingroup wm
+ *
+ * \name Custom Orientation/Navigation Manipulator for the 3D View
+ *
+ * \brief Simple manipulator to axis and translate.
+ *
+ * - scale_basis: used for the size.
+ * - matrix_basis: used for the location.
+ * - matrix_offset: used to store the orientation.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_sort_utils.h"
+
+#include "BKE_context.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+
+#include "view3d_intern.h"
+
+#define DIAL_RESOLUTION 32
+
+#define HANDLE_SIZE 0.33
+
+static void axis_geom_draw(
+ const wmManipulator *mpr, const float color[4], const bool UNUSED(select))
+{
+ glLineWidth(mpr->line_width);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ const uint pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ /* flip z for reverse */
+ const float cone_coords[5][3] = {
+ {-1, -1, 4},
+ {-1, +1, 4},
+ {+1, +1, 4},
+ {+1, -1, 4},
+ {0, 0, 2},
+ };
+
+ struct {
+ float depth;
+ char index;
+ char axis;
+ char is_pos;
+ } axis_order[6] = {
+ {-mpr->matrix_offset[0][2], 0, 0, false},
+ {+mpr->matrix_offset[0][2], 1, 0, true},
+ {-mpr->matrix_offset[1][2], 2, 1, false},
+ {+mpr->matrix_offset[1][2], 3, 1, true},
+ {-mpr->matrix_offset[2][2], 4, 2, false},
+ {+mpr->matrix_offset[2][2], 5, 2, true},
+ };
+ qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float);
+
+ const float scale_axis = 0.25f;
+ static const float axis_highlight[4] = {1, 1, 1, 1};
+ static const float axis_nop[4] = {1, 1, 1, 0};
+ static const float axis_black[4] = {0, 0, 0, 1};
+ static float axis_color[3][4];
+ gpuPushMatrix();
+ gpuMultMatrix(mpr->matrix_offset);
+
+ bool draw_center_done = false;
+
+ for (int axis_index = 0; axis_index < ARRAY_SIZE(axis_order); axis_index++) {
+ const int index = axis_order[axis_index].index;
+ const int axis = axis_order[axis_index].axis;
+ const bool is_pos = axis_order[axis_index].is_pos;
+
+ /* Draw slightly before, so axis aligned arrows draw ontop. */
+ if ((draw_center_done == false) && (axis_order[axis_index].depth > -0.01f)) {
+
+ /* Circle defining active area (revert back to 2D space). */
+ {
+ gpuPopMatrix();
+ immUniformColor4fv(color);
+ imm_draw_circle_fill_3d(pos_id, 0, 0, 1.0f, DIAL_RESOLUTION);
+ gpuPushMatrix();
+ gpuMultMatrix(mpr->matrix_offset);
+ }
+
+ /* Center cube. */
+ {
+ float center[3], size[3];
+
+ zero_v3(center);
+ copy_v3_fl(size, HANDLE_SIZE);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_TRUE);
+ glDepthFunc(GL_LEQUAL);
+ glBlendFunc(GL_ONE, GL_ZERO);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glLineWidth(1.0f);
+ /* Just draw depth values. */
+ immUniformColor4fv(axis_nop);
+ imm_draw_cube_fill_3d(pos_id, center, size);
+ immUniformColor4fv(axis_black);
+ madd_v3_v3fl(
+ center,
+ (float[3]){
+ mpr->matrix_offset[0][2],
+ mpr->matrix_offset[1][2],
+ mpr->matrix_offset[2][2],
+ },
+ 0.08f);
+ imm_draw_cube_wire_3d(pos_id, center, size);
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ draw_center_done = true;
+ }
+ UI_GetThemeColor3fv(TH_AXIS_X + axis, axis_color[axis]);
+ axis_color[axis][3] = 1.0f;
+
+ const int index_z = axis;
+ const int index_y = (axis + 1) % 3;
+ const int index_x = (axis + 2) % 3;
+
+#define ROTATED_VERT(v_orig) \
+ { \
+ float v[3]; \
+ copy_v3_v3(v, v_orig); \
+ if (is_pos == 0) { \
+ v[2] *= -1.0f; \
+ } \
+ immVertex3f(pos_id, v[index_x] * scale_axis, v[index_y] * scale_axis, v[index_z] * scale_axis); \
+ } ((void)0)
+
+ bool ok = true;
+
+ /* skip view align axis */
+ if (len_squared_v2(mpr->matrix_offset[axis]) < 1e-6f && (mpr->matrix_offset[axis][2] > 0.0f) == is_pos) {
+ ok = false;
+ }
+ if (ok) {
+ immUniformColor4fv(index + 1 == mpr->highlight_part ? axis_highlight : axis_color[axis]);
+ immBegin(GWN_PRIM_TRI_FAN, 6);
+ ROTATED_VERT(cone_coords[4]);
+ for (int j = 0; j <= 4; j++) {
+ ROTATED_VERT(cone_coords[j % 4]);
+ }
+ immEnd();
+ }
+
+#undef ROTATED_VERT
+ }
+
+ gpuPopMatrix();
+ immUnbindProgram();
+}
+
+static void axis3d_draw_intern(
+ const bContext *UNUSED(C), wmManipulator *mpr,
+ const bool select, const bool highlight)
+{
+ const float *color = highlight ? mpr->color_hi : mpr->color;
+ float matrix_final[4][4];
+ float matrix_unit[4][4];
+
+ unit_m4(matrix_unit);
+
+ WM_manipulator_calc_matrix_final_params(
+ mpr,
+ &((struct WM_ManipulatorMatrixParams) {
+ .matrix_offset = matrix_unit,
+ }), matrix_final);
+
+ gpuPushMatrix();
+ gpuMultMatrix(matrix_final);
+
+ glEnable(GL_BLEND);
+ axis_geom_draw(mpr, color, select);
+ glDisable(GL_BLEND);
+ gpuPopMatrix();
+}
+
+static void manipulator_axis_draw(const bContext *C, wmManipulator *mpr)
+{
+ const bool is_modal = mpr->state & WM_MANIPULATOR_STATE_MODAL;
+ const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
+
+ (void)is_modal;
+
+ glEnable(GL_BLEND);
+ axis3d_draw_intern(C, mpr, false, is_highlight);
+ glDisable(GL_BLEND);
+}
+
+static int manipulator_axis_test_select(
+ bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event)
+{
+ float point_local[2] = {UNPACK2(event->mval)};
+ sub_v2_v2(point_local, mpr->matrix_basis[3]);
+ mul_v2_fl(point_local, 1.0f / (mpr->scale_basis * UI_DPI_FAC));
+
+ const float len_sq = len_squared_v2(point_local);
+ if (len_sq > 1.0) {
+ return -1;
+ }
+
+ int part_best = -1;
+ int part_index = 1;
+ /* Use 'SQUARE(HANDLE_SIZE)' if we want to be able to _not_ focus on one of the axis. */
+ float i_best_len_sq = FLT_MAX;
+ for (int i = 0; i < 3; i++) {
+ for (int is_pos = 0; is_pos < 2; is_pos++) {
+ float co[2] = {
+ mpr->matrix_offset[i][0] * (is_pos ? 1 : -1),
+ mpr->matrix_offset[i][1] * (is_pos ? 1 : -1),
+ };
+
+ bool ok = true;
+
+ /* Check if we're viewing on an axis, there is no point to clicking on the current axis so show the reverse. */
+ if (len_squared_v2(co) < 1e-6f && (mpr->matrix_offset[i][2] > 0.0f) == is_pos) {
+ ok = false;
+ }
+
+ if (ok) {
+ const float len_axis_sq = len_squared_v2v2(co, point_local);
+ if (len_axis_sq < i_best_len_sq) {
+ part_best = part_index;
+ i_best_len_sq = len_axis_sq;
+ }
+ }
+ part_index += 1;
+ }
+ }
+
+ if (part_best != -1) {
+ return part_best;
+ }
+
+ /* The 'mpr->scale_final' is already applied when projecting. */
+ if (len_sq < 1.0f) {
+ return 0;
+ }
+
+ return -1;
+}
+
+static int manipulator_axis_cursor_get(wmManipulator *mpr)
+{
+ if (mpr->highlight_part > 0) {
+ return CURSOR_EDIT;
+ }
+ return BC_NSEW_SCROLLCURSOR;
+}
+
+void VIEW3D_WT_navigate_rotate(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "VIEW3D_WT_navigate_rotate";
+
+ /* api callbacks */
+ wt->draw = manipulator_axis_draw;
+ wt->test_select = manipulator_axis_test_select;
+ wt->cursor_get = manipulator_axis_cursor_get;
+
+ wt->struct_size = sizeof(wmManipulator);
+}
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..8178c2f5be9
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
@@ -0,0 +1,1100 @@
+/*
+ * ***** 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_gpencil.h"
+#include "BKE_main.h"
+
+#include "BKE_object.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 "WM_toolsystem.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_remove(bContext *C, wmManipulatorGroup *mgroup, RulerItem *ruler_item)
+{
+ WM_manipulator_unlink(&mgroup->manipulators, mgroup->parent_mmap, &ruler_item->mpr, C);
+}
+
+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)
+{
+ Main *bmain = CTX_data_main(C);
+ 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(
+ bmain, CTX_data_scene(C), CTX_data_depsgraph(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(
+ ruler_info->snap_context,
+ SCE_SNAP_MODE_FACE,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = true,
+ },
+ mval_fl, &dist_px,
+ 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) {
+ const float mval_fl[2] = {UNPACK2(mval)};
+
+ if (ED_transform_snap_object_project_view3d(
+ ruler_info->snap_context,
+ (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE),
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = true,
+ .use_occlusion_test = true,
+ },
+ mval_fl, &dist_px,
+ 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;
+ Main *bmain = CTX_data_main(C);
+ 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(bmain, "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;
+
+ if (!cancel) {
+ if (ruler_info->state == RULER_STATE_DRAG) {
+ RulerItem *ruler_item = (RulerItem *)mpr;
+ RulerInteraction *inter = mpr->interaction_data;
+ /* rubber-band angle removal */
+ if (!inter->inside_region) {
+ if ((inter->co_index == 1) && (ruler_item->flag & RULERITEM_USE_ANGLE)) {
+ ruler_item->flag &= ~RULERITEM_USE_ANGLE;
+ }
+ else {
+ /* Not ideal, since the ruler isn't a mode and we don't want to override delete key
+ * use dragging out of the view for removal. */
+ ruler_item_remove(C, mgroup, ruler_item);
+ ruler_item = NULL;
+ mpr = NULL;
+ inter = NULL;
+ }
+ }
+ 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);
+ }
+
+ if (mpr) {
+ 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)
+{
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
+ if ((tref_rt == NULL) ||
+ !STREQ(wgt->idname, tref_rt->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 | WM_MANIPULATORGROUPTYPE_DRAW_MODAL_ALL;
+
+ 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)
+{
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
+ if ((tref_rt == NULL) ||
+ !STREQ(view3d_wgt_ruler_id, tref_rt->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 5734fba84b5..267712b3339 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -45,6 +45,7 @@
#include "BKE_appdir.h"
#include "BKE_blender_copybuffer.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -80,12 +81,14 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- for (Group *group = bmain->group.first; group; group = group->id.next) {
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- if (go->ob && (go->ob->id.tag & LIB_TAG_DOIT)) {
- BKE_copybuffer_tag_ID(&group->id);
+ for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Object *object = cob->ob;
+
+ if (object && (object->id.tag & LIB_TAG_DOIT)) {
+ BKE_copybuffer_tag_ID(&collection->id);
/* don't expand out to all other objects */
- group->id.tag &= ~LIB_TAG_NEED_EXPAND;
+ collection->id.tag &= ~LIB_TAG_NEED_EXPAND;
break;
}
}
@@ -119,8 +122,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 +155,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,16 +196,12 @@ 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);
WM_operatortype_append(VIEW3D_OT_select_menu);
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);
WM_operatortype_append(VIEW3D_OT_navigate);
@@ -223,6 +222,10 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_snap_cursor_to_active);
WM_operatortype_append(VIEW3D_OT_toggle_render);
+ WM_operatortype_append(VIEW3D_OT_toggle_xray_draw_option);
+ WM_operatortype_append(VIEW3D_OT_toggle_matcap_flip);
+
+ WM_operatortype_append(VIEW3D_OT_ruler_add);
transform_operatortypes();
}
@@ -240,24 +243,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);
@@ -316,6 +302,8 @@ void view3d_keymap(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", CKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "center", true);
+ WM_keymap_add_menu_pie(keymap, "VIEW3D_MT_view_pie", ACCENTGRAVEKEY, KM_CLICK_DRAG, 0, 0);
+
/* numpad view hotkeys*/
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD0, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_CAMERA);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD1, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
@@ -373,8 +361,6 @@ void view3d_keymap(wmKeyConfig *keyconf)
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 */
/* 3D mouse */
@@ -406,32 +392,17 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "align_active", true);
#endif /* WITH_INPUT_NDOF */
- /* layers, shift + alt are properties set in invoke() */
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ACCENTGRAVEKEY, KM_PRESS, 0, 0)->ptr, "nr", 0);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ONEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 1);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", TWOKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 2);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", THREEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 3);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", FOURKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 4);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", FIVEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 5);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", SIXKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 6);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", SEVENKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 7);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", EIGHTKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 8);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", NINEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 9);
- RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ZEROKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 10);
-
/* drawtype */
-
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", ZKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.viewport_shade");
- RNA_string_set(kmi->ptr, "value_1", "SOLID");
- RNA_string_set(kmi->ptr, "value_2", "WIREFRAME");
-
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", ZKEY, KM_PRESS, KM_ALT, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.viewport_shade");
+ RNA_string_set(kmi->ptr, "data_path", "space_data.shading.type");
RNA_string_set(kmi->ptr, "value_1", "SOLID");
RNA_string_set(kmi->ptr, "value_2", "TEXTURED");
WM_keymap_add_item(keymap, "VIEW3D_OT_toggle_render", ZKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_toggle_xray_draw_option", ZKEY, KM_PRESS, 0, 0);
+
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", ZKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.use_occlude_geometry");
/* selection*/
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
@@ -524,31 +495,32 @@ void view3d_keymap(wmKeyConfig *keyconf)
/* context ops */
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "BOUNDING_BOX_CENTER");
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, KM_CTRL, 0); /* 2.4x allowed Comma+Shift too, rather not use both */
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ /* 2.4x allowed Comma+Shift too, rather not use both */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "MEDIAN_POINT");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", COMMAKEY, KM_PRESS, KM_ALT, 0); /* new in 2.5 */
- RNA_string_set(kmi->ptr, "data_path", "space_data.use_pivot_point_align");
-
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SPACEKEY, KM_PRESS, KM_CTRL, 0); /* new in 2.5 */
- RNA_string_set(kmi->ptr, "data_path", "space_data.show_manipulator");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_transform_pivot_point_align");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "CURSOR");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, KM_CTRL, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "INDIVIDUAL_ORIGINS");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, KM_ALT, 0);
- RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.transform_pivot_point");
RNA_string_set(kmi->ptr, "value", "ACTIVE_ELEMENT");
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SPACEKEY, KM_PRESS, KM_CTRL, 0); /* new in 2.5 */
+ RNA_string_set(kmi->ptr, "data_path", "space_data.show_manipulator");
+
transform_keymap_for_space(keyconf, keymap, SPACE_VIEW3D);
fly_modal_keymap(keyconf);
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 767df04c0b0..30b91c1a8ee 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
@@ -315,6 +314,7 @@ float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3], bool *r_f
}
static void view3d_win_to_ray_segment(
+ struct Depsgraph *depsgraph,
const ARegion *ar, const View3D *v3d, const float mval[2],
float r_ray_co[3], float r_ray_dir[3], float r_ray_start[3], float r_ray_end[3])
{
@@ -332,7 +332,7 @@ static void view3d_win_to_ray_segment(
start_offset = -end_offset;
}
else {
- ED_view3d_clip_range_get(v3d, rv3d, &start_offset, &end_offset, false);
+ ED_view3d_clip_range_get(depsgraph, v3d, rv3d, &start_offset, &end_offset, false);
}
if (r_ray_start) {
@@ -371,12 +371,13 @@ bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float
* \return success, false if the ray is totally clipped.
*/
bool ED_view3d_win_to_ray_ex(
+ struct Depsgraph *depsgraph,
const ARegion *ar, const View3D *v3d, const float mval[2],
float r_ray_co[3], float r_ray_normal[3], float r_ray_start[3], bool do_clip)
{
float ray_end[3];
- view3d_win_to_ray_segment(ar, v3d, mval, r_ray_co, r_ray_normal, r_ray_start, ray_end);
+ view3d_win_to_ray_segment(depsgraph, ar, v3d, mval, r_ray_co, r_ray_normal, r_ray_start, ray_end);
/* bounds clipping */
if (do_clip) {
@@ -400,10 +401,11 @@ bool ED_view3d_win_to_ray_ex(
* \return success, false if the ray is totally clipped.
*/
bool ED_view3d_win_to_ray(
+ struct Depsgraph *depsgraph,
const ARegion *ar, const View3D *v3d, const float mval[2],
float r_ray_start[3], float r_ray_normal[3], const bool do_clip)
{
- return ED_view3d_win_to_ray_ex(ar, v3d, mval, NULL, r_ray_normal, r_ray_start, do_clip);
+ return ED_view3d_win_to_ray_ex(depsgraph, ar, v3d, mval, NULL, r_ray_normal, r_ray_start, do_clip);
}
/**
@@ -633,10 +635,11 @@ void ED_view3d_win_to_vector(const ARegion *ar, const float mval[2], float out[3
* \param do_clip Optionally clip the ray by the view clipping planes.
* \return success, false if the segment is totally clipped.
*/
-bool ED_view3d_win_to_segment(const ARegion *ar, View3D *v3d, const float mval[2],
+bool ED_view3d_win_to_segment(struct Depsgraph *depsgraph,
+ const ARegion *ar, View3D *v3d, const float mval[2],
float r_ray_start[3], float r_ray_end[3], const bool do_clip)
{
- view3d_win_to_ray_segment(ar, v3d, mval, NULL, NULL, r_ray_start, r_ray_end);
+ view3d_win_to_ray_segment(depsgraph, ar, v3d, mval, NULL, NULL, r_ray_start, r_ray_end);
/* bounds clipping */
if (do_clip) {
@@ -666,16 +669,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 012f71c10ba..e001ed9112b 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -44,6 +44,9 @@
#include "BIF_gl.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -265,6 +268,7 @@ static bool view3d_ruler_pick(RulerInfo *ruler_info, const float mval[2],
*/
static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
{
+ Main *bmain = CTX_data_main(C);
if (state == ruler_info->state) {
return;
}
@@ -280,7 +284,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,
+ bmain, CTX_data_scene(C), CTX_data_depsgraph(C), 0,
ruler_info->ar, CTX_wm_view3d(C));
}
else {
@@ -427,12 +431,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);
@@ -457,28 +460,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];
@@ -502,46 +514,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 */
@@ -562,75 +547,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 */
{
@@ -640,22 +634,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));
+ }
}
}
@@ -674,8 +702,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();
}
}
@@ -730,14 +764,14 @@ static bool view3d_ruler_item_mousemove(
co_other = ruler_item->co[ruler_item->co_index == 0 ? 2 : 0];
- if (ED_transform_snap_object_project_view3d_mixed(
+ if (ED_transform_snap_object_project_view3d(
ruler_info->snap_context,
- SCE_SELECT_FACE,
+ SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
.use_object_edit_cage = true,
},
- mval_fl, &dist_px, true,
+ mval_fl, &dist_px,
co, ray_normal))
{
negate_v3(ray_normal);
@@ -754,19 +788,17 @@ static bool view3d_ruler_item_mousemove(
}
}
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(
+ if (ED_transform_snap_object_project_view3d(
ruler_info->snap_context,
- (SCE_SELECT_VERTEX | SCE_SELECT_EDGE) | (use_depth ? SCE_SELECT_FACE : 0),
+ (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE),
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
.use_object_edit_cage = true,
+ .use_occlusion_test = true,
},
- mval_fl, &dist_px, use_depth,
+ mval_fl, &dist_px,
co, NULL))
{
ruler_info->snap_flag |= RULER_SNAP_OK;
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index c3a8374d82e..b4f3be178aa 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -47,6 +47,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_array.h"
#include "BLI_math.h"
#include "BLI_lasso_2d.h"
#include "BLI_rect.h"
@@ -55,6 +56,10 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#ifdef __BIG_ENDIAN__
+# include "BLI_endian_switch.h"
+#endif
+
/* vertex box select */
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -63,16 +68,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"
@@ -94,6 +99,8 @@
#include "UI_interface.h"
#include "GPU_draw.h"
+#include "GPU_glew.h"
+#include "GPU_matrix.h"
#include "view3d_intern.h" /* own include */
@@ -110,7 +117,9 @@ void ED_view3d_viewcontext_init(bContext *C, ViewContext *vc)
memset(vc, 0, sizeof(ViewContext));
vc->ar = CTX_wm_region(C);
vc->bmain = CTX_data_main(C);
+ vc->depsgraph = CTX_data_depsgraph(C);
vc->scene = CTX_data_scene(C);
+ vc->view_layer = CTX_data_view_layer(C);
vc->v3d = CTX_wm_view3d(C);
vc->win = CTX_wm_window(C);
vc->rv3d = CTX_wm_region_view3d(C);
@@ -118,32 +127,19 @@ void ED_view3d_viewcontext_init(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)
+void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
{
- float cpy[4][4];
- int i, j;
-
- if (ob) {
- mul_m4_m4m4(cpy, rv3d->viewmat, ob->obmat);
- }
- else {
- copy_m4_m4(cpy, rv3d->viewmat);
- }
+ vc->obact = obact;
+ if (vc->obedit) {
+ BLI_assert(BKE_object_is_in_editmode(obact));
+ vc->obedit = obact;
+ /* previous selections are now invalid. */
+ vc->v3d->flag |= V3D_INVALID_BACKBUF;
- 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];
+ if (vc->em) {
+ vc->em = BKE_editmesh_from_object(vc->obedit);
}
}
-
- 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 ********************* */
@@ -398,18 +394,20 @@ 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);
}
+ /* bone selection status is on armature not object */
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
}
}
-static void object_deselect_all_visible(Scene *scene, View3D *v3d)
+static void object_deselect_all_visible(ViewLayer *view_layer)
{
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 = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTABLE(base)) {
+ ED_object_base_select(base, BA_DESELECT);
}
}
}
@@ -418,21 +416,24 @@ static void do_lasso_select_objects(
ViewContext *vc, const int mcords[][2], const short moves,
const bool extend, const bool select)
{
+ bool is_pose_mode = vc->obact ? (vc->obact->mode & OB_MODE_POSE) : false;
Base *base;
if (extend == false && select)
- object_deselect_all_visible(vc->scene, vc->v3d);
+ object_deselect_all_visible(vc->view_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 */
- if (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) {
+ for (base = vc->view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTABLE(base)) { /* use this to avoid un-needed lasso lookups */
+ if (((vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
+ (is_pose_mode == false) : true) &&
+ 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)) {
+ if (is_pose_mode && (base->object->mode & OB_MODE_POSE)) {
do_lasso_select_pose(vc, base->object, mcords, moves, select);
}
}
@@ -487,7 +488,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(
+ ViewContext *vc,
+ const int mcords[][2], short moves, bool extend, bool select)
{
LassoSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
@@ -507,7 +510,7 @@ 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);
+ gpuLoadMatrix(vc->rv3d->viewmat);
bbsel = EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
if (ts->selectmode & SCE_SELECT_VERTEX) {
@@ -542,8 +545,7 @@ static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short m
EDBM_selectmode_flush(vc->em);
}
-static void do_lasso_select_curve__doSelect(
- void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
+static void do_lasso_select_curve__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
{
LassoSelectUserData *data = userData;
Object *obedit = data->vc->obedit;
@@ -618,8 +620,7 @@ static void do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], shor
lattice_foreachScreenVert(vc, do_lasso_select_lattice__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
-static void do_lasso_select_armature__doSelectBone(
- void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2])
+static void do_lasso_select_armature__doSelectBone(void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2])
{
LassoSelectUserData *data = userData;
bArmature *arm = data->vc->obedit->data;
@@ -725,8 +726,7 @@ static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short m
mball_foreachScreenElem(vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
-static void do_lasso_select_meshobject__doSelectVert(
- void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
+static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
{
LassoSelectUserData *data = userData;
@@ -839,44 +839,55 @@ static void view3d_lasso_select(
Object *ob = CTX_data_active_object(C);
if (vc->obedit == NULL) { /* Object Mode */
- if (BKE_paint_select_face_test(ob))
+ if (BKE_paint_select_face_test(ob)) {
do_lasso_select_paintface(vc, mcords, moves, extend, select);
- else if (BKE_paint_select_vert_test(ob))
+ }
+ else if (BKE_paint_select_vert_test(ob)) {
do_lasso_select_paintvert(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);
+ DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
}
}
else { /* Edit Mode */
- switch (vc->obedit->type) {
- case OB_MESH:
- do_lasso_select_mesh(vc, mcords, moves, extend, select);
- break;
- case OB_CURVE:
- case OB_SURF:
- do_lasso_select_curve(vc, mcords, moves, extend, select);
- break;
- case OB_LATTICE:
- do_lasso_select_lattice(vc, mcords, moves, extend, select);
- break;
- case OB_ARMATURE:
- do_lasso_select_armature(vc, mcords, moves, extend, select);
- break;
- case OB_MBALL:
- do_lasso_select_meta(vc, mcords, moves, extend, select);
- break;
- default:
- assert(!"lasso select on incorrect object type");
- break;
- }
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data);
+ FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, ob->mode, ob_iter) {
+ ED_view3d_viewcontext_init_object(vc, ob_iter);
+
+ switch (vc->obedit->type) {
+ case OB_MESH:
+ do_lasso_select_mesh(vc, mcords, moves, extend, select);
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ do_lasso_select_curve(vc, mcords, moves, extend, select);
+ break;
+ case OB_LATTICE:
+ do_lasso_select_lattice(vc, mcords, moves, extend, select);
+ break;
+ case OB_ARMATURE:
+ do_lasso_select_armature(vc, mcords, moves, extend, select);
+ break;
+ case OB_MBALL:
+ do_lasso_select_meta(vc, mcords, moves, extend, select);
+ break;
+ default:
+ assert(!"lasso select on incorrect object type");
+ break;
+ }
+
+ DEG_id_tag_update(vc->obedit->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
}
}
@@ -974,8 +985,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;
}
}
@@ -986,8 +997,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;
}
}
@@ -998,7 +1009,9 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
/* undo? */
if (changed) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
else {
@@ -1031,14 +1044,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(ViewLayer *view_layer, Base *b) /* deselect all except b */
{
- Base *base;
-
- for (base = FIRSTBASE; base; base = base->next) {
- if (base->flag & SELECT) {
+ for (Base *base = view_layer->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);
}
}
}
@@ -1052,6 +1063,7 @@ static Base *object_mouse_select_menu(
bool ok;
LinkNode *linklist = NULL;
+ /* handle base->object->select_color */
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
ok = false;
@@ -1060,7 +1072,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;
}
@@ -1160,7 +1172,7 @@ static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits15, const
/* so check three selection levels and compare */
static int mixed_bones_object_selectbuffer(
ViewContext *vc, unsigned int *buffer, const int mval[2],
- bool use_cycle, bool enumerate,
+ bool use_cycle, bool enumerate, eV3DSelectObjectFilter select_filter,
bool *r_do_nearest)
{
rcti rect;
@@ -1199,7 +1211,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(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
if (hits15 == 1) {
hits = selectbuffer_ret_hits_15(buffer, hits15);
goto finally;
@@ -1210,7 +1222,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(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
if (hits9 == 1) {
hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
goto finally;
@@ -1220,7 +1232,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(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
if (hits5 == 1) {
hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
goto finally;
@@ -1242,6 +1254,23 @@ static int mixed_bones_object_selectbuffer(
finally:
view3d_opengl_select_cache_end();
+ if (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ const bool is_pose_mode = (vc->obact && vc->obact->mode & OB_MODE_POSE);
+ struct {
+ uint data[4];
+ } *buffer4 = (void *)buffer;
+ uint j = 0;
+ for (uint i = 0; i < hits; i++) {
+ if (((buffer4[i].data[3] & 0xFFFF0000) != 0) == is_pose_mode) {
+ if (i != j) {
+ buffer4[j] = buffer4[i];
+ }
+ j++;
+ }
+ }
+ hits = j;
+ }
+
return hits;
}
@@ -1250,8 +1279,7 @@ static Base *mouse_select_eval_buffer(
ViewContext *vc, const uint *buffer, int hits,
Base *startbase, bool has_bones, bool do_nearest)
{
- Scene *scene = vc->scene;
- View3D *v3d = vc->v3d;
+ ViewLayer *view_layer = vc->view_layer;
Base *base, *basact = NULL;
int a;
@@ -1271,7 +1299,9 @@ static Base *mouse_select_eval_buffer(
}
else {
/* only exclude active object when it is selected... */
- if (BASACT && (BASACT->flag & SELECT) && hits > 1) notcol = BASACT->selcol;
+ if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) {
+ notcol = BASACT(view_layer)->object->select_color;
+ }
for (a = 0; a < hits; a++) {
if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) {
@@ -1281,10 +1311,10 @@ static Base *mouse_select_eval_buffer(
}
}
- base = FIRSTBASE;
+ base = FIRSTBASE(view_layer);
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;
}
@@ -1296,23 +1326,23 @@ static Base *mouse_select_eval_buffer(
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(view_layer);
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;
}
}
@@ -1321,7 +1351,7 @@ static Base *mouse_select_eval_buffer(
if (basact) break;
base = base->next;
- if (base == NULL) base = FIRSTBASE;
+ if (base == NULL) base = FIRSTBASE(view_layer);
if (base == startbase) break;
}
}
@@ -1340,13 +1370,17 @@ 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);
+
ED_view3d_viewcontext_init(C, &vc);
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, false, false, &do_nearest);
+ hits = mixed_bones_object_selectbuffer(
+ &vc, buffer, mval,
+ false, false, VIEW3D_SELECT_FILTER_NOP,
+ &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.view_layer->object_bases.first, has_bones, do_nearest);
}
return basact;
@@ -1378,16 +1412,16 @@ static bool ed_object_select_pick(
{
ViewContext vc;
ARegion *ar = CTX_wm_region(C);
- View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
- Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base, *startbase = NULL, *basact = NULL, *oldbasact = BASACT(view_layer);
+ const eObjectMode object_mode = oldbasact ? oldbasact->object->mode : OB_MODE_OBJECT;
bool is_obedit;
float dist = ED_view3d_select_dist_px() * 1.3333f;
bool retval = false;
int hits;
const float mval_fl[2] = {(float)mval[0], (float)mval[1]};
-
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc);
@@ -1397,9 +1431,12 @@ static bool ed_object_select_pick(
vc.obedit = NULL;
}
+ /* In pose mode we don't want to mess with object selection. */
+ const bool is_pose_mode = (vc.obact && vc.obact->mode & OB_MODE_POSE);
+
/* always start list from basact in wire mode */
- startbase = FIRSTBASE;
- if (BASACT && BASACT->next) startbase = BASACT->next;
+ startbase = FIRSTBASE(view_layer);
+ if (BASACT(view_layer) && BASACT(view_layer)->next) startbase = BASACT(view_layer)->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 */
@@ -1412,14 +1449,14 @@ 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(view_layer)) dist_temp += 10.0f;
if (dist_temp < dist) {
dist = dist_temp;
basact = base;
@@ -1428,10 +1465,23 @@ static bool ed_object_select_pick(
}
base = base->next;
- if (base == NULL) base = FIRSTBASE;
+ if (base == NULL) base = FIRSTBASE(view_layer);
if (base == startbase) break;
}
}
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ if (is_obedit == false) {
+ if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
+ if (object_mode == OB_MODE_OBJECT) {
+ struct Main *bmain = CTX_data_main(C);
+ ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
+ }
+ if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
+ basact = NULL;
+ }
+ }
+ }
+ }
}
else {
unsigned int buffer[MAXPICKBUF];
@@ -1440,7 +1490,13 @@ 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);
+ const eV3DSelectObjectFilter select_filter = (
+ (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
+ VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP);
+ hits = mixed_bones_object_selectbuffer(
+ &vc, buffer, mval,
+ true, enumerate, select_filter,
+ &do_nearest);
// TIMEIT_END(select_time);
@@ -1456,9 +1512,23 @@ static bool ed_object_select_pick(
basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest);
}
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ if (is_obedit == false) {
+ if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
+ if (object_mode == OB_MODE_OBJECT) {
+ struct Main *bmain = CTX_data_main(C);
+ ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
+ }
+ if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
+ basact = NULL;
+ }
+ }
+ }
+ }
+
if (has_bones && basact) {
if (basact->object->type == OB_CAMERA) {
- if (BASACT == basact) {
+ if (BASACT(view_layer) == basact) {
int i, hitresult;
bool changed = false;
@@ -1467,7 +1537,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;
}
@@ -1496,11 +1566,12 @@ 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;
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, track);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -1516,73 +1587,88 @@ static bool ed_object_select_pick(
}
}
else if (ED_armature_pose_select_pick_with_buffer(
- scene, basact, buffer, hits, extend, deselect, toggle, do_nearest))
+ view_layer, 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(view_layer) && (BASACT(view_layer)->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(view_layer))
basact = NULL;
}
}
}
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ /* Disallow switching modes,
+ * special exception for edit-mode - vertex-parent operator. */
+ if (is_obedit == false) {
+ if (oldbasact && basact) {
+ if ((oldbasact->object->mode != basact->object->mode) &&
+ (oldbasact->object->mode & basact->object->mode) == 0)
+ {
+ basact = NULL;
+ }
+ }
+ }
+ }
+
/* so, do we have something selected? */
if (basact) {
retval = true;
if (vc.obedit) {
/* only do select */
- deselectall_except(scene, basact);
- ED_base_object_select(basact, BA_SELECT);
+ deselectall_except(view_layer, basact);
+ ED_object_base_select(basact, BA_SELECT);
}
/* also prevent making it active on mouse selection */
- else if (BASE_SELECTABLE(v3d, basact)) {
-
- oldbasact = BASACT;
-
+ else if (BASE_SELECTABLE(basact)) {
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);
+ /* When enabled, this puts other objects out of multi pose-mode. */
+ if (is_pose_mode == false) {
+ deselectall_except(view_layer, 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 */
}
}
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
@@ -1636,7 +1722,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(
+ ViewContext *vc, rcti *rect, bool select, bool extend)
{
const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
Mesh *me;
@@ -1825,7 +1912,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(
+ ViewContext *vc, rcti *rect, bool select, bool extend)
{
BoxSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
@@ -1839,7 +1927,7 @@ 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);
+ gpuLoadMatrix(vc->rv3d->viewmat);
bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
if (ts->selectmode & SCE_SELECT_VERTEX) {
@@ -1878,7 +1966,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(
+ ViewContext *vc,
+ const rcti *rect, bool select, bool extend)
{
MetaBall *mb = (MetaBall *)vc->obedit->data;
MetaElem *ml;
@@ -1887,7 +1977,9 @@ 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(
+ vc, buffer, MAXPICKBUF, rect,
+ VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
if (extend == false && select)
BKE_mball_deselect_all(mb);
@@ -1912,22 +2004,34 @@ 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(
+ ViewContext *vc,
+ const rcti *rect, bool select, bool extend)
{
- bArmature *arm = vc->obedit->data;
int a;
unsigned int buffer[MAXPICKBUF];
int hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL);
+ hits = view3d_opengl_select(
+ vc, buffer, MAXPICKBUF, rect,
+ VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc->view_layer, &objects_len);
/* clear flag we use to detect point was affected */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next)
- ebone->flag &= ~BONE_DONE;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ bArmature *arm = obedit->data;
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ ebone->flag &= ~BONE_DONE;
+ }
+ }
- if (extend == false && select)
- ED_armature_edit_deselect_all_visible(vc->obedit);
+ if (extend == false && select) {
+ ED_armature_edit_deselect_all_visible_multi(objects, objects_len);
+ }
/* first we only check points inside the border */
for (a = 0; a < hits; a++) {
@@ -1936,7 +2040,9 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
if ((index & 0xFFFF0000) == 0) {
continue;
}
- EditBone *ebone = BLI_findlink(arm->edbo, index & ~(BONESEL_ANY));
+
+ EditBone *ebone;
+ ED_armature_object_and_ebone_from_select_buffer(objects, objects_len, index, &ebone);
if ((select == false) || ((ebone->flag & BONE_UNSELECTABLE) == 0)) {
if (index & BONESEL_TIP) {
ebone->flag |= BONE_DONE;
@@ -1954,10 +2060,14 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
}
/* now we have to flush tag from parents... */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- if (ebone->parent->flag & BONE_DONE) {
- ebone->flag |= BONE_DONE;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ bArmature *arm = obedit->data;
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ if (ebone->parent->flag & BONE_DONE) {
+ ebone->flag |= BONE_DONE;
+ }
}
}
}
@@ -1967,7 +2077,8 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
int index = buffer[(4 * a) + 3];
if (index != -1) {
if (index & BONESEL_BONE) {
- EditBone *ebone = BLI_findlink(arm->edbo, index & ~(BONESEL_ANY));
+ EditBone *ebone;
+ ED_armature_object_and_ebone_from_select_buffer(objects, objects_len, index, &ebone);
if ((select == false) || ((ebone->flag & BONE_UNSELECTABLE) == 0)) {
if (!(ebone->flag & BONE_DONE)) {
if (select) {
@@ -1982,45 +2093,82 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
}
}
- ED_armature_edit_sync_selection(arm->edbo);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ bArmature *arm = obedit->data;
+ ED_armature_edit_sync_selection(arm->edbo);
+ }
+
+ MEM_freeN(objects);
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_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p)
+{
+ /* 4th element is select id */
+ uint sel_a = ((uint *)sel_a_p)[3];
+ uint sel_b = ((uint *)sel_b_p)[3];
+
+#ifdef __BIG_ENDIAN__
+ BLI_endian_switch_uint32(&sel_a);
+ BLI_endian_switch_uint32(&sel_b);
+#endif
+
+ 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)
{
- Bone *bone;
- Object *ob = vc->obact;
unsigned int *vbuffer = NULL; /* selection buffer */
- unsigned int *col; /* color in buffer */
int bone_only;
- int bone_selected = 0;
int totobj = MAXPICKBUF; /* XXX solve later */
int hits;
- if ((ob) && (ob->mode & OB_MODE_POSE))
+ if (vc->obact && (vc->obact->mode & OB_MODE_POSE))
bone_only = 1;
else
bone_only = 0;
if (extend == false && select) {
if (bone_only) {
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
- {
- if ((select == false) || ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)) {
- pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, OB_MODE_POSE, ob_iter) {
+ bArmature *arm = ob_iter->data;
+ for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (PBONE_VISIBLE(arm, pchan->bone)) {
+ if ((select == false) || ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)) {
+ pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
}
}
- CTX_DATA_END;
+ FOREACH_OBJECT_IN_MODE_END;
}
else {
- object_deselect_all_visible(vc->scene, vc->v3d);
+ object_deselect_all_visible(vc->view_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);
+ const eV3DSelectObjectFilter select_filter = (
+ (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
+ VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP);
+ hits = view3d_opengl_select(
+ vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect,
+ VIEW3D_SELECT_ALL, select_filter);
/*
* LOGIC NOTES (theeth):
* The buffer and ListBase have the same relative order, which makes the selection
@@ -2028,59 +2176,92 @@ 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 */
- if (*col & 0xFFFF0000) { /* we got a bone */
- bone = ED_armature_bone_find_index(base->object, *col & ~(BONESEL_ANY));
- if (bone) {
- if (select) {
- if ((bone->flag & BONE_UNSELECTABLE) == 0) {
- bone->flag |= BONE_SELECTED;
- bone_selected = 1;
- }
- }
- else {
- bArmature *arm = base->object->data;
- bone->flag &= ~BONE_SELECTED;
- if (arm->act_bone == bone)
- arm->act_bone = NULL;
- }
+
+ /* The draw order doesn't always match the order we populate the engine, see: T51695. */
+ qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
+
+ Base **bases = NULL;
+ BLI_array_declare(bases);
+
+ for (Base *base = vc->view_layer->object_bases.first; base && hits; base = base->next) {
+ if (BASE_SELECTABLE(base)) {
+ if ((base->object->select_color & 0x0000FFFF) != 0) {
+ BLI_array_append(bases, base);
+ }
+ }
+ }
+
+ for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
+ Bone *bone;
+ Base *base = ED_armature_base_and_bone_from_select_buffer(bases, BLI_array_len(bases), *col, &bone);
+
+ if (base == NULL) {
+ continue;
+ }
+ /* Loop over contiguous bone hits for 'base'. */
+ bool changed = false;
+ for (; col != col_end; col += 4) {
+ /* should never fail */
+ if (bone != NULL) {
+ if (select) {
+ if ((bone->flag & BONE_UNSELECTABLE) == 0) {
+ bone->flag |= BONE_SELECTED;
}
}
- else if (!bone_only) {
- ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
+ else {
+ bArmature *arm = base->object->data;
+ if ((bone->flag & BONE_UNSELECTABLE) == 0) {
+ bone->flag &= ~BONE_SELECTED;
+ if (arm->act_bone == bone)
+ arm->act_bone = NULL;
+ }
+ }
+ changed = true;
+ }
+ else if (!bone_only) {
+ ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
+ }
+
+ /* Select the next bone if we're not switching bases. */
+ if (col + 4 != col_end) {
+ if ((base->object->select_color & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
+ break;
}
- col += 4; /* next color */
- hits--;
- if (hits == 0) break;
+ if ((base->object->pose != NULL) && bone_only) {
+ const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16;
+ bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
+ bone = pchan ? pchan->bone : NULL;
+ }
+ else {
+ bone = NULL;
+ }
}
}
- if (bone_selected) {
+ if (changed) {
if (base->object && (base->object->type == OB_ARMATURE)) {
bArmature *arm = base->object->data;
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
- if (arm && (arm->flag & ARM_HAS_VIZ_DEPS)) {
+ if (vc->obact && 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(&vc->obact->id, OB_RECALC_DATA);
}
+
+ /* copy on write tag is needed (for the armature), or else no refresh happens */
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
}
}
}
+ MEM_freeN(bases);
+
+ DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
}
MEM_freeN(vbuffer);
@@ -2107,63 +2288,80 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
WM_operator_properties_border_to_rcti(op, &rect);
if (vc.obedit) {
- switch (vc.obedit->type) {
- case OB_MESH:
- vc.em = BKE_editmesh_from_object(vc.obedit);
- ret = do_mesh_box_select(&vc, &rect, select, extend);
-// if (EM_texFaceCheck())
- if (ret & OPERATOR_FINISHED) {
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
- }
- break;
- case OB_CURVE:
- case OB_SURF:
- ret = do_nurbs_box_select(&vc, &rect, select, extend);
- if (ret & OPERATOR_FINISHED) {
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
- }
- break;
- case OB_MBALL:
- ret = do_meta_box_select(&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);
- if (ret & OPERATOR_FINISHED) {
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
- }
- break;
- case OB_LATTICE:
- ret = do_lattice_box_select(&vc, &rect, select, extend);
- if (ret & OPERATOR_FINISHED) {
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
- }
- break;
- default:
- assert(!"border select on incorrect object type");
- break;
+
+ FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.obedit->mode, ob_iter) {
+ ED_view3d_viewcontext_init_object(&vc, ob_iter);
+
+ switch (vc.obedit->type) {
+ case OB_MESH:
+ vc.em = BKE_editmesh_from_object(vc.obedit);
+ ret |= do_mesh_box_select(&vc, &rect, select, extend);
+ if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
+ }
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ ret |= do_nurbs_box_select(&vc, &rect, select, extend);
+ if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
+ }
+ break;
+ case OB_MBALL:
+ ret |= do_meta_box_select(&vc, &rect, select, extend);
+ if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
+ 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);
+ if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(&vc.obedit->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
+ }
+ break;
+ case OB_LATTICE:
+ ret |= do_lattice_box_select(&vc, &rect, select, extend);
+ if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
+ }
+ break;
+ default:
+ assert(!"border select on incorrect object type");
+ break;
+ }
}
+ FOREACH_OBJECT_IN_MODE_END;
}
else { /* no editmode, unified for bones and objects */
if (vc.obact && vc.obact->mode & OB_MODE_SCULPT) {
- ret = ED_sculpt_mask_box_select(C, &vc, &rect, select, extend);
+ 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(&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(&vc, &rect, select, extend);
}
else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
- ret = PE_border_select(C, &rect, select, extend);
+ ret |= PE_border_select(C, &rect, select, extend);
}
else { /* object mode with none active */
- ret = do_object_pose_box_select(C, &vc, &rect, select, extend);
+ ret |= do_object_pose_box_select(C, &vc, &rect, select, extend);
}
}
+ if (ret & OPERATOR_FINISHED) {
+ ret = OPERATOR_FINISHED;
+ }
+ else {
+ ret = OPERATOR_CANCELLED;
+ }
+
return ret;
}
@@ -2231,6 +2429,7 @@ static bool ed_wpaint_vertex_select_pick(
}
paintvert_flush_flags(obact);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
return true;
}
@@ -2460,8 +2659,7 @@ static void paint_facesel_circle_select(ViewContext *vc, const bool select, cons
}
}
-static void paint_vertsel_circle_select_doSelectVert(
- void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
+static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
{
CircleSelectUserData *data = userData;
@@ -2638,8 +2836,11 @@ 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);
}
+
+ /* copy on write tag is needed (for the armature), or else no refresh happens */
+ DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
}
}
@@ -2749,7 +2950,8 @@ 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(
+ ViewContext *vc, const bool select, const int mval[2], float rad)
{
switch (vc->obedit->type) {
case OB_MESH:
@@ -2775,23 +2977,23 @@ 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;
+ ViewLayer *view_layer = vc->view_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(view_layer); 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;
}
}
@@ -2805,43 +3007,58 @@ static bool object_circle_select(ViewContext *vc, const bool select, const int m
static int view3d_circle_select_exec(bContext *C, wmOperator *op)
{
ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
- Object *obact = vc.obact;
- Object *obedit = vc.obedit;
const int radius = RNA_int_get(op->ptr, "radius");
const bool select = !RNA_boolean_get(op->ptr, "deselect");
const int mval[2] = {RNA_int_get(op->ptr, "x"),
RNA_int_get(op->ptr, "y")};
+
+ ED_view3d_viewcontext_init(C, &vc);
+
+ Object *obact = vc.obact;
+ Object *obedit = vc.obedit;
+
if (obedit || BKE_paint_select_elem_test(obact) ||
(obact && (obact->mode & (OB_MODE_PARTICLE_EDIT | OB_MODE_POSE))) )
{
view3d_operator_needs_opengl(C);
- if (CTX_data_edit_object(C)) {
- obedit_circle_select(&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);
- 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);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
- }
- else if (obact->mode & OB_MODE_POSE) {
- pose_circle_select(&vc, select, mval, (float)radius);
- }
- else {
- return PE_circle_select(C, select, mval, (float)radius);
+ FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, obact->mode, ob_iter) {
+ ED_view3d_viewcontext_init_object(&vc, ob_iter);
+
+ obact = vc.obact;
+ obedit = vc.obedit;
+
+ if (CTX_data_edit_object(C)) {
+ obedit_circle_select(&vc, select, mval, (float)radius);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
+ 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);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
+ 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);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
+ }
+ else if (obact->mode & OB_MODE_POSE) {
+ pose_circle_select(&vc, select, mval, (float)radius);
+ }
+ else {
+ return PE_circle_select(C, select, mval, (float)radius);
+ }
}
+ FOREACH_OBJECT_IN_MODE_END;
}
else if (obact && obact->mode & OB_MODE_SCULPT) {
return OPERATOR_CANCELLED;
}
else {
if (object_circle_select(&vc, select, mval, (float)radius)) {
+ DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 80586217691..606c07cd1fa 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -30,6 +30,8 @@
*/
+#include "MEM_guardedalloc.h"
+
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
@@ -40,13 +42,17 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
+#include "BKE_editmesh.h"
+#include "BKE_layer.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 "DEG_depsgraph_query.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -68,6 +74,8 @@ static bool snap_calc_active_center(bContext *C, const bool select_only, float r
static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
RegionView3D *rv3d = CTX_wm_region_data(C);
@@ -79,62 +87,83 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
gridf = rv3d->gridview;
if (obedit) {
- if (ED_transverts_check_obedit(obedit))
- ED_transverts_create_from_obedit(&tvs, obedit, 0);
- if (tvs.transverts_tot == 0)
- return OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if ((em->bm->totvertsel == 0) &&
+ (em->bm->totedgesel == 0) &&
+ (em->bm->totfacesel == 0))
+ {
+ continue;
+ }
- copy_m3_m4(bmat, obedit->obmat);
- invert_m3_m3(imat, bmat);
+ if (ED_transverts_check_obedit(obedit)) {
+ ED_transverts_create_from_obedit(&tvs, obedit, 0);
+ }
- tv = tvs.transverts;
- for (a = 0; a < tvs.transverts_tot; a++, tv++) {
- copy_v3_v3(vec, tv->loc);
- mul_m3_v3(bmat, vec);
- add_v3_v3(vec, obedit->obmat[3]);
- vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
- vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
- vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
- sub_v3_v3(vec, obedit->obmat[3]);
-
- mul_m3_v3(imat, vec);
- copy_v3_v3(tv->loc, vec);
- }
+ if (tvs.transverts_tot == 0) {
+ continue;
+ }
- ED_transverts_update_obedit(&tvs, obedit);
- ED_transverts_free(&tvs);
+ copy_m3_m4(bmat, obedit->obmat);
+ invert_m3_m3(imat, bmat);
+
+ tv = tvs.transverts;
+ for (a = 0; a < tvs.transverts_tot; a++, tv++) {
+ copy_v3_v3(vec, tv->loc);
+ mul_m3_v3(bmat, vec);
+ add_v3_v3(vec, obedit->obmat[3]);
+ vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
+ vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
+ vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
+ sub_v3_v3(vec, obedit->obmat[3]);
+
+ mul_m3_v3(imat, vec);
+ copy_v3_v3(tv->loc, vec);
+ }
+
+ ED_transverts_update_obedit(&tvs, obedit);
+ ED_transverts_free(&tvs);
+ }
+ MEM_freeN(objects);
}
else {
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
+ FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN(view_layer_eval, ob_eval)
{
+ Object *ob = DEG_get_original_object(ob_eval);
if (ob->mode & OB_MODE_POSE) {
- bPoseChannel *pchan;
- bArmature *arm = ob->data;
+ bPoseChannel *pchan_eval;
+ bArmature *arm_eval = ob_eval->data;
- invert_m4_m4(ob->imat, ob->obmat);
+ invert_m4_m4(ob_eval->imat, ob_eval->obmat);
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & BONE_SELECTED) {
- if (pchan->bone->layer & arm->layer) {
- if ((pchan->bone->flag & BONE_CONNECTED) == 0) {
+ for (pchan_eval = ob_eval->pose->chanbase.first; pchan_eval; pchan_eval = pchan_eval->next) {
+ if (pchan_eval->bone->flag & BONE_SELECTED) {
+ if (pchan_eval->bone->layer & arm_eval->layer) {
+ if ((pchan_eval->bone->flag & BONE_CONNECTED) == 0) {
float nLoc[3];
/* get nearest grid point to snap to */
- copy_v3_v3(nLoc, pchan->pose_mat[3]);
+ copy_v3_v3(nLoc, pchan_eval->pose_mat[3]);
/* We must operate in world space! */
- mul_m4_v3(ob->obmat, nLoc);
+ mul_m4_v3(ob_eval->obmat, nLoc);
vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
/* Back in object space... */
- mul_m4_v3(ob->imat, vec);
+ mul_m4_v3(ob_eval->imat, vec);
/* Get location of grid point in pose space. */
- BKE_armature_loc_pose_to_bone(pchan, vec, vec);
+ BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec);
- /* adjust location */
+ /* adjust location on the original pchan*/
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, pchan_eval->name);
if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
pchan->loc[0] = vec[0];
if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
@@ -153,34 +182,34 @@ 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);
- vec[1] = -ob->obmat[3][1] + gridf * floorf(0.5f + ob->obmat[3][1] / gridf);
- vec[2] = -ob->obmat[3][2] + gridf * floorf(0.5f + ob->obmat[3][2] / gridf);
+ vec[0] = -ob_eval->obmat[3][0] + gridf * floorf(0.5f + ob_eval->obmat[3][0] / gridf);
+ vec[1] = -ob_eval->obmat[3][1] + gridf * floorf(0.5f + ob_eval->obmat[3][1] / gridf);
+ vec[2] = -ob_eval->obmat[3][2] + gridf * floorf(0.5f + ob_eval->obmat[3][2] / gridf);
if (ob->parent) {
float originmat[3][3];
- BKE_object_where_is_calc_ex(scene, NULL, ob, originmat);
+ BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat);
invert_m3_m3(imat, originmat);
mul_m3_v3(imat, vec);
}
if ((ob->protectflag & OB_LOCK_LOCX) == 0)
- ob->loc[0] += vec[0];
+ ob->loc[0] = ob_eval->loc[0] + vec[0];
if ((ob->protectflag & OB_LOCK_LOCY) == 0)
- ob->loc[1] += vec[1];
+ ob->loc[1] = ob_eval->loc[1] + vec[1];
if ((ob->protectflag & OB_LOCK_LOCZ) == 0)
- ob->loc[2] += vec[2];
+ ob->loc[2] = ob_eval->loc[2] + vec[2];
/* 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;
+ FOREACH_SELECTED_EDITABLE_OBJECT_END;
}
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -207,6 +236,7 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset)
{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
Object *obact = CTX_data_active_object(C);
@@ -219,7 +249,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global
int a;
if (use_offset) {
- if ((v3d && v3d->around == V3D_AROUND_ACTIVE) &&
+ if ((v3d && scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) &&
snap_calc_active_center(C, true, center_global))
{
/* pass */
@@ -329,7 +359,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 +400,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(depsgraph, scene, NULL, ob, originmat);
invert_m3_m3(imat, originmat);
mul_m3_v3(imat, cursor_parent);
@@ -385,7 +415,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);
}
}
@@ -404,7 +434,7 @@ static int snap_selected_to_cursor_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- const float *snap_target_global = ED_view3d_cursor3d_get(scene, v3d);
+ const float *snap_target_global = ED_view3d_cursor3d_get(scene, v3d)->location;
return snap_selected_to_location(C, snap_target_global, use_offset);
}
@@ -465,13 +495,14 @@ static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
float gridf, *curs;
gridf = rv3d->gridview;
- curs = ED_view3d_cursor3d_get(scene, v3d);
+ curs = ED_view3d_cursor3d_get(scene, v3d)->location;
curs[0] = gridf * floorf(0.5f + curs[0] / gridf);
curs[1] = gridf * floorf(0.5f + curs[1] / gridf);
curs[2] = gridf * floorf(0.5f + curs[2] / gridf);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); /* hrm */
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
@@ -493,7 +524,7 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
/* **************************************************** */
-static void bundle_midpoint(Scene *scene, Object *ob, float vec[3])
+static void bundle_midpoint(Depsgraph *depsgraph, Scene *scene, Object *ob, float vec[3])
{
MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
MovieTracking *tracking;
@@ -508,7 +539,7 @@ static void bundle_midpoint(Scene *scene, Object *ob, float vec[3])
copy_m4_m4(cammat, ob->obmat);
- BKE_tracking_get_camera_object_matrix(scene, ob, mat);
+ BKE_tracking_get_camera_object_matrix(depsgraph, scene, ob, mat);
INIT_MINMAX(min, max);
@@ -547,6 +578,8 @@ static void bundle_midpoint(Scene *scene, Object *ob, float vec[3])
static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -560,7 +593,6 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
zero_v3(centroid);
if (obedit) {
-
if (ED_transverts_check_obedit(obedit))
ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);
@@ -568,18 +600,19 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
return false;
}
- copy_m3_m4(bmat, obedit->obmat);
+ Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
+ copy_m3_m4(bmat, obedit_eval->obmat);
tv = tvs.transverts;
for (a = 0; a < tvs.transverts_tot; a++, tv++) {
copy_v3_v3(vec, tv->loc);
mul_m3_v3(bmat, vec);
- add_v3_v3(vec, obedit->obmat[3]);
+ add_v3_v3(vec, obedit_eval->obmat[3]);
add_v3_v3(centroid, vec);
minmax_v3v3_v3(min, max, vec);
}
- if (v3d->around == V3D_AROUND_CENTER_MEAN) {
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEAN) {
mul_v3_fl(centroid, 1.0f / (float)tvs.transverts_tot);
copy_v3_v3(cursor, centroid);
}
@@ -593,13 +626,14 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
Object *obact = CTX_data_active_object(C);
if (obact && (obact->mode & OB_MODE_POSE)) {
- bArmature *arm = obact->data;
+ Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
+ bArmature *arm = obact_eval->data;
bPoseChannel *pchan;
- for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
+ for (pchan = obact_eval->pose->chanbase.first; pchan; pchan = pchan->next) {
if (arm->layer & pchan->bone->layer) {
if (pchan->bone->flag & BONE_SELECTED) {
copy_v3_v3(vec, pchan->pose_head);
- mul_m4_v3(obact->obmat, vec);
+ mul_m4_v3(obact_eval->obmat, vec);
add_v3_v3(centroid, vec);
minmax_v3v3_v3(min, max, vec);
count++;
@@ -608,15 +642,15 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
}
}
else {
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
+ FOREACH_SELECTED_OBJECT_BEGIN(view_layer_eval, ob_eval)
{
- copy_v3_v3(vec, ob->obmat[3]);
+ copy_v3_v3(vec, ob_eval->obmat[3]);
/* special case for camera -- snap to bundles */
- if (ob->type == OB_CAMERA) {
+ if (ob_eval->type == OB_CAMERA) {
/* snap to bundles should happen only when bundles are visible */
if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) {
- bundle_midpoint(scene, ob, vec);
+ bundle_midpoint(depsgraph, scene, DEG_get_original_object(ob_eval), vec);
}
}
@@ -624,14 +658,14 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
minmax_v3v3_v3(min, max, vec);
count++;
}
- CTX_DATA_END;
+ FOREACH_SELECTED_OBJECT_END;
}
if (count == 0) {
return false;
}
- if (v3d->around == V3D_AROUND_CENTER_MEAN) {
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEAN) {
mul_v3_fl(centroid, 1.0f / (float)count);
copy_v3_v3(cursor, centroid);
}
@@ -648,10 +682,11 @@ static int snap_curs_to_sel_exec(bContext *C, wmOperator *UNUSED(op))
View3D *v3d = CTX_wm_view3d(C);
float *curs;
- curs = ED_view3d_cursor3d_get(scene, v3d);
+ curs = ED_view3d_cursor3d_get(scene, v3d)->location;
if (snap_curs_to_sel_ex(C, curs)) {
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
@@ -682,31 +717,36 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3])
{
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
Object *obedit = CTX_data_edit_object(C);
if (obedit) {
- if (ED_object_editmode_calc_active_center(obedit, select_only, r_center)) {
- mul_m4_v3(obedit->obmat, r_center);
+ Object *ob_edit_eval = DEG_get_evaluated_object(depsgraph, obedit);
+
+ if (ED_object_editmode_calc_active_center(ob_edit_eval, select_only, r_center)) {
+ mul_m4_v3(ob_edit_eval->obmat, r_center);
return true;
}
}
else {
Object *ob = CTX_data_active_object(C);
-
if (ob) {
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+
if (ob->mode & OB_MODE_POSE) {
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
+ bPoseChannel *pchan = BKE_pose_channel_active(ob_eval);
if (pchan) {
if (!select_only || (pchan->bone->flag & BONE_SELECTED)) {
copy_v3_v3(r_center, pchan->pose_head);
- mul_m4_v3(ob->obmat, r_center);
+ mul_m4_v3(ob_eval->obmat, r_center);
return true;
}
}
}
else {
- if (!select_only || (ob->flag & SELECT)) {
- copy_v3_v3(r_center, ob->obmat[3]);
+
+ if (!select_only || (ob_eval->flag & SELECT)) {
+ copy_v3_v3(r_center, ob_eval->obmat[3]);
return true;
}
}
@@ -722,10 +762,12 @@ static int snap_curs_to_active_exec(bContext *C, wmOperator *UNUSED(op))
View3D *v3d = CTX_wm_view3d(C);
float *curs;
- curs = ED_view3d_cursor3d_get(scene, v3d);
+ curs = ED_view3d_cursor3d_get(scene, v3d)->location;
if (snap_calc_active_center(C, false, curs)) {
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
+
return OPERATOR_FINISHED;
}
else {
@@ -755,11 +797,12 @@ static int snap_curs_to_center_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
float *curs;
- curs = ED_view3d_cursor3d_get(scene, v3d);
+ curs = ED_view3d_cursor3d_get(scene, v3d)->location;
zero_v3(curs);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index e7ae0d39a2b..707e0e7a394 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -28,230 +28,24 @@
* \ingroup spview3d
*/
-
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <float.h>
-#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "MEM_guardedalloc.h"
-
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
-
-#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_screen.h"
-
#include "WM_api.h"
#include "WM_types.h"
-#include "RNA_access.h"
-
#include "ED_screen.h"
-#include "ED_undo.h"
-
-#include "UI_interface.h"
-#include "UI_resources.h"
#include "view3d_intern.h" /* own include */
-
-/* ******************* view3d space & buttons ************** */
-
-static void view3d_panel_operator_redo_buts(const bContext *C, Panel *pa, wmOperator *op)
-{
- uiTemplateOperatorPropertyButs(C, pa->layout, op, NULL, 'V', 0);
-}
-
-static void view3d_panel_operator_redo_header(const bContext *C, Panel *pa)
-{
- wmOperator *op = WM_operator_last_redo(C);
-
- if (op)
- BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname));
- else
- BLI_strncpy(pa->drawname, IFACE_("Operator"), sizeof(pa->drawname));
-}
-
-static void view3d_panel_operator_redo_operator(const bContext *C, Panel *pa, wmOperator *op)
-{
- if (op->type->flag & OPTYPE_MACRO) {
- for (op = op->macro.first; op; op = op->next) {
- uiItemL(pa->layout, RNA_struct_ui_name(op->type->srna), ICON_NONE);
- view3d_panel_operator_redo_operator(C, pa, op);
- }
- }
- else {
- view3d_panel_operator_redo_buts(C, pa, op);
- }
-}
-
-/* TODO de-duplicate redo panel functions - campbell */
-static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
-{
- wmOperator *op = WM_operator_last_redo(C);
- ARegion *ar;
- ARegion *ar1;
-
- if (op == NULL) {
- return;
- }
-
- /* keep in sync with logic in ED_undo_operator_repeat() */
- ar = CTX_wm_region(C);
- ar1 = BKE_area_find_region_active_win(CTX_wm_area(C));
- if (ar1)
- CTX_wm_region_set((bContext *)C, ar1);
-
- if (WM_operator_poll((bContext *)C, op->type)) {
- uiBlock *block = uiLayoutGetBlock(pa->layout);
-
- if (!WM_operator_check_ui_enabled(C, op->type->name))
- uiLayoutSetEnabled(pa->layout, false);
-
- /* note, blockfunc is a default but->func, use Handle func to allow button callbacks too */
- UI_block_func_handle_set(block, ED_undo_operator_repeat_cb_evt, op);
-
- view3d_panel_operator_redo_operator(C, pa, op);
- }
-
- /* set region back */
- CTX_wm_region_set((bContext *)C, ar);
-}
-
-/* ******************* */
-
-typedef struct CustomTool {
- struct CustomTool *next, *prev;
- char opname[OP_MAX_TYPENAME];
- char context[OP_MAX_TYPENAME];
-} CustomTool;
-
-static void operator_call_cb(struct bContext *C, void *arg_listbase, void *arg2)
-{
- wmOperatorType *ot = arg2;
-
- if (ot) {
- CustomTool *ct = MEM_callocN(sizeof(CustomTool), "CustomTool");
-
- BLI_addtail(arg_listbase, ct);
- BLI_strncpy(ct->opname, ot->idname, OP_MAX_TYPENAME);
- BLI_strncpy(ct->context, CTX_data_mode_string(C), OP_MAX_TYPENAME);
- }
-
-}
-
-static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items)
-{
- GHashIterator iter;
-
- for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
- wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
-
- if (BLI_strcasestr(ot->name, str)) {
- if (WM_operator_poll((bContext *)C, ot)) {
-
- if (false == UI_search_item_add(items, ot->name, ot, 0))
- break;
- }
- }
- }
-}
-
-
-/* ID Search browse menu, open */
-static uiBlock *tool_search_menu(bContext *C, ARegion *ar, void *arg_listbase)
-{
- static char search[OP_MAX_TYPENAME];
- wmEvent event;
- wmWindow *win = CTX_wm_window(C);
- uiBlock *block;
- uiBut *but;
-
- /* clear initial search string, then all items show */
- search[0] = 0;
-
- block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
- UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU);
-
- /* fake button, it holds space for search items */
- uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 15, UI_searchbox_size_x(), UI_searchbox_size_y(), NULL, 0, 0, 0, 0, NULL);
-
- but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, 19, 0, 0, "");
- UI_but_func_search_set(but, NULL, operator_search_cb, arg_listbase, operator_call_cb, NULL);
-
- UI_block_bounds_set_normal(block, 6);
- UI_block_direction_set(block, UI_DIR_DOWN);
- UI_block_end(C, block);
-
- wm_event_init_from_window(win, &event);
- event.type = EVT_BUT_OPEN;
- event.val = KM_PRESS;
- event.customdata = but;
- event.customdatafree = false;
- wm_event_add(win, &event);
-
- return block;
-}
-
-
-static void view3d_panel_tool_shelf(const bContext *C, Panel *pa)
-{
- SpaceLink *sl = CTX_wm_space_data(C);
- SpaceType *st = NULL;
- uiLayout *col;
- const char *context = CTX_data_mode_string(C);
-
- if (sl)
- st = BKE_spacetype_from_id(sl->spacetype);
-
- if (st && st->toolshelf.first) {
- CustomTool *ct;
-
- for (ct = st->toolshelf.first; ct; ct = ct->next) {
- if (STREQLEN(context, ct->context, OP_MAX_TYPENAME)) {
- col = uiLayoutColumn(pa->layout, true);
- uiItemFullO(col, ct->opname, NULL, ICON_NONE, NULL, WM_OP_INVOKE_REGION_WIN, 0, NULL);
- }
- }
- }
- col = uiLayoutColumn(pa->layout, true);
- uiDefBlockBut(uiLayoutGetBlock(pa->layout), tool_search_menu, &st->toolshelf, "Add Tool", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Add Tool in shelf, gets saved in files");
-}
-
-
-void view3d_toolshelf_register(ARegionType *art)
-{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel tools");
- strcpy(pt->idname, "VIEW3D_PT_tool_shelf");
- strcpy(pt->label, N_("Tool Shelf"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = view3d_panel_tool_shelf;
- BLI_addtail(&art->paneltypes, pt);
-}
-
-void view3d_tool_props_register(ARegionType *art)
-{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel last operator");
- strcpy(pt->idname, "VIEW3D_PT_last_operator");
- strcpy(pt->label, N_("Operator"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw_header = view3d_panel_operator_redo_header;
- pt->draw = view3d_panel_operator_redo;
- BLI_addtail(&art->paneltypes, pt);
-}
-
/* ********** operator to open/close toolshelf region */
static int view3d_toolshelf_toggle_exec(bContext *C, wmOperator *UNUSED(op))
@@ -267,7 +61,7 @@ static int view3d_toolshelf_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void VIEW3D_OT_toolshelf(wmOperatorType *ot)
{
- ot->name = "Tool Shelf";
+ ot->name = "Toggle Toolbar";
ot->description = "Toggles tool shelf display";
ot->idname = "VIEW3D_OT_toolshelf";
@@ -277,4 +71,3 @@ void VIEW3D_OT_toolshelf(wmOperatorType *ot)
/* flags */
ot->flag = 0;
}
-
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 68582644f34..ca5375b6b54 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -46,14 +46,18 @@
#include "BKE_camera.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h" /* for ED_view3d_camera_lock_sync */
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_screen.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_matrix.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -68,10 +72,27 @@
*
* \{ */
-float *ED_view3d_cursor3d_get(Scene *scene, View3D *v3d)
+View3DCursor *ED_view3d_cursor3d_get(Scene *scene, View3D *v3d)
+{
+ if (v3d && v3d->localvd) {
+ return &v3d->cursor;
+ }
+ else {
+ return &scene->cursor;
+ }
+}
+
+void ED_view3d_cursor3d_calc_mat3(const Scene *scene, const View3D *v3d, float mat[3][3])
+{
+ const View3DCursor *cursor = ED_view3d_cursor3d_get((Scene *)scene, (View3D *)v3d);
+ quat_to_mat3(mat, cursor->rotation);
+}
+
+void ED_view3d_cursor3d_calc_mat4(const Scene *scene, const View3D *v3d, float mat[4][4])
{
- if (v3d && v3d->localvd) return v3d->cursor;
- else return scene->cursor;
+ const View3DCursor *cursor = ED_view3d_cursor3d_get((Scene *)scene, (View3D *)v3d);
+ quat_to_mat4(mat, cursor->rotation);
+ copy_v3_v3(mat[3], cursor->location);
}
Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d)
@@ -97,6 +118,7 @@ void ED_view3d_dist_range_get(
* \note copies logic of #ED_view3d_viewplane_get(), keep in sync.
*/
bool ED_view3d_clip_range_get(
+ Depsgraph *depsgraph,
const View3D *v3d, const RegionView3D *rv3d,
float *r_clipsta, float *r_clipend,
const bool use_ortho_factor)
@@ -104,7 +126,7 @@ bool ED_view3d_clip_range_get(
CameraParams params;
BKE_camera_params_init(&params);
- BKE_camera_params_from_view3d(&params, v3d, rv3d);
+ BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
if (use_ortho_factor && params.is_ortho) {
const float fac = 2.0f / (params.clipend - params.clipsta);
@@ -119,13 +141,14 @@ bool ED_view3d_clip_range_get(
}
bool ED_view3d_viewplane_get(
+ Depsgraph *depsgraph,
const View3D *v3d, const RegionView3D *rv3d, int winx, int winy,
rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize)
{
CameraParams params;
BKE_camera_params_init(&params);
- BKE_camera_params_from_view3d(&params, v3d, rv3d);
+ BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
BKE_camera_params_compute_viewplane(&params, winx, winy, 1.0f, 1.0f);
if (r_viewplane) *r_viewplane = params.viewplane;
@@ -156,7 +179,7 @@ void view3d_operator_needs_opengl(const bContext *C)
view3d_region_operator_needs_opengl(win, ar);
}
-void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar)
+void view3d_region_operator_needs_opengl(wmWindow *UNUSED(win), ARegion *ar)
{
/* for debugging purpose, context should always be OK */
if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW)) {
@@ -165,11 +188,9 @@ void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar)
else {
RegionView3D *rv3d = ar->regiondata;
- wmSubWindowSet(win, ar->swinid);
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(rv3d->winmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(rv3d->viewmat);
+ wmViewport(&ar->winrct); // TODO: bad
+ gpuLoadProjectionMatrix(rv3d->winmat);
+ gpuLoadMatrix(rv3d->viewmat);
}
}
@@ -231,6 +252,7 @@ bool ED_view3d_context_activate(bContext *C)
/** \name View Clipping Utilities
*
* \{ */
+
void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip)
{
int val;
@@ -245,40 +267,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;
+
+ 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, 0.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]);
- copy_v3fl_v3db(bb->vec[val], p);
+ /* optionally transform to object space */
+ if (ob) {
+ float imat[4][4];
+ invert_m4_m4(imat, ob->obmat);
- 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);
+ 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);
}
@@ -379,14 +396,15 @@ void ED_view3d_lock_clear(View3D *v3d)
* sets the ``ofs`` and ``dist`` values of the viewport so it matches the camera,
* otherwise switching out of camera view may jump to a different part of the scene.
*/
-void ED_view3d_persp_switch_from_camera(View3D *v3d, RegionView3D *rv3d, const char persp)
+void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d, const char persp)
{
BLI_assert(rv3d->persp == RV3D_CAMOB);
BLI_assert(persp != RV3D_CAMOB);
if (v3d->camera) {
- rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
- ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
+ rv3d->dist = ED_view3d_offset_distance(ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
+ ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
}
if (!ED_view3d_camera_lock_check(v3d, rv3d)) {
@@ -399,7 +417,7 @@ void ED_view3d_persp_switch_from_camera(View3D *v3d, RegionView3D *rv3d, const c
*
* shared with NDOF.
*/
-bool ED_view3d_persp_ensure(struct View3D *v3d, ARegion *ar)
+bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *ar)
{
RegionView3D *rv3d = ar->regiondata;
const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0;
@@ -413,7 +431,7 @@ bool ED_view3d_persp_ensure(struct View3D *v3d, ARegion *ar)
if (rv3d->persp == RV3D_CAMOB) {
/* If autopersp and previous view was an axis one, switch back to PERSP mode, else reuse previous mode. */
char persp = (autopersp && RV3D_VIEW_IS_AXIS(rv3d->lview)) ? RV3D_PERSP : rv3d->lpersp;
- ED_view3d_persp_switch_from_camera(v3d, rv3d, persp);
+ ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, persp);
}
else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
rv3d->persp = RV3D_PERSP;
@@ -447,20 +465,21 @@ bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d)
* Apply the camera object transformation to the view-port.
* (needed so we can use regular view-port manipulation operators, that sync back to the camera).
*/
-void ED_view3d_camera_lock_init_ex(View3D *v3d, RegionView3D *rv3d, const bool calc_dist)
+void ED_view3d_camera_lock_init_ex(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d, const bool calc_dist)
{
if (ED_view3d_camera_lock_check(v3d, rv3d)) {
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
if (calc_dist) {
/* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */
- rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
+ rv3d->dist = ED_view3d_offset_distance(ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
}
- ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
+ ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
}
}
-void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d)
+void ED_view3d_camera_lock_init(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d)
{
- ED_view3d_camera_lock_init_ex(v3d, rv3d, true);
+ ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, true);
}
/**
@@ -468,7 +487,7 @@ void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d)
*
* \return true if the camera is moved.
*/
-bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
+bool ED_view3d_camera_lock_sync(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d)
{
if (ED_view3d_camera_lock_check(v3d, rv3d)) {
ObjectTfmProtectedChannels obtfm;
@@ -485,15 +504,17 @@ bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
while (root_parent->parent) {
root_parent = root_parent->parent;
}
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
+ Object *root_parent_eval = DEG_get_evaluated_object(depsgraph, root_parent);
ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
- normalize_m4_m4(tmat, v3d->camera->obmat);
+ normalize_m4_m4(tmat, ob_camera_eval->obmat);
invert_m4_m4(imat, tmat);
mul_m4_m4m4(diff_mat, view_mat, imat);
- mul_m4_m4m4(parent_mat, diff_mat, root_parent->obmat);
+ mul_m4_m4m4(parent_mat, diff_mat, root_parent_eval->obmat);
BKE_object_tfm_protected_backup(root_parent, &obtfm);
BKE_object_apply_mat4(root_parent, parent_mat, true, false);
@@ -501,7 +522,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;
}
@@ -510,10 +531,10 @@ bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
/* always maintain the same scale */
const short protect_scale_all = (OB_LOCK_SCALEX | OB_LOCK_SCALEY | OB_LOCK_SCALEZ);
BKE_object_tfm_protected_backup(v3d->camera, &obtfm);
- ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ ED_view3d_to_object(depsgraph, 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);
}
@@ -594,6 +615,7 @@ bool ED_view3d_camera_lock_autokey(
/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Box View Support
*
@@ -878,22 +900,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(
- Main *bmain, Scene *scene, ARegion *ar, View3D *v3d,
+ Depsgraph *depsgraph, 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(bmain, 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(depsgraph, ar, v3d, alphaoverride);
/* Attempt with low margin's first */
i = 0;
@@ -903,15 +920,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;
}
}
@@ -925,27 +937,28 @@ bool ED_view3d_autodist(
}
}
-void ED_view3d_autodist_init(Main *bmain, Scene *scene, ARegion *ar, View3D *v3d, int mode)
+void ED_view3d_autodist_init(Depsgraph *depsgraph,
+ ARegion *ar, View3D *v3d, int mode)
{
/* Get Z Depths, needed for perspective, nice for ortho */
switch (mode) {
case 0:
- ED_view3d_draw_depth(bmain, scene, ar, v3d, true);
+ ED_view3d_draw_depth(depsgraph, ar, v3d, true);
break;
case 1:
- ED_view3d_draw_depth_gpencil(scene, ar, v3d);
+ {
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ ED_view3d_draw_depth_gpencil(depsgraph, scene, ar, v3d);
break;
+ }
}
}
/* no 4x4 sampling, run #ED_view3d_autodist_init first */
-bool ED_view3d_autodist_simple(
- ARegion *ar, const int mval[2], float mouse_worldloc[3],
- int margin, float *force_depth)
+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)
@@ -956,21 +969,9 @@ bool ED_view3d_autodist_simple(
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)
@@ -1066,6 +1067,7 @@ float ED_view3d_radius_to_dist_ortho(const float lens, const float radius)
*/
float ED_view3d_radius_to_dist(
const View3D *v3d, const ARegion *ar,
+ const struct Depsgraph *depsgraph,
const char persp, const bool use_aspect,
const float radius)
{
@@ -1086,7 +1088,8 @@ float ED_view3d_radius_to_dist(
BKE_camera_params_init(&params);
params.clipsta = v3d->near;
params.clipend = v3d->far;
- BKE_camera_params_from_object(&params, v3d->camera);
+ Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
+ BKE_camera_params_from_object(&params, camera_eval);
lens = params.lens;
sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y);
@@ -1276,7 +1279,7 @@ bool ED_view3d_lock(RegionView3D *rv3d)
* \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
* \param dist The view distance from ofs, normally from RegionView3D.dist.
*/
-void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist)
+void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], float *dist)
{
float nmat[3][3];
@@ -1321,13 +1324,14 @@ void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], c
/**
* Set the RegionView3D members from an objects transformation and optionally lens.
+ * \param depsgraph The depsgraph to get the evaluated object for the lens calculation.
* \param ob The object to set the view to.
* \param ofs The view offset to be set, normally from RegionView3D.ofs.
* \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat.
* \param dist The view distance from ofs to be set, normally from RegionView3D.dist.
* \param lens The view lens angle set for cameras and lamps, normally from View3D.lens.
*/
-void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens)
+void ED_view3d_from_object(const Object *ob, float ofs[3], float quat[4], float *dist, float *lens)
{
ED_view3d_from_m4(ob->obmat, ofs, quat, dist);
@@ -1342,16 +1346,19 @@ void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist,
/**
* Set the object transformation from RegionView3D members.
+ * \param depsgraph The depsgraph to get the evaluated object parent for the transformation calculation.
* \param ob The object which has the transformation assigned.
* \param ofs The view offset, normally from RegionView3D.ofs.
* \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
* \param dist The view distance from ofs, normally from RegionView3D.dist.
*/
-void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], const float dist)
+void ED_view3d_to_object(const Depsgraph *depsgraph, 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);
+
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ BKE_object_apply_mat4_ex(ob, mat, ob_eval->parent, ob_eval->parentinv, true);
}
/** \} */
@@ -1377,7 +1384,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.
@@ -1396,7 +1403,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;
}
}
@@ -1438,21 +1445,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);
}
void ED_view3d_depth_tag_update(RegionView3D *rv3d)
@@ -1462,46 +1461,3 @@ void ED_view3d_depth_tag_update(RegionView3D *rv3d)
}
/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Background Image Utilities
- * \{ */
-
-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;
- }
-}
-
-/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 0f09d7fefa2..8b9ad387065 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -41,32 +41,27 @@
#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"
#include "BKE_report.h"
#include "BKE_scene.h"
-#include "BIF_gl.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.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"
#include "ED_screen.h"
-#ifdef WITH_GAMEENGINE
-# include "BLI_listbase.h"
-# include "BLI_callbacks.h"
-
-# include "GPU_draw.h"
-
-# include "BL_System.h"
-#endif
+#include "DRW_engine.h"
#include "view3d_intern.h" /* own include */
@@ -125,7 +120,7 @@ static void view3d_smooth_view_state_restore(const struct SmoothView3DState *sms
/* the arguments are the desired situation */
void ED_view3d_smooth_view_ex(
/* avoid passing in the context */
- wmWindowManager *wm, wmWindow *win, ScrArea *sa,
+ const Depsgraph *depsgraph, wmWindowManager *wm, wmWindow *win, ScrArea *sa,
View3D *v3d, ARegion *ar, const int smooth_viewtx,
const V3D_SmoothParams *sview)
{
@@ -156,7 +151,7 @@ void ED_view3d_smooth_view_ex(
* we allow camera option locking to initialize the view settings from the camera.
*/
if (sview->camera == NULL && sview->camera_old == NULL) {
- ED_view3d_camera_lock_init(v3d, rv3d);
+ ED_view3d_camera_lock_init(depsgraph, v3d, rv3d);
}
/* store the options we want to end with */
@@ -181,8 +176,9 @@ void ED_view3d_smooth_view_ex(
}
if (sview->camera) {
- sms.dst.dist = ED_view3d_offset_distance(sview->camera->obmat, sview->ofs, VIEW3D_DIST_FALLBACK);
- ED_view3d_from_object(sview->camera, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens);
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera);
+ sms.dst.dist = ED_view3d_offset_distance(ob_camera_eval->obmat, sview->ofs, VIEW3D_DIST_FALLBACK);
+ ED_view3d_from_object(ob_camera_eval, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens);
sms.to_camera = true; /* restore view3d values in end */
}
@@ -206,9 +202,10 @@ void ED_view3d_smooth_view_ex(
if (changed) {
/* original values */
if (sview->camera_old) {
- sms.src.dist = ED_view3d_offset_distance(sview->camera_old->obmat, rv3d->ofs, 0.0f);
+ Object *ob_camera_old_eval = DEG_get_evaluated_object(depsgraph, sview->camera_old);
+ sms.src.dist = ED_view3d_offset_distance(ob_camera_old_eval->obmat, rv3d->ofs, 0.0f);
/* this */
- ED_view3d_from_object(sview->camera_old, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens);
+ ED_view3d_from_object(ob_camera_old_eval, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens);
}
/* grid draw as floor */
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
@@ -230,9 +227,10 @@ void ED_view3d_smooth_view_ex(
/* ensure it shows correct */
if (sms.to_camera) {
/* use ortho if we move from an ortho view to an ortho camera */
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera);
rv3d->persp = (((rv3d->is_persp == false) &&
- (sview->camera->type == OB_CAMERA) &&
- (((Camera *)sview->camera->data)->type == CAM_ORTHO)) ?
+ (ob_camera_eval->type == OB_CAMERA) &&
+ (((Camera *)ob_camera_eval->data)->type == CAM_ORTHO)) ?
RV3D_ORTHO : RV3D_PERSP);
}
@@ -265,7 +263,7 @@ void ED_view3d_smooth_view_ex(
rv3d->dist = sms.dst.dist;
v3d->lens = sms.dst.lens;
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
}
if (rv3d->viewlock & RV3D_BOXVIEW) {
@@ -281,11 +279,13 @@ void ED_view3d_smooth_view(
View3D *v3d, ARegion *ar, const int smooth_viewtx,
const struct V3D_SmoothParams *sview)
{
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = CTX_wm_area(C);
ED_view3d_smooth_view_ex(
+ depsgraph,
wm, win, sa,
v3d, ar, smooth_viewtx,
sview);
@@ -294,6 +294,7 @@ void ED_view3d_smooth_view(
/* only meant for timer usage */
static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool sync_boxview)
{
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
RegionView3D *rv3d = ar->regiondata;
struct SmoothView3DStore *sms = rv3d->sms;
float step, step_inv;
@@ -314,7 +315,7 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool
else {
view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d);
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
}
@@ -347,7 +348,7 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool
rv3d->dist = sms->dst.dist * step + sms->src.dist * step_inv;
v3d->lens = sms->dst.lens * step + sms->src.lens * step_inv;
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
}
@@ -405,8 +406,9 @@ void ED_view3d_smooth_view_force_finish(
/* force update of view matrix so tools that run immediately after
* can use them without redrawing first */
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
- ED_view3d_update_viewmat(scene, v3d, ar, NULL, NULL, NULL);
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL);
}
}
@@ -434,6 +436,7 @@ void VIEW3D_OT_smoothview(wmOperatorType *ot)
static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op))
{
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
View3D *v3d;
ARegion *ar;
RegionView3D *rv3d;
@@ -447,11 +450,11 @@ static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op))
BKE_object_tfm_protected_backup(v3d->camera, &obtfm);
- ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ ED_view3d_to_object(depsgraph, v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
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);
@@ -504,29 +507,30 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot)
* meant to take into account vertex/bone selection for eg. */
static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
Object *camera_ob = v3d ? v3d->camera : scene->camera;
+ Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob);
float r_co[3]; /* the new location to apply */
float r_scale; /* only for ortho cameras */
- if (camera_ob == NULL) {
+ if (camera_ob_eval == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active camera");
return OPERATOR_CANCELLED;
}
/* this function does all the important stuff */
- if (BKE_camera_view_frame_fit_to_scene(bmain, scene, v3d, camera_ob, r_co, &r_scale)) {
+ if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, camera_ob_eval, r_co, &r_scale)) {
ObjectTfmProtectedChannels obtfm;
float obmat_new[4][4];
- if ((camera_ob->type == OB_CAMERA) && (((Camera *)camera_ob->data)->type == CAM_ORTHO)) {
+ if ((camera_ob_eval->type == OB_CAMERA) && (((Camera *)camera_ob_eval->data)->type == CAM_ORTHO)) {
((Camera *)camera_ob->data)->ortho_scale = r_scale;
}
- copy_m4_m4(obmat_new, camera_ob->obmat);
+ copy_m4_m4(obmat_new, camera_ob_eval->obmat);
copy_v3_v3(obmat_new[3], r_co);
/* only touch location */
@@ -535,7 +539,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;
}
@@ -690,14 +694,14 @@ void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
/**
* \param rect optional for picking (can be NULL).
*/
-void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect)
+void view3d_winmatrix_set(Depsgraph *depsgraph, ARegion *ar, const View3D *v3d, const rcti *rect)
{
RegionView3D *rv3d = ar->regiondata;
rctf viewplane;
float clipsta, clipend;
bool is_ortho;
- is_ortho = ED_view3d_viewplane_get(v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend, NULL);
+ is_ortho = ED_view3d_viewplane_get(depsgraph, v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend, NULL);
rv3d->is_persp = !is_ortho;
#if 0
@@ -716,14 +720,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)
@@ -742,6 +746,7 @@ static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
/**
* Sets #RegionView3D.viewmat
*
+ * \param depsgraph: Depsgraph.
* \param scene: Scene for camera and cursor location.
* \param v3d: View 3D space data.
* \param rv3d: 3D region which stores the final matrices.
@@ -751,13 +756,14 @@ static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
* \note don't set windows active in here, is used by renderwin too.
*/
void view3d_viewmatrix_set(
- Scene *scene,
+ Depsgraph *depsgraph, Scene *scene,
const View3D *v3d, RegionView3D *rv3d, const float rect_scale[2])
{
if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */
if (v3d->camera) {
- BKE_object_where_is_calc(scene, v3d->camera);
- obmat_to_viewmat(rv3d, v3d->camera);
+ Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
+ BKE_object_where_is_calc(depsgraph, scene, ob_camera_eval);
+ obmat_to_viewmat(rv3d, ob_camera_eval);
}
else {
quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
@@ -775,15 +781,15 @@ void view3d_viewmatrix_set(
quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
if (rv3d->persp == RV3D_PERSP) rv3d->viewmat[3][2] -= rv3d->dist;
if (v3d->ob_centre) {
- Object *ob = v3d->ob_centre;
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, v3d->ob_centre);
float vec[3];
- copy_v3_v3(vec, ob->obmat[3]);
- if (ob->type == OB_ARMATURE && v3d->ob_centre_bone[0]) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, v3d->ob_centre_bone);
+ copy_v3_v3(vec, ob_eval->obmat[3]);
+ if (ob_eval->type == OB_ARMATURE && v3d->ob_centre_bone[0]) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob_eval->pose, v3d->ob_centre_bone);
if (pchan) {
copy_v3_v3(vec, pchan->pose_mat[3]);
- mul_m4_v3(ob->obmat, vec);
+ mul_m4_v3(ob_eval->obmat, vec);
}
}
translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
@@ -791,7 +797,7 @@ void view3d_viewmatrix_set(
}
else if (v3d->ob_centre_cursor) {
float vec[3];
- copy_v3_v3(vec, ED_view3d_cursor3d_get(scene, (View3D *)v3d));
+ copy_v3_v3(vec, ED_view3d_cursor3d_get(scene, (View3D *)v3d)->location);
translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
use_lock_ofs = true;
}
@@ -850,6 +856,52 @@ void view3d_opengl_select_cache_end(void)
GPU_select_cache_end();
}
+#ifndef WITH_OPENGL_LEGACY
+struct DrawSelectLoopUserData {
+ uint pass;
+ uint hits;
+ uint *buffer;
+ uint buffer_len;
+ const rcti *rect;
+ char gpu_select_mode;
+};
+
+static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
+{
+ bool continue_pass = false;
+ struct DrawSelectLoopUserData *data = user_data;
+ if (stage == DRW_SELECT_PASS_PRE) {
+ GPU_select_begin(data->buffer, data->buffer_len, data->rect, data->gpu_select_mode, data->hits);
+ /* always run POST after PRE. */
+ continue_pass = true;
+ }
+ else if (stage == DRW_SELECT_PASS_POST) {
+ int hits = GPU_select_end();
+ if (data->pass == 0) {
+ /* quirk of GPU_select_end, only take hits value from first call. */
+ data->hits = hits;
+ }
+ if (data->gpu_select_mode == GPU_SELECT_NEAREST_FIRST_PASS) {
+ data->gpu_select_mode = GPU_SELECT_NEAREST_SECOND_PASS;
+ continue_pass = (hits > 0);
+ }
+ data->pass += 1;
+ }
+ else {
+ BLI_assert(0);
+ }
+ return continue_pass;
+
+}
+#endif /* WITH_OPENGL_LEGACY */
+
+/** Implement #VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK. */
+static bool drw_select_filter_object_mode_lock(Object *ob, void *user_data)
+{
+ const Object *obact = user_data;
+ return BKE_object_is_mode_compat(ob, obact->mode);
+}
+
/**
* \warning be sure to account for a negative return value
* This is an error, "Too many objects in select buffer"
@@ -859,15 +911,16 @@ void view3d_opengl_select_cache_end(void)
*/
int view3d_opengl_select(
ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input,
- eV3DSelectMode select_mode)
+ eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter)
{
struct bThemeState theme_state;
+ Depsgraph *depsgraph = vc->depsgraph;
Scene *scene = vc->scene;
View3D *v3d = vc->v3d;
ARegion *ar = vc->ar;
rcti rect;
int hits;
- const bool use_obedit_skip = (scene->obedit != NULL) && (vc->obedit == NULL);
+ const bool use_obedit_skip = (OBEDIT_FROM_VIEW_LAYER(vc->view_layer) != NULL) && (vc->obedit == NULL);
const bool is_pick_select = (U.gpu_select_pick_deph != 0);
const bool do_passes = (
(is_pick_select == false) &&
@@ -906,6 +959,25 @@ int view3d_opengl_select(
}
}
+ struct {
+ DRW_ObjectFilterFn fn;
+ void *user_data;
+ } object_filter = {NULL, NULL};
+ switch (select_filter) {
+ case VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK:
+ {
+ Object *obact = OBACT(vc->view_layer);
+ if (obact && obact->mode != OB_MODE_OBJECT) {
+ object_filter.fn = drw_select_filter_object_mode_lock;
+ object_filter.user_data = obact;
+ }
+ break;
+ }
+ case VIEW3D_SELECT_FILTER_NOP:
+ break;
+
+ }
+
/* Tools may request depth outside of regular drawing code. */
UI_Theme_Store(&theme_state);
UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
@@ -919,11 +991,16 @@ int view3d_opengl_select(
goto finally;
}
+#ifndef WITH_OPENGL_LEGACY
+ /* All of the queries need to be perform on the drawing context. */
+ DRW_opengl_context_enable();
+#endif
+
G.f |= G_PICKSEL;
/* 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, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect);
if (v3d->drawtype > OB_WIRE) {
v3d->zbuf = true;
@@ -933,23 +1010,43 @@ int view3d_opengl_select(
if (vc->rv3d->rflag & RV3D_CLIPPING)
ED_view3d_clipping_set(vc->rv3d);
- GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
-
- ED_view3d_draw_select_loop(vc, scene, v3d, ar, use_obedit_skip, use_nearest);
- hits = GPU_select_end();
-
- /* second pass, to get the closest object to camera */
- 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)) {
+ GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
+ ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
+ hits = GPU_select_end();
- GPU_select_end();
+ if (do_passes && (hits > 0)) {
+ GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+ ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
+ GPU_select_end();
+ }
+ }
+ else
+#else
+ {
+ /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop
+ * because the OpenGL context created & destroyed inside this function. */
+ struct DrawSelectLoopUserData drw_select_loop_user_data = {
+ .pass = 0,
+ .hits = 0,
+ .buffer = buffer,
+ .buffer_len = bufsize,
+ .rect = &rect,
+ .gpu_select_mode = gpu_select_mode,
+ };
+ DRW_draw_select_loop(
+ depsgraph, ar, v3d,
+ use_obedit_skip, use_nearest, &rect,
+ drw_select_loop_pass, &drw_select_loop_user_data,
+ object_filter.fn, object_filter.user_data);
+ hits = drw_select_loop_user_data.hits;
}
+#endif /* WITH_OPENGL_LEGACY */
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, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
if (v3d->drawtype > OB_WIRE) {
v3d->zbuf = 0;
@@ -959,7 +1056,12 @@ int view3d_opengl_select(
if (vc->rv3d->rflag & RV3D_CLIPPING)
ED_view3d_clipping_disable();
+#ifndef WITH_OPENGL_LEGACY
+ DRW_opengl_context_disable();
+#endif
+
finally:
+
if (hits < 0) printf("Too many objects in select buffer\n"); /* XXX make error message */
UI_Theme_Restore(&theme_state);
@@ -970,44 +1072,10 @@ finally:
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Local View Operators
+/** \name View Layer Utilities
* \{ */
-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 ED_view3d_view_layer_set(int lay, const int *values, int *active)
{
int i, tot = 0;
@@ -1045,478 +1113,4 @@ 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, 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, 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, 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;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Game Engine Operator
- *
- * Start the game engine (handles context switching).
- * \{ */
-
-#ifdef WITH_GAMEENGINE
-
-static ListBase queue_back;
-static void game_engine_save_state(bContext *C, wmWindow *win)
-{
- Main *bmain = CTX_data_main(C);
- Object *obact = CTX_data_active_object(C);
-
- glPushAttrib(GL_ALL_ATTRIB_BITS);
-
- if (obact && obact->mode & OB_MODE_TEXTURE_PAINT)
- GPU_paint_set_mipmap(bmain, 1);
-
- queue_back = win->queue;
-
- BLI_listbase_clear(&win->queue);
-}
-
-static void game_engine_restore_state(bContext *C, wmWindow *win)
-{
- Main *bmain = CTX_data_main(C);
- Object *obact = CTX_data_active_object(C);
-
- if (obact && obact->mode & OB_MODE_TEXTURE_PAINT)
- GPU_paint_set_mipmap(bmain, 0);
-
- /* check because closing win can set to NULL */
- if (win) {
- win->queue = queue_back;
- }
-
- GPU_state_init();
- GPU_set_tpage(NULL, 0, 0);
-
- glPopAttrib();
-}
-
-/* was space_set_commmandline_options in 2.4x */
-static void game_set_commmandline_options(GameData *gm)
-{
- SYS_SystemHandle syshandle;
- int test;
-
- if ((syshandle = SYS_GetSystem())) {
- /* User defined settings */
- test = (U.gameflags & USER_DISABLE_MIPMAP);
- GPU_set_mipmap(G_MAIN, !test);
- SYS_WriteCommandLineInt(syshandle, "nomipmap", test);
-
- /* File specific settings: */
- /* Only test the first one. These two are switched
- * simultaneously. */
- test = (gm->flag & GAME_SHOW_FRAMERATE);
- SYS_WriteCommandLineInt(syshandle, "show_framerate", test);
- SYS_WriteCommandLineInt(syshandle, "show_profile", test);
-
- test = (gm->flag & GAME_SHOW_DEBUG_PROPS);
- SYS_WriteCommandLineInt(syshandle, "show_properties", test);
-
- test = (gm->flag & GAME_SHOW_PHYSICS);
- SYS_WriteCommandLineInt(syshandle, "show_physics", test);
-
- test = (gm->flag & GAME_ENABLE_ALL_FRAMES);
- SYS_WriteCommandLineInt(syshandle, "fixedtime", test);
-
- test = (gm->flag & GAME_ENABLE_ANIMATION_RECORD);
- SYS_WriteCommandLineInt(syshandle, "animation_record", test);
-
- test = (gm->flag & GAME_IGNORE_DEPRECATION_WARNINGS);
- SYS_WriteCommandLineInt(syshandle, "ignore_deprecation_warnings", test);
-
- test = (gm->matmode == GAME_MAT_MULTITEX);
- 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);
-
-
- }
-}
-
-#endif /* WITH_GAMEENGINE */
-
-static int game_engine_poll(bContext *C)
-{
- bScreen *screen;
- /* 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 (CTX_data_mode_enum(C) != CTX_MODE_OBJECT)
- return 0;
-
- if (!BKE_scene_uses_blender_game(screen->scene))
- return 0;
-
- return 1;
-}
-
-static int game_engine_exec(bContext *C, wmOperator *op)
-{
-#ifdef WITH_GAMEENGINE
- Scene *startscene = CTX_data_scene(C);
- Main *bmain = CTX_data_main(C);
- ScrArea /* *sa, */ /* UNUSED */ *prevsa = CTX_wm_area(C);
- ARegion *ar, *prevar = CTX_wm_region(C);
- wmWindow *prevwin = CTX_wm_window(C);
- RegionView3D *rv3d;
- rcti cam_frame;
-
- UNUSED_VARS(op);
-
- /* bad context switch .. */
- if (!ED_view3d_context_activate(C))
- return OPERATOR_CANCELLED;
-
- /* redraw to hide any menus/popups, we don't go back to
- * the window manager until after this operator exits */
- WM_redraw_windows(C);
-
- BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_PRE);
-
- rv3d = CTX_wm_region_view3d(C);
- /* sa = CTX_wm_area(C); */ /* UNUSED */
- ar = CTX_wm_region(C);
-
- view3d_operator_needs_opengl(C);
-
- game_set_commmandline_options(&startscene->gm);
-
- if ((rv3d->persp == RV3D_CAMOB) &&
- (startscene->gm.framing.type == SCE_GAMEFRAMING_BARS) &&
- (startscene->gm.stereoflag != STEREO_DOME))
- {
- /* Letterbox */
- rctf cam_framef;
- ED_view3d_calc_camera_border(startscene, ar, CTX_wm_view3d(C), rv3d, &cam_framef, false);
- cam_frame.xmin = cam_framef.xmin + ar->winrct.xmin;
- cam_frame.xmax = cam_framef.xmax + ar->winrct.xmin;
- cam_frame.ymin = cam_framef.ymin + ar->winrct.ymin;
- cam_frame.ymax = cam_framef.ymax + ar->winrct.ymin;
- BLI_rcti_isect(&ar->winrct, &cam_frame, &cam_frame);
- }
- else {
- cam_frame.xmin = ar->winrct.xmin;
- cam_frame.xmax = ar->winrct.xmax;
- cam_frame.ymin = ar->winrct.ymin;
- cam_frame.ymax = ar->winrct.ymax;
- }
-
-
- game_engine_save_state(C, prevwin);
-
- StartKetsjiShell(C, ar, &cam_frame, 1);
-
- /* window wasnt closed while the BGE was running */
- if (BLI_findindex(&CTX_wm_manager(C)->windows, prevwin) == -1) {
- prevwin = NULL;
- CTX_wm_window_set(C, NULL);
- }
-
- ED_area_tag_redraw(CTX_wm_area(C));
-
- if (prevwin) {
- /* restore context, in case it changed in the meantime, for
- * example by working in another window or closing it */
- CTX_wm_region_set(C, prevar);
- CTX_wm_window_set(C, prevwin);
- CTX_wm_area_set(C, prevsa);
- }
-
- game_engine_restore_state(C, prevwin);
-
- //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);
-
- BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_POST);
-
- return OPERATOR_FINISHED;
-#else
- UNUSED_VARS(C);
- BKE_report(op->reports, RPT_ERROR, "Game engine is disabled in this build");
- return OPERATOR_CANCELLED;
-#endif
-}
-
-void VIEW3D_OT_game_start(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Start Game Engine";
- ot->description = "Start game engine";
- ot->idname = "VIEW3D_OT_game_start";
-
- /* api callbacks */
- ot->exec = game_engine_exec;
-
- ot->poll = game_engine_poll;
-}
-
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index f780ca35f30..352e85703bc 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -37,6 +37,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_main.h"
#include "BKE_report.h"
#include "BLT_translation.h"
@@ -56,6 +57,10 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_immediate.h"
+
+#include "DEG_depsgraph.h"
+
#include "view3d_intern.h" /* own include */
#ifdef WITH_INPUT_NDOF
@@ -245,6 +250,7 @@ typedef struct WalkInfo {
RegionView3D *rv3d;
View3D *v3d;
ARegion *ar;
+ struct Depsgraph *depsgraph;
Scene *scene;
wmTimer *timer; /* needed for redraws */
@@ -328,7 +334,7 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *a
rctf viewborder;
if (walk->scene->camera) {
- ED_view3d_calc_camera_border(walk->scene, ar, walk->v3d, walk->rv3d, &viewborder, false);
+ ED_view3d_calc_camera_border(walk->scene, walk->depsgraph, ar, walk->v3d, walk->rv3d, &viewborder, false);
xoff = viewborder.xmin + BLI_rctf_size_x(&viewborder) * 0.5f;
yoff = viewborder.ymin + BLI_rctf_size_y(&viewborder) * 0.5f;
}
@@ -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)
@@ -493,11 +508,13 @@ static float userdef_speed = -1.f;
static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
walk->rv3d = CTX_wm_region_view3d(C);
walk->v3d = CTX_wm_view3d(C);
walk->ar = CTX_wm_region(C);
+ walk->depsgraph = CTX_data_depsgraph(C);
walk->scene = CTX_data_scene(C);
#ifdef NDOF_WALK_DEBUG
@@ -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,
+ bmain, walk->scene, CTX_data_depsgraph(C), 0,
walk->ar, walk->v3d);
walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
- walk->scene, walk->v3d, walk->rv3d,
+ walk->depsgraph, walk->scene, walk->v3d, walk->rv3d,
(U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
/* center the mouse */