portals and dash. Also a bit of terrain building and level design

This commit is contained in:
2022-03-13 00:26:35 +02:00
parent 813cd0c451
commit e82799c36a
6242 changed files with 2160679 additions and 188245 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 77c593e5314781d4aa291761be14e03e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,184 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine.SocialPlatforms;
namespace Pinwheel.Poseidon
{
public class PAreaEditingGUIDrawer
{
private PWater water;
private int selectedAnchorIndex;
public PAreaEditingGUIDrawer(PWater water)
{
this.water = water;
selectedAnchorIndex = -1;
}
public void Draw()
{
if (Event.current == null)
return;
HandleSelectTranslateRemoveAnchors();
HandleAddAnchor();
DrawInstruction();
CatchHotControl();
}
private void HandleSelectTranslateRemoveAnchors()
{
List<Vector3> localPositions = water.AreaMeshAnchors;
if (localPositions.Count == 0)
return;
if (localPositions.Count >= 2)
{
List<Vector3> worldPositions = new List<Vector3>();
for (int i = 0; i < localPositions.Count; ++i)
{
worldPositions.Add(water.transform.TransformPoint(localPositions[i]));
}
Handles.DrawPolyLine(worldPositions.ToArray());
Handles.DrawLine(worldPositions[0], worldPositions[worldPositions.Count - 1]);
}
for (int i = 0; i < localPositions.Count; ++i)
{
Vector3 localPos = localPositions[i];
Vector3 worldPos = water.transform.TransformPoint(localPos);
float handleSize = HandleUtility.GetHandleSize(worldPos) * 0.2f;
if (i == selectedAnchorIndex)
{
Handles.color = Handles.selectedColor;
Handles.SphereHandleCap(0, worldPos, Quaternion.identity, handleSize, EventType.Repaint);
worldPos = Handles.PositionHandle(worldPos, Quaternion.identity);
localPos = water.transform.InverseTransformPoint(worldPos);
localPos.y = 0;
localPositions[i] = localPos;
}
else
{
Handles.color = Color.cyan;
if (Handles.Button(worldPos, Quaternion.identity, handleSize, handleSize * 0.5f, Handles.SphereHandleCap))
{
if (Event.current.control)
{
selectedAnchorIndex = -1;
localPositions.RemoveAt(i);
}
else
{
selectedAnchorIndex = i;
}
}
}
}
if (Event.current.type == EventType.MouseUp && Event.current.button == 0)
{
selectedAnchorIndex = -1;
}
}
private void HandleAddAnchor()
{
if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
{
Plane plane = new Plane(Vector3.up, water.transform.position);
Ray r = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
float distance = -1;
if (plane.Raycast(r, out distance))
{
Vector3 hitWorldPos = r.origin + r.direction * distance;
Vector3 hitLocalPos = water.transform.InverseTransformPoint(hitWorldPos);
if (Event.current.shift)
{
water.AreaMeshAnchors.Add(hitLocalPos);
}
}
}
}
private void VisualizeIntersections()
{
if (water.AreaMeshAnchors.Count < 3)
return;
Plane plane = new Plane(Vector3.up, water.transform.position);
Ray r = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
float distance = -1;
if (plane.Raycast(r, out distance))
{
Vector3 hitWorldPos = r.origin + r.direction * distance;
float lineY = hitWorldPos.z;
Handles.color = Color.red;
Handles.DrawLine(new Vector3(-100, 0, lineY), new Vector3(100, 0, lineY));
List<Vector3> intersections = new List<Vector3>();
List<Vector3> anchors = new List<Vector3>(water.AreaMeshAnchors);
anchors.Add(water.AreaMeshAnchors[0]);
for (int i = 0; i < anchors.Count - 1; ++i)
{
Vector3 a0 = anchors[i];
Vector3 a1 = anchors[i + 1];
Vector2 inter;
if (PGeometryUtilities.IsIntersectHorizontalLine(a0.x, a0.z, a1.x, a1.z, lineY, out inter))
{
intersections.Add(new Vector3(inter.x, 0, inter.y));
}
}
for (int i = 0; i < intersections.Count; ++i)
{
Handles.color = Color.red;
Handles.CubeHandleCap(0, intersections[i], Quaternion.identity, 1, EventType.Repaint);
}
}
}
private void DrawInstruction()
{
string s = string.Format(
"{0}" +
"{1}" +
"{2}" +
"{3}",
"Click to select,",
"\nShift+Click to add,",
"\nCtrl+Click to remove anchor.",
"\nClick End Editing Tiles when done.");
GUIContent mouseMessage = new GUIContent(s);
PEditorCommon.SceneViewMouseMessage(mouseMessage);
}
private void CatchHotControl()
{
int controlId = GUIUtility.GetControlID(this.GetHashCode(), FocusType.Passive);
if (Event.current.type == EventType.MouseDown)
{
if (Event.current.button == 0)
{
GUIUtility.hotControl = controlId;
//OnMouseDown(Event.current);
}
}
else if (Event.current.type == EventType.MouseUp)
{
if (GUIUtility.hotControl == controlId)
{
//OnMouseUp(Event.current);
//Return the hot control back to Unity, use the default
GUIUtility.hotControl = 0;
}
}
else if (Event.current.type == EventType.KeyDown)
{
//OnKeyDown(Event.current);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2a8144486c5466742ba52c5dcef76990
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,63 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.Callbacks;
namespace Pinwheel.Poseidon
{
internal class PCompileLogger
{
private const string PACKAGE_NAME = "Poseidon - Low Poly Water System";
private const string PACKAGE_NAME_PLACEHOLDER = "${PACKAGE_NAME}";
private const string WEBSITE = "http://pinwheel.studio";
private const string WEBSITE_PLACEHOLDER = "${WEBSITE}";
private const string SUPPORT_MAIL = "support@pinwheel.studio";
private const string SUPPORT_MAIL_PLACEHOLDER = "${SUPPORT_MAIL}";
private const string LINK_COLOR = "blue";
private const string LINK_COLOR_PLACEHOLDER = "${LC}";
private const float LOG_MESSAGE_PROBABIILITY = 0.03F;
private static string[] messages = new string[]
{
"Thanks for using the ${PACKAGE_NAME}, please contact <color=${LC}>${SUPPORT_MAIL}</color> for support!",
"Thanks for using the ${PACKAGE_NAME}, please give it a 5-stars rating and a positive review on the store!"
};
//[DidReloadScripts]
public static void ShowMessageOnCompileSucceeded()
{
ValidatePackageAndNamespace();
if (Random.value < LOG_MESSAGE_PROBABIILITY)
{
if (messages.Length == 0)
return;
int msgIndex = Random.Range(0, messages.Length);
string msg = messages[msgIndex]
.Replace(PACKAGE_NAME_PLACEHOLDER, PVersionInfo.ProductNameAndVersionShort)
.Replace(WEBSITE_PLACEHOLDER, WEBSITE)
.Replace(SUPPORT_MAIL_PLACEHOLDER, SUPPORT_MAIL)
.Replace(LINK_COLOR_PLACEHOLDER, LINK_COLOR);
Debug.Log(msg, null);
}
}
private static void ValidatePackageAndNamespace()
{
bool isPackageNameInvalid = PACKAGE_NAME.Equals("PACKAGE_NAME");
bool isNamespaceInvalid = typeof(PCompileLogger).Namespace.Contains("PACKAGE_NAME");
if (isPackageNameInvalid)
{
string message = "<color=red>Invalid PACKAGE_NAME in CompileLogger, fix it before release!</color>";
Debug.Log(message);
}
if (isNamespaceInvalid)
{
string message = "<color=red>Invalid NAMESPACE in CompileLogger, fix it before release!</color>";
Debug.Log(message);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e965947bfaa45714a828aeb78f6f8190
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4bc1ffda7fc15ff4daf998b3db6956dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,133 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace Pinwheel.Poseidon
{
public static class PEditorMenus
{
[MenuItem("GameObject/3D Object/Poseidon/Calm Water")]
public static PWater CreateCalmWaterObject(MenuCommand cmd)
{
GameObject g = new GameObject("Calm Water");
if (cmd != null && cmd.context != null)
{
GameObject root = cmd.context as GameObject;
GameObjectUtility.SetParentAndAlign(g, root);
}
PWater waterComponent = g.AddComponent<PWater>();
PWaterProfile profile = PWaterProfile.CreateInstance<PWaterProfile>();
string fileName = "WaterProfile_" + PCommon.GetUniqueID();
string filePath = string.Format("Assets/{0}.asset", fileName);
AssetDatabase.CreateAsset(profile, filePath);
profile.CopyFrom(PPoseidonSettings.Instance.CalmWaterProfile);
waterComponent.Profile = profile;
waterComponent.TileSize = new Vector2(100, 100);
return waterComponent;
}
[MenuItem("GameObject/3D Object/Poseidon/Calm Water HQ")]
public static PWater CreateCalmWaterHQObject(MenuCommand cmd)
{
GameObject g = new GameObject("Calm Water HQ");
if (cmd != null && cmd.context != null)
{
GameObject root = cmd.context as GameObject;
GameObjectUtility.SetParentAndAlign(g, root);
}
PWater waterComponent = g.AddComponent<PWater>();
PWaterProfile profile = PWaterProfile.CreateInstance<PWaterProfile>();
string fileName = "WaterProfile_" + PCommon.GetUniqueID();
string filePath = string.Format("Assets/{0}.asset", fileName);
AssetDatabase.CreateAsset(profile, filePath);
profile.CopyFrom(PPoseidonSettings.Instance.CalmWaterHQProfile);
waterComponent.Profile = profile;
waterComponent.TileSize = new Vector2(100, 100);
return waterComponent;
}
[MenuItem("Window/Poseidon/Project/Settings")]
public static void ShowSettings()
{
Selection.activeObject = PPoseidonSettings.Instance;
EditorGUIUtility.PingObject(PPoseidonSettings.Instance);
}
[MenuItem("Window/Poseidon/Project/Update Dependencies")]
public static void UpdateDependencies()
{
PPackageInitializer.Init();
PWaterShaderProvider.ResetShaderReferences();
}
[MenuItem("Window/Poseidon/Project/Version Info")]
public static void ShowVersionInfo()
{
EditorUtility.DisplayDialog(
"Version Info",
PVersionInfo.ProductNameAndVersion,
"OK");
}
[MenuItem("Window/Poseidon/Learning Resources/Online Manual")]
public static void ShowOnlineUserGuide()
{
Application.OpenURL(PCommon.ONLINE_MANUAL);
}
[MenuItem("Window/Poseidon/Learning Resources/Youtube Channel")]
public static void ShowYoutubeChannel()
{
Application.OpenURL(PCommon.YOUTUBE_CHANNEL);
}
[MenuItem("Window/Poseidon/Learning Resources/Facebook Page")]
public static void ShowFacebookPage()
{
Application.OpenURL(PCommon.FACEBOOK_PAGE);
}
[MenuItem("Window/Poseidon/Community/Forum")]
public static void ShowForum()
{
Application.OpenURL(PCommon.FORUM);
}
[MenuItem("Window/Poseidon/Community/Discord")]
public static void ShowDiscord()
{
Application.OpenURL(PCommon.DISCORD);
}
[MenuItem("Window/Poseidon/Contact/Support")]
public static void ShowSupportEmailEditor()
{
PEditorCommon.OpenEmailEditor(
PCommon.SUPPORT_EMAIL,
"[Poseidon] SHORT_QUESTION_HERE",
"YOUR_QUESTION_IN_DETAIL");
}
[MenuItem("Window/Poseidon/Contact/Business")]
public static void ShowBusinessEmailEditor()
{
PEditorCommon.OpenEmailEditor(
PCommon.BUSINESS_EMAIL,
"[Poseidon] SHORT_MESSAGE_HERE",
"YOUR_MESSAGE_IN_DETAIL");
}
[MenuItem("Window/Poseidon/Write a Review")]
public static void OpenStorePage()
{
Application.OpenURL("http://u3d.as/1CsU");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4814c4364842e0a4a8a38e90ee72c35a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,102 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Callbacks;
using System;
using UnityEditor.PackageManager;
using UnityEditor.PackageManager.Requests;
namespace Pinwheel.Poseidon
{
public static class PPackageInitializer
{
public static string POSEIDON_KW = "POSEIDON";
public static string POSEIDON_URP_KW = "POSEIDON_URP";
private static ListRequest listPackageRequest = null;
#pragma warning disable 0414
private static bool isUrpInstalled = false;
private static bool isShaderGraphInstalled = false;
#pragma warning restore 0414
[DidReloadScripts]
public static void Init()
{
isUrpInstalled = false;
isShaderGraphInstalled = false;
CheckUnityPackagesAndInit();
}
private static void CheckUnityPackagesAndInit()
{
listPackageRequest = Client.List(true);
EditorApplication.update += OnRequestingPackageList;
}
private static void OnRequestingPackageList()
{
if (listPackageRequest == null)
return;
if (!listPackageRequest.IsCompleted)
return;
if (listPackageRequest.Error != null)
{
isUrpInstalled = false;
isShaderGraphInstalled = false;
}
else
{
isUrpInstalled = false;
isShaderGraphInstalled = false;
foreach (UnityEditor.PackageManager.PackageInfo p in listPackageRequest.Result)
{
if (p.name.Equals("com.unity.render-pipelines.universal"))
{
isUrpInstalled = true;
}
if (p.name.Equals("com.unity.shadergraph"))
{
isShaderGraphInstalled = true;
}
}
}
EditorApplication.update -= OnRequestingPackageList;
InitPackage();
}
private static void InitPackage()
{
BuildTarget buildTarget = EditorUserBuildSettings.activeBuildTarget;
BuildTargetGroup buildGroup = BuildPipeline.GetBuildTargetGroup(buildTarget);
string symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildGroup);
List<string> symbolList = new List<string>(symbols.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries));
bool isDirty = false;
if (!symbolList.Contains(POSEIDON_KW))
{
symbolList.Add(POSEIDON_KW);
isDirty = true;
}
if (isUrpInstalled && !symbolList.Contains(POSEIDON_URP_KW))
{
symbolList.Add(POSEIDON_URP_KW);
isDirty = true;
}
else if (!isUrpInstalled && symbolList.Contains(POSEIDON_URP_KW))
{
symbolList.RemoveAll(s => s.Equals(POSEIDON_URP_KW));
isDirty = true;
}
if (isDirty)
{
symbols = symbolList.ListElementsToString(";");
PlayerSettings.SetScriptingDefineSymbolsForGroup(buildGroup, symbols);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 24fc572b506f66a4b93162a883aaaea1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,24 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace Pinwheel.Poseidon
{
public struct PSelectionGridArgs
{
public ICollection collection;
public int selectedIndex;
public Vector2 tileSize;
public delegate void DrawHandler(Rect r, object o);
public DrawHandler drawPreviewFunction;
public DrawHandler drawLabelFunction;
public DrawHandler customDrawFunction;
public delegate object CategorizeHandler(object o);
public CategorizeHandler categorizeFunction;
public delegate string TooltipHandler(object o);
public TooltipHandler tooltipFunction;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6ab1fccc6c07924419849c24c11e351e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,364 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace Pinwheel.Poseidon
{
public class PSplineEditingGUIDrawer
{
private const float BEZIER_SELECT_DISTANCE = 10;
private const float BEZIER_WIDTH = 5;
private PWater water;
public int selectedAnchorIndex = -1;
public int selectedSegmentIndex = -1;
public PSplineEditingGUIDrawer(PWater water)
{
this.water = water;
}
public void Draw()
{
if (Event.current == null)
return;
//DrawDebug();
HandleSelectTransformRemoveAnchor();
HandleSelectTransformRemoveSegment();
HandleAddAnchor();
DrawPivot();
DrawInstruction();
CatchHotControl();
}
private void HandleSelectTransformRemoveAnchor()
{
List<PSplineAnchor> anchors = water.Spline.Anchors;
for (int i = 0; i < anchors.Count; ++i)
{
PSplineAnchor a = anchors[i];
Vector3 localPos = a.Position;
Vector3 worldPos = water.transform.TransformPoint(localPos);
float handleSize = HandleUtility.GetHandleSize(worldPos) * 0.2f;
if (i == selectedAnchorIndex)
{
Handles.color = Handles.selectedColor;
Handles.SphereHandleCap(0, worldPos, Quaternion.identity, handleSize, EventType.Repaint);
bool isGlobalRotation = Tools.pivotRotation == PivotRotation.Global;
EditorGUI.BeginChangeCheck();
if (Tools.current == Tool.Move)
{
worldPos = Handles.PositionHandle(worldPos, isGlobalRotation ? Quaternion.identity : a.Rotation);
localPos = water.transform.InverseTransformPoint(worldPos);
a.Position = localPos;
}
else if (Tools.current == Tool.Rotate && !PSplineToolConfig.Instance.AutoTangent)
{
a.Rotation = Handles.RotationHandle(a.Rotation, worldPos);
}
else if (Tools.current == Tool.Scale)
{
a.Scale = Handles.ScaleHandle(a.Scale, worldPos, isGlobalRotation ? Quaternion.identity : a.Rotation, HandleUtility.GetHandleSize(worldPos));
}
anchors[i] = a;
if (EditorGUI.EndChangeCheck())
{
if (PSplineToolConfig.Instance.AutoTangent)
{
water.Spline.SmoothTangents(selectedAnchorIndex);
}
List<int> segmentIndices = water.Spline.FindSegments(selectedAnchorIndex);
water.GenerateSplineMeshAtSegments(segmentIndices);
}
}
else
{
Handles.color = Color.cyan;
if (Handles.Button(worldPos, Quaternion.identity, handleSize, handleSize * 0.5f, Handles.SphereHandleCap))
{
if (Event.current.control)
{
selectedAnchorIndex = -1;
selectedSegmentIndex = -1;
water.Spline.RemoveAnchor(i);
}
else if (Event.current.shift)
{
if (selectedAnchorIndex != i &&
selectedAnchorIndex >= 0 &&
selectedAnchorIndex < anchors.Count)
{
water.Spline.AddSegment(selectedAnchorIndex, i);
if (PSplineToolConfig.Instance.AutoTangent)
{
int[] segmentsIndices = water.Spline.SmoothTangents(selectedAnchorIndex, i);
water.GenerateSplineMeshAtSegments(segmentsIndices);
}
else
{
water.GenerateSplineMeshAtSegment(water.Spline.Segments.Count - 1);
}
selectedAnchorIndex = i;
selectedSegmentIndex = -1;
}
}
else
{
selectedAnchorIndex = i;
selectedSegmentIndex = -1;
}
Event.current.Use();
}
}
}
}
private void HandleAddAnchor()
{
bool isLeftMouseUp = Event.current.type == EventType.MouseUp && Event.current.button == 0;
bool isShift = Event.current.shift;
if (!isLeftMouseUp)
return;
int raycastLayer = PSplineToolConfig.Instance.RaycastLayer;
Ray r = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
RaycastHit hit;
if (Physics.Raycast(r, out hit, 10000, LayerMask.GetMask(LayerMask.LayerToName(raycastLayer))))
{
if (!isShift)
{
selectedAnchorIndex = -1;
return;
}
Vector3 offset = Vector3.up * PSplineToolConfig.Instance.YOffset;
Vector3 worldPos = hit.point + offset;
Vector3 localPos = water.transform.InverseTransformPoint(worldPos);
PSplineAnchor a = new PSplineAnchor(localPos);
water.Spline.AddAnchor(a);
if (selectedAnchorIndex >= 0 && selectedAnchorIndex < water.Spline.Anchors.Count - 1)
{
water.Spline.AddSegment(selectedAnchorIndex, water.Spline.Anchors.Count - 1);
if (PSplineToolConfig.Instance.AutoTangent)
{
int[] segmentIndices = water.Spline.SmoothTangents(selectedAnchorIndex, water.Spline.Anchors.Count - 1);
water.GenerateSplineMeshAtSegments(segmentIndices);
}
else
{
water.GenerateSplineMeshAtSegment(water.Spline.Segments.Count - 1);
}
}
selectedAnchorIndex = water.Spline.Anchors.Count - 1;
Event.current.Use();
}
else
{
selectedAnchorIndex = -1;
}
}
private void HandleSelectTransformRemoveSegment()
{
List<PSplineSegment> segments = water.Spline.Segments;
List<PSplineAnchor> anchors = water.Spline.Anchors;
for (int i = 0; i < segments.Count; ++i)
{
if (!water.Spline.IsSegmentValid(i))
continue;
if (i == selectedSegmentIndex && !PSplineToolConfig.Instance.AutoTangent)
HandleSelectedSegmentModifications();
int i0 = segments[i].StartIndex;
int i1 = segments[i].EndIndex;
PSplineAnchor a0 = anchors[i0];
PSplineAnchor a1 = anchors[i1];
Vector3 startPosition = water.transform.TransformPoint(a0.Position);
Vector3 endPosition = water.transform.TransformPoint(a1.Position);
Vector3 startTangent = water.transform.TransformPoint(segments[i].StartTangent);
Vector3 endTangent = water.transform.TransformPoint(segments[i].EndTangent);
Color color = (i == selectedSegmentIndex) ?
Handles.selectedColor :
Color.white;
Color colorFade = new Color(color.r, color.g, color.b, color.a * 0.1f);
Vector3[] bezierPoints = Handles.MakeBezierPoints(startPosition, endPosition, startTangent, endTangent, 11);
Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual;
Handles.color = color;
Handles.DrawAAPolyLine(BEZIER_WIDTH, bezierPoints);
Handles.zTest = UnityEngine.Rendering.CompareFunction.Greater;
Handles.color = colorFade;
Handles.DrawAAPolyLine(BEZIER_WIDTH, bezierPoints);
Matrix4x4 localToWorld = water.transform.localToWorldMatrix;
Matrix4x4 splineToLocal = water.Spline.TRS(i, 0.5f);
Matrix4x4 splineToWorld = localToWorld * splineToLocal;
Vector3 arrow0 = splineToWorld.MultiplyPoint(Vector3.zero);
splineToLocal = water.Spline.TRS(i, 0.45f);
splineToWorld = localToWorld * splineToLocal;
Vector3 arrow1 = splineToWorld.MultiplyPoint(Vector3.left * 0.5f);
Vector3 arrow2 = splineToWorld.MultiplyPoint(Vector3.right * 0.5f);
Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual;
Handles.color = color;
Handles.DrawAAPolyLine(BEZIER_WIDTH, arrow1, arrow0, arrow2);
Handles.zTest = UnityEngine.Rendering.CompareFunction.Greater;
Handles.color = colorFade;
Handles.DrawAAPolyLine(BEZIER_WIDTH, arrow1, arrow0, arrow2);
if (Event.current.type == EventType.MouseUp && Event.current.button == 0)
{
float d0 = DistanceMouseToSpline(Event.current.mousePosition, bezierPoints);
float d1 = DistanceMouseToPoint(Event.current.mousePosition, bezierPoints[0]);
float d2 = DistanceMouseToPoint(Event.current.mousePosition, bezierPoints[bezierPoints.Length - 1]);
if (d0 <= BEZIER_SELECT_DISTANCE &&
d1 > BEZIER_SELECT_DISTANCE &&
d2 > BEZIER_SELECT_DISTANCE)
{
selectedSegmentIndex = i;
if (Event.current.control)
{
water.Spline.RemoveSegment(selectedSegmentIndex);
selectedSegmentIndex = -1;
GUI.changed = true;
}
//don't Use() the event here
}
else
{
if (selectedSegmentIndex == i)
{
selectedSegmentIndex = -1;
}
}
}
}
Handles.zTest = UnityEngine.Rendering.CompareFunction.Always;
}
private void HandleSelectedSegmentModifications()
{
if (selectedSegmentIndex < 0 || selectedSegmentIndex >= water.Spline.Segments.Count)
return;
if (!water.Spline.IsSegmentValid(selectedSegmentIndex))
return;
PSplineSegment segment = water.Spline.Segments[selectedSegmentIndex];
PSplineAnchor startAnchor = water.Spline.Anchors[segment.StartIndex];
PSplineAnchor endAnchor = water.Spline.Anchors[segment.EndIndex];
Vector3 worldStartPosition = water.transform.TransformPoint(startAnchor.Position);
Vector3 worldEndPosition = water.transform.TransformPoint(endAnchor.Position);
Vector3 worldStartTangent = water.transform.TransformPoint(segment.StartTangent);
Vector3 worldEndTangent = water.transform.TransformPoint(segment.EndTangent);
EditorGUI.BeginChangeCheck();
Handles.zTest = UnityEngine.Rendering.CompareFunction.Always;
worldStartTangent = Handles.PositionHandle(worldStartTangent, Quaternion.identity);
worldEndTangent = Handles.PositionHandle(worldEndTangent, Quaternion.identity);
segment.StartTangent = water.transform.InverseTransformPoint(worldStartTangent);
segment.EndTangent = water.transform.InverseTransformPoint(worldEndTangent);
if (EditorGUI.EndChangeCheck())
{
water.GenerateSplineMeshAtSegment(selectedSegmentIndex);
}
Handles.color = Color.white;
Handles.DrawLine(worldStartPosition, worldStartTangent);
Handles.DrawLine(worldEndPosition, worldEndTangent);
}
private void DrawPivot()
{
Vector3 pivot = water.transform.position;
float size = HandleUtility.GetHandleSize(pivot);
Vector3 xStart = pivot + Vector3.left * size;
Vector3 xEnd = pivot + Vector3.right * size;
Handles.zTest = UnityEngine.Rendering.CompareFunction.Always;
Handles.color = Handles.xAxisColor;
Handles.DrawLine(xStart, xEnd);
Vector3 yStart = pivot + Vector3.down * size;
Vector3 yEnd = pivot + Vector3.up * size;
Handles.color = Handles.yAxisColor;
Handles.DrawLine(yStart, yEnd);
Vector3 zStart = pivot + Vector3.back * size;
Vector3 zEnd = pivot + Vector3.forward * size;
Handles.color = Handles.zAxisColor;
Handles.DrawLine(zStart, zEnd);
}
private void DrawInstruction()
{
string s = string.Format(
"{0}" +
"{1}" +
"{2}" +
"{3}",
"Click to select,",
"\nShift+Click to add,",
"\nCtrl+Click to remove anchor.",
"\nClick End Editing Spline when done.");
GUIContent mouseMessage = new GUIContent(s);
PEditorCommon.SceneViewMouseMessage(mouseMessage);
}
private void CatchHotControl()
{
int controlId = GUIUtility.GetControlID(this.GetHashCode(), FocusType.Passive);
if (Event.current.type == EventType.MouseDown)
{
if (Event.current.button == 0)
{
GUIUtility.hotControl = controlId;
//OnMouseDown(Event.current);
}
}
else if (Event.current.type == EventType.MouseUp)
{
if (GUIUtility.hotControl == controlId)
{
//OnMouseUp(Event.current);
//Return the hot control back to Unity, use the default
GUIUtility.hotControl = 0;
}
}
else if (Event.current.type == EventType.KeyDown)
{
//OnKeyDown(Event.current);
}
}
public static float DistanceMouseToSpline(Vector2 mousePosition, params Vector3[] splinePoint)
{
float d = float.MaxValue;
for (int i = 0; i < splinePoint.Length - 1; ++i)
{
float d1 = HandleUtility.DistancePointToLineSegment(
mousePosition,
HandleUtility.WorldToGUIPoint(splinePoint[i]),
HandleUtility.WorldToGUIPoint(splinePoint[i + 1]));
if (d1 < d)
d = d1;
}
return d;
}
public static float DistanceMouseToPoint(Vector2 mousePosition, Vector3 worldPoint)
{
float d = Vector2.Distance(
mousePosition,
HandleUtility.WorldToGUIPoint(worldPoint));
return d;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 98ebbf81516ce744095876c548d6dbe4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,70 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Pinwheel.Poseidon;
namespace Pinwheel.Poseidon
{
//[CreateAssetMenu(menuName = "Poseidon/Spline Tool Config")]
public class PSplineToolConfig : ScriptableObject
{
private static PSplineToolConfig instance;
public static PSplineToolConfig Instance
{
get
{
if (instance==null)
{
instance = Resources.Load<PSplineToolConfig>("SplineToolConfig");
if (instance==null)
{
instance = ScriptableObject.CreateInstance<PSplineToolConfig>();
}
}
return instance;
}
}
[SerializeField]
private int raycastLayer;
public int RaycastLayer
{
get
{
return raycastLayer;
}
set
{
raycastLayer = value;
}
}
[SerializeField]
private float yOffset;
public float YOffset
{
get
{
return yOffset;
}
set
{
yOffset = value;
}
}
[SerializeField]
private bool autoTangent;
public bool AutoTangent
{
get
{
return autoTangent;
}
set
{
autoTangent = value;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 86645776c4e1905439fdfc64c6cc0794
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,135 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace Pinwheel.Poseidon
{
public class PTilesEditingGUIDrawer
{
private PWater water;
public PTilesEditingGUIDrawer(PWater water)
{
this.water = water;
}
public void Draw()
{
if (Event.current == null)
return;
DrawExistingTiles();
HandleAddRemoveTiles();
CatchHotControl();
}
private void DrawExistingTiles()
{
for (int i = 0; i < water.TileIndices.Count; ++i)
{
PIndex2D index = water.TileIndices[i];
Vector3 rectCenter = water.transform.TransformPoint(new Vector3(
(index.X + 0.5f) * water.TileSize.x,
0,
(index.Z + 0.5f) * water.TileSize.y));
Vector3 rectSize = water.transform.TransformVector(new Vector3(
water.TileSize.x,
0,
water.TileSize.y));
Handles.color = new Color(1, 1, 1, 0.05f);
Handles.zTest = UnityEngine.Rendering.CompareFunction.Greater;
Handles.DrawWireCube(rectCenter, rectSize);
Handles.color = new Color(1, 1, 1, 1);
Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual;
Handles.DrawWireCube(rectCenter, rectSize);
}
}
private void HandleAddRemoveTiles()
{
Plane plane = new Plane(Vector3.up, water.transform.position);
Ray r = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
float distance = -1;
if (plane.Raycast(r, out distance))
{
Vector3 hitWorldPos = r.origin + r.direction * distance;
Vector3 hitLocalPos = water.transform.InverseTransformPoint(hitWorldPos);
PIndex2D index = new PIndex2D(
Mathf.FloorToInt(hitLocalPos.x / water.TileSize.x),
Mathf.FloorToInt(hitLocalPos.z / water.TileSize.y));
Vector3 rectCenter = water.transform.TransformPoint(new Vector3(
(index.X + 0.5f) * water.TileSize.x,
hitLocalPos.y,
(index.Z + 0.5f) * water.TileSize.y));
Vector3 rectSize = water.transform.TransformVector(new Vector3(
water.TileSize.x,
0,
water.TileSize.y));
if (Event.current.type == EventType.MouseDrag || Event.current.type == EventType.MouseUp)
{
if (Event.current.button != 0)
return;
if (Event.current.control)
{
water.TileIndices.Remove(index);
water.ReCalculateBounds();
}
else if (Event.current.shift)
{
if (!water.TileIndices.Contains(index))
{
water.TileIndices.Add(index);
water.ReCalculateBounds();
}
}
PUtilities.MarkCurrentSceneDirty();
EditorUtility.SetDirty(water);
}
Handles.color = Handles.selectedColor;
Handles.DrawWireCube(rectCenter, rectSize);
string s = string.Format(
"{0}" +
"{1}" +
"{2}",
index.ToString(),
"\nShift+Click to pin, Ctrl+Click to unpin water planes.",
"\nClick End Editing Tiles when done.");
GUIContent mouseMessage = new GUIContent(s);
PEditorCommon.SceneViewMouseMessage(mouseMessage);
}
}
private void CatchHotControl()
{
int controlId = GUIUtility.GetControlID(this.GetHashCode(), FocusType.Passive);
if (Event.current.type == EventType.MouseDown)
{
if (Event.current.button == 0)
{
GUIUtility.hotControl = controlId;
//OnMouseDown(Event.current);
}
}
else if (Event.current.type == EventType.MouseUp)
{
if (GUIUtility.hotControl == controlId)
{
//OnMouseUp(Event.current);
//Return the hot control back to Unity, use the default
GUIUtility.hotControl = 0;
}
}
else if (Event.current.type == EventType.KeyDown)
{
//OnKeyDown(Event.current);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e796169c8ef1d6147bd2556326c1f222
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,958 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using Pinwheel.Poseidon.FX;
using UnityEngine.Rendering;
#if TEXTURE_GRAPH
using Pinwheel.TextureGraph;
#endif
namespace Pinwheel.Poseidon
{
[CustomEditor(typeof(PWater))]
public class PWaterInspector : Editor
{
private PWater water;
private PWaterProfile profile;
private bool willDrawDebugGUI = false;
private SerializedObject so;
private SerializedProperty reflectionLayersSO;
private SerializedProperty refractionLayersSO;
private readonly int[] renderTextureSizes = new int[] { 128, 256, 512, 1024, 2048 };
private readonly string[] renderTextureSizeLabels = new string[] { "128", "256", "512", "1024", "2048*" };
private readonly int[] meshTypes = new int[]
{
(int)PWaterMeshType.TileablePlane,
(int)PWaterMeshType.Area,
(int)PWaterMeshType.Spline,
(int)PWaterMeshType.CustomMesh
};
private readonly string[] meshTypeLabels = new string[]
{
"Tilealbe Plane",
"Area (Experimental)",
"Spline (Experimental)",
"Custom (Experimental)"
};
private bool isEditingTileIndices = false;
private bool isEditingAreaMesh = false;
private bool isEditingSplineMesh = false;
private PTilesEditingGUIDrawer tileEditingGUIDrawer;
private PAreaEditingGUIDrawer areaEditingGUIDrawer;
private PSplineEditingGUIDrawer splineEditingGUIDrawer;
private static Mesh quadMesh;
private static Mesh QuadMesh
{
get
{
if (quadMesh == null)
{
quadMesh = Resources.GetBuiltinResource<Mesh>("Quad.fbx");
}
return quadMesh;
}
}
private static Material maskVisualizerMaterial;
private static Material MaskVisualizerMaterial
{
get
{
if (maskVisualizerMaterial == null)
{
maskVisualizerMaterial = new Material(Shader.Find("Hidden/Poseidon/WaveMaskVisualizer"));
}
return maskVisualizerMaterial;
}
}
private enum PWaveMaskVisualizationMode
{
None,
//Flow,
Crest,
Height
}
private PWaveMaskVisualizationMode waveMaskVisMode;
private void OnEnable()
{
LoadPrefs();
water = target as PWater;
if (water.Profile != null)
{
water.ReCalculateBounds();
}
tileEditingGUIDrawer = new PTilesEditingGUIDrawer(water);
areaEditingGUIDrawer = new PAreaEditingGUIDrawer(water);
splineEditingGUIDrawer = new PSplineEditingGUIDrawer(water);
SceneView.duringSceneGui += DuringSceneGUI;
Camera.onPreCull += OnRenderCamera;
RenderPipelineManager.beginCameraRendering += OnRenderCameraSRP;
}
private void OnDisable()
{
SavePrefs();
isEditingTileIndices = false;
if (isEditingAreaMesh)
{
isEditingAreaMesh = false;
water.GenerateAreaMesh();
}
if (isEditingSplineMesh)
{
isEditingSplineMesh = false;
water.GenerateSplineMesh();
}
SceneView.duringSceneGui -= DuringSceneGUI;
Camera.onPreCull -= OnRenderCamera;
RenderPipelineManager.beginCameraRendering -= OnRenderCameraSRP;
}
private void LoadPrefs()
{
waveMaskVisMode = (PWaveMaskVisualizationMode)SessionState.GetInt("poseidon-wave-mask-vis-mode", 0);
}
private void SavePrefs()
{
SessionState.SetInt("poseidon-wave-mask-vis-mode", (int)waveMaskVisMode);
}
public override void OnInspectorGUI()
{
if (water.transform.rotation != Quaternion.identity)
{
string warning = "The water object is designed to work without rotation. Some features may not work correctly.";
EditorGUILayout.LabelField(warning, PEditorCommon.WarningLabel);
}
water.Profile = PEditorCommon.ScriptableObjectField<PWaterProfile>("Profile", water.Profile);
profile = water.Profile;
if (water.Profile == null)
return;
so = new SerializedObject(profile);
reflectionLayersSO = so.FindProperty("reflectionLayers");
refractionLayersSO = so.FindProperty("refractionLayers");
EditorGUI.BeginChangeCheck();
DrawMeshSettingsGUI();
DrawRenderingSettingsGUI();
DrawTimeSettingsGUI();
DrawColorsSettingsGUI();
DrawFresnelSettingsGUI();
DrawRippleSettingsGUI();
DrawWaveSettingsGUI();
DrawLightAbsorbtionSettingsGUI();
DrawFoamSettingsGUI();
DrawReflectionSettingsGUI();
DrawRefractionSettingsGUI();
DrawCausticSettingsGUI();
#if AURA_IN_PROJECT
if (PCommon.CurrentRenderPipeline == PRenderPipelineType.Builtin)
{
DrawAuraIntegrationSettingsGUI();
}
#endif
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(water);
EditorUtility.SetDirty(profile);
water.UpdateMaterial();
}
DrawEffectsGUI();
if (willDrawDebugGUI)
DrawDebugGUI();
if (so != null)
{
so.Dispose();
}
if (reflectionLayersSO != null)
{
reflectionLayersSO.Dispose();
}
if (refractionLayersSO != null)
{
refractionLayersSO.Dispose();
}
}
private void DrawEffectsGUI()
{
PWaterFX fx = water.GetComponent<PWaterFX>();
if (fx != null)
return;
string label = "Effects";
string id = "effects" + water.GetInstanceID();
PEditorCommon.Foldout(label, false, id, () =>
{
GUI.enabled = true;
if (PCommon.CurrentRenderPipeline == PRenderPipelineType.Builtin)
{
bool isStackV2Installed = false;
#if UNITY_POST_PROCESSING_STACK_V2
isStackV2Installed = true;
#endif
if (!isStackV2Installed)
{
EditorGUILayout.LabelField("Water effect need the Post Processing Stack V2 to work. Please install it using the Package Manager", PEditorCommon.WordWrapItalicLabel);
}
GUI.enabled = isStackV2Installed;
}
if (GUILayout.Button("Add Effects"))
{
fx = water.gameObject.AddComponent<PWaterFX>();
fx.Water = water;
}
GUI.enabled = true;
});
}
private void DrawMeshSettingsGUI()
{
string label = "Mesh";
string id = "water-profile-mesh";
GenericMenu menu = new GenericMenu();
menu.AddItem(
new GUIContent("Generate"),
false,
() => { water.GenerateMesh(); });
PEditorCommon.Foldout(label, true, id, () =>
{
if (water.MeshType == PWaterMeshType.TileablePlane)
{
DrawTilableMeshGUI();
}
else if (water.MeshType == PWaterMeshType.Area)
{
DrawAreaMeshGUI();
}
else if (water.MeshType == PWaterMeshType.Spline)
{
DrawSplineMeshGUI();
}
else if (water.MeshType == PWaterMeshType.CustomMesh)
{
DrawCustomMeshGUI();
}
}, menu);
}
private void DrawTilableMeshGUI()
{
if (!isEditingTileIndices)
{
EditorGUI.BeginChangeCheck();
//water.MeshType = (PWaterMeshType)EditorGUILayout.EnumPopup("Mesh Type", water.MeshType);
water.MeshType = (PWaterMeshType)EditorGUILayout.IntPopup("Mesh Type", (int)water.MeshType, meshTypeLabels, meshTypes);
water.PlanePattern = (PPlaneMeshPattern)EditorGUILayout.EnumPopup("Pattern", water.PlanePattern);
water.MeshResolution = EditorGUILayout.DelayedIntField("Resolution", water.MeshResolution);
if (EditorGUI.EndChangeCheck())
{
water.GenerateMesh();
water.ReCalculateBounds();
}
water.MeshNoise = EditorGUILayout.FloatField("Noise", water.MeshNoise);
EditorGUI.BeginChangeCheck();
water.TileSize = PEditorCommon.InlineVector2Field("Tile Size", water.TileSize);
water.TilesFollowMainCamera = EditorGUILayout.Toggle("Follow Main Camera", water.TilesFollowMainCamera);
SerializedObject so = new SerializedObject(water);
SerializedProperty sp = so.FindProperty("tileIndices");
if (sp != null)
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(sp, true);
if (EditorGUI.EndChangeCheck())
{
so.ApplyModifiedProperties();
}
}
sp.Dispose();
so.Dispose();
if (EditorGUI.EndChangeCheck())
{
water.ReCalculateBounds();
}
}
if (!isEditingTileIndices)
{
if (GUILayout.Button("Edit Tiles"))
{
isEditingTileIndices = true;
}
}
else
{
EditorGUILayout.LabelField("Edit water tiles in Scene View.", PEditorCommon.WordWrapItalicLabel);
if (GUILayout.Button("End Editing Tiles"))
{
isEditingTileIndices = false;
}
}
}
private void DrawAreaMeshGUI()
{
if (!isEditingAreaMesh)
{
EditorGUI.BeginChangeCheck();
//water.MeshType = (PWaterMeshType)EditorGUILayout.EnumPopup("Mesh Type", water.MeshType);
water.MeshType = (PWaterMeshType)EditorGUILayout.IntPopup("Mesh Type", (int)water.MeshType, meshTypeLabels, meshTypes);
water.MeshResolution = EditorGUILayout.DelayedIntField("Resolution", water.MeshResolution);
if (EditorGUI.EndChangeCheck())
{
water.GenerateMesh();
water.ReCalculateBounds();
}
water.MeshNoise = EditorGUILayout.FloatField("Noise", water.MeshNoise);
SerializedObject so = new SerializedObject(water);
SerializedProperty sp = so.FindProperty("areaMeshAnchors");
if (sp != null)
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(sp, true);
if (EditorGUI.EndChangeCheck())
{
so.ApplyModifiedProperties();
}
}
sp.Dispose();
so.Dispose();
}
if (!isEditingAreaMesh)
{
if (GUILayout.Button("Edit Area"))
{
isEditingAreaMesh = true;
}
}
else
{
if (GUILayout.Button("End Editing Area"))
{
isEditingAreaMesh = false;
water.GenerateAreaMesh();
water.ReCalculateBounds();
}
}
}
private void DrawSplineMeshGUI()
{
if (!isEditingSplineMesh)
{
EditorGUI.BeginChangeCheck();
//water.MeshType = (PWaterMeshType)EditorGUILayout.EnumPopup("Mesh Type", water.MeshType);
water.MeshType = (PWaterMeshType)EditorGUILayout.IntPopup("Mesh Type", (int)water.MeshType, meshTypeLabels, meshTypes);
water.SplineResolutionX = EditorGUILayout.DelayedIntField("Resolution X", water.SplineResolutionX);
water.SplineResolutionY = EditorGUILayout.DelayedIntField("Resolution Y", water.SplineResolutionY);
water.SplineWidth = EditorGUILayout.DelayedFloatField("Width", water.SplineWidth);
if (EditorGUI.EndChangeCheck())
{
water.GenerateMesh();
water.ReCalculateBounds();
}
//water.MeshNoise = EditorGUILayout.FloatField("Noise", water.MeshNoise);
}
if (!isEditingSplineMesh)
{
if (GUILayout.Button("Edit Spline"))
{
isEditingSplineMesh = true;
}
}
else
{
PSplineToolConfig.Instance.RaycastLayer = EditorGUILayout.LayerField("Raycast Layer", PSplineToolConfig.Instance.RaycastLayer);
PSplineToolConfig.Instance.YOffset = EditorGUILayout.FloatField("Y Offset", PSplineToolConfig.Instance.YOffset);
EditorGUI.BeginChangeCheck();
PSplineToolConfig.Instance.AutoTangent = EditorGUILayout.Toggle("Auto Tangent", PSplineToolConfig.Instance.AutoTangent);
if (EditorGUI.EndChangeCheck() && PSplineToolConfig.Instance.AutoTangent)
{
water.Spline.SmoothTangents();
water.GenerateSplineMesh();
water.ReCalculateBounds();
}
EditorUtility.SetDirty(PSplineToolConfig.Instance);
DrawSelectedAnchorGUI();
DrawSelectedSegmentGUI();
if (GUILayout.Button("Smooth Tangents"))
{
water.Spline.SmoothTangents();
water.GenerateSplineMesh();
water.ReCalculateBounds();
}
if (GUILayout.Button("Pivot To Spline Center"))
{
PSplineUtilities.WaterPivotToSplineCenter(water);
water.GenerateSplineMesh();
water.ReCalculateBounds();
}
if (GUILayout.Button("End Editing Spline"))
{
isEditingSplineMesh = false;
water.GenerateSplineMesh();
water.ReCalculateBounds();
}
}
}
private void DrawSelectedAnchorGUI()
{
int anchorIndex = splineEditingGUIDrawer.selectedAnchorIndex;
if (anchorIndex < 0 ||
anchorIndex >= water.Spline.Anchors.Count)
return;
string label = "Selected Anchor";
string id = "poseidon-selected-anchor";
PEditorCommon.Foldout(label, true, id, () =>
{
EditorGUI.indentLevel -= 1;
PSplineAnchor a = water.Spline.Anchors[anchorIndex];
EditorGUI.BeginChangeCheck();
a.Position = PEditorCommon.InlineVector3Field("Position", a.Position);
a.Rotation = Quaternion.Euler(PEditorCommon.InlineVector3Field("Rotation", a.Rotation.eulerAngles));
a.Scale = PEditorCommon.InlineVector3Field("Scale", a.Scale);
water.Spline.Anchors[anchorIndex] = a;
if (EditorGUI.EndChangeCheck())
{
if (PSplineToolConfig.Instance.AutoTangent)
{
int[] segmentIndices = water.Spline.SmoothTangents(anchorIndex);
water.GenerateSplineMeshAtSegments(segmentIndices);
}
else
{
List<int> segmentIndices = water.Spline.FindSegments(anchorIndex);
water.GenerateSplineMeshAtSegments(segmentIndices);
}
}
EditorGUI.indentLevel += 1;
});
}
private void DrawSelectedSegmentGUI()
{
int segmentIndex = splineEditingGUIDrawer.selectedSegmentIndex;
if (segmentIndex < 0 ||
segmentIndex >= water.Spline.Anchors.Count)
return;
string label = "Selected Segment";
string id = "poseidon-selected-segment";
PEditorCommon.Foldout(label, true, id, () =>
{
EditorGUI.indentLevel -= 1;
EditorGUI.BeginChangeCheck();
PSplineSegment s = water.Spline.Segments[segmentIndex];
GUI.enabled = !PSplineToolConfig.Instance.AutoTangent;
s.StartTangent = PEditorCommon.InlineVector3Field("Start Tangent", s.StartTangent);
s.EndTangent = PEditorCommon.InlineVector3Field("End Tangent", s.EndTangent);
GUI.enabled = true;
s.ResolutionMultiplierY = EditorGUILayout.Slider("Resolution Multiplier Y", s.ResolutionMultiplierY, 0f, 2f);
water.Spline.Segments[segmentIndex] = s;
if (EditorGUI.EndChangeCheck())
{
water.GenerateSplineMeshAtSegment(segmentIndex);
}
EditorGUI.indentLevel += 1;
});
}
private void DrawCustomMeshGUI()
{
EditorGUI.BeginChangeCheck();
//water.MeshType = (PWaterMeshType)EditorGUILayout.EnumPopup("Mesh Type", water.MeshType);
water.MeshType = (PWaterMeshType)EditorGUILayout.IntPopup("Mesh Type", (int)water.MeshType, meshTypeLabels, meshTypes);
water.SourceMesh = EditorGUILayout.ObjectField("Source Mesh", water.SourceMesh, typeof(Mesh), false) as Mesh;
if (EditorGUI.EndChangeCheck())
{
if (water.SourceMesh != null)
{
water.GenerateMesh();
}
water.ReCalculateBounds();
}
water.MeshNoise = EditorGUILayout.FloatField("Noise", water.MeshNoise);
}
private void DrawRenderingSettingsGUI()
{
string label = "Rendering";
string id = "water-profile-general";
PEditorCommon.Foldout(label, true, id, () =>
{
GUI.enabled = false;
EditorGUILayout.ObjectField("Material", water.MaterialToRender, typeof(Material), false);
if (water.MeshType == PWaterMeshType.TileablePlane && water.ShouldRenderBackface)
{
EditorGUILayout.ObjectField("Material Back Face", water.MaterialBackFace, typeof(Material), false);
}
GUI.enabled = true;
profile.RenderQueueIndex = EditorGUILayout.IntField("Queue Index", profile.RenderQueueIndex);
profile.LightingModel = (PLightingModel)EditorGUILayout.EnumPopup("Light Model", profile.LightingModel);
profile.UseFlatLighting = EditorGUILayout.Toggle("Flat Lighting", profile.UseFlatLighting);
if (water.MeshType == PWaterMeshType.TileablePlane)
{
water.ShouldRenderBackface = EditorGUILayout.Toggle("Render Back Face", water.ShouldRenderBackface);
}
});
}
private void DrawTimeSettingsGUI()
{
string label = "Time";
string id = "water-time";
PEditorCommon.Foldout(label, true, id, () =>
{
water.TimeMode = (PTimeMode)EditorGUILayout.EnumPopup("Time Mode", water.TimeMode);
if (water.TimeMode == PTimeMode.Auto)
{
EditorGUILayout.LabelField("Time", water.GetTimeParam().ToString());
}
else
{
water.ManualTimeSeconds = EditorGUILayout.FloatField("Time", (float)water.ManualTimeSeconds);
}
});
}
private void DrawColorsSettingsGUI()
{
string label = "Colors";
string id = "water-profile-colors";
PEditorCommon.Foldout(label, true, id, () =>
{
profile.Color = EditorGUILayout.ColorField("Color", profile.Color);
if (profile.EnableLightAbsorption)
{
profile.DepthColor = EditorGUILayout.ColorField("Depth Color", profile.DepthColor);
}
if (profile.LightingModel == PLightingModel.PhysicalBased || profile.LightingModel == PLightingModel.BlinnPhong)
{
//instance.SpecColor = EditorGUILayout.ColorField("Specular Color", instance.SpecColor);
profile.SpecColor = EditorGUILayout.ColorField(new GUIContent("Specular Color"), profile.SpecColor, true, false, true);
profile.Smoothness = EditorGUILayout.Slider("Smoothness", profile.Smoothness, 0f, 1f);
}
});
}
private void DrawFresnelSettingsGUI()
{
string label = "Fresnel";
string id = "water-profile-fresnel";
PEditorCommon.Foldout(label, true, id, () =>
{
profile.FresnelStrength = EditorGUILayout.Slider("Strength", profile.FresnelStrength, 0f, 10f);
profile.FresnelBias = EditorGUILayout.Slider("Bias", profile.FresnelBias, 0f, 1f);
});
}
private void DrawLightAbsorbtionSettingsGUI()
{
string label = "Light Absorption";
string id = "water-profile-absorption";
PEditorCommon.Foldout(label, true, id, () =>
{
profile.EnableLightAbsorption = EditorGUILayout.Toggle("Enable", profile.EnableLightAbsorption);
if (profile.EnableLightAbsorption)
{
profile.DepthColor = EditorGUILayout.ColorField("Depth Color", profile.DepthColor);
profile.MaxDepth = EditorGUILayout.FloatField("Max Depth", profile.MaxDepth);
}
});
}
private void DrawFoamSettingsGUI()
{
string label = "Foam";
string id = "water-profile-foam";
PEditorCommon.Foldout(label, true, id, () =>
{
profile.EnableFoam = EditorGUILayout.Toggle("Enable", profile.EnableFoam);
if (profile.EnableFoam)
{
profile.EnableFoamHQ = EditorGUILayout.Toggle("High Quality", profile.EnableFoamHQ);
if (profile.EnableFoamHQ)
{
profile.FoamNoiseScaleHQ = EditorGUILayout.FloatField("Scale", profile.FoamNoiseScaleHQ);
profile.FoamNoiseSpeedHQ = EditorGUILayout.FloatField("Speed", profile.FoamNoiseSpeedHQ);
}
profile.FoamColor = EditorGUILayout.ColorField(new GUIContent("Color"), profile.FoamColor, true, true, true);
PEditorCommon.Header("Shoreline");
profile.FoamDistance = EditorGUILayout.FloatField("Distance", profile.FoamDistance);
profile.ShorelineFoamStrength = EditorGUILayout.Slider("Strength", profile.ShorelineFoamStrength, 0f, 1f);
if (profile.EnableWave)
{
PEditorCommon.Header("Crest");
profile.CrestMaxDepth = EditorGUILayout.FloatField("Max Depth", profile.CrestMaxDepth);
profile.CrestFoamStrength = EditorGUILayout.Slider("Strength", profile.CrestFoamStrength, 0f, 1f);
}
if (water.MeshType == PWaterMeshType.Spline)
{
PEditorCommon.Header("Slope");
profile.SlopeFoamDistance = EditorGUILayout.FloatField("Distance", profile.SlopeFoamDistance);
profile.SlopeFoamFlowSpeed = EditorGUILayout.FloatField("Flow Speed", profile.SlopeFoamFlowSpeed);
profile.SlopeFoamStrength = EditorGUILayout.Slider("Strength", profile.SlopeFoamStrength, 0f, 1f);
}
}
});
}
private void DrawRippleSettingsGUI()
{
string label = "Ripple";
string id = "water-profile-ripple";
PEditorCommon.Foldout(label, true, id, () =>
{
profile.RippleHeight = EditorGUILayout.Slider("Height", profile.RippleHeight, 0f, 1f);
profile.RippleNoiseScale = EditorGUILayout.FloatField("Scale", profile.RippleNoiseScale);
profile.RippleSpeed = EditorGUILayout.FloatField("Speed", profile.RippleSpeed);
});
}
private void DrawWaveSettingsGUI()
{
string label = "Wave";
string id = "water-profile-wave";
PEditorCommon.Foldout(label, false, id, () =>
{
profile.EnableWave = EditorGUILayout.Toggle("Enable", profile.EnableWave);
if (profile.EnableWave)
{
profile.WaveDirection = EditorGUILayout.Slider("Direction", profile.WaveDirection, 0f, 360f);
profile.WaveSpeed = EditorGUILayout.FloatField("Speed", profile.WaveSpeed);
profile.WaveHeight = EditorGUILayout.FloatField("Height", profile.WaveHeight);
profile.WaveLength = EditorGUILayout.FloatField("Length", profile.WaveLength);
profile.WaveSteepness = EditorGUILayout.Slider("Steepness", profile.WaveSteepness, 0f, 1f);
profile.WaveDeform = EditorGUILayout.Slider("Deform", profile.WaveDeform, 0f, 1f);
water.UseWaveMask = EditorGUILayout.Toggle("Use Mask", water.UseWaveMask);
if (water.UseWaveMask)
{
waveMaskVisMode = (PWaveMaskVisualizationMode)EditorGUILayout.EnumPopup("Visualization", waveMaskVisMode);
EditorGUIUtility.wideMode = true;
water.WaveMaskBounds = EditorGUILayout.RectField("Bounds", water.WaveMaskBounds);
EditorGUIUtility.wideMode = false;
//#if TEXTURE_GRAPH
// water.UseEmbeddedWaveMask = EditorGUILayout.Toggle("Use Embedded Mask", water.UseEmbeddedWaveMask);
// if (water.UseEmbeddedWaveMask)
// {
// water.TextureGraphAsset = EditorGUILayout.ObjectField("Texture Graph Asset", water.TextureGraphAsset, typeof(TGraph), false) as TGraph;
// GUI.enabled = false;
// PEditorCommon.InlineTextureField("Mask", water.EmbeddedWaveMask, -1);
// GUI.enabled = water.TextureGraphAsset != null;
// if (GUILayout.Button("Embed Mask"))
// {
// water.EmbedWaveMask();
// }
// GUI.enabled = true;
// }
// else
//#endif
{
water.WaveMask = PEditorCommon.InlineTexture2DField("Mask", water.WaveMask, -1);
}
}
}
});
}
private void DrawReflectionSettingsGUI()
{
if (water.MeshType == PWaterMeshType.Spline)
return;
bool stereoEnable = false;
if (Camera.main != null)
{
stereoEnable = Camera.main.stereoEnabled;
}
string label = "Reflection" + (stereoEnable ? " (Not support for VR)" : "");
string id = "water-profile-reflection";
GUI.enabled = !stereoEnable;
PEditorCommon.Foldout(label, true, id, () =>
{
profile.EnableReflection = EditorGUILayout.Toggle("Enable", profile.EnableReflection);
if (profile.EnableReflection)
{
profile.ReflectCustomSkybox = EditorGUILayout.Toggle("Custom Skybox", profile.ReflectCustomSkybox);
profile.EnableReflectionPixelLight = EditorGUILayout.Toggle("Pixel Light", profile.EnableReflectionPixelLight);
profile.ReflectionClipPlaneOffset = EditorGUILayout.FloatField("Clip Plane Offset", profile.ReflectionClipPlaneOffset);
if (reflectionLayersSO != null)
{
EditorGUILayout.PropertyField(reflectionLayersSO);
}
so.ApplyModifiedProperties();
profile.ReflectionTextureResolution = EditorGUILayout.IntPopup("Resolution", profile.ReflectionTextureResolution, renderTextureSizeLabels, renderTextureSizes);
profile.ReflectionDistortionStrength = EditorGUILayout.FloatField("Distortion", profile.ReflectionDistortionStrength);
}
});
GUI.enabled = true;
}
private void DrawRefractionSettingsGUI()
{
string label = "Refraction";
string id = "water-profile-refraction";
PEditorCommon.Foldout(label, true, id, () =>
{
if (water.MeshType != PWaterMeshType.Spline)
{
profile.EnableRefraction = EditorGUILayout.Toggle("Enable", profile.EnableRefraction);
}
if (profile.EnableRefraction || water.MeshType == PWaterMeshType.Spline)
{
profile.RefractionDistortionStrength = EditorGUILayout.FloatField("Distortion", profile.RefractionDistortionStrength);
}
});
}
private void DrawCausticSettingsGUI()
{
string label = "Caustic";
string id = "water-profile-caustic";
PEditorCommon.Foldout(label, true, id, () =>
{
bool valid = (profile.EnableRefraction || water.MeshType == PWaterMeshType.Spline);
if (!valid)
{
EditorGUILayout.LabelField("Requires Refraction.", PEditorCommon.WordWrapItalicLabel);
profile.EnableCaustic = false;
}
GUI.enabled = valid;
profile.EnableCaustic = EditorGUILayout.Toggle("Enable", profile.EnableCaustic);
if (profile.EnableCaustic)
{
profile.CausticTexture = PEditorCommon.InlineTextureField("Texture", profile.CausticTexture, -1);
profile.CausticSize = EditorGUILayout.FloatField("Size", profile.CausticSize);
profile.CausticStrength = EditorGUILayout.Slider("Strength", profile.CausticStrength, 0f, 5f);
profile.CausticDistortionStrength = EditorGUILayout.FloatField("Distortion", profile.CausticDistortionStrength);
}
GUI.enabled = true;
});
}
#if AURA_IN_PROJECT
private void DrawAuraIntegrationSettingsGUI()
{
string label = "Aura 2 Integration";
string id = "water-profile-aura-integration";
PEditorCommon.Foldout(label, false, id, () =>
{
profile.ApplyAuraFog = EditorGUILayout.Toggle("Apply Fog", profile.ApplyAuraFog);
profile.ApplyAuraLighting = EditorGUILayout.Toggle("Apply Lighting", profile.ApplyAuraLighting);
if (profile.ApplyAuraLighting)
{
profile.AuraLightingFactor = EditorGUILayout.FloatField("Lighting Factor", profile.AuraLightingFactor);
}
});
}
#endif
private void DuringSceneGUI(SceneView sv)
{
Tools.hidden = isEditingTileIndices || isEditingAreaMesh || isEditingSplineMesh;
if (water.MeshType == PWaterMeshType.TileablePlane && isEditingTileIndices)
{
DrawEditingTilesGUI();
}
if (water.MeshType == PWaterMeshType.Area && isEditingAreaMesh)
{
DrawEditingAreaMeshGUI();
}
if (water.MeshType == PWaterMeshType.Spline && isEditingSplineMesh)
{
DrawEditingSplineGUI();
}
if (isEditingTileIndices || isEditingAreaMesh || isEditingSplineMesh)
{
DrawBounds();
}
bool isWaveSectionExpanded = PEditorCommon.IsFoldoutExpanded("water-profile-wave");
if (isWaveSectionExpanded && water.UseWaveMask)
{
DrawWaveMaskBounds();
}
}
private void DrawEditingTilesGUI()
{
tileEditingGUIDrawer.Draw();
}
private void DrawEditingAreaMeshGUI()
{
areaEditingGUIDrawer.Draw();
}
private void DrawEditingSplineGUI()
{
splineEditingGUIDrawer.Draw();
}
private void DrawBounds()
{
if (Event.current == null)
return;
if (water.Profile == null)
return;
Vector3 center = water.transform.TransformPoint(water.Bounds.center);
Vector3 size = water.transform.TransformVector(water.Bounds.size);
Handles.color = Color.yellow;
Handles.DrawWireCube(center, size);
}
private void DrawWaveMaskBounds()
{
if (Event.current == null)
return;
if (water.Profile == null)
return;
Vector2 center = water.WaveMaskBounds.center;
Vector3 worldCenter = new Vector3(center.x, water.transform.position.y, center.y);
Vector2 size = water.WaveMaskBounds.size;
Vector3 worldSize = new Vector3(size.x, 0.01f, size.y);
Handles.color = Color.cyan;
Handles.DrawWireCube(worldCenter, worldSize);
}
public void DrawDebugGUI()
{
string label = "Debug";
string id = "debug" + water.GetInstanceID().ToString();
PEditorCommon.Foldout(label, false, id, () =>
{
Camera[] cams = water.GetComponentsInChildren<Camera>();
for (int i = 0; i < cams.Length; ++i)
{
if (!cams[i].name.StartsWith("~"))
continue;
if (cams[i].targetTexture == null)
continue;
EditorGUILayout.LabelField(cams[i].name);
Rect r = GUILayoutUtility.GetAspectRect(1);
EditorGUI.DrawPreviewTexture(r, cams[i].targetTexture);
EditorGUILayout.Space();
}
});
}
public override bool RequiresConstantRepaint()
{
return willDrawDebugGUI;
}
private void OnRenderCamera(Camera cam)
{
bool isWaveSectionExpanded = PEditorCommon.IsFoldoutExpanded("water-profile-wave");
if (isWaveSectionExpanded && water.UseWaveMask)
{
if (waveMaskVisMode != PWaveMaskVisualizationMode.None)
{
Vector2 center = water.WaveMaskBounds.center;
Vector3 worldCenter = new Vector3(center.x, water.transform.position.y, center.y);
Vector2 size = water.WaveMaskBounds.size;
Vector3 worldSize = new Vector3(size.x, size.y, 1);
MaskVisualizerMaterial.SetTexture("_MainTex", water.WaveMask);
MaskVisualizerMaterial.DisableKeyword("FLOW");
MaskVisualizerMaterial.DisableKeyword("CREST");
MaskVisualizerMaterial.DisableKeyword("HEIGHT");
//if (waveMaskVisMode == PWaveMaskVisualizationMode.Flow)
//{
// MaskVisualizerMaterial.EnableKeyword("FLOW");
//}
//else
if (waveMaskVisMode == PWaveMaskVisualizationMode.Crest)
{
MaskVisualizerMaterial.EnableKeyword("CREST");
}
else if (waveMaskVisMode == PWaveMaskVisualizationMode.Height)
{
MaskVisualizerMaterial.EnableKeyword("HEIGHT");
}
Graphics.DrawMesh(
QuadMesh,
Matrix4x4.TRS(worldCenter, Quaternion.Euler(90, 0, 0), worldSize),
MaskVisualizerMaterial,
0,
cam,
0,
null,
ShadowCastingMode.Off,
false,
null,
LightProbeUsage.Off,
null);
}
}
}
private void OnRenderCameraSRP(ScriptableRenderContext context, Camera cam)
{
OnRenderCamera(cam);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 91dc0346f67e24246a4b9ca11000c0d0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace Pinwheel.Poseidon
{
[CustomEditor(typeof(PWaterProfile))]
public class PWaterProfileInspector : Editor
{
private PWaterProfile instance;
private void OnEnable()
{
instance = target as PWaterProfile;
}
public override void OnInspectorGUI()
{
EditorGUILayout.LabelField("Select the associated water in the scene to edit this profile.", PEditorCommon.WordWrapItalicLabel);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 09bf2b12f5c4f3047a75dc3c14800f5c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8766a47346cf5384e831a2fa74e14e1a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,170 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine.Rendering;
#if UNITY_POST_PROCESSING_STACK_V2
using UnityEngine.Rendering.PostProcessing;
#endif
#if POSEIDON_URP
using UnityEngine.Rendering.Universal;
using Pinwheel.Poseidon.FX.Universal;
#endif
using System.Reflection;
namespace Pinwheel.Poseidon.FX
{
[CustomEditor(typeof(PWaterFX))]
public class PWaterFXInspector : Editor
{
private PWaterFX instance;
private void OnEnable()
{
instance = target as PWaterFX;
SceneView.duringSceneGui += DuringSceneGUI;
if (instance.Profile != null)
{
instance.UpdatePostProcessOrVolumeProfile();
}
}
private void OnDisable()
{
SceneView.duringSceneGui -= DuringSceneGUI;
}
public override void OnInspectorGUI()
{
bool willDrawGUI = false;
string msg = null;
if (PCommon.CurrentRenderPipeline == PRenderPipelineType.Builtin)
{
#if UNITY_POST_PROCESSING_STACK_V2
willDrawGUI = true;
#else
msg = "Please install Post Processing Stack V2 to setup water effect";
#endif
}
else if (PCommon.CurrentRenderPipeline == PRenderPipelineType.Universal)
{
#if POSEIDON_URP
willDrawGUI = true;
#endif
}
else
{
willDrawGUI = false;
msg = "Water effect doesn't support custom render pipeline.";
}
if (!willDrawGUI)
{
EditorGUILayout.LabelField(msg, PEditorCommon.WordWrapItalicLabel);
return;
}
#if POSEIDON_URP
if (PCommon.CurrentRenderPipeline == PRenderPipelineType.Universal)
{
if (!CheckRendererFeatureConfig())
{
EditorGUILayout.LabelField("Please add a Water Effect Renderer Feature to the current URP Asset to setup water effect.", PEditorCommon.WordWrapItalicLabel);
return;
}
}
#endif
instance.Water = EditorGUILayout.ObjectField("Water", instance.Water, typeof(PWater), true) as PWater;
instance.Profile = PEditorCommon.ScriptableObjectField<PWaterFXProfile>("Profile", instance.Profile);
if (instance.Water == null || instance.Profile == null)
return;
DrawVolumesGUI();
EditorGUI.BeginChangeCheck();
PWaterFXProfileInspectorDrawer.Create(instance.Profile, instance.Water).DrawGUI();
if (EditorGUI.EndChangeCheck())
{
instance.UpdatePostProcessOrVolumeProfile();
}
DrawEventsGUI();
}
#if POSEIDON_URP
private bool CheckRendererFeatureConfig()
{
UniversalRenderPipelineAsset uAsset = UniversalRenderPipeline.asset;
ScriptableRenderer renderer = uAsset.scriptableRenderer;
PropertyInfo rendererFeaturesProperty = renderer.GetType().GetProperty("rendererFeatures", BindingFlags.Instance | BindingFlags.NonPublic);
if (rendererFeaturesProperty != null)
{
List<ScriptableRendererFeature> rendererFeatures = rendererFeaturesProperty.GetValue(renderer) as List<ScriptableRendererFeature>;
if (rendererFeatures != null)
{
bool waterFxFeatureAdded = false;
for (int i=0;i<rendererFeatures.Count;++i)
{
if (rendererFeatures[i] is PWaterEffectRendererFeature)
{
waterFxFeatureAdded = true;
}
}
return waterFxFeatureAdded;
}
}
return true;
}
#endif
private void DrawVolumesGUI()
{
string label = "Volumes";
string id = "volumes" + instance.GetInstanceID();
PEditorCommon.Foldout(label, false, id, () =>
{
instance.VolumeExtent = PEditorCommon.InlineVector3Field("Extent", instance.VolumeExtent);
instance.VolumeLayer = EditorGUILayout.LayerField("Layer", instance.VolumeLayer);
});
}
private void DrawEventsGUI()
{
string label = "Events";
string id = "events" + instance.GetInstanceID();
PEditorCommon.Foldout(label, false, id, () =>
{
SerializedObject so = new SerializedObject(instance);
SerializedProperty sp0 = so.FindProperty("onEnterWater");
if (sp0 != null)
{
EditorGUILayout.PropertyField(sp0);
}
SerializedProperty sp1 = so.FindProperty("onExitWater");
if (sp1 != null)
{
EditorGUILayout.PropertyField(sp1);
}
so.ApplyModifiedProperties();
});
}
private void DuringSceneGUI(SceneView sv)
{
if (instance.Water == null || instance.Profile == null)
return;
Bounds waterBounds = instance.Water.Bounds;
Vector3 size = waterBounds.size + instance.VolumeExtent;
Color color = Handles.yAxisColor;
Matrix4x4 matrix = Matrix4x4.TRS(waterBounds.center + instance.transform.position, instance.transform.rotation, instance.transform.localScale);
using (var scope = new Handles.DrawingScope(color, matrix))
{
Handles.DrawWireCube(Vector3.zero, size);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c3726835830f7544e8fb1a79548b2761
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace Pinwheel.Poseidon.FX
{
[CustomEditor(typeof(PWaterFXProfile))]
public class PWaterFXProfileInspector : Editor
{
private PWaterFXProfile instance;
private void OnEnable()
{
instance = target as PWaterFXProfile;
}
public override void OnInspectorGUI()
{
PWaterFXProfileInspectorDrawer.Create(instance, null).DrawGUI();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b29231a8f69bc3e46ba5e8c572478c00
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,114 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace Pinwheel.Poseidon.FX
{
public class PWaterFXProfileInspectorDrawer
{
private PWaterFXProfile instance;
private PWater water;
private PWaterFXProfileInspectorDrawer(PWaterFXProfile instance, PWater water)
{
this.instance = instance;
this.water = water;
}
public static PWaterFXProfileInspectorDrawer Create(PWaterFXProfile instance, PWater water)
{
return new PWaterFXProfileInspectorDrawer(instance, water);
}
public void DrawGUI()
{
EditorGUI.BeginChangeCheck();
DrawUnderwaterGUI();
DrawWetLensGUI();
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(instance);
}
}
private void DrawUnderwaterGUI()
{
string label = "Underwater";
string id = "underwater" + instance.GetInstanceID();
PEditorCommon.Foldout(label, false, id, () =>
{
instance.EnableUnderwater = EditorGUILayout.Toggle("Enable", instance.EnableUnderwater);
if (instance.EnableUnderwater)
{
PEditorCommon.SpacePixel(0);
EditorGUILayout.LabelField("Water Body", PEditorCommon.BoldHeader);
instance.UnderwaterMaxDepth = EditorGUILayout.FloatField("Max Depth", instance.UnderwaterMaxDepth);
instance.UnderwaterSurfaceColorBoost = EditorGUILayout.Slider("Surface Color Boost", instance.UnderwaterSurfaceColorBoost, 1f, 3f);
PEditorCommon.SpacePixel(0);
EditorGUILayout.LabelField("Fog", PEditorCommon.BoldHeader);
instance.UnderwaterShallowFogColor = EditorGUILayout.ColorField("Shallow Fog Color", instance.UnderwaterShallowFogColor);
instance.UnderwaterDeepFogColor = EditorGUILayout.ColorField("Deep Fog Color", instance.UnderwaterDeepFogColor);
instance.UnderwaterViewDistance = EditorGUILayout.FloatField("View Distance", instance.UnderwaterViewDistance);
PEditorCommon.SpacePixel(0);
EditorGUILayout.LabelField("Caustic", PEditorCommon.BoldHeader);
instance.UnderwaterEnableCaustic = EditorGUILayout.Toggle("Enable", instance.UnderwaterEnableCaustic);
if (instance.UnderwaterEnableCaustic)
{
instance.UnderwaterCausticTexture = PEditorCommon.InlineTextureField("Texture", instance.UnderwaterCausticTexture, -1);
instance.UnderwaterCausticSize = EditorGUILayout.FloatField("Size", instance.UnderwaterCausticSize);
instance.UnderwaterCausticStrength = EditorGUILayout.Slider("Strength", instance.UnderwaterCausticStrength, 0f, 1f);
}
PEditorCommon.SpacePixel(0);
EditorGUILayout.LabelField("Distortion", PEditorCommon.BoldHeader);
instance.UnderwaterEnableDistortion = EditorGUILayout.Toggle("Enable", instance.UnderwaterEnableDistortion);
if (instance.UnderwaterEnableDistortion)
{
instance.UnderwaterDistortionTexture = PEditorCommon.InlineTextureField("Normal Map", instance.UnderwaterDistortionTexture, -1);
instance.UnderwaterDistortionStrength = EditorGUILayout.FloatField("Strength", instance.UnderwaterDistortionStrength);
instance.UnderwaterWaterFlowSpeed = EditorGUILayout.FloatField("Water Flow Speed", instance.UnderwaterWaterFlowSpeed);
}
PEditorCommon.Separator();
}
if (water != null && instance.EnableUnderwater)
{
GUI.enabled = water.Profile != null;
if (GUILayout.Button("Inherit Parameters"))
{
instance.UnderwaterMaxDepth = water.Profile.MaxDepth;
instance.UnderwaterShallowFogColor = water.Profile.Color;
instance.UnderwaterDeepFogColor = water.Profile.DepthColor;
instance.UnderwaterEnableCaustic = water.Profile.EnableCaustic;
instance.UnderwaterCausticTexture = water.Profile.CausticTexture;
instance.UnderwaterCausticSize = water.Profile.CausticSize;
instance.UnderwaterCausticStrength = water.Profile.CausticStrength;
}
GUI.enabled = true;
}
});
}
private void DrawWetLensGUI()
{
string label = "Wet Lens";
string id = "wet-lens" + instance.GetInstanceID();
PEditorCommon.Foldout(label, false, id, () =>
{
instance.EnableWetLens = EditorGUILayout.Toggle("Enable", instance.EnableWetLens);
if (instance.EnableWetLens)
{
instance.WetLensNormalMap = PEditorCommon.InlineTextureField("Normal Map", instance.WetLensNormalMap, -1);
instance.WetLensStrength = EditorGUILayout.Slider("Strength", instance.WetLensStrength, 0f, 1f);
instance.WetLensDuration = EditorGUILayout.FloatField("Duration", instance.WetLensDuration);
instance.WetLensFadeCurve = EditorGUILayout.CurveField("Fade", instance.WetLensFadeCurve, Color.red, new Rect(0, 0, 1, 1));
}
});
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b391a0bf945395e44b4087de4fc66d76
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 639294d91651d874b9acb629cdc24635
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
#if UNITY_EDITOR && GRIFFIN
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace Pinwheel.Poseidon.GriffinExtension
{
public static class PGriffinExtensionCommon
{
public static PWater FindTargetWaterObject()
{
PWater[] waters = Object.FindObjectsOfType<PWater>();
for (int i=0;i<waters.Length;++i)
{
if (waters[i].gameObject.name.StartsWith("~"))
{
return waters[i];
}
}
return null;
}
public static PWater CreateTargetWaterObject()
{
PWater water = PEditorMenus.CreateCalmWaterHQObject(null);
water.name = "~PoseidonWater";
return water;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 443e1772d9e010648b32ed90a069b35e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,117 @@
#if UNITY_EDITOR && GRIFFIN
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace Pinwheel.Poseidon.GriffinExtension
{
//[CreateAssetMenu(menuName = "Poseidon/Water Quick Setup Config")]
public class PWaterQuickSetupConfig : ScriptableObject
{
private static PWaterQuickSetupConfig instance;
public static PWaterQuickSetupConfig Instance
{
get
{
if (instance == null)
{
instance = Resources.Load<PWaterQuickSetupConfig>("WaterQuickSetupConfig");
if (instance == null)
{
instance = ScriptableObject.CreateInstance<PWaterQuickSetupConfig>();
}
}
return instance;
}
}
[SerializeField]
private float waterLevel;
public float WaterLevel
{
get
{
return waterLevel;
}
set
{
waterLevel = value;
}
}
[SerializeField]
private int meshResolution;
public int MeshResolution
{
get
{
return meshResolution;
}
set
{
meshResolution = Mathf.Clamp(value, 2, 100);
if (meshResolution % 2 == 1)
{
meshResolution -= 1;
}
}
}
[SerializeField]
private float meshNoise;
public float MeshNoise
{
get
{
return meshNoise;
}
set
{
meshNoise = Mathf.Max(0, value);
}
}
[SerializeField]
private float approximateSizeX;
public float ApproximateSizeX
{
get
{
return approximateSizeX;
}
set
{
approximateSizeX = Mathf.Max(0, value);
}
}
[SerializeField]
private float approximateSizeZ;
public float ApproximateSizeZ
{
get
{
return approximateSizeZ;
}
set
{
approximateSizeZ = Mathf.Max(0, value);
}
}
[SerializeField]
private Vector2 tileSize;
public Vector2 TileSize
{
get
{
return tileSize;
}
set
{
tileSize = new Vector2(Mathf.Max(1, value.x), Mathf.Max(1, value.y));
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d7f31d2ebf097e84998b1e56436b331a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,255 @@
#if GRIFFIN && UNITY_EDITOR && POSEIDON
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using Pinwheel.Poseidon;
using Pinwheel.Griffin;
namespace Pinwheel.Poseidon.GriffinExtension
{
public static class PWaterQuickSetupGriffinExtension
{
private const string GX_POSEIDON_WATER_QUICK_SETUP = "http://bit.ly/2qb2gLO";
public static string GetExtensionName()
{
return "Poseidon - Water Quick Setup";
}
public static string GetPublisherName()
{
return "Pinwheel Studio";
}
public static string GetDescription()
{
return
"Quickly add low poly water which fit into your scene mood.";
}
public static string GetVersion()
{
return "v1.0.0";
}
public static void OpenSupportLink()
{
PEditorCommon.OpenEmailEditor(
"customer@pinwheel.studio",
"Griffin Extension - Poseidon",
"YOUR_MESSAGE_HERE");
}
public static void OnGUI()
{
PWater water = PGriffinExtensionCommon.FindTargetWaterObject();
if (water == null)
{
DrawCreateWaterGUI();
}
else
{
DrawWaterConfigGUI(water);
}
}
private static void DrawCreateWaterGUI()
{
if (GUILayout.Button("Add Low Poly Water"))
{
GAnalytics.Record(GX_POSEIDON_WATER_QUICK_SETUP);
InitDefaultConfigs();
AddWater();
}
}
private static void InitDefaultConfigs()
{
PWaterQuickSetupConfig config = PWaterQuickSetupConfig.Instance;
config.WaterLevel = 1;
config.MeshResolution = 100;
config.MeshNoise = 0;
Bounds levelBounds = GCommon.GetLevelBounds();
config.ApproximateSizeX = levelBounds.size.x;
config.ApproximateSizeZ = levelBounds.size.z;
config.TileSize = Vector2.one * 100;
}
private static void AddWater()
{
PWaterQuickSetupConfig config = PWaterQuickSetupConfig.Instance;
PWater water = PGriffinExtensionCommon.CreateTargetWaterObject();
water.TileSize = config.TileSize;
water.MeshResolution = config.MeshResolution;
water.MeshNoise = config.MeshNoise;
water.GeneratePlaneMesh();
CenterToLevel(water);
MatchWaterLevel(water);
MatchWaterSize(water);
Selection.activeGameObject = water.gameObject;
}
private static void CenterToLevel(PWater water)
{
PWaterQuickSetupConfig config = PWaterQuickSetupConfig.Instance;
Bounds levelBounds = GCommon.GetLevelBounds();
water.transform.position = new Vector3(levelBounds.center.x, config.WaterLevel, levelBounds.center.z);
}
private static void MatchWaterLevel(PWater water)
{
PWaterQuickSetupConfig config = PWaterQuickSetupConfig.Instance;
water.transform.position = new Vector3(water.transform.position.x, config.WaterLevel, water.transform.position.z);
}
private static void MatchWaterSize(PWater water)
{
PWaterQuickSetupConfig config = PWaterQuickSetupConfig.Instance;
water.TileSize = config.TileSize;
int radiusX = 1 + Mathf.FloorToInt(config.ApproximateSizeX * 0.5f / water.TileSize.x);
int radiusZ = 1 + Mathf.FloorToInt(config.ApproximateSizeZ * 0.5f / water.TileSize.y);
water.TileIndices.Clear();
for (int x = -radiusX; x < radiusX; ++x)
{
for (int z = -radiusZ; z < radiusZ; ++z)
{
water.TileIndices.AddIfNotContains(new PIndex2D(x, z));
}
}
}
private static void DrawWaterConfigGUI(PWater water)
{
DrawTemplateSelectionGUI(water);
PWaterQuickSetupConfig config = PWaterQuickSetupConfig.Instance;
bool changed = false;
bool meshChanged = false;
EditorGUI.BeginChangeCheck();
config.WaterLevel = EditorGUILayout.FloatField("Water Level", config.WaterLevel);
if (EditorGUI.EndChangeCheck())
{
changed = true;
}
EditorGUI.BeginChangeCheck();
config.MeshResolution = EditorGUILayout.DelayedIntField("Resolution", config.MeshResolution);
if (EditorGUI.EndChangeCheck())
{
meshChanged = true;
}
EditorGUI.BeginChangeCheck();
config.MeshNoise = EditorGUILayout.FloatField("Noise", config.MeshNoise);
config.ApproximateSizeX = EditorGUILayout.FloatField("Approx. Size X", config.ApproximateSizeX);
config.ApproximateSizeZ = EditorGUILayout.FloatField("Approx. Size Z", config.ApproximateSizeZ);
config.TileSize = PEditorCommon.InlineVector2Field("Tile Size", config.TileSize);
if (EditorGUI.EndChangeCheck())
{
changed = true;
}
if (meshChanged)
{
water.GeneratePlaneMesh();
}
if (changed || meshChanged)
{
water.MeshNoise = config.MeshNoise;
water.TileSize = config.TileSize;
water.UpdateMaterial();
MatchWaterLevel(water);
MatchWaterSize(water);
}
EditorUtility.SetDirty(config);
GEditorCommon.Separator();
if (GUILayout.Button("Center To Level Bounds"))
{
CenterToLevel(water);
}
if (GUILayout.Button("Fill Level Bounds"))
{
Bounds levelBounds = GCommon.GetLevelBounds();
config.ApproximateSizeX = levelBounds.size.x;
config.ApproximateSizeZ = levelBounds.size.z;
CenterToLevel(water);
MatchWaterSize(water);
}
if (GUILayout.Button("Done"))
{
Done(water);
}
}
private const string WATER_TEMPLATE_RESOURCES_PATH = "WaterTemplates";
private static Rect templatePopupRect;
private static void DrawTemplateSelectionGUI(PWater water)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Template");
Rect r = EditorGUILayout.GetControlRect();
if (Event.current.type == EventType.Repaint)
{
templatePopupRect = r;
}
if (GUI.Button(r, "Select", EditorStyles.popup))
{
GenericMenu menu = new GenericMenu();
PWaterProfile[] templates = Resources.LoadAll<PWaterProfile>(WATER_TEMPLATE_RESOURCES_PATH);
if (templates.Length == 0)
{
menu.AddDisabledItem(new GUIContent("No Template found!"));
}
else
{
for (int i = 0; i < templates.Length; ++i)
{
int index = i;
string label = templates[i].name.Replace("_", "/");
menu.AddItem(
new GUIContent(label),
false,
() =>
{
ApplyTemplate(water, templates[index]);
});
}
}
menu.DropDown(templatePopupRect);
}
EditorGUILayout.EndHorizontal();
}
private static void ApplyTemplate(PWater water, PWaterProfile template)
{
water.Profile.CopyFrom(template);
PWaterQuickSetupConfig config = PWaterQuickSetupConfig.Instance;
water.MeshResolution = config.MeshResolution;
water.MeshNoise = config.MeshNoise;
water.GeneratePlaneMesh();
water.UpdateMaterial();
water.TileSize = config.TileSize;
MatchWaterLevel(water);
MatchWaterSize(water);
}
private static void Done(PWater water)
{
water.name = water.name.Replace("~", "");
Selection.activeGameObject = water.gameObject;
EditorGUIUtility.PingObject(water.gameObject);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 855f18207cd40714aa5eb5abd870c2a7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: