2020-08-26 00:55:29 +08:00
|
|
|
#pragma once
|
|
|
|
|
2020-10-26 16:07:11 +08:00
|
|
|
#include <map>
|
2020-08-26 00:55:29 +08:00
|
|
|
#include <vector>
|
|
|
|
#include <wil\resource.h>
|
|
|
|
#include <winrt/base.h>
|
2020-10-14 20:45:50 +08:00
|
|
|
#include <d2d1.h>
|
2020-10-20 21:49:05 +08:00
|
|
|
#include <dwrite.h>
|
2020-08-26 00:55:29 +08:00
|
|
|
|
|
|
|
#include "util.h"
|
|
|
|
#include "Zone.h"
|
2020-10-26 16:07:11 +08:00
|
|
|
#include "ZoneSet.h"
|
2020-08-26 00:55:29 +08:00
|
|
|
|
2020-10-14 20:45:50 +08:00
|
|
|
namespace ZoneWindowDrawingNS
|
2020-08-26 00:55:29 +08:00
|
|
|
{
|
|
|
|
struct ColorSetting
|
|
|
|
{
|
|
|
|
BYTE fillAlpha{};
|
|
|
|
COLORREF fill{};
|
|
|
|
BYTE borderAlpha{};
|
|
|
|
COLORREF border{};
|
|
|
|
int thickness{};
|
|
|
|
};
|
|
|
|
|
|
|
|
void DrawBackdrop(wil::unique_hdc& hdc, RECT const& clientRect) noexcept;
|
|
|
|
void DrawActiveZoneSet(wil::unique_hdc& hdc,
|
|
|
|
COLORREF zoneColor,
|
|
|
|
COLORREF zoneBorderColor,
|
|
|
|
COLORREF highlightColor,
|
|
|
|
int zoneOpacity,
|
2020-10-26 16:07:11 +08:00
|
|
|
const IZoneSet::ZonesMap& zones,
|
2020-08-26 00:55:29 +08:00
|
|
|
const std::vector<size_t>& highlightZones,
|
2020-10-15 23:08:55 +08:00
|
|
|
bool flashMode) noexcept;
|
2020-08-26 00:55:29 +08:00
|
|
|
}
|
2020-10-14 20:45:50 +08:00
|
|
|
|
|
|
|
class ZoneWindowDrawing
|
|
|
|
{
|
2020-10-20 21:19:10 +08:00
|
|
|
struct DrawableRect
|
|
|
|
{
|
|
|
|
D2D1_RECT_F rect;
|
|
|
|
D2D1_COLOR_F borderColor;
|
|
|
|
D2D1_COLOR_F fillColor;
|
2020-10-20 21:49:05 +08:00
|
|
|
size_t id;
|
2020-10-20 21:19:10 +08:00
|
|
|
};
|
|
|
|
|
2020-10-14 20:45:50 +08:00
|
|
|
HWND m_window;
|
2020-10-20 21:19:10 +08:00
|
|
|
RECT m_clientRect;
|
|
|
|
// winrt::com_ptr<IZoneWindowHost> m_host;
|
|
|
|
ID2D1HwndRenderTarget* m_renderTarget;
|
|
|
|
|
|
|
|
std::mutex m_sceneMutex;
|
|
|
|
std::vector<DrawableRect> m_sceneRects;
|
|
|
|
|
|
|
|
void DrawBackdrop()
|
|
|
|
{
|
|
|
|
m_renderTarget->Clear(D2D1::ColorF(0.f, 0.f, 0.f, 0.f));
|
|
|
|
}
|
|
|
|
|
|
|
|
static ID2D1Factory* GetD2DFactory()
|
|
|
|
{
|
2020-10-20 21:49:05 +08:00
|
|
|
static ID2D1Factory* pD2DFactory = nullptr;
|
2020-10-20 21:19:10 +08:00
|
|
|
if (!pD2DFactory)
|
|
|
|
{
|
|
|
|
D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, &pD2DFactory);
|
|
|
|
}
|
|
|
|
return pD2DFactory;
|
|
|
|
|
|
|
|
// TODO: Destroy factory
|
|
|
|
}
|
|
|
|
|
2020-10-20 21:49:05 +08:00
|
|
|
static IDWriteFactory* GetWriteFactory()
|
|
|
|
{
|
|
|
|
static IUnknown* pDWriteFactory = nullptr;
|
|
|
|
if (!pDWriteFactory)
|
|
|
|
{
|
|
|
|
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &pDWriteFactory);
|
|
|
|
}
|
|
|
|
return reinterpret_cast<IDWriteFactory*>(pDWriteFactory);
|
|
|
|
|
|
|
|
// TODO: Destroy factory
|
|
|
|
}
|
|
|
|
|
2020-10-20 21:19:10 +08:00
|
|
|
static D2D1_COLOR_F ConvertColor(COLORREF color)
|
|
|
|
{
|
|
|
|
return D2D1::ColorF(GetRValue(color) / 255.f,
|
|
|
|
GetGValue(color) / 255.f,
|
|
|
|
GetBValue(color) / 255.f,
|
|
|
|
1.f);
|
|
|
|
}
|
|
|
|
|
|
|
|
static D2D1_RECT_F ConvertRect(RECT rect)
|
|
|
|
{
|
|
|
|
return D2D1::RectF(rect.left, rect.top, rect.right, rect.bottom);
|
|
|
|
}
|
2020-10-14 20:45:50 +08:00
|
|
|
|
|
|
|
public:
|
2020-10-20 21:19:10 +08:00
|
|
|
ZoneWindowDrawing(HWND window)
|
|
|
|
{
|
|
|
|
m_window = window;
|
2020-10-20 21:49:05 +08:00
|
|
|
m_renderTarget = nullptr;
|
2020-10-20 21:19:10 +08:00
|
|
|
|
|
|
|
// Obtain the size of the drawing area.
|
2020-10-20 21:49:05 +08:00
|
|
|
if (!GetClientRect(window, &m_clientRect))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-10-20 21:19:10 +08:00
|
|
|
|
|
|
|
// Create a Direct2D render target
|
|
|
|
GetD2DFactory()->CreateHwndRenderTarget(
|
|
|
|
D2D1::RenderTargetProperties(
|
|
|
|
D2D1_RENDER_TARGET_TYPE_DEFAULT,
|
|
|
|
D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED)),
|
|
|
|
D2D1::HwndRenderTargetProperties(
|
|
|
|
window,
|
|
|
|
D2D1::SizeU(
|
|
|
|
m_clientRect.right - m_clientRect.left,
|
|
|
|
m_clientRect.bottom - m_clientRect.top)),
|
|
|
|
&m_renderTarget);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Render()
|
|
|
|
{
|
|
|
|
std::unique_lock lock(m_sceneMutex);
|
|
|
|
|
2020-10-20 21:49:05 +08:00
|
|
|
if (!m_renderTarget)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-10-20 21:19:10 +08:00
|
|
|
m_renderTarget->BeginDraw();
|
|
|
|
DrawBackdrop();
|
|
|
|
|
2020-10-20 21:49:05 +08:00
|
|
|
|
|
|
|
|
2020-10-20 21:19:10 +08:00
|
|
|
for (const auto& drawableRect : m_sceneRects)
|
|
|
|
{
|
2020-10-20 21:49:05 +08:00
|
|
|
ID2D1SolidColorBrush* borderBrush = nullptr;
|
|
|
|
ID2D1SolidColorBrush* fillBrush = nullptr;
|
|
|
|
ID2D1SolidColorBrush* textBrush = nullptr;
|
2020-10-20 21:19:10 +08:00
|
|
|
m_renderTarget->CreateSolidColorBrush(drawableRect.borderColor, &borderBrush);
|
|
|
|
m_renderTarget->CreateSolidColorBrush(drawableRect.fillColor, &fillBrush);
|
2020-10-20 21:49:05 +08:00
|
|
|
m_renderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &textBrush);
|
2020-10-20 21:19:10 +08:00
|
|
|
|
|
|
|
if (fillBrush)
|
|
|
|
{
|
|
|
|
m_renderTarget->FillRectangle(drawableRect.rect, fillBrush);
|
|
|
|
fillBrush->Release();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (borderBrush)
|
|
|
|
{
|
|
|
|
m_renderTarget->DrawRectangle(drawableRect.rect, borderBrush);
|
|
|
|
borderBrush->Release();
|
|
|
|
}
|
2020-10-20 21:49:05 +08:00
|
|
|
|
|
|
|
std::wstring idStr = std::to_wstring(drawableRect.id);
|
|
|
|
|
|
|
|
// TODO: mark string as non-localizable
|
|
|
|
IDWriteTextFormat* textFormat = nullptr;
|
|
|
|
auto writeFactory = GetWriteFactory();
|
|
|
|
|
|
|
|
if (writeFactory)
|
|
|
|
{
|
|
|
|
writeFactory->CreateTextFormat(L"Segoe ui", nullptr, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 80.f, L"en-US", &textFormat);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (textFormat && textBrush)
|
|
|
|
{
|
|
|
|
textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
|
|
|
|
textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
|
|
|
|
m_renderTarget->DrawTextW(idStr.c_str(), idStr.size(), textFormat, drawableRect.rect, textBrush);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (textFormat)
|
|
|
|
{
|
|
|
|
textFormat->Release();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (textBrush)
|
|
|
|
{
|
|
|
|
textBrush->Release();
|
|
|
|
}
|
2020-10-20 21:19:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
m_renderTarget->EndDraw();
|
|
|
|
}
|
|
|
|
|
|
|
|
void StartAnimation(unsigned millis)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void DrawActiveZoneSet(const std::vector<winrt::com_ptr<IZone>>& zones,
|
|
|
|
const std::vector<size_t>& highlightZones,
|
|
|
|
winrt::com_ptr<IZoneWindowHost> host)
|
|
|
|
{
|
|
|
|
std::unique_lock lock(m_sceneMutex);
|
|
|
|
|
|
|
|
m_sceneRects = {};
|
|
|
|
|
|
|
|
auto borderColor = ConvertColor(host->GetZoneBorderColor());
|
|
|
|
auto inactiveColor = ConvertColor(host->GetZoneColor());
|
|
|
|
auto highlightColor = ConvertColor(host->GetZoneHighlightColor());
|
|
|
|
|
|
|
|
inactiveColor.a = host->GetZoneHighlightOpacity() / 255.f;
|
|
|
|
highlightColor.a = host->GetZoneHighlightOpacity() / 255.f;
|
|
|
|
|
|
|
|
std::vector<bool> isHighlighted(zones.size(), false);
|
|
|
|
for (size_t x : highlightZones)
|
|
|
|
{
|
|
|
|
isHighlighted[x] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// First draw the inactive zones
|
|
|
|
for (auto iter = zones.begin(); iter != zones.end(); iter++)
|
|
|
|
{
|
|
|
|
int zoneId = static_cast<int>(iter - zones.begin());
|
|
|
|
winrt::com_ptr<IZone> zone = iter->try_as<IZone>();
|
|
|
|
if (!zone)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isHighlighted[zoneId])
|
|
|
|
{
|
|
|
|
DrawableRect drawableRect{
|
|
|
|
.rect = ConvertRect(zone->GetZoneRect()),
|
|
|
|
.borderColor = borderColor,
|
2020-10-20 21:49:05 +08:00
|
|
|
.fillColor = inactiveColor,
|
|
|
|
.id = zone->Id()
|
2020-10-20 21:19:10 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
m_sceneRects.push_back(drawableRect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw the active zones on top of the inactive zones
|
|
|
|
for (auto iter = zones.begin(); iter != zones.end(); iter++)
|
|
|
|
{
|
|
|
|
int zoneId = static_cast<int>(iter - zones.begin());
|
|
|
|
winrt::com_ptr<IZone> zone = iter->try_as<IZone>();
|
|
|
|
if (!zone)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isHighlighted[zoneId])
|
|
|
|
{
|
|
|
|
DrawableRect drawableRect{
|
|
|
|
.rect = ConvertRect(zone->GetZoneRect()),
|
|
|
|
.borderColor = borderColor,
|
2020-10-20 21:49:05 +08:00
|
|
|
.fillColor = highlightColor,
|
|
|
|
.id = zone->Id()
|
2020-10-20 21:19:10 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
m_sceneRects.push_back(drawableRect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|