Release 2.3.0 (#429)
* Package upver for Development * Added OnHighlightChanged and OnPressChanged events Added getters and setters for Highlighted and Pressed * Patch fix for UILineRenderer * Update package preview release * Resolves issue where the lower range value would become stuck when moved to the max value position Resolves: https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/issues/381/cant-move-range-slider-if-low-is-moved-to * Updated Infinite scroll to work with content of different sizes * Clean-up and reset pivots on scene start * Patches from PR * Clean up range slider unused variables * Updated Dropdown list to NOT resize text Rect on draw * Upgraded RangeSlider to work in both Horizontal and Verticle setups, just like regular slider. Also fixed a minor issue with offset when dragging on the bar. # Conflicts: # Runtime/Scripts/Controls/RangeSlider.cs * Taking in fix from https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/pull-requests/132 * Applying PR manually, because Bitbucket https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/pull-requests/128 * Merged in fix manually because... Bitbucket https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/pull-requests/130 * Remove old BitBucket Pipeline for GitHub * Fixes issue #398 where the Next / Previous buttons filed to work if the ScrollSnap was previously scrolling. Also renamed the Extension Methods scripts and added a new function. Resolves: #398 * Resolves #397 Moved OnValidate checks which redraw the component to the RectTransformDimensionsCHanged event * Updated UIParticleSystem access to Particles array to ensure it is more stable. Updated some #if statements to be better future proofed Resolves #360 * Fixed the UIConnector to safely handle when no parent canvas can be found. Resolves #392 * Fixed issue which allowed an item marked as NOT transferable to actually be transferred between lists Resolves #382 * Updated #if filter inclusion to 2019_1_OR_Newer resolves: - https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/411 * Updated UIVertical scroller to be 2022 compliant Resolves: - https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/410 * Updated Curly UI to wait until end of the frame to recalculate positions Also updated Editor script to work in 2022 Resolves: - https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/409 * Updated Depth Texture sampler in UI Particles Shaders Resolves: - https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/401 * Remove meta duplicates for HSVColour Picker * Add newly generated HSV picker meta files * Hard reset of Colour picker guids * Updated Points to always be an array of 1 when set to nothing. Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/295 * Updated Cooldown button to work with Keyboard input Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/171 * Added error handling around setting Unity UI Components for Vertical/Horizontal scrolling Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/296 * Protecting Remove too * Added SetArc method to UICircle as requested Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/280 * Marked ScrollPositionController as Obsolete, users should use the newer Scroller component instead, will be removed in a future release. Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/305 * Updated ScrollPositionControllerEditor as obsolete too * Removed unneeded size calculation which caused some issues with mixed height/width children. Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/380 * Resolved issue whereby the last row in a flow layout group would not size correctly. Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/357 * Updated all components using "LayoutGroup" to override their OnDisable feature to incorporate this fix: https://gist.github.com/randomize/73ca6d3b6aa7210073692eb5cabd537e Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/178 * Checking in new MinMaxSlider TODO - Finish Editor creator * Added Editor Menu Option to create a Min/Max slider Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/270 * Marked TileSizeFitter as obsolete as Unity has made this unworkable Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/214 * Updated Editor create options to add the correct Event System Input module for the Input system used, now or old. Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/378 * Updated Editor menu layout * Updated initialisation logic to not cause an endless loop in the TabNavigationHelper Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/208 * Added new FIFO based UI Line Render when dynamic line rendering is needed (basic, no Beziers) Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/324 * Clean-up of ScrollSnapBase * Updated "Action" use to "UnityAction" to avoid Unity issues Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/253 * Updated UIVerticalScroller for standards and added UIHorizontalScroller Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/205 * Updated ReorderableList/ReorderableListElement to prevent creating a "Fake" droppable when the item is not transferable Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/164 * Updated panel drawing for ComboBox controls and added DropdownOffset Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/393 * Base update for pointers to new version / package home * Cleanup and ensuring the UIParticleSystem is disposed on Destroy correctly. Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/412 * Refresh FancyScrollView with latest fixes * Remove broken examples link * Break Module * Update Examples module to new home * Updating GitHub artifacts and automation * Updated build issue with ReorderableListElement * Revised the Curly UI fix as it was preventing the graphic from being updated in the scene view. Thanks to @solidsign for the update. * Removed legacy Examples link, moving to separate repository * Added new submodule for extracted examples * Fix class spellings and update MultiTouchScrollRect * Updated NonDrawingGraphic to require a CanvasRender, else it causes an error on run (and doesn't work) - Resolves: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/420 * Add updated test flow for builds * Fix github issue templates * Add the Version upgrade pipeline * Added ResetSelectableHighlight component * Resolves issue in 2022 with the missing Text component Fixes: https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/424 * The BIG Unity 2022 Text reorganisation * Remove editor validation and add error checking for the ColorLabel component * Add 2019 to the testing validation * Switch android builds to windows * Several lifetime feature updates for the ComboBox controls: - Resolves startup issue that prevented the control being used (Unity changed the start order in some instances), this was causing null reference issues with comboboxes - Added the ability to set a specific item on start and not just the first - Added the ability to disable the dropdown to make a read-only dropdown Resolves: - https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/426 - https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/425 * Resolved issues with DisplayAbove and using a 0 ItemsToDisplay * Update pipelines for release * Final checks for merge! --------- Co-authored-by: Robert Rioja <rrioja@immersivedisplayinc.com> Co-authored-by: Simon Jackson <darkside@xna-uk.net> Co-authored-by: Ben MacKinnon <bilmackinnon@googlemail.com> Co-authored-by: Simon Jackson <sjackson@ethar.com> Co-authored-by: action <action@users.noreply.github.com>release
parent
c3fd580886
commit
89403a2611
|
@ -2,7 +2,7 @@
|
|||
name: Bug report
|
||||
about: Create a report to identify a potential issue
|
||||
title: 'BUG: '
|
||||
labels: Bug
|
||||
labels: bug
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
|
|
|
@ -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: ''
|
||||
---
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
name: Request for Information
|
||||
about: Not sure how to do something, just ask.
|
||||
title: 'RFI: '
|
||||
labels: Question
|
||||
labels: question
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
|
|
|
@ -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 }}
|
||||
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
|
||||
|
|
|
@ -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/**
|
|
@ -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/**
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -35,6 +35,4 @@ sysinfo.txt
|
|||
/.vs
|
||||
*.gitmodules
|
||||
|
||||
# NPM publish exclusions
|
||||
bitbucket-pipelines.yml
|
||||
bitbucket-pipelines.yml.meta
|
||||
**/.github/*
|
127
CHANGELOG.md
127
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.
|
||||
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8701e045b26e51f4eb345f2ccb3c13f5
|
||||
timeCreated: 1426804458
|
||||
licenseType: Free
|
||||
guid: c1047f9974e7ee1478bbf5490a7a62d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if floating point numbers are within 0.01f (close enough to be considered equal)
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
private static bool IsEqualFloat(float a, float b)
|
||||
{
|
||||
return Math.Abs(a - b) < 0.01f;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 69352ed1561021b48ac258f81f48a988
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,12 @@
|
|||
{
|
||||
"name": "UnityUIExtensions.editor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:343deaaf83e0cee4ca978e7df0b80d21",
|
||||
"GUID:2bafac87e7f4b9b418d9448d219b01ab",
|
||||
"GUID:cf414061cae3a954baf92763590f3127"
|
||||
"GUID:cf414061cae3a954baf92763590f3127",
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
|
@ -14,5 +17,6 @@
|
|||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": []
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
|
@ -1 +1 @@
|
|||
Subproject commit d08257d62c3c95771540f51f77f50a491715d3b7
|
||||
Subproject commit 774bde78bf8792ad8de1c96ad7e874932fd716d7
|
254
README.md
254
README.md
|
@ -1,18 +1,10 @@
|
|||
# This repository is being migrated to GitHub
|
||||
# Unity UI Extensions README
|
||||
|
||||
The new home for this repository is:
|
||||
|
||||
> ## https://github.com/Unity-UI-Extensions/com.unity.uiextensions
|
||||
|
||||
BitBucket is just not what it used to be (workable)
|
||||
|
||||
## Unity UI Extensions README
|
||||
|
||||
This is an extension project for the new Unity UI system which can be found at: [Unity UI Source](https://bitbucket.org/Unity-Technologies/ui)
|
||||
This is an extension project for the new Unity UI system which can be found at: [Unity UI Source](https://github.com/Unity-Technologies/uGUI)
|
||||
|
||||
> [Check out the control demos on our Tumblr page](https://unityuiextensions.tumblr.com/)
|
||||
|
||||
## [Intro](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/GettingStarted)
|
||||
## [Intro](https://unity-ui-extensions.github.io/GettingStarted)
|
||||
|
||||
For more info, here's a little introduction video for the project:
|
||||
|
||||
|
@ -20,15 +12,16 @@ For more info, here's a little introduction video for the project:
|
|||
|
||||
You can follow the UI Extensions team for updates and news on:
|
||||
|
||||
### [Twitter](https://twitter.com/hashtag/UnityUIExtensions?src=hash) / [Facebook](https://www.facebook.com/UnityUIExtensions/) / [YouTube](https://www.youtube.com/channel/UCG3gZOkmL-2rmZat4ufv28Q)
|
||||
### [Twitter - #unityuiextensions](https://twitter.com/search?q=%23unityuiextensions) / [Facebook](https://www.facebook.com/UnityUIExtensions/) / [YouTube](https://www.youtube.com/@UnityUIExtensions)
|
||||
|
||||
> ## Chat live with the Unity UI Extensions community on Gitter here:
|
||||
> Ways to get in touch:
|
||||
>
|
||||
> ## [UI Extensions Live Chat](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
|
||||
|
||||
-----
|
||||
|
||||
## [What is this repository for?](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/About)
|
||||
## [What is this repository for?](https://unity-ui-extensions.github.io/About)
|
||||
|
||||
In this repository is a collection of extension scripts / effects and controls to enhance your Unity UI experience. These scripts have been gathered from many sources, combined and improved over time.
|
||||
|
||||
|
@ -36,19 +29,19 @@ In this repository is a collection of extension scripts / effects and controls t
|
|||
|
||||
You can either download / fork this project to access the scripts, or you can also download these pre-compiled Unity Assets, chock full of goodness for each release:
|
||||
|
||||
## [Download - 2019.6 (aka 2.5)](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Downloads)
|
||||
## [Download - 2019.6 (aka 2.5)](https://unity-ui-extensions.github.io/Downloads)
|
||||
|
||||
We have expanded where you can download the UnityPackage asset and widened the options to contribute to the project.
|
||||
|
||||
> I will still stress however, ***contribution is optional***. **The assets / code will always remain FREE**
|
||||
|
||||
| [![Download from Itch.IO](https://bytebucket.org/UnityUIExtensions/unity-ui-extensions/wiki/SiteImages/itchio.png)](https://unityuiextensions.itch.io/uiextensions2-0 "Download from Itch.IO") | [![Download from Itch.IO](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/SiteImages/unionassets.png)](https://unionassets.com/unity-ui-extensions "Download from Union Assets") | [![Download from Itch.IO](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/SiteImages/patreon.jpg)](https://www.patreon.com/UnityUIExtensions "Support Unity UI Extensions on Patreon & download")|
|
||||
| [![Download from Itch.IO](https://unity-ui-extensions.github.io/SiteImages/itchio.png)](https://unityuiextensions.itch.io/uiextensions2-0 "Download from Itch.IO") | [![Download from Itch.IO](https://unity-ui-extensions.github.io/SiteImages/unionassets.png)](https://unionassets.com/unity-ui-extensions "Download from Union Assets") | [![Download from Itch.IO](https://unity-ui-extensions.github.io/SiteImages/patreon.jpg)](https://www.patreon.com/UnityUIExtensions "Support Unity UI Extensions on Patreon & download")|
|
||||
| :--- | :--- | :--- |
|
||||
| [Grab from Itchio](https://unityuiextensions.itch.io/uiextensions2-0) | [Obtain via Union Assets](https://unionassets.com/unity-ui-extensions) |[Support through Patreon](https://www.patreon.com/UnityUIExtensions) |
|
||||
|
||||
> Still available to download on the [BitBucket site](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/downloads) if you prefer
|
||||
> Still available to download on the [GitHub site](https://github.com/Unity-UI-Extensions/com.unity.uiextensions/releases) if you prefer
|
||||
|
||||
To view previous releases, visit the [release archive](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Downloads)
|
||||
To view previous releases, visit the [release archive](https://unity-ui-extensions.github.io/Downloads)
|
||||
|
||||
-----
|
||||
|
||||
|
@ -58,15 +51,15 @@ If you wish to further support the Unity UI Extensions project itself, then you
|
|||
|
||||
All funds go to support the project, no matter the amount. **Donations in code are also extremely welcome**
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| [![Donate via PayPal](https://www.paypalobjects.com/webstatic/mktg/Logo/pp-logo-150px.png)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=89L8T9N6BR7LJ "Donating via Paypal") | [![Buy us a Coffee](https://uploads-ssl.webflow.com/5c14e387dab576fe667689cf/5cbed8a4ae2b88347c06c923_BuyMeACoffee_blue-p-500.png)](https://ko-fi.com/uiextensions "Buy us a Coffee") |
|
||||
|[![Donate via PayPal](https://www.paypalobjects.com/webstatic/mktg/Logo/pp-logo-150px.png)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=89L8T9N6BR7LJ "Donating via Paypal")|[![Buy us a Coffee](https://uploads-ssl.webflow.com/5c14e387dab576fe667689cf/5cbed8a4ae2b88347c06c923_BuyMeACoffee_blue-p-500.png)](https://ko-fi.com/uiextensions "Buy us a Coffee")|
|
||||
|-|-|
|
||||
|||
|
||||
|
||||
> (PayPal account not required and you can remain anonymous if you wish)
|
||||
|
||||
-----
|
||||
|
||||
## [Getting Started](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/GettingStarted)
|
||||
## [Getting Started](https://unity-ui-extensions.github.io/GettingStarted)
|
||||
|
||||
To get started with the project, here's a little guide:
|
||||
|
||||
|
@ -74,58 +67,92 @@ To get started with the project, here's a little guide:
|
|||
|
||||
-----
|
||||
|
||||
## [Updates:](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/ReleaseNotes/RELEASENOTES)
|
||||
## [Updates:](https://unity-ui-extensions.github.io/ReleaseNotes/RELEASENOTES)
|
||||
|
||||
## Maintenance release 2019.6 - 2.5 - Bug squash
|
||||
## 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 also check out the "Examples" option in the Package Manager window to import the samples to your project.
|
||||
To get up to speed with the Unity UI Extensions, check out the [Getting Started](https://unity-ui-extensions.github.io/GettingStarted.html) Page.
|
||||
|
||||
> 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
|
||||
> 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)
|
||||
|
||||
### New / updated features
|
||||
## Breaking changes
|
||||
|
||||
- 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
|
||||
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.
|
||||
|
||||
### Examples / Examples / Examples
|
||||
> New users to 2022 are unaffected as all the Editor commands have been updated to use the newer TextMeshPro versions.
|
||||
|
||||
Examples can be found either in the UPM package manager window or via the extra downloadable UnityAsset from the Bitbucket site - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Downloads
|
||||
For more details, see the [deprecation notice](https://github.com/Unity-UI-Extensions/com.unity.uiextensions/discussions/428) on GitHub.
|
||||
|
||||
### Fixes
|
||||
## Added
|
||||
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
### Known issues
|
||||
## Changed
|
||||
|
||||
No new issues in this release, but check the issues list for things we are currently working on:
|
||||
- Refresh FancyScrollView with the latest fixes
|
||||
- All Text based components updated to use TextMeshPro from Unity 2022 **Breaking Change**
|
||||
|
||||
* [UI Extensions Issue log](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/issues?status=new&status=open)
|
||||
- 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
|
||||
|
||||
|
@ -137,79 +164,88 @@ We recommend using the UPM delivery method. If you are using the Unity asset, th
|
|||
|
||||
For the full release history, follow the below link to the full release notes page.
|
||||
|
||||
### [Release Notes](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/ReleaseNotes/RELEASENOTES)
|
||||
### [Release Notes](https://unity-ui-extensions.github.io/ReleaseNotes/RELEASENOTES)
|
||||
|
||||
-----
|
||||
|
||||
## [Controls and extensions listed in this project](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Controls)
|
||||
## [Controls and extensions listed in this project](https://unity-ui-extensions.github.io/Controls)
|
||||
|
||||
There are almost 70+ extension controls / effect and other utilities in the project which are listed on the following page:
|
||||
|
||||
> ## [Check out the control demos on our Tumblr page](https://www.tumblr.com/blog/unityuiextensions)
|
||||
>
|
||||
> | [![UI Line Renderer](https://bytebucket.org/UnityUIExtensions/unity-ui-extensions/wiki/SiteImages/LineRenderer.gif)](https://www.tumblr.com/blog/unityuiextensions "UI Line Renderer") | [![UI Knob](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/SiteImages/UIKnob.gif)](https://www.tumblr.com/blog/unityuiextensions "UI Knob") | [![ScrollSnap](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/SiteImages/ScrollSnap.gif)](https://www.tumblr.com/blog/unityuiextensions "Scroll Snap")|
|
||||
> | [![UI Line Renderer](https://unity-ui-extensions.github.io/SiteImages/LineRenderer.gif)](https://www.tumblr.com/blog/unityuiextensions "UI Line Renderer") | [![UI Knob](https://unity-ui-extensions.github.io/SiteImages/UIKnob.gif)](https://www.tumblr.com/blog/unityuiextensions "UI Knob") | [![ScrollSnap](https://unity-ui-extensions.github.io/SiteImages/ScrollSnap.gif)](https://www.tumblr.com/blog/unityuiextensions "Scroll Snap")|
|
||||
> | :--- | :--- | :--- |
|
||||
> | [UI Line Renderer](https://www.tumblr.com/blog/unityuiextensions) | [UI Knob](https://www.tumblr.com/blog/unityuiextensions) |[Scroll Snap](https://www.tumblr.com/blog/unityuiextensions) |
|
||||
|
||||
## [UI Extensions controls list](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Controls)
|
||||
## [UI Extensions controls list](https://unity-ui-extensions.github.io/Controls)
|
||||
|
||||
[Controls](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Controls#markdown-header-controls)|||||
|
||||
------|------|------|------|------|
|
||||
Accordion|ColorPicker|Selection Box|UI Flippable|ComboBox
|
||||
AutoComplete ComboBox|DropDown List|BoundToolTip|UIWindowBase|UI Knob
|
||||
TextPic|Input Focus|Box Slider|Cooldown Button|Segmented Control
|
||||
Stepper|Range Slider|Radial Slider|MultiTouch Scroll Rect|
|
||||
||||
|
||||
[Controls](https://unity-ui-extensions.github.io/Controls.html#controls)
|
||||
|
||||
[Primitives](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Controls#markdown-header-primitives)|||||
|
||||
------|------|------|------|------|
|
||||
UILineRenderer|UILineTextureRenderer|UICircle|DiamondGraph|UICornerCut
|
||||
UIPolygon||||
|
||||
||||
|
||||
|Accordion|ColorPicker|Selection Box|UI Flippable|ComboBox|
|
||||
|-|-|-|-|-|
|
||||
|AutoComplete ComboBox|DropDown List|BoundToolTip|UIWindowBase|UI Knob|
|
||||
|TextPic|Input Focus|Box Slider|Cooldown Button|Segmented Control|
|
||||
|Stepper|Range Slider|Radial Slider|MultiTouch Scroll Rect|MinMax SLider|
|
||||
|
||||
[Layouts](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Controls#markdown-header-layouts)|||||
|
||||
------|------|------|------|------|
|
||||
Horizontal Scroll Snap|Vertical Scroll Snap|Flow Layout Group|Radial Layout|Tile Size Fitter
|
||||
Scroll Snap (alt implementation)|Reorderable List|UI Vertical Scroller|Curved Layout|Table Layout
|
||||
FancyScrollView|Card UI|Scroll Position Controller||
|
||||
||||
|
||||
[Primitives](https://unity-ui-extensions.github.io/Controls.html#primitives)
|
||||
|
||||
[Effects](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Controls#markdown-header-effect_components)|||||
|
||||
------|------|------|------|------|
|
||||
Best Fit Outline|Curved Text|Gradient|Gradient2|Letter Spacing
|
||||
NicerOutline|RaycastMask|UIFlippable|UIImageCrop|SoftAlphaMask
|
||||
CylinderText|UIParticleSystem|CurlyUI|Shine Effect|Shader Effects
|
||||
||||
|
||||
|UILineRenderer|UILineTextureRenderer|UICircle|DiamondGraph|UICornerCut|
|
||||
|-|-|-|-|-|
|
||||
|UIPolygon|UISquircle||||
|
||||
|
||||
[Additional Components](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Controls#markdown-header-additional_components)|||||
|
||||
------|------|------|------|------|
|
||||
ReturnKeyTrigger|TabNavigation|uGUITools|ScrollRectTweener|ScrollRectLinker
|
||||
ScrollRectEx|UI_InfiniteScroll|UI_ScrollRectOcclusion|UIScrollToSelection|UISelectableExtension
|
||||
switchToRectTransform|ScrollConflictManager|CLFZ2 (Encryption)|DragCorrector|PPIViewer
|
||||
UI_TweenScale|UI_MagneticInfiniteScroll|UI_ScrollRectOcclusion|NonDrawingGraphic|
|
||||
UILineConnector|UIHighlightable|Menu Manager|Pagination Manager|
|
||||
||||
|
||||
[Layouts](https://unity-ui-extensions.github.io/Controls.html#layouts)
|
||||
|
||||
|Horizontal Scroll Snap|Vertical Scroll Snap|Flow Layout Group|Radial Layout|Tile Size Fitter|
|
||||
|-|-|-|-|-|
|
||||
|Scroll Snap (alt implementation)|Reorderable List|UI Vertical Scroller|Curved Layout|Table Layout|
|
||||
|FancyScrollView|Card UI|Scroll Position Controller (obsolete)|Content Scroll Snap Horizontal|Scroller|
|
||||
|ResizePanel|RescalePanel|RescaleDragPanel|||
|
||||
|
||||
[Effects](https://unity-ui-extensions.github.io/Controls.html#effect-components)
|
||||
|
||||
|Best Fit Outline|Curved Text|Gradient|Gradient2|Letter Spacing|
|
||||
|-|-|-|-|-|
|
||||
|NicerOutline|RaycastMask|UIFlippable|UIImageCrop|SoftAlphaMask|
|
||||
|CylinderText|UIParticleSystem|CurlyUI|Shine Effect|Shader Effects|
|
||||
|
||||
[Additional Components](https://unity-ui-extensions.github.io/Controls.html#additional-components)
|
||||
|
||||
|ReturnKeyTrigger|TabNavigation|uGUITools|ScrollRectTweener|ScrollRectLinker|
|
||||
|-|-|-|-|-|
|
||||
|ScrollRectEx|UI_InfiniteScroll|UI_ScrollRectOcclusion|UIScrollToSelection|UISelectableExtension|
|
||||
|switchToRectTransform|ScrollConflictManager|CLFZ2 (Encryption)|DragCorrector|PPIViewer|
|
||||
|UI_TweenScale|UI_MagneticInfiniteScroll|UI_ScrollRectOcclusion|NonDrawingGraphic|
|
||||
|UILineConnector|
|
||||
|UIHighlightable|Menu Manager|Pagination Manager|||
|
||||
|
||||
*More to come*
|
||||
|
||||
-----
|
||||
|
||||
## [How do I get set up?](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/GettingStarted)
|
||||
## [How do I get set up?](https://unity-ui-extensions.github.io/UPMInstallation.html)
|
||||
|
||||
As of Unity 2019, there are now two paths for getting access to the Unity UI Extensions project:
|
||||
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
|
||||
|
||||
- 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](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/UPMInstallation) to reference the project and install it.
|
||||
New for 2020, we have added OpenUPM support and the package can be installed using the following [OpenUPM CLI](https://openupm.com/docs/) command:
|
||||
|
||||
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.
|
||||
```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.
|
||||
|
||||
## [Contribution guidelines](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/ContributionGuidelines)
|
||||
## [Contribution guidelines](https://unity-ui-extensions.github.io/ContributionGuidelines)
|
||||
|
||||
Got a script you want added? Then just fork the bitbucket repository and submit a PR. All contributions accepted (including fixes)
|
||||
Got a script you want added? Then just fork the [GitHub repository](https://github.com/unity-UI-Extensions/com.unity.uiextensions) and submit a PR. All contributions accepted (including fixes)
|
||||
|
||||
Just ensure:
|
||||
|
||||
|
@ -217,21 +253,21 @@ Just ensure:
|
|||
* The script uses the **Unity.UI.Extensions** namespace so they do not affect any other developments.
|
||||
* (optional) Add Component and Editor options where possible. (editor options are in the Editor\UIExtensionsMenuOptions.cs file)
|
||||
|
||||
## [License](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/License)
|
||||
## [License](https://raw.githubusercontent.com/Unity-UI-Extensions/com.unity.uiextensions/release/LICENSE.md)
|
||||
|
||||
All scripts conform to the BSD3 license and are free to use / distribute. See the [LICENSE](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/License) file for more information =
|
||||
All scripts conform to the BSD3 license and are free to use / distribute. See the [LICENSE](https://raw.githubusercontent.com/Unity-UI-Extensions/com.unity.uiextensions/release/LICENSE.md) file for more information =
|
||||
|
||||
## [Like what you see?](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/FurtherInfo)
|
||||
## [Like what you see?](https://unity-ui-extensions.github.io/FurtherInfo)
|
||||
|
||||
All these scripts were put together for my latest book Unity3D UI Essentials
|
||||
Check out the [page on my blog](http://bit.ly/Unity3DUIEssentials) for more details and learn all about the inner workings of the new Unity UI System.
|
||||
|
||||
## [The downloads](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Downloads)
|
||||
## [The downloads](https://unity-ui-extensions.github.io/Downloads)
|
||||
|
||||
As this repo was created to support my new Unity UI Title ["Unity 3D UI Essentials"](http://bit.ly/Unity3DUIEssentials), in the downloads section you will find two custom assets (SpaceShip-DemoScene-Start.unitypackage and RollABallSample-Start.unitypackage). These are just here as starter scenes for doing UI tasks in the book.
|
||||
|
||||
I will add more sample scenes for the UI examples in this repository and detail them above over time.
|
||||
|
||||
## [Previous Releases](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Downloads)
|
||||
## [Previous Releases](https://unity-ui-extensions.github.io/Downloads)
|
||||
|
||||
Please see the [full downloads list](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Downloads) for all previous releases and their corresponding download links.
|
||||
Please see the [full downloads list](https://unity-ui-extensions.github.io/Downloads) for all previous releases and their corresponding download links.
|
||||
|
|
|
@ -82,7 +82,7 @@ Category {
|
|||
return v;
|
||||
}
|
||||
|
||||
sampler2D_float _CameraDepthTexture;
|
||||
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||
float _InvFade;
|
||||
|
||||
fixed4 frag (v2f IN) : SV_Target
|
||||
|
|
|
@ -82,7 +82,7 @@ Category {
|
|||
return v;
|
||||
}
|
||||
|
||||
sampler2D_float _CameraDepthTexture;
|
||||
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||
float _InvFade;
|
||||
|
||||
fixed4 frag (v2f i) : SV_Target
|
||||
|
|
|
@ -2,8 +2,7 @@ Shader "UI Extensions/Particles/Additive (Soft)" {
|
|||
Properties {
|
||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
|
||||
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_Stencil ("Stencil ID", Float) = 0
|
||||
_StencilOp ("Stencil Operation", Float) = 0
|
||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
|
@ -81,7 +80,7 @@ Category {
|
|||
return v;
|
||||
}
|
||||
|
||||
sampler2D_float _CameraDepthTexture;
|
||||
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||
float _InvFade;
|
||||
|
||||
fixed4 frag (v2f i) : SV_Target
|
||||
|
|
|
@ -3,8 +3,7 @@ Properties {
|
|||
_TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
|
||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
|
||||
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_Stencil ("Stencil ID", Float) = 0
|
||||
_StencilOp ("Stencil Operation", Float) = 0
|
||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
|
@ -82,7 +81,7 @@ Category {
|
|||
return v;
|
||||
}
|
||||
|
||||
sampler2D_float _CameraDepthTexture;
|
||||
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||
float _InvFade;
|
||||
|
||||
fixed4 frag (v2f i) : SV_Target
|
||||
|
|
|
@ -2,8 +2,7 @@ Shader "UI Extensions/Particles/Blend" {
|
|||
Properties {
|
||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
|
||||
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_Stencil ("Stencil ID", Float) = 0
|
||||
_StencilOp ("Stencil Operation", Float) = 0
|
||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
|
@ -81,7 +80,7 @@ Category {
|
|||
return v;
|
||||
}
|
||||
|
||||
sampler2D_float _CameraDepthTexture;
|
||||
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||
float _InvFade;
|
||||
|
||||
fixed4 frag (v2f i) : SV_Target
|
||||
|
|
|
@ -2,8 +2,7 @@ Shader "UI Extensions/Particles/Multiply" {
|
|||
Properties {
|
||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
|
||||
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_Stencil ("Stencil ID", Float) = 0
|
||||
_StencilOp ("Stencil Operation", Float) = 0
|
||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
|
@ -80,7 +79,7 @@ Category {
|
|||
return v;
|
||||
}
|
||||
|
||||
sampler2D_float _CameraDepthTexture;
|
||||
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||
float _InvFade;
|
||||
|
||||
fixed4 frag (v2f i) : SV_Target
|
||||
|
|
|
@ -2,8 +2,7 @@ Shader "UI Extensions/Particles/Multiply (Double)" {
|
|||
Properties {
|
||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
|
||||
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_Stencil ("Stencil ID", Float) = 0
|
||||
_StencilOp ("Stencil Operation", Float) = 0
|
||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
|
@ -81,7 +80,7 @@ Category {
|
|||
return v;
|
||||
}
|
||||
|
||||
sampler2D_float _CameraDepthTexture;
|
||||
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||
float _InvFade;
|
||||
|
||||
fixed4 frag (v2f i) : SV_Target
|
||||
|
|
|
@ -3,8 +3,7 @@ Properties {
|
|||
|
||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
|
||||
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_Stencil ("Stencil ID", Float) = 0
|
||||
_StencilOp ("Stencil Operation", Float) = 0
|
||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
|
@ -82,7 +81,7 @@ Category {
|
|||
return v;
|
||||
}
|
||||
|
||||
sampler2D_float _CameraDepthTexture;
|
||||
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||
float _InvFade;
|
||||
|
||||
fixed4 frag (v2f IN) : SV_Target
|
||||
|
|
|
@ -3,7 +3,7 @@ Properties {
|
|||
_EmisColor ("Emissive Color", Color) = (.2,.2,.2,0)
|
||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_Stencil ("Stencil ID", Float) = 0
|
||||
_StencilOp ("Stencil Operation", Float) = 0
|
||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
|
|
|
@ -5,83 +5,89 @@
|
|||
namespace UnityEngine.UI.Extensions.ColorPicker
|
||||
{
|
||||
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
[RequireComponent(typeof(TMPro.TMP_Text))]
|
||||
#else
|
||||
[RequireComponent(typeof(Text))]
|
||||
public class ColorLabel : MonoBehaviour
|
||||
{
|
||||
public ColorPickerControl picker;
|
||||
|
||||
public ColorValues type;
|
||||
|
||||
public string prefix = "R: ";
|
||||
public float minValue = 0;
|
||||
public float maxValue = 255;
|
||||
|
||||
public int precision = 0;
|
||||
|
||||
private Text label;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
label = GetComponent<Text>();
|
||||
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (Application.isPlaying && picker != null)
|
||||
{
|
||||
picker.onValueChanged.AddListener(ColorChanged);
|
||||
picker.onHSVChanged.AddListener(HSVChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (picker != null)
|
||||
{
|
||||
picker.onValueChanged.RemoveListener(ColorChanged);
|
||||
picker.onHSVChanged.RemoveListener(HSVChanged);
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
label = GetComponent<Text>();
|
||||
UpdateValue();
|
||||
}
|
||||
#endif
|
||||
|
||||
private void ColorChanged(Color color)
|
||||
public class ColorLabel : MonoBehaviour
|
||||
{
|
||||
UpdateValue();
|
||||
}
|
||||
public ColorPickerControl picker;
|
||||
|
||||
private void HSVChanged(float hue, float sateration, float value)
|
||||
{
|
||||
UpdateValue();
|
||||
}
|
||||
public ColorValues type;
|
||||
|
||||
private void UpdateValue()
|
||||
{
|
||||
if (picker == null)
|
||||
public string prefix = "R: ";
|
||||
public float minValue = 0;
|
||||
public float maxValue = 255;
|
||||
|
||||
public int precision = 0;
|
||||
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
private TMPro.TMP_Text label;
|
||||
#else
|
||||
private Text label;
|
||||
#endif
|
||||
private void Awake()
|
||||
{
|
||||
label.text = prefix + "-";
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
label = GetComponent<TMPro.TMP_Text>();
|
||||
#else
|
||||
label = GetComponent<Text>();
|
||||
#endif
|
||||
if (!label)
|
||||
{
|
||||
Debug.LogError($"{gameObject.name} does not have a Text component assigned for the {nameof(ColorLabel)}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float value = minValue + (picker.GetValue(type) * (maxValue - minValue));
|
||||
|
||||
label.text = prefix + ConvertToDisplayString(value);
|
||||
private void OnEnable()
|
||||
{
|
||||
if (Application.isPlaying && picker != null)
|
||||
{
|
||||
picker.onValueChanged.AddListener(ColorChanged);
|
||||
picker.onHSVChanged.AddListener(HSVChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (picker != null)
|
||||
{
|
||||
picker.onValueChanged.RemoveListener(ColorChanged);
|
||||
picker.onHSVChanged.RemoveListener(HSVChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private void ColorChanged(Color color)
|
||||
{
|
||||
UpdateValue();
|
||||
}
|
||||
|
||||
private void HSVChanged(float hue, float sateration, float value)
|
||||
{
|
||||
UpdateValue();
|
||||
}
|
||||
|
||||
private void UpdateValue()
|
||||
{
|
||||
if (picker == null)
|
||||
{
|
||||
label.text = prefix + "-";
|
||||
}
|
||||
else
|
||||
{
|
||||
float value = minValue + (picker.GetValue(type) * (maxValue - minValue));
|
||||
|
||||
label.text = prefix + ConvertToDisplayString(value);
|
||||
}
|
||||
}
|
||||
|
||||
private string ConvertToDisplayString(float value)
|
||||
{
|
||||
if (precision > 0)
|
||||
return value.ToString("f " + precision);
|
||||
else
|
||||
return Mathf.FloorToInt(value).ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private string ConvertToDisplayString(float value)
|
||||
{
|
||||
if (precision > 0)
|
||||
return value.ToString("f " + precision);
|
||||
else
|
||||
return Mathf.FloorToInt(value).ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 06851a815227e5044b0e3c1bf9b3a282
|
||||
guid: dea5b3bc15f78d04d8dcae27500f784e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
|
@ -59,7 +59,9 @@ namespace UnityEngine.UI.Extensions.ColorPicker
|
|||
private void OnDestroy()
|
||||
{
|
||||
if (image.texture != null)
|
||||
{
|
||||
DestroyImmediate(image.texture);
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ff46fbecea7739f4690e4285c88f53c5
|
||||
guid: 9d3cae3318559ae449731a7db00c9bdd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3d95ce8fba3dbbf4eb14411412169b88
|
||||
timeCreated: 1442747317
|
||||
licenseType: Free
|
||||
guid: 97950dcfb7ac51c4c95431d68ad7bea5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4f3189246d7fc204faba7a1e9c08e0af
|
||||
guid: 0e93d154602ed7e4787f2a7b9d3101b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
|
@ -7,95 +7,95 @@ namespace UnityEngine.UI.Extensions.ColorPicker
|
|||
{
|
||||
|
||||
[RequireComponent(typeof(InputField))]
|
||||
public class HexColorField : MonoBehaviour
|
||||
{
|
||||
public ColorPickerControl ColorPicker;
|
||||
|
||||
public bool displayAlpha;
|
||||
|
||||
private InputField hexInputField;
|
||||
|
||||
private const string hexRegex = "^#?(?:[0-9a-fA-F]{3,4}){1,2}$";
|
||||
|
||||
private void Awake()
|
||||
public class HexColorField : MonoBehaviour
|
||||
{
|
||||
hexInputField = GetComponent<InputField>();
|
||||
public ColorPickerControl ColorPicker;
|
||||
|
||||
// Add listeners to keep text (and color) up to date
|
||||
hexInputField.onEndEdit.AddListener(UpdateColor);
|
||||
ColorPicker.onValueChanged.AddListener(UpdateHex);
|
||||
}
|
||||
public bool displayAlpha;
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
hexInputField.onValueChanged.RemoveListener(UpdateColor);
|
||||
ColorPicker.onValueChanged.RemoveListener(UpdateHex);
|
||||
}
|
||||
private InputField hexInputField;
|
||||
|
||||
private void UpdateHex(Color newColor)
|
||||
{
|
||||
hexInputField.text = ColorToHex(newColor);
|
||||
}
|
||||
private const string hexRegex = "^#?(?:[0-9a-fA-F]{3,4}){1,2}$";
|
||||
|
||||
private void UpdateColor(string newHex)
|
||||
{
|
||||
Color32 color;
|
||||
if (HexToColor(newHex, out color))
|
||||
ColorPicker.CurrentColor = color;
|
||||
else
|
||||
Debug.Log("hex value is in the wrong format, valid formats are: #RGB, #RGBA, #RRGGBB and #RRGGBBAA (# is optional)");
|
||||
}
|
||||
|
||||
private string ColorToHex(Color32 color)
|
||||
{
|
||||
if (displayAlpha)
|
||||
return string.Format("#{0:X2}{1:X2}{2:X2}{3:X2}", color.r, color.g, color.b, color.a);
|
||||
else
|
||||
return string.Format("#{0:X2}{1:X2}{2:X2}", color.r, color.g, color.b);
|
||||
}
|
||||
|
||||
public static bool HexToColor(string hex, out Color32 color)
|
||||
{
|
||||
// Check if this is a valid hex string (# is optional)
|
||||
if (System.Text.RegularExpressions.Regex.IsMatch(hex, hexRegex))
|
||||
private void Awake()
|
||||
{
|
||||
int startIndex = hex.StartsWith("#") ? 1 : 0;
|
||||
hexInputField = GetComponent<InputField>();
|
||||
|
||||
if (hex.Length == startIndex + 8) //#RRGGBBAA
|
||||
{
|
||||
color = new Color32(byte.Parse(hex.Substring(startIndex, 2), NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse(hex.Substring(startIndex + 2, 2), NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse(hex.Substring(startIndex + 4, 2), NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse(hex.Substring(startIndex + 6, 2), NumberStyles.AllowHexSpecifier));
|
||||
}
|
||||
else if (hex.Length == startIndex + 6) //#RRGGBB
|
||||
{
|
||||
color = new Color32(byte.Parse(hex.Substring(startIndex, 2), NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse(hex.Substring(startIndex + 2, 2), NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse(hex.Substring(startIndex + 4, 2), NumberStyles.AllowHexSpecifier),
|
||||
255);
|
||||
}
|
||||
else if (hex.Length == startIndex + 4) //#RGBA
|
||||
{
|
||||
color = new Color32(byte.Parse("" + hex[startIndex] + hex[startIndex], NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse("" + hex[startIndex + 1] + hex[startIndex + 1], NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse("" + hex[startIndex + 2] + hex[startIndex + 2], NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse("" + hex[startIndex + 3] + hex[startIndex + 3], NumberStyles.AllowHexSpecifier));
|
||||
}
|
||||
else //#RGB
|
||||
{
|
||||
color = new Color32(byte.Parse("" + hex[startIndex] + hex[startIndex], NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse("" + hex[startIndex + 1] + hex[startIndex + 1], NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse("" + hex[startIndex + 2] + hex[startIndex + 2], NumberStyles.AllowHexSpecifier),
|
||||
255);
|
||||
}
|
||||
return true;
|
||||
// Add listeners to keep text (and color) up to date
|
||||
hexInputField.onEndEdit.AddListener(UpdateColor);
|
||||
ColorPicker.onValueChanged.AddListener(UpdateHex);
|
||||
}
|
||||
else
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
color = new Color32();
|
||||
return false;
|
||||
hexInputField.onValueChanged.RemoveListener(UpdateColor);
|
||||
ColorPicker.onValueChanged.RemoveListener(UpdateHex);
|
||||
}
|
||||
|
||||
private void UpdateHex(Color newColor)
|
||||
{
|
||||
hexInputField.text = ColorToHex(newColor);
|
||||
}
|
||||
|
||||
private void UpdateColor(string newHex)
|
||||
{
|
||||
Color32 color;
|
||||
if (HexToColor(newHex, out color))
|
||||
ColorPicker.CurrentColor = color;
|
||||
else
|
||||
Debug.Log("hex value is in the wrong format, valid formats are: #RGB, #RGBA, #RRGGBB and #RRGGBBAA (# is optional)");
|
||||
}
|
||||
|
||||
private string ColorToHex(Color32 color)
|
||||
{
|
||||
if (displayAlpha)
|
||||
return string.Format("#{0:X2}{1:X2}{2:X2}{3:X2}", color.r, color.g, color.b, color.a);
|
||||
else
|
||||
return string.Format("#{0:X2}{1:X2}{2:X2}", color.r, color.g, color.b);
|
||||
}
|
||||
|
||||
public static bool HexToColor(string hex, out Color32 color)
|
||||
{
|
||||
// Check if this is a valid hex string (# is optional)
|
||||
if (System.Text.RegularExpressions.Regex.IsMatch(hex, hexRegex))
|
||||
{
|
||||
int startIndex = hex.StartsWith("#") ? 1 : 0;
|
||||
|
||||
if (hex.Length == startIndex + 8) //#RRGGBBAA
|
||||
{
|
||||
color = new Color32(byte.Parse(hex.Substring(startIndex, 2), NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse(hex.Substring(startIndex + 2, 2), NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse(hex.Substring(startIndex + 4, 2), NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse(hex.Substring(startIndex + 6, 2), NumberStyles.AllowHexSpecifier));
|
||||
}
|
||||
else if (hex.Length == startIndex + 6) //#RRGGBB
|
||||
{
|
||||
color = new Color32(byte.Parse(hex.Substring(startIndex, 2), NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse(hex.Substring(startIndex + 2, 2), NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse(hex.Substring(startIndex + 4, 2), NumberStyles.AllowHexSpecifier),
|
||||
255);
|
||||
}
|
||||
else if (hex.Length == startIndex + 4) //#RGBA
|
||||
{
|
||||
color = new Color32(byte.Parse("" + hex[startIndex] + hex[startIndex], NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse("" + hex[startIndex + 1] + hex[startIndex + 1], NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse("" + hex[startIndex + 2] + hex[startIndex + 2], NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse("" + hex[startIndex + 3] + hex[startIndex + 3], NumberStyles.AllowHexSpecifier));
|
||||
}
|
||||
else //#RGB
|
||||
{
|
||||
color = new Color32(byte.Parse("" + hex[startIndex] + hex[startIndex], NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse("" + hex[startIndex + 1] + hex[startIndex + 1], NumberStyles.AllowHexSpecifier),
|
||||
byte.Parse("" + hex[startIndex + 2] + hex[startIndex + 2], NumberStyles.AllowHexSpecifier),
|
||||
255);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = new Color32();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -52,7 +52,9 @@ namespace UnityEngine.UI.Extensions.ColorPicker
|
|||
private void OnDestroy()
|
||||
{
|
||||
if (image.texture != null)
|
||||
{
|
||||
DestroyImmediate(image.texture);
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
///Credit perchik
|
||||
///Sourced from - http://forum.unity3d.com/threads/receive-onclick-event-and-pass-it-on-to-lower-ui-elements.293642/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
|
@ -13,10 +14,9 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[AddComponentMenu("UI/Extensions/AutoComplete ComboBox")]
|
||||
[AddComponentMenu("UI/Extensions/ComboBox/AutoComplete ComboBox")]
|
||||
public class AutoCompleteComboBox : MonoBehaviour
|
||||
{
|
||||
public Color disabledTextColor;
|
||||
public DropDownListItem SelectedItem { get; private set; } //outside world gets to get this, not set it
|
||||
|
||||
/// <summary>
|
||||
|
@ -24,17 +24,15 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <see cref="RemoveItem(string)"/> and <see cref="SetAvailableOptions(List{string})"/> methods as these also execute
|
||||
/// the required methods to update to the current collection.
|
||||
/// </summary>
|
||||
[Header("AutoComplete Box Items")]
|
||||
public List<string> AvailableOptions;
|
||||
|
||||
//private bool isInitialized = false;
|
||||
private bool _isPanelActive = false;
|
||||
private bool _hasDrawnOnce = false;
|
||||
|
||||
private InputField _mainInput;
|
||||
private RectTransform _inputRT;
|
||||
|
||||
//private Button _arrow_Button;
|
||||
|
||||
private RectTransform _rectTransform;
|
||||
|
||||
private RectTransform _overlayRT;
|
||||
|
@ -54,9 +52,14 @@ namespace UnityEngine.UI.Extensions
|
|||
private Dictionary<string, GameObject> panelObjects;
|
||||
|
||||
private GameObject itemTemplate;
|
||||
private bool _initialized;
|
||||
|
||||
public string Text { get; private set; }
|
||||
|
||||
[Header("Properties")]
|
||||
[SerializeField]
|
||||
private bool isActive = true;
|
||||
|
||||
[SerializeField]
|
||||
private float _scrollBarWidth = 20.0f;
|
||||
public float ScrollBarWidth
|
||||
|
@ -69,9 +72,6 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
// private int scrollOffset; //offset of the selected item
|
||||
// private int _selectedIndex = 0;
|
||||
|
||||
[SerializeField]
|
||||
private int _itemsToDisplay;
|
||||
public int ItemsToDisplay
|
||||
|
@ -84,71 +84,85 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
public bool SelectFirstItemOnStart = false;
|
||||
|
||||
[SerializeField]
|
||||
[SerializeField]
|
||||
[Tooltip("Change input text color based on matching items")]
|
||||
private bool _ChangeInputTextColorBasedOnMatchingItems = false;
|
||||
public bool InputColorMatching{
|
||||
get { return _ChangeInputTextColorBasedOnMatchingItems; }
|
||||
set
|
||||
{
|
||||
_ChangeInputTextColorBasedOnMatchingItems = value;
|
||||
if (_ChangeInputTextColorBasedOnMatchingItems) {
|
||||
SetInputTextColor ();
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool InputColorMatching
|
||||
{
|
||||
get { return _ChangeInputTextColorBasedOnMatchingItems; }
|
||||
set
|
||||
{
|
||||
_ChangeInputTextColorBasedOnMatchingItems = value;
|
||||
if (_ChangeInputTextColorBasedOnMatchingItems)
|
||||
{
|
||||
SetInputTextColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float DropdownOffset = 10f;
|
||||
|
||||
//TODO design as foldout for Inspector
|
||||
public Color ValidSelectionTextColor = Color.green;
|
||||
public Color MatchingItemsRemainingTextColor = Color.black;
|
||||
public Color NoItemsRemainingTextColor = Color.red;
|
||||
public Color MatchingItemsRemainingTextColor = Color.black;
|
||||
public Color NoItemsRemainingTextColor = Color.red;
|
||||
|
||||
public AutoCompleteSearchType autocompleteSearchType = AutoCompleteSearchType.Linq;
|
||||
|
||||
[SerializeField]
|
||||
private float dropdownOffset;
|
||||
|
||||
[SerializeField]
|
||||
private bool _displayPanelAbove = false;
|
||||
|
||||
public bool SelectFirstItemOnStart = false;
|
||||
|
||||
[SerializeField]
|
||||
private int selectItemIndexOnStart = 0;
|
||||
|
||||
private bool shouldSelectItemOnStart => SelectFirstItemOnStart || selectItemIndexOnStart > 0;
|
||||
|
||||
private bool _selectionIsValid = false;
|
||||
|
||||
[System.Serializable]
|
||||
public class SelectionChangedEvent : UnityEngine.Events.UnityEvent<string, bool> {
|
||||
}
|
||||
[System.Serializable]
|
||||
public class SelectionChangedEvent : Events.UnityEvent<string, bool> { }
|
||||
|
||||
[System.Serializable]
|
||||
public class SelectionTextChangedEvent : UnityEngine.Events.UnityEvent<string> {
|
||||
}
|
||||
public class SelectionTextChangedEvent : Events.UnityEvent<string> { }
|
||||
|
||||
[System.Serializable]
|
||||
public class SelectionValidityChangedEvent : UnityEngine.Events.UnityEvent<bool> {
|
||||
}
|
||||
[System.Serializable]
|
||||
public class SelectionValidityChangedEvent : Events.UnityEvent<bool> { }
|
||||
|
||||
// fires when input text is changed;
|
||||
public SelectionTextChangedEvent OnSelectionTextChanged;
|
||||
// fires when an Item gets selected / deselected (including when items are added/removed once this is possible)
|
||||
public SelectionValidityChangedEvent OnSelectionValidityChanged;
|
||||
// fires in both cases
|
||||
public SelectionChangedEvent OnSelectionChanged;
|
||||
[System.Serializable]
|
||||
public class ControlDisabledEvent : Events.UnityEvent<bool> { }
|
||||
|
||||
// fires when input text is changed;
|
||||
[Header("Events")]
|
||||
public SelectionTextChangedEvent OnSelectionTextChanged;
|
||||
// fires when an Item gets selected / deselected (including when items are added/removed once this is possible)
|
||||
public SelectionValidityChangedEvent OnSelectionValidityChanged;
|
||||
// fires in both cases
|
||||
public SelectionChangedEvent OnSelectionChanged;
|
||||
// fires when item is changed;
|
||||
public ControlDisabledEvent OnControlDisabled;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (SelectFirstItemOnStart && AvailableOptions.Count > 0) {
|
||||
ToggleDropdownPanel (false);
|
||||
OnItemClicked (AvailableOptions [0]);
|
||||
}
|
||||
public void Start()
|
||||
{
|
||||
if (shouldSelectItemOnStart && AvailableOptions.Count > 0)
|
||||
{
|
||||
SelectItemIndex(SelectFirstItemOnStart ? 0 : selectItemIndexOnStart);
|
||||
}
|
||||
RedrawPanel();
|
||||
}
|
||||
|
||||
private bool Initialize()
|
||||
{
|
||||
if (_initialized) return true;
|
||||
|
||||
bool success = true;
|
||||
try
|
||||
{
|
||||
|
@ -156,8 +170,6 @@ namespace UnityEngine.UI.Extensions
|
|||
_inputRT = _rectTransform.Find("InputField").GetComponent<RectTransform>();
|
||||
_mainInput = _inputRT.GetComponent<InputField>();
|
||||
|
||||
//_arrow_Button = _rectTransform.FindChild ("ArrowBtn").GetComponent<Button> ();
|
||||
|
||||
_overlayRT = _rectTransform.Find("Overlay").GetComponent<RectTransform>();
|
||||
_overlayRT.gameObject.SetActive(false);
|
||||
|
||||
|
@ -167,7 +179,6 @@ namespace UnityEngine.UI.Extensions
|
|||
_slidingAreaRT = _scrollBarRT.Find("SlidingArea").GetComponent<RectTransform>();
|
||||
_scrollHandleRT = _slidingAreaRT.Find("Handle").GetComponent<RectTransform>();
|
||||
_itemsPanelRT = _scrollPanelRT.Find("Items").GetComponent<RectTransform>();
|
||||
//itemPanelLayout = itemsPanelRT.gameObject.GetComponent<LayoutGroup>();
|
||||
|
||||
_canvas = GetComponentInParent<Canvas>();
|
||||
_canvasRT = _canvas.GetComponent<RectTransform>();
|
||||
|
@ -191,6 +202,8 @@ namespace UnityEngine.UI.Extensions
|
|||
_prunedPanelItems = new List<string>();
|
||||
_panelItems = new List<string>();
|
||||
|
||||
_initialized = true;
|
||||
|
||||
RebuildPanel();
|
||||
return success;
|
||||
}
|
||||
|
@ -225,21 +238,25 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Update the drop down selection to a specific index
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
public void SelectItemIndex(int index)
|
||||
{
|
||||
ToggleDropdownPanel(false);
|
||||
OnItemClicked(AvailableOptions[index]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the given items as new content for the comboBox. Previous entries will be cleared.
|
||||
/// </summary>
|
||||
/// <param name="newOptions">New entries.</param>
|
||||
public void SetAvailableOptions(List<string> newOptions)
|
||||
{
|
||||
var uniqueOptions = newOptions.Distinct().ToList();
|
||||
if (newOptions.Count != uniqueOptions.Count)
|
||||
{
|
||||
Debug.LogWarning($"{nameof(AutoCompleteComboBox)}.{nameof(SetAvailableOptions)}: items may only exists once. {newOptions.Count - uniqueOptions.Count} duplicates.");
|
||||
}
|
||||
|
||||
this.AvailableOptions.Clear();
|
||||
this.AvailableOptions = uniqueOptions;
|
||||
this.RebuildPanel();
|
||||
var uniqueOptions = newOptions.Distinct().ToArray();
|
||||
SetAvailableOptions(uniqueOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -255,18 +272,21 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
|
||||
this.AvailableOptions.Clear();
|
||||
|
||||
for (int i = 0; i < newOptions.Length; i++)
|
||||
{
|
||||
this.AvailableOptions.Add(newOptions[i]);
|
||||
}
|
||||
|
||||
this.RebuildPanel();
|
||||
this.RedrawPanel();
|
||||
}
|
||||
|
||||
public void ResetItems()
|
||||
{
|
||||
AvailableOptions.Clear();
|
||||
RebuildPanel();
|
||||
RedrawPanel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -274,6 +294,11 @@ namespace UnityEngine.UI.Extensions
|
|||
/// </summary>
|
||||
private void RebuildPanel()
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
Start();
|
||||
}
|
||||
|
||||
if (_isPanelActive) ToggleDropdownPanel();
|
||||
|
||||
//panel starts with all options
|
||||
|
@ -310,8 +335,11 @@ namespace UnityEngine.UI.Extensions
|
|||
if (i < AvailableOptions.Count)
|
||||
{
|
||||
itemObjs[i].name = "Item " + i + " " + _panelItems[i];
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
itemObjs[i].transform.Find("Text").GetComponent<TMPro.TMP_Text>().text = AvailableOptions[i]; //set the text value
|
||||
#else
|
||||
itemObjs[i].transform.Find("Text").GetComponent<Text>().text = AvailableOptions[i]; //set the text value
|
||||
|
||||
#endif
|
||||
Button itemBtn = itemObjs[i].GetComponent<Button>();
|
||||
itemBtn.onClick.RemoveAllListeners();
|
||||
string textOfItem = _panelItems[i]; //has to be copied for anonymous function or it gets garbage collected away
|
||||
|
@ -322,7 +350,7 @@ namespace UnityEngine.UI.Extensions
|
|||
panelObjects[_panelItems[i]] = itemObjs[i];
|
||||
}
|
||||
}
|
||||
SetInputTextColor ();
|
||||
SetInputTextColor();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -337,63 +365,39 @@ namespace UnityEngine.UI.Extensions
|
|||
ToggleDropdownPanel(true);
|
||||
}
|
||||
|
||||
//private void UpdateSelected()
|
||||
//{
|
||||
// SelectedItem = (_selectedIndex > -1 && _selectedIndex < Items.Count) ? Items[_selectedIndex] : null;
|
||||
// if (SelectedItem == null) return;
|
||||
|
||||
// bool hasImage = SelectedItem.Image != null;
|
||||
// if (hasImage)
|
||||
// {
|
||||
// mainButton.img.sprite = SelectedItem.Image;
|
||||
// mainButton.img.color = Color.white;
|
||||
|
||||
// //if (Interactable) mainButton.img.color = Color.white;
|
||||
// //else mainButton.img.color = new Color(1, 1, 1, .5f);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// mainButton.img.sprite = null;
|
||||
// }
|
||||
|
||||
// mainButton.txt.text = SelectedItem.Caption;
|
||||
|
||||
// //update selected index color
|
||||
// for (int i = 0; i < itemsPanelRT.childCount; i++)
|
||||
// {
|
||||
// panelItems[i].btnImg.color = (_selectedIndex == i) ? mainButton.btn.colors.highlightedColor : new Color(0, 0, 0, 0);
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
private void RedrawPanel()
|
||||
{
|
||||
float scrollbarWidth = _panelItems.Count > ItemsToDisplay ? _scrollBarWidth : 0f;//hide the scrollbar if there's not enough items
|
||||
_scrollBarRT.gameObject.SetActive(_panelItems.Count > ItemsToDisplay);
|
||||
|
||||
float dropdownHeight = _itemsToDisplay > 0 ? _rectTransform.sizeDelta.y * Mathf.Min(_itemsToDisplay, _panelItems.Count) : _rectTransform.sizeDelta.y * _panelItems.Count;
|
||||
dropdownHeight += dropdownOffset;
|
||||
|
||||
if (!_hasDrawnOnce || _rectTransform.sizeDelta != _inputRT.sizeDelta)
|
||||
{
|
||||
_hasDrawnOnce = true;
|
||||
_inputRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
||||
_inputRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _rectTransform.sizeDelta.y);
|
||||
|
||||
_scrollPanelRT.SetParent(transform, true);//break the scroll panel from the overlay
|
||||
var itemsRemaining = _panelItems.Count - ItemsToDisplay;
|
||||
itemsRemaining = itemsRemaining < 0 ? 0 : itemsRemaining;
|
||||
|
||||
_scrollPanelRT.SetParent(transform, true);
|
||||
_scrollPanelRT.anchoredPosition = _displayPanelAbove ?
|
||||
new Vector2(0, DropdownOffset + _rectTransform.sizeDelta.y * _panelItems.Count - 1) :
|
||||
new Vector2(0, -_rectTransform.sizeDelta.y);
|
||||
new Vector2(0, dropdownOffset + dropdownHeight) :
|
||||
new Vector2(0, -(dropdownOffset + _rectTransform.sizeDelta.y));
|
||||
|
||||
//make the overlay fill the screen
|
||||
_overlayRT.SetParent(_canvas.transform, false); //attach it to top level object
|
||||
_overlayRT.SetParent(_canvas.transform, false);
|
||||
_overlayRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _canvasRT.sizeDelta.x);
|
||||
_overlayRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _canvasRT.sizeDelta.y);
|
||||
|
||||
_overlayRT.SetParent(transform, true);//reattach to this object
|
||||
_scrollPanelRT.SetParent(_overlayRT, true); //reattach the scrollpanel to the overlay
|
||||
_overlayRT.SetParent(transform, true);
|
||||
_scrollPanelRT.SetParent(_overlayRT, true);
|
||||
}
|
||||
|
||||
if (_panelItems.Count < 1) return;
|
||||
|
||||
float dropdownHeight = _rectTransform.sizeDelta.y * Mathf.Min(_itemsToDisplay, _panelItems.Count) + DropdownOffset;
|
||||
|
||||
_scrollPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, dropdownHeight);
|
||||
_scrollPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
||||
|
||||
|
@ -413,7 +417,6 @@ namespace UnityEngine.UI.Extensions
|
|||
Text = currText;
|
||||
PruneItems(currText);
|
||||
RedrawPanel();
|
||||
//Debug.Log("value changed to: " + currText);
|
||||
|
||||
if (_panelItems.Count == 0)
|
||||
{
|
||||
|
@ -425,30 +428,36 @@ namespace UnityEngine.UI.Extensions
|
|||
ToggleDropdownPanel(false);
|
||||
}
|
||||
|
||||
bool validity_changed = (_panelItems.Contains (Text) != _selectionIsValid);
|
||||
_selectionIsValid = _panelItems.Contains (Text);
|
||||
OnSelectionChanged.Invoke (Text, _selectionIsValid);
|
||||
OnSelectionTextChanged.Invoke (Text);
|
||||
if(validity_changed){
|
||||
OnSelectionValidityChanged.Invoke (_selectionIsValid);
|
||||
}
|
||||
bool validity_changed = (_panelItems.Contains(Text) != _selectionIsValid);
|
||||
_selectionIsValid = _panelItems.Contains(Text);
|
||||
OnSelectionChanged.Invoke(Text, _selectionIsValid);
|
||||
OnSelectionTextChanged.Invoke(Text);
|
||||
if (validity_changed)
|
||||
{
|
||||
OnSelectionValidityChanged.Invoke(_selectionIsValid);
|
||||
}
|
||||
|
||||
SetInputTextColor ();
|
||||
SetInputTextColor();
|
||||
}
|
||||
|
||||
private void SetInputTextColor(){
|
||||
if (InputColorMatching) {
|
||||
if (_selectionIsValid) {
|
||||
_mainInput.textComponent.color = ValidSelectionTextColor;
|
||||
} else if (_panelItems.Count > 0) {
|
||||
_mainInput.textComponent.color = MatchingItemsRemainingTextColor;
|
||||
} else {
|
||||
_mainInput.textComponent.color = NoItemsRemainingTextColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void SetInputTextColor()
|
||||
{
|
||||
if (InputColorMatching)
|
||||
{
|
||||
if (_selectionIsValid)
|
||||
{
|
||||
_mainInput.textComponent.color = ValidSelectionTextColor;
|
||||
}
|
||||
else if (_panelItems.Count > 0)
|
||||
{
|
||||
_mainInput.textComponent.color = MatchingItemsRemainingTextColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
_mainInput.textComponent.color = NoItemsRemainingTextColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle the drop down list
|
||||
|
@ -456,6 +465,8 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <param name="directClick"> whether an item was directly clicked on</param>
|
||||
public void ToggleDropdownPanel(bool directClick = false)
|
||||
{
|
||||
if (!isActive) return;
|
||||
|
||||
_isPanelActive = !_isPanelActive;
|
||||
|
||||
_overlayRT.gameObject.SetActive(_isPanelActive);
|
||||
|
@ -469,6 +480,20 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Updates the control and sets its active status, determines whether the dropdown will open ot not
|
||||
/// </summary>
|
||||
/// <param name="status"></param>
|
||||
public void SetActive(bool status)
|
||||
{
|
||||
if (status != isActive)
|
||||
{
|
||||
OnControlDisabled?.Invoke(status);
|
||||
}
|
||||
isActive = status;
|
||||
}
|
||||
|
||||
private void PruneItems(string currText)
|
||||
{
|
||||
if (autocompleteSearchType == AutoCompleteSearchType.Linq)
|
||||
|
|
|
@ -3,48 +3,61 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static UnityEditor.Progress;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[AddComponentMenu("UI/Extensions/ComboBox")]
|
||||
[AddComponentMenu("UI/Extensions/ComboBox/ComboBox")]
|
||||
public class ComboBox : MonoBehaviour
|
||||
{
|
||||
public Color disabledTextColor;
|
||||
public DropDownListItem SelectedItem { get; private set; } //outside world gets to get this, not set it
|
||||
public DropDownListItem SelectedItem { get; private set; }
|
||||
|
||||
[Header("Combo Box Items")]
|
||||
public List<string> AvailableOptions;
|
||||
|
||||
[Header("Properties")]
|
||||
[SerializeField]
|
||||
private bool isActive = true;
|
||||
|
||||
[SerializeField]
|
||||
private float _scrollBarWidth = 20.0f;
|
||||
|
||||
[SerializeField]
|
||||
private int _itemsToDisplay;
|
||||
|
||||
//Sorting disabled as it causes issues.
|
||||
//[SerializeField]
|
||||
//private bool _sortItems = true;
|
||||
[SerializeField]
|
||||
private float dropdownOffset;
|
||||
|
||||
[SerializeField]
|
||||
private bool _displayPanelAbove = false;
|
||||
|
||||
public bool SelectFirstItemOnStart = false;
|
||||
|
||||
[SerializeField]
|
||||
private int selectItemIndexOnStart = 0;
|
||||
|
||||
private bool shouldSelectItemOnStart => SelectFirstItemOnStart || selectItemIndexOnStart > 0;
|
||||
|
||||
[System.Serializable]
|
||||
public class SelectionChangedEvent : UnityEngine.Events.UnityEvent<string>
|
||||
{
|
||||
}
|
||||
public class SelectionChangedEvent : Events.UnityEvent<string> { }
|
||||
|
||||
[Header("Events")]
|
||||
// fires when item is changed;
|
||||
public SelectionChangedEvent OnSelectionChanged;
|
||||
|
||||
[System.Serializable]
|
||||
public class ControlDisabledEvent : Events.UnityEvent<bool> { }
|
||||
|
||||
// fires when item is changed;
|
||||
public ControlDisabledEvent OnControlDisabled;
|
||||
|
||||
//private bool isInitialized = false;
|
||||
private bool _isPanelActive = false;
|
||||
private bool _hasDrawnOnce = false;
|
||||
|
||||
private InputField _mainInput;
|
||||
private RectTransform _inputRT;
|
||||
|
||||
|
||||
private RectTransform _rectTransform;
|
||||
|
||||
private RectTransform _overlayRT;
|
||||
private RectTransform _scrollPanelRT;
|
||||
private RectTransform _scrollBarRT;
|
||||
|
@ -53,14 +66,11 @@ namespace UnityEngine.UI.Extensions
|
|||
private RectTransform _itemsPanelRT;
|
||||
private Canvas _canvas;
|
||||
private RectTransform _canvasRT;
|
||||
|
||||
private ScrollRect _scrollRect;
|
||||
|
||||
private List<string> _panelItems; //items that will get shown in the drop-down
|
||||
|
||||
private Dictionary<string, GameObject> panelObjects;
|
||||
|
||||
private GameObject itemTemplate;
|
||||
private bool _initialized;
|
||||
|
||||
public string Text { get; private set; }
|
||||
|
||||
|
@ -74,9 +84,6 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
// private int scrollOffset; //offset of the selected item
|
||||
// private int _selectedIndex = 0;
|
||||
|
||||
public int ItemsToDisplay
|
||||
{
|
||||
get { return _itemsToDisplay; }
|
||||
|
@ -94,11 +101,17 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
public void Start()
|
||||
{
|
||||
if (shouldSelectItemOnStart && AvailableOptions.Count > 0)
|
||||
{
|
||||
SelectItemIndex(SelectFirstItemOnStart ? 0 : selectItemIndexOnStart);
|
||||
}
|
||||
RedrawPanel();
|
||||
}
|
||||
|
||||
private bool Initialize()
|
||||
{
|
||||
if (_initialized) return true;
|
||||
|
||||
bool success = true;
|
||||
try
|
||||
{
|
||||
|
@ -138,11 +151,22 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
_panelItems = AvailableOptions.ToList();
|
||||
|
||||
_initialized = true;
|
||||
|
||||
RebuildPanel();
|
||||
//RedrawPanel(); - causes an initialisation failure in U5
|
||||
return success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the drop down selection to a specific index
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
public void SelectItemIndex(int index)
|
||||
{
|
||||
ToggleDropdownPanel(false);
|
||||
OnItemClicked(AvailableOptions[index]);
|
||||
}
|
||||
|
||||
public void AddItem(string item)
|
||||
{
|
||||
AvailableOptions.Add(item);
|
||||
|
@ -157,26 +181,34 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
public void SetAvailableOptions(List<string> newOptions)
|
||||
{
|
||||
AvailableOptions.Clear();
|
||||
AvailableOptions = newOptions;
|
||||
RebuildPanel();
|
||||
var uniqueOptions = newOptions.Distinct().ToArray();
|
||||
SetAvailableOptions(uniqueOptions);
|
||||
}
|
||||
|
||||
public void SetAvailableOptions(string[] newOptions)
|
||||
{
|
||||
AvailableOptions.Clear();
|
||||
var uniqueOptions = newOptions.Distinct().ToList();
|
||||
if (newOptions.Length != uniqueOptions.Count)
|
||||
{
|
||||
Debug.LogWarning($"{nameof(ComboBox)}.{nameof(SetAvailableOptions)}: items may only exists once. {newOptions.Length - uniqueOptions.Count} duplicates.");
|
||||
}
|
||||
|
||||
this.AvailableOptions.Clear();
|
||||
|
||||
for (int i = 0; i < newOptions.Length; i++)
|
||||
{
|
||||
AvailableOptions.Add(newOptions[i]);
|
||||
this.AvailableOptions.Add(newOptions[i]);
|
||||
}
|
||||
RebuildPanel();
|
||||
|
||||
this.RebuildPanel();
|
||||
this.RedrawPanel();
|
||||
}
|
||||
|
||||
public void ResetItems()
|
||||
{
|
||||
AvailableOptions.Clear();
|
||||
RebuildPanel();
|
||||
RedrawPanel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -184,13 +216,17 @@ namespace UnityEngine.UI.Extensions
|
|||
/// </summary>
|
||||
private void RebuildPanel()
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
Start();
|
||||
}
|
||||
|
||||
//panel starts with all options
|
||||
_panelItems.Clear();
|
||||
foreach (string option in AvailableOptions)
|
||||
{
|
||||
_panelItems.Add(option.ToLower());
|
||||
}
|
||||
//if(_sortItems) _panelItems.Sort();
|
||||
|
||||
List<GameObject> itemObjs = new List<GameObject>(panelObjects.Values);
|
||||
panelObjects.Clear();
|
||||
|
@ -211,8 +247,11 @@ namespace UnityEngine.UI.Extensions
|
|||
if (i < AvailableOptions.Count)
|
||||
{
|
||||
itemObjs[i].name = "Item " + i + " " + _panelItems[i];
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
itemObjs[i].transform.Find("Text").GetComponent<TMPro.TMP_Text>().text = AvailableOptions[i]; //set the text value
|
||||
#else
|
||||
itemObjs[i].transform.Find("Text").GetComponent<Text>().text = AvailableOptions[i]; //set the text value
|
||||
|
||||
#endif
|
||||
Button itemBtn = itemObjs[i].GetComponent<Button>();
|
||||
itemBtn.onClick.RemoveAllListeners();
|
||||
string textOfItem = _panelItems[i]; //has to be copied for anonymous function or it gets garbage collected away
|
||||
|
@ -237,63 +276,39 @@ namespace UnityEngine.UI.Extensions
|
|||
ToggleDropdownPanel(true);
|
||||
}
|
||||
|
||||
//private void UpdateSelected()
|
||||
//{
|
||||
// SelectedItem = (_selectedIndex > -1 && _selectedIndex < Items.Count) ? Items[_selectedIndex] : null;
|
||||
// if (SelectedItem == null) return;
|
||||
|
||||
// bool hasImage = SelectedItem.Image != null;
|
||||
// if (hasImage)
|
||||
// {
|
||||
// mainButton.img.sprite = SelectedItem.Image;
|
||||
// mainButton.img.color = Color.white;
|
||||
|
||||
// //if (Interactable) mainButton.img.color = Color.white;
|
||||
// //else mainButton.img.color = new Color(1, 1, 1, .5f);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// mainButton.img.sprite = null;
|
||||
// }
|
||||
|
||||
// mainButton.txt.text = SelectedItem.Caption;
|
||||
|
||||
// //update selected index color
|
||||
// for (int i = 0; i < itemsPanelRT.childCount; i++)
|
||||
// {
|
||||
// panelItems[i].btnImg.color = (_selectedIndex == i) ? mainButton.btn.colors.highlightedColor : new Color(0, 0, 0, 0);
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
private void RedrawPanel()
|
||||
{
|
||||
float scrollbarWidth = _panelItems.Count > ItemsToDisplay ? _scrollBarWidth : 0f;//hide the scrollbar if there's not enough items
|
||||
_scrollBarRT.gameObject.SetActive(_panelItems.Count > ItemsToDisplay);
|
||||
|
||||
float dropdownHeight = _itemsToDisplay > 0 ? _rectTransform.sizeDelta.y * Mathf.Min(_itemsToDisplay, _panelItems.Count) : _rectTransform.sizeDelta.y * _panelItems.Count;
|
||||
dropdownHeight += dropdownOffset;
|
||||
|
||||
if (!_hasDrawnOnce || _rectTransform.sizeDelta != _inputRT.sizeDelta)
|
||||
{
|
||||
_hasDrawnOnce = true;
|
||||
_inputRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
||||
_inputRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _rectTransform.sizeDelta.y);
|
||||
|
||||
_scrollPanelRT.SetParent(transform, true);//break the scroll panel from the overlay
|
||||
var itemsRemaining = _panelItems.Count - ItemsToDisplay;
|
||||
itemsRemaining = itemsRemaining < 0 ? 0 : itemsRemaining;
|
||||
|
||||
_scrollPanelRT.SetParent(transform, true);
|
||||
_scrollPanelRT.anchoredPosition = _displayPanelAbove ?
|
||||
new Vector2(0, _rectTransform.sizeDelta.y * ItemsToDisplay - 1) :
|
||||
new Vector2(0, -_rectTransform.sizeDelta.y);
|
||||
new Vector2(0, dropdownOffset + dropdownHeight) :
|
||||
new Vector2(0, -(dropdownOffset + _rectTransform.sizeDelta.y));
|
||||
|
||||
//make the overlay fill the screen
|
||||
_overlayRT.SetParent(_canvas.transform, false); //attach it to top level object
|
||||
_overlayRT.SetParent(_canvas.transform, false);
|
||||
_overlayRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _canvasRT.sizeDelta.x);
|
||||
_overlayRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _canvasRT.sizeDelta.y);
|
||||
|
||||
_overlayRT.SetParent(transform, true);//reattach to this object
|
||||
_scrollPanelRT.SetParent(_overlayRT, true); //reattach the scrollpanel to the overlay
|
||||
_overlayRT.SetParent(transform, true);
|
||||
_scrollPanelRT.SetParent(_overlayRT, true);
|
||||
}
|
||||
|
||||
if (_panelItems.Count < 1) return;
|
||||
|
||||
float dropdownHeight = _rectTransform.sizeDelta.y * Mathf.Min(_itemsToDisplay, _panelItems.Count);
|
||||
|
||||
_scrollPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, dropdownHeight);
|
||||
_scrollPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
||||
|
||||
|
@ -312,7 +327,6 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
Text = currText;
|
||||
RedrawPanel();
|
||||
//Debug.Log("value changed to: " + currText);
|
||||
|
||||
if (_panelItems.Count == 0)
|
||||
{
|
||||
|
@ -332,6 +346,8 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <param name="directClick"> whether an item was directly clicked on</param>
|
||||
public void ToggleDropdownPanel(bool directClick)
|
||||
{
|
||||
if (!isActive) return;
|
||||
|
||||
_isPanelActive = !_isPanelActive;
|
||||
|
||||
_overlayRT.gameObject.SetActive(_isPanelActive);
|
||||
|
@ -344,5 +360,18 @@ namespace UnityEngine.UI.Extensions
|
|||
// scrollOffset = Mathf.RoundToInt(itemsPanelRT.anchoredPosition.y / _rectTransform.sizeDelta.y);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the control and sets its active status, determines whether the dropdown will open ot not
|
||||
/// </summary>
|
||||
/// <param name="status"></param>
|
||||
public void SetActive(bool status)
|
||||
{
|
||||
if (status != isActive)
|
||||
{
|
||||
OnControlDisabled?.Invoke(status);
|
||||
}
|
||||
isActive = status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
///Credit perchik
|
||||
///Sourced from - http://forum.unity3d.com/threads/receive-onclick-event-and-pass-it-on-to-lower-ui-elements.293642/
|
||||
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
|
@ -10,13 +9,20 @@ namespace UnityEngine.UI.Extensions
|
|||
/// Extension to the UI class which creates a dropdown list
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[AddComponentMenu("UI/Extensions/Dropdown List")]
|
||||
[AddComponentMenu("UI/Extensions/ComboBox/Dropdown List")]
|
||||
public class DropDownList : MonoBehaviour
|
||||
{
|
||||
public Color disabledTextColor;
|
||||
public DropDownListItem SelectedItem { get; private set; } //outside world gets to get this, not set it
|
||||
|
||||
public List<DropDownListItem> Items;
|
||||
[Header("Dropdown List Items")]
|
||||
public List<DropDownListItem> Items;
|
||||
|
||||
[Header("Properties")]
|
||||
|
||||
[SerializeField]
|
||||
private bool isActive = true;
|
||||
|
||||
public bool OverrideHighlighted = true;
|
||||
|
||||
//private bool isInitialized = false;
|
||||
|
@ -38,11 +44,12 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
private ScrollRect _scrollRect;
|
||||
|
||||
private List<DropDownListButton> _panelItems;
|
||||
private List<DropDownListButton> _panelItems = new List<DropDownListButton>();
|
||||
|
||||
private GameObject _itemTemplate;
|
||||
private GameObject _itemTemplate;
|
||||
private bool _initialized;
|
||||
|
||||
[SerializeField]
|
||||
[SerializeField]
|
||||
private float _scrollBarWidth = 20.0f;
|
||||
public float ScrollBarWidth
|
||||
{
|
||||
|
@ -69,30 +76,45 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
public bool SelectFirstItemOnStart = false;
|
||||
[SerializeField]
|
||||
private float dropdownOffset;
|
||||
|
||||
[SerializeField]
|
||||
private bool _displayPanelAbove = false;
|
||||
[SerializeField]
|
||||
private bool _displayPanelAbove = false;
|
||||
|
||||
[System.Serializable]
|
||||
public class SelectionChangedEvent : UnityEngine.Events.UnityEvent<int> {
|
||||
}
|
||||
// fires when item is changed;
|
||||
public SelectionChangedEvent OnSelectionChanged;
|
||||
public bool SelectFirstItemOnStart = false;
|
||||
|
||||
[SerializeField]
|
||||
private int selectItemIndexOnStart = 0;
|
||||
private bool shouldSelectItemOnStart => SelectFirstItemOnStart || selectItemIndexOnStart > 0;
|
||||
|
||||
public void Start()
|
||||
[System.Serializable]
|
||||
public class SelectionChangedEvent : Events.UnityEvent<int> { }
|
||||
|
||||
// fires when item is changed;
|
||||
[Header("Events")]
|
||||
public SelectionChangedEvent OnSelectionChanged;
|
||||
|
||||
[System.Serializable]
|
||||
public class ControlDisabledEvent : Events.UnityEvent<bool> { }
|
||||
|
||||
// fires when item is changed;
|
||||
public ControlDisabledEvent OnControlDisabled;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Initialize();
|
||||
if (shouldSelectItemOnStart && Items.Count > 0)
|
||||
{
|
||||
SelectItemIndex(SelectFirstItemOnStart ? 0 : selectItemIndexOnStart);
|
||||
}
|
||||
RedrawPanel();
|
||||
}
|
||||
|
||||
private bool Initialize()
|
||||
{
|
||||
Initialize();
|
||||
if (SelectFirstItemOnStart && Items.Count > 0) {
|
||||
ToggleDropdownPanel (false);
|
||||
OnItemClicked (0);
|
||||
}
|
||||
RedrawPanel();
|
||||
}
|
||||
if (_initialized) return true;
|
||||
|
||||
private bool Initialize()
|
||||
{
|
||||
bool success = true;
|
||||
try
|
||||
{
|
||||
|
@ -101,8 +123,6 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
_overlayRT = _rectTransform.Find("Overlay").GetComponent<RectTransform>();
|
||||
_overlayRT.gameObject.SetActive(false);
|
||||
|
||||
|
||||
_scrollPanelRT = _overlayRT.Find("ScrollPanel").GetComponent<RectTransform>();
|
||||
_scrollBarRT = _scrollPanelRT.Find("Scrollbar").GetComponent<RectTransform>();
|
||||
_slidingAreaRT = _scrollBarRT.Find("SlidingArea").GetComponent<RectTransform>();
|
||||
|
@ -118,7 +138,6 @@ namespace UnityEngine.UI.Extensions
|
|||
_scrollRect.movementType = ScrollRect.MovementType.Clamped;
|
||||
_scrollRect.content = _itemsPanelRT;
|
||||
|
||||
|
||||
_itemTemplate = _rectTransform.Find("ItemTemplate").gameObject;
|
||||
_itemTemplate.SetActive(false);
|
||||
}
|
||||
|
@ -128,23 +147,32 @@ namespace UnityEngine.UI.Extensions
|
|||
Debug.LogError("Something is setup incorrectly with the dropdownlist component causing a Null Reference Exception");
|
||||
success = false;
|
||||
}
|
||||
_initialized = true;
|
||||
|
||||
_panelItems = new List<DropDownListButton>();
|
||||
|
||||
RebuildPanel();
|
||||
RebuildPanel();
|
||||
RedrawPanel();
|
||||
return success;
|
||||
}
|
||||
|
||||
// currently just using items in the list instead of being able to add to it.
|
||||
/// <summary>
|
||||
/// Rebuilds the list from a new collection.
|
||||
/// <summary>
|
||||
/// Update the drop down selection to a specific index
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// NOTE, this will clear all existing items
|
||||
/// </remarks>
|
||||
/// <param name="list"></param>
|
||||
public void RefreshItems(params object[] list)
|
||||
/// <param name="index"></param>
|
||||
public void SelectItemIndex(int index)
|
||||
{
|
||||
ToggleDropdownPanel(false);
|
||||
OnItemClicked(index);
|
||||
}
|
||||
|
||||
// currently just using items in the list instead of being able to add to it.
|
||||
/// <summary>
|
||||
/// Rebuilds the list from a new collection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// NOTE, this will clear all existing items
|
||||
/// </remarks>
|
||||
/// <param name="list"></param>
|
||||
public void RefreshItems(params object[] list)
|
||||
{
|
||||
Items.Clear();
|
||||
List<DropDownListItem> ddItems = new List<DropDownListItem>();
|
||||
|
@ -169,72 +197,80 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
Items.AddRange(ddItems);
|
||||
RebuildPanel();
|
||||
}
|
||||
RedrawPanel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an additional item to the drop down list (recommended)
|
||||
/// </summary>
|
||||
/// <param name="item">Item of type DropDownListItem</param>
|
||||
public void AddItem(DropDownListItem item)
|
||||
/// <summary>
|
||||
/// Adds an additional item to the drop down list (recommended)
|
||||
/// </summary>
|
||||
/// <param name="item">Item of type DropDownListItem</param>
|
||||
public void AddItem(DropDownListItem item)
|
||||
{
|
||||
Items.Add(item);
|
||||
RebuildPanel();
|
||||
}
|
||||
RedrawPanel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an additional drop down list item using a string name
|
||||
/// </summary>
|
||||
/// <param name="item">Item of type String</param>
|
||||
public void AddItem(string item)
|
||||
/// <summary>
|
||||
/// Adds an additional drop down list item using a string name
|
||||
/// </summary>
|
||||
/// <param name="item">Item of type String</param>
|
||||
public void AddItem(string item)
|
||||
{
|
||||
Items.Add(new DropDownListItem(caption: (string)item));
|
||||
RebuildPanel();
|
||||
}
|
||||
RedrawPanel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an additional drop down list item using a sprite image
|
||||
/// </summary>
|
||||
/// <param name="item">Item of type UI Sprite</param>
|
||||
public void AddItem(Sprite item)
|
||||
/// <summary>
|
||||
/// Adds an additional drop down list item using a sprite image
|
||||
/// </summary>
|
||||
/// <param name="item">Item of type UI Sprite</param>
|
||||
public void AddItem(Sprite item)
|
||||
{
|
||||
Items.Add(new DropDownListItem(image: (Sprite)item));
|
||||
RebuildPanel();
|
||||
}
|
||||
RedrawPanel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an item from the drop down list (recommended)
|
||||
/// </summary>
|
||||
/// <param name="item">Item of type DropDownListItem</param>
|
||||
public void RemoveItem(DropDownListItem item)
|
||||
/// <summary>
|
||||
/// Removes an item from the drop down list (recommended)
|
||||
/// </summary>
|
||||
/// <param name="item">Item of type DropDownListItem</param>
|
||||
public void RemoveItem(DropDownListItem item)
|
||||
{
|
||||
Items.Remove(item);
|
||||
RebuildPanel();
|
||||
}
|
||||
RedrawPanel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an item from the drop down list item using a string name
|
||||
/// </summary>
|
||||
/// <param name="item">Item of type String</param>
|
||||
public void RemoveItem(string item)
|
||||
/// <summary>
|
||||
/// Removes an item from the drop down list item using a string name
|
||||
/// </summary>
|
||||
/// <param name="item">Item of type String</param>
|
||||
public void RemoveItem(string item)
|
||||
{
|
||||
Items.Remove(new DropDownListItem(caption: (string)item));
|
||||
RebuildPanel();
|
||||
}
|
||||
RedrawPanel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an item from the drop down list item using a sprite image
|
||||
/// </summary>
|
||||
/// <param name="item">Item of type UI Sprite</param>
|
||||
public void RemoveItem(Sprite item)
|
||||
/// <summary>
|
||||
/// Removes an item from the drop down list item using a sprite image
|
||||
/// </summary>
|
||||
/// <param name="item">Item of type UI Sprite</param>
|
||||
public void RemoveItem(Sprite item)
|
||||
{
|
||||
Items.Remove(new DropDownListItem(image: (Sprite)item));
|
||||
RebuildPanel();
|
||||
}
|
||||
RedrawPanel();
|
||||
}
|
||||
|
||||
public void ResetItems()
|
||||
public void ResetItems()
|
||||
{
|
||||
Items.Clear();
|
||||
RebuildPanel();
|
||||
RedrawPanel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -244,6 +280,11 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
if (Items.Count == 0) return;
|
||||
|
||||
if (!_initialized)
|
||||
{
|
||||
Start();
|
||||
}
|
||||
|
||||
int indx = _panelItems.Count;
|
||||
while (_panelItems.Count < Items.Count)
|
||||
{
|
||||
|
@ -300,9 +341,6 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
_mainButton.img.sprite = SelectedItem.Image;
|
||||
_mainButton.img.color = Color.white;
|
||||
|
||||
//if (Interactable) mainButton.img.color = Color.white;
|
||||
//else mainButton.img.color = new Color(1, 1, 1, .5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -314,7 +352,6 @@ namespace UnityEngine.UI.Extensions
|
|||
//update selected index color
|
||||
if (OverrideHighlighted)
|
||||
{
|
||||
|
||||
for (int i = 0; i < _itemsPanelRT.childCount; i++)
|
||||
{
|
||||
_panelItems[i].btnImg.color = (_selectedIndex == i) ? _mainButton.btn.colors.highlightedColor : new Color(0, 0, 0, 0);
|
||||
|
@ -322,37 +359,40 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void RedrawPanel()
|
||||
private void RedrawPanel()
|
||||
{
|
||||
float scrollbarWidth = Items.Count > ItemsToDisplay ? _scrollBarWidth : 0f;//hide the scrollbar if there's not enough items
|
||||
float scrollbarWidth = _panelItems.Count > ItemsToDisplay ? _scrollBarWidth : 0f;//hide the scrollbar if there's not enough items
|
||||
_scrollBarRT.gameObject.SetActive(_panelItems.Count > ItemsToDisplay);
|
||||
|
||||
if (!_hasDrawnOnce || _rectTransform.sizeDelta != _mainButton.rectTransform.sizeDelta)
|
||||
float dropdownHeight = _itemsToDisplay > 0 ? _rectTransform.sizeDelta.y * Mathf.Min(_itemsToDisplay, _panelItems.Count) : _rectTransform.sizeDelta.y * _panelItems.Count;
|
||||
dropdownHeight += dropdownOffset;
|
||||
|
||||
if (!_hasDrawnOnce || _rectTransform.sizeDelta != _mainButton.rectTransform.sizeDelta)
|
||||
{
|
||||
_hasDrawnOnce = true;
|
||||
_mainButton.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
||||
_mainButton.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _rectTransform.sizeDelta.y);
|
||||
_mainButton.txt.rectTransform.offsetMax = new Vector2(4, 0);
|
||||
|
||||
_scrollPanelRT.SetParent(transform, true);//break the scroll panel from the overlay
|
||||
_scrollPanelRT.anchoredPosition = _displayPanelAbove ?
|
||||
new Vector2(0, _rectTransform.sizeDelta.y * ItemsToDisplay - 1) :
|
||||
new Vector2(0, -_rectTransform.sizeDelta.y);
|
||||
var itemsRemaining = _panelItems.Count - ItemsToDisplay;
|
||||
itemsRemaining = itemsRemaining < 0 ? 0 : itemsRemaining;
|
||||
|
||||
//make the overlay fill the screen
|
||||
_overlayRT.SetParent(_canvas.transform, false); //attach it to top level object
|
||||
_scrollPanelRT.SetParent(transform, true);
|
||||
_scrollPanelRT.anchoredPosition = _displayPanelAbove ?
|
||||
new Vector2(0, dropdownOffset + dropdownHeight) :
|
||||
new Vector2(0, -(dropdownOffset + _rectTransform.sizeDelta.y));
|
||||
|
||||
//make the overlay fill the screen
|
||||
_overlayRT.SetParent(_canvas.transform, false);
|
||||
_overlayRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _canvasRT.sizeDelta.x);
|
||||
_overlayRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _canvasRT.sizeDelta.y);
|
||||
|
||||
_overlayRT.SetParent(transform, true);//reattach to this object
|
||||
_scrollPanelRT.SetParent(_overlayRT, true); //reattach the scrollpanel to the overlay
|
||||
_overlayRT.SetParent(transform, true);
|
||||
_scrollPanelRT.SetParent(_overlayRT, true);
|
||||
}
|
||||
|
||||
if (Items.Count < 1) return;
|
||||
if (_panelItems.Count < 1) return;
|
||||
|
||||
float dropdownHeight = _rectTransform.sizeDelta.y * Mathf.Min(_itemsToDisplay, Items.Count);
|
||||
|
||||
_scrollPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, dropdownHeight);
|
||||
_scrollPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, dropdownHeight);
|
||||
_scrollPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
||||
|
||||
_itemsPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _scrollPanelRT.sizeDelta.x - scrollbarWidth - 5);
|
||||
|
@ -372,6 +412,8 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <param name="directClick"> whether an item was directly clicked on</param>
|
||||
public void ToggleDropdownPanel(bool directClick)
|
||||
{
|
||||
if (!isActive) return;
|
||||
|
||||
_overlayRT.transform.localScale = new Vector3(1, 1, 1);
|
||||
_scrollBarRT.transform.localScale = new Vector3(1, 1, 1);
|
||||
_isPanelActive = !_isPanelActive;
|
||||
|
@ -385,5 +427,18 @@ namespace UnityEngine.UI.Extensions
|
|||
// scrollOffset = Mathf.RoundToInt(itemsPanelRT.anchoredPosition.y / _rectTransform.sizeDelta.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the control and sets its active status, determines whether the dropdown will open ot not
|
||||
/// </summary>
|
||||
/// <param name="status"></param>
|
||||
public void SetActive(bool status)
|
||||
{
|
||||
if (status != isActive)
|
||||
{
|
||||
OnControlDisabled?.Invoke(status);
|
||||
}
|
||||
isActive = status;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,11 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
public RectTransform rectTransform;
|
||||
public Button btn;
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
public TMPro.TMP_Text txt;
|
||||
#else
|
||||
public Text txt;
|
||||
#endif
|
||||
public Image btnImg;
|
||||
public Image img;
|
||||
public GameObject gameobject;
|
||||
|
@ -19,7 +23,11 @@ namespace UnityEngine.UI.Extensions
|
|||
rectTransform = btnObj.GetComponent<RectTransform>();
|
||||
btnImg = btnObj.GetComponent<Image>();
|
||||
btn = btnObj.GetComponent<Button>();
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
txt = rectTransform.Find("Text").GetComponent<TMPro.TMP_Text>();
|
||||
#else
|
||||
txt = rectTransform.Find("Text").GetComponent<Text>();
|
||||
#endif
|
||||
img = rectTransform.Find("Image").GetComponent<Image>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
///Sourced from - http://forum.unity3d.com/threads/receive-onclick-event-and-pass-it-on-to-lower-ui-elements.293642/
|
||||
|
||||
using System;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
|
@ -76,9 +77,9 @@ namespace UnityEngine.UI.Extensions
|
|||
set { _id = value; }
|
||||
}
|
||||
|
||||
public Action OnSelect = null; //action to be called when this item is selected
|
||||
public UnityAction OnSelect = null; //action to be called when this item is selected
|
||||
|
||||
internal Action OnUpdate = null; //action to be called when something changes.
|
||||
internal UnityAction OnUpdate = null; //action to be called when something changes.
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for Drop Down List panelItems
|
||||
|
@ -87,8 +88,8 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <param name="val">ID of the item </param>
|
||||
/// <param name="image"></param>
|
||||
/// <param name="disabled">Should the item start disabled</param>
|
||||
/// <param name="onSelect">Action to be called when this item is selected</param>
|
||||
public DropDownListItem(string caption = "", string inId = "", Sprite image = null, bool disabled = false, Action onSelect = null)
|
||||
/// <param name="onSelect">UnityAction to be called when this item is selected</param>
|
||||
public DropDownListItem(string caption = "", string inId = "", Sprite image = null, bool disabled = false, UnityAction onSelect = null)
|
||||
{
|
||||
_caption = caption;
|
||||
_image = image;
|
||||
|
|
|
@ -7,15 +7,14 @@ using UnityEngine.EventSystems;
|
|||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[AddComponentMenu("UI/Extensions/Cooldown Button")]
|
||||
public class CooldownButton : MonoBehaviour, IPointerDownHandler
|
||||
public class CooldownButton : MonoBehaviour, IPointerDownHandler, ISubmitHandler
|
||||
{
|
||||
#region Sub-Classes
|
||||
[System.Serializable]
|
||||
public class CooldownButtonEvent : UnityEvent<PointerEventData.InputButton> { }
|
||||
public class CooldownButtonEvent : UnityEvent<GameObject> { }
|
||||
#endregion
|
||||
|
||||
#region Private variables
|
||||
|
||||
[SerializeField]
|
||||
private float cooldownTimeout;
|
||||
[SerializeField]
|
||||
|
@ -33,7 +32,7 @@ namespace UnityEngine.UI.Extensions
|
|||
[SerializeField][ReadOnly]
|
||||
private int cooldownPercentComplete;
|
||||
|
||||
PointerEventData buttonSource;
|
||||
BaseEventData buttonSource;
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
@ -116,7 +115,6 @@ namespace UnityEngine.UI.Extensions
|
|||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Pause Cooldown without resetting values, allows Restarting of cooldown
|
||||
/// </summary>
|
||||
|
@ -144,9 +142,9 @@ namespace UnityEngine.UI.Extensions
|
|||
/// </summary>
|
||||
public void StartCooldown()
|
||||
{
|
||||
PointerEventData emptySource = new PointerEventData(EventSystem.current);
|
||||
BaseEventData emptySource = new BaseEventData(EventSystem.current);
|
||||
buttonSource = emptySource;
|
||||
OnCooldownStart.Invoke(emptySource.button);
|
||||
OnCooldownStart.Invoke(emptySource.selectedObject);
|
||||
cooldownTimeRemaining = cooldownTimeout;
|
||||
CooldownActive = cooldownInEffect = true;
|
||||
}
|
||||
|
@ -161,7 +159,7 @@ namespace UnityEngine.UI.Extensions
|
|||
cooldownPercentRemaining = 0;
|
||||
cooldownPercentComplete = 100;
|
||||
cooldownActive = cooldownInEffect = false;
|
||||
if (OnCoolDownFinish != null) OnCoolDownFinish.Invoke(buttonSource.button);
|
||||
OnCoolDownFinish?.Invoke(buttonSource.selectedObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -171,27 +169,38 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
cooldownActive = cooldownInEffect = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IPointerDownHandler
|
||||
|
||||
void IPointerDownHandler.OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
HandleButtonClick(eventData);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ISubmitHandler
|
||||
public void OnSubmit(BaseEventData eventData)
|
||||
{
|
||||
HandleButtonClick(eventData);
|
||||
}
|
||||
#endregion ISubmitHandler
|
||||
|
||||
#region Private Methods
|
||||
public void HandleButtonClick(BaseEventData eventData)
|
||||
{
|
||||
buttonSource = eventData;
|
||||
|
||||
if (CooldownInEffect)
|
||||
{
|
||||
if (OnButtonClickDuringCooldown != null) OnButtonClickDuringCooldown.Invoke(eventData.button);
|
||||
OnButtonClickDuringCooldown?.Invoke(buttonSource.selectedObject);
|
||||
}
|
||||
if (!CooldownInEffect)
|
||||
{
|
||||
if(OnCooldownStart != null) OnCooldownStart.Invoke(eventData.button);
|
||||
OnCooldownStart?.Invoke(buttonSource.selectedObject);
|
||||
cooldownTimeRemaining = cooldownTimeout;
|
||||
cooldownActive = cooldownInEffect = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
/// Credit Erdener Gonenc - @PixelEnvision
|
||||
/*USAGE: Simply use that instead of the regular ScrollRect */
|
||||
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[AddComponentMenu ("UI/Extensions/MultiTouchScrollRect")]
|
||||
|
|
|
@ -6,7 +6,6 @@ using UnityEngine.Events;
|
|||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
|
||||
[RequireComponent(typeof(RectTransform)), DisallowMultipleComponent]
|
||||
[AddComponentMenu("UI/Extensions/Re-orderable list")]
|
||||
public class ReorderableList : MonoBehaviour
|
||||
|
@ -33,9 +32,9 @@ namespace UnityEngine.UI.Extensions
|
|||
[Tooltip("Should items being dragged over this list have their sizes equalized?")]
|
||||
public bool EqualizeSizesOnDrag = false;
|
||||
|
||||
[Tooltip("Maximum number of items this container can hold")]
|
||||
public int maxItems = int.MaxValue;
|
||||
|
||||
|
||||
[Header("UI Re-orderable Events")]
|
||||
public ReorderableListHandler OnElementDropped = new ReorderableListHandler();
|
||||
public ReorderableListHandler OnElementGrabbed = new ReorderableListHandler();
|
||||
|
@ -62,7 +61,7 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
Canvas GetCanvas()
|
||||
public Canvas GetCanvas()
|
||||
{
|
||||
Transform t = transform;
|
||||
Canvas canvas = null;
|
||||
|
@ -73,8 +72,7 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
while (canvas == null && lvl < lvlLimit)
|
||||
{
|
||||
canvas = t.gameObject.GetComponent<Canvas>();
|
||||
if (canvas == null)
|
||||
if (!t.gameObject.TryGetComponent<Canvas>(out canvas))
|
||||
{
|
||||
t = t.parent;
|
||||
}
|
||||
|
@ -95,7 +93,6 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
private void Start()
|
||||
{
|
||||
|
||||
if (ContentLayout == null)
|
||||
{
|
||||
Debug.LogError("You need to have a child LayoutGroup content set for the list: " + name, gameObject);
|
||||
|
@ -114,7 +111,6 @@ namespace UnityEngine.UI.Extensions
|
|||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
#region Nested type: ReorderableListEventStruct
|
||||
|
||||
[Serializable]
|
||||
|
@ -136,13 +132,10 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Nested type: ReorderableListHandler
|
||||
|
||||
[Serializable]
|
||||
public class ReorderableListHandler : UnityEvent<ReorderableListEventStruct>
|
||||
{
|
||||
}
|
||||
public class ReorderableListHandler : UnityEvent<ReorderableListEventStruct> { }
|
||||
|
||||
public void TestReOrderableListTarget(ReorderableListEventStruct item)
|
||||
{
|
||||
|
|
|
@ -21,7 +21,6 @@ namespace UnityEngine.UI.Extensions
|
|||
if(_rect)StartCoroutine(RefreshChildren());
|
||||
}
|
||||
|
||||
|
||||
public void OnTransformChildrenChanged()
|
||||
{
|
||||
if(this.isActiveAndEnabled)StartCoroutine(RefreshChildren());
|
||||
|
|
|
@ -5,7 +5,11 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
public class ReorderableListDebug : MonoBehaviour
|
||||
{
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
public TMPro.TMP_Text DebugLabel;
|
||||
#else
|
||||
public Text DebugLabel;
|
||||
#endif
|
||||
|
||||
void Awake()
|
||||
{
|
||||
|
|
|
@ -8,31 +8,29 @@ using UnityEngine.EventSystems;
|
|||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
|
||||
[RequireComponent(typeof(RectTransform), typeof(LayoutElement))]
|
||||
public class ReorderableListElement : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
|
||||
{
|
||||
[Tooltip("Can this element be dragged?")]
|
||||
[SerializeField]
|
||||
private bool IsGrabbable = true;
|
||||
private bool isGrabbable = true;
|
||||
|
||||
[Tooltip("Can this element be transfered to another list")]
|
||||
[Tooltip("Can this element be dropped in another container?")]
|
||||
[SerializeField]
|
||||
private bool _isTransferable = true;
|
||||
private bool isTransferable = true;
|
||||
|
||||
[Tooltip("Can this element be dropped in space?")]
|
||||
[SerializeField]
|
||||
private bool isDroppableInSpace = false;
|
||||
|
||||
|
||||
public bool IsTransferable
|
||||
{
|
||||
get { return _isTransferable; }
|
||||
get { return isTransferable; }
|
||||
set
|
||||
{
|
||||
_canvasGroup = gameObject.GetOrAddComponent<CanvasGroup>();
|
||||
_canvasGroup.blocksRaycasts = value;
|
||||
_isTransferable = value;
|
||||
isTransferable = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +59,6 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
|
||||
#region IBeginDragHandler Members
|
||||
|
||||
public void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!_canvasGroup) { _canvasGroup = gameObject.GetOrAddComponent<CanvasGroup>(); }
|
||||
|
@ -71,7 +68,7 @@ namespace UnityEngine.UI.Extensions
|
|||
return;
|
||||
|
||||
//Can't drag, return...
|
||||
if (!_reorderableList.IsDraggable || !this.IsGrabbable)
|
||||
if (!_reorderableList.IsDraggable || !this.isGrabbable)
|
||||
{
|
||||
_draggingObject = null;
|
||||
return;
|
||||
|
@ -142,12 +139,9 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
_isDragging = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region IDragHandler Members
|
||||
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!_isDragging)
|
||||
|
@ -179,7 +173,6 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
//If nothing found or the list is not dropable, put the fake element outside
|
||||
if (_currentReorderableListRaycasted == null || _currentReorderableListRaycasted.IsDropable == false
|
||||
// || (_oldReorderableListRaycasted != _reorderableList && !IsTransferable)
|
||||
|| ((_fakeElement.parent == _currentReorderableListRaycasted.Content
|
||||
? _currentReorderableListRaycasted.Content.childCount - 1
|
||||
: _currentReorderableListRaycasted.Content.childCount) >= _currentReorderableListRaycasted.maxItems && !_currentReorderableListRaycasted.IsDisplacable)
|
||||
|
@ -194,7 +187,7 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
//Else find the best position on the list and put fake element on the right index
|
||||
else
|
||||
else if (_currentReorderableListRaycasted == _reorderableList || IsTransferable)
|
||||
{
|
||||
if (_currentReorderableListRaycasted.Content.childCount < _currentReorderableListRaycasted.maxItems && _fakeElement.parent != _currentReorderableListRaycasted.Content)
|
||||
{
|
||||
|
@ -245,12 +238,9 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Displacement
|
||||
|
||||
private void displaceElement(int targetIndex, Transform displaced)
|
||||
{
|
||||
_displacedFromIndex = targetIndex;
|
||||
|
@ -343,7 +333,6 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
}
|
||||
|
||||
|
||||
public void finishDisplacingElement()
|
||||
{
|
||||
if (_displacedObject.parent == null)
|
||||
|
@ -355,12 +344,9 @@ namespace UnityEngine.UI.Extensions
|
|||
_displacedObject = null;
|
||||
_displacedObjectLE = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region IEndDragHandler Members
|
||||
|
||||
public void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
_isDragging = false;
|
||||
|
@ -381,16 +367,19 @@ namespace UnityEngine.UI.Extensions
|
|||
ToList = _currentReorderableListRaycasted,
|
||||
ToIndex = _fakeElement.GetSiblingIndex()
|
||||
};
|
||||
|
||||
//Send OnelementDropped Event
|
||||
if (_reorderableList && _reorderableList.OnElementDropped != null)
|
||||
{
|
||||
_reorderableList.OnElementDropped.Invoke(args);
|
||||
}
|
||||
if (!isValid)
|
||||
|
||||
if (!isValid || (!IsTransferable && _currentReorderableListRaycasted != _reorderableList))
|
||||
{
|
||||
CancelDrag();
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshSizes();
|
||||
_draggingObject.SetParent(_currentReorderableListRaycasted.Content, false);
|
||||
_draggingObject.rotation = _currentReorderableListRaycasted.transform.rotation;
|
||||
|
@ -470,11 +459,9 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
_canvasGroup.blocksRaycasts = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
void CancelDrag()
|
||||
private void CancelDrag()
|
||||
{
|
||||
_isDragging = false;
|
||||
//If it's a clone, delete it
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
/// Credit David Gileadi
|
||||
/// Sourced from - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/pull-requests/12
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
|
@ -205,7 +203,11 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
void ChangeTextColor(Color targetColor)
|
||||
{
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
var text = GetComponentInChildren<TMPro.TMP_Text>();
|
||||
#else
|
||||
var text = GetComponentInChildren<Text>();
|
||||
#endif
|
||||
if (!text)
|
||||
return;
|
||||
|
||||
|
|
|
@ -40,13 +40,21 @@ namespace UnityEngine.UI.Extensions
|
|||
//We want the test object to be either a UI element, a 2D element or a 3D element, so we'll get the appropriate components
|
||||
SpriteRenderer spriteRenderer;
|
||||
Image image;
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
TMPro.TMP_Text text;
|
||||
#else
|
||||
Text text;
|
||||
#endif
|
||||
|
||||
void Start()
|
||||
{
|
||||
spriteRenderer = transform.GetComponent<SpriteRenderer>();
|
||||
image = transform.GetComponent<Image>();
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
text = transform.GetComponent<TMPro.TMP_Text>();
|
||||
#else
|
||||
text = transform.GetComponent<Text>();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Update()
|
||||
|
@ -86,8 +94,6 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
GetComponent<UnityEngine.Renderer>().material.color = color;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8045f74f29fafa944b1539a3a1c6dc5c
|
||||
guid: d7bdc7e70331fe24aba2c9549f84c657
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
|
@ -8,7 +8,7 @@ using UnityEngine.EventSystems;
|
|||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[AddComponentMenu("UI/Extensions/BoxSlider")]
|
||||
[AddComponentMenu("UI/Extensions/Sliders/BoxSlider")]
|
||||
public class BoxSlider : Selectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement
|
||||
{
|
||||
public enum Direction
|
|
@ -0,0 +1,347 @@
|
|||
///Credit brogan89
|
||||
///Sourced from - https://github.com/brogan89/MinMaxSlider
|
||||
|
||||
using System;
|
||||
using TMPro;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[AddComponentMenu("UI/Extensions/Sliders/MinMax Slider")]
|
||||
public class MinMaxSlider : Selectable, IBeginDragHandler, IDragHandler, IEndDragHandler
|
||||
{
|
||||
private enum DragState
|
||||
{
|
||||
Both,
|
||||
Min,
|
||||
Max
|
||||
}
|
||||
|
||||
[Header("UI Controls")]
|
||||
[SerializeField] private Camera customCamera = null;
|
||||
[SerializeField] private RectTransform sliderBounds = null;
|
||||
[SerializeField] private RectTransform minHandle = null;
|
||||
[SerializeField] private RectTransform maxHandle = null;
|
||||
[SerializeField] private RectTransform middleGraphic = null;
|
||||
|
||||
// text components (optional)
|
||||
[Header("Display Text (Optional)")]
|
||||
[SerializeField] private TextMeshProUGUI minText = null;
|
||||
[SerializeField] private TextMeshProUGUI maxText = null;
|
||||
[SerializeField] private string textFormat = "0";
|
||||
|
||||
// values
|
||||
[Header("Limits")]
|
||||
[SerializeField] private float minLimit = 0;
|
||||
[SerializeField] private float maxLimit = 100;
|
||||
|
||||
[Header("Values")]
|
||||
public bool wholeNumbers;
|
||||
[SerializeField] private float minValue = 25;
|
||||
[SerializeField] private float maxValue = 75;
|
||||
|
||||
public MinMaxValues Values => new MinMaxValues(minValue, maxValue, minLimit, maxLimit);
|
||||
|
||||
public RectTransform SliderBounds { get => sliderBounds; set => sliderBounds = value; }
|
||||
public RectTransform MinHandle { get => minHandle; set => minHandle = value; }
|
||||
public RectTransform MaxHandle { get => maxHandle; set => maxHandle = value; }
|
||||
public RectTransform MiddleGraphic { get => middleGraphic; set => middleGraphic = value; }
|
||||
public TextMeshProUGUI MinText { get => minText; set => minText = value; }
|
||||
public TextMeshProUGUI MaxText { get => maxText; set => maxText = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Event invoked when either slider value has changed
|
||||
/// <para></para>
|
||||
/// T0 = min, T1 = max
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class SliderEvent : UnityEvent<float, float> { }
|
||||
|
||||
public SliderEvent onValueChanged = new SliderEvent();
|
||||
|
||||
private Vector2 dragStartPosition;
|
||||
private float dragStartMinValue01;
|
||||
private float dragStartMaxValue01;
|
||||
private DragState dragState;
|
||||
private bool passDragEvents; // this allows drag events to be passed through to scrollers
|
||||
|
||||
private Camera mainCamera;
|
||||
private Canvas parentCanvas;
|
||||
private bool isOverlayCanvas;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
if (!sliderBounds)
|
||||
{
|
||||
sliderBounds = transform as RectTransform;
|
||||
}
|
||||
|
||||
parentCanvas = GetComponentInParent<Canvas>();
|
||||
isOverlayCanvas = parentCanvas.renderMode == RenderMode.ScreenSpaceOverlay;
|
||||
mainCamera = customCamera != null ? customCamera : Camera.main;
|
||||
}
|
||||
|
||||
public void SetLimits(float minLimit, float maxLimit)
|
||||
{
|
||||
this.minLimit = wholeNumbers ? Mathf.RoundToInt(minLimit) : minLimit;
|
||||
this.maxLimit = wholeNumbers ? Mathf.RoundToInt(maxLimit) : maxLimit;
|
||||
}
|
||||
|
||||
public void SetValues(MinMaxValues values, bool notify = true)
|
||||
{
|
||||
SetValues(values.minValue, values.maxValue, values.minLimit, values.maxLimit, notify);
|
||||
}
|
||||
|
||||
public void SetValues(float minValue, float maxValue, bool notify = true)
|
||||
{
|
||||
SetValues(minValue, maxValue, minLimit, maxLimit, notify);
|
||||
}
|
||||
|
||||
public void SetValues(float minValue, float maxValue, float minLimit, float maxLimit, bool notify = true)
|
||||
{
|
||||
this.minValue = wholeNumbers ? Mathf.RoundToInt(minValue) : minValue;
|
||||
this.maxValue = wholeNumbers ? Mathf.RoundToInt(maxValue) : maxValue;
|
||||
SetLimits(minLimit, maxLimit);
|
||||
|
||||
RefreshSliders();
|
||||
UpdateText();
|
||||
UpdateMiddleGraphic();
|
||||
|
||||
if (notify)
|
||||
{
|
||||
// event
|
||||
onValueChanged.Invoke(this.minValue, this.maxValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshSliders()
|
||||
{
|
||||
SetSliderAnchors();
|
||||
|
||||
float clampedMin = Mathf.Clamp(minValue, minLimit, maxLimit);
|
||||
SetMinHandleValue01(minHandle, GetPercentage(minLimit, maxLimit, clampedMin));
|
||||
|
||||
float clampedMax = Mathf.Clamp(maxValue, minLimit, maxLimit);
|
||||
SetMaxHandleValue01(maxHandle, GetPercentage(minLimit, maxLimit, clampedMax));
|
||||
}
|
||||
|
||||
private void SetSliderAnchors()
|
||||
{
|
||||
minHandle.anchorMin = new Vector2(0, 0.5f);
|
||||
minHandle.anchorMax = new Vector2(0, 0.5f);
|
||||
minHandle.pivot = new Vector2(0.5f, 0.5f);
|
||||
|
||||
maxHandle.anchorMin = new Vector2(1, 0.5f);
|
||||
maxHandle.anchorMax = new Vector2(1, 0.5f);
|
||||
maxHandle.pivot = new Vector2(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
private void UpdateText()
|
||||
{
|
||||
if (minText)
|
||||
{
|
||||
minText.SetText(minValue.ToString(textFormat));
|
||||
}
|
||||
|
||||
if (maxText)
|
||||
{
|
||||
maxText.SetText(maxValue.ToString(textFormat));
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateMiddleGraphic()
|
||||
{
|
||||
if (!middleGraphic) return;
|
||||
|
||||
middleGraphic.anchorMin = Vector2.zero;
|
||||
middleGraphic.anchorMax = Vector2.one;
|
||||
middleGraphic.offsetMin = new Vector2(minHandle.anchoredPosition.x, 0);
|
||||
middleGraphic.offsetMax = new Vector2(maxHandle.anchoredPosition.x, 0);
|
||||
}
|
||||
|
||||
#region IDragHandler
|
||||
public void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
passDragEvents = Math.Abs(eventData.delta.x) < Math.Abs(eventData.delta.y);
|
||||
|
||||
if (passDragEvents)
|
||||
{
|
||||
PassDragEvents<IBeginDragHandler>(x => x.OnBeginDrag(eventData));
|
||||
}
|
||||
else
|
||||
{
|
||||
Camera uiCamera = isOverlayCanvas ? null : mainCamera;
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(sliderBounds, eventData.position, uiCamera, out dragStartPosition);
|
||||
|
||||
float dragStartValue = GetValueOfPointInSliderBounds01(dragStartPosition);
|
||||
dragStartMinValue01 = GetMinHandleValue01(minHandle);
|
||||
dragStartMaxValue01 = GetMaxHandleValue01(maxHandle);
|
||||
|
||||
// set drag state
|
||||
if (dragStartValue < dragStartMinValue01 || RectTransformUtility.RectangleContainsScreenPoint(minHandle, eventData.position, uiCamera))
|
||||
{
|
||||
dragState = DragState.Min;
|
||||
minHandle.SetAsLastSibling();
|
||||
}
|
||||
else if (dragStartValue > dragStartMaxValue01 || RectTransformUtility.RectangleContainsScreenPoint(maxHandle, eventData.position, uiCamera))
|
||||
{
|
||||
dragState = DragState.Max;
|
||||
maxHandle.SetAsLastSibling();
|
||||
}
|
||||
else
|
||||
{
|
||||
dragState = DragState.Both;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
if (passDragEvents)
|
||||
{
|
||||
PassDragEvents<IDragHandler>(x => x.OnDrag(eventData));
|
||||
}
|
||||
else if (minHandle && maxHandle)
|
||||
{
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(sliderBounds, eventData.position, isOverlayCanvas ? null : mainCamera, out Vector2 clickPosition);
|
||||
|
||||
SetSliderAnchors();
|
||||
|
||||
if (dragState == DragState.Min || dragState == DragState.Max)
|
||||
{
|
||||
float dragPosition01 = GetValueOfPointInSliderBounds01(clickPosition);
|
||||
float minHandleValue = GetMinHandleValue01(minHandle);
|
||||
float maxHandleValue = GetMaxHandleValue01(maxHandle);
|
||||
|
||||
if (dragState == DragState.Min)
|
||||
SetMinHandleValue01(minHandle, Mathf.Clamp(dragPosition01, 0, maxHandleValue));
|
||||
else if (dragState == DragState.Max)
|
||||
SetMaxHandleValue01(maxHandle, Mathf.Clamp(dragPosition01, minHandleValue, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
float distancePercent = (clickPosition.x - dragStartPosition.x) / sliderBounds.rect.width;
|
||||
SetMinHandleValue01(minHandle, dragStartMinValue01 + distancePercent);
|
||||
SetMaxHandleValue01(maxHandle, dragStartMaxValue01 + distancePercent);
|
||||
}
|
||||
|
||||
// set values
|
||||
float min = Mathf.Lerp(minLimit, maxLimit, GetMinHandleValue01(minHandle));
|
||||
float max = Mathf.Lerp(minLimit, maxLimit, GetMaxHandleValue01(maxHandle));
|
||||
SetValues(min, max);
|
||||
|
||||
UpdateText();
|
||||
UpdateMiddleGraphic();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
if (passDragEvents)
|
||||
{
|
||||
PassDragEvents<IEndDragHandler>(x => x.OnEndDrag(eventData));
|
||||
}
|
||||
else
|
||||
{
|
||||
float minHandleValue = GetMinHandleValue01(minHandle);
|
||||
float maxHandleValue = GetMaxHandleValue01(maxHandle);
|
||||
|
||||
// this safe guards a possible situation where the slides can get stuck
|
||||
if (Math.Abs(minHandleValue) < MinMaxValues.FLOAT_TOL && Math.Abs(maxHandleValue) < MinMaxValues.FLOAT_TOL)
|
||||
{
|
||||
maxHandle.SetAsLastSibling();
|
||||
}
|
||||
else if (Math.Abs(minHandleValue - 1) < MinMaxValues.FLOAT_TOL && Math.Abs(maxHandleValue - 1) < MinMaxValues.FLOAT_TOL)
|
||||
{
|
||||
minHandle.SetAsLastSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion IDragHandler
|
||||
|
||||
private void PassDragEvents<T>(Action<T> callback) where T : IEventSystemHandler
|
||||
{
|
||||
Transform parent = transform.parent;
|
||||
|
||||
while (parent != null)
|
||||
{
|
||||
foreach (var component in parent.GetComponents<Component>())
|
||||
{
|
||||
if (!(component is T)) continue;
|
||||
|
||||
callback.Invoke((T)(IEventSystemHandler)component);
|
||||
return;
|
||||
}
|
||||
|
||||
parent = parent.parent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets position of max handle RectTransform
|
||||
/// </summary>
|
||||
/// <param name="handle"></param>
|
||||
/// <param name="value01">Normalized handle position</param>
|
||||
private void SetMaxHandleValue01(RectTransform handle, float value01)
|
||||
{
|
||||
handle.anchoredPosition = new Vector2(value01 * sliderBounds.rect.width - sliderBounds.rect.width + sliderBounds.offsetMax.x, handle.anchoredPosition.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets position of min handle RectTransform
|
||||
/// </summary>
|
||||
/// <param name="handle"></param>
|
||||
/// <param name="value01">Normalized handle position</param>
|
||||
private void SetMinHandleValue01(RectTransform handle, float value01)
|
||||
{
|
||||
handle.anchoredPosition = new Vector2(value01 * sliderBounds.rect.width + sliderBounds.offsetMin.x, handle.anchoredPosition.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns normalized position of max handle RectTransform
|
||||
/// </summary>
|
||||
/// <param name="handle"></param>
|
||||
/// <returns>Normalized position of max handle RectTransform</returns>
|
||||
private float GetMaxHandleValue01(RectTransform handle)
|
||||
{
|
||||
return 1 + (handle.anchoredPosition.x - sliderBounds.offsetMax.x) / sliderBounds.rect.width;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns normalized position of min handle RectTransform
|
||||
/// </summary>
|
||||
/// <param name="handle"></param>
|
||||
/// <returns>Normalized position of min handle RectTransform</returns>
|
||||
private float GetMinHandleValue01(RectTransform handle)
|
||||
{
|
||||
return (handle.anchoredPosition.x - sliderBounds.offsetMin.x) / sliderBounds.rect.width;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns normalized position of a point in a slider bounds rectangle
|
||||
/// </summary>
|
||||
/// <param name="position"></param>
|
||||
/// <returns>Normalized position of a point in a slider bounds rectangle</returns>
|
||||
private float GetValueOfPointInSliderBounds01(Vector2 position)
|
||||
{
|
||||
var width = sliderBounds.rect.width;
|
||||
return Mathf.Clamp((position.x + width / 2) / width, 0, 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns percentage of input based on min and max values
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
private static float GetPercentage(float min, float max, float input)
|
||||
{
|
||||
return (input - min) / (max - min);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b9f9954231c8bab419504a7ac5ff133e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -8,8 +8,8 @@ using UnityEngine.EventSystems;
|
|||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[AddComponentMenu("UI/Extensions/Radial Slider")]
|
||||
[RequireComponent(typeof(Image))]
|
||||
[AddComponentMenu("UI/Extensions/Sliders/Radial Slider")]
|
||||
public class RadialSlider : MonoBehaviour, IPointerEnterHandler, IPointerDownHandler, IPointerUpHandler, IDragHandler
|
||||
{
|
||||
private bool isPointerDown, isPointerReleased, lerpInProgress;
|
|
@ -9,50 +9,129 @@ using UnityEngine.EventSystems;
|
|||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[AddComponentMenu("UI/Extensions/Range Slider", 34)]
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[AddComponentMenu("UI/Extensions/Sliders/Range Slider", 34)]
|
||||
public class RangeSlider : Selectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement
|
||||
{
|
||||
public enum Direction
|
||||
{
|
||||
Horizontal,
|
||||
Vertical
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class RangeSliderEvent : UnityEvent<float, float> { }
|
||||
public class RangeSliderEvent : UnityEvent<float, float>
|
||||
{
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform m_FillRect;
|
||||
[SerializeField] private RectTransform m_FillRect;
|
||||
|
||||
public RectTransform FillRect { get { return m_FillRect; } set { if (SetClass(ref m_FillRect, value)) { UpdateCachedReferences(); UpdateVisuals(); } } }
|
||||
public RectTransform FillRect
|
||||
{
|
||||
get { return m_FillRect; }
|
||||
set
|
||||
{
|
||||
if (SetClass(ref m_FillRect, value))
|
||||
{
|
||||
UpdateCachedReferences();
|
||||
UpdateVisuals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform m_LowHandleRect;
|
||||
[SerializeField] private RectTransform m_LowHandleRect;
|
||||
|
||||
public RectTransform LowHandleRect { get { return m_LowHandleRect; } set { if (SetClass(ref m_LowHandleRect, value)) { UpdateCachedReferences(); UpdateVisuals(); } } }
|
||||
public RectTransform LowHandleRect
|
||||
{
|
||||
get { return m_LowHandleRect; }
|
||||
set
|
||||
{
|
||||
if (SetClass(ref m_LowHandleRect, value))
|
||||
{
|
||||
UpdateCachedReferences();
|
||||
UpdateVisuals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform m_HighHandleRect;
|
||||
[SerializeField] private RectTransform m_HighHandleRect;
|
||||
|
||||
public RectTransform HighHandleRect { get { return m_HighHandleRect; } set { if (SetClass(ref m_HighHandleRect, value)) { UpdateCachedReferences(); UpdateVisuals(); } } }
|
||||
public RectTransform HighHandleRect
|
||||
{
|
||||
get { return m_HighHandleRect; }
|
||||
set
|
||||
{
|
||||
if (SetClass(ref m_HighHandleRect, value))
|
||||
{
|
||||
UpdateCachedReferences();
|
||||
UpdateVisuals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Space]
|
||||
[Space] [SerializeField] private Direction m_Direction = Direction.Horizontal;
|
||||
|
||||
[SerializeField]
|
||||
private float m_MinValue = 0;
|
||||
public Direction direction
|
||||
{
|
||||
get { return m_Direction; }
|
||||
set
|
||||
{
|
||||
if (SetPropertyUtility.SetStruct(ref m_Direction, value)) UpdateVisuals();
|
||||
}
|
||||
}
|
||||
|
||||
public float MinValue { get { return m_MinValue; } set { if (SetStruct(ref m_MinValue, value)) { SetLow(m_LowValue); SetHigh(m_HighValue); UpdateVisuals(); } } }
|
||||
[SerializeField] private float m_MinValue = 0;
|
||||
|
||||
public float MinValue
|
||||
{
|
||||
get { return m_MinValue; }
|
||||
set
|
||||
{
|
||||
if (SetStruct(ref m_MinValue, value))
|
||||
{
|
||||
SetLow(m_LowValue);
|
||||
SetHigh(m_HighValue);
|
||||
UpdateVisuals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[SerializeField]
|
||||
private float m_MaxValue = 1;
|
||||
[SerializeField] private float m_MaxValue = 1;
|
||||
|
||||
public float MaxValue { get { return m_MaxValue; } set { if (SetStruct(ref m_MaxValue, value)) { SetLow(m_LowValue); SetHigh(m_HighValue); UpdateVisuals(); } } }
|
||||
public float MaxValue
|
||||
{
|
||||
get { return m_MaxValue; }
|
||||
set
|
||||
{
|
||||
if (SetStruct(ref m_MaxValue, value))
|
||||
{
|
||||
SetLow(m_LowValue);
|
||||
SetHigh(m_HighValue);
|
||||
UpdateVisuals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_WholeNumbers = false;
|
||||
[SerializeField] private bool m_WholeNumbers = false;
|
||||
|
||||
public bool WholeNumbers { get { return m_WholeNumbers; } set { if (SetStruct(ref m_WholeNumbers, value)) { SetLow(m_LowValue); SetHigh(m_HighValue); UpdateVisuals(); } } }
|
||||
public bool WholeNumbers
|
||||
{
|
||||
get { return m_WholeNumbers; }
|
||||
set
|
||||
{
|
||||
if (SetStruct(ref m_WholeNumbers, value))
|
||||
{
|
||||
SetLow(m_LowValue);
|
||||
SetHigh(m_HighValue);
|
||||
UpdateVisuals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField] private float m_LowValue;
|
||||
|
||||
[SerializeField]
|
||||
private float m_LowValue;
|
||||
public virtual float LowValue
|
||||
{
|
||||
get
|
||||
|
@ -78,6 +157,7 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Mathf.InverseLerp(MinValue, MaxValue, LowValue);
|
||||
}
|
||||
set
|
||||
|
@ -87,8 +167,8 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
|
||||
|
||||
[SerializeField]
|
||||
private float m_HighValue;
|
||||
[SerializeField] private float m_HighValue;
|
||||
|
||||
public virtual float HighValue
|
||||
{
|
||||
get
|
||||
|
@ -114,6 +194,7 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Mathf.InverseLerp(MinValue, MaxValue, HighValue);
|
||||
}
|
||||
set
|
||||
|
@ -132,10 +213,7 @@ namespace UnityEngine.UI.Extensions
|
|||
SetHigh(high, false);
|
||||
}
|
||||
|
||||
[Space]
|
||||
|
||||
[SerializeField]
|
||||
private RangeSliderEvent m_OnValueChanged = new RangeSliderEvent();
|
||||
[Space] [SerializeField] private RangeSliderEvent m_OnValueChanged = new RangeSliderEvent();
|
||||
|
||||
public RangeSliderEvent OnValueChanged { get { return m_OnValueChanged; } set { m_OnValueChanged = value; } }
|
||||
|
||||
|
@ -162,10 +240,8 @@ namespace UnityEngine.UI.Extensions
|
|||
private Transform m_LowHandleTransform;
|
||||
private RectTransform m_LowHandleContainerRect;
|
||||
|
||||
// The offset from handle position to mouse down position
|
||||
private Vector2 m_LowOffset = Vector2.zero;
|
||||
// The offset from handle position to mouse down position
|
||||
private Vector2 m_HighOffset = Vector2.zero;
|
||||
// The offset from interacted component position to mouse down position
|
||||
private Vector2 m_Offset = Vector2.zero;
|
||||
|
||||
private DrivenRectTransformTracker m_Tracker;
|
||||
|
||||
|
@ -176,7 +252,8 @@ namespace UnityEngine.UI.Extensions
|
|||
float StepSize { get { return WholeNumbers ? 1 : (MaxValue - MinValue) * 0.1f; } }
|
||||
|
||||
protected RangeSlider()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
|
@ -219,13 +296,15 @@ namespace UnityEngine.UI.Extensions
|
|||
/// See ICanvasElement.LayoutComplete
|
||||
/// </summary>
|
||||
public virtual void LayoutComplete()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See ICanvasElement.GraphicUpdateComplete
|
||||
/// </summary>
|
||||
public virtual void GraphicUpdateComplete()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
public static bool SetClass<T>(ref T currentValue, T newValue) where T : class
|
||||
{
|
||||
|
@ -388,6 +467,13 @@ namespace UnityEngine.UI.Extensions
|
|||
UpdateVisuals();
|
||||
}
|
||||
|
||||
enum Axis
|
||||
{
|
||||
Horizontal = 0,
|
||||
Vertical = 1
|
||||
}
|
||||
|
||||
Axis axis { get { return m_Direction == Direction.Horizontal ? Axis.Horizontal : Axis.Vertical; } }
|
||||
|
||||
// Force-update the slider. Useful if you've changed the properties and want it to update visually.
|
||||
private void UpdateVisuals()
|
||||
|
@ -407,8 +493,8 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
//this is where some new magic must happen. Slider just uses a filled image
|
||||
//and changes the % of fill. We must move the image anchors to be between the two handles.
|
||||
anchorMin[0] = NormalizedLowValue;
|
||||
anchorMax[0] = NormalizedHighValue;
|
||||
anchorMin[(int)axis] = NormalizedLowValue;
|
||||
anchorMax[(int)axis] = NormalizedHighValue;
|
||||
|
||||
m_FillRect.anchorMin = anchorMin;
|
||||
m_FillRect.anchorMax = anchorMax;
|
||||
|
@ -419,7 +505,7 @@ namespace UnityEngine.UI.Extensions
|
|||
m_Tracker.Add(this, m_LowHandleRect, DrivenTransformProperties.Anchors);
|
||||
Vector2 anchorMin = Vector2.zero;
|
||||
Vector2 anchorMax = Vector2.one;
|
||||
anchorMin[0] = anchorMax[0] = NormalizedLowValue;
|
||||
anchorMin[(int)axis] = anchorMax[(int)axis] = NormalizedLowValue;
|
||||
m_LowHandleRect.anchorMin = anchorMin;
|
||||
m_LowHandleRect.anchorMax = anchorMax;
|
||||
}
|
||||
|
@ -429,7 +515,7 @@ namespace UnityEngine.UI.Extensions
|
|||
m_Tracker.Add(this, m_HighHandleRect, DrivenTransformProperties.Anchors);
|
||||
Vector2 anchorMin = Vector2.zero;
|
||||
Vector2 anchorMax = Vector2.one;
|
||||
anchorMin[0] = anchorMax[0] = NormalizedHighValue;
|
||||
anchorMin[(int)axis] = anchorMax[(int)axis] = NormalizedHighValue;
|
||||
m_HighHandleRect.anchorMin = anchorMin;
|
||||
m_HighHandleRect.anchorMax = anchorMax;
|
||||
}
|
||||
|
@ -446,10 +532,10 @@ namespace UnityEngine.UI.Extensions
|
|||
switch (interactionState)
|
||||
{
|
||||
case InteractionState.Low:
|
||||
NormalizedLowValue = CalculateDrag(eventData, cam, m_LowHandleContainerRect, m_LowOffset);
|
||||
NormalizedLowValue = CalculateDrag(eventData, cam, m_LowHandleContainerRect);
|
||||
break;
|
||||
case InteractionState.High:
|
||||
NormalizedHighValue = CalculateDrag(eventData, cam, m_HighHandleContainerRect, m_HighOffset);
|
||||
NormalizedHighValue = CalculateDrag(eventData, cam, m_HighHandleContainerRect);
|
||||
break;
|
||||
case InteractionState.Bar:
|
||||
//special case
|
||||
|
@ -460,35 +546,40 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
private float CalculateDrag(PointerEventData eventData, Camera cam, RectTransform containerRect, Vector2 offset)
|
||||
private float CalculateDrag(PointerEventData eventData, Camera cam, RectTransform containerRect)
|
||||
{
|
||||
RectTransform clickRect = containerRect ?? m_FillContainerRect;
|
||||
if (clickRect != null && clickRect.rect.size[0] > 0)
|
||||
if (clickRect != null && clickRect.rect.size[(int)axis] > 0)
|
||||
{
|
||||
Vector2 localCursor;
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam, out localCursor))
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam,
|
||||
out localCursor))
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
localCursor -= clickRect.rect.position;
|
||||
|
||||
float val = Mathf.Clamp01((localCursor - offset)[0] / clickRect.rect.size[0]);
|
||||
float val = Mathf.Clamp01((localCursor - m_Offset)[(int)axis] / clickRect.rect.size[(int)axis]);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void CalculateBarDrag(PointerEventData eventData, Camera cam)
|
||||
{
|
||||
RectTransform clickRect = m_FillContainerRect;
|
||||
if (clickRect != null && clickRect.rect.size[0] > 0)
|
||||
if (clickRect != null && clickRect.rect.size[(int)axis] > 0)
|
||||
{
|
||||
Vector2 localCursor;
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam, out localCursor))
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam,
|
||||
out localCursor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
localCursor -= clickRect.rect.position;
|
||||
|
||||
//now we need to get the delta drag on the bar
|
||||
|
@ -497,9 +588,9 @@ namespace UnityEngine.UI.Extensions
|
|||
if (NormalizedLowValue >= 0 && NormalizedHighValue <= 1)
|
||||
{
|
||||
//find the mid point on the current bar
|
||||
float mid = (NormalizedHighValue + NormalizedLowValue)/2;
|
||||
float mid = (NormalizedHighValue + NormalizedLowValue) / 2;
|
||||
//find where the new mid point should be
|
||||
float val = Mathf.Clamp01((localCursor)[0] / clickRect.rect.size[0]);
|
||||
float val = Mathf.Clamp01((localCursor - m_Offset)[(int)axis] / clickRect.rect.size[(int)axis]);
|
||||
//calculate the delta
|
||||
float delta = val - mid;
|
||||
//check the clamp range
|
||||
|
@ -529,52 +620,72 @@ namespace UnityEngine.UI.Extensions
|
|||
if (!MayDrag(eventData))
|
||||
return;
|
||||
|
||||
|
||||
//HANDLE DRAG EVENTS
|
||||
m_LowOffset = m_HighOffset = Vector2.zero;
|
||||
Vector2 localMousePos;
|
||||
if (m_HighHandleRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_HighHandleRect, eventData.position, eventData.enterEventCamera))
|
||||
m_Offset = Vector2.zero;
|
||||
if(m_LowHandleRect != null && LowValue == MaxValue && RectTransformUtility.RectangleContainsScreenPoint(m_LowHandleRect, eventData.position, eventData.enterEventCamera))
|
||||
{
|
||||
//dragging the high value handle
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_HighHandleRect, eventData.position, eventData.pressEventCamera, out localMousePos))
|
||||
{
|
||||
m_HighOffset = localMousePos;
|
||||
}
|
||||
interactionState = InteractionState.High;
|
||||
if (transition == Transition.ColorTint)
|
||||
{
|
||||
targetGraphic = m_HighHandleRect.GetComponent<Graphic>();
|
||||
}
|
||||
SetToMoveLowValueHandle(m_LowHandleRect, eventData);
|
||||
}
|
||||
else if (m_HighHandleRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_HighHandleRect, eventData.position, eventData.enterEventCamera))
|
||||
{
|
||||
SetToMoveHighValueHandle(m_HighHandleRect, eventData);
|
||||
}
|
||||
else if (m_LowHandleRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_LowHandleRect, eventData.position, eventData.enterEventCamera))
|
||||
{
|
||||
//dragging the low value handle
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_LowHandleRect, eventData.position, eventData.pressEventCamera, out localMousePos))
|
||||
SetToMoveLowValueHandle(m_LowHandleRect, eventData);
|
||||
}
|
||||
else if (m_FillRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_FillRect, eventData.position, eventData.enterEventCamera))
|
||||
{
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_FillRect, eventData.position, eventData.pressEventCamera, out var localMousePos))
|
||||
{
|
||||
m_LowOffset = localMousePos;
|
||||
m_Offset = localMousePos;
|
||||
}
|
||||
interactionState = InteractionState.Low;
|
||||
|
||||
interactionState = InteractionState.Bar;
|
||||
|
||||
|
||||
if (transition == Transition.ColorTint)
|
||||
{
|
||||
targetGraphic = m_LowHandleRect.GetComponent<Graphic>();
|
||||
targetGraphic = m_FillImage;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//outside the handles, move the entire slider along
|
||||
UpdateDrag(eventData, eventData.pressEventCamera);
|
||||
if (eventData.pointerCurrentRaycast.gameObject == m_FillRect.gameObject)
|
||||
{
|
||||
interactionState = InteractionState.Bar;
|
||||
}
|
||||
if (transition == Transition.ColorTint)
|
||||
{
|
||||
targetGraphic = m_FillImage;
|
||||
}
|
||||
}
|
||||
|
||||
base.OnPointerDown(eventData);
|
||||
}
|
||||
|
||||
private void SetToMoveLowValueHandle(RectTransform transform, PointerEventData eventData)
|
||||
{
|
||||
//dragging the low value handle
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(transform, eventData.position, eventData.pressEventCamera, out var localMousePos))
|
||||
{
|
||||
m_Offset = localMousePos;
|
||||
}
|
||||
interactionState = InteractionState.Low;
|
||||
if (transition == Transition.ColorTint)
|
||||
{
|
||||
targetGraphic = m_LowHandleRect.GetComponent<Graphic>();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetToMoveHighValueHandle(RectTransform transform, PointerEventData eventData)
|
||||
{
|
||||
//dragging the low value handle
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(transform, eventData.position, eventData.pressEventCamera, out var localMousePos))
|
||||
{
|
||||
m_Offset = localMousePos;
|
||||
}
|
||||
interactionState = InteractionState.High;
|
||||
if (transition == Transition.ColorTint)
|
||||
{
|
||||
targetGraphic = m_HighHandleRect.GetComponent<Graphic>();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!MayDrag(eventData))
|
||||
|
@ -600,5 +711,17 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
eventData.useDragThreshold = false;
|
||||
}
|
||||
|
||||
public void SetDirection(Direction direction, bool includeRectLayouts)
|
||||
{
|
||||
Axis oldAxis = axis;
|
||||
this.direction = direction;
|
||||
|
||||
if (!includeRectLayouts)
|
||||
return;
|
||||
|
||||
if (axis != oldAxis)
|
||||
RectTransformUtility.FlipLayoutAxes(transform as RectTransform, true, true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,8 +9,8 @@ using UnityEngine.EventSystems;
|
|||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
// Stepper control
|
||||
[AddComponentMenu("UI/Extensions/Stepper")]
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[AddComponentMenu("UI/Extensions/Sliders/Stepper")]
|
||||
public class Stepper : UIBehaviour
|
||||
{
|
||||
private Selectable[] _sides;
|
|
@ -16,7 +16,12 @@ namespace UnityEngine.UI.Extensions {
|
|||
[AddComponentMenu("UI/Extensions/TextPic")]
|
||||
|
||||
[ExecuteInEditMode] // Needed for culling images that are not used //
|
||||
public class TextPic : Text, IPointerClickHandler, IPointerExitHandler, IPointerEnterHandler, ISelectHandler {
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
public class TextPic : TMPro.TMP_Text, IPointerClickHandler, IPointerExitHandler, IPointerEnterHandler, ISelectHandler
|
||||
#else
|
||||
public class TextPic : Text, IPointerClickHandler, IPointerExitHandler, IPointerEnterHandler, ISelectHandler
|
||||
#endif
|
||||
{
|
||||
// Icon entry to replace text with
|
||||
[Serializable]
|
||||
public struct IconName {
|
||||
|
@ -465,14 +470,21 @@ namespace UnityEngine.UI.Extensions {
|
|||
/// UNITY METHODS ///
|
||||
|
||||
protected override void OnPopulateMesh(VertexHelper toFill) {
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
originalText = text;
|
||||
text = GetOutputText();
|
||||
base.OnPopulateMesh(toFill);
|
||||
|
||||
text = originalText;
|
||||
#else
|
||||
originalText = m_Text;
|
||||
m_Text = GetOutputText();
|
||||
|
||||
base.OnPopulateMesh(toFill);
|
||||
|
||||
m_DisableFontTextureRebuiltCallback = true;
|
||||
m_DisableFontTextureRebuiltCallback = true;
|
||||
|
||||
m_Text = originalText;
|
||||
#endif
|
||||
|
||||
positions.Clear();
|
||||
|
||||
|
@ -539,8 +551,10 @@ namespace UnityEngine.UI.Extensions {
|
|||
// Update the quad images
|
||||
updateQuad = true;
|
||||
|
||||
#if !UNITY_2022_1_OR_NEWER
|
||||
m_DisableFontTextureRebuiltCallback = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Click event is detected whether to click a hyperlink text
|
||||
|
@ -641,7 +655,7 @@ namespace UnityEngine.UI.Extensions {
|
|||
#endif
|
||||
|
||||
protected override void OnEnable() {
|
||||
#if UNITY_2019_1_OR_NEWER
|
||||
#if UNITY_2019_1_OR_NEWER
|
||||
// Here is the hack to see if Unity is using the new rendering system for text
|
||||
usesNewRendering = false;
|
||||
|
||||
|
@ -660,13 +674,14 @@ namespace UnityEngine.UI.Extensions {
|
|||
else {
|
||||
usesNewRendering = true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
base.OnEnable();
|
||||
|
||||
#if !UNITY_2022_1_OR_NEWER
|
||||
supportRichText = true;
|
||||
alignByGeometry = true;
|
||||
|
||||
#endif
|
||||
// Enable images on TextPic disable
|
||||
if (m_ImagesPool.Count >= 1) {
|
||||
for (int i = 0; i < m_ImagesPool.Count; i++) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/// Credit Melang
|
||||
/// Sourced from - http://forum.unity3d.com/members/melang.593409/
|
||||
/// NOT supported in Unity 2022
|
||||
|
||||
#if !UNITY_2022_1_OR_NEWER
|
||||
using System.Collections.Generic;
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
|
@ -60,3 +62,4 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,6 +1,7 @@
|
|||
/// Credit Titinious (https://github.com/Titinious)
|
||||
/// Sourced from - https://github.com/Titinious/CurlyUI
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
@ -284,7 +285,9 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
public void Refresh() { Invoke(nameof(Refreshx), 0.3f); }
|
||||
|
||||
private void Refreshx()
|
||||
{
|
||||
ReportSet();
|
||||
|
||||
|
|
|
@ -4,14 +4,24 @@
|
|||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
[RequireComponent(typeof(TMPro.TMP_Text))]
|
||||
#else
|
||||
[RequireComponent(typeof(Text))]
|
||||
#endif
|
||||
[AddComponentMenu("UI/Effects/Extensions/Curly UI Text")]
|
||||
public class CUIText : CUIGraphic
|
||||
{
|
||||
public override void ReportSet()
|
||||
{
|
||||
if (uiGraphic == null)
|
||||
{
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
uiGraphic = GetComponent<TMPro.TMP_Text>();
|
||||
#else
|
||||
uiGraphic = GetComponent<Text>();
|
||||
#endif
|
||||
}
|
||||
|
||||
base.ReportSet();
|
||||
}
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[RequireComponent(typeof(Text), typeof(RectTransform))]
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
[RequireComponent(typeof(TMPro.TMP_Text))]
|
||||
#else
|
||||
[RequireComponent(typeof(Text))]
|
||||
#endif
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[AddComponentMenu("UI/Effects/Extensions/Curved Text")]
|
||||
public class CurvedText : BaseMeshEffect
|
||||
{
|
||||
|
|
|
@ -4,7 +4,12 @@
|
|||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[RequireComponent(typeof(Text), typeof(RectTransform))]
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
[RequireComponent(typeof(TMPro.TMP_Text))]
|
||||
#else
|
||||
[RequireComponent(typeof(Text))]
|
||||
#endif
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[AddComponentMenu("UI/Effects/Extensions/Cylinder Text")]
|
||||
public class CylinderText : BaseMeshEffect
|
||||
{
|
||||
|
|
|
@ -81,8 +81,12 @@ namespace UnityEngine.UI.Extensions
|
|||
List<UIVertex> verts = new List<UIVertex>();
|
||||
vh.GetUIVertexStream(verts);
|
||||
|
||||
Text text = GetComponent<Text>();
|
||||
if (text == null)
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
var text = GetComponent<TMPro.TMP_Text>();
|
||||
#else
|
||||
var text = GetComponent<Text>();
|
||||
#endif
|
||||
if (text == null)
|
||||
{
|
||||
Debug.LogWarning("LetterSpacing: Missing Text component");
|
||||
return;
|
||||
|
@ -94,28 +98,51 @@ namespace UnityEngine.UI.Extensions
|
|||
float alignmentFactor = 0;
|
||||
int glyphIdx = 0;
|
||||
|
||||
switch (text.alignment)
|
||||
{
|
||||
case TextAnchor.LowerLeft:
|
||||
case TextAnchor.MiddleLeft:
|
||||
case TextAnchor.UpperLeft:
|
||||
alignmentFactor = 0f;
|
||||
break;
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
switch (text.alignment)
|
||||
{
|
||||
case TMPro.TextAlignmentOptions.BottomLeft:
|
||||
case TMPro.TextAlignmentOptions.MidlineLeft:
|
||||
case TMPro.TextAlignmentOptions.TopLeft:
|
||||
alignmentFactor = 0f;
|
||||
break;
|
||||
|
||||
case TextAnchor.LowerCenter:
|
||||
case TextAnchor.MiddleCenter:
|
||||
case TextAnchor.UpperCenter:
|
||||
alignmentFactor = 0.5f;
|
||||
break;
|
||||
case TMPro.TextAlignmentOptions.BottomJustified:
|
||||
case TMPro.TextAlignmentOptions.MidlineJustified:
|
||||
case TMPro.TextAlignmentOptions.TopJustified:
|
||||
alignmentFactor = 0.5f;
|
||||
break;
|
||||
|
||||
case TextAnchor.LowerRight:
|
||||
case TextAnchor.MiddleRight:
|
||||
case TextAnchor.UpperRight:
|
||||
alignmentFactor = 1f;
|
||||
break;
|
||||
}
|
||||
case TMPro.TextAlignmentOptions.BottomRight:
|
||||
case TMPro.TextAlignmentOptions.MidlineRight:
|
||||
case TMPro.TextAlignmentOptions.TopRight:
|
||||
alignmentFactor = 1f;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (text.alignment)
|
||||
{
|
||||
case TextAnchor.LowerLeft:
|
||||
case TextAnchor.MiddleLeft:
|
||||
case TextAnchor.UpperLeft:
|
||||
alignmentFactor = 0f;
|
||||
break;
|
||||
|
||||
for (int lineIdx=0; lineIdx < lines.Length; lineIdx++)
|
||||
case TextAnchor.LowerCenter:
|
||||
case TextAnchor.MiddleCenter:
|
||||
case TextAnchor.UpperCenter:
|
||||
alignmentFactor = 0.5f;
|
||||
break;
|
||||
|
||||
case TextAnchor.LowerRight:
|
||||
case TextAnchor.MiddleRight:
|
||||
case TextAnchor.UpperRight:
|
||||
alignmentFactor = 1f;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int lineIdx=0; lineIdx < lines.Length; lineIdx++)
|
||||
{
|
||||
string line = lines[lineIdx];
|
||||
float lineOffset = (line.Length -1) * letterOffset * alignmentFactor;
|
||||
|
|
|
@ -46,7 +46,11 @@ using System.Collections.Generic;
|
|||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[AddComponentMenu("UI/Effects/Extensions/Mono Spacing")]
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
[RequireComponent(typeof(TMPro.TMP_Text))]
|
||||
#else
|
||||
[RequireComponent(typeof(Text))]
|
||||
#endif
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
///Summary
|
||||
/// Note, Vertex Count has changed in 5.2.1+, is now 6 (two tris) instead of 4 (tri strip).
|
||||
|
@ -58,13 +62,21 @@ namespace UnityEngine.UI.Extensions
|
|||
public bool UseHalfCharWidth = false;
|
||||
|
||||
private RectTransform rectTransform;
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
private TMPro.TMP_Text text;
|
||||
#else
|
||||
private Text text;
|
||||
#endif
|
||||
|
||||
protected MonoSpacing() { }
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
text = GetComponent<TMPro.TMP_Text>();
|
||||
#else
|
||||
text = GetComponent<Text>();
|
||||
#endif
|
||||
if (text == null)
|
||||
{
|
||||
Debug.LogWarning("MonoSpacing: Missing Text component");
|
||||
|
@ -105,28 +117,50 @@ namespace UnityEngine.UI.Extensions
|
|||
float alignmentFactor = 0;
|
||||
int glyphIdx = 0;
|
||||
|
||||
switch (text.alignment)
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
switch (text.alignment)
|
||||
{
|
||||
case TextAnchor.LowerLeft:
|
||||
case TextAnchor.MiddleLeft:
|
||||
case TextAnchor.UpperLeft:
|
||||
case TMPro.TextAlignmentOptions.BottomLeft:
|
||||
case TMPro.TextAlignmentOptions.MidlineLeft:
|
||||
case TMPro.TextAlignmentOptions.TopLeft:
|
||||
alignmentFactor = 0f;
|
||||
break;
|
||||
|
||||
case TextAnchor.LowerCenter:
|
||||
case TextAnchor.MiddleCenter:
|
||||
case TextAnchor.UpperCenter:
|
||||
case TMPro.TextAlignmentOptions.BottomJustified:
|
||||
case TMPro.TextAlignmentOptions.MidlineJustified:
|
||||
case TMPro.TextAlignmentOptions.TopJustified:
|
||||
alignmentFactor = 0.5f;
|
||||
break;
|
||||
|
||||
case TextAnchor.LowerRight:
|
||||
case TextAnchor.MiddleRight:
|
||||
case TextAnchor.UpperRight:
|
||||
case TMPro.TextAlignmentOptions.BottomRight:
|
||||
case TMPro.TextAlignmentOptions.MidlineRight:
|
||||
case TMPro.TextAlignmentOptions.TopRight:
|
||||
alignmentFactor = 1f;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (text.alignment)
|
||||
{
|
||||
case TextAnchor.LowerLeft:
|
||||
case TextAnchor.MiddleLeft:
|
||||
case TextAnchor.UpperLeft:
|
||||
alignmentFactor = 0f;
|
||||
break;
|
||||
|
||||
for (int lineIdx=0; lineIdx < lines.Length; lineIdx++)
|
||||
case TextAnchor.LowerCenter:
|
||||
case TextAnchor.MiddleCenter:
|
||||
case TextAnchor.UpperCenter:
|
||||
alignmentFactor = 0.5f;
|
||||
break;
|
||||
|
||||
case TextAnchor.LowerRight:
|
||||
case TextAnchor.MiddleRight:
|
||||
case TextAnchor.UpperRight:
|
||||
alignmentFactor = 1f;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
for (int lineIdx=0; lineIdx < lines.Length; lineIdx++)
|
||||
{
|
||||
string line = lines[lineIdx];
|
||||
float lineOffset = (line.Length - 1) * letterOffset * (alignmentFactor) - (alignmentFactor - 0.5f) * rectTransform.rect.width;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
/// Credit Melang
|
||||
/// Credit Melang, Lee Hui
|
||||
/// Sourced from - http://forum.unity3d.com/members/melang.593409/
|
||||
/// GC Alloc fix - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/pull-requests/130
|
||||
/// NOT supported in Unity 2022
|
||||
|
||||
#if !UNITY_2022_1_OR_NEWER
|
||||
using System.Collections.Generic;
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
|
@ -90,41 +93,6 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
protected void ApplyShadowZeroAlloc(List<UIVertex> verts, Color32 color, int start, int end, float x, float y)
|
||||
{
|
||||
UIVertex vt;
|
||||
|
||||
var neededCpacity = verts.Count * 2;
|
||||
if (verts.Capacity < neededCpacity)
|
||||
verts.Capacity = neededCpacity;
|
||||
|
||||
for (int i = start; i < end; ++i)
|
||||
{
|
||||
vt = verts[i];
|
||||
verts.Add(vt);
|
||||
|
||||
Vector3 v = vt.position;
|
||||
v.x += x;
|
||||
v.y += y;
|
||||
vt.position = v;
|
||||
var newColor = color;
|
||||
if (m_UseGraphicAlpha)
|
||||
newColor.a = (byte)((newColor.a * verts[i].color.a) / 255);
|
||||
vt.color = newColor;
|
||||
verts[i] = vt;
|
||||
}
|
||||
}
|
||||
|
||||
protected void ApplyShadow(List<UIVertex> verts, Color32 color, int start, int end, float x, float y)
|
||||
{
|
||||
var neededCpacity = verts.Count * 2;
|
||||
if (verts.Capacity < neededCpacity)
|
||||
verts.Capacity = neededCpacity;
|
||||
|
||||
ApplyShadowZeroAlloc(verts, color, start, end, x, y);
|
||||
}
|
||||
|
||||
|
||||
public override void ModifyMesh(VertexHelper vh)
|
||||
{
|
||||
if (!this.IsActive ())
|
||||
|
@ -148,37 +116,76 @@ namespace UnityEngine.UI.Extensions
|
|||
float distanceX = this.effectDistance.x * best_fit_adjustment;
|
||||
float distanceY = this.effectDistance.y * best_fit_adjustment;
|
||||
|
||||
vh.Clear();
|
||||
|
||||
int start = 0;
|
||||
int count = m_Verts.Count;
|
||||
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, distanceX, distanceY);
|
||||
start = count;
|
||||
count = m_Verts.Count;
|
||||
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, distanceX, -distanceY);
|
||||
start = count;
|
||||
count = m_Verts.Count;
|
||||
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, -distanceX, distanceY);
|
||||
start = count;
|
||||
count = m_Verts.Count;
|
||||
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, -distanceX, -distanceY);
|
||||
|
||||
start = count;
|
||||
count = m_Verts.Count;
|
||||
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, distanceX, 0);
|
||||
start = count;
|
||||
count = m_Verts.Count;
|
||||
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, -distanceX, 0);
|
||||
// Apply Outline
|
||||
start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, distanceX, distanceY, vh, start);
|
||||
start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, distanceX, -distanceY, vh, start);
|
||||
start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, -distanceX, distanceY, vh, start);
|
||||
start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, -distanceX, -distanceY, vh, start);
|
||||
start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, distanceX, 0, vh, start);
|
||||
start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, -distanceX, 0, vh, start);
|
||||
start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, 0, distanceY, vh, start);
|
||||
start += this.ApplyOutlineNoGC(m_Verts, this.effectColor, 0, -distanceY, vh, start);
|
||||
|
||||
start = count;
|
||||
count = m_Verts.Count;
|
||||
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, 0, distanceY);
|
||||
start = count;
|
||||
count = m_Verts.Count;
|
||||
this.ApplyShadow (m_Verts, this.effectColor, start, m_Verts.Count, 0, -distanceY);
|
||||
|
||||
vh.Clear();
|
||||
vh.AddUIVertexTriangleStream(m_Verts);
|
||||
// Apply self Text stuff
|
||||
start += ApplyText(m_Verts, vh, start);
|
||||
}
|
||||
|
||||
private int ApplyOutlineNoGC(List<UIVertex> verts, Color color, float x, float y, VertexHelper vh, int startIndex)
|
||||
{
|
||||
int length = verts.Count;
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
UIVertex vt = verts[i];
|
||||
|
||||
Vector3 v = vt.position;
|
||||
v.x += x;
|
||||
v.y += y;
|
||||
vt.position = v;
|
||||
var newColor = color;
|
||||
if (m_UseGraphicAlpha)
|
||||
newColor.a = (byte)((newColor.a * verts[i].color.a) / 255);
|
||||
vt.color = newColor;
|
||||
|
||||
// Tips: Since two triangles share same two vertices, in theory vertices can reduce to 4 / 6
|
||||
// But VertexHelper.FillMesh forbid, so leave it be.
|
||||
|
||||
vh.AddVert(vt);
|
||||
}
|
||||
|
||||
int triangleCount = length / 3;
|
||||
for(int i=0; i<triangleCount; ++i)
|
||||
{
|
||||
int start = startIndex + 3 * i;
|
||||
vh.AddTriangle(start + 0, start + 1, start + 2);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private int ApplyText(List<UIVertex> verts, VertexHelper vh, int startIndex)
|
||||
{
|
||||
int length = verts.Count;
|
||||
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
vh.AddVert(verts[i]);
|
||||
}
|
||||
|
||||
int triangleCount = length / 3;
|
||||
for (int i = 0; i < triangleCount; ++i)
|
||||
{
|
||||
int start = startIndex + 3 * i;
|
||||
vh.AddTriangle(start + 0, start + 1, start + 2);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate ()
|
||||
{
|
||||
|
@ -188,3 +195,4 @@ namespace UnityEngine.UI.Extensions
|
|||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -96,10 +96,8 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
effectRoot.SetActive(true);
|
||||
}
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
/// Credit NemoKrad (aka Charles Humphrey) / valtain
|
||||
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
/// Credit NemoKrad (aka Charles Humphrey) / valtain
|
||||
/// Sourced from - http://www.randomchaos.co.uk/SoftAlphaUIMask.aspx
|
||||
/// Updated by valtain - https://bitbucket.org/SimonDarksideJ/unity-ui-extensions/pull-requests/33
|
||||
|
||||
|
@ -45,7 +47,11 @@ namespace UnityEngine.UI.Extensions
|
|||
MaskArea = GetComponent<RectTransform>();
|
||||
}
|
||||
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
var text = GetComponent<TMPro.TMP_Text>();
|
||||
#else
|
||||
var text = GetComponent<Text>();
|
||||
#endif
|
||||
if (text != null)
|
||||
{
|
||||
mat = new Material(ShaderLibrary.GetShaderInstance("UI Extensions/SoftMaskShader"));
|
||||
|
|
|
@ -43,6 +43,22 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
public ParticleSystem.Particle[] Particles
|
||||
{
|
||||
get
|
||||
{
|
||||
if (particles == null)
|
||||
{
|
||||
#if UNITY_5_5_OR_NEWER
|
||||
particles = new ParticleSystem.Particle[pSystem.main.maxParticles];
|
||||
#else
|
||||
particles = new ParticleSystem.Particle[pSystem.maxParticles];
|
||||
#endif
|
||||
}
|
||||
return particles;
|
||||
}
|
||||
}
|
||||
|
||||
protected bool Initialize()
|
||||
{
|
||||
// initialize members
|
||||
|
@ -66,8 +82,10 @@ namespace UnityEngine.UI.Extensions
|
|||
mainModule.maxParticles = 14000;
|
||||
}
|
||||
#else
|
||||
if (pSystem.maxParticles > 14000)
|
||||
pSystem.maxParticles = 14000;
|
||||
if (pSystem.maxParticles > 14000)
|
||||
{
|
||||
pSystem.maxParticles = 14000;
|
||||
}
|
||||
#endif
|
||||
|
||||
pRenderer = pSystem.GetComponent<ParticleSystemRenderer>();
|
||||
|
@ -95,18 +113,9 @@ namespace UnityEngine.UI.Extensions
|
|||
#if UNITY_5_5_OR_NEWER
|
||||
mainModule.scalingMode = ParticleSystemScalingMode.Hierarchy;
|
||||
#else
|
||||
pSystem.scalingMode = ParticleSystemScalingMode.Hierarchy;
|
||||
pSystem.scalingMode = ParticleSystemScalingMode.Hierarchy;
|
||||
#endif
|
||||
|
||||
particles = null;
|
||||
}
|
||||
#if UNITY_5_5_OR_NEWER
|
||||
if (particles == null)
|
||||
particles = new ParticleSystem.Particle[pSystem.main.maxParticles];
|
||||
#else
|
||||
if (particles == null)
|
||||
particles = new ParticleSystem.Particle[pSystem.maxParticles];
|
||||
#endif
|
||||
|
||||
imageUV = new Vector4(0, 0, 1, 1);
|
||||
|
||||
|
@ -127,7 +136,9 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
base.Awake();
|
||||
if (!Initialize())
|
||||
{
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -160,17 +171,17 @@ namespace UnityEngine.UI.Extensions
|
|||
Vector2 corner1 = Vector2.zero;
|
||||
Vector2 corner2 = Vector2.zero;
|
||||
// iterate through current particles
|
||||
int count = pSystem.GetParticles(particles);
|
||||
int count = pSystem.GetParticles(Particles);
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
ParticleSystem.Particle particle = particles[i];
|
||||
ParticleSystem.Particle particle = Particles[i];
|
||||
|
||||
// get particle properties
|
||||
#if UNITY_5_5_OR_NEWER
|
||||
Vector2 position = (mainModule.simulationSpace == ParticleSystemSimulationSpace.Local ? particle.position : _transform.InverseTransformPoint(particle.position));
|
||||
#else
|
||||
Vector2 position = (pSystem.simulationSpace == ParticleSystemSimulationSpace.Local ? particle.position : _transform.InverseTransformPoint(particle.position));
|
||||
Vector2 position = (pSystem.simulationSpace == ParticleSystemSimulationSpace.Local ? particle.position : _transform.InverseTransformPoint(particle.position));
|
||||
#endif
|
||||
float rotation = -particle.rotation * Mathf.Deg2Rad;
|
||||
float rotation90 = rotation + Mathf.PI / 2;
|
||||
|
@ -182,8 +193,8 @@ namespace UnityEngine.UI.Extensions
|
|||
if (mainModule.scalingMode == ParticleSystemScalingMode.Shape)
|
||||
position /= canvas.scaleFactor;
|
||||
#else
|
||||
if (pSystem.scalingMode == ParticleSystemScalingMode.Shape)
|
||||
position /= canvas.scaleFactor;
|
||||
if (pSystem.scalingMode == ParticleSystemScalingMode.Shape)
|
||||
position /= canvas.scaleFactor;
|
||||
#endif
|
||||
|
||||
// apply texture sheet animation
|
||||
|
@ -223,7 +234,7 @@ namespace UnityEngine.UI.Extensions
|
|||
frame = Mathf.FloorToInt(frameProgress * textureSheetAnimation.numTilesX);
|
||||
|
||||
int row = textureSheetAnimation.rowIndex;
|
||||
#if UNITY_2020 || UNITY_2019
|
||||
#if UNITY_2019_1_OR_NEWER
|
||||
if (textureSheetAnimation.rowMode == ParticleSystemAnimationRowMode.Random)
|
||||
#else
|
||||
if (textureSheetAnimation.useRandomRow)
|
||||
|
@ -378,8 +389,7 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
}
|
||||
if (material == currentMaterial)
|
||||
return;
|
||||
if (material == currentMaterial) { return; }
|
||||
pSystem = null;
|
||||
Initialize();
|
||||
}
|
||||
|
@ -388,6 +398,7 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
currentMaterial = null;
|
||||
currentTexture = null;
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
public void StartParticleEmission()
|
||||
|
@ -407,4 +418,4 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -29,6 +29,13 @@ namespace UnityEngine.UI.Extensions
|
|||
public float centerpoint = 0.5f;
|
||||
|
||||
protected override void OnEnable() { base.OnEnable(); CalculateRadial(); }
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
m_Tracker.Clear();
|
||||
LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
|
||||
}
|
||||
|
||||
public override void SetLayoutHorizontal() {
|
||||
}
|
||||
public override void SetLayoutVertical() {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/// Credit setchi (https://github.com/setchi)
|
||||
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -101,7 +101,7 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <param name="p"><see cref="Scroller"/> のスクロール位置.</param>
|
||||
void OnScrollerValueChanged(float p)
|
||||
{
|
||||
base.UpdatePosition(Scrollable ? ToFancyScrollViewPosition(p) : 0f);
|
||||
base.UpdatePosition(ToFancyScrollViewPosition(Scrollable ? p : 0f));
|
||||
|
||||
if (Scroller.Scrollbar)
|
||||
{
|
||||
|
@ -161,8 +161,6 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <inheritdoc/>
|
||||
protected override void UpdateContents(IList<TItemData> items)
|
||||
{
|
||||
Debug.Assert(Context.CalculateScrollSize != null);
|
||||
|
||||
AdjustCellIntervalAndScrollOffset();
|
||||
base.UpdateContents(items);
|
||||
|
||||
|
|
|
@ -329,7 +329,7 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
if (hold && snap.Enable)
|
||||
{
|
||||
UpdateSelection(Mathf.Clamp(Mathf.RoundToInt(currentPosition), 0, totalCount - 1));
|
||||
UpdateSelection(Mathf.RoundToInt(CircularPosition(currentPosition, totalCount)));
|
||||
ScrollTo(Mathf.RoundToInt(currentPosition), snap.Duration, snap.Easing);
|
||||
}
|
||||
|
||||
|
|
|
@ -166,7 +166,6 @@ namespace UnityEngine.UI.Extensions
|
|||
childSize = LayoutUtility.GetPreferredSize (child, 0);
|
||||
childSize = Mathf.Min (childSize, workingSize);
|
||||
childOtherSize = LayoutUtility.GetPreferredSize (child, 1);
|
||||
childOtherSize = Mathf.Min (childOtherSize, workingSize);
|
||||
} else if (startAxis == Axis.Vertical) {
|
||||
if (invertOrder) {
|
||||
index = IsRightAlign ? rectChildren.Count - 1 - i : i;
|
||||
|
@ -175,7 +174,6 @@ namespace UnityEngine.UI.Extensions
|
|||
childSize = LayoutUtility.GetPreferredSize (child, 1);
|
||||
childSize = Mathf.Min (childSize, workingSize);
|
||||
childOtherSize = LayoutUtility.GetPreferredSize (child, 0);
|
||||
childOtherSize = Mathf.Min (childOtherSize, workingSize);
|
||||
}
|
||||
|
||||
// If adding this element would exceed the bounds of the container,
|
||||
|
@ -227,11 +225,11 @@ namespace UnityEngine.UI.Extensions
|
|||
if (startAxis == Axis.Horizontal) {
|
||||
float newOffset = CalculateRowVerticalOffset (groupHeight, offset, currentBarSpace);
|
||||
currentBarSize -= spacingBetweenElements;
|
||||
LayoutRow (_itemList, currentBarSize, currentBarSpace, workingSize - (ChildForceExpandWidth ? 0 : spacingBetweenElements), padding.left, newOffset, axis);
|
||||
LayoutRow (_itemList, currentBarSize, currentBarSpace, workingSize, padding.left, newOffset, axis);
|
||||
}else if (startAxis == Axis.Vertical) {
|
||||
float newOffset = CalculateColHorizontalOffset(groupWidth, offset, currentBarSpace);
|
||||
currentBarSize -= spacingBetweenElements;
|
||||
LayoutCol(_itemList, currentBarSpace, currentBarSize, workingSize - (ChildForceExpandHeight ? 0 : spacingBetweenElements), newOffset, padding.top, axis);
|
||||
LayoutCol(_itemList, currentBarSpace, currentBarSize, workingSize, newOffset, padding.top, axis);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -424,5 +422,13 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
return max;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
m_Tracker.Clear();
|
||||
LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -114,12 +114,20 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <param name="WorldPositionStays">Should the world position be updated to it's parent transform?</param>
|
||||
public void AddChild(GameObject GO, bool WorldPositionStays)
|
||||
{
|
||||
_scroll_rect.horizontalNormalizedPosition = 0;
|
||||
try
|
||||
{
|
||||
// Rare instances of Unity bug cause error, adding try to manage it.
|
||||
_scroll_rect.horizontalNormalizedPosition = 0;
|
||||
}
|
||||
catch { }
|
||||
|
||||
GO.transform.SetParent(_screensContainer, WorldPositionStays);
|
||||
InitialiseChildObjectsFromScene();
|
||||
DistributePages();
|
||||
if (MaskArea)
|
||||
{
|
||||
UpdateVisible();
|
||||
}
|
||||
|
||||
SetScrollContainerPosition();
|
||||
}
|
||||
|
@ -149,7 +157,12 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
return;
|
||||
}
|
||||
_scroll_rect.horizontalNormalizedPosition = 0;
|
||||
try
|
||||
{
|
||||
// Rare instances of Unity bug cause error, adding try to manage it.
|
||||
_scroll_rect.horizontalNormalizedPosition = 0;
|
||||
}
|
||||
catch { }
|
||||
|
||||
Transform child = _screensContainer.transform.GetChild(index);
|
||||
child.SetParent(null, WorldPositionStays);
|
||||
|
|
|
@ -55,6 +55,13 @@ namespace UnityEngine.UI.Extensions
|
|||
CalculateRadial();
|
||||
}
|
||||
#endif
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
m_Tracker.Clear(); // key change - do not restore - false
|
||||
LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
|
||||
}
|
||||
|
||||
void CalculateRadial()
|
||||
{
|
||||
m_Tracker.Clear();
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||
|
||||
using System;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[Obsolete("ScrollPositionController has been replaced by the Scroller component", true)]
|
||||
public class ScrollPositionController : UIBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
|
||||
{
|
||||
[SerializeField]
|
||||
|
|
|
@ -13,9 +13,7 @@ namespace UnityEngine.UI.Extensions
|
|||
internal Rect panelDimensions;
|
||||
internal RectTransform _screensContainer;
|
||||
internal bool _isVertical;
|
||||
|
||||
internal int _screens = 1;
|
||||
|
||||
internal float _scrollStartPosition;
|
||||
internal float _childSize;
|
||||
private float _childPos, _maskSize;
|
||||
|
@ -26,7 +24,6 @@ namespace UnityEngine.UI.Extensions
|
|||
internal bool _pointerDown = false;
|
||||
internal bool _settled = true;
|
||||
internal Vector3 _startPosition = new Vector3();
|
||||
[Tooltip("The currently active page")]
|
||||
internal int _currentPage;
|
||||
internal int _previousPage;
|
||||
internal int _halfNoVisibleItems;
|
||||
|
@ -67,13 +64,13 @@ namespace UnityEngine.UI.Extensions
|
|||
public float transitionSpeed = 7.5f;
|
||||
|
||||
[Tooltip("Hard Swipe forces to swiping to the next / previous page (optional)")]
|
||||
public Boolean UseHardSwipe = false;
|
||||
public bool UseHardSwipe = false;
|
||||
|
||||
[Tooltip("Fast Swipe makes swiping page next / previous (optional)")]
|
||||
public Boolean UseFastSwipe = false;
|
||||
public bool UseFastSwipe = false;
|
||||
|
||||
[Tooltip("Swipe Delta Threshold looks at the speed of input to decide if a swipe will be initiated (optional)")]
|
||||
public Boolean UseSwipeDeltaThreshold = false;
|
||||
public bool UseSwipeDeltaThreshold = false;
|
||||
|
||||
[Tooltip("Offset for how far a swipe has to travel to initiate a page change (optional)")]
|
||||
public int FastSwipeThreshold = 100;
|
||||
|
@ -84,8 +81,8 @@ namespace UnityEngine.UI.Extensions
|
|||
[Tooltip("Threshold for swipe speed to initiate a swipe, below threshold will return to closest page (optional)")]
|
||||
public float SwipeDeltaThreshold = 5.0f;
|
||||
|
||||
[Tooltip("Use time scale instead of unscaled time (optional)")]
|
||||
public Boolean UseTimeScale = true;
|
||||
[Tooltip("Use time scale instead of unscaled time (optional)")]
|
||||
public bool UseTimeScale = true;
|
||||
|
||||
[Tooltip("The visible bounds area, controls which items are visible/enabled. *Note Should use a RectMask. (optional)")]
|
||||
public RectTransform MaskArea;
|
||||
|
@ -167,7 +164,6 @@ namespace UnityEngine.UI.Extensions
|
|||
private SelectionChangeEndEvent m_OnSelectionChangeEndEvent = new SelectionChangeEndEvent();
|
||||
public SelectionChangeEndEvent OnSelectionChangeEndEvent { get { return m_OnSelectionChangeEndEvent; } set { m_OnSelectionChangeEndEvent = value; } }
|
||||
|
||||
// Use this for initialization
|
||||
void Awake()
|
||||
{
|
||||
if (_scroll_rect == null)
|
||||
|
|
|
@ -284,5 +284,11 @@ namespace UnityEngine.UI.Extensions
|
|||
// Set preferredRowHeights to null to free memory
|
||||
preferredRowHeights = null;
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
m_Tracker.Clear(); // key change - do not restore - false
|
||||
LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
/// Credit Ges
|
||||
/// Sourced from - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-3#post-2280109
|
||||
|
||||
using System;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[Obsolete("TileSizeFitter will be deprecated in next version as Unity has disabled this feature")]
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[AddComponentMenu("Layout/Extensions/Tile Size Fitter")]
|
||||
|
|
|
@ -0,0 +1,276 @@
|
|||
/// Credit Ahmad S. Al-Faqeeh
|
||||
/// Sourced from - https://github.com/Unity-UI-Extensions/com.unity.uiextensions/issues/205
|
||||
/// Based on the UIVerticalScroller
|
||||
///
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[RequireComponent(typeof(ScrollRect))]
|
||||
[AddComponentMenu("Layout/Extensions/Horizontal Scroller")]
|
||||
public class UIHorizontalScroller : MonoBehaviour
|
||||
{
|
||||
private float[] distReposition;
|
||||
private float[] distance;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("desired ScrollRect")]
|
||||
private ScrollRect scrollRect;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Elements to populate inside the scroller")]
|
||||
private GameObject[] arrayOfElements;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Center display area (position of zoomed content)")]
|
||||
private RectTransform center;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Size / spacing of elements")]
|
||||
private RectTransform elementSize;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Scale = 1/ (1+distance from center * shrinkage)")]
|
||||
private Vector2 elementShrinkage = new Vector2(1f / 200, 1f / 200);
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Minimum element scale (furthest from center)")]
|
||||
private Vector2 minScale = new Vector2(0.7f, 0.7f);
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Select the item to be in center on start. (optional)")]
|
||||
private int startingIndex = -1;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Stop scrolling past last element from inertia.")]
|
||||
private bool stopMomentumOnEnd = true;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Set Items out of center to not interactible.")]
|
||||
private bool disableUnfocused = true;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Button to go to the next page. (optional)")]
|
||||
private GameObject scrollLeftButton;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Button to go to the previous page. (optional)")]
|
||||
private GameObject scrollRightButton;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Event fired when a specific item is clicked, exposes index number of item. (optional)")]
|
||||
private UnityEvent<int> onButtonClicked;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Event fired when the focused item is Changed. (optional)")]
|
||||
private UnityEvent<int> onFocusChanged;
|
||||
|
||||
public int FocusedElementIndex { get; private set; }
|
||||
|
||||
public RectTransform Center { get => center; set => center = value; }
|
||||
|
||||
//Scrollable area (content of desired ScrollRect)
|
||||
public RectTransform ScrollingPanel { get { return scrollRect.content; } }
|
||||
|
||||
public string Result { get; private set; }
|
||||
|
||||
public UIHorizontalScroller() { }
|
||||
|
||||
public UIHorizontalScroller(RectTransform center, RectTransform elementSize, ScrollRect scrollRect, GameObject[] arrayOfElements)
|
||||
{
|
||||
this.scrollRect = scrollRect;
|
||||
this.elementSize = elementSize;
|
||||
this.arrayOfElements = arrayOfElements;
|
||||
this.center = center;
|
||||
}
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
if (!scrollRect)
|
||||
{
|
||||
scrollRect = GetComponent<ScrollRect>();
|
||||
}
|
||||
|
||||
if (!center)
|
||||
{
|
||||
Debug.LogError("Please define the RectTransform for the Center viewport of the scrollable area");
|
||||
}
|
||||
|
||||
if (!elementSize)
|
||||
{
|
||||
elementSize = center;
|
||||
}
|
||||
|
||||
if (arrayOfElements == null || arrayOfElements.Length == 0)
|
||||
{
|
||||
var childCount = scrollRect.content.childCount;
|
||||
if (childCount > 0)
|
||||
{
|
||||
arrayOfElements = new GameObject[childCount];
|
||||
for (int i = 0; i < childCount; i++)
|
||||
{
|
||||
arrayOfElements[i] = scrollRect.content.GetChild(i).gameObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (scrollLeftButton)
|
||||
{
|
||||
scrollLeftButton.GetComponent<Button>().onClick.AddListener(() => ScrollLeft());
|
||||
}
|
||||
|
||||
if (scrollRightButton)
|
||||
{
|
||||
scrollRightButton.GetComponent<Button>().onClick.AddListener(() => ScrollRight());
|
||||
}
|
||||
|
||||
UpdateChildren(startingIndex, arrayOfElements);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recognises and resizes the children.
|
||||
/// </summary>
|
||||
/// <param name="startingIndex">Starting index.</param>
|
||||
/// <param name="arrayOfElements">Array of elements.</param>
|
||||
public void UpdateChildren(int startingIndex = -1, GameObject[] arrayOfElements = null)
|
||||
{
|
||||
// Set _arrayOfElements to arrayOfElements if given, otherwise to child objects of the scrolling panel.
|
||||
if (arrayOfElements != null)
|
||||
{
|
||||
this.arrayOfElements = arrayOfElements;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.arrayOfElements = new GameObject[ScrollingPanel.childCount];
|
||||
for (int i = 0; i < ScrollingPanel.childCount; i++)
|
||||
{
|
||||
this.arrayOfElements[i] = ScrollingPanel.GetChild(i).gameObject;
|
||||
}
|
||||
}
|
||||
|
||||
// resize the elements to match elementSize rect
|
||||
for (var i = 0; i < this.arrayOfElements.Length; i++)
|
||||
{
|
||||
AddListener(arrayOfElements[i], i);
|
||||
|
||||
RectTransform r = this.arrayOfElements[i].GetComponent<RectTransform>();
|
||||
r.anchorMax = r.anchorMin = r.pivot = new Vector2(0.5f, 0.5f);
|
||||
r.localPosition = new Vector2(i * elementSize.rect.size.x,0);
|
||||
r.sizeDelta = elementSize.rect.size;
|
||||
}
|
||||
|
||||
// prepare for scrolling
|
||||
distance = new float[this.arrayOfElements.Length];
|
||||
distReposition = new float[this.arrayOfElements.Length];
|
||||
FocusedElementIndex = -1;
|
||||
|
||||
// if starting index is given, snap to respective element
|
||||
if (startingIndex > -1)
|
||||
{
|
||||
startingIndex = startingIndex > this.arrayOfElements.Length ? this.arrayOfElements.Length - 1 : startingIndex;
|
||||
SnapToElement(startingIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddListener(GameObject button, int index)
|
||||
{
|
||||
var buttonClick = button.GetComponent<Button>();
|
||||
buttonClick.onClick.RemoveAllListeners();
|
||||
buttonClick.onClick.AddListener(() => onButtonClicked?.Invoke(index));
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (arrayOfElements.Length < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < arrayOfElements.Length; i++)
|
||||
{
|
||||
var arrayElementRT = arrayOfElements[i].GetComponent<RectTransform>();
|
||||
distReposition[i] = center.position.x - arrayElementRT.position.x;
|
||||
distance[i] = Mathf.Abs(distReposition[i]);
|
||||
|
||||
//Magnifying effect
|
||||
Vector2 scale = Vector2.Max(minScale, new Vector2(1 / (1 + distance[i] * elementShrinkage.x), (1 / (1 + distance[i] * elementShrinkage.y))));
|
||||
arrayElementRT.transform.localScale = new Vector3(scale.x, scale.y, 1f);
|
||||
}
|
||||
|
||||
float minDistance = Mathf.Min(distance);
|
||||
int oldFocusedElement = FocusedElementIndex;
|
||||
|
||||
for (var i = 0; i < arrayOfElements.Length; i++)
|
||||
{
|
||||
arrayOfElements[i].GetComponent<CanvasGroup>().interactable = !disableUnfocused || minDistance == distance[i];
|
||||
if (minDistance == distance[i])
|
||||
{
|
||||
FocusedElementIndex = i;
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
var textComponentTxtMeshPro = arrayOfElements[i].GetComponentInChildren<TMPro.TMP_Text>();
|
||||
if (textComponentTxtMeshPro != null)
|
||||
{
|
||||
Result = textComponentTxtMeshPro.text;
|
||||
}
|
||||
#else
|
||||
var textComponent = arrayOfElements[i].GetComponentInChildren<Text>();
|
||||
if (textComponent != null)
|
||||
{
|
||||
Result = textComponent.text;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (FocusedElementIndex != oldFocusedElement && onFocusChanged != null)
|
||||
{
|
||||
onFocusChanged.Invoke(FocusedElementIndex);
|
||||
}
|
||||
|
||||
if (!UIExtensionsInputManager.GetMouseButton(0))
|
||||
{
|
||||
// scroll slowly to nearest element when not dragged
|
||||
ScrollingElements();
|
||||
}
|
||||
|
||||
// stop scrolling past last element from inertia
|
||||
if (stopMomentumOnEnd
|
||||
&& (arrayOfElements[0].GetComponent<RectTransform>().position.x > center.position.x
|
||||
|| arrayOfElements[arrayOfElements.Length - 1].GetComponent<RectTransform>().position.x < center.position.x))
|
||||
{
|
||||
scrollRect.velocity = Vector2.zero;
|
||||
}
|
||||
}
|
||||
|
||||
private void ScrollingElements()
|
||||
{
|
||||
float newX = Mathf.Lerp(ScrollingPanel.anchoredPosition.x, ScrollingPanel.anchoredPosition.x + distReposition[FocusedElementIndex], Time.deltaTime * 2f);
|
||||
Vector2 newPosition = new Vector2(newX, ScrollingPanel.anchoredPosition.y);
|
||||
ScrollingPanel.anchoredPosition = newPosition;
|
||||
}
|
||||
|
||||
public void SnapToElement(int element)
|
||||
{
|
||||
float deltaElementPositionX = elementSize.rect.width / 1.2f * element;
|
||||
Vector2 newPosition = new Vector2(-deltaElementPositionX, ScrollingPanel.anchoredPosition.y);
|
||||
ScrollingPanel.anchoredPosition = newPosition;
|
||||
}
|
||||
|
||||
public void ScrollLeft()
|
||||
{
|
||||
float deltaLeft = elementSize.rect.width / 1.2f;
|
||||
Vector2 newPositionLeft = new Vector2(ScrollingPanel.anchoredPosition.x - deltaLeft, ScrollingPanel.anchoredPosition.y);
|
||||
ScrollingPanel.anchoredPosition = Vector2.Lerp(ScrollingPanel.anchoredPosition, newPositionLeft, 1);
|
||||
}
|
||||
|
||||
public void ScrollRight()
|
||||
{
|
||||
float deltaRight = elementSize.rect.width / 1.2f;// arrayOfElements[0].GetComponent<RectTransform>().rect.width;
|
||||
Vector2 newPositionRight = new Vector2(ScrollingPanel.anchoredPosition.x + deltaRight, ScrollingPanel.anchoredPosition.y);
|
||||
ScrollingPanel.anchoredPosition = newPositionRight;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8fe84cbf30cb0874091fd899fe1457d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -10,53 +10,69 @@ namespace UnityEngine.UI.Extensions
|
|||
[AddComponentMenu("Layout/Extensions/Vertical Scroller")]
|
||||
public class UIVerticalScroller : MonoBehaviour
|
||||
{
|
||||
[Tooltip("desired ScrollRect")]
|
||||
public ScrollRect scrollRect;
|
||||
[Tooltip("Center display area (position of zoomed content)")]
|
||||
public RectTransform center;
|
||||
[Tooltip("Size / spacing of elements")]
|
||||
public RectTransform elementSize;
|
||||
[Tooltip("Scale = 1/ (1+distance from center * shrinkage)")]
|
||||
public Vector2 elementShrinkage = new Vector2(1f / 200, 1f / 200);
|
||||
[Tooltip("Minimum element scale (furthest from center)")]
|
||||
public Vector2 minScale = new Vector2(0.7f, 0.7f);
|
||||
[Tooltip("Select the item to be in center on start.")]
|
||||
public int startingIndex = -1;
|
||||
[Tooltip("Stop scrolling past last element from inertia.")]
|
||||
public bool stopMomentumOnEnd = true;
|
||||
[Tooltip("Set Items out of center to not interactible.")]
|
||||
public bool disableUnfocused = true;
|
||||
[Tooltip("Button to go to the next page. (optional)")]
|
||||
public GameObject scrollUpButton;
|
||||
[Tooltip("Button to go to the previous page. (optional)")]
|
||||
public GameObject scrollDownButton;
|
||||
[Tooltip("Event fired when a specific item is clicked, exposes index number of item. (optional)")]
|
||||
public IntEvent OnButtonClicked;
|
||||
[Tooltip("Event fired when the focused item is Changed. (optional)")]
|
||||
public IntEvent OnFocusChanged;
|
||||
[HideInInspector]
|
||||
public GameObject[] _arrayOfElements;
|
||||
|
||||
public int focusedElementIndex { get; private set; }
|
||||
|
||||
public string result { get; private set; }
|
||||
|
||||
private float[] distReposition;
|
||||
private float[] distance;
|
||||
//private int elementsDistance;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("desired ScrollRect")]
|
||||
private ScrollRect scrollRect;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Elements to populate inside the scroller")]
|
||||
private GameObject[] arrayOfElements;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Center display area (position of zoomed content)")]
|
||||
private RectTransform center;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Size / spacing of elements")]
|
||||
private RectTransform elementSize;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Scale = 1/ (1+distance from center * shrinkage)")]
|
||||
private Vector2 elementShrinkage = new Vector2(1f / 200, 1f / 200);
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Minimum element scale (furthest from center)")]
|
||||
private Vector2 minScale = new Vector2(0.7f, 0.7f);
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Select the item to be in center on start.")]
|
||||
private int startingIndex = -1;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Stop scrolling past last element from inertia.")]
|
||||
private bool stopMomentumOnEnd = true;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Set Items out of center to not interactible.")]
|
||||
private bool disableUnfocused = true;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Button to go to the next page. (optional)")]
|
||||
private GameObject scrollUpButton;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Button to go to the previous page. (optional)")]
|
||||
private GameObject scrollDownButton;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Event fired when a specific item is clicked, exposes index number of item. (optional)")]
|
||||
private UnityEvent<int> onButtonClicked;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Event fired when the focused item is Changed. (optional)")]
|
||||
private UnityEvent<int> onFocusChanged;
|
||||
|
||||
public int FocusedElementIndex { get; private set; }
|
||||
|
||||
public RectTransform Center { get => center; set => center = value; }
|
||||
|
||||
public string Result { get; private set; }
|
||||
|
||||
//Scrollable area (content of desired ScrollRect)
|
||||
[HideInInspector]
|
||||
public RectTransform scrollingPanel{ get { return scrollRect.content; } }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor when not used as component but called from other script, don't forget to set the non-optional properties.
|
||||
/// </summary>
|
||||
public UIVerticalScroller()
|
||||
{
|
||||
}
|
||||
public RectTransform ScrollingPanel{ get { return scrollRect.content; } }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor when not used as component but called from other script
|
||||
|
@ -66,7 +82,7 @@ namespace UnityEngine.UI.Extensions
|
|||
this.center = center;
|
||||
this.elementSize = elementSize;
|
||||
this.scrollRect = scrollRect;
|
||||
_arrayOfElements = arrayOfElements;
|
||||
this.arrayOfElements = arrayOfElements;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -78,20 +94,27 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
scrollRect = GetComponent<ScrollRect>();
|
||||
}
|
||||
|
||||
if (!center)
|
||||
{
|
||||
Debug.LogError("Please define the RectTransform for the Center viewport of the scrollable area");
|
||||
}
|
||||
|
||||
if (!elementSize)
|
||||
{
|
||||
elementSize = center;
|
||||
}
|
||||
if (_arrayOfElements == null || _arrayOfElements.Length == 0)
|
||||
|
||||
if (arrayOfElements == null || arrayOfElements.Length == 0)
|
||||
{
|
||||
_arrayOfElements = new GameObject[scrollingPanel.childCount];
|
||||
for (int i = 0; i < scrollingPanel.childCount; i++)
|
||||
var childCount = ScrollingPanel.childCount;
|
||||
if (childCount > 0)
|
||||
{
|
||||
_arrayOfElements[i] = scrollingPanel.GetChild(i).gameObject;
|
||||
arrayOfElements = new GameObject[childCount];
|
||||
for (int i = 0; i < childCount; i++)
|
||||
{
|
||||
arrayOfElements[i] = ScrollingPanel.GetChild(i).gameObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,104 +124,114 @@ namespace UnityEngine.UI.Extensions
|
|||
/// </summary>
|
||||
/// <param name="startingIndex">Starting index.</param>
|
||||
/// <param name="arrayOfElements">Array of elements.</param>
|
||||
public void updateChildren(int startingIndex = -1, GameObject[] arrayOfElements = null)
|
||||
public void UpdateChildren(int startingIndex = -1, GameObject[] arrayOfElements = null)
|
||||
{
|
||||
// Set _arrayOfElements to arrayOfElements if given, otherwise to child objects of the scrolling panel.
|
||||
if (arrayOfElements != null)
|
||||
{
|
||||
_arrayOfElements = arrayOfElements;
|
||||
this.arrayOfElements = arrayOfElements;
|
||||
}
|
||||
else
|
||||
{
|
||||
_arrayOfElements = new GameObject[scrollingPanel.childCount];
|
||||
for (int i = 0; i < scrollingPanel.childCount; i++)
|
||||
this.arrayOfElements = new GameObject[ScrollingPanel.childCount];
|
||||
for (int i = 0; i < ScrollingPanel.childCount; i++)
|
||||
{
|
||||
_arrayOfElements[i] = scrollingPanel.GetChild(i).gameObject;
|
||||
this.arrayOfElements[i] = ScrollingPanel.GetChild(i).gameObject;
|
||||
}
|
||||
}
|
||||
|
||||
// resize the elements to match elementSize rect
|
||||
for (var i = 0; i < _arrayOfElements.Length; i++)
|
||||
for (var i = 0; i < this.arrayOfElements.Length; i++)
|
||||
{
|
||||
int j = i;
|
||||
_arrayOfElements[i].GetComponent<Button>().onClick.RemoveAllListeners();
|
||||
if (OnButtonClicked != null)
|
||||
{
|
||||
_arrayOfElements[i].GetComponent<Button>().onClick.AddListener(() => OnButtonClicked.Invoke(j));
|
||||
}
|
||||
RectTransform r = _arrayOfElements[i].GetComponent<RectTransform>();
|
||||
AddListener(arrayOfElements[i], i);
|
||||
|
||||
RectTransform r = this.arrayOfElements[i].GetComponent<RectTransform>();
|
||||
r.anchorMax = r.anchorMin = r.pivot = new Vector2(0.5f, 0.5f);
|
||||
r.localPosition = new Vector2(0, i * elementSize.rect.size.y);
|
||||
r.sizeDelta = elementSize.rect.size;
|
||||
}
|
||||
|
||||
// prepare for scrolling
|
||||
distance = new float[_arrayOfElements.Length];
|
||||
distReposition = new float[_arrayOfElements.Length];
|
||||
focusedElementIndex = -1;
|
||||
|
||||
//scrollRect.scrollSensitivity = elementSize.rect.height / 5;
|
||||
distance = new float[this.arrayOfElements.Length];
|
||||
distReposition = new float[this.arrayOfElements.Length];
|
||||
FocusedElementIndex = -1;
|
||||
|
||||
// if starting index is given, snap to respective element
|
||||
if (startingIndex > -1)
|
||||
{
|
||||
startingIndex = startingIndex > _arrayOfElements.Length ? _arrayOfElements.Length - 1 : startingIndex;
|
||||
startingIndex = startingIndex > this.arrayOfElements.Length ? this.arrayOfElements.Length - 1 : startingIndex;
|
||||
SnapToElement(startingIndex);
|
||||
}
|
||||
}
|
||||
private void AddListener(GameObject button, int index)
|
||||
{
|
||||
var buttonClick = button.GetComponent<Button>();
|
||||
buttonClick.onClick.RemoveAllListeners();
|
||||
buttonClick.onClick.AddListener(() => onButtonClicked?.Invoke(index));
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
|
||||
if (scrollUpButton)
|
||||
scrollUpButton.GetComponent<Button>().onClick.AddListener(() =>
|
||||
{
|
||||
ScrollUp();
|
||||
});
|
||||
|
||||
{
|
||||
scrollUpButton.GetComponent<Button>().onClick.AddListener(() => ScrollUp());
|
||||
}
|
||||
if (scrollDownButton)
|
||||
scrollDownButton.GetComponent<Button>().onClick.AddListener(() =>
|
||||
{
|
||||
ScrollDown();
|
||||
});
|
||||
updateChildren(startingIndex, _arrayOfElements);
|
||||
{
|
||||
scrollDownButton.GetComponent<Button>().onClick.AddListener(() => ScrollDown());
|
||||
}
|
||||
UpdateChildren(startingIndex, arrayOfElements);
|
||||
}
|
||||
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (_arrayOfElements.Length < 1)
|
||||
if (arrayOfElements.Length < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < _arrayOfElements.Length; i++)
|
||||
for (var i = 0; i < arrayOfElements.Length; i++)
|
||||
{
|
||||
distReposition[i] = center.GetComponent<RectTransform>().position.y - _arrayOfElements[i].GetComponent<RectTransform>().position.y;
|
||||
var arrayElementRT = arrayOfElements[i].GetComponent<RectTransform>();
|
||||
|
||||
distReposition[i] = center.position.y - arrayElementRT.position.y;
|
||||
distance[i] = Mathf.Abs(distReposition[i]);
|
||||
|
||||
//Magnifying effect
|
||||
Vector2 scale = Vector2.Max(minScale, new Vector2(1 / (1 + distance[i] * elementShrinkage.x), (1 / (1 + distance[i] * elementShrinkage.y))));
|
||||
_arrayOfElements[i].GetComponent<RectTransform>().transform.localScale = new Vector3(scale.x, scale.y, 1f);
|
||||
arrayElementRT.transform.localScale = new Vector3(scale.x, scale.y, 1f);
|
||||
}
|
||||
|
||||
// detect focused element
|
||||
float minDistance = Mathf.Min(distance);
|
||||
int oldFocusedElement = focusedElementIndex;
|
||||
for (var i = 0; i < _arrayOfElements.Length; i++)
|
||||
int oldFocusedElement = FocusedElementIndex;
|
||||
|
||||
for (var i = 0; i < arrayOfElements.Length; i++)
|
||||
{
|
||||
_arrayOfElements[i].GetComponent<CanvasGroup>().interactable = !disableUnfocused || minDistance == distance[i];
|
||||
arrayOfElements[i].GetComponent<CanvasGroup>().interactable = !disableUnfocused || minDistance == distance[i];
|
||||
if (minDistance == distance[i])
|
||||
{
|
||||
focusedElementIndex = i;
|
||||
result = _arrayOfElements[i].GetComponentInChildren<Text>().text;
|
||||
FocusedElementIndex = i;
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
var textComponentTxtMeshPro = arrayOfElements[i].GetComponentInChildren<TMPro.TMP_Text>();
|
||||
if (textComponentTxtMeshPro != null)
|
||||
{
|
||||
Result = textComponentTxtMeshPro.text;
|
||||
}
|
||||
#else
|
||||
var textComponent = arrayOfElements[i].GetComponentInChildren<Text>();
|
||||
if (textComponent != null)
|
||||
{
|
||||
Result = textComponent.text;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (focusedElementIndex != oldFocusedElement && OnFocusChanged != null)
|
||||
{
|
||||
OnFocusChanged.Invoke(focusedElementIndex);
|
||||
}
|
||||
|
||||
if (FocusedElementIndex != oldFocusedElement)
|
||||
{
|
||||
onFocusChanged?.Invoke(FocusedElementIndex);
|
||||
}
|
||||
|
||||
if (!UIExtensionsInputManager.GetMouseButton(0))
|
||||
{
|
||||
|
@ -206,11 +239,10 @@ namespace UnityEngine.UI.Extensions
|
|||
ScrollingElements();
|
||||
}
|
||||
|
||||
|
||||
// stop scrolling past last element from inertia
|
||||
if (stopMomentumOnEnd
|
||||
&& (_arrayOfElements[0].GetComponent<RectTransform>().position.y > center.position.y
|
||||
|| _arrayOfElements[_arrayOfElements.Length - 1].GetComponent<RectTransform>().position.y < center.position.y))
|
||||
&& (arrayOfElements[0].GetComponent<RectTransform>().position.y > center.position.y
|
||||
|| arrayOfElements[arrayOfElements.Length - 1].GetComponent<RectTransform>().position.y < center.position.y))
|
||||
{
|
||||
scrollRect.velocity = Vector2.zero;
|
||||
}
|
||||
|
@ -218,37 +250,30 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
private void ScrollingElements()
|
||||
{
|
||||
float newY = Mathf.Lerp(scrollingPanel.anchoredPosition.y, scrollingPanel.anchoredPosition.y + distReposition[focusedElementIndex], Time.deltaTime * 2f);
|
||||
Vector2 newPosition = new Vector2(scrollingPanel.anchoredPosition.x, newY);
|
||||
scrollingPanel.anchoredPosition = newPosition;
|
||||
float newY = Mathf.Lerp(ScrollingPanel.anchoredPosition.y, ScrollingPanel.anchoredPosition.y + distReposition[FocusedElementIndex], Time.deltaTime * 2f);
|
||||
Vector2 newPosition = new Vector2(ScrollingPanel.anchoredPosition.x, newY);
|
||||
ScrollingPanel.anchoredPosition = newPosition;
|
||||
}
|
||||
|
||||
public void SnapToElement(int element)
|
||||
{
|
||||
float deltaElementPositionY = elementSize.rect.height * element;
|
||||
Vector2 newPosition = new Vector2(scrollingPanel.anchoredPosition.x, -deltaElementPositionY);
|
||||
scrollingPanel.anchoredPosition = newPosition;
|
||||
|
||||
Vector2 newPosition = new Vector2(ScrollingPanel.anchoredPosition.x, -deltaElementPositionY);
|
||||
ScrollingPanel.anchoredPosition = newPosition;
|
||||
}
|
||||
|
||||
public void ScrollUp()
|
||||
{
|
||||
float deltaUp = elementSize.rect.height / 1.2f;
|
||||
Vector2 newPositionUp = new Vector2(scrollingPanel.anchoredPosition.x, scrollingPanel.anchoredPosition.y - deltaUp);
|
||||
scrollingPanel.anchoredPosition = Vector2.Lerp(scrollingPanel.anchoredPosition, newPositionUp, 1);
|
||||
Vector2 newPositionUp = new Vector2(ScrollingPanel.anchoredPosition.x, ScrollingPanel.anchoredPosition.y - deltaUp);
|
||||
ScrollingPanel.anchoredPosition = Vector2.Lerp(ScrollingPanel.anchoredPosition, newPositionUp, 1);
|
||||
}
|
||||
|
||||
public void ScrollDown()
|
||||
{
|
||||
float deltaDown = elementSize.rect.height / 1.2f;
|
||||
Vector2 newPositionDown = new Vector2(scrollingPanel.anchoredPosition.x, scrollingPanel.anchoredPosition.y + deltaDown);
|
||||
scrollingPanel.anchoredPosition = newPositionDown;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class IntEvent:UnityEvent<int>
|
||||
{
|
||||
|
||||
Vector2 newPositionDown = new Vector2(ScrollingPanel.anchoredPosition.x, ScrollingPanel.anchoredPosition.y + deltaDown);
|
||||
ScrollingPanel.anchoredPosition = newPositionDown;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -114,7 +114,13 @@ namespace UnityEngine.UI.Extensions
|
|||
/// <param name="WorldPositionStays">Should the world position be updated to it's parent transform?</param>
|
||||
public void AddChild(GameObject GO, bool WorldPositionStays)
|
||||
{
|
||||
_scroll_rect.verticalNormalizedPosition = 0;
|
||||
try
|
||||
{
|
||||
// Rare instances of Unity bug cause error, adding try to manage it.
|
||||
_scroll_rect.verticalNormalizedPosition = 0;
|
||||
}
|
||||
catch { }
|
||||
|
||||
GO.transform.SetParent(_screensContainer, WorldPositionStays);
|
||||
InitialiseChildObjectsFromScene();
|
||||
DistributePages();
|
||||
|
@ -148,7 +154,12 @@ namespace UnityEngine.UI.Extensions
|
|||
{
|
||||
return;
|
||||
}
|
||||
_scroll_rect.verticalNormalizedPosition = 0;
|
||||
try
|
||||
{
|
||||
// Rare instances of Unity bug cause error, adding try to manage it.
|
||||
_scroll_rect.verticalNormalizedPosition = 0;
|
||||
}
|
||||
catch { }
|
||||
|
||||
Transform child = _screensContainer.transform.GetChild(index);
|
||||
child.SetParent(null, WorldPositionStays);
|
||||
|
|
|
@ -155,6 +155,12 @@ namespace UnityEngine.UI.Extensions
|
|||
SetVerticesDirty();
|
||||
}
|
||||
|
||||
public void SetArc(float arc)
|
||||
{
|
||||
Arc = arc;
|
||||
SetVerticesDirty();
|
||||
}
|
||||
|
||||
public void SetArcSteps(int steps)
|
||||
{
|
||||
ArcSteps = steps;
|
||||
|
|
|
@ -111,10 +111,18 @@ namespace UnityEngine.UI.Extensions
|
|||
|
||||
set
|
||||
{
|
||||
if (m_points == value)
|
||||
return;
|
||||
m_points = value;
|
||||
SetAllDirty();
|
||||
if (m_points == value) return;
|
||||
|
||||
if (value == null || value.Length == 0)
|
||||
{
|
||||
m_points = new Vector2[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_points = value;
|
||||
}
|
||||
|
||||
SetAllDirty();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,7 +474,7 @@ namespace UnityEngine.UI.Extensions
|
|||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
if (m_points.Length == 0)
|
||||
if (m_points == null || m_points?.Length == 0)
|
||||
{
|
||||
m_points = new Vector2[1];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
/// Credit Steve Westhoff, jack.sydorenko, firagon
|
||||
/// Sourced from - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/issues/324
|
||||
/// Refactored and updated for performance from UILineRenderer by Steve Westhoff
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
{
|
||||
[AddComponentMenu("UI/Extensions/Primitives/UILineRendererFIFO")]
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
public class UILineRendererFIFO : UIPrimitiveBase
|
||||
{
|
||||
private static readonly Vector2[] middleUvs = new[] { new Vector2(0.5f, 0), new Vector2(0.5f, 1), new Vector2(0.5f, 1), new Vector2(0.5f, 0) };
|
||||
private List<Vector2> addedPoints = new List<Vector2>();
|
||||
private bool needsResize;
|
||||
|
||||
[SerializeField, Tooltip("Thickness of the line")]
|
||||
private float lineThickness = 1;
|
||||
|
||||
[SerializeField, Tooltip("Points to draw lines between\n Can be improved using the Resolution Option")]
|
||||
private List<Vector2> points = new List<Vector2>();
|
||||
|
||||
[SerializeField, Tooltip("Segments to be drawn\n This is a list of arrays of points")]
|
||||
private List<UIVertex[]> segments = new List<UIVertex[]>();
|
||||
|
||||
/// <summary>
|
||||
/// Thickness of the line
|
||||
/// </summary>
|
||||
public float LineThickness
|
||||
{
|
||||
get { return lineThickness; }
|
||||
set { lineThickness = value; SetAllDirty(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Points to be drawn in the line.
|
||||
/// </summary>
|
||||
/// <remarks>Don't add points to the list directly, use the add / remove functions</remarks>
|
||||
public List<Vector2> Points
|
||||
{
|
||||
get
|
||||
{
|
||||
return points;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (points == value)
|
||||
return;
|
||||
points = value;
|
||||
SetAllDirty();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds to head
|
||||
/// </summary>
|
||||
/// <param name="point"></param>
|
||||
public void AddPoint(Vector2 point) {
|
||||
points.Add(point);
|
||||
addedPoints.Add(point);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes from tail (FIFO)
|
||||
/// </summary>
|
||||
public void RemovePoint() {
|
||||
points.RemoveAt(0);
|
||||
needsResize = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all the points from the LineRenderer
|
||||
/// </summary>
|
||||
public void ClearPoints()
|
||||
{
|
||||
segments.Clear();
|
||||
points.Clear();
|
||||
addedPoints.Clear();
|
||||
needsResize = false;
|
||||
}
|
||||
|
||||
public void Resize() {
|
||||
needsResize = true;
|
||||
}
|
||||
|
||||
protected override void OnPopulateMesh(VertexHelper vertexHelper) {
|
||||
vertexHelper.Clear();
|
||||
if(needsResize) {
|
||||
needsResize = false;
|
||||
segments.Clear();
|
||||
addedPoints = new List<Vector2>(points);
|
||||
}
|
||||
int count = addedPoints.Count;
|
||||
if(count > 1) {
|
||||
PopulateMesh(addedPoints, vertexHelper);
|
||||
if(count % 2 == 0) {
|
||||
addedPoints.Clear();
|
||||
} else {
|
||||
Vector2 extraPoint = addedPoints[count - 1];
|
||||
addedPoints.Clear();
|
||||
addedPoints.Add(extraPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PopulateMesh(List<Vector2> pointsToDraw, VertexHelper vertexHelper) {
|
||||
if(ImproveResolution != ResolutionMode.None) {
|
||||
pointsToDraw = IncreaseResolution(pointsToDraw);
|
||||
}
|
||||
float sizeX = rectTransform.rect.width;
|
||||
float sizeY = rectTransform.rect.height;
|
||||
float offsetX = -rectTransform.pivot.x * sizeX;
|
||||
float offsetY = -rectTransform.pivot.y * sizeY;
|
||||
for(int i = 1; i < pointsToDraw.Count; i += 2) {
|
||||
Vector2 start = pointsToDraw[i - 1];
|
||||
Vector2 end = pointsToDraw[i];
|
||||
start = new Vector2(start.x * sizeX + offsetX, start.y * sizeY + offsetY);
|
||||
end = new Vector2(end.x * sizeX + offsetX, end.y * sizeY + offsetY);
|
||||
UIVertex[] segment = CreateLineSegment(start, end, segments.Count > 1 ? segments[segments.Count - 2] : null);
|
||||
segments.Add(segment);
|
||||
}
|
||||
for(int i = 0; i < segments.Count; i++) {
|
||||
vertexHelper.AddUIVertexQuad(segments[i]);
|
||||
}
|
||||
if(vertexHelper.currentVertCount > 64000) {
|
||||
Debug.LogError("Max Verticies size is 64000, current mesh vertcies count is [" + vertexHelper.currentVertCount + "] - Cannot Draw");
|
||||
vertexHelper.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
UIVertex[] CreateLineSegment(Vector2 start, Vector2 end, UIVertex[] previousVert = null) {
|
||||
Vector2 offset = new Vector2(start.y - end.y, end.x - start.x).normalized * lineThickness * 0.5f;
|
||||
Vector2 v1;
|
||||
Vector2 v2;
|
||||
if(previousVert != null) {
|
||||
v1 = new Vector2(previousVert[3].position.x, previousVert[3].position.y);
|
||||
v2 = new Vector2(previousVert[2].position.x, previousVert[2].position.y);
|
||||
} else {
|
||||
v1 = start - offset;
|
||||
v2 = start + offset;
|
||||
}
|
||||
return SetVbo(new[] { v1, v2, end + offset, end - offset }, middleUvs);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a3a91607af301f241b9f0a860c720b21
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -118,24 +118,6 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// List of Segments to be drawn.
|
||||
// /// </summary>
|
||||
// public List<Vector2[]> Segments
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// return m_segments;
|
||||
// }
|
||||
|
||||
// set
|
||||
// {
|
||||
// m_segments = value;
|
||||
// SetAllDirty();
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
public void AddPoint(Vector2 pointToAdd)
|
||||
{
|
||||
m_points.Add(pointToAdd);
|
||||
|
@ -298,15 +280,6 @@ namespace UnityEngine.UI.Extensions
|
|||
PopulateMesh (vh, m_points);
|
||||
|
||||
}
|
||||
//else if (m_segments != null && m_segments.Count > 0) {
|
||||
// GeneratedUVs ();
|
||||
// vh.Clear ();
|
||||
|
||||
// for (int s = 0; s < m_segments.Count; s++) {
|
||||
// Vector2[] pointsToDraw = m_segments [s];
|
||||
// PopulateMesh (vh, pointsToDraw);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
private UIVertex[] CreateLineCap(Vector2 start, Vector2 end, SegmentType type)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
/// - autoselect "firstSelectedGameObject" since it doesn't seem to work automatically
|
||||
/// Updated 08-29-15 - On request of Issue #13 on repo, added a manual navigation order.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UI.Extensions
|
||||
|
@ -16,15 +17,19 @@ namespace UnityEngine.UI.Extensions
|
|||
public class TabNavigationHelper : MonoBehaviour
|
||||
{
|
||||
private EventSystem _system;
|
||||
private Selectable StartingObject;
|
||||
private Selectable LastObject;
|
||||
private Selectable startingObject;
|
||||
private Selectable lastObject;
|
||||
|
||||
[Tooltip("The path to take when user is tabbing through ui components.")]
|
||||
public Selectable[] NavigationPath;
|
||||
|
||||
[Tooltip("Use the default Unity navigation system or a manual fixed order using Navigation Path")]
|
||||
public NavigationMode NavigationMode;
|
||||
|
||||
[Tooltip("If True, this will loop the tab order from last to first automatically")]
|
||||
public bool CircularNavigation;
|
||||
|
||||
|
||||
void Start()
|
||||
{
|
||||
_system = GetComponent<EventSystem>();
|
||||
|
@ -34,24 +39,35 @@ namespace UnityEngine.UI.Extensions
|
|||
}
|
||||
if (NavigationMode == NavigationMode.Manual && NavigationPath.Length > 0)
|
||||
{
|
||||
StartingObject = NavigationPath[0].gameObject.GetComponent<Selectable>();
|
||||
startingObject = NavigationPath[0].gameObject.GetComponent<Selectable>();
|
||||
}
|
||||
if (StartingObject == null && CircularNavigation)
|
||||
if (startingObject == null && CircularNavigation)
|
||||
{
|
||||
SelectDefaultObject(out StartingObject);
|
||||
SelectDefaultObject(out startingObject);
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
Selectable next = null;
|
||||
if (LastObject == null && _system.currentSelectedGameObject != null)
|
||||
if (lastObject == null && _system.currentSelectedGameObject != null)
|
||||
{
|
||||
var startingPoint = _system.currentSelectedGameObject.GetComponent<Selectable>();
|
||||
var selectableItems = new Stack<Selectable>();
|
||||
selectableItems.Push(startingPoint);
|
||||
|
||||
//Find the last selectable object
|
||||
next = _system.currentSelectedGameObject.GetComponent<Selectable>().FindSelectableOnDown();
|
||||
next = startingPoint.FindSelectableOnDown();
|
||||
while (next != null)
|
||||
{
|
||||
LastObject = next;
|
||||
if (selectableItems.Contains(next))
|
||||
{
|
||||
lastObject = selectableItems.Pop();
|
||||
selectableItems.Clear();
|
||||
break;
|
||||
}
|
||||
lastObject = next;
|
||||
selectableItems.Push(next);
|
||||
next = next.FindSelectableOnDown();
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +92,7 @@ namespace UnityEngine.UI.Extensions
|
|||
next = _system.currentSelectedGameObject.GetComponent<Selectable>().FindSelectableOnUp();
|
||||
if (next == null && CircularNavigation)
|
||||
{
|
||||
next = LastObject;
|
||||
next = lastObject;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -105,7 +121,7 @@ namespace UnityEngine.UI.Extensions
|
|||
next = _system.currentSelectedGameObject.GetComponent<Selectable>().FindSelectableOnDown();
|
||||
if (next == null && CircularNavigation)
|
||||
{
|
||||
next = StartingObject;
|
||||
next = startingObject;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -119,9 +135,9 @@ namespace UnityEngine.UI.Extensions
|
|||
SelectDefaultObject(out next);
|
||||
}
|
||||
|
||||
if (CircularNavigation && StartingObject == null)
|
||||
if (CircularNavigation && startingObject == null)
|
||||
{
|
||||
StartingObject = next;
|
||||
startingObject = next;
|
||||
}
|
||||
selectGameObject(next);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,11 @@ namespace UnityEngine.UI.Extensions
|
|||
public int verticalPadding;
|
||||
|
||||
//tooltip text
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
public TMPro.TMP_Text thisText;
|
||||
#else
|
||||
public Text thisText;
|
||||
#endif
|
||||
|
||||
//horizontal layout of the tooltip
|
||||
public HorizontalLayoutGroup hlG;
|
||||
|
|
|
@ -27,7 +27,11 @@ namespace UnityEngine.UI.Extensions
|
|||
public class ToolTip : MonoBehaviour
|
||||
{
|
||||
//text of the tooltip
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
private TMPro.TMP_Text _text;
|
||||
#else
|
||||
private Text _text;
|
||||
#endif
|
||||
private RectTransform _rectTransform, canvasRectTransform;
|
||||
|
||||
[Tooltip("The canvas used by the tooltip as positioning and scaling reference. Should usually be the root Canvas of the hierarchy this component is in")]
|
||||
|
@ -114,7 +118,11 @@ namespace UnityEngine.UI.Extensions
|
|||
canvasRectTransform = canvas.GetComponent<RectTransform>();
|
||||
_layoutGroup = GetComponentInChildren<LayoutGroup>();
|
||||
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
_text = GetComponentInChildren<TMPro.TMP_Text>();
|
||||
#else
|
||||
_text = GetComponentInChildren<Text>();
|
||||
#endif
|
||||
|
||||
_inside = false;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue