diff --git a/src/gs-limits.h b/src/gs-limits.h index e3d7714a0..6c54798a1 100644 --- a/src/gs-limits.h +++ b/src/gs-limits.h @@ -22,5 +22,5 @@ namespace GS { static const uint32_t MAXIMUM_VERTICES = 0xFFFFFFu; - static const uint32_t MAXIMUM_UVW_LAYERS = 1u; + static const uint32_t MAXIMUM_UVW_LAYERS = 8u; } \ No newline at end of file diff --git a/src/nodeobs_display.cpp b/src/nodeobs_display.cpp index aa32561a1..0d60a9d1c 100644 --- a/src/nodeobs_display.cpp +++ b/src/nodeobs_display.cpp @@ -57,11 +57,11 @@ static void RecalculateApectRatioConstrainedSize( } OBS::Display::Display() { -#if defined(_WIN32) + #if defined(_WIN32) DisplayWndClass(); -#elif defined(__APPLE__) -#elif defined(__linux__) || defined(__FreeBSD__) -#endif + #elif defined(__APPLE__) + #elif defined(__linux__) || defined(__FreeBSD__) + #endif m_gsInitData.adapter = 0; m_gsInitData.cx = 960; @@ -77,51 +77,8 @@ OBS::Display::Display() { obs_enter_graphics(); m_gsSolidEffect = obs_get_base_effect(OBS_EFFECT_SOLID); - GS::Vertex v(nullptr, nullptr, nullptr, nullptr, nullptr); - - m_boxLine = std::make_unique(6); - m_boxLine->Resize(6); - v = m_boxLine->At(0); - vec3_set(v.position, 0, 0, 0); - vec4_set(v.uv[0], 0, 0, 0, 0); - *v.color = 0xFFFFFFFF; - v = m_boxLine->At(1); - vec3_set(v.position, 1, 0, 0); - vec4_set(v.uv[0], 1, 0, 0, 0); - *v.color = 0xFFFFFFFF; - v = m_boxLine->At(2); - vec3_set(v.position, 1, 1, 0); - vec4_set(v.uv[0], 1, 1, 0, 0); - *v.color = 0xFFFFFFFF; - v = m_boxLine->At(3); - vec3_set(v.position, 0, 1, 0); - vec4_set(v.uv[0], 0, 1, 0, 0); - *v.color = 0xFFFFFFFF; - v = m_boxLine->At(4); - vec3_set(v.position, 0, 0, 0); - vec4_set(v.uv[0], 0, 0, 0, 0); - *v.color = 0xFFFFFFFF; - m_boxLine->Update(); - - m_boxTris = std::make_unique(4); - m_boxTris->Resize(4); - v = m_boxTris->At(0); - vec3_set(v.position, 0, 0, 0); - vec4_set(v.uv[0], 0, 0, 0, 0); - *v.color = 0xFFFFFFFF; - v = m_boxTris->At(1); - vec3_set(v.position, 1, 0, 0); - vec4_set(v.uv[0], 1, 0, 0, 0); - *v.color = 0xFFFFFFFF; - v = m_boxTris->At(2); - vec3_set(v.position, 0, 1, 0); - vec4_set(v.uv[0], 0, 1, 0, 0); - *v.color = 0xFFFFFFFF; - v = m_boxTris->At(3); - vec3_set(v.position, 1, 1, 0); - vec4_set(v.uv[0], 1, 1, 0, 0); - *v.color = 0xFFFFFFFF; - m_boxTris->Update(); + m_lines = new GS::VertexBuffer(65535); + m_triangles = new GS::VertexBuffer(65535); // Text m_textVertices = new GS::VertexBuffer(65535); @@ -140,7 +97,7 @@ OBS::Display::Display() { } OBS::Display::Display(uint64_t windowHandle) : Display() { -#if defined(_WIN32) + #if defined(_WIN32) FixChromeD3DIssue((HWND)windowHandle); m_ourWindow = CreateWindowEx( @@ -164,11 +121,11 @@ OBS::Display::Display(uint64_t windowHandle) : Display() { SetParent(m_ourWindow, (HWND)windowHandle); m_gsInitData.window.hwnd = reinterpret_cast(m_ourWindow); -#elif defined(__APPLE__) + #elif defined(__APPLE__) // ToDo -#elif defined(__linux__) || defined(__FreeBSD__) + #elif defined(__linux__) || defined(__FreeBSD__) // ToDo -#endif + #endif m_display = obs_display_create(&m_gsInitData); if (!m_display) @@ -194,19 +151,21 @@ OBS::Display::~Display() { obs_enter_graphics(); if (m_textVertices) delete m_textVertices; - m_boxLine = nullptr; - m_boxTris = nullptr; + if (m_triangles) + delete m_triangles; + if (m_lines) + delete m_lines; obs_leave_graphics(); -#if defined(_WIN32) + #if defined(_WIN32) if (m_ourWindow) { DestroyWindow((HWND)(m_gsInitData.window.hwnd)); } -#elif defined(__APPLE__) + #elif defined(__APPLE__) // ToDo -#elif defined(__linux__) || defined(__FreeBSD__) + #elif defined(__linux__) || defined(__FreeBSD__) // ToDo -#endif + #endif } void OBS::Display::SetPosition(uint32_t x, uint32_t y) { @@ -216,15 +175,15 @@ void OBS::Display::SetPosition(uint32_t x, uint32_t y) { } // Move Window -#if defined(_WIN32) + #if defined(_WIN32) SetWindowPos(m_ourWindow, NULL, x, y, m_gsInitData.cx, m_gsInitData.cy, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE); -#elif defined(__APPLE__) -#elif defined(__linux__) || defined(__FreeBSD__) -#endif + #elif defined(__APPLE__) + #elif defined(__linux__) || defined(__FreeBSD__) + #endif -// Store new position. + // Store new position. m_position.first = x; m_position.second = y; } @@ -240,15 +199,15 @@ void OBS::Display::SetSize(uint32_t width, uint32_t height) { } // Resize Window -#if defined(_WIN32) + #if defined(_WIN32) SetWindowPos((HWND)(m_gsInitData.window.hwnd), NULL, m_position.first, m_position.second, width, height, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE); -#elif defined(__APPLE__) -#elif defined(__linux__) || defined(__FreeBSD__) -#endif + #elif defined(__APPLE__) + #elif defined(__linux__) || defined(__FreeBSD__) + #endif -// Resize Display + // Resize Display obs_display_resize(m_display, width, height); // Store new size. @@ -371,230 +330,117 @@ static void DrawGlyph(GS::VertexBuffer* vb, float_t x, float_t y, float_t scale, GS::Vertex v(nullptr, nullptr, nullptr, nullptr, nullptr); size_t bs = vb->Size(); - vb->Resize(uint32_t(bs + 6)); + vb->Resize(bs + 6); // Top Left - v = vb->At(uint32_t(bs + 0)); + v = vb->At(bs + 0); vec3_set(v.position, x, y, depth); vec4_set(v.uv[0], uvX, uvY, 0, 0); *v.color = color; // Top Right - v = vb->At(uint32_t(bs + 1)); + v = vb->At(bs + 1); vec3_set(v.position, x + scale, y, depth); vec4_set(v.uv[0], uvX + uvO, uvY, 0, 0); *v.color = color; // Bottom Left - v = vb->At(uint32_t(bs + 2)); + v = vb->At(bs + 2); vec3_set(v.position, x, y + scale * 2, depth); vec4_set(v.uv[0], uvX, uvY + uvO, 0, 0); *v.color = color; // Top Right - v = vb->At(uint32_t(bs + 3)); + v = vb->At(bs + 3); vec3_set(v.position, x + scale, y, depth); vec4_set(v.uv[0], uvX + uvO, uvY, 0, 0); *v.color = color; // Bottom Left - v = vb->At(uint32_t(bs + 4)); + v = vb->At(bs + 4); vec3_set(v.position, x, y + scale * 2, depth); vec4_set(v.uv[0], uvX, uvY + uvO, 0, 0); *v.color = color; // Bottom Right - v = vb->At(uint32_t(bs + 5)); + v = vb->At(bs + 5); vec3_set(v.position, x + scale, y + scale * 2, depth); vec4_set(v.uv[0], uvX + uvO, uvY + uvO, 0, 0); *v.color = color; } -#define HANDLE_RADIUS 5.0f -#define HANDLE_DIAMETER 10.0f +inline void DrawBox(float_t x, float_t y, float_t w, float_t h, float_t depth, uint32_t color, GS::VertexBuffer* vbh) { + GS::Vertex v(nullptr, nullptr, nullptr, nullptr, nullptr); + size_t bs = vbh->Size(); + vbh->Resize(bs + 6); -inline bool CloseFloat(float a, float b, float epsilon = 0.01) { - return std::abs(a - b) <= epsilon; -} + v = vbh->At(bs + 0); + vec3_set(v.position, x, y, depth); + *v.color = color; -inline void DrawOutline(OBS::Display* dp, matrix4& mtx, obs_transform_info& info) { - gs_matrix_push(); - gs_matrix_set(&mtx); - gs_draw(GS_LINESTRIP, 0, 0); - gs_matrix_pop(); -} + v = vbh->At(bs + 1); + vec3_set(v.position, x + w, y, depth); + *v.color = color; -inline void DrawBoxAt(OBS::Display* dp, float_t x, float_t y, matrix4& mtx) { - gs_matrix_push(); + v = vbh->At(bs + 2); + vec3_set(v.position, x, y + h, depth); + *v.color = color; - vec3 pos = { x, y, 0.0f }; - vec3_transform(&pos, &pos, &mtx); + v = vbh->At(bs + 3); + vec3_set(v.position, x, y + h, depth); + *v.color = color; - vec3 offset = { -HANDLE_RADIUS, -HANDLE_RADIUS, 0.0f }; - gs_matrix_translate(&pos); - gs_matrix_translate(&offset); - gs_matrix_scale3f(HANDLE_DIAMETER, HANDLE_DIAMETER, 1.0f); + v = vbh->At(bs + 4); + vec3_set(v.position, x + w, y, depth); + *v.color = color; - gs_draw(GS_LINESTRIP, 0, 0); - gs_matrix_pop(); + v = vbh->At(bs + 5); + vec3_set(v.position, x + w, y + h, depth); + *v.color = color; } -inline void DrawSquareAt(OBS::Display* dp, float_t x, float_t y, matrix4& mtx) { - gs_matrix_push(); +inline void DrawBoxOutline(float_t x, float_t y, float_t w, float_t h, float_t depth, uint32_t color, GS::VertexBuffer* vbh) { + GS::Vertex v(nullptr, nullptr, nullptr, nullptr, nullptr); + size_t bs = vbh->Size(); + vbh->Resize(bs + 8); + + v = vbh->At(bs + 0); + vec3_set(v.position, x, y, depth); + *v.color = color; - vec3 pos = { x, y, 0.0f }; - vec3_transform(&pos, &pos, &mtx); + v = vbh->At(bs + 1); + vec3_set(v.position, x + w, y, depth); + *v.color = color; - vec3 offset = { -HANDLE_RADIUS, -HANDLE_RADIUS, 0.0f }; - gs_matrix_translate(&pos); - gs_matrix_translate(&offset); - gs_matrix_scale3f(HANDLE_DIAMETER, HANDLE_DIAMETER, 1.0f); - gs_draw(GS_TRISTRIP, 0, 0); - gs_matrix_pop(); -} + v = vbh->At(bs + 2); + vec3_set(v.position, x + w, y, depth); + *v.color = color; -inline void DrawGuideline(OBS::Display* dp, float_t x, float_t y, matrix4& mtx) { - gs_rect rect; - rect.x = dp->GetPreviewOffset().first; - rect.y = dp->GetPreviewOffset().second; - rect.cx = dp->GetPreviewSize().first; - rect.cy = dp->GetPreviewSize().second; - - gs_set_scissor_rect(&rect); - gs_matrix_push(); - - vec3 center = { 0.5, 0.5, 0.0f }; - vec3_transform(¢er, ¢er, &mtx); - - vec3 pos = { x, y, 0.0f }; - vec3_transform(&pos, &pos, &mtx); - - vec3 normal; - vec3_sub(&normal, ¢er, &pos); - vec3_norm(&normal, &normal); - - gs_matrix_translate(&pos); - - vec3 up = { 0, 1.0, 0 }; - vec3 dn = { 0, -1.0, 0 }; - vec3 lt = { -1.0, 0, 0 }; - vec3 rt = { 1.0, 0, 0 }; - - if (vec3_dot(&up, &normal) > 0.5f) { - // Dominantly looking up. - gs_matrix_rotaa4f(0, 0, 1, RAD(-90.0f)); - } else if (vec3_dot(&dn, &normal) > 0.5f) { - // Dominantly looking down. - gs_matrix_rotaa4f(0, 0, 1, RAD(90.0f)); - } else if (vec3_dot(<, &normal) > 0.5f) { - // Dominantly looking left. - gs_matrix_rotaa4f(0, 0, 1, RAD(0.0f)); - } else if (vec3_dot(&rt, &normal) > 0.5f) { - // Dominantly looking right. - gs_matrix_rotaa4f(0, 0, 1, RAD(180.0f)); - } + v = vbh->At(bs + 3); + vec3_set(v.position, x + w, y + h, depth); + *v.color = color; - gs_matrix_scale3f(65535, 65535, 65535); - gs_draw(GS_LINES, 0, 2); + v = vbh->At(bs + 4); + vec3_set(v.position, x + w, y + h, depth); + *v.color = color; + + v = vbh->At(bs + 5); + vec3_set(v.position, x, y + h, depth); + *v.color = color; + + + v = vbh->At(bs + 6); + vec3_set(v.position, x, y + h, depth); + *v.color = color; - gs_matrix_pop(); - gs_set_scissor_rect(nullptr); + v = vbh->At(bs + 7); + vec3_set(v.position, x, y, depth); + *v.color = color; } bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, void *param) { - // This is partially code from OBS Studio. See window-basic-preview.cpp in obs-studio for copyright/license. - if (obs_sceneitem_locked(item)) - return true; - if (!obs_sceneitem_selected(item)) - return true; - - matrix4 boxTransform; - matrix4 invBoxTransform; - obs_sceneitem_get_box_transform(item, &boxTransform); - matrix4_inv(&invBoxTransform, &boxTransform); - - vec3 bounds[] = { - { { { 0.f, 0.f, 0.f } } }, - { { { 1.f, 0.f, 0.f } } }, - { { { 0.f, 1.f, 0.f } } }, - { { { 1.f, 1.f, 0.f } } }, - }; - bool visible = std::all_of(std::begin(bounds), std::end(bounds), - [&](const vec3 &b) { - vec3 pos; - vec3_transform(&pos, &b, &boxTransform); - vec3_transform(&pos, &pos, &invBoxTransform); - return CloseFloat(pos.x, b.x) && CloseFloat(pos.y, b.y); - }); - - if (!visible) - return true; - OBS::Display* dp = reinterpret_cast(param); - vec4 color; - gs_effect_t* solid = obs_get_base_effect(OBS_EFFECT_SOLID); - gs_eparam_t* solid_color = gs_effect_get_param_by_name(solid, "color"); - - obs_transform_info info; - obs_sceneitem_get_info(item, &info); - - gs_load_vertexbuffer(dp->m_boxLine->Update(false)); - vec4_set(&color, - (dp->m_outlineColor & 0xFF) / 255.0f, - ((dp->m_outlineColor & 0xFF00) >> 8) / 255.0f, - ((dp->m_outlineColor & 0xFF0000) >> 16) / 255.0f, - ((dp->m_outlineColor & 0xFF000000) >> 24) / 255.0f); - gs_effect_set_vec4(solid_color, &color); - DrawOutline(dp, boxTransform, info); - - vec4_set(&color, - (dp->m_guidelineColor & 0xFF) / 255.0f, - ((dp->m_guidelineColor & 0xFF00) >> 8) / 255.0f, - ((dp->m_guidelineColor & 0xFF0000) >> 16) / 255.0f, - ((dp->m_guidelineColor & 0xFF000000) >> 24) / 255.0f); - gs_effect_set_vec4(solid_color, &color); - DrawGuideline(dp, 0.5, 0, boxTransform); - DrawGuideline(dp, 0.5, 1, boxTransform); - DrawGuideline(dp, 0, 0.5, boxTransform); - DrawGuideline(dp, 1, 0.5, boxTransform); - - gs_load_vertexbuffer(dp->m_boxTris->Update(false)); - vec4_set(&color, - (dp->m_resizeInnerColor & 0xFF) / 255.0f, - ((dp->m_resizeInnerColor & 0xFF00) >> 8) / 255.0f, - ((dp->m_resizeInnerColor & 0xFF0000) >> 16) / 255.0f, - ((dp->m_resizeInnerColor & 0xFF000000) >> 24) / 255.0f); - gs_effect_set_vec4(solid_color, &color); - DrawSquareAt(dp, 0, 0, boxTransform); - DrawSquareAt(dp, 1, 0, boxTransform); - DrawSquareAt(dp, 0, 1, boxTransform); - DrawSquareAt(dp, 1, 1, boxTransform); - DrawSquareAt(dp, 0.5, 0, boxTransform); - DrawSquareAt(dp, 0.5, 1, boxTransform); - DrawSquareAt(dp, 0, 0.5, boxTransform); - DrawSquareAt(dp, 1, 0.5, boxTransform); - - gs_load_vertexbuffer(dp->m_boxLine->Update(false)); - vec4_set(&color, - (dp->m_resizeOuterColor & 0xFF) / 255.0f, - ((dp->m_resizeOuterColor & 0xFF00) >> 8) / 255.0f, - ((dp->m_resizeOuterColor & 0xFF0000) >> 16) / 255.0f, - ((dp->m_resizeOuterColor & 0xFF000000) >> 24) / 255.0f); - gs_effect_set_vec4(solid_color, &color); - DrawBoxAt(dp, 0, 0, boxTransform); - DrawBoxAt(dp, 1, 0, boxTransform); - DrawBoxAt(dp, 0, 1, boxTransform); - DrawBoxAt(dp, 1, 1, boxTransform); - DrawBoxAt(dp, 0.5, 0, boxTransform); - DrawBoxAt(dp, 0.5, 1, boxTransform); - DrawBoxAt(dp, 0, 0.5, boxTransform); - DrawBoxAt(dp, 1, 0.5, boxTransform); - - // TEXT RENDERING - // THIS DESPERATELY NEEDS TO BE REWRITTEN INTO SHADER CODE - // DO SO WHENEVER... obs_source_t* itemSource = obs_sceneitem_get_source(item); obs_source_t* sceneSource = obs_scene_get_source(scene); - uint32_t sceneWidth = obs_source_get_width(sceneSource); // Xaymar: this actually works \o/ uint32_t sceneHeight = obs_source_get_height(sceneSource); uint32_t itemWidth = obs_source_get_width(itemSource); @@ -613,30 +459,51 @@ bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, sceneToView.y.y = dp->m_worldToPreviewScale.y; // Retrieve actual corner and edge positions. - vec3 edge[4], center; + vec3 corner[4], edge[4], center; { + vec3_set(&corner[0], 0, 0, 0); + vec3_transform(&corner[0], &corner[0], &itemMatrix); + vec3_transform(&corner[0], &corner[0], &sceneToView); + vec3_set(&corner[1], 1, 0, 0); + vec3_transform(&corner[1], &corner[1], &itemMatrix); + vec3_transform(&corner[1], &corner[1], &sceneToView); + vec3_set(&corner[2], 1, 1, 0); + vec3_transform(&corner[2], &corner[2], &itemMatrix); + vec3_transform(&corner[2], &corner[2], &sceneToView); + vec3_set(&corner[3], 0, 1, 0); + vec3_transform(&corner[3], &corner[3], &itemMatrix); + vec3_transform(&corner[3], &corner[3], &sceneToView); + vec3_set(&edge[0], 0, 0.5, 0); vec3_transform(&edge[0], &edge[0], &itemMatrix); + vec3_transform(&edge[0], &edge[0], &sceneToView); vec3_set(&edge[1], 0.5, 0, 0); vec3_transform(&edge[1], &edge[1], &itemMatrix); + vec3_transform(&edge[1], &edge[1], &sceneToView); vec3_set(&edge[2], 1, 0.5, 0); vec3_transform(&edge[2], &edge[2], &itemMatrix); + vec3_transform(&edge[2], &edge[2], &sceneToView); vec3_set(&edge[3], 0.5, 1, 0); vec3_transform(&edge[3], &edge[3], &itemMatrix); + vec3_transform(&edge[3], &edge[3], &sceneToView); vec3_set(¢er, 0.5, 0.5, 0); - vec3_transform(¢er, ¢er, &itemMatrix);; + vec3_transform(¢er, ¢er, &itemMatrix); + vec3_transform(¢er, ¢er, &sceneToView); } - std::vector buf(8); - float_t pt = 16 * dp->m_worldToPreviewScale.y; + float_t pt = 8; for (size_t n = 0; n < 4; n++) { - bool isIn = (edge[n].x >= 0) && (edge[n].x < sceneWidth) - && (edge[n].y >= 0) && (edge[n].y < sceneHeight); + + bool isIn = (edge[n].x >= 0) && (edge[n].x < sceneWidth * dp->m_worldToPreviewScale.x) + && (edge[n].y >= 0) && (edge[n].y < sceneHeight * dp->m_worldToPreviewScale.y); if (!isIn) continue; + size_t bs = dp->m_lines->Size(); + dp->m_lines->Resize(bs + 2); + vec3 alignLeft = { -1, 0, 0 }; vec3 alignTop = { 0, -1, 0 }; @@ -646,9 +513,19 @@ bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, float left = vec3_dot(&temp, &alignLeft), top = vec3_dot(&temp, &alignTop); if (left > 0.5) { // LEFT + v = dp->m_lines->At(bs + 0); + vec3_set(v.position, 0, edge[n].y, 0); + *v.color = dp->m_guidelineColor; + + v = dp->m_lines->At(bs + 1); + vec3_set(v.position, edge[n].x, edge[n].y, 0); + *v.color = dp->m_guidelineColor; + float_t dist = edge[n].x; if (dist > (pt * 4)) { - size_t len = (size_t)snprintf(buf.data(), buf.size(), "%ld px", (uint32_t)dist); + float_t textdist = float(dist * (1.0 / dp->m_worldToPreviewScale.x)); + std::vector buf(1024); + size_t len = (size_t)snprintf(buf.data(), buf.size(), "%ld px", (uint32_t)textdist); float_t offset = float((pt * len) / 2.0); for (size_t p = 0; p < len; p++) { @@ -659,9 +536,19 @@ bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, } } } else if (left < -0.5) { // RIGHT - float_t dist = sceneWidth - edge[n].x; + v = dp->m_lines->At(bs + 0); + vec3_set(v.position, sceneWidth * dp->m_worldToPreviewScale.x, edge[n].y, 0); + *v.color = dp->m_guidelineColor; + + v = dp->m_lines->At(bs + 1); + vec3_set(v.position, edge[n].x, edge[n].y, 0); + *v.color = dp->m_guidelineColor; + + float_t dist = sceneWidth * dp->m_worldToPreviewScale.x - edge[n].x; if (dist > (pt * 4)) { - size_t len = (size_t)snprintf(buf.data(), buf.size(), "%ld px", (uint32_t)dist); + float_t textdist = float(dist * (1.0 / dp->m_worldToPreviewScale.x)); + std::vector buf(1024); + size_t len = (size_t)snprintf(buf.data(), buf.size(), "%ld px", (uint32_t)textdist); float_t offset = float((pt * len) / 2.0); for (size_t p = 0; p < len; p++) { @@ -672,9 +559,19 @@ bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, } } } else if (top > 0.5) { // UP + v = dp->m_lines->At(bs + 0); + vec3_set(v.position, edge[n].x, 0, 0); + *v.color = dp->m_guidelineColor; + + v = dp->m_lines->At(bs + 1); + vec3_set(v.position, edge[n].x, edge[n].y, 0); + *v.color = dp->m_guidelineColor; + float_t dist = edge[n].y; if (dist > pt) { - size_t len = (size_t)snprintf(buf.data(), buf.size(), "%ld px", (uint32_t)dist); + float_t textdist = float(dist * (1.0 / dp->m_worldToPreviewScale.y)); + std::vector buf(1024); + size_t len = (size_t)snprintf(buf.data(), buf.size(), "%ld px", (uint32_t)textdist); float_t offset = float((pt * len) / 2.0); for (size_t p = 0; p < len; p++) { @@ -685,9 +582,19 @@ bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, } } } else if (top < -0.5) { // DOWN - float_t dist = sceneHeight - edge[n].y; + v = dp->m_lines->At(bs + 0); + vec3_set(v.position, edge[n].x, sceneHeight * dp->m_worldToPreviewScale.y, 0); + *v.color = dp->m_guidelineColor; + + v = dp->m_lines->At(bs + 1); + vec3_set(v.position, edge[n].x, edge[n].y, 0); + *v.color = dp->m_guidelineColor; + + float_t dist = sceneHeight * dp->m_worldToPreviewScale.y - edge[n].y; if (dist > (pt * 4)) { - size_t len = (size_t)snprintf(buf.data(), buf.size(), "%ld px", (uint32_t)dist); + float_t textdist = float(dist * (1.0 / dp->m_worldToPreviewScale.y)); + std::vector buf(1024); + size_t len = (size_t)snprintf(buf.data(), buf.size(), "%ld px", (uint32_t)textdist); float_t offset = float((pt * len) / 2.0); for (size_t p = 0; p < len; p++) { @@ -699,18 +606,72 @@ bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, } } } + size_t bs = dp->m_lines->Size(); + dp->m_lines->Resize(bs + 8); + + // Drawing + /// Outline + v = dp->m_lines->At(bs + 0); + vec3_set(v.position, corner[0].x, corner[0].y, 0); + *v.color = dp->m_outlineColor; + v = dp->m_lines->At(bs + 1); + vec3_set(v.position, corner[1].x, corner[1].y, 0); + *v.color = dp->m_outlineColor; + + v = dp->m_lines->At(bs + 2); + vec3_set(v.position, corner[1].x, corner[1].y, 0); + *v.color = dp->m_outlineColor; + v = dp->m_lines->At(bs + 3); + vec3_set(v.position, corner[2].x, corner[2].y, 0); + *v.color = dp->m_outlineColor; + + v = dp->m_lines->At(bs + 4); + vec3_set(v.position, corner[2].x, corner[2].y, 0); + *v.color = dp->m_outlineColor; + v = dp->m_lines->At(bs + 5); + vec3_set(v.position, corner[3].x, corner[3].y, 0); + *v.color = dp->m_outlineColor; + + v = dp->m_lines->At(bs + 6); + vec3_set(v.position, corner[3].x, corner[3].y, 0); + *v.color = dp->m_outlineColor; + v = dp->m_lines->At(bs + 7); + vec3_set(v.position, corner[0].x, corner[0].y, 0); + *v.color = dp->m_outlineColor; + + /// Resize Boxes + DrawBox(corner[0].x - 5, corner[0].y - 5, 10, 10, 0, dp->m_resizeOuterColor, dp->m_triangles); + DrawBox(corner[0].x - 4, corner[0].y - 4, 8, 8, 0, dp->m_resizeInnerColor, dp->m_triangles); + DrawBox(corner[1].x - 5, corner[1].y - 5, 10, 10, 0, dp->m_resizeOuterColor, dp->m_triangles); + DrawBox(corner[1].x - 4, corner[1].y - 4, 8, 8, 0, dp->m_resizeInnerColor, dp->m_triangles); + DrawBox(corner[2].x - 5, corner[2].y - 5, 10, 10, 0, dp->m_resizeOuterColor, dp->m_triangles); + DrawBox(corner[2].x - 4, corner[2].y - 4, 8, 8, 0, dp->m_resizeInnerColor, dp->m_triangles); + DrawBox(corner[3].x - 5, corner[3].y - 5, 10, 10, 0, dp->m_resizeOuterColor, dp->m_triangles); + DrawBox(corner[3].x - 4, corner[3].y - 4, 8, 8, 0, dp->m_resizeInnerColor, dp->m_triangles); + DrawBox(edge[0].x - 5, edge[0].y - 5, 10, 10, 0, dp->m_resizeOuterColor, dp->m_triangles); + DrawBox(edge[0].x - 4, edge[0].y - 4, 8, 8, 0, dp->m_resizeInnerColor, dp->m_triangles); + DrawBox(edge[1].x - 5, edge[1].y - 5, 10, 10, 0, dp->m_resizeOuterColor, dp->m_triangles); + DrawBox(edge[1].x - 4, edge[1].y - 4, 8, 8, 0, dp->m_resizeInnerColor, dp->m_triangles); + DrawBox(edge[2].x - 5, edge[2].y - 5, 10, 10, 0, dp->m_resizeOuterColor, dp->m_triangles); + DrawBox(edge[2].x - 4, edge[2].y - 4, 8, 8, 0, dp->m_resizeInnerColor, dp->m_triangles); + DrawBox(edge[3].x - 5, edge[3].y - 5, 10, 10, 0, dp->m_resizeOuterColor, dp->m_triangles); + DrawBox(edge[3].x - 4, edge[3].y - 4, 8, 8, 0, dp->m_resizeInnerColor, dp->m_triangles); } return true; } void OBS::Display::DisplayCallback(OBS::Display* dp, uint32_t cx, uint32_t cy) { - gs_effect_t* solid = obs_get_base_effect(OBS_EFFECT_SOLID); - gs_eparam_t* solid_color = gs_effect_get_param_by_name(solid, "color"); - gs_technique_t* solid_tech = gs_effect_get_technique(solid, "Solid"); + dp->UpdatePreviewArea(); vec4 color; - dp->UpdatePreviewArea(); + gs_viewport_push(); + gs_projection_push(); + + // Padding Area + vec4_set(&color, dp->m_paddingColor[0], dp->m_paddingColor[1], + dp->m_paddingColor[2], dp->m_paddingColor[3]); + gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH | GS_CLEAR_STENCIL, &color, 100, 0); // Get proper source/base size. uint32_t sourceW, sourceH; @@ -728,85 +689,85 @@ void OBS::Display::DisplayCallback(OBS::Display* dp, uint32_t cx, uint32_t cy) { if (sourceW == 0) sourceW = 1; if (sourceH == 0) sourceH = 1; } - - gs_viewport_push(); - gs_projection_push(); - gs_ortho(0.0f, float(sourceW), 0.0f, float(sourceH), -100.0f, 100.0f); gs_set_viewport(dp->m_previewOffset.first, dp->m_previewOffset.second, dp->m_previewSize.first, dp->m_previewSize.second); - // Padding - vec4_set(&color, dp->m_paddingColor[0], dp->m_paddingColor[1], dp->m_paddingColor[2], dp->m_paddingColor[3]); - gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH | GS_CLEAR_STENCIL, &color, 100, 0); - - // Background - if (dp->m_boxTris) { - vec4_set(&color, - ((dp->m_backgroundColor & 0xFF)) / 255.0f, - ((dp->m_backgroundColor & 0xFF00) >> 8) / 255.0f, - ((dp->m_backgroundColor & 0xFF0000) >> 16) / 255.0f, - ((dp->m_backgroundColor & 0xFF000000) >> 24) / 255.0f); - gs_effect_set_vec4(solid_color, &color); - - gs_technique_begin(solid_tech); - gs_technique_begin_pass(solid_tech, 0); - - gs_matrix_push(); - gs_matrix_identity(); - gs_matrix_scale3f(float(sourceW), float(sourceH), 1.0f); + #pragma region Background + dp->m_triangles->Resize(4); + { + GS::Vertex v = dp->m_triangles->At(0); + vec3_set(v.position, 0, 0, 0); + *v.color = dp->m_backgroundColor; - gs_load_vertexbuffer(dp->m_boxTris->Update(false)); - gs_draw(GS_TRISTRIP, 0, 0); + v = dp->m_triangles->At(1); + vec3_set(v.position, float(sourceW), 0, 0); + *v.color = dp->m_backgroundColor; - gs_matrix_pop(); + v = dp->m_triangles->At(2); + vec3_set(v.position, 0, float(sourceH), 0); + *v.color = dp->m_backgroundColor; - gs_technique_end_pass(solid_tech); - gs_technique_end(solid_tech); + v = dp->m_triangles->At(3); + vec3_set(v.position, float(sourceW), float(sourceH), 0); + *v.color = dp->m_backgroundColor; + } - gs_load_vertexbuffer(nullptr); + gs_vertbuffer_t *vb = dp->m_triangles->Update(); + while (gs_effect_loop(dp->m_gsSolidEffect, "SolidColored")) { + gs_load_vertexbuffer(vb); + gs_load_indexbuffer(nullptr); + gs_draw(GS_TRISTRIP, 0, (uint32_t)dp->m_triangles->Size()); } + #pragma endregion Background - // Source Rendering if (dp->m_source) { obs_source_video_render(dp->m_source); } else { obs_render_main_view(); - } - gs_load_vertexbuffer(nullptr); - - if (!dp->m_source && dp->m_shouldDrawUI == true) { - // Display-Aligned Drawing - vec2 tlCorner = { (float)-dp->m_previewOffset.first, (float)-dp->m_previewOffset.second }; - vec2 brCorner = { (float)(cx - dp->m_previewOffset.first), (float)(cy - dp->m_previewOffset.second) }; - vec2_mul(&tlCorner, &tlCorner, &dp->m_previewToWorldScale); - vec2_mul(&brCorner, &brCorner, &dp->m_previewToWorldScale); - - gs_set_viewport(0, 0, cx, cy); - gs_ortho( - tlCorner.x, brCorner.x, - tlCorner.y, brCorner.y, - -100.0f, 100.0f); - - /* Here we assume that channel 0 holds the one and only transition. - * We also assume that the active source within that transition is - * the scene that we need */ - obs_source_t *transition = obs_get_output_source(0); - obs_source_t *source = obs_transition_get_active_source(transition); - obs_source_release(transition); - obs_scene_t *scene = obs_scene_from_source(source); - - if (scene) { - dp->m_textVertices->Resize(0); - gs_technique_begin(solid_tech); - gs_technique_begin_pass(solid_tech, 0); + if (dp->m_shouldDrawUI) { + // Display-Aligned Drawing + gs_set_viewport(0, 0, dp->m_gsInitData.cx, dp->m_gsInitData.cy); + gs_ortho((float)-dp->m_previewOffset.first, (float)(dp->m_gsInitData.cx - dp->m_previewOffset.first), + (float)-dp->m_previewOffset.second, (float)(dp->m_gsInitData.cy - dp->m_previewOffset.second), + -100.0f, 100.0f); + + // Clear Buffers + dp->m_lines->Resize(0); + dp->m_triangles->Resize(0); + dp->m_textVertices->Resize(0); - obs_scene_enum_items(scene, DrawSelectedSource, dp); - gs_load_vertexbuffer(nullptr); + /* Here we assume that channel 0 holds the one and only transition. + * We also assume that the active source within that transition is + * the scene that we need */ + obs_source_t *transition = obs_get_output_source(0); + obs_source_t *source = obs_transition_get_active_source(transition); + obs_source_release(transition); + obs_scene_t *scene = obs_scene_from_source(source); + if (scene) + obs_scene_enum_items(scene, DrawSelectedSource, dp); + obs_source_release(source); + + // Lines + if (dp->m_lines->Size() > 0) { + gs_vertbuffer_t* vb = dp->m_lines->Update(); + while (gs_effect_loop(dp->m_gsSolidEffect, "SolidColored")) { + gs_load_vertexbuffer(vb); + gs_load_indexbuffer(nullptr); + gs_draw(GS_LINES, 0, (uint32_t)dp->m_lines->Size()); + } + } - gs_technique_end_pass(solid_tech); - gs_technique_end(solid_tech); + // Triangles + if (dp->m_triangles->Size() > 0) { + gs_vertbuffer_t* vb = dp->m_triangles->Update(); + while (gs_effect_loop(dp->m_gsSolidEffect, "SolidColored")) { + gs_load_vertexbuffer(vb); + gs_load_indexbuffer(nullptr); + gs_draw(GS_TRIS, 0, (uint32_t)dp->m_triangles->Size()); + } + } // Text Rendering if (dp->m_textVertices->Size() > 0) { @@ -821,8 +782,6 @@ void OBS::Display::DisplayCallback(OBS::Display* dp, uint32_t cx, uint32_t cy) { } } } - - obs_source_release(source); } gs_projection_pop(); @@ -862,8 +821,6 @@ void OBS::Display::UpdatePreviewArea() { m_previewSize.second -= offsetY * 2; m_worldToPreviewScale.x = float_t(m_previewSize.first) / float_t(sourceW); m_worldToPreviewScale.y = float_t(m_previewSize.second) / float_t(sourceH); - m_previewToWorldScale.x = float_t(sourceW) / float_t(m_previewSize.first); - m_previewToWorldScale.y = float_t(sourceH) / float_t(m_previewSize.second); } #if defined(_WIN32) @@ -917,4 +874,3 @@ LRESULT CALLBACK OBS::Display::DisplayWndProc(_In_ HWND hwnd, _In_ UINT uMsg, _I } #endif - diff --git a/src/nodeobs_display.h b/src/nodeobs_display.h index 0f27bd19d..b05b495bd 100644 --- a/src/nodeobs_display.h +++ b/src/nodeobs_display.h @@ -58,10 +58,6 @@ namespace OBS { static bool DrawSelectedSource(obs_scene_t* scene, obs_sceneitem_t* item, void* param); void UpdatePreviewArea(); - public: // Rendering code needs it. - vec2 m_worldToPreviewScale, - m_previewToWorldScale; - private: gs_init_data m_gsInitData; obs_display_t* m_display; @@ -74,6 +70,7 @@ namespace OBS { std::pair m_previewOffset; /// Actual Preview Size std::pair m_previewSize; + vec2 m_worldToPreviewScale; // OBS Graphics API gs_effect_t @@ -82,13 +79,10 @@ namespace OBS { gs_texture_t *m_textTexture; GS::VertexBuffer + *m_lines, + *m_triangles, *m_textVertices; - std::unique_ptr - m_boxLine, - m_boxTris; - - // Theme/Style /// Padding uint32_t m_paddingSize = 10;