commit
8cbd1c3c1e
|
@ -0,0 +1 @@
|
||||||
|
* SimonDarksideJ
|
|
@ -0,0 +1,6 @@
|
||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: [SimonDarksideJ]
|
||||||
|
ko_fi: Ko-fi.com/uiextensions
|
||||||
|
issuehunt: simondarksidej
|
||||||
|
custom: https://paypal.me/unityuiextensions
|
|
@ -0,0 +1,44 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to identify a potential issue
|
||||||
|
title: 'BUG: '
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
# Unity UI Extensions Bug Report
|
||||||
|
|
||||||
|
## Describe the bug
|
||||||
|
<!-- Please provide a clear and concise description of what the bug is. -->
|
||||||
|
|
||||||
|
## To Reproduce
|
||||||
|
<!-- Include Steps to reproduce the behavior: -->
|
||||||
|
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
## Expected behavior
|
||||||
|
<!-- A clear and concise description of what you expected to happen. -->
|
||||||
|
|
||||||
|
## Actual behavior
|
||||||
|
<!-- What is actually happening -->
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||||
|
|
||||||
|
## Your Setup
|
||||||
|
<!-- please complete any/all the following information. -->
|
||||||
|
|
||||||
|
- **Operation System:**
|
||||||
|
- [ ] Windows
|
||||||
|
- [ ] MacOs
|
||||||
|
- [ ] Linux
|
||||||
|
- [ ] Other <!-- Please Specify Platform -->
|
||||||
|
- **Unity Version:** <!-- Please Specify Version --> 2020.3.15f
|
||||||
|
- **Unity UI Extensions Version**
|
||||||
|
- [ ] 2.3.0 <!-- Please Specify Version or commit sha -->
|
||||||
|
|
||||||
|
## Additional context
|
||||||
|
<!-- Add any other context about the problem here. -->
|
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for the Unity UI Extensions
|
||||||
|
title: 'Feature Request: '
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
# Unity UI Extensions Feature Request
|
||||||
|
|
||||||
|
## Is your feature request related to a problem? Please describe
|
||||||
|
|
||||||
|
<!--Please provide a clear and concise description of what the problem is.
|
||||||
|
E.g. I'm always frustrated when [...]-->
|
||||||
|
|
||||||
|
## How would you classify your suggestion
|
||||||
|
<!--What type of enhancement is it, e.g:-->
|
||||||
|
|
||||||
|
- New platform support
|
||||||
|
- Usability / Configuration
|
||||||
|
- Architecture / Services
|
||||||
|
|
||||||
|
## Describe the solution you'd like
|
||||||
|
<!--A clear and concise description of what you want to happen.-->
|
||||||
|
|
||||||
|
## Describe alternatives you've considered
|
||||||
|
<!--A clear and concise description of any alternative solutions or features you've considered.-->
|
||||||
|
|
||||||
|
## Additional context
|
||||||
|
<!--Add any other context or screenshots about the feature request here.-->
|
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
name: Request for Information
|
||||||
|
about: Not sure how to do something, just ask.
|
||||||
|
title: 'RFI: '
|
||||||
|
labels: question
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
# Unity UI Extensions Request for Information
|
||||||
|
|
||||||
|
<!-- As imperfect beings, we try to teach and show how to make using the framework easy to handle, but sometimes we will fall short. Help us to better educate adopters by pointing out where we need to give more information. -->
|
||||||
|
|
||||||
|
## What are you trying to achieve?
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Add a clear and concise description of what is it you are trying to implement.
|
||||||
|
Include screenshots or examples from other projects if it helps.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## What have you already tried
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Have you tried to complete the task yourself but couldn't figure it out, if so what and why?
|
||||||
|
-->
|
||||||
|
|
||||||
|
## What material have you referenced that didn't answer your question
|
||||||
|
|
||||||
|
<!--
|
||||||
|
What other content have you tried reading / viewing that didn't answer your question?
|
||||||
|
-->
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Unity UI Extensions - Pull Request
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
<!-- Please provide a clear and concise description of the pull request. -->
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
<!-- Brief list of the targeted features that are being changed. -->
|
||||||
|
|
||||||
|
- Fixes: <!--issue number or url-->
|
||||||
|
|
||||||
|
## Breaking Changes
|
||||||
|
<!-- Are there any breaking changes included in this change that would prevent or cause issue for existing projects? -->
|
||||||
|
|
||||||
|
- Breaks
|
||||||
|
|
||||||
|
## Related Submodule Changes
|
||||||
|
|
||||||
|
<!-- Include any submodule related Pull Request links here -->
|
||||||
|
- URL
|
||||||
|
|
||||||
|
## Testing status
|
||||||
|
<!-- Remove the options that do not apply -->
|
||||||
|
* No tests have been added.
|
||||||
|
* Includes unit tests.
|
||||||
|
* Includes performance tests.
|
||||||
|
* Includes integration tests.
|
||||||
|
|
||||||
|
### Manual testing status
|
||||||
|
<!-- Describe how you tested your implementation/fix. Try to mention all the cases and flows. -->
|
||||||
|
<!-- It will help the reviewer to understand if you missed any cases or test steps as well as will tell more about your feature or fix. -->
|
|
@ -0,0 +1,37 @@
|
||||||
|
name: Build and test UPM packages for platforms on all available Unity Versions
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches-ignore:
|
||||||
|
- 'release'
|
||||||
|
# Ignore PRs targetting main
|
||||||
|
|
||||||
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# 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
|
||||||
|
if: github.ref != 'refs/heads/development'
|
||||||
|
uses: ./.github/workflows/rununitysinglebuild.yml
|
||||||
|
with:
|
||||||
|
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~"]
|
[submodule "Examples~"]
|
||||||
path = Examples~
|
path = Examples~
|
||||||
url = https://SimonDarksideJ@bitbucket.org/UnityUIExtensions/unity-ui-extensions.git
|
url = https://github.com/Unity-UI-Extensions/com.unity.uiextensions-examples.git
|
||||||
branch = Examples
|
|
||||||
|
|
|
@ -35,6 +35,4 @@ sysinfo.txt
|
||||||
/.vs
|
/.vs
|
||||||
*.gitmodules
|
*.gitmodules
|
||||||
|
|
||||||
# NPM publish exclusions
|
**/.github/*
|
||||||
bitbucket-pipelines.yml
|
|
||||||
bitbucket-pipelines.yml.meta
|
|
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/).
|
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
|
> 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.
|
## Added
|
||||||
- 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
|
|
||||||
|
|
||||||
### 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.
|
- Clean-up and reset pivots on scene start.
|
||||||
- Fixed Sorting at min and max positions for ScrollRect
|
- Merged in feature/improved-ui-highlightable (pull request UILineRenderer - issues with specifying point locations at runtime #123).
|
||||||
- Updated ScrollToSelect script provided by zero3growlithe, tested and vastly reduces the previous jitter. Still present but barely noticeable now.
|
- Merged in fix/rangesliderfix (pull request HorizontalScrollSnap Mask Area doesn't work when content created dynamically #125).
|
||||||
- Fixed Issue # 363 Update Combobox control that takes multiple items programmatically, to only allow distinct items
|
- Merged in fix/infinitescrollcontentsize (pull request Gradient initialization should be in Awake() #126).
|
||||||
- Fixed the issues where dragging outside the range slider handle causes the range to update. - Resolves #369
|
- Merged in feature/controlTouchUp (pull request UILineRenderer mesh not updating in Editor scene view #127).
|
||||||
- Resolves an issue with Unity putting the previous controls vertex array in an uninitialised control.
|
- Upgraded RangeSlider to work in both Horizontal and Vertical setups.
|
||||||
- Applied J.R. Mitchell's fix for the Accordion Controls/Accordion/AccordionElement.cs - resolves: #364
|
- Merged in RangeSlider-upgrade. (pull request Newtonsoft.Json.dll conflict #131)
|
||||||
- Resolved issue where the Content Scroll snap issue with only 1 child. Resolves #362
|
- Updated UIVertical scroller to be 2022 compliant.
|
||||||
- Updated the PaginationManager to override if the ScrollSnap is in motion.
|
- 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
|
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
|
- 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.
|
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.
|
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.
|
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.
|
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)
|
[Check out our Tumblr page for a sneak peek](https://www.tumblr.com/blog/unityuiextensions)
|
||||||
|
|
||||||
> Contact the UI Extensions Team
|
You can follow the UI Extensions team for updates and news on:
|
||||||
> 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
|
### [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
|
# Installing Unity UI Extensions
|
||||||
|
|
||||||
To install this package, follow the instructions in the Package Manager documentation.
|
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
|
# 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.
|
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
|
# 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:
|
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.
|
> 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
|
To get up to speed with the Unity UI Extensions, check out the [Getting Started](https://unity-ui-extensions.github.io/GettingStarted.html) Page.
|
||||||
- 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
|
|
||||||
|
|
||||||
#### 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
|
## Breaking changes
|
||||||
- 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.
|
|
||||||
|
|
||||||
#### 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
|
## Added
|
||||||
- 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
|
|
||||||
|
|
||||||
#### 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
|
# Document revision history
|
||||||
|
|
||||||
|
@ -98,3 +139,4 @@ None
|
||||||
|September 3rd, 2019|2019.1 (v2.1) released, First major update for the 2.0 series.|
|
|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.|
|
|August 8th, 2020|2019.4 (v2.2) released, New UPM Delivery.|
|
||||||
|October 10th, 2020|2019.5 (v2.2) released, New UPM fast 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,12 +1,11 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 8701e045b26e51f4eb345f2ccb3c13f5
|
guid: c1047f9974e7ee1478bbf5490a7a62d8
|
||||||
timeCreated: 1426804458
|
MonoImporter:
|
||||||
licenseType: Free
|
externalObjects: {}
|
||||||
MonoImporter:
|
serializedVersion: 2
|
||||||
serializedVersion: 2
|
defaultReferences: []
|
||||||
defaultReferences: []
|
executionOrder: 0
|
||||||
executionOrder: 0
|
icon: {instanceID: 0}
|
||||||
icon: {instanceID: 0}
|
userData:
|
||||||
userData:
|
assetBundleName:
|
||||||
assetBundleName:
|
assetBundleVariant:
|
||||||
assetBundleVariant:
|
|
||||||
|
|
|
@ -68,7 +68,12 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
Handles.color = Color.gray;
|
Handles.color = Color.gray;
|
||||||
EditorGUI.BeginChangeCheck();
|
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);
|
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"));
|
Handles.Label(newCornerPos, string.Format("Corner Mover"));
|
||||||
|
|
||||||
newCornerPos = script.transform.InverseTransformPoint(newCornerPos);
|
newCornerPos = script.transform.InverseTransformPoint(newCornerPos);
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEditor.AnimatedValues;
|
using UnityEditor.AnimatedValues;
|
||||||
|
|
||||||
// For maintenance, every new [SerializeField] variable in Scroller must be declared here
|
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
[CustomEditor(typeof(Scroller))]
|
[CustomEditor(typeof(Scroller))]
|
||||||
|
@ -20,16 +18,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
SerializedProperty inertia;
|
SerializedProperty inertia;
|
||||||
SerializedProperty decelerationRate;
|
SerializedProperty decelerationRate;
|
||||||
SerializedProperty snap;
|
SerializedProperty snap;
|
||||||
SerializedProperty snapEnable;
|
|
||||||
SerializedProperty snapVelocityThreshold;
|
|
||||||
SerializedProperty snapDuration;
|
|
||||||
SerializedProperty snapEasing;
|
|
||||||
SerializedProperty draggable;
|
SerializedProperty draggable;
|
||||||
SerializedProperty scrollbar;
|
SerializedProperty scrollbar;
|
||||||
|
|
||||||
AnimBool showElasticity;
|
AnimBool showElasticity;
|
||||||
AnimBool showInertiaRelatedValues;
|
AnimBool showInertiaRelatedValues;
|
||||||
AnimBool showSnapEnableRelatedValues;
|
|
||||||
|
|
||||||
void OnEnable()
|
void OnEnable()
|
||||||
{
|
{
|
||||||
|
@ -41,16 +34,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
inertia = serializedObject.FindProperty("inertia");
|
inertia = serializedObject.FindProperty("inertia");
|
||||||
decelerationRate = serializedObject.FindProperty("decelerationRate");
|
decelerationRate = serializedObject.FindProperty("decelerationRate");
|
||||||
snap = serializedObject.FindProperty("snap");
|
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");
|
draggable = serializedObject.FindProperty("draggable");
|
||||||
scrollbar = serializedObject.FindProperty("scrollbar");
|
scrollbar = serializedObject.FindProperty("scrollbar");
|
||||||
|
|
||||||
showElasticity = new AnimBool(Repaint);
|
showElasticity = new AnimBool(Repaint);
|
||||||
showInertiaRelatedValues = new AnimBool(Repaint);
|
showInertiaRelatedValues = new AnimBool(Repaint);
|
||||||
showSnapEnableRelatedValues = new AnimBool(Repaint);
|
|
||||||
SetAnimBools(true);
|
SetAnimBools(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,14 +46,12 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
showElasticity.valueChanged.RemoveListener(Repaint);
|
showElasticity.valueChanged.RemoveListener(Repaint);
|
||||||
showInertiaRelatedValues.valueChanged.RemoveListener(Repaint);
|
showInertiaRelatedValues.valueChanged.RemoveListener(Repaint);
|
||||||
showSnapEnableRelatedValues.valueChanged.RemoveListener(Repaint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetAnimBools(bool instant)
|
void SetAnimBools(bool instant)
|
||||||
{
|
{
|
||||||
SetAnimBool(showElasticity, !movementType.hasMultipleDifferentValues && movementType.enumValueIndex == (int)MovementType.Elastic, instant);
|
SetAnimBool(showElasticity, !movementType.hasMultipleDifferentValues && movementType.enumValueIndex == (int)MovementType.Elastic, instant);
|
||||||
SetAnimBool(showInertiaRelatedValues, !inertia.hasMultipleDifferentValues && inertia.boolValue, instant);
|
SetAnimBool(showInertiaRelatedValues, !inertia.hasMultipleDifferentValues && inertia.boolValue, instant);
|
||||||
SetAnimBool(showSnapEnableRelatedValues, !snapEnable.hasMultipleDifferentValues && snapEnable.boolValue, instant);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetAnimBool(AnimBool a, bool value, bool instant)
|
void SetAnimBool(AnimBool a, bool value, bool instant)
|
||||||
|
@ -126,31 +112,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
EditorGUILayout.PropertyField(decelerationRate);
|
EditorGUILayout.PropertyField(decelerationRate);
|
||||||
EditorGUILayout.PropertyField(snap);
|
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:
|
|
@ -3,10 +3,12 @@
|
||||||
|
|
||||||
// For maintenance, every new [SerializeField] variable in ScrollPositionController must be declared here
|
// For maintenance, every new [SerializeField] variable in ScrollPositionController must be declared here
|
||||||
|
|
||||||
|
using System;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
|
[Obsolete("ScrollPositionController has been replaced by the Scroller component", true)]
|
||||||
[CustomEditor(typeof(ScrollPositionController))]
|
[CustomEditor(typeof(ScrollPositionController))]
|
||||||
[CanEditMultipleObjects]
|
[CanEditMultipleObjects]
|
||||||
public class ScrollPositionControllerEditor : Editor
|
public class ScrollPositionControllerEditor : Editor
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "UnityUIExtensions.editor",
|
"name": "UnityUIExtensions.editor",
|
||||||
|
"rootNamespace": "",
|
||||||
"references": [
|
"references": [
|
||||||
"GUID:343deaaf83e0cee4ca978e7df0b80d21",
|
"GUID:343deaaf83e0cee4ca978e7df0b80d21",
|
||||||
"GUID:2bafac87e7f4b9b418d9448d219b01ab",
|
"GUID:2bafac87e7f4b9b418d9448d219b01ab",
|
||||||
"GUID:cf414061cae3a954baf92763590f3127"
|
"GUID:cf414061cae3a954baf92763590f3127",
|
||||||
|
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||||
|
"GUID:75469ad4d38634e559750d17036d5f7c"
|
||||||
],
|
],
|
||||||
"includePlatforms": [
|
"includePlatforms": [
|
||||||
"Editor"
|
"Editor"
|
||||||
|
@ -14,5 +17,6 @@
|
||||||
"precompiledReferences": [],
|
"precompiledReferences": [],
|
||||||
"autoReferenced": true,
|
"autoReferenced": true,
|
||||||
"defineConstraints": [],
|
"defineConstraints": [],
|
||||||
"versionDefines": []
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
}
|
}
|
|
@ -1 +1 @@
|
||||||
Subproject commit d08257d62c3c95771540f51f77f50a491715d3b7
|
Subproject commit 774bde78bf8792ad8de1c96ad7e874932fd716d7
|
244
README.md
244
README.md
|
@ -1,10 +1,10 @@
|
||||||
# Unity UI Extensions README
|
# 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/)
|
> [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:
|
For more info, here's a little introduction video for the project:
|
||||||
|
|
||||||
|
@ -12,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:
|
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.
|
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.
|
||||||
|
|
||||||
|
@ -28,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:
|
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.
|
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**
|
> 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) |
|
| [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)
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
@ -50,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**
|
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)
|
> (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:
|
To get started with the project, here's a little guide:
|
||||||
|
|
||||||
|
@ -66,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
|
> 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.
|
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.
|
||||||
- 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
|
|
||||||
|
|
||||||
### 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.
|
- Added new FIFO based UI Line Render when dynamic line rendering is needed.
|
||||||
- Fixed Sorting at min and max positions for ScrollRect
|
- Added ResetSelectableHighlight component.
|
||||||
- Updated ScrollToSelect script provided by zero3growlithe, tested and vastly reduces the previous jitter. Still present but barely noticeable now.
|
- Added SetArc method to UICircle as requested.
|
||||||
- Fixed Issue # 363 Update Combobox control that takes multiple items programmatically, to only allow distinct items
|
- Added new UIHorizontalScroller based on UIVerticalScroller.
|
||||||
- Fixed the issues where dragging outside the range slider handle causes the range to update. - Resolves #369
|
- Added OnHighlightChanged and OnPressChanged events for UI Button.
|
||||||
- Resolves an issue with Unity putting the previous controls vertex array in an uninitialised control.
|
- Added error handling around setting Unity UI Components for Vertical/Horizontal ScrollSnaps.
|
||||||
- Applied J.R. Mitchell's fix for the Accordion Controls/Accordion/AccordionElement.cs - resolves: #364
|
- Added Editor Menu Option to create a Min/Max slider.
|
||||||
- Resolved issue where the Content Scroll snap issue with only 1 child. Resolves #362
|
- Added the ability to set a specific item for combobox controls on start and not just the first.
|
||||||
- Updated the PaginationManager to override if the ScrollSnap is in motion.
|
- 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
|
## Upgrade Notes
|
||||||
|
|
||||||
|
@ -129,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.
|
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:
|
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)
|
> ## [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 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)|||||
|
[Controls](https://unity-ui-extensions.github.io/Controls.html#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|
|
|
||||||
||||
|
|
||||||
|
|
||||||
[Primitives](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Controls#markdown-header-primitives)|||||
|
|Accordion|ColorPicker|Selection Box|UI Flippable|ComboBox|
|
||||||
------|------|------|------|------|
|
|-|-|-|-|-|
|
||||||
UILineRenderer|UILineTextureRenderer|UICircle|DiamondGraph|UICornerCut
|
|AutoComplete ComboBox|DropDown List|BoundToolTip|UIWindowBase|UI Knob|
|
||||||
UIPolygon||||
|
|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)|||||
|
[Primitives](https://unity-ui-extensions.github.io/Controls.html#primitives)
|
||||||
------|------|------|------|------|
|
|
||||||
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||
|
|
||||||
||||
|
|
||||||
|
|
||||||
[Effects](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Controls#markdown-header-effect_components)|||||
|
|UILineRenderer|UILineTextureRenderer|UICircle|DiamondGraph|UICornerCut|
|
||||||
------|------|------|------|------|
|
|-|-|-|-|-|
|
||||||
Best Fit Outline|Curved Text|Gradient|Gradient2|Letter Spacing
|
|UIPolygon|UISquircle||||
|
||||||
NicerOutline|RaycastMask|UIFlippable|UIImageCrop|SoftAlphaMask
|
|
||||||
CylinderText|UIParticleSystem|CurlyUI|Shine Effect|Shader Effects
|
|
||||||
||||
|
|
||||||
|
|
||||||
[Additional Components](https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/wiki/Controls#markdown-header-additional_components)|||||
|
[Layouts](https://unity-ui-extensions.github.io/Controls.html#layouts)
|
||||||
------|------|------|------|------|
|
|
||||||
ReturnKeyTrigger|TabNavigation|uGUITools|ScrollRectTweener|ScrollRectLinker
|
|Horizontal Scroll Snap|Vertical Scroll Snap|Flow Layout Group|Radial Layout|Tile Size Fitter|
|
||||||
ScrollRectEx|UI_InfiniteScroll|UI_ScrollRectOcclusion|UIScrollToSelection|UISelectableExtension
|
|-|-|-|-|-|
|
||||||
switchToRectTransform|ScrollConflictManager|CLFZ2 (Encryption)|DragCorrector|PPIViewer
|
|Scroll Snap (alt implementation)|Reorderable List|UI Vertical Scroller|Curved Layout|Table Layout|
|
||||||
UI_TweenScale|UI_MagneticInfiniteScroll|UI_ScrollRectOcclusion|NonDrawingGraphic|
|
|FancyScrollView|Card UI|Scroll Position Controller (obsolete)|Content Scroll Snap Horizontal|Scroller|
|
||||||
UILineConnector|UIHighlightable|Menu Manager|Pagination Manager|
|
|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*
|
*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
|
New for 2020, we have added OpenUPM support and the package can be installed using the following [OpenUPM CLI](https://openupm.com/docs/) command:
|
||||||
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.
|
|
||||||
|
|
||||||
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
|
- 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.
|
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.
|
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:
|
Just ensure:
|
||||||
|
|
||||||
|
@ -209,21 +253,21 @@ Just ensure:
|
||||||
* The script uses the **Unity.UI.Extensions** namespace so they do not affect any other developments.
|
* 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)
|
* (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
|
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.
|
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.
|
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.
|
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;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
sampler2D_float _CameraDepthTexture;
|
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||||
float _InvFade;
|
float _InvFade;
|
||||||
|
|
||||||
fixed4 frag (v2f IN) : SV_Target
|
fixed4 frag (v2f IN) : SV_Target
|
||||||
|
|
|
@ -82,7 +82,7 @@ Category {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
sampler2D_float _CameraDepthTexture;
|
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||||
float _InvFade;
|
float _InvFade;
|
||||||
|
|
||||||
fixed4 frag (v2f i) : SV_Target
|
fixed4 frag (v2f i) : SV_Target
|
||||||
|
|
|
@ -2,8 +2,7 @@ Shader "UI Extensions/Particles/Additive (Soft)" {
|
||||||
Properties {
|
Properties {
|
||||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||||
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
|
_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
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
_StencilOp ("Stencil Operation", Float) = 0
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
@ -81,7 +80,7 @@ Category {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
sampler2D_float _CameraDepthTexture;
|
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||||
float _InvFade;
|
float _InvFade;
|
||||||
|
|
||||||
fixed4 frag (v2f i) : SV_Target
|
fixed4 frag (v2f i) : SV_Target
|
||||||
|
|
|
@ -3,8 +3,7 @@ Properties {
|
||||||
_TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
|
_TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
|
||||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||||
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
|
_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
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
_StencilOp ("Stencil Operation", Float) = 0
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
@ -82,7 +81,7 @@ Category {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
sampler2D_float _CameraDepthTexture;
|
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||||
float _InvFade;
|
float _InvFade;
|
||||||
|
|
||||||
fixed4 frag (v2f i) : SV_Target
|
fixed4 frag (v2f i) : SV_Target
|
||||||
|
|
|
@ -2,8 +2,7 @@ Shader "UI Extensions/Particles/Blend" {
|
||||||
Properties {
|
Properties {
|
||||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||||
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
|
_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
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
_StencilOp ("Stencil Operation", Float) = 0
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
@ -81,7 +80,7 @@ Category {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
sampler2D_float _CameraDepthTexture;
|
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||||
float _InvFade;
|
float _InvFade;
|
||||||
|
|
||||||
fixed4 frag (v2f i) : SV_Target
|
fixed4 frag (v2f i) : SV_Target
|
||||||
|
|
|
@ -2,8 +2,7 @@ Shader "UI Extensions/Particles/Multiply" {
|
||||||
Properties {
|
Properties {
|
||||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||||
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
|
_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
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
_StencilOp ("Stencil Operation", Float) = 0
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
@ -80,7 +79,7 @@ Category {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
sampler2D_float _CameraDepthTexture;
|
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||||
float _InvFade;
|
float _InvFade;
|
||||||
|
|
||||||
fixed4 frag (v2f i) : SV_Target
|
fixed4 frag (v2f i) : SV_Target
|
||||||
|
|
|
@ -2,8 +2,7 @@ Shader "UI Extensions/Particles/Multiply (Double)" {
|
||||||
Properties {
|
Properties {
|
||||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||||
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
|
_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
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
_StencilOp ("Stencil Operation", Float) = 0
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
@ -81,7 +80,7 @@ Category {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
sampler2D_float _CameraDepthTexture;
|
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||||
float _InvFade;
|
float _InvFade;
|
||||||
|
|
||||||
fixed4 frag (v2f i) : SV_Target
|
fixed4 frag (v2f i) : SV_Target
|
||||||
|
|
|
@ -3,8 +3,7 @@ Properties {
|
||||||
|
|
||||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||||
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
|
_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
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
_StencilOp ("Stencil Operation", Float) = 0
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
@ -82,7 +81,7 @@ Category {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
sampler2D_float _CameraDepthTexture;
|
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||||
float _InvFade;
|
float _InvFade;
|
||||||
|
|
||||||
fixed4 frag (v2f IN) : SV_Target
|
fixed4 frag (v2f IN) : SV_Target
|
||||||
|
|
|
@ -3,7 +3,7 @@ Properties {
|
||||||
_EmisColor ("Emissive Color", Color) = (.2,.2,.2,0)
|
_EmisColor ("Emissive Color", Color) = (.2,.2,.2,0)
|
||||||
_MainTex ("Particle Texture", 2D) = "white" {}
|
_MainTex ("Particle Texture", 2D) = "white" {}
|
||||||
|
|
||||||
_StencilComp ("Stencil Comparison", Float) = 8
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
_Stencil ("Stencil ID", Float) = 0
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
_StencilOp ("Stencil Operation", Float) = 0
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
|
|
@ -5,83 +5,89 @@
|
||||||
namespace UnityEngine.UI.Extensions.ColorPicker
|
namespace UnityEngine.UI.Extensions.ColorPicker
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
[RequireComponent(typeof(TMPro.TMP_Text))]
|
||||||
|
#else
|
||||||
[RequireComponent(typeof(Text))]
|
[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
|
#endif
|
||||||
|
public class ColorLabel : MonoBehaviour
|
||||||
private void ColorChanged(Color color)
|
|
||||||
{
|
{
|
||||||
UpdateValue();
|
public ColorPickerControl picker;
|
||||||
}
|
|
||||||
|
|
||||||
private void HSVChanged(float hue, float sateration, float value)
|
public ColorValues type;
|
||||||
{
|
|
||||||
UpdateValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateValue()
|
public string prefix = "R: ";
|
||||||
{
|
public float minValue = 0;
|
||||||
if (picker == null)
|
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
|
fileFormatVersion: 2
|
||||||
guid: 06851a815227e5044b0e3c1bf9b3a282
|
guid: dea5b3bc15f78d04d8dcae27500f784e
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
defaultReferences: []
|
defaultReferences: []
|
||||||
executionOrder: 0
|
executionOrder: 0
|
||||||
icon: {instanceID: 0}
|
icon: {instanceID: 0}
|
||||||
userData:
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
|
@ -59,7 +59,9 @@ namespace UnityEngine.UI.Extensions.ColorPicker
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
if (image.texture != null)
|
if (image.texture != null)
|
||||||
|
{
|
||||||
DestroyImmediate(image.texture);
|
DestroyImmediate(image.texture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: ff46fbecea7739f4690e4285c88f53c5
|
guid: 9d3cae3318559ae449731a7db00c9bdd
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
serializedVersion: 2
|
externalObjects: {}
|
||||||
defaultReferences: []
|
serializedVersion: 2
|
||||||
executionOrder: 0
|
defaultReferences: []
|
||||||
icon: {instanceID: 0}
|
executionOrder: 0
|
||||||
userData:
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 3d95ce8fba3dbbf4eb14411412169b88
|
guid: 97950dcfb7ac51c4c95431d68ad7bea5
|
||||||
timeCreated: 1442747317
|
MonoImporter:
|
||||||
licenseType: Free
|
externalObjects: {}
|
||||||
MonoImporter:
|
serializedVersion: 2
|
||||||
serializedVersion: 2
|
defaultReferences: []
|
||||||
defaultReferences: []
|
executionOrder: 0
|
||||||
executionOrder: 0
|
icon: {instanceID: 0}
|
||||||
icon: {instanceID: 0}
|
userData:
|
||||||
userData:
|
assetBundleName:
|
||||||
assetBundleName:
|
assetBundleVariant:
|
||||||
assetBundleVariant:
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 4f3189246d7fc204faba7a1e9c08e0af
|
guid: 0e93d154602ed7e4787f2a7b9d3101b0
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
defaultReferences: []
|
defaultReferences: []
|
||||||
executionOrder: 0
|
executionOrder: 0
|
||||||
icon: {instanceID: 0}
|
icon: {instanceID: 0}
|
||||||
userData:
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
|
@ -7,95 +7,95 @@ namespace UnityEngine.UI.Extensions.ColorPicker
|
||||||
{
|
{
|
||||||
|
|
||||||
[RequireComponent(typeof(InputField))]
|
[RequireComponent(typeof(InputField))]
|
||||||
public class HexColorField : MonoBehaviour
|
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()
|
|
||||||
{
|
{
|
||||||
hexInputField = GetComponent<InputField>();
|
public ColorPickerControl ColorPicker;
|
||||||
|
|
||||||
// Add listeners to keep text (and color) up to date
|
public bool displayAlpha;
|
||||||
hexInputField.onEndEdit.AddListener(UpdateColor);
|
|
||||||
ColorPicker.onValueChanged.AddListener(UpdateHex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDestroy()
|
private InputField hexInputField;
|
||||||
{
|
|
||||||
hexInputField.onValueChanged.RemoveListener(UpdateColor);
|
|
||||||
ColorPicker.onValueChanged.RemoveListener(UpdateHex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateHex(Color newColor)
|
private const string hexRegex = "^#?(?:[0-9a-fA-F]{3,4}){1,2}$";
|
||||||
{
|
|
||||||
hexInputField.text = ColorToHex(newColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateColor(string newHex)
|
private void Awake()
|
||||||
{
|
|
||||||
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;
|
hexInputField = GetComponent<InputField>();
|
||||||
|
|
||||||
if (hex.Length == startIndex + 8) //#RRGGBBAA
|
// Add listeners to keep text (and color) up to date
|
||||||
{
|
hexInputField.onEndEdit.AddListener(UpdateColor);
|
||||||
color = new Color32(byte.Parse(hex.Substring(startIndex, 2), NumberStyles.AllowHexSpecifier),
|
ColorPicker.onValueChanged.AddListener(UpdateHex);
|
||||||
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
|
|
||||||
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
color = new Color32();
|
hexInputField.onValueChanged.RemoveListener(UpdateColor);
|
||||||
return false;
|
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()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
if (image.texture != null)
|
if (image.texture != null)
|
||||||
|
{
|
||||||
DestroyImmediate(image.texture);
|
DestroyImmediate(image.texture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
///Credit perchik
|
///Credit perchik
|
||||||
///Sourced from - http://forum.unity3d.com/threads/receive-onclick-event-and-pass-it-on-to-lower-ui-elements.293642/
|
///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.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
|
@ -13,10 +14,9 @@ namespace UnityEngine.UI.Extensions
|
||||||
}
|
}
|
||||||
|
|
||||||
[RequireComponent(typeof(RectTransform))]
|
[RequireComponent(typeof(RectTransform))]
|
||||||
[AddComponentMenu("UI/Extensions/AutoComplete ComboBox")]
|
[AddComponentMenu("UI/Extensions/ComboBox/AutoComplete ComboBox")]
|
||||||
public class AutoCompleteComboBox : MonoBehaviour
|
public class AutoCompleteComboBox : 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; } //outside world gets to get this, not set it
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -24,17 +24,15 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// <see cref="RemoveItem(string)"/> and <see cref="SetAvailableOptions(List{string})"/> methods as these also execute
|
/// <see cref="RemoveItem(string)"/> and <see cref="SetAvailableOptions(List{string})"/> methods as these also execute
|
||||||
/// the required methods to update to the current collection.
|
/// the required methods to update to the current collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Header("AutoComplete Box Items")]
|
||||||
public List<string> AvailableOptions;
|
public List<string> AvailableOptions;
|
||||||
|
|
||||||
//private bool isInitialized = false;
|
|
||||||
private bool _isPanelActive = false;
|
private bool _isPanelActive = false;
|
||||||
private bool _hasDrawnOnce = false;
|
private bool _hasDrawnOnce = false;
|
||||||
|
|
||||||
private InputField _mainInput;
|
private InputField _mainInput;
|
||||||
private RectTransform _inputRT;
|
private RectTransform _inputRT;
|
||||||
|
|
||||||
//private Button _arrow_Button;
|
|
||||||
|
|
||||||
private RectTransform _rectTransform;
|
private RectTransform _rectTransform;
|
||||||
|
|
||||||
private RectTransform _overlayRT;
|
private RectTransform _overlayRT;
|
||||||
|
@ -52,11 +50,16 @@ namespace UnityEngine.UI.Extensions
|
||||||
private List<string> _prunedPanelItems; //items that used to show in the drop-down
|
private List<string> _prunedPanelItems; //items that used to show in the drop-down
|
||||||
|
|
||||||
private Dictionary<string, GameObject> panelObjects;
|
private Dictionary<string, GameObject> panelObjects;
|
||||||
|
|
||||||
private GameObject itemTemplate;
|
private GameObject itemTemplate;
|
||||||
|
private bool _initialized;
|
||||||
|
|
||||||
public string Text { get; private set; }
|
public string Text { get; private set; }
|
||||||
|
|
||||||
|
[Header("Properties")]
|
||||||
|
[SerializeField]
|
||||||
|
private bool isActive = true;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private float _scrollBarWidth = 20.0f;
|
private float _scrollBarWidth = 20.0f;
|
||||||
public float ScrollBarWidth
|
public float ScrollBarWidth
|
||||||
|
@ -69,9 +72,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private int scrollOffset; //offset of the selected item
|
|
||||||
// private int _selectedIndex = 0;
|
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int _itemsToDisplay;
|
private int _itemsToDisplay;
|
||||||
public 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")]
|
[Tooltip("Change input text color based on matching items")]
|
||||||
private bool _ChangeInputTextColorBasedOnMatchingItems = false;
|
private bool _ChangeInputTextColorBasedOnMatchingItems = false;
|
||||||
public bool InputColorMatching{
|
public bool InputColorMatching
|
||||||
get { return _ChangeInputTextColorBasedOnMatchingItems; }
|
{
|
||||||
set
|
get { return _ChangeInputTextColorBasedOnMatchingItems; }
|
||||||
{
|
set
|
||||||
_ChangeInputTextColorBasedOnMatchingItems = value;
|
{
|
||||||
if (_ChangeInputTextColorBasedOnMatchingItems) {
|
_ChangeInputTextColorBasedOnMatchingItems = value;
|
||||||
SetInputTextColor ();
|
if (_ChangeInputTextColorBasedOnMatchingItems)
|
||||||
}
|
{
|
||||||
}
|
SetInputTextColor();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public float DropdownOffset = 10f;
|
public float DropdownOffset = 10f;
|
||||||
|
|
||||||
//TODO design as foldout for Inspector
|
|
||||||
public Color ValidSelectionTextColor = Color.green;
|
public Color ValidSelectionTextColor = Color.green;
|
||||||
public Color MatchingItemsRemainingTextColor = Color.black;
|
public Color MatchingItemsRemainingTextColor = Color.black;
|
||||||
public Color NoItemsRemainingTextColor = Color.red;
|
public Color NoItemsRemainingTextColor = Color.red;
|
||||||
|
|
||||||
public AutoCompleteSearchType autocompleteSearchType = AutoCompleteSearchType.Linq;
|
public AutoCompleteSearchType autocompleteSearchType = AutoCompleteSearchType.Linq;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private float dropdownOffset;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private bool _displayPanelAbove = false;
|
private bool _displayPanelAbove = false;
|
||||||
|
|
||||||
|
public bool SelectFirstItemOnStart = false;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private int selectItemIndexOnStart = 0;
|
||||||
|
|
||||||
|
private bool shouldSelectItemOnStart => SelectFirstItemOnStart || selectItemIndexOnStart > 0;
|
||||||
|
|
||||||
private bool _selectionIsValid = false;
|
private bool _selectionIsValid = false;
|
||||||
|
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public class SelectionChangedEvent : UnityEngine.Events.UnityEvent<string, bool> {
|
public class SelectionChangedEvent : Events.UnityEvent<string, bool> { }
|
||||||
}
|
|
||||||
|
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public class SelectionTextChangedEvent : UnityEngine.Events.UnityEvent<string> {
|
public class SelectionTextChangedEvent : Events.UnityEvent<string> { }
|
||||||
}
|
|
||||||
|
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public class SelectionValidityChangedEvent : UnityEngine.Events.UnityEvent<bool> {
|
public class SelectionValidityChangedEvent : Events.UnityEvent<bool> { }
|
||||||
}
|
|
||||||
|
|
||||||
// fires when input text is changed;
|
[System.Serializable]
|
||||||
public SelectionTextChangedEvent OnSelectionTextChanged;
|
public class ControlDisabledEvent : Events.UnityEvent<bool> { }
|
||||||
// fires when an Item gets selected / deselected (including when items are added/removed once this is possible)
|
|
||||||
public SelectionValidityChangedEvent OnSelectionValidityChanged;
|
// fires when input text is changed;
|
||||||
// fires in both cases
|
[Header("Events")]
|
||||||
public SelectionChangedEvent OnSelectionChanged;
|
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()
|
public void Awake()
|
||||||
{
|
{
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
if (SelectFirstItemOnStart && AvailableOptions.Count > 0) {
|
if (shouldSelectItemOnStart && AvailableOptions.Count > 0)
|
||||||
ToggleDropdownPanel (false);
|
{
|
||||||
OnItemClicked (AvailableOptions [0]);
|
SelectItemIndex(SelectFirstItemOnStart ? 0 : selectItemIndexOnStart);
|
||||||
}
|
}
|
||||||
RedrawPanel();
|
RedrawPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Initialize()
|
private bool Initialize()
|
||||||
{
|
{
|
||||||
|
if (_initialized) return true;
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -156,8 +170,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
_inputRT = _rectTransform.Find("InputField").GetComponent<RectTransform>();
|
_inputRT = _rectTransform.Find("InputField").GetComponent<RectTransform>();
|
||||||
_mainInput = _inputRT.GetComponent<InputField>();
|
_mainInput = _inputRT.GetComponent<InputField>();
|
||||||
|
|
||||||
//_arrow_Button = _rectTransform.FindChild ("ArrowBtn").GetComponent<Button> ();
|
|
||||||
|
|
||||||
_overlayRT = _rectTransform.Find("Overlay").GetComponent<RectTransform>();
|
_overlayRT = _rectTransform.Find("Overlay").GetComponent<RectTransform>();
|
||||||
_overlayRT.gameObject.SetActive(false);
|
_overlayRT.gameObject.SetActive(false);
|
||||||
|
|
||||||
|
@ -167,7 +179,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
_slidingAreaRT = _scrollBarRT.Find("SlidingArea").GetComponent<RectTransform>();
|
_slidingAreaRT = _scrollBarRT.Find("SlidingArea").GetComponent<RectTransform>();
|
||||||
_scrollHandleRT = _slidingAreaRT.Find("Handle").GetComponent<RectTransform>();
|
_scrollHandleRT = _slidingAreaRT.Find("Handle").GetComponent<RectTransform>();
|
||||||
_itemsPanelRT = _scrollPanelRT.Find("Items").GetComponent<RectTransform>();
|
_itemsPanelRT = _scrollPanelRT.Find("Items").GetComponent<RectTransform>();
|
||||||
//itemPanelLayout = itemsPanelRT.gameObject.GetComponent<LayoutGroup>();
|
|
||||||
|
|
||||||
_canvas = GetComponentInParent<Canvas>();
|
_canvas = GetComponentInParent<Canvas>();
|
||||||
_canvasRT = _canvas.GetComponent<RectTransform>();
|
_canvasRT = _canvas.GetComponent<RectTransform>();
|
||||||
|
@ -191,6 +202,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
_prunedPanelItems = new List<string>();
|
_prunedPanelItems = new List<string>();
|
||||||
_panelItems = new List<string>();
|
_panelItems = new List<string>();
|
||||||
|
|
||||||
|
_initialized = true;
|
||||||
|
|
||||||
RebuildPanel();
|
RebuildPanel();
|
||||||
return success;
|
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>
|
/// <summary>
|
||||||
/// Sets the given items as new content for the comboBox. Previous entries will be cleared.
|
/// Sets the given items as new content for the comboBox. Previous entries will be cleared.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="newOptions">New entries.</param>
|
/// <param name="newOptions">New entries.</param>
|
||||||
public void SetAvailableOptions(List<string> newOptions)
|
public void SetAvailableOptions(List<string> newOptions)
|
||||||
{
|
{
|
||||||
var uniqueOptions = newOptions.Distinct().ToList();
|
var uniqueOptions = newOptions.Distinct().ToArray();
|
||||||
if (newOptions.Count != uniqueOptions.Count)
|
SetAvailableOptions(uniqueOptions);
|
||||||
{
|
|
||||||
Debug.LogWarning($"{nameof(AutoCompleteComboBox)}.{nameof(SetAvailableOptions)}: items may only exists once. {newOptions.Count - uniqueOptions.Count} duplicates.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.AvailableOptions.Clear();
|
|
||||||
this.AvailableOptions = uniqueOptions;
|
|
||||||
this.RebuildPanel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -255,18 +272,21 @@ namespace UnityEngine.UI.Extensions
|
||||||
}
|
}
|
||||||
|
|
||||||
this.AvailableOptions.Clear();
|
this.AvailableOptions.Clear();
|
||||||
|
|
||||||
for (int i = 0; i < newOptions.Length; i++)
|
for (int i = 0; i < newOptions.Length; i++)
|
||||||
{
|
{
|
||||||
this.AvailableOptions.Add(newOptions[i]);
|
this.AvailableOptions.Add(newOptions[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.RebuildPanel();
|
this.RebuildPanel();
|
||||||
|
this.RedrawPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetItems()
|
public void ResetItems()
|
||||||
{
|
{
|
||||||
AvailableOptions.Clear();
|
AvailableOptions.Clear();
|
||||||
RebuildPanel();
|
RebuildPanel();
|
||||||
|
RedrawPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -274,6 +294,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void RebuildPanel()
|
private void RebuildPanel()
|
||||||
{
|
{
|
||||||
|
if (!_initialized)
|
||||||
|
{
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
if (_isPanelActive) ToggleDropdownPanel();
|
if (_isPanelActive) ToggleDropdownPanel();
|
||||||
|
|
||||||
//panel starts with all options
|
//panel starts with all options
|
||||||
|
@ -310,8 +335,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
if (i < AvailableOptions.Count)
|
if (i < AvailableOptions.Count)
|
||||||
{
|
{
|
||||||
itemObjs[i].name = "Item " + i + " " + _panelItems[i];
|
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
|
itemObjs[i].transform.Find("Text").GetComponent<Text>().text = AvailableOptions[i]; //set the text value
|
||||||
|
#endif
|
||||||
Button itemBtn = itemObjs[i].GetComponent<Button>();
|
Button itemBtn = itemObjs[i].GetComponent<Button>();
|
||||||
itemBtn.onClick.RemoveAllListeners();
|
itemBtn.onClick.RemoveAllListeners();
|
||||||
string textOfItem = _panelItems[i]; //has to be copied for anonymous function or it gets garbage collected away
|
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];
|
panelObjects[_panelItems[i]] = itemObjs[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetInputTextColor ();
|
SetInputTextColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -337,63 +365,39 @@ namespace UnityEngine.UI.Extensions
|
||||||
ToggleDropdownPanel(true);
|
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()
|
private void RedrawPanel()
|
||||||
{
|
{
|
||||||
float scrollbarWidth = _panelItems.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);
|
_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)
|
if (!_hasDrawnOnce || _rectTransform.sizeDelta != _inputRT.sizeDelta)
|
||||||
{
|
{
|
||||||
_hasDrawnOnce = true;
|
_hasDrawnOnce = true;
|
||||||
_inputRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
_inputRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
||||||
_inputRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _rectTransform.sizeDelta.y);
|
_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 ?
|
_scrollPanelRT.anchoredPosition = _displayPanelAbove ?
|
||||||
new Vector2(0, DropdownOffset + _rectTransform.sizeDelta.y * _panelItems.Count - 1) :
|
new Vector2(0, dropdownOffset + dropdownHeight) :
|
||||||
new Vector2(0, -_rectTransform.sizeDelta.y);
|
new Vector2(0, -(dropdownOffset + _rectTransform.sizeDelta.y));
|
||||||
|
|
||||||
//make the overlay fill the screen
|
//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.Horizontal, _canvasRT.sizeDelta.x);
|
||||||
_overlayRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _canvasRT.sizeDelta.y);
|
_overlayRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _canvasRT.sizeDelta.y);
|
||||||
|
|
||||||
_overlayRT.SetParent(transform, true);//reattach to this object
|
_overlayRT.SetParent(transform, true);
|
||||||
_scrollPanelRT.SetParent(_overlayRT, true); //reattach the scrollpanel to the overlay
|
_scrollPanelRT.SetParent(_overlayRT, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_panelItems.Count < 1) return;
|
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.Vertical, dropdownHeight);
|
||||||
_scrollPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
_scrollPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
||||||
|
|
||||||
|
@ -402,7 +406,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
_scrollBarRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, scrollbarWidth);
|
_scrollBarRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, scrollbarWidth);
|
||||||
_scrollBarRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, dropdownHeight);
|
_scrollBarRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, dropdownHeight);
|
||||||
if (scrollbarWidth == 0) _scrollHandleRT.gameObject.SetActive(false); else _scrollHandleRT.gameObject.SetActive(true);
|
if (scrollbarWidth == 0) _scrollHandleRT.gameObject.SetActive(false); else _scrollHandleRT.gameObject.SetActive(true);
|
||||||
|
|
||||||
_slidingAreaRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 0);
|
_slidingAreaRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 0);
|
||||||
_slidingAreaRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, dropdownHeight - _scrollBarRT.sizeDelta.x);
|
_slidingAreaRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, dropdownHeight - _scrollBarRT.sizeDelta.x);
|
||||||
|
@ -413,7 +417,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
Text = currText;
|
Text = currText;
|
||||||
PruneItems(currText);
|
PruneItems(currText);
|
||||||
RedrawPanel();
|
RedrawPanel();
|
||||||
//Debug.Log("value changed to: " + currText);
|
|
||||||
|
|
||||||
if (_panelItems.Count == 0)
|
if (_panelItems.Count == 0)
|
||||||
{
|
{
|
||||||
|
@ -425,30 +428,36 @@ namespace UnityEngine.UI.Extensions
|
||||||
ToggleDropdownPanel(false);
|
ToggleDropdownPanel(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validity_changed = (_panelItems.Contains (Text) != _selectionIsValid);
|
bool validity_changed = (_panelItems.Contains(Text) != _selectionIsValid);
|
||||||
_selectionIsValid = _panelItems.Contains (Text);
|
_selectionIsValid = _panelItems.Contains(Text);
|
||||||
OnSelectionChanged.Invoke (Text, _selectionIsValid);
|
OnSelectionChanged.Invoke(Text, _selectionIsValid);
|
||||||
OnSelectionTextChanged.Invoke (Text);
|
OnSelectionTextChanged.Invoke(Text);
|
||||||
if(validity_changed){
|
if (validity_changed)
|
||||||
OnSelectionValidityChanged.Invoke (_selectionIsValid);
|
{
|
||||||
}
|
OnSelectionValidityChanged.Invoke(_selectionIsValid);
|
||||||
|
}
|
||||||
|
|
||||||
SetInputTextColor ();
|
SetInputTextColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetInputTextColor(){
|
private void SetInputTextColor()
|
||||||
if (InputColorMatching) {
|
{
|
||||||
if (_selectionIsValid) {
|
if (InputColorMatching)
|
||||||
_mainInput.textComponent.color = ValidSelectionTextColor;
|
{
|
||||||
} else if (_panelItems.Count > 0) {
|
if (_selectionIsValid)
|
||||||
_mainInput.textComponent.color = MatchingItemsRemainingTextColor;
|
{
|
||||||
} else {
|
_mainInput.textComponent.color = ValidSelectionTextColor;
|
||||||
_mainInput.textComponent.color = NoItemsRemainingTextColor;
|
}
|
||||||
}
|
else if (_panelItems.Count > 0)
|
||||||
}
|
{
|
||||||
}
|
_mainInput.textComponent.color = MatchingItemsRemainingTextColor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_mainInput.textComponent.color = NoItemsRemainingTextColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Toggle the drop down list
|
/// Toggle the drop down list
|
||||||
|
@ -456,6 +465,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// <param name="directClick"> whether an item was directly clicked on</param>
|
/// <param name="directClick"> whether an item was directly clicked on</param>
|
||||||
public void ToggleDropdownPanel(bool directClick = false)
|
public void ToggleDropdownPanel(bool directClick = false)
|
||||||
{
|
{
|
||||||
|
if (!isActive) return;
|
||||||
|
|
||||||
_isPanelActive = !_isPanelActive;
|
_isPanelActive = !_isPanelActive;
|
||||||
|
|
||||||
_overlayRT.gameObject.SetActive(_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)
|
private void PruneItems(string currText)
|
||||||
{
|
{
|
||||||
if (autocompleteSearchType == AutoCompleteSearchType.Linq)
|
if (autocompleteSearchType == AutoCompleteSearchType.Linq)
|
||||||
|
@ -528,4 +553,4 @@ namespace UnityEngine.UI.Extensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,48 +3,61 @@
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using static UnityEditor.Progress;
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
[RequireComponent(typeof(RectTransform))]
|
[RequireComponent(typeof(RectTransform))]
|
||||||
[AddComponentMenu("UI/Extensions/ComboBox")]
|
[AddComponentMenu("UI/Extensions/ComboBox/ComboBox")]
|
||||||
public class ComboBox : MonoBehaviour
|
public class ComboBox : MonoBehaviour
|
||||||
{
|
{
|
||||||
public Color disabledTextColor;
|
public DropDownListItem SelectedItem { get; private set; }
|
||||||
public DropDownListItem SelectedItem { get; private set; } //outside world gets to get this, not set it
|
|
||||||
|
|
||||||
|
[Header("Combo Box Items")]
|
||||||
public List<string> AvailableOptions;
|
public List<string> AvailableOptions;
|
||||||
|
|
||||||
|
[Header("Properties")]
|
||||||
|
[SerializeField]
|
||||||
|
private bool isActive = true;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private float _scrollBarWidth = 20.0f;
|
private float _scrollBarWidth = 20.0f;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int _itemsToDisplay;
|
private int _itemsToDisplay;
|
||||||
|
|
||||||
//Sorting disabled as it causes issues.
|
[SerializeField]
|
||||||
//[SerializeField]
|
private float dropdownOffset;
|
||||||
//private bool _sortItems = true;
|
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private bool _displayPanelAbove = false;
|
private bool _displayPanelAbove = false;
|
||||||
|
|
||||||
|
public bool SelectFirstItemOnStart = false;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private int selectItemIndexOnStart = 0;
|
||||||
|
|
||||||
|
private bool shouldSelectItemOnStart => SelectFirstItemOnStart || selectItemIndexOnStart > 0;
|
||||||
|
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public class SelectionChangedEvent : UnityEngine.Events.UnityEvent<string>
|
public class SelectionChangedEvent : Events.UnityEvent<string> { }
|
||||||
{
|
|
||||||
}
|
[Header("Events")]
|
||||||
// fires when item is changed;
|
// fires when item is changed;
|
||||||
public SelectionChangedEvent OnSelectionChanged;
|
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 isInitialized = false;
|
||||||
private bool _isPanelActive = false;
|
private bool _isPanelActive = false;
|
||||||
private bool _hasDrawnOnce = false;
|
private bool _hasDrawnOnce = false;
|
||||||
|
|
||||||
private InputField _mainInput;
|
private InputField _mainInput;
|
||||||
private RectTransform _inputRT;
|
private RectTransform _inputRT;
|
||||||
|
|
||||||
|
|
||||||
private RectTransform _rectTransform;
|
private RectTransform _rectTransform;
|
||||||
|
|
||||||
private RectTransform _overlayRT;
|
private RectTransform _overlayRT;
|
||||||
private RectTransform _scrollPanelRT;
|
private RectTransform _scrollPanelRT;
|
||||||
private RectTransform _scrollBarRT;
|
private RectTransform _scrollBarRT;
|
||||||
|
@ -53,14 +66,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
private RectTransform _itemsPanelRT;
|
private RectTransform _itemsPanelRT;
|
||||||
private Canvas _canvas;
|
private Canvas _canvas;
|
||||||
private RectTransform _canvasRT;
|
private RectTransform _canvasRT;
|
||||||
|
|
||||||
private ScrollRect _scrollRect;
|
private ScrollRect _scrollRect;
|
||||||
|
|
||||||
private List<string> _panelItems; //items that will get shown in the drop-down
|
private List<string> _panelItems; //items that will get shown in the drop-down
|
||||||
|
|
||||||
private Dictionary<string, GameObject> panelObjects;
|
private Dictionary<string, GameObject> panelObjects;
|
||||||
|
|
||||||
private GameObject itemTemplate;
|
private GameObject itemTemplate;
|
||||||
|
private bool _initialized;
|
||||||
|
|
||||||
public string Text { get; private set; }
|
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
|
public int ItemsToDisplay
|
||||||
{
|
{
|
||||||
get { return _itemsToDisplay; }
|
get { return _itemsToDisplay; }
|
||||||
|
@ -94,11 +101,17 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
|
if (shouldSelectItemOnStart && AvailableOptions.Count > 0)
|
||||||
|
{
|
||||||
|
SelectItemIndex(SelectFirstItemOnStart ? 0 : selectItemIndexOnStart);
|
||||||
|
}
|
||||||
RedrawPanel();
|
RedrawPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Initialize()
|
private bool Initialize()
|
||||||
{
|
{
|
||||||
|
if (_initialized) return true;
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -138,11 +151,22 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
_panelItems = AvailableOptions.ToList();
|
_panelItems = AvailableOptions.ToList();
|
||||||
|
|
||||||
|
_initialized = true;
|
||||||
|
|
||||||
RebuildPanel();
|
RebuildPanel();
|
||||||
//RedrawPanel(); - causes an initialisation failure in U5
|
|
||||||
return success;
|
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)
|
public void AddItem(string item)
|
||||||
{
|
{
|
||||||
AvailableOptions.Add(item);
|
AvailableOptions.Add(item);
|
||||||
|
@ -157,26 +181,34 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
public void SetAvailableOptions(List<string> newOptions)
|
public void SetAvailableOptions(List<string> newOptions)
|
||||||
{
|
{
|
||||||
AvailableOptions.Clear();
|
var uniqueOptions = newOptions.Distinct().ToArray();
|
||||||
AvailableOptions = newOptions;
|
SetAvailableOptions(uniqueOptions);
|
||||||
RebuildPanel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAvailableOptions(string[] newOptions)
|
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++)
|
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()
|
public void ResetItems()
|
||||||
{
|
{
|
||||||
AvailableOptions.Clear();
|
AvailableOptions.Clear();
|
||||||
RebuildPanel();
|
RebuildPanel();
|
||||||
|
RedrawPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -184,13 +216,17 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void RebuildPanel()
|
private void RebuildPanel()
|
||||||
{
|
{
|
||||||
|
if (!_initialized)
|
||||||
|
{
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
//panel starts with all options
|
//panel starts with all options
|
||||||
_panelItems.Clear();
|
_panelItems.Clear();
|
||||||
foreach (string option in AvailableOptions)
|
foreach (string option in AvailableOptions)
|
||||||
{
|
{
|
||||||
_panelItems.Add(option.ToLower());
|
_panelItems.Add(option.ToLower());
|
||||||
}
|
}
|
||||||
//if(_sortItems) _panelItems.Sort();
|
|
||||||
|
|
||||||
List<GameObject> itemObjs = new List<GameObject>(panelObjects.Values);
|
List<GameObject> itemObjs = new List<GameObject>(panelObjects.Values);
|
||||||
panelObjects.Clear();
|
panelObjects.Clear();
|
||||||
|
@ -211,8 +247,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
if (i < AvailableOptions.Count)
|
if (i < AvailableOptions.Count)
|
||||||
{
|
{
|
||||||
itemObjs[i].name = "Item " + i + " " + _panelItems[i];
|
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
|
itemObjs[i].transform.Find("Text").GetComponent<Text>().text = AvailableOptions[i]; //set the text value
|
||||||
|
#endif
|
||||||
Button itemBtn = itemObjs[i].GetComponent<Button>();
|
Button itemBtn = itemObjs[i].GetComponent<Button>();
|
||||||
itemBtn.onClick.RemoveAllListeners();
|
itemBtn.onClick.RemoveAllListeners();
|
||||||
string textOfItem = _panelItems[i]; //has to be copied for anonymous function or it gets garbage collected away
|
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);
|
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()
|
private void RedrawPanel()
|
||||||
{
|
{
|
||||||
float scrollbarWidth = _panelItems.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);
|
_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)
|
if (!_hasDrawnOnce || _rectTransform.sizeDelta != _inputRT.sizeDelta)
|
||||||
{
|
{
|
||||||
_hasDrawnOnce = true;
|
_hasDrawnOnce = true;
|
||||||
_inputRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
_inputRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
||||||
_inputRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _rectTransform.sizeDelta.y);
|
_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 ?
|
_scrollPanelRT.anchoredPosition = _displayPanelAbove ?
|
||||||
new Vector2(0, _rectTransform.sizeDelta.y * ItemsToDisplay - 1) :
|
new Vector2(0, dropdownOffset + dropdownHeight) :
|
||||||
new Vector2(0, -_rectTransform.sizeDelta.y);
|
new Vector2(0, -(dropdownOffset + _rectTransform.sizeDelta.y));
|
||||||
|
|
||||||
//make the overlay fill the screen
|
//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.Horizontal, _canvasRT.sizeDelta.x);
|
||||||
_overlayRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _canvasRT.sizeDelta.y);
|
_overlayRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _canvasRT.sizeDelta.y);
|
||||||
|
|
||||||
_overlayRT.SetParent(transform, true);//reattach to this object
|
_overlayRT.SetParent(transform, true);
|
||||||
_scrollPanelRT.SetParent(_overlayRT, true); //reattach the scrollpanel to the overlay
|
_scrollPanelRT.SetParent(_overlayRT, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_panelItems.Count < 1) return;
|
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.Vertical, dropdownHeight);
|
||||||
_scrollPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
_scrollPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
||||||
|
|
||||||
|
@ -312,7 +327,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
Text = currText;
|
Text = currText;
|
||||||
RedrawPanel();
|
RedrawPanel();
|
||||||
//Debug.Log("value changed to: " + currText);
|
|
||||||
|
|
||||||
if (_panelItems.Count == 0)
|
if (_panelItems.Count == 0)
|
||||||
{
|
{
|
||||||
|
@ -332,6 +346,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// <param name="directClick"> whether an item was directly clicked on</param>
|
/// <param name="directClick"> whether an item was directly clicked on</param>
|
||||||
public void ToggleDropdownPanel(bool directClick)
|
public void ToggleDropdownPanel(bool directClick)
|
||||||
{
|
{
|
||||||
|
if (!isActive) return;
|
||||||
|
|
||||||
_isPanelActive = !_isPanelActive;
|
_isPanelActive = !_isPanelActive;
|
||||||
|
|
||||||
_overlayRT.gameObject.SetActive(_isPanelActive);
|
_overlayRT.gameObject.SetActive(_isPanelActive);
|
||||||
|
@ -344,5 +360,18 @@ namespace UnityEngine.UI.Extensions
|
||||||
// scrollOffset = Mathf.RoundToInt(itemsPanelRT.anchoredPosition.y / _rectTransform.sizeDelta.y);
|
// 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
|
///Credit perchik
|
||||||
///Sourced from - http://forum.unity3d.com/threads/receive-onclick-event-and-pass-it-on-to-lower-ui-elements.293642/
|
///Sourced from - http://forum.unity3d.com/threads/receive-onclick-event-and-pass-it-on-to-lower-ui-elements.293642/
|
||||||
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
|
@ -10,13 +9,20 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// Extension to the UI class which creates a dropdown list
|
/// Extension to the UI class which creates a dropdown list
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RequireComponent(typeof(RectTransform))]
|
[RequireComponent(typeof(RectTransform))]
|
||||||
[AddComponentMenu("UI/Extensions/Dropdown List")]
|
[AddComponentMenu("UI/Extensions/ComboBox/Dropdown List")]
|
||||||
public class DropDownList : MonoBehaviour
|
public class DropDownList : MonoBehaviour
|
||||||
{
|
{
|
||||||
public Color disabledTextColor;
|
public Color disabledTextColor;
|
||||||
public DropDownListItem SelectedItem { get; private set; } //outside world gets to get this, not set it
|
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;
|
public bool OverrideHighlighted = true;
|
||||||
|
|
||||||
//private bool isInitialized = false;
|
//private bool isInitialized = false;
|
||||||
|
@ -38,11 +44,12 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
private ScrollRect _scrollRect;
|
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;
|
private float _scrollBarWidth = 20.0f;
|
||||||
public float ScrollBarWidth
|
public float ScrollBarWidth
|
||||||
{
|
{
|
||||||
|
@ -69,32 +76,45 @@ namespace UnityEngine.UI.Extensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SelectFirstItemOnStart = false;
|
[SerializeField]
|
||||||
|
private float dropdownOffset;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private bool _displayPanelAbove = false;
|
private bool _displayPanelAbove = false;
|
||||||
|
|
||||||
[SerializeField]
|
public bool SelectFirstItemOnStart = false;
|
||||||
[Tooltip("Override the Text width for the values.")]
|
|
||||||
private bool _overrideTextWidth = true;
|
|
||||||
|
|
||||||
[System.Serializable]
|
[SerializeField]
|
||||||
public class SelectionChangedEvent : UnityEngine.Events.UnityEvent<int> { }
|
private int selectItemIndexOnStart = 0;
|
||||||
// fires when item is changed;
|
private bool shouldSelectItemOnStart => SelectFirstItemOnStart || selectItemIndexOnStart > 0;
|
||||||
public SelectionChangedEvent OnSelectionChanged;
|
|
||||||
|
|
||||||
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 (_initialized) return true;
|
||||||
if (SelectFirstItemOnStart && Items.Count > 0) {
|
|
||||||
ToggleDropdownPanel (false);
|
|
||||||
OnItemClicked (0);
|
|
||||||
}
|
|
||||||
RedrawPanel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool Initialize()
|
|
||||||
{
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -103,8 +123,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
_overlayRT = _rectTransform.Find("Overlay").GetComponent<RectTransform>();
|
_overlayRT = _rectTransform.Find("Overlay").GetComponent<RectTransform>();
|
||||||
_overlayRT.gameObject.SetActive(false);
|
_overlayRT.gameObject.SetActive(false);
|
||||||
|
|
||||||
|
|
||||||
_scrollPanelRT = _overlayRT.Find("ScrollPanel").GetComponent<RectTransform>();
|
_scrollPanelRT = _overlayRT.Find("ScrollPanel").GetComponent<RectTransform>();
|
||||||
_scrollBarRT = _scrollPanelRT.Find("Scrollbar").GetComponent<RectTransform>();
|
_scrollBarRT = _scrollPanelRT.Find("Scrollbar").GetComponent<RectTransform>();
|
||||||
_slidingAreaRT = _scrollBarRT.Find("SlidingArea").GetComponent<RectTransform>();
|
_slidingAreaRT = _scrollBarRT.Find("SlidingArea").GetComponent<RectTransform>();
|
||||||
|
@ -120,7 +138,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
_scrollRect.movementType = ScrollRect.MovementType.Clamped;
|
_scrollRect.movementType = ScrollRect.MovementType.Clamped;
|
||||||
_scrollRect.content = _itemsPanelRT;
|
_scrollRect.content = _itemsPanelRT;
|
||||||
|
|
||||||
|
|
||||||
_itemTemplate = _rectTransform.Find("ItemTemplate").gameObject;
|
_itemTemplate = _rectTransform.Find("ItemTemplate").gameObject;
|
||||||
_itemTemplate.SetActive(false);
|
_itemTemplate.SetActive(false);
|
||||||
}
|
}
|
||||||
|
@ -130,23 +147,32 @@ namespace UnityEngine.UI.Extensions
|
||||||
Debug.LogError("Something is setup incorrectly with the dropdownlist component causing a Null Reference Exception");
|
Debug.LogError("Something is setup incorrectly with the dropdownlist component causing a Null Reference Exception");
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
_initialized = true;
|
||||||
|
|
||||||
_panelItems = new List<DropDownListButton>();
|
RebuildPanel();
|
||||||
|
|
||||||
RebuildPanel();
|
|
||||||
RedrawPanel();
|
RedrawPanel();
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// currently just using items in the list instead of being able to add to it.
|
/// <summary>
|
||||||
/// <summary>
|
/// Update the drop down selection to a specific index
|
||||||
/// Rebuilds the list from a new collection.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <param name="index"></param>
|
||||||
/// NOTE, this will clear all existing items
|
public void SelectItemIndex(int index)
|
||||||
/// </remarks>
|
{
|
||||||
/// <param name="list"></param>
|
ToggleDropdownPanel(false);
|
||||||
public void RefreshItems(params object[] list)
|
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();
|
Items.Clear();
|
||||||
List<DropDownListItem> ddItems = new List<DropDownListItem>();
|
List<DropDownListItem> ddItems = new List<DropDownListItem>();
|
||||||
|
@ -171,72 +197,80 @@ namespace UnityEngine.UI.Extensions
|
||||||
}
|
}
|
||||||
Items.AddRange(ddItems);
|
Items.AddRange(ddItems);
|
||||||
RebuildPanel();
|
RebuildPanel();
|
||||||
}
|
RedrawPanel();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds an additional item to the drop down list (recommended)
|
/// Adds an additional item to the drop down list (recommended)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">Item of type DropDownListItem</param>
|
/// <param name="item">Item of type DropDownListItem</param>
|
||||||
public void AddItem(DropDownListItem item)
|
public void AddItem(DropDownListItem item)
|
||||||
{
|
{
|
||||||
Items.Add(item);
|
Items.Add(item);
|
||||||
RebuildPanel();
|
RebuildPanel();
|
||||||
}
|
RedrawPanel();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds an additional drop down list item using a string name
|
/// Adds an additional drop down list item using a string name
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">Item of type String</param>
|
/// <param name="item">Item of type String</param>
|
||||||
public void AddItem(string item)
|
public void AddItem(string item)
|
||||||
{
|
{
|
||||||
Items.Add(new DropDownListItem(caption: (string)item));
|
Items.Add(new DropDownListItem(caption: (string)item));
|
||||||
RebuildPanel();
|
RebuildPanel();
|
||||||
}
|
RedrawPanel();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds an additional drop down list item using a sprite image
|
/// Adds an additional drop down list item using a sprite image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">Item of type UI Sprite</param>
|
/// <param name="item">Item of type UI Sprite</param>
|
||||||
public void AddItem(Sprite item)
|
public void AddItem(Sprite item)
|
||||||
{
|
{
|
||||||
Items.Add(new DropDownListItem(image: (Sprite)item));
|
Items.Add(new DropDownListItem(image: (Sprite)item));
|
||||||
RebuildPanel();
|
RebuildPanel();
|
||||||
}
|
RedrawPanel();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes an item from the drop down list (recommended)
|
/// Removes an item from the drop down list (recommended)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">Item of type DropDownListItem</param>
|
/// <param name="item">Item of type DropDownListItem</param>
|
||||||
public void RemoveItem(DropDownListItem item)
|
public void RemoveItem(DropDownListItem item)
|
||||||
{
|
{
|
||||||
Items.Remove(item);
|
Items.Remove(item);
|
||||||
RebuildPanel();
|
RebuildPanel();
|
||||||
}
|
RedrawPanel();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes an item from the drop down list item using a string name
|
/// Removes an item from the drop down list item using a string name
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">Item of type String</param>
|
/// <param name="item">Item of type String</param>
|
||||||
public void RemoveItem(string item)
|
public void RemoveItem(string item)
|
||||||
{
|
{
|
||||||
Items.Remove(new DropDownListItem(caption: (string)item));
|
Items.Remove(new DropDownListItem(caption: (string)item));
|
||||||
RebuildPanel();
|
RebuildPanel();
|
||||||
}
|
RedrawPanel();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes an item from the drop down list item using a sprite image
|
/// Removes an item from the drop down list item using a sprite image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">Item of type UI Sprite</param>
|
/// <param name="item">Item of type UI Sprite</param>
|
||||||
public void RemoveItem(Sprite item)
|
public void RemoveItem(Sprite item)
|
||||||
{
|
{
|
||||||
Items.Remove(new DropDownListItem(image: (Sprite)item));
|
Items.Remove(new DropDownListItem(image: (Sprite)item));
|
||||||
RebuildPanel();
|
RebuildPanel();
|
||||||
}
|
RedrawPanel();
|
||||||
|
}
|
||||||
|
|
||||||
public void ResetItems()
|
public void ResetItems()
|
||||||
{
|
{
|
||||||
Items.Clear();
|
Items.Clear();
|
||||||
RebuildPanel();
|
RebuildPanel();
|
||||||
|
RedrawPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -246,6 +280,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
if (Items.Count == 0) return;
|
if (Items.Count == 0) return;
|
||||||
|
|
||||||
|
if (!_initialized)
|
||||||
|
{
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
int indx = _panelItems.Count;
|
int indx = _panelItems.Count;
|
||||||
while (_panelItems.Count < Items.Count)
|
while (_panelItems.Count < Items.Count)
|
||||||
{
|
{
|
||||||
|
@ -302,9 +341,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
_mainButton.img.sprite = SelectedItem.Image;
|
_mainButton.img.sprite = SelectedItem.Image;
|
||||||
_mainButton.img.color = Color.white;
|
_mainButton.img.color = Color.white;
|
||||||
|
|
||||||
//if (Interactable) mainButton.img.color = Color.white;
|
|
||||||
//else mainButton.img.color = new Color(1, 1, 1, .5f);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -316,7 +352,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
//update selected index color
|
//update selected index color
|
||||||
if (OverrideHighlighted)
|
if (OverrideHighlighted)
|
||||||
{
|
{
|
||||||
|
|
||||||
for (int i = 0; i < _itemsPanelRT.childCount; i++)
|
for (int i = 0; i < _itemsPanelRT.childCount; i++)
|
||||||
{
|
{
|
||||||
_panelItems[i].btnImg.color = (_selectedIndex == i) ? _mainButton.btn.colors.highlightedColor : new Color(0, 0, 0, 0);
|
_panelItems[i].btnImg.color = (_selectedIndex == i) ? _mainButton.btn.colors.highlightedColor : new Color(0, 0, 0, 0);
|
||||||
|
@ -324,40 +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;
|
_hasDrawnOnce = true;
|
||||||
_mainButton.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
_mainButton.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
||||||
_mainButton.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _rectTransform.sizeDelta.y);
|
_mainButton.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _rectTransform.sizeDelta.y);
|
||||||
if (_overrideTextWidth)
|
|
||||||
{
|
|
||||||
_mainButton.txt.rectTransform.offsetMax = new Vector2(4, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
_scrollPanelRT.SetParent(transform, true);//break the scroll panel from the overlay
|
var itemsRemaining = _panelItems.Count - ItemsToDisplay;
|
||||||
_scrollPanelRT.anchoredPosition = _displayPanelAbove ?
|
itemsRemaining = itemsRemaining < 0 ? 0 : itemsRemaining;
|
||||||
new Vector2(0, _rectTransform.sizeDelta.y * ItemsToDisplay - 1) :
|
|
||||||
new Vector2(0, -_rectTransform.sizeDelta.y);
|
|
||||||
|
|
||||||
//make the overlay fill the screen
|
_scrollPanelRT.SetParent(transform, true);
|
||||||
_overlayRT.SetParent(_canvas.transform, false); //attach it to top level object
|
_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.Horizontal, _canvasRT.sizeDelta.x);
|
||||||
_overlayRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _canvasRT.sizeDelta.y);
|
_overlayRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _canvasRT.sizeDelta.y);
|
||||||
|
|
||||||
_overlayRT.SetParent(transform, true);//reattach to this object
|
_overlayRT.SetParent(transform, true);
|
||||||
_scrollPanelRT.SetParent(_overlayRT, true); //reattach the scrollpanel to the overlay
|
_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);
|
_scrollPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _rectTransform.sizeDelta.x);
|
||||||
|
|
||||||
_itemsPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _scrollPanelRT.sizeDelta.x - scrollbarWidth - 5);
|
_itemsPanelRT.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _scrollPanelRT.sizeDelta.x - scrollbarWidth - 5);
|
||||||
|
@ -377,6 +412,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// <param name="directClick"> whether an item was directly clicked on</param>
|
/// <param name="directClick"> whether an item was directly clicked on</param>
|
||||||
public void ToggleDropdownPanel(bool directClick)
|
public void ToggleDropdownPanel(bool directClick)
|
||||||
{
|
{
|
||||||
|
if (!isActive) return;
|
||||||
|
|
||||||
_overlayRT.transform.localScale = new Vector3(1, 1, 1);
|
_overlayRT.transform.localScale = new Vector3(1, 1, 1);
|
||||||
_scrollBarRT.transform.localScale = new Vector3(1, 1, 1);
|
_scrollBarRT.transform.localScale = new Vector3(1, 1, 1);
|
||||||
_isPanelActive = !_isPanelActive;
|
_isPanelActive = !_isPanelActive;
|
||||||
|
@ -390,5 +427,18 @@ namespace UnityEngine.UI.Extensions
|
||||||
// scrollOffset = Mathf.RoundToInt(itemsPanelRT.anchoredPosition.y / _rectTransform.sizeDelta.y);
|
// 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 RectTransform rectTransform;
|
||||||
public Button btn;
|
public Button btn;
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
public TMPro.TMP_Text txt;
|
||||||
|
#else
|
||||||
public Text txt;
|
public Text txt;
|
||||||
|
#endif
|
||||||
public Image btnImg;
|
public Image btnImg;
|
||||||
public Image img;
|
public Image img;
|
||||||
public GameObject gameobject;
|
public GameObject gameobject;
|
||||||
|
@ -19,7 +23,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
rectTransform = btnObj.GetComponent<RectTransform>();
|
rectTransform = btnObj.GetComponent<RectTransform>();
|
||||||
btnImg = btnObj.GetComponent<Image>();
|
btnImg = btnObj.GetComponent<Image>();
|
||||||
btn = btnObj.GetComponent<Button>();
|
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>();
|
txt = rectTransform.Find("Text").GetComponent<Text>();
|
||||||
|
#endif
|
||||||
img = rectTransform.Find("Image").GetComponent<Image>();
|
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/
|
///Sourced from - http://forum.unity3d.com/threads/receive-onclick-event-and-pass-it-on-to-lower-ui-elements.293642/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using UnityEngine.Events;
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
|
@ -76,9 +77,9 @@ namespace UnityEngine.UI.Extensions
|
||||||
set { _id = value; }
|
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>
|
/// <summary>
|
||||||
/// Constructor for Drop Down List panelItems
|
/// Constructor for Drop Down List panelItems
|
||||||
|
@ -87,8 +88,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// <param name="val">ID of the item </param>
|
/// <param name="val">ID of the item </param>
|
||||||
/// <param name="image"></param>
|
/// <param name="image"></param>
|
||||||
/// <param name="disabled">Should the item start disabled</param>
|
/// <param name="disabled">Should the item start disabled</param>
|
||||||
/// <param name="onSelect">Action to be called when this item is selected</param>
|
/// <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, Action onSelect = null)
|
public DropDownListItem(string caption = "", string inId = "", Sprite image = null, bool disabled = false, UnityAction onSelect = null)
|
||||||
{
|
{
|
||||||
_caption = caption;
|
_caption = caption;
|
||||||
_image = image;
|
_image = image;
|
||||||
|
|
|
@ -7,15 +7,14 @@ using UnityEngine.EventSystems;
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
[AddComponentMenu("UI/Extensions/Cooldown Button")]
|
[AddComponentMenu("UI/Extensions/Cooldown Button")]
|
||||||
public class CooldownButton : MonoBehaviour, IPointerDownHandler
|
public class CooldownButton : MonoBehaviour, IPointerDownHandler, ISubmitHandler
|
||||||
{
|
{
|
||||||
#region Sub-Classes
|
#region Sub-Classes
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public class CooldownButtonEvent : UnityEvent<PointerEventData.InputButton> { }
|
public class CooldownButtonEvent : UnityEvent<GameObject> { }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private variables
|
#region Private variables
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private float cooldownTimeout;
|
private float cooldownTimeout;
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
|
@ -33,7 +32,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
[SerializeField][ReadOnly]
|
[SerializeField][ReadOnly]
|
||||||
private int cooldownPercentComplete;
|
private int cooldownPercentComplete;
|
||||||
|
|
||||||
PointerEventData buttonSource;
|
BaseEventData buttonSource;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
@ -116,7 +115,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pause Cooldown without resetting values, allows Restarting of cooldown
|
/// Pause Cooldown without resetting values, allows Restarting of cooldown
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -144,9 +142,9 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void StartCooldown()
|
public void StartCooldown()
|
||||||
{
|
{
|
||||||
PointerEventData emptySource = new PointerEventData(EventSystem.current);
|
BaseEventData emptySource = new BaseEventData(EventSystem.current);
|
||||||
buttonSource = emptySource;
|
buttonSource = emptySource;
|
||||||
OnCooldownStart.Invoke(emptySource.button);
|
OnCooldownStart.Invoke(emptySource.selectedObject);
|
||||||
cooldownTimeRemaining = cooldownTimeout;
|
cooldownTimeRemaining = cooldownTimeout;
|
||||||
CooldownActive = cooldownInEffect = true;
|
CooldownActive = cooldownInEffect = true;
|
||||||
}
|
}
|
||||||
|
@ -161,7 +159,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
cooldownPercentRemaining = 0;
|
cooldownPercentRemaining = 0;
|
||||||
cooldownPercentComplete = 100;
|
cooldownPercentComplete = 100;
|
||||||
cooldownActive = cooldownInEffect = false;
|
cooldownActive = cooldownInEffect = false;
|
||||||
if (OnCoolDownFinish != null) OnCoolDownFinish.Invoke(buttonSource.button);
|
OnCoolDownFinish?.Invoke(buttonSource.selectedObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -171,27 +169,38 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
cooldownActive = cooldownInEffect = false;
|
cooldownActive = cooldownInEffect = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region IPointerDownHandler
|
#region IPointerDownHandler
|
||||||
|
|
||||||
void IPointerDownHandler.OnPointerDown(PointerEventData eventData)
|
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;
|
buttonSource = eventData;
|
||||||
|
|
||||||
if (CooldownInEffect)
|
if (CooldownInEffect)
|
||||||
{
|
{
|
||||||
if (OnButtonClickDuringCooldown != null) OnButtonClickDuringCooldown.Invoke(eventData.button);
|
OnButtonClickDuringCooldown?.Invoke(buttonSource.selectedObject);
|
||||||
}
|
}
|
||||||
if (!CooldownInEffect)
|
if (!CooldownInEffect)
|
||||||
{
|
{
|
||||||
if(OnCooldownStart != null) OnCooldownStart.Invoke(eventData.button);
|
OnCooldownStart?.Invoke(buttonSource.selectedObject);
|
||||||
cooldownTimeRemaining = cooldownTimeout;
|
cooldownTimeRemaining = cooldownTimeout;
|
||||||
cooldownActive = cooldownInEffect = true;
|
cooldownActive = cooldownInEffect = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion Private Methods
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
/// Credit Erdener Gonenc - @PixelEnvision
|
/// Credit Erdener Gonenc - @PixelEnvision
|
||||||
/*USAGE: Simply use that instead of the regular ScrollRect */
|
/*USAGE: Simply use that instead of the regular ScrollRect */
|
||||||
|
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
[AddComponentMenu ("UI/Extensions/MultiTouchScrollRect")]
|
[AddComponentMenu ("UI/Extensions/MultiTouchScrollRect")]
|
||||||
|
|
|
@ -6,7 +6,6 @@ using UnityEngine.Events;
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
|
|
||||||
[RequireComponent(typeof(RectTransform)), DisallowMultipleComponent]
|
[RequireComponent(typeof(RectTransform)), DisallowMultipleComponent]
|
||||||
[AddComponentMenu("UI/Extensions/Re-orderable list")]
|
[AddComponentMenu("UI/Extensions/Re-orderable list")]
|
||||||
public class ReorderableList : MonoBehaviour
|
public class ReorderableList : MonoBehaviour
|
||||||
|
@ -31,11 +30,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
// This sets every item size (when being dragged over this list) to the current size of the first element of this list
|
// This sets every item size (when being dragged over this list) to the current size of the first element of this list
|
||||||
[Tooltip("Should items being dragged over this list have their sizes equalized?")]
|
[Tooltip("Should items being dragged over this list have their sizes equalized?")]
|
||||||
public bool EqualizeSizesOnDrag = false;
|
public bool EqualizeSizesOnDrag = false;
|
||||||
|
|
||||||
|
[Tooltip("Maximum number of items this container can hold")]
|
||||||
public int maxItems = int.MaxValue;
|
public int maxItems = int.MaxValue;
|
||||||
|
|
||||||
|
|
||||||
[Header("UI Re-orderable Events")]
|
[Header("UI Re-orderable Events")]
|
||||||
public ReorderableListHandler OnElementDropped = new ReorderableListHandler();
|
public ReorderableListHandler OnElementDropped = new ReorderableListHandler();
|
||||||
public ReorderableListHandler OnElementGrabbed = new ReorderableListHandler();
|
public ReorderableListHandler OnElementGrabbed = new ReorderableListHandler();
|
||||||
|
@ -62,7 +61,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas GetCanvas()
|
public Canvas GetCanvas()
|
||||||
{
|
{
|
||||||
Transform t = transform;
|
Transform t = transform;
|
||||||
Canvas canvas = null;
|
Canvas canvas = null;
|
||||||
|
@ -73,8 +72,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
while (canvas == null && lvl < lvlLimit)
|
while (canvas == null && lvl < lvlLimit)
|
||||||
{
|
{
|
||||||
canvas = t.gameObject.GetComponent<Canvas>();
|
if (!t.gameObject.TryGetComponent<Canvas>(out canvas))
|
||||||
if (canvas == null)
|
|
||||||
{
|
{
|
||||||
t = t.parent;
|
t = t.parent;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +93,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (ContentLayout == null)
|
if (ContentLayout == null)
|
||||||
{
|
{
|
||||||
Debug.LogError("You need to have a child LayoutGroup content set for the list: " + name, gameObject);
|
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();
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#region Nested type: ReorderableListEventStruct
|
#region Nested type: ReorderableListEventStruct
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
@ -136,13 +132,10 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Nested type: ReorderableListHandler
|
#region Nested type: ReorderableListHandler
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class ReorderableListHandler : UnityEvent<ReorderableListEventStruct>
|
public class ReorderableListHandler : UnityEvent<ReorderableListEventStruct> { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void TestReOrderableListTarget(ReorderableListEventStruct item)
|
public void TestReOrderableListTarget(ReorderableListEventStruct item)
|
||||||
{
|
{
|
||||||
|
@ -152,4 +145,4 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,7 +21,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
if(_rect)StartCoroutine(RefreshChildren());
|
if(_rect)StartCoroutine(RefreshChildren());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void OnTransformChildrenChanged()
|
public void OnTransformChildrenChanged()
|
||||||
{
|
{
|
||||||
if(this.isActiveAndEnabled)StartCoroutine(RefreshChildren());
|
if(this.isActiveAndEnabled)StartCoroutine(RefreshChildren());
|
||||||
|
|
|
@ -5,7 +5,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
public class ReorderableListDebug : MonoBehaviour
|
public class ReorderableListDebug : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
public TMPro.TMP_Text DebugLabel;
|
||||||
|
#else
|
||||||
public Text DebugLabel;
|
public Text DebugLabel;
|
||||||
|
#endif
|
||||||
|
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,31 +8,29 @@ using UnityEngine.EventSystems;
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
|
|
||||||
[RequireComponent(typeof(RectTransform), typeof(LayoutElement))]
|
[RequireComponent(typeof(RectTransform), typeof(LayoutElement))]
|
||||||
public class ReorderableListElement : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
|
public class ReorderableListElement : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
|
||||||
{
|
{
|
||||||
[Tooltip("Can this element be dragged?")]
|
[Tooltip("Can this element be dragged?")]
|
||||||
[SerializeField]
|
[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]
|
[SerializeField]
|
||||||
private bool _isTransferable = true;
|
private bool isTransferable = true;
|
||||||
|
|
||||||
[Tooltip("Can this element be dropped in space?")]
|
[Tooltip("Can this element be dropped in space?")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private bool isDroppableInSpace = false;
|
private bool isDroppableInSpace = false;
|
||||||
|
|
||||||
|
|
||||||
public bool IsTransferable
|
public bool IsTransferable
|
||||||
{
|
{
|
||||||
get { return _isTransferable; }
|
get { return isTransferable; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_canvasGroup = gameObject.GetOrAddComponent<CanvasGroup>();
|
_canvasGroup = gameObject.GetOrAddComponent<CanvasGroup>();
|
||||||
_canvasGroup.blocksRaycasts = value;
|
_canvasGroup.blocksRaycasts = value;
|
||||||
_isTransferable = value;
|
isTransferable = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +59,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
|
|
||||||
#region IBeginDragHandler Members
|
#region IBeginDragHandler Members
|
||||||
|
|
||||||
public void OnBeginDrag(PointerEventData eventData)
|
public void OnBeginDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
if (!_canvasGroup) { _canvasGroup = gameObject.GetOrAddComponent<CanvasGroup>(); }
|
if (!_canvasGroup) { _canvasGroup = gameObject.GetOrAddComponent<CanvasGroup>(); }
|
||||||
|
@ -71,7 +68,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//Can't drag, return...
|
//Can't drag, return...
|
||||||
if (!_reorderableList.IsDraggable || !this.IsGrabbable)
|
if (!_reorderableList.IsDraggable || !this.isGrabbable)
|
||||||
{
|
{
|
||||||
_draggingObject = null;
|
_draggingObject = null;
|
||||||
return;
|
return;
|
||||||
|
@ -142,12 +139,9 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
_isDragging = true;
|
_isDragging = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region IDragHandler Members
|
#region IDragHandler Members
|
||||||
|
|
||||||
public void OnDrag(PointerEventData eventData)
|
public void OnDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
if (!_isDragging)
|
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 nothing found or the list is not dropable, put the fake element outside
|
||||||
if (_currentReorderableListRaycasted == null || _currentReorderableListRaycasted.IsDropable == false
|
if (_currentReorderableListRaycasted == null || _currentReorderableListRaycasted.IsDropable == false
|
||||||
|| (_oldReorderableListRaycasted != _reorderableList && !IsTransferable)
|
|
||||||
|| ((_fakeElement.parent == _currentReorderableListRaycasted.Content
|
|| ((_fakeElement.parent == _currentReorderableListRaycasted.Content
|
||||||
? _currentReorderableListRaycasted.Content.childCount - 1
|
? _currentReorderableListRaycasted.Content.childCount - 1
|
||||||
: _currentReorderableListRaycasted.Content.childCount) >= _currentReorderableListRaycasted.maxItems && !_currentReorderableListRaycasted.IsDisplacable)
|
: _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 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)
|
if (_currentReorderableListRaycasted.Content.childCount < _currentReorderableListRaycasted.maxItems && _fakeElement.parent != _currentReorderableListRaycasted.Content)
|
||||||
{
|
{
|
||||||
|
@ -245,12 +238,9 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Displacement
|
#region Displacement
|
||||||
|
|
||||||
private void displaceElement(int targetIndex, Transform displaced)
|
private void displaceElement(int targetIndex, Transform displaced)
|
||||||
{
|
{
|
||||||
_displacedFromIndex = targetIndex;
|
_displacedFromIndex = targetIndex;
|
||||||
|
@ -343,7 +333,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void finishDisplacingElement()
|
public void finishDisplacingElement()
|
||||||
{
|
{
|
||||||
if (_displacedObject.parent == null)
|
if (_displacedObject.parent == null)
|
||||||
|
@ -355,12 +344,9 @@ namespace UnityEngine.UI.Extensions
|
||||||
_displacedObject = null;
|
_displacedObject = null;
|
||||||
_displacedObjectLE = null;
|
_displacedObjectLE = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region IEndDragHandler Members
|
#region IEndDragHandler Members
|
||||||
|
|
||||||
public void OnEndDrag(PointerEventData eventData)
|
public void OnEndDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
_isDragging = false;
|
_isDragging = false;
|
||||||
|
@ -473,11 +459,9 @@ namespace UnityEngine.UI.Extensions
|
||||||
}
|
}
|
||||||
_canvasGroup.blocksRaycasts = true;
|
_canvasGroup.blocksRaycasts = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private void CancelDrag()
|
||||||
void CancelDrag()
|
|
||||||
{
|
{
|
||||||
_isDragging = false;
|
_isDragging = false;
|
||||||
//If it's a clone, delete it
|
//If it's a clone, delete it
|
||||||
|
@ -556,4 +540,4 @@ namespace UnityEngine.UI.Extensions
|
||||||
_canvasGroup = gameObject.GetOrAddComponent<CanvasGroup>();
|
_canvasGroup = gameObject.GetOrAddComponent<CanvasGroup>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,7 @@
|
||||||
/// Credit David Gileadi
|
/// Credit David Gileadi
|
||||||
/// Sourced from - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/pull-requests/12
|
/// Sourced from - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/pull-requests/12
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using UnityEngine.Events;
|
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
|
@ -205,7 +203,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
void ChangeTextColor(Color targetColor)
|
void ChangeTextColor(Color targetColor)
|
||||||
{
|
{
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
var text = GetComponentInChildren<TMPro.TMP_Text>();
|
||||||
|
#else
|
||||||
var text = GetComponentInChildren<Text>();
|
var text = GetComponentInChildren<Text>();
|
||||||
|
#endif
|
||||||
if (!text)
|
if (!text)
|
||||||
return;
|
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
|
//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;
|
SpriteRenderer spriteRenderer;
|
||||||
Image image;
|
Image image;
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
TMPro.TMP_Text text;
|
||||||
|
#else
|
||||||
Text text;
|
Text text;
|
||||||
|
#endif
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
spriteRenderer = transform.GetComponent<SpriteRenderer>();
|
spriteRenderer = transform.GetComponent<SpriteRenderer>();
|
||||||
image = transform.GetComponent<Image>();
|
image = transform.GetComponent<Image>();
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
text = transform.GetComponent<TMPro.TMP_Text>();
|
||||||
|
#else
|
||||||
text = transform.GetComponent<Text>();
|
text = transform.GetComponent<Text>();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update()
|
void Update()
|
||||||
|
@ -86,8 +94,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
GetComponent<UnityEngine.Renderer>().material.color = color;
|
GetComponent<UnityEngine.Renderer>().material.color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d7bdc7e70331fe24aba2c9549f84c657
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -1,371 +1,371 @@
|
||||||
///Credit judah4
|
///Credit judah4
|
||||||
///Sourced from - http://forum.unity3d.com/threads/color-picker.267043/
|
///Sourced from - http://forum.unity3d.com/threads/color-picker.267043/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
[RequireComponent(typeof(RectTransform))]
|
[RequireComponent(typeof(RectTransform))]
|
||||||
[AddComponentMenu("UI/Extensions/BoxSlider")]
|
[AddComponentMenu("UI/Extensions/Sliders/BoxSlider")]
|
||||||
public class BoxSlider : Selectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement
|
public class BoxSlider : Selectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement
|
||||||
{
|
{
|
||||||
public enum Direction
|
public enum Direction
|
||||||
{
|
{
|
||||||
LeftToRight,
|
LeftToRight,
|
||||||
RightToLeft,
|
RightToLeft,
|
||||||
BottomToTop,
|
BottomToTop,
|
||||||
TopToBottom,
|
TopToBottom,
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class BoxSliderEvent : UnityEvent<float, float> { }
|
public class BoxSliderEvent : UnityEvent<float, float> { }
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private RectTransform m_HandleRect;
|
private RectTransform m_HandleRect;
|
||||||
public RectTransform HandleRect { get { return m_HandleRect; } set { if (SetClass(ref m_HandleRect, value)) { UpdateCachedReferences(); UpdateVisuals(); } } }
|
public RectTransform HandleRect { get { return m_HandleRect; } set { if (SetClass(ref m_HandleRect, value)) { UpdateCachedReferences(); UpdateVisuals(); } } }
|
||||||
|
|
||||||
[Space(6)]
|
[Space(6)]
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private float m_MinValue = 0;
|
private float m_MinValue = 0;
|
||||||
public float MinValue { get { return m_MinValue; } set { if (SetStruct(ref m_MinValue, value)) { SetX(m_ValueX); SetY(m_ValueY); UpdateVisuals(); } } }
|
public float MinValue { get { return m_MinValue; } set { if (SetStruct(ref m_MinValue, value)) { SetX(m_ValueX); SetY(m_ValueY); UpdateVisuals(); } } }
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private float m_MaxValue = 1;
|
private float m_MaxValue = 1;
|
||||||
public float MaxValue { get { return m_MaxValue; } set { if (SetStruct(ref m_MaxValue, value)) { SetX(m_ValueX); SetY(m_ValueY); UpdateVisuals(); } } }
|
public float MaxValue { get { return m_MaxValue; } set { if (SetStruct(ref m_MaxValue, value)) { SetX(m_ValueX); SetY(m_ValueY); UpdateVisuals(); } } }
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private bool m_WholeNumbers = false;
|
private bool m_WholeNumbers = false;
|
||||||
public bool WholeNumbers { get { return m_WholeNumbers; } set { if (SetStruct(ref m_WholeNumbers, value)) { SetX(m_ValueX); SetY(m_ValueY); UpdateVisuals(); } } }
|
public bool WholeNumbers { get { return m_WholeNumbers; } set { if (SetStruct(ref m_WholeNumbers, value)) { SetX(m_ValueX); SetY(m_ValueY); UpdateVisuals(); } } }
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private float m_ValueX = 1f;
|
private float m_ValueX = 1f;
|
||||||
public float ValueX
|
public float ValueX
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (WholeNumbers)
|
if (WholeNumbers)
|
||||||
return Mathf.Round(m_ValueX);
|
return Mathf.Round(m_ValueX);
|
||||||
return m_ValueX;
|
return m_ValueX;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SetX(value);
|
SetX(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float NormalizedValueX
|
public float NormalizedValueX
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (Mathf.Approximately(MinValue, MaxValue))
|
if (Mathf.Approximately(MinValue, MaxValue))
|
||||||
return 0;
|
return 0;
|
||||||
return Mathf.InverseLerp(MinValue, MaxValue, ValueX);
|
return Mathf.InverseLerp(MinValue, MaxValue, ValueX);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
this.ValueX = Mathf.Lerp(MinValue, MaxValue, value);
|
this.ValueX = Mathf.Lerp(MinValue, MaxValue, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private float m_ValueY = 1f;
|
private float m_ValueY = 1f;
|
||||||
public float ValueY
|
public float ValueY
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (WholeNumbers)
|
if (WholeNumbers)
|
||||||
return Mathf.Round(m_ValueY);
|
return Mathf.Round(m_ValueY);
|
||||||
return m_ValueY;
|
return m_ValueY;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SetY(value);
|
SetY(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float NormalizedValueY
|
public float NormalizedValueY
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (Mathf.Approximately(MinValue, MaxValue))
|
if (Mathf.Approximately(MinValue, MaxValue))
|
||||||
return 0;
|
return 0;
|
||||||
return Mathf.InverseLerp(MinValue, MaxValue, ValueY);
|
return Mathf.InverseLerp(MinValue, MaxValue, ValueY);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
this.ValueY = Mathf.Lerp(MinValue, MaxValue, value);
|
this.ValueY = Mathf.Lerp(MinValue, MaxValue, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Space(6)]
|
[Space(6)]
|
||||||
|
|
||||||
// Allow for delegate-based subscriptions for faster events than 'eventReceiver', and allowing for multiple receivers.
|
// Allow for delegate-based subscriptions for faster events than 'eventReceiver', and allowing for multiple receivers.
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private BoxSliderEvent m_OnValueChanged = new BoxSliderEvent();
|
private BoxSliderEvent m_OnValueChanged = new BoxSliderEvent();
|
||||||
public BoxSliderEvent OnValueChanged { get { return m_OnValueChanged; } set { m_OnValueChanged = value; } }
|
public BoxSliderEvent OnValueChanged { get { return m_OnValueChanged; } set { m_OnValueChanged = value; } }
|
||||||
|
|
||||||
// Private fields
|
// Private fields
|
||||||
|
|
||||||
private Transform m_HandleTransform;
|
private Transform m_HandleTransform;
|
||||||
private RectTransform m_HandleContainerRect;
|
private RectTransform m_HandleContainerRect;
|
||||||
|
|
||||||
// The offset from handle position to mouse down position
|
// The offset from handle position to mouse down position
|
||||||
private Vector2 m_Offset = Vector2.zero;
|
private Vector2 m_Offset = Vector2.zero;
|
||||||
|
|
||||||
private DrivenRectTransformTracker m_Tracker;
|
private DrivenRectTransformTracker m_Tracker;
|
||||||
|
|
||||||
// Size of each step.
|
// Size of each step.
|
||||||
float StepSize { get { return WholeNumbers ? 1 : (MaxValue - MinValue) * 0.1f; } }
|
float StepSize { get { return WholeNumbers ? 1 : (MaxValue - MinValue) * 0.1f; } }
|
||||||
|
|
||||||
protected BoxSlider()
|
protected BoxSlider()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
protected override void OnValidate()
|
protected override void OnValidate()
|
||||||
{
|
{
|
||||||
base.OnValidate();
|
base.OnValidate();
|
||||||
|
|
||||||
if (WholeNumbers)
|
if (WholeNumbers)
|
||||||
{
|
{
|
||||||
m_MinValue = Mathf.Round(m_MinValue);
|
m_MinValue = Mathf.Round(m_MinValue);
|
||||||
m_MaxValue = Mathf.Round(m_MaxValue);
|
m_MaxValue = Mathf.Round(m_MaxValue);
|
||||||
}
|
}
|
||||||
UpdateCachedReferences();
|
UpdateCachedReferences();
|
||||||
SetX(m_ValueX, false);
|
SetX(m_ValueX, false);
|
||||||
SetY(m_ValueY, false);
|
SetY(m_ValueY, false);
|
||||||
// Update rects since other things might affect them even if value didn't change.
|
// Update rects since other things might affect them even if value didn't change.
|
||||||
if(!Application.isPlaying) UpdateVisuals();
|
if(!Application.isPlaying) UpdateVisuals();
|
||||||
|
|
||||||
#if UNITY_2018_3_OR_NEWER
|
#if UNITY_2018_3_OR_NEWER
|
||||||
if (!Application.isPlaying)
|
if (!Application.isPlaying)
|
||||||
#else
|
#else
|
||||||
var prefabType = UnityEditor.PrefabUtility.GetPrefabType(this);
|
var prefabType = UnityEditor.PrefabUtility.GetPrefabType(this);
|
||||||
if (prefabType != UnityEditor.PrefabType.Prefab && !Application.isPlaying)
|
if (prefabType != UnityEditor.PrefabType.Prefab && !Application.isPlaying)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this);
|
CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // if UNITY_EDITOR
|
#endif // if UNITY_EDITOR
|
||||||
|
|
||||||
public virtual void Rebuild(CanvasUpdate executing)
|
public virtual void Rebuild(CanvasUpdate executing)
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
if (executing == CanvasUpdate.Prelayout)
|
if (executing == CanvasUpdate.Prelayout)
|
||||||
OnValueChanged.Invoke(ValueX, ValueY);
|
OnValueChanged.Invoke(ValueX, ValueY);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LayoutComplete()
|
public void LayoutComplete()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GraphicUpdateComplete()
|
public void GraphicUpdateComplete()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool SetClass<T>(ref T currentValue, T newValue) where T : class
|
public static bool SetClass<T>(ref T currentValue, T newValue) where T : class
|
||||||
{
|
{
|
||||||
if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue)))
|
if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
currentValue = newValue;
|
currentValue = newValue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool SetStruct<T>(ref T currentValue, T newValue) where T : struct
|
public static bool SetStruct<T>(ref T currentValue, T newValue) where T : struct
|
||||||
{
|
{
|
||||||
if (currentValue.Equals(newValue))
|
if (currentValue.Equals(newValue))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
currentValue = newValue;
|
currentValue = newValue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnEnable()
|
protected override void OnEnable()
|
||||||
{
|
{
|
||||||
base.OnEnable();
|
base.OnEnable();
|
||||||
UpdateCachedReferences();
|
UpdateCachedReferences();
|
||||||
SetX(m_ValueX, false);
|
SetX(m_ValueX, false);
|
||||||
SetY(m_ValueY, false);
|
SetY(m_ValueY, false);
|
||||||
// Update rects since they need to be initialized correctly.
|
// Update rects since they need to be initialized correctly.
|
||||||
UpdateVisuals();
|
UpdateVisuals();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisable()
|
protected override void OnDisable()
|
||||||
{
|
{
|
||||||
m_Tracker.Clear();
|
m_Tracker.Clear();
|
||||||
base.OnDisable();
|
base.OnDisable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateCachedReferences()
|
void UpdateCachedReferences()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (m_HandleRect)
|
if (m_HandleRect)
|
||||||
{
|
{
|
||||||
m_HandleTransform = m_HandleRect.transform;
|
m_HandleTransform = m_HandleRect.transform;
|
||||||
if (m_HandleTransform.parent != null)
|
if (m_HandleTransform.parent != null)
|
||||||
m_HandleContainerRect = m_HandleTransform.parent.GetComponent<RectTransform>();
|
m_HandleContainerRect = m_HandleTransform.parent.GetComponent<RectTransform>();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_HandleContainerRect = null;
|
m_HandleContainerRect = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the valueUpdate the visible Image.
|
// Set the valueUpdate the visible Image.
|
||||||
void SetX(float input)
|
void SetX(float input)
|
||||||
{
|
{
|
||||||
SetX(input, true);
|
SetX(input, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetX(float input, bool sendCallback)
|
void SetX(float input, bool sendCallback)
|
||||||
{
|
{
|
||||||
// Clamp the input
|
// Clamp the input
|
||||||
float newValue = Mathf.Clamp(input, MinValue, MaxValue);
|
float newValue = Mathf.Clamp(input, MinValue, MaxValue);
|
||||||
if (WholeNumbers)
|
if (WholeNumbers)
|
||||||
newValue = Mathf.Round(newValue);
|
newValue = Mathf.Round(newValue);
|
||||||
|
|
||||||
// If the stepped value doesn't match the last one, it's time to update
|
// If the stepped value doesn't match the last one, it's time to update
|
||||||
if (m_ValueX == newValue)
|
if (m_ValueX == newValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_ValueX = newValue;
|
m_ValueX = newValue;
|
||||||
UpdateVisuals();
|
UpdateVisuals();
|
||||||
if (sendCallback)
|
if (sendCallback)
|
||||||
m_OnValueChanged.Invoke(newValue, ValueY);
|
m_OnValueChanged.Invoke(newValue, ValueY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetY(float input)
|
void SetY(float input)
|
||||||
{
|
{
|
||||||
SetY(input, true);
|
SetY(input, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetY(float input, bool sendCallback)
|
void SetY(float input, bool sendCallback)
|
||||||
{
|
{
|
||||||
// Clamp the input
|
// Clamp the input
|
||||||
float newValue = Mathf.Clamp(input, MinValue, MaxValue);
|
float newValue = Mathf.Clamp(input, MinValue, MaxValue);
|
||||||
if (WholeNumbers)
|
if (WholeNumbers)
|
||||||
newValue = Mathf.Round(newValue);
|
newValue = Mathf.Round(newValue);
|
||||||
|
|
||||||
// If the stepped value doesn't match the last one, it's time to update
|
// If the stepped value doesn't match the last one, it's time to update
|
||||||
if (m_ValueY == newValue)
|
if (m_ValueY == newValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_ValueY = newValue;
|
m_ValueY = newValue;
|
||||||
UpdateVisuals();
|
UpdateVisuals();
|
||||||
if (sendCallback)
|
if (sendCallback)
|
||||||
m_OnValueChanged.Invoke(ValueX, newValue);
|
m_OnValueChanged.Invoke(ValueX, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void OnRectTransformDimensionsChange()
|
protected override void OnRectTransformDimensionsChange()
|
||||||
{
|
{
|
||||||
base.OnRectTransformDimensionsChange();
|
base.OnRectTransformDimensionsChange();
|
||||||
UpdateVisuals();
|
UpdateVisuals();
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Axis
|
enum Axis
|
||||||
{
|
{
|
||||||
Horizontal = 0,
|
Horizontal = 0,
|
||||||
Vertical = 1
|
Vertical = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Force-update the slider. Useful if you've changed the properties and want it to update visually.
|
// Force-update the slider. Useful if you've changed the properties and want it to update visually.
|
||||||
private void UpdateVisuals()
|
private void UpdateVisuals()
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
if (!Application.isPlaying)
|
if (!Application.isPlaying)
|
||||||
UpdateCachedReferences();
|
UpdateCachedReferences();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_Tracker.Clear();
|
m_Tracker.Clear();
|
||||||
|
|
||||||
|
|
||||||
//to business!
|
//to business!
|
||||||
if (m_HandleContainerRect != null)
|
if (m_HandleContainerRect != null)
|
||||||
{
|
{
|
||||||
m_Tracker.Add(this, m_HandleRect, DrivenTransformProperties.Anchors);
|
m_Tracker.Add(this, m_HandleRect, DrivenTransformProperties.Anchors);
|
||||||
Vector2 anchorMin = Vector2.zero;
|
Vector2 anchorMin = Vector2.zero;
|
||||||
Vector2 anchorMax = Vector2.one;
|
Vector2 anchorMax = Vector2.one;
|
||||||
anchorMin[0] = anchorMax[0] = (NormalizedValueX);
|
anchorMin[0] = anchorMax[0] = (NormalizedValueX);
|
||||||
anchorMin[1] = anchorMax[1] = (NormalizedValueY);
|
anchorMin[1] = anchorMax[1] = (NormalizedValueY);
|
||||||
|
|
||||||
if (Application.isPlaying)
|
if (Application.isPlaying)
|
||||||
{
|
{
|
||||||
m_HandleRect.anchorMin = anchorMin;
|
m_HandleRect.anchorMin = anchorMin;
|
||||||
m_HandleRect.anchorMax = anchorMax;
|
m_HandleRect.anchorMax = anchorMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the slider's position based on the mouse.
|
// Update the slider's position based on the mouse.
|
||||||
void UpdateDrag(PointerEventData eventData, Camera cam)
|
void UpdateDrag(PointerEventData eventData, Camera cam)
|
||||||
{
|
{
|
||||||
RectTransform clickRect = m_HandleContainerRect;
|
RectTransform clickRect = m_HandleContainerRect;
|
||||||
if (clickRect != null && clickRect.rect.size[0] > 0)
|
if (clickRect != null && clickRect.rect.size[0] > 0)
|
||||||
{
|
{
|
||||||
Vector2 localCursor;
|
Vector2 localCursor;
|
||||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam, out localCursor))
|
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam, out localCursor))
|
||||||
return;
|
return;
|
||||||
localCursor -= clickRect.rect.position;
|
localCursor -= clickRect.rect.position;
|
||||||
|
|
||||||
float val = Mathf.Clamp01((localCursor - m_Offset)[0] / clickRect.rect.size[0]);
|
float val = Mathf.Clamp01((localCursor - m_Offset)[0] / clickRect.rect.size[0]);
|
||||||
NormalizedValueX = (val);
|
NormalizedValueX = (val);
|
||||||
|
|
||||||
float valY = Mathf.Clamp01((localCursor - m_Offset)[1] / clickRect.rect.size[1]);
|
float valY = Mathf.Clamp01((localCursor - m_Offset)[1] / clickRect.rect.size[1]);
|
||||||
NormalizedValueY = (valY);
|
NormalizedValueY = (valY);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanDrag(PointerEventData eventData)
|
private bool CanDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
return IsActive() && IsInteractable() && eventData.button == PointerEventData.InputButton.Left;
|
return IsActive() && IsInteractable() && eventData.button == PointerEventData.InputButton.Left;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnPointerDown(PointerEventData eventData)
|
public override void OnPointerDown(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
if (!CanDrag(eventData))
|
if (!CanDrag(eventData))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
base.OnPointerDown(eventData);
|
base.OnPointerDown(eventData);
|
||||||
|
|
||||||
m_Offset = Vector2.zero;
|
m_Offset = Vector2.zero;
|
||||||
if (m_HandleContainerRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_HandleRect, eventData.position, eventData.enterEventCamera))
|
if (m_HandleContainerRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_HandleRect, eventData.position, eventData.enterEventCamera))
|
||||||
{
|
{
|
||||||
Vector2 localMousePos;
|
Vector2 localMousePos;
|
||||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_HandleRect, eventData.position, eventData.pressEventCamera, out localMousePos))
|
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_HandleRect, eventData.position, eventData.pressEventCamera, out localMousePos))
|
||||||
m_Offset = localMousePos;
|
m_Offset = localMousePos;
|
||||||
m_Offset.y = -m_Offset.y;
|
m_Offset.y = -m_Offset.y;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Outside the slider handle - jump to this point instead
|
// Outside the slider handle - jump to this point instead
|
||||||
UpdateDrag(eventData, eventData.pressEventCamera);
|
UpdateDrag(eventData, eventData.pressEventCamera);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnDrag(PointerEventData eventData)
|
public virtual void OnDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
if (!CanDrag(eventData))
|
if (!CanDrag(eventData))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateDrag(eventData, eventData.pressEventCamera);
|
UpdateDrag(eventData, eventData.pressEventCamera);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnInitializePotentialDrag(PointerEventData eventData)
|
public virtual void OnInitializePotentialDrag(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
eventData.useDragThreshold = false;
|
eventData.useDragThreshold = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
[AddComponentMenu("UI/Extensions/Radial Slider")]
|
|
||||||
[RequireComponent(typeof(Image))]
|
[RequireComponent(typeof(Image))]
|
||||||
|
[AddComponentMenu("UI/Extensions/Sliders/Radial Slider")]
|
||||||
public class RadialSlider : MonoBehaviour, IPointerEnterHandler, IPointerDownHandler, IPointerUpHandler, IDragHandler
|
public class RadialSlider : MonoBehaviour, IPointerEnterHandler, IPointerDownHandler, IPointerUpHandler, IDragHandler
|
||||||
{
|
{
|
||||||
private bool isPointerDown, isPointerReleased, lerpInProgress;
|
private bool isPointerDown, isPointerReleased, lerpInProgress;
|
|
@ -9,9 +9,9 @@ using UnityEngine.EventSystems;
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
[AddComponentMenu("UI/Extensions/Range Slider", 34)]
|
|
||||||
[ExecuteInEditMode]
|
[ExecuteInEditMode]
|
||||||
[RequireComponent(typeof(RectTransform))]
|
[RequireComponent(typeof(RectTransform))]
|
||||||
|
[AddComponentMenu("UI/Extensions/Sliders/Range Slider", 34)]
|
||||||
public class RangeSlider : Selectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement
|
public class RangeSlider : Selectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement
|
||||||
{
|
{
|
||||||
public enum Direction
|
public enum Direction
|
|
@ -9,9 +9,8 @@ using UnityEngine.EventSystems;
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
// Stepper control
|
// Stepper control
|
||||||
[ExecuteInEditMode]
|
|
||||||
[AddComponentMenu("UI/Extensions/Stepper")]
|
|
||||||
[RequireComponent(typeof(RectTransform))]
|
[RequireComponent(typeof(RectTransform))]
|
||||||
|
[AddComponentMenu("UI/Extensions/Sliders/Stepper")]
|
||||||
public class Stepper : UIBehaviour
|
public class Stepper : UIBehaviour
|
||||||
{
|
{
|
||||||
private Selectable[] _sides;
|
private Selectable[] _sides;
|
||||||
|
@ -90,6 +89,28 @@ namespace UnityEngine.UI.Extensions
|
||||||
protected Stepper()
|
protected Stepper()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
protected override void OnValidate()
|
||||||
|
{
|
||||||
|
base.OnValidate();
|
||||||
|
|
||||||
|
RecreateSprites(sides);
|
||||||
|
if (separator)
|
||||||
|
LayoutSides();
|
||||||
|
|
||||||
|
if (!wrap)
|
||||||
|
{
|
||||||
|
DisableAtExtremes(sides);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected override void Start()
|
||||||
|
{
|
||||||
|
if (isActiveAndEnabled)
|
||||||
|
StartCoroutine(DelayedInit());
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnEnable()
|
protected override void OnEnable()
|
||||||
{
|
{
|
||||||
StartCoroutine(DelayedInit());
|
StartCoroutine(DelayedInit());
|
|
@ -16,7 +16,12 @@ namespace UnityEngine.UI.Extensions {
|
||||||
[AddComponentMenu("UI/Extensions/TextPic")]
|
[AddComponentMenu("UI/Extensions/TextPic")]
|
||||||
|
|
||||||
[ExecuteInEditMode] // Needed for culling images that are not used //
|
[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
|
// Icon entry to replace text with
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public struct IconName {
|
public struct IconName {
|
||||||
|
@ -465,14 +470,21 @@ namespace UnityEngine.UI.Extensions {
|
||||||
/// UNITY METHODS ///
|
/// UNITY METHODS ///
|
||||||
|
|
||||||
protected override void OnPopulateMesh(VertexHelper toFill) {
|
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;
|
originalText = m_Text;
|
||||||
m_Text = GetOutputText();
|
m_Text = GetOutputText();
|
||||||
|
|
||||||
base.OnPopulateMesh(toFill);
|
base.OnPopulateMesh(toFill);
|
||||||
|
|
||||||
m_DisableFontTextureRebuiltCallback = true;
|
m_DisableFontTextureRebuiltCallback = true;
|
||||||
|
|
||||||
m_Text = originalText;
|
m_Text = originalText;
|
||||||
|
#endif
|
||||||
|
|
||||||
positions.Clear();
|
positions.Clear();
|
||||||
|
|
||||||
|
@ -539,8 +551,10 @@ namespace UnityEngine.UI.Extensions {
|
||||||
// Update the quad images
|
// Update the quad images
|
||||||
updateQuad = true;
|
updateQuad = true;
|
||||||
|
|
||||||
|
#if !UNITY_2022_1_OR_NEWER
|
||||||
m_DisableFontTextureRebuiltCallback = false;
|
m_DisableFontTextureRebuiltCallback = false;
|
||||||
}
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Click event is detected whether to click a hyperlink text
|
/// Click event is detected whether to click a hyperlink text
|
||||||
|
@ -641,7 +655,7 @@ namespace UnityEngine.UI.Extensions {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected override void OnEnable() {
|
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
|
// Here is the hack to see if Unity is using the new rendering system for text
|
||||||
usesNewRendering = false;
|
usesNewRendering = false;
|
||||||
|
|
||||||
|
@ -660,13 +674,14 @@ namespace UnityEngine.UI.Extensions {
|
||||||
else {
|
else {
|
||||||
usesNewRendering = true;
|
usesNewRendering = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
base.OnEnable();
|
base.OnEnable();
|
||||||
|
|
||||||
|
#if !UNITY_2022_1_OR_NEWER
|
||||||
supportRichText = true;
|
supportRichText = true;
|
||||||
alignByGeometry = true;
|
alignByGeometry = true;
|
||||||
|
#endif
|
||||||
// Enable images on TextPic disable
|
// Enable images on TextPic disable
|
||||||
if (m_ImagesPool.Count >= 1) {
|
if (m_ImagesPool.Count >= 1) {
|
||||||
for (int i = 0; i < m_ImagesPool.Count; i++) {
|
for (int i = 0; i < m_ImagesPool.Count; i++) {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/// Credit Melang
|
/// Credit Melang
|
||||||
/// Sourced from - http://forum.unity3d.com/members/melang.593409/
|
/// Sourced from - http://forum.unity3d.com/members/melang.593409/
|
||||||
|
/// NOT supported in Unity 2022
|
||||||
|
|
||||||
|
#if !UNITY_2022_1_OR_NEWER
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
|
@ -60,3 +62,4 @@ namespace UnityEngine.UI.Extensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
|
@ -1,6 +1,7 @@
|
||||||
/// Credit Titinious (https://github.com/Titinious)
|
/// Credit Titinious (https://github.com/Titinious)
|
||||||
/// Sourced from - https://github.com/Titinious/CurlyUI
|
/// Sourced from - https://github.com/Titinious/CurlyUI
|
||||||
|
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#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();
|
ReportSet();
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,24 @@
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
[RequireComponent(typeof(RectTransform))]
|
[RequireComponent(typeof(RectTransform))]
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
[RequireComponent(typeof(TMPro.TMP_Text))]
|
||||||
|
#else
|
||||||
[RequireComponent(typeof(Text))]
|
[RequireComponent(typeof(Text))]
|
||||||
|
#endif
|
||||||
[AddComponentMenu("UI/Effects/Extensions/Curly UI Text")]
|
[AddComponentMenu("UI/Effects/Extensions/Curly UI Text")]
|
||||||
public class CUIText : CUIGraphic
|
public class CUIText : CUIGraphic
|
||||||
{
|
{
|
||||||
public override void ReportSet()
|
public override void ReportSet()
|
||||||
{
|
{
|
||||||
if (uiGraphic == null)
|
if (uiGraphic == null)
|
||||||
|
{
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
uiGraphic = GetComponent<TMPro.TMP_Text>();
|
||||||
|
#else
|
||||||
uiGraphic = GetComponent<Text>();
|
uiGraphic = GetComponent<Text>();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
base.ReportSet();
|
base.ReportSet();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,12 @@
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
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")]
|
[AddComponentMenu("UI/Effects/Extensions/Curved Text")]
|
||||||
public class CurvedText : BaseMeshEffect
|
public class CurvedText : BaseMeshEffect
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,12 @@
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
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")]
|
[AddComponentMenu("UI/Effects/Extensions/Cylinder Text")]
|
||||||
public class CylinderText : BaseMeshEffect
|
public class CylinderText : BaseMeshEffect
|
||||||
{
|
{
|
||||||
|
|
|
@ -81,8 +81,12 @@ namespace UnityEngine.UI.Extensions
|
||||||
List<UIVertex> verts = new List<UIVertex>();
|
List<UIVertex> verts = new List<UIVertex>();
|
||||||
vh.GetUIVertexStream(verts);
|
vh.GetUIVertexStream(verts);
|
||||||
|
|
||||||
Text text = GetComponent<Text>();
|
#if UNITY_2022_1_OR_NEWER
|
||||||
if (text == null)
|
var text = GetComponent<TMPro.TMP_Text>();
|
||||||
|
#else
|
||||||
|
var text = GetComponent<Text>();
|
||||||
|
#endif
|
||||||
|
if (text == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("LetterSpacing: Missing Text component");
|
Debug.LogWarning("LetterSpacing: Missing Text component");
|
||||||
return;
|
return;
|
||||||
|
@ -93,29 +97,52 @@ namespace UnityEngine.UI.Extensions
|
||||||
float letterOffset = spacing * (float)text.fontSize / 100f;
|
float letterOffset = spacing * (float)text.fontSize / 100f;
|
||||||
float alignmentFactor = 0;
|
float alignmentFactor = 0;
|
||||||
int glyphIdx = 0;
|
int glyphIdx = 0;
|
||||||
|
|
||||||
switch (text.alignment)
|
#if UNITY_2022_1_OR_NEWER
|
||||||
{
|
switch (text.alignment)
|
||||||
case TextAnchor.LowerLeft:
|
{
|
||||||
case TextAnchor.MiddleLeft:
|
case TMPro.TextAlignmentOptions.BottomLeft:
|
||||||
case TextAnchor.UpperLeft:
|
case TMPro.TextAlignmentOptions.MidlineLeft:
|
||||||
alignmentFactor = 0f;
|
case TMPro.TextAlignmentOptions.TopLeft:
|
||||||
break;
|
alignmentFactor = 0f;
|
||||||
|
break;
|
||||||
case TextAnchor.LowerCenter:
|
|
||||||
case TextAnchor.MiddleCenter:
|
case TMPro.TextAlignmentOptions.BottomJustified:
|
||||||
case TextAnchor.UpperCenter:
|
case TMPro.TextAlignmentOptions.MidlineJustified:
|
||||||
alignmentFactor = 0.5f;
|
case TMPro.TextAlignmentOptions.TopJustified:
|
||||||
break;
|
alignmentFactor = 0.5f;
|
||||||
|
break;
|
||||||
case TextAnchor.LowerRight:
|
|
||||||
case TextAnchor.MiddleRight:
|
case TMPro.TextAlignmentOptions.BottomRight:
|
||||||
case TextAnchor.UpperRight:
|
case TMPro.TextAlignmentOptions.MidlineRight:
|
||||||
alignmentFactor = 1f;
|
case TMPro.TextAlignmentOptions.TopRight:
|
||||||
break;
|
alignmentFactor = 1f;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
for (int lineIdx=0; lineIdx < lines.Length; lineIdx++)
|
#else
|
||||||
|
switch (text.alignment)
|
||||||
|
{
|
||||||
|
case TextAnchor.LowerLeft:
|
||||||
|
case TextAnchor.MiddleLeft:
|
||||||
|
case TextAnchor.UpperLeft:
|
||||||
|
alignmentFactor = 0f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
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];
|
string line = lines[lineIdx];
|
||||||
float lineOffset = (line.Length -1) * letterOffset * alignmentFactor;
|
float lineOffset = (line.Length -1) * letterOffset * alignmentFactor;
|
||||||
|
|
|
@ -46,7 +46,11 @@ using System.Collections.Generic;
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
[AddComponentMenu("UI/Effects/Extensions/Mono Spacing")]
|
[AddComponentMenu("UI/Effects/Extensions/Mono Spacing")]
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
[RequireComponent(typeof(TMPro.TMP_Text))]
|
||||||
|
#else
|
||||||
[RequireComponent(typeof(Text))]
|
[RequireComponent(typeof(Text))]
|
||||||
|
#endif
|
||||||
[RequireComponent(typeof(RectTransform))]
|
[RequireComponent(typeof(RectTransform))]
|
||||||
///Summary
|
///Summary
|
||||||
/// Note, Vertex Count has changed in 5.2.1+, is now 6 (two tris) instead of 4 (tri strip).
|
/// 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;
|
public bool UseHalfCharWidth = false;
|
||||||
|
|
||||||
private RectTransform rectTransform;
|
private RectTransform rectTransform;
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
private TMPro.TMP_Text text;
|
||||||
|
#else
|
||||||
private Text text;
|
private Text text;
|
||||||
|
#endif
|
||||||
|
|
||||||
protected MonoSpacing() { }
|
protected MonoSpacing() { }
|
||||||
|
|
||||||
protected override void Awake()
|
protected override void Awake()
|
||||||
{
|
{
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
text = GetComponent<TMPro.TMP_Text>();
|
||||||
|
#else
|
||||||
text = GetComponent<Text>();
|
text = GetComponent<Text>();
|
||||||
|
#endif
|
||||||
if (text == null)
|
if (text == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("MonoSpacing: Missing Text component");
|
Debug.LogWarning("MonoSpacing: Missing Text component");
|
||||||
|
@ -104,29 +116,51 @@ namespace UnityEngine.UI.Extensions
|
||||||
float letterOffset = Spacing * (float)text.fontSize / 100f;
|
float letterOffset = Spacing * (float)text.fontSize / 100f;
|
||||||
float alignmentFactor = 0;
|
float alignmentFactor = 0;
|
||||||
int glyphIdx = 0;
|
int glyphIdx = 0;
|
||||||
|
|
||||||
switch (text.alignment)
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
switch (text.alignment)
|
||||||
{
|
{
|
||||||
case TextAnchor.LowerLeft:
|
case TMPro.TextAlignmentOptions.BottomLeft:
|
||||||
case TextAnchor.MiddleLeft:
|
case TMPro.TextAlignmentOptions.MidlineLeft:
|
||||||
case TextAnchor.UpperLeft:
|
case TMPro.TextAlignmentOptions.TopLeft:
|
||||||
alignmentFactor = 0f;
|
alignmentFactor = 0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TextAnchor.LowerCenter:
|
case TMPro.TextAlignmentOptions.BottomJustified:
|
||||||
case TextAnchor.MiddleCenter:
|
case TMPro.TextAlignmentOptions.MidlineJustified:
|
||||||
case TextAnchor.UpperCenter:
|
case TMPro.TextAlignmentOptions.TopJustified:
|
||||||
alignmentFactor = 0.5f;
|
alignmentFactor = 0.5f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TextAnchor.LowerRight:
|
case TMPro.TextAlignmentOptions.BottomRight:
|
||||||
case TextAnchor.MiddleRight:
|
case TMPro.TextAlignmentOptions.MidlineRight:
|
||||||
case TextAnchor.UpperRight:
|
case TMPro.TextAlignmentOptions.TopRight:
|
||||||
alignmentFactor = 1f;
|
alignmentFactor = 1f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
for (int lineIdx=0; lineIdx < lines.Length; lineIdx++)
|
switch (text.alignment)
|
||||||
|
{
|
||||||
|
case TextAnchor.LowerLeft:
|
||||||
|
case TextAnchor.MiddleLeft:
|
||||||
|
case TextAnchor.UpperLeft:
|
||||||
|
alignmentFactor = 0f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
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];
|
string line = lines[lineIdx];
|
||||||
float lineOffset = (line.Length - 1) * letterOffset * (alignmentFactor) - (alignmentFactor - 0.5f) * rectTransform.rect.width;
|
float lineOffset = (line.Length - 1) * letterOffset * (alignmentFactor) - (alignmentFactor - 0.5f) * rectTransform.rect.width;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
/// Credit Melang, Lee Hui
|
/// Credit Melang, Lee Hui
|
||||||
/// Sourced from - http://forum.unity3d.com/members/melang.593409/
|
/// Sourced from - http://forum.unity3d.com/members/melang.593409/
|
||||||
/// GC Alloc fix - https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/pull-requests/130
|
/// 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;
|
using System.Collections.Generic;
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
|
@ -192,4 +194,5 @@ namespace UnityEngine.UI.Extensions
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
|
@ -96,10 +96,8 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
effectRoot.SetActive(true);
|
effectRoot.SetActive(true);
|
||||||
}
|
}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnDestroy()
|
void OnDestroy()
|
||||||
{
|
{
|
||||||
if (!Application.isPlaying)
|
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
|
/// Sourced from - http://www.randomchaos.co.uk/SoftAlphaUIMask.aspx
|
||||||
/// Updated by valtain - https://bitbucket.org/SimonDarksideJ/unity-ui-extensions/pull-requests/33
|
/// Updated by valtain - https://bitbucket.org/SimonDarksideJ/unity-ui-extensions/pull-requests/33
|
||||||
|
|
||||||
|
@ -45,7 +47,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
MaskArea = GetComponent<RectTransform>();
|
MaskArea = GetComponent<RectTransform>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_2022_1_OR_NEWER
|
||||||
|
var text = GetComponent<TMPro.TMP_Text>();
|
||||||
|
#else
|
||||||
var text = GetComponent<Text>();
|
var text = GetComponent<Text>();
|
||||||
|
#endif
|
||||||
if (text != null)
|
if (text != null)
|
||||||
{
|
{
|
||||||
mat = new Material(ShaderLibrary.GetShaderInstance("UI Extensions/SoftMaskShader"));
|
mat = new Material(ShaderLibrary.GetShaderInstance("UI Extensions/SoftMaskShader"));
|
||||||
|
|
|
@ -398,6 +398,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
currentMaterial = null;
|
currentMaterial = null;
|
||||||
currentTexture = null;
|
currentTexture = null;
|
||||||
|
base.OnDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartParticleEmission()
|
public void StartParticleEmission()
|
||||||
|
|
|
@ -29,6 +29,13 @@ namespace UnityEngine.UI.Extensions
|
||||||
public float centerpoint = 0.5f;
|
public float centerpoint = 0.5f;
|
||||||
|
|
||||||
protected override void OnEnable() { base.OnEnable(); CalculateRadial(); }
|
protected override void OnEnable() { base.OnEnable(); CalculateRadial(); }
|
||||||
|
|
||||||
|
protected override void OnDisable()
|
||||||
|
{
|
||||||
|
m_Tracker.Clear();
|
||||||
|
LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetLayoutHorizontal() {
|
public override void SetLayoutHorizontal() {
|
||||||
}
|
}
|
||||||
public override void SetLayoutVertical() {
|
public override void SetLayoutVertical() {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/// Credit setchi (https://github.com/setchi)
|
/// Credit setchi (https://github.com/setchi)
|
||||||
/// Sourced from - https://github.com/setchi/FancyScrollView
|
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||||
|
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -101,7 +101,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// <param name="p"><see cref="Scroller"/> のスクロール位置.</param>
|
/// <param name="p"><see cref="Scroller"/> のスクロール位置.</param>
|
||||||
void OnScrollerValueChanged(float p)
|
void OnScrollerValueChanged(float p)
|
||||||
{
|
{
|
||||||
base.UpdatePosition(Scrollable ? ToFancyScrollViewPosition(p) : 0f);
|
base.UpdatePosition(ToFancyScrollViewPosition(Scrollable ? p : 0f));
|
||||||
|
|
||||||
if (Scroller.Scrollbar)
|
if (Scroller.Scrollbar)
|
||||||
{
|
{
|
||||||
|
@ -161,8 +161,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override void UpdateContents(IList<TItemData> items)
|
protected override void UpdateContents(IList<TItemData> items)
|
||||||
{
|
{
|
||||||
Debug.Assert(Context.CalculateScrollSize != null);
|
|
||||||
|
|
||||||
AdjustCellIntervalAndScrollOffset();
|
AdjustCellIntervalAndScrollOffset();
|
||||||
base.UpdateContents(items);
|
base.UpdateContents(items);
|
||||||
|
|
||||||
|
|
|
@ -53,4 +53,4 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public sealed override void SetContext(FancyScrollRectContext context) => base.SetContext(context);
|
public sealed override void SetContext(FancyScrollRectContext context) => base.SetContext(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -329,7 +329,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
if (hold && snap.Enable)
|
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);
|
ScrollTo(Mathf.RoundToInt(currentPosition), snap.Duration, snap.Easing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -166,7 +166,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
childSize = LayoutUtility.GetPreferredSize (child, 0);
|
childSize = LayoutUtility.GetPreferredSize (child, 0);
|
||||||
childSize = Mathf.Min (childSize, workingSize);
|
childSize = Mathf.Min (childSize, workingSize);
|
||||||
childOtherSize = LayoutUtility.GetPreferredSize (child, 1);
|
childOtherSize = LayoutUtility.GetPreferredSize (child, 1);
|
||||||
childOtherSize = Mathf.Min (childOtherSize, workingSize);
|
|
||||||
} else if (startAxis == Axis.Vertical) {
|
} else if (startAxis == Axis.Vertical) {
|
||||||
if (invertOrder) {
|
if (invertOrder) {
|
||||||
index = IsRightAlign ? rectChildren.Count - 1 - i : i;
|
index = IsRightAlign ? rectChildren.Count - 1 - i : i;
|
||||||
|
@ -175,7 +174,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
childSize = LayoutUtility.GetPreferredSize (child, 1);
|
childSize = LayoutUtility.GetPreferredSize (child, 1);
|
||||||
childSize = Mathf.Min (childSize, workingSize);
|
childSize = Mathf.Min (childSize, workingSize);
|
||||||
childOtherSize = LayoutUtility.GetPreferredSize (child, 0);
|
childOtherSize = LayoutUtility.GetPreferredSize (child, 0);
|
||||||
childOtherSize = Mathf.Min (childOtherSize, workingSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If adding this element would exceed the bounds of the container,
|
// If adding this element would exceed the bounds of the container,
|
||||||
|
@ -227,11 +225,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
if (startAxis == Axis.Horizontal) {
|
if (startAxis == Axis.Horizontal) {
|
||||||
float newOffset = CalculateRowVerticalOffset (groupHeight, offset, currentBarSpace);
|
float newOffset = CalculateRowVerticalOffset (groupHeight, offset, currentBarSpace);
|
||||||
currentBarSize -= spacingBetweenElements;
|
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) {
|
}else if (startAxis == Axis.Vertical) {
|
||||||
float newOffset = CalculateColHorizontalOffset(groupWidth, offset, currentBarSpace);
|
float newOffset = CalculateColHorizontalOffset(groupWidth, offset, currentBarSpace);
|
||||||
currentBarSize -= spacingBetweenElements;
|
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;
|
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>
|
/// <param name="WorldPositionStays">Should the world position be updated to it's parent transform?</param>
|
||||||
public void AddChild(GameObject GO, bool WorldPositionStays)
|
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);
|
GO.transform.SetParent(_screensContainer, WorldPositionStays);
|
||||||
InitialiseChildObjectsFromScene();
|
InitialiseChildObjectsFromScene();
|
||||||
DistributePages();
|
DistributePages();
|
||||||
if (MaskArea)
|
if (MaskArea)
|
||||||
|
{
|
||||||
UpdateVisible();
|
UpdateVisible();
|
||||||
|
}
|
||||||
|
|
||||||
SetScrollContainerPosition();
|
SetScrollContainerPosition();
|
||||||
}
|
}
|
||||||
|
@ -149,7 +157,12 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
return;
|
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);
|
Transform child = _screensContainer.transform.GetChild(index);
|
||||||
child.SetParent(null, WorldPositionStays);
|
child.SetParent(null, WorldPositionStays);
|
||||||
|
|
|
@ -55,6 +55,13 @@ namespace UnityEngine.UI.Extensions
|
||||||
CalculateRadial();
|
CalculateRadial();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
protected override void OnDisable()
|
||||||
|
{
|
||||||
|
m_Tracker.Clear(); // key change - do not restore - false
|
||||||
|
LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
|
||||||
|
}
|
||||||
|
|
||||||
void CalculateRadial()
|
void CalculateRadial()
|
||||||
{
|
{
|
||||||
m_Tracker.Clear();
|
m_Tracker.Clear();
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
/// Sourced from - https://github.com/setchi/FancyScrollView
|
/// Sourced from - https://github.com/setchi/FancyScrollView
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using UnityEngine.Events;
|
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
|
[Obsolete("ScrollPositionController has been replaced by the Scroller component", true)]
|
||||||
public class ScrollPositionController : UIBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
|
public class ScrollPositionController : UIBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
|
||||||
{
|
{
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
using System;
|
using System;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.UI.Extensions;
|
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
|
@ -14,9 +13,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
internal Rect panelDimensions;
|
internal Rect panelDimensions;
|
||||||
internal RectTransform _screensContainer;
|
internal RectTransform _screensContainer;
|
||||||
internal bool _isVertical;
|
internal bool _isVertical;
|
||||||
|
|
||||||
internal int _screens = 1;
|
internal int _screens = 1;
|
||||||
|
|
||||||
internal float _scrollStartPosition;
|
internal float _scrollStartPosition;
|
||||||
internal float _childSize;
|
internal float _childSize;
|
||||||
private float _childPos, _maskSize;
|
private float _childPos, _maskSize;
|
||||||
|
@ -27,7 +24,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
internal bool _pointerDown = false;
|
internal bool _pointerDown = false;
|
||||||
internal bool _settled = true;
|
internal bool _settled = true;
|
||||||
internal Vector3 _startPosition = new Vector3();
|
internal Vector3 _startPosition = new Vector3();
|
||||||
[Tooltip("The currently active page")]
|
|
||||||
internal int _currentPage;
|
internal int _currentPage;
|
||||||
internal int _previousPage;
|
internal int _previousPage;
|
||||||
internal int _halfNoVisibleItems;
|
internal int _halfNoVisibleItems;
|
||||||
|
@ -37,7 +33,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
private int _bottomItem, _topItem;
|
private int _bottomItem, _topItem;
|
||||||
internal bool _startEventCalled = false;
|
internal bool _startEventCalled = false;
|
||||||
internal bool _endEventCalled = false;
|
internal bool _endEventCalled = false;
|
||||||
internal bool _suspendEvents = false;
|
internal bool _suspendEvents = false;
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class SelectionChangeStartEvent : UnityEvent { }
|
public class SelectionChangeStartEvent : UnityEvent { }
|
||||||
|
@ -68,25 +64,25 @@ namespace UnityEngine.UI.Extensions
|
||||||
public float transitionSpeed = 7.5f;
|
public float transitionSpeed = 7.5f;
|
||||||
|
|
||||||
[Tooltip("Hard Swipe forces to swiping to the next / previous page (optional)")]
|
[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)")]
|
[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)")]
|
[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)")]
|
[Tooltip("Offset for how far a swipe has to travel to initiate a page change (optional)")]
|
||||||
public int FastSwipeThreshold = 100;
|
public int FastSwipeThreshold = 100;
|
||||||
|
|
||||||
[Tooltip("Speed at which the ScrollRect will keep scrolling before slowing down and stopping (optional)")]
|
[Tooltip("Speed at which the ScrollRect will keep scrolling before slowing down and stopping (optional)")]
|
||||||
public int SwipeVelocityThreshold = 100;
|
public int SwipeVelocityThreshold = 100;
|
||||||
|
|
||||||
[Tooltip("Threshold for swipe speed to initiate a swipe, below threshold will return to closest page (optional)")]
|
[Tooltip("Threshold for swipe speed to initiate a swipe, below threshold will return to closest page (optional)")]
|
||||||
public float SwipeDeltaThreshold = 5.0f;
|
public float SwipeDeltaThreshold = 5.0f;
|
||||||
|
|
||||||
[Tooltip("Use time scale instead of unscaled time (optional)")]
|
[Tooltip("Use time scale instead of unscaled time (optional)")]
|
||||||
public Boolean UseTimeScale = true;
|
public bool UseTimeScale = true;
|
||||||
|
|
||||||
[Tooltip("The visible bounds area, controls which items are visible/enabled. *Note Should use a RectMask. (optional)")]
|
[Tooltip("The visible bounds area, controls which items are visible/enabled. *Note Should use a RectMask. (optional)")]
|
||||||
public RectTransform MaskArea;
|
public RectTransform MaskArea;
|
||||||
|
@ -168,7 +164,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
private SelectionChangeEndEvent m_OnSelectionChangeEndEvent = new SelectionChangeEndEvent();
|
private SelectionChangeEndEvent m_OnSelectionChangeEndEvent = new SelectionChangeEndEvent();
|
||||||
public SelectionChangeEndEvent OnSelectionChangeEndEvent { get { return m_OnSelectionChangeEndEvent; } set { m_OnSelectionChangeEndEvent = value; } }
|
public SelectionChangeEndEvent OnSelectionChangeEndEvent { get { return m_OnSelectionChangeEndEvent; } set { m_OnSelectionChangeEndEvent = value; } }
|
||||||
|
|
||||||
// Use this for initialization
|
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
if (_scroll_rect == null)
|
if (_scroll_rect == null)
|
||||||
|
@ -186,7 +181,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
vscroll.ss = this;
|
vscroll.ss = this;
|
||||||
}
|
}
|
||||||
panelDimensions = gameObject.GetComponent<RectTransform>().rect;
|
panelDimensions = gameObject.GetComponent<RectTransform>().rect;
|
||||||
|
|
||||||
if (StartingScreen < 0)
|
if (StartingScreen < 0)
|
||||||
{
|
{
|
||||||
StartingScreen = 0;
|
StartingScreen = 0;
|
||||||
|
@ -315,8 +310,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
//Function for switching screens with buttons
|
//Function for switching screens with buttons
|
||||||
public void NextScreen()
|
public void NextScreen()
|
||||||
{
|
{
|
||||||
_scroll_rect.velocity = Vector2.zero;
|
|
||||||
|
|
||||||
if (_currentPage < _screens - 1 || _isInfinite)
|
if (_currentPage < _screens - 1 || _isInfinite)
|
||||||
{
|
{
|
||||||
if (!_lerp) StartScreenChange();
|
if (!_lerp) StartScreenChange();
|
||||||
|
@ -339,8 +332,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
//Function for switching screens with buttons
|
//Function for switching screens with buttons
|
||||||
public void PreviousScreen()
|
public void PreviousScreen()
|
||||||
{
|
{
|
||||||
_scroll_rect.velocity = Vector2.zero;
|
|
||||||
|
|
||||||
if (_currentPage > 0 || _isInfinite)
|
if (_currentPage > 0 || _isInfinite)
|
||||||
{
|
{
|
||||||
if (!_lerp) StartScreenChange();
|
if (!_lerp) StartScreenChange();
|
||||||
|
@ -419,7 +410,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_infiniteOffset = _screensContainer.anchoredPosition.x < 0 ? -_screensContainer.sizeDelta.x * _infiniteWindow : _screensContainer.sizeDelta.x * _infiniteWindow;
|
_infiniteOffset = _screensContainer.anchoredPosition.x < 0 ? -_screensContainer.sizeDelta.x * _infiniteWindow : _screensContainer.sizeDelta.x * _infiniteWindow;
|
||||||
_infiniteOffset = _infiniteOffset == 0 ? 0 : _infiniteOffset < 0 ? _infiniteOffset - _childSize * _infiniteWindow : _infiniteOffset + _childSize * _infiniteWindow;
|
_infiniteOffset = _infiniteOffset == 0 ? 0 : _infiniteOffset < 0 ? _infiniteOffset - _childSize * _infiniteWindow : _infiniteOffset + _childSize * _infiniteWindow;
|
||||||
target.x = _childPos + _scrollStartPosition + _infiniteOffset;
|
target.x = _childPos + _scrollStartPosition + _infiniteOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -520,8 +511,15 @@ namespace UnityEngine.UI.Extensions
|
||||||
MaskBuffer = 1;
|
MaskBuffer = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageStep.Clamp(0, 9);
|
if (PageStep < 0)
|
||||||
|
{
|
||||||
|
PageStep = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PageStep > 8)
|
||||||
|
{
|
||||||
|
PageStep = 9;
|
||||||
|
}
|
||||||
var infiniteScroll = GetComponent<UI_InfiniteScroll>();
|
var infiniteScroll = GetComponent<UI_InfiniteScroll>();
|
||||||
if (ChildObjects != null && ChildObjects.Length > 0 && infiniteScroll != null && !infiniteScroll.InitByUser)
|
if (ChildObjects != null && ChildObjects.Length > 0 && infiniteScroll != null && !infiniteScroll.InitByUser)
|
||||||
{
|
{
|
||||||
|
@ -645,4 +643,4 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -284,5 +284,11 @@ namespace UnityEngine.UI.Extensions
|
||||||
// Set preferredRowHeights to null to free memory
|
// Set preferredRowHeights to null to free memory
|
||||||
preferredRowHeights = null;
|
preferredRowHeights = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnDisable()
|
||||||
|
{
|
||||||
|
m_Tracker.Clear(); // key change - do not restore - false
|
||||||
|
LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,12 @@
|
||||||
/// Credit Ges
|
/// Credit Ges
|
||||||
/// Sourced from - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-3#post-2280109
|
/// Sourced from - http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-3#post-2280109
|
||||||
|
|
||||||
|
using System;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
|
||||||
namespace UnityEngine.UI.Extensions
|
namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
|
[Obsolete("TileSizeFitter will be deprecated in next version as Unity has disabled this feature")]
|
||||||
[ExecuteInEditMode]
|
[ExecuteInEditMode]
|
||||||
[RequireComponent(typeof(RectTransform))]
|
[RequireComponent(typeof(RectTransform))]
|
||||||
[AddComponentMenu("Layout/Extensions/Tile Size Fitter")]
|
[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")]
|
[AddComponentMenu("Layout/Extensions/Vertical Scroller")]
|
||||||
public class UIVerticalScroller : MonoBehaviour
|
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[] distReposition;
|
||||||
private float[] distance;
|
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)
|
//Scrollable area (content of desired ScrollRect)
|
||||||
[HideInInspector]
|
public RectTransform ScrollingPanel{ get { return scrollRect.content; } }
|
||||||
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()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor when not used as component but called from other script
|
/// Constructor when not used as component but called from other script
|
||||||
|
@ -66,7 +82,7 @@ namespace UnityEngine.UI.Extensions
|
||||||
this.center = center;
|
this.center = center;
|
||||||
this.elementSize = elementSize;
|
this.elementSize = elementSize;
|
||||||
this.scrollRect = scrollRect;
|
this.scrollRect = scrollRect;
|
||||||
_arrayOfElements = arrayOfElements;
|
this.arrayOfElements = arrayOfElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -78,21 +94,28 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
scrollRect = GetComponent<ScrollRect>();
|
scrollRect = GetComponent<ScrollRect>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!center)
|
if (!center)
|
||||||
{
|
{
|
||||||
Debug.LogError("Please define the RectTransform for the Center viewport of the scrollable area");
|
Debug.LogError("Please define the RectTransform for the Center viewport of the scrollable area");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!elementSize)
|
if (!elementSize)
|
||||||
{
|
{
|
||||||
elementSize = center;
|
elementSize = center;
|
||||||
}
|
}
|
||||||
if (_arrayOfElements == null || _arrayOfElements.Length == 0)
|
|
||||||
|
if (arrayOfElements == null || arrayOfElements.Length == 0)
|
||||||
{
|
{
|
||||||
_arrayOfElements = new GameObject[scrollingPanel.childCount];
|
var childCount = ScrollingPanel.childCount;
|
||||||
for (int i = 0; i < scrollingPanel.childCount; i++)
|
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>
|
/// </summary>
|
||||||
/// <param name="startingIndex">Starting index.</param>
|
/// <param name="startingIndex">Starting index.</param>
|
||||||
/// <param name="arrayOfElements">Array of elements.</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.
|
// Set _arrayOfElements to arrayOfElements if given, otherwise to child objects of the scrolling panel.
|
||||||
if (arrayOfElements != null)
|
if (arrayOfElements != null)
|
||||||
{
|
{
|
||||||
_arrayOfElements = arrayOfElements;
|
this.arrayOfElements = arrayOfElements;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_arrayOfElements = new GameObject[scrollingPanel.childCount];
|
this.arrayOfElements = new GameObject[ScrollingPanel.childCount];
|
||||||
for (int i = 0; i < scrollingPanel.childCount; i++)
|
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
|
// 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;
|
AddListener(arrayOfElements[i], i);
|
||||||
_arrayOfElements[i].GetComponent<Button>().onClick.RemoveAllListeners();
|
|
||||||
if (OnButtonClicked != null)
|
RectTransform r = this.arrayOfElements[i].GetComponent<RectTransform>();
|
||||||
{
|
|
||||||
_arrayOfElements[i].GetComponent<Button>().onClick.AddListener(() => OnButtonClicked.Invoke(j));
|
|
||||||
}
|
|
||||||
RectTransform r = _arrayOfElements[i].GetComponent<RectTransform>();
|
|
||||||
r.anchorMax = r.anchorMin = r.pivot = new Vector2(0.5f, 0.5f);
|
r.anchorMax = r.anchorMin = r.pivot = new Vector2(0.5f, 0.5f);
|
||||||
r.localPosition = new Vector2(0, i * elementSize.rect.size.y);
|
r.localPosition = new Vector2(0, i * elementSize.rect.size.y);
|
||||||
r.sizeDelta = elementSize.rect.size;
|
r.sizeDelta = elementSize.rect.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare for scrolling
|
// prepare for scrolling
|
||||||
distance = new float[_arrayOfElements.Length];
|
distance = new float[this.arrayOfElements.Length];
|
||||||
distReposition = new float[_arrayOfElements.Length];
|
distReposition = new float[this.arrayOfElements.Length];
|
||||||
focusedElementIndex = -1;
|
FocusedElementIndex = -1;
|
||||||
|
|
||||||
//scrollRect.scrollSensitivity = elementSize.rect.height / 5;
|
|
||||||
|
|
||||||
// if starting index is given, snap to respective element
|
// if starting index is given, snap to respective element
|
||||||
if (startingIndex > -1)
|
if (startingIndex > -1)
|
||||||
{
|
{
|
||||||
startingIndex = startingIndex > _arrayOfElements.Length ? _arrayOfElements.Length - 1 : startingIndex;
|
startingIndex = startingIndex > this.arrayOfElements.Length ? this.arrayOfElements.Length - 1 : startingIndex;
|
||||||
SnapToElement(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()
|
public void Start()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (scrollUpButton)
|
if (scrollUpButton)
|
||||||
scrollUpButton.GetComponent<Button>().onClick.AddListener(() =>
|
{
|
||||||
{
|
scrollUpButton.GetComponent<Button>().onClick.AddListener(() => ScrollUp());
|
||||||
ScrollUp();
|
}
|
||||||
});
|
|
||||||
|
|
||||||
if (scrollDownButton)
|
if (scrollDownButton)
|
||||||
scrollDownButton.GetComponent<Button>().onClick.AddListener(() =>
|
{
|
||||||
{
|
scrollDownButton.GetComponent<Button>().onClick.AddListener(() => ScrollDown());
|
||||||
ScrollDown();
|
}
|
||||||
});
|
UpdateChildren(startingIndex, arrayOfElements);
|
||||||
updateChildren(startingIndex, _arrayOfElements);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
if (_arrayOfElements.Length < 1)
|
if (arrayOfElements.Length < 1)
|
||||||
{
|
{
|
||||||
return;
|
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]);
|
distance[i] = Mathf.Abs(distReposition[i]);
|
||||||
|
|
||||||
//Magnifying effect
|
//Magnifying effect
|
||||||
Vector2 scale = Vector2.Max(minScale, new Vector2(1 / (1 + distance[i] * elementShrinkage.x), (1 / (1 + distance[i] * elementShrinkage.y))));
|
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
|
// detect focused element
|
||||||
float minDistance = Mathf.Min(distance);
|
float minDistance = Mathf.Min(distance);
|
||||||
int oldFocusedElement = focusedElementIndex;
|
int oldFocusedElement = FocusedElementIndex;
|
||||||
for (var i = 0; i < _arrayOfElements.Length; i++)
|
|
||||||
|
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])
|
if (minDistance == distance[i])
|
||||||
{
|
{
|
||||||
focusedElementIndex = i;
|
FocusedElementIndex = i;
|
||||||
result = _arrayOfElements[i].GetComponentInChildren<Text>().text;
|
#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))
|
if (!UIExtensionsInputManager.GetMouseButton(0))
|
||||||
{
|
{
|
||||||
|
@ -206,11 +239,10 @@ namespace UnityEngine.UI.Extensions
|
||||||
ScrollingElements();
|
ScrollingElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// stop scrolling past last element from inertia
|
// stop scrolling past last element from inertia
|
||||||
if (stopMomentumOnEnd
|
if (stopMomentumOnEnd
|
||||||
&& (_arrayOfElements[0].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))
|
|| arrayOfElements[arrayOfElements.Length - 1].GetComponent<RectTransform>().position.y < center.position.y))
|
||||||
{
|
{
|
||||||
scrollRect.velocity = Vector2.zero;
|
scrollRect.velocity = Vector2.zero;
|
||||||
}
|
}
|
||||||
|
@ -218,37 +250,30 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
private void ScrollingElements()
|
private void ScrollingElements()
|
||||||
{
|
{
|
||||||
float newY = Mathf.Lerp(scrollingPanel.anchoredPosition.y, scrollingPanel.anchoredPosition.y + distReposition[focusedElementIndex], Time.deltaTime * 2f);
|
float newY = Mathf.Lerp(ScrollingPanel.anchoredPosition.y, ScrollingPanel.anchoredPosition.y + distReposition[FocusedElementIndex], Time.deltaTime * 2f);
|
||||||
Vector2 newPosition = new Vector2(scrollingPanel.anchoredPosition.x, newY);
|
Vector2 newPosition = new Vector2(ScrollingPanel.anchoredPosition.x, newY);
|
||||||
scrollingPanel.anchoredPosition = newPosition;
|
ScrollingPanel.anchoredPosition = newPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SnapToElement(int element)
|
public void SnapToElement(int element)
|
||||||
{
|
{
|
||||||
float deltaElementPositionY = elementSize.rect.height * element;
|
float deltaElementPositionY = elementSize.rect.height * element;
|
||||||
Vector2 newPosition = new Vector2(scrollingPanel.anchoredPosition.x, -deltaElementPositionY);
|
Vector2 newPosition = new Vector2(ScrollingPanel.anchoredPosition.x, -deltaElementPositionY);
|
||||||
scrollingPanel.anchoredPosition = newPosition;
|
ScrollingPanel.anchoredPosition = newPosition;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ScrollUp()
|
public void ScrollUp()
|
||||||
{
|
{
|
||||||
float deltaUp = elementSize.rect.height / 1.2f;
|
float deltaUp = elementSize.rect.height / 1.2f;
|
||||||
Vector2 newPositionUp = new Vector2(scrollingPanel.anchoredPosition.x, scrollingPanel.anchoredPosition.y - deltaUp);
|
Vector2 newPositionUp = new Vector2(ScrollingPanel.anchoredPosition.x, ScrollingPanel.anchoredPosition.y - deltaUp);
|
||||||
scrollingPanel.anchoredPosition = Vector2.Lerp(scrollingPanel.anchoredPosition, newPositionUp, 1);
|
ScrollingPanel.anchoredPosition = Vector2.Lerp(ScrollingPanel.anchoredPosition, newPositionUp, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ScrollDown()
|
public void ScrollDown()
|
||||||
{
|
{
|
||||||
float deltaDown = elementSize.rect.height / 1.2f;
|
float deltaDown = elementSize.rect.height / 1.2f;
|
||||||
Vector2 newPositionDown = new Vector2(scrollingPanel.anchoredPosition.x, scrollingPanel.anchoredPosition.y + deltaDown);
|
Vector2 newPositionDown = new Vector2(ScrollingPanel.anchoredPosition.x, ScrollingPanel.anchoredPosition.y + deltaDown);
|
||||||
scrollingPanel.anchoredPosition = newPositionDown;
|
ScrollingPanel.anchoredPosition = newPositionDown;
|
||||||
}
|
|
||||||
|
|
||||||
[System.Serializable]
|
|
||||||
public class IntEvent:UnityEvent<int>
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -114,7 +114,13 @@ namespace UnityEngine.UI.Extensions
|
||||||
/// <param name="WorldPositionStays">Should the world position be updated to it's parent transform?</param>
|
/// <param name="WorldPositionStays">Should the world position be updated to it's parent transform?</param>
|
||||||
public void AddChild(GameObject GO, bool WorldPositionStays)
|
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);
|
GO.transform.SetParent(_screensContainer, WorldPositionStays);
|
||||||
InitialiseChildObjectsFromScene();
|
InitialiseChildObjectsFromScene();
|
||||||
DistributePages();
|
DistributePages();
|
||||||
|
@ -148,7 +154,12 @@ namespace UnityEngine.UI.Extensions
|
||||||
{
|
{
|
||||||
return;
|
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);
|
Transform child = _screensContainer.transform.GetChild(index);
|
||||||
child.SetParent(null, WorldPositionStays);
|
child.SetParent(null, WorldPositionStays);
|
||||||
|
|
|
@ -155,6 +155,12 @@ namespace UnityEngine.UI.Extensions
|
||||||
SetVerticesDirty();
|
SetVerticesDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetArc(float arc)
|
||||||
|
{
|
||||||
|
Arc = arc;
|
||||||
|
SetVerticesDirty();
|
||||||
|
}
|
||||||
|
|
||||||
public void SetArcSteps(int steps)
|
public void SetArcSteps(int steps)
|
||||||
{
|
{
|
||||||
ArcSteps = steps;
|
ArcSteps = steps;
|
||||||
|
|
|
@ -111,10 +111,18 @@ namespace UnityEngine.UI.Extensions
|
||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (m_points == value)
|
if (m_points == value) return;
|
||||||
return;
|
|
||||||
m_points = value;
|
if (value == null || value.Length == 0)
|
||||||
SetAllDirty();
|
{
|
||||||
|
m_points = new Vector2[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_points = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetAllDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
public void AddPoint(Vector2 pointToAdd)
|
||||||
{
|
{
|
||||||
m_points.Add(pointToAdd);
|
m_points.Add(pointToAdd);
|
||||||
|
@ -298,15 +280,6 @@ namespace UnityEngine.UI.Extensions
|
||||||
PopulateMesh (vh, m_points);
|
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)
|
private UIVertex[] CreateLineCap(Vector2 start, Vector2 end, SegmentType type)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue