Second commit

This commit is contained in:
ThomasCharester committed 2026-09-20 15:26:03 +03:00
commit 36840f3ad4
999 files changed
+61364

No files matched your search

@@ -0,0 +1,117 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using System;
using UnityEngine;
using System.Collections.Generic;
using UnityEditor;
namespace TinyGoose.Tremble.Editor
{
internal static class EditorGUILayoutUtil
{
internal static void Pad(float pad, Action content) => Pad(pad, pad, content);
internal static void Pad(float hPad, float vPad, Action content)
{
GUILayout.BeginHorizontal();
{
GUILayout.Space(hPad);
GUILayout.BeginVertical();
{
GUILayout.Space(vPad);
try
{
content();
}
catch (ExitGUIException)
{
// ignore
}
catch (Exception ex)
{
Debug.LogException(ex);
}
GUILayout.Space(vPad);
}
GUILayout.EndVertical();
GUILayout.Space(hPad);
}
GUILayout.EndHorizontal();
}
private static readonly Dictionary<string, bool> s_CollapsibleHeaderStates = new();
internal static void Indent(Action inside)
{
EditorGUI.indentLevel++;
inside();
EditorGUI.indentLevel--;
}
internal static bool FoldoutArrow(bool isOpen)
{
bool toggle = GUILayout.Button(GUIContent.none, EditorStyles.label, GUILayout.Width(20f));
Rect buttonRect = GUILayoutUtility.GetLastRect();
buttonRect.x += 5f;
if (Event.current.type == EventType.Repaint)
{
EditorStyles.foldout.Draw(buttonRect, false, false, isOpen, false);
}
return toggle;
}
internal static bool CollapsibleHeader(string header, bool isOpen, Action inside)
{
GUILayout.BeginHorizontal();
{
bool toggle = FoldoutArrow(isOpen);
toggle |= GUILayout.Button(header, EditorStyles.label);
if (toggle)
{
isOpen = !isOpen;
}
}
GUILayout.EndHorizontal();
if (isOpen)
{
GUILayout.BeginHorizontal();
{
GUILayout.Space(20f);
GUILayout.BeginVertical();
{
inside();
}
GUILayout.EndVertical();
}
GUILayout.EndHorizontal();
}
return isOpen;
}
internal static void CollapsibleHeader(string header, string id, bool defaultOpen, Action inside)
{
bool wasOpen = s_CollapsibleHeaderStates.GetValueOrDefault(id, defaultOpen);
s_CollapsibleHeaderStates[id] = CollapsibleHeader(header, wasOpen, inside);
}
internal static void CollapsibleHeader(string header, string id, Action inside)
=> CollapsibleHeader(header, id, defaultOpen: false, inside);
internal static void SetHeaderOpen(string id, bool isOpened)
{
s_CollapsibleHeaderStates[id] = isOpened;
}
internal static bool IsHeaderOpen(string id) => s_CollapsibleHeaderStates.GetValueOrDefault(id, false);
}
}
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 4c018a50074942338e9d90803f43545a
timeCreated: 1712049970
AssetOrigin:
serializedVersion: 1
productId: 277805
packageName: Tremble - Map Importer
packageVersion: 1.11.1
assetPath: Assets/Tremble/Editor/EditorUI/Utils/EditorGUILayoutUtil.cs
uploadId: 939664
@@ -0,0 +1,81 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
// Adapted from Unity3D-IconManager by Thundernerd.
// This is only a tiny portion of the original code, but in the interest of attributing to his good work,
// I'll include his licence and a link to the original.
// https://github.com/Thundernerd/Unity3D-IconManager/
// Original Licence follows:
// MIT License
//
// Copyright (c) [2020] [Christiaan Bloemendaal]
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
// associated documentation files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial
// portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using UnityEditor;
using UnityEngine;
namespace TinyGoose.Tremble.Editor
{
public static class EditorGameObjectIconUtil
{
public enum EditorIcon
{
GrayDiamond,
BlueDiamond,
TealDiamond,
GreenDiamond,
YellowDiamond,
OrangeDiamond,
RedDiamond,
PurpleDiamond,
MAX
}
public enum EditorLabel
{
Gray,
Blue,
Teal,
Green,
Yellow,
Orange,
Red,
Purple,
MAX
}
public static void SetEditorIcon(this GameObject go, EditorIcon icon)
{
//TODO(jwf): cache these!
Texture2D texture = EditorGUIUtility.FindTexture($"sv_icon_dot{(int)icon+8}_pix16_gizmo");
EditorGUIUtility.SetIconForObject(go, texture);
}
public static void SetEditorIcon(this GameObject go, EditorLabel label)
{
//TODO(jwf): cache these!
Texture2D texture = EditorGUIUtility.FindTexture($"sv_label_{(int)label}");
EditorGUIUtility.SetIconForObject(go, texture);
}
}
}
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 053deb05101c4cf29d8d760aa74f619f
timeCreated: 1724832500
AssetOrigin:
serializedVersion: 1
productId: 277805
packageName: Tremble - Map Importer
packageVersion: 1.11.1
assetPath: Assets/Tremble/Editor/EditorUI/Utils/EditorGameObjectIconUtil.cs
uploadId: 939664
@@ -0,0 +1,154 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace TinyGoose.Tremble.Editor
{
public static class MaterialGroupUtil
{
public static bool RemoveMaterialsFromGroups(Material[] materials)
=> MoveMaterialsToGroupIdx(materials, -1);
public static bool MoveMaterialsToGroup(Material[] materials, string groupName, bool createIfNotExist = false)
{
int index = GetMaterialGroupIndex(groupName);
if (index == -1 && !createIfNotExist)
{
Debug.LogError($"Could not move materials to non-existent group '{groupName}'!");
return false;
}
TrembleSyncSettings syncSettings = TrembleSyncSettings.Get();
// New group - create and add
if (index == -1)
{
syncSettings.Modify(so =>
{
SerializedProperty materialGroupsArray = so.FindBackedProperty(nameof(TrembleSyncSettings.MaterialGroups));
materialGroupsArray.AppendArrayElement();
});
MaterialGroup[] mgs = syncSettings.MaterialGroups;
mgs[^1].Name = groupName;
mgs[^1].Materials = Array.Empty<Material>();
index = mgs.Length - 1;
}
return MoveMaterialsToGroupIdx(materials, index);
}
public static int GetMaterialGroupIndexForMaterial(Material material)
{
TrembleSyncSettings syncSettings = TrembleSyncSettings.Get();
for (int materialGroupIdx = 0; materialGroupIdx < syncSettings.MaterialGroups.Length; materialGroupIdx++)
{
MaterialGroup mg = syncSettings.MaterialGroups[materialGroupIdx];
foreach (Material m in mg.Materials)
{
if (material == m)
return materialGroupIdx;
}
}
return -1;
}
public static bool IsMaterialPartOfAnyMaterialGroup(Material material)
=> GetMaterialGroupIndexForMaterial(material) != -1;
private static bool MoveMaterialsToGroupIdx(Material[] materials, int index)
{
TrembleSyncSettings syncSettings = TrembleSyncSettings.Get();
MaterialGroup[] mgs = syncSettings.MaterialGroups;
for (int groupIdx = 0; groupIdx < mgs.Length; groupIdx++)
{
if (groupIdx == index)
{
// Our target group - remove these mats, and add to end
mgs[groupIdx].Materials = mgs[groupIdx].Materials
.Where(m => !materials.Contains(m))
.Concat(materials)
.ToArray();
}
else
{
// Not our target group - remove these mats
mgs[groupIdx].Materials = mgs[groupIdx].Materials
.Where(m => !materials.Contains(m))
.ToArray();
}
}
CleanupMissingMaterials(mgs);
CleanupEmptyGroups(mgs);
return true;
}
private static void CleanupMissingMaterials(MaterialGroup[] mgs)
{
for (int groupIdx = 0; groupIdx < mgs.Length; groupIdx++)
{
mgs[groupIdx].Materials = mgs[groupIdx].Materials
.Where(m => m)
.ToArray();
}
}
private static void CleanupEmptyGroups(MaterialGroup[] mgs)
{
// Now check for empty groups
List<int> removeIndexes = new();
for (int groupIdx = 0; groupIdx < mgs.Length; groupIdx++)
{
if (mgs[groupIdx].Materials.Length != 0)
continue;
bool remove = EditorUtility.DisplayDialog("Empty Material Group", $"Material Group '{mgs[groupIdx].Name}' is empty - delete it?", "Yup", "No - keep it!");
if (!remove)
continue;
removeIndexes.Add(groupIdx);
}
int numRemoved = 0;
foreach (int idx in removeIndexes)
{
int removeIdx = idx - numRemoved;
numRemoved++;
TrembleSyncSettings.Get().Modify(so =>
{
SerializedProperty groupsProp = so.FindBackedProperty(nameof(TrembleSyncSettings.MaterialGroups));
groupsProp.DeleteArrayElementAtIndex(removeIdx);
});
}
}
private static int GetMaterialGroupIndex(string groupName)
{
TrembleSyncSettings syncSettings = TrembleSyncSettings.Get();
for (int mgIdx = 0; mgIdx < syncSettings.MaterialGroups.Length; mgIdx++)
{
if (syncSettings.MaterialGroups[mgIdx].Name.EqualsInvariant(groupName))
return mgIdx;
}
return -1;
}
}
}
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: bfca730eb4364517a3fa6aafb28dc837
timeCreated: 1722943294
AssetOrigin:
serializedVersion: 1
productId: 277805
packageName: Tremble - Map Importer
packageVersion: 1.11.1
assetPath: Assets/Tremble/Editor/EditorUI/Utils/MaterialGroupUtil.cs
uploadId: 939664
@@ -0,0 +1,31 @@
using System;
using UnityEditor;
using UnityEngine;
namespace TinyGoose.Tremble.Editor
{
public static class MaterialRenderDataUtil
{
public static void SetMaterialImportMode(this Material mat, MaterialImportMode mode)
=> ModifyRenderData(mat, mrd => mrd.ExportMode = mode);
public static void SetMaterialResolutionOverridden(this Material mat, bool overrideResolution)
=> ModifyRenderData(mat, mrd => mrd.IsResolutionOverridden = overrideResolution);
public static void SetMaterialResolutionX(this Material mat, MaterialExportSize size)
=> ModifyRenderData(mat, mrd => mrd.ResolutionX = size);
public static void SetMaterialResolutionY(this Material mat, MaterialExportSize size)
=> ModifyRenderData(mat, mrd => mrd.ResolutionY = size);
private static void ModifyRenderData(Material mat, Action<MaterialRenderData> action)
{
TrembleSyncSettings syncSettings = TrembleSyncSettings.Get();
MaterialRenderData renderData = TrembleSyncSettings.Get().GetMaterialRenderData(mat);
action(renderData);
EditorUtility.SetDirty(syncSettings);
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 808c02ac921b9e4638fdb31dd490d61c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 277805
packageName: Tremble - Map Importer
packageVersion: 1.11.1
assetPath: Assets/Tremble/Editor/EditorUI/Utils/MaterialRenderDataUtil.cs
uploadId: 939664
@@ -0,0 +1,391 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace TinyGoose.Tremble.Editor
{
// This wraps EditorGUI, EditorGUILayout, GUI, and GUILayout calls.
// The purpose is that you can call them in "normal" mode, which forwards the calls on to Unity,
// or "keywords capture" mode, which performs no GUI work at all but captures a list of
// keywords to expose to the Project Settings window's search.
public static class TrembleSettingsGUI
{
private static readonly List<string> s_Keywords = new(256);
private static bool s_IsCapturingKeywords = false;
private static GUIStyle s_LineStyle;
private static readonly Dictionary<string, bool> s_FoldoutStates = new();
public static void BeginKeywordCapture()
{
s_IsCapturingKeywords = true;
s_Keywords.Clear();
}
public static List<string> EndKeywordCapture()
{
s_IsCapturingKeywords = false;
return s_Keywords;
}
public static void Space(float size)
{
if (s_IsCapturingKeywords)
return;
GUILayout.Space(size);
}
public static void FlexibleSpace()
{
if (s_IsCapturingKeywords)
return;
GUILayout.FlexibleSpace();
}
public static void LabelledHyperlink(string label, string buttonText, string url)
=> LabelledHyperlink(label, buttonText, () => Application.OpenURL(url));
public static void LabelledHyperlink(string label, string buttonText, Action action)
{
if (s_IsCapturingKeywords)
{
s_Keywords.Add(label);
s_Keywords.Add(buttonText);
return;
}
BeginHorizontal();
{
Label(label + ":");
if (Button(buttonText, GUILayout.Width(250f)))
{
action();
}
}
EndHorizontal();
}
public static void BeginHorizontal(GUIStyle style, params GUILayoutOption[] options)
{
if (s_IsCapturingKeywords)
return;
GUILayout.BeginHorizontal(style, options);
}
public static void BeginHorizontal(params GUILayoutOption[] options)
{
if (s_IsCapturingKeywords)
return;
GUILayout.BeginHorizontal(options);
}
public static void EndHorizontal()
{
if (s_IsCapturingKeywords)
return;
GUILayout.EndHorizontal();
}
public static void BeginVertical(GUIStyle style, params GUILayoutOption[] options)
{
if (s_IsCapturingKeywords)
return;
GUILayout.BeginVertical(style, options);
}
public static void BeginVertical(params GUILayoutOption[] options)
{
if (s_IsCapturingKeywords)
return;
GUILayout.BeginVertical(options);
}
public static void EndVertical()
{
if (s_IsCapturingKeywords)
return;
GUILayout.EndVertical();
}
public static void BeginScrollView(ref Vector2 scrollPosition, params GUILayoutOption[] options)
{
if (s_IsCapturingKeywords)
return;
scrollPosition = GUILayout.BeginScrollView(scrollPosition, options);
}
public static void EndScrollView()
{
if (s_IsCapturingKeywords)
return;
GUILayout.EndScrollView();
}
public static void MakeLastRectClickable(Action onClick)
{
if (s_IsCapturingKeywords)
return;
Rect verticalRect = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.MouseDown && verticalRect.Contains(Event.current.mousePosition))
{
onClick();
Event.current.Use(); // consume
}
}
public static void HelpBox(string message, MessageType type)
{
if (s_IsCapturingKeywords)
{
s_Keywords.Add(message);
return;
}
EditorGUILayout.HelpBox(message, type);
}
public static void Separator(float height = 1f)
{
if (s_IsCapturingKeywords)
return;
s_LineStyle ??= new() { normal = new() { background = Texture2D.grayTexture } };
GUILayout.Box(Texture2D.grayTexture, s_LineStyle, GUILayout.ExpandWidth(true), GUILayout.Height(height));
}
public static void Label(string text, params GUILayoutOption[] options)
{
if (s_IsCapturingKeywords)
{
s_Keywords.Add(text);
return;
}
GUILayout.Label(text, GUI.skin.label, options);
}
public static void Label(string text, GUIStyle style, params GUILayoutOption[] options)
{
if (s_IsCapturingKeywords)
{
s_Keywords.Add(text);
return;
}
GUILayout.Label(text, style, options);
}
public static bool Button(string text, params GUILayoutOption[] options)
{
if (s_IsCapturingKeywords)
{
s_Keywords.Add(text);
return false;
}
return GUILayout.Button(text, options);
}
public static bool Button(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
{
if (s_IsCapturingKeywords)
{
s_Keywords.Add(content.text);
return false;
}
return GUILayout.Button(content, style, options);
}
public static bool Toggle(bool value, GUIContent content)
{
if (s_IsCapturingKeywords)
{
s_Keywords.Add(content.text);
return value;
}
return GUILayout.Toggle(value, content);
}
public static bool Toggle(bool value, GUIContent content, params GUILayoutOption[] options)
{
if (s_IsCapturingKeywords)
{
s_Keywords.Add(content.text);
return value;
}
return GUILayout.Toggle(value, content, options);
}
public static float FloatField(float value)
{
if (s_IsCapturingKeywords)
return value;
return EditorGUILayout.FloatField(value);
}
public static void PropertyField(SerializedProperty sp, params GUILayoutOption[] options)
{
if (s_IsCapturingKeywords)
return;
EditorGUILayout.PropertyField(sp, GUIContent.none, options);
}
public static void Image(Texture2D texture, float width, float height)
{
if (s_IsCapturingKeywords)
return;
GUILayout.Box(texture, GUILayout.Width(width), GUILayout.Height(height));
}
public static bool Foldout(bool foldout, string content, bool toggleOnLabelClick)
=> Foldout(foldout, content, toggleOnLabelClick, EditorStyles.foldout);
public static bool Foldout(bool foldout, string content, bool toggleOnLabelClick, GUIStyle style)
{
if (s_IsCapturingKeywords)
return foldout;
return EditorGUILayout.Foldout(foldout, content, toggleOnLabelClick, style);
}
public static void Foldout(string title, Action contents)
=> Foldout(title, contents, EditorStyles.foldout);
public static void Foldout(string title, Action contents, GUIStyle style)
{
if (s_IsCapturingKeywords)
return;
bool foldout = s_FoldoutStates.GetValueOrDefault(title, false);
foldout = Foldout(foldout, title, true, style);
if (foldout)
{
Space(10f);
BeginHorizontal();
{
Space(20f);
BeginVertical();
{
contents();
}
EndVertical();
}
EndHorizontal();
Space(10f);
}
s_FoldoutStates[title] = foldout;
}
public static void PrefixLabel(string text, string tooltip)
{
if (s_IsCapturingKeywords)
{
s_Keywords.Add(text);
return;
}
EditorGUILayout.PrefixLabel(new GUIContent(text, tooltip));
}
public static int Popup(int value, string[] options)
{
if (s_IsCapturingKeywords)
{
s_Keywords.AddRange(options);
return value;
}
return EditorGUILayout.Popup(value, options);
}
public static int Popup(int value, string[] options, GUIStyle style)
{
if (s_IsCapturingKeywords)
{
s_Keywords.AddRange(options);
return value;
}
return EditorGUILayout.Popup(value, options, style);
}
public static void UseDisabled(bool disabled, Action inside)
{
bool prevDisabled = false;
if (!s_IsCapturingKeywords)
{
prevDisabled = !GUI.enabled;
GUI.enabled = !disabled;
}
inside();
if (!s_IsCapturingKeywords)
{
GUI.enabled = !prevDisabled;
}
}
public static void UseColour(Color c, Action inside)
{
Color previousColour = Color.white;
if (!s_IsCapturingKeywords)
{
previousColour = GUI.color;
GUI.color = c;
}
inside();
if (!s_IsCapturingKeywords)
{
GUI.color = previousColour;
}
}
public static void Indent(Action inside)
{
if (!s_IsCapturingKeywords)
{
EditorGUI.indentLevel++;
}
inside();
if (!s_IsCapturingKeywords)
{
EditorGUI.indentLevel--;
}
}
}
}
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 4aa6428101b54401a08834d76320438b
timeCreated: 1721666909
AssetOrigin:
serializedVersion: 1
productId: 277805
packageName: Tremble - Map Importer
packageVersion: 1.11.1
assetPath: Assets/Tremble/Editor/EditorUI/Utils/TrembleSettingsGUI.cs
uploadId: 939664