Created
March 26, 2025 19:16
-
-
Save ahmed605/779a548515214a698999090e86dac835 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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