Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions .github/workflows/main-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ jobs:
secrets: inherit

release-Complete:
if: ${{ always() }}
# Only succeed if no upstream release job actually failed. Skipped siblings
# (the build-types that didn't match the PR title) are tolerated; a real
# failure makes this job skip so it can no longer report a false "success".
if: ${{ !failure() && !cancelled() }}
needs: [upversion-major-Package, upversion-minor-Package, upversion-patch-Package, release-Package-only]
name: Release complete
runs-on: ubuntu-latest
Expand All @@ -67,19 +70,24 @@ jobs:

# Refresh the development branch with the main publish
refresh-development:
if: ${{ always() }}
# Skip if the release didn't actually complete, so we never refresh
# development from a half-finished or failed release.
if: ${{ needs.release-Complete.result == 'success' }}
needs: [release-Complete]
name: Refresh development branch
uses: ./.github/workflows/refreshbranch.yml
with:
build-host: ubuntu-latest
target-branch: development
source-branch: main
# The branch this release PR merged into (the trigger pins this to the
# release branch). Avoids hardcoding a branch name that doesn't exist.
source-branch: ${{ github.event.pull_request.base.ref }}
secrets: inherit

# Up version the development branch ready for future development
upversion-development:
if: ${{ always() }}
# Only re-version development once it has been refreshed successfully.
if: ${{ needs.refresh-development.result == 'success' }}
needs: [refresh-development]
name: UpVersion the development branch for the next release
uses: ./.github/workflows/upversionandtagrelease.yml
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/refreshbranch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,33 @@ jobs:
echo "Build Script Version: $scriptVersion"
echo "::endgroup::"
shell: pwsh
- name: Validate GIT_PAT
env:
GIT_PAT: ${{ secrets.GIT_PAT }}
shell: pwsh
run: |
if ([string]::IsNullOrWhiteSpace($env:GIT_PAT)) {
Write-Error "GIT_PAT secret is empty or not set. Add a valid Personal Access Token to the repository/org secrets and re-run."
exit 1
}
$headers = @{
Authorization = "Bearer $env:GIT_PAT"
"User-Agent" = "uiextensions-release-preflight"
Accept = "application/vnd.github+json"
}
try {
$repo = Invoke-RestMethod -Uri "https://api.github.com/repos/$env:GITHUB_REPOSITORY" -Headers $headers -ErrorAction Stop
}
catch {
$code = if ($_.Exception.Response) { [int]$_.Exception.Response.StatusCode } else { "unknown" }
Write-Error "GIT_PAT was rejected by GitHub (HTTP $code). It is likely expired, revoked, or lacks access to $env:GITHUB_REPOSITORY. Regenerate the token and update the GIT_PAT secret. Details: $($_.Exception.Message)"
exit 1
}
if ($null -ne $repo.permissions -and -not $repo.permissions.push) {
Write-Error "GIT_PAT authenticated but does not have push access to $env:GITHUB_REPOSITORY. Grant 'repo' (classic PAT) or Contents: read & write (fine-grained PAT)."
exit 1
}
Write-Host "GIT_PAT validated: authenticated with push access to $env:GITHUB_REPOSITORY."
- uses: actions/checkout@v7
with:
ref: ${{ inputs.target-branch }}
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/tagrelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,33 @@ jobs:
echo "Build Script Version: $scriptVersion"
echo "::endgroup::"
shell: pwsh
- name: Validate GIT_PAT
env:
GIT_PAT: ${{ secrets.GIT_PAT }}
shell: pwsh
run: |
if ([string]::IsNullOrWhiteSpace($env:GIT_PAT)) {
Write-Error "GIT_PAT secret is empty or not set. Add a valid Personal Access Token to the repository/org secrets and re-run."
exit 1
}
$headers = @{
Authorization = "Bearer $env:GIT_PAT"
"User-Agent" = "uiextensions-release-preflight"
Accept = "application/vnd.github+json"
}
try {
$repo = Invoke-RestMethod -Uri "https://api.github.com/repos/$env:GITHUB_REPOSITORY" -Headers $headers -ErrorAction Stop
}
catch {
$code = if ($_.Exception.Response) { [int]$_.Exception.Response.StatusCode } else { "unknown" }
Write-Error "GIT_PAT was rejected by GitHub (HTTP $code). It is likely expired, revoked, or lacks access to $env:GITHUB_REPOSITORY. Regenerate the token and update the GIT_PAT secret. Details: $($_.Exception.Message)"
exit 1
}
if ($null -ne $repo.permissions -and -not $repo.permissions.push) {
Write-Error "GIT_PAT authenticated but does not have push access to $env:GITHUB_REPOSITORY. Grant 'repo' (classic PAT) or Contents: read & write (fine-grained PAT)."
exit 1
}
Write-Host "GIT_PAT validated: authenticated with push access to $env:GITHUB_REPOSITORY."
- uses: actions/checkout@v7
with:
fetch-depth: 0
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/upversionandtagrelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,33 @@ jobs:
echo "Build Script Version: $scriptVersion"
echo "::endgroup::"
shell: pwsh
- name: Validate GIT_PAT
env:
GIT_PAT: ${{ secrets.GIT_PAT }}
shell: pwsh
run: |
if ([string]::IsNullOrWhiteSpace($env:GIT_PAT)) {
Write-Error "GIT_PAT secret is empty or not set. Add a valid Personal Access Token to the repository/org secrets and re-run."
exit 1
}
$headers = @{
Authorization = "Bearer $env:GIT_PAT"
"User-Agent" = "uiextensions-release-preflight"
Accept = "application/vnd.github+json"
}
try {
$repo = Invoke-RestMethod -Uri "https://api.github.com/repos/$env:GITHUB_REPOSITORY" -Headers $headers -ErrorAction Stop
}
catch {
$code = if ($_.Exception.Response) { [int]$_.Exception.Response.StatusCode } else { "unknown" }
Write-Error "GIT_PAT was rejected by GitHub (HTTP $code). It is likely expired, revoked, or lacks access to $env:GITHUB_REPOSITORY. Regenerate the token and update the GIT_PAT secret. Details: $($_.Exception.Message)"
exit 1
}
if ($null -ne $repo.permissions -and -not $repo.permissions.push) {
Write-Error "GIT_PAT authenticated but does not have push access to $env:GITHUB_REPOSITORY. Grant 'repo' (classic PAT) or Contents: read & write (fine-grained PAT)."
exit 1
}
Write-Host "GIT_PAT validated: authenticated with push access to $env:GITHUB_REPOSITORY."
- uses: actions/checkout@v7
with:
ref: ${{ inputs.target-branch }}
Expand Down
43 changes: 43 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,49 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/).

