349 lines
13 KiB
C#
349 lines
13 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEditor.UIElements;
|
|
using UnityEngine.UIElements;
|
|
using NUnit.Framework;
|
|
using static SLZ.CustomStaticBatching.PackedChannel;
|
|
using static UnityEngine.UI.InputField;
|
|
using System.Runtime.Remoting.Messaging;
|
|
using UnityEditor.UIElements.Bindings;
|
|
using System;
|
|
using static UnityEditor.Search.SearchValue;
|
|
using System.Reflection;
|
|
using Unity.Collections.LowLevel.Unsafe;
|
|
|
|
namespace SLZ.CustomStaticBatching.Editor
|
|
{
|
|
/// <summary>
|
|
/// Menu that controls the global settings used by the static batcher in editor
|
|
/// </summary>
|
|
static class SBSettingsProvider
|
|
{
|
|
[SettingsProvider]
|
|
public static SettingsProvider CreateSBSettingsProvider()
|
|
{
|
|
|
|
System.Action<string, VisualElement> uiAction = SBSettingsUI;
|
|
SettingsProvider provider = new SettingsProvider("Project/SLZCustomStaticBatching", SettingsScope.Project)
|
|
{
|
|
label = "Custom Static Batching",
|
|
activateHandler = uiAction,
|
|
};
|
|
return provider;
|
|
}
|
|
|
|
public static void SBSettingsUI(string searchContext, VisualElement rootElement)
|
|
{
|
|
|
|
SerializedObject globalSettings = new SerializedObject(SBSettingsSO.GlobalSettings);
|
|
VisualElement margin = new VisualElement();
|
|
margin.style.paddingLeft = 8;
|
|
margin.style.paddingRight = 8;
|
|
margin.style.paddingTop = 4;
|
|
margin.style.flexDirection = FlexDirection.Column;
|
|
margin.style.flexGrow = 1;
|
|
margin.style.alignItems = Align.Stretch;
|
|
margin.style.flexShrink = 1;
|
|
margin.style.flexBasis = StyleKeyword.Auto;
|
|
|
|
Label title = new Label("<b>Custom Static Batching</b>");
|
|
title.style.fontSize = 20;
|
|
title.style.paddingBottom = 8;
|
|
|
|
|
|
|
|
|
|
VisualElement testButtonStrip = new VisualElement();
|
|
//testButtonStrip.style.marginTop = 4;
|
|
testButtonStrip.style.flexShrink = 0;
|
|
|
|
testButtonStrip.style.flexDirection = FlexDirection.Row;
|
|
testButtonStrip.style.justifyContent = Justify.Center;
|
|
|
|
|
|
BuildPlatformsMirror.buildPlatformInfo[] buildPlatforms = BuildPlatformsMirror.ValidBuildPlatforms;
|
|
|
|
int numPlatforms = buildPlatforms.Length;
|
|
TabBox tabBox = new TabBox(numPlatforms + 1);
|
|
tabBox.tabs[0].text = "Default";
|
|
|
|
for (int i = 0; i < numPlatforms; i++)
|
|
{
|
|
if (buildPlatforms[i].icon != null)
|
|
{
|
|
tabBox.tabs[i + 1].icon = buildPlatforms[i].icon;
|
|
}
|
|
else
|
|
{
|
|
tabBox.tabs[i + 1].text = buildPlatforms[i].name;
|
|
}
|
|
tabBox.tabs[i + 1].tooltip = buildPlatforms[i].tooltip;
|
|
}
|
|
|
|
PlatformSettingsPage[] settingsPage = new PlatformSettingsPage[numPlatforms + 1];
|
|
|
|
settingsPage[0] = new PlatformSettingsPage(globalSettings);
|
|
|
|
tabBox.tabPages[0].Add(settingsPage[0]);
|
|
|
|
for (int i = 1; i <= numPlatforms; i++)
|
|
{
|
|
settingsPage[i] = new PlatformSettingsPage(globalSettings, buildPlatforms[i - 1].buildTarget.TargetName);
|
|
tabBox.tabPages[i].Add(settingsPage[i]);
|
|
}
|
|
|
|
rootElement.Add(margin);
|
|
margin.Add(title);
|
|
margin.Add(tabBox);
|
|
//EditorToolbarUtility.SetupChildrenAsButtonStrip(testButtonStrip);
|
|
}
|
|
|
|
static string[] VtxFormatNames = new string[] { "Use Player Vertex Compression", "UNorm8", "SNorm8", "Float16", "Float32" };
|
|
|
|
class PlatformSettingsPage : VisualElement
|
|
{
|
|
VisualElement toggleGroup;
|
|
public readonly int index;
|
|
public readonly string rootBindingPath;
|
|
|
|
public PlatformSettingsPage(SerializedObject settings)
|
|
{
|
|
index = -1;
|
|
rootBindingPath = "defaultSettings.";
|
|
InitializePage(settings, false);
|
|
}
|
|
public PlatformSettingsPage(SerializedObject settings, string buildTargetName)
|
|
{
|
|
index = 0;
|
|
SBSettingsSO globalSettings = SBSettingsSO.GlobalSettings;
|
|
int settingsCount = globalSettings.platformOverrideSettings.Count;
|
|
for (; index < settingsCount; index++)
|
|
{
|
|
if (buildTargetName == globalSettings.platformOverrideSettings[index].buildTarget)
|
|
break;
|
|
}
|
|
|
|
rootBindingPath = "platformOverrideSettings.Array.data[" + index + "].";
|
|
|
|
|
|
InitializePage(settings, true);
|
|
}
|
|
|
|
void InitializePage(SerializedObject settings, bool isOverride)
|
|
{
|
|
VisualElement root;
|
|
|
|
if (isOverride)
|
|
{
|
|
SBSettingsSO globalSettings = SBSettingsSO.GlobalSettings;
|
|
Toggle enableOverride = new Toggle("Override Default Settings");
|
|
|
|
enableOverride.tooltip = "Use settings specific to this platform rather than the global defaults";
|
|
enableOverride.bindingPath = rootBindingPath + "overrideBuildTarget";
|
|
SetToggleStyle(enableOverride);
|
|
enableOverride.BindProperty(settings);
|
|
enableOverride.RegisterValueChangedCallback(OnOverrideToggled);
|
|
enableOverride.style.paddingBottom = 8;
|
|
|
|
style.flexGrow = 1;
|
|
style.flexDirection = FlexDirection.Column;
|
|
style.flexGrow = 1;
|
|
style.alignItems = Align.Stretch;
|
|
style.flexShrink = 1;
|
|
style.flexBasis = StyleKeyword.Auto;
|
|
|
|
toggleGroup = new VisualElement();
|
|
toggleGroup.SetEnabled(globalSettings.platformOverrideSettings[index].overrideBuildTarget);
|
|
|
|
Add(enableOverride);
|
|
Add(toggleGroup);
|
|
root = toggleGroup;
|
|
}
|
|
else
|
|
{
|
|
root = this;
|
|
}
|
|
|
|
root.style.flexGrow = 1;
|
|
root.style.flexDirection = FlexDirection.Column;
|
|
root.style.flexGrow = 1;
|
|
root.style.alignItems = Align.Stretch;
|
|
root.style.flexShrink = 1;
|
|
root.style.flexBasis = StyleKeyword.Auto;
|
|
|
|
Toggle highPIdx = new Toggle("Allow 32 bit index combined meshes");
|
|
highPIdx.bindingPath = rootBindingPath + "settings.allow32bitIdx";
|
|
highPIdx.tooltip = "Allow making combined meshes of 32-bit index buffer meshes. This sorts the 32 bit meshes into their own set combined meshes, so it should not cause issues";
|
|
SetToggleStyle(highPIdx);
|
|
highPIdx.BindProperty(settings);
|
|
|
|
IntegerField highPIdxCount = new IntegerField("Max vertices per 32-bit index combined mesh");
|
|
highPIdxCount.isDelayed = true;
|
|
highPIdxCount.tooltip = "The maximum number of vertices that can be in a 32-bit index buffer combined mesh. Since a 32-bit index buffer can represent trillions of vertices, its a good idea to arbitrarily put a cap on how large the combined mesh can be";
|
|
highPIdxCount.bindingPath = rootBindingPath + "settings.maxCombined32Idx";
|
|
SetToggleStyle(highPIdxCount);
|
|
highPIdxCount.BindProperty(settings);
|
|
highPIdxCount.RegisterValueChangedCallback((ChangeEvent<int> e) => { highPIdxCount.value = Math.Max( 0x10000, highPIdxCount.value); });
|
|
|
|
Foldout vertexSettings = new Foldout();
|
|
vertexSettings.text = "Vertex Attribute Format Settings";
|
|
VisualElement columnLabels = new VisualElement();
|
|
columnLabels.style.alignSelf = Align.Stretch;
|
|
columnLabels.style.flexGrow = 1;
|
|
columnLabels.style.flexDirection = FlexDirection.Row;
|
|
columnLabels.style.alignItems = Align.Center;
|
|
columnLabels.style.justifyContent = Justify.SpaceBetween;
|
|
columnLabels.style.flexShrink = 1;
|
|
columnLabels.style.flexBasis = StyleKeyword.Auto;
|
|
|
|
|
|
Label channelLabel = new Label("<b>Attribute</b>");
|
|
channelLabel.style.flexGrow =0.4f;
|
|
channelLabel.style.flexBasis = 0.4f;
|
|
channelLabel.style.flexShrink = 0.4f;
|
|
channelLabel.style.textOverflow = TextOverflow.Ellipsis;
|
|
channelLabel.style.overflow = Overflow.Hidden;
|
|
channelLabel.style.unityTextOverflowPosition = TextOverflowPosition.End;
|
|
channelLabel.tooltip = "Vertex Attribute";
|
|
|
|
Label altStreamLabel = new Label("<b>Secondary Stream</b>");
|
|
altStreamLabel.style.flexGrow = 0.6f;
|
|
altStreamLabel.style.flexBasis = 0.6f;
|
|
altStreamLabel.style.flexShrink = 0.6f;
|
|
altStreamLabel.style.textOverflow = TextOverflow.Ellipsis;
|
|
altStreamLabel.style.overflow = Overflow.Hidden;
|
|
altStreamLabel.style.unityTextOverflowPosition = TextOverflowPosition.End;
|
|
altStreamLabel.tooltip = "Split the vertex buffer and put the marked attributes in a secondary vertex stream. Useful for many tile-based mobile GPUs, you should put any attributes that do not affect the vertex position into the secondary stream";
|
|
|
|
Label maxPrecisionLabel = new Label("<b>Maximum Precision</b>");
|
|
maxPrecisionLabel.style.flexGrow = 1f;
|
|
maxPrecisionLabel.style.flexBasis = 1f;
|
|
maxPrecisionLabel.style.flexShrink = 1f;
|
|
maxPrecisionLabel.style.textOverflow = TextOverflow.Ellipsis;
|
|
maxPrecisionLabel.style.overflow = Overflow.Hidden;
|
|
maxPrecisionLabel.style.unityTextOverflowPosition = TextOverflowPosition.End;
|
|
|
|
|
|
columnLabels.Add(channelLabel);
|
|
columnLabels.Add(altStreamLabel);
|
|
columnLabels.Add(maxPrecisionLabel);
|
|
|
|
vertexSettings.Add(columnLabels);
|
|
|
|
// vertex channel compression
|
|
List<int> normTanFmtsInt = new List<int>() { (int)VtxFormats.Float32, (int)VtxFormats.Float16, (int)VtxFormats.SNorm8, 0};
|
|
VisualElement normField = VtxCompressionOption("Normal", settings, rootBindingPath, 1, normTanFmtsInt);
|
|
|
|
vertexSettings.contentContainer.Add(normField);
|
|
|
|
VisualElement tanField = VtxCompressionOption("Tangent", settings, rootBindingPath, 2, normTanFmtsInt);
|
|
vertexSettings.contentContainer.Add(tanField);
|
|
|
|
List<int> colorFmtsInt = new List<int>() { (int)VtxFormats.Float32, (int)VtxFormats.Float16, (int)VtxFormats.UNorm8, 0 };
|
|
VisualElement colorField = VtxCompressionOption("Color", settings, rootBindingPath, 3, colorFmtsInt);
|
|
|
|
vertexSettings.contentContainer.Add(colorField);
|
|
|
|
List<int> uvFmtsInt = new List<int>() { (int)VtxFormats.Float32, (int)VtxFormats.Float16, (int)VtxFormats.SNorm8, (int)VtxFormats.UNorm8, 0 };
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
VisualElement uvField = VtxCompressionOption("UV" + i, settings, rootBindingPath, i + 4, uvFmtsInt);
|
|
vertexSettings.contentContainer.Add(uvField);
|
|
}
|
|
|
|
|
|
Label NotImplHeader = new Label("\nNot Yet Implemented");
|
|
|
|
Toggle splitMultiMeshes = new Toggle("Split Multi-Material Renderers (DANGEROUS!)");
|
|
splitMultiMeshes.tooltip =
|
|
"Splits Renderers with multi-material meshes into several single material renderers " +
|
|
"parented to the original game object. This is slow, and will break scripts and animations " +
|
|
"that expect to be able to change the materials on or change the state of the whole mesh";
|
|
splitMultiMeshes.bindingPath = rootBindingPath + "settings.splitMultiMaterialMeshes";
|
|
splitMultiMeshes.SetEnabled(false);
|
|
SetToggleStyle(splitMultiMeshes);
|
|
splitMultiMeshes.BindProperty(settings);
|
|
|
|
|
|
|
|
root.Add(highPIdx);
|
|
root.Add(highPIdxCount);
|
|
root.Add(vertexSettings);
|
|
root.Add(NotImplHeader);
|
|
root.Add(splitMultiMeshes);
|
|
}
|
|
|
|
private void OnOverrideToggled(ChangeEvent<bool> evt)
|
|
{
|
|
toggleGroup.SetEnabled(evt.newValue);
|
|
}
|
|
|
|
private VisualElement VtxCompressionOption(string name, SerializedObject settings, string rootPath, int index, List<int> options)
|
|
{
|
|
VisualElement vtxOptions = new VisualElement();
|
|
|
|
vtxOptions.style.flexGrow = 1;
|
|
vtxOptions.style.flexDirection = FlexDirection.Row;
|
|
vtxOptions.style.flexGrow = 1;
|
|
vtxOptions.style.alignItems = Align.Stretch;
|
|
vtxOptions.style.flexShrink = 1;
|
|
vtxOptions.style.flexBasis = StyleKeyword.Auto;
|
|
|
|
Label label = new Label(name);
|
|
label.style.flexGrow = 0.4f;
|
|
label.style.flexBasis = 0.4f;
|
|
label.style.flexShrink = 0.4f;
|
|
label.style.textOverflow = TextOverflow.Ellipsis;
|
|
label.style.overflow = Overflow.Hidden;
|
|
label.style.unityTextOverflowPosition = TextOverflowPosition.End;
|
|
|
|
Toggle toggle = new Toggle();
|
|
toggle.bindingPath = rootPath + "settings.altStream.Array.data[" + index + "]";
|
|
toggle.BindProperty(settings);
|
|
toggle.style.flexGrow = 0.6f;
|
|
toggle.style.flexBasis = 0.6f;
|
|
toggle.style.flexShrink = 0.6f;
|
|
toggle.style.flexDirection = FlexDirection.Row;
|
|
|
|
PopupField<int> popup = new PopupField<int>();
|
|
popup.formatListItemCallback = (int b) => { return VtxFormatNames[b]; };
|
|
popup.formatSelectedValueCallback = (int b) => { return VtxFormatNames[b]; };
|
|
popup.choices = options;
|
|
popup.bindingPath = rootPath + "settings.serializedVtxFormats.Array.data[" + index + "]";
|
|
popup.BindProperty(settings);
|
|
popup.style.flexGrow = 1f;
|
|
popup.style.flexBasis = 1;
|
|
popup.style.flexShrink = 1f;
|
|
popup.style.flexDirection = FlexDirection.Row;
|
|
|
|
vtxOptions.Add(label);
|
|
vtxOptions.Add(toggle);
|
|
vtxOptions.Add(popup);
|
|
//popup.label = name;
|
|
|
|
return vtxOptions;
|
|
}
|
|
}
|
|
static void SetToggleStyle(VisualElement el)
|
|
{
|
|
el.style.alignItems = Align.Stretch;
|
|
el.style.justifyContent = Justify.FlexStart;
|
|
|
|
VisualElement label = el.ElementAt(0);
|
|
label.style.flexGrow = 1f;
|
|
label.style.flexBasis = 1f;
|
|
label.style.flexShrink = 1f;
|
|
label.style.textOverflow = TextOverflow.Ellipsis;
|
|
label.style.overflow = Overflow.Hidden;
|
|
label.style.unityTextOverflowPosition = TextOverflowPosition.End;
|
|
VisualElement checkmark = el.ElementAt(1);
|
|
checkmark.style.flexGrow = 1f;
|
|
checkmark.style.flexBasis = 1;
|
|
checkmark.style.flexShrink = 0.25f;
|
|
checkmark.style.flexDirection = FlexDirection.Row;
|
|
}
|
|
}
|
|
}
|