WIP: UI: Camera View Drawing #117117

Draft
Harley Acheson wants to merge 4 commits from Harley/blender:CameraView into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
8 changed files with 152 additions and 160 deletions

View File

@ -1148,8 +1148,11 @@ void OVERLAY_camera_cache_populate(OVERLAY_Data *vedata, Object *ob)
float vec[4][3], asp[2], shift[2], scale[3], drawsize, center[2], corner[2];
float *color_p;
DRW_object_wire_theme_get(ob, view_layer, &color_p);
copy_v4_v4(instdata.color, color_p);
if (rv3d->persp != RV3D_CAMOB) {
DRW_object_wire_theme_get(ob, view_layer, &color_p);
copy_v4_v4(instdata.color, color_p);
}
normalize_m4_m4(instdata.mat, ob->object_to_world);

View File

@ -500,13 +500,9 @@ void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const flo
/**
* Draw title and text safe areas.
*
* \note This function is to be used with the 2D dashed shader enabled.
*
* \param pos: is a #PRIM_FLOAT, 2, #GPU_FETCH_FLOAT vertex attribute.
* \param rect: The offsets for the view, not the zones.
*/
void UI_draw_safe_areas(uint pos,
const rctf *rect,
void UI_draw_safe_areas(const rctf *rect,
const float title_aspect[2],
const float action_aspect[2]);

View File

@ -384,29 +384,28 @@ void ui_draw_but_IMAGE(ARegion * /*region*/,
#endif
}
void UI_draw_safe_areas(uint pos,
const rctf *rect,
void UI_draw_safe_areas(const rctf *rect,
const float title_aspect[2],
const float action_aspect[2])
{
const float size_x_half = (rect->xmax - rect->xmin) * 0.5f;
const float size_y_half = (rect->ymax - rect->ymin) * 0.5f;
const float radius = (BLI_rctf_size_x(rect) + BLI_rctf_size_y(rect)) / 200.0f;
const float color[4] = {0.5f, 1.0f, 0.5f, 0.1f};
rctf border;
const float *safe_areas[] = {title_aspect, action_aspect};
const int safe_len = ARRAY_SIZE(safe_areas);
if (title_aspect[0] || title_aspect[1]) {
border = *rect;
BLI_rctf_resize(&border,
BLI_rctf_size_x(rect) * (1.0f - title_aspect[0]),
BLI_rctf_size_y(rect) * (1.0f - title_aspect[1]));
UI_draw_roundbox_4fv(&border, false, 0.0f, color);
}
for (int i = 0; i < safe_len; i++) {
if (safe_areas[i][0] || safe_areas[i][1]) {
const float margin_x = safe_areas[i][0] * size_x_half;
const float margin_y = safe_areas[i][1] * size_y_half;
const float minx = rect->xmin + margin_x;
const float miny = rect->ymin + margin_y;
const float maxx = rect->xmax - margin_x;
const float maxy = rect->ymax - margin_y;
imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
}
if (action_aspect[0] || action_aspect[1]) {
border = *rect;
BLI_rctf_resize(&border,
BLI_rctf_size_x(rect) * (1.0f - action_aspect[0]),
BLI_rctf_size_y(rect) * (1.0f - action_aspect[1]));
UI_draw_roundbox_4fv(&border, false, 0.0f, color);
}
}

View File

@ -201,54 +201,20 @@ static void sequencer_draw_gpencil_overlay(const bContext *C)
}
/**
* Draw content and safety borders.
* Draw safety borders.
*/
static void sequencer_draw_borders_overlay(const SpaceSeq *sseq,
const View2D *v2d,
const Scene *scene)
{
float x1 = v2d->tot.xmin;
float y1 = v2d->tot.ymin;
float x2 = v2d->tot.xmax;
float y2 = v2d->tot.ymax;
GPU_line_width(1.0f);
/* Draw border. */
const uint shdr_pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC);
immUniformThemeColor(TH_BACK);
immUniform1i("colors_len", 0); /* Simple dashes. */
immUniform1f("dash_width", 6.0f);
immUniform1f("udash_factor", 0.5f);
imm_draw_box_wire_2d(shdr_pos, x1 - 0.5f, y1 - 0.5f, x2 + 0.5f, y2 + 0.5f);
/* Draw safety border. */
if (sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_SAFE_MARGINS) {
immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f);
rctf rect;
rect.xmin = x1;
rect.xmax = x2;
rect.ymin = y1;
rect.ymax = y2;
UI_draw_safe_areas(shdr_pos, &rect, scene->safe_areas.title, scene->safe_areas.action);
UI_draw_safe_areas(&v2d->tot, scene->safe_areas.title, scene->safe_areas.action);
if (sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_SAFE_CENTER) {
UI_draw_safe_areas(
shdr_pos, &rect, scene->safe_areas.title_center, scene->safe_areas.action_center);
&v2d->tot, scene->safe_areas.title_center, scene->safe_areas.action_center);
}
}
immUnbindProgram();
}
#if 0

