WinUI 3용으로 Win2D Example Gallery 변환 - slog

Win2D Example Gallery는 Win2D의 기능을 갤러리 형식으로 확인할 수 있고요, Microsoft Store에서 설치할 수 있습니다.

image

그런데 WinUI 3용으로는 아직 없어서 Win2D 기능중 어떤게 정상 동작하는지를 알길이 없어서 Windows Template Studio을 이용해 간단히 WinUI 프로젝트를 생성한 후 필요한 기능부터 하나씩 페이지를 추가해가며 기능을 파악할 계획입니다.

전체 중 일단 제가 필요로 하는 기능부터 변환해 나갈 생각입니다.

  • [x] Layer
  • [x] Mandelbrot
  • [x] Shapes
  • [x] Stroke Styles
  • [x] Arc Options
  • [ ] Gradient Mesh
  • [x] Geometry Operations
  • [x] Text Directions
  • [ ] Subscript And Superscript
  • [ ] Text Layouts
  • [ ] Virtual Control
  • [ ] Keyboard Input
  • [ ] DPI
좋아요 2

CanvasAnimatedControl는 아직 지원하지 않는다 합니다.

좋아요 2

Windows Template Studio 를 확장 관리로 설치하면 프로젝트 생성 시 WinUI 3의 프로젝트를 생성할 수 있습니다. App (WinUI 3 in Desktop App)를 선택합니다.

Navigation Pane을 선택합니다. 계획은 왼쪽 햄버거 메뉴에서 각각의 Win2D 기능 메뉴를 노출할 계획입니다.

디자인 패턴은 MVVM Toolkit 입니다.

페이지에 Settings를 추가합니다. 기본적인 테마 관련 기능이 추가됩니다.

만들기로 프로젝트 생성후 실행해 봅니다.

좋은 세상이군요. 이정도의 구조가 마법사를 통해 빠르게 구성되었네요.

좋아요 1

LayerPage를 추가하려고 합니다. MVVM 구조이므로 Views에 LayerPage(Page)를 ViewModels에 LayerViewModel(ObservableRecipient 상속)을 각각 추가합니다. ViewModel을 당장에 쓰지는 않겠지만, 일단 구조에 맞게 추가해봅시다.

ViewModel과 Page를 App.xaml.cs의 ConfigureServices()에 추가합니다.

...
            services.AddTransient<LayerPage>();
            services.AddTransient<LayerViewModel>();

그리고 햄버거 메뉴에 Layer 메뉴를 등록해야 하는데요. ShellPage.xaml을 수정합니다.

...
<NavigationViewItem x:Uid="Shell_Main" Icon="Document" helpers:NavHelper.NavigateTo="Win2DExampleGallery.WinUI3.ViewModels.MainViewModel" />
<NavigationViewItem x:Uid="Shell_Layer" Icon="Document" helpers:NavHelper.NavigateTo="Win2DExampleGallery.WinUI3.ViewModels.LayerViewModel" />

메뉴 타이틀을 표시하기 위해 Resources.resw에 다음을 추가합니다.

...
Shell_Main.Content = "Main"

실행하면 Layer 메뉴가 추가된 것을 보실 수 있습니다.

좋아요 1

진행하다가 ABI로 시작하는 네임스페이스가 궁금해졌습니다. 저는 UWP 및 WinRT에 대한 경험이 없기 때문에 ABI에 대해서 모릅니다.

조사한 바로는,

WinRT는 COM 기반이며 ABI(Application Binary Interface)를 통해 접근된다고 합니다. 그러니까 ABI를 통해 WinRT의 기능을 이용할 수 있군요. (소스코드 레벨로는 아직 전혀 모르겠습니다.)

또, 언어 프로젝션을 이용하면 COM 세부 정보를 알 필요 없이, 해당 언어에 맞는 API 형태로 이용할 수도 있다고 합니다. (그런 형태가 아마 C++/WinRT 등이겠지요)

좋아요 2

Layer Example 페이지를 추가했습니다.

