Skip to content

Instantly share code, notes, and snippets.

@ahmed605
Created March 26, 2025 19:16
Show Gist options
  • Save ahmed605/779a548515214a698999090e86dac835 to your computer and use it in GitHub Desktop.
Save ahmed605/779a548515214a698999090e86dac835 to your computer and use it in GitHub Desktop.
//
// XWine1
//
// This code is licensed under MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include <Windows.h>
#include <dxgi1_6.h>
#include <d3d11_4.h>
#include <wincodec.h>
#include <d2d1.h>
#include <d2d1effects_2.h>
#include <winrt/windows.ui.core.h>
#include <winrt/windows.ui.composition.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Graphics.DirectX.h>
#include <winrt/Windows.Graphics.Effects.h>
#include <windows.ui.composition.interop.h>
#include <windows.graphics.effects.interop.h>
#include <chrono>
#include <random>
#include <functional>
#include <limits>
#include <cmath>
#pragma comment(lib, "dxguid.lib")
namespace wge = winrt::Windows::Graphics::Effects;
namespace awge = ABI::Windows::Graphics::Effects;
struct TintEffect : winrt::implements<TintEffect, wge::IGraphicsEffect, wge::IGraphicsEffectSource, awge::IGraphicsEffectD2D1Interop>
{
public:
HRESULT STDMETHODCALLTYPE GetEffectId(GUID *id) noexcept override
{
if (id == nullptr) [[unlikely]]
{
return E_INVALIDARG;
}
*id = CLSID_D2D1Tint;
return S_OK;
}
HRESULT STDMETHODCALLTYPE GetNamedPropertyMapping(LPCWSTR name, UINT *index, awge::GRAPHICS_EFFECT_PROPERTY_MAPPING *mapping) noexcept override
{
if (index == nullptr || mapping == nullptr) [[unlikely]]
{
return E_INVALIDARG;
}
const std::wstring_view nameView(name);
if (nameView == L"Color")
{
*index = D2D1_TINT_PROP_COLOR;
*mapping = awge::GRAPHICS_EFFECT_PROPERTY_MAPPING_COLOR_TO_VECTOR4;
return S_OK;
}
else if (nameView == L"ClampOutput")
{
*index = D2D1_TINT_PROP_CLAMP_OUTPUT;
*mapping = awge::GRAPHICS_EFFECT_PROPERTY_MAPPING_DIRECT;
return S_OK;
}
return E_INVALIDARG;
}
HRESULT STDMETHODCALLTYPE GetPropertyCount(UINT *count) noexcept override
{
if (count == nullptr) [[unlikely]]
{
return E_INVALIDARG;
}
*count = 2;
return S_OK;
}
inline float ToNormalizedFloat(uint8_t v)
{
return static_cast<float>(v) / 255.0f;
}
inline D2D1_COLOR_F ToD2DColor(winrt::Windows::UI::Color const &color)
{
return D2D1::ColorF(
ToNormalizedFloat(color.R),
ToNormalizedFloat(color.G),
ToNormalizedFloat(color.B),
ToNormalizedFloat(color.A));
}
inline winrt::Windows::Foundation::Numerics::float4 ToVector4(winrt::Windows::UI::Color const &color)
{
auto d2dColor = ToD2DColor(color);
return std::_Bit_cast<winrt::Windows::Foundation::Numerics::float4>(d2dColor);
}
HRESULT STDMETHODCALLTYPE GetProperty(UINT index, ABI::Windows::Foundation::IPropertyValue **value) noexcept override
{
if (value == nullptr) [[unlikely]]
{
return E_INVALIDARG;
}
switch (index)
{
case D2D1_TINT_PROP_COLOR:
auto color = ToVector4(Color);
*value = winrt::Windows::Foundation::PropertyValue::CreateSingleArray({ color.x, color.y, color.z, color.w }).as<ABI::Windows::Foundation::IPropertyValue>().detach();
break;
case D2D1_TINT_PROP_CLAMP_OUTPUT:
*value = winrt::Windows::Foundation::PropertyValue::CreateBoolean(ClampOutput).as<ABI::Windows::Foundation::IPropertyValue>().detach();
break;
default:
return E_BOUNDS;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE GetSource(UINT index, awge::IGraphicsEffectSource **source) noexcept override
{
if (source == nullptr) [[unlikely]]
{
return E_INVALIDARG;
}
if (index == 0)
{
winrt::copy_to_abi(Source, *reinterpret_cast<void **>(source));
return S_OK;
}
else
{
return E_BOUNDS;
}
}
HRESULT STDMETHODCALLTYPE GetSourceCount(UINT *count) noexcept override
{
if (count == nullptr) [[unlikely]]
{
return E_INVALIDARG;
}
*count = 1;
return S_OK;
}
winrt::hstring Name() { return m_name; }
void Name(winrt::hstring name) { m_name = name; }
wge::IGraphicsEffectSource Source;
winrt::Windows::UI::Color Color{ 255, 255, 255, 255 };
bool ClampOutput = false;
private:
winrt::hstring m_name = L"TintEffect";
};
auto CreateCompositionGraphicsDevice(IUnknown* device, winrt::Windows::UI::Composition::Compositor compositor)
{
winrt::com_ptr<ABI::Windows::UI::Composition::ICompositorInterop> compositorInterop = compositor.as<ABI::Windows::UI::Composition::ICompositorInterop>();
winrt::Windows::UI::Composition::CompositionGraphicsDevice graphicsDevice { nullptr };
compositorInterop->CreateGraphicsDevice(device, (ABI::Windows::UI::Composition::ICompositionGraphicsDevice **)winrt::put_abi(graphicsDevice));
return graphicsDevice;
}
std::tuple<winrt::com_ptr<ID3D11Texture2D>, winrt::Windows::Foundation::Size> CreateD3D11Texture2D(ID3D11Device* d3d11Device, winrt::hstring filename)
{
winrt::com_ptr<IWICImagingFactory> imagingFactory;
winrt::check_hresult(CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_ALL,
__uuidof(IWICImagingFactory),
(void **)imagingFactory.put()));
winrt::com_ptr<IWICBitmapDecoder> decoder;
winrt::check_hresult(imagingFactory->CreateDecoderFromFilename(
filename.c_str(),
nullptr,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
decoder.put()));
winrt::com_ptr<IWICBitmapFrameDecode> frame;
winrt::check_hresult(decoder->GetFrame(0, frame.put()));
winrt::com_ptr<IWICFormatConverter> converter;
winrt::check_hresult(imagingFactory->CreateFormatConverter(converter.put()));
winrt::check_hresult(converter->Initialize(
(IWICBitmapSource*)frame.get(),
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
nullptr,
0.0f,
WICBitmapPaletteTypeCustom));
uint32_t width, height;
winrt::check_hresult(converter->GetSize(&width, &height));
D3D11_TEXTURE2D_DESC desc = { };
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.SampleDesc = DXGI_SAMPLE_DESC{ 1, 0 };
desc.Usage = D3D11_USAGE_DEFAULT;
winrt::com_ptr<ID3D11Texture2D> texture;
auto size = width * height * 4;
auto buffer = new byte[size];
winrt::check_hresult(converter->CopyPixels(nullptr, width * 4, size, buffer));
D3D11_SUBRESOURCE_DATA initData = { };
initData.pSysMem = buffer;
initData.SysMemPitch = width * 4;
winrt::check_hresult(d3d11Device->CreateTexture2D(&desc, &initData, texture.put()));
delete[] buffer;
return { texture, { (float)width, (float)height } };
}
void DrawTextureToCompositionDrawingSurface(ID3D11DeviceContext* d3d11DeviceContext, winrt::Windows::UI::Composition::CompositionDrawingSurface surface, ID3D11Texture2D* texture2D)
{
winrt::com_ptr<ABI::Windows::UI::Composition::ICompositionDrawingSurfaceInterop> surfaceInterop = surface.as<ABI::Windows::UI::Composition::ICompositionDrawingSurfaceInterop>();
POINT pt = { 0 };
winrt::com_ptr<IDXGISurface> dxgiSurface;
winrt::check_hresult(surfaceInterop->BeginDraw(nullptr, __uuidof(IDXGISurface), (void**)dxgiSurface.put(), &pt));
winrt::com_ptr<ID3D11Resource> resource;
dxgiSurface.as(resource);
d3d11DeviceContext->CopySubresourceRegion(
resource.get(),
0,
0,
0,
0,
(ID3D11Resource*)texture2D,
0,
nullptr);
winrt::check_hresult(surfaceInterop->EndDraw());
}
winrt::Windows::UI::Core::CoreWindow m_coreWindow{ nullptr };
winrt::Windows::UI::Composition::Compositor m_compositor{ nullptr };
winrt::Windows::UI::Composition::CompositionTarget m_target{ nullptr };
winrt::Windows::UI::Composition::SpriteVisual animatedVisual{ nullptr };
winrt::Windows::UI::Composition::CompositionAnimationGroup group1{ nullptr };
winrt::Windows::UI::Composition::CompositionAnimationGroup group2{ nullptr };
winrt::Windows::UI::Composition::CompositionAnimationGroup currentGroup{ nullptr };
winrt::Windows::UI::Composition::CompositionScopedBatch batch{ nullptr };
winrt::Windows::UI::Composition::CompositionEasingFunction linearEasing{ nullptr };
winrt::Windows::UI::Composition::ScalarKeyFrameAnimation fadeAnimation{ nullptr };
winrt::Windows::UI::Composition::CompositionEffectBrush tintBrush{ nullptr };
winrt::event_token completedToken;
std::random_device rd;
std::mt19937 gen = std::mt19937(rd());
std::chrono::steady_clock::time_point startTime;
std::chrono::seconds totalDuration = std::chrono::seconds(20);
winrt::Windows::Foundation::Rect dvdContainerSize;
winrt::Windows::Foundation::Numerics::float3 targetPos;
winrt::Windows::Foundation::Numerics::float3 dvdCurrentVelocity;
float timeX;
float timeY;
const float visualWidth = 200.0f;
const float visualHeight = 200.0f;
void OnCompleted(winrt::Windows::Foundation::IInspectable const &, winrt::Windows::UI::Composition::CompositionBatchCompletedEventArgs const &);
void AnimateSegment(winrt::Windows::Foundation::Numerics::float3 currentPos, winrt::Windows::Foundation::Numerics::float3 currentVelocity);
void OnDvdCompleted(winrt::Windows::Foundation::IInspectable const &, winrt::Windows::UI::Composition::CompositionBatchCompletedEventArgs const &)
{
winrt::Windows::Foundation::Numerics::float3 newPos = targetPos;
winrt::Windows::Foundation::Numerics::float3 newVelocity = dvdCurrentVelocity;
if (timeX < timeY)
{
newVelocity.x = -newVelocity.x;
}
else if (timeY < timeX)
{
newVelocity.y = -newVelocity.y;
}
else
{
newVelocity.x = -newVelocity.x;
newVelocity.y = -newVelocity.y;
}
std::uniform_real_distribution<float> deltaAngleDist(-0.1f, 0.1f);
float deltaAngle = deltaAngleDist(gen);
float currentSpeed = std::sqrt(newVelocity.x * newVelocity.x + newVelocity.y * newVelocity.y);
float newAngle = std::atan2(newVelocity.y, newVelocity.x) + deltaAngle;
newVelocity.x = currentSpeed * std::cos(newAngle);
newVelocity.y = currentSpeed * std::sin(newAngle);
static const winrt::Windows::UI::Color colors[18] =
{
winrt::Windows::UI::Color{180, 200, 100, 100},
winrt::Windows::UI::Color{180, 220, 150, 100},
winrt::Windows::UI::Color{180, 230, 200, 120},
winrt::Windows::UI::Color{180, 120, 200, 120},
winrt::Windows::UI::Color{180, 120, 160, 220},
winrt::Windows::UI::Color{180, 180, 140, 220},
winrt::Windows::UI::Color{180, 190, 130, 150},
winrt::Windows::UI::Color{180, 210, 170, 130},
winrt::Windows::UI::Color{180, 180, 190, 110},
winrt::Windows::UI::Color{180, 140, 200, 140},
winrt::Windows::UI::Color{180, 150, 150, 230},
winrt::Windows::UI::Color{180, 160, 180, 200},
winrt::Windows::UI::Color{180, 170, 110, 160},
winrt::Windows::UI::Color{180, 190, 140, 180},
winrt::Windows::UI::Color{180, 175, 155, 100},
winrt::Windows::UI::Color{180, 145, 180, 145},
winrt::Windows::UI::Color{180, 130, 190, 210},
winrt::Windows::UI::Color{180, 200, 170, 190}
};
static constexpr auto maxLimit = _countof(colors) - 1;
std::uniform_int_distribution<int> colorDist(0, maxLimit);
tintBrush.Properties().InsertColor(L"TintEffect.Color", colors[colorDist(gen)]);
AnimateSegment(newPos, newVelocity);
}
void OnFadeCompleted(winrt::Windows::Foundation::IInspectable const &, winrt::Windows::UI::Composition::CompositionBatchCompletedEventArgs const &)
{
animatedVisual.Brush(tintBrush.GetSourceParameter(L"source"));
animatedVisual.Offset({ 0, 0, 0 });
animatedVisual.AnchorPoint({ 0.5f, 0.5f });
OnCompleted(nullptr, nullptr);
}
void AnimateSegment(winrt::Windows::Foundation::Numerics::float3 currentPos, winrt::Windows::Foundation::Numerics::float3 currentVelocity)
{
auto now = std::chrono::steady_clock::now();
if (now - startTime >= totalDuration)
{
batch = m_compositor.CreateScopedBatch(winrt::Windows::UI::Composition::CompositionBatchTypes::Animation);
completedToken = batch.Completed({ &OnFadeCompleted });
fadeAnimation.Direction(winrt::Windows::UI::Composition::AnimationDirection::Reverse);
animatedVisual.StartAnimation(L"Opacity", fadeAnimation);
batch.End();
return;
}
timeX = std::numeric_limits<float>::infinity();
if (currentVelocity.x > 0)
timeX = (dvdContainerSize.Width - visualWidth - currentPos.x) / currentVelocity.x;
else if (currentVelocity.x < 0)
timeX = (0.0f - currentPos.x) / currentVelocity.x;
timeY = std::numeric_limits<float>::infinity();
if (currentVelocity.y > 0)
timeY = (dvdContainerSize.Height - visualHeight - currentPos.y) / currentVelocity.y;
else if (currentVelocity.y < 0)
timeY = (0.0f - currentPos.y) / currentVelocity.y;
float segmentTime = min(timeX, timeY);
float timeRemaining = std::chrono::duration<float>(totalDuration - (now - startTime)).count();
if (segmentTime > timeRemaining)
{
segmentTime = timeRemaining;
}
targetPos = currentPos + currentVelocity * segmentTime;
dvdCurrentVelocity = currentVelocity;
auto offsetAnimation = m_compositor.CreateVector3KeyFrameAnimation();
offsetAnimation.InsertKeyFrame(1.0f, targetPos, linearEasing);
int64_t durationTicks = static_cast<int64_t>(segmentTime * 10000000);
offsetAnimation.Duration(winrt::Windows::Foundation::TimeSpan { durationTicks });
offsetAnimation.Target(L"Offset");
batch.Completed(completedToken);
batch = m_compositor.CreateScopedBatch(winrt::Windows::UI::Composition::CompositionBatchTypes::Animation);
completedToken = batch.Completed({ &OnDvdCompleted });
animatedVisual.StartAnimation(L"Offset", offsetAnimation);
batch.End();
}
void StartDVDAnimation(winrt::Windows::UI::Composition::SpriteVisual const &dvdVisual, winrt::Windows::Foundation::Rect containerSize)
{
dvdContainerSize = containerSize;
std::uniform_real_distribution<float> posXDist(0.0f, containerSize.Width - visualWidth);
std::uniform_real_distribution<float> posYDist(0.0f, containerSize.Height - visualHeight);
float startX = posXDist(gen);
float startY = posYDist(gen);
dvdVisual.RelativeOffsetAdjustment({ 0, 0, 0 });
dvdVisual.Offset({ startX, startY, 0.0f });
dvdVisual.AnchorPoint({ 0.0f, 0.0f });
dvdVisual.Properties().InsertScalar(L"BrushRotation", 0.0f);
fadeAnimation.Direction(winrt::Windows::UI::Composition::AnimationDirection::Normal);
dvdVisual.StartAnimation(L"Opacity", fadeAnimation);
dvdVisual.Brush(tintBrush);
const float speed = 380.0f;
std::uniform_real_distribution<float> angleDist(0.0f, 2.0f * 3.14159265f);
//float angle = angleDist(gen);
float angle;
do { angle = angleDist(gen); } while (std::fabs(std::sin(angle)) < 0.3f || std::fabs(std::cos(angle)) < 0.3f);
float vx = speed * std::cos(angle);
float vy = speed * std::sin(angle);
winrt::Windows::Foundation::Numerics::float3 velocity = { vx, vy, 0.0f };
startTime = std::chrono::steady_clock::now();
AnimateSegment({ startX, startY, 0.0f }, velocity);
}
void OnCompleted(winrt::Windows::Foundation::IInspectable const &, winrt::Windows::UI::Composition::CompositionBatchCompletedEventArgs const &)
{
if (currentGroup == group2)
{
currentGroup = nullptr;
StartDVDAnimation(animatedVisual, m_coreWindow.Bounds());
return;
}
currentGroup = currentGroup == group1 ? group2 : group1;
batch.Completed(completedToken);
batch = m_compositor.CreateScopedBatch(winrt::Windows::UI::Composition::CompositionBatchTypes::Animation);
completedToken = batch.Completed({ &OnCompleted });
animatedVisual.StartAnimationGroup(currentGroup);
batch.End();
}
void SetupWatermark(IUnknown* device, winrt::Windows::UI::Core::CoreWindow window, winrt::Windows::UI::Composition::ContainerVisual root)
{
using namespace std::chrono_literals;
auto compositor = m_compositor;
m_coreWindow = window;
ComPtr<ID3D11Device> d3dDevice;
device->QueryInterface(d3dDevice.GetAddressOf());
ComPtr<ID3D11DeviceContext> d3dContext;
d3dDevice->GetImmediateContext(d3dContext.GetAddressOf());
auto graphicsDevice = CreateCompositionGraphicsDevice(device, compositor);
auto tuple = CreateD3D11Texture2D(d3dDevice.Get(), L"xw_logo.png");
auto texture = std::get<0>(tuple);
auto size = std::get<1>(tuple);
auto surface = graphicsDevice.CreateDrawingSurface(size, winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized, winrt::Windows::Graphics::DirectX::DirectXAlphaMode::Premultiplied);
DrawTextureToCompositionDrawingSurface(d3dContext.Get(), surface, texture.get());
auto brush = compositor.CreateSurfaceBrush(surface);
brush.Stretch(winrt::Windows::UI::Composition::CompositionStretch::UniformToFill);
const winrt::Windows::Foundation::Numerics::float2 targetSize = { 200.0f, 200.0f };
winrt::Windows::Foundation::Numerics::float2 scale = { targetSize.x / size.Width, targetSize.y / size.Height };
brush.Scale(scale);
auto visual = compositor.CreateSpriteVisual();
visual.Size(targetSize);
visual.RelativeOffsetAdjustment({ -0.1f, 0.5f, 0 });
visual.Brush(brush);
root.Children().InsertAtTop(visual);
visual.AnchorPoint({ 0.5f, 0.5f });
brush.RotationAngleInDegrees(-45.0f);
brush.CenterPoint({ 100, 100 });
visual.Opacity(0.0f);
visual.Properties().InsertScalar(L"BrushRotation", -45.0f);
auto linkAnimation = compositor.CreateExpressionAnimation(L"visual.BrushRotation");
linkAnimation.SetReferenceParameter(L"visual", visual);
brush.StartAnimation(L"RotationAngleInDegrees", linkAnimation);
auto easeIn = winrt::Windows::UI::Composition::CompositionEasingFunction::CreateExponentialEasingFunction(compositor, winrt::Windows::UI::Composition::CompositionEasingFunctionMode::In, 5.0f);
auto easeOut = winrt::Windows::UI::Composition::CompositionEasingFunction::CreateExponentialEasingFunction(compositor, winrt::Windows::UI::Composition::CompositionEasingFunctionMode::Out, 5.0f);
linearEasing = winrt::Windows::UI::Composition::CompositionEasingFunction::CreateLinearEasingFunction(compositor);
static const auto iterations = 3;
auto slideAnimation = compositor.CreateVector3KeyFrameAnimation();
slideAnimation.InsertKeyFrame(0.0f, { -0.1f, 0.5f, 0 });
slideAnimation.InsertKeyFrame(0.1f, { -0.1f, 0.5f, 0 });
slideAnimation.InsertKeyFrame(0.5f, { 0.5f, 0.5f, 0 }, easeOut);
slideAnimation.InsertKeyFrame(0.9f, { 1.1f, 0.5f, 0 }, easeIn);
slideAnimation.InsertKeyFrame(1.0f, { 1.1f, 0.5f, 0 });
slideAnimation.Duration(5s);
slideAnimation.DelayTime(1s);
slideAnimation.IterationCount(iterations);
slideAnimation.Direction(winrt::Windows::UI::Composition::AnimationDirection::Alternate);
slideAnimation.Target(L"RelativeOffsetAdjustment");
auto rotationAnimation = compositor.CreateScalarKeyFrameAnimation();
rotationAnimation.InsertKeyFrame(0.0f, -45.0f);
rotationAnimation.InsertKeyFrame(0.1f, -45.0f);
rotationAnimation.InsertKeyFrame(0.5f, 0.0f, easeOut);
rotationAnimation.InsertKeyFrame(0.9f, 45.0f, easeIn);
rotationAnimation.InsertKeyFrame(1.0f, 45.0f);
rotationAnimation.Duration(5s);
rotationAnimation.DelayTime(1s);
rotationAnimation.IterationCount(iterations);
rotationAnimation.Direction(winrt::Windows::UI::Composition::AnimationDirection::Alternate);
rotationAnimation.Target(L"BrushRotation");
auto opacityAnimation = compositor.CreateScalarKeyFrameAnimation();
opacityAnimation.InsertKeyFrame(0.0f, 0.0f);
opacityAnimation.InsertKeyFrame(0.1f, 0.0f);
opacityAnimation.InsertKeyFrame(0.5f, 1.0f, easeOut);
opacityAnimation.InsertKeyFrame(0.9f, 0.0f, easeIn);
opacityAnimation.InsertKeyFrame(1.0f, 0.0f);
opacityAnimation.Duration(5s);
opacityAnimation.DelayTime(1s);
opacityAnimation.IterationCount(iterations);
opacityAnimation.Direction(winrt::Windows::UI::Composition::AnimationDirection::Alternate);
opacityAnimation.Target(L"Opacity");
group1 = compositor.CreateAnimationGroup();
group1.Add(slideAnimation);
group1.Add(rotationAnimation);
group1.Add(opacityAnimation);
auto slideAnimation2 = compositor.CreateVector3KeyFrameAnimation();
slideAnimation2.InsertKeyFrame(0.0f, { 0.5f, -0.1f, 0 });
slideAnimation2.InsertKeyFrame(0.1f, { 0.5f, -0.1f, 0 });
slideAnimation2.InsertKeyFrame(0.5f, { 0.5f, 0.5f, 0 }, easeOut);
slideAnimation2.InsertKeyFrame(0.9f, { 0.5f, 1.1f, 0 }, easeIn);
slideAnimation2.InsertKeyFrame(1.0f, { 0.5f, 1.1f, 0 });
slideAnimation2.Duration(5s);
slideAnimation2.DelayTime(1s);
slideAnimation2.IterationCount(iterations);
slideAnimation2.Direction(winrt::Windows::UI::Composition::AnimationDirection::Alternate);
slideAnimation2.Target(L"RelativeOffsetAdjustment");
auto rotationAnimation2 = compositor.CreateScalarKeyFrameAnimation();
rotationAnimation2.InsertKeyFrame(0.0f, -1440.0f);
rotationAnimation2.InsertKeyFrame(0.1f, -1440.0f);
rotationAnimation2.InsertKeyFrame(0.5f, 0.0f, easeOut);
rotationAnimation2.InsertKeyFrame(0.9f, 1440.0f, easeIn);
rotationAnimation2.InsertKeyFrame(1.0f, 1440.0f);
rotationAnimation2.Duration(5s);
rotationAnimation2.DelayTime(1s);
rotationAnimation2.IterationCount(iterations);
rotationAnimation2.Direction(winrt::Windows::UI::Composition::AnimationDirection::Alternate);
rotationAnimation2.Target(L"BrushRotation");
group2 = compositor.CreateAnimationGroup();
group2.Add(slideAnimation2);
group2.Add(rotationAnimation2);
group2.Add(opacityAnimation);
fadeAnimation = compositor.CreateScalarKeyFrameAnimation();
fadeAnimation.InsertKeyFrame(0.0f, 0.0f);
fadeAnimation.InsertKeyFrame(1.0f, 1.0f);
fadeAnimation.Duration(1s);
auto tintEffect = winrt::make_self<TintEffect>();
tintEffect->Source = winrt::Windows::UI::Composition::CompositionEffectSourceParameter(L"source");
tintEffect->Color = winrt::Windows::UI::Colors::Transparent();
auto factory = m_compositor.CreateEffectFactory(*tintEffect, { L"TintEffect.Color" });
tintBrush = factory.CreateBrush();
tintBrush.SetSourceParameter(L"source", brush);
currentGroup = group1;
animatedVisual = visual;
batch = compositor.CreateScopedBatch(winrt::Windows::UI::Composition::CompositionBatchTypes::Animation);
completedToken = batch.Completed({ &OnCompleted });
visual.StartAnimationGroup(group1);
batch.End();
}
typedef HRESULT(WINAPI* CreateSwapChainForCoreWindow_t)(IDXGIFactory2* This, IUnknown* pDevice, IUnknown* pWindow, const DXGI_SWAP_CHAIN_DESC1* pDesc, IDXGIOutput* pRestrictToOutput, IDXGISwapChain1** ppSwapChain);
CreateSwapChainForCoreWindow_t g_CreateSwapChainForCoreWindow;
HRESULT STDMETHODCALLTYPE CreateSwapChainForCoreWindow(IDXGIFactory2* This, IUnknown* pDevice, IUnknown* pWindow, const DXGI_SWAP_CHAIN_DESC1* pDesc, IDXGIOutput* pRestrictToOutput, IDXGISwapChain1** ppSwapChain)
{
DXGI_SWAP_CHAIN_DESC1 desc = ConvertSwapchainDesc(pDesc);
XWineUnwrapInterface(pWindow, (void**)&pWindow);
if (!(UINT)XWineGetSettings()->EnableLegacyMode) [[likely]]
{
auto hr = This->CreateSwapChainForComposition(pDevice, &desc, pRestrictToOutput, ppSwapChain);
if (SUCCEEDED(hr))
{
m_compositor = winrt::Windows::UI::Composition::Compositor();
m_target = m_compositor.CreateTargetForCurrentView();
auto root = m_compositor.CreateSpriteVisual();
root.RelativeSizeAdjustment({ 1.0f, 1.0f });
winrt::com_ptr<ABI::Windows::UI::Composition::ICompositorInterop> compositorInterop = m_compositor.as<ABI::Windows::UI::Composition::ICompositorInterop>();
winrt::Windows::UI::Composition::ICompositionSurface surface{ nullptr };
compositorInterop->CreateCompositionSurfaceForSwapChain(*ppSwapChain, (ABI::Windows::UI::Composition::ICompositionSurface**)winrt::put_abi(surface));
auto brush = m_compositor.CreateSurfaceBrush(surface);
brush.Stretch(winrt::Windows::UI::Composition::CompositionStretch::Fill);
root.Brush(brush);
m_target.Root(root);
winrt::Windows::UI::Core::CoreWindow window { nullptr };
winrt::copy_from_abi(window, pWindow);
SetupWatermark(pDevice, window, root);
}
return hr;
}
else
return This->CreateSwapChainForHwnd(pDevice, (HWND)pWindow, &desc, nullptr, pRestrictToOutput, ppSwapChain);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment