diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 93400c4..4682ec9 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -2,7 +2,7 @@ name: Bug report about: Create a report to identify a potential issue title: 'BUG: ' -labels: Bug +labels: bug assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 15ff012..e087ead 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,7 +2,7 @@ name: Feature request about: Suggest an idea for the Unity UI Extensions title: 'Feature Request: ' -labels: Feature Request +labels: enhancement assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/request_for_information.md b/.github/ISSUE_TEMPLATE/request_for_information.md index a5a3a7c..131b1e0 100644 --- a/.github/ISSUE_TEMPLATE/request_for_information.md +++ b/.github/ISSUE_TEMPLATE/request_for_information.md @@ -2,7 +2,7 @@ name: Request for Information about: Not sure how to do something, just ask. title: 'RFI: ' -labels: Question +labels: question assignees: '' --- diff --git a/.github/workflows/buildupmpackages.yml b/.github/workflows/buildupmpackages.yml index 38da957..01e1795 100644 --- a/.github/workflows/buildupmpackages.yml +++ b/.github/workflows/buildupmpackages.yml @@ -1,4 +1,4 @@ -name: Build and test UPM packages for platforms +name: Build and test UPM packages for platforms on all available Unity Versions on: pull_request: @@ -14,27 +14,24 @@ concurrency: cancel-in-progress: true jobs: - # Check Unity version requird by the package - validate-environment: - name: Get Unity Version from UPM package - uses: Unity-UI-Extensions/reusableworkflows/.github/workflows/getunityversionfrompackage.yml@main - with: - build-target: self-hosted - - # Check Unity Hub and Editor Environment - Setup-Unity: - name: Validate Unity Install - needs: validate-environment - uses: Unity-UI-Extensions/reusableworkflows/.github/workflows/validateunityinstall.yml@main - with: - build-target: self-hosted - unityversion: ${{ needs.validate-environment.outputs.unityversion }} - - # Run Unity unit tests defined in the package - Run-Unit-Tests: + # Run Unity build unit tests defined in the package for a single version for feature branches + Run-Partial-Unit-Tests: name: Run Unity Unit Tests - needs: Setup-Unity - uses: Unity-UI-Extensions/reusableworkflows/.github/workflows/rununityunittests.yml@main + if: github.ref != 'refs/heads/development' + uses: ./.github/workflows/rununitysinglebuild.yml with: - build-target: self-hosted - unityversion: ${{ needs.Setup-Unity.outputs.unityeditorversion }} \ No newline at end of file + unityversion: 2020.3 + + # Run Unity multi-version build unit tests defined in the package for the development branch + Run-Full-Unit-Tests: + name: Run Unity Unit Tests + if: github.ref == 'refs/heads/development' + uses: ./.github/workflows/rununitybuildmultiversion.yml + + # Update the package release version + Update-Version: + name: Update Package Version + uses: ./.github/workflows/tagrelease.yml + with: + build-target: windows + secrets: inherit diff --git a/.github/workflows/rununitybuildmultiversion.yml b/.github/workflows/rununitybuildmultiversion.yml new file mode 100644 index 0000000..bd98ccf --- /dev/null +++ b/.github/workflows/rununitybuildmultiversion.yml @@ -0,0 +1,459 @@ +name: Run Unity Builds + +on: + workflow_call: + inputs: + dependencies: + description: "json array of dependencies and their targets" + required: false + type: string + +jobs: + run_build: + name: Run Unity Build process + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: windows + unityVersion: 2019.4 + build-target: Android + - os: macos + unityVersion: 2019.4 + build-target: iOS + - os: windows + unityVersion: 2019.4 + build-target: StandaloneWindows64 + - os: windows + unityVersion: 2019.4 + build-target: WSAPlayer + - os: windows + unityVersion: 2020.3 + build-target: Android + - os: macos + unityVersion: 2020.3 + build-target: iOS + - os: windows + unityVersion: 2020.3 + build-target: StandaloneWindows64 + - os: windows + unityVersion: 2020.3 + build-target: WSAPlayer + - os: windows + unityVersion: 2021.3 + build-target: Android + - os: macos + unityVersion: 2021.3 + build-target: iOS + - os: windows + unityVersion: 2021.3 + build-target: StandaloneWindows64 + - os: windows + unityVersion: 2021.3 + build-target: WSAPlayer + - os: windows + unityVersion: 2022.2 + build-target: Android + - os: macos + unityVersion: 2022.2 + build-target: iOS + - os: windows + unityVersion: 2022.2 + build-target: StandaloneWindows64 + - os: windows + unityVersion: 2022.2 + build-target: WSAPlayer + steps: + - name: Script Version + run: | + echo "::group::Script Versioning" + $scriptVersion = "1.0.0" + echo "Build Script Version: $scriptVersion" + echo "::endgroup::" + shell: pwsh + - uses: actions/checkout@v3 + with: + submodules: recursive + clean: true + + - id: build + name: 'Run Unity Builds' + run: | + echo "::group::Set Hub and editor locations" + $unityVersion = ${{ matrix.unityVersion }} + + echo "::group::Set Hub and editor locations" + + ## Set Hub and editor locations + if ( (-not $global:PSVersionTable.Platform) -or ($global:PSVersionTable.Platform -eq "Win32NT") ) + { + $hubPath = "C:\Program Files\Unity Hub\Unity Hub.exe" + $editorRootPath = "C:\Program Files\Unity\Hub\Editor\" + $editorFileEx = "\Editor\Unity.exe" + + #"Unity Hub.exe" -- --headless help + #. 'C:\Program Files\Unity Hub\Unity Hub.exe' -- --headless help + function unity-hub + { + & $hubPath -- --headless $args.Split(" ") | Out-String -NoNewline + } + } + elseif ( $global:PSVersionTable.OS.Contains("Darwin") ) + { + $hubPath = "/Applications/Unity Hub.app/Contents/MacOS/Unity Hub" + $editorRootPath = "/Applications/Unity/Hub/Editor/" + $editorFileEx = "/Unity.app/Contents/MacOS/Unity" + + # /Applications/Unity\ Hub.app/Contents/MacOS/Unity\ Hub -- --headless help + function unity-hub + { + & $hubPath -- --headless $args.Split(" ") | Out-String -NoNewline + } + } + elseif ( $global:PSVersionTable.OS.Contains("Linux") ) + { + $hubPath = "$HOME/Unity Hub/UnityHub.AppImage" + $editorRootPath = "$HOME/Unity/Hub/Editor/" + $editorFileEx = "/Editor/Unity" + + # /UnityHub.AppImage --headless help + # xvfb-run --auto-servernum "$HOME/Unity Hub/UnityHub.AppImage" --headless help + function unity-hub + { + xvfb-run --auto-servernum "$hubPath" --headless $args.Split(" ") + } + } + + echo "::endgroup::" + + + + echo "::group::Get String function to query a string for a value" + + function GetString($InputString, $InputPattern, $MatchIndex) + { + $regExResult = $InputString | Select-String -Pattern $InputPattern + if($regExResult.Length -gt 0) + { + return $regExResult.Matches[$MatchIndex].Value + } + else + { + return 0 + } + } + + function Get-LetterCount + { + Param ([string]$string) + return $string.Length + } + echo "::endgroup::" + + echo "::group::Get Installed Unity version based on Matrix" + echo 'Script Start' + echo "Unity hub path is {$hubPath}" + echo "Requested unity version is {$unityVersion}" + + $InstalledUnityVersions = unity-hub editors + $editorRootPath = unity-hub ip -g + echo "Installed unity versions are {$InstalledUnityVersions}" + echo "Unity install path is {$editorRootPath}" + + $versionLength = Get-LetterCount $unityVersion + if ($versionLength -eq 4) { + $queryUnityVersion = GetString $InstalledUnityVersions "$unityVersion.{4,7}" -MatchIndex 0 + } + elseif ($versionLength -eq 6) { + $queryUnityVersion = GetString $InstalledUnityVersions "$unityVersion.{4,5}" -MatchIndex 0 + } + else { + $queryUnityVersion = GetString $InstalledUnityVersions "$unityVersion" -MatchIndex 0 + } + + echo "Found unity version is {$queryUnityVersion}" + + if ($queryUnityVersion -ne 0) + { + $unityVersion = $queryUnityVersion.Trim(","," ").Trim() + echo "Long Unity version is $unityVersion" + } + else + { + echo "Unity $unityVersion not found on this machine, skipping" + exit 0 + } + + echo "::endgroup::" + + echo "::group::Search for Editor if not found" + $checkPath = Join-Path $editorRootPath $unityVersion + echo "Testing for editor at $checkPath" + while (-not (Test-Path "$checkPath")) { + $source = $unityVersion.Replace("f1","") + $newversion = $source.Split(".") + $newversion[2] = [int]$newversion[2] - 1 + if ([int]$newversion[2] -lt 1) { + echo "Unity ${{ matrix.unityVersion }} not found on this machine, skipping" + exit 0 + } + $newunityVersion = "{0}.{1}.{2}f1" -f $newversion[0],$newversion[1],$newversion[2] + echo "Unity $unityVersion not found on this machine, trying $newunityVersion" + $unityVersion = $newunityVersion + $checkPath = Join-Path $editorRootPath $unityVersion + } + echo "::endgroup::" + + echo "::group::Set editor locations" + + if ( (-not $global:PSVersionTable.Platform) -or ($global:PSVersionTable.Platform -eq "Win32NT") ) { + echo 'Building using Windows' + $editorFileEx = "/Editor/Unity.exe" + $editorrunpath = Join-Path $editorRootPath $unityVersion $editorFileEx + + function unity-editor { + #$p = Start-Process -Verbose -NoNewWindow -PassThru -Wait -FilePath "$editorrunpath" -ArgumentList (@(' -batchmode') + $args.Split(" ")) + & $editorrunpath -batchmode $args.Split(" ") | Out-String + } + } + elseif ( $global:PSVersionTable.OS.Contains("Darwin") ) { + echo 'Building using Mac' + $editorFileEx = "/Unity.app/Contents/MacOS/Unity" + $editorrunpath = Join-Path $editorRootPath $unityVersion $editorFileEx + + function unity-editor { + #$p = Start-Process -Verbose -NoNewWindow -PassThru -Wait -FilePath "$editorrunpath" -ArgumentList (@(' -batchmode') + $args.Split(" ")) + & $editorrunpath -batchmode $args.Split(" ") | Out-String + } + } + elseif ( $global:PSVersionTable.OS.Contains("Linux") ) { + echo 'Building using Linux' + $editorFileEx = "/Editor/Unity" + $editorrunpath = Join-Path $editorRootPath $unityVersion $editorFileEx + + function unity-editor { + xvfb-run --auto-servernum "$editorrunpath" -batchmode $args.Split(" ") + } + } + else + { + echo 'Unknown build platform' + } + + echo "::endgroup::" + + echo "::group::Test Unity version is installed" + + if ( -not (Test-Path "$editorrunpath") ) + { + Write-Error "Editor not Found for $unityVersion" + exit 1 + } + else { + echo "Editor Path is {$editorrunpath}" + } + + echo "::endgroup::" + + echo "::group::Setup logging and run Unit tests" + + # Log detail + $logDirectory = "Logs" + if (Test-Path -Path $logDirectory) { + echo "Clearing logs from a previous run" + Remove-item $logDirectory -recurse + } + + $logDirectory = New-Item -ItemType Directory -Force -Path $logDirectory | Select-Object + + echo "Log Directory: $logDirectory" + $date = Get-Date -Format "yyyyMMddTHHmmss" + + # If run manually, the Refname is actually blank, so just use date + if([string]::IsNullOrEmpty(${GITHUB_REF_NAME})) { + $logName = "$logDirectory$directorySeparatorChar$date" + } + else{ + $logName = "$logDirectory$directorySeparatorChar${GITHUB_REF_NAME}-$date" + } + + $logPath = "$logName.log" + $testsLogPath = "$logName-tests.xml" + + echo "Logpath [$logPath]" + echo "TestsPath [$testsLogPath]" + echo "::endgroup::" + + echo "::group::Grouping Package in a UPM folder" + + $UPMFolderName = 'u' + + if ( -not (Test-Path '$UPMFolderName') ) + { + New-Item $UPMFolderName -ItemType Directory + } + + Move-Item -Path * -Destination $UPMFolderName -exclude $UPMFolderName + + echo "::endgroup::" + + echo "::group::Creating Temp Unity project" + + $TempUnityProjectName = 'P' + + unity-editor '-createProject' $TempUnityProjectName -quit + + $destinationPath = $TempUnityProjectName + $directorySeparatorChar + 'packages' + Move-Item -Path $UPMFolderName -Destination $destinationPath + + echo "::endgroup::" + + echo "::group::If required, clone dependencies in to test project" + + <# Dependency option requires specific inputs + + * A dependency input string in json format, listing each dependency by name and git url, e.g. + $dependencies = '[{"ASADependencies": "github.com/SimonDarksideJ/upmGithubActionsTests.git"}]' + *Note, remove the https:// portion to allow using a PAT to access the repo + The Name of the dependency should ALSO MATCH the name of the branch on the repo where the dependency is held (files intended for the packages folder) + + * Additionally, if Manifest entries are required, then a manifest file with those dependencies (and ONLY the new dependancies) should also be in the dependency branch named the same as the branch name + e.g. "ASADependencies.json" - keep the same structure, but only the dependancy entries + + !!Does NOT support additional scoped registries at this time! #> + + echo "---------------------------------------------" + echo "Read dependancy input value" + if([string]::IsNullOrEmpty('${{ inputs.dependencies }}')) + { + echo "No dependencies provided" + echo "input ${{ inputs.dependencies }}" + echo "------------------------------" + } + else { + echo "dependencies provided, validating" + + # Read dependancy input value + $dependencies = '${{ inputs.dependencies }}' + + if([string]::IsNullOrEmpty('${{ secrets.GIT_USER_NAME }}') -or [string]::IsNullOrEmpty('${{ secrets.GIT_PAT }}')){ + echo "" + echo "Secrets for GIT_USER_NAME or GIT_PAT missing, please register them with access to this runner" + echo "*Note, Organisation secrets are not accessible to Forked repos and need registering in the local fork" + exit 1 + } + + echo "---------------------------------------------" + echo "Read dependancy input values as json" + $JSONdependencies = $dependencies | ConvertFrom-Json + + echo $JSONdependencies + + # Read current Manifest json + $manifestPath = $destinationPath + $directorySeparatorChar + 'manifest.json' + $projectManifest = Get-Content -Path $manifestPath | ConvertFrom-Json + $strArray = $projectManifest.dependencies.PsObject.Properties | ForEach-Object {"$($_.Name)@$($_.Value),"} + + echo "---------------------------------------------" + echo "Loop through new dependancies and add them to the project Manifest" + foreach($dependency in $JSONdependencies){ + $dependency.PsObject.Properties | ForEach-Object -Process { + $dependencyName = $_.Name + $dependencyPath = $dependencyName.Replace("/","_") + $dependencyURL = $_.Value + echo "---------------------------------------------" + echo "Cloning dependency - Name [$dependencyName] - Path [$dependencyPath] - URL [$dependencyURL]" + $cloneURL = "https://${{ secrets.GIT_USER_NAME }}:${{ secrets.GIT_PAT }}@$dependencyURL" + + echo "cloning $dependencyName from $dependencyURL and moving to $destinationPath" + echo "git path - $cloneURL" + + # Clone Dependancy repo to destination folder + git clone -b $dependencyName --single-branch $cloneURL $dependencyPath + + if( -not (Test-Path -Path "$dependencyPath")){ + echo "Unable to clone $dependencyName from $dependencyURL" + exit 1 + } + + # Move files from clone path into packages folder, if the dependency contains a UPM package then move the entire folder and not just its contents + if (Test-Path -Path "$dependencyPath/package.json") { + $package_json = Get-Content -Path $dependencyPath/package.json | ConvertFrom-Json + $packageName = $package_json.name + Rename-Item $dependencyPath $packageName + echo "Moving whole $packageName UPM package to $destinationPath" + Move-Item -Path "$packageName" -Destination $destinationPath + } + else { + echo "Moving the contents of $dependencyName into the $destinationPath folder" + Move-Item -Path "$dependencyPath/*" -Destination $destinationPath + } + + # Get Dependency manifest entries (if applicable) + if (Test-Path -Path "$destinationPath/$dependencyName.json") { + $dependencyManifest = Get-Content -Path "$destinationPath/$dependencyName.json" | ConvertFrom-Json + $dependencyManifest.dependencies.PsObject.Properties | ForEach-Object { + $strArray += "$($_.Name)@$($_.Value)," + } + } + else{ + echo "No denendency json found called $destinationPath/$dependencyName.json, skipping adding additional manifest entries" + } + } + } + echo "---------------------------------------------" + + # Reformat combined dependancies list + $strArray = $strArray.Trim(",") | ConvertTo-Json + $strArray = $strArray.Replace("@",'":"').Replace("[","{").Replace("]","}") + $strArrayObject = $strArray | ConvertFrom-Json + + # Save manifest back to project + $projectManifest.dependencies = $strArrayObject + $projectManifest | ConvertTo-Json | Set-Content -Path "$destinationPath/manifest.json" + + echo "Project updated with the following dependencies" + echo "-----------------------------------------------" + echo $projectManifest + } + + echo "::endgroup::" + + echo "::group::Run build" + + echo "---------------------------------------------" + echo "Start Testing" + echo "Unity Command\n[unity-editor -projectPath $TempUnityProjectName -logfile $logPath -batchmode -nographics -quit -buildTarget ${{ matrix.build-target }}]" + + unity-editor -projectPath $TempUnityProjectName -logfile $logPath -batchmode -nographics -quit -buildTarget ${{ matrix.build-target }} + + echo "---------------------------------------------" + echo "::group::Unity Unit tests Results" + if (Test-Path $testsLogPath) { + echo "Test Run results for ${GITHUB_REPOSITORY} Branch ${GITHUB_REF}" + echo "" + Select-Xml -Path $testsLogPath -XPath '/test-run/test-suite' | ForEach-Object { "Name: " +$_.Node.name, ", Result: " + $_.Node.result, ", Total Tests: " + $_.Node.total, ", Passed: " + $_.Node.passed, ", Failed: " + $_.Node.failed, ", Skipped: " + $_.Node.skipped } + } + else { + echo "No test results found for ${GITHUB_REPOSITORY} Branch ${GITHUB_REF} at $testsLogPath" + echo "" + } + echo "::endgroup::" + + if($LASTEXITCODE -ne '0'){ + echo "::group::Unity Unit tests errors" + $exitCode = $testResult.ExitCode + Get-Content $logPath + echo "Build failed due to errors ($LASTEXITCODE), please check the log at $logPath" + echo "::endgroup::" + + exit $LASTEXITCODE + } + echo "::endgroup::" + + shell: pwsh + - uses: actions/upload-artifact@v3 + if: always() + with: + name: unity-build-log + path: Logs/** \ No newline at end of file diff --git a/.github/workflows/rununitysinglebuild.yml b/.github/workflows/rununitysinglebuild.yml new file mode 100644 index 0000000..58404ce --- /dev/null +++ b/.github/workflows/rununitysinglebuild.yml @@ -0,0 +1,424 @@ +name: Run Limited Unity Builds + +on: + workflow_call: + inputs: + unityVersion: + description: "The version of Unity to validate on" + required: true + type: string + dependencies: + description: "json array of dependencies and their targets" + required: false + type: string + +jobs: + run_build: + name: Run Unity Build process + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: macos + build-target: iOS + - os: windows + build-target: Android + - os: windows + build-target: StandaloneWindows64 + - os: windows + build-target: WSAPlayer + + steps: + - name: Script Version + run: | + echo "::group::Script Versioning" + $scriptVersion = "1.0.0" + echo "Build Script Version: $scriptVersion" + echo "::endgroup::" + shell: pwsh + - uses: actions/checkout@v3 + with: + submodules: recursive + clean: true + + - id: build + name: 'Run Unity Builds' + run: | + echo "::group::Set Hub and editor locations" + $unityVersion = ${{ inputs.unityVersion }} + + echo "::group::Set Hub and editor locations" + + ## Set Hub and editor locations + if ( (-not $global:PSVersionTable.Platform) -or ($global:PSVersionTable.Platform -eq "Win32NT") ) + { + $hubPath = "C:\Program Files\Unity Hub\Unity Hub.exe" + $editorRootPath = "C:\Program Files\Unity\Hub\Editor\" + $editorFileEx = "\Editor\Unity.exe" + + #"Unity Hub.exe" -- --headless help + #. 'C:\Program Files\Unity Hub\Unity Hub.exe' -- --headless help + function unity-hub + { + & $hubPath -- --headless $args.Split(" ") | Out-String -NoNewline + } + } + elseif ( $global:PSVersionTable.OS.Contains("Darwin") ) + { + $hubPath = "/Applications/Unity Hub.app/Contents/MacOS/Unity Hub" + $editorRootPath = "/Applications/Unity/Hub/Editor/" + $editorFileEx = "/Unity.app/Contents/MacOS/Unity" + + # /Applications/Unity\ Hub.app/Contents/MacOS/Unity\ Hub -- --headless help + function unity-hub + { + & $hubPath -- --headless $args.Split(" ") | Out-String -NoNewline + } + } + elseif ( $global:PSVersionTable.OS.Contains("Linux") ) + { + $hubPath = "$HOME/Unity Hub/UnityHub.AppImage" + $editorRootPath = "$HOME/Unity/Hub/Editor/" + $editorFileEx = "/Editor/Unity" + + # /UnityHub.AppImage --headless help + # xvfb-run --auto-servernum "$HOME/Unity Hub/UnityHub.AppImage" --headless help + function unity-hub + { + xvfb-run --auto-servernum "$hubPath" --headless $args.Split(" ") + } + } + + echo "::endgroup::" + + + + echo "::group::Get String function to query a string for a value" + + function GetString($InputString, $InputPattern, $MatchIndex) + { + $regExResult = $InputString | Select-String -Pattern $InputPattern + if($regExResult.Length -gt 0) + { + return $regExResult.Matches[$MatchIndex].Value + } + else + { + return 0 + } + } + + function Get-LetterCount + { + Param ([string]$string) + return $string.Length + } + echo "::endgroup::" + + echo "::group::Get Installed Unity version based on Matrix" + echo 'Script Start' + echo "Unity hub path is {$hubPath}" + echo "Requested unity version is {$unityVersion}" + + $InstalledUnityVersions = unity-hub editors + $editorRootPath = unity-hub ip -g + echo "Installed unity versions are {$InstalledUnityVersions}" + echo "Unity install path is {$editorRootPath}" + + $versionLength = Get-LetterCount $unityVersion + if ($versionLength -eq 4) { + $queryUnityVersion = GetString $InstalledUnityVersions "$unityVersion.{4,7}" -MatchIndex 0 + } + elseif ($versionLength -eq 6) { + $queryUnityVersion = GetString $InstalledUnityVersions "$unityVersion.{4,5}" -MatchIndex 0 + } + else { + $queryUnityVersion = GetString $InstalledUnityVersions "$unityVersion" -MatchIndex 0 + } + + echo "Found unity version is {$queryUnityVersion}" + + if ($queryUnityVersion -ne 0) + { + $unityVersion = $queryUnityVersion.Trim(","," ").Trim() + echo "Long Unity version is $unityVersion" + } + else + { + echo "Unity $unityVersion not found on this machine, skipping" + exit 0 + } + + echo "::endgroup::" + + echo "::group::Search for Editor if not found" + $checkPath = Join-Path $editorRootPath $unityVersion + echo "Testing for editor at $checkPath" + while (-not (Test-Path "$checkPath")) { + $source = $unityVersion.Replace("f1","") + $newversion = $source.Split(".") + $newversion[2] = [int]$newversion[2] - 1 + if ([int]$newversion[2] -lt 1) { + echo "Unity ${{ inputs.unityVersion }} not found on this machine, skipping" + exit 0 + } + $newunityVersion = "{0}.{1}.{2}f1" -f $newversion[0],$newversion[1],$newversion[2] + echo "Unity $unityVersion not found on this machine, trying $newunityVersion" + $unityVersion = $newunityVersion + $checkPath = Join-Path $editorRootPath $unityVersion + } + echo "::endgroup::" + + echo "::group::Set editor locations" + + if ( (-not $global:PSVersionTable.Platform) -or ($global:PSVersionTable.Platform -eq "Win32NT") ) { + echo 'Building using Windows' + $editorFileEx = "/Editor/Unity.exe" + $editorrunpath = Join-Path $editorRootPath $unityVersion $editorFileEx + + function unity-editor { + #$p = Start-Process -Verbose -NoNewWindow -PassThru -Wait -FilePath "$editorrunpath" -ArgumentList (@(' -batchmode') + $args.Split(" ")) + & $editorrunpath -batchmode $args.Split(" ") | Out-String + } + } + elseif ( $global:PSVersionTable.OS.Contains("Darwin") ) { + echo 'Building using Mac' + $editorFileEx = "/Unity.app/Contents/MacOS/Unity" + $editorrunpath = Join-Path $editorRootPath $unityVersion $editorFileEx + + function unity-editor { + #$p = Start-Process -Verbose -NoNewWindow -PassThru -Wait -FilePath "$editorrunpath" -ArgumentList (@(' -batchmode') + $args.Split(" ")) + & $editorrunpath -batchmode $args.Split(" ") | Out-String + } + } + elseif ( $global:PSVersionTable.OS.Contains("Linux") ) { + echo 'Building using Linux' + $editorFileEx = "/Editor/Unity" + $editorrunpath = Join-Path $editorRootPath $unityVersion $editorFileEx + + function unity-editor { + xvfb-run --auto-servernum "$editorrunpath" -batchmode $args.Split(" ") + } + } + else + { + echo 'Unknown build platform' + } + + echo "::endgroup::" + + echo "::group::Test Unity version is installed" + + if ( -not (Test-Path "$editorrunpath") ) + { + Write-Error "Editor not Found for $unityVersion" + exit 1 + } + else { + echo "Editor Path is {$editorrunpath}" + } + + echo "::endgroup::" + + echo "::group::Setup logging and run Unit tests" + + # Log detail + $logDirectory = "Logs" + if (Test-Path -Path $logDirectory) { + echo "Clearing logs from a previous run" + Remove-item $logDirectory -recurse + } + + $logDirectory = New-Item -ItemType Directory -Force -Path $logDirectory | Select-Object + + echo "Log Directory: $logDirectory" + $date = Get-Date -Format "yyyyMMddTHHmmss" + + # If run manually, the Refname is actually blank, so just use date + if([string]::IsNullOrEmpty(${GITHUB_REF_NAME})) { + $logName = "$logDirectory$directorySeparatorChar$date" + } + else{ + $logName = "$logDirectory$directorySeparatorChar${GITHUB_REF_NAME}-$date" + } + + $logPath = "$logName.log" + $testsLogPath = "$logName-tests.xml" + + echo "Logpath [$logPath]" + echo "TestsPath [$testsLogPath]" + echo "::endgroup::" + + echo "::group::Grouping Package in a UPM folder" + + $UPMFolderName = 'u' + + if ( -not (Test-Path '$UPMFolderName') ) + { + New-Item $UPMFolderName -ItemType Directory + } + + Move-Item -Path * -Destination $UPMFolderName -exclude $UPMFolderName + + echo "::endgroup::" + + echo "::group::Creating Temp Unity project" + + $TempUnityProjectName = 'P' + + unity-editor '-createProject' $TempUnityProjectName -quit + + $destinationPath = $TempUnityProjectName + $directorySeparatorChar + 'packages' + Move-Item -Path $UPMFolderName -Destination $destinationPath + + echo "::endgroup::" + + echo "::group::If required, clone dependencies in to test project" + + <# Dependency option requires specific inputs + + * A dependency input string in json format, listing each dependency by name and git url, e.g. + $dependencies = '[{"ASADependencies": "github.com/SimonDarksideJ/upmGithubActionsTests.git"}]' + *Note, remove the https:// portion to allow using a PAT to access the repo + The Name of the dependency should ALSO MATCH the name of the branch on the repo where the dependency is held (files intended for the packages folder) + + * Additionally, if Manifest entries are required, then a manifest file with those dependencies (and ONLY the new dependancies) should also be in the dependency branch named the same as the branch name + e.g. "ASADependencies.json" - keep the same structure, but only the dependancy entries + + !!Does NOT support additional scoped registries at this time! #> + + echo "---------------------------------------------" + echo "Read dependancy input value" + if([string]::IsNullOrEmpty('${{ inputs.dependencies }}')) + { + echo "No dependencies provided" + echo "input ${{ inputs.dependencies }}" + echo "------------------------------" + } + else { + echo "dependencies provided, validating" + + # Read dependancy input value + $dependencies = '${{ inputs.dependencies }}' + + if([string]::IsNullOrEmpty('${{ secrets.GIT_USER_NAME }}') -or [string]::IsNullOrEmpty('${{ secrets.GIT_PAT }}')){ + echo "" + echo "Secrets for GIT_USER_NAME or GIT_PAT missing, please register them with access to this runner" + echo "*Note, Organisation secrets are not accessible to Forked repos and need registering in the local fork" + exit 1 + } + + echo "---------------------------------------------" + echo "Read dependancy input values as json" + $JSONdependencies = $dependencies | ConvertFrom-Json + + echo $JSONdependencies + + # Read current Manifest json + $manifestPath = $destinationPath + $directorySeparatorChar + 'manifest.json' + $projectManifest = Get-Content -Path $manifestPath | ConvertFrom-Json + $strArray = $projectManifest.dependencies.PsObject.Properties | ForEach-Object {"$($_.Name)@$($_.Value),"} + + echo "---------------------------------------------" + echo "Loop through new dependancies and add them to the project Manifest" + foreach($dependency in $JSONdependencies){ + $dependency.PsObject.Properties | ForEach-Object -Process { + $dependencyName = $_.Name + $dependencyPath = $dependencyName.Replace("/","_") + $dependencyURL = $_.Value + echo "---------------------------------------------" + echo "Cloning dependency - Name [$dependencyName] - Path [$dependencyPath] - URL [$dependencyURL]" + $cloneURL = "https://${{ secrets.GIT_USER_NAME }}:${{ secrets.GIT_PAT }}@$dependencyURL" + + echo "cloning $dependencyName from $dependencyURL and moving to $destinationPath" + echo "git path - $cloneURL" + + # Clone Dependancy repo to destination folder + git clone -b $dependencyName --single-branch $cloneURL $dependencyPath + + if( -not (Test-Path -Path "$dependencyPath")){ + echo "Unable to clone $dependencyName from $dependencyURL" + exit 1 + } + + # Move files from clone path into packages folder, if the dependency contains a UPM package then move the entire folder and not just its contents + if (Test-Path -Path "$dependencyPath/package.json") { + $package_json = Get-Content -Path $dependencyPath/package.json | ConvertFrom-Json + $packageName = $package_json.name + Rename-Item $dependencyPath $packageName + echo "Moving whole $packageName UPM package to $destinationPath" + Move-Item -Path "$packageName" -Destination $destinationPath + } + else { + echo "Moving the contents of $dependencyName into the $destinationPath folder" + Move-Item -Path "$dependencyPath/*" -Destination $destinationPath + } + + # Get Dependency manifest entries (if applicable) + if (Test-Path -Path "$destinationPath/$dependencyName.json") { + $dependencyManifest = Get-Content -Path "$destinationPath/$dependencyName.json" | ConvertFrom-Json + $dependencyManifest.dependencies.PsObject.Properties | ForEach-Object { + $strArray += "$($_.Name)@$($_.Value)," + } + } + else{ + echo "No denendency json found called $destinationPath/$dependencyName.json, skipping adding additional manifest entries" + } + } + } + echo "---------------------------------------------" + + # Reformat combined dependancies list + $strArray = $strArray.Trim(",") | ConvertTo-Json + $strArray = $strArray.Replace("@",'":"').Replace("[","{").Replace("]","}") + $strArrayObject = $strArray | ConvertFrom-Json + + # Save manifest back to project + $projectManifest.dependencies = $strArrayObject + $projectManifest | ConvertTo-Json | Set-Content -Path "$destinationPath/manifest.json" + + echo "Project updated with the following dependencies" + echo "-----------------------------------------------" + echo $projectManifest + } + + echo "::endgroup::" + + echo "::group::Run build" + + echo "---------------------------------------------" + echo "Start Testing" + echo "Unity Command\n[unity-editor -projectPath $TempUnityProjectName -logfile $logPath -batchmode -nographics -quit -buildTarget ${{ matrix.build-target }}]" + + unity-editor -projectPath $TempUnityProjectName -logfile $logPath -batchmode -nographics -quit -buildTarget ${{ matrix.build-target }} + + echo "---------------------------------------------" + echo "::group::Unity Unit tests Results" + if (Test-Path $testsLogPath) { + echo "Test Run results for ${GITHUB_REPOSITORY} Branch ${GITHUB_REF}" + echo "" + Select-Xml -Path $testsLogPath -XPath '/test-run/test-suite' | ForEach-Object { "Name: " +$_.Node.name, ", Result: " + $_.Node.result, ", Total Tests: " + $_.Node.total, ", Passed: " + $_.Node.passed, ", Failed: " + $_.Node.failed, ", Skipped: " + $_.Node.skipped } + } + else { + echo "No test results found for ${GITHUB_REPOSITORY} Branch ${GITHUB_REF} at $testsLogPath" + echo "" + } + echo "::endgroup::" + + if($LASTEXITCODE -ne '0'){ + echo "::group::Unity Unit tests errors" + $exitCode = $testResult.ExitCode + Get-Content $logPath + echo "Build failed due to errors ($LASTEXITCODE), please check the log at $logPath" + echo "::endgroup::" + + exit $LASTEXITCODE + } + echo "::endgroup::" + + shell: pwsh + - uses: actions/upload-artifact@v3 + if: always() + with: + name: unity-build-log + path: Logs/** \ No newline at end of file diff --git a/.github/workflows/tagrelease.yml b/.github/workflows/tagrelease.yml new file mode 100644 index 0000000..c690863 --- /dev/null +++ b/.github/workflows/tagrelease.yml @@ -0,0 +1,146 @@ +name: Package UPM project and deploy + +on: + workflow_call: + inputs: + build-target: + required: true + type: string + build-type: + required: false + default: 'pre-release' + type: string +# options: +# - major +# - minor +# - patch +# - pre-release +# - build + outputs: + packageversion: + description: "Returns the version of Unity the UPM package requires" + value: ${{ jobs.packageRelease.outputs.packageversion }} + secrets: + GIT_USER_NAME: + required: false + +jobs: + packageRelease: + name: Package UPM Project and tag + runs-on: ${{ inputs.build-target }} + outputs: + packageversion: ${{ steps.getpackageversion.outputs.packageversion }} + steps: + - name: Script Version + run: | + echo "::group::Script Versioning" + $scriptVersion = "1.0.2" + echo "Build Script Version: $scriptVersion" + echo "::endgroup::" + shell: pwsh + - uses: actions/checkout@v3 + with: + submodules: recursive + clean: true + token: ${{ secrets.GIT_PAT }} + - uses: actions/setup-node@v3 + - name: Set Github vars + run: | + if([string]::IsNullOrEmpty('${{ secrets.GIT_USER_NAME }}')){ + if([string]::IsNullOrEmpty('${{ secrets.GIT_USER_NAME }}')){ + $gitUser = "action" + $gitEmail = "action@github.com" + } + else { + $gitUser = "${GITHUB_ACTOR}" + $gitEmail = "$gitUser@users.noreply.github.com" + } + } + else { + $gitUser = "${{ secrets.GIT_USER_NAME }}" + $gitEmail = "$gitUser@users.noreply.github.com" + } + echo "email $gitUser@users.noreply.github.com" + git config --global user.email "$gitUser@users.noreply.github.com" + git config --global user.name "$gitUser" + shell: pwsh + - id: getpackageversion + name: Bump UPM Package version + run: | + function UpdateProjectVersionJSON { + param ( + [Parameter(Mandatory)] + $type, + $packageFile = 'package.json' + ) + <# + Type of build can be one of the following + - 'build' # Build release - 1.0.0-pre-release.0+1 + - 'pre-release' # Pre-Release release - 1.0.0-pre-release.1 + - 'patch' # Patch release - 1.0.1 + - 'minor' # Minor release - 1.1.0 + - 'major' # Major release - 2.0.0 + #> + + if ( -not (Test-Path -Path $packageFile) ) { + Write-Error "Failed to find a valid project manifest at `"$packageFile`"" + return $null + } + + $packageInfo = (Get-Content $packageFile -Raw) | ConvertFrom-Json + Write-Host "Detected Project Version:" $packageInfo.version + function IfNull($a, $b, $c) { if ($null -eq $a) { return $b } else { return $c } } + + $packageSemVer = [System.Management.Automation.SemanticVersion]$packageInfo.version + $majorVersion = if($null -eq $packageSemVer.Major) {0} else {$packageSemVer.Major} + $minorVersion = if($null -eq $packageSemVer.Minor) {0} else {$packageSemVer.Minor} + $patchVersion = if($null -eq $packageSemVer.Patch) {0} else {$packageSemVer.Patch} + $prereleaseVersion = if($null -eq $packageSemVer.PreReleaseLabel) {0} else {$packageSemVer.PreReleaseLabel.Replace('pre-release.','')} + $buildVersion = if($null -eq $packageSemVer.BuildLabel) {0} else {$packageSemVer.BuildLabel} + + # work out new version + switch ($type) { + 'build' { + [int]$buildVersion += 1 + $newPackageSemVer = [System.Management.Automation.SemanticVersion]::New($majorVersion, $minorVersion, $patchVersion, "pre-release." + $prereleaseVersion, $buildVersion) + } + 'pre-release' { + [int]$prereleaseVersion += 1 + $newPackageSemVer = [System.Management.Automation.SemanticVersion]::New($majorVersion, $minorVersion, $patchVersion, "pre-release." + $prereleaseVersion) + } + 'patch' { + [int]$patchVersion += 1 + $newPackageSemVer = [System.Management.Automation.SemanticVersion]::New($majorVersion, $minorVersion, $patchVersion) + } + 'minor' { + [int]$minorVersion += 1 + $newPackageSemVer = [System.Management.Automation.SemanticVersion]::New($majorVersion, $minorVersion, 0) + } + 'major' { + [int]$majorVersion += 1 + $newPackageSemVer = [System.Management.Automation.SemanticVersion]::New($majorVersion, 0, 0) + } + } + + Write-Host "Upgrading project version [$packageSemVer] to [$newPackageSemVer]" + + # Write out updated package info + + $packageInfo.version = $newPackageSemVer.ToString() + $packageInfo | ConvertTo-Json | Set-Content $packageFile + + return $packageInfo.version + } + + $packageFile = 'package.json' + $result = UpdateProjectVersionJSON("${{ inputs.build-type }}","$packageFile") + if([string]::IsNullOrEmpty($result)) { + echo "Version patch failed" + exit 1 + } + echo "packageversion=$result" >> $env:GITHUB_OUTPUT + git add "$packageFile" + git commit -m "Auto increment pre-release version to $result [skip ci]" + git tag -fa "$result" "${GITHUB_SHA}" -m "$result Release" + git push origin --force + shell: pwsh \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index fd7acb8..777b91d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,3 @@ [submodule "Examples~"] path = Examples~ - url = https://SimonDarksideJ@bitbucket.org/UnityUIExtensions/unity-ui-extensions.git - branch = Examples + url = https://github.com/Unity-UI-Extensions/com.unity.uiextensions-examples.git diff --git a/.npmignore b/.npmignore index edc7da1..cd85c8d 100644 --- a/.npmignore +++ b/.npmignore @@ -35,6 +35,4 @@ sysinfo.txt /.vs *.gitmodules -# NPM publish exclusions -bitbucket-pipelines.yml -bitbucket-pipelines.yml.meta \ No newline at end of file +**/.github/* \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b1c096..da6b774 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,74 +4,117 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/). -## 2019.6 - 2.5 - Bug squash - 2021/05/10 +## Release 2.3 - Reanimation - 2022/02/07 -Its been a while since the last update and although Unity keeps changing, thankfully the parts underneath do not. THanks to some awesome work by our contributors and the test teams, we made a run on some underlying bugs and issues. If you spot anything else, please log it on the BitBucket site for resolution. +It has been a tough time for all since the last update, but things have been moving steadily along. In the past few months there has been a concerted effort to revamp and update the project ready for Unity 2022, as well as migrating the source repository over to GitHub and refreshing all the things. +We hope the new release is better for everyone and we have paid close attention to the editor menus and places to find all the controls for this release. -> Be sure to logon to the new [Gitter Chat](https://gitter.im/Unity-UI-Extensions/Lobby) site for the UI Extensions project, if you have any questions, queries or suggestions +To get up to speed with the Unity UI Extensions, check out the [Getting Started](https://unity-ui-extensions.github.io/GettingStarted.html) Page. + +> Ways to get in touch: +> +> - [Gitter Chat](https://gitter.im/Unity-UI-Extensions/Lobby) site for the UI Extensions project +> - [GitHub Discussions](https://github.com/Unity-UI-Extensions/com.unity.uiextensions/discussions), if you have any questions, queries or suggestions > > Much easier that posting a question / issue on YouTube, Twitter or Facebook :D -> -> ## [UIExtensions Gitter Channel](https://gitter.im/Unity-UI-Extensions/Lobby) +## Breaking changes -### Added +For customers upgrading from earlier versions of Unity to Unity 2020, please be aware of the Breaking change related to Text Based components. You will need to manually replace any UI using the older ```Text``` component and replace them with ```TextMeshPro``` versions. This is unavoidable due to Unity deprecating the Text component. -Nothing new this time, bugfix release. +> New users to 2022 are unaffected as all the Editor commands have been updated to use the newer TextMeshPro versions. -### Changed +For more details, see the [deprecation notice](https://github.com/Unity-UI-Extensions/com.unity.uiextensions/discussions/428) on GitHub. -- Updated UI Line connector to use relative position instead of anchored position to verify if the Lines need updating. -- Allow menu prefabs to not have to have canvas components. This allows you to use any type of prefab as a "menu". Adam Kapos mentions the concept on the Unite talk, https://youtu.be/wbmjturGbAQ?t=1654 -- Updated segment line drawing for Line Lists. Seems Unity no longer needs UV's to be wrapped manually. -- Updated the AutoCompleteComboBox to display text as entered (instead of all lowercase) -- Updated the ComboBox to display text as entered (instead of all lowercase) -- Updated ComboBox Examples to include programmatic versions -- Further ComboBox improvements including: - * Upwards panel - * Start fixes - * Item Template resize - * Disabled sorting on combobox as it wasn't working - * Disabled Slider handle when not in use - * Updated Example -- Updated the new Input system switch and tested against 2021 +## Added -### Deprecated +- Added new FIFO based UI Line Render when dynamic line rendering is needed. +- Added ResetSelectableHighlight component. +- Added SetArc method to UICircle as requested. +- Added new UIHorizontalScroller based on UIVerticalScroller. +- Added OnHighlightChanged and OnPressChanged events for UI Button. +- Added error handling around setting Unity UI Components for Vertical/Horizontal ScrollSnaps. +- Added Editor Menu Option to create a Min/Max slider. +- Added the ability to set a specific item for combobox controls on start and not just the first. +- Added the ability to disable the combo boxes and make them read-only. -None +## Changed -### Fixed +- Refresh FancyScrollView with the latest fixes +- All Text based components updated to use TextMeshPro from Unity 2022 **Breaking Change** -- Reordering issue resolved with ScrollRectOcclusion. -- Fixed Sorting at min and max positions for ScrollRect -- Updated ScrollToSelect script provided by zero3growlithe, tested and vastly reduces the previous jitter. Still present but barely noticeable now. -- Fixed Issue # 363 Update Combobox control that takes multiple items programmatically, to only allow distinct items -- Fixed the issues where dragging outside the range slider handle causes the range to update. - Resolves #369 -- Resolves an issue with Unity putting the previous controls vertex array in an uninitialised control. -- Applied J.R. Mitchell's fix for the Accordion Controls/Accordion/AccordionElement.cs - resolves: #364 -- Resolved issue where the Content Scroll snap issue with only 1 child. Resolves #362 -- Updated the PaginationManager to override if the ScrollSnap is in motion. +- Clean-up and reset pivots on scene start. +- Merged in feature/improved-ui-highlightable (pull request UILineRenderer - issues with specifying point locations at runtime #123). +- Merged in fix/rangesliderfix (pull request HorizontalScrollSnap Mask Area doesn't work when content created dynamically #125). +- Merged in fix/infinitescrollcontentsize (pull request Gradient initialization should be in Awake() #126). +- Merged in feature/controlTouchUp (pull request UILineRenderer mesh not updating in Editor scene view #127). +- Upgraded RangeSlider to work in both Horizontal and Vertical setups. +- Merged in RangeSlider-upgrade. (pull request Newtonsoft.Json.dll conflict #131) +- Updated UIVertical scroller to be 2022 compliant. +- Updated Curly UI to wait until end of the frame to recalculate positions. +- Updated Depth Texture sampler in UI Particles Shaders. +- Updated Points to always be an array of 1 when set to nothing for the Line Renderer. +- Updated Cooldown button to work with Keyboard input. +- Removed unneeded size calculation which caused some issues with mixed content. +- Resolved an issue whereby the last row in a flow layout group would not size correctly. +- Updated all components using "LayoutGroup" to override their OnDisable. +- Updated validation in the new MinMaxSlider. +- Updated Editor create options to add the correct Event System Input manager. +- Updated initialisation logic to not cause an endless loop in the TabNavigationHelper. +- Updated "Action" use to "UnityAction" to avoid Unity issues for DropDowns. +- Updated UIVerticalScroller for standards. +- Updated ReorderableList/ReorderableListElement to prevent creating a fake object for non-transferable items. +- Updated panel drawing for ComboBox controls and added DropdownOffset. +- Updated build issue with ReorderableListElement. +- Updated NonDrawingGraphic to require a CanvasRender, else it causes an error on run. -### Removed +## Deprecated -None +- Marked ScrollPositionController as Obsolete, users should use the new Scoller. +- BestFitOutline - Deprecated in Unity 2020 onwards. (still available for earlier versions) +- NicerOutline - Deprecated in Unity 2020 onwards. (still available for earlier versions) +- Marked TileSizeFitter as obsolete as Unity has made this unworkable. -### Additional Notes +## Fixed -#### [Installation Instructions](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/GettingStarted) +- Resolved issues with DisplayAbove and using a 0 ItemsToDisplay for ComboBox controls. +- Resolved startup issue that prevented the control from being used (Unity changed the start order in some instances), this was causing null reference issues with comboboxes. +- Patch fix for UILineRenderer. +- Resolves issue where the lower range value would become stuck when moving. +- Updated Infinite scroll to work with content of different sizes. +- Updated Dropdown list to NOT resize text Rect on draw. +- Revised the Curly UI fix as it was preventing the graphic from being updated in the scene view. +- Cleanup and ensuring the UIParticleSystem is disposed in onDestroy correctly. +- Clean up range slider unused variables. -As of Unity 2019, there are now two paths for getting access to the Unity UI Extensions project: +## Additional Notes + +### [Installation Instructions](https://unity-ui-extensions.github.io/UPMInstallation.html) -- Unity 2019 or higher The recommended way to add the Unity UI Extensions project to your solution is to use the Unity package Manager. Simply use the Unity Package Manager to reference the project to install it -Alternatively, you can also use the pre-compiled Unity packages if you wish, however, UPM offers full versioning support to allow you to switch versions as you wish. +New for 2020, we have added OpenUPM support and the package can be installed using the following [OpenUPM CLI](https://openupm.com/docs/) command: + +```cli +`openupm add com.unity.uiextensions` +``` +> For more details on using [OpenUPM CLI, check the docs here](https://github.com/openupm/openupm-cli#installation). + +- Unity Package Manager - manual + +Alternatively, you can also add the package manually through the Unity package manager using the scope ```com.unity.uiextensions```, see the [Unity Package Manager docs](https://learn.unity.com/tutorial/the-package-manager) for more information. - Unity 2018 or lower The pre-compiled Unity assets are the only solution for Unity 2018 or earlier due to the changes in the Unity UI framework in Unity made for 2019. Either clone / download this repository to your machine and then copy the scripts in, or use the pre-packaged .UnityPackage for your version of Unity and import it as a custom package in to your project. -#### Upgrade Notes +### Upgrade Notes + +### UPM + +If you are using UPM to gain access to the Unity UI Extensions, then you only need to update to the latest version in the Package Manager, no other changes needed. + +### Customers using the .UnityPackage Due to the restructure of the package to meet Unity's new package guidelines, we recommend **Deleting the current Unity UI Extensions** folder prior to importing the new package. diff --git a/Documentation~/com.unity.uiextensions.md b/Documentation~/com.unity.uiextensions.md index 93ed189..51debb1 100644 --- a/Documentation~/com.unity.uiextensions.md +++ b/Documentation~/com.unity.uiextensions.md @@ -5,17 +5,20 @@ The Unity UI Extensions project is a collection of extension scripts/effects and controls to enhance your Unity UI experience. This includes over 70+ controls, utilities, effects and some much-needed love to make the most out of the Unity UI system (formally uGUI) in Unity. [Check out our Tumblr page for a sneak peek](https://www.tumblr.com/blog/unityuiextensions) -> Contact the UI Extensions Team -> Be sure to logon to the new [Gitter Chat site](https://gitter.im/Unity-UI-Extensions/Lobby) for the UI Extensions project, if you have any questions, queries or suggestions -> Much easier than posting a question / issue on [YouTube](http://www.youtube.com/c/UnityUIExtensions), [Twitter](https://twitter.com/hashtag/UnityUIExtensions) or [Facebook](https://www.facebook.com/UnityUIExtensions) :D +You can follow the UI Extensions team for updates and news on: + +### [Twitter - #unityuiextensions](https://twitter.com/search?q=%23unityuiextensions) / [Facebook](https://www.facebook.com/UnityUIExtensions/) / [YouTube](https://www.youtube.com/@UnityUIExtensions) + +> Ways to get in touch: > -> [**UIExtensions Gitter Chanel**](https://gitter.im/Unity-UI-Extensions/Lobby) +> - [Gitter Chat](https://gitter.im/Unity-UI-Extensions/Lobby) site for the UI Extensions project +> - [GitHub Discussions](https://github.com/Unity-UI-Extensions/com.unity.uiextensions/discussions), if you have any questions, queries or suggestions # Installing Unity UI Extensions To install this package, follow the instructions in the Package Manager documentation. -For more details on [Getting Started](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/GettingStarted) please checkout the [online documentation here](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/GettingStarted). +For more details on [Getting Started](https://unity-ui-extensions.github.io/GettingStarted) please checkout the [online documentation here](https://unity-ui-extensions.github.io/). # Using Unity UI Extensions @@ -23,7 +26,7 @@ The UI Extensions project provides many automated functions to add the various c Some of the features are also available through the GameObject "Add Component" menu in the inspector. -For a full list of the controls and how they are used, please see the [online documentation](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Controls) for the project. +For a full list of the controls and how they are used, please see the [online documentation](https://unity-ui-extensions.github.io/Controls.html) for the project. # Technical details @@ -31,64 +34,102 @@ For a full list of the controls and how they are used, please see the [online do This version of the Unity UI Extensions is compatible with the following versions of the Unity Editor: -- 2019 and above - the recommended path for 2019+ is to use the Unity Package Manager to get access to the package. Full details for installing via UPM can be [found here](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/UPMInstallation). +- 2019 and above - the recommended path for 2019+ is to use the Unity Package Manager to get access to the package. Full details for installing via UPM can be [found here](https://unity-ui-extensions.github.io/UPMInstallation.html). > Alternatively, the Asset packages have been tested to work with 2019 as well if you prefer to install that way. -- 2018 and below - for 2018 and use this package, you will have to import the asset package(s), either from the Asset Store or from the alternate download locations [listed here](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Downloads). +- 2018 and below - for 2018 and use this package, you will have to import the asset package(s), either from the Asset Store or from the alternate download locations [listed here](https://unity-ui-extensions.github.io/Downloads). -## [Release Notes](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/ReleaseNotes/RELEASENOTES) +## [Release Notes](https://unity-ui-extensions.github.io/ReleaseNotes/RELEASENOTES) -### 2019.5 - 2.3 - Accelerated Deployment +## Release 2.3 - Reanimation - 2022/02/07 -#### Added +It has been a tough time for all since the last update, but things have been moving steadily along. In the past few months there has been a concerted effort to revamp and update the project ready for Unity 2022, as well as migrating the source repository over to GitHub and refreshing all the things. +We hope the new release is better for everyone and we have paid close attention to the editor menus and places to find all the controls for this release. -- Add squircle primitive -- Adding new magnetic scroll control -- Added a static library to collate shaders on first use. -- Finalized new InputManagerHelper, which translates input based on the operating input system, new or old Updated CardStack2D to have defined keyboard input or specific gamepad input over the older axisname for new input system. -- Updated DropDown and Autocomplete controls based on feedback in #204 +To get up to speed with the Unity UI Extensions, check out the [Getting Started](https://unity-ui-extensions.github.io/GettingStarted.html) Page. -#### Changed +> Ways to get in touch: +> +> - [Gitter Chat](https://gitter.im/Unity-UI-Extensions/Lobby) site for the UI Extensions project +> - [GitHub Discussions](https://github.com/Unity-UI-Extensions/com.unity.uiextensions/discussions), if you have any questions, queries or suggestions +> +> Much easier that posting a question / issue on YouTube, Twitter or Facebook :D -- Examples now included with UPM delivery and available as a button on the UPM package manager window -- Updated DropDown and Autocomplete controls based on feedback in #204 -- Updated Accordion to support both Vertical as well as Horizontal layout -- Updated ComboBox controls to improve better programmatic controls -- Updates to the Infinite scroll to support content of various sizes -- Updated UI Knob control - enabled dragging outside the target area, added example scene -- Minor update to MagneticInfinite Scroll -- Refactored and extended the ContentScrollSnap control -- Added protection against errors and empty scrollrect content -- Added new SetNewItems function to add children programmatically to the control and reset accordingly -- Patch supplied by a contributor to improve the texture sheet use with the UIParticlesystem -- Added "SetKnobValue" function which allows the setting of Value and loops -- Added the programmatic capability to change the parent scroll rect on the ScrollConflictManager at runtime. +## Breaking changes -#### Deprecated +For customers upgrading from earlier versions of Unity to Unity 2020, please be aware of the Breaking change related to Text Based components. You will need to manually replace any UI using the older ```Text``` component and replace them with ```TextMeshPro``` versions. This is unavoidable due to Unity deprecating the Text component. -None +> New users to 2022 are unaffected as all the Editor commands have been updated to use the newer TextMeshPro versions. -#### Fixed +For more details, see the [deprecation notice](https://github.com/Unity-UI-Extensions/com.unity.uiextensions/discussions/428) on GitHub. -- Fix to add a "RequireComponent" to Primitives as Unity 2020 does not add them by default -- Remove old Examples submodule -- Updated submodules to hide Examples folder Additionally, updated Package manifest to allow importing of examples direct from UPM package. -- Fixed hard swipe to ensure it only ever moves one page, no matter how far you swipe. -- Fixed a conflict when using the ScrollConflictManager in child content of a HSS or VSS -- Fix for UI Particle system looping -- Fixed public GoToScreen call to only raise events internally (not multiple) -- Final roll-up and fix. Resolved race condition for associated pagination controls. -- Fixed issue with page events not being raised when inertia was disabled (velocity was always zero) -- When cloned, reorderable list was creating a second List Content component that was not initialized. Refactored to ensure only one list content was present and is initialized correctly -- Reorderable list items marked as transferable, remain transferable after being dropped -- Patch to resolve issues without the new Input System installed -- Refined magnetic scroll and dependencies while documenting Updated example -- Patch Tooltip +## Added -#### Removed +- Added new FIFO based UI Line Render when dynamic line rendering is needed. +- Added ResetSelectableHighlight component. +- Added SetArc method to UICircle as requested. +- Added new UIHorizontalScroller based on UIVerticalScroller. +- Added OnHighlightChanged and OnPressChanged events for UI Button. +- Added error handling around setting Unity UI Components for Vertical/Horizontal ScrollSnaps. +- Added Editor Menu Option to create a Min/Max slider. +- Added the ability to set a specific item for combobox controls on start and not just the first. +- Added the ability to disable the combo boxes and make them read-only. -None +## Changed + +- Refresh FancyScrollView with the latest fixes +- All Text based components updated to use TextMeshPro from Unity 2022 **Breaking Change** + +- Clean-up and reset pivots on scene start. +- Merged in feature/improved-ui-highlightable (pull request UILineRenderer - issues with specifying point locations at runtime #123). +- Merged in fix/ragesliderfix (pull request HorizontalScrollSnap Mask Area doesn't work when content created dynamically #125). +- Merged in fix/infinitescrollcontentsize (pull request Gradient initialization should be in Awake() #126). +- Merged in feature/controlTouchUp (pull request UILineRenderer mesh not updating in Editor scene view #127). +- Upgraded RangeSlider to work in both Horizontal and Vertical setups. +- Merged in RangeSlider-upgrade. (pull request Newtonsoft.Json.dll conflict #131) +- Updated UIVertical scroller to be 2022 compliant. +- Updated Curly UI to wait until end of the frame to recalculate positions. +- Updated Depth Texture sampler in UI Particles Shaders. +- Updated Points to always be an array of 1 when set to nothing for the Line Renderer. +- Updated Cooldown button to work with Keyboard input. +- Removed unneeded size calculation which caused some issues with mixed content. +- Resolved an issue whereby the last row in a flow layout group would not size correctly. +- Updated all components using "LayoutGroup" to override their OnDisable. +- Updated validation in the new MinMaxSlider. +- Updated Editor create options to add the correct Event System Input manager. +- Updated initialisation logic to not cause an endless loop in the TabNavigationHelper. +- Updated "Action" use to "UnityAction" to avoid Unity issues for DropDowns. +- Updated UIVerticalScroller for standards. +- Updated ReorderableList/ReorderableListElement to prevent creating a fake object for non-transferable items. +- Updated panel drawing for ComboBox controls and added DropdownOffset. +- Updated build issue with ReorderableListElement. +- Updated NonDrawingGraphic to require a CanvasRender, else it causes an error on run. + +## Deprecated + +- Marked ScrollPositionController as Obsolete, users should use the new Scoller. +- BestFitOutline - Deprecated in Unity 2020 onwards. (still available for earlier versions) +- NicerOutline - Deprecated in Unity 2020 onwards. (still available for earlier versions) +- Marked TileSizeFitter as obsolete as Unity has made this unworkable. + +## Fixed + +- Resolved issues with DisplayAbove and using a 0 ItemsToDisplay for ComboBox controls. +- Resolved startup issue that prevented the control from being used (Unity changed the start order in some instances), this was causing null reference issues with comboboxes. +- Patch fix for UILineRenderer. +- Resolves issue where the lower range value would become stuck when moving. +- Updated Infinite scroll to work with content of different sizes. +- Updated Dropdown list to NOT resize text Rect on draw. +- Revised the Curly UI fix as it was preventing the graphic from being updated in the scene view. +- Cleanup and ensuring the UIParticleSystem is disposed in onDestroy correctly. +- Clean up range slider unused variables. + +- [UI Extensions Issue log](https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues) + +## Upgrade Notes + +We recommend using the UPM delivery method. If you are using the Unity asset, there should be no issues updating but if you have a problem, just deleted the old Unity-UI-Extensions folder and import the asset new. # Document revision history @@ -98,3 +139,4 @@ None |September 3rd, 2019|2019.1 (v2.1) released, First major update for the 2.0 series.| |August 8th, 2020|2019.4 (v2.2) released, New UPM Delivery.| |October 10th, 2020|2019.5 (v2.2) released, New UPM fast delivery| +|February 7th, 2022|v2.3 released, New Home, UPM fast delivery via OpenUPM| diff --git a/Editor/BoxSliderEditor.cs.meta b/Editor/BoxSliderEditor.cs.meta index fa47eba..9e12253 100644 --- a/Editor/BoxSliderEditor.cs.meta +++ b/Editor/BoxSliderEditor.cs.meta @@ -1,12 +1,11 @@ -fileFormatVersion: 2 -guid: 8701e045b26e51f4eb345f2ccb3c13f5 -timeCreated: 1426804458 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: c1047f9974e7ee1478bbf5490a7a62d8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/CUIImageEditor.cs b/Editor/CUIImageEditor.cs index c961d07..a3eb6f1 100644 --- a/Editor/CUIImageEditor.cs +++ b/Editor/CUIImageEditor.cs @@ -68,7 +68,12 @@ namespace UnityEngine.UI.Extensions Handles.color = Color.gray; EditorGUI.BeginChangeCheck(); +#if UNITY_2022_1_OR_NEWER + Vector3 newCornerPos = Handles.FreeMoveHandle(script.transform.TransformPoint(cornerPos), HandleUtility.GetHandleSize(script.transform.TransformPoint(cornerPos)) / 7, Vector3.one, Handles.SphereHandleCap); +#else Vector3 newCornerPos = Handles.FreeMoveHandle(script.transform.TransformPoint(cornerPos), script.transform.rotation, HandleUtility.GetHandleSize(script.transform.TransformPoint(cornerPos)) / 7, Vector3.one, Handles.SphereHandleCap); +#endif + Handles.Label(newCornerPos, string.Format("Corner Mover")); newCornerPos = script.transform.InverseTransformPoint(newCornerPos); diff --git a/Editor/FancyScrollView/ScrollerEditor.cs b/Editor/FancyScrollView/ScrollerEditor.cs index 2d4982f..34673e3 100644 --- a/Editor/FancyScrollView/ScrollerEditor.cs +++ b/Editor/FancyScrollView/ScrollerEditor.cs @@ -4,8 +4,6 @@ using UnityEditor; using UnityEditor.AnimatedValues; -// For maintenance, every new [SerializeField] variable in Scroller must be declared here - namespace UnityEngine.UI.Extensions { [CustomEditor(typeof(Scroller))] @@ -20,16 +18,11 @@ namespace UnityEngine.UI.Extensions SerializedProperty inertia; SerializedProperty decelerationRate; SerializedProperty snap; - SerializedProperty snapEnable; - SerializedProperty snapVelocityThreshold; - SerializedProperty snapDuration; - SerializedProperty snapEasing; SerializedProperty draggable; SerializedProperty scrollbar; AnimBool showElasticity; AnimBool showInertiaRelatedValues; - AnimBool showSnapEnableRelatedValues; void OnEnable() { @@ -41,16 +34,11 @@ namespace UnityEngine.UI.Extensions inertia = serializedObject.FindProperty("inertia"); decelerationRate = serializedObject.FindProperty("decelerationRate"); snap = serializedObject.FindProperty("snap"); - snapEnable = serializedObject.FindProperty("snap.Enable"); - snapVelocityThreshold = serializedObject.FindProperty("snap.VelocityThreshold"); - snapDuration = serializedObject.FindProperty("snap.Duration"); - snapEasing = serializedObject.FindProperty("snap.Easing"); draggable = serializedObject.FindProperty("draggable"); scrollbar = serializedObject.FindProperty("scrollbar"); showElasticity = new AnimBool(Repaint); showInertiaRelatedValues = new AnimBool(Repaint); - showSnapEnableRelatedValues = new AnimBool(Repaint); SetAnimBools(true); } @@ -58,14 +46,12 @@ namespace UnityEngine.UI.Extensions { showElasticity.valueChanged.RemoveListener(Repaint); showInertiaRelatedValues.valueChanged.RemoveListener(Repaint); - showSnapEnableRelatedValues.valueChanged.RemoveListener(Repaint); } void SetAnimBools(bool instant) { SetAnimBool(showElasticity, !movementType.hasMultipleDifferentValues && movementType.enumValueIndex == (int)MovementType.Elastic, instant); SetAnimBool(showInertiaRelatedValues, !inertia.hasMultipleDifferentValues && inertia.boolValue, instant); - SetAnimBool(showSnapEnableRelatedValues, !snapEnable.hasMultipleDifferentValues && snapEnable.boolValue, instant); } void SetAnimBool(AnimBool a, bool value, bool instant) @@ -126,31 +112,6 @@ namespace UnityEngine.UI.Extensions { EditorGUILayout.PropertyField(decelerationRate); EditorGUILayout.PropertyField(snap); - - using (new EditorGUI.IndentLevelScope()) - { - DrawSnapRelatedValues(); - } - } - } - } - - void DrawSnapRelatedValues() - { - if (snap.isExpanded) - { - EditorGUILayout.PropertyField(snapEnable); - - using (var group = new EditorGUILayout.FadeGroupScope(showSnapEnableRelatedValues.faded)) - { - if (!group.visible) - { - return; - } - - EditorGUILayout.PropertyField(snapVelocityThreshold); - EditorGUILayout.PropertyField(snapDuration); - EditorGUILayout.PropertyField(snapEasing); } } } diff --git a/Editor/MinMaxSliderEditor.cs b/Editor/MinMaxSliderEditor.cs new file mode 100644 index 0000000..19f6457 --- /dev/null +++ b/Editor/MinMaxSliderEditor.cs @@ -0,0 +1,121 @@ +///Credit brogan89 +///Sourced from - https://github.com/brogan89/MinMaxSlider + +using System; +using UnityEditor; +using UnityEditor.UI; + +namespace UnityEngine.UI.Extensions +{ + [CustomEditor(typeof(MinMaxSlider), true)] + [CanEditMultipleObjects] + public class MinMaxSliderEditor : SelectableEditor + { + private SerializedProperty _customCamera; + private SerializedProperty _sliderBounds; + private SerializedProperty _minHandle; + private SerializedProperty _maxHandle; + private SerializedProperty _minText; + private SerializedProperty _maxText; + private SerializedProperty _textFormat; + private SerializedProperty _middleGraphic; + private SerializedProperty _minLimit; + private SerializedProperty _maxLimit; + private SerializedProperty _wholeNumbers; + private SerializedProperty _minValue; + private SerializedProperty _maxValue; + + private SerializedProperty _onValueChanged; + + private readonly GUIContent label = new GUIContent("Min Max Values"); + + protected override void OnEnable() + { + base.OnEnable(); + _customCamera = serializedObject.FindProperty("customCamera"); + _sliderBounds = serializedObject.FindProperty("sliderBounds"); + _minHandle = serializedObject.FindProperty("minHandle"); + _maxHandle = serializedObject.FindProperty("maxHandle"); + _minText = serializedObject.FindProperty("minText"); + _maxText = serializedObject.FindProperty("maxText"); + _textFormat = serializedObject.FindProperty("textFormat"); + _middleGraphic = serializedObject.FindProperty("middleGraphic"); + _minLimit = serializedObject.FindProperty("minLimit"); + _maxLimit = serializedObject.FindProperty("maxLimit"); + _wholeNumbers = serializedObject.FindProperty("wholeNumbers"); + _minValue = serializedObject.FindProperty("minValue"); + _maxValue = serializedObject.FindProperty("maxValue"); + _onValueChanged = serializedObject.FindProperty("onValueChanged"); + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + float minLimitOld = _minLimit.floatValue; + float maxLimitOld = _maxLimit.floatValue; + float minValueOld = _minValue.floatValue; + float maxValueOld = _maxValue.floatValue; + + EditorGUILayout.PropertyField(_customCamera); + EditorGUILayout.PropertyField(_sliderBounds); + EditorGUILayout.PropertyField(_minHandle); + EditorGUILayout.PropertyField(_maxHandle); + EditorGUILayout.PropertyField(_middleGraphic); + + EditorGUILayout.PropertyField(_minText); + EditorGUILayout.PropertyField(_maxText); + EditorGUILayout.PropertyField(_textFormat); + + EditorGUILayout.PropertyField(_minLimit); + EditorGUILayout.PropertyField(_maxLimit); + + EditorGUILayout.PropertyField(_wholeNumbers); + EditorGUILayout.PropertyField(_minValue); + EditorGUILayout.PropertyField(_maxValue); + + float minValue = Mathf.Clamp(_minValue.floatValue, _minLimit.floatValue, _maxLimit.floatValue); + float maxValue = Mathf.Clamp(_maxValue.floatValue, _minLimit.floatValue, _maxLimit.floatValue); + EditorGUILayout.MinMaxSlider(label, ref minValue, ref maxValue, _minLimit.floatValue, _maxLimit.floatValue); + + bool anyValueChanged = !IsEqualFloat(minValueOld, minValue) + || !IsEqualFloat(maxValueOld, maxValue) + || !IsEqualFloat(minLimitOld, _minLimit.floatValue) + || !IsEqualFloat(maxLimitOld, _maxLimit.floatValue); + + if (anyValueChanged) + { + MinMaxSlider slider = (MinMaxSlider)target; + + // force limits to ints if whole numbers. + // needed to do this here because it wouldn't set in component script for some reason + if (slider.wholeNumbers) + { + _minLimit.floatValue = Mathf.RoundToInt(_minLimit.floatValue); + _maxLimit.floatValue = Mathf.RoundToInt(_maxLimit.floatValue); + } + + // set slider values + slider.SetValues(minValue, maxValue, _minLimit.floatValue, _maxLimit.floatValue); + } + + EditorGUILayout.Space(); + EditorGUILayout.PropertyField(_onValueChanged); + + serializedObject.ApplyModifiedProperties(); + } + + /// + /// Returns true if floating point numbers are within 0.01f (close enough to be considered equal) + /// + /// + /// + /// + private static bool IsEqualFloat(float a, float b) + { + return Math.Abs(a - b) < 0.01f; + } + } +} \ No newline at end of file diff --git a/Editor/MinMaxSliderEditor.cs.meta b/Editor/MinMaxSliderEditor.cs.meta new file mode 100644 index 0000000..6730b44 --- /dev/null +++ b/Editor/MinMaxSliderEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 69352ed1561021b48ac258f81f48a988 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/RangeSliderEditor.cs b/Editor/RangeSliderEditor.cs index 516d5ab..df0ba53 100644 --- a/Editor/RangeSliderEditor.cs +++ b/Editor/RangeSliderEditor.cs @@ -12,6 +12,7 @@ namespace UnityEngine.UI.Extensions [CanEditMultipleObjects] public class RangeSliderEditor : SelectableEditor { + SerializedProperty m_Direction; SerializedProperty m_LowHandleRect; SerializedProperty m_HighHandleRect; SerializedProperty m_FillRect; @@ -36,6 +37,7 @@ namespace UnityEngine.UI.Extensions m_LowHandleRect = serializedObject.FindProperty("m_LowHandleRect"); m_HighHandleRect = serializedObject.FindProperty("m_HighHandleRect"); m_FillRect = serializedObject.FindProperty("m_FillRect"); + m_Direction = serializedObject.FindProperty("m_Direction"); m_MinValue = serializedObject.FindProperty("m_MinValue"); m_MaxValue = serializedObject.FindProperty("m_MaxValue"); @@ -66,6 +68,16 @@ namespace UnityEngine.UI.Extensions if (m_LowHandleRect.objectReferenceValue != null && m_HighHandleRect.objectReferenceValue != null) { EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(m_Direction); + if (EditorGUI.EndChangeCheck()) + { + RangeSlider.Direction direction = (RangeSlider.Direction)m_Direction.enumValueIndex; + foreach (var obj in serializedObject.targetObjects) + { + RangeSlider rangeSlider = obj as RangeSlider; + rangeSlider.SetDirection(direction, true); + } + } EditorGUILayout.PropertyField(m_MinValue); EditorGUILayout.PropertyField(m_MaxValue); @@ -120,4 +132,3 @@ namespace UnityEngine.UI.Extensions } } - diff --git a/Editor/ScrollPositionControllerEditor.cs b/Editor/ScrollPositionControllerEditor.cs index e4ae2cc..f56c735 100644 --- a/Editor/ScrollPositionControllerEditor.cs +++ b/Editor/ScrollPositionControllerEditor.cs @@ -3,10 +3,12 @@ // For maintenance, every new [SerializeField] variable in ScrollPositionController must be declared here +using System; using UnityEditor; namespace UnityEngine.UI.Extensions { + [Obsolete("ScrollPositionController has been replaced by the Scroller component", true)] [CustomEditor(typeof(ScrollPositionController))] [CanEditMultipleObjects] public class ScrollPositionControllerEditor : Editor diff --git a/Editor/UIExtensionsMenuOptions.cs b/Editor/UIExtensionsMenuOptions.cs index b445a7b..75711d6 100644 --- a/Editor/UIExtensionsMenuOptions.cs +++ b/Editor/UIExtensionsMenuOptions.cs @@ -1,15 +1,24 @@ -using UnityEngine; +#if UNITY_2019_1_OR_NEWER && !ENABLE_LEGACY_INPUT_MANAGER +#define NEW_INPUT_SYSTEM +#endif + +using TMPro; +using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using UnityEngine.UI.Extensions; +#if NEW_INPUT_SYSTEM +using UnityEngine.InputSystem.UI; +#endif + namespace UnityEditor.UI { - /// - /// This script adds the Extensions UI menu options to the Unity Editor. - /// + /// + /// This script adds the Extensions UI menu options to the Unity Editor. + /// - static internal class ExtensionMenuOptions + static internal class ExtensionMenuOptions { #region Unity Builder section - Do not change unless UI Source (Editor\MenuOptions) changes #region Unity Builder properties - Do not change unless UI Source (Editor\MenuOptions) changes @@ -156,7 +165,11 @@ namespace UnityEditor.UI var eventSystem = new GameObject("EventSystem"); GameObjectUtility.SetParentAndAlign(eventSystem, parent); esys = eventSystem.AddComponent(); +#if NEW_INPUT_SYSTEM + eventSystem.AddComponent(); +#else eventSystem.AddComponent(); +#endif Undo.RegisterCreatedObjectUndo(eventSystem, "Create " + eventSystem.name); } @@ -207,7 +220,7 @@ namespace UnityEditor.UI #region UI Extensions "Create" Menu items #region Scroll Snap controls - [MenuItem("GameObject/UI/Extensions/Horizontal Scroll Snap", false)] + [MenuItem("GameObject/UI/Extensions/Layout/Horizontal Scroll Snap", false)] static public void AddHorizontalScrollSnap(MenuCommand menuCommand) { GameObject horizontalScrollSnapRoot = CreateUIElementRoot("Horizontal Scroll Snap", menuCommand, s_ThickGUIElementSize); @@ -272,7 +285,7 @@ namespace UnityEditor.UI Selection.activeGameObject = horizontalScrollSnapRoot; } - [MenuItem("GameObject/UI/Extensions/Vertical Scroll Snap", false)] + [MenuItem("GameObject/UI/Extensions/Layout/Vertical Scroll Snap", false)] static public void AddVerticallScrollSnap(MenuCommand menuCommand) { GameObject verticalScrollSnapRoot = CreateUIElementRoot("Vertical Scroll Snap", menuCommand, s_ThickGUIElementSize); @@ -466,119 +479,119 @@ namespace UnityEditor.UI { FixedScrollSnapBase(menuCommand, "Scroll Snap Vertical Multiple", ScrollSnap.ScrollDirection.Vertical, 3, 15, new Vector2(100, 100)); } - #endregion + #endregion - #region ContentScrollSnapHorizontal - [MenuItem("GameObject/UI/Extensions/Content Scroll Snap Horizontal", false)] - static public void AddContentScrollSnapHorizontal(MenuCommand menuCommand) - { - GameObject contentScrollSnapRoot = CreateUIElementRoot("Content Scroll Snap Horizontal", menuCommand, s_ThickGUIElementSize); + #region ContentScrollSnapHorizontal + [MenuItem("GameObject/UI/Extensions/Layout/Content Scroll Snap Horizontal", false)] + static public void AddContentScrollSnapHorizontal(MenuCommand menuCommand) + { + GameObject contentScrollSnapRoot = CreateUIElementRoot("Content Scroll Snap Horizontal", menuCommand, s_ThickGUIElementSize); - GameObject childContent = CreateUIObject("Content", contentScrollSnapRoot); + GameObject childContent = CreateUIObject("Content", contentScrollSnapRoot); - GameObject childPage01 = CreateUIObject("Position 1", childContent); + GameObject childPage01 = CreateUIObject("Position 1", childContent); - GameObject childPage02 = CreateUIObject("Position 2", childContent); + GameObject childPage02 = CreateUIObject("Position 2", childContent); - GameObject childPage03 = CreateUIObject("Position 3", childContent); + GameObject childPage03 = CreateUIObject("Position 3", childContent); - GameObject childPage04 = CreateUIObject("Position 4", childContent); + GameObject childPage04 = CreateUIObject("Position 4", childContent); - GameObject childPage05 = CreateUIObject("Position 5", childContent); + GameObject childPage05 = CreateUIObject("Position 5", childContent); - //setup root - RectTransform contentScrollSnapRectTransform = ((RectTransform)contentScrollSnapRoot.transform); - contentScrollSnapRectTransform.anchorMin = new Vector2(0.5f, 0.5f); - contentScrollSnapRectTransform.anchorMax = new Vector2(0.5f, 0.5f); - contentScrollSnapRectTransform.anchoredPosition = Vector2.zero; - contentScrollSnapRectTransform.sizeDelta = new Vector2(100, 200); + //setup root + RectTransform contentScrollSnapRectTransform = ((RectTransform)contentScrollSnapRoot.transform); + contentScrollSnapRectTransform.anchorMin = new Vector2(0.5f, 0.5f); + contentScrollSnapRectTransform.anchorMax = new Vector2(0.5f, 0.5f); + contentScrollSnapRectTransform.anchoredPosition = Vector2.zero; + contentScrollSnapRectTransform.sizeDelta = new Vector2(100, 200); - Image image = contentScrollSnapRoot.AddComponent(); - image.sprite = null; - image.color = new Color(1, 0, 0, .5f); + Image image = contentScrollSnapRoot.AddComponent(); + image.sprite = null; + image.color = new Color(1, 0, 0, .5f); - ScrollRect sr = contentScrollSnapRoot.AddComponent(); - sr.vertical = false; - sr.horizontal = true; + ScrollRect sr = contentScrollSnapRoot.AddComponent(); + sr.vertical = false; + sr.horizontal = true; - //setup content container - RectTransform contentTransform = ((RectTransform)childContent.transform); - contentTransform.anchorMin = new Vector2(.5f, .5f); - contentTransform.anchorMax = new Vector2(.5f, .5f); - contentTransform.pivot = new Vector2(.5f, .5f); - contentTransform.sizeDelta = new Vector2(200, 300); + //setup content container + RectTransform contentTransform = ((RectTransform)childContent.transform); + contentTransform.anchorMin = new Vector2(.5f, .5f); + contentTransform.anchorMax = new Vector2(.5f, .5f); + contentTransform.pivot = new Vector2(.5f, .5f); + contentTransform.sizeDelta = new Vector2(200, 300); - Image contentImage = childContent.AddComponent(); - contentImage.sprite = null; - contentImage.color = new Color(0, 0, 1, .5f); + Image contentImage = childContent.AddComponent(); + contentImage.sprite = null; + contentImage.color = new Color(0, 0, 1, .5f); - sr.content = contentTransform; + sr.content = contentTransform; - //setup child 1 - RectTransform childPage01Transform = (RectTransform)childPage01.transform; - childPage01Transform.anchorMin = new Vector2(0, 1); - childPage01Transform.anchorMax = new Vector2(0, 1); - childPage01Transform.pivot = new Vector2(0, 1); - childPage01Transform.anchoredPosition = new Vector2(0, -125); + //setup child 1 + RectTransform childPage01Transform = (RectTransform)childPage01.transform; + childPage01Transform.anchorMin = new Vector2(0, 1); + childPage01Transform.anchorMax = new Vector2(0, 1); + childPage01Transform.pivot = new Vector2(0, 1); + childPage01Transform.anchoredPosition = new Vector2(0, -125); - Image childPage01Image = childPage01.AddComponent(); - childPage01Image.sprite = null; - childPage01Image.color = Color.white; + Image childPage01Image = childPage01.AddComponent(); + childPage01Image.sprite = null; + childPage01Image.color = Color.white; - //setup child 2 - RectTransform childPage02Transform = (RectTransform)childPage02.transform; - childPage02Transform.anchorMin = new Vector2(0, 1); - childPage02Transform.anchorMax = new Vector2(0, 1); - childPage02Transform.pivot = new Vector2(0, 1); - childPage02Transform.anchoredPosition = new Vector2(175, -150); + //setup child 2 + RectTransform childPage02Transform = (RectTransform)childPage02.transform; + childPage02Transform.anchorMin = new Vector2(0, 1); + childPage02Transform.anchorMax = new Vector2(0, 1); + childPage02Transform.pivot = new Vector2(0, 1); + childPage02Transform.anchoredPosition = new Vector2(175, -150); - Image childPage02Image = childPage02.AddComponent(); - childPage02Image.sprite = null; - childPage02Image.color = Color.white; + Image childPage02Image = childPage02.AddComponent(); + childPage02Image.sprite = null; + childPage02Image.color = Color.white; - //setup child 3 - RectTransform childPage03Transform = (RectTransform)childPage03.transform; - childPage03Transform.anchorMin = new Vector2(0, 1); - childPage03Transform.anchorMax = new Vector2(0, 1); - childPage03Transform.pivot = new Vector2(0, 1); - childPage03Transform.anchoredPosition = new Vector2(315, -125); - childPage03Transform.sizeDelta = new Vector2(50, 100); + //setup child 3 + RectTransform childPage03Transform = (RectTransform)childPage03.transform; + childPage03Transform.anchorMin = new Vector2(0, 1); + childPage03Transform.anchorMax = new Vector2(0, 1); + childPage03Transform.pivot = new Vector2(0, 1); + childPage03Transform.anchoredPosition = new Vector2(315, -125); + childPage03Transform.sizeDelta = new Vector2(50, 100); - Image childPage03Image = childPage03.AddComponent(); - childPage03Image.sprite = null; - childPage03Image.color = Color.white; + Image childPage03Image = childPage03.AddComponent(); + childPage03Image.sprite = null; + childPage03Image.color = Color.white; - //setup child 4 - RectTransform childPage04Transform = (RectTransform)childPage04.transform; - childPage04Transform.anchorMin = new Vector2(0, 1); - childPage04Transform.anchorMax = new Vector2(0, 1); - childPage04Transform.pivot = new Vector2(0, 1); - childPage04Transform.anchoredPosition = new Vector2(490, -110); + //setup child 4 + RectTransform childPage04Transform = (RectTransform)childPage04.transform; + childPage04Transform.anchorMin = new Vector2(0, 1); + childPage04Transform.anchorMax = new Vector2(0, 1); + childPage04Transform.pivot = new Vector2(0, 1); + childPage04Transform.anchoredPosition = new Vector2(490, -110); - Image childPage04Image = childPage04.AddComponent(); - childPage04Image.sprite = null; - childPage04Image.color = Color.white; + Image childPage04Image = childPage04.AddComponent(); + childPage04Image.sprite = null; + childPage04Image.color = Color.white; - //setup child 5 - RectTransform childPage05Transform = (RectTransform)childPage05.transform; - childPage05Transform.anchorMin = new Vector2(0, 1); - childPage05Transform.anchorMax = new Vector2(0, 1); - childPage05Transform.pivot = new Vector2(0, 1); - childPage05Transform.anchoredPosition = new Vector2(630, -180); + //setup child 5 + RectTransform childPage05Transform = (RectTransform)childPage05.transform; + childPage05Transform.anchorMin = new Vector2(0, 1); + childPage05Transform.anchorMax = new Vector2(0, 1); + childPage05Transform.pivot = new Vector2(0, 1); + childPage05Transform.anchoredPosition = new Vector2(630, -180); - Image childPage05Image = childPage05.AddComponent(); - childPage05Image.sprite = null; - childPage05Image.color = Color.white; + Image childPage05Image = childPage05.AddComponent(); + childPage05Image.sprite = null; + childPage05Image.color = Color.white; - //add scroll snap after we've added the content & items - contentScrollSnapRoot.AddComponent(); - } - #endregion + //add scroll snap after we've added the content & items + contentScrollSnapRoot.AddComponent(); + } + #endregion - #endregion + #endregion - #region UIVertical Scroller - [MenuItem("GameObject/UI/Extensions/UI Vertical Scroller", false)] + #region UIVertical Scroller + [MenuItem("GameObject/UI/Extensions/Layout/UI Vertical Scroller", false)] static public void AddUIVerticallScroller(MenuCommand menuCommand) { GameObject uiVerticalScrollerRoot = CreateUIElementRoot("UI Vertical Scroller", menuCommand, s_ThickGUIElementSize); @@ -607,7 +620,7 @@ namespace UnityEditor.UI rectTransformCenter.anchorMax = new Vector2(1f, 0.6f); rectTransformCenter.sizeDelta = Vector2.zero; - uiscr.center = uiScrollerCenter.GetComponent(); + uiscr.Center = uiScrollerCenter.GetComponent(); //Setup Content container RectTransform rectTransformContent = childContent.GetComponent(); @@ -658,8 +671,89 @@ namespace UnityEditor.UI } #endregion + #region UIHorizontal Scroller + [MenuItem("GameObject/UI/Extensions/Layout/UI Horizontal Scroller", false)] + static public void AddUIHorizontalScroller(MenuCommand menuCommand) + { + GameObject uiHorizontalScrollerRoot = CreateUIElementRoot("UI Horizontal Scroller", menuCommand, s_ThickGUIElementSize); + + GameObject uiScrollerCenter = CreateUIObject("Center", uiHorizontalScrollerRoot); + + GameObject childContent = CreateUIObject("Content", uiHorizontalScrollerRoot); + + // Set RectTransform to stretch + RectTransform rectTransformScrollSnapRoot = uiHorizontalScrollerRoot.GetComponent(); + rectTransformScrollSnapRoot.anchorMin = new Vector2(0.5f, 0.5f); + rectTransformScrollSnapRoot.anchorMax = new Vector2(0.5f, 0.5f); + rectTransformScrollSnapRoot.anchoredPosition = Vector2.zero; + rectTransformScrollSnapRoot.sizeDelta = new Vector2(500f, 150f); + + // Add required ScrollRect + ScrollRect sr = uiHorizontalScrollerRoot.AddComponent(); + sr.vertical = false; + sr.horizontal = true; + sr.movementType = ScrollRect.MovementType.Unrestricted; + var uiscr = uiHorizontalScrollerRoot.AddComponent(); + + //Setup container center point + RectTransform rectTransformCenter = uiScrollerCenter.GetComponent(); + rectTransformCenter.anchorMin = new Vector2(0.3f,0f); + rectTransformCenter.anchorMax = new Vector2(0.6f,1f); + rectTransformCenter.sizeDelta = Vector2.zero; + + uiscr.Center = uiScrollerCenter.GetComponent(); + + //Setup Content container + RectTransform rectTransformContent = childContent.GetComponent(); + rectTransformContent.anchorMin = Vector2.zero; + rectTransformContent.anchorMax = new Vector2(1f, 1f); + rectTransformContent.sizeDelta = Vector2.zero; + + sr.content = rectTransformContent; + + // Add sample children + for (int i = 0; i < 10; i++) + { + GameObject childPage = CreateUIObject("Page_" + i, childContent); + + GameObject childText = CreateUIObject("Text", childPage); + + //Setup 1st Child + Image pageImage = childPage.AddComponent(); + pageImage.sprite = AssetDatabase.GetBuiltinExtraResource(kStandardSpritePath); + pageImage.type = Image.Type.Sliced; + pageImage.color = s_DefaultSelectableColor; + + RectTransform rectTransformPage = childPage.GetComponent(); + rectTransformPage.anchorMin = new Vector2(0.5f, 0); + rectTransformPage.anchorMax = new Vector2(0.5f, 1f); + rectTransformPage.sizeDelta = new Vector2(80f, 0f); + rectTransformPage.pivot = new Vector2(0.5f, 0.5f); + rectTransformPage.localPosition = new Vector3(80 * i, 0, 0); + childPage.AddComponent