Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
7a4b2db
Add button color binding support with MultiColorBinderEntry and Gener…
IvanMurzak Nov 23, 2025
b00fd2c
Add unit tests for MultiColorBinder functionality
IvanMurzak Nov 23, 2025
5ff4bea
Make label field read-only in MultiColorBinderEntryDrawer
IvanMurzak Nov 23, 2025
e8757fe
Update Unity MCP connection configuration and package dependencies
IvanMurzak Nov 23, 2025
9ef91fd
Update Unity-MCP-ConnectionConfig.json
IvanMurzak Nov 23, 2025
b686f55
Refactor color binder classes to use LogableMonoBehaviour for improve…
IvanMurzak Nov 23, 2025
26fa630
Refactor ButtonColorBinder and GenericColorBinder to improve paramete…
IvanMurzak Nov 23, 2025
02a10ad
Format JSON settings for improved readability
IvanMurzak Nov 23, 2025
61a17c4
Add SelectableColorBinder for theme color management in Unity UI
IvanMurzak Nov 23, 2025
3ba5a54
Remove unnecessary yield return statements in theme switching tests f…
IvanMurzak Nov 23, 2025
7673550
Fix null color data log message formatting in BaseMultiColorBinder
IvanMurzak Nov 23, 2025
43971b0
Add yield return statements to ensure theme switching tests verify co…
IvanMurzak Nov 24, 2025
abc110d
Refactor MultiColorBinder Tests to Use Utility Methods
IvanMurzak Nov 24, 2025
ac49e4d
Add FixedMultiColorBinderEntries and update related classes for impro…
IvanMurzak Nov 24, 2025
b6ea6c9
Add ToggleColorBinder to manage theme colors for Unity Toggle's Color…
IvanMurzak Nov 24, 2025
13080f2
Refactor property references in ColorBinderDataDrawer, FixedMultiColo…
IvanMurzak Nov 24, 2025
1ff18b5
Refactor FixedMultiColorBinderEntriesDrawer to remove foldout and upd…
IvanMurzak Nov 24, 2025
39c5c9f
Remove unnecessary margin setting from label container in MultiColorB…
IvanMurzak Nov 24, 2025
d2de260
Refactor GitHub Actions workflow to streamline OS and platform config…
IvanMurzak Nov 24, 2025
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
22 changes: 9 additions & 13 deletions .github/workflows/test_unity_plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,11 @@ jobs:
strategy:
fail-fast: false
matrix:
include:
- os: windows
runs-on: [windows-latest]
- os: ubuntu
runs-on: [ubuntu-latest]
os: [ubuntu-latest]
platform: [base, windows-mono]

name: ${{ inputs.unityVersion }} ${{ inputs.testMode }} on ${{ matrix.os }}
runs-on: ${{ matrix.runs-on }}
name: ${{ inputs.unityVersion }} ${{ inputs.testMode }} on ${{ matrix.platform }}
runs-on: ${{ matrix.os }}

# permissions: # minimize the default token
# contents: write
Expand Down Expand Up @@ -65,13 +62,12 @@ jobs:
path: |
${{ inputs.projectPath }}/Library
~/.cache/unity3d
key: Library-${{ inputs.unityVersion }}-${{ matrix.os }}
key: Library-${{ inputs.unityVersion }}-${{ inputs.testMode }}-${{ matrix.platform }}

# --------------------------------------------------------------------- #
- name: Generate custom image name
id: custom_image
run: |
echo "image=unityci/editor:${{ matrix.os }}-${{ inputs.unityVersion }}-base-3" >> $GITHUB_OUTPUT
run: echo "image=unityci/editor:ubuntu-${{ inputs.unityVersion }}-${{ matrix.platform }}-3" >> $GITHUB_OUTPUT
shell: bash

- uses: game-ci/unity-test-runner@v4
Expand All @@ -86,13 +82,13 @@ jobs:
testMode: ${{ inputs.testMode }}
customImage: ${{ steps.custom_image.outputs.image }}
githubToken: ${{ secrets.GITHUB_TOKEN }}
checkName: ${{ inputs.unityVersion }} ${{ inputs.testMode }} ${{ matrix.os }} Test Results
artifactsPath: artifacts-${{ inputs.unityVersion }}-${{ inputs.testMode }}-${{ matrix.os }}
checkName: ${{ inputs.unityVersion }} ${{ inputs.testMode }} ${{ matrix.platform }} Test Results
artifactsPath: artifacts-${{ inputs.unityVersion }}-${{ inputs.testMode }}-${{ matrix.platform }}
customParameters: -CI true -GITHUB_ACTIONS true

