Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ME] Projector support #244

Merged
merged 33 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1aac150
Allow editing of projector materials
RikkiBalboa Apr 18, 2024
312aea7
Add editing of projector settings
RikkiBalboa Apr 18, 2024
5532402
implement studio abstractions
RikkiBalboa Apr 18, 2024
f7fe705
Implement scene save/load and object copy/delete
RikkiBalboa Apr 18, 2024
2b96c97
Fix projectors always sharing their material
RikkiBalboa Apr 19, 2024
519677e
Make copy/pasting projector properties work
RikkiBalboa Apr 19, 2024
4ce2064
Add timeline support
RikkiBalboa Apr 19, 2024
3b9f205
Hide "Copy Material" button for projectors
RikkiBalboa Apr 19, 2024
4427232
Remove debug logging
RikkiBalboa Apr 19, 2024
c62404b
Toggle projectors off when items are invisible
RikkiBalboa Apr 19, 2024
239afc3
Remove toggling of projector components
RikkiBalboa Apr 20, 2024
2c41dee
Update comments
RikkiBalboa Apr 20, 2024
94f6d14
Add proper projector integrity check
RikkiBalboa Apr 20, 2024
5cff9d7
Remove unused usings
RikkiBalboa Apr 20, 2024
b868e9b
revert method to original state
RikkiBalboa Apr 20, 2024
b17813b
Fix editing projectors affecting all child projectors
RikkiBalboa Apr 21, 2024
3e66114
Reverse changing public facing abstract copy/paste methods
RikkiBalboa Apr 21, 2024
9ddd388
Prevent null error when searching projectors
RikkiBalboa Apr 21, 2024
a731e78
Implement character support
RikkiBalboa Apr 23, 2024
30e1ec6
Add projector filtering
RikkiBalboa Apr 23, 2024
1ac365d
remove logging
RikkiBalboa Apr 23, 2024
813a04f
Make max value of projector sliders configurable
RikkiBalboa Apr 24, 2024
67c6f20
Remove hardcoding of projector default values
RikkiBalboa Apr 24, 2024
971cab6
Change returned projectors depending on if it's maker or studio
RikkiBalboa Apr 24, 2024
c7ef865
Move projector properties above shader/material properties
RikkiBalboa Apr 24, 2024
244a237
Change function name to prevent conflict with existing plugin
RikkiBalboa Apr 24, 2024
e5502d0
Add enabled slider
RikkiBalboa Apr 24, 2024
b258f24
Allow ignoring layers
RikkiBalboa Apr 24, 2024
2f28109
updated some summaries
RikkiBalboa Apr 24, 2024
567f005
Update src/MaterialEditor.Base/MaterialAPI.cs
ManlyMarco Apr 25, 2024
46e6ddb
Better defaults for AI/HS2/PH
RikkiBalboa Apr 25, 2024
58452ad
Update defaults for Orthographic Size in AI/HS2
RikkiBalboa Apr 25, 2024
5e7e3af
update value range
RikkiBalboa Apr 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion src/MaterialEditor.Base/CopyContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ public class CopyContainer
/// List of shader edits
/// </summary>
public List<MaterialShader> MaterialShaderList = new List<MaterialShader>();
/// <summary>
/// List of projector edits
/// </summary>
public List<ProjectorProperty> ProjectorPropertyList = new List<ProjectorProperty>();

/// <summary>
/// Whether there are any copied edits
Expand All @@ -36,7 +40,7 @@ public bool IsEmpty
{
get
{
if (MaterialFloatPropertyList.Count == 0 && MaterialKeywordPropertyList.Count == 0 && MaterialColorPropertyList.Count == 0 && MaterialTexturePropertyList.Count == 0 && MaterialShaderList.Count == 0)
if (MaterialFloatPropertyList.Count == 0 && MaterialKeywordPropertyList.Count == 0 && MaterialColorPropertyList.Count == 0 && MaterialTexturePropertyList.Count == 0 && MaterialShaderList.Count == 0 && ProjectorPropertyList.Count == 0)
return true;
return false;
}
Expand All @@ -52,6 +56,7 @@ public void ClearAll()
MaterialColorPropertyList = new List<MaterialColorProperty>();
MaterialTexturePropertyList = new List<MaterialTextureProperty>();
MaterialShaderList = new List<MaterialShader>();
ProjectorPropertyList = new List<ProjectorProperty>();
}