## Release 3.0.0 - Unity 6, reimagined - 2026/06

The V3 relaunch brings **full Unity 6 support**, a refreshed brand, and the start of a two-package ecosystem — the proven uGUI library you know, now joined by a modern UI Toolkit companion.

> **Two packages. One ecosystem.** These notes cover the **uGUI** package (`com.unity.uiextensions`). Meet its new companion: [UI Toolkit Extensions](https://github.com/Unity-UI-Extensions/com.unity.uitoolkitextensions).

### Highlights

- **Full Unity 6 support** — the whole library verified and updated for Unity 6, with legacy dependencies cleared out and the examples refreshed.
- **Two-package ecosystem** — the new UI Toolkit Extensions package launches alongside under the shared 3.0 banner.

### Added

- New control: **GridRawImage**
- New control: **UI Knob 2** (`UI_Knob2`)
- New control: **UI Segmented Circle** / Segmented Control
- New control: **UI Graphic Selector**
- UILineConnector: the pivot can now be used as the reference point when drawing lines (#490)
- UILineConnector: new "close line" option to finish a line off and fill any gaps at the end
- BoxSlider: added `SetXWithoutNotify` and `SetYWithoutNotify`

### Changed / Fixed

- Reorderable List: fixed a null-reference exception, and resolved element-stacking when moving elements slightly
- Scroll Snap: resolved a race condition that could raise a NaN error when lerping; made rescaling and full-screen scroll snap more resilient
- HSS/VSS: guarded against a divide-by-zero when the scroll snap has a single page; `GetCurrentPage` made more resilient
- Infinite Scroll: resolved out-of-bounds issues
- Flow Layout Group: addressed layout issues and fixed the last line overflowing the rect bounds
- UI Particle System: new "CullingMode" option to resolve unscaled delta time (#486 / #487)
- Gradient2: optimised `ModifyMesh`; fixed radial triangle add order (#384)
- ScrollRect: force `ScrollRect.content` setup (#485)
- UILineConnector: improved point-array calculation (#495); refresh on global scale change
- Layout groups now rebuild on disable/enable
- General TMPro/Text compatibility housekeeping (#477)
- Compile-flag support for Unity 6 (#493)

### Contributors

Huge thanks to everyone who contributed to this release:
[@SimonDarksideJ](https://github.com/SimonDarksideJ), [@bluefallsky](https://github.com/bluefallsky), [@hugoymh](https://github.com/hugoymh), [@JavierMonton](https://github.com/JavierMonton), [@Dover8](https://github.com/Dover8), [@fgrg2801](https://github.com/fgrg2801), [@Moderbord](https://github.com/Moderbord).

-----

## Release 2.3.2 - Rejuvenation - 2023/11/26

2023 is certainly an interesting year to keep you on your toes, and finding time to keep managing all the requests and updates that come in are taking their toll, especially for a FREE project, but nonetheless, I still do it.
Expand Down
19 changes: 19 additions & 0 deletions Documentation~/Examples/Accordion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Example: Accordion

## Overview

This scene demonstrates the Accordion control: a vertical stack of expandable/collapsible sections where opening one section animates its content into view. Use it when you need a compact panel of grouped content (settings categories, FAQs, inspector-style sections) that the user can reveal one piece at a time.

## Controls Featured

- [Accordion](/ugui/controls/accordion/) — the scene wires an Accordion Group around several Accordion Elements, each with a header and animated content body.

## Scene Setup

1. Add the **UI Extensions Samples** sample to your project (open the package in the Unity Package Manager and import **UI Extensions Samples**), or copy `Examples~/Accordion/` into your project's `Assets/` folder.
2. Open the example scene in that folder (`Accordion.unity`).
3. Press **Play**.

## What to Expect

At runtime you see a list of Accordion Elements, each showing a header. Clicking a header expands that element to reveal its content, animating open with the group's configured transition (instant or a tween over the transition duration). By default opening one element collapses the previously open one; with **Allow Multiple** enabled, several can stay open at once, and **Toggle On** lets you click an open header to close it again. The **On Value Changed** event fires whenever the active element changes.
27 changes: 27 additions & 0 deletions Documentation~/Examples/CardUI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Example: Card UI

## Overview

This example ships a collection of scenes showing the different Card UI presentation styles in one place: 2D expanding cards, a 2D popup with falling cards, a 2D card stack, 3D expanding cards, and a superellipse playground. Use it when you want a card-based interface for content presentation, hands of cards, or stacked/expandable panels.

## Controls Featured

- [Card UI](/ugui/controls/card-ui/) — each scene exercises a different card behaviour (expand, popup/fall, stack depth, 3D rounded panels) from the Card UI suite.

## Scene Setup

1. Add the **UI Extensions Samples** sample to your project (open the package in the Unity Package Manager and import **UI Extensions Samples**), or copy `Examples~/CardUI/` into your project's `Assets/` folder.
2. Open one of the example scenes in that folder: `2D Card Expanding.unity`, `2D Card Popup.unity`, `2D Card Stack.unity`, `3D Card Expanding.unity`, or `Superellipse Playground.unity`.
3. Press **Play**.

## What to Expect

What you see depends on the scene you open:

- **2D Card Expanding** — clickable cards that expand from a compact layout to a larger view and collapse again.
- **2D Card Popup** — physics-driven cards that pop up and fall into place.
- **2D Card Stack** — cards arranged in a depth-ordered stack, offset so each sits over the one behind it.
- **3D Card Expanding** — custom panel meshes with rounded (superellipse) corners for a 3D card effect.
- **Superellipse Playground** — a sandbox for tuning the rounded-corner superellipse shapes used by the 3D cards.

Expand/popup/stack animations run over the configured animation duration, and selecting or closing a card fires the relevant card event where exposed.
19 changes: 19 additions & 0 deletions Documentation~/Examples/ColorPicker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Example: Color Picker

## Overview

This scene demonstrates the Color Picker control built from the `Picker 2.0` prefab, combining a box slider, HSV/RGB sliders, hex input, alpha, an on-screen colour sampler, and saveable presets. Use it whenever your project needs runtime colour selection, for example in an editor tool, character customiser, or paint feature.

## Controls Featured

- [Color Picker](/ugui/controls/color-picker/) — the `PickerTest` scene drops the `Picker 2.0` prefab into a canvas, exposing the combined HSV/RGB sliders, hex field, colour sampler, and preset swatches.

## Scene Setup

1. Add the **UI Extensions Samples** sample to your project (open the package in the Unity Package Manager and import **UI Extensions Samples**), or copy `Examples~/ColorPicker/` into your project's `Assets/` folder.
2. Open the example scene in that folder (`PickerTest.unity`).
3. Press **Play**.

## What to Expect

At runtime you can drag the box slider and the HSV/RGB/alpha sliders, or type a hex code, to change the current colour; the picker raises its **On Value Changed** event each time the colour changes. The colour sampler lets you click anywhere on screen to pick that pixel's colour into the picker. Presets let you save the current colour as a swatch and reload it later; depending on the presets **Save Mode** (None, JSON, or PlayerPrefs) user-defined swatches persist between sessions, alongside any predefined preset colours. The picker and its presets/sampler are configured entirely in the prefab, so no scripting is required to try it.
48 changes: 48 additions & 0 deletions Documentation~/Examples/ComboBox.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Example: ComboBox & Dropdowns

## Overview

This scene places the three Unity UI Extensions selection controls side by side so you can compare them: the plain ComboBox, the AutoComplete ComboBox, and the DropDown List. It ships demo scripts that populate the controls, refresh their options at runtime, add items from an input field, and log every change event. Use it to decide which selection control best fits your UI and to see the correct way to manage their contents from code.

## Controls Featured

- [ComboBox](/ugui/controls/combobox/) — a fixed text combobox; the demo adds items to it and logs its selection-changed event.
- [AutoComplete ComboBox](/ugui/controls/autocomplete-combobox/) — a text field with live filtering against a vocabulary; the demo logs its text, validity, selection, and item-selected events.
- [DropDown List](/ugui/controls/dropdown-list/) — a richer dropdown supporting text and images; the demo refreshes its items and logs its changed event.

## Scene Setup

1. Add the **UI Extensions Samples** sample to your project (open the package in the Unity Package Manager and import **UI Extensions Samples**), or copy `Examples~/ComboBox/` into your project's `Assets/` folder.
2. Open the example scene in that folder (`ComboBox.unity`).
3. Press **Play**.

## What to Expect

At runtime each of the three controls is pre-populated with a shared set of options (`More`, `ComboBox`, `Example`, `Goodness`). Open the ComboBox or DropDown List to pick from the list, or type into the AutoComplete ComboBox to filter matches as you go. An input field plus buttons let you add new entries into each control live. Every interaction is written to the Console: the ComboBox and DropDown log their selection changes, while the AutoComplete logs separate events for text changes, validity changes, selection changes, and item selection. This makes it a useful reference for wiring up the controls' events and for the recommended `SetAvailableOptions` / `RefreshItems` / `AddItem` APIs rather than editing the options list directly.

## Key Code Patterns

Populate (and reset) each control's options at startup — note `RefreshItems` for the DropDown List versus `SetAvailableOptions` for the others:

```csharp
private string[] dropDownItems = { "More", "ComboBox", "Example", "Goodness" };

void Start()
{
acb.SetAvailableOptions(dropDownItems); // AutoCompleteComboBox
cb.SetAvailableOptions(dropDownItems); // ComboBox
ddl.RefreshItems(dropDownItems); // DropDownList
}
```

Add a single item from an input field at runtime:

```csharp
public void AddComboBox()
{
if (!string.IsNullOrWhiteSpace(input.text))
{
comboBox.AddItem(input.text);
}
}
```
46 changes: 46 additions & 0 deletions Documentation~/Examples/Cooldown.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Example: Cooldown Button

## Overview

This scene demonstrates the Cooldown Button control, which makes a Selectable (Button, Toggle, etc.) unusable for a set time after it is clicked. It also shows how to drive visual feedback from the button's cooldown progress by pairing it with a Unity Image fill and with the SoftMask effect. Use it for ability/power-up buttons, rate-limited actions, or any UI where an action needs a recovery delay.

## Controls Featured

- [Cooldown Button](/ugui/controls/cooldown-button/) — the scene attaches a CooldownButton and reads its timing properties (`CooldownTimeRemaining`, `CooldownTimeElapsed`, `CooldownTimeout`, `CooldownPercentComplete`) each frame to animate the cooldown effect.

## Scene Setup

1. Add the **UI Extensions Samples** sample to your project (open the package in the Unity Package Manager and import **UI Extensions Samples**), or copy `Examples~/Cooldown/` into your project's `Assets/` folder.
2. Open the example scene in that folder (`CooldownExamples.unity`).
3. Press **Play**.

## What to Expect

Clicking a cooldown button starts its timer and triggers the **On Cooldown Start** event. While the timer runs, the linked visuals update every frame: one example sweeps a Unity Image's radial fill from empty to full, optionally showing the cooldown percentage as text, while another drives the `CutOff` of a SoftMask to reveal/wipe the graphic over the cooldown. Clicking the button again before it finishes fires **On Button Click During Cooldown** so you can give "still cooling down" feedback, and **On Cooldown Finish** fires once the timeout elapses and the button is ready again.

## Key Code Patterns

Driving a Unity Image's radial fill from the button's remaining time:

```csharp
public CooldownButton coolDown;
private Image target;

void Update()
{
target.fillAmount = Mathf.Lerp(0, 1, coolDown.CooldownTimeRemaining / coolDown.CooldownTimeout);
if (displayText)
{
displayText.text = string.Format("{0}%", coolDown.CooldownPercentComplete);
}
}
```

Driving the SoftMask cutoff from elapsed time:

```csharp
void Update()
{
sauim.CutOff = Mathf.Lerp(0, 1, cooldown.CooldownTimeElapsed / cooldown.CooldownTimeout);
}
```
Loading
Loading