├── .editorconfig ├── .gitattributes ├── .gitignore ├── .sbproj ├── Assets ├── Content │ ├── alpha-inv.png │ ├── alpha.png │ ├── background.png │ ├── balloon.jpg │ ├── border-diamonds.png │ ├── border-ff.png │ ├── boxes.webm │ ├── fp.png │ ├── small-2x2.png │ ├── svg-1.svg │ └── svg-2.svg └── start.scene ├── Code ├── Assembly.cs ├── Staging │ ├── CalcPanel.razor │ ├── VideoControls.razor │ ├── VideoControls.razor.scss │ ├── VideoPanel.razor │ └── VideoPanel.razor.scss ├── Tests │ ├── Basics │ │ ├── Calc.razor │ │ ├── EmRem.razor │ │ ├── FlexShorthand.razor │ │ ├── MouseCapture.razor │ │ ├── MouseCapture.razor.scss │ │ ├── Opacity.cs │ │ ├── Opacity.cs.scss │ │ ├── Scissoring.razor │ │ ├── Scrolling.razor │ │ ├── VirtualScrolling.cs │ │ └── VwVh.razor │ ├── Elements │ │ ├── AnimatedImages.razor │ │ ├── AnimatedImages.razor.scss │ │ ├── InputButtons.cs │ │ ├── RenderScene.cs │ │ ├── SliderTests.razor │ │ ├── SliderTests.razor.scss │ │ ├── SvgTests.razor │ │ ├── TextEntry.cs │ │ ├── TextEntry.cs.scss │ │ ├── VideoImages.razor │ │ ├── VideoImages.razor.scss │ │ ├── VideoPanelTest.razor │ │ ├── VideoPanelTest.razor.scss │ │ ├── WebPanelTest.razor │ │ └── WebPanelTest.razor.scss │ ├── Razor │ │ ├── RazorBinds.razor │ │ ├── RazorFragment.razor │ │ ├── RazorFragment.razor.scss │ │ ├── TableComponent.razor │ │ └── TableComponent.razor.scss │ ├── Styles │ │ ├── Animations.cs │ │ ├── Animations.cs.scss │ │ ├── BackdropFilter.cs │ │ ├── BackdropFilter.cs.scss │ │ ├── Background.cs │ │ ├── Background.cs.scss │ │ ├── BackgroundBlendMode.razor │ │ ├── BackgroundBlendMode.razor.scss │ │ ├── BackgroundPosition.cs │ │ ├── BackgroundPosition.cs.scss │ │ ├── BorderImages.cs │ │ ├── BorderRadius.cs │ │ ├── BorderRadius.cs.scss │ │ ├── Borders.cs │ │ ├── BoxShadow.cs │ │ ├── Effects.cs │ │ ├── Filters.razor │ │ ├── Filters.razor.scss │ │ ├── ImageRendering.cs │ │ ├── ImageRendering.cs.scss │ │ ├── Keyframes.razor │ │ ├── Keyframes.razor.scss │ │ ├── MaskImage.razor │ │ ├── MaskImage.razor.scss │ │ ├── TextAlign.cs │ │ ├── TextColor.cs │ │ ├── TextOverflow.razor │ │ ├── TextOverflow.razor.scss │ │ ├── TextShadow.cs │ │ ├── TextShadow.cs.scss │ │ ├── TextStyles.razor │ │ ├── Transitions.razor │ │ └── Transitions.razor.scss │ └── Transforms │ │ ├── TransformedInteract.razor │ │ ├── TransformedInteract.razor.scss │ │ ├── Transforms.razor │ │ └── Transforms.razor.scss ├── UILab.razor ├── UILab.razor.scss ├── UILabComponent.razor └── UILabComponent.razor.scss ├── LICENSE ├── ProjectSettings └── Collision.config └── uilab.sln /.editorconfig: -------------------------------------------------------------------------------- 1 | # Remove the line below if you want to inherit .editorconfig settings from higher directories 2 | root = true 3 | 4 | # C# files 5 | [*.{cs,razor}] 6 | indent_style = tab 7 | indent_size = 4 8 | tab_size = 4 9 | 10 | # New line preferences 11 | end_of_line = crlf 12 | insert_final_newline = true 13 | 14 | 15 | #### C# Coding Conventions #### 16 | 17 | # Expression-bodied members 18 | csharp_style_expression_bodied_accessors = true:silent 19 | csharp_style_expression_bodied_constructors = false:silent 20 | csharp_style_expression_bodied_indexers = true:silent 21 | csharp_style_expression_bodied_lambdas = true:silent 22 | csharp_style_expression_bodied_local_functions = false:silent 23 | csharp_style_expression_bodied_methods = false:silent 24 | csharp_style_expression_bodied_operators = false:silent 25 | csharp_style_expression_bodied_properties = true:silent 26 | 27 | # Pattern matching preferences 28 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion 29 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion 30 | csharp_style_prefer_not_pattern = true:suggestion 31 | csharp_style_prefer_pattern_matching = true:silent 32 | csharp_style_prefer_switch_expression = true:suggestion 33 | 34 | # Null-checking preferences 35 | csharp_style_conditional_delegate_call = true:suggestion 36 | 37 | # Code-block preferences 38 | csharp_prefer_braces = true:silent 39 | 40 | # Expression-level preferences 41 | csharp_prefer_simple_default_expression = true:suggestion 42 | csharp_style_deconstructed_variable_declaration = true:suggestion 43 | csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion 44 | csharp_style_inlined_variable_declaration = true:suggestion 45 | csharp_style_pattern_local_over_anonymous_function = true:suggestion 46 | csharp_style_prefer_index_operator = true:suggestion 47 | csharp_style_prefer_range_operator = true:suggestion 48 | csharp_style_throw_expression = true:suggestion 49 | csharp_style_unused_value_assignment_preference = discard_variable:suggestion 50 | csharp_style_unused_value_expression_statement_preference = discard_variable:silent 51 | 52 | # 'using' directive preferences 53 | csharp_using_directive_placement = outside_namespace:silent 54 | 55 | #### C# Formatting Rules #### 56 | 57 | # New line preferences 58 | csharp_new_line_before_catch = true 59 | csharp_new_line_before_else = true 60 | csharp_new_line_before_finally = true 61 | csharp_new_line_before_members_in_anonymous_types = true 62 | csharp_new_line_before_members_in_object_initializers = true 63 | csharp_new_line_before_open_brace = all 64 | csharp_new_line_between_query_expression_clauses = true 65 | 66 | # Indentation preferences 67 | csharp_indent_block_contents = true 68 | csharp_indent_braces = false 69 | csharp_indent_case_contents = true 70 | csharp_indent_case_contents_when_block = true 71 | csharp_indent_labels = no_change 72 | csharp_indent_switch_labels = true 73 | 74 | # Space preferences 75 | csharp_space_after_cast = false 76 | csharp_space_after_colon_in_inheritance_clause = true 77 | csharp_space_after_comma = true 78 | csharp_space_after_dot = false 79 | csharp_space_after_keywords_in_control_flow_statements = true 80 | csharp_space_after_semicolon_in_for_statement = true 81 | csharp_space_around_binary_operators = before_and_after 82 | csharp_space_around_declaration_statements = false 83 | csharp_space_before_colon_in_inheritance_clause = true 84 | csharp_space_before_comma = false 85 | csharp_space_before_dot = false 86 | csharp_space_before_open_square_brackets = false 87 | csharp_space_before_semicolon_in_for_statement = false 88 | csharp_space_between_empty_square_brackets = false 89 | csharp_space_between_method_call_empty_parameter_list_parentheses = false 90 | csharp_space_between_method_call_name_and_opening_parenthesis = false 91 | csharp_space_between_method_call_parameter_list_parentheses = true 92 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false 93 | csharp_space_between_method_declaration_name_and_open_parenthesis = false 94 | csharp_space_between_method_declaration_parameter_list_parentheses = true 95 | csharp_space_between_parentheses = control_flow_statements 96 | csharp_space_between_square_brackets = false 97 | 98 | # Wrapping preferences 99 | csharp_preserve_single_line_blocks = true 100 | csharp_preserve_single_line_statements = true -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # This file describes files and paths that should not be tracked by Git version control 3 | # https://git-scm.com/docs/gitignore 4 | 5 | # Auto-generated code editor files 6 | .vs/* 7 | .vscode/* 8 | *.csproj 9 | obj/* 10 | Properties/* 11 | code/obj/* 12 | code/Properties/* 13 | 14 | # Auto-generated asset related files 15 | *.generated.* 16 | *.*_c 17 | *.los 18 | *.vpk -------------------------------------------------------------------------------- /.sbproj: -------------------------------------------------------------------------------- 1 | { 2 | "Title": "UI Lab", 3 | "Type": "game", 4 | "Org": "facepunch", 5 | "Ident": "uilab", 6 | "Tags": null, 7 | "Schema": 1, 8 | "Resources": null, 9 | "PackageReferences": [], 10 | "EditorReferences": null, 11 | "Metadata": { 12 | "MaxPlayers": 64, 13 | "MinPlayers": 1, 14 | "GameNetworkType": "Multiplayer", 15 | "MapSelect": "Unrestricted", 16 | "MapList": [ 17 | "facepunch.flatgrass" 18 | ], 19 | "RankType": "None", 20 | "PerMapRanking": false, 21 | "LeaderboardType": "None", 22 | "ProjectTemplate": null, 23 | "CsProjName": "", 24 | "HttpAllowList": null, 25 | "Compiler": { 26 | "RootNamespace": "Sandbox", 27 | "DefineConstants": "SANDBOX;ADDON;DEBUG", 28 | "NoWarn": "1701;1702;1591;", 29 | "References": [], 30 | "DistinctReferences": [] 31 | }, 32 | "Summary": "", 33 | "Description": "", 34 | "Public": true, 35 | "TickRate": 50, 36 | "ControlModes": {}, 37 | "InputSettings": { 38 | "Actions": [ 39 | { 40 | "Name": "Forward", 41 | "KeyboardCode": "W", 42 | "GroupName": "Movement" 43 | }, 44 | { 45 | "Name": "Backward", 46 | "KeyboardCode": "S", 47 | "GroupName": "Movement" 48 | }, 49 | { 50 | "Name": "Left", 51 | "KeyboardCode": "A", 52 | "GroupName": "Movement" 53 | }, 54 | { 55 | "Name": "Right", 56 | "KeyboardCode": "D", 57 | "GroupName": "Movement" 58 | }, 59 | { 60 | "Name": "Jump", 61 | "KeyboardCode": "space", 62 | "GamepadCode": "A", 63 | "GroupName": "Movement" 64 | }, 65 | { 66 | "Name": "Run", 67 | "KeyboardCode": "shift", 68 | "GamepadCode": "LeftJoystickButton", 69 | "GroupName": "Movement" 70 | }, 71 | { 72 | "Name": "Walk", 73 | "KeyboardCode": "alt", 74 | "GroupName": "Movement" 75 | }, 76 | { 77 | "Name": "Duck", 78 | "KeyboardCode": "ctrl", 79 | "GamepadCode": "B", 80 | "GroupName": "Movement" 81 | }, 82 | { 83 | "Name": "attack1", 84 | "KeyboardCode": "mouse1", 85 | "GamepadCode": "RightTrigger", 86 | "GroupName": "Actions" 87 | }, 88 | { 89 | "Name": "attack2", 90 | "KeyboardCode": "mouse2", 91 | "GamepadCode": "LeftTrigger", 92 | "GroupName": "Actions" 93 | }, 94 | { 95 | "Name": "reload", 96 | "KeyboardCode": "r", 97 | "GamepadCode": "X", 98 | "GroupName": "Actions" 99 | }, 100 | { 101 | "Name": "use", 102 | "KeyboardCode": "e", 103 | "GamepadCode": "Y", 104 | "GroupName": "Actions" 105 | }, 106 | { 107 | "Name": "Slot1", 108 | "KeyboardCode": "1", 109 | "GamepadCode": "DpadWest", 110 | "GroupName": "Inventory" 111 | }, 112 | { 113 | "Name": "Slot2", 114 | "KeyboardCode": "2", 115 | "GamepadCode": "DpadEast", 116 | "GroupName": "Inventory" 117 | }, 118 | { 119 | "Name": "Slot3", 120 | "KeyboardCode": "3", 121 | "GamepadCode": "DpadSouth", 122 | "GroupName": "Inventory" 123 | }, 124 | { 125 | "Name": "Slot4", 126 | "KeyboardCode": "4", 127 | "GroupName": "Inventory" 128 | }, 129 | { 130 | "Name": "Slot5", 131 | "KeyboardCode": "5", 132 | "GroupName": "Inventory" 133 | }, 134 | { 135 | "Name": "Slot6", 136 | "KeyboardCode": "6", 137 | "GroupName": "Inventory" 138 | }, 139 | { 140 | "Name": "Slot7", 141 | "KeyboardCode": "7", 142 | "GroupName": "Inventory" 143 | }, 144 | { 145 | "Name": "Slot8", 146 | "KeyboardCode": "8", 147 | "GroupName": "Inventory" 148 | }, 149 | { 150 | "Name": "Slot9", 151 | "KeyboardCode": "9", 152 | "GroupName": "Inventory" 153 | }, 154 | { 155 | "Name": "Slot0", 156 | "KeyboardCode": "0", 157 | "GroupName": "Inventory" 158 | }, 159 | { 160 | "Name": "SlotPrev", 161 | "KeyboardCode": "mouse4", 162 | "GamepadCode": "SwitchLeftBumper", 163 | "GroupName": "Inventory" 164 | }, 165 | { 166 | "Name": "SlotNext", 167 | "KeyboardCode": "mouse5", 168 | "GamepadCode": "SwitchRightBumper", 169 | "GroupName": "Inventory" 170 | }, 171 | { 172 | "Name": "View", 173 | "KeyboardCode": "C", 174 | "GamepadCode": "RightJoystickButton", 175 | "GroupName": "Other" 176 | }, 177 | { 178 | "Name": "Voice", 179 | "KeyboardCode": "v", 180 | "GamepadCode": "RightJoystickButton", 181 | "GroupName": "Other" 182 | }, 183 | { 184 | "Name": "Drop", 185 | "KeyboardCode": "g", 186 | "GamepadCode": "RightJoystickButton", 187 | "GroupName": "Other" 188 | }, 189 | { 190 | "Name": "Chat", 191 | "KeyboardCode": "enter", 192 | "GroupName": "Other" 193 | } 194 | ] 195 | } 196 | } 197 | } -------------------------------------------------------------------------------- /Assets/Content/alpha-inv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sboxgame/ui_lab/ab71524ba1fe8f509baf1c410835e531cf8e908f/Assets/Content/alpha-inv.png -------------------------------------------------------------------------------- /Assets/Content/alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sboxgame/ui_lab/ab71524ba1fe8f509baf1c410835e531cf8e908f/Assets/Content/alpha.png -------------------------------------------------------------------------------- /Assets/Content/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sboxgame/ui_lab/ab71524ba1fe8f509baf1c410835e531cf8e908f/Assets/Content/background.png -------------------------------------------------------------------------------- /Assets/Content/balloon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sboxgame/ui_lab/ab71524ba1fe8f509baf1c410835e531cf8e908f/Assets/Content/balloon.jpg -------------------------------------------------------------------------------- /Assets/Content/border-diamonds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sboxgame/ui_lab/ab71524ba1fe8f509baf1c410835e531cf8e908f/Assets/Content/border-diamonds.png -------------------------------------------------------------------------------- /Assets/Content/border-ff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sboxgame/ui_lab/ab71524ba1fe8f509baf1c410835e531cf8e908f/Assets/Content/border-ff.png -------------------------------------------------------------------------------- /Assets/Content/boxes.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sboxgame/ui_lab/ab71524ba1fe8f509baf1c410835e531cf8e908f/Assets/Content/boxes.webm -------------------------------------------------------------------------------- /Assets/Content/fp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sboxgame/ui_lab/ab71524ba1fe8f509baf1c410835e531cf8e908f/Assets/Content/fp.png -------------------------------------------------------------------------------- /Assets/Content/small-2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sboxgame/ui_lab/ab71524ba1fe8f509baf1c410835e531cf8e908f/Assets/Content/small-2x2.png -------------------------------------------------------------------------------- /Assets/Content/svg-1.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 384 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | -------------------------------------------------------------------------------- /Assets/Content/svg-2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Assets/start.scene: -------------------------------------------------------------------------------- 1 | { 2 | "GameObjects": [ 3 | { 4 | "Id": "235499ff-ccdf-4ec2-a002-e1812738da3c", 5 | "Name": "Camera", 6 | "Enabled": true, 7 | "Components": [ 8 | { 9 | "__type": "CameraComponent", 10 | "__enabled": true, 11 | "BackgroundColor": "0.33333,0.46275,0.52157,1", 12 | "ClearFlags": "All", 13 | "FieldOfView": 60, 14 | "Orthographic": false, 15 | "OrthographicHeight": 1204, 16 | "RenderExcludeTags": "", 17 | "RenderTags": "", 18 | "TargetEye": "None", 19 | "ZFar": 10000, 20 | "ZNear": 10 21 | } 22 | ] 23 | }, 24 | { 25 | "Id": "37732e62-f0d0-4b1e-bdff-c1e9b8468aa9", 26 | "Name": "Screen", 27 | "Enabled": true, 28 | "Components": [ 29 | { 30 | "__type": "ScreenPanel", 31 | "__enabled": true, 32 | "AutoScreenScale": true, 33 | "Opacity": 1, 34 | "Scale": 1, 35 | "ZIndex": 100 36 | } 37 | ], 38 | "Children": [ 39 | { 40 | "Id": "51168d4b-f711-4fdc-9d34-8212389deb3f", 41 | "Name": "UI Lab", 42 | "Enabled": true, 43 | "Components": [ 44 | { 45 | "__type": "UILabComponent", 46 | "__enabled": true 47 | } 48 | ] 49 | } 50 | ] 51 | } 52 | ], 53 | "SceneProperties": { 54 | "FixedUpdateFrequency": 50, 55 | "Lerping": true, 56 | "MaxFixedUpdates": 5, 57 | "NetworkFrequency": 60, 58 | "ThreadedAnimation": true, 59 | "TimeScale": 1, 60 | "UseFixedUpdate": true 61 | }, 62 | "Title": "start", 63 | "Description": "", 64 | "__references": [] 65 | } -------------------------------------------------------------------------------- /Code/Assembly.cs: -------------------------------------------------------------------------------- 1 | global using System.Collections; 2 | global using System.Collections.Generic; 3 | global using System.Linq; 4 | global using Sandbox; 5 | global using Sandbox.Razor; 6 | global using Sandbox.UI; 7 | -------------------------------------------------------------------------------- /Code/Staging/CalcPanel.razor: -------------------------------------------------------------------------------- 1 | @using System 2 | 3 | @namespace Sandbox.UI 4 | @inherits Sandbox.UI.Panel 5 | 6 | 21 | 22 | 23 | 24 |
25 | 26 |
27 | 28 | @code { 29 | public string Calc { get; set; } 30 | private Panel InnerPanel { get; set; } 31 | 32 | protected override void OnAfterTreeRender(bool firstTime) 33 | { 34 | base.OnAfterTreeRender(firstTime); 35 | 36 | var style = $"div {{ width: {Calc}; }}"; 37 | StyleSheet.Parse(style); 38 | } 39 | 40 | public string Title() 41 | { 42 | return $"{Calc}"; 43 | } 44 | 45 | public string Text() 46 | { 47 | return $"Width: {InnerPanel.Box.Rect.Width}px"; 48 | } 49 | 50 | protected override int BuildHash() 51 | { 52 | return HashCode.Combine(Time.Now); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Code/Staging/VideoControls.razor: -------------------------------------------------------------------------------- 1 | @using System 2 | @namespace Sandbox.UI 3 | @attribute [StyleSheet] 4 | @inherits Sandbox.UI.Panel 5 | 6 | @if (VideoPlayer == null) 7 | return; 8 | 9 | 10 | 11 |
12 | 13 | @if ( VideoPlayer.IsPaused ) 14 | { 15 |
16 | play_arrow 17 |
18 | } 19 | else 20 | { 21 |
22 | pause 23 |
24 | } 25 | 26 |
27 | 28 |
29 | 30 |
31 | 32 |
33 | 34 |
35 | 36 |
37 | 38 | @if ( !VideoPlayer.HasAudio ) 39 | { 40 |
41 | volume_off 42 |
43 | } 44 | else if ( VideoPlayer.Muted ) 45 | { 46 |
47 | volume_off 48 |
49 | } 50 | else 51 | { 52 |
53 | volume_up 54 |
55 | } 56 | 57 |
58 | 59 |
60 | @GetPlayback() 61 | / 62 | @GetDuration() 63 |
64 | 65 |
66 | 67 |
68 | 69 |
70 | 71 | @code 72 | { 73 | public Sandbox.VideoPlayer VideoPlayer { get; set; } 74 | 75 | protected override int BuildHash() 76 | { 77 | return System.HashCode.Combine( VideoPlayer, VideoPlayer?.PlaybackTime, VideoPlayer.IsPaused ); 78 | } 79 | 80 | void TimelineChanged( float value ) 81 | { 82 | VideoPlayer.Seek( value ); 83 | } 84 | 85 | string GetPlayback() 86 | { 87 | return TimeSpan.FromSeconds( VideoPlayer.PlaybackTime ).ToString( "mm\\:ss" ); //); 88 | } 89 | 90 | string GetDuration() 91 | { 92 | return TimeSpan.FromSeconds( VideoPlayer.Duration ).ToString( "mm\\:ss" ); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /Code/Staging/VideoControls.razor.scss: -------------------------------------------------------------------------------- 1 |  2 | .videocontrols 3 | { 4 | background-color: #0005; 5 | backdrop-filter: blur( 10px ); 6 | min-width: 200px; 7 | max-width: 800px; 8 | flex-grow: 1; 9 | border-radius: 10px; 10 | pointer-events: all; 11 | flex-direction: row; 12 | 13 | 14 | > .left 15 | { 16 | .playbutton 17 | { 18 | font-size: 60px; 19 | padding: 20px; 20 | pointer-events: all; 21 | justify-content: center; 22 | align-items: center; 23 | } 24 | } 25 | 26 | > .right 27 | { 28 | flex-grow: 1; 29 | flex-direction: column; 30 | padding: 16px 32px; 31 | padding-left: 0px; 32 | gap: 5px; 33 | } 34 | 35 | .meta 36 | { 37 | .left 38 | { 39 | flex-grow: 1; 40 | 41 | i 42 | { 43 | font-size: 25px; 44 | } 45 | } 46 | 47 | .right 48 | { 49 | font-size: 15px; 50 | opacity: 0.8; 51 | gap: 5px; 52 | } 53 | } 54 | 55 | .video-control-button 56 | { 57 | opacity: 0.8; 58 | cursor: pointer; 59 | 60 | &:hover 61 | { 62 | opacity: 1; 63 | } 64 | 65 | &.disabled 66 | { 67 | pointer-events: none; 68 | opacity: 0.2; 69 | } 70 | } 71 | 72 | .slidercontrol 73 | { 74 | .thumb 75 | { 76 | display: none; 77 | } 78 | 79 | .track 80 | { 81 | margin: 0; 82 | height: 10px; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Code/Staging/VideoPanel.razor: -------------------------------------------------------------------------------- 1 | @namespace Sandbox.UI 2 | @attribute [StyleSheet] 3 | @inherits Sandbox.UI.Panel 4 | 5 | 6 | 7 | @if (Controls) 8 | { 9 | 10 | } 11 | 12 | 13 | 14 | @code 15 | { 16 | string _source; 17 | 18 | public string Source 19 | { 20 | get => _source; 21 | 22 | set 23 | { 24 | if (_source == value) return; 25 | 26 | _source = value; 27 | 28 | videoPlayer.Play( FileSystem.Mounted, Source ); 29 | } 30 | } 31 | 32 | public bool Repeat 33 | { 34 | set 35 | { 36 | videoPlayer.Repeat = value; 37 | } 38 | } 39 | 40 | public bool Controls { get; set; } = true; 41 | 42 | Sandbox.VideoPlayer videoPlayer; 43 | 44 | public VideoPanel() 45 | { 46 | videoPlayer = new VideoPlayer(); 47 | 48 | // TODO: Let the user decide how audio is played 49 | // videoPlayer.OnAudioReady = () => videoPlayer.PlayAudio(); 50 | 51 | Repeat = true; 52 | Style.AspectRatio = 16.0f / 9.0f; 53 | } 54 | 55 | public override void OnDeleted() 56 | { 57 | videoPlayer?.Dispose(); 58 | videoPlayer = null; 59 | } 60 | 61 | public override bool HasContent => true; 62 | 63 | public override void Tick() 64 | { 65 | base.Tick(); 66 | 67 | // Try to match the aspect ratio of the video 68 | if (videoPlayer.Width > 4 && videoPlayer.Height > 4) 69 | { 70 | Style.AspectRatio = (float)videoPlayer.Width / (float)videoPlayer.Height; 71 | } 72 | } 73 | 74 | 75 | public override void DrawContent(ref RenderState state) 76 | { 77 | base.DrawContent(ref state); 78 | 79 | videoPlayer.Present(); 80 | 81 | var tex = videoPlayer?.Texture; 82 | 83 | // todo - change the UV so we can do object-fit: cover 84 | Graphics.Attributes.Set("Texture", videoPlayer.Texture ); 85 | Graphics.DrawQuad( Box.Rect, Material.UI.Basic, Color.White ); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /Code/Staging/VideoPanel.razor.scss: -------------------------------------------------------------------------------- 1 |  2 | .videopanel 3 | { 4 | width: 100%; 5 | 6 | flex-grow: 1; 7 | flex-shrink: 0; 8 | 9 | // Where we want the video controls 10 | align-items: flex-end; 11 | padding: 30px; 12 | justify-content: center; 13 | } -------------------------------------------------------------------------------- /Code/Tests/Basics/Calc.razor: -------------------------------------------------------------------------------- 1 | @namespace Sandbox.UI.Tests.Basics 2 | @inherits Sandbox.UI.Panel 3 | 4 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Code/Tests/Basics/EmRem.razor: -------------------------------------------------------------------------------- 1 | @namespace Sandbox.UI.Tests.Basics 2 | @inherits Sandbox.UI.Panel 3 | 4 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 |
27 | 28 |
29 | 30 | 31 | 32 |
33 | 34 | 35 |
36 |
37 |
38 | -------------------------------------------------------------------------------- /Code/Tests/Basics/FlexShorthand.razor: -------------------------------------------------------------------------------- 1 | @namespace Sandbox.UI.Tests.Basics 2 | @inherits Sandbox.UI.Panel 3 | 4 | 21 | 22 | 23 | @* https://files.facepunch.com/alexguthrie/1b0211b1/msedge_pdsBTNfASA.png *@ 24 | 25 |
26 | @for ( int i = 0; i < 10; ++i ) 27 | { 28 | 29 | Hello 30 | 31 | } 32 |
33 | 34 | 35 |
36 | @for (int i = 0; i < 10; ++i) 37 | { 38 | 39 | Hello 40 | 41 | } 42 |
43 | 44 | 45 |
46 | @for (int i = 0; i < 10; ++i) 47 | { 48 | 49 | Hello 50 | 51 | } 52 |
53 | 54 | 55 |
56 | @for (int i = 0; i < 10; ++i) 57 | { 58 | 59 | Hello 60 | 61 | } 62 |
63 | 64 | 65 |
66 | @for (int i = 0; i < 10; ++i) 67 | { 68 | 69 | Hello 70 | 71 | } 72 |
73 | 74 | 75 |
76 | @for (int i = 0; i < 10; ++i) 77 | { 78 | 79 | Hello 80 | 81 | } 82 |
83 | 84 | 85 |
86 | @for (int i = 0; i < 10; ++i) 87 | { 88 | 89 | Hello 90 | 91 | } 92 |
93 |
94 | -------------------------------------------------------------------------------- /Code/Tests/Basics/MouseCapture.razor: -------------------------------------------------------------------------------- 1 | @namespace Sandbox.UI.Tests.Basics 2 | @attribute [StyleSheet] 3 | @inherits Sandbox.UI.Panel 4 | 5 |
6 | 7 | 8 | 9 |
10 | 11 | @code 12 | { 13 | Label label; 14 | Vector2 position; 15 | 16 | public override void Tick() 17 | { 18 | base.Tick(); 19 | 20 | if (HasMouseCapture) 21 | { 22 | position += Mouse.Delta; 23 | 24 | label.Text = $"{position.x}\n{position.y}"; 25 | 26 | label.Style.Left = position.x; 27 | label.Style.Top = position.y; 28 | label.Style.Dirty(); 29 | 30 | // When the mouse becomes visible again, 31 | // we'll put the cursor in the middle of this box 32 | Mouse.Position = label.Box.Rect.Position + label.Box.Rect.Size * 0.5f; 33 | } 34 | } 35 | 36 | protected override void OnMouseDown( MousePanelEvent e ) 37 | { 38 | base.OnMouseDown( e ); 39 | e.StopPropagation(); 40 | } 41 | 42 | public override void OnButtonEvent( ButtonEvent e ) 43 | { 44 | if ( e.Button == "mouseleft" ) 45 | { 46 | SetMouseCapture( e.Pressed ); 47 | } 48 | 49 | base.OnButtonEvent( e ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Code/Tests/Basics/MouseCapture.razor.scss: -------------------------------------------------------------------------------- 1 |  2 | .root 3 | { 4 | width: 100%; 5 | height: 800px; 6 | overflow: hidden; 7 | 8 | label 9 | { 10 | background-color: white; 11 | color: black; 12 | font-weight: bold; 13 | border-radius: 20px; 14 | width: 100px; 15 | height: 100px; 16 | padding: 20px; 17 | text-align: center; 18 | align-items: center; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Code/Tests/Basics/Opacity.cs: -------------------------------------------------------------------------------- 1 | using Sandbox.UI.Construct; 2 | using System; 3 | using System.Linq; 4 | 5 | namespace Sandbox.UI.Tests.Basics; 6 | 7 | [StyleSheet] 8 | public class Opacity : Panel 9 | { 10 | public Opacity() 11 | { 12 | AddTest( ( p ) => { p.Add.Label( "Hello" ).Style.Set( "color: white;" ); } ); 13 | AddTest( ( p ) => { p.Add.Label( "Hello" ).Style.Set( "color: black;" ); } ); 14 | AddTest( ( p ) => { p.Add.Label( "Hello" ).Style.Set( "color: white; text-shadow: 2px 2px 10px black;" ); } ); 15 | AddTest( ( p ) => { p.Add.Panel().Style.Set( "background-color: white; width: 50px; height: 50px; border-radius: 10px;" ); } ); 16 | AddTest( ( p ) => { p.Add.Panel().Style.Set( "background-color: black; width: 50px; height: 50px; border-radius: 10px;" ); } ); 17 | AddTest( ( p ) => { p.Add.Panel().Style.Set( "border: 4px solid white; width: 50px; height: 50px; border-radius: 10px;" ); } ); 18 | AddTest( ( p ) => { p.Add.Panel().Style.Set( "border: 4px solid black; width: 50px; height: 50px; border-radius: 10px;" ); } ); 19 | AddTest( ( p ) => { p.Add.Panel().Style.Set( "background-image: url( /content/background.png ); background-size: cover; width: 50px; height: 50px; border-radius: 10px;" ); } ); 20 | } 21 | 22 | private void AddTest( Action p ) 23 | { 24 | var group = Add.Panel( "group" ); 25 | 26 | var a = group.Add.Panel( "a" ); 27 | p( a ); 28 | 29 | var b = group.Add.Panel( "b" ); 30 | p( b ); 31 | 32 | var c = group.Add.Panel( "c" ); 33 | p( c ); 34 | 35 | var d = group.Add.Panel( "d" ); 36 | p( d ); 37 | 38 | var e = group.Add.Panel( "e" ); 39 | p( e ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Code/Tests/Basics/Opacity.cs.scss: -------------------------------------------------------------------------------- 1 | 2 | Opacity 3 | { 4 | align-items: center; 5 | justify-content: center; 6 | 7 | .group 8 | { 9 | width: 100px; 10 | height: 400px; 11 | margin: 10px; 12 | flex-direction: column; 13 | background-color: #0094ff; 14 | 15 | 16 | .a, .b, .c, .d, .e 17 | { 18 | flex-grow: 1; 19 | width: 100%; 20 | align-items: center; 21 | justify-content: center; 22 | margin-bottom: 2px; 23 | transition: all 1s linear; 24 | } 25 | 26 | .a 27 | { 28 | opacity: 1.0; 29 | } 30 | 31 | .b 32 | { 33 | opacity: 0.75; 34 | } 35 | 36 | .c 37 | { 38 | opacity: 0.5; 39 | } 40 | 41 | .d 42 | { 43 | opacity: 0.25; 44 | } 45 | 46 | .e 47 | { 48 | opacity: 0; 49 | } 50 | 51 | &:hover 52 | { 53 | .a, .b, .c, .d, .e 54 | { 55 | opacity: 1.0; 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Code/Tests/Basics/Scissoring.razor: -------------------------------------------------------------------------------- 1 |  2 | @namespace Sandbox.UI.Tests.Basics 3 | @inherits Sandbox.UI.Panel 4 | 5 | 42 | 43 | 44 | 45 |
46 | 47 |
48 |
49 |
50 | 51 |
52 |
53 |
54 | 55 |
56 |
57 |
58 | 59 |
60 |
61 |
62 | 63 |
64 |
65 |
66 | 67 |
68 | 69 |
70 |
71 |
72 |
73 | 74 |
75 |
76 |
77 | 78 |
79 |
80 |
81 |
82 | 83 |
84 | -------------------------------------------------------------------------------- /Code/Tests/Basics/Scrolling.razor: -------------------------------------------------------------------------------- 1 |  2 | @namespace Sandbox.UI.Tests.Basics 3 | @inherits Sandbox.UI.Panel 4 | 5 | 70 | 71 | 72 | 73 |
74 | 75 |
76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 |
87 | 88 |
89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 |
100 | 101 |
102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 |
113 | 114 |
115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 |
126 | 127 |
128 | 129 |
130 | 131 |
132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 |
143 | 144 |
145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 |
156 | 157 |
158 | 159 |
160 |
161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 |
177 |
178 | 179 |
180 | -------------------------------------------------------------------------------- /Code/Tests/Basics/VirtualScrolling.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Sandbox.UI.Tests.Basics; 4 | 5 | public class VirtualScrolling : Panel 6 | { 7 | public VirtualScrolling() 8 | { 9 | Style.FlexWrap = Wrap.Wrap; 10 | Style.JustifyContent = Justify.Center; 11 | Style.AlignItems = Align.Center; 12 | Style.AlignContent = Align.Center; 13 | Style.Set( "flex-wrap: wrap; flex-direction: row;" ); 14 | StyleSheet.Parse( "label { flex-grow: 1; font-size: 13px; padding: 10px; border-radius: 2px; background-color: #aaa3; color: white; margin: 5px; margin-bottom: 0; } \n" + 15 | "button { label { margin: 0; padding: 0; background-color: transparent; } cursor: pointer; flex-grow: 1; font-size: 10px; padding: 10px; border-radius: 2px; color: white; margin: 2px; margin-bottom: 0; &:hover{ background-color: #4af;} }" ); 16 | 17 | 18 | { 19 | var data = new List(); 20 | 21 | var date = DateTime.Now; 22 | for ( int i = 0; i < 10; i++ ) 23 | { 24 | data.Add( $"{date.ToLongDateString()} is on a {date.DayOfWeek}" ); 25 | date = date.AddDays( 1 ); 26 | } 27 | 28 | var vs = AddChild(); 29 | vs.OnCreateCell = ( cell, data ) => 30 | { 31 | var label = cell.AddChild