Skip to content

Commit

Permalink
Add com.varneon.v-udon.components
Browse files Browse the repository at this point in the history
  • Loading branch information
Varneon committed Aug 28, 2022
1 parent bec116f commit 43cd9d8
Show file tree
Hide file tree
Showing 20 changed files with 1,037 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@
!/Packages/com.varneon.v-udon.vehicles
!/Packages/com.varneon.v-udon.vehicles-lite
!/Packages/com.varneon.v-udon.tween
!/Packages/com.varneon.v-udon.array-extensions
!/Packages/com.varneon.v-udon.array-extensions
!/Packages/com.varneon.v-udon.components
8 changes: 8 additions & 0 deletions Packages/com.varneon.v-udon.components/Editor.meta

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,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UdonSharpEditor;
using UnityEditor.Callbacks;
using UnityEditor.Events;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using VRC.Udon;
using static UnityEngine.EventSystems.EventTrigger;

namespace Varneon.VUdon.Components.Editor
{
internal static class LayerMaskDropdownUpdater
{
[PostProcessScene(-1)] // Ensure that all of the dropdowns get processed before U# saves the C# component data into UdonBehaviours
private static void InitializeLayerMaskDropdowns()
{
foreach(LayerMaskDropdown dropdown in UnityEngine.Object.FindObjectsOfType<LayerMaskDropdown>())
{
UpdateLayerMaskDropdown(dropdown);
}
}

private static void UpdateLayerMaskDropdown(LayerMaskDropdown layerMaskDropdown)
{
List<int> layerIndices = new List<int>();

List<string> optionNames = new List<string>() { "Nothing", "Everything" };

for (int i = 0; i < 32; i++)
{
string name = LayerMask.LayerToName(i);

bool isDefined = !string.IsNullOrEmpty(name);

if (isDefined)
{
optionNames.Add(string.Format("{0}: {1}", i, name));

layerIndices.Add(i);
}
}

Dropdown dropdown = layerMaskDropdown.GetComponent<Dropdown>();

IEnumerable<FieldInfo> fields = typeof(LayerMaskDropdown).GetRuntimeFields();

FieldInfo layerCountField = fields.FirstOrDefault(f => f.Name == "projectLayerCount");

FieldInfo layersField = fields.FirstOrDefault(f => f.Name == "layers");

EventTrigger trigger = layerMaskDropdown.GetComponent<EventTrigger>();

layerCountField.SetValue(layerMaskDropdown, optionNames.Count - 2);

layersField.SetValue(layerMaskDropdown, layerIndices.ToArray());

dropdown.options = optionNames.Select(l => new Dropdown.OptionData(l)).ToList();

UdonBehaviour ub = UdonSharpEditorUtility.GetBackingUdonBehaviour(layerMaskDropdown);

MethodInfo sendCustomEventInfo = UnityEventBase.GetValidMethodInfo(ub, nameof(UdonBehaviour.SendCustomEvent), new[] { typeof(string) });

UnityAction<string> sendCustomEventDelegate = Delegate.CreateDelegate(typeof(UnityAction<string>), ub, sendCustomEventInfo, false) as UnityAction<string>;

UnityEventTools.AddStringPersistentListener(dropdown.onValueChanged, sendCustomEventDelegate, "OnValueChanged");

Entry pointerClickEntry = new Entry
{
eventID = EventTriggerType.PointerClick,
callback = new TriggerEvent()
};
UnityEventTools.AddStringPersistentListener(pointerClickEntry.callback, sendCustomEventDelegate, "OnClick");

Entry selectEntry = new Entry
{
eventID = EventTriggerType.Select,
callback = new TriggerEvent()
};
UnityEventTools.AddStringPersistentListener(selectEntry.callback, sendCustomEventDelegate, "OnSelect");

trigger.triggers.Add(pointerClickEntry);
trigger.triggers.Add(selectEntry);
}
}
}

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,22 @@
{
"name": "Varneon.V-Udon.Components.Editor",
"references": [
"Varneon.V-Udon.Components.Runtime",
"UdonSharp.Runtime",
"VRC.Udon",
"UdonSharp.Editor"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [
"UDONSHARP"
],
"versionDefines": [],
"noEngineReferences": false
}

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

8 changes: 8 additions & 0 deletions Packages/com.varneon.v-udon.components/Runtime.meta

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

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,159 @@
using UdonSharp;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using VRC.Udon;

namespace Varneon.VUdon.Components
{
[RequireComponent(typeof(Dropdown))]
[RequireComponent(typeof(EventTrigger))]
[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class LayerMaskDropdown : UdonSharpBehaviour
{
[SerializeField, HideInInspector]
private int projectLayerCount;

[SerializeField, HideInInspector]
private int[] layers;

[SerializeField]
private UdonBehaviour target;

[SerializeField]
private string variable;

private LayerMask mask;

private Dropdown cullingMaskDropdown;

private int maskInt;

private Toggle[] cullingMaskToggles;

private Text dropdownValueLabel;

private bool isOpen;

private void Start()
{
cullingMaskDropdown = GetComponent<Dropdown>();

dropdownValueLabel = cullingMaskDropdown.captionText;

maskInt = mask;

SetTargetVariable();

CheckMixedLayers();
}

private void SetTargetVariable()
{
if(target != null && !string.IsNullOrWhiteSpace(variable))

target.SetProgramVariable(variable, mask);
}

private void OpenCullingMaskMenu()
{
isOpen = true;

cullingMaskToggles = cullingMaskDropdown.GetComponentsInChildren<Toggle>(true);

for (int i = 0; i < projectLayerCount; i++)
{
cullingMaskToggles[i + 4].SetIsOnWithoutNotify((maskInt & (1 << layers[i])) != 0);
}
}

public void OnClick()
{
OpenCullingMaskMenu();
}

public void OnSelect()
{
if (isOpen) { UpdateCullingMask(); }
}

public void OnValueChanged()
{
UpdateCullingMask();
}

private void UpdateCullingMask()
{
int selectedLayerOption = cullingMaskDropdown.value;

switch (selectedLayerOption)
{
case 0: // Nothing
maskInt = 0;
break;
case 1: // Everything
maskInt = -1;
break;
default:
int mask = 1 << layers[selectedLayerOption - 2]; // Create bitmask of the layer that was clicked

if (isOpen)
{
if ((maskInt & mask) != 0) // If same bit is set on both the culling mask and the selection mask
{
maskInt &= ~mask; // Reset the bit
}
else
{
maskInt |= mask; // Set the bit
}
}

CheckMixedLayers();
break;
}

mask = maskInt;

SetTargetVariable();

isOpen = false;
}

private void CheckMixedLayers()
{
int layerCount = 0;

int optionIndex = 0;

for (int i = 0; i < projectLayerCount; i++)
{
if ((maskInt & (1 << layers[i])) != 0)
{
optionIndex = i;

layerCount += 1;
}
}

if (layerCount == projectLayerCount)
{
maskInt = -1;

cullingMaskDropdown.SetValueWithoutNotify(1);
}
else if (layerCount > 1) // If multiple layers are selected, set the preview label as "Mixed..."
{
dropdownValueLabel.text = "Mixed...";
}
else if (layerCount == 1) // If only one layer is selected, override the dropdown with the remaining layer
{
cullingMaskDropdown.SetValueWithoutNotify(optionIndex + 2);
}
else if (layerCount == 0) // If no layers have been selected, override the dropdown to Nothing / 0
{
cullingMaskDropdown.SetValueWithoutNotify(0);
}
}
}
}

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

Loading

0 comments on commit 43cd9d8

Please sign in to comment.