├── .github └── workflows │ ├── ci.yml │ ├── develop.yml │ └── release.yml ├── .gitignore ├── Download-References-Staging.ps1 ├── Download-References.ps1 ├── LICENSE ├── README.md └── src ├── Rust.UIFramework.sln ├── Rust.UIFramework ├── Benchmarks │ └── BenchmarkNetWrite.cs ├── Builder │ ├── BaseBuilder.cs │ ├── BaseUiBuilder.Components.cs │ ├── BaseUiBuilder.Controls.cs │ ├── BaseUiBuilder.cs │ ├── Cached │ │ └── CachedUiBuilder.cs │ ├── UI │ │ ├── UiBuilder.CreateBuilders.cs │ │ └── UiBuilder.cs │ └── Update │ │ └── UpdateBuilder.cs ├── Builders │ └── SendInfoBuilder.cs ├── Cache │ ├── EnumCache{T}.cs │ ├── StringCache.cs │ ├── UiColorCache.cs │ ├── UiFontCache.cs │ ├── UiLayerCache.cs │ ├── UiNameCache.cs │ └── VectorCache.cs ├── Colors │ ├── UiColor.cs │ ├── UiColorConverter.cs │ └── UiColors.cs ├── Commands │ └── UiCommand.cs ├── Components │ ├── BaseComponent.cs │ ├── BaseImageComponent.cs │ ├── BasePoolableComponent.cs │ ├── BaseTextComponent.cs │ ├── ButtonComponent.cs │ ├── CountdownComponent.cs │ ├── IComponent.cs │ ├── ImageComponent.cs │ ├── InputComponent.cs │ ├── ItemIconComponent.cs │ ├── OutlineComponent.cs │ ├── PlayerAvatarComponent.cs │ ├── RawImageComponent.cs │ ├── RectTransformComponent.cs │ ├── ScrollViewComponent.cs │ ├── ScrollViewContentTransformComponent.cs │ ├── ScrollbarComponent.cs │ └── TextComponent.cs ├── Controls │ ├── BaseUiControl.cs │ ├── Data │ │ ├── ButtonGroupData.cs │ │ ├── DropdownMenuData.cs │ │ ├── TimePickerData.cs │ │ └── UiBorderWidth.cs │ ├── NumberPicker │ │ ├── BaseNumberPicker.cs │ │ ├── UiIncrementalNumberPicker.cs │ │ └── UiNumberPicker.cs │ ├── Popover │ │ ├── BasePopoverControl.cs │ │ ├── UiCalenderPicker.cs │ │ ├── UiColorPickerMenu.cs │ │ ├── UiDatePickerMenu.cs │ │ ├── UiDropdownMenu.cs │ │ ├── UiDropdownMenuItem.cs │ │ ├── UiPopover.cs │ │ └── UiTimePickerMenu.cs │ ├── UiBorder.cs │ ├── UiButtonGroup.cs │ ├── UiCheckbox.cs │ ├── UiColorPicker.cs │ ├── UiDatePicker.cs │ ├── UiDropdown.cs │ ├── UiInputBackground.cs │ ├── UiLabelBackground.cs │ ├── UiPaginator.cs │ ├── UiPicker.cs │ ├── UiProgressBar.cs │ ├── UiScrollBar.cs │ └── UiTimePicker.cs ├── Enums │ ├── BorderMode.cs │ ├── ClockMode.cs │ ├── ColorPickerMode.cs │ ├── DatePickerDisplayMode.cs │ ├── DatePickerDisplayOrder.cs │ ├── InputMode.cs │ ├── NumberPickerMode.cs │ ├── PopoverPosition.cs │ ├── ScrollbarDirection.cs │ ├── TimePickerDisplayMode.cs │ ├── TimerFormat.cs │ ├── UiFont.cs │ └── UiLayer.cs ├── Exceptions │ ├── UiFrameworkException.cs │ └── UiReferenceException.cs ├── Extension │ ├── Carbon │ │ └── CarbonExtension.cs │ └── Oxide │ │ └── UiFrameworkExtension.cs ├── Extensions │ ├── ArgExt.cs │ ├── OxideCuiExt.cs │ ├── StringBuilderExt.cs │ ├── TypeExt.cs │ ├── UiColorExt.cs │ ├── UiOffsetExt.cs │ ├── UiPositionExt.cs │ └── UiReferenceExt.cs ├── Helpers │ └── GenericMath.cs ├── Json │ ├── JsonBinaryWriter.cs │ ├── JsonDefaults.cs │ ├── JsonFrameworkWriter.cs │ └── SizedArray.cs ├── Offsets │ ├── BaseOffset.cs │ ├── GridOffset.cs │ ├── GridOffsetBuilder.cs │ └── UiOffset.cs ├── Pooling │ ├── BasePool.cs │ ├── BasePoolable.cs │ ├── HashPool.cs │ ├── IPool.cs │ ├── IPool{T}.cs │ ├── ListPool.cs │ ├── ObjectPool.cs │ ├── StringBuilderPool.cs │ └── UiFrameworkPool.cs ├── Positions │ ├── BasePosition.cs │ ├── GridPosition.cs │ ├── GridPositionBuilder.cs │ └── UiPosition.cs ├── Rust.UIFramework.csproj ├── Threading │ ├── BaseUiRequest.cs │ ├── IUiRequest.cs │ ├── OxideCuiRequest.cs │ ├── SendHandler.cs │ └── UiSendRequest.cs ├── UiConstants.cs ├── UiElements │ ├── BaseUiComponent.cs │ ├── BaseUiImage.cs │ ├── BaseUiOutline.cs │ ├── UiButton.cs │ ├── UiImage.cs │ ├── UiInput.cs │ ├── UiItemIcon.cs │ ├── UiLabel.cs │ ├── UiPanel.cs │ ├── UiPlayerAvatar.cs │ ├── UiRawImage.cs │ ├── UiReference.cs │ ├── UiScrollView.cs │ └── UiSection.cs └── UiHelpers.cs └── Rust.UiFramework.Benchmarks ├── Benchmarks.cs ├── Program.cs └── Rust.UiFramework.Benchmarks.csproj /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: windows-latest 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | 18 | - name: Setup .NET 19 | uses: actions/setup-dotnet@v4 20 | 21 | - name: Display .NET version 22 | run: dotnet --version 23 | 24 | - name: Set VERSION variable from tag 25 | run: echo "VERSION=0.0.0" | Out-File -FilePath $env:GITHUB_ENV 26 | 27 | - name: Download References 28 | shell: pwsh 29 | run: | 30 | .\Download-References.ps1 31 | 32 | - name: Build DLLs - Oxide 33 | run: dotnet build Rust.UIFramework.csproj -c Release /p:Platform=Oxide /p:Version=${{ env.VERSION }} -f net48 34 | working-directory: src/Rust.UIFramework 35 | 36 | - name: Build DLLs - Carbon 37 | run: dotnet build Rust.UIFramework.csproj -c Release /p:Platform=Carbon /p:Version=${{ env.VERSION }} -f net48 38 | working-directory: src/Rust.UIFramework 39 | -------------------------------------------------------------------------------- /.github/workflows/develop.yml: -------------------------------------------------------------------------------- 1 | name: Create Pre Release Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v[0-9]+.[0-9]+.[0-9]+-preview.[0-9]+.[0-9]+.[0-9]" 7 | 8 | jobs: 9 | build: 10 | 11 | runs-on: windows-latest 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | 17 | - name: Setup .NET 18 | uses: actions/setup-dotnet@v4 19 | 20 | - name: Set VERSION variable from tag 21 | run: echo "VERSION=${GITHUB_REF/refs\/tags\/v/}" | Out-File -FilePath $env:GITHUB_ENV 22 | 23 | - name: Download References 24 | shell: pwsh 25 | run: | 26 | .\Download-References.ps1 27 | 28 | - name: Build DLLs - Oxide 29 | run: dotnet build Rust.UIFramework.csproj -c Release /p:Platform=Oxide /p:Version=${{ env.VERSION }} -f net48 30 | working-directory: src/Rust.UIFramework 31 | 32 | - name: Build DLLs - Carbon 33 | run: dotnet build Rust.UIFramework.csproj -c Release /p:Platform=Carbon /p:Version=${{ env.VERSION }} -f net48 34 | working-directory: src/Rust.UIFramework 35 | 36 | - name: Move DLLs 37 | run: | 38 | mkdir -p bin 39 | mv Rust.UIFramework/bin/Oxide/Release/net48/Oxide.Ext.UiFramework.dll bin/ 40 | mv Rust.UIFramework/bin/Carbon/Release/net48/Carbon.Ext.UiFramework.dll bin/ 41 | working-directory: src 42 | 43 | - name: Upload Release Assets 44 | run: | 45 | $TAG=($env:GITHUB_REF -replace 'refs/tags/', '') 46 | $dllPath = Get-ChildItem -Path src/bin -Filter *.dll -File | Select-Object -ExpandProperty FullName 47 | gh release upload $TAG $dllPath 48 | env: 49 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 50 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Create Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "[0-9]+.[0-9]+.[0-9]+" 7 | 8 | jobs: 9 | build: 10 | 11 | runs-on: windows-latest 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | 17 | - name: Setup .NET 18 | uses: actions/setup-dotnet@v4 19 | 20 | - name: Display .NET version 21 | run: dotnet --version 22 | 23 | - name: Set VERSION variable from tag 24 | run: echo "VERSION=${{github.ref_name}}" | Out-File -FilePath $env:GITHUB_ENV 25 | 26 | - name: Download References 27 | shell: pwsh 28 | run: | 29 | .\Download-References.ps1 30 | 31 | - name: Build DLLs - Oxide 32 | run: dotnet build Rust.UIFramework.csproj -c Release /p:Platform=Oxide /p:Version=${{ env.VERSION }} -f net48 33 | working-directory: src/Rust.UIFramework 34 | 35 | - name: Build DLLs - Carbon 36 | run: dotnet build Rust.UIFramework.csproj -c Release /p:Platform=Carbon /p:Version=${{ env.VERSION }} -f net48 37 | working-directory: src/Rust.UIFramework 38 | 39 | - name: Move DLLs 40 | run: | 41 | mkdir -p bin 42 | mv Rust.UIFramework/bin/Oxide/Release/net48/Oxide.Ext.UiFramework.dll bin/ 43 | mv Rust.UIFramework/bin/Carbon/Release/net48/Carbon.Ext.UiFramework.dll bin/ 44 | working-directory: src 45 | 46 | - name: Upload Release Assets 47 | run: | 48 | $TAG=($env:GITHUB_REF -replace 'refs/tags/', '') 49 | $dllPath = Get-ChildItem -Path src/bin -Filter *.dll -File | Select-Object -ExpandProperty FullName 50 | gh release upload $TAG $dllPath 51 | env: 52 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 53 | -------------------------------------------------------------------------------- /Download-References-Staging.ps1: -------------------------------------------------------------------------------- 1 | # Clear the current directory (except the script itself) 2 | 3 | $resourcesDir = Join-Path -Path $PSScriptRoot -ChildPath "src/references" 4 | 5 | New-Item -ItemType Directory -Force -Path $resourcesDir 6 | 7 | Get-ChildItem -Path $resourcesDir | Remove-Item -Force -Recurse 8 | 9 | # Create a temporary folder 10 | $tmpDir = New-Item -ItemType Directory -Force -Path "$env:TEMP\Download-References" 11 | 12 | # Temporary folders for DepotDownloader and Rust DLLs 13 | $depotDir = Join-Path -Path $tmpDir -ChildPath "DepotDownloader" 14 | $rustDir = Join-Path -Path $depotDir -ChildPath "RustDLLs" 15 | 16 | # Create a temporary folder for DepotDownloader and Rust DLLs 17 | New-Item -ItemType Directory -Force -Path $depotDir 18 | New-Item -ItemType Directory -Force -Path $rustDir 19 | 20 | # Download and extract DepotDownloader 21 | Invoke-WebRequest -Uri "https://github.com/SteamRE/DepotDownloader/releases/latest/download/DepotDownloader-windows-x64.zip" -OutFile "$depotDir\DepotDownloader.zip" 22 | Expand-Archive -Path "$depotDir\DepotDownloader.zip" -DestinationPath $depotDir -Force 23 | Remove-Item -Path "$depotDir\DepotDownloader.zip" 24 | 25 | # Create a file named filelist.txt for downloading .dll files 26 | $fileListPath = Join-Path -Path $rustDir -ChildPath "filelist.txt" 27 | @("regex:RustDedicated_Data/Managed/.*\.dll") | Set-Content -Path $fileListPath 28 | 29 | # Download .dll files using DepotDownloader 30 | $depotArgs = "-app 258550 -beta staging -depot 258551 -filelist $fileListPath -dir $rustDir" 31 | Start-Process -FilePath "$depotDir\DepotDownloader.exe" -ArgumentList $depotArgs -NoNewWindow -Wait 32 | 33 | # Move .dll files to the current directory 34 | Move-Item -Path "$rustDir\RustDedicated_Data\Managed\*.dll" -Destination $resourcesDir -Force 35 | 36 | # Download and extract Carbon (presumably for Windows) 37 | $carbonDir = Join-Path -Path $tmpDir -ChildPath "Carbon" 38 | New-Item -ItemType Directory -Force -Path $carbonDir 39 | Invoke-WebRequest -Uri "https://github.com/CarbonCommunity/Carbon/releases/download/production_build/Carbon.Windows.Release.zip" -OutFile "$carbonDir\Carbon.zip" 40 | Expand-Archive -Path "$carbonDir\Carbon.zip" -DestinationPath $carbonDir -Force 41 | Remove-Item -Path "$carbonDir\Carbon.zip" 42 | 43 | # Move .dll files from Carbon to the current directory 44 | Move-Item -Path "$carbonDir\carbon\managed\*.dll" -Destination $resourcesDir -Force 45 | 46 | # Download and extract Oxide (presumably for Windows) 47 | $oxideDir = Join-Path -Path $tmpDir -ChildPath "Oxide" 48 | New-Item -ItemType Directory -Force -Path $oxideDir 49 | Invoke-WebRequest -Uri "https://downloads.oxidemod.com/artifacts/Oxide.Rust/staging/Oxide.Rust.zip" -OutFile "$oxideDir\Oxide.Rust.zip" 50 | Expand-Archive -Path "$oxideDir\Oxide.Rust.zip" -DestinationPath $oxideDir -Force 51 | Remove-Item -Path "$oxideDir\Oxide.Rust.zip" 52 | 53 | # Move .dll files from Oxide to the current directory 54 | Move-Item -Path "$oxideDir\RustDedicated_Data\Managed\*.dll" -Destination $resourcesDir -Force 55 | 56 | # Delete the temporary folder 57 | Remove-Item -Path $tmpDir -Force -Recurse 58 | 59 | # Display a completion message 60 | Write-Host "References downloaded and copied to $PSScriptRoot." 61 | -------------------------------------------------------------------------------- /Download-References.ps1: -------------------------------------------------------------------------------- 1 | # Clear the current directory (except the script itself) 2 | 3 | $resourcesDir = Join-Path -Path $PSScriptRoot -ChildPath "src/references" 4 | 5 | New-Item -ItemType Directory -Force -Path $resourcesDir 6 | 7 | Get-ChildItem -Path $resourcesDir | Remove-Item -Force -Recurse 8 | 9 | # Create a temporary folder 10 | $tmpDir = New-Item -ItemType Directory -Force -Path "$env:TEMP\Download-References" 11 | 12 | # Temporary folders for DepotDownloader and Rust DLLs 13 | $depotDir = Join-Path -Path $tmpDir -ChildPath "DepotDownloader" 14 | $rustDir = Join-Path -Path $depotDir -ChildPath "RustDLLs" 15 | 16 | # Create a temporary folder for DepotDownloader and Rust DLLs 17 | New-Item -ItemType Directory -Force -Path $depotDir 18 | New-Item -ItemType Directory -Force -Path $rustDir 19 | 20 | # Download and extract DepotDownloader 21 | Invoke-WebRequest -Uri "https://github.com/SteamRE/DepotDownloader/releases/latest/download/DepotDownloader-windows-x64.zip" -OutFile "$depotDir\DepotDownloader.zip" 22 | Expand-Archive -Path "$depotDir\DepotDownloader.zip" -DestinationPath $depotDir -Force 23 | Remove-Item -Path "$depotDir\DepotDownloader.zip" 24 | 25 | # Create a file named filelist.txt for downloading .dll files 26 | $fileListPath = Join-Path -Path $rustDir -ChildPath "filelist.txt" 27 | @("regex:RustDedicated_Data/Managed/.*\.dll") | Set-Content -Path $fileListPath 28 | 29 | # Download .dll files using DepotDownloader 30 | $depotArgs = "-app 258550 -depot 258551 -filelist $fileListPath -dir $rustDir" 31 | Start-Process -FilePath "$depotDir\DepotDownloader.exe" -ArgumentList $depotArgs -NoNewWindow -Wait 32 | 33 | # Move .dll files to the current directory 34 | Move-Item -Path "$rustDir\RustDedicated_Data\Managed\*.dll" -Destination $resourcesDir -Force 35 | 36 | # Download and extract Carbon (presumably for Windows) 37 | $carbonDir = Join-Path -Path $tmpDir -ChildPath "Carbon" 38 | New-Item -ItemType Directory -Force -Path $carbonDir 39 | Invoke-WebRequest -Uri "https://github.com/CarbonCommunity/Carbon/releases/download/production_build/Carbon.Windows.Release.zip" -OutFile "$carbonDir\Carbon.zip" 40 | Expand-Archive -Path "$carbonDir\Carbon.zip" -DestinationPath $carbonDir -Force 41 | Remove-Item -Path "$carbonDir\Carbon.zip" 42 | 43 | # Move .dll files from Carbon to the current directory 44 | Move-Item -Path "$carbonDir\carbon\managed\*.dll" -Destination $resourcesDir -Force 45 | 46 | # Download and extract Oxide (presumably for Windows) 47 | $oxideDir = Join-Path -Path $tmpDir -ChildPath "Oxide" 48 | New-Item -ItemType Directory -Force -Path $oxideDir 49 | Invoke-WebRequest -Uri "https://github.com/OxideMod/Oxide.Rust/releases/latest/download/Oxide.Rust.zip" -OutFile "$oxideDir\Oxide.Rust.zip" 50 | Expand-Archive -Path "$oxideDir\Oxide.Rust.zip" -DestinationPath $oxideDir -Force 51 | Remove-Item -Path "$oxideDir\Oxide.Rust.zip" 52 | 53 | # Move .dll files from Oxide to the current directory 54 | Move-Item -Path "$oxideDir\RustDedicated_Data\Managed\*.dll" -Destination $resourcesDir -Force 55 | 56 | # Delete the temporary folder 57 | Remove-Item -Path $tmpDir -Force -Recurse 58 | 59 | # Display a completion message 60 | Write-Host "References downloaded and copied to $PSScriptRoot." 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Josh Dassinger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rust UI Framework 2 | UI Framework for Rust (The Game) using the [Oxide/uMod](https://umod.org) plugin platform 3 | 4 | ## Performance Comparison vs Oxide 5 | 6 | This benchmark shows the performance comparison when creating 100 UI Elements and then serializing them to JSON. 7 | UiFramework_Async is 51.31x faster than CUI provided by oxide and 5.66x faster than Oxide AddUiAsync extension method UI Framework provides. 8 | The async option in the framework queues the UI to be serialized and sent on a separate thread while CUI from oxide is all ran on the main thread. 9 | UI Framework also doesn't have any memory allocations from the framework and pooling is used heavily for performance. 10 | 11 | | Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | 12 | |------------------ |-----------:|----------:|----------:|------:|--------:|--------:|-------:|----------:| 13 | | UiFramework_Async | 6.329 us | 0.0143 us | 0.0214 us | 1.00 | 0.00 | - | - | - | 14 | | Oxide_Async | 35.812 us | 0.2101 us | 0.3145 us | 5.66 | 0.05 | 2.9907 | 0.3052 | 51792 B | 15 | | Oxide_Full | 324.565 us | 1.8106 us | 2.4783 us | 51.31 | 0.33 | 11.7188 | 1.9531 | 204088 B | 16 | 17 | 18 | ## Getting Started 19 | 20 | ### Server Installation 21 | 1. Grab the Oxide.Ext.UiFramework.dll from the latest release 22 | 2. Put the DLL into `RustDedicated_Data\Managed` folder 23 | 3. Restart the server 24 | 25 | ### Developer Install 26 | 1. Grab the Oxide.Ext.UiFramework.dll from the latest release 27 | 2. Add the DLL to your project repo 28 | 29 | 30 | ## Plugin Examples 31 | 32 | ### Generic Example 33 | ```csharp 34 | private const string MainUi = "UI_Name"; 35 | private const int TitleFontSize = 20; 36 | 37 | private readonly UiPosition _titleBarPos = new(0, .95f, 1f, 1f); 38 | private readonly UiPosition _closeButtonPos = new(0.95f, 0f, 1f, 1f); 39 | 40 | private void CreateUi(BasePlayer player 41 | { 42 | UiBuilder builder = UiBuilder.Create(UiPosition.MiddleMiddle, new UiOffset(-420, -270, 420, 330), UiColors.Body, MainUi, UiLayer.Hud); 43 | 44 | builder.NeedsMouse(); 45 | builder.NeedsKeyboard(); 46 | 47 | UiLabelBackground title = builder.LabelBackground(builder.Root, _titleBarPos, Title, TitleFontSize, UiColors.Text, UiColors.BodyHeader); 48 | builder.TextButton(title.Background, _closeButtonPos, "X", TitleFontSize, UiColors.Text, UiColors.CloseButton, nameof(CloseCommand)); 49 | 50 | builder.AddUi(player); //By default the builder will auto destroy the previous UI if it exists on the client 51 | } 52 | 53 | 54 | [ConsoleCommand(nameof(CloseCommand))] 55 | private void CloseCommand(ConsoleSystem.Arg arg) 56 | { 57 | BasePlayer player = arg.Player(); 58 | if (player) 59 | { 60 | UiBuilder.DestroyUi(player, MainUi); 61 | } 62 | } 63 | ``` -------------------------------------------------------------------------------- /src/Rust.UIFramework.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rust.UIFramework", "Rust.UIFramework\Rust.UIFramework.csproj", "{2CEE08B1-A5BD-4F64-A1A9-5242440758D0}" 4 | EndProject 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rust.UiFramework.Benchmarks", "Rust.UiFramework.Benchmarks\Rust.UiFramework.Benchmarks.csproj", "{6C18B22C-7319-4C3F-B7F9-F9B87B6B244C}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Release|Oxide = Release|Oxide 10 | Release|Carbon = Release|Carbon 11 | Debug|Carbon = Debug|Carbon 12 | Debug|Oxide = Debug|Oxide 13 | Benchmarks|Oxide = Benchmarks|Oxide 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {2CEE08B1-A5BD-4F64-A1A9-5242440758D0}.Debug|Carbon.ActiveCfg = Debug|Carbon 17 | {2CEE08B1-A5BD-4F64-A1A9-5242440758D0}.Debug|Carbon.Build.0 = Debug|Carbon 18 | {2CEE08B1-A5BD-4F64-A1A9-5242440758D0}.Debug|Oxide.ActiveCfg = Debug|Oxide 19 | {2CEE08B1-A5BD-4F64-A1A9-5242440758D0}.Debug|Oxide.Build.0 = Debug|Oxide 20 | {2CEE08B1-A5BD-4F64-A1A9-5242440758D0}.Release|Carbon.ActiveCfg = Release|Carbon 21 | {2CEE08B1-A5BD-4F64-A1A9-5242440758D0}.Release|Carbon.Build.0 = Release|Carbon 22 | {2CEE08B1-A5BD-4F64-A1A9-5242440758D0}.Release|Oxide.ActiveCfg = Release|Oxide 23 | {2CEE08B1-A5BD-4F64-A1A9-5242440758D0}.Release|Oxide.Build.0 = Release|Oxide 24 | {2CEE08B1-A5BD-4F64-A1A9-5242440758D0}.Benchmarks|Oxide.ActiveCfg = Benchmarks|Oxide 25 | {2CEE08B1-A5BD-4F64-A1A9-5242440758D0}.Benchmarks|Oxide.Build.0 = Benchmarks|Oxide 26 | {6C18B22C-7319-4C3F-B7F9-F9B87B6B244C}.Release|Oxide.ActiveCfg = Release|Oxide 27 | {6C18B22C-7319-4C3F-B7F9-F9B87B6B244C}.Release|Oxide.Build.0 = Release|Oxide 28 | {6C18B22C-7319-4C3F-B7F9-F9B87B6B244C}.Benchmarks|Oxide.ActiveCfg = Benchmarks|Oxide 29 | {6C18B22C-7319-4C3F-B7F9-F9B87B6B244C}.Benchmarks|Oxide.Build.0 = Benchmarks|Oxide 30 | {6C18B22C-7319-4C3F-B7F9-F9B87B6B244C}.Debug|Oxide.ActiveCfg = Debug|Oxide 31 | {6C18B22C-7319-4C3F-B7F9-F9B87B6B244C}.Debug|Oxide.Build.0 = Debug|Oxide 32 | EndGlobalSection 33 | EndGlobal 34 | -------------------------------------------------------------------------------- /src/Rust.UIFramework/Benchmarks/BenchmarkNetWrite.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Facepunch; 4 | using Network; 5 | using UnityEngine; 6 | 7 | 8 | namespace Oxide.Ext.UiFramework.Benchmarks; 9 | #if BENCHMARKS 10 | internal class BenchmarkNetWrite : Stream, Pool.IPooled 11 | { 12 | public byte[] Data; 13 | private int _position; 14 | private int _length; 15 | 16 | public override void Flush() 17 | { 18 | 19 | } 20 | 21 | public override long Seek(long offset, SeekOrigin origin) 22 | { 23 | int num; 24 | switch (origin) 25 | { 26 | case SeekOrigin.Current: 27 | num = _position + (int) offset; 28 | break; 29 | case SeekOrigin.End: 30 | num = _length + (int) offset; 31 | break; 32 | default: 33 | num = (int) offset; 34 | break; 35 | } 36 | _position = num >= 0 && num <= _length ? num : throw new ArgumentOutOfRangeException(nameof (offset)); 37 | return _position; 38 | } 39 | 40 | public override void SetLength(long value) 41 | { 42 | throw new NotImplementedException(); 43 | } 44 | 45 | public override int Read(byte[] buffer, int offset, int count) 46 | { 47 | int max = _length - _position; 48 | int num = Mathf.Clamp(count, 0, max); 49 | Buffer.BlockCopy(Data, _position, buffer, offset, count); 50 | _position += num; 51 | return num; 52 | } 53 | 54 | public override void Write(byte[] buffer, int offset, int count) 55 | { 56 | EnsureCapacity(count); 57 | Buffer.BlockCopy(buffer, offset, Data, _position, count); 58 | _position += count; 59 | if (_position <= _length) 60 | return; 61 | _length = _position; 62 | } 63 | 64 | public override bool CanRead => true; 65 | public override bool CanSeek => true; 66 | public override bool CanWrite => true; 67 | public override long Length => _length; 68 | public override long Position 69 | { 70 | get => _position; 71 | set => Seek(value, SeekOrigin.Begin); 72 | } 73 | 74 | public void EnterPool() 75 | { 76 | if (Data == null) 77 | return; 78 | BaseNetwork.ArrayPool.Return(Data); 79 | Data = null; 80 | } 81 | 82 | public void LeavePool() 83 | { 84 | _position = 0; 85 | _length = 0; 86 | } 87 | 88 | private void EnsureCapacity(int spaceRequired) 89 | { 90 | if (Data == null) 91 | { 92 | int num = spaceRequired <= 2048 ? 2048 : spaceRequired; 93 | int minSize = NextPowerOfTwo(num); 94 | Data = minSize <= 4194304 ? BaseNetwork.ArrayPool.Rent(minSize) : throw new Exception(string.Format("Preventing NetWrite buffer from growing too large (requiredLength={0})", num)); 95 | } 96 | else 97 | { 98 | if (Data.Length - _position >= spaceRequired) 99 | return; 100 | int val1 = _position + spaceRequired; 101 | int minSize = NextPowerOfTwo(Math.Max(val1, Data.Length)); 102 | byte[] dst = minSize <= 4194304 ? BaseNetwork.ArrayPool.Rent(minSize) : throw new Exception(string.Format("Preventing NetWrite buffer from growing too large (requiredLength={0})", val1)); 103 | Buffer.BlockCopy(Data, 0, dst, 0, _length); 104 | BaseNetwork.ArrayPool.Return(Data); 105 | Data = dst; 106 | } 107 | } 108 | 109 | private int NextPowerOfTwo(int value) 110 | { 111 | value -= 1; 112 | value |= value >> 16; 113 | value |= value >> 16; 114 | value |= value >> 8; 115 | value |= value >> 4; 116 | value |= value >> 2; 117 | value |= value >> 1; 118 | return value + 1; 119 | } 120 | } 121 | #endif -------------------------------------------------------------------------------- /src/Rust.UIFramework/Builder/BaseUiBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Network; 3 | using Oxide.Ext.UiFramework.Cache; 4 | using Oxide.Ext.UiFramework.Controls; 5 | using Oxide.Ext.UiFramework.Enums; 6 | using Oxide.Ext.UiFramework.Json; 7 | using Oxide.Ext.UiFramework.UiElements; 8 | 9 | namespace Oxide.Ext.UiFramework.Builder; 10 | 11 | public abstract partial class BaseUiBuilder : BaseBuilder 12 | { 13 | protected readonly List Components = new(); 14 | protected readonly List Controls = new(); 15 | protected readonly List Anchors = new(); 16 | 17 | protected string Font; 18 | protected static string GlobalFont; 19 | 20 | static BaseUiBuilder() 21 | { 22 | SetGlobalFont(UiFont.RobotoCondensedRegular); 23 | } 24 | 25 | public void EnsureCapacity(int capacity) 26 | { 27 | if (Components.Capacity < capacity) 28 | { 29 | Components.Capacity = capacity; 30 | } 31 | } 32 | 33 | public void SetCurrentFont(UiFont font) 34 | { 35 | Font = UiFontCache.GetUiFont(font); 36 | } 37 | 38 | public static void SetGlobalFont(UiFont font) 39 | { 40 | GlobalFont = UiFontCache.GetUiFont(font); 41 | } 42 | 43 | public override byte[] GetBytes() 44 | { 45 | JsonFrameworkWriter writer = CreateWriter(); 46 | byte[] bytes = writer.ToArray(); 47 | writer.Dispose(); 48 | return bytes; 49 | } 50 | 51 | internal override void SendUi(SendInfo send) 52 | { 53 | JsonFrameworkWriter writer = CreateWriter(); 54 | AddUi(send, writer); 55 | writer.Dispose(); 56 | } 57 | 58 | public JsonFrameworkWriter CreateWriter() 59 | { 60 | int count = Controls.Count; 61 | if (count != 0) 62 | { 63 | for (int index = 0; index < count; index++) 64 | { 65 | BaseUiControl control = Controls[index]; 66 | control.RenderControl(this); 67 | } 68 | } 69 | 70 | JsonFrameworkWriter writer = JsonFrameworkWriter.Create(); 71 | writer.WriteStartArray(); 72 | WriteComponentsInternal(writer); 73 | writer.WriteEndArray(); 74 | return writer; 75 | } 76 | 77 | protected abstract void WriteComponentsInternal(JsonFrameworkWriter writer); 78 | 79 | protected override void EnterPool() 80 | { 81 | base.EnterPool(); 82 | FreeComponents(); 83 | Font = null; 84 | } 85 | 86 | private void FreeComponents() 87 | { 88 | int count = Components.Count; 89 | for (int index = 0; index < count; index++) 90 | { 91 | Components[index].Dispose(); 92 | } 93 | 94 | Components.Clear(); 95 | 96 | count = Controls.Count; 97 | for (int index = 0; index < count; index++) 98 | { 99 | Controls[index].Dispose(); 100 | } 101 | 102 | Controls.Clear(); 103 | 104 | count = Anchors.Count; 105 | for (int index = 0; index < count; index++) 106 | { 107 | Anchors[index].Dispose(); 108 | } 109 | 110 | Anchors.Clear(); 111 | } 112 | 113 | protected override void LeavePool() 114 | { 115 | base.LeavePool(); 116 | Font = GlobalFont; 117 | } 118 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Builder/Cached/CachedUiBuilder.cs: -------------------------------------------------------------------------------- 1 | using Network; 2 | using Oxide.Ext.UiFramework.Builder.UI; 3 | 4 | namespace Oxide.Ext.UiFramework.Builder.Cached; 5 | 6 | public class CachedUiBuilder : BaseBuilder 7 | { 8 | private readonly byte[] _cachedJson; 9 | 10 | private CachedUiBuilder(UiBuilder builder) 11 | { 12 | _cachedJson = builder.GetBytes(); 13 | RootName = builder.GetRootName(); 14 | } 15 | 16 | internal static CachedUiBuilder CreateCachedBuilder(UiBuilder builder) => new(builder); 17 | 18 | public override byte[] GetBytes() => _cachedJson; 19 | 20 | internal override void SendUi(SendInfo send) 21 | { 22 | AddUi(send, GetBytes()); 23 | } 24 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Builder/UI/UiBuilder.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Builder.Cached; 2 | using Oxide.Ext.UiFramework.Cache; 3 | using Oxide.Ext.UiFramework.Exceptions; 4 | using Oxide.Ext.UiFramework.Json; 5 | using Oxide.Ext.UiFramework.UiElements; 6 | 7 | namespace Oxide.Ext.UiFramework.Builder.UI; 8 | 9 | public partial class UiBuilder : BaseUiBuilder 10 | { 11 | public BaseUiComponent Root; 12 | 13 | private bool _needsMouse; 14 | private bool _needsKeyboard; 15 | private bool _autoDestroy = true; 16 | 17 | #region Decontructor 18 | ~UiBuilder() 19 | { 20 | Dispose(); 21 | //Need this because there is a global GC class that causes issues 22 | //ReSharper disable once RedundantNameQualifier 23 | System.GC.SuppressFinalize(this); 24 | } 25 | #endregion 26 | 27 | #region Setup 28 | public void SetRoot(BaseUiComponent component, string name, string parent) 29 | { 30 | Root = component; 31 | component.Reference = new UiReference(parent, name); 32 | Components.Add(component); 33 | RootName = name; 34 | } 35 | 36 | public void OverrideRoot(BaseUiComponent component) 37 | { 38 | Root = component; 39 | } 40 | 41 | public void NeedsMouse(bool enabled = true) 42 | { 43 | _needsMouse = enabled; 44 | } 45 | 46 | public void NeedsKeyboard(bool enabled = true) 47 | { 48 | _needsKeyboard = enabled; 49 | } 50 | 51 | public void EnableAutoDestroy(bool enabled = true) 52 | { 53 | _autoDestroy = enabled; 54 | } 55 | #endregion 56 | 57 | #region JSON 58 | public int WriteBuffer(byte[] buffer) 59 | { 60 | JsonFrameworkWriter writer = CreateWriter(); 61 | int bytes = writer.WriteTo(buffer); 62 | writer.Dispose(); 63 | return bytes; 64 | } 65 | 66 | public CachedUiBuilder ToCachedBuilder(bool dispose = true) 67 | { 68 | CachedUiBuilder cached = CachedUiBuilder.CreateCachedBuilder(this); 69 | if (dispose && !Disposed) 70 | { 71 | Dispose(); 72 | } 73 | return cached; 74 | } 75 | #endregion 76 | 77 | #region Add Components 78 | public override void AddComponent(BaseUiComponent component, in UiReference parent) 79 | { 80 | UiReferenceException.ThrowIfInvalidParent(parent); 81 | component.Reference = parent.WithChild(UiNameCache.GetComponentName(RootName, Components.Count)); 82 | Components.Add(component); 83 | } 84 | 85 | protected override void AddAnchor(BaseUiComponent component, in UiReference parent) 86 | { 87 | UiReferenceException.ThrowIfInvalidParent(parent); 88 | component.Reference = parent.WithChild(UiNameCache.GetAnchorName(RootName, Anchors.Count)); 89 | Anchors.Add(component); 90 | } 91 | #endregion 92 | 93 | protected override void WriteComponentsInternal(JsonFrameworkWriter writer) 94 | { 95 | Components[0].WriteRootComponent(writer, _needsMouse, _needsKeyboard, _autoDestroy); 96 | 97 | int count = Components.Count; 98 | for (int index = 1; index < count; index++) 99 | { 100 | Components[index].WriteComponent(writer); 101 | } 102 | 103 | count = Anchors.Count; 104 | for (int index = 0; index < count; index++) 105 | { 106 | Anchors[index].WriteComponent(writer); 107 | } 108 | } 109 | 110 | protected override void EnterPool() 111 | { 112 | base.EnterPool(); 113 | Root = null; 114 | _needsKeyboard = false; 115 | _needsMouse = false; 116 | _autoDestroy = true; 117 | } 118 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Builder/Update/UpdateBuilder.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Exceptions; 2 | using Oxide.Ext.UiFramework.Json; 3 | using Oxide.Ext.UiFramework.Pooling; 4 | using Oxide.Ext.UiFramework.UiElements; 5 | 6 | namespace Oxide.Ext.UiFramework.Builder.Update; 7 | 8 | public class UpdateBuilder : BaseUiBuilder 9 | { 10 | public static UpdateBuilder Create() => UiFrameworkPool.Get(); 11 | 12 | protected override void WriteComponentsInternal(JsonFrameworkWriter writer) 13 | { 14 | int count = Components.Count; 15 | for (int index = 0; index < count; index++) 16 | { 17 | Components[index].WriteUpdateComponent(writer); 18 | } 19 | 20 | count = Anchors.Count; 21 | if (count != 0) 22 | { 23 | for (int index = 0; index < count; index++) 24 | { 25 | Anchors[index].WriteUpdateComponent(writer); 26 | } 27 | } 28 | } 29 | 30 | #region Add Components 31 | public override void AddComponent(BaseUiComponent component, in UiReference parent) 32 | { 33 | UiReferenceException.ThrowIfInvalidReference(parent); 34 | component.Reference = parent; 35 | Components.Add(component); 36 | } 37 | 38 | protected override void AddAnchor(BaseUiComponent component, in UiReference parent) 39 | { 40 | UiReferenceException.ThrowIfInvalidReference(parent); 41 | component.Reference = parent; 42 | Anchors.Add(component); 43 | } 44 | #endregion 45 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Builders/SendInfoBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | using Network; 5 | using Oxide.Ext.UiFramework.Pooling; 6 | 7 | namespace Oxide.Ext.UiFramework.Builders; 8 | 9 | internal static class SendInfoBuilder 10 | { 11 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 12 | internal static SendInfo Get(BasePlayer player) 13 | { 14 | if (!player) throw new ArgumentNullException(nameof(player)); 15 | return Get(player.Connection); 16 | } 17 | 18 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 19 | internal static SendInfo Get(Connection connection) 20 | { 21 | if (connection == null) throw new ArgumentNullException(nameof(connection)); 22 | return new SendInfo(connection); 23 | } 24 | 25 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 26 | internal static SendInfo Get(IEnumerable connections) 27 | { 28 | if (connections == null) throw new ArgumentNullException(nameof(connections)); 29 | List pooledConnection = ListPool.Instance.Get(); 30 | pooledConnection.AddRange(connections); 31 | return new SendInfo(pooledConnection); 32 | } 33 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Cache/EnumCache{T}.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Linq; 4 | 5 | namespace Oxide.Ext.UiFramework.Cache; 6 | 7 | public static class EnumCache 8 | { 9 | private static readonly ConcurrentDictionary CachedStrings = new(); 10 | 11 | static EnumCache() 12 | { 13 | foreach (T value in Enum.GetValues(typeof(T)).Cast()) 14 | { 15 | CachedStrings[value] = value.ToString(); 16 | } 17 | } 18 | 19 | public static string ToString(T value) 20 | { 21 | return CachedStrings[value]; 22 | } 23 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Cache/StringCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Globalization; 4 | 5 | namespace Oxide.Ext.UiFramework.Cache; 6 | 7 | public static class StringCache where T : IFormattable 8 | { 9 | private static readonly ConcurrentDictionary Cache = new(); 10 | private static readonly ConcurrentDictionary> FormatCache = new(); 11 | 12 | public static string ToString(T value) 13 | { 14 | if (!Cache.TryGetValue(value, out string text)) 15 | { 16 | text = value.ToString(); 17 | Cache[value] = text; 18 | } 19 | 20 | return text; 21 | } 22 | 23 | public static string ToString(T value, string format) 24 | { 25 | if (!FormatCache.TryGetValue(format, out ConcurrentDictionary values)) 26 | { 27 | values = new ConcurrentDictionary(); 28 | FormatCache[format] = values; 29 | } 30 | 31 | if (!values.TryGetValue(value, out string text)) 32 | { 33 | text = value.ToString(format, NumberFormatInfo.CurrentInfo); 34 | values[value] = text; 35 | } 36 | 37 | return text; 38 | } 39 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Cache/UiColorCache.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | using System.Text; 3 | using Oxide.Ext.UiFramework.Colors; 4 | using Oxide.Ext.UiFramework.Extensions; 5 | using Oxide.Ext.UiFramework.Json; 6 | using Oxide.Ext.UiFramework.Pooling; 7 | using UnityEngine; 8 | 9 | namespace Oxide.Ext.UiFramework.Cache; 10 | 11 | public static class UiColorCache 12 | { 13 | private const string Format = "0.####"; 14 | private const char Space = ' '; 15 | 16 | private static readonly ConcurrentDictionary ColorCache = new(); 17 | 18 | public static void WriteColor(JsonBinaryWriter writer, UiColor uiColor) 19 | { 20 | int hashCode = uiColor.GetHashCode(); 21 | if (!ColorCache.TryGetValue(hashCode, out string color)) 22 | { 23 | color = GetColor(uiColor); 24 | ColorCache[hashCode] = color; 25 | } 26 | 27 | writer.Write(color); 28 | } 29 | 30 | private static string GetColor(Color color) 31 | { 32 | StringBuilder builder = UiFrameworkPool.GetStringBuilder(); 33 | builder.Append(StringCache.ToString(color.r, Format)); 34 | builder.Append(Space); 35 | builder.Append(StringCache.ToString(color.g, Format)); 36 | builder.Append(Space); 37 | builder.Append(StringCache.ToString(color.b, Format)); 38 | if (color.a < 1f) 39 | { 40 | builder.Append(Space); 41 | builder.Append(StringCache.ToString(color.a, Format)); 42 | } 43 | 44 | return builder.ToStringAndFree(); 45 | } 46 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Cache/UiFontCache.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Oxide.Ext.UiFramework.Enums; 3 | 4 | namespace Oxide.Ext.UiFramework.Cache; 5 | 6 | public static class UiFontCache 7 | { 8 | private const string DroidSansMono = "droidsansmono.ttf"; 9 | private const string PermanentMarker = "permanentmarker.ttf"; 10 | private const string RobotoCondensedBold = "robotocondensed-bold.ttf"; 11 | private const string RobotoCondensedRegular = "robotocondensed-regular.ttf"; 12 | private const string PressStart2PRegular = "PressStart2P-Regular.ttf"; 13 | 14 | private static readonly IReadOnlyDictionary Fonts = new Dictionary 15 | { 16 | [UiFont.DroidSansMono] = DroidSansMono, 17 | [UiFont.PermanentMarker] = PermanentMarker, 18 | [UiFont.RobotoCondensedBold] = RobotoCondensedBold, 19 | [UiFont.RobotoCondensedRegular] = RobotoCondensedRegular, 20 | [UiFont.PressStart2PRegular] = PressStart2PRegular 21 | }; 22 | 23 | public static string GetUiFont(UiFont font) 24 | { 25 | return Fonts[font]; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Cache/UiLayerCache.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | using Oxide.Ext.UiFramework.Enums; 3 | 4 | namespace Oxide.Ext.UiFramework.Cache; 5 | 6 | public static class UiLayerCache 7 | { 8 | private const string Overall = "Overall"; 9 | private const string OverlayNonScaled = "OverlayNonScaled"; 10 | private const string Overlay = "Overlay"; 11 | private const string Hud = "Hud"; 12 | private const string HudMenu = "Hud.Menu"; 13 | private const string Under = "Under"; 14 | private const string UnderNonScaled = "UnderNonScaled"; 15 | private const string Inventory = "Inventory"; 16 | private const string Crafting = "Crafting"; 17 | private const string Contacts = "Contacts"; 18 | private const string Clans = "Clans"; 19 | private const string TechTree = "TechTree"; 20 | private const string Map = "Map"; 21 | 22 | private static readonly ConcurrentDictionary Layers = new() 23 | { 24 | [UiLayer.Overall] = Overall, 25 | [UiLayer.Overlay] = Overlay, 26 | [UiLayer.OverlayNonScaled] = OverlayNonScaled, 27 | [UiLayer.Hud] = Hud, 28 | [UiLayer.HudMenu] = HudMenu, 29 | [UiLayer.Under] = Under, 30 | [UiLayer.UnderNonScaled] = UnderNonScaled, 31 | [UiLayer.Inventory] = Inventory, 32 | [UiLayer.Crafting] = Crafting, 33 | [UiLayer.Contacts] = Contacts, 34 | [UiLayer.Clans] = Clans, 35 | [UiLayer.TechTree] = TechTree, 36 | [UiLayer.Map] = Map, 37 | }; 38 | 39 | public static string GetLayer(UiLayer layer) 40 | { 41 | return Layers[layer]; 42 | } 43 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Cache/UiNameCache.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Oxide.Ext.UiFramework.Cache; 4 | 5 | public static class UiNameCache 6 | { 7 | private static readonly Dictionary> ComponentNameCache = new(); 8 | private static readonly Dictionary> AnchorNameCache = new(); 9 | 10 | public static string GetComponentName(string baseName, int index) => GetName(ComponentNameCache, baseName, "_", index); 11 | public static string GetAnchorName(string baseName, int index) => GetName(AnchorNameCache, baseName, "_anchor_", index); 12 | 13 | private static string GetName(Dictionary> cache, string baseName, string splitter, int index) 14 | { 15 | if (!cache.TryGetValue(baseName, out List names)) 16 | { 17 | names = []; 18 | cache[baseName] = names; 19 | } 20 | 21 | if (index >= names.Count) 22 | { 23 | for (int i = names.Count; i <= index; i++) 24 | { 25 | names.Add(string.Concat(baseName, splitter, index.ToString())); 26 | } 27 | } 28 | 29 | return names[index]; 30 | } 31 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Cache/VectorCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using Oxide.Ext.UiFramework.Json; 4 | using UnityEngine; 5 | 6 | namespace Oxide.Ext.UiFramework.Cache; 7 | 8 | public static class VectorCache 9 | { 10 | private const string Format = "0.####"; 11 | private const char Space = ' '; 12 | private const short PositionRounder = 10000; 13 | 14 | private static readonly ConcurrentDictionary PositionCache = new(); 15 | 16 | public static void WritePosition(JsonBinaryWriter writer, Vector2 pos) 17 | { 18 | WriteFromCache(writer, pos.x); 19 | writer.Write(Space); 20 | WriteFromCache(writer, pos.y); 21 | } 22 | 23 | private static void WriteFromCache(JsonBinaryWriter writer, float pos) 24 | { 25 | string value; 26 | if (!PositionCache.TryGetValue((short)(pos * PositionRounder), out value)) 27 | { 28 | value = pos.ToString(Format); 29 | PositionCache[(short)(pos * PositionRounder)] = value; 30 | } 31 | 32 | writer.Write(value); 33 | } 34 | 35 | public static void WriteVector(JsonBinaryWriter writer, Vector2 pos) 36 | { 37 | string formattedPos; 38 | if (!PositionCache.TryGetValue((short)(pos.x * PositionRounder), out formattedPos)) 39 | { 40 | formattedPos = pos.x.ToString(Format); 41 | PositionCache[(short)(pos.x * PositionRounder)] = formattedPos; 42 | } 43 | 44 | writer.Write(formattedPos); 45 | writer.Write(Space); 46 | 47 | if (!PositionCache.TryGetValue((short)(pos.y * PositionRounder), out formattedPos)) 48 | { 49 | formattedPos = pos.y.ToString(Format); 50 | PositionCache[(short)(pos.y * PositionRounder)] = formattedPos; 51 | } 52 | 53 | writer.Write(formattedPos); 54 | } 55 | 56 | public static void WriteOffset(JsonBinaryWriter writer, Vector2 pos) 57 | { 58 | writer.Write(StringCache.ToString((short)Math.Round(pos.x))); 59 | writer.Write(Space); 60 | writer.Write(StringCache.ToString((short)Math.Round(pos.y))); 61 | } 62 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Colors/UiColorConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | 4 | namespace Oxide.Ext.UiFramework.Colors; 5 | 6 | public class UiColorConverter : JsonConverter 7 | { 8 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 9 | { 10 | writer.WriteValue(((UiColor)value).ToHtmlColor()); 11 | } 12 | 13 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 14 | { 15 | switch (reader.TokenType) 16 | { 17 | case JsonToken.Null: 18 | if (Nullable.GetUnderlyingType(objectType) != null) 19 | { 20 | return null; 21 | } 22 | 23 | return default(UiColor); 24 | 25 | case JsonToken.String: 26 | return UiColor.ParseHexColor(reader.Value.ToString()); 27 | } 28 | 29 | return default(UiColor); 30 | } 31 | 32 | public override bool CanConvert(Type objectType) 33 | { 34 | return objectType == typeof(UiColor); 35 | } 36 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Colors/UiColors.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Extensions; 2 | 3 | namespace Oxide.Ext.UiFramework.Colors; 4 | 5 | public static class UiColors 6 | { 7 | public static class BootStrap 8 | { 9 | public static readonly UiColor Blue = "#007bff"; 10 | public static readonly UiColor Indigo = "#6610f2"; 11 | public static readonly UiColor Purple = "#6f42c1"; 12 | public static readonly UiColor Pink = "#e83e8c"; 13 | public static readonly UiColor Red = "#dc3545"; 14 | public static readonly UiColor Orange = "#fd7e14"; 15 | public static readonly UiColor Yellow = "#ffc107"; 16 | public static readonly UiColor Green = "#28a745"; 17 | public static readonly UiColor Teal = "#20c997"; 18 | public static readonly UiColor Cyan = "#17a2b8"; 19 | public static readonly UiColor White = "#fff"; 20 | public static readonly UiColor Gray = "#6c757d"; 21 | public static readonly UiColor DarkGray = "#343a40"; 22 | public static readonly UiColor Primary = "#007bff"; 23 | public static readonly UiColor Secondary = "#6c757d"; 24 | public static readonly UiColor Success = "#28a745"; 25 | public static readonly UiColor Info = "#17a2b8"; 26 | public static readonly UiColor Warning = "#ffc107"; 27 | public static readonly UiColor Danger = "#dc3545"; 28 | public static readonly UiColor Light = "#f8f9fa"; 29 | public static readonly UiColor Dark = "#343a40"; 30 | } 31 | 32 | public static class Material 33 | { 34 | public static readonly UiColor MatPrimary = "#dfe6e9"; 35 | public static readonly UiColor MatPrimaryLight = "#b2bec3"; 36 | public static readonly UiColor MatPrimaryDark = "#636e72"; 37 | public static readonly UiColor MatSecondary = "#2d3436"; 38 | public static readonly UiColor MatSecondaryLight = "#74b9ff"; 39 | public static readonly UiColor MatSecondaryDark = "#0984e3"; 40 | public static readonly UiColor MatTextOnPrimary = "#0984e3"; 41 | public static readonly UiColor MatTextOnSecondary = "#0984e3"; 42 | } 43 | 44 | public static class Supreme 45 | { 46 | public static readonly UiColor Lime = "#acfa58"; 47 | public static readonly UiColor SilverText = "#e3e3e3"; 48 | public static readonly UiColor K1lly0usRed = "#ce422b"; 49 | } 50 | 51 | public static class MJSU 52 | { 53 | public static readonly UiColor Orange = "#de8732"; 54 | } 55 | 56 | public static class Rust 57 | { 58 | public static readonly UiColor Red = "#cd4632"; 59 | public static readonly UiColor Green = "#8cc83c"; 60 | public static readonly UiColor Panel = "#CCCCCC"; 61 | 62 | public static class Ui 63 | { 64 | public static readonly UiColor Panel = "#A6A6A60F"; 65 | public static readonly UiColor Header = "#DBDBDB33"; 66 | public static readonly UiColor PanelButton = "#A6A6A60F"; 67 | public static readonly UiColor OkButton = "#6A804266"; 68 | public static readonly UiColor Button = "#BFBFBF1A"; 69 | public static readonly UiColor PanelText = "#E8dED4"; 70 | public static readonly UiColor PanelButtonText = "#C4C4C4"; 71 | public static readonly UiColor OkButtonText = "#9BB46E"; 72 | public static readonly UiColor ButtonText = "#E8DED4CC"; 73 | } 74 | 75 | public static class Chat 76 | { 77 | public static readonly UiColor Player = "#55AAFF"; 78 | public static readonly UiColor Developer = "#FFAA55"; 79 | public static readonly UiColor Admin = "#AAFF55"; 80 | } 81 | 82 | public static class Steam 83 | { 84 | public static readonly UiColor InGame = "#A2DB40"; 85 | public static readonly UiColor Online = "#60CBF2"; 86 | public static readonly UiColor Normal = "#F7EBE1"; 87 | } 88 | } 89 | 90 | public static class Form 91 | { 92 | public static readonly UiColor Body = "#00001F"; 93 | public static readonly UiColor Header = "#00001F"; 94 | public static readonly UiColor Text = UiColor.White; 95 | public static readonly UiColor Panel = "#2B2B2B"; 96 | public static readonly UiColor PanelSecondary = "#3f3f3f"; 97 | public static readonly UiColor PanelTertiary = "#525252"; 98 | public static readonly UiColor ButtonPrimary = Rust.Red; 99 | public static readonly UiColor ButtonSecondary = "#666666"; 100 | } 101 | 102 | #region UI Colors 103 | public static readonly UiColor Body = Form.Body.WithAlpha("B2"); 104 | public static readonly UiColor BodyHeader = Form.Header; 105 | public static readonly UiColor Text = Form.Text.WithAlpha("80"); 106 | public static readonly UiColor Panel = Form.Panel; 107 | public static readonly UiColor PanelSecondary = Form.PanelSecondary; 108 | public static readonly UiColor PanelTertiary = Form.PanelTertiary; 109 | public static readonly UiColor CloseButton = Form.ButtonPrimary; 110 | public static readonly UiColor ButtonPrimary = Form.ButtonPrimary; 111 | public static readonly UiColor ButtonSecondary = Form.ButtonSecondary; 112 | #endregion 113 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/BaseComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Json; 2 | 3 | namespace Oxide.Ext.UiFramework.Components; 4 | 5 | public abstract class BaseComponent : IComponent 6 | { 7 | public bool Enabled = true; 8 | 9 | public virtual void WriteComponent(JsonFrameworkWriter writer) 10 | { 11 | writer.AddField(JsonDefaults.Common.EnabledName, Enabled, true); 12 | } 13 | 14 | public virtual void Reset() 15 | { 16 | Enabled = true; 17 | } 18 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/BaseImageComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Json; 3 | 4 | namespace Oxide.Ext.UiFramework.Components; 5 | 6 | public abstract class BaseImageComponent : BaseComponent 7 | { 8 | public UiColor Color; 9 | public float FadeIn; 10 | public string Sprite; 11 | public string Material; 12 | 13 | public override void WriteComponent(JsonFrameworkWriter writer) 14 | { 15 | writer.AddField(JsonDefaults.BaseImage.SpriteName, Sprite, JsonDefaults.BaseImage.Sprite); 16 | writer.AddField(JsonDefaults.BaseImage.MaterialName, Material, JsonDefaults.BaseImage.Material); 17 | writer.AddField(JsonDefaults.Common.FadeInName, FadeIn, JsonDefaults.Common.FadeIn); 18 | writer.AddField(JsonDefaults.Color.ColorName, Color); 19 | base.WriteComponent(writer); 20 | } 21 | 22 | public override void Reset() 23 | { 24 | base.Reset(); 25 | Color = default; 26 | FadeIn = 0; 27 | Sprite = null; 28 | Material = null; 29 | } 30 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/BasePoolableComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Json; 2 | using Oxide.Ext.UiFramework.Pooling; 3 | 4 | namespace Oxide.Ext.UiFramework.Components; 5 | 6 | public abstract class BasePoolableComponent : BasePoolable, IComponent 7 | { 8 | public bool Enabled = true; 9 | 10 | public virtual void WriteComponent(JsonFrameworkWriter writer) 11 | { 12 | writer.AddField(JsonDefaults.Common.EnabledName, Enabled, true); 13 | } 14 | 15 | protected override void EnterPool() 16 | { 17 | Reset(); 18 | } 19 | 20 | public virtual void Reset() 21 | { 22 | Enabled = true; 23 | } 24 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/BaseTextComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Json; 3 | using UnityEngine; 4 | 5 | namespace Oxide.Ext.UiFramework.Components; 6 | 7 | public abstract class BaseTextComponent : BaseComponent 8 | { 9 | public UiColor Color; 10 | public float FadeIn; 11 | public int FontSize = JsonDefaults.BaseText.FontSize; 12 | public string Font; 13 | public TextAnchor Align; 14 | public string Text; 15 | public VerticalWrapMode VerticalOverflow; 16 | 17 | public override void WriteComponent(JsonFrameworkWriter writer) 18 | { 19 | writer.AddTextField(JsonDefaults.BaseText.TextName, Text); 20 | writer.AddField(JsonDefaults.BaseText.FontSizeName, FontSize, JsonDefaults.BaseText.FontSize); 21 | writer.AddField(JsonDefaults.BaseText.FontName, Font, JsonDefaults.BaseText.FontValue); 22 | writer.AddField(JsonDefaults.BaseText.AlignName, Align); 23 | writer.AddField(JsonDefaults.BaseText.VerticalOverflowName, VerticalOverflow); 24 | writer.AddField(JsonDefaults.Common.FadeInName, FadeIn, JsonDefaults.Common.FadeIn); 25 | writer.AddField(JsonDefaults.Color.ColorName, Color); 26 | base.WriteComponent(writer); 27 | } 28 | 29 | public override void Reset() 30 | { 31 | base.Reset(); 32 | Color = default; 33 | FadeIn = 0; 34 | FontSize = JsonDefaults.BaseText.FontSize; 35 | Font = null; 36 | Align = TextAnchor.UpperLeft; 37 | Text = null; 38 | VerticalOverflow = VerticalWrapMode.Truncate; 39 | } 40 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/ButtonComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Json; 2 | using UnityEngine.UI; 3 | 4 | namespace Oxide.Ext.UiFramework.Components; 5 | 6 | public class ButtonComponent : BaseImageComponent 7 | { 8 | private const string Type = "UnityEngine.UI.Button"; 9 | 10 | public string Command; 11 | public string Close; 12 | public Image.Type ImageType; 13 | 14 | public override void WriteComponent(JsonFrameworkWriter writer) 15 | { 16 | writer.WriteStartObject(); 17 | writer.AddFieldRaw(JsonDefaults.Common.ComponentTypeName, Type); 18 | writer.AddField(JsonDefaults.Common.CommandName, Command, JsonDefaults.Common.NullValue); 19 | writer.AddField(JsonDefaults.Button.CloseName, Close, JsonDefaults.Common.NullValue); 20 | writer.AddField(JsonDefaults.Image.ImageType, ImageType); 21 | base.WriteComponent(writer); 22 | writer.WriteEndObject(); 23 | } 24 | 25 | public override void Reset() 26 | { 27 | base.Reset(); 28 | Command = null; 29 | Close = null; 30 | ImageType = Image.Type.Simple; 31 | } 32 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/CountdownComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Enums; 2 | using Oxide.Ext.UiFramework.Json; 3 | using Oxide.Ext.UiFramework.Pooling; 4 | 5 | namespace Oxide.Ext.UiFramework.Components; 6 | 7 | public class CountdownComponent : BasePoolable, IComponent 8 | { 9 | private const string Type = "Countdown"; 10 | 11 | public float StartTime; 12 | public float EndTime; 13 | public float Step; 14 | public float Interval; 15 | public TimerFormat TimerFormat; 16 | public string NumberFormat; 17 | public bool DestroyIfDone = true; 18 | public string Command; 19 | 20 | public virtual void WriteComponent(JsonFrameworkWriter writer) 21 | { 22 | writer.WriteStartObject(); 23 | writer.AddFieldRaw(JsonDefaults.Common.ComponentTypeName, Type); 24 | writer.AddField(JsonDefaults.Countdown.StartTimeName, StartTime, JsonDefaults.Countdown.StartTimeValue); 25 | writer.AddField(JsonDefaults.Countdown.EndTimeName, EndTime, JsonDefaults.Countdown.EndTimeValue); 26 | writer.AddField(JsonDefaults.Countdown.StepName, Step, JsonDefaults.Countdown.StepValue); 27 | writer.AddField(JsonDefaults.Countdown.IntervalName, Interval, JsonDefaults.Countdown.IntervalValue); 28 | writer.AddField(JsonDefaults.Countdown.TimerFormatName, TimerFormat); 29 | writer.AddField(JsonDefaults.Countdown.NumberFormatName, NumberFormat, JsonDefaults.Countdown.NumberFormatValue); 30 | writer.AddField(JsonDefaults.Countdown.DestroyIfDoneName, DestroyIfDone, true); 31 | writer.AddField(JsonDefaults.Countdown.CountdownCommandName, Command, JsonDefaults.Common.NullValue); 32 | writer.WriteEndObject(); 33 | } 34 | 35 | public virtual void Reset() 36 | { 37 | StartTime = JsonDefaults.Countdown.StartTimeValue; 38 | EndTime = JsonDefaults.Countdown.EndTimeValue; 39 | Step = JsonDefaults.Countdown.StepValue; 40 | Interval = JsonDefaults.Countdown.IntervalValue; 41 | TimerFormat = TimerFormat.None; 42 | NumberFormat = JsonDefaults.Countdown.NumberFormatValue; 43 | DestroyIfDone = true; 44 | Command = null; 45 | } 46 | 47 | protected override void EnterPool() 48 | { 49 | Reset(); 50 | } 51 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/IComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Json; 2 | 3 | namespace Oxide.Ext.UiFramework.Components; 4 | 5 | public interface IComponent 6 | { 7 | void WriteComponent(JsonFrameworkWriter writer); 8 | void Reset(); 9 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/ImageComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Json; 2 | using UnityEngine.UI; 3 | 4 | namespace Oxide.Ext.UiFramework.Components; 5 | 6 | public class ImageComponent : BaseImageComponent 7 | { 8 | private const string Type = "UnityEngine.UI.Image"; 9 | 10 | public string Png; 11 | public Image.Type ImageType; 12 | 13 | public override void WriteComponent(JsonFrameworkWriter writer) 14 | { 15 | writer.WriteStartObject(); 16 | writer.AddFieldRaw(JsonDefaults.Common.ComponentTypeName, Type); 17 | writer.AddField(JsonDefaults.Image.PngName, Png, JsonDefaults.Common.NullValue); 18 | writer.AddField(JsonDefaults.Image.ImageType, ImageType); 19 | base.WriteComponent(writer); 20 | writer.WriteEndObject(); 21 | } 22 | 23 | public override void Reset() 24 | { 25 | base.Reset(); 26 | Png = JsonDefaults.Common.NullValue; 27 | ImageType = Image.Type.Simple; 28 | } 29 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/InputComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Enums; 2 | using Oxide.Ext.UiFramework.Json; 3 | using UnityEngine.UI; 4 | 5 | namespace Oxide.Ext.UiFramework.Components; 6 | 7 | public class InputComponent : BaseTextComponent 8 | { 9 | private const string Type = "UnityEngine.UI.InputField"; 10 | 11 | public int CharsLimit; 12 | public string Command; 13 | public InputMode Mode; 14 | public InputField.LineType LineType; 15 | 16 | public override void WriteComponent(JsonFrameworkWriter writer) 17 | { 18 | writer.WriteStartObject(); 19 | writer.AddFieldRaw(JsonDefaults.Common.ComponentTypeName, Type); 20 | writer.AddField(JsonDefaults.Input.CharacterLimitName, CharsLimit, JsonDefaults.Input.CharacterLimitValue); 21 | writer.AddField(JsonDefaults.Input.LineTypeName, LineType); 22 | 23 | if (HasMode(InputMode.ReadOnly)) 24 | { 25 | writer.AddField(JsonDefaults.Input.ReadOnlyName, true, false); 26 | } 27 | else 28 | { 29 | writer.AddField(JsonDefaults.Common.CommandName, Command, JsonDefaults.Common.NullValue); 30 | } 31 | 32 | if (HasMode(InputMode.Password)) 33 | { 34 | writer.AddFieldRaw(JsonDefaults.Input.PasswordName, true); 35 | } 36 | 37 | if (HasMode(InputMode.NeedsKeyboard)) 38 | { 39 | writer.AddFieldRaw(JsonDefaults.Input.NeedsKeyboardName, true); 40 | } 41 | 42 | if (HasMode(InputMode.HudNeedsKeyboard)) 43 | { 44 | writer.AddFieldRaw(JsonDefaults.Input.NeedsHudKeyboardName, true); 45 | } 46 | 47 | if (HasMode(InputMode.AutoFocus)) 48 | { 49 | writer.AddKeyField(JsonDefaults.Input.AutoFocusName); 50 | } 51 | 52 | base.WriteComponent(writer); 53 | writer.WriteEndObject(); 54 | } 55 | 56 | public bool HasMode(InputMode mode) 57 | { 58 | return (Mode & mode) == mode; 59 | } 60 | 61 | public void SetMode(InputMode mode, bool enabled) 62 | { 63 | if (enabled) 64 | { 65 | Mode |= mode; 66 | } 67 | else 68 | { 69 | Mode &= ~mode; 70 | } 71 | } 72 | 73 | public override void Reset() 74 | { 75 | base.Reset(); 76 | CharsLimit = JsonDefaults.Input.CharacterLimitValue; 77 | Command = null; 78 | Mode = default; 79 | LineType = default; 80 | } 81 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/ItemIconComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Json; 2 | 3 | namespace Oxide.Ext.UiFramework.Components; 4 | 5 | public class ItemIconComponent : BaseImageComponent 6 | { 7 | private const string Type = "UnityEngine.UI.Image"; 8 | 9 | public int ItemId; 10 | public ulong SkinId; 11 | 12 | public override void WriteComponent(JsonFrameworkWriter writer) 13 | { 14 | writer.WriteStartObject(); 15 | writer.AddFieldRaw(JsonDefaults.Common.ComponentTypeName, Type); 16 | writer.AddFieldRaw(JsonDefaults.ItemIcon.ItemIdName, ItemId); 17 | writer.AddField(JsonDefaults.ItemIcon.SkinIdName, SkinId, default); 18 | base.WriteComponent(writer); 19 | writer.WriteEndObject(); 20 | } 21 | 22 | public override void Reset() 23 | { 24 | base.Reset(); 25 | ItemId = default; 26 | SkinId = default; 27 | } 28 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/OutlineComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Json; 3 | using Oxide.Ext.UiFramework.Pooling; 4 | using UnityEngine; 5 | 6 | namespace Oxide.Ext.UiFramework.Components; 7 | 8 | public class OutlineComponent : BasePoolable, IComponent 9 | { 10 | private const string Type = "UnityEngine.UI.Outline"; 11 | 12 | public UiColor Color; 13 | public Vector2 Distance = JsonDefaults.Outline.Distance; 14 | public bool UseGraphicAlpha; 15 | 16 | public virtual void WriteComponent(JsonFrameworkWriter writer) 17 | { 18 | writer.WriteStartObject(); 19 | writer.AddFieldRaw(JsonDefaults.Common.ComponentTypeName, Type); 20 | writer.AddField(JsonDefaults.Outline.DistanceName, Distance, JsonDefaults.Outline.FpDistance); 21 | if (UseGraphicAlpha) 22 | { 23 | writer.AddKeyField(JsonDefaults.Outline.UseGraphicAlphaName); 24 | } 25 | 26 | writer.AddField(JsonDefaults.Color.ColorName, Color); 27 | writer.WriteEndObject(); 28 | } 29 | 30 | public virtual void Reset() 31 | { 32 | Distance = JsonDefaults.Outline.Distance; 33 | UseGraphicAlpha = false; 34 | Color = default; 35 | } 36 | 37 | protected override void EnterPool() 38 | { 39 | Reset(); 40 | } 41 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/PlayerAvatarComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Json; 2 | 3 | namespace Oxide.Ext.UiFramework.Components; 4 | 5 | public class PlayerAvatarComponent : BaseImageComponent 6 | { 7 | private const string Type = "UnityEngine.UI.RawImage"; 8 | 9 | public string SteamId; 10 | 11 | public override void WriteComponent(JsonFrameworkWriter writer) 12 | { 13 | writer.WriteStartObject(); 14 | writer.AddFieldRaw(JsonDefaults.Common.ComponentTypeName, Type); 15 | writer.AddField(JsonDefaults.PlayerAvatar.SteamIdName, SteamId, default); 16 | base.WriteComponent(writer); 17 | writer.WriteEndObject(); 18 | } 19 | 20 | public override void Reset() 21 | { 22 | base.Reset(); 23 | SteamId = default; 24 | } 25 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/RawImageComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Json; 3 | 4 | namespace Oxide.Ext.UiFramework.Components; 5 | 6 | public class RawImageComponent : IComponent 7 | { 8 | private const string Type = "UnityEngine.UI.RawImage"; 9 | 10 | public UiColor Color; 11 | public float FadeIn; 12 | public string Url; 13 | public string Png; 14 | public string Texture; 15 | public string Material; 16 | 17 | public virtual void WriteComponent(JsonFrameworkWriter writer) 18 | { 19 | writer.WriteStartObject(); 20 | writer.AddFieldRaw(JsonDefaults.Common.ComponentTypeName, Type); 21 | writer.AddField(JsonDefaults.BaseImage.SpriteName, Texture, JsonDefaults.RawImage.TextureValue); 22 | writer.AddField(JsonDefaults.BaseImage.MaterialName, Material, JsonDefaults.BaseImage.Material); 23 | if (!string.IsNullOrEmpty(Url)) 24 | { 25 | writer.AddFieldRaw(JsonDefaults.Image.UrlName, Url); 26 | } 27 | 28 | if (!string.IsNullOrEmpty(Png)) 29 | { 30 | writer.AddFieldRaw(JsonDefaults.Image.PngName, Png); 31 | } 32 | 33 | writer.AddField(JsonDefaults.Common.FadeInName, FadeIn, JsonDefaults.Common.FadeIn); 34 | writer.AddField(JsonDefaults.Color.ColorName, Color); 35 | 36 | writer.WriteEndObject(); 37 | } 38 | 39 | public virtual void Reset() 40 | { 41 | Color = default; 42 | FadeIn = 0; 43 | Url = null; 44 | Texture = null; 45 | Material = null; 46 | } 47 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/RectTransformComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Json; 2 | using Oxide.Ext.UiFramework.Offsets; 3 | using Oxide.Ext.UiFramework.Positions; 4 | 5 | namespace Oxide.Ext.UiFramework.Components; 6 | 7 | public abstract class RectTransformComponent : IComponent 8 | { 9 | public UiPosition Position; 10 | public UiOffset Offset; 11 | 12 | public abstract void WriteComponent(JsonFrameworkWriter writer); 13 | 14 | public virtual void Reset() 15 | { 16 | Position = default; 17 | Offset = default; 18 | } 19 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/ScrollViewComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Json; 2 | using UnityEngine.UI; 3 | 4 | namespace Oxide.Ext.UiFramework.Components; 5 | 6 | public class ScrollViewComponent : IComponent 7 | { 8 | private const string Type = "UnityEngine.UI.ScrollView"; 9 | 10 | public ScrollViewContentTransformComponent ContentTransform = new(); 11 | public bool Horizontal; 12 | public bool Vertical; 13 | public ScrollRect.MovementType MovementType = ScrollRect.MovementType.Clamped; 14 | public float Elasticity = JsonDefaults.ScrollView.Elasticity; 15 | public bool Inertia; 16 | public float DecelerationRate = JsonDefaults.ScrollView.DecelerationRate; 17 | public float ScrollSensitivity = JsonDefaults.ScrollView.ScrollSensitivity; 18 | public ScrollbarComponent HorizontalScrollbar; 19 | public ScrollbarComponent VerticalScrollbar; 20 | 21 | public void WriteComponent(JsonFrameworkWriter writer) 22 | { 23 | writer.WriteStartObject(); 24 | writer.AddFieldRaw(JsonDefaults.Common.ComponentTypeName, Type); 25 | writer.AddField(JsonDefaults.ScrollView.Horizontal, Horizontal, false); 26 | writer.AddField(JsonDefaults.ScrollView.Vertical, Vertical, false); 27 | writer.AddField(JsonDefaults.ScrollView.MovementType, MovementType); 28 | writer.AddField(JsonDefaults.ScrollView.ElasticityName, Elasticity, JsonDefaults.ScrollView.Elasticity); 29 | writer.AddField(JsonDefaults.ScrollView.Inertia, Inertia, false); 30 | writer.AddField(JsonDefaults.ScrollView.DecelerationRateName, DecelerationRate, JsonDefaults.ScrollView.DecelerationRate); 31 | writer.AddField(JsonDefaults.ScrollView.ScrollSensitivityName, ScrollSensitivity, JsonDefaults.ScrollView.ScrollSensitivity); 32 | 33 | if (Horizontal) 34 | { 35 | writer.AddComponent(JsonDefaults.ScrollView.HorizontalScrollbar, HorizontalScrollbar); 36 | } 37 | 38 | if (Vertical) 39 | { 40 | writer.AddComponent(JsonDefaults.ScrollView.VerticalScrollbar, VerticalScrollbar); 41 | } 42 | 43 | if (ContentTransform != null) 44 | { 45 | writer.AddComponent(JsonDefaults.ScrollView.ContentTransform, ContentTransform); 46 | } 47 | 48 | writer.WriteEndObject(); 49 | } 50 | 51 | public void Reset() 52 | { 53 | ContentTransform.Reset(); 54 | Horizontal = false; 55 | Vertical = false; 56 | MovementType = ScrollRect.MovementType.Clamped; 57 | Elasticity = JsonDefaults.ScrollView.Elasticity; 58 | Inertia = false; 59 | DecelerationRate = JsonDefaults.ScrollView.DecelerationRate; 60 | ScrollSensitivity = JsonDefaults.ScrollView.ScrollSensitivity; 61 | HorizontalScrollbar = null; 62 | VerticalScrollbar = null; 63 | } 64 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/ScrollViewContentTransformComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Json; 2 | using Oxide.Ext.UiFramework.Offsets; 3 | using Oxide.Ext.UiFramework.Positions; 4 | 5 | namespace Oxide.Ext.UiFramework.Components; 6 | 7 | public class ScrollViewContentTransformComponent : RectTransformComponent 8 | { 9 | public ScrollViewContentTransformComponent() 10 | { 11 | Position = new UiPosition(0, 0, 1, 1); 12 | Offset = new UiOffset(0, 0, 0, 0); 13 | } 14 | 15 | public override void WriteComponent(JsonFrameworkWriter writer) 16 | { 17 | writer.WriteStartObject(); 18 | writer.AddPosition(JsonDefaults.Position.AnchorMinName, Position.Min, JsonDefaults.ScrollView.Min); 19 | writer.AddPosition(JsonDefaults.Position.AnchorMaxName, Position.Max, JsonDefaults.ScrollView.AnchorMax); 20 | writer.AddOffset(JsonDefaults.Offset.OffsetMinName, Offset.Min, JsonDefaults.ScrollView.Min); 21 | writer.AddOffset(JsonDefaults.Offset.OffsetMaxName, Offset.Max, JsonDefaults.ScrollView.OffsetMax); 22 | writer.WriteEndObject(); 23 | } 24 | 25 | public override void Reset() 26 | { 27 | Position = new UiPosition(0, 0, 1, 1); 28 | Offset = new UiOffset(0, 0, 0, 0); 29 | } 30 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/ScrollbarComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Json; 3 | 4 | namespace Oxide.Ext.UiFramework.Components; 5 | 6 | public class ScrollbarComponent : BasePoolableComponent 7 | { 8 | public bool Invert; 9 | public bool AutoHide; 10 | public string HandleSprite; 11 | public string TrackSprite; 12 | public float Size = JsonDefaults.ScrollBar.Size; 13 | public UiColor HandleColor = JsonDefaults.ScrollBar.HandleColor; 14 | public UiColor HighlightColor = JsonDefaults.ScrollBar.HighlightColor; 15 | public UiColor PressedColor = JsonDefaults.ScrollBar.PressedColor; 16 | public UiColor TrackColor = JsonDefaults.ScrollBar.TrackColor; 17 | 18 | public override void WriteComponent(JsonFrameworkWriter writer) 19 | { 20 | writer.WriteStartObject(); 21 | base.WriteComponent(writer); 22 | writer.AddField(JsonDefaults.ScrollBar.Invert, Invert, false); 23 | writer.AddField(JsonDefaults.ScrollBar.AutoHide, AutoHide, false); 24 | writer.AddField(JsonDefaults.ScrollBar.HandleSprite, HandleSprite, null); 25 | writer.AddField(JsonDefaults.ScrollBar.TrackSprite, TrackSprite, null); 26 | writer.AddField(JsonDefaults.ScrollBar.SizeName, Size, JsonDefaults.ScrollBar.Size); 27 | writer.AddField(JsonDefaults.ScrollBar.HandleColorName, HandleColor, JsonDefaults.ScrollBar.HandleColor); 28 | writer.AddField(JsonDefaults.ScrollBar.HighlightColorName, HighlightColor, JsonDefaults.ScrollBar.HighlightColor); 29 | writer.AddField(JsonDefaults.ScrollBar.PressedColorName, PressedColor, JsonDefaults.ScrollBar.PressedColor); 30 | writer.AddField(JsonDefaults.ScrollBar.TrackColorName, TrackColor, JsonDefaults.ScrollBar.TrackColor); 31 | writer.WriteEndObject(); 32 | } 33 | 34 | public override void Reset() 35 | { 36 | base.Reset(); 37 | Invert = false; 38 | AutoHide = false; 39 | HandleSprite = null; 40 | TrackSprite = null; 41 | Size = JsonDefaults.ScrollBar.Size; 42 | HandleColor = JsonDefaults.ScrollBar.HandleColor; 43 | HighlightColor = JsonDefaults.ScrollBar.HighlightColor; 44 | PressedColor = JsonDefaults.ScrollBar.PressedColor; 45 | TrackColor = JsonDefaults.ScrollBar.TrackColor; 46 | } 47 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Components/TextComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Json; 2 | 3 | namespace Oxide.Ext.UiFramework.Components; 4 | 5 | public class TextComponent : BaseTextComponent 6 | { 7 | private const string Type = "UnityEngine.UI.Text"; 8 | 9 | public override void WriteComponent(JsonFrameworkWriter writer) 10 | { 11 | writer.WriteStartObject(); 12 | writer.AddFieldRaw(JsonDefaults.Common.ComponentTypeName, Type); 13 | base.WriteComponent(writer); 14 | writer.WriteEndObject(); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/BaseUiControl.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Builder; 2 | using Oxide.Ext.UiFramework.Pooling; 3 | 4 | namespace Oxide.Ext.UiFramework.Controls; 5 | 6 | public abstract class BaseUiControl : BasePoolable 7 | { 8 | private bool _hasRendered; 9 | 10 | protected static T CreateControl() where T : BaseUiControl, new() 11 | { 12 | return UiFrameworkPool.Get(); 13 | } 14 | 15 | public void RenderControl(BaseUiBuilder builder) 16 | { 17 | if (!_hasRendered) 18 | { 19 | Render(builder); 20 | _hasRendered = true; 21 | } 22 | } 23 | 24 | protected virtual void Render(BaseUiBuilder builder) 25 | { 26 | 27 | } 28 | 29 | protected override void EnterPool() 30 | { 31 | _hasRendered = false; 32 | } 33 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/Data/ButtonGroupData.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Controls.Data; 2 | 3 | public readonly struct ButtonGroupData 4 | { 5 | public readonly string DisplayName; 6 | public readonly string CommandArgs; 7 | public readonly bool IsActive; 8 | 9 | public ButtonGroupData(string displayName, string commandArgs, bool isActive = false) 10 | { 11 | DisplayName = displayName; 12 | CommandArgs = commandArgs; 13 | IsActive = isActive; 14 | } 15 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/Data/DropdownMenuData.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Controls.Data; 2 | 3 | public readonly struct DropdownMenuData 4 | { 5 | public readonly string DisplayName; 6 | public readonly string CommandArgs; 7 | public readonly bool IsActive; 8 | 9 | public DropdownMenuData(string displayName, string commandArgs, bool isActive = false) 10 | { 11 | DisplayName = displayName; 12 | CommandArgs = commandArgs; 13 | IsActive = isActive; 14 | } 15 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/Data/TimePickerData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Oxide.Ext.UiFramework.Controls.Data; 4 | 5 | public struct TimePickerData 6 | { 7 | public byte Hour; 8 | public byte Minute; 9 | public byte Second; 10 | 11 | public TimePickerData(DateTime time) 12 | { 13 | Hour = (byte)time.Hour; 14 | Minute = (byte)time.Minute; 15 | Second = (byte)time.Second; 16 | } 17 | 18 | public TimePickerData(int hour, int minute, int second) 19 | { 20 | Hour = (byte)hour; 21 | Minute = (byte)minute; 22 | Second = (byte)second; 23 | } 24 | 25 | public void Update(int seconds) 26 | { 27 | int abs = Math.Abs(seconds); 28 | if (abs == 1) 29 | { 30 | Second += (byte)seconds; 31 | } 32 | else if (abs == 60) 33 | { 34 | Minute += (byte)(seconds / 60); 35 | } 36 | else 37 | { 38 | Hour += (byte)(seconds / 3600); 39 | } 40 | } 41 | 42 | public DateTime AsDateTime() 43 | { 44 | DateTime now = DateTime.Now; 45 | return new DateTime(now.Year, now.Month, now.Day, Hour, Minute, Second); 46 | } 47 | 48 | public DateTime AsDateTime(DateTime time) 49 | { 50 | return new DateTime(time.Year, time.Month, time.Day, Hour, Minute, Second); 51 | } 52 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/Data/UiBorderWidth.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Controls.Data; 2 | 3 | public readonly struct UiBorderWidth 4 | { 5 | public static readonly UiBorderWidth Default = new(1); 6 | 7 | public readonly float Left; 8 | public readonly float Top; 9 | public readonly float Right; 10 | public readonly float Bottom; 11 | 12 | public UiBorderWidth(float left, float top, float right, float bottom) 13 | { 14 | Left = left; 15 | Top = top; 16 | Right = right; 17 | Bottom = bottom; 18 | } 19 | 20 | public UiBorderWidth(float width, float height) : this(width, height, width, height) { } 21 | 22 | public UiBorderWidth(float width) : this(width, width) { } 23 | 24 | public bool IsEmpty() => Left == 0 || Top == 0 || Right == 0 || Bottom == 0; 25 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/NumberPicker/BaseNumberPicker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Oxide.Ext.UiFramework.Builder; 3 | using Oxide.Ext.UiFramework.Cache; 4 | using Oxide.Ext.UiFramework.Colors; 5 | using Oxide.Ext.UiFramework.Enums; 6 | using Oxide.Ext.UiFramework.Extensions; 7 | using Oxide.Ext.UiFramework.Offsets; 8 | using Oxide.Ext.UiFramework.Positions; 9 | using Oxide.Ext.UiFramework.UiElements; 10 | using UnityEngine; 11 | 12 | namespace Oxide.Ext.UiFramework.Controls.NumberPicker; 13 | 14 | public abstract class BaseNumberPicker : BaseUiControl where T : struct, IConvertible, IFormattable, IComparable 15 | { 16 | public UiPanel Background; 17 | public UiInput Input; 18 | 19 | protected void CreateLeftRightPicker(BaseUiBuilder builder, in UiReference parent, in UiPosition pos, in UiOffset offset, T value, int fontSize, UiColor textColor, UiColor backgroundColor, string command, InputMode mode, float buttonWidth, TextAnchor align, string numberFormat) 20 | { 21 | Background = builder.Panel(parent, pos, offset, backgroundColor); 22 | string displayValue = string.IsNullOrEmpty(numberFormat) ? StringCache.ToString(value) : StringCache.ToString(value, numberFormat); 23 | Input = builder.Input(Background, UiPosition.Full.SliceHorizontal(buttonWidth, 1 - buttonWidth), displayValue, fontSize, textColor, command, align, mode: mode); 24 | } 25 | 26 | protected void CreateUpDownPicker(BaseUiBuilder builder, in UiReference parent, in UiPosition pos, in UiOffset offset, T value, int fontSize, UiColor textColor, UiColor backgroundColor, string command, TextAnchor align, InputMode mode, string numberFormat) 27 | { 28 | Background = builder.Panel(parent, pos, offset, backgroundColor); 29 | string displayValue = string.IsNullOrEmpty(numberFormat) ? StringCache.ToString(value) : StringCache.ToString(value, numberFormat); 30 | Input = builder.Input(Background, UiPosition.HorizontalPaddedFull, displayValue, fontSize, textColor, command, mode: mode, align: align); 31 | } 32 | 33 | protected override void EnterPool() 34 | { 35 | Background = null; 36 | Input = null; 37 | } 38 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/NumberPicker/UiIncrementalNumberPicker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Oxide.Ext.UiFramework.Builder; 4 | using Oxide.Ext.UiFramework.Cache; 5 | using Oxide.Ext.UiFramework.Colors; 6 | using Oxide.Ext.UiFramework.Enums; 7 | using Oxide.Ext.UiFramework.Extensions; 8 | using Oxide.Ext.UiFramework.Helpers; 9 | using Oxide.Ext.UiFramework.Offsets; 10 | using Oxide.Ext.UiFramework.Pooling; 11 | using Oxide.Ext.UiFramework.Positions; 12 | using Oxide.Ext.UiFramework.UiElements; 13 | using UnityEngine; 14 | 15 | namespace Oxide.Ext.UiFramework.Controls.NumberPicker; 16 | 17 | public class UiIncrementalNumberPicker : BaseNumberPicker where T : struct, IConvertible, IFormattable, IComparable 18 | { 19 | public List Subtracts; 20 | public List Adds; 21 | 22 | public static UiIncrementalNumberPicker Create(BaseUiBuilder builder, in UiReference parent, in UiPosition pos, in UiOffset offset, T value, IList increments, int fontSize, UiColor textColor, UiColor backgroundColor, UiColor buttonColor, UiColor disabledButtonColor, string command, TextAnchor align, InputMode mode, T minValue, T maxValue, float buttonWidth, string incrementFormat, string numberFormat) 23 | { 24 | UiIncrementalNumberPicker control = CreateControl>(); 25 | int incrementCount = increments.Count; 26 | 27 | control.CreateLeftRightPicker(builder, parent, pos, offset, value, fontSize, textColor, backgroundColor, command, mode, buttonWidth * incrementCount, align, numberFormat); 28 | List subtracts = control.Subtracts; 29 | List adds = control.Adds; 30 | UiPanel background = control.Background; 31 | 32 | for (int i = 0; i < incrementCount; i++) 33 | { 34 | T increment = increments[i]; 35 | string incrementValue = StringCache.ToString(increment); 36 | UiPosition subtractSlice = UiPosition.Full.SliceHorizontal(i * buttonWidth, (i + 1) * buttonWidth); 37 | UiPosition addSlice = UiPosition.Full.SliceHorizontal(1 - (buttonWidth * incrementCount) + i * buttonWidth, 1 - (buttonWidth * incrementCount) + (i + 1) * buttonWidth); 38 | 39 | string displayIncrement = StringCache.ToString(increment, incrementFormat); 40 | 41 | if (GenericMath.Subtract(value, increment).CompareTo(minValue) >= 0) 42 | { 43 | subtracts.Add(builder.TextButton(background, subtractSlice, $"-{displayIncrement}", fontSize, textColor, buttonColor, $"{command} -{incrementValue}")); 44 | } 45 | else 46 | { 47 | subtracts.Add(builder.TextButton(background, subtractSlice, $"-{displayIncrement}", fontSize, textColor, disabledButtonColor, string.Empty)); 48 | } 49 | 50 | if (GenericMath.Add(value, increment).CompareTo(maxValue) <= 0) 51 | { 52 | adds.Add(builder.TextButton(background, addSlice, displayIncrement, fontSize, textColor, buttonColor, $"{command} {incrementValue}")); 53 | } 54 | else 55 | { 56 | adds.Add(builder.TextButton(background, addSlice, displayIncrement, fontSize, textColor, disabledButtonColor, string.Empty)); 57 | } 58 | } 59 | 60 | return control; 61 | } 62 | 63 | protected override void LeavePool() 64 | { 65 | Subtracts = UiFrameworkPool.GetList(); 66 | Adds = UiFrameworkPool.GetList(); 67 | } 68 | 69 | protected override void EnterPool() 70 | { 71 | UiFrameworkPool.FreeList(Subtracts); 72 | UiFrameworkPool.FreeList(Adds); 73 | } 74 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/NumberPicker/UiNumberPicker.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Builder; 2 | using Oxide.Ext.UiFramework.Colors; 3 | using Oxide.Ext.UiFramework.Enums; 4 | using Oxide.Ext.UiFramework.Extensions; 5 | using Oxide.Ext.UiFramework.Offsets; 6 | using Oxide.Ext.UiFramework.Positions; 7 | using Oxide.Ext.UiFramework.UiElements; 8 | using UnityEngine; 9 | 10 | namespace Oxide.Ext.UiFramework.Controls.NumberPicker; 11 | 12 | public class UiNumberPicker : BaseNumberPicker 13 | { 14 | public UiButton Subtract; 15 | public UiButton Add; 16 | 17 | public static UiNumberPicker Create(BaseUiBuilder builder, in UiReference parent, in UiPosition pos, in UiOffset offset, int value, int fontSize, int buttonFontSize, UiColor textColor, UiColor backgroundColor, UiColor buttonColor, UiColor disabledButtonColor, string command, string incrementCommand, string decrementCommand, int minValue, int maxValue, float buttonWidth, TextAnchor align, InputMode mode, NumberPickerMode numberMode, string numberFormat) 18 | { 19 | UiNumberPicker control = CreateControl(); 20 | 21 | if (numberMode == NumberPickerMode.LeftRight) 22 | { 23 | control.CreateLeftRightPicker(builder, parent, pos, offset, value, fontSize, textColor, backgroundColor, command, mode, buttonWidth, align, numberFormat); 24 | UiPosition subtractPosition = UiPosition.Full.SliceHorizontal(0, buttonWidth); 25 | UiPosition addPosition = UiPosition.Full.SliceHorizontal(1 - buttonWidth, 1); 26 | control.CreateAdd(builder, value, maxValue, addPosition, default, "+", buttonFontSize, textColor, buttonColor, disabledButtonColor, incrementCommand); 27 | control.CreateSubtract(builder, value, minValue, subtractPosition, default, "-", buttonFontSize, textColor, buttonColor, disabledButtonColor, decrementCommand); 28 | } 29 | else 30 | { 31 | int width = UiHelpers.TextOffsetWidth(1, buttonFontSize, 4); 32 | UiOffset pickerOffset = offset.SliceHorizontal(0, width); 33 | control.CreateUpDownPicker(builder, parent, pos, pickerOffset, value, fontSize, textColor, backgroundColor, command, align, mode, numberFormat); 34 | UiOffset buttonOffset = new(0, 0, width, 0); 35 | control.CreateAdd(builder, value, maxValue, new UiPosition(1, 0.5f, 1, 1), buttonOffset, "˄", buttonFontSize, textColor, buttonColor, disabledButtonColor, incrementCommand); 36 | control.CreateSubtract(builder, value, minValue, new UiPosition(1, 0, 1, 0.5f), buttonOffset, "˅", buttonFontSize, textColor, buttonColor, disabledButtonColor, decrementCommand); 37 | } 38 | 39 | return control; 40 | } 41 | 42 | private void CreateSubtract(BaseUiBuilder builder, int value, int minValue, in UiPosition position, in UiOffset offset, string text, int fontSize, UiColor textColor, UiColor buttonColor, UiColor disabledButtonColor, string command) 43 | { 44 | if (value > minValue) 45 | { 46 | Subtract = builder.TextButton(Background, position, offset, text, fontSize, textColor, buttonColor, command); 47 | } 48 | else 49 | { 50 | Subtract = builder.TextButton(Background, position, offset, text, fontSize, textColor.MultiplyAlpha(0.5f), disabledButtonColor, null); 51 | } 52 | } 53 | 54 | private void CreateAdd(BaseUiBuilder builder, int value, int maxValue, in UiPosition position, in UiOffset offset, string text, int fontSize, UiColor textColor, UiColor buttonColor, UiColor disabledButtonColor, string command) 55 | { 56 | if (value < maxValue) 57 | { 58 | Add = builder.TextButton(Background, position, offset, text, fontSize, textColor, buttonColor, command); 59 | } 60 | else 61 | { 62 | Add = builder.TextButton(Background, position, offset, text, fontSize, textColor.MultiplyAlpha(0.5f), disabledButtonColor, null); 63 | } 64 | } 65 | 66 | protected override void EnterPool() 67 | { 68 | Subtract = null; 69 | Add = null; 70 | } 71 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/Popover/BasePopoverControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Oxide.Ext.UiFramework.Builder.UI; 3 | using Oxide.Ext.UiFramework.Colors; 4 | using Oxide.Ext.UiFramework.Enums; 5 | using Oxide.Ext.UiFramework.Extensions; 6 | using Oxide.Ext.UiFramework.Offsets; 7 | using Oxide.Ext.UiFramework.Positions; 8 | using Oxide.Ext.UiFramework.UiElements; 9 | using UnityEngine; 10 | using UnityEngine.UI; 11 | 12 | namespace Oxide.Ext.UiFramework.Controls.Popover; 13 | 14 | public abstract class BasePopoverControl : BaseUiControl 15 | { 16 | public UiBuilder Builder; 17 | public UiButton OutsideClose; 18 | public UiPanel PopoverBackground; 19 | 20 | public static BasePopoverControl CreateBuilder(BasePopoverControl control, string parentName, Vector2Int size, UiColor backgroundColor, PopoverPosition position = PopoverPosition.Bottom, string menuSprite = UiConstants.Sprites.RoundedBackground2) 21 | { 22 | string name = $"{parentName}_Popover"; 23 | 24 | UiBuilder builder = UiBuilder.Create(UiSection.Create(UiPosition.Full, default), name, parentName); 25 | 26 | UiPosition anchor = GetPopoverPosition(position); 27 | UiOffset offset = GetPopoverOffset(position, size); 28 | 29 | control.Builder = builder; 30 | control.OutsideClose = builder.CloseButton(builder.Root, UiPosition.Full, new UiOffset(-1000, -1000, 1000, 1000), UiColor.Clear, name); 31 | control.PopoverBackground = builder.Panel(builder.Root, anchor, offset, backgroundColor); 32 | control.PopoverBackground.SetSpriteMaterialImage(menuSprite, null, Image.Type.Sliced); 33 | control.PopoverBackground.AddElementOutline(UiColor.Black.WithAlpha(0.75f)); 34 | builder.OverrideRoot(control.PopoverBackground); 35 | 36 | return control; 37 | } 38 | 39 | public static UiPosition GetPopoverPosition(PopoverPosition position) 40 | { 41 | switch (position) 42 | { 43 | case PopoverPosition.Top: 44 | case PopoverPosition.Left: 45 | return UiPosition.TopLeft; 46 | 47 | case PopoverPosition.Right: 48 | return UiPosition.TopRight; 49 | 50 | case PopoverPosition.Bottom: 51 | return UiPosition.BottomLeft; 52 | 53 | default: 54 | throw new ArgumentOutOfRangeException(nameof(position), position, null); 55 | } 56 | } 57 | 58 | public static UiOffset GetPopoverOffset(PopoverPosition position, Vector2Int size) 59 | { 60 | switch (position) 61 | { 62 | case PopoverPosition.Top: 63 | return new UiOffset(0, 1, 1 + size.x, size.y); 64 | 65 | case PopoverPosition.Left: 66 | return new UiOffset(-size.x, -size.y - 1, 0, -1); 67 | 68 | case PopoverPosition.Right: 69 | return new UiOffset(0, -size.y - 1, size.x, -1); 70 | 71 | case PopoverPosition.Bottom: 72 | return new UiOffset(1, -size.y, 1 + size.x, 0); 73 | 74 | default: 75 | throw new ArgumentOutOfRangeException(nameof(position), position, null); 76 | } 77 | } 78 | 79 | protected override void EnterPool() 80 | { 81 | Builder = null; 82 | OutsideClose = null; 83 | PopoverBackground = null; 84 | } 85 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/Popover/UiDropdownMenu.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Oxide.Ext.UiFramework.Builder.UI; 4 | using Oxide.Ext.UiFramework.Colors; 5 | using Oxide.Ext.UiFramework.Controls.Data; 6 | using Oxide.Ext.UiFramework.Enums; 7 | using Oxide.Ext.UiFramework.Extensions; 8 | using Oxide.Ext.UiFramework.Offsets; 9 | using Oxide.Ext.UiFramework.Positions; 10 | using Oxide.Ext.UiFramework.UiElements; 11 | using UnityEngine; 12 | using UnityEngine.UI; 13 | 14 | namespace Oxide.Ext.UiFramework.Controls.Popover; 15 | 16 | public class UiDropdownMenu : BasePopoverControl 17 | { 18 | public UiSection ScrollBarSection; 19 | public UiScrollBar ScrollBar; 20 | public List Items; 21 | 22 | public static UiDropdownMenu Create(in UiReference reference, List items, int fontSize, UiColor textColor, UiColor backgroundColor, string selectedCommand, string pageCommand = null, int page = 0, int maxValuesPerPage = 100, int minWidth = 100, 23 | PopoverPosition position = PopoverPosition.Bottom, string menuSprite = UiConstants.Sprites.RoundedBackground2) 24 | { 25 | const int itemPadding = 4; 26 | const int menuPadding = 5; 27 | 28 | UiDropdownMenu control = CreateControl(); 29 | 30 | int itemCount = Math.Min(items.Count, maxValuesPerPage); 31 | int width = Math.Max(minWidth, control.GetWidth(items, fontSize)); 32 | int itemHeight = UiHelpers.TextOffsetHeight(fontSize); 33 | int height = itemCount * (itemHeight + itemPadding) + menuPadding * 2; 34 | int maxPage = UiHelpers.CalculateMaxPage(items.Count, maxValuesPerPage); 35 | 36 | Vector2Int size = new(width, height); 37 | CreateBuilder(control, reference.Parent, size, backgroundColor, position, menuSprite); 38 | 39 | UiBuilder builder = control.Builder; 40 | 41 | UiOffset buttonPos = new(menuPadding, -itemHeight - menuPadding, width + menuPadding, -menuPadding); 42 | if (maxPage > 0) 43 | { 44 | buttonPos = buttonPos.SliceHorizontal(0, 10); 45 | control.ScrollBarSection = builder.Section(builder.Root, UiPosition.Right, new UiOffset(-10, 5, -3, -5)); 46 | control.ScrollBar = builder.ScrollBar(control.ScrollBarSection, UiPosition.Full, default, page, maxPage, UiColors.ButtonPrimary, UiColors.PanelSecondary, pageCommand); 47 | control.ScrollBar.SetSpriteMaterialImage(UiConstants.Sprites.RoundedBackground1, null, Image.Type.Sliced); 48 | } 49 | 50 | for (int i = page * maxValuesPerPage; i < page * maxValuesPerPage + itemCount; i++) 51 | { 52 | control.Items.Add(UiDropdownMenuItem.Create(builder, buttonPos, items[i], fontSize, textColor, backgroundColor, selectedCommand)); 53 | buttonPos = buttonPos.MoveY(-itemHeight - itemPadding); 54 | } 55 | 56 | return control; 57 | } 58 | 59 | public virtual int GetWidth(List items, int fontSize) 60 | { 61 | int width = 0; 62 | int count = items.Count; 63 | for (int i = 0; i < count; i++) 64 | { 65 | DropdownMenuData item = items[i]; 66 | int valueWidth = UiHelpers.TextOffsetWidth(item.DisplayName.Length, fontSize); 67 | if (valueWidth > width) 68 | { 69 | width = valueWidth; 70 | } 71 | } 72 | 73 | return width; 74 | } 75 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/Popover/UiDropdownMenuItem.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Builder.UI; 2 | using Oxide.Ext.UiFramework.Colors; 3 | using Oxide.Ext.UiFramework.Controls.Data; 4 | using Oxide.Ext.UiFramework.Offsets; 5 | using Oxide.Ext.UiFramework.Positions; 6 | using Oxide.Ext.UiFramework.UiElements; 7 | 8 | namespace Oxide.Ext.UiFramework.Controls.Popover; 9 | 10 | public class UiDropdownMenuItem : BaseUiControl 11 | { 12 | public UiButton Button; 13 | public UiLabel Label; 14 | 15 | public static UiDropdownMenuItem Create(UiBuilder builder, in UiOffset position, in DropdownMenuData item, int fontSize, UiColor textColor, UiColor backgroundColor, string selectedCommand) 16 | { 17 | UiDropdownMenuItem control = CreateControl(); 18 | 19 | control.Button = builder.CommandButton(builder.Root, UiPosition.TopLeft, position, backgroundColor, $"{selectedCommand} {item.CommandArgs}"); 20 | control.Label = builder.Label(control.Button, UiPosition.Full, item.DisplayName, fontSize, textColor); 21 | 22 | return control; 23 | } 24 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/Popover/UiPopover.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Enums; 3 | using UnityEngine; 4 | 5 | namespace Oxide.Ext.UiFramework.Controls.Popover; 6 | 7 | public class UiPopover : BasePopoverControl 8 | { 9 | public static UiPopover Create(string parentName, Vector2Int size, UiColor backgroundColor, PopoverPosition position = PopoverPosition.Bottom, string menuSprite = UiConstants.Sprites.RoundedBackground2) 10 | { 11 | UiPopover control = CreateControl(); 12 | CreateBuilder(control, parentName, size, backgroundColor, position, menuSprite); 13 | return control; 14 | } 15 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/UiBorder.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Builder; 2 | using Oxide.Ext.UiFramework.Colors; 3 | using Oxide.Ext.UiFramework.Controls.Data; 4 | using Oxide.Ext.UiFramework.Enums; 5 | using Oxide.Ext.UiFramework.Offsets; 6 | using Oxide.Ext.UiFramework.Positions; 7 | using Oxide.Ext.UiFramework.UiElements; 8 | 9 | namespace Oxide.Ext.UiFramework.Controls; 10 | 11 | public class UiBorder : BaseUiControl 12 | { 13 | public UiPanel Left; 14 | public UiPanel Right; 15 | public UiPanel Top; 16 | public UiPanel Bottom; 17 | 18 | public static UiBorder Create(BaseUiBuilder builder, in UiReference parent, UiColor color, 19 | in UiBorderWidth width, BorderMode border = BorderMode.All) 20 | { 21 | UiBorder control = CreateControl(); 22 | if (width.IsEmpty()) 23 | { 24 | return control; 25 | } 26 | 27 | bool top = HasBorderFlag(border, BorderMode.Top); 28 | bool left = HasBorderFlag(border, BorderMode.Left); 29 | bool bottom = HasBorderFlag(border, BorderMode.Bottom); 30 | bool right = HasBorderFlag(border, BorderMode.Right); 31 | 32 | if (top) 33 | { 34 | control.Top = builder.Panel(parent, UiPosition.Top, new UiOffset(left ? -width.Left : 0, 0, right ? width.Right : 0, width.Top), color); 35 | } 36 | 37 | if (left) 38 | { 39 | control.Left = builder.Panel(parent, UiPosition.Left, new UiOffset(-width.Left, bottom ? -width.Bottom : 0, 0, top ? width.Top : 0), color); 40 | } 41 | 42 | if (bottom) 43 | { 44 | control.Bottom = builder.Panel(parent, UiPosition.Bottom, new UiOffset(left ? -width.Left : 0, -width.Bottom, right ? width.Right : 0, 0), color); 45 | } 46 | 47 | if (right) 48 | { 49 | control.Right = builder.Panel(parent, UiPosition.Right, new UiOffset(0, bottom ? -width.Bottom : 0, width.Right, top ? width.Top : 0), color); 50 | } 51 | 52 | return control; 53 | } 54 | 55 | private static bool HasBorderFlag(BorderMode mode, BorderMode flag) 56 | { 57 | return (mode & flag) != 0; 58 | } 59 | 60 | protected override void EnterPool() 61 | { 62 | base.EnterPool(); 63 | Left = null; 64 | Top = null; 65 | Right = null; 66 | Bottom = null; 67 | } 68 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/UiButtonGroup.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Oxide.Ext.UiFramework.Builder; 3 | using Oxide.Ext.UiFramework.Cache; 4 | using Oxide.Ext.UiFramework.Colors; 5 | using Oxide.Ext.UiFramework.Controls.Data; 6 | using Oxide.Ext.UiFramework.Extensions; 7 | using Oxide.Ext.UiFramework.Offsets; 8 | using Oxide.Ext.UiFramework.Pooling; 9 | using Oxide.Ext.UiFramework.Positions; 10 | using Oxide.Ext.UiFramework.UiElements; 11 | 12 | namespace Oxide.Ext.UiFramework.Controls; 13 | 14 | public class UiButtonGroup : BaseUiControl 15 | { 16 | public UiSection Base; 17 | public List Buttons; 18 | 19 | public static UiButtonGroup Create(BaseUiBuilder builder, in UiReference parent, in UiPosition pos, in UiOffset offset, List buttons, int textSize, UiColor textColor, UiColor buttonColor, UiColor activeButtonColor, string command) 20 | { 21 | UiButtonGroup control = CreateControl(); 22 | control.Base = builder.Section(parent, pos, offset); 23 | 24 | float buttonSize = 1f / (buttons.Count + 1); 25 | for (int i = 0; i < buttons.Count; i++) 26 | { 27 | ButtonGroupData button = buttons[i]; 28 | 29 | UiPosition buttonPos = UiPosition.Full.SliceHorizontal(buttonSize * i, buttonSize * (i + 1)); 30 | control.Buttons.Add(builder.TextButton(control.Base, buttonPos, button.DisplayName, textSize, textColor, button.IsActive ? activeButtonColor : buttonColor, $"{command} {button.CommandArgs}")); 31 | } 32 | 33 | return control; 34 | } 35 | 36 | public static UiButtonGroup CreateNumeric(BaseUiBuilder builder, in UiReference parent, in UiPosition pos, in UiOffset offset, int value, int minValue, int maxValue, int textSize, UiColor textColor, UiColor buttonColor, UiColor activeButtonColor, string command) 37 | { 38 | List data = UiFrameworkPool.GetList(); 39 | for (int i = minValue; i <= maxValue; i++) 40 | { 41 | string num = StringCache.ToString(i); 42 | data.Add(new ButtonGroupData(num, num, i == value)); 43 | } 44 | 45 | UiButtonGroup control = Create(builder, parent, pos, offset, data, textSize, textColor, buttonColor, activeButtonColor, command); 46 | UiFrameworkPool.FreeList(data); 47 | 48 | return control; 49 | } 50 | 51 | protected override void LeavePool() 52 | { 53 | base.LeavePool(); 54 | Buttons = UiFrameworkPool.GetList(); 55 | } 56 | 57 | protected override void EnterPool() 58 | { 59 | base.EnterPool(); 60 | UiFrameworkPool.FreeList(Buttons); 61 | Base = null; 62 | } 63 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/UiCheckbox.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Builder; 2 | using Oxide.Ext.UiFramework.Colors; 3 | using Oxide.Ext.UiFramework.Extensions; 4 | using Oxide.Ext.UiFramework.Offsets; 5 | using Oxide.Ext.UiFramework.Positions; 6 | using Oxide.Ext.UiFramework.UiElements; 7 | 8 | namespace Oxide.Ext.UiFramework.Controls; 9 | 10 | public class UiCheckbox : BaseUiControl 11 | { 12 | private const string DefaultCheckmark = ""; 13 | 14 | public bool IsChecked; 15 | public string Checkmark = DefaultCheckmark; 16 | public UiButton Button; 17 | public UiLabel Label; 18 | 19 | public static UiCheckbox CreateCheckbox(BaseUiBuilder builder, in UiReference parent, in UiPosition pos, in UiOffset offset, bool isChecked, int textSize, UiColor textColor, UiColor backgroundColor, string command) 20 | { 21 | UiCheckbox control = CreateControl(); 22 | control.IsChecked = isChecked; 23 | control.Button = builder.CommandButton(parent, pos, offset, backgroundColor, command); 24 | control.Label = builder.Label(control.Button, UiPosition.Full, string.Empty, textSize, textColor); 25 | control.Button.AddElementOutline(UiColor.Black.WithAlpha(0.75f)); 26 | return control; 27 | } 28 | 29 | protected override void Render(BaseUiBuilder builder) 30 | { 31 | if (IsChecked) 32 | { 33 | Label.Text.Text = Checkmark; 34 | } 35 | } 36 | 37 | protected override void EnterPool() 38 | { 39 | base.EnterPool(); 40 | IsChecked = false; 41 | Button = null; 42 | Label = null; 43 | Checkmark = DefaultCheckmark; 44 | } 45 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/UiColorPicker.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Builder; 2 | using Oxide.Ext.UiFramework.Colors; 3 | using Oxide.Ext.UiFramework.Extensions; 4 | using Oxide.Ext.UiFramework.Offsets; 5 | using Oxide.Ext.UiFramework.Positions; 6 | using Oxide.Ext.UiFramework.UiElements; 7 | using UnityEngine; 8 | 9 | namespace Oxide.Ext.UiFramework.Controls; 10 | 11 | public class UiColorPicker : BaseUiControl 12 | { 13 | public UiSection Anchor; 14 | public UiButton Button; 15 | public UiLabel Text; 16 | public UiPanel Color; 17 | 18 | public static UiColorPicker Create(BaseUiBuilder builder, BaseUiComponent parent, in UiPosition pos, in UiOffset offset, UiColor selectedColor, int fontSize, UiColor textColor, UiColor backgroundColor, string openCommand) 19 | { 20 | UiColorPicker control = CreateControl(); 21 | control.Anchor = builder.Anchor(parent, pos, offset); 22 | control.Button = builder.CommandButton(parent, pos, offset, backgroundColor, $"{openCommand} {control.Anchor.Reference.Name}"); 23 | control.Text = builder.Label(control.Button, UiPosition.Full, new UiOffset(5, 0, 0, 0), selectedColor.ToHtmlColor(), fontSize, textColor, TextAnchor.MiddleLeft); 24 | control.Color = builder.Panel(control.Button, UiPosition.Full.SliceHorizontal(1f - (pos.Max.y - pos.Min.y), 1), new UiOffset(-4, 4, -4, -4), selectedColor); 25 | return control; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/UiDatePicker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Oxide.Ext.UiFramework.Builder; 3 | using Oxide.Ext.UiFramework.Colors; 4 | using Oxide.Ext.UiFramework.Offsets; 5 | using Oxide.Ext.UiFramework.Positions; 6 | using Oxide.Ext.UiFramework.UiElements; 7 | using UnityEngine; 8 | 9 | namespace Oxide.Ext.UiFramework.Controls; 10 | 11 | public class UiDatePicker : BaseUiControl 12 | { 13 | public UiSection Anchor; 14 | public UiButton Command; 15 | public UiLabel Text; 16 | public UiLabel Icon; 17 | 18 | public static UiDatePicker Create(BaseUiBuilder builder, in UiReference parent, in UiPosition pos, in UiOffset offset, DateTime date, int fontSize, UiColor textColor, UiColor backgroundColor, string openCommand, string displayFormat = "MM/dd/yyyy") 19 | { 20 | UiDatePicker control = CreateControl(); 21 | 22 | control.Anchor = builder.Anchor(parent, pos, offset); 23 | control.Command = builder.CommandButton(parent, pos, offset, backgroundColor, $"{openCommand} {control.Anchor.Reference.Name}"); 24 | control.Text = builder.Label(control.Command, UiPosition.Full, new UiOffset(5, 0, 0, 0), date.ToString(displayFormat), fontSize, textColor, TextAnchor.MiddleLeft); 25 | control.Icon = builder.Label(control.Command, UiPosition.Right, new UiOffset(-fontSize - 4, 0, -4 , 0), "⏱", fontSize, textColor); 26 | 27 | return control; 28 | } 29 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/UiDropdown.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Builder; 2 | using Oxide.Ext.UiFramework.Colors; 3 | using Oxide.Ext.UiFramework.Offsets; 4 | using Oxide.Ext.UiFramework.Positions; 5 | using Oxide.Ext.UiFramework.UiElements; 6 | using UnityEngine; 7 | 8 | namespace Oxide.Ext.UiFramework.Controls; 9 | 10 | public class UiDropdown : BaseUiControl 11 | { 12 | public UiSection Anchor; 13 | public UiButton Command; 14 | public UiLabel Text; 15 | public UiLabel Icon; 16 | 17 | public static UiDropdown Create(BaseUiBuilder builder, in UiReference parent, in UiPosition pos, in UiOffset offset, string displayValue, int fontSize, UiColor textColor, UiColor backgroundColor, string openCommand) 18 | { 19 | UiDropdown control = CreateControl(); 20 | control.Anchor = builder.Anchor(parent, pos); 21 | control.Command = builder.CommandButton(parent, pos, offset, backgroundColor, $"{openCommand} {control.Anchor.Reference.Name}"); 22 | control.Text = builder.Label(control.Command, UiPosition.Full, new UiOffset(5, 0, 0, 0), displayValue, fontSize, textColor, TextAnchor.MiddleLeft); 23 | control.Icon = builder.Label(control.Command, UiPosition.Right, new UiOffset(-UiHelpers.TextOffsetWidth(1, fontSize) - 4, 0, -4 , 0), "▼", fontSize, textColor); 24 | return control; 25 | } 26 | 27 | protected override void EnterPool() 28 | { 29 | base.EnterPool(); 30 | Anchor = null; 31 | Command = null; 32 | Text = null; 33 | Icon = null; 34 | } 35 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/UiInputBackground.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Builder; 2 | using Oxide.Ext.UiFramework.Colors; 3 | using Oxide.Ext.UiFramework.Enums; 4 | using Oxide.Ext.UiFramework.Offsets; 5 | using Oxide.Ext.UiFramework.Positions; 6 | using Oxide.Ext.UiFramework.UiElements; 7 | using UnityEngine; 8 | using UnityEngine.UI; 9 | 10 | namespace Oxide.Ext.UiFramework.Controls; 11 | 12 | public class UiInputBackground : BaseUiControl 13 | { 14 | public UiInput Input; 15 | public UiPanel Background; 16 | 17 | public static UiInputBackground Create(BaseUiBuilder builder, in UiReference parent, in UiPosition pos, in UiOffset offset, string text, int fontSize, UiColor textColor, UiColor backgroundColor, string command, TextAnchor align = TextAnchor.MiddleCenter, int charsLimit = 0, InputMode mode = InputMode.Default, InputField.LineType lineType = InputField.LineType.SingleLine) 18 | { 19 | UiInputBackground control = CreateControl(); 20 | control.Background = builder.Panel(parent, pos, offset, backgroundColor); 21 | control.Input = builder.Input(control.Background, UiPosition.HorizontalPaddedFull, text, fontSize, textColor, command, align, charsLimit, mode, lineType); 22 | return control; 23 | } 24 | 25 | protected override void EnterPool() 26 | { 27 | base.EnterPool(); 28 | Input = null; 29 | Background = null; 30 | } 31 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/UiLabelBackground.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Builder; 2 | using Oxide.Ext.UiFramework.Colors; 3 | using Oxide.Ext.UiFramework.Offsets; 4 | using Oxide.Ext.UiFramework.Positions; 5 | using Oxide.Ext.UiFramework.UiElements; 6 | using UnityEngine; 7 | 8 | namespace Oxide.Ext.UiFramework.Controls; 9 | 10 | public class UiLabelBackground : BaseUiControl 11 | { 12 | public UiLabel Label; 13 | public UiPanel Background; 14 | 15 | public static UiLabelBackground Create(BaseUiBuilder builder, in UiReference parent, in UiPosition pos, in UiOffset offset, string text, int fontSize, UiColor textColor, UiColor backgroundColor, TextAnchor align = TextAnchor.MiddleCenter) 16 | { 17 | UiLabelBackground control = CreateControl(); 18 | control.Background = builder.Panel(parent, pos, offset, backgroundColor); 19 | control.Label = builder.Label(control.Background, UiPosition.HorizontalPaddedFull, text, fontSize, textColor, align); 20 | return control; 21 | } 22 | 23 | protected override void EnterPool() 24 | { 25 | base.EnterPool(); 26 | Label = null; 27 | Background = null; 28 | } 29 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/UiPaginator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Oxide.Ext.UiFramework.Builder; 4 | using Oxide.Ext.UiFramework.Cache; 5 | using Oxide.Ext.UiFramework.Colors; 6 | using Oxide.Ext.UiFramework.Pooling; 7 | using Oxide.Ext.UiFramework.Positions; 8 | using Oxide.Ext.UiFramework.UiElements; 9 | 10 | namespace Oxide.Ext.UiFramework.Controls; 11 | 12 | public class UiPaginator : BaseUiControl 13 | { 14 | public UiButton FirstPage; 15 | public UiButton PreviousPage; 16 | public List PageButtons; 17 | public UiButton NextPage; 18 | public UiButton LastPage; 19 | 20 | public static UiPaginator Create(BaseUiBuilder builder, in UiReference parent, GridPosition grid, int currentPage, int maxPage, int fontSize, UiColor textColor, UiColor buttonColor, UiColor activePageColor, string command) 21 | { 22 | UiPaginator control = CreateControl(); 23 | grid.Reset(); 24 | 25 | int totalButtons = (int)Math.Round(grid.NumCols, 0); 26 | int pageButtons = totalButtons - 5; 27 | 28 | int startPage = Math.Max(currentPage - pageButtons / 2, 0); 29 | int endPage = Math.Min(maxPage, startPage + pageButtons); 30 | if (endPage - startPage != pageButtons) 31 | { 32 | startPage = Math.Max(endPage - pageButtons, 0); 33 | if (endPage - startPage != pageButtons) 34 | { 35 | grid.MoveCols((pageButtons - endPage - startPage) / 2f); 36 | } 37 | } 38 | 39 | control.FirstPage = builder.TextButton(parent, grid, "<<<", fontSize, textColor, buttonColor, $"{command} 0"); 40 | grid.MoveCols(1); 41 | control.PreviousPage = builder.TextButton(parent, grid, "<", fontSize, textColor, buttonColor, $"{command} {StringCache.ToString(Math.Max(0, currentPage - 1))}"); 42 | grid.MoveCols(1); 43 | 44 | for (int i = startPage; i <= endPage; i++) 45 | { 46 | control.PageButtons.Add(builder.TextButton(parent, grid, (i + 1).ToString(), fontSize, textColor, i == currentPage ? activePageColor : buttonColor, $"{command} {StringCache.ToString(i)}")); 47 | grid.MoveCols(1); 48 | } 49 | 50 | control.NextPage = builder.TextButton(parent, grid, ">", fontSize, textColor, buttonColor, $"{command} {StringCache.ToString(Math.Min(maxPage, currentPage + 1))}"); 51 | grid.MoveCols(1); 52 | control.LastPage = builder.TextButton(parent, grid, ">>>", fontSize, textColor, buttonColor, $"{command} {StringCache.ToString(maxPage)}"); 53 | 54 | return control; 55 | } 56 | 57 | protected override void LeavePool() 58 | { 59 | base.LeavePool(); 60 | PageButtons = UiFrameworkPool.GetList(); 61 | } 62 | 63 | protected override void EnterPool() 64 | { 65 | base.EnterPool(); 66 | FirstPage = null; 67 | PreviousPage = null; 68 | UiFrameworkPool.FreeList(PageButtons); 69 | NextPage = null; 70 | LastPage = null; 71 | } 72 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/UiPicker.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Builder; 2 | using Oxide.Ext.UiFramework.Colors; 3 | using Oxide.Ext.UiFramework.Extensions; 4 | using Oxide.Ext.UiFramework.Offsets; 5 | using Oxide.Ext.UiFramework.Positions; 6 | using Oxide.Ext.UiFramework.UiElements; 7 | 8 | namespace Oxide.Ext.UiFramework.Controls; 9 | 10 | public class UiPicker : BaseUiControl 11 | { 12 | public UiButton Previous; 13 | public UiLabel Value; 14 | public UiButton Next; 15 | 16 | public static UiPicker Create(BaseUiBuilder builder, in UiReference parent, in UiOffset pos, string value, int fontSize, UiColor textColor, UiColor backgroundColor, float height, string incrementCommand, string decrementCommand) 17 | { 18 | UiPicker control = CreateControl(); 19 | 20 | UiOffset slice = pos.SliceVertical(0, (int)height * 2); 21 | control.Next = builder.TextButton(parent, UiPosition.BottomLeft, slice, "˅", fontSize, textColor, backgroundColor, decrementCommand); 22 | slice = slice.MoveY(height); 23 | control.Value = builder.Label(parent, UiPosition.BottomLeft, slice, value, fontSize, textColor); 24 | slice = slice.MoveY(height); 25 | control.Previous = builder.TextButton(parent, UiPosition.BottomLeft, slice, "˄", fontSize, textColor, backgroundColor, incrementCommand); 26 | 27 | return control; 28 | } 29 | 30 | protected override void EnterPool() 31 | { 32 | base.EnterPool(); 33 | Previous = null; 34 | Value = null; 35 | Next = null; 36 | } 37 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/UiProgressBar.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Builder; 2 | using Oxide.Ext.UiFramework.Colors; 3 | using Oxide.Ext.UiFramework.Extensions; 4 | using Oxide.Ext.UiFramework.Offsets; 5 | using Oxide.Ext.UiFramework.Positions; 6 | using Oxide.Ext.UiFramework.UiElements; 7 | 8 | namespace Oxide.Ext.UiFramework.Controls; 9 | 10 | public class UiProgressBar : BaseUiControl 11 | { 12 | public UiPanel BackgroundPanel; 13 | public UiPanel BarPanel; 14 | 15 | public static UiProgressBar Create(BaseUiBuilder builder, in UiReference parent, in UiPosition pos, in UiOffset offset, float percentage, UiColor barColor, UiColor backgroundColor) 16 | { 17 | UiProgressBar control = CreateControl(); 18 | control.BackgroundPanel = builder.Panel(parent, pos, offset, backgroundColor); 19 | control.BarPanel = builder.Panel(control.BackgroundPanel, UiPosition.Full.SliceHorizontal(0, percentage), barColor); 20 | return control; 21 | } 22 | 23 | protected override void EnterPool() 24 | { 25 | base.EnterPool(); 26 | BackgroundPanel = null; 27 | BarPanel = null; 28 | } 29 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/UiScrollBar.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Oxide.Ext.UiFramework.Builder; 3 | using Oxide.Ext.UiFramework.Cache; 4 | using Oxide.Ext.UiFramework.Colors; 5 | using Oxide.Ext.UiFramework.Enums; 6 | using Oxide.Ext.UiFramework.Extensions; 7 | using Oxide.Ext.UiFramework.Offsets; 8 | using Oxide.Ext.UiFramework.Pooling; 9 | using Oxide.Ext.UiFramework.Positions; 10 | using Oxide.Ext.UiFramework.UiElements; 11 | using UnityEngine.UI; 12 | 13 | namespace Oxide.Ext.UiFramework.Controls; 14 | 15 | public class UiScrollBar : BaseUiControl 16 | { 17 | public UiPanel Background; 18 | public UiPanel ScrollBar; 19 | public List ScrollButtons; 20 | 21 | public static UiScrollBar Create(BaseUiBuilder builder, in UiReference parent, in UiPosition position, in UiOffset offset, int currentPage, int maxPage, UiColor barColor, UiColor backgroundColor, string command, ScrollbarDirection direction, string sprite) 22 | { 23 | UiScrollBar control = CreateControl(); 24 | 25 | control.Background = builder.Panel(parent, position, offset, backgroundColor); 26 | control.Background.SetSpriteMaterialImage(sprite, null, Image.Type.Sliced); 27 | float buttonSize = 1f / (maxPage + 1); 28 | for (int i = 0; i <= maxPage; i++) 29 | { 30 | float min = buttonSize * i; 31 | float max = buttonSize * (i + 1); 32 | UiPosition pagePosition = direction == ScrollbarDirection.Horizontal ? UiPosition.Full.SliceHorizontal(min, max) : new UiPosition(0, 1 - max, 1, 1 - min); 33 | 34 | if (i != currentPage) 35 | { 36 | UiButton button = builder.CommandButton(control.Background, pagePosition, backgroundColor, $"{command} {StringCache.ToString(i)}"); 37 | button.SetSpriteMaterialImage(sprite, null, Image.Type.Sliced); 38 | control.ScrollButtons.Add(button); 39 | } 40 | else 41 | { 42 | control.ScrollBar = builder.Panel(control.Background, pagePosition, barColor); 43 | control.ScrollBar.SetSpriteMaterialImage(sprite, null, Image.Type.Sliced); 44 | } 45 | } 46 | 47 | return control; 48 | } 49 | 50 | public void SetSpriteMaterialImage(string sprite = null, string material = null, Image.Type type = Image.Type.Simple) 51 | { 52 | Background.SetSpriteMaterialImage(sprite, material, type); 53 | ScrollBar.SetSpriteMaterialImage(sprite, material, type); 54 | for (int index = 0; index < ScrollButtons.Count; index++) 55 | { 56 | UiButton button = ScrollButtons[index]; 57 | button.SetSpriteMaterialImage(sprite, material, type); 58 | } 59 | } 60 | 61 | protected override void LeavePool() 62 | { 63 | base.LeavePool(); 64 | ScrollButtons = UiFrameworkPool.GetList(); 65 | } 66 | 67 | protected override void EnterPool() 68 | { 69 | base.EnterPool(); 70 | Background = null; 71 | ScrollBar = null; 72 | UiFrameworkPool.FreeList(ScrollButtons); 73 | } 74 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Controls/UiTimePicker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Oxide.Ext.UiFramework.Builder; 3 | using Oxide.Ext.UiFramework.Colors; 4 | using Oxide.Ext.UiFramework.Offsets; 5 | using Oxide.Ext.UiFramework.Positions; 6 | using Oxide.Ext.UiFramework.UiElements; 7 | using UnityEngine; 8 | 9 | namespace Oxide.Ext.UiFramework.Controls; 10 | 11 | public class UiTimePicker : BaseUiControl 12 | { 13 | public UiSection Anchor; 14 | public UiButton Command; 15 | public UiLabel Text; 16 | public UiLabel Icon; 17 | 18 | public static UiTimePicker Create(BaseUiBuilder builder, in UiReference parent, in UiPosition pos, in UiOffset offset, DateTime time, int fontSize, UiColor textColor, UiColor backgroundColor, string openCommand, string displayFormat = "hh:mm:ss tt") 19 | { 20 | UiTimePicker control = CreateControl(); 21 | 22 | control.Anchor = builder.Anchor(parent, pos, offset); 23 | control.Command = builder.CommandButton(parent, pos, offset, backgroundColor, $"{openCommand} {control.Anchor.Reference.Name}"); 24 | control.Text = builder.Label(control.Command, UiPosition.Full, new UiOffset(5, 0, 0, 0), time.ToString(displayFormat), fontSize, textColor, TextAnchor.MiddleLeft); 25 | control.Icon = builder.Label(control.Command, UiPosition.Right, new UiOffset(-fontSize - 4, 0, -4 , 0), "⏱", fontSize, textColor); 26 | 27 | return control; 28 | } 29 | 30 | protected override void EnterPool() 31 | { 32 | base.EnterPool(); 33 | Anchor = null; 34 | Command = null; 35 | Text = null; 36 | Icon = null; 37 | } 38 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Enums/BorderMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Oxide.Ext.UiFramework.Enums; 4 | 5 | [Flags] 6 | public enum BorderMode : byte 7 | { 8 | Top = 1 << 0, 9 | Left = 1 << 1, 10 | Bottom = 1 << 2, 11 | Right = 1 << 3, 12 | All = Top | Left | Bottom | Right 13 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Enums/ClockMode.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Enums; 2 | 3 | public enum ClockMode 4 | { 5 | Hour12, 6 | Hour24 7 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Enums/ColorPickerMode.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Enums; 2 | 3 | public enum ColorPickerMode 4 | { 5 | RGB, 6 | RGBA 7 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Enums/DatePickerDisplayMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Oxide.Ext.UiFramework.Enums; 4 | 5 | [Flags] 6 | public enum DatePickerDisplayMode : byte 7 | { 8 | Day = 1 << 0, 9 | Month = 1 << 1, 10 | Year = 1 << 2, 11 | All = Day | Month | Year 12 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Enums/DatePickerDisplayOrder.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Enums; 2 | 3 | public enum DatePickerDisplayOrder 4 | { 5 | YearMonthDay, 6 | MonthDayYear, 7 | DayMonthYear, 8 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Enums/InputMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Oxide.Ext.UiFramework.Enums; 4 | 5 | [Flags] 6 | public enum InputMode : byte 7 | { 8 | Default = 0, 9 | ReadOnly = 1 << 0, 10 | NeedsKeyboard = 1 << 1, 11 | HudNeedsKeyboard = 1 << 2, 12 | Password = 1 << 3, 13 | AutoFocus = 1 << 4 14 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Enums/NumberPickerMode.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Enums; 2 | 3 | public enum NumberPickerMode 4 | { 5 | LeftRight, 6 | UpDown 7 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Enums/PopoverPosition.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Enums; 2 | 3 | public enum PopoverPosition 4 | { 5 | Top, 6 | Left, 7 | Right, 8 | Bottom 9 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Enums/ScrollbarDirection.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Enums; 2 | 3 | public enum ScrollbarDirection 4 | { 5 | Vertical, 6 | Horizontal 7 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Enums/TimePickerDisplayMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Oxide.Ext.UiFramework.Enums; 4 | 5 | [Flags] 6 | public enum TimePickerDisplayMode : byte 7 | { 8 | Hours = 1 << 0, 9 | Minutes = 1 << 1, 10 | Seconds = 1 << 2, 11 | HoursMinutes = Hours | Minutes, 12 | All = Hours | Minutes | Seconds 13 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Enums/TimerFormat.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Enums; 2 | 3 | public enum TimerFormat 4 | { 5 | None, 6 | SecondsHundreth, 7 | MinutesSeconds, 8 | MinutesSecondsHundreth, 9 | HoursMinutes, 10 | HoursMinutesSeconds, 11 | HoursMinutesSecondsMilliseconds, 12 | HoursMinutesSecondsTenths, 13 | DaysHoursMinutes, 14 | DaysHoursMinutesSeconds, 15 | Custom 16 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Enums/UiFont.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Enums; 2 | 3 | public enum UiFont : byte 4 | { 5 | /// 6 | /// droidsansmono.ttf 7 | /// 8 | DroidSansMono, 9 | 10 | /// 11 | /// permanentmarker.ttf 12 | /// 13 | PermanentMarker, 14 | 15 | /// 16 | /// robotocondensed-bold.ttf 17 | /// 18 | RobotoCondensedBold, 19 | 20 | /// 21 | /// robotocondensed-regular.ttf 22 | /// 23 | RobotoCondensedRegular, 24 | 25 | /// 26 | /// PressStart2P-Regular.ttf 27 | /// 28 | PressStart2PRegular 29 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Enums/UiLayer.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Enums; 2 | 3 | public enum UiLayer : byte 4 | { 5 | Overall, 6 | Overlay, 7 | OverlayNonScaled, 8 | HudMenu, 9 | Hud, 10 | Under, 11 | UnderNonScaled, 12 | Inventory, 13 | Crafting, 14 | Contacts, 15 | Clans, 16 | TechTree, 17 | Map, 18 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Exceptions/UiFrameworkException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Oxide.Ext.UiFramework.Exceptions; 4 | 5 | public class UiFrameworkException : Exception 6 | { 7 | public UiFrameworkException(string message) : base(message) { } 8 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Exceptions/UiReferenceException.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.UiElements; 2 | 3 | namespace Oxide.Ext.UiFramework.Exceptions; 4 | 5 | public class UiReferenceException : UiFrameworkException 6 | { 7 | private UiReferenceException(string message) : base(message) { } 8 | 9 | public static void ThrowIfInvalidParent(in UiReference reference) 10 | { 11 | if (!reference.IsValidParent()) throw new UiReferenceException($"{nameof(UiReference)} parent is not a valid parent reference value. Parent: {reference.Parent}"); 12 | } 13 | 14 | public static void ThrowIfInvalidReference(in UiReference reference) 15 | { 16 | if (!reference.IsValidParent()) throw new UiReferenceException($"{nameof(UiReference)} parent is not a valid reference value. Parent: {reference.Parent} Name: {reference.Name}"); 17 | } 18 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Extension/Carbon/CarbonExtension.cs: -------------------------------------------------------------------------------- 1 | #if CARBON 2 | using System; 3 | using API.Assembly; 4 | using Carbon; 5 | 6 | namespace Oxide.Ext.UiFramework 7 | { 8 | public class CarbonExtension : ICarbonExtension 9 | { 10 | public void Awake(EventArgs args) 11 | { 12 | Logger.Log("Carbon.Ext.UiFramework Awake"); 13 | } 14 | 15 | public void OnLoaded(EventArgs args) 16 | { 17 | Logger.Log("Carbon.Ext.UiFramework Loaded"); 18 | } 19 | 20 | public void OnUnloaded(EventArgs args) 21 | { 22 | Logger.Log("Carbon.Ext.UiFramework Unloaded"); 23 | } 24 | } 25 | } 26 | #endif -------------------------------------------------------------------------------- /src/Rust.UIFramework/Extension/Oxide/UiFrameworkExtension.cs: -------------------------------------------------------------------------------- 1 | #if OXIDE 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using Oxide.Core; 5 | using Oxide.Core.Extensions; 6 | 7 | // ReSharper disable once CheckNamespace 8 | namespace Oxide.Ext.UiFramework; 9 | 10 | public class UiFrameworkExtension : Extension 11 | { 12 | public override string Name => "UiFramework"; 13 | public override string Author => "MJSU"; 14 | public override VersionNumber Version { get; } 15 | 16 | public UiFrameworkExtension(ExtensionManager manager) : base(manager) 17 | { 18 | AssemblyName assembly = Assembly.GetExecutingAssembly().GetName(); 19 | Version = new VersionNumber(assembly.Version.Major, assembly.Version.Minor, assembly.Version.Build); 20 | } 21 | 22 | public override IEnumerable GetPreprocessorDirectives() 23 | { 24 | string name = Name.ToUpper(); 25 | yield return $"{name}_EXT"; 26 | for (int i = 0; i <= Version.Minor; i++) 27 | { 28 | yield return $"{name}_EXT_{Version.Major}_{i}"; 29 | } 30 | } 31 | } 32 | #endif -------------------------------------------------------------------------------- /src/Rust.UIFramework/Extensions/ArgExt.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Oxide.Ext.UiFramework.UiElements; 3 | 4 | namespace Oxide.Ext.UiFramework.Extensions; 5 | 6 | public static class ArgExt 7 | { 8 | public static DateTime GetDateTime(this ConsoleSystem.Arg arg, int iArg, DateTime def) 9 | { 10 | string s = arg.GetString(iArg, null); 11 | if (string.IsNullOrEmpty(s)) 12 | { 13 | return def; 14 | } 15 | 16 | DateTime date = DateTime.Parse(s); 17 | return date; 18 | } 19 | 20 | public static UiReference GetParentReference(this ConsoleSystem.Arg arg, int iArg) 21 | { 22 | string s = arg.GetString(iArg); 23 | return new UiReference(s, null); 24 | } 25 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Extensions/OxideCuiExt.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Network; 3 | using Oxide.Ext.UiFramework.Builder; 4 | using Oxide.Ext.UiFramework.Builders; 5 | using Oxide.Ext.UiFramework.Threading; 6 | using Oxide.Game.Rust.Cui; 7 | 8 | namespace Oxide.Ext.UiFramework.Extensions; 9 | 10 | public static class OxideCuiExt 11 | { 12 | public static void AddUiAsync(this CuiElementContainer container, BasePlayer player, string destroyUiName = null) 13 | { 14 | SendInfo send = SendInfoBuilder.Get(player); 15 | AddUiAsync(container, send, destroyUiName); 16 | } 17 | 18 | public static void AddUiAsync(this CuiElementContainer container, Connection connection, string destroyUiName = null) 19 | { 20 | SendInfo send = SendInfoBuilder.Get(connection); 21 | AddUiAsync(container, send, destroyUiName); 22 | } 23 | 24 | public static void AddUiAsync(this CuiElementContainer container, IEnumerable connections, string destroyUiName = null) 25 | { 26 | SendInfo send = SendInfoBuilder.Get(connections); 27 | AddUiAsync(container, send, destroyUiName); 28 | } 29 | 30 | public static void AddUiAsync(this CuiElementContainer container, string destroyUiName = null) 31 | { 32 | SendInfo send = SendInfoBuilder.Get(Net.sv.connections); 33 | AddUiAsync(container, send, destroyUiName); 34 | } 35 | 36 | public static void AddUiAsync(this CuiElementContainer container, SendInfo send, string destroyUiName = null) 37 | { 38 | OxideCuiRequest request = OxideCuiRequest.Create(container, send, destroyUiName); 39 | SendHandler.Enqueue(request); 40 | } 41 | 42 | public static void DestroyUi(Connection connection, string destroyUiName = null) 43 | { 44 | SendInfo send = SendInfoBuilder.Get(connection); 45 | DestroyUi(send, destroyUiName); 46 | } 47 | 48 | public static void DestroyUi(IEnumerable connections, string destroyUiName = null) 49 | { 50 | SendInfo send = SendInfoBuilder.Get(connections); 51 | DestroyUi(send, destroyUiName); 52 | } 53 | 54 | public static void DestroyUi(string destroyUiName = null) 55 | { 56 | SendInfo send = SendInfoBuilder.Get(Net.sv.connections); 57 | DestroyUi(send, destroyUiName); 58 | } 59 | 60 | public static void DestroyUi(SendInfo send, string destroyUiName) 61 | { 62 | BaseBuilder.DestroyUi(send, destroyUiName); 63 | } 64 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Extensions/StringBuilderExt.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Oxide.Ext.UiFramework.Pooling; 3 | 4 | namespace Oxide.Ext.UiFramework.Extensions; 5 | 6 | public static class StringBuilderExt 7 | { 8 | /// 9 | /// Frees a back to the pool returning the created 10 | /// 11 | /// with string and being freed 12 | public static string ToStringAndFree(this StringBuilder sb) 13 | { 14 | string result = sb.ToString(); 15 | UiFrameworkPool.FreeStringBuilder(sb); 16 | return result; 17 | } 18 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Extensions/TypeExt.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Text; 4 | using Oxide.Ext.UiFramework.Pooling; 5 | 6 | namespace Oxide.Ext.UiFramework.Extensions; 7 | 8 | /// 9 | /// Extensions for 10 | /// 11 | internal static class TypeExt 12 | { 13 | /// 14 | /// Returns if the type is 15 | /// 16 | /// Type to check 17 | /// True if type is ; false otherwise 18 | public static bool IsNullable(this Type objectType) => objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Nullable<>); 19 | 20 | /// 21 | /// Returns if the type is 22 | /// 23 | /// Type to check 24 | /// True if type is ; false otherwise 25 | public static Type GetNullableType(this Type objectType) => Nullable.GetUnderlyingType(objectType); 26 | 27 | /// 28 | /// Returns if a type is a value type 29 | /// 30 | /// 31 | /// 32 | public static bool IsValueType(this Type source) => source.IsValueType; 33 | 34 | /// 35 | /// Returns the default value for 36 | /// 37 | /// Type to get default value for 38 | /// default value for 39 | public static object GetDefault(this Type type) => type.IsValueType ? Activator.CreateInstance(type) : null; 40 | 41 | internal static T GetAttribute(this Type type, bool inherit) where T : Attribute => type.GetCustomAttribute(typeof(T), inherit) as T; 42 | internal static bool HasAttribute(this Type type, bool inherit) where T : Attribute => GetAttribute(type, inherit) != null; 43 | 44 | public static string GetRealTypeName(this Type t) 45 | { 46 | if (!t.IsGenericType) 47 | { 48 | return t.Name; 49 | } 50 | 51 | StringBuilder sb = StringBuilderPool.Instance.Get(); 52 | sb.Append(t.Name.AsSpan().Slice(0, t.Name.IndexOf('`'))); 53 | sb.Append('<'); 54 | Type[] args = t.GetGenericArguments(); 55 | for (int index = 0; index < args.Length; index++) 56 | { 57 | Type arg = args[index]; 58 | if (index != 0) 59 | { 60 | sb.Append(','); 61 | } 62 | sb.Append(GetRealTypeName(arg)); 63 | } 64 | sb.Append('>'); 65 | string type = sb.ToString(); 66 | StringBuilderPool.Instance.Free(sb); 67 | return type; 68 | } 69 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Extensions/UiColorExt.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Oxide.Ext.UiFramework.Colors; 3 | using UnityEngine; 4 | 5 | namespace Oxide.Ext.UiFramework.Extensions; 6 | 7 | public static class UiColorExt 8 | { 9 | public static UiColor WithAlpha(this UiColor color, byte alpha) 10 | { 11 | return new UiColor(color._red, color._green, color._blue, alpha); 12 | } 13 | 14 | public static UiColor WithAlpha(this UiColor color, string hex) 15 | { 16 | return color.WithAlpha(byte.Parse(hex, NumberStyles.HexNumber)); 17 | } 18 | 19 | public static UiColor WithAlpha(this UiColor color, int alpha) 20 | { 21 | return color.WithAlpha((byte)alpha); 22 | } 23 | 24 | public static UiColor WithAlpha(this UiColor color, float alpha) 25 | { 26 | return color.WithAlpha((byte)Mathf.Clamp(alpha * 255f, 0, byte.MaxValue)); 27 | } 28 | 29 | public static UiColor MultiplyAlpha(this UiColor color, float alpha) 30 | { 31 | return color.WithAlpha((byte)Mathf.Clamp(color._alpha * alpha, 0, byte.MaxValue)); 32 | } 33 | 34 | public static UiColor ToGrayScale(this UiColor color) 35 | { 36 | float scale = ((Color)color).grayscale; 37 | return new UiColor(new Color(scale, scale, scale)); 38 | } 39 | 40 | public static UiColor Darken(this UiColor color, float percentage) 41 | { 42 | percentage = Mathf.Clamp01(percentage); 43 | byte red = (byte)Mathf.Clamp(color._red * (1 - percentage), 0, byte.MaxValue); 44 | byte green = (byte)Mathf.Clamp(color._green * (1 - percentage), 0, byte.MaxValue); 45 | byte blue = (byte)Mathf.Clamp(color._blue * (1 - percentage), 0, byte.MaxValue); 46 | 47 | return new UiColor(red, green, blue, color._alpha); 48 | } 49 | 50 | public static UiColor Lighten(this UiColor color, float percentage) 51 | { 52 | percentage = Mathf.Clamp01(percentage); 53 | float red = (byte)Mathf.Clamp(byte.MaxValue - color._red * percentage + color._red, 0, byte.MaxValue); 54 | float green = (byte)Mathf.Clamp(byte.MaxValue - color._green * percentage + color._red, 0, byte.MaxValue); 55 | float blue = (byte)Mathf.Clamp(byte.MaxValue - color._blue * percentage + color._red, 0, byte.MaxValue); 56 | 57 | return new UiColor(red, green, blue, color._alpha); 58 | } 59 | 60 | public static UiColor Lerp(this UiColor start, UiColor end, float value) 61 | { 62 | return new UiColor(start._red + (end._red - start._red) * value, start._green + (end._green - start._green) * value, start._blue + (end._blue - start._blue) * value, start._alpha + (end._alpha - start._alpha) * value); 63 | } 64 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Extensions/UiReferenceExt.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.UiElements; 2 | 3 | namespace Oxide.Ext.UiFramework.Extensions; 4 | 5 | public static class UiReferenceExt 6 | { 7 | public static UiReference WithName(in this UiReference element, string name) => new(element.Parent, name); 8 | public static UiReference WithParent(in this UiReference element, string parent) => new(parent, element.Name); 9 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Helpers/GenericMath.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Oxide.Ext.UiFramework.Exceptions; 3 | 4 | namespace Oxide.Ext.UiFramework.Helpers; 5 | 6 | public static class GenericMath 7 | { 8 | public static T Add(T left, T right) where T : struct 9 | { 10 | Type type = typeof(T); 11 | if (type == typeof(int)) return GenericsUtil.Cast( GenericsUtil.Cast(left) + GenericsUtil.Cast(right)); 12 | if (type == typeof(float)) return GenericsUtil.Cast( GenericsUtil.Cast(left) + GenericsUtil.Cast(right)); 13 | if (type == typeof(double)) return GenericsUtil.Cast( GenericsUtil.Cast(left) + GenericsUtil.Cast(right)); 14 | if (type == typeof(long)) return GenericsUtil.Cast( GenericsUtil.Cast(left) + GenericsUtil.Cast(right)); 15 | if (type == typeof(uint)) return GenericsUtil.Cast( GenericsUtil.Cast(left) + GenericsUtil.Cast(right)); 16 | if (type == typeof(ulong)) return GenericsUtil.Cast( GenericsUtil.Cast(left) + GenericsUtil.Cast(right)); 17 | 18 | throw new UiFrameworkException($"{typeof(T).Name} is not a supported numeric type"); 19 | } 20 | 21 | public static T Subtract(T left, T right) where T : struct 22 | { 23 | Type type = typeof(T); 24 | if (type == typeof(int)) return GenericsUtil.Cast( GenericsUtil.Cast(left) - GenericsUtil.Cast(right)); 25 | if (type == typeof(float)) return GenericsUtil.Cast( GenericsUtil.Cast(left) - GenericsUtil.Cast(right)); 26 | if (type == typeof(double)) return GenericsUtil.Cast( GenericsUtil.Cast(left) - GenericsUtil.Cast(right)); 27 | if (type == typeof(long)) return GenericsUtil.Cast( GenericsUtil.Cast(left) - GenericsUtil.Cast(right)); 28 | if (type == typeof(uint)) return GenericsUtil.Cast( GenericsUtil.Cast(left) - GenericsUtil.Cast(right)); 29 | if (type == typeof(ulong)) return GenericsUtil.Cast( GenericsUtil.Cast(left) - GenericsUtil.Cast(right)); 30 | 31 | throw new UiFrameworkException($"{typeof(T).Name} is not a supported numeric type"); 32 | } 33 | 34 | public static T Multiply(T left, T right) where T : struct 35 | { 36 | Type type = typeof(T); 37 | if (type == typeof(int)) return GenericsUtil.Cast( GenericsUtil.Cast(left) * GenericsUtil.Cast(right)); 38 | if (type == typeof(float)) return GenericsUtil.Cast( GenericsUtil.Cast(left) * GenericsUtil.Cast(right)); 39 | if (type == typeof(double)) return GenericsUtil.Cast( GenericsUtil.Cast(left) * GenericsUtil.Cast(right)); 40 | if (type == typeof(long)) return GenericsUtil.Cast( GenericsUtil.Cast(left) * GenericsUtil.Cast(right)); 41 | if (type == typeof(uint)) return GenericsUtil.Cast( GenericsUtil.Cast(left) * GenericsUtil.Cast(right)); 42 | if (type == typeof(ulong)) return GenericsUtil.Cast( GenericsUtil.Cast(left) * GenericsUtil.Cast(right)); 43 | 44 | throw new UiFrameworkException($"{typeof(T).Name} is not a supported numeric type"); 45 | } 46 | 47 | public static T Divide(T left, T right) where T : struct 48 | { 49 | Type type = typeof(T); 50 | if (type == typeof(int)) return GenericsUtil.Cast( GenericsUtil.Cast(left) / GenericsUtil.Cast(right)); 51 | if (type == typeof(float)) return GenericsUtil.Cast( GenericsUtil.Cast(left) / GenericsUtil.Cast(right)); 52 | if (type == typeof(double)) return GenericsUtil.Cast( GenericsUtil.Cast(left) / GenericsUtil.Cast(right)); 53 | if (type == typeof(long)) return GenericsUtil.Cast( GenericsUtil.Cast(left) / GenericsUtil.Cast(right)); 54 | if (type == typeof(uint)) return GenericsUtil.Cast( GenericsUtil.Cast(left) / GenericsUtil.Cast(right)); 55 | if (type == typeof(ulong)) return GenericsUtil.Cast( GenericsUtil.Cast(left) / GenericsUtil.Cast(right)); 56 | 57 | throw new UiFrameworkException($"{typeof(T).Name} is not a supported numeric type"); 58 | } 59 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Json/JsonBinaryWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Runtime.CompilerServices; 6 | using System.Text; 7 | using Network; 8 | using Oxide.Ext.UiFramework.Benchmarks; 9 | using Oxide.Ext.UiFramework.Pooling; 10 | 11 | namespace Oxide.Ext.UiFramework.Json; 12 | 13 | public class JsonBinaryWriter : BasePoolable 14 | { 15 | private const int SegmentSize = 4096; 16 | 17 | private readonly List> _segments = new(100); 18 | private short _charIndex; 19 | private readonly char[] _charBuffer = new char[SegmentSize * 2]; 20 | 21 | public void Write(char character) 22 | { 23 | _charBuffer[_charIndex] = character; 24 | _charIndex++; 25 | if (_charIndex >= SegmentSize) 26 | { 27 | Flush(); 28 | } 29 | } 30 | 31 | public void Write(ReadOnlySpan text) 32 | { 33 | int length = text.Length; 34 | Span buffer = _charBuffer.AsSpan(); 35 | int charIndex = _charIndex; 36 | for (int i = 0; i < length; i++) 37 | { 38 | buffer[charIndex + i] = text[i]; 39 | } 40 | _charIndex += (short)length; 41 | if (_charIndex >= SegmentSize) 42 | { 43 | Flush(); 44 | } 45 | } 46 | 47 | private void Flush() 48 | { 49 | if (_charIndex == 0) 50 | { 51 | return; 52 | } 53 | 54 | byte[] segment = ArrayPool.Shared.Rent(SegmentSize * 2); 55 | 56 | int size = Encoding.UTF8.GetBytes(_charBuffer, 0, _charIndex, segment, 0); 57 | _segments.Add(new SizedArray(segment, size)); 58 | _charIndex = 0; 59 | } 60 | 61 | public int WriteToArray(byte[] bytes) 62 | { 63 | Flush(); 64 | int writeIndex = 0; 65 | for (int i = 0; i < _segments.Count; i++) 66 | { 67 | SizedArray segment = _segments[i]; 68 | Buffer.BlockCopy(segment.Array, 0, bytes, writeIndex, segment.Size); 69 | writeIndex += segment.Size; 70 | } 71 | 72 | return writeIndex; 73 | } 74 | 75 | public uint GetSize() 76 | { 77 | uint size = 0; 78 | int count = _segments.Count; 79 | for (int i = 0; i < count; i++) 80 | { 81 | size += (uint)_segments[i].Size; 82 | } 83 | 84 | return size; 85 | } 86 | 87 | public void WriteToNetwork(NetWrite write) 88 | { 89 | Flush(); 90 | write.UInt32(GetSize()); 91 | WriteToNetwork((Stream)write); 92 | } 93 | 94 | #if BENCHMARKS 95 | internal void WriteToNetwork(BenchmarkNetWrite write) 96 | { 97 | Flush(); 98 | WriteToNetwork((Stream)write); 99 | } 100 | #endif 101 | 102 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 103 | private void WriteToNetwork(Stream write) 104 | { 105 | int count = _segments.Count; 106 | for (int i = 0; i < count; i++) 107 | { 108 | SizedArray segment = _segments[i]; 109 | write.Write(segment.Array, 0, segment.Size); 110 | } 111 | } 112 | 113 | public byte[] ToArray() 114 | { 115 | Flush(); 116 | byte[] bytes = new byte[GetSize()]; 117 | WriteToArray(bytes); 118 | return bytes; 119 | } 120 | 121 | protected override void LeavePool() 122 | { 123 | 124 | } 125 | 126 | protected override void EnterPool() 127 | { 128 | for (int index = 0; index < _segments.Count; index++) 129 | { 130 | byte[] bytes = _segments[index].Array; 131 | ArrayPool.Shared.Return(bytes); 132 | } 133 | _segments.Clear(); 134 | _charIndex = 0; 135 | } 136 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Json/SizedArray.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Json; 2 | 3 | public readonly struct SizedArray 4 | { 5 | public readonly T[] Array; 6 | public readonly int Size; 7 | 8 | public SizedArray(T[] array, int size) 9 | { 10 | Array = array; 11 | Size = size; 12 | } 13 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Offsets/BaseOffset.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Offsets; 2 | 3 | public abstract class BaseOffset 4 | { 5 | public float XMin; 6 | public float YMin; 7 | public float XMax; 8 | public float YMax; 9 | private readonly UiOffset _initialState; 10 | 11 | protected BaseOffset(float xMin, float yMin, float xMax, float yMax) 12 | { 13 | XMin = xMin; 14 | YMin = yMin; 15 | XMax = xMin + xMax; 16 | YMax = yMin + yMax; 17 | _initialState = new UiOffset(XMin, YMin, XMax, YMax); 18 | } 19 | 20 | public UiOffset ToOffset() 21 | { 22 | return new UiOffset(XMin, YMin, XMax, YMax); 23 | } 24 | 25 | public void Reset() 26 | { 27 | XMin = _initialState.Min.x; 28 | YMin = _initialState.Min.y; 29 | XMax = _initialState.Max.x; 30 | YMax = _initialState.Max.y; 31 | } 32 | 33 | public static implicit operator UiOffset(BaseOffset offset) => offset.ToOffset(); 34 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Offsets/GridOffset.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Offsets; 2 | 3 | public class GridOffset : BaseOffset 4 | { 5 | public readonly int NumCols; 6 | public readonly int NumRows; 7 | public readonly float Width; 8 | public readonly float Height; 9 | 10 | public GridOffset(float xMin, float yMin, float xMax, float yMax, int numCols, int numRows, float width, float height) : base(xMin, yMin, xMax, yMax) 11 | { 12 | NumCols = numCols; 13 | NumRows = numRows; 14 | Width = width; 15 | Height = height; 16 | } 17 | 18 | public void MoveCols(int cols) 19 | { 20 | MoveCols((float)cols); 21 | } 22 | 23 | public void MoveCols(float cols) 24 | { 25 | float distance = cols / NumCols * Width; 26 | XMin += distance; 27 | XMax += distance; 28 | 29 | if (XMax > Width) 30 | { 31 | XMin -= Width; 32 | XMax -= Width; 33 | MoveRows(1); 34 | } 35 | } 36 | 37 | public void MoveRows(int rows) 38 | { 39 | float distance = rows / (float)NumRows * Height; 40 | YMin -= distance; 41 | YMax -= distance; 42 | } 43 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Offsets/GridOffsetBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Oxide.Ext.UiFramework.Offsets; 4 | 5 | public class GridOffsetBuilder 6 | { 7 | private readonly int _numCols; 8 | private readonly int _numRows; 9 | private readonly UiOffset _area; 10 | private readonly float _width; 11 | private readonly float _height; 12 | private int _rowHeight = 1; 13 | private int _rowOffset; 14 | private int _colWidth = 1; 15 | private int _colOffset; 16 | private int _xPad; 17 | private int _yPad; 18 | 19 | public GridOffsetBuilder(int size, UiOffset area) : this(size, size, area) 20 | { 21 | 22 | } 23 | 24 | public GridOffsetBuilder(int numCols, int numRows, UiOffset area) 25 | { 26 | if (numCols <= 0) throw new ArgumentOutOfRangeException(nameof(numCols)); 27 | if (numRows <= 0) throw new ArgumentOutOfRangeException(nameof(numCols)); 28 | _numCols = numCols; 29 | _numRows = numRows; 30 | _area = area; 31 | _width = area.Max.x - area.Min.x; 32 | _height = area.Max.y - area.Min.y; 33 | } 34 | 35 | public GridOffsetBuilder SetRowHeight(int height) 36 | { 37 | if (height <= 0) throw new ArgumentOutOfRangeException(nameof(height)); 38 | _rowHeight = height; 39 | return this; 40 | } 41 | 42 | public GridOffsetBuilder SetRowOffset(int offset) 43 | { 44 | if (offset < 0) throw new ArgumentOutOfRangeException(nameof(offset)); 45 | _rowOffset = offset; 46 | return this; 47 | } 48 | 49 | public GridOffsetBuilder SetColWidth(int width) 50 | { 51 | if (width <= 0) throw new ArgumentOutOfRangeException(nameof(width)); 52 | _colWidth = width; 53 | return this; 54 | } 55 | 56 | public GridOffsetBuilder SetColOffset(int offset) 57 | { 58 | if (offset < 0) throw new ArgumentOutOfRangeException(nameof(offset)); 59 | _colOffset = offset; 60 | return this; 61 | } 62 | 63 | public GridOffsetBuilder SetPadding(int padding) 64 | { 65 | _xPad = padding; 66 | _yPad = padding; 67 | return this; 68 | } 69 | 70 | public GridOffsetBuilder SetPadding(int xPad, int yPad) 71 | { 72 | _xPad = xPad; 73 | _yPad = yPad; 74 | return this; 75 | } 76 | 77 | public GridOffsetBuilder SetRowPadding(int padding) 78 | { 79 | _xPad = padding; 80 | return this; 81 | } 82 | 83 | public GridOffsetBuilder SetColPadding(int padding) 84 | { 85 | _yPad = padding; 86 | return this; 87 | } 88 | 89 | public GridOffset Build() 90 | { 91 | float xMin = _area.Min.x; 92 | float yMin = _area.Max.y - _rowHeight / (float)_numRows * _height; 93 | float xMax = _colWidth / (float)_numCols * _width; 94 | float yMax = _rowHeight / (float)_numRows * _height; 95 | 96 | if (_colOffset != 0) 97 | { 98 | int size = (int)(_colOffset / (float)_numCols * _width); 99 | xMin += size; 100 | xMax += size; 101 | } 102 | 103 | if (_rowOffset != 0) 104 | { 105 | int size = (int)(_rowOffset / (float)_numRows * _height); 106 | yMin += size; 107 | yMax += size; 108 | } 109 | 110 | xMin += _xPad; 111 | xMax -= _xPad * 2; 112 | yMin += _yPad; 113 | yMax -= _yPad * 2; 114 | 115 | return new GridOffset(xMin, yMin, xMax, yMax, _numCols, _numRows, _width, _height); 116 | } 117 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Offsets/UiOffset.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Oxide.Ext.UiFramework.Offsets; 4 | 5 | public readonly struct UiOffset 6 | { 7 | public static readonly UiOffset None = new(0, 0, 0, 0); 8 | public static readonly UiOffset Scaled = new(1280, 720); 9 | 10 | public readonly Vector2 Min; 11 | public readonly Vector2 Max; 12 | 13 | public Vector2 Size => Max - Min; 14 | public float Width => Max.x - Min.x; 15 | public float Height => Max.y - Min.y; 16 | 17 | public UiOffset(int width, int height) : this(-width / 2f, -height / 2f, width / 2f, height / 2f) { } 18 | 19 | public UiOffset(float xMin, float yMin, float xMax, float yMax) 20 | { 21 | Min = new Vector2(xMin, yMin); 22 | Max = new Vector2(xMax, yMax); 23 | } 24 | 25 | public static UiOffset CreateRect(int x, int y, int width, int height) 26 | { 27 | return new UiOffset(x, y, x + width, y + height); 28 | } 29 | 30 | public override string ToString() 31 | { 32 | return $"({Min.x:0}, {Min.y:0}) ({Max.x:0}, {Max.y:0}) WxH:({Width} x {Height})"; 33 | } 34 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Pooling/BasePool.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Pooling; 2 | 3 | /// 4 | /// Represents a BasePool in UiFramework 5 | /// 6 | /// Type being pooled 7 | public abstract class BasePool : IPool where T : class 8 | { 9 | private readonly T[] _pool; 10 | private readonly object _lock = new(); 11 | private int _index; 12 | 13 | /// 14 | /// Base Pool Constructor 15 | /// 16 | /// Max Size of the pool 17 | protected BasePool(int maxSize) 18 | { 19 | _pool = new T[maxSize]; 20 | UiFrameworkPool.AddPool(this); 21 | } 22 | 23 | /// 24 | /// Returns an element from the pool if it exists else it creates a new one 25 | /// 26 | /// 27 | public T Get() 28 | { 29 | T item = null; 30 | 31 | lock (_lock) 32 | { 33 | if (_index < _pool.Length) 34 | { 35 | item = _pool[_index]; 36 | _pool[_index] = null; 37 | _index++; 38 | } 39 | } 40 | 41 | item ??= CreateNew(); 42 | OnGetItem(item); 43 | return item; 44 | } 45 | 46 | /// 47 | /// Creates new type of T 48 | /// 49 | /// Newly created type of T 50 | protected abstract T CreateNew(); 51 | 52 | /// 53 | /// Frees an item back to the pool 54 | /// 55 | /// Item being freed 56 | public void Free(T item) => Free(ref item); 57 | 58 | /// 59 | /// Frees an item back to the pool 60 | /// 61 | /// Item being freed 62 | private void Free(ref T item) 63 | { 64 | if (item == null) 65 | { 66 | return; 67 | } 68 | 69 | if (!OnFreeItem(ref item)) 70 | { 71 | return; 72 | } 73 | 74 | lock (_lock) 75 | { 76 | if (_index != 0) 77 | { 78 | _index--; 79 | _pool[_index] = item; 80 | } 81 | } 82 | 83 | item = null; 84 | } 85 | 86 | /// 87 | /// Called when an item is retrieved from the pool 88 | /// 89 | /// Item being retrieved 90 | protected virtual void OnGetItem(T item) { } 91 | 92 | /// 93 | /// Returns if an item can be freed to the pool 94 | /// 95 | /// Item to be freed 96 | /// True if can be freed; false otherwise 97 | protected virtual bool OnFreeItem(ref T item) => true; 98 | 99 | public void Clear() 100 | { 101 | lock (_lock) 102 | { 103 | for (int index = 0; index < _pool.Length; index++) 104 | { 105 | _pool[index] = null; 106 | _index = 0; 107 | } 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Pooling/BasePoolable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Oxide.Ext.UiFramework.Pooling; 4 | 5 | /// 6 | /// Represents a poolable object 7 | /// 8 | public abstract class BasePoolable : IDisposable 9 | { 10 | internal bool Disposed; 11 | 12 | /// 13 | /// Returns if the object should be pooled. 14 | /// This field is set to true when leaving the pool. 15 | /// If the object instantiated using new() outside the pool it will be false 16 | /// 17 | private bool _shouldPool; 18 | private IPool _pool; 19 | 20 | internal void OnInit(IPool pool) 21 | { 22 | _pool = pool; 23 | } 24 | 25 | internal void EnterPoolInternal() 26 | { 27 | EnterPool(); 28 | _shouldPool = false; 29 | Disposed = true; 30 | } 31 | 32 | internal void LeavePoolInternal() 33 | { 34 | _shouldPool = true; 35 | Disposed = false; 36 | LeavePool(); 37 | } 38 | 39 | /// 40 | /// Called when the object is returned to the pool. 41 | /// Can be overriden in child classes to cleanup used data 42 | /// 43 | protected virtual void EnterPool() 44 | { 45 | 46 | } 47 | 48 | /// 49 | /// Called when the object leaves the pool. 50 | /// Can be overriden in child classes to set the initial object state 51 | /// 52 | protected virtual void LeavePool() 53 | { 54 | 55 | } 56 | 57 | public virtual void Dispose() 58 | { 59 | if (!_shouldPool) 60 | { 61 | return; 62 | } 63 | 64 | if (Disposed) 65 | { 66 | throw new ObjectDisposedException(GetType().Name); 67 | } 68 | 69 | _pool.Free(this); 70 | } 71 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Pooling/HashPool.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Plugins; 2 | 3 | namespace Oxide.Ext.UiFramework.Pooling; 4 | 5 | /// 6 | /// Represents a pool for Hash<TKey, TValue> 7 | /// 8 | /// 9 | /// 10 | public class HashPool : BasePool> 11 | { 12 | public static readonly IPool> Instance; 13 | 14 | static HashPool() 15 | { 16 | Instance = new HashPool(); 17 | } 18 | 19 | private HashPool() : base(128) { } 20 | 21 | protected override Hash CreateNew() => new(); 22 | 23 | /// 24 | protected override bool OnFreeItem(ref Hash item) 25 | { 26 | item.Clear(); 27 | return true; 28 | } 29 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Pooling/IPool.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Pooling; 2 | 3 | /// 4 | /// Represents a pool 5 | /// 6 | public interface IPool 7 | { 8 | void Clear(); 9 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Pooling/IPool{T}.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Pooling; 2 | 3 | /// 4 | /// Represents a pool of type T 5 | /// 6 | /// Type to be pooled 7 | public interface IPool : IPool 8 | { 9 | /// 10 | /// Returns the Pooled type or a new instance if pool is empty. 11 | /// 12 | /// 13 | T Get(); 14 | 15 | /// 16 | /// Returns the pooled type back to the pool 17 | /// 18 | /// 19 | void Free(T item); 20 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Pooling/ListPool.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Oxide.Ext.UiFramework.Pooling; 4 | 5 | /// 6 | /// Represents a pool for 7 | /// 8 | /// Type that will be in the list 9 | public class ListPool : BasePool> 10 | { 11 | public static readonly IPool> Instance; 12 | 13 | static ListPool() 14 | { 15 | Instance = new ListPool(); 16 | } 17 | 18 | private ListPool() : base(128) { } 19 | 20 | protected override List CreateNew() => []; 21 | 22 | /// 23 | protected override bool OnFreeItem(ref List item) 24 | { 25 | item.Clear(); 26 | return true; 27 | } 28 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Pooling/ObjectPool.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Pooling; 2 | 3 | public class ObjectPool : BasePool where T : BasePoolable, new() 4 | { 5 | public static readonly IPool Instance = new ObjectPool(); 6 | 7 | private ObjectPool() : base(1024) { } 8 | 9 | protected override BasePoolable CreateNew() 10 | { 11 | T obj = new(); 12 | obj.OnInit(this); 13 | return obj; 14 | } 15 | 16 | protected override void OnGetItem(BasePoolable item) 17 | { 18 | item.LeavePoolInternal(); 19 | } 20 | 21 | protected override bool OnFreeItem(ref BasePoolable item) 22 | { 23 | if (item.Disposed) 24 | { 25 | return false; 26 | } 27 | 28 | item.EnterPoolInternal(); 29 | return true; 30 | } 31 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Pooling/StringBuilderPool.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Oxide.Ext.UiFramework.Pooling; 4 | 5 | /// 6 | /// Pool for StringBuilders 7 | /// 8 | public class StringBuilderPool : BasePool 9 | { 10 | public static readonly IPool Instance; 11 | 12 | static StringBuilderPool() 13 | { 14 | Instance = new StringBuilderPool(); 15 | } 16 | 17 | private StringBuilderPool() : base(64) { } 18 | 19 | protected override StringBuilder CreateNew() => new(); 20 | 21 | /// 22 | protected override bool OnFreeItem(ref StringBuilder item) 23 | { 24 | item.Length = 0; 25 | return true; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Pooling/UiFrameworkPool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Oxide.Plugins; 5 | 6 | namespace Oxide.Ext.UiFramework.Pooling; 7 | 8 | public static class UiFrameworkPool 9 | { 10 | private static readonly Hash Pools = new(); 11 | 12 | /// 13 | /// Returns a pooled object of type T 14 | /// Must inherit from and have an empty default constructor 15 | /// 16 | /// Type to be returned 17 | /// Pooled object of type T 18 | public static T Get() where T : BasePoolable, new() 19 | { 20 | return (T)ObjectPool.Instance.Get(); 21 | } 22 | 23 | /// 24 | /// Returns a back into the pool 25 | /// 26 | /// Object to free 27 | /// Type of object being freed 28 | internal static void Free(T value) where T : BasePoolable, new() 29 | { 30 | ObjectPool.Instance.Free(value); 31 | } 32 | 33 | /// 34 | /// Returns a pooled 35 | /// 36 | /// Type for the list 37 | /// Pooled List 38 | public static List GetList() 39 | { 40 | return ListPool.Instance.Get(); 41 | } 42 | 43 | /// 44 | /// Returns a pooled 45 | /// 46 | /// Type for the key 47 | /// Type for the value 48 | /// Pooled Hash 49 | public static Hash GetHash() 50 | { 51 | return HashPool.Instance.Get(); 52 | } 53 | 54 | /// 55 | /// Returns a pooled 56 | /// 57 | /// Pooled 58 | public static StringBuilder GetStringBuilder() 59 | { 60 | return StringBuilderPool.Instance.Get(); 61 | } 62 | 63 | /// 64 | /// Free's a pooled 65 | /// 66 | /// List to be freed 67 | /// Type of the list 68 | public static void FreeList(List list) 69 | { 70 | ListPool.Instance.Free(list); 71 | } 72 | 73 | /// 74 | /// Frees a pooled 75 | /// 76 | /// Hash to be freed 77 | /// Type for key 78 | /// Type for value 79 | public static void FreeHash(Hash hash) 80 | { 81 | HashPool.Instance.Free(hash); 82 | } 83 | 84 | /// 85 | /// Frees a back to the pool 86 | /// 87 | /// StringBuilder being freed 88 | public static void FreeStringBuilder(StringBuilder sb) 89 | { 90 | StringBuilderPool.Instance.Free(sb); 91 | } 92 | 93 | public static void AddPool(BasePool pool) where TType : class 94 | { 95 | Pools[typeof(TType)] = pool; 96 | } 97 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Positions/BasePosition.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Positions; 2 | 3 | public abstract class BasePosition 4 | { 5 | public float XMin; 6 | public float YMin; 7 | public float XMax; 8 | public float YMax; 9 | protected readonly UiPosition InitialState; 10 | 11 | protected BasePosition(float xMin, float yMin, float xMax, float yMax) 12 | { 13 | XMin = xMin; 14 | YMin = yMin; 15 | XMax = xMax; 16 | YMax = yMax; 17 | InitialState = new UiPosition(XMin, YMin, XMax, YMax); 18 | } 19 | 20 | public UiPosition ToPosition() 21 | { 22 | return new UiPosition(XMin, YMin, XMax, YMax); 23 | } 24 | 25 | public void Reset() 26 | { 27 | XMin = InitialState.Min.x; 28 | YMin = InitialState.Min.y; 29 | XMax = InitialState.Max.x; 30 | YMax = InitialState.Max.y; 31 | } 32 | 33 | public override string ToString() 34 | { 35 | return $"{XMin.ToString()} {YMin.ToString()} {XMax.ToString()} {YMax.ToString()}"; 36 | } 37 | 38 | public static implicit operator UiPosition(BasePosition pos) => pos.ToPosition(); 39 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Positions/GridPosition.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.Positions; 2 | 3 | public class GridPosition : BasePosition 4 | { 5 | public readonly float NumCols; 6 | public readonly float NumRows; 7 | 8 | public GridPosition(float xMin, float yMin, float xMax, float yMax, float numCols, float numRows) : base(xMin, yMin, xMax, yMax) 9 | { 10 | NumCols = numCols; 11 | NumRows = numRows; 12 | } 13 | 14 | public void MoveCols(int cols) 15 | { 16 | XMin += cols / NumCols; 17 | XMax += cols / NumCols; 18 | 19 | if (XMax > 1) 20 | { 21 | XMin -= 1; 22 | XMax -= 1; 23 | MoveRows(1); 24 | } 25 | } 26 | 27 | public void MoveCols(float cols) 28 | { 29 | XMin += cols / NumCols; 30 | XMax += cols / NumCols; 31 | 32 | if (XMax > 1) 33 | { 34 | XMin -= 1; 35 | XMax -= 1; 36 | MoveRows(1); 37 | } 38 | } 39 | 40 | public void MoveRows(int rows) 41 | { 42 | YMin -= rows / NumRows; 43 | YMax -= rows / NumRows; 44 | } 45 | 46 | public float GetScrollViewYMin(int totalRows) 47 | { 48 | return InitialState.Min.y - (totalRows / NumRows); 49 | } 50 | 51 | public float GetScrollViewYMin(int count, int countPerRow) 52 | { 53 | int totalRows = count / countPerRow; 54 | if (count % countPerRow != 0) 55 | { 56 | totalRows++; 57 | } 58 | 59 | return GetScrollViewYMin(totalRows); 60 | } 61 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Positions/GridPositionBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Oxide.Ext.UiFramework.Positions; 4 | 5 | public class GridPositionBuilder 6 | { 7 | private readonly float _numCols; 8 | private readonly float _numRows; 9 | private int _rowHeight = 1; 10 | private int _rowOffset; 11 | private int _colWidth = 1; 12 | private int _colOffset; 13 | private float _xPad; 14 | private float _yPad; 15 | 16 | public GridPositionBuilder(int size) : this(size, size) 17 | { 18 | } 19 | 20 | public GridPositionBuilder(int numCols, int numRows) 21 | { 22 | if (numCols <= 0) throw new ArgumentOutOfRangeException(nameof(numCols)); 23 | if (numRows <= 0) throw new ArgumentOutOfRangeException(nameof(numCols)); 24 | _numCols = numCols; 25 | _numRows = numRows; 26 | } 27 | 28 | public GridPositionBuilder SetRowHeight(int height) 29 | { 30 | if (height <= 0) throw new ArgumentOutOfRangeException(nameof(height)); 31 | _rowHeight = height; 32 | return this; 33 | } 34 | 35 | public GridPositionBuilder SetRowOffset(int offset) 36 | { 37 | if (offset < 0) throw new ArgumentOutOfRangeException(nameof(offset)); 38 | _rowOffset = offset; 39 | return this; 40 | } 41 | 42 | public GridPositionBuilder SetColWidth(int width) 43 | { 44 | if (width <= 0) throw new ArgumentOutOfRangeException(nameof(width)); 45 | _colWidth = width; 46 | return this; 47 | } 48 | 49 | public GridPositionBuilder SetColOffset(int offset) 50 | { 51 | if (offset < 0) throw new ArgumentOutOfRangeException(nameof(offset)); 52 | _colOffset = offset; 53 | return this; 54 | } 55 | 56 | public GridPositionBuilder SetPadding(float padding) 57 | { 58 | _xPad = padding; 59 | _yPad = padding; 60 | return this; 61 | } 62 | 63 | public GridPositionBuilder SetPadding(float xPad, float yPad) 64 | { 65 | _xPad = xPad; 66 | _yPad = yPad; 67 | return this; 68 | } 69 | 70 | public GridPositionBuilder SetRowPadding(float padding) 71 | { 72 | _xPad = padding; 73 | return this; 74 | } 75 | 76 | public GridPositionBuilder SetColPadding(float padding) 77 | { 78 | _yPad = padding; 79 | return this; 80 | } 81 | 82 | public GridPosition Build() 83 | { 84 | float xMin = 0; 85 | float yMin = 1 - _rowHeight / _numRows; 86 | float xMax = _colWidth / _numCols; 87 | float yMax = 1; 88 | 89 | if (_colOffset != 0) 90 | { 91 | float size = _colOffset / _numCols; 92 | xMin += size; 93 | xMax += size; 94 | } 95 | 96 | if (_rowOffset != 0) 97 | { 98 | float size = _rowOffset / _numRows; 99 | yMin -= size; 100 | yMax -= size; 101 | } 102 | 103 | xMin += _xPad; 104 | xMax -= _xPad; 105 | yMin += _yPad; 106 | yMax -= _yPad; 107 | 108 | return new GridPosition(xMin, yMin, xMax, yMax, _numCols, _numRows); 109 | } 110 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Positions/UiPosition.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Extensions; 2 | using UnityEngine; 3 | 4 | namespace Oxide.Ext.UiFramework.Positions; 5 | 6 | public readonly struct UiPosition 7 | { 8 | public static readonly UiPosition None = new(0, 0, 0, 0); 9 | public static readonly UiPosition Full = new(0, 0, 1, 1); 10 | public static readonly UiPosition HorizontalPaddedFull = Full.SliceHorizontal(0.01f, 0.99f); 11 | public static readonly UiPosition VerticalPaddedFull = Full.SliceVertical(0.01f, 0.99f); 12 | public static readonly UiPosition TopLeft = new(0, 1, 0, 1); 13 | public static readonly UiPosition MiddleLeft = new(0, .5f, 0, .5f); 14 | public static readonly UiPosition BottomLeft = new(0, 0, 0, 0); 15 | public static readonly UiPosition TopMiddle = new(.5f, 1, .5f, 1); 16 | public static readonly UiPosition MiddleMiddle = new(.5f, .5f, .5f, .5f); 17 | public static readonly UiPosition BottomMiddle = new(.5f, 0, .5f, 0); 18 | public static readonly UiPosition TopRight = new(1, 1, 1, 1); 19 | public static readonly UiPosition MiddleRight = new(1, .5f, 1, .5f); 20 | public static readonly UiPosition BottomRight = new(1, 0, 1, 0); 21 | 22 | public static readonly UiPosition Top = new(0, 1, 1, 1); 23 | public static readonly UiPosition Bottom = new(0, 0, 1, 0); 24 | public static readonly UiPosition Left = new(0, 0, 0, 1); 25 | public static readonly UiPosition Right = new(1, 0, 1, 1); 26 | 27 | public static readonly UiPosition LeftHalf = new(0, 0, 0.5f, 1); 28 | public static readonly UiPosition TopHalf = new(0, 0.5f, 1, 1); 29 | public static readonly UiPosition RightHalf = new(0.5f, 0, 1, 1); 30 | public static readonly UiPosition BottomHalf = new(0, 0, 1, 0.5f); 31 | 32 | public readonly Vector2 Min; 33 | public readonly Vector2 Max; 34 | 35 | public UiPosition(float xMin, float yMin, float xMax, float yMax) 36 | { 37 | Min = new Vector2(xMin, yMin); 38 | Max = new Vector2(xMax, yMax); 39 | } 40 | 41 | public override string ToString() 42 | { 43 | return $"({Min.x:0.####}, {Min.y:0.####}) ({Max.x:0.####}, {Max.y:0.####})"; 44 | } 45 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Threading/BaseUiRequest.cs: -------------------------------------------------------------------------------- 1 | using Network; 2 | using Oxide.Ext.UiFramework.Pooling; 3 | 4 | namespace Oxide.Ext.UiFramework.Threading; 5 | 6 | public abstract class BaseUiRequest : BasePoolable 7 | { 8 | protected SendInfo Send; 9 | 10 | protected void Init(SendInfo send) 11 | { 12 | Send = send; 13 | } 14 | 15 | protected override void EnterPool() 16 | { 17 | base.EnterPool(); 18 | if (Send.connections != null) 19 | { 20 | ListPool.Instance.Free(Send.connections); 21 | } 22 | Send = default; 23 | } 24 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Threading/IUiRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Oxide.Ext.UiFramework.Threading; 4 | 5 | public interface IUiRequest : IDisposable 6 | { 7 | public void SendUi(); 8 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Threading/OxideCuiRequest.cs: -------------------------------------------------------------------------------- 1 | using Network; 2 | using Oxide.Ext.UiFramework.Pooling; 3 | using Oxide.Game.Rust.Cui; 4 | 5 | namespace Oxide.Ext.UiFramework.Threading; 6 | 7 | public class OxideCuiRequest : BaseUiRequest, IUiRequest 8 | { 9 | private CuiElementContainer _container; 10 | private string _destroyUiName; 11 | 12 | public static OxideCuiRequest Create(CuiElementContainer container, SendInfo send, string destroyUiName) 13 | { 14 | OxideCuiRequest request = UiFrameworkPool.Get(); 15 | request.Init(container, send, destroyUiName); 16 | return request; 17 | } 18 | 19 | private void Init(CuiElementContainer container, SendInfo send, string destroyUiName) 20 | { 21 | base.Init(send); 22 | _container = container; 23 | _destroyUiName = destroyUiName; 24 | } 25 | 26 | public void SendUi() 27 | { 28 | if (!string.IsNullOrEmpty(_destroyUiName)) 29 | { 30 | CommunityEntity.ServerInstance.ClientRPC(RpcTarget.SendInfo("DestroyUI", Send)); 31 | } 32 | CommunityEntity.ServerInstance.ClientRPC(RpcTarget.SendInfo("AddUI", Send), _container.ToJson()); 33 | } 34 | 35 | protected override void EnterPool() 36 | { 37 | base.EnterPool(); 38 | _container = null; 39 | _destroyUiName = null; 40 | } 41 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Threading/SendHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Threading; 4 | using Oxide.Core; 5 | 6 | namespace Oxide.Ext.UiFramework.Threading; 7 | 8 | internal static class SendHandler 9 | { 10 | private static readonly ConcurrentQueue Queue = new(); 11 | private static readonly AutoResetEvent Reset = new(false); 12 | private static readonly Thread _thread; 13 | 14 | static SendHandler() 15 | { 16 | _thread = new Thread(Send) 17 | { 18 | IsBackground = true, 19 | Name = $"UiFramework.{nameof(SendHandler)}", 20 | }; 21 | _thread.Start(); 22 | } 23 | 24 | internal static void Enqueue(IUiRequest request) 25 | { 26 | Queue.Enqueue(request); 27 | Reset.Set(); 28 | } 29 | 30 | private static void Send() 31 | { 32 | while (true) 33 | { 34 | SendInternal(); 35 | Reset.WaitOne(); 36 | } 37 | } 38 | 39 | private static void SendInternal() 40 | { 41 | while (Queue.TryDequeue(out IUiRequest request)) 42 | { 43 | try 44 | { 45 | #if !BENCHMARKS 46 | request.SendUi(); 47 | #endif 48 | } 49 | catch (Exception ex) 50 | { 51 | Interface.Oxide.LogException("An error occured during UI Send", ex); 52 | } 53 | finally 54 | { 55 | request.Dispose(); 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/Threading/UiSendRequest.cs: -------------------------------------------------------------------------------- 1 | using Network; 2 | using Oxide.Ext.UiFramework.Builder; 3 | using Oxide.Ext.UiFramework.Pooling; 4 | 5 | namespace Oxide.Ext.UiFramework.Threading; 6 | 7 | internal class UiSendRequest : BaseUiRequest, IUiRequest 8 | { 9 | public BaseBuilder Builder; 10 | 11 | public static UiSendRequest Create(BaseBuilder builder, SendInfo send) 12 | { 13 | UiSendRequest request = UiFrameworkPool.Get(); 14 | request.Init(builder, send); 15 | return request; 16 | } 17 | 18 | private void Init(BaseBuilder builder, SendInfo send) 19 | { 20 | base.Init(send); 21 | Builder = builder; 22 | } 23 | 24 | public void SendUi() 25 | { 26 | Builder.SendUi(Send); 27 | } 28 | 29 | protected override void EnterPool() 30 | { 31 | base.EnterPool(); 32 | Builder = null; 33 | } 34 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiConstants.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework; 2 | 3 | public class UiConstants 4 | { 5 | public static class RpcFunctions 6 | { 7 | public const string AddUiFunc = "AddUI"; 8 | public const string DestroyUiFunc = "DestroyUI"; 9 | } 10 | 11 | public static class Materials 12 | { 13 | public const string InGameBlur = "assets/content/ui/uibackgroundblur-ingamemenu.mat"; 14 | public const string NoticeBlur = "assets/content/ui/uibackgroundblur-notice.mat"; 15 | public const string BackgroundBlur = "assets/content/ui/uibackgroundblur.mat"; 16 | public const string Icon = "assets/icons/iconmaterial.mat"; 17 | } 18 | 19 | public static class Sprites 20 | { 21 | public const string Default = "Assets/Content/UI/UI.Background.Tile.psd"; 22 | public const string Transparent = "Assets/Content/Textures/Generic/fulltransparent.tga"; 23 | public const string RoundedBackground1 = "Assets/Content/UI/UI.Rounded.tga"; 24 | public const string RoundedBackground2 = "Assets/Content/UI/UI.Background.Rounded.png"; 25 | public const string GradientUp = "Assets/Content/UI/UI.Gradient.Up.psd"; 26 | public const string BackgroundTransparentLinear = "Assets/Content/UI/UI.Background.Transparent.Linear.png"; 27 | public const string BackgroundTransparentLinearLtr = "Assets/Content/UI/UI.Background.Transparent.LinearLTR.png"; 28 | public const string White = "Assets/Content/UI/UI.White.tga"; 29 | public const string Circle = "Assets/Icons/circle_closed_white.png"; 30 | public const string CircleToEdge = "Assets/Icons/circle_closed_white_toEdge.png"; 31 | public const string Box = "Assets/Content/UI/UI.Box.tga"; 32 | public const string BoxSharp = "Assets/Content/UI/UI.Box.Sharp.tga"; 33 | } 34 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/BaseUiComponent.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Json; 2 | using Oxide.Ext.UiFramework.Offsets; 3 | using Oxide.Ext.UiFramework.Pooling; 4 | using Oxide.Ext.UiFramework.Positions; 5 | 6 | namespace Oxide.Ext.UiFramework.UiElements; 7 | 8 | public abstract class BaseUiComponent : BasePoolable 9 | { 10 | public UiReference Reference; 11 | public float FadeOut; 12 | public UiPosition Position; 13 | public UiOffset Offset; 14 | 15 | protected static T CreateBase(in UiPosition pos, in UiOffset offset) where T : BaseUiComponent, new() 16 | { 17 | T component = UiFrameworkPool.Get(); 18 | component.Position = pos; 19 | component.Offset = offset; 20 | return component; 21 | } 22 | 23 | public void WriteRootComponent(JsonFrameworkWriter writer, bool needsMouse, bool needsKeyboard, bool autoDestroy) 24 | { 25 | writer.WriteStartObject(); 26 | writer.AddFieldRaw(JsonDefaults.Common.ComponentName, Reference.Name); 27 | writer.AddFieldRaw(JsonDefaults.Common.ParentName, Reference.Parent); 28 | writer.AddField(JsonDefaults.Common.FadeOutName, FadeOut, JsonDefaults.Common.FadeOut); 29 | 30 | if (autoDestroy) 31 | { 32 | writer.AddFieldRaw(JsonDefaults.Common.AutoDestroy, Reference.Name); 33 | } 34 | 35 | writer.WritePropertyName("components"); 36 | writer.WriteStartArray(); 37 | WriteComponents(writer); 38 | 39 | if (needsMouse) 40 | { 41 | writer.AddMouse(); 42 | } 43 | 44 | if (needsKeyboard) 45 | { 46 | writer.AddKeyboard(); 47 | } 48 | 49 | writer.WriteEndArray(); 50 | writer.WriteEndObject(); 51 | } 52 | 53 | public void WriteUpdateComponent(JsonFrameworkWriter writer) 54 | { 55 | writer.WriteStartObject(); 56 | writer.AddFieldRaw(JsonDefaults.Common.ComponentName, Reference.Name); 57 | writer.AddFieldRaw(JsonDefaults.Common.ParentName, Reference.Parent); 58 | writer.AddField(JsonDefaults.Common.FadeOutName, FadeOut, JsonDefaults.Common.FadeOut); 59 | writer.AddFieldRaw(JsonDefaults.Common.AutoDestroy, Reference.Name); 60 | 61 | writer.WritePropertyName("components"); 62 | writer.WriteStartArray(); 63 | WriteComponents(writer); 64 | writer.WriteEndArray(); 65 | writer.WriteEndObject(); 66 | } 67 | 68 | public void WriteComponent(JsonFrameworkWriter writer) 69 | { 70 | writer.WriteStartObject(); 71 | writer.AddFieldRaw(JsonDefaults.Common.ComponentName, Reference.Name); 72 | writer.AddFieldRaw(JsonDefaults.Common.ParentName, Reference.Parent); 73 | writer.AddField(JsonDefaults.Common.FadeOutName, FadeOut, JsonDefaults.Common.FadeOut); 74 | 75 | writer.WritePropertyName("components"); 76 | writer.WriteStartArray(); 77 | WriteComponents(writer); 78 | writer.WriteEndArray(); 79 | writer.WriteEndObject(); 80 | } 81 | 82 | protected virtual void WriteComponents(JsonFrameworkWriter writer) 83 | { 84 | writer.WriteStartObject(); 85 | writer.AddFieldRaw(JsonDefaults.Common.ComponentTypeName, JsonDefaults.Common.RectTransformName); 86 | writer.AddPosition(JsonDefaults.Position.AnchorMinName, Position.Min, JsonDefaults.Common.Min); 87 | writer.AddPosition(JsonDefaults.Position.AnchorMaxName, Position.Max, JsonDefaults.Common.Max); 88 | writer.AddOffset(JsonDefaults.Offset.OffsetMinName, Offset.Min, JsonDefaults.Common.Min); 89 | writer.AddOffset(JsonDefaults.Offset.OffsetMaxName, Offset.Max, JsonDefaults.Common.Max); 90 | writer.WriteEndObject(); 91 | } 92 | 93 | public void SetFadeOut(float duration) 94 | { 95 | FadeOut = duration; 96 | } 97 | 98 | protected override void EnterPool() 99 | { 100 | Reference = default; 101 | FadeOut = 0; 102 | Position = default; 103 | Offset = default; 104 | } 105 | 106 | public static implicit operator UiReference(BaseUiComponent component) => component.Reference; 107 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/BaseUiImage.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Components; 2 | using Oxide.Ext.UiFramework.Json; 3 | using UnityEngine.UI; 4 | 5 | namespace Oxide.Ext.UiFramework.UiElements; 6 | 7 | public abstract class BaseUiImage : BaseUiOutline 8 | { 9 | public readonly ImageComponent Image = new(); 10 | 11 | public void SetImageType(Image.Type type) 12 | { 13 | Image.ImageType = type; 14 | } 15 | 16 | public void SetSprite(string sprite) 17 | { 18 | Image.Sprite = sprite; 19 | } 20 | 21 | public void SetMaterial(string material) 22 | { 23 | Image.Material = material; 24 | } 25 | 26 | public void SetSpriteMaterialImage(string sprite = null, string material = null, Image.Type type = UnityEngine.UI.Image.Type.Simple) 27 | { 28 | Image.Sprite = sprite; 29 | Image.Material = material; 30 | Image.ImageType = type; 31 | } 32 | 33 | public void SetFadeIn(float duration) 34 | { 35 | Image.FadeIn = duration; 36 | } 37 | 38 | protected override void WriteComponents(JsonFrameworkWriter writer) 39 | { 40 | Image.WriteComponent(writer); 41 | base.WriteComponents(writer); 42 | } 43 | 44 | protected override void EnterPool() 45 | { 46 | base.EnterPool(); 47 | Image.Reset(); 48 | } 49 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/BaseUiOutline.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Components; 3 | using Oxide.Ext.UiFramework.Json; 4 | using Oxide.Ext.UiFramework.Pooling; 5 | using UnityEngine; 6 | 7 | namespace Oxide.Ext.UiFramework.UiElements; 8 | 9 | public abstract class BaseUiOutline : BaseUiComponent 10 | { 11 | public OutlineComponent Outline; 12 | 13 | public void AddElementOutline(UiColor color) 14 | { 15 | Outline = UiFrameworkPool.Get(); 16 | Outline.Color = color; 17 | } 18 | 19 | public void AddElementOutline(UiColor color, Vector2 distance) 20 | { 21 | AddElementOutline(color); 22 | Outline.Distance = distance; 23 | } 24 | 25 | public void AddElementOutline(UiColor color, Vector2 distance, bool useGraphicAlpha) 26 | { 27 | AddElementOutline(color, distance); 28 | Outline.UseGraphicAlpha = useGraphicAlpha; 29 | } 30 | 31 | public void RemoveOutline() 32 | { 33 | if (Outline != null) 34 | { 35 | Outline.Dispose(); 36 | Outline = null; 37 | } 38 | } 39 | 40 | protected override void WriteComponents(JsonFrameworkWriter writer) 41 | { 42 | Outline?.WriteComponent(writer); 43 | base.WriteComponents(writer); 44 | } 45 | 46 | protected override void EnterPool() 47 | { 48 | RemoveOutline(); 49 | } 50 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/UiButton.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Components; 3 | using Oxide.Ext.UiFramework.Json; 4 | using Oxide.Ext.UiFramework.Offsets; 5 | using Oxide.Ext.UiFramework.Positions; 6 | using UnityEngine.UI; 7 | 8 | namespace Oxide.Ext.UiFramework.UiElements; 9 | 10 | public class UiButton : BaseUiOutline 11 | { 12 | public readonly ButtonComponent Button = new(); 13 | 14 | public static UiButton CreateCommand(in UiPosition pos, in UiOffset offset, UiColor color, string command) 15 | { 16 | UiButton button = CreateBase(pos, offset); 17 | button.Button.Color = color; 18 | button.Button.Command = command; 19 | return button; 20 | } 21 | 22 | public static UiButton CreateClose(in UiPosition pos, in UiOffset offset, UiColor color, string close) 23 | { 24 | UiButton button = CreateBase(pos, offset); 25 | button.Button.Color = color; 26 | button.Button.Close = close; 27 | return button; 28 | } 29 | 30 | public void SetFadeIn(float duration) 31 | { 32 | Button.FadeIn = duration; 33 | } 34 | 35 | public void SetImageType(Image.Type type) 36 | { 37 | Button.ImageType = type; 38 | } 39 | 40 | public void SetSprite(string sprite) 41 | { 42 | Button.Sprite = sprite; 43 | } 44 | 45 | public void SetMaterial(string material) 46 | { 47 | Button.Material = material; 48 | } 49 | 50 | public void SetSpriteMaterialImage(string sprite = null, string material = null, Image.Type type = Image.Type.Simple) 51 | { 52 | Button.Sprite = sprite; 53 | Button.Material = material; 54 | Button.ImageType = type; 55 | } 56 | 57 | protected override void WriteComponents(JsonFrameworkWriter writer) 58 | { 59 | Button.WriteComponent(writer); 60 | base.WriteComponents(writer); 61 | } 62 | 63 | protected override void EnterPool() 64 | { 65 | base.EnterPool(); 66 | Button.Reset(); 67 | } 68 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/UiImage.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Offsets; 3 | using Oxide.Ext.UiFramework.Positions; 4 | 5 | namespace Oxide.Ext.UiFramework.UiElements; 6 | 7 | public class UiImage : BaseUiImage 8 | { 9 | public static UiImage CreateSpriteImage(in UiPosition pos, in UiOffset offset, UiColor color, string sprite) 10 | { 11 | UiImage image = CreateBase(pos, offset); 12 | image.Image.Color = color; 13 | image.Image.Sprite = sprite; 14 | return image; 15 | } 16 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/UiInput.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Components; 3 | using Oxide.Ext.UiFramework.Enums; 4 | using Oxide.Ext.UiFramework.Json; 5 | using Oxide.Ext.UiFramework.Offsets; 6 | using Oxide.Ext.UiFramework.Positions; 7 | using UnityEngine; 8 | using UnityEngine.UI; 9 | 10 | namespace Oxide.Ext.UiFramework.UiElements; 11 | 12 | public class UiInput : BaseUiOutline 13 | { 14 | public readonly InputComponent Input = new(); 15 | 16 | public static UiInput Create(in UiPosition pos, in UiOffset offset, UiColor textColor, string text, int size, string cmd, string font, TextAnchor align = TextAnchor.MiddleCenter, int charsLimit = 0, InputMode mode = InputMode.Default, InputField.LineType lineType = InputField.LineType.SingleLine) 17 | { 18 | UiInput input = CreateBase(pos, offset); 19 | InputComponent comp = input.Input; 20 | comp.Text = text; 21 | comp.FontSize = size; 22 | comp.Color = textColor; 23 | comp.Align = align; 24 | comp.Font = font; 25 | comp.Command = cmd; 26 | comp.CharsLimit = charsLimit; 27 | comp.Mode = mode; 28 | comp.LineType = lineType; 29 | return input; 30 | } 31 | 32 | public void SetTextAlign(TextAnchor align) 33 | { 34 | Input.Align = align; 35 | } 36 | 37 | public void SetCharsLimit(int limit) 38 | { 39 | Input.CharsLimit = limit; 40 | } 41 | 42 | public void SetIsPassword(bool isPassword) 43 | { 44 | Input.SetMode(InputMode.Password, isPassword); 45 | } 46 | 47 | public void SetIsReadonly(bool isReadonly) 48 | { 49 | Input.SetMode(InputMode.ReadOnly, isReadonly); 50 | } 51 | 52 | public void SetAutoFocus(bool autoFocus) 53 | { 54 | Input.SetMode(InputMode.AutoFocus, autoFocus); 55 | } 56 | 57 | /// 58 | /// Sets if the input should block keyboard input when focused. 59 | /// This should not be used when the loot panel / crafting UI is open. Use SetNeedsHudKeyboard instead 60 | /// 61 | /// 62 | public void SetNeedsKeyboard(bool needsKeyboard) 63 | { 64 | Input.SetMode(InputMode.NeedsKeyboard, needsKeyboard); 65 | } 66 | 67 | /// 68 | /// Sets if the input should block keyboard input when focused a loot panel / crafting ui is open. 69 | /// This should not if a loot panel / crafting ui won't be open when displaying the UI. 70 | /// 71 | /// 72 | public void SetNeedsHudKeyboard(bool needsKeyboard) 73 | { 74 | Input.SetMode(InputMode.HudNeedsKeyboard, needsKeyboard); 75 | } 76 | 77 | public void SetLineType(InputField.LineType lineType) 78 | { 79 | Input.LineType = lineType; 80 | } 81 | 82 | protected override void WriteComponents(JsonFrameworkWriter writer) 83 | { 84 | Input.WriteComponent(writer); 85 | base.WriteComponents(writer); 86 | } 87 | 88 | protected override void EnterPool() 89 | { 90 | base.EnterPool(); 91 | Input.Reset(); 92 | } 93 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/UiItemIcon.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Components; 3 | using Oxide.Ext.UiFramework.Json; 4 | using Oxide.Ext.UiFramework.Offsets; 5 | using Oxide.Ext.UiFramework.Positions; 6 | 7 | namespace Oxide.Ext.UiFramework.UiElements; 8 | 9 | public class UiItemIcon : BaseUiOutline 10 | { 11 | public readonly ItemIconComponent Icon = new(); 12 | 13 | public static UiItemIcon Create(in UiPosition pos, in UiOffset offset, UiColor color, int itemId, ulong skinId = 0) 14 | { 15 | UiItemIcon icon = CreateBase(pos, offset); 16 | icon.Icon.Color = color; 17 | icon.Icon.ItemId = itemId; 18 | icon.Icon.SkinId = skinId; 19 | return icon; 20 | } 21 | 22 | public void SetFadeIn(float duration) 23 | { 24 | Icon.FadeIn = duration; 25 | } 26 | 27 | protected override void WriteComponents(JsonFrameworkWriter writer) 28 | { 29 | Icon.WriteComponent(writer); 30 | base.WriteComponents(writer); 31 | } 32 | 33 | protected override void EnterPool() 34 | { 35 | base.EnterPool(); 36 | Icon.Reset(); 37 | } 38 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/UiLabel.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Components; 3 | using Oxide.Ext.UiFramework.Enums; 4 | using Oxide.Ext.UiFramework.Json; 5 | using Oxide.Ext.UiFramework.Offsets; 6 | using Oxide.Ext.UiFramework.Pooling; 7 | using Oxide.Ext.UiFramework.Positions; 8 | using UnityEngine; 9 | 10 | namespace Oxide.Ext.UiFramework.UiElements; 11 | 12 | public class UiLabel : BaseUiOutline 13 | { 14 | public readonly TextComponent Text = new(); 15 | public CountdownComponent Countdown; 16 | 17 | public static UiLabel Create(in UiPosition pos, in UiOffset offset, UiColor color, string text, int size, string font, TextAnchor align = TextAnchor.MiddleCenter) 18 | { 19 | UiLabel label = CreateBase(pos, offset); 20 | TextComponent textComp = label.Text; 21 | textComp.Text = text; 22 | textComp.FontSize = size; 23 | textComp.Color = color; 24 | textComp.Align = align; 25 | textComp.Font = font; 26 | return label; 27 | } 28 | 29 | public CountdownComponent AddCountdown(float startTime, float endTime, float step, float interval, TimerFormat timerFormat, string numberFormat, bool destroyIfDone, string command) 30 | { 31 | Countdown = UiFrameworkPool.Get(); 32 | Countdown.StartTime = startTime; 33 | Countdown.EndTime = endTime; 34 | Countdown.Step = step; 35 | Countdown.Interval = interval; 36 | Countdown.TimerFormat = timerFormat; 37 | Countdown.NumberFormat = numberFormat; 38 | Countdown.DestroyIfDone = destroyIfDone; 39 | Countdown.Command = command; 40 | return Countdown; 41 | } 42 | 43 | public void SetFadeIn(float duration) 44 | { 45 | Text.FadeIn = duration; 46 | } 47 | 48 | protected override void WriteComponents(JsonFrameworkWriter writer) 49 | { 50 | Text.WriteComponent(writer); 51 | Countdown?.WriteComponent(writer); 52 | base.WriteComponents(writer); 53 | } 54 | 55 | protected override void EnterPool() 56 | { 57 | base.EnterPool(); 58 | Text.Reset(); 59 | Countdown?.Dispose(); 60 | Countdown = null; 61 | } 62 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/UiPanel.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Offsets; 3 | using Oxide.Ext.UiFramework.Positions; 4 | 5 | namespace Oxide.Ext.UiFramework.UiElements; 6 | 7 | public class UiPanel : BaseUiImage 8 | { 9 | public static UiPanel Create(in UiPosition pos, in UiOffset offset, UiColor color) 10 | { 11 | UiPanel panel = CreateBase(pos, offset); 12 | panel.Image.Color = color; 13 | return panel; 14 | } 15 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/UiPlayerAvatar.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Components; 3 | using Oxide.Ext.UiFramework.Json; 4 | using Oxide.Ext.UiFramework.Offsets; 5 | using Oxide.Ext.UiFramework.Positions; 6 | 7 | namespace Oxide.Ext.UiFramework.UiElements; 8 | 9 | public class UiPlayerAvatar : BaseUiOutline 10 | { 11 | public readonly PlayerAvatarComponent Avatar = new(); 12 | 13 | public static UiPlayerAvatar Create(in UiPosition pos, in UiOffset offset, UiColor color, string steamId) 14 | { 15 | UiPlayerAvatar icon = CreateBase(pos, offset); 16 | icon.Avatar.Color = color; 17 | icon.Avatar.SteamId = steamId; 18 | return icon; 19 | } 20 | 21 | public void SetFadeIn(float duration) 22 | { 23 | Avatar.FadeIn = duration; 24 | } 25 | 26 | protected override void WriteComponents(JsonFrameworkWriter writer) 27 | { 28 | Avatar.WriteComponent(writer); 29 | base.WriteComponents(writer); 30 | } 31 | 32 | protected override void EnterPool() 33 | { 34 | base.EnterPool(); 35 | Avatar.Reset(); 36 | } 37 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/UiRawImage.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Components; 3 | using Oxide.Ext.UiFramework.Json; 4 | using Oxide.Ext.UiFramework.Offsets; 5 | using Oxide.Ext.UiFramework.Positions; 6 | 7 | namespace Oxide.Ext.UiFramework.UiElements; 8 | 9 | public class UiRawImage : BaseUiOutline 10 | { 11 | public readonly RawImageComponent RawImage = new(); 12 | 13 | public static UiRawImage CreateDefault(in UiPosition pos, in UiOffset offset) 14 | { 15 | UiRawImage image = CreateBase(pos, offset); 16 | return image; 17 | } 18 | 19 | public static UiRawImage CreateUrl(in UiPosition pos, in UiOffset offset, UiColor color, string url) 20 | { 21 | UiRawImage image = CreateBase(pos, offset); 22 | image.RawImage.Color = color; 23 | image.RawImage.Url = url; 24 | return image; 25 | } 26 | 27 | public static UiRawImage CreateTexture(in UiPosition pos, in UiOffset offset, UiColor color, string icon) 28 | { 29 | UiRawImage image = CreateBase(pos, offset); 30 | image.RawImage.Color = color; 31 | image.RawImage.Texture = icon; 32 | return image; 33 | } 34 | 35 | public static UiRawImage CreateFileImage(in UiPosition pos, in UiOffset offset, UiColor color, string png) 36 | { 37 | UiRawImage image = CreateBase(pos, offset); 38 | image.RawImage.Color = color; 39 | image.RawImage.Png = png; 40 | return image; 41 | } 42 | 43 | public void SetMaterial(string material) 44 | { 45 | RawImage.Material = material; 46 | } 47 | 48 | public void SetFadeIn(float duration) 49 | { 50 | RawImage.FadeIn = duration; 51 | } 52 | 53 | protected override void WriteComponents(JsonFrameworkWriter writer) 54 | { 55 | RawImage.WriteComponent(writer); 56 | base.WriteComponents(writer); 57 | } 58 | 59 | protected override void EnterPool() 60 | { 61 | base.EnterPool(); 62 | RawImage.Reset(); 63 | } 64 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/UiReference.cs: -------------------------------------------------------------------------------- 1 | namespace Oxide.Ext.UiFramework.UiElements; 2 | 3 | public readonly struct UiReference 4 | { 5 | public readonly string Parent; 6 | public readonly string Name; 7 | 8 | public UiReference(string parent, string name) 9 | { 10 | Parent = parent; 11 | Name = name; 12 | } 13 | 14 | public UiReference WithChild(string name) => new(Name, name); 15 | 16 | public bool IsValidParent() => !string.IsNullOrEmpty(Parent); 17 | public bool IsValidReference() => IsValidParent() && !string.IsNullOrEmpty(Name); 18 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/UiScrollView.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Colors; 2 | using Oxide.Ext.UiFramework.Components; 3 | using Oxide.Ext.UiFramework.Json; 4 | using Oxide.Ext.UiFramework.Offsets; 5 | using Oxide.Ext.UiFramework.Pooling; 6 | using Oxide.Ext.UiFramework.Positions; 7 | using UnityEngine.UI; 8 | 9 | namespace Oxide.Ext.UiFramework.UiElements; 10 | 11 | public class UiScrollView : BaseUiComponent 12 | { 13 | public readonly ScrollViewComponent ScrollView = new(); 14 | 15 | public UiReference ViewPort => _viewPort ??= Reference.WithChild($"{Reference.Name}___Viewport"); 16 | public UiReference Content => _content ??= Reference.WithChild($"{Reference.Name}___Content"); 17 | 18 | private UiReference? _viewPort; 19 | private UiReference? _content; 20 | 21 | public static UiScrollView Create(in UiPosition pos, in UiOffset offset, bool horizontal, bool vertical, ScrollRect.MovementType movementType, float elasticity, 22 | bool inertia, float decelerationRate, float scrollSensitivity) 23 | { 24 | UiScrollView scroll = CreateBase(pos, offset); 25 | ScrollViewComponent comp = scroll.ScrollView; 26 | comp.Horizontal = horizontal; 27 | comp.Vertical = vertical; 28 | comp.MovementType = movementType; 29 | comp.Elasticity = elasticity; 30 | comp.Inertia = inertia; 31 | comp.DecelerationRate = decelerationRate; 32 | comp.ScrollSensitivity = scrollSensitivity; 33 | return scroll; 34 | } 35 | 36 | public void UpdateContentTransform(in UiPosition? position = null, in UiOffset? offset = null) 37 | { 38 | if (position.HasValue) 39 | { 40 | ScrollView.ContentTransform.Position = position.Value; 41 | } 42 | 43 | if (offset.HasValue) 44 | { 45 | ScrollView.ContentTransform.Offset = offset.Value; 46 | } 47 | } 48 | 49 | public void AddScrollBars(bool invert = false, bool autoHide = false, string handleSprite = null, string trackSprite = null, float size = 20f, 50 | UiColor? handleColor = null, UiColor? highlightColor = null, UiColor? pressedColor = null, UiColor? trackColor = null) 51 | { 52 | AddHorizontalScrollBar(invert, autoHide, handleSprite, trackSprite, size, handleColor, highlightColor, pressedColor, trackColor); 53 | AddVerticalScrollBar(invert, autoHide, handleSprite, trackSprite, size, handleColor, highlightColor, pressedColor, trackColor); 54 | } 55 | 56 | public ScrollbarComponent AddHorizontalScrollBar(bool invert = false, bool autoHide = false, string handleSprite = null, string trackSprite = null, float size = 20f, 57 | UiColor? handleColor = null, UiColor? highlightColor = null, UiColor? pressedColor = null, UiColor? trackColor = null) 58 | { 59 | ScrollView.Horizontal = true; 60 | ScrollbarComponent bar = CreateScrollBar(invert, autoHide, handleSprite, trackSprite, size, handleColor, highlightColor, pressedColor, trackColor); 61 | ScrollView.HorizontalScrollbar = bar; 62 | return bar; 63 | } 64 | 65 | public ScrollbarComponent AddVerticalScrollBar(bool invert = false, bool autoHide = false, string handleSprite = null, string trackSprite = null, float size = 20f, 66 | UiColor? handleColor = null, UiColor? highlightColor = null, UiColor? pressedColor = null, UiColor? trackColor = null) 67 | { 68 | ScrollView.Vertical = true; 69 | ScrollbarComponent bar = CreateScrollBar(invert, autoHide, handleSprite, trackSprite, size, handleColor, highlightColor, pressedColor, trackColor); 70 | ScrollView.VerticalScrollbar = bar; 71 | return bar; 72 | } 73 | 74 | private ScrollbarComponent CreateScrollBar(bool invert = false, bool autoHide = false, string handleSprite = null, string trackSprite = null, float size = 20f, 75 | UiColor? handleColor = null, UiColor? highlightColor = null, UiColor? pressedColor = null, UiColor? trackColor = null) 76 | { 77 | ScrollbarComponent comp = UiFrameworkPool.Get(); 78 | comp.Invert = invert; 79 | comp.AutoHide = autoHide; 80 | comp.HandleSprite = handleSprite; 81 | comp.TrackSprite = trackSprite; 82 | comp.Size = size; 83 | if (handleColor.HasValue) 84 | { 85 | comp.HandleColor = handleColor.Value; 86 | } 87 | if (highlightColor.HasValue) 88 | { 89 | comp.HighlightColor = highlightColor.Value; 90 | } 91 | if (pressedColor.HasValue) 92 | { 93 | comp.PressedColor = pressedColor.Value; 94 | } 95 | if (trackColor.HasValue) 96 | { 97 | comp.TrackColor = trackColor.Value; 98 | } 99 | return comp; 100 | } 101 | 102 | protected override void WriteComponents(JsonFrameworkWriter writer) 103 | { 104 | ScrollView.WriteComponent(writer); 105 | base.WriteComponents(writer); 106 | } 107 | 108 | protected override void EnterPool() 109 | { 110 | base.EnterPool(); 111 | ScrollView.HorizontalScrollbar?.Dispose(); 112 | ScrollView.HorizontalScrollbar = null; 113 | ScrollView.VerticalScrollbar?.Dispose(); 114 | ScrollView.VerticalScrollbar = null; 115 | _viewPort = null; 116 | _content = null; 117 | } 118 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiElements/UiSection.cs: -------------------------------------------------------------------------------- 1 | using Oxide.Ext.UiFramework.Offsets; 2 | using Oxide.Ext.UiFramework.Positions; 3 | 4 | namespace Oxide.Ext.UiFramework.UiElements; 5 | 6 | public class UiSection : BaseUiComponent 7 | { 8 | public static UiSection Create(in UiPosition pos, in UiOffset offset) 9 | { 10 | UiSection panel = CreateBase(pos, offset); 11 | return panel; 12 | } 13 | } -------------------------------------------------------------------------------- /src/Rust.UIFramework/UiHelpers.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Oxide.Ext.UiFramework; 4 | 5 | public static class UiHelpers 6 | { 7 | public static int CalculateMaxPage(int count, int perPage) 8 | { 9 | int maxPage = count / perPage; 10 | if (count % perPage == 0) 11 | { 12 | maxPage -= 1; 13 | } 14 | 15 | return maxPage; 16 | } 17 | 18 | public static int TextOffsetWidth(int length, int fontSize, float padding = 0) 19 | { 20 | return Mathf.CeilToInt(length * fontSize * 0.5f + padding * 2) + 1; 21 | //return (int)(length * fontSize * 1f) + 1; 22 | } 23 | 24 | public static int TextOffsetHeight(int fontSize, float padding = 0) 25 | { 26 | return Mathf.CeilToInt(fontSize * 1.25f + padding * 2); 27 | } 28 | } -------------------------------------------------------------------------------- /src/Rust.UiFramework.Benchmarks/Benchmarks.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using BenchmarkDotNet.Attributes; 3 | using Facepunch; 4 | using Network; 5 | using Oxide.Ext.UiFramework.Builder.UI; 6 | using Oxide.Ext.UiFramework.Colors; 7 | using Oxide.Ext.UiFramework.Extensions; 8 | using Oxide.Ext.UiFramework.Json; 9 | using Oxide.Ext.UiFramework.Positions; 10 | using Oxide.Game.Rust.Cui; 11 | 12 | namespace Rust.UiFramework.Benchmarks; 13 | 14 | #if BENCHMARKS 15 | 16 | using Oxide.Ext.UiFramework.Benchmarks; 17 | 18 | [MemoryDiagnoser] 19 | public class Benchmarks 20 | { 21 | private const int Iterations = 100; 22 | private readonly List _oxideMins = new(); 23 | private readonly List _oxideMaxs = new(); 24 | private readonly List _frameworkPos = new(); 25 | private readonly Random _random = new(); 26 | public readonly byte[] Buffer = new byte[1024 * 1024]; 27 | private CuiElementContainer _oxideContainer; 28 | private string _oxideJson; 29 | private UiBuilder _builder; 30 | private UiBuilder _randomBuilder; 31 | private JsonFrameworkWriter _writer; 32 | private JsonFrameworkWriter _randomWriter; 33 | private readonly Connection _connection = new(); 34 | 35 | [GlobalSetup] 36 | public void Setup() 37 | { 38 | for (int i = 0; i < Iterations; i++) 39 | { 40 | float xMin = (float)_random.NextDouble(); 41 | float xMax = (float)_random.NextDouble(); 42 | float yMin = (float)_random.NextDouble(); 43 | float yMax = (float)_random.NextDouble(); 44 | _oxideMins.Add($"{xMin} {yMin}"); 45 | _oxideMaxs.Add($"{xMax} {yMax}"); 46 | _frameworkPos.Add(new UiPosition(xMin, yMin, xMax, yMax)); 47 | } 48 | 49 | _oxideContainer = GetOxideContainer(); 50 | _oxideJson = _oxideContainer.ToJson(); 51 | _builder = GetFrameworkBuilder(); 52 | //_randomBuilder = GetRandomPositionBuilder(); 53 | _writer = _builder.CreateWriter(); 54 | //_randomWriter = _randomBuilder.CreateWriter(); 55 | } 56 | 57 | // [Benchmark] 58 | // public CuiElementContainer Oxide_CreateContainer() 59 | // { 60 | // return GetOxideContainer(); 61 | // } 62 | 63 | // [Benchmark(Baseline = true)] 64 | // public UiBuilder UiFramework_CreateContainer() 65 | // { 66 | // UiBuilder builder = GetFrameworkBuilder(); 67 | // builder.Dispose(); 68 | // return builder; 69 | // } 70 | 71 | // 72 | // [Benchmark] 73 | // public string Oxide_CreateJson() 74 | // { 75 | // return _oxideContainer.ToJson(); 76 | // } 77 | // 78 | // [Benchmark] 79 | // public JsonFrameworkWriter UiFramework_CreateJson() 80 | // { 81 | // JsonFrameworkWriter writer = _builder.CreateWriter(); 82 | // writer.Dispose(); 83 | // return writer; 84 | // } 85 | // 86 | // [Benchmark] 87 | // public byte[] Oxide_EncodeJson() 88 | // { 89 | // return Encoding.UTF8.GetBytes(_oxideJson); 90 | // } 91 | // 92 | // [Benchmark] 93 | // public int UiFramework_EncodeJson() 94 | // { 95 | // int count = _writer.WriteTo(Buffer); 96 | // return count; 97 | // } 98 | 99 | [Benchmark(Baseline = true)] 100 | public void UiFramework_Async() 101 | { 102 | UiBuilder builder = GetFrameworkBuilder(); 103 | builder.AddUi(default(SendInfo)); 104 | builder.Dispose(); 105 | } 106 | 107 | [Benchmark] 108 | public void Oxide_Async() 109 | { 110 | CuiElementContainer builder = GetOxideContainer(); 111 | builder.AddUiAsync(_connection); 112 | } 113 | 114 | //[Benchmark] 115 | public void UiFramework_Full() 116 | { 117 | UiBuilder builder = GetFrameworkBuilder(); 118 | JsonFrameworkWriter writer = builder.CreateWriter(); 119 | BenchmarkNetWrite write = Pool.Get(); 120 | writer.WriteToNetwork(write); 121 | writer.Dispose(); 122 | Pool.Free(ref write); 123 | builder.Dispose(); 124 | } 125 | 126 | [Benchmark] 127 | public byte[] Oxide_Full() 128 | { 129 | CuiElementContainer builder = GetOxideContainer(); 130 | string json = builder.ToJson(); 131 | return Encoding.UTF8.GetBytes(json); 132 | } 133 | 134 | private CuiElementContainer GetOxideContainer() 135 | { 136 | CuiElementContainer container = new(); 137 | for (int i = 0; i < Iterations; i++) 138 | { 139 | container.Add(new CuiPanel 140 | { 141 | Image = 142 | { 143 | Color = "1.0 1.0 1.0 1.0" 144 | }, 145 | RectTransform = 146 | { 147 | AnchorMin = _oxideMins[i], 148 | AnchorMax = _oxideMaxs[i] 149 | } 150 | }); 151 | } 152 | 153 | return container; 154 | } 155 | 156 | private UiBuilder GetFrameworkBuilder() 157 | { 158 | UiBuilder builder = UiBuilder.Create(UiPosition.Full, UiColor.Clear, "123"); 159 | builder.EnsureCapacity(Iterations); 160 | for (int i = 0; i < Iterations - 1; i++) 161 | { 162 | builder.Panel(builder.Root, _frameworkPos[i], UiColor.Black); 163 | } 164 | 165 | return builder; 166 | } 167 | } 168 | #endif -------------------------------------------------------------------------------- /src/Rust.UiFramework.Benchmarks/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Configs; 2 | using BenchmarkDotNet.Jobs; 3 | using BenchmarkDotNet.Running; 4 | using BenchmarkDotNet.Toolchains.InProcess.Emit; 5 | 6 | namespace Rust.UiFramework.Benchmarks; 7 | 8 | class Program 9 | { 10 | static void Main(string[] args) 11 | { 12 | #if BENCHMARKS 13 | ManualConfig config = DefaultConfig.Instance.AddJob(Job.Default 14 | .WithToolchain(InProcessEmitToolchain.Instance) 15 | .WithIterationCount(30)); 16 | BenchmarkRunner.Run(config, args); 17 | #endif 18 | } 19 | } -------------------------------------------------------------------------------- /src/Rust.UiFramework.Benchmarks/Rust.UiFramework.Benchmarks.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | enable 5 | enable 6 | 12 7 | true 8 | Debug;Release;Benchmarks 9 | Oxide 10 | Exe 11 | netcoreapp3.0 12 | 13 | 14 | 15 | TRACE;DEBUG;CARBON 16 | Carbon.Ext.UiFramework 17 | 18 | 19 | 20 | TRACE;DEBUG;OXIDE 21 | 22 | 23 | 24 | TRACE;CARBON 25 | Carbon.Ext.UiFramework 26 | 27 | 28 | 29 | TRACE;OXIDE 30 | 31 | 32 | 33 | TRACE;BENCHMARKS 34 | true 35 | 36 | 37 | 38 | 39 | ..\references\Assembly-CSharp.dll 40 | 41 | 42 | ..\references\Facepunch.Network.dll 43 | 44 | 45 | ..\references\Facepunch.System.dll 46 | 47 | 48 | ..\References\mscorlib.dll 49 | 50 | 51 | ..\References\Oxide.Common.dll 52 | 53 | 54 | ..\References\Oxide.Core.dll 55 | 56 | 57 | ..\references\Oxide.CSharp.dll 58 | 59 | 60 | ..\references\Oxide.References.dll 61 | 62 | 63 | ..\References\Oxide.Rust.dll 64 | 65 | 66 | ..\references\System.Memory.dll 67 | 68 | 69 | ..\references\System.Runtime.dll 70 | 71 | 72 | ..\references\UnityEngine.TextRenderingModule.dll 73 | 74 | 75 | ..\references\UnityEngine.UI.dll 76 | 77 | 78 | ..\references\UnityEngine.UIElementsModule.dll 79 | 80 | 81 | ..\references\UnityEngine.UIModule.dll 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | --------------------------------------------------------------------------------