Skip to content

Commit 17dd945

Browse files
MartinZikmundclaude
andcommitted
feat: Add 3D Projection Gallery sample
Showcases PlaneProjection and Matrix3DProjection rendering on the Skia targets (new in Uno Platform 6.6, PR unoplatform/uno#22449): an interactive card driven by rotation sliders plus a depth-preset gallery. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent e593c24 commit 17dd945

44 files changed

Lines changed: 2259 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

UI/ProjectionGallery/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# 3D Projection Gallery
2+
3+
This sample showcases **`PlaneProjection`** and **`Matrix3DProjection`**, which now render on the [Uno Platform](https://platform.uno) **Skia** targets as of **Uno Platform 6.6** ([PR #22449](https://github.com/unoplatform/uno/pull/22449)).
4+
5+
Projections let you rotate and translate any `UIElement` in 3D space — with real perspective — directly from XAML, without writing any custom rendering code. Think flip cards, carousels, cover-flow effects, and subtle depth.
6+
7+
![3D Projection Gallery running on Skia Desktop](doc/assets/ProjectionGallery.png)
8+
9+
The app runs from a single C# + XAML codebase on the Web (WebAssembly) and Desktop (Windows, macOS, Linux) via the Skia renderer.
10+
11+
## Features shown
12+
13+
- **Interactive card** — three sliders drive the `PlaneProjection.RotationX` / `RotationY` / `RotationZ` of a card, so you can spin it in 3D live.
14+
- **Depth presets** — the same card at fixed angles, making the perspective foreshortening obvious (the far edge shrinks).
15+
16+
## How it works
17+
18+
A `PlaneProjection` is attached to any element through the inherited `UIElement.Projection` property:
19+
20+
```xml
21+
<Border Width="240" Height="320">
22+
<Border.Projection>
23+
<PlaneProjection x:Name="HeroProjection"
24+
RotationX="{Binding Value, ElementName=RotX}"
25+
RotationY="{Binding Value, ElementName=RotY}"
26+
RotationZ="{Binding Value, ElementName=RotZ}" />
27+
</Border.Projection>
28+
<!-- card content -->
29+
</Border>
30+
```
31+
32+
The rotation values are two-way bound to `Slider` controls, so moving a slider rotates the card in real time. For full control you can instead use `Matrix3DProjection` and supply your own 4×4 `Matrix3D`.
33+
34+
![The same card at different fixed rotation angles](doc/assets/ProjectionGallery-Presets.png)
35+
36+
## Codebase
37+
38+
* [**MainPage.xaml**](src/ProjectionGallery/MainPage.xaml): the entire UI — the interactive hero card, the rotation sliders, and the depth-preset gallery, all using `PlaneProjection`.
39+
* [**MainPage.xaml.cs**](src/ProjectionGallery/MainPage.xaml.cs): a small `Reset` handler that returns the sliders to zero.
40+
41+
## What is the Uno Platform
42+
43+
[Uno Platform](https://platform.uno) is an open-source .NET platform for building single-codebase native mobile, web, desktop, and embedded apps quickly.
44+
For additional information about Uno Platform or if you have any feedback to share, please refer to the [README.md](../../README.md) file in this Samples repository.
111 KB
Loading
107 KB
Loading
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
; This file is for unifying the coding style for different editors and IDEs.
2+
; More information at http://editorconfig.org
3+
4+
# This file is the top-most EditorConfig file
5+
root = true
6+
7+
##########################################
8+
# Common Settings
9+
##########################################
10+
11+
[*]
12+
indent_style = space
13+
end_of_line = crlf
14+
trim_trailing_whitespace = true
15+
insert_final_newline = true
16+
charset = utf-8
17+
18+
##########################################
19+
# File Extension Settings
20+
##########################################
21+
22+
[*.{yml,yaml}]
23+
indent_size = 2
24+
25+
[.vsconfig]
26+
indent_size = 2
27+
end_of_line = lf
28+
29+
[*.sln]
30+
indent_style = tab
31+
indent_size = 2
32+
33+
[*.{csproj,proj,projitems,shproj}]
34+
indent_size = 4
35+
36+
[*.{json,slnf}]
37+
indent_size = 2
38+
end_of_line = lf
39+
40+
[*.{props,targets}]
41+
indent_size = 4
42+
43+
[*.xaml]
44+
indent_size = 4
45+
charset = utf-8-bom
46+
47+
[*.xml]
48+
indent_size = 4
49+
end_of_line = lf
50+
51+
[*.plist]
52+
indent_size = 4
53+
indent_style = tab
54+
end_of_line = lf
55+
56+
[*.manifest]
57+
indent_size = 4
58+
59+
[*.appxmanifest]
60+
indent_size = 4
61+
62+
[*.{json,css,webmanifest}]
63+
indent_size = 2
64+
end_of_line = lf
65+
66+
[web.config]
67+
indent_size = 4
68+
end_of_line = lf
69+
70+
[*.sh]
71+
indent_size = 2
72+
end_of_line = lf
73+
74+
[*.cs]
75+
# EOL should be normalized by Git. See https://github.com/dotnet/format/issues/1099
76+
end_of_line = unset
77+
78+
# See https://github.com/dotnet/roslyn/issues/20356#issuecomment-310143926
79+
trim_trailing_whitespace = false
80+
81+
tab_width = 4
82+
indent_size = 4
83+
84+
# Sort using and Import directives with System.* appearing first
85+
dotnet_sort_system_directives_first = true
86+
87+
# Avoid "this." and "Me." if not necessary
88+
dotnet_style_qualification_for_field = false:suggestion
89+
dotnet_style_qualification_for_property = false:suggestion
90+
dotnet_style_qualification_for_method = false:suggestion
91+
dotnet_style_qualification_for_event = false:suggestion
92+
93+
#### Naming styles ####
94+
95+
# Naming rules
96+
97+
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
98+
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
99+
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
100+
101+
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
102+
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
103+
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
104+
105+
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
106+
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
107+
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
108+
109+
# Symbol specifications
110+
111+
dotnet_naming_symbols.interface.applicable_kinds = interface
112+
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
113+
dotnet_naming_symbols.interface.required_modifiers =
114+
115+
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
116+
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
117+
dotnet_naming_symbols.types.required_modifiers =
118+
119+
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
120+
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
121+
dotnet_naming_symbols.non_field_members.required_modifiers =
122+
123+
# Naming styles
124+
125+
dotnet_naming_style.begins_with_i.required_prefix = I
126+
dotnet_naming_style.begins_with_i.required_suffix =
127+
dotnet_naming_style.begins_with_i.word_separator =
128+
dotnet_naming_style.begins_with_i.capitalization = pascal_case
129+
130+
dotnet_naming_style.pascal_case.required_prefix =
131+
dotnet_naming_style.pascal_case.required_suffix =
132+
dotnet_naming_style.pascal_case.word_separator =
133+
dotnet_naming_style.pascal_case.capitalization = pascal_case
134+
135+
dotnet_naming_style.pascal_case.required_prefix =
136+
dotnet_naming_style.pascal_case.required_suffix =
137+
dotnet_naming_style.pascal_case.word_separator =
138+
dotnet_naming_style.pascal_case.capitalization = pascal_case
139+
dotnet_style_operator_placement_when_wrapping = beginning_of_line
140+
dotnet_style_coalesce_expression = true:suggestion
141+
dotnet_style_null_propagation = true:suggestion
142+
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
143+
dotnet_style_prefer_auto_properties = true:silent
144+
dotnet_style_object_initializer = true:suggestion
145+
dotnet_style_collection_initializer = true:suggestion
146+
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
147+
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
148+
dotnet_style_prefer_conditional_expression_over_return = true:silent
149+
dotnet_style_explicit_tuple_names = true:suggestion
150+
dotnet_style_prefer_inferred_tuple_names = true:suggestion
151+
152+
csharp_indent_labels = one_less_than_current
153+
csharp_using_directive_placement = outside_namespace:silent
154+
csharp_prefer_simple_using_statement = true:suggestion
155+
csharp_prefer_braces = true:silent
156+
csharp_style_namespace_declarations = file_scoped:warning
157+
csharp_style_prefer_method_group_conversion = true:silent
158+
csharp_style_prefer_top_level_statements = true:silent
159+
csharp_style_prefer_primary_constructors = true:suggestion
160+
csharp_style_expression_bodied_methods = false:silent
161+
csharp_style_expression_bodied_constructors = false:silent
162+
csharp_style_expression_bodied_operators = false:silent
163+
csharp_style_expression_bodied_properties = true:silent
164+
csharp_style_expression_bodied_indexers = true:silent
165+
csharp_style_expression_bodied_accessors = true:silent
166+
csharp_style_expression_bodied_lambdas = true:silent
167+
csharp_style_expression_bodied_local_functions = false:silent

0 commit comments

Comments
 (0)