/// <summary>
Expand Down Expand Up @@ -217,5 +222,31 @@ public MaterialShader(int? renderQueue)
/// <returns></returns>
public bool NullCheck() => ShaderName.IsNullOrEmpty() && RenderQueue == null;
}

/// <summary>
/// Data storage class for projector properties
/// </summary>
public class ProjectorProperty
{
/// <summary>
/// Name of the property
/// </summary>
public MaterialAPI.ProjectorProperties Property;
/// <summary>
/// Value
/// </summary>
public float Value;

/// <summary>
/// Data storage class for projector properties
/// </summary>
/// <param name="property">Name of the property</param>
/// <param name="value">Value</param>
public ProjectorProperty(MaterialAPI.ProjectorProperties property, float value)
{
Property = property;
Value = value;
}
}
}
}
1 change: 1 addition & 0 deletions src/MaterialEditor.Base/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public static void Randomize<T>(this IList<T> list)
public static string NameFormatted(this GameObject go) => go == null ? "" : go.name.Replace("(Instance)", "").Replace(" Instance", "").Trim();
public static string NameFormatted(this Material go) => go == null ? "" : go.name.Replace("(Instance)", "").Replace(" Instance", "").Trim();
public static string NameFormatted(this Renderer go) => go == null ? "" : go.name.Replace("(Instance)", "").Replace(" Instance", "").Trim();
public static string NameFormatted(this Projector go) => go == null ? "" : go.name.Replace("(Instance)", "").Replace(" Instance", "").Trim();
public static string NameFormatted(this Shader go) => go == null ? "" : go.name.Replace("(Instance)", "").Replace(" Instance", "").Trim();
public static string NameFormatted(this Mesh go) => go == null ? "" : go.name.Replace("(Instance)", "").Replace(" Instance", "").Trim();
/// <summary>
Expand Down
274 changes: 273 additions & 1 deletion src/MaterialEditor.Base/MaterialAPI.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;

namespace MaterialEditorAPI
Expand All @@ -10,6 +9,12 @@ namespace MaterialEditorAPI
/// </summary>
public static class MaterialAPI
{
/// <summary>
/// Projector materials share an instance by default, unlike renderers which get a unique one by default.
/// This list keeps track of every projector and it's new unique material instance
/// </summary>
internal static readonly Dictionary<Projector, Material> ProjectorMaterialInstances = new Dictionary<Projector, Material>();

/// <summary>
/// Postfix added to the name of a material when copied
/// </summary>
Expand All @@ -26,6 +31,30 @@ public static IEnumerable<Renderer> GetRendererList(GameObject gameObject)
return gameObject.GetComponentsInChildren<Renderer>(true);
}

/// <summary>
/// Get a list of all the projectors of a GameObject
/// </summary>
public static IEnumerable<Projector> GetProjectorList(GameObject gameObject, bool inChildren = false)
{
if (gameObject == null)
return new List<Projector>();

IEnumerable<Projector> projectors;
if(inChildren)
projectors = gameObject.GetComponentsInChildren<Projector>(true);
else
projectors = gameObject.GetComponents<Projector>();

//Assign a unique copy of the material if the projector didn't have one already
foreach (var projector in projectors)
if (!ProjectorMaterialInstances.ContainsKey(projector))
{
projector.material = new Material(projector.material);
ProjectorMaterialInstances[projector] = projector.material;
}
return projectors;
}

/// <summary>
/// Get a list of materials for the renderer
/// </summary>
Expand Down Expand Up @@ -58,6 +87,9 @@ private static List<Material> GetObjectMaterials(GameObject gameObject, string m
if (material.NameFormatted() == materialName)
materials.Add(material);

foreach (var projector in GetProjectorList(gameObject))
ManlyMarco marked this conversation as resolved.
Show resolved Hide resolved
materials.Add(projector.material);

return materials;
}