# --------------------------------------------------------------------- #
- uses: actions/upload-artifact@v4
if: always()
with:
name: Test results for ${{ inputs.unityVersion }} ${{ inputs.testMode }} on ${{ matrix.os }}
name: Test results for ${{ inputs.unityVersion }} ${{ inputs.testMode }} on ${{ matrix.platform }}
path: ${{ steps.tests.outputs.artifactsPath }}
114 changes: 57 additions & 57 deletions Unity-Theme/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,67 +1,67 @@
{
"files.exclude":
{
"**/.DS_Store":true,
"**/.git":true,
"**/.vs":true,
"**/.gitmodules":true,
"**/.vsconfig":true,
"**/*.booproj":true,
"**/*.pidb":true,
"**/*.suo":true,
"**/*.user":true,
"**/*.userprefs":true,
"**/*.unityproj":true,
"**/*.dll":true,
"**/*.exe":true,
"**/*.pdf":true,
"**/*.mid":true,
"**/*.midi":true,
"**/*.wav":true,
"**/*.gif":true,
"**/*.ico":true,
"**/*.jpg":true,
"**/*.jpeg":true,
"**/*.png":true,
"**/*.psd":true,
"**/*.tga":true,
"**/*.tif":true,
"**/*.tiff":true,
"**/*.3ds":true,
"**/*.3DS":true,
"**/*.fbx":true,
"**/*.FBX":true,
"**/*.lxo":true,
"**/*.LXO":true,
"**/*.ma":true,
"**/*.MA":true,
"**/*.obj":true,
"**/*.OBJ":true,
"**/*.asset":true,
"**/*.cubemap":true,
"**/*.flare":true,
"**/*.mat":true,
"**/*.meta":true,
"**/*.prefab":true,
"**/*.unity":true,
"build/":true,
"Build/":true,
"Library/":true,
"library/":true,
"obj/":true,
"Obj/":true,
"Logs/":true,
"logs/":true,
"ProjectSettings/":true,
"UserSettings/":true,
"temp/":true,
"Temp/":true
"files.exclude": {
"**/.DS_Store": true,
"**/.git": true,
"**/.vs": true,
"**/.gitmodules": true,
"**/.vsconfig": true,
"**/*.booproj": true,
"**/*.pidb": true,
"**/*.suo": true,
"**/*.user": true,
"**/*.userprefs": true,
"**/*.unityproj": true,
"**/*.dll": true,
"**/*.exe": true,
"**/*.pdf": true,
"**/*.mid": true,
"**/*.midi": true,
"**/*.wav": true,
"**/*.gif": true,
"**/*.ico": true,
"**/*.jpg": true,
"**/*.jpeg": true,
"**/*.png": true,
"**/*.psd": true,
"**/*.tga": true,
"**/*.tif": true,
"**/*.tiff": true,
"**/*.3ds": true,
"**/*.3DS": true,
"**/*.fbx": true,
"**/*.FBX": true,
"**/*.lxo": true,
"**/*.LXO": true,
"**/*.ma": true,
"**/*.MA": true,
"**/*.obj": true,
"**/*.OBJ": true,
"**/*.asset": true,
"**/*.cubemap": true,
"**/*.flare": true,
"**/*.mat": true,
"**/*.meta": true,
"**/*.prefab": true,
"**/*.unity": true,
"build/": true,
"Build/": true,
"Library/": true,
"library/": true,
"obj/": true,
"Obj/": true,
"Logs/": true,
"logs/": true,
"ProjectSettings/": true,
"UserSettings/": true,
"temp/": true,
"Temp/": true
},
"omnisharp.enableRoslynAnalyzers": true,
"dotnet.defaultSolution": "Unity-Theme.sln",
"cSpell.words": [
"imgui",
"jsonserialize",
"Logable",
"Mathf",
"reorderable",
"UGUI",
Expand Down
16 changes: 12 additions & 4 deletions Unity-Theme/Assets/Resources/Unity-MCP-ConnectionConfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
{
"Host": "http://localhost:8080",
"Port": 8080,
"KeepConnected": true,
"LogLevel": 3,
"TimeoutMs": 10000
"EnabledTools": [
"*"
],
"EnabledPrompts": [
"*"
],
"EnabledResources": [
"*"
],
"Host": "http://localhost:8080",
"TimeoutMs": 10000,
"KeepConnected": false
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public override VisualElement CreatePropertyGUI(SerializedProperty property)
var sliderAlpha = root.Query<Slider>("sliderAlpha").First();
var colorFill = root.Query<VisualElement>("colorFill").Last();

var colorGuid = property.FindPropertyRelative("colorGuid");
var overrideAlpha = property.FindPropertyRelative("overrideAlpha");
var alpha = property.FindPropertyRelative("alpha");
var colorGuid = property.FindPropertyRelative(nameof(Binders.ColorBinderData.colorGuid));
var overrideAlpha = property.FindPropertyRelative(nameof(Binders.ColorBinderData.overrideAlpha));
var alpha = property.FindPropertyRelative(nameof(Binders.ColorBinderData.alpha));

dropdownColor.choices = Theme.Instance?.ColorNames?.ToList() ?? new List<string>() { "error" };
dropdownColor.value = Theme.Instance?.GetColorName(colorGuid.stringValue);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;

namespace Unity.Theme.Binders
{
/// <summary>
/// Custom property drawer for FixedMultiColorBinderEntries.
/// Displays the entries array without allowing size modification.
/// </summary>
[CustomPropertyDrawer(typeof(FixedMultiColorBinderEntries))]
public class FixedMultiColorBinderEntriesDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var root = new VisualElement();

// Get the entries array property
var entriesProperty = property.FindPropertyRelative(nameof(FixedMultiColorBinderEntries.colorBindings));

if (entriesProperty == null || !entriesProperty.isArray)
{
var errorLabel = new Label("Error: Could not find entries array");
errorLabel.style.color = UnityEngine.Color.red;
root.Add(errorLabel);
return root;
}

// Add each entry to the foldout
for (int i = 0; i < entriesProperty.arraySize; i++)
{
var elementProperty = entriesProperty.GetArrayElementAtIndex(i);

// Create a PropertyField for each entry
// This will use the MultiColorBinderEntryDrawer for rendering
var entryField = new PropertyField(elementProperty, $"Color Binding {i}");
entryField.Bind(property.serializedObject);

root.Add(entryField);
}

return root;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor;
using UnityEditor.UIElements;

namespace Unity.Theme.Editor
{
[CustomPropertyDrawer(typeof(Binders.MultiColorBinderEntry), true)]
public class MultiColorBinderEntryDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var root = new VisualElement();
root.style.marginBottom = 4;

// Add a separator line
var separator = new VisualElement();
separator.style.height = 1;
separator.style.backgroundColor = new StyleColor(new Color(0.5f, 0.5f, 0.5f, 0.3f));
separator.style.marginTop = 4;
separator.style.marginBottom = 10;
root.Add(separator);

var labelProperty = property.FindPropertyRelative(nameof(Binders.MultiColorBinderEntry.label));
var colorDataProperty = property.FindPropertyRelative(nameof(Binders.MultiColorBinderEntry.colorData));

// Create a container for the label
var labelContainer = new VisualElement();
labelContainer.style.flexDirection = FlexDirection.Row;

// Create label field (readonly)
var labelField = new TextField("Label");
labelField.value = labelProperty.stringValue;
labelField.isReadOnly = true;
labelField.style.flexGrow = 1;

labelContainer.Add(labelField);

// Add the label container to root
root.Add(labelContainer);

// Create a property field for the ColorBinderData
// This will automatically use the ColorBinderDataDrawer
var colorDataField = new PropertyField(colorDataProperty, "Color");
colorDataField.Bind(property.serializedObject);

root.Add(colorDataField);

return root;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Unity.Theme.Binders
{
public abstract partial class BaseColorBinder : MonoBehaviour
public abstract partial class BaseColorBinder : LogableMonoBehaviour
{
/// <summary>
/// Set color by name from current theme
Expand Down Expand Up @@ -40,14 +40,13 @@ public abstract partial class BaseColorBinder : MonoBehaviour
/// <returns>Operation success</returns>
public bool SetAlphaOverride(bool overrideAlpha, float alpha = 1.0f)
{
if (data.overrideAlpha == overrideAlpha && data.alpha == alpha)
if (data.overrideAlpha == overrideAlpha && Mathf.Abs(data.alpha - alpha) < Mathf.Epsilon)
return true; // skip if the same alpha

data.overrideAlpha = overrideAlpha;
data.alpha = alpha;

if (Theme.IsLogActive(DebugLevel.Trace) && this.IsNotNull())
Debug.Log($"[Theme] SetAlpha: '<b>{data.ColorName}</b>' {alpha} at <b>{GameObjectPath()}</b>", gameObject);
LogTrace("SetAlpha: '<b>{0}</b>' {1}", data.ColorName, alpha);

InvalidateColor(Theme.Instance?.CurrentTheme);
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
using System.Text;
using UnityEngine;

namespace Unity.Theme.Binders
{
public abstract partial class BaseColorBinder : MonoBehaviour
public abstract partial class BaseColorBinder : LogableMonoBehaviour
{
#if UNITY_EDITOR
protected virtual void OnValidate() => UnityEditor.EditorApplication.delayCall += Validate;
Expand All @@ -14,16 +11,19 @@ protected virtual void Validate()
if (this.IsNull())
return;


if (string.IsNullOrEmpty(data.colorGuid))
{
if (Theme.IsLogActive(DebugLevel.Error) && this.IsNotNull())
Debug.LogError($"[Theme] Color GUID is <b><color=red>null</color></b> at <b>{GameObjectPath()}</b>", gameObject);
#if UNITY_EDITOR
LogError("Color GUID is <b><color=red>null</color></b> or <b><color=red>empty</color></b>");
#else
LogError("Color GUID is null or empty");
#endif
return;
}
if (!data.IsConnected)
{
if (Theme.IsLogActive(DebugLevel.Error) && this.IsNotNull())
Debug.LogError($"[Theme] Color with GUID='{data.colorGuid}' not found in database at <b>{GameObjectPath()}</b>", gameObject);
LogError("Color with GUID='{0}' not found in database", data.colorGuid);
return;
}
#if UNITY_EDITOR
Expand Down
Loading