mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-01 13:59:22 +00:00
Merge remote-tracking branch 'CVRGizmos/main'
Merge CVRGizmos
This commit is contained in:
commit
58a6f1a7b2
30 changed files with 2159 additions and 1 deletions
58
CVRGizmos/CVRGizmoManager.cs
Normal file
58
CVRGizmos/CVRGizmoManager.cs
Normal file
|
@ -0,0 +1,58 @@
|
|||
using CVRGizmos.GismoTypes;
|
||||
using Gizmos = Popcron.Gizmos;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CVRGizmos
|
||||
{
|
||||
public class CVRGizmoManager : MonoBehaviour
|
||||
{
|
||||
public static CVRGizmoManager Instance;
|
||||
|
||||
public bool g_enabled = false;
|
||||
public bool g_localOnly = false;
|
||||
|
||||
public MonoBehaviour[] managed;
|
||||
|
||||
public System.Type[] GizmoTypes = {
|
||||
typeof(CVRGizmos_Pointer),
|
||||
typeof(CVRGizmos_AdvancedAvatarSettingsTrigger),
|
||||
typeof(CVRGizmos_SpawnableTrigger),
|
||||
typeof(CVRGizmos_AdvancedAvatarSettingsPointer),
|
||||
typeof(CVRGizmos_DistanceLod),
|
||||
typeof(CVRGizmos_HapticZone),
|
||||
typeof(CVRGizmos_HapticAreaChest),
|
||||
typeof(CVRGizmos_ToggleStateTrigger),
|
||||
typeof(CVRGizmos_Avatar),
|
||||
typeof(CVRGizmos_AvatarPickupMarker),
|
||||
typeof(CVRGizmos_DistanceConstrain),
|
||||
};
|
||||
|
||||
void Start()
|
||||
{
|
||||
CVRGizmoManager.Instance = this;
|
||||
managed = new MonoBehaviour[GizmoTypes.Count()];
|
||||
for (int i = 0; i < GizmoTypes.Count(); i++)
|
||||
{
|
||||
managed[i] = gameObject.AddComponent(GizmoTypes[i]) as MonoBehaviour;
|
||||
}
|
||||
}
|
||||
|
||||
public void EnableGizmos(bool able)
|
||||
{
|
||||
for (int i = 0; i < GizmoTypes.Count(); i++)
|
||||
{
|
||||
managed[i].enabled = able;
|
||||
Gizmos.Enabled = able;
|
||||
}
|
||||
RefreshGizmos();
|
||||
}
|
||||
|
||||
public void RefreshGizmos()
|
||||
{
|
||||
for (int i = 0; i < GizmoTypes.Count(); i++)
|
||||
{
|
||||
managed[i].Invoke("CacheGizmos", 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
31
CVRGizmos/CVRGizmos.csproj
Normal file
31
CVRGizmos/CVRGizmos.csproj
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\MelonLoader\0Harmony.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MelonLoader">
|
||||
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\MelonLoader\MelonLoader.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="Deploy" AfterTargets="Build">
|
||||
<Copy SourceFiles="$(TargetPath)" DestinationFolder="C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\Mods\" />
|
||||
<Message Text="Copied $(TargetPath) to C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\Mods\" Importance="high" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
25
CVRGizmos/CVRGizmos.sln
Normal file
25
CVRGizmos/CVRGizmos.sln
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.2.32630.192
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CVRGizmos", "CVRGizmos.csproj", "{5465736B-DE27-4413-A374-1834FDE7DB0D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{5465736B-DE27-4413-A374-1834FDE7DB0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5465736B-DE27-4413-A374-1834FDE7DB0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5465736B-DE27-4413-A374-1834FDE7DB0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5465736B-DE27-4413-A374-1834FDE7DB0D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C0002BEC-CB43-4733-9961-C9CDDB3AC4EA}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
49
CVRGizmos/GizmoTypes/CVRAdvancedAvatarSettingsPointer.cs
Normal file
49
CVRGizmos/GizmoTypes/CVRAdvancedAvatarSettingsPointer.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
using ABI.CCK.Components;
|
||||
using UnityEngine;
|
||||
using Gizmos = Popcron.Gizmos;
|
||||
|
||||
/**
|
||||
|
||||
CVRAdvancedAvatarSettingsPointer shouldn't really be used at this point. Only including because it still exists in the CCK/Game.
|
||||
|
||||
**/
|
||||
|
||||
namespace CVRGizmos.GismoTypes
|
||||
{
|
||||
public class CVRGizmos_AdvancedAvatarSettingsPointer : CVRGizmoBase
|
||||
{
|
||||
public static CVRAdvancedAvatarSettingsPointer[] references;
|
||||
|
||||
public override void CacheGizmos()
|
||||
{
|
||||
var found = Resources.FindObjectsOfTypeAll(typeof(CVRAdvancedAvatarSettingsPointer)) as CVRAdvancedAvatarSettingsPointer[];
|
||||
|
||||
if (CVRGizmoManager.Instance.g_localOnly)
|
||||
{
|
||||
references = Array.ConvertAll(GetLocalOnly(found), item => (CVRAdvancedAvatarSettingsPointer)item);
|
||||
}
|
||||
else
|
||||
{
|
||||
references = found;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawGizmos()
|
||||
{
|
||||
for (int i = 0; i < references.Count(); i++)
|
||||
{
|
||||
if (references[i] == null)
|
||||
{
|
||||
CacheGizmos();
|
||||
break;
|
||||
}
|
||||
if (references[i].isActiveAndEnabled)
|
||||
{
|
||||
Gizmos.Color = Color.cyan;
|
||||
Gizmos.Matrix = Matrix4x4.TRS(references[i].transform.position, references[i].transform.rotation, references[i].transform.lossyScale);
|
||||
Gizmos.Sphere(Vector3.zero, 0.015f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
113
CVRGizmos/GizmoTypes/CVRAdvancedAvatarSettingsTrigger.cs
Normal file
113
CVRGizmos/GizmoTypes/CVRAdvancedAvatarSettingsTrigger.cs
Normal file
|
@ -0,0 +1,113 @@
|
|||
using ABI.CCK.Components;
|
||||
using ABI_RC.Core.Player;
|
||||
using UnityEngine;
|
||||
using Gizmos = Popcron.Gizmos;
|
||||
|
||||
namespace CVRGizmos.GismoTypes
|
||||
{
|
||||
public class CVRGizmos_AdvancedAvatarSettingsTrigger : CVRGizmoBase
|
||||
{
|
||||
public static CVRAdvancedAvatarSettingsTrigger[] references;
|
||||
|
||||
public override void CacheGizmos()
|
||||
{
|
||||
var found = Resources.FindObjectsOfTypeAll(typeof(CVRAdvancedAvatarSettingsTrigger)) as CVRAdvancedAvatarSettingsTrigger[];
|
||||
|
||||
if (CVRGizmoManager.Instance.g_localOnly)
|
||||
{
|
||||
references = Array.ConvertAll(GetLocalOnly(found), item => (CVRAdvancedAvatarSettingsTrigger)item);
|
||||
}
|
||||
else
|
||||
{
|
||||
references = found;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawGizmos()
|
||||
{
|
||||
for (int i = 0; i < references.Count(); i++)
|
||||
{
|
||||
if (references[i] == null)
|
||||
{
|
||||
CacheGizmos();
|
||||
break;
|
||||
}
|
||||
if (references[i].isActiveAndEnabled)
|
||||
{
|
||||
Gizmos.Color = Color.cyan;
|
||||
Gizmos.Matrix = Matrix4x4.TRS(references[i].transform.position, references[i].transform.rotation, references[i].transform.lossyScale);
|
||||
Gizmos.Cube(references[i].areaOffset, Quaternion.identity, references[i].areaSize);
|
||||
if (references[i].stayTasks.Count > 0)
|
||||
{
|
||||
for (int ii = 0; ii < references[i].stayTasks.Count(); ii++)
|
||||
{
|
||||
var stayTask = references[i].stayTasks[ii];
|
||||
float num = PlayerSetup.Instance.GetAnimatorParam(stayTask.settingName);
|
||||
switch (stayTask.updateMethod)
|
||||
{
|
||||
case CVRAdvancedAvatarSettingsTriggerTaskStay.UpdateMethod.SetFromPosition:
|
||||
{
|
||||
num = Mathf.InverseLerp(stayTask.minValue, stayTask.maxValue, num);
|
||||
Gizmos.Color = new Color(2.0f * num, 2.0f * (1 - num), 0);
|
||||
break;
|
||||
}
|
||||
case CVRAdvancedAvatarSettingsTriggerTaskStay.UpdateMethod.Add:
|
||||
num = num + stayTask.minValue / 60f;
|
||||
Gizmos.Color = new Color(2.0f * num, 2.0f * (1 - num), 0);
|
||||
break;
|
||||
case CVRAdvancedAvatarSettingsTriggerTaskStay.UpdateMethod.Subtract:
|
||||
num = num - stayTask.minValue / 60f;
|
||||
Gizmos.Color = new Color(2.0f * num, 2.0f * (1 - num), 0);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
Vector3 vector = new Vector3(references[i].areaSize.x * 0.5f, references[i].areaSize.y * 0.5f, references[i].areaSize.z * 0.5f);
|
||||
switch (references[i].sampleDirection)
|
||||
{
|
||||
case CVRAdvancedAvatarSettingsTrigger.SampleDirection.XPositive:
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(vector.x, 0f, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, -vector.y, vector.z) + references[i].areaOffset, new Vector3(vector.x, 0f, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(vector.x, vector.y, 0f) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, -vector.z) + references[i].areaOffset, new Vector3(vector.x, vector.y, 0f) + references[i].areaOffset);
|
||||
break;
|
||||
case CVRAdvancedAvatarSettingsTrigger.SampleDirection.XNegative:
|
||||
Gizmos.Line(new Vector3(vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, 0f, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, -vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, 0f, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, vector.y, 0f) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, vector.y, -vector.z) + references[i].areaOffset, new Vector3(-vector.x, vector.y, 0f) + references[i].areaOffset);
|
||||
break;
|
||||
case CVRAdvancedAvatarSettingsTrigger.SampleDirection.YPositive:
|
||||
Gizmos.Line(new Vector3(-vector.x, -vector.y, vector.z) + references[i].areaOffset, new Vector3(0f, vector.y, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, -vector.y, vector.z) + references[i].areaOffset, new Vector3(0f, vector.y, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, -vector.y, -vector.z) + references[i].areaOffset, new Vector3(-vector.x, vector.y, 0f) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, -vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, vector.y, 0f) + references[i].areaOffset);
|
||||
break;
|
||||
case CVRAdvancedAvatarSettingsTrigger.SampleDirection.YNegative:
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(0f, -vector.y, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(0f, -vector.y, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, -vector.z) + references[i].areaOffset, new Vector3(-vector.x, -vector.y, 0f) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, -vector.y, 0f) + references[i].areaOffset);
|
||||
break;
|
||||
case CVRAdvancedAvatarSettingsTrigger.SampleDirection.ZPositive:
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, -vector.z) + references[i].areaOffset, new Vector3(0f, vector.y, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, vector.y, -vector.z) + references[i].areaOffset, new Vector3(0f, vector.y, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, -vector.z) + references[i].areaOffset, new Vector3(-vector.x, 0f, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, -vector.y, -vector.z) + references[i].areaOffset, new Vector3(-vector.x, 0f, vector.z) + references[i].areaOffset);
|
||||
break;
|
||||
case CVRAdvancedAvatarSettingsTrigger.SampleDirection.ZNegative:
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(0f, vector.y, -vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(0f, vector.y, -vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, 0f, -vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, -vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, 0f, -vector.z) + references[i].areaOffset);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
50
CVRGizmos/GizmoTypes/CVRAvatar.cs
Normal file
50
CVRGizmos/GizmoTypes/CVRAvatar.cs
Normal file
|
@ -0,0 +1,50 @@
|
|||
using ABI.CCK.Components;
|
||||
using UnityEngine;
|
||||
using Gizmos = Popcron.Gizmos;
|
||||
|
||||
namespace CVRGizmos.GismoTypes
|
||||
{
|
||||
public class CVRGizmos_Avatar : CVRGizmoBase
|
||||
{
|
||||
public static CVRAvatar[] references;
|
||||
|
||||
public override void CacheGizmos()
|
||||
{
|
||||
var found = Resources.FindObjectsOfTypeAll(typeof(CVRAvatar)) as CVRAvatar[];
|
||||
|
||||
if (CVRGizmoManager.Instance.g_localOnly)
|
||||
{
|
||||
references = Array.ConvertAll(GetLocalOnly(found), item => (CVRAvatar)item);
|
||||
}
|
||||
else
|
||||
{
|
||||
references = found;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawGizmos()
|
||||
{
|
||||
for (int i = 0; i < references.Count(); i++)
|
||||
{
|
||||
if (references[i] == null)
|
||||
{
|
||||
CacheGizmos();
|
||||
break;
|
||||
}
|
||||
if (references[i].isActiveAndEnabled)
|
||||
{
|
||||
//viewPosition & voicePosition seem to be rounded... not good, may be why viewpoint drift is bad on scale
|
||||
Gizmos.Color = Color.green;
|
||||
Gizmos.Matrix = Matrix4x4.TRS(references[i].transform.position, references[i].transform.rotation, references[i].transform.localScale);
|
||||
Gizmos.Sphere(references[i].viewPosition, 0.01f);
|
||||
Gizmos.Line(references[i].viewPosition, references[i].viewPosition + Vector3.forward * 0.05f);
|
||||
Gizmos.Line(references[i].viewPosition, references[i].viewPosition + Vector3.right * 0.05f);
|
||||
Gizmos.Color = Color.red;
|
||||
Gizmos.Sphere(references[i].voicePosition, 0.01f);
|
||||
Gizmos.Line(references[i].voicePosition, references[i].voicePosition + Vector3.forward * 0.05f);
|
||||
Gizmos.Line(references[i].voicePosition, references[i].voicePosition + Vector3.right * 0.05f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
51
CVRGizmos/GizmoTypes/CVRAvatarPickupMarker.cs
Normal file
51
CVRGizmos/GizmoTypes/CVRAvatarPickupMarker.cs
Normal file
|
@ -0,0 +1,51 @@
|
|||
using ABI.CCK.Components;
|
||||
using UnityEngine;
|
||||
using Gizmos = Popcron.Gizmos;
|
||||
|
||||
namespace CVRGizmos.GismoTypes
|
||||
{
|
||||
public class CVRGizmos_AvatarPickupMarker : CVRGizmoBase
|
||||
{
|
||||
public static CVRAvatarPickupMarker[] references;
|
||||
|
||||
public override void CacheGizmos()
|
||||
{
|
||||
var found = Resources.FindObjectsOfTypeAll(typeof(CVRAvatarPickupMarker)) as CVRAvatarPickupMarker[];
|
||||
|
||||
if (CVRGizmoManager.Instance.g_localOnly)
|
||||
{
|
||||
references = Array.ConvertAll(GetLocalOnly(found), item => (CVRAvatarPickupMarker)item);
|
||||
}
|
||||
else
|
||||
{
|
||||
references = found;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawGizmos()
|
||||
{
|
||||
for (int i = 0; i < references.Count(); i++)
|
||||
{
|
||||
if (references[i] == null)
|
||||
{
|
||||
CacheGizmos();
|
||||
break;
|
||||
}
|
||||
if (references[i].isActiveAndEnabled)
|
||||
{
|
||||
Gizmos.Color = Color.magenta;
|
||||
Gizmos.Matrix = Matrix4x4.TRS(references[i].transform.position, references[i].transform.rotation, references[i].transform.lossyScale);
|
||||
Gizmos.Cube(new Vector3(0f, 0.75f, 0f), Quaternion.identity, new Vector3(1f, 1.5f, 0f));
|
||||
Gizmos.Cube(new Vector3(0f, 0.7f, 0f), Quaternion.identity, new Vector3(0.8f, 0.1f, 0f));
|
||||
Gizmos.Cube(new Vector3(0f, 0.615f, 0f), Quaternion.identity, new Vector3(0.6f, 0.07f, 0f));
|
||||
Gizmos.Cube(new Vector3(0.24f, 0.28f, 0f), Quaternion.identity, new Vector3(0.32f, 0.42f, 0f));
|
||||
Gizmos.Cube(new Vector3(-0.24f, 0.28f, 0f), Quaternion.identity, new Vector3(0.32f, 0.42f, 0f));
|
||||
Vector3 lossyScale = references[i].transform.lossyScale;
|
||||
lossyScale.Scale(new Vector3(1f, 1f, 0f));
|
||||
Gizmos.Matrix = Matrix4x4.TRS(references[i].transform.position, references[i].transform.rotation, lossyScale);
|
||||
Gizmos.Sphere(new Vector3(0f, 1.11f, 0f), 0.31f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
79
CVRGizmos/GizmoTypes/CVRDistanceConstrain.cs
Normal file
79
CVRGizmos/GizmoTypes/CVRDistanceConstrain.cs
Normal file
|
@ -0,0 +1,79 @@
|
|||
using ABI.CCK.Components;
|
||||
using UnityEngine;
|
||||
using Gizmos = Popcron.Gizmos;
|
||||
|
||||
namespace CVRGizmos.GismoTypes
|
||||
{
|
||||
public class CVRGizmos_DistanceConstrain : CVRGizmoBase
|
||||
{
|
||||
public static CVRDistanceConstrain[] references;
|
||||
|
||||
public override void CacheGizmos()
|
||||
{
|
||||
var found = Resources.FindObjectsOfTypeAll(typeof(CVRDistanceConstrain)) as CVRDistanceConstrain[];
|
||||
|
||||
if (CVRGizmoManager.Instance.g_localOnly)
|
||||
{
|
||||
references = Array.ConvertAll(GetLocalOnly(found), item => (CVRDistanceConstrain)item);
|
||||
}
|
||||
else
|
||||
{
|
||||
references = found;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawGizmos()
|
||||
{
|
||||
for (int i = 0; i < references.Count(); i++)
|
||||
{
|
||||
if (references[i] == null)
|
||||
{
|
||||
CacheGizmos();
|
||||
break;
|
||||
}
|
||||
if (references[i].target == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (references[i].maxDistance < references[i].minDistance && references[i].maxDistance != 0f)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Vector3 normalized = (references[i].transform.position - references[i].target.position).normalized;
|
||||
|
||||
//BUG: Matrix addition isn't reset, other gizmo types Matrix will persist.
|
||||
//This gizmo type could be a bit fucked, but I don't have the time to test.
|
||||
Gizmos.Matrix = Matrix4x4.identity;
|
||||
|
||||
if (references[i].minDistance == 0f)
|
||||
{
|
||||
if (references[i].maxDistance == 0f)
|
||||
{
|
||||
Gizmos.Color = Color.green;
|
||||
Gizmos.Line(references[i].target.position, normalized * 9999f);
|
||||
break;
|
||||
}
|
||||
Gizmos.Color = Color.green;
|
||||
Gizmos.Line(references[i].target.position, references[i].target.position + normalized * references[i].maxDistance);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (references[i].maxDistance == 0f)
|
||||
{
|
||||
Gizmos.Color = Color.red;
|
||||
Gizmos.Line(references[i].target.position, references[i].target.position + normalized * references[i].minDistance);
|
||||
Gizmos.Color = Color.green;
|
||||
Gizmos.Line(references[i].target.position + normalized * references[i].minDistance, normalized * 9999f);
|
||||
break;
|
||||
}
|
||||
Gizmos.Color = Color.red;
|
||||
Gizmos.Line(references[i].target.position, references[i].target.position + normalized * references[i].minDistance);
|
||||
Gizmos.Color = Color.green;
|
||||
Gizmos.Line(references[i].target.position + normalized * references[i].minDistance, references[i].target.position + normalized * references[i].maxDistance);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
62
CVRGizmos/GizmoTypes/CVRDistanceLod.cs
Normal file
62
CVRGizmos/GizmoTypes/CVRDistanceLod.cs
Normal file
|
@ -0,0 +1,62 @@
|
|||
using ABI.CCK.Components;
|
||||
using UnityEngine;
|
||||
using Gizmos = Popcron.Gizmos;
|
||||
|
||||
namespace CVRGizmos.GismoTypes
|
||||
{
|
||||
public class CVRGizmos_DistanceLod : CVRGizmoBase
|
||||
{
|
||||
public static CVRDistanceLod[] references;
|
||||
|
||||
private static Color[] _gizmoColors = new Color[]
|
||||
{
|
||||
Color.green,
|
||||
Color.yellow,
|
||||
Color.red,
|
||||
Color.white
|
||||
};
|
||||
|
||||
public override void CacheGizmos()
|
||||
{
|
||||
var found = Resources.FindObjectsOfTypeAll(typeof(CVRDistanceLod)) as CVRDistanceLod[];
|
||||
|
||||
if (CVRGizmoManager.Instance.g_localOnly)
|
||||
{
|
||||
references = Array.ConvertAll(GetLocalOnly(found), item => (CVRDistanceLod)item);
|
||||
}
|
||||
else
|
||||
{
|
||||
references = found;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawGizmos()
|
||||
{
|
||||
for (int i = 0; i < references.Count(); i++)
|
||||
{
|
||||
if (references[i] == null)
|
||||
{
|
||||
CacheGizmos();
|
||||
break;
|
||||
}
|
||||
if (!references[i].distance3D)
|
||||
{
|
||||
Gizmos.Matrix = Matrix4x4.TRS(references[i].transform.position, Quaternion.identity, new Vector3(1f, 0f, 1f));
|
||||
}
|
||||
else
|
||||
{
|
||||
Gizmos.Matrix = Matrix4x4.TRS(references[i].transform.position, Quaternion.identity, Vector3.one);
|
||||
}
|
||||
float num = 0;
|
||||
foreach (CVRDistanceLodGroup cvrdistanceLodGroup in references[i].Groups)
|
||||
{
|
||||
//Gizmos.Color = _gizmoColors[Math.Min(num, 3)];
|
||||
num = Mathf.InverseLerp(0, references[i].Groups.Count, num);
|
||||
Gizmos.Color = new Color(2.0f * num, 2.0f * (1 - num), 0);
|
||||
Gizmos.Sphere(Vector3.zero, cvrdistanceLodGroup.MaxDistance);
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
CVRGizmos/GizmoTypes/CVRGizmoBase.cs
Normal file
37
CVRGizmos/GizmoTypes/CVRGizmoBase.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace CVRGizmos.GismoTypes
|
||||
{
|
||||
public class CVRGizmoBase : MonoBehaviour
|
||||
{
|
||||
public MonoBehaviour[] GetLocalOnly(MonoBehaviour[] input)
|
||||
{
|
||||
return input.Where(c => c.gameObject.scene.name == "DontDestroyOnLoad").ToArray();
|
||||
}
|
||||
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
CacheGizmos();
|
||||
// register the callback when enabling object
|
||||
Camera.onPreRender += RenderGizmos;
|
||||
}
|
||||
public virtual void OnDisable()
|
||||
{
|
||||
// remove the callback when disabling object
|
||||
Camera.onPreRender -= RenderGizmos;
|
||||
}
|
||||
|
||||
public virtual void RenderGizmos(Camera cam)
|
||||
{
|
||||
DrawGizmos();
|
||||
}
|
||||
|
||||
public virtual void CacheGizmos()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void DrawGizmos()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
53
CVRGizmos/GizmoTypes/CVRHapticAreaChest.cs
Normal file
53
CVRGizmos/GizmoTypes/CVRHapticAreaChest.cs
Normal file
|
@ -0,0 +1,53 @@
|
|||
using ABI.CCK.Components;
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
using Gizmos = Popcron.Gizmos;
|
||||
|
||||
namespace CVRGizmos.GismoTypes
|
||||
{
|
||||
public class CVRGizmos_HapticAreaChest : CVRGizmoBase
|
||||
{
|
||||
public static CVRHapticAreaChest[] references;
|
||||
|
||||
public override void CacheGizmos()
|
||||
{
|
||||
var found = Resources.FindObjectsOfTypeAll(typeof(CVRHapticAreaChest)) as CVRHapticAreaChest[];
|
||||
|
||||
if (CVRGizmoManager.Instance.g_localOnly)
|
||||
{
|
||||
references = Array.ConvertAll(GetLocalOnly(found), item => (CVRHapticAreaChest)item);
|
||||
}
|
||||
else
|
||||
{
|
||||
references = found;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawGizmos()
|
||||
{
|
||||
for (int i = 0; i < references.Count(); i++)
|
||||
{
|
||||
if (references[i] == null)
|
||||
{
|
||||
CacheGizmos();
|
||||
break;
|
||||
}
|
||||
if (references[i].isActiveAndEnabled)
|
||||
{
|
||||
Gizmos.Color = Color.yellow;
|
||||
Gizmos.Matrix = Matrix4x4.TRS(references[i].transform.position, references[i].transform.rotation, references[i].transform.lossyScale);
|
||||
Gizmos.Cube(Vector3.zero, Quaternion.identity, references[i].chestAreaSize);
|
||||
int num = 0;
|
||||
foreach (Vector3 center in references[i].HapticPoints40)
|
||||
{
|
||||
float[] pointValues = Traverse.Create(references[i]).Field("pointValues").GetValue() as float[];
|
||||
center.Scale(references[i].chestAreaSize * 0.5f);
|
||||
Gizmos.Color = new Color(1f - pointValues[num], pointValues[num], 0f);
|
||||
Gizmos.Cube(center, Quaternion.identity, new Vector3(0.01f, 0.01f, 0.01f));
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
CVRGizmos/GizmoTypes/CVRHapticZone.cs
Normal file
45
CVRGizmos/GizmoTypes/CVRHapticZone.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
using ABI.CCK.Components;
|
||||
using UnityEngine;
|
||||
using Gizmos = Popcron.Gizmos;
|
||||
|
||||
namespace CVRGizmos.GismoTypes
|
||||
{
|
||||
public class CVRGizmos_HapticZone : CVRGizmoBase
|
||||
{
|
||||
public static CVRHapticZone[] references;
|
||||
|
||||
public override void CacheGizmos()
|
||||
{
|
||||
var found = Resources.FindObjectsOfTypeAll(typeof(CVRHapticZone)) as CVRHapticZone[];
|
||||
|
||||
if (CVRGizmoManager.Instance.g_localOnly)
|
||||
{
|
||||
references = Array.ConvertAll(GetLocalOnly(found), item => (CVRHapticZone)item);
|
||||
}
|
||||
else
|
||||
{
|
||||
references = found;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawGizmos()
|
||||
{
|
||||
for (int i = 0; i < references.Count(); i++)
|
||||
{
|
||||
if (references[i] == null)
|
||||
{
|
||||
CacheGizmos();
|
||||
break;
|
||||
}
|
||||
Gizmos.Color = Color.yellow;
|
||||
Gizmos.Matrix = Matrix4x4.TRS(references[i].transform.position, references[i].transform.rotation, references[i].transform.lossyScale);
|
||||
if (references[i].triggerForm == CVRHapticZone.TriggerForm.Box)
|
||||
{
|
||||
Gizmos.Cube(references[i].center, Quaternion.identity, references[i].bounds);
|
||||
return;
|
||||
}
|
||||
Gizmos.Sphere(references[i].center, references[i].bounds.x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
44
CVRGizmos/GizmoTypes/CVRPointer.cs
Normal file
44
CVRGizmos/GizmoTypes/CVRPointer.cs
Normal file
|
@ -0,0 +1,44 @@
|
|||
using ABI.CCK.Components;
|
||||
using UnityEngine;
|
||||
using Gizmos = Popcron.Gizmos;
|
||||
|
||||
namespace CVRGizmos.GismoTypes
|
||||
{
|
||||
public class CVRGizmos_Pointer : CVRGizmoBase
|
||||
{
|
||||
public static CVRPointer[] references;
|
||||
|
||||
public override void CacheGizmos()
|
||||
{
|
||||
var found = Resources.FindObjectsOfTypeAll(typeof(CVRPointer)) as CVRPointer[];
|
||||
|
||||
if (CVRGizmoManager.Instance.g_localOnly)
|
||||
{
|
||||
references = Array.ConvertAll(GetLocalOnly(found), item => (CVRPointer)item);
|
||||
}
|
||||
else
|
||||
{
|
||||
references = found;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawGizmos()
|
||||
{
|
||||
for (int i = 0; i < references.Count(); i++)
|
||||
{
|
||||
if (references[i] == null)
|
||||
{
|
||||
CacheGizmos();
|
||||
break;
|
||||
}
|
||||
if (references[i].isActiveAndEnabled)
|
||||
{
|
||||
Gizmos.Color = Color.blue;
|
||||
Vector3 lossyScale = references[i].transform.lossyScale;
|
||||
Gizmos.Matrix = Matrix4x4.TRS(references[i].transform.position, references[i].transform.rotation, lossyScale);
|
||||
Gizmos.Sphere(Vector3.zero, 0.00125f / Mathf.Max(Mathf.Max(lossyScale.x, lossyScale.y), lossyScale.z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
127
CVRGizmos/GizmoTypes/CVRSpawnableTrigger.cs
Normal file
127
CVRGizmos/GizmoTypes/CVRSpawnableTrigger.cs
Normal file
|
@ -0,0 +1,127 @@
|
|||
using ABI.CCK.Components;
|
||||
using UnityEngine;
|
||||
using Gizmos = Popcron.Gizmos;
|
||||
|
||||
/**
|
||||
|
||||
CVRSpawnableTrigger **can** be local using CVROfflinePreview or similar mods.
|
||||
|
||||
**/
|
||||
|
||||
namespace CVRGizmos.GismoTypes
|
||||
{
|
||||
public class CVRGizmos_SpawnableTrigger : CVRGizmoBase
|
||||
{
|
||||
public static CVRSpawnableTrigger[] references;
|
||||
|
||||
public override void CacheGizmos()
|
||||
{
|
||||
var found = Resources.FindObjectsOfTypeAll(typeof(CVRSpawnableTrigger)) as CVRSpawnableTrigger[];
|
||||
|
||||
if (CVRGizmoManager.Instance.g_localOnly)
|
||||
{
|
||||
references = Array.ConvertAll(GetLocalOnly(found), item => (CVRSpawnableTrigger)item);
|
||||
}
|
||||
else
|
||||
{
|
||||
references = found;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawGizmos()
|
||||
{
|
||||
for (int i = 0; i < references.Count(); i++)
|
||||
{
|
||||
if (references[i] == null)
|
||||
{
|
||||
CacheGizmos();
|
||||
break;
|
||||
}
|
||||
if (references[i].isActiveAndEnabled)
|
||||
{
|
||||
|
||||
Gizmos.Color = Color.blue;
|
||||
Gizmos.Matrix = Matrix4x4.TRS(references[i].transform.position, references[i].transform.rotation, references[i].transform.lossyScale);
|
||||
|
||||
Gizmos.Cube(references[i].areaOffset, Quaternion.identity, references[i].areaSize);
|
||||
|
||||
//stayTask colors
|
||||
if (references[i].stayTasks.Count > 0)
|
||||
{
|
||||
for (int ii = 0; ii < references[i].stayTasks.Count(); ii++)
|
||||
{
|
||||
var stayTask = references[i].stayTasks[ii];
|
||||
if (stayTask.spawnable != null)
|
||||
{
|
||||
float num = stayTask.spawnable.GetValue(stayTask.settingIndex);
|
||||
switch (stayTask.updateMethod)
|
||||
{
|
||||
case CVRSpawnableTriggerTaskStay.UpdateMethod.SetFromPosition:
|
||||
{
|
||||
num = Mathf.InverseLerp(stayTask.minValue, stayTask.maxValue, num);
|
||||
Gizmos.Color = new Color(2.0f * num, 2.0f * (1 - num), 0);
|
||||
break;
|
||||
}
|
||||
case CVRSpawnableTriggerTaskStay.UpdateMethod.Add:
|
||||
num = num + stayTask.minValue / 60f;
|
||||
Gizmos.Color = new Color(2.0f * num, 2.0f * (1 - num), 0);
|
||||
break;
|
||||
case CVRSpawnableTriggerTaskStay.UpdateMethod.Subtract:
|
||||
num = num - stayTask.minValue / 60f;
|
||||
Gizmos.Color = new Color(2.0f * num, 2.0f * (1 - num), 0);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 vector = new Vector3(references[i].areaSize.x * 0.5f, references[i].areaSize.y * 0.5f, references[i].areaSize.z * 0.5f);
|
||||
switch (references[i].sampleDirection)
|
||||
{
|
||||
case CVRSpawnableTrigger.SampleDirection.XPositive:
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(vector.x, 0f, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, -vector.y, vector.z) + references[i].areaOffset, new Vector3(vector.x, 0f, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(vector.x, vector.y, 0f) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, -vector.z) + references[i].areaOffset, new Vector3(vector.x, vector.y, 0f) + references[i].areaOffset);
|
||||
break;
|
||||
case CVRSpawnableTrigger.SampleDirection.XNegative:
|
||||
Gizmos.Line(new Vector3(vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, 0f, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, -vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, 0f, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, vector.y, 0f) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, vector.y, -vector.z) + references[i].areaOffset, new Vector3(-vector.x, vector.y, 0f) + references[i].areaOffset);
|
||||
break;
|
||||
case CVRSpawnableTrigger.SampleDirection.YPositive:
|
||||
Gizmos.Line(new Vector3(-vector.x, -vector.y, vector.z) + references[i].areaOffset, new Vector3(0f, vector.y, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, -vector.y, vector.z) + references[i].areaOffset, new Vector3(0f, vector.y, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, -vector.y, -vector.z) + references[i].areaOffset, new Vector3(-vector.x, vector.y, 0f) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, -vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, vector.y, 0f) + references[i].areaOffset);
|
||||
break;
|
||||
case CVRSpawnableTrigger.SampleDirection.YNegative:
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(0f, -vector.y, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(0f, -vector.y, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, -vector.z) + references[i].areaOffset, new Vector3(-vector.x, -vector.y, 0f) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, -vector.y, 0f) + references[i].areaOffset);
|
||||
break;
|
||||
case CVRSpawnableTrigger.SampleDirection.ZPositive:
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, -vector.z) + references[i].areaOffset, new Vector3(0f, vector.y, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, vector.y, -vector.z) + references[i].areaOffset, new Vector3(0f, vector.y, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, -vector.z) + references[i].areaOffset, new Vector3(-vector.x, 0f, vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, -vector.y, -vector.z) + references[i].areaOffset, new Vector3(-vector.x, 0f, vector.z) + references[i].areaOffset);
|
||||
break;
|
||||
case CVRSpawnableTrigger.SampleDirection.ZNegative:
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(0f, vector.y, -vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(0f, vector.y, -vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, 0f, -vector.z) + references[i].areaOffset);
|
||||
Gizmos.Line(new Vector3(-vector.x, -vector.y, vector.z) + references[i].areaOffset, new Vector3(-vector.x, 0f, -vector.z) + references[i].areaOffset);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
49
CVRGizmos/GizmoTypes/CVRToggleStateTrigger.cs
Normal file
49
CVRGizmos/GizmoTypes/CVRToggleStateTrigger.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
using ABI.CCK.Components;
|
||||
using UnityEngine;
|
||||
using Gizmos = Popcron.Gizmos;
|
||||
|
||||
/**
|
||||
|
||||
CVRToggleStateTrigger **can** be local using CVROfflinePreview or similar mods.
|
||||
|
||||
**/
|
||||
|
||||
namespace CVRGizmos.GismoTypes
|
||||
{
|
||||
public class CVRGizmos_ToggleStateTrigger : CVRGizmoBase
|
||||
{
|
||||
public static CVRToggleStateTrigger[] references;
|
||||
|
||||
public override void CacheGizmos()
|
||||
{
|
||||
var found = Resources.FindObjectsOfTypeAll(typeof(CVRToggleStateTrigger)) as CVRToggleStateTrigger[];
|
||||
|
||||
if (CVRGizmoManager.Instance.g_localOnly)
|
||||
{
|
||||
references = Array.ConvertAll(GetLocalOnly(found), item => (CVRToggleStateTrigger)item);
|
||||
}
|
||||
else
|
||||
{
|
||||
references = found;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawGizmos()
|
||||
{
|
||||
for (int i = 0; i < references.Count(); i++)
|
||||
{
|
||||
if (references[i] == null)
|
||||
{
|
||||
CacheGizmos();
|
||||
break;
|
||||
}
|
||||
if (references[i].isActiveAndEnabled)
|
||||
{
|
||||
Gizmos.Color = Color.green;
|
||||
Gizmos.Matrix = Matrix4x4.TRS(references[i].transform.position, references[i].transform.rotation, references[i].transform.lossyScale);
|
||||
Gizmos.Cube(references[i].areaOffset, Quaternion.identity, references[i].areaSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
49
CVRGizmos/Main.cs
Normal file
49
CVRGizmos/Main.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
using ABI_RC.Core.Player;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace CVRGizmos;
|
||||
|
||||
public class CVRGizmos : MelonMod
|
||||
{
|
||||
|
||||
private static MelonPreferences_Category m_categoryCVRGizmos;
|
||||
private static MelonPreferences_Entry<bool> m_entryCVRGizmosEnabled;
|
||||
private static MelonPreferences_Entry<bool> m_entryCVRGizmosLocalOnly;
|
||||
|
||||
public override void OnApplicationStart()
|
||||
{
|
||||
m_categoryCVRGizmos = MelonPreferences.CreateCategory(nameof(CVRGizmos));
|
||||
m_entryCVRGizmosEnabled = m_categoryCVRGizmos.CreateEntry<bool>("Enabled", false);
|
||||
m_entryCVRGizmosLocalOnly = m_categoryCVRGizmos.CreateEntry<bool>("Local Only", false);
|
||||
m_entryCVRGizmosEnabled.Value = false;
|
||||
|
||||
m_categoryCVRGizmos.SaveToFile(false);
|
||||
m_entryCVRGizmosEnabled.OnValueChangedUntyped += CVRGizmosEnabled;
|
||||
m_entryCVRGizmosLocalOnly.OnValueChangedUntyped += CVRGizmosLocalOnly;
|
||||
|
||||
MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer());
|
||||
}
|
||||
|
||||
IEnumerator WaitForLocalPlayer()
|
||||
{
|
||||
while (PlayerSetup.Instance == null)
|
||||
yield return null;
|
||||
|
||||
PlayerSetup.Instance.gameObject.AddComponent<CVRGizmoManager>();
|
||||
}
|
||||
|
||||
public void CVRGizmosEnabled()
|
||||
{
|
||||
if (!CVRGizmoManager.Instance) return;
|
||||
CVRGizmoManager.Instance.EnableGizmos(m_entryCVRGizmosEnabled.Value);
|
||||
}
|
||||
|
||||
public void CVRGizmosLocalOnly()
|
||||
{
|
||||
if (!CVRGizmoManager.Instance) return;
|
||||
CVRGizmoManager.Instance.g_localOnly = m_entryCVRGizmosLocalOnly.Value;
|
||||
CVRGizmoManager.Instance.RefreshGizmos();
|
||||
}
|
||||
}
|
8
CVRGizmos/Popcron.Gizmos/Constants.cs
Normal file
8
CVRGizmos/Popcron.Gizmos/Constants.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Popcron
|
||||
{
|
||||
public class Constants
|
||||
{
|
||||
public const string UniqueIdentifier = "Popcron.Gizmos";
|
||||
public const string EnabledKey = UniqueIdentifier + ".Enabled";
|
||||
}
|
||||
}
|
68
CVRGizmos/Popcron.Gizmos/Drawer.cs
Normal file
68
CVRGizmos/Popcron.Gizmos/Drawer.cs
Normal file
|
@ -0,0 +1,68 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Popcron
|
||||
{
|
||||
public abstract class Drawer
|
||||
{
|
||||
private static Dictionary<Type, Drawer> typeToDrawer = null;
|
||||
|
||||
public abstract int Draw(ref Vector3[] buffer, params object[] args);
|
||||
|
||||
public Drawer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static Drawer Get<T>() where T : class
|
||||
{
|
||||
//find all drawers
|
||||
if (typeToDrawer == null)
|
||||
{
|
||||
typeToDrawer = new Dictionary<Type, Drawer>();
|
||||
|
||||
//add defaults
|
||||
typeToDrawer.Add(typeof(CubeDrawer), new CubeDrawer());
|
||||
typeToDrawer.Add(typeof(LineDrawer), new LineDrawer());
|
||||
typeToDrawer.Add(typeof(PolygonDrawer), new PolygonDrawer());
|
||||
typeToDrawer.Add(typeof(SquareDrawer), new SquareDrawer());
|
||||
|
||||
//find extras
|
||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
foreach (Assembly assembly in assemblies)
|
||||
{
|
||||
Type[] types = assembly.GetTypes();
|
||||
foreach (Type type in types)
|
||||
{
|
||||
if (type.IsAbstract)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type.IsSubclassOf(typeof(Drawer)) && !typeToDrawer.ContainsKey(type))
|
||||
{
|
||||
try
|
||||
{
|
||||
Drawer value = (Drawer)Activator.CreateInstance(type);
|
||||
typeToDrawer[type] = value;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"couldnt register drawer of type {type} because {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeToDrawer.TryGetValue(typeof(T), out Drawer drawer))
|
||||
{
|
||||
return drawer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
96
CVRGizmos/Popcron.Gizmos/Drawers/CubeDrawer.cs
Normal file
96
CVRGizmos/Popcron.Gizmos/Drawers/CubeDrawer.cs
Normal file
|
@ -0,0 +1,96 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Popcron
|
||||
{
|
||||
public class CubeDrawer : Drawer
|
||||
{
|
||||
public CubeDrawer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override int Draw(ref Vector3[] buffer, params object[] values)
|
||||
{
|
||||
Vector3 position = (Vector3)values[0];
|
||||
Quaternion rotation = (Quaternion)values[1];
|
||||
Vector3 size = (Vector3)values[2];
|
||||
|
||||
size *= 0.5f;
|
||||
|
||||
Vector3 point1 = new Vector3(position.x - size.x, position.y - size.y, position.z - size.z);
|
||||
Vector3 point2 = new Vector3(position.x + size.x, position.y - size.y, position.z - size.z);
|
||||
Vector3 point3 = new Vector3(position.x + size.x, position.y + size.y, position.z - size.z);
|
||||
Vector3 point4 = new Vector3(position.x - size.x, position.y + size.y, position.z - size.z);
|
||||
|
||||
Vector3 point5 = new Vector3(position.x - size.x, position.y - size.y, position.z + size.z);
|
||||
Vector3 point6 = new Vector3(position.x + size.x, position.y - size.y, position.z + size.z);
|
||||
Vector3 point7 = new Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
|
||||
Vector3 point8 = new Vector3(position.x - size.x, position.y + size.y, position.z + size.z);
|
||||
|
||||
point1 = rotation * (point1 - position);
|
||||
point1 += position;
|
||||
|
||||
point2 = rotation * (point2 - position);
|
||||
point2 += position;
|
||||
|
||||
point3 = rotation * (point3 - position);
|
||||
point3 += position;
|
||||
|
||||
point4 = rotation * (point4 - position);
|
||||
point4 += position;
|
||||
|
||||
point5 = rotation * (point5 - position);
|
||||
point5 += position;
|
||||
|
||||
point6 = rotation * (point6 - position);
|
||||
point6 += position;
|
||||
|
||||
point7 = rotation * (point7 - position);
|
||||
point7 += position;
|
||||
|
||||
point8 = rotation * (point8 - position);
|
||||
point8 += position;
|
||||
|
||||
//square
|
||||
buffer[0] = point1;
|
||||
buffer[1] = point2;
|
||||
|
||||
buffer[2] = point2;
|
||||
buffer[3] = point3;
|
||||
|
||||
buffer[4] = point3;
|
||||
buffer[5] = point4;
|
||||
|
||||
buffer[6] = point4;
|
||||
buffer[7] = point1;
|
||||
|
||||
//other square
|
||||
buffer[8] = point5;
|
||||
buffer[9] = point6;
|
||||
|
||||
buffer[10] = point6;
|
||||
buffer[11] = point7;
|
||||
|
||||
buffer[12] = point7;
|
||||
buffer[13] = point8;
|
||||
|
||||
buffer[14] = point8;
|
||||
buffer[15] = point5;
|
||||
|
||||
//connectors
|
||||
buffer[16] = point1;
|
||||
buffer[17] = point5;
|
||||
|
||||
buffer[18] = point2;
|
||||
buffer[19] = point6;
|
||||
|
||||
buffer[20] = point3;
|
||||
buffer[21] = point7;
|
||||
|
||||
buffer[22] = point4;
|
||||
buffer[23] = point8;
|
||||
|
||||
return 24;
|
||||
}
|
||||
}
|
||||
}
|
19
CVRGizmos/Popcron.Gizmos/Drawers/LineDrawer.cs
Normal file
19
CVRGizmos/Popcron.Gizmos/Drawers/LineDrawer.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Popcron
|
||||
{
|
||||
public class LineDrawer : Drawer
|
||||
{
|
||||
public LineDrawer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override int Draw(ref Vector3[] buffer, params object[] args)
|
||||
{
|
||||
buffer[0] = (Vector3)args[0];
|
||||
buffer[1] = (Vector3)args[1];
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
40
CVRGizmos/Popcron.Gizmos/Drawers/PolygonDrawer.cs
Normal file
40
CVRGizmos/Popcron.Gizmos/Drawers/PolygonDrawer.cs
Normal file
|
@ -0,0 +1,40 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Popcron
|
||||
{
|
||||
public class PolygonDrawer : Drawer
|
||||
{
|
||||
public PolygonDrawer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override int Draw(ref Vector3[] buffer, params object[] values)
|
||||
{
|
||||
Vector3 position = (Vector3)values[0];
|
||||
int points = (int)values[1];
|
||||
float radius = (float)values[2];
|
||||
float offset = (float)values[3];
|
||||
Quaternion rotation = (Quaternion)values[4];
|
||||
|
||||
float step = 360f / points;
|
||||
offset *= Mathf.Deg2Rad;
|
||||
|
||||
for (int i = 0; i < points; i++)
|
||||
{
|
||||
float cx = Mathf.Cos(Mathf.Deg2Rad * step * i + offset) * radius;
|
||||
float cy = Mathf.Sin(Mathf.Deg2Rad * step * i + offset) * radius;
|
||||
Vector3 current = new Vector3(cx, cy);
|
||||
|
||||
float nx = Mathf.Cos(Mathf.Deg2Rad * step * (i + 1) + offset) * radius;
|
||||
float ny = Mathf.Sin(Mathf.Deg2Rad * step * (i + 1) + offset) * radius;
|
||||
Vector3 next = new Vector3(nx, ny);
|
||||
|
||||
buffer[i * 2] = position + (rotation * current);
|
||||
buffer[(i * 2) + 1] = position + (rotation * next);
|
||||
}
|
||||
|
||||
return points * 2;
|
||||
}
|
||||
}
|
||||
}
|
72
CVRGizmos/Popcron.Gizmos/Drawers/SquareDrawer.cs
Normal file
72
CVRGizmos/Popcron.Gizmos/Drawers/SquareDrawer.cs
Normal file
|
@ -0,0 +1,72 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Popcron
|
||||
{
|
||||
public class SquareDrawer : Drawer
|
||||
{
|
||||
public SquareDrawer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override int Draw(ref Vector3[] buffer, params object[] values)
|
||||
{
|
||||
Vector2 position = default;
|
||||
if (values[0] is Vector2 p2)
|
||||
{
|
||||
position = p2;
|
||||
}
|
||||
else if (values[0] is Vector3 p3)
|
||||
{
|
||||
position = p3;
|
||||
}
|
||||
|
||||
Quaternion rotation = (Quaternion)values[1];
|
||||
|
||||
Vector2 size = default;
|
||||
if (values[2] is Vector2 s2)
|
||||
{
|
||||
size = s2;
|
||||
}
|
||||
else if (values[2] is Vector3 s3)
|
||||
{
|
||||
size = s3;
|
||||
}
|
||||
|
||||
size *= 0.5f;
|
||||
|
||||
Vector2 point1 = new Vector3(position.x - size.x, position.y - size.y);
|
||||
Vector2 point2 = new Vector3(position.x + size.x, position.y - size.y);
|
||||
Vector2 point3 = new Vector3(position.x + size.x, position.y + size.y);
|
||||
Vector2 point4 = new Vector3(position.x - size.x, position.y + size.y);
|
||||
|
||||
point1 = rotation * (point1 - position);
|
||||
point1 += position;
|
||||
|
||||
point2 = rotation * (point2 - position);
|
||||
point2 += position;
|
||||
|
||||
point3 = rotation * (point3 - position);
|
||||
point3 += position;
|
||||
|
||||
point4 = rotation * (point4 - position);
|
||||
point4 += position;
|
||||
|
||||
//square
|
||||
buffer[0] = point1;
|
||||
buffer[1] = point2;
|
||||
|
||||
buffer[2] = point2;
|
||||
buffer[3] = point3;
|
||||
|
||||
buffer[4] = point3;
|
||||
buffer[5] = point4;
|
||||
|
||||
//loop back to start
|
||||
buffer[6] = point4;
|
||||
buffer[7] = point1;
|
||||
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
}
|
12
CVRGizmos/Popcron.Gizmos/Element.cs
Normal file
12
CVRGizmos/Popcron.Gizmos/Element.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Popcron
|
||||
{
|
||||
internal class Element
|
||||
{
|
||||
public Vector3[] points = { };
|
||||
public Color color = Color.white;
|
||||
public bool dashed = false;
|
||||
public Matrix4x4 matrix = Matrix4x4.identity;
|
||||
}
|
||||
}
|
393
CVRGizmos/Popcron.Gizmos/Gizmos.cs
Normal file
393
CVRGizmos/Popcron.Gizmos/Gizmos.cs
Normal file
|
@ -0,0 +1,393 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Popcron
|
||||
{
|
||||
public class Gizmos
|
||||
{
|
||||
private static string _prefsKey = null;
|
||||
private static int? _bufferSize = null;
|
||||
private static bool? _enabled = null;
|
||||
private static float? _dashGap = null;
|
||||
private static bool? _cull = null;
|
||||
private static int? _pass = null;
|
||||
private static Vector3? _offset = null;
|
||||
|
||||
private static Vector3[] buffer = new Vector3[BufferSize];
|
||||
|
||||
/// <summary>
|
||||
/// By default, it will always render to scene view camera and the main camera.
|
||||
/// Subscribing to this allows you to whitelist your custom cameras.
|
||||
/// </summary>
|
||||
public static Func<Camera, bool> CameraFilter = cam => false;
|
||||
|
||||
private static string PrefsKey
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_prefsKey))
|
||||
{
|
||||
_prefsKey = $"{SystemInfo.deviceUniqueIdentifier}.{Application.companyName}.{Application.productName}.{Constants.UniqueIdentifier}";
|
||||
}
|
||||
|
||||
return _prefsKey;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The matrix to use.
|
||||
/// </summary>
|
||||
public static Matrix4x4 Matrix
|
||||
{
|
||||
get => GizmosInstance.Matrix;
|
||||
set => GizmosInstance.Matrix = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The matrix to use.
|
||||
/// </summary>
|
||||
public static Color Color
|
||||
{
|
||||
get => GizmosInstance.Color;
|
||||
set => GizmosInstance.Color = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The size of the total gizmos buffer.
|
||||
/// Default is 4096.
|
||||
/// </summary>
|
||||
public static int BufferSize
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_bufferSize == null)
|
||||
{
|
||||
_bufferSize = PlayerPrefs.GetInt($"{PrefsKey}.BufferSize", 4096);
|
||||
}
|
||||
|
||||
return _bufferSize.Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
value = Mathf.Clamp(value, 0, int.MaxValue);
|
||||
if (_bufferSize != value)
|
||||
{
|
||||
_bufferSize = value;
|
||||
PlayerPrefs.SetInt($"{PrefsKey}.BufferSize", value);
|
||||
|
||||
//buffer size changed, so recreate the buffer array too
|
||||
buffer = new Vector3[value];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles wether the gizmos could be drawn or not.
|
||||
/// </summary>
|
||||
public static bool Enabled
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_enabled == null)
|
||||
{
|
||||
_enabled = PlayerPrefs.GetInt($"{PrefsKey}.Enabled", 1) == 1;
|
||||
}
|
||||
|
||||
return _enabled.Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_enabled != value)
|
||||
{
|
||||
_enabled = value;
|
||||
PlayerPrefs.SetInt($"{PrefsKey}.Enabled", value ? 1 : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The size of the gap when drawing dashed elements.
|
||||
/// Default gap size is 0.1
|
||||
/// </summary>
|
||||
public static float DashGap
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dashGap == null)
|
||||
{
|
||||
_dashGap = PlayerPrefs.GetFloat($"{PrefsKey}.DashGap", 0.1f);
|
||||
}
|
||||
|
||||
return _dashGap.Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_dashGap != value)
|
||||
{
|
||||
_dashGap = value;
|
||||
PlayerPrefs.SetFloat($"{PrefsKey}.DashGap", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("This property is obsolete. Use FrustumCulling instead.", false)]
|
||||
public static bool Cull
|
||||
{
|
||||
get
|
||||
{
|
||||
return FrustumCulling;
|
||||
}
|
||||
set
|
||||
{
|
||||
FrustumCulling = value;
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("This property is obsolete. Subscribe to CameraFilter predicate instead and return true for your custom camera.", false)]
|
||||
public static Camera Camera
|
||||
{
|
||||
get => null;
|
||||
set
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should the camera not draw elements that are not visible?
|
||||
/// </summary>
|
||||
public static bool FrustumCulling
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_cull == null)
|
||||
{
|
||||
_cull = PlayerPrefs.GetInt($"{PrefsKey}.FrustumCulling", 1) == 1;
|
||||
}
|
||||
|
||||
return _cull.Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_cull != value)
|
||||
{
|
||||
_cull = value;
|
||||
PlayerPrefs.SetInt($"{PrefsKey}.FrustumCulling", value ? 1 : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The material being used to render.
|
||||
/// </summary>
|
||||
public static Material Material
|
||||
{
|
||||
get => GizmosInstance.Material;
|
||||
set => GizmosInstance.Material = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rendering pass to activate.
|
||||
/// </summary>
|
||||
public static int Pass
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_pass == null)
|
||||
{
|
||||
_pass = PlayerPrefs.GetInt($"{PrefsKey}.Pass", 0);
|
||||
}
|
||||
|
||||
return _pass.Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_pass != value)
|
||||
{
|
||||
_pass = value;
|
||||
PlayerPrefs.SetInt($"{PrefsKey}.Pass", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Global offset for all points. Default is (0, 0, 0).
|
||||
/// </summary>
|
||||
public static Vector3 Offset
|
||||
{
|
||||
get
|
||||
{
|
||||
const string Delim = ",";
|
||||
if (_offset == null)
|
||||
{
|
||||
string data = PlayerPrefs.GetString($"{PrefsKey}.Offset", 0 + Delim + 0 + Delim + 0);
|
||||
int indexOf = data.IndexOf(Delim);
|
||||
int lastIndexOf = data.LastIndexOf(Delim);
|
||||
if (indexOf + lastIndexOf > 0)
|
||||
{
|
||||
string[] arr = data.Split(Delim[0]);
|
||||
_offset = new Vector3(float.Parse(arr[0]), float.Parse(arr[1]), float.Parse(arr[2]));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
return _offset.Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
const string Delim = ",";
|
||||
if (_offset != value)
|
||||
{
|
||||
_offset = value;
|
||||
PlayerPrefs.SetString($"{PrefsKey}.Offset", value.x + Delim + value.y + Delim + value.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws an element onto the screen.
|
||||
/// </summary>
|
||||
public static void Draw<T>(Color? color, bool dashed, params object[] args) where T : Drawer
|
||||
{
|
||||
if (!Enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Drawer drawer = Drawer.Get<T>();
|
||||
if (drawer != null)
|
||||
{
|
||||
int points = drawer.Draw(ref buffer, args);
|
||||
|
||||
//copy from buffer and add to the queue
|
||||
Vector3[] array = new Vector3[points];
|
||||
Array.Copy(buffer, array, points);
|
||||
GizmosInstance.Submit(array, color, dashed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws an array of lines. Useful for things like paths.
|
||||
/// </summary>
|
||||
public static void Lines(Vector3[] lines, Color? color = null, bool dashed = false)
|
||||
{
|
||||
if (!Enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GizmosInstance.Submit(lines, color, dashed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw line in world space.
|
||||
/// </summary>
|
||||
public static void Line(Vector3 a, Vector3 b, Color? color = null, bool dashed = false)
|
||||
{
|
||||
Draw<LineDrawer>(color, dashed, a, b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw square in world space.
|
||||
/// </summary>
|
||||
public static void Square(Vector2 position, Vector2 size, Color? color = null, bool dashed = false)
|
||||
{
|
||||
Square(position, Quaternion.identity, size, color, dashed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw square in world space with float diameter parameter.
|
||||
/// </summary>
|
||||
public static void Square(Vector2 position, float diameter, Color? color = null, bool dashed = false)
|
||||
{
|
||||
Square(position, Quaternion.identity, Vector2.one * diameter, color, dashed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw square in world space with a rotation parameter.
|
||||
/// </summary>
|
||||
public static void Square(Vector2 position, Quaternion rotation, Vector2 size, Color? color = null, bool dashed = false)
|
||||
{
|
||||
Draw<SquareDrawer>(color, dashed, position, rotation, size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a cube in world space.
|
||||
/// </summary>
|
||||
public static void Cube(Vector3 position, Quaternion rotation, Vector3 size, Color? color = null, bool dashed = false)
|
||||
{
|
||||
Draw<CubeDrawer>(color, dashed, position, rotation, size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a rectangle in screen space.
|
||||
/// </summary>
|
||||
public static void Rect(Rect rect, Camera camera, Color? color = null, bool dashed = false)
|
||||
{
|
||||
rect.y = Screen.height - rect.y;
|
||||
Vector2 corner = camera.ScreenToWorldPoint(new Vector2(rect.x, rect.y - rect.height));
|
||||
Draw<SquareDrawer>(color, dashed, corner + rect.size * 0.5f, Quaternion.identity, rect.size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a representation of a bounding box.
|
||||
/// </summary>
|
||||
public static void Bounds(Bounds bounds, Color? color = null, bool dashed = false)
|
||||
{
|
||||
Draw<CubeDrawer>(color, dashed, bounds.center, Quaternion.identity, bounds.size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a cone similar to the one that spot lights draw.
|
||||
/// </summary>
|
||||
public static void Cone(Vector3 position, Quaternion rotation, float length, float angle, Color? color = null, bool dashed = false, int pointsCount = 16)
|
||||
{
|
||||
//draw the end of the cone
|
||||
float endAngle = Mathf.Tan(angle * 0.5f * Mathf.Deg2Rad) * length;
|
||||
Vector3 forward = rotation * Vector3.forward;
|
||||
Vector3 endPosition = position + forward * length;
|
||||
float offset = 0f;
|
||||
Draw<PolygonDrawer>(color, dashed, endPosition, pointsCount, endAngle, offset, rotation);
|
||||
|
||||
//draw the 4 lines
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
float a = i * 90f * Mathf.Deg2Rad;
|
||||
Vector3 point = rotation * new Vector3(Mathf.Cos(a), Mathf.Sin(a)) * endAngle;
|
||||
Line(position, position + point + forward * length, color, dashed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a sphere at position with specified radius.
|
||||
/// </summary>
|
||||
public static void Sphere(Vector3 position, float radius, Color? color = null, bool dashed = false, int pointsCount = 16)
|
||||
{
|
||||
float offset = 0f;
|
||||
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, Quaternion.Euler(0f, 0f, 0f));
|
||||
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, Quaternion.Euler(90f, 0f, 0f));
|
||||
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, Quaternion.Euler(0f, 90f, 90f));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a circle in world space and billboards towards the camera.
|
||||
/// </summary>
|
||||
public static void Circle(Vector3 position, float radius, Camera camera, Color? color = null, bool dashed = false, int pointsCount = 16)
|
||||
{
|
||||
float offset = 0f;
|
||||
Quaternion rotation = Quaternion.LookRotation(position - camera.transform.position);
|
||||
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, rotation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a circle in world space with a specified rotation.
|
||||
/// </summary>
|
||||
public static void Circle(Vector3 position, float radius, Quaternion rotation, Color? color = null, bool dashed = false, int pointsCount = 16)
|
||||
{
|
||||
float offset = 0f;
|
||||
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, rotation);
|
||||
}
|
||||
}
|
||||
}
|
443
CVRGizmos/Popcron.Gizmos/GizmosInstance.cs
Normal file
443
CVRGizmos/Popcron.Gizmos/GizmosInstance.cs
Normal file
|
@ -0,0 +1,443 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
#endif
|
||||
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
|
||||
public struct ScriptableRenderContext { }
|
||||
|
||||
public static class RenderPipelineManager
|
||||
{
|
||||
public static event Action<ScriptableRenderContext, Camera> endCameraRendering;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace Popcron
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
[AddComponentMenu("")]
|
||||
public class GizmosInstance : MonoBehaviour
|
||||
{
|
||||
private const int DefaultQueueSize = 4096;
|
||||
|
||||
private static GizmosInstance instance;
|
||||
private static bool hotReloaded = true;
|
||||
private static Material defaultMaterial;
|
||||
private static Plane[] cameraPlanes = new Plane[6];
|
||||
|
||||
private Color color = Color.white;
|
||||
private Matrix4x4 matrix;
|
||||
private Material overrideMaterial;
|
||||
private int queueIndex = 0;
|
||||
private int lastFrame;
|
||||
private Element[] queue = new Element[DefaultQueueSize];
|
||||
|
||||
/// <summary>
|
||||
/// The material being used to render
|
||||
/// </summary>
|
||||
public static Material Material
|
||||
{
|
||||
get
|
||||
{
|
||||
GizmosInstance inst = GetOrCreate();
|
||||
if (inst.overrideMaterial)
|
||||
{
|
||||
return inst.overrideMaterial;
|
||||
}
|
||||
|
||||
return DefaultMaterial;
|
||||
}
|
||||
set
|
||||
{
|
||||
GizmosInstance inst = GetOrCreate();
|
||||
inst.overrideMaterial = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The matrix to use
|
||||
/// </summary>
|
||||
public static Matrix4x4 Matrix
|
||||
{
|
||||
get
|
||||
{
|
||||
GizmosInstance inst = GetOrCreate();
|
||||
if (!inst.matrix.isIdentity)
|
||||
{
|
||||
return inst.matrix;
|
||||
}
|
||||
|
||||
return Matrix4x4.identity;
|
||||
}
|
||||
set
|
||||
{
|
||||
GizmosInstance inst = GetOrCreate();
|
||||
inst.matrix = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The matrix to use
|
||||
/// </summary>
|
||||
public static Color Color
|
||||
{
|
||||
get
|
||||
{
|
||||
GizmosInstance inst = GetOrCreate();
|
||||
return inst.color;
|
||||
}
|
||||
set
|
||||
{
|
||||
GizmosInstance inst = GetOrCreate();
|
||||
inst.color = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The default line renderer material
|
||||
/// </summary>
|
||||
public static Material DefaultMaterial
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!defaultMaterial)
|
||||
{
|
||||
// Unity has a built-in shader that is useful for drawing
|
||||
// simple colored things.
|
||||
Shader shader = Shader.Find("Hidden/Internal-Colored");
|
||||
defaultMaterial = new Material(shader)
|
||||
{
|
||||
hideFlags = HideFlags.HideAndDontSave
|
||||
};
|
||||
|
||||
// Turn on alpha blending
|
||||
defaultMaterial.SetInt("_SrcBlend", (int)BlendMode.SrcAlpha);
|
||||
defaultMaterial.SetInt("_DstBlend", (int)BlendMode.OneMinusSrcAlpha);
|
||||
defaultMaterial.SetInt("_Cull", (int)CullMode.Off);
|
||||
defaultMaterial.SetInt("_ZWrite", 0);
|
||||
}
|
||||
|
||||
return defaultMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
internal static GizmosInstance GetOrCreate()
|
||||
{
|
||||
if (hotReloaded || !instance)
|
||||
{
|
||||
bool markDirty = false;
|
||||
GizmosInstance[] gizmosInstances = FindObjectsOfType<GizmosInstance>();
|
||||
for (int i = 0; i < gizmosInstances.Length; i++)
|
||||
{
|
||||
instance = gizmosInstances[i];
|
||||
|
||||
//destroy any extra gizmo instances
|
||||
if (i > 0)
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
Destroy(gizmosInstances[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyImmediate(gizmosInstances[i]);
|
||||
markDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//none were found, create a new one
|
||||
if (!instance)
|
||||
{
|
||||
instance = new GameObject(typeof(GizmosInstance).FullName).AddComponent<GizmosInstance>();
|
||||
instance.gameObject.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
|
||||
|
||||
markDirty = true;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
//mark scene as dirty
|
||||
if (markDirty && !Application.isPlaying)
|
||||
{
|
||||
Scene scene = SceneManager.GetActiveScene();
|
||||
EditorSceneManager.MarkSceneDirty(scene);
|
||||
}
|
||||
#endif
|
||||
|
||||
hotReloaded = false;
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private float CurrentTime
|
||||
{
|
||||
get
|
||||
{
|
||||
float time = 0f;
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
time = Time.time;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
time = (float)EditorApplication.timeSinceStartup;
|
||||
#endif
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submits an array of points to draw into the queue.
|
||||
/// </summary>
|
||||
internal static void Submit(Vector3[] points, Color? color2, bool dashed)
|
||||
{
|
||||
GizmosInstance inst = GetOrCreate();
|
||||
|
||||
//if new frame, reset index
|
||||
if (inst.lastFrame != Time.frameCount)
|
||||
{
|
||||
inst.lastFrame = Time.frameCount;
|
||||
inst.queueIndex = 0;
|
||||
}
|
||||
|
||||
//multiply points by matrix
|
||||
for (int i = 0; i < points.Length; i++)
|
||||
{
|
||||
points[i] = inst.matrix.MultiplyPoint3x4(points[i]);
|
||||
}
|
||||
|
||||
//excedeed the length, so make it even bigger
|
||||
if (inst.queueIndex >= inst.queue.Length)
|
||||
{
|
||||
Element[] bigger = new Element[inst.queue.Length + DefaultQueueSize];
|
||||
for (int i = inst.queue.Length; i < bigger.Length; i++)
|
||||
{
|
||||
bigger[i] = new Element();
|
||||
}
|
||||
|
||||
Array.Copy(inst.queue, 0, bigger, 0, inst.queue.Length);
|
||||
inst.queue = bigger;
|
||||
}
|
||||
|
||||
inst.queue[inst.queueIndex].color = inst.color;
|
||||
inst.queue[inst.queueIndex].points = points;
|
||||
inst.queue[inst.queueIndex].dashed = dashed;
|
||||
inst.queue[inst.queueIndex].matrix = inst.matrix;
|
||||
|
||||
inst.queueIndex++;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
//populate queue with empty elements
|
||||
queue = new Element[DefaultQueueSize];
|
||||
for (int i = 0; i < DefaultQueueSize; i++)
|
||||
{
|
||||
queue[i] = new Element();
|
||||
}
|
||||
|
||||
if (GraphicsSettings.renderPipelineAsset == null)
|
||||
{
|
||||
Camera.onPostRender += OnRendered;
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderPipelineManager.endCameraRendering += OnRendered;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (GraphicsSettings.renderPipelineAsset == null)
|
||||
{
|
||||
Camera.onPostRender -= OnRendered;
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderPipelineManager.endCameraRendering -= OnRendered;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRendered(ScriptableRenderContext context, Camera camera) => OnRendered(camera);
|
||||
|
||||
private bool ShouldRenderCamera(Camera camera)
|
||||
{
|
||||
if (!camera)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//allow the scene and main camera always
|
||||
bool isSceneCamera = false;
|
||||
#if UNITY_EDITOR
|
||||
SceneView sceneView = SceneView.currentDrawingSceneView;
|
||||
if (sceneView == null)
|
||||
{
|
||||
sceneView = SceneView.lastActiveSceneView;
|
||||
}
|
||||
|
||||
if (sceneView != null && sceneView.camera == camera)
|
||||
{
|
||||
isSceneCamera = true;
|
||||
}
|
||||
#endif
|
||||
if (isSceneCamera || camera.CompareTag("MainCamera"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (camera.name.StartsWith("Mirror "))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//it passed through the filter
|
||||
if (Gizmos.CameraFilter?.Invoke(camera) == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsVisibleByCamera(Element points, Camera camera)
|
||||
{
|
||||
if (!camera)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//essentially check if at least 1 point is visible by the camera
|
||||
for (int i = 0; i < points.points.Length; i++)
|
||||
{
|
||||
Vector3 vp = camera.WorldToViewportPoint(points.points[i], camera.stereoActiveEye);
|
||||
if (vp.x >= 0 && vp.x <= 1 && vp.y >= 0 && vp.y <= 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//private void Update()
|
||||
//{
|
||||
// //always render something
|
||||
// Gizmos.Line(default, default);
|
||||
//}
|
||||
|
||||
private void OnRendered(Camera camera)
|
||||
{
|
||||
Material.SetPass(Gizmos.Pass);
|
||||
|
||||
//shouldnt be rendering
|
||||
if (!Gizmos.Enabled)
|
||||
{
|
||||
queueIndex = 0;
|
||||
}
|
||||
|
||||
//check if this camera is ok to render with
|
||||
if (!ShouldRenderCamera(camera))
|
||||
{
|
||||
GL.PushMatrix();
|
||||
GL.Begin(GL.LINES);
|
||||
|
||||
//bla bla bla
|
||||
|
||||
GL.End();
|
||||
GL.PopMatrix();
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 offset = Gizmos.Offset;
|
||||
|
||||
GL.PushMatrix();
|
||||
GL.MultMatrix(Matrix4x4.identity);
|
||||
GL.Begin(GL.LINES);
|
||||
|
||||
bool alt = CurrentTime % 1 > 0.5f;
|
||||
float dashGap = Mathf.Clamp(Gizmos.DashGap, 0.01f, 32f);
|
||||
bool frustumCull = Gizmos.FrustumCulling;
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
|
||||
//draw le elements
|
||||
for (int e = 0; e < queueIndex; e++)
|
||||
{
|
||||
//just in case
|
||||
if (queue.Length <= e)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Element element = queue[e];
|
||||
|
||||
//dont render this thingy if its not inside the frustum
|
||||
if (frustumCull)
|
||||
{
|
||||
if (!IsVisibleByCamera(element, camera))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
points.Clear();
|
||||
if (element.dashed)
|
||||
{
|
||||
//subdivide
|
||||
for (int i = 0; i < element.points.Length - 1; i++)
|
||||
{
|
||||
Vector3 pointA = element.points[i];
|
||||
Vector3 pointB = element.points[i + 1];
|
||||
Vector3 direction = pointB - pointA;
|
||||
if (direction.sqrMagnitude > dashGap * dashGap * 2f)
|
||||
{
|
||||
float magnitude = direction.magnitude;
|
||||
int amount = Mathf.RoundToInt(magnitude / dashGap);
|
||||
direction /= magnitude;
|
||||
|
||||
for (int p = 0; p < amount - 1; p++)
|
||||
{
|
||||
if (p % 2 == (alt ? 1 : 0))
|
||||
{
|
||||
float startLerp = p / (amount - 1f);
|
||||
float endLerp = (p + 1) / (amount - 1f);
|
||||
Vector3 start = Vector3.Lerp(pointA, pointB, startLerp);
|
||||
Vector3 end = Vector3.Lerp(pointA, pointB, endLerp);
|
||||
points.Add(start);
|
||||
points.Add(end);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
points.Add(pointA);
|
||||
points.Add(pointB);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
points.AddRange(element.points);
|
||||
}
|
||||
|
||||
GL.Color(element.color);
|
||||
for (int i = 0; i < points.Count; i++)
|
||||
{
|
||||
GL.Vertex(points[i] + offset);
|
||||
}
|
||||
}
|
||||
|
||||
GL.End();
|
||||
GL.PopMatrix();
|
||||
}
|
||||
}
|
||||
}
|
21
CVRGizmos/Popcron.Gizmos/LICENSE.md
Normal file
21
CVRGizmos/Popcron.Gizmos/LICENSE.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Phillip DaSilva-Damaskin
|
||||
|
||||
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.
|
30
CVRGizmos/Properties/AssemblyInfo.cs
Normal file
30
CVRGizmos/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,30 @@
|
|||
using CVRGizmos.Properties;
|
||||
using MelonLoader;
|
||||
using System.Reflection;
|
||||
|
||||
|
||||
[assembly: AssemblyVersion(AssemblyInfoParams.Version)]
|
||||
[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)]
|
||||
[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)]
|
||||
[assembly: AssemblyTitle(nameof(CVRGizmos))]
|
||||
[assembly: AssemblyCompany(AssemblyInfoParams.Author)]
|
||||
[assembly: AssemblyProduct(nameof(CVRGizmos))]
|
||||
|
||||
[assembly: MelonInfo(
|
||||
typeof(CVRGizmos.CVRGizmos),
|
||||
nameof(CVRGizmos),
|
||||
AssemblyInfoParams.Version,
|
||||
AssemblyInfoParams.Author,
|
||||
downloadLink: "https://github.com/NotAKidOnSteam/CVRGizmos"
|
||||
)]
|
||||
|
||||
[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")]
|
||||
[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
||||
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
|
||||
|
||||
namespace CVRGizmos.Properties;
|
||||
internal static class AssemblyInfoParams
|
||||
{
|
||||
public const string Version = "1.0.0";
|
||||
public const string Author = "NotAKidoS";
|
||||
}
|
23
CVRGizmos/format.json
Normal file
23
CVRGizmos/format.json
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"_id": 95,
|
||||
"name": "CVRGizmos",
|
||||
"modversion": "1.1.0",
|
||||
"gameversion": "2022r168",
|
||||
"loaderversion": "0.5.4",
|
||||
"modtype": "Mod",
|
||||
"author": "NotAKidoS",
|
||||
"description": "Corrects MM and QM position when avatar is scaled.\nAdditional option to scale player collision.",
|
||||
"searchtags": [
|
||||
"menu",
|
||||
"scale",
|
||||
"avatarscale",
|
||||
"slider"
|
||||
],
|
||||
"requirements": [
|
||||
"None"
|
||||
],
|
||||
"downloadlink": "https://github.com/NotAKidOnSteam/CVRGizmos/releases/download/r2/CVRGizmos.dll",
|
||||
"sourcelink": "https://github.com/NotAKidOnSteam/CVRGizmos/",
|
||||
"changelog": "Added option to scale player collision. Fixed some VR specific issues.",
|
||||
"embedcolor": "804221"
|
||||
}
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 NotAKidoS
|
||||
Copyright (c) 2022 NotAKidoS
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
11
README.md
11
README.md
|
@ -14,6 +14,17 @@ The avatar will stay in the default animator state until AAS data is received th
|
|||
|
||||
You will no longer sync garbage AAS while switching avatar.
|
||||
|
||||
# CVRGizmos
|
||||
Adds in-game gizmos to CCK components.
|
||||
|
||||
Current implementation may be a bit ugly, but at least it doesn't tank FPS.
|
||||
|
||||
Uses modified version of Popcron.Gizmos:
|
||||
|
||||
https://github.com/popcron/gizmos
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
Here is the block of text where I tell you this mod is not affiliated or endorsed by ABI.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue