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 vec[4][3], asp[2], shift[2], scale[3], drawsize, center[2], corner[2];
float *color_p; 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); 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. * 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. * \param rect: The offsets for the view, not the zones.
*/ */
void UI_draw_safe_areas(uint pos, void UI_draw_safe_areas(const rctf *rect,
const rctf *rect,
const float title_aspect[2], const float title_aspect[2],
const float action_aspect[2]); const float action_aspect[2]);

View File

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

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, static void sequencer_draw_borders_overlay(const SpaceSeq *sseq,
const View2D *v2d, const View2D *v2d,
const Scene *scene) 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. */ /* Draw safety border. */
if (sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_SAFE_MARGINS) { if (sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_SAFE_MARGINS) {
immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f); UI_draw_safe_areas(&v2d->tot, scene->safe_areas.title, scene->safe_areas.action);
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);
if (sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_SAFE_CENTER) { if (sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_SAFE_CENTER) {
UI_draw_safe_areas( 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 #if 0

View File

@ -34,8 +34,3 @@
#include "DRW_engine.hh" #include "DRW_engine.hh"
#include "view3d_intern.h" /* bad level include */ #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); x4 = x1 + (1.0f - fac) * (x2 - x1);
y4 = y1 + (1.0f - fac) * (y2 - y1); y4 = y1 + (1.0f - fac) * (y2 - y1);
float overlap = (x2 - x1 + y2 - y1) * 0.015f;
immBegin(GPU_PRIM_LINES, 8); immBegin(GPU_PRIM_LINES, 8);
immVertex2f(shdr_pos, x1, y3); immVertex2f(shdr_pos, x1 - overlap, y4);
immVertex2f(shdr_pos, x2, y3); immVertex2f(shdr_pos, x2 + overlap, y4);
immVertex2f(shdr_pos, x1, y4); immVertex2f(shdr_pos, x1 - overlap, y3);
immVertex2f(shdr_pos, x2, y4); immVertex2f(shdr_pos, x2 + overlap, y3);
immVertex2f(shdr_pos, x3, y1); immVertex2f(shdr_pos, x3, y1 - overlap);
immVertex2f(shdr_pos, x3, y2); immVertex2f(shdr_pos, x3, y2 + overlap);
immVertex2f(shdr_pos, x4, y1); immVertex2f(shdr_pos, x4, y1 - overlap);
immVertex2f(shdr_pos, x4, y2); immVertex2f(shdr_pos, x4, y2 + overlap);
immEnd(); immEnd();
} }
@ -537,13 +539,82 @@ static void drawviewborder_triangle(
immEnd(); 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 x1, x2, y1, y2;
float x1i, x2i, y1i, y2i; float x1i, x2i, y1i, y2i;
rctf viewborder; rctf viewborder;
Camera *ca = nullptr;
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata); RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
if (v3d->camera == nullptr) { 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 /* NOTE: quite un-scientific but without this bit extra
* 0.0001 on the lower left the 2D border sometimes * 0.0001 on the lower left the 2D border sometimes
* obscures the 3D camera border */ * 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); x1i = int(x1 - 1.0001f);
y1i = int(y1 - 1.0001f); y1i = int(y1 - 1.0001f);
x2i = int(x2 + (1.0f - 0.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) { if (y2i > 0.0f) {
immRectf(shdr_pos, x1i, y1i, x2i, 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. */ /* When overlays are disabled, only show camera outline & passepartout. */
if (v3d->flag2 & V3D_HIDE_OVERLAYS) { if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
immUnbindProgram();
return; return;
} }
/* And now, the dashed lines! */ /* outer line not to confuse with object selection */
immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); if (v3d->flag2 & V3D_LOCK_CAMERA) {
immUniformThemeColor(TH_REDALERT);
{ imm_draw_box_wire_2d(shdr_pos, x1i - 1, y1i - 1, x2i + 1, y2i + 1);
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);
} }
/* Render Border. */ /* 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); 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 */ /* safety border */
if (ca) { if (ca) {
GPU_blend(GPU_BLEND_ALPHA); 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) { if (ca->dtx & CAM_DTX_CENTER) {
float x3, y3; float x3, y3;
x3 = x1 + 0.5f * (x2 - x1); x3 = x1 + 0.5f * (x2 - x1);
y3 = y1 + 0.5f * (y2 - y1); y3 = y1 + 0.5f * (y2 - y1);
float overlap = (x2 - x1 + y2 - y1) * 0.015f;
immBegin(GPU_PRIM_LINES, 4); immBegin(GPU_PRIM_LINES, 4);
immVertex2f(shdr_pos, x1 - overlap, y3);
immVertex2f(shdr_pos, x1, y3); immVertex2f(shdr_pos, x2 + overlap, y3);
immVertex2f(shdr_pos, x2, y3); immVertex2f(shdr_pos, x3, y1 - overlap);
immVertex2f(shdr_pos, x3, y2 + overlap);
immVertex2f(shdr_pos, x3, y1);
immVertex2f(shdr_pos, x3, y2);
immEnd(); immEnd();
} }
@ -722,29 +764,6 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region,
drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'B'); 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) { if (ca->flag & CAM_SHOWSENSOR) {
/* determine sensor fit, and get sensor x/y, for auto fit we /* determine sensor fit, and get sensor x/y, for auto fit we
* assume and square sensor and only use sensor_x */ * assume and square sensor and only use sensor_x */
@ -777,7 +796,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region,
} }
/* draw */ /* draw */
immUniformThemeColorShadeAlpha(TH_VIEW_OVERLAY, 100, 255); immUniformColor4f(1.0f, 1.0f, 1.0f, 0.1f);
/* TODO: Was using: /* TODO: Was using:
* `UI_draw_roundbox_4fv(false, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color);` * `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. */ * 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); imm_draw_box_wire_2d(shdr_pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
} }
GPU_blend(GPU_BLEND_NONE);
} }
immUnbindProgram(); 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 */ /* camera name - draw in highlighted text color */
if (ca && ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) && (ca->flag & CAM_SHOWNAME)) { 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); View3D *v3d = CTX_wm_view3d(C);
if (rv3d->persp == RV3D_CAMOB) { 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) { else if (v3d->flag2 & V3D_RENDER_BORDER) {
drawrenderborder(region, v3d); drawrenderborder(region, v3d);

View File

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

View File

@ -241,17 +241,6 @@ void VIEW3D_GT_navigate_rotate(struct wmGizmoType *gzt);
void VIEW3D_GGT_placement(struct wmGizmoGroupType *gzgt); 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 #ifdef __cplusplus
} }
#endif #endif