Expand Down Expand Up @@ -396,6 +428,204 @@ public static bool SetRendererRecalculateNormals(GameObject gameObject, string r
return didSet;
}

/// <summary>
/// Set the value of the specified projector property
/// </summary>
/// <param name="gameObject">GameObject to search for the projector</param>
/// <param name="projectorName">Name of the projector being modified</param>
/// <param name="propertyName">Property of the projector being modified</param>
/// <param name="value">Value to be set</param>
/// <returns>True if the value was set, false if it could not be set</returns>
public static bool SetProjectorProperty(GameObject gameObject, string projectorName, ProjectorProperties propertyName, float value)
{
if (propertyName == ProjectorProperties.Enabled)
return SetProjectorEnabled(gameObject, projectorName, System.Convert.ToBoolean(value));
else if (propertyName == ProjectorProperties.FarClipPlane)
return SetProjectorFarClipPlane(gameObject, projectorName, value);
else if (propertyName == ProjectorProperties.NearClipPlane)
return SetProjectorNearClipPlane(gameObject, projectorName, value);
else if (propertyName == ProjectorProperties.FieldOfView)
return SetProjectorFieldOfView(gameObject, projectorName, value);
else if (propertyName == ProjectorProperties.AspectRatio)
return SetProjectorAspectRatio(gameObject, projectorName, value);
else if (propertyName == ProjectorProperties.Orthographic)
return SetProjectorOrthographic(gameObject, projectorName, System.Convert.ToBoolean(value));
else if (propertyName == ProjectorProperties.OrthographicSize)
return SetProjectorOrthographicSize(gameObject, projectorName, value);
else if (propertyName == ProjectorProperties.IgnoreCharaLayer)
return SetProjectorIgnoreLayers(gameObject, projectorName, System.Convert.ToBoolean(value), 10);
else if (propertyName == ProjectorProperties.IgnoreMapLayer)
return SetProjectorIgnoreLayers(gameObject, projectorName, System.Convert.ToBoolean(value), 11);
return false;
}

/// <summary>
/// Set the enabled property of a projector
/// </summary>
/// <param name="gameObject">GameObject to search for the renderer</param>
/// <param name="projectorName">Name of the renderer being modified</param>
/// <param name="value">Value to be set</param>
/// <returns>True if the value was set, false if it could not be set</returns>
public static bool SetProjectorEnabled(GameObject gameObject, string projectorName, bool value)
{
foreach (var projector in GetProjectorList(gameObject))
{
if (projector.NameFormatted() == projectorName)
{
projector.enabled = value;
return true;
}
}
return false;
}

/// <summary>
/// Set the farclipPlane property of a projector
/// </summary>
/// <param name="gameObject">GameObject to search for the projector</param>
/// <param name="projectorName">Name of the projector being modified</param>
/// <param name="value">Value to be set</param>
/// <returns>True if the value was set, false if it could not be set</returns>
public static bool SetProjectorFarClipPlane(GameObject gameObject, string projectorName, float value)
{
foreach(var projector in GetProjectorList(gameObject))
{
if(projector.NameFormatted() == projectorName)
{
projector.farClipPlane = value;
return true;
}
}
return false;
}

/// <summary>
/// Set the nearClipPlane property of a projector
/// </summary>
/// <param name="gameObject">GameObject to search for the projector</param>
/// <param name="projectorName">Name of the projector being modified</param>
/// <param name="value">Value to be set</param>
/// <returns>True if the value was set, false if it could not be set</returns>
public static bool SetProjectorNearClipPlane(GameObject gameObject, string projectorName, float value)
{
foreach (var projector in GetProjectorList(gameObject))
{
if (projector.NameFormatted() == projectorName)
{
projector.nearClipPlane = value;
return true;
}
}
return false;
}

/// <summary>
/// Set the fieldOfView property of a projector
/// </summary>
/// <param name="gameObject">GameObject to search for the projector</param>
/// <param name="projectorName">Name of the projector being modified</param>
/// <param name="value">Value to be set</param>
/// <returns>True if the value was set, false if it could not be set</returns>
public static bool SetProjectorFieldOfView(GameObject gameObject, string projectorName, float value)
{
foreach (var projector in GetProjectorList(gameObject))
{
if (projector.NameFormatted() == projectorName)
{
projector.fieldOfView = value;
return true;
}
}
return false;
}