아직 WinUI 3용 CanvasAnimatedControl를 지원하지 않아 canvas.Invalidate()Update의 동작을 대신했습니다. 비교해 보니 CanvasAnimatedControl가 훨씬 빠르게 동작은 하네요. 아무래도 CanvasAnimatedControl은 모니터에 맞는 최적의 FPS로 Draw를 해줄 것 같고 canvas.Invalidate()는 메시지 큐에 의해 업데이트를 할 것이므로, 그런 차이가 생기는 것 같습니다.

좋아요 1

Mandelbrot Example 페이지를 추가했습니다. DisplayInformation이 WinUI 3에는 지원하지 않아 DPI 변경을 감지하는 코드를 주석 처리 했고 나머지는 정상 동작합니다.
UWP의 동작 보다는 WinUI 3에서 동작이 좀 느린 느낌입니다.

좋아요 1

Shapes Example 페이지를 추가했습니다.

좋아요 1

StrokeStyles Example 페이지를 추가했습니다. 특별한 문제 없이 잘 변환됩니다.

좋아요 1

ArcOptions Example 페이지를 추가했습니다. 마우스로 Arc의 사이즈를 조절할 수 있는 예제인데, UWP와 WinUI 3의 성능차이가 있습니다.

좋아요 1

Gradient Mesh Example 는 실행시 예외가 발생합니다.

Object contains non-primitive or non-blittable data. 예외가 발생하는데, 인자대로 메소드 호출을 잘 한것 같은데 예외가 발생하는 이유를 모르겠네요.

좋아요 1

Geometry Operations Example 페이지를 추가했습니다. 역시 아직 WinUI 3에서 CanvasAnimatedControl을 지원하지 않아 CanvasControl로 컨버팅했습니다.

좋아요 1

Text Directions Example 페이지를 추가했습니다.

좋아요 1

목표의 절반 정도를 WinUI 3 용으로 변환하면서 느낀 점은, UWP용 Win2D 라이브러리의 대부분의 namespace는 그대로 유지되어 대체로 잘 동작하고, (변환 작업 중 Gradient Mesh Example은 오류를 발생했지만, ) CanvasAnimatedControl은 아마 WinUI 3와의 최적화 문제로 미 적용 된 듯 하며, 이 컨트롤이 추가되는 시점에 CanvasControl의 Invalidate의 성능도 정상화 될 것 같다는 점입니다.

WinUI 3 in Desktop App 형태는 win32로 구동된다는 점 빼고는 UWP의 컨트롤 및 구성을 그대로 계승한 것 처럼 보입니다. 컨트롤의 사용도 WPF의 그것과 같아 어려움은 없었습니다.

오늘은 여기까지;

좋아요 1

아직까지는 WinUI3 에서 Win2D의 활용은 어려운 것으로 보입니다. 사실, 정식 출시전이니까요.
Windows App SDK GitHub를 둘러본 결과, Win2D의 지원은 우선순위에 의해 후순위로 배치되어 있는 듯 합니다. 그리고 WinUI3 역시 Windows App SDK의 구성요소로 포함될 것으로 보이며, 2021년도에는 글쎄요 제가 원하는 수준으로 안정화 될 것 같지는 않네요.

다음의 대안으로 Avalonia UI를 살펴보고 있습니다. Avalonia UI는 오랜 시간 공을 들여 만들어진 WPF과 유사한 프레임워크이면서 클로스 플랫폼으로 윈도, 리눅스, 맥OS에서 동일한 코드로 데스크톱 어플리케이션을 개발할 수 있도록 합니다. 상용 어플리케이션에 적용할 수 있을정도로 안정화 되었으며 Skia를 백엔드 렌더러로 선택할 수 있어서 그리기 퍼포먼스가 인상적인 정도로 빠름을 확인할 수 있었습니다.

좋아요 2

드디어 Win2D Github에서 질문에 대한 답변을 달아줬군요! 본인들도 몰랐던 것 같습니다. WinUI 3용 갤러리 작업 예정이라고 하는군요.

좋아요 1