View File

@ -34,8 +34,3 @@
#include "DRW_engine.hh"
#include "view3d_intern.h" /* bad level include */
#ifdef VIEW3D_CAMERA_BORDER_HACK
uchar view3d_camera_border_hack_col[3];
bool view3d_camera_border_hack_test = false;
#endif

View File

@ -466,19 +466,21 @@ static void drawviewborder_grid3(uint shdr_pos, float x1, float x2, float y1, fl
x4 = x1 + (1.0f - fac) * (x2 - x1);
y4 = y1 + (1.0f - fac) * (y2 - y1);
float overlap = (x2 - x1 + y2 - y1) * 0.015f;
immBegin(GPU_PRIM_LINES, 8);
immVertex2f(shdr_pos, x1, y3);
immVertex2f(shdr_pos, x2, y3);
immVertex2f(shdr_pos, x1 - overlap, y4);
immVertex2f(shdr_pos, x2 + overlap, y4);
immVertex2f(shdr_pos, x1, y4);
immVertex2f(shdr_pos, x2, y4);
immVertex2f(shdr_pos, x1 - overlap, y3);
immVertex2f(shdr_pos, x2 + overlap, y3);
immVertex2f(shdr_pos, x3, y1);
immVertex2f(shdr_pos, x3, y2);
immVertex2f(shdr_pos, x3, y1 - overlap);
immVertex2f(shdr_pos, x3, y2 + overlap);
immVertex2f(shdr_pos, x4, y1);
immVertex2f(shdr_pos, x4, y2);
immVertex2f(shdr_pos, x4, y1 - overlap);
immVertex2f(shdr_pos, x4, y2 + overlap);
immEnd();
}
@ -537,13 +539,82 @@ static void drawviewborder_triangle(
immEnd();
}
static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region, View3D *v3d)
static void drawviewborder_corners(uint shdr_pos,
rctf *border,
const bool active,
float corner_len)
{
if (active)
{
float active[4];
UI_GetThemeColor4fv(TH_ACTIVE, active);
active[3] = 0.8;
immUniformColor4fv(active);
}
else
{
float inactive[4];
UI_GetThemeColor4fv(TH_ACTIVE, inactive);
float gray = rgb_to_grayscale(inactive);
inactive[0] = gray;
inactive[1] = gray;
inactive[2] = gray;
inactive[3] = 0.4f;
immUniformColor4fv(inactive);
}
float width = (corner_len / 10) + U.pixelsize;
/* Top-Left. */
immRectf(
shdr_pos, border->xmin, border->ymax + width, border->xmin + corner_len, border->ymax);
immRectf(shdr_pos,
border->xmin - width,
border->ymax - corner_len,
border->xmin,
border->ymax + width);
/* Top-Right. */
immRectf(
shdr_pos, border->xmax - corner_len, border->ymax + width, border->xmax, border->ymax);
immRectf(shdr_pos,
border->xmax,
border->ymax - corner_len,
border->xmax + width,
border->ymax + width);
/* Bottom-Left. */
immRectf(
shdr_pos, border->xmin, border->ymin, border->xmin + corner_len, border->ymin - width);
immRectf(shdr_pos,
border->xmin - width,
border->ymin + corner_len,
border->xmin,
border->ymin - width);
/* Bottom-Right. */
immRectf(
shdr_pos, border->xmax - corner_len, border->ymin - width, border->xmax, border->ymin);
immRectf(shdr_pos,
border->xmax,
border->ymin + corner_len,
border->xmax + width,
border->ymin - width);
}
static void drawviewborder(
Scene *scene, Depsgraph *depsgraph, ARegion *region, View3D *v3d, bool active)
{
Camera *ca = (v3d->camera->type == OB_CAMERA) ? (Camera *)v3d->camera->data : NULL;
if (ca == NULL)
{
return;
}
float x1, x2, y1, y2;
float x1i, x2i, y1i, y2i;
rctf viewborder;
Camera *ca = nullptr;
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
if (v3d->camera == nullptr) {
@ -567,8 +638,6 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region,
/* NOTE: quite un-scientific but without this bit extra
* 0.0001 on the lower left the 2D border sometimes
* obscures the 3D camera border */
/* NOTE: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable
* but keep it here in case we need to remove the workaround */
x1i = int(x1 - 1.0001f);
y1i = int(y1 - 1.0001f);
x2i = int(x2 + (1.0f - 0.0001f));
@ -607,48 +676,19 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region,
if (y2i > 0.0f) {
immRectf(shdr_pos, x1i, y1i, x2i, 0.0f);
}
GPU_blend(GPU_BLEND_NONE);
immUniformThemeColor3(TH_BACK);
imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i);
}
#ifdef VIEW3D_CAMERA_BORDER_HACK
if (view3d_camera_border_hack_test == true) {
immUniformColor3ubv(view3d_camera_border_hack_col);
imm_draw_box_wire_2d(shdr_pos, x1i + 1, y1i + 1, x2i - 1, y2i - 1);
view3d_camera_border_hack_test = false;
}
#endif
immUnbindProgram();
}
/* When overlays are disabled, only show camera outline & passepartout. */
if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
immUnbindProgram();
return;
}
/* And now, the dashed lines! */
immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
{
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniform1i("colors_len", 0); /* "simple" mode */
immUniform1f("dash_width", 6.0f);
immUniform1f("udash_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);
}
immUniformThemeColor3(TH_VIEW_OVERLAY);
imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i);
/* 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);
}
/* Render Border. */
@ -664,25 +704,27 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region,
imm_draw_box_wire_2d(shdr_pos, x3, y3, x4, y4);
}
float corner_size = ((viewborder.xmax - viewborder.xmin) + (viewborder.ymax - viewborder.ymin)) *
0.04f;
drawviewborder_corners(shdr_pos, &viewborder, active, corner_size);
/* safety border */
if (ca) {
GPU_blend(GPU_BLEND_ALPHA);
immUniformThemeColorAlpha(TH_VIEW_OVERLAY, 0.75f);
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.15f);
if (ca->dtx & CAM_DTX_CENTER) {
float x3, y3;
x3 = x1 + 0.5f * (x2 - x1);
y3 = y1 + 0.5f * (y2 - y1);
float overlap = (x2 - x1 + y2 - y1) * 0.015f;
immBegin(GPU_PRIM_LINES, 4);
immVertex2f(shdr_pos, x1, y3);
immVertex2f(shdr_pos, x2, y3);
immVertex2f(shdr_pos, x3, y1);
immVertex2f(shdr_pos, x3, y2);
immVertex2f(shdr_pos, x1 - overlap, y3);
immVertex2f(shdr_pos, x2 + overlap, y3);
immVertex2f(shdr_pos, x3, y1 - overlap);
immVertex2f(shdr_pos, x3, y2 + overlap);
immEnd();
}
@ -722,29 +764,6 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region,
drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'B');
}
if (ca->flag & CAM_SHOW_SAFE_MARGINS) {
rctf margins_rect{};
margins_rect.xmin = x1;
margins_rect.xmax = x2;
margins_rect.ymin = y1;
margins_rect.ymax = y2;
UI_draw_safe_areas(
shdr_pos, &margins_rect, scene->safe_areas.title, scene->safe_areas.action);
if (ca->flag & CAM_SHOW_SAFE_CENTER) {
rctf center_rect{};
center_rect.xmin = x1;
center_rect.xmax = x2;
center_rect.ymin = y1;
center_rect.ymax = y2;
UI_draw_safe_areas(shdr_pos,
&center_rect,
scene->safe_areas.title_center,
scene->safe_areas.action_center);
}
}
if (ca->flag & CAM_SHOWSENSOR) {
/* determine sensor fit, and get sensor x/y, for auto fit we
* assume and square sensor and only use sensor_x */
@ -777,7 +796,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region,
}
/* draw */
immUniformThemeColorShadeAlpha(TH_VIEW_OVERLAY, 100, 255);
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.1f);
/* TODO: Was using:
* `UI_draw_roundbox_4fv(false, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color);`
@ -785,12 +804,31 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region,
* 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);
}
GPU_blend(GPU_BLEND_NONE);
}
immUnbindProgram();
/* end dashed lines */
if (ca && ca->flag & CAM_SHOW_SAFE_MARGINS) {
rctf margins_rect{};
margins_rect.xmin = x1;
margins_rect.xmax = x2;
margins_rect.ymin = y1;
margins_rect.ymax = y2;
UI_draw_safe_areas(&margins_rect, scene->safe_areas.title, scene->safe_areas.action);
if (ca && ca->flag & CAM_SHOW_SAFE_CENTER) {
rctf center_rect{};
center_rect.xmin = x1;
center_rect.xmax = x2;
center_rect.ymin = y1;
center_rect.ymax = y2;
UI_draw_safe_areas(
&center_rect, scene->safe_areas.title_center, scene->safe_areas.action_center);
}
}
GPU_blend(GPU_BLEND_NONE);
/* camera name - draw in highlighted text color */
if (ca && ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) && (ca->flag & CAM_SHOWNAME)) {
@ -1149,7 +1187,9 @@ static void view3d_draw_border(const bContext *C, ARegion *region)
View3D *v3d = CTX_wm_view3d(C);
if (rv3d->persp == RV3D_CAMOB) {
drawviewborder(scene, depsgraph, region, v3d);
Object *ob = CTX_data_active_object(C);
const bool active = ob == v3d->camera;
drawviewborder(scene, depsgraph, region, v3d, active);
}
else if (v3d->flag2 & V3D_RENDER_BORDER) {
drawrenderborder(region, v3d);

View File

@ -49,6 +49,10 @@ struct CameraWidgetGroup {
static bool WIDGETGROUP_camera_poll(const bContext *C, wmGizmoGroupType * /*gzgt*/)
{
if (CTX_wm_region_view3d(C)->persp == RV3D_CAMOB) {
return false;
}
View3D *v3d = CTX_wm_view3d(C);
if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
return false;

View File

@ -241,17 +241,6 @@ void VIEW3D_GT_navigate_rotate(struct wmGizmoType *gzt);
void VIEW3D_GGT_placement(struct wmGizmoGroupType *gzgt);
/* workaround for trivial but noticeable camera bug caused by imprecision
* between view border calculation in 2D/3D space, workaround for bug #28037.
* without this define we get the old behavior which is to try and align them
* both which _mostly_ works fine, but when the camera moves beyond ~1000 in
* any direction it starts to fail */
#define VIEW3D_CAMERA_BORDER_HACK
#ifdef VIEW3D_CAMERA_BORDER_HACK
extern uchar view3d_camera_border_hack_col[3];
extern bool view3d_camera_border_hack_test;
#endif
#ifdef __cplusplus
}
#endif