/// <summary>
/// Set the aspectRatio property of a projector
/// </summary>
/// <param name="gameObject">GameObject to search for the projector</param>
/// <param name="projectorName">Name of the projector being modified</param>
/// <param name="value">Value to be set</param>
/// <returns>True if the value was set, false if it could not be set</returns>
public static bool SetProjectorAspectRatio(GameObject gameObject, string projectorName, float value)
{
foreach (var projector in GetProjectorList(gameObject))
{
if (projector.NameFormatted() == projectorName)
{
projector.aspectRatio = value;
return true;
}
}
return false;
}

/// <summary>
/// Set the orthographic property of a projector
/// </summary>
/// <param name="gameObject">GameObject to search for the projector</param>
/// <param name="projectorName">Name of the projector being modified</param>
/// <param name="value">Value to be set</param>
/// <returns>True if the value was set, false if it could not be set</returns>
public static bool SetProjectorOrthographic(GameObject gameObject, string projectorName, bool value)
{
foreach (var projector in GetProjectorList(gameObject))
{
if (projector.NameFormatted() == projectorName)
{
projector.orthographic = value;
return true;
}
}
return false;
}

/// <summary>
/// Set the orthoGraphicSize property of a projector
/// </summary>
/// <param name="gameObject">GameObject to search for the projector</param>
/// <param name="projectorName">Name of the projector being modified</param>
/// <param name="value">Value to be set</param>
/// <returns>True if the value was set, false if it could not be set</returns>
public static bool SetProjectorOrthographicSize(GameObject gameObject, string projectorName, float value)
{
foreach (var projector in GetProjectorList(gameObject))
{
if (projector.NameFormatted() == projectorName)
{
projector.orthographicSize = value;
return true;
}
}
return false;
}

/// <summary>
/// Add or remove the given layer to/from the ignored layers property.
/// Ensures it's not removed/added that was already the case
/// </summary>
/// <param name="gameObject">GameObject to search for the projector</param>
/// <param name="projectorName">Name of the projector being modified</param>
/// <param name="ignore">If the given layer should be ignored or not</param>
/// <param name="layer">The index of the layer to be added/removed</param>
/// <returns>True if the value was set, false if it could not be set</returns>
public static bool SetProjectorIgnoreLayers(GameObject gameObject, string projectorName, bool ignore, int layer)
{
foreach (var projector in GetProjectorList(gameObject))
{
if (projector.NameFormatted() == projectorName)
{
bool inMask = projector.ignoreLayers == (projector.ignoreLayers | (1 << layer));
//Remove layer from mask
if (inMask && !ignore)
projector.ignoreLayers &= ~(1 << layer);
//Add layer to mask
else if(!inMask && ignore)
projector.ignoreLayers |= (1 << layer);
}
}
return false;
}

/// <summary>
/// Set the texture property of a material
/// </summary>
Expand Down Expand Up @@ -625,5 +855,47 @@ public enum RendererProperties
/// </summary>
UpdateWhenOffscreen
}
/// <summary>
/// Properties of a projector that can be set
/// </summary>
public enum ProjectorProperties
{
/// <summary>
/// Whether the projector is enabled
/// </summary>
Enabled,
/// <summary>
/// Near clip plane to start projecting
/// </summary>
NearClipPlane,
/// <summary>
/// Far clip plane to stop projecting
/// </summary>
FarClipPlane,
/// <summary>
/// Field of View of projection
/// </summary>
FieldOfView,
/// <summary>
/// Aspect ratio of the projection
/// </summary>
AspectRatio,
/// <summary>
/// Whether the projector should project in orthographic mode
/// </summary>
Orthographic,
/// <summary>
/// The size of the orthographic projection
/// </summary>
OrthographicSize,
/// <summary>
/// If the projector should ignore objects on the chara layer
/// </summary>
IgnoreCharaLayer,
/// <summary>
/// If the projector should ignore objects on the map layer
/// </summary>
IgnoreMapLayer
}
}
}
Loading