diff --git a/.github/workflows/development-buildandtestupmrelease.yml b/.github/workflows/development-buildandtestupmrelease.yml
index 6eafe78..570fcd5 100644
--- a/.github/workflows/development-buildandtestupmrelease.yml
+++ b/.github/workflows/development-buildandtestupmrelease.yml
@@ -33,8 +33,8 @@ jobs:
- '6000.6'
- '6000.7'
include:
- - os: ubuntu-latest
- build-targets: StandaloneLinux64, Android
+ # - os: ubuntu-latest
+ # build-targets: StandaloneLinux64, Android
- os: windows-latest
build-targets: StandaloneWindows64, Android
- os: macos-latest
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6ae6374..4761cdc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/).
+## [Unreleased]
+
+### Added
+
+- **Editor menu integration** — a new `GameObject/UI Toolkit/Extensions` menu adds any of the 22 UXML-placeable controls to the scene in basic form with demo content, automatically creating a `UIDocument` and `PanelSettings` (with the default runtime theme) if the scene has none. The UI Toolkit counterpart of the uGUI Extensions `GameObject/UI/Extensions` menu.
+- **Starter templates** — per-control starter UXML templates with demo content, also available from `Assets/Create/UI Toolkit/Extensions` for dropping into existing documents. Instantiated copies are placed under `Assets/UI Toolkit Extensions` so they remain freely editable.
+- **Self-applying control styles** — while authoring (UI Builder) and in Play Mode, controls attach the shared extensions stylesheet automatically on construction, so they render correctly without manually referencing the stylesheet. Overlay controls (`DropDownControl`, `DropDownMenuControl`, `ImageCropOverlayControl`) also style their root-attached panels directly. In player builds, styling comes from the explicit stylesheet references in the starter templates and from the theme generated by the editor menu (which imports the shared stylesheet panel-wide).
+- **`ElasticListView` UXML-authored items** — child elements declared inside an `ElasticListView` tag (or added via plain `Add()`) now become list items, via a `contentContainer` override routing them into the item content. Items were previously only addable from code with `AddItem()`/`SetItems()`.
+
+### Changed
+
+- Package dependency corrected from the deprecated `com.unity.ui` preview package to the built-in `com.unity.modules.uielements` module.
+- Removed leftover uGUI assembly references from the Runtime and Editor assembly definitions, and the placeholder `DumbScript` from the Editor assembly.
+
## Release 1.0.0 - Launch - 2026/06
The first release of **Unity UI Toolkit Extensions** — a brand-new companion to the long-running uGUI Extensions library, built from the ground up for Unity 6 and the UI Toolkit (UITK) system.
diff --git a/Editor/ControlTemplates.meta b/Editor/ControlTemplates.meta
new file mode 100644
index 0000000..69be819
--- /dev/null
+++ b/Editor/ControlTemplates.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d2af0b38f3e541e6a4d002fef9372a8b
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
\ No newline at end of file
diff --git a/Editor/ControlTemplates/CircularImageButtonStarter.uxml b/Editor/ControlTemplates/CircularImageButtonStarter.uxml
new file mode 100644
index 0000000..05da6cd
--- /dev/null
+++ b/Editor/ControlTemplates/CircularImageButtonStarter.uxml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/CircularImageButtonStarter.uxml.meta b/Editor/ControlTemplates/CircularImageButtonStarter.uxml.meta
new file mode 100644
index 0000000..379558c
--- /dev/null
+++ b/Editor/ControlTemplates/CircularImageButtonStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 69bf9d43785a41e6899e32e3a71ac80c
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/CollapsibleSectionStarter.uxml b/Editor/ControlTemplates/CollapsibleSectionStarter.uxml
new file mode 100644
index 0000000..0b8bee1
--- /dev/null
+++ b/Editor/ControlTemplates/CollapsibleSectionStarter.uxml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/CollapsibleSectionStarter.uxml.meta b/Editor/ControlTemplates/CollapsibleSectionStarter.uxml.meta
new file mode 100644
index 0000000..5292ebb
--- /dev/null
+++ b/Editor/ControlTemplates/CollapsibleSectionStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 3ab13d1bcdf74bc1b06f11f554b5aabb
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/ColorToggleButtonStarter.uxml b/Editor/ControlTemplates/ColorToggleButtonStarter.uxml
new file mode 100644
index 0000000..6c23cd5
--- /dev/null
+++ b/Editor/ControlTemplates/ColorToggleButtonStarter.uxml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/ColorToggleButtonStarter.uxml.meta b/Editor/ControlTemplates/ColorToggleButtonStarter.uxml.meta
new file mode 100644
index 0000000..b8c78f7
--- /dev/null
+++ b/Editor/ControlTemplates/ColorToggleButtonStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: ba737b1ead6f451f9774421791e62cbc
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/ColorToggleGroupStarter.uxml b/Editor/ControlTemplates/ColorToggleGroupStarter.uxml
new file mode 100644
index 0000000..029acfe
--- /dev/null
+++ b/Editor/ControlTemplates/ColorToggleGroupStarter.uxml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/ColorToggleGroupStarter.uxml.meta b/Editor/ControlTemplates/ColorToggleGroupStarter.uxml.meta
new file mode 100644
index 0000000..70a2f51
--- /dev/null
+++ b/Editor/ControlTemplates/ColorToggleGroupStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 82a17b32ce0043bd9886674577781f57
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/ComingSoonMessageStarter.uxml b/Editor/ControlTemplates/ComingSoonMessageStarter.uxml
new file mode 100644
index 0000000..cd1bdc1
--- /dev/null
+++ b/Editor/ControlTemplates/ComingSoonMessageStarter.uxml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/ComingSoonMessageStarter.uxml.meta b/Editor/ControlTemplates/ComingSoonMessageStarter.uxml.meta
new file mode 100644
index 0000000..f3446c0
--- /dev/null
+++ b/Editor/ControlTemplates/ComingSoonMessageStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 4e135d3355ef49ceb92d8fedbb69d33f
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/DropDownControlStarter.uxml b/Editor/ControlTemplates/DropDownControlStarter.uxml
new file mode 100644
index 0000000..c1fcd4a
--- /dev/null
+++ b/Editor/ControlTemplates/DropDownControlStarter.uxml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/DropDownControlStarter.uxml.meta b/Editor/ControlTemplates/DropDownControlStarter.uxml.meta
new file mode 100644
index 0000000..9c5008d
--- /dev/null
+++ b/Editor/ControlTemplates/DropDownControlStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 2b0448453bb04bcbba6b6a936eef9935
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/DropDownMenuStarter.uxml b/Editor/ControlTemplates/DropDownMenuStarter.uxml
new file mode 100644
index 0000000..5be0a51
--- /dev/null
+++ b/Editor/ControlTemplates/DropDownMenuStarter.uxml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/DropDownMenuStarter.uxml.meta b/Editor/ControlTemplates/DropDownMenuStarter.uxml.meta
new file mode 100644
index 0000000..c997ee0
--- /dev/null
+++ b/Editor/ControlTemplates/DropDownMenuStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 5c8d2f7a9e1b4c60b3a6d9e2c5f8b140
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
diff --git a/Editor/ControlTemplates/ElasticListViewStarter.uxml b/Editor/ControlTemplates/ElasticListViewStarter.uxml
new file mode 100644
index 0000000..fa95b6f
--- /dev/null
+++ b/Editor/ControlTemplates/ElasticListViewStarter.uxml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/ElasticListViewStarter.uxml.meta b/Editor/ControlTemplates/ElasticListViewStarter.uxml.meta
new file mode 100644
index 0000000..7c604db
--- /dev/null
+++ b/Editor/ControlTemplates/ElasticListViewStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 597d91ba7f9c4742adb022919adc87ea
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/GrayscaleImageStarter.uxml b/Editor/ControlTemplates/GrayscaleImageStarter.uxml
new file mode 100644
index 0000000..b74996e
--- /dev/null
+++ b/Editor/ControlTemplates/GrayscaleImageStarter.uxml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/GrayscaleImageStarter.uxml.meta b/Editor/ControlTemplates/GrayscaleImageStarter.uxml.meta
new file mode 100644
index 0000000..315dae2
--- /dev/null
+++ b/Editor/ControlTemplates/GrayscaleImageStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: fb96a2cbd60941388dbc7e4b362051f8
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/IconLabelButtonStarter.uxml b/Editor/ControlTemplates/IconLabelButtonStarter.uxml
new file mode 100644
index 0000000..4d38b2f
--- /dev/null
+++ b/Editor/ControlTemplates/IconLabelButtonStarter.uxml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/IconLabelButtonStarter.uxml.meta b/Editor/ControlTemplates/IconLabelButtonStarter.uxml.meta
new file mode 100644
index 0000000..6beb2b9
--- /dev/null
+++ b/Editor/ControlTemplates/IconLabelButtonStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 1b3184d2d1f04fafa88ae973d199ec7e
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/LoadingIconStarter.uxml b/Editor/ControlTemplates/LoadingIconStarter.uxml
new file mode 100644
index 0000000..154c12f
--- /dev/null
+++ b/Editor/ControlTemplates/LoadingIconStarter.uxml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/LoadingIconStarter.uxml.meta b/Editor/ControlTemplates/LoadingIconStarter.uxml.meta
new file mode 100644
index 0000000..b71cb8b
--- /dev/null
+++ b/Editor/ControlTemplates/LoadingIconStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 6c75c5d0dd20406cae631abf62569c75
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/NotificationBadgeStarter.uxml b/Editor/ControlTemplates/NotificationBadgeStarter.uxml
new file mode 100644
index 0000000..eb50773
--- /dev/null
+++ b/Editor/ControlTemplates/NotificationBadgeStarter.uxml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/NotificationBadgeStarter.uxml.meta b/Editor/ControlTemplates/NotificationBadgeStarter.uxml.meta
new file mode 100644
index 0000000..069bb10
--- /dev/null
+++ b/Editor/ControlTemplates/NotificationBadgeStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: dd32eb2ecc0b4fb2bb2c9bac5fb17323
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/PageDotIndicatorStarter.uxml b/Editor/ControlTemplates/PageDotIndicatorStarter.uxml
new file mode 100644
index 0000000..1d2225e
--- /dev/null
+++ b/Editor/ControlTemplates/PageDotIndicatorStarter.uxml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/PageDotIndicatorStarter.uxml.meta b/Editor/ControlTemplates/PageDotIndicatorStarter.uxml.meta
new file mode 100644
index 0000000..c83bd3a
--- /dev/null
+++ b/Editor/ControlTemplates/PageDotIndicatorStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 22c1b9cbe17545398f868fdd874e0d1e
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/PillButtonStarter.uxml b/Editor/ControlTemplates/PillButtonStarter.uxml
new file mode 100644
index 0000000..7983518
--- /dev/null
+++ b/Editor/ControlTemplates/PillButtonStarter.uxml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/PillButtonStarter.uxml.meta b/Editor/ControlTemplates/PillButtonStarter.uxml.meta
new file mode 100644
index 0000000..16a4cc0
--- /dev/null
+++ b/Editor/ControlTemplates/PillButtonStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 751295301b3145ab9126aecf743a6c81
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/PillInputFieldStarter.uxml b/Editor/ControlTemplates/PillInputFieldStarter.uxml
new file mode 100644
index 0000000..a118f2e
--- /dev/null
+++ b/Editor/ControlTemplates/PillInputFieldStarter.uxml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/PillInputFieldStarter.uxml.meta b/Editor/ControlTemplates/PillInputFieldStarter.uxml.meta
new file mode 100644
index 0000000..bb6edc1
--- /dev/null
+++ b/Editor/ControlTemplates/PillInputFieldStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: f84bc1aaa87c4d76891c2e04fb5855ff
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/PillSelectorStarter.uxml b/Editor/ControlTemplates/PillSelectorStarter.uxml
new file mode 100644
index 0000000..6f21867
--- /dev/null
+++ b/Editor/ControlTemplates/PillSelectorStarter.uxml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/PillSelectorStarter.uxml.meta b/Editor/ControlTemplates/PillSelectorStarter.uxml.meta
new file mode 100644
index 0000000..7686429
--- /dev/null
+++ b/Editor/ControlTemplates/PillSelectorStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: ae1b268989a547ebbef0f6de150eaffb
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/QuadrantStepperStarter.uxml b/Editor/ControlTemplates/QuadrantStepperStarter.uxml
new file mode 100644
index 0000000..911584a
--- /dev/null
+++ b/Editor/ControlTemplates/QuadrantStepperStarter.uxml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/QuadrantStepperStarter.uxml.meta b/Editor/ControlTemplates/QuadrantStepperStarter.uxml.meta
new file mode 100644
index 0000000..3624c63
--- /dev/null
+++ b/Editor/ControlTemplates/QuadrantStepperStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 656731e9c84e4a02bc0f467c5fd02afc
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/RoundedInputFieldStarter.uxml b/Editor/ControlTemplates/RoundedInputFieldStarter.uxml
new file mode 100644
index 0000000..ee63101
--- /dev/null
+++ b/Editor/ControlTemplates/RoundedInputFieldStarter.uxml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/RoundedInputFieldStarter.uxml.meta b/Editor/ControlTemplates/RoundedInputFieldStarter.uxml.meta
new file mode 100644
index 0000000..ccd9182
--- /dev/null
+++ b/Editor/ControlTemplates/RoundedInputFieldStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: e19350a1489747009f9283d2d51c3cd1
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/ScreenHeaderStarter.uxml b/Editor/ControlTemplates/ScreenHeaderStarter.uxml
new file mode 100644
index 0000000..04e2cbd
--- /dev/null
+++ b/Editor/ControlTemplates/ScreenHeaderStarter.uxml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/ScreenHeaderStarter.uxml.meta b/Editor/ControlTemplates/ScreenHeaderStarter.uxml.meta
new file mode 100644
index 0000000..0ab0569
--- /dev/null
+++ b/Editor/ControlTemplates/ScreenHeaderStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 6515564757d24df6b8c216f49faa11f8
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/ScrollSnapStarter.uxml b/Editor/ControlTemplates/ScrollSnapStarter.uxml
new file mode 100644
index 0000000..ce17521
--- /dev/null
+++ b/Editor/ControlTemplates/ScrollSnapStarter.uxml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/ScrollSnapStarter.uxml.meta b/Editor/ControlTemplates/ScrollSnapStarter.uxml.meta
new file mode 100644
index 0000000..20fec5a
--- /dev/null
+++ b/Editor/ControlTemplates/ScrollSnapStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: bfa76ba706aa4231a557595162a6e9bd
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/SocialLinkContainerStarter.uxml b/Editor/ControlTemplates/SocialLinkContainerStarter.uxml
new file mode 100644
index 0000000..a4a2a4e
--- /dev/null
+++ b/Editor/ControlTemplates/SocialLinkContainerStarter.uxml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/SocialLinkContainerStarter.uxml.meta b/Editor/ControlTemplates/SocialLinkContainerStarter.uxml.meta
new file mode 100644
index 0000000..686fdc2
--- /dev/null
+++ b/Editor/ControlTemplates/SocialLinkContainerStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: bbd08e19eefb4b699e76b28a10792aa1
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/StarterTemplateStyles.uss b/Editor/ControlTemplates/StarterTemplateStyles.uss
new file mode 100644
index 0000000..c9fed14
--- /dev/null
+++ b/Editor/ControlTemplates/StarterTemplateStyles.uss
@@ -0,0 +1,159 @@
+/* Starter-template icon overrides.
+ The starter scenes render on Unity's light default runtime theme, where the controls'
+ light icon tints (designed for the dark example cards) are invisible. These selectors
+ use two classes so they take precedence over the single-class rules in the shared
+ control stylesheet. Remove this reference from your copy if you restyle on a dark UI. */
+
+.iconLabelButton .iconLabelButton__icon,
+.collapsibleSection .collapsibleSection__chevron,
+.loadingIcon .loadingIcon__image,
+.pillSelector .pillSelector__icon,
+.circularImageButton .circularImageButton__icon,
+.dropDownControl .dropDownControl__triggerIcon {
+ -unity-background-image-tint-color: rgba(0, 0, 0, 1);
+}
+
+/* ToggleButton starter: the base control renders nothing until an image is assigned,
+ so the starter carries a demo look — a circular button with a volume icon and a
+ green selected state. Replace with your own image/styling in real use. */
+.toggleButtonStarter.toggleButton {
+ border-radius: 32px;
+ background-color: rgba(0, 0, 0, 0.08);
+ border-width: 2px;
+ border-color: rgba(0, 0, 0, 0.25);
+}
+
+.toggleButtonStarter .toggleButton__image {
+ width: 60%;
+ height: 60%;
+ background-image: url("../../Runtime/Assets/Icons/Volume-on.svg");
+ -unity-background-image-tint-color: rgba(0, 0, 0, 0.55);
+}
+
+.toggleButtonStarter.toggleButton--selected {
+ background-color: rgba(46, 204, 113, 1);
+ border-color: rgba(39, 174, 96, 1);
+}
+
+.toggleButtonStarter.toggleButton--selected .toggleButton__image {
+ background-image: url("../../Runtime/Assets/Icons/Volume-off.svg");
+ -unity-background-image-tint-color: rgba(255, 255, 255, 1);
+}
+
+/* ScreenHeader starter: dark header surface with icons assigned to the enabled actions
+ (back chevron, info button, volume on/off toggle), mirroring the ScreenHeader sample.
+ Also repositions the sound toggle to the right edge — the control's default placement
+ (left: 32px) overlaps the back button. */
+.screenHeaderStarter.screenHeader {
+ background-color: rgba(20, 28, 44, 0.94);
+ border-bottom-width: 1px;
+ border-bottom-color: rgba(255, 255, 255, 0.08);
+}
+
+.screenHeaderStarter .screenHeader__title {
+ color: rgba(255, 255, 255, 1);
+}
+
+.screenHeaderStarter .screenHeader__action1Button .toggleButton__image {
+ background-image: url("../../Runtime/Assets/Icons/ChevronLeft.svg");
+ -unity-background-image-tint-color: rgba(236, 240, 252, 1);
+}
+
+.screenHeaderStarter .screenHeader__action3Button.toggleButton {
+ right: 92px;
+}
+
+.screenHeaderStarter .screenHeader__action3Button .toggleButton__image {
+ background-image: url("../../Runtime/Assets/Icons/Information-icon.svg");
+ -unity-background-image-tint-color: rgba(236, 240, 252, 1);
+}
+
+.screenHeaderStarter .screenHeader__action4Toggle.toggleButton {
+ left: auto;
+ right: 16px;
+}
+
+/* Unselected = sound on */
+.screenHeaderStarter .screenHeader__action4Toggle .toggleButton__image {
+ background-image: url("../../Runtime/Assets/Icons/Volume-on.svg");
+ -unity-background-image-tint-color: rgba(124, 230, 200, 1);
+}
+
+/* Selected = muted */
+.screenHeaderStarter .screenHeader__action4Toggle.toggleButton--selected .toggleButton__image {
+ background-image: url("../../Runtime/Assets/Icons/Volume-off.svg");
+ -unity-background-image-tint-color: rgba(255, 138, 138, 1);
+}
+
+/* DropDownMenu starter: DropDownMenuControl is code-only, so the starter ships a single
+ bordered item row (white card look for the light default runtime theme) whose "···"
+ trigger is wired by DropDownMenuStarterController, added by the GameObject menu entry. */
+.dropDownMenuStarter__row {
+ width: 80%;
+ max-width: 420px;
+ height: 72px;
+ flex-direction: row;
+ align-items: center;
+ padding-left: 20px;
+ padding-right: 12px;
+ background-color: rgba(255, 255, 255, 1);
+ border-width: 1px;
+ border-color: rgba(0, 0, 0, 0.15);
+ border-radius: 22px;
+}
+
+.dropDownMenuStarter__label {
+ flex-grow: 1;
+ font-size: 17px;
+ color: rgba(20, 24, 32, 1);
+ -unity-text-align: middle-left;
+}
+
+.dropDownMenuStarter__trigger {
+ width: 44px;
+ height: 44px;
+ flex-shrink: 0;
+ border-radius: 22px;
+ background-color: rgba(0, 0, 0, 0.06);
+ color: rgba(20, 24, 32, 0.8);
+ font-size: 22px;
+ -unity-font-style: bold;
+ -unity-text-align: middle-center;
+}
+
+.dropDownMenuStarter__trigger:hover {
+ background-color: rgba(0, 0, 0, 0.12);
+}
+
+/* ComingSoonMessage starter: white bordered card around the message panel so it
+ reads as a distinct surface instead of floating text. */
+.comingSoonMessageStarter .comingSoonMessage__background {
+ background-color: rgba(255, 255, 255, 1);
+ border-width: 1px;
+ border-color: rgba(0, 0, 0, 0.15);
+ border-radius: 12px;
+ padding: 28px 40px;
+ color: rgba(20, 24, 32, 1);
+}
+
+/* ElasticListView starter: simple demo rows so the list has content to scroll. */
+.elasticListViewStarter.elasticListView {
+ background-color: rgba(0, 0, 0, 0.05);
+ border-radius: 12px;
+ border-width: 1px;
+ border-color: rgba(0, 0, 0, 0.15);
+ padding: 6px;
+}
+
+.elasticListViewStarter .elasticListViewStarter__item {
+ height: 34px;
+ flex-shrink: 0;
+ margin: 3px 4px;
+ padding-left: 12px;
+ border-radius: 8px;
+ background-color: rgba(255, 255, 255, 0.85);
+ border-width: 1px;
+ border-color: rgba(0, 0, 0, 0.12);
+ color: rgba(20, 24, 32, 1);
+ -unity-text-align: middle-left;
+}
diff --git a/Editor/ControlTemplates/StarterTemplateStyles.uss.meta b/Editor/ControlTemplates/StarterTemplateStyles.uss.meta
new file mode 100644
index 0000000..0a4de92
--- /dev/null
+++ b/Editor/ControlTemplates/StarterTemplateStyles.uss.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: d4c51049405542c8821b93be5b28b1cf
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/StepProgressBarStarter.uxml b/Editor/ControlTemplates/StepProgressBarStarter.uxml
new file mode 100644
index 0000000..7a8d873
--- /dev/null
+++ b/Editor/ControlTemplates/StepProgressBarStarter.uxml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/StepProgressBarStarter.uxml.meta b/Editor/ControlTemplates/StepProgressBarStarter.uxml.meta
new file mode 100644
index 0000000..aca7bf3
--- /dev/null
+++ b/Editor/ControlTemplates/StepProgressBarStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 53e4411aedc141c2ba3cdfa012ef51a4
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/ControlTemplates/ToggleButtonStarter.uxml b/Editor/ControlTemplates/ToggleButtonStarter.uxml
new file mode 100644
index 0000000..3b28392
--- /dev/null
+++ b/Editor/ControlTemplates/ToggleButtonStarter.uxml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Editor/ControlTemplates/ToggleButtonStarter.uxml.meta b/Editor/ControlTemplates/ToggleButtonStarter.uxml.meta
new file mode 100644
index 0000000..a7c45da
--- /dev/null
+++ b/Editor/ControlTemplates/ToggleButtonStarter.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: ff5936ff747944dc8ac8edee83ade393
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
\ No newline at end of file
diff --git a/Editor/DumbScript.cs b/Editor/DumbScript.cs
deleted file mode 100644
index b0c3297..0000000
--- a/Editor/DumbScript.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using UnityEngine;
-
-public class DumbScript : MonoBehaviour
-{
- // Start is called once before the first execution of Update after the MonoBehaviour is created
- void Start()
- {
-
- }
-
- // Update is called once per frame
- void Update()
- {
-
- }
-}
diff --git a/Editor/DumbScript.cs.meta b/Editor/DumbScript.cs.meta
deleted file mode 100644
index 4e7288b..0000000
--- a/Editor/DumbScript.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: 8182807fddc513041bab86e60a48f7a0
\ No newline at end of file
diff --git a/Editor/UIToolkitExtensionsMenuOptions.cs b/Editor/UIToolkitExtensionsMenuOptions.cs
new file mode 100644
index 0000000..7323596
--- /dev/null
+++ b/Editor/UIToolkitExtensionsMenuOptions.cs
@@ -0,0 +1,327 @@
+// Credit SimonDarksideJ
+
+using UnityEditor;
+using UnityEngine;
+using UnityEngine.UIElements;
+
+namespace UnityUIToolkit.Extensions.Editor
+{
+ ///
+ /// Adds the UI Toolkit Extensions menu options to the Unity Editor, the UI Toolkit
+ /// counterpart of the uGUI Extensions "GameObject/UI/Extensions" menu.
+ ///
+ ///
+ /// Each "GameObject/UI Toolkit/Extensions" entry bootstraps the scene for UI Toolkit
+ /// (creating a UIDocument and PanelSettings where needed) and instantiates a starter
+ /// UXML template containing a basic, demo-content version of the chosen control that
+ /// the user can open and tweak in UI Builder.
+ /// The "Assets/Create/UI Toolkit/Extensions" entries copy just the starter UXML into
+ /// the active project folder for use in existing documents.
+ ///
+ internal static class UIToolkitExtensionsMenuOptions
+ {
+ private const string TemplateRoot = "Packages/com.unity.uitoolkitextensions/Editor/ControlTemplates/";
+ private const string GeneratedAssetFolder = "Assets/UI Toolkit Extensions";
+ private const string PanelSettingsAssetPath = GeneratedAssetFolder + "/UIToolkitExtensionsPanelSettings.asset";
+ private const string ThemeAssetPath = GeneratedAssetFolder + "/UnityDefaultRuntimeTheme.tss";
+ private const string DefaultThemeContent =
+ "@import url(\"unity-theme://default\");\n" +
+ "@import url(\"/Packages/com.unity.uitoolkitextensions/Runtime/Styles/UIToolkitExtensionsControlStyles.uss\");\n";
+
+ #region GameObject menu entries
+ [MenuItem("GameObject/UI Toolkit/Extensions/Circular Image Button", false, 10)]
+ public static void AddCircularImageButton(MenuCommand menuCommand) => AddControl("CircularImageButton", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Collapsible Section", false, 10)]
+ public static void AddCollapsibleSection(MenuCommand menuCommand) => AddControl("CollapsibleSection", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Color Toggle Button", false, 10)]
+ public static void AddColorToggleButton(MenuCommand menuCommand) => AddControl("ColorToggleButton", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Color Toggle Group", false, 10)]
+ public static void AddColorToggleGroup(MenuCommand menuCommand) => AddControl("ColorToggleGroup", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Coming Soon Message", false, 10)]
+ public static void AddComingSoonMessage(MenuCommand menuCommand) => AddControl("ComingSoonMessage", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Drop Down Control", false, 10)]
+ public static void AddDropDownControl(MenuCommand menuCommand) => AddControl("DropDownControl", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Drop Down Menu", false, 10)]
+ public static void AddDropDownMenu(MenuCommand menuCommand)
+ {
+ // DropDownMenuControl is code-only (no UXML element), so this starter pairs its
+ // UXML layout with a demo driver component that opens the menu from the "···" trigger.
+ var go = AddControl("DropDownMenu", menuCommand);
+ if (go != null)
+ {
+ go.AddComponent();
+ }
+ }
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Elastic List View", false, 10)]
+ public static void AddElasticListView(MenuCommand menuCommand) => AddControl("ElasticListView", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Grayscale Image", false, 10)]
+ public static void AddGrayscaleImage(MenuCommand menuCommand) => AddControl("GrayscaleImage", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Icon Label Button", false, 10)]
+ public static void AddIconLabelButton(MenuCommand menuCommand) => AddControl("IconLabelButton", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Loading Icon", false, 10)]
+ public static void AddLoadingIcon(MenuCommand menuCommand) => AddControl("LoadingIcon", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Notification Badge", false, 10)]
+ public static void AddNotificationBadge(MenuCommand menuCommand) => AddControl("NotificationBadge", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Page Dot Indicator", false, 10)]
+ public static void AddPageDotIndicator(MenuCommand menuCommand) => AddControl("PageDotIndicator", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Pill Button", false, 10)]
+ public static void AddPillButton(MenuCommand menuCommand) => AddControl("PillButton", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Pill Input Field", false, 10)]
+ public static void AddPillInputField(MenuCommand menuCommand) => AddControl("PillInputField", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Pill Selector", false, 10)]
+ public static void AddPillSelector(MenuCommand menuCommand) => AddControl("PillSelector", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Rounded Input Field", false, 10)]
+ public static void AddRoundedInputField(MenuCommand menuCommand) => AddControl("RoundedInputField", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Screen Header", false, 10)]
+ public static void AddScreenHeader(MenuCommand menuCommand) => AddControl("ScreenHeader", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Scroll Snap", false, 10)]
+ public static void AddScrollSnap(MenuCommand menuCommand) => AddControl("ScrollSnap", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Social Link Container", false, 10)]
+ public static void AddSocialLinkContainer(MenuCommand menuCommand) => AddControl("SocialLinkContainer", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Quadrant Stepper", false, 10)]
+ public static void AddQuadrantStepper(MenuCommand menuCommand) => AddControl("QuadrantStepper", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Step Progress Bar", false, 10)]
+ public static void AddStepProgressBar(MenuCommand menuCommand) => AddControl("StepProgressBar", menuCommand);
+
+ [MenuItem("GameObject/UI Toolkit/Extensions/Toggle Button", false, 10)]
+ public static void AddToggleButton(MenuCommand menuCommand) => AddControl("ToggleButton", menuCommand);
+ #endregion
+
+ #region Assets/Create menu entries
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Circular Image Button Starter", false, 601)]
+ public static void CreateCircularImageButtonStarter() => CreateStarterAsset("CircularImageButton");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Collapsible Section Starter", false, 601)]
+ public static void CreateCollapsibleSectionStarter() => CreateStarterAsset("CollapsibleSection");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Color Toggle Button Starter", false, 601)]
+ public static void CreateColorToggleButtonStarter() => CreateStarterAsset("ColorToggleButton");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Color Toggle Group Starter", false, 601)]
+ public static void CreateColorToggleGroupStarter() => CreateStarterAsset("ColorToggleGroup");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Coming Soon Message Starter", false, 601)]
+ public static void CreateComingSoonMessageStarter() => CreateStarterAsset("ComingSoonMessage");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Drop Down Control Starter", false, 601)]
+ public static void CreateDropDownControlStarter() => CreateStarterAsset("DropDownControl");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Drop Down Menu Starter", false, 601)]
+ public static void CreateDropDownMenuStarter() => CreateStarterAsset("DropDownMenu");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Elastic List View Starter", false, 601)]
+ public static void CreateElasticListViewStarter() => CreateStarterAsset("ElasticListView");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Grayscale Image Starter", false, 601)]
+ public static void CreateGrayscaleImageStarter() => CreateStarterAsset("GrayscaleImage");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Icon Label Button Starter", false, 601)]
+ public static void CreateIconLabelButtonStarter() => CreateStarterAsset("IconLabelButton");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Loading Icon Starter", false, 601)]
+ public static void CreateLoadingIconStarter() => CreateStarterAsset("LoadingIcon");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Notification Badge Starter", false, 601)]
+ public static void CreateNotificationBadgeStarter() => CreateStarterAsset("NotificationBadge");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Page Dot Indicator Starter", false, 601)]
+ public static void CreatePageDotIndicatorStarter() => CreateStarterAsset("PageDotIndicator");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Pill Button Starter", false, 601)]
+ public static void CreatePillButtonStarter() => CreateStarterAsset("PillButton");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Pill Input Field Starter", false, 601)]
+ public static void CreatePillInputFieldStarter() => CreateStarterAsset("PillInputField");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Pill Selector Starter", false, 601)]
+ public static void CreatePillSelectorStarter() => CreateStarterAsset("PillSelector");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Rounded Input Field Starter", false, 601)]
+ public static void CreateRoundedInputFieldStarter() => CreateStarterAsset("RoundedInputField");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Screen Header Starter", false, 601)]
+ public static void CreateScreenHeaderStarter() => CreateStarterAsset("ScreenHeader");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Scroll Snap Starter", false, 601)]
+ public static void CreateScrollSnapStarter() => CreateStarterAsset("ScrollSnap");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Social Link Container Starter", false, 601)]
+ public static void CreateSocialLinkContainerStarter() => CreateStarterAsset("SocialLinkContainer");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Quadrant Stepper Starter", false, 601)]
+ public static void CreateQuadrantStepperStarter() => CreateStarterAsset("QuadrantStepper");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Step Progress Bar Starter", false, 601)]
+ public static void CreateStepProgressBarStarter() => CreateStarterAsset("StepProgressBar");
+
+ [MenuItem("Assets/Create/UI Toolkit/Extensions/Toggle Button Starter", false, 601)]
+ public static void CreateToggleButtonStarter() => CreateStarterAsset("ToggleButton");
+ #endregion
+
+ ///
+ /// Ensures the scene can display UI Toolkit content and adds a UIDocument showing
+ /// the starter template for the requested control. Returns the created GameObject
+ /// (or null if the template could not be loaded) so callers can attach extras.
+ ///
+ private static GameObject AddControl(string controlName, MenuCommand menuCommand)
+ {
+ var template = InstantiateTemplate(controlName, GeneratedAssetFolder);
+ if (template == null)
+ {
+ return null;
+ }
+
+ var panelSettings = GetOrCreatePanelSettings();
+
+ var go = new GameObject(ObjectNames.NicifyVariableName(controlName));
+ Undo.RegisterCreatedObjectUndo(go, "Create " + go.name);
+ GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject);
+
+ var document = go.AddComponent();
+ document.panelSettings = panelSettings;
+ document.visualTreeAsset = template;
+
+ Selection.activeGameObject = go;
+ return go;
+ }
+
+ ///
+ /// Copies the starter template for a control into the project (if not already present)
+ /// so the user has an editable copy, and returns it.
+ ///
+ private static VisualTreeAsset InstantiateTemplate(string controlName, string destinationFolder)
+ {
+ var sourcePath = TemplateRoot + controlName + "Starter.uxml";
+ if (AssetDatabase.LoadAssetAtPath(sourcePath) == null)
+ {
+ Debug.LogError($"UI Toolkit Extensions starter template not found at [{sourcePath}]");
+ return null;
+ }
+
+ var destinationPath = destinationFolder + "/" + controlName + "Starter.uxml";
+ var existing = AssetDatabase.LoadAssetAtPath(destinationPath);
+ if (existing != null)
+ {
+ if (System.IO.File.ReadAllText(sourcePath) == System.IO.File.ReadAllText(destinationPath))
+ {
+ return existing;
+ }
+
+ if (!EditorUtility.DisplayDialog(
+ "Starter template has changed",
+ $"{controlName}Starter.uxml already exists in {destinationFolder} but differs from the packaged template (it may contain your edits, or come from an older package version).\n\nReplace it with the latest packaged template?",
+ "Replace",
+ "Keep existing"))
+ {
+ return existing;
+ }
+
+ System.IO.File.Copy(sourcePath, destinationPath, true);
+ AssetDatabase.ImportAsset(destinationPath);
+ return AssetDatabase.LoadAssetAtPath(destinationPath);
+ }
+
+ EnsureGeneratedAssetFolder();
+ AssetDatabase.CopyAsset(sourcePath, destinationPath);
+ return AssetDatabase.LoadAssetAtPath(destinationPath);
+ }
+
+ ///
+ /// Copies a starter template into the currently selected project folder.
+ ///
+ private static void CreateStarterAsset(string controlName)
+ {
+ var sourcePath = TemplateRoot + controlName + "Starter.uxml";
+ if (AssetDatabase.LoadAssetAtPath(sourcePath) == null)
+ {
+ Debug.LogError($"UI Toolkit Extensions starter template not found at [{sourcePath}]");
+ return;
+ }
+
+ var destinationPath = AssetDatabase.GenerateUniqueAssetPath(GetActiveFolderPath() + "/" + controlName + "Starter.uxml");
+ AssetDatabase.CopyAsset(sourcePath, destinationPath);
+ Selection.activeObject = AssetDatabase.LoadAssetAtPath(destinationPath);
+ }
+
+ ///
+ /// Finds a PanelSettings to render with, preferring one already in use in the open scene,
+ /// then any project asset, before finally creating one configured with the default runtime theme.
+ ///
+ private static PanelSettings GetOrCreatePanelSettings()
+ {
+ var existingDocument = Object.FindFirstObjectByType();
+ if (existingDocument != null && existingDocument.panelSettings != null)
+ {
+ return existingDocument.panelSettings;
+ }
+
+ var guids = AssetDatabase.FindAssets("t:PanelSettings");
+ if (guids.Length > 0)
+ {
+ return AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guids[0]));
+ }
+
+ EnsureGeneratedAssetFolder();
+
+ var theme = AssetDatabase.LoadAssetAtPath(ThemeAssetPath);
+ if (theme == null)
+ {
+ System.IO.File.WriteAllText(ThemeAssetPath, DefaultThemeContent);
+ AssetDatabase.ImportAsset(ThemeAssetPath);
+ theme = AssetDatabase.LoadAssetAtPath(ThemeAssetPath);
+ }
+
+ var panelSettings = ScriptableObject.CreateInstance();
+ panelSettings.themeStyleSheet = theme;
+ AssetDatabase.CreateAsset(panelSettings, PanelSettingsAssetPath);
+ AssetDatabase.SaveAssets();
+ return panelSettings;
+ }
+
+ private static void EnsureGeneratedAssetFolder()
+ {
+ if (!AssetDatabase.IsValidFolder(GeneratedAssetFolder))
+ {
+ AssetDatabase.CreateFolder("Assets", GeneratedAssetFolder.Substring("Assets/".Length));
+ }
+ }
+
+ private static string GetActiveFolderPath()
+ {
+ var obj = Selection.activeObject;
+ if (obj == null)
+ {
+ return "Assets";
+ }
+
+ var path = AssetDatabase.GetAssetPath(obj);
+ if (string.IsNullOrEmpty(path))
+ {
+ return "Assets";
+ }
+
+ return AssetDatabase.IsValidFolder(path) ? path : System.IO.Path.GetDirectoryName(path).Replace('\\', '/');
+ }
+ }
+}
diff --git a/Editor/UIToolkitExtensionsMenuOptions.cs.meta b/Editor/UIToolkitExtensionsMenuOptions.cs.meta
new file mode 100644
index 0000000..917e68d
--- /dev/null
+++ b/Editor/UIToolkitExtensionsMenuOptions.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 68219ffe64c445aeb74064a4b6db4f71
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/UnityUIToolkitExtensions.Editor.asmdef b/Editor/UnityUIToolkitExtensions.Editor.asmdef
index 76ca544..2ddf3ad 100644
--- a/Editor/UnityUIToolkitExtensions.Editor.asmdef
+++ b/Editor/UnityUIToolkitExtensions.Editor.asmdef
@@ -2,8 +2,6 @@
"name": "UnityUIToolkitExtensions.Editor",
"rootNamespace": "",
"references": [
- "GUID:343deaaf83e0cee4ca978e7df0b80d21",
- "GUID:2bafac87e7f4b9b418d9448d219b01ab",
"GUID:9ee68b2f38bf7f4418701e4ac76fb98b"
],
"includePlatforms": [],
diff --git a/Examples~ b/Examples~
index e6ab227..5f35008 160000
--- a/Examples~
+++ b/Examples~
@@ -1 +1 @@
-Subproject commit e6ab227c534dc041a786ac01ce1e902baec49197
+Subproject commit 5f35008ee1ea4097423999229533b2193a2b7dcb
diff --git a/Runtime/Controls/CircularImageButton/CircularImageButton.cs b/Runtime/Controls/CircularImageButton/CircularImageButton.cs
index 2bff08c..f3930fe 100644
--- a/Runtime/Controls/CircularImageButton/CircularImageButton.cs
+++ b/Runtime/Controls/CircularImageButton/CircularImageButton.cs
@@ -29,6 +29,7 @@ public partial class CircularImageButton : VisualElement
public CircularImageButton()
{
+ this.ApplyControlStyles();
AddToClassList(RootClass);
focusable = true;
diff --git a/Runtime/Controls/CollapsibleSection/CollapsibleSection.cs b/Runtime/Controls/CollapsibleSection/CollapsibleSection.cs
index f09abe0..2458840 100644
--- a/Runtime/Controls/CollapsibleSection/CollapsibleSection.cs
+++ b/Runtime/Controls/CollapsibleSection/CollapsibleSection.cs
@@ -54,6 +54,7 @@ public string BodyText
public CollapsibleSection()
{
+ this.ApplyControlStyles();
AddToClassList(RootClass);
var header = UIToolkitExtensions.CreateVisualElement(HeaderClass);
diff --git a/Runtime/Controls/ColorToggleButton/ColorToggleButton.cs b/Runtime/Controls/ColorToggleButton/ColorToggleButton.cs
index 5df1eb4..ed7494f 100644
--- a/Runtime/Controls/ColorToggleButton/ColorToggleButton.cs
+++ b/Runtime/Controls/ColorToggleButton/ColorToggleButton.cs
@@ -13,6 +13,7 @@ namespace UnityUIToolkit.Extensions
[UxmlElement]
public partial class ColorToggleButton : ToggleButton
{
+ public const string ColorRootClass = "colorToggleButton";
public const string IconClass = "toggleButton__icon";
public const string RippleOverlayClass = "toggleButton__ripple";
public const string RippleOverlayVisibleClass = "toggleButton__ripple--visible";
@@ -47,6 +48,8 @@ public ColorToggleButton(Color tintColor) : this(tintColor, tintColor) { }
public ColorToggleButton(Color tintColor, Color selectedTintColor)
{
+ this.ApplyControlStyles();
+ AddToClassList(ColorRootClass);
image.AddToClassList(IconClass);
rippleOverlay = UIToolkitExtensions.CreateVisualElement(this, RippleOverlayClass);
@@ -66,14 +69,19 @@ public void SetTintColor(Color color)
{
tintColor = color;
image.style.unityBackgroundImageTintColor = color;
+ // background-color fallback so the control renders without a texture assigned
+ image.style.backgroundColor = color;
}
public void SetSelectedTintColor(Color color)
{
selectedTintColor = color;
selectedOverlay.style.unityBackgroundImageTintColor = color;
+ selectedOverlay.style.backgroundColor = color;
rippleOverlay.style.unityBackgroundImageTintColor = color;
+ rippleOverlay.style.backgroundColor = color;
rippleOverlaySecondary.style.unityBackgroundImageTintColor = color;
+ rippleOverlaySecondary.style.backgroundColor = color;
}
protected override void ApplySelectionState(bool selected)
diff --git a/Runtime/Controls/ColorToggleGroup/ColorToggleGroup.cs b/Runtime/Controls/ColorToggleGroup/ColorToggleGroup.cs
index c5ca86d..64ebc50 100644
--- a/Runtime/Controls/ColorToggleGroup/ColorToggleGroup.cs
+++ b/Runtime/Controls/ColorToggleGroup/ColorToggleGroup.cs
@@ -75,6 +75,7 @@ public List ColorsList
public ColorToggleGroup()
{
+ this.ApplyControlStyles();
AddToClassList(RootClass);
container = UIToolkitExtensions.CreateVisualElement(this, ContainerClass);
diff --git a/Runtime/Controls/ComingSoonMessage/ComingSoonMessage.cs b/Runtime/Controls/ComingSoonMessage/ComingSoonMessage.cs
index 2016ce4..e50e5d9 100644
--- a/Runtime/Controls/ComingSoonMessage/ComingSoonMessage.cs
+++ b/Runtime/Controls/ComingSoonMessage/ComingSoonMessage.cs
@@ -20,6 +20,7 @@ public partial class ComingSoonMessage : VisualElement
public ComingSoonMessage()
{
+ this.ApplyControlStyles();
AddToClassList(RootClass);
var background = UIToolkitExtensions.CreateVisualElement(this, BackgroundClass);
diff --git a/Runtime/Controls/DropDownControl/DropDownControl.cs b/Runtime/Controls/DropDownControl/DropDownControl.cs
index 582329c..b848f29 100644
--- a/Runtime/Controls/DropDownControl/DropDownControl.cs
+++ b/Runtime/Controls/DropDownControl/DropDownControl.cs
@@ -94,6 +94,7 @@ public List ItemsList
public DropDownControl()
{
+ this.ApplyControlStyles();
AddToClassList(RootClass);
triggerElement = UIToolkitExtensions.CreateVisualElement(this, TriggerClass);
@@ -106,10 +107,14 @@ public DropDownControl()
triggerElement.RegisterCallback(_ => Open());
triggerElement.RegisterCallback(OnTriggerPointerDown, TrickleDown.TrickleDown);
+ // The backdrop and panel are re-parented to the panel root while open, outside this
+ // control's subtree, so they need the shared stylesheet attached directly.
backdropElement = UIToolkitExtensions.CreateVisualElement(BackdropClass);
+ backdropElement.ApplyControlStyles();
backdropElement.RegisterCallback(OnBackdropClicked);
panelElement = UIToolkitExtensions.CreateVisualElement(PanelClass);
+ panelElement.ApplyControlStyles();
panelElement.RegisterCallback(evt => evt.StopPropagation());
viewportElement = UIToolkitExtensions.CreateVisualElement(panelElement, ViewportClass);
diff --git a/Runtime/Controls/DropDownMenuControl/DropDownMenuControl.cs b/Runtime/Controls/DropDownMenuControl/DropDownMenuControl.cs
index c8fb7ca..0ef5bc5 100644
--- a/Runtime/Controls/DropDownMenuControl/DropDownMenuControl.cs
+++ b/Runtime/Controls/DropDownMenuControl/DropDownMenuControl.cs
@@ -76,10 +76,14 @@ public DropDownOption(string label, Action onSelected)
public DropDownMenuControl()
{
+ // The backdrop and panel attach to the panel root while open, outside any styled
+ // subtree, so they need the shared stylesheet attached directly.
backdropElement = UIToolkitExtensions.CreateVisualElement(BackdropClass);
+ backdropElement.ApplyControlStyles();
backdropElement.RegisterCallback(_ => Close());
panelElement = UIToolkitExtensions.CreateVisualElement(PanelClass);
+ panelElement.ApplyControlStyles();
panelElement.RegisterCallback(evt => evt.StopPropagation());
}
diff --git a/Runtime/Controls/DropDownMenuControl/DropDownMenuStarterController.cs b/Runtime/Controls/DropDownMenuControl/DropDownMenuStarterController.cs
new file mode 100644
index 0000000..3a883ad
--- /dev/null
+++ b/Runtime/Controls/DropDownMenuControl/DropDownMenuStarterController.cs
@@ -0,0 +1,73 @@
+/// Credit SimonDarksideJ
+
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UIElements;
+
+namespace UnityUIToolkit.Extensions
+{
+ ///
+ /// Demo driver for the Drop Down Menu starter template.
+ /// is purely programmatic (it has no UXML element), so unlike the other starters this one
+ /// pairs its UXML layout with a small component that constructs the menu and wires the
+ /// "···" trigger. Replace it with your own controller in real use — the ActionMenu example
+ /// shows the same wiring across multiple rows and placements.
+ ///
+ [RequireComponent(typeof(UIDocument))]
+ public class DropDownMenuStarterController : MonoBehaviour
+ {
+ // Constructed in Start — VisualElements must not be created from a MonoBehaviour
+ // constructor or field initializer.
+ private DropDownMenuControl menu;
+
+ private Label statusLabel;
+
+ private void Start()
+ {
+ var document = GetComponent();
+ VisualElement root = document.rootVisualElement;
+
+ menu = new DropDownMenuControl();
+
+ statusLabel = root.Q