去掉obi,使用自写绳索
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d5722720e25b4db69e767c6920cf081
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1af54f7feeec0410cada2fc051752b61
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa63386a67f904b399175c9931270250
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,40 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public abstract class ObiBlueprintEditorTool
|
||||
{
|
||||
protected ObiActorBlueprintEditor editor;
|
||||
protected string m_Name;
|
||||
protected Texture m_Icon;
|
||||
|
||||
public string name
|
||||
{
|
||||
get { return m_Name; }
|
||||
}
|
||||
|
||||
public Texture icon
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Icon;
|
||||
}
|
||||
}
|
||||
|
||||
public ObiBlueprintEditorTool(ObiActorBlueprintEditor editor)
|
||||
{
|
||||
this.editor = editor;
|
||||
}
|
||||
|
||||
public virtual void OnEnable(){}
|
||||
public virtual void OnDisable(){}
|
||||
public virtual void OnDestroy(){}
|
||||
public virtual string GetHelpString() { return string.Empty; }
|
||||
|
||||
public abstract void OnInspectorGUI();
|
||||
public virtual void OnSceneGUI(SceneView sceneView){}
|
||||
|
||||
public virtual bool Editable(int index) { return editor.visible[index]; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca0c1c4cbbd024d49b15bf3439506500
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,130 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiPaintBrushEditorTool : ObiBlueprintEditorTool
|
||||
{
|
||||
public ObiRaycastBrush paintBrush;
|
||||
public bool selectionMask = false;
|
||||
public int sourcePropertyIndex = 0; /**<index of the property to copy from*/
|
||||
|
||||
public ObiMeshBasedActorBlueprintEditor meshBasedEditor
|
||||
{
|
||||
get { return editor as ObiMeshBasedActorBlueprintEditor; }
|
||||
}
|
||||
|
||||
public ObiPaintBrushEditorTool(ObiMeshBasedActorBlueprintEditor editor) : base(editor)
|
||||
{
|
||||
|
||||
m_Icon = Resources.Load<Texture2D>("BrushIcon");
|
||||
m_Name = "Property painting";
|
||||
|
||||
paintBrush = new ObiRaycastBrush(editor.sourceMesh,
|
||||
() =>
|
||||
{
|
||||
// As RecordObject diffs with the end of the current frame,
|
||||
// and this is a multi-frame operation, we need to use RegisterCompleteObjectUndo instead.
|
||||
Undo.RegisterCompleteObjectUndo(editor.blueprint, "Paint particles");
|
||||
},
|
||||
() =>
|
||||
{
|
||||
editor.Refresh();
|
||||
},
|
||||
() =>
|
||||
{
|
||||
EditorUtility.SetDirty(editor.blueprint);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public override string GetHelpString()
|
||||
{
|
||||
return "Paint particle properties directly on the mesh. Most brushes have an alternate mode, accesed by holding 'shift' while painting.";
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// toolbar with available brush modes for the current property:
|
||||
editor.currentProperty.BrushModes(paintBrush);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
editor.currentPropertyIndex = editor.PropertySelector(editor.currentPropertyIndex);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
editor.Refresh();
|
||||
editor.currentProperty.OnSelect(paintBrush);
|
||||
}
|
||||
|
||||
if (paintBrush.brushMode is ObiFloatCopyBrushMode)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
sourcePropertyIndex = editor.PropertySelector(sourcePropertyIndex, "Copy from");
|
||||
var sourceProperty = editor.GetProperty(sourcePropertyIndex) as ObiBlueprintFloatProperty;
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
(paintBrush.brushMode as ObiFloatCopyBrushMode).source = sourceProperty;
|
||||
}
|
||||
if (sourceProperty == null)
|
||||
EditorGUILayout.HelpBox("You can't copy value from this property.", MessageType.Error);
|
||||
}
|
||||
|
||||
if (paintBrush.brushMode.needsInputValue)
|
||||
editor.currentProperty.PropertyField();
|
||||
|
||||
paintBrush.radius = EditorGUILayout.Slider("Brush size", paintBrush.radius, 0.0001f, 0.5f);
|
||||
paintBrush.innerRadius = EditorGUILayout.Slider("Brush inner size", paintBrush.innerRadius, 0, 1);
|
||||
paintBrush.opacity = EditorGUILayout.Slider("Brush opacity", paintBrush.opacity, 0, 1);
|
||||
paintBrush.mirror.axis = (ObiBrushMirrorSettings.MirrorAxis)EditorGUILayout.EnumPopup("Brush mirror axis", paintBrush.mirror.axis);
|
||||
paintBrush.mirror.space = (ObiBrushMirrorSettings.MirrorSpace)EditorGUILayout.EnumPopup("Brush mirror space", paintBrush.mirror.space);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
meshBasedEditor.particleCulling = (ObiMeshBasedActorBlueprintEditor.ParticleCulling)EditorGUILayout.EnumPopup("Culling", meshBasedEditor.particleCulling);
|
||||
if (ObiActorBlueprintEditor.selectedCount == 0)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Select at least one particle to use selection mask.", MessageType.Info);
|
||||
selectionMask = false;
|
||||
GUI.enabled = false;
|
||||
}
|
||||
selectionMask = EditorGUILayout.Toggle("Selection mask", selectionMask);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
SceneView.RepaintAll();
|
||||
GUI.enabled = true;
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
GUILayout.Box(GUIContent.none, ObiEditorUtils.GetSeparatorLineStyle());
|
||||
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
|
||||
editor.RenderModeSelector();
|
||||
editor.currentProperty.VisualizationOptions();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
public override bool Editable(int index)
|
||||
{
|
||||
return editor.visible[index] && (!selectionMask || ObiActorBlueprintEditor.selectionStatus[index]);
|
||||
}
|
||||
|
||||
public override void OnSceneGUI(SceneView view)
|
||||
{
|
||||
if (Camera.current != null)
|
||||
{
|
||||
var blueprint = meshBasedEditor.blueprint as ObiMeshBasedActorBlueprint;
|
||||
paintBrush.raycastTransform = blueprint != null ? Matrix4x4.TRS(Vector3.zero, blueprint.rotation, blueprint.scale) : Matrix4x4.identity;
|
||||
|
||||
paintBrush.raycastTarget = meshBasedEditor.sourceMesh;
|
||||
paintBrush.DoBrush(editor.blueprint.positions);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 332bb5fc94a774291b4c4ebe50f61205
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,336 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiParticleSelectionEditorTool : ObiBlueprintEditorTool
|
||||
{
|
||||
ObiScreenSpaceBrush selectionBrush;
|
||||
ObiSelectBrushMode selectMode;
|
||||
ObiTethersTool tethersTool;
|
||||
|
||||
protected ReorderableList particleGroupList;
|
||||
protected bool mixedPropertyValue = false;
|
||||
protected float minSelectionValue;
|
||||
protected float maxSelectionValue;
|
||||
|
||||
public ObiParticleSelectionEditorTool(ObiActorBlueprintEditor editor) : base(editor)
|
||||
{
|
||||
m_Icon = Resources.Load<Texture2D>("SelectIcon");
|
||||
m_Name = "Particle selection";
|
||||
|
||||
selectionBrush = new ObiScreenSpaceBrush(null, UpdateSelection, null);
|
||||
selectMode = new ObiSelectBrushMode(new ObiBlueprintSelected(editor));
|
||||
|
||||
selectionBrush.brushMode = selectMode;
|
||||
tethersTool = new ObiTethersTool();
|
||||
|
||||
InitializeGroupsList();
|
||||
}
|
||||
|
||||
|
||||
public override string GetHelpString()
|
||||
{
|
||||
if (ObiActorBlueprintEditor.selectedCount > 0)
|
||||
return "" + ObiActorBlueprintEditor.selectedCount + " selected particles.";
|
||||
else
|
||||
return "No particles selected. Click and drag over particles to select them.";
|
||||
}
|
||||
|
||||
private void InitializeGroupsList()
|
||||
{
|
||||
particleGroupList = new ReorderableList(editor.serializedObject,
|
||||
editor.serializedObject.FindProperty("groups"),
|
||||
false, true, true, true);
|
||||
|
||||
particleGroupList.drawHeaderCallback = (Rect rect) =>
|
||||
{
|
||||
EditorGUI.LabelField(rect, "Groups");
|
||||
};
|
||||
|
||||
particleGroupList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
|
||||
{
|
||||
var element = particleGroupList.serializedProperty.GetArrayElementAtIndex(index);
|
||||
rect.y += 4;
|
||||
|
||||
SerializedObject obj = new SerializedObject(element.objectReferenceValue);
|
||||
ObiParticleGroup group = obj.targetObject as ObiParticleGroup;
|
||||
|
||||
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight),
|
||||
obj.FindProperty("m_Name"), new GUIContent("Name"));
|
||||
rect.y += EditorGUIUtility.singleLineHeight + 2;
|
||||
|
||||
if (GUI.Button(new Rect(rect.x, rect.y, rect.width * 0.5f, EditorGUIUtility.singleLineHeight), "Select", EditorStyles.miniButtonLeft))
|
||||
{
|
||||
if ((Event.current.modifiers & EventModifiers.Shift) == 0)
|
||||
{
|
||||
for (int p = 0; p < ObiActorBlueprintEditor.selectionStatus.Length; p++)
|
||||
ObiActorBlueprintEditor.selectionStatus[p] = false;
|
||||
}
|
||||
|
||||
foreach (int p in group.particleIndices)
|
||||
ObiActorBlueprintEditor.selectionStatus[p] = true;
|
||||
|
||||
UpdateSelection();
|
||||
}
|
||||
|
||||
if (GUI.Button(new Rect(rect.x + rect.width * 0.5f, rect.y, rect.width * 0.5f, EditorGUIUtility.singleLineHeight), "Set", EditorStyles.miniButtonRight))
|
||||
{
|
||||
group.particleIndices.Clear();
|
||||
for (int p = 0; p < ObiActorBlueprintEditor.selectionStatus.Length; p++)
|
||||
{
|
||||
if (ObiActorBlueprintEditor.selectionStatus[p])
|
||||
group.particleIndices.Add(p);
|
||||
}
|
||||
}
|
||||
|
||||
obj.ApplyModifiedProperties();
|
||||
};
|
||||
|
||||
particleGroupList.elementHeight = (EditorGUIUtility.singleLineHeight + 2) * 2 + 8;
|
||||
|
||||
particleGroupList.onAddCallback = (ReorderableList list) =>
|
||||
{
|
||||
|
||||
var group = editor.blueprint.AppendNewParticleGroup("new group");
|
||||
|
||||
for (int i = 0; i < ObiActorBlueprintEditor.selectionStatus.Length; i++)
|
||||
{
|
||||
if (ObiActorBlueprintEditor.selectionStatus[i])
|
||||
group.particleIndices.Add(i);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
};
|
||||
|
||||
particleGroupList.onRemoveCallback = (ReorderableList list) =>
|
||||
{
|
||||
editor.blueprint.RemoveParticleGroupAt(list.index);
|
||||
};
|
||||
}
|
||||
|
||||
private void SelectionTools()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button(new GUIContent(Resources.Load<Texture2D>("InvertButton"), "Invert selection"), GUILayout.MaxHeight(24), GUILayout.MaxWidth(48)))
|
||||
{
|
||||
for (int i = 0; i < ObiActorBlueprintEditor.selectionStatus.Length; i++)
|
||||
{
|
||||
if (editor.blueprint.IsParticleActive(i))
|
||||
ObiActorBlueprintEditor.selectionStatus[i] = !ObiActorBlueprintEditor.selectionStatus[i];
|
||||
}
|
||||
UpdateSelection();
|
||||
}
|
||||
|
||||
GUI.enabled = ObiActorBlueprintEditor.selectedCount > 0;
|
||||
if (GUILayout.Button(new GUIContent(Resources.Load<Texture2D>("ClearButton"), "Clear selection"), GUILayout.MaxHeight(24), GUILayout.MaxWidth(48)))
|
||||
{
|
||||
for (int i = 0; i < ObiActorBlueprintEditor.selectionStatus.Length; i++)
|
||||
ObiActorBlueprintEditor.selectionStatus[i] = false;
|
||||
UpdateSelection();
|
||||
}
|
||||
|
||||
if (GUILayout.Button(new GUIContent(Resources.Load<Texture2D>("OptimizeButton"), "Optimize selected"), GUILayout.MaxHeight(24), GUILayout.MaxWidth(48)))
|
||||
{
|
||||
Undo.RecordObject(editor.blueprint, "Optimize particles away");
|
||||
editor.blueprint.RemoveSelectedParticles(ref ObiActorBlueprintEditor.selectionStatus);
|
||||
editor.Refresh();
|
||||
}
|
||||
|
||||
if (GUILayout.Button(new GUIContent(Resources.Load<Texture2D>("RemoveButton"), "Remove selected"), GUILayout.MaxHeight(24), GUILayout.MaxWidth(48)))
|
||||
{
|
||||
Undo.RecordObject(editor.blueprint, "Remove particles");
|
||||
editor.blueprint.RemoveSelectedParticles(ref ObiActorBlueprintEditor.selectionStatus, false);
|
||||
editor.Refresh();
|
||||
}
|
||||
GUI.enabled = true;
|
||||
|
||||
if (GUILayout.Button(new GUIContent(Resources.Load<Texture2D>("RestoreButton"), "Restore removed particles"), GUILayout.MaxHeight(24), GUILayout.MaxWidth(48)))
|
||||
{
|
||||
Undo.RecordObject(editor.blueprint, "Restore removed particles");
|
||||
editor.blueprint.RestoreRemovedParticles();
|
||||
editor.Refresh();
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Property-based selection", EditorStyles.boldLabel);
|
||||
var property = editor.currentProperty as ObiBlueprintFloatProperty;
|
||||
if (property != null)
|
||||
{
|
||||
if (!Mathf.Approximately(property.minVisualizationValue,property.maxVisualizationValue))
|
||||
{
|
||||
EditorGUILayout.HelpBox("Drag the slider to select based on " + property.name + ". You can choose a different property in the \"Property\" dropdown below.", MessageType.None);
|
||||
minSelectionValue = Mathf.Max(minSelectionValue, property.minVisualizationValue);
|
||||
maxSelectionValue = Mathf.Min(maxSelectionValue, property.maxVisualizationValue);
|
||||
maxSelectionValue = Mathf.Max(maxSelectionValue, minSelectionValue);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.MinMaxSlider("Select by " + property.name, ref minSelectionValue, ref maxSelectionValue, property.minVisualizationValue, property.maxVisualizationValue);
|
||||
minSelectionValue = EditorGUILayout.FloatField("Minimum " + property.name, minSelectionValue);
|
||||
maxSelectionValue = EditorGUILayout.FloatField("Maximum " + property.name, maxSelectionValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
for (int i = 0; i < ObiActorBlueprintEditor.selectionStatus.Length; i++)
|
||||
{
|
||||
if (editor.blueprint.IsParticleActive(i))
|
||||
{
|
||||
var value = property.Get(i);
|
||||
ObiActorBlueprintEditor.selectionStatus[i] = value >= minSelectionValue && value <= maxSelectionValue;
|
||||
}
|
||||
}
|
||||
UpdateSelection();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.HelpBox("All particles have the same " + property.name + " value.", MessageType.Info);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.HelpBox("Property-based selection only works with scalar properties.",MessageType.Info);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
// Selection tools:
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
selectionBrush.radius = EditorGUILayout.Slider("Brush size", selectionBrush.radius, 5, 200);
|
||||
|
||||
if (editor is ObiMeshBasedActorBlueprintEditor)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
(editor as ObiMeshBasedActorBlueprintEditor).particleCulling = (ObiMeshBasedActorBlueprintEditor.ParticleCulling)EditorGUILayout.EnumPopup("Culling", (editor as ObiMeshBasedActorBlueprintEditor).particleCulling);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
|
||||
|
||||
EditorGUILayout.Space();
|
||||
SelectionTools();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
|
||||
// Properties:
|
||||
EditorGUILayout.Space();
|
||||
GUILayout.Box(GUIContent.none, ObiEditorUtils.GetSeparatorLineStyle());
|
||||
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Properties", EditorStyles.boldLabel);
|
||||
EditorGUILayout.HelpBox("Select a property to view and edit. Currently editing " + editor.currentProperty.name+".", MessageType.None);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
editor.currentPropertyIndex = editor.PropertySelector(editor.currentPropertyIndex);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
editor.Refresh();
|
||||
UpdateSelection();
|
||||
}
|
||||
|
||||
// Property value:
|
||||
EditorGUI.showMixedValue = mixedPropertyValue;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
editor.currentProperty.PropertyField();
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(editor.blueprint, "Set particle property");
|
||||
for (int i = 0; i < ObiActorBlueprintEditor.selectionStatus.Length; i++)
|
||||
{
|
||||
if (!ObiActorBlueprintEditor.selectionStatus[i]) continue;
|
||||
editor.currentProperty.SetDefaultToIndex(i);
|
||||
}
|
||||
editor.Refresh();
|
||||
}
|
||||
|
||||
EditorGUI.showMixedValue = false;
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
|
||||
// Particle groups:
|
||||
EditorGUILayout.Space();
|
||||
GUILayout.Box(GUIContent.none, ObiEditorUtils.GetSeparatorLineStyle());
|
||||
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Particle groups", EditorStyles.boldLabel);
|
||||
particleGroupList.DoLayoutList();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
|
||||
|
||||
if (editor.blueprint.usesTethers)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
GUILayout.Box(GUIContent.none, ObiEditorUtils.GetSeparatorLineStyle());
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
EditorGUILayout.Space();
|
||||
tethersTool.DoTethers(editor);
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
GUILayout.Box(GUIContent.none, ObiEditorUtils.GetSeparatorLineStyle());
|
||||
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
|
||||
editor.RenderModeSelector();
|
||||
ObiActorBlueprintEditor.dotRadiusScale = EditorGUILayout.Slider(new GUIContent("Particle dot size"), ObiActorBlueprintEditor.dotRadiusScale, 0, 5);
|
||||
editor.currentProperty.VisualizationOptions();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
public override void OnSceneGUI(SceneView sceneView)
|
||||
{
|
||||
if (Camera.current != null)
|
||||
selectionBrush.DoBrush(editor.blueprint.positions);
|
||||
}
|
||||
|
||||
protected void UpdateSelection()
|
||||
{
|
||||
ObiActorBlueprintEditor.selectedCount = 0;
|
||||
mixedPropertyValue = false;
|
||||
|
||||
// Find out how many selected particles we have, and whether they all have the same value for the current property:
|
||||
for (int i = 0; i < ObiActorBlueprintEditor.selectionStatus.Length; i++)
|
||||
{
|
||||
if (editor.blueprint.IsParticleActive(i) && ObiActorBlueprintEditor.selectionStatus[i])
|
||||
{
|
||||
ObiActorBlueprintEditor.selectedCount++;
|
||||
|
||||
if (ObiActorBlueprintEditor.activeParticle >= 0)
|
||||
{
|
||||
if (!editor.currentProperty.Equals(ObiActorBlueprintEditor.activeParticle, i))
|
||||
mixedPropertyValue = true;
|
||||
}
|
||||
else
|
||||
ObiActorBlueprintEditor.activeParticle = i;
|
||||
}
|
||||
else if (ObiActorBlueprintEditor.activeParticle == i)
|
||||
ObiActorBlueprintEditor.activeParticle = -1;
|
||||
}
|
||||
|
||||
// Set initial property value:
|
||||
if (!mixedPropertyValue && ObiActorBlueprintEditor.activeParticle >= 0)
|
||||
editor.currentProperty.GetDefaultFromIndex(ObiActorBlueprintEditor.activeParticle);
|
||||
|
||||
editor.Repaint();
|
||||
SceneView.RepaintAll();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3940c62f9ffe4808afc4d2d70ae5e28
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,166 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using System.Collections;
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiPropertyTextureEditorTool : ObiBlueprintEditorTool
|
||||
{
|
||||
public enum TextureChannel
|
||||
{
|
||||
Red = 0,
|
||||
Green = 1,
|
||||
Blue = 2,
|
||||
Alpha = 3,
|
||||
}
|
||||
|
||||
protected bool selectionMask = false;
|
||||
protected bool import = true;
|
||||
protected bool export = true;
|
||||
|
||||
protected float minPropertyValue = 0;
|
||||
protected float maxPropertyValue = 10;
|
||||
|
||||
protected int exportWidth = 512;
|
||||
protected int exportHeight = 512;
|
||||
protected int padding = 64;
|
||||
|
||||
protected Texture2D propertyTexture;
|
||||
protected TextureChannel textureChannel;
|
||||
|
||||
protected ObiBlueprintFloatProperty floatProperty;
|
||||
protected ObiBlueprintColorProperty colorProperty;
|
||||
protected Action<int, Color> textureReadCallback;
|
||||
|
||||
public ObiMeshBasedActorBlueprintEditor meshBasedEditor
|
||||
{
|
||||
get { return editor as ObiMeshBasedActorBlueprintEditor; }
|
||||
}
|
||||
|
||||
public ObiPropertyTextureEditorTool(ObiMeshBasedActorBlueprintEditor editor) : base(editor)
|
||||
{
|
||||
m_Icon = Resources.Load<Texture2D>("TextureIcon");
|
||||
m_Name = "Texture import/export";
|
||||
}
|
||||
|
||||
public override string GetHelpString()
|
||||
{
|
||||
return "Import/export particle properties to textures. Assumes that your mesh has non-overlapping UVs.";
|
||||
}
|
||||
|
||||
private void FloatFromTexture(int i, Color color)
|
||||
{
|
||||
if (!selectionMask || ObiActorBlueprintEditor.selectionStatus[i])
|
||||
{
|
||||
float value = minPropertyValue + color[(int)textureChannel] * (maxPropertyValue - minPropertyValue);
|
||||
floatProperty.Set(i, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void ColorFromTexture(int i, Color color)
|
||||
{
|
||||
if (!selectionMask || ObiActorBlueprintEditor.selectionStatus[i])
|
||||
colorProperty.Set(i, color);
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
editor.currentPropertyIndex = editor.PropertySelector(editor.currentPropertyIndex);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
editor.Refresh();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
GUILayout.Box(GUIContent.none, ObiEditorUtils.GetSeparatorLineStyle());
|
||||
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
import = EditorGUILayout.BeginFoldoutHeaderGroup(import, "Import texture");
|
||||
|
||||
if (import)
|
||||
{
|
||||
propertyTexture = (Texture2D)EditorGUILayout.ObjectField("Source", propertyTexture, typeof(Texture2D), false);
|
||||
|
||||
floatProperty = editor.currentProperty as ObiBlueprintFloatProperty;
|
||||
colorProperty = editor.currentProperty as ObiBlueprintColorProperty;
|
||||
|
||||
if (floatProperty != null)
|
||||
{
|
||||
textureReadCallback = FloatFromTexture;
|
||||
textureChannel = (TextureChannel)EditorGUILayout.EnumPopup("Source channel", textureChannel);
|
||||
minPropertyValue = EditorGUILayout.FloatField("Min value", minPropertyValue);
|
||||
maxPropertyValue = EditorGUILayout.FloatField("Max value", maxPropertyValue);
|
||||
}
|
||||
else if (colorProperty != null)
|
||||
{
|
||||
textureReadCallback = ColorFromTexture;
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Import"))
|
||||
{
|
||||
Undo.RecordObject(editor.blueprint, "Import particle property");
|
||||
if (!meshBasedEditor.ReadParticlePropertyFromTexture(propertyTexture, textureReadCallback))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Invalid texture", "The texture is either null or not readable.", "Ok");
|
||||
}
|
||||
|
||||
// force automatic range calculation for floating point properties.
|
||||
if (floatProperty != null)
|
||||
floatProperty.autoRange = true;
|
||||
editor.Refresh();
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
GUILayout.Box(GUIContent.none, ObiEditorUtils.GetSeparatorLineStyle());
|
||||
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
export = EditorGUILayout.BeginFoldoutHeaderGroup(export, "Export texture");
|
||||
|
||||
if (export)
|
||||
{
|
||||
exportWidth = EditorGUILayout.IntField("Texture width", exportWidth);
|
||||
exportHeight = EditorGUILayout.IntField("Texture height", exportHeight);
|
||||
padding = EditorGUILayout.IntField("Padding", padding);
|
||||
if (GUILayout.Button("Export"))
|
||||
{
|
||||
var path = EditorUtility.SaveFilePanel("Save texture as PNG",
|
||||
"",
|
||||
"property.png",
|
||||
"png");
|
||||
if (path.Length > 0)
|
||||
{
|
||||
// force automatic range calculation for floating point properties.
|
||||
if (floatProperty != null)
|
||||
floatProperty.autoRange = true;
|
||||
editor.Refresh();
|
||||
|
||||
if (!meshBasedEditor.WriteParticlePropertyToTexture(path, exportWidth, exportHeight, padding))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Invalid path", "Could not write a texture to that location.", "Ok");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
GUILayout.Box(GUIContent.none, ObiEditorUtils.GetSeparatorLineStyle());
|
||||
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
editor.RenderModeSelector();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7727285b07aa44d6e8f65a8bc1f5d972
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,86 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiTethersTool
|
||||
{
|
||||
protected Rect tetherDropdownRect;
|
||||
protected bool[] tetheredGroups = new bool[0];
|
||||
|
||||
// the GenericMenu.MenuFunction2 event handler for when a menu item is selected
|
||||
void OnTetherGroupSelected(object index)
|
||||
{
|
||||
int i = (int)index;
|
||||
tetheredGroups[i] = !tetheredGroups[i];
|
||||
}
|
||||
|
||||
public void DoTethers(ObiActorBlueprintEditor editor)
|
||||
{
|
||||
EditorGUILayout.LabelField("Tethers", EditorStyles.boldLabel);
|
||||
|
||||
var tethers = editor.blueprint.GetConstraintsByType(Oni.ConstraintType.Tether);
|
||||
int tetherCount = 0;
|
||||
if (tethers != null)
|
||||
tetherCount = tethers.GetConstraintCount();
|
||||
|
||||
if (tetherCount > 0)
|
||||
EditorGUILayout.LabelField("" + tetherCount + " tether constraints.", EditorStyles.helpBox);
|
||||
else
|
||||
EditorGUILayout.LabelField("No tether constraints. Select at least one particle group in the dropdown, then click 'Generate Tethers'.", EditorStyles.helpBox);
|
||||
|
||||
Array.Resize(ref tetheredGroups, editor.blueprint.groups.Count);
|
||||
|
||||
// display the GenericMenu when pressing a button
|
||||
if (GUILayout.Button("Tethered groups", EditorStyles.popup))
|
||||
{
|
||||
// create the menu and add items to it
|
||||
GenericMenu menu = new GenericMenu();
|
||||
|
||||
// forward slashes nest menu items under submenus
|
||||
for (int i = 0; i < editor.blueprint.groups.Count; ++i)
|
||||
{
|
||||
menu.AddItem(new GUIContent(editor.blueprint.groups[i].name), tetheredGroups[i], OnTetherGroupSelected, i);
|
||||
}
|
||||
|
||||
// display the menu
|
||||
menu.DropDown(tetherDropdownRect);
|
||||
}
|
||||
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
tetherDropdownRect = GUILayoutUtility.GetLastRect();
|
||||
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("Generate tethers",GUILayout.MinHeight(32)))
|
||||
{
|
||||
// Select all particles in the tethered groups:
|
||||
for (int i = 0; i < ObiActorBlueprintEditor.selectionStatus.Length; ++i)
|
||||
{
|
||||
ObiActorBlueprintEditor.selectionStatus[i] = false;
|
||||
for (int j = 0; j < tetheredGroups.Length; ++j)
|
||||
{
|
||||
if (tetheredGroups[j] && editor.blueprint.groups[j].ContainsParticle(i))
|
||||
{
|
||||
ObiActorBlueprintEditor.selectionStatus[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
editor.blueprint.GenerateTethers(ObiActorBlueprintEditor.selectionStatus);
|
||||
editor.Refresh();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Clear tethers",GUILayout.MinHeight(32)))
|
||||
{
|
||||
editor.blueprint.ClearTethers();
|
||||
editor.Refresh();
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6aefc9e7e74be461e93ee58f15c5a1dd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 625a6e0c1ba72483190830373b7b45fe
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4fc4d44dc6d334c2985875fc6f7b8cb1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Obi
|
||||
{
|
||||
public interface IObiBrushMode
|
||||
{
|
||||
string name{get;}
|
||||
bool needsInputValue{ get; }
|
||||
void ApplyStamps(ObiBrushBase brush, bool modified);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c46364da0f1641c7ab84e12348a6a4b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,38 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiColorPaintBrushMode : IObiBrushMode
|
||||
{
|
||||
ObiBlueprintColorProperty property;
|
||||
|
||||
public ObiColorPaintBrushMode(ObiBlueprintColorProperty property)
|
||||
{
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public string name
|
||||
{
|
||||
get { return "Paint"; }
|
||||
}
|
||||
|
||||
public bool needsInputValue
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public void ApplyStamps(ObiBrushBase brush, bool modified)
|
||||
{
|
||||
for (int i = 0; i < brush.weights.Length; ++i)
|
||||
{
|
||||
if (!property.Masked(i) && brush.weights[i] > 0)
|
||||
{
|
||||
Color currentValue = property.Get(i);
|
||||
Color delta = brush.weights[i] * brush.opacity * brush.speed * (property.GetDefault() - currentValue);
|
||||
|
||||
property.Set(i, currentValue + delta * (modified ? -1 : 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fd033c8f79b1494d8b8de5c8311f8c1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,53 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiColorSmoothBrushMode : IObiBrushMode
|
||||
{
|
||||
ObiBlueprintColorProperty property;
|
||||
|
||||
public ObiColorSmoothBrushMode(ObiBlueprintColorProperty property)
|
||||
{
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public string name
|
||||
{
|
||||
get { return "Smooth"; }
|
||||
}
|
||||
|
||||
public bool needsInputValue
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void ApplyStamps(ObiBrushBase brush, bool modified)
|
||||
{
|
||||
Color averageValue = Color.black;
|
||||
float totalWeight = 0;
|
||||
|
||||
for (int i = 0; i < brush.weights.Length; ++i)
|
||||
{
|
||||
if (!property.Masked(i) && brush.weights[i] > 0)
|
||||
{
|
||||
averageValue += property.Get(i) * brush.weights[i];
|
||||
totalWeight += brush.weights[i];
|
||||
}
|
||||
|
||||
}
|
||||
averageValue /= totalWeight;
|
||||
|
||||
for (int i = 0; i < brush.weights.Length; ++i)
|
||||
{
|
||||
if (!property.Masked(i) && brush.weights[i] > 0)
|
||||
{
|
||||
Color currentValue = property.Get(i);
|
||||
Color delta = brush.opacity * brush.speed * (Color.Lerp(currentValue, averageValue, brush.weights[i]) - currentValue);
|
||||
|
||||
property.Set(i, currentValue + delta * (modified ? -1 : 1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a69a8a1614478445cbb770a5e123ab18
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,36 +0,0 @@
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiFloatAddBrushMode : IObiBrushMode
|
||||
{
|
||||
ObiBlueprintFloatProperty property;
|
||||
|
||||
public ObiFloatAddBrushMode(ObiBlueprintFloatProperty property)
|
||||
{
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public string name
|
||||
{
|
||||
get { return "Add"; }
|
||||
}
|
||||
|
||||
public bool needsInputValue
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public void ApplyStamps(ObiBrushBase brush, bool modified)
|
||||
{
|
||||
for (int i = 0; i < brush.weights.Length; ++i)
|
||||
{
|
||||
if (!property.Masked(i) && brush.weights[i] > 0)
|
||||
{
|
||||
float currentValue = property.Get(i);
|
||||
float delta = brush.weights[i] * brush.opacity * brush.speed * property.GetDefault();
|
||||
|
||||
property.Set(i, currentValue + delta * (modified ? -1 : 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b39e10cedc94461083b3b19c3ddb343
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,42 +0,0 @@
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiFloatCopyBrushMode : IObiBrushMode
|
||||
{
|
||||
ObiBlueprintFloatProperty property;
|
||||
public ObiBlueprintFloatProperty source;
|
||||
|
||||
public ObiFloatCopyBrushMode(ObiBlueprintFloatProperty property, ObiBlueprintFloatProperty source)
|
||||
{
|
||||
this.property = property;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public string name
|
||||
{
|
||||
get { return "Copy"; }
|
||||
}
|
||||
|
||||
public bool needsInputValue
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void ApplyStamps(ObiBrushBase brush, bool modified)
|
||||
{
|
||||
if (property != null && source != null)
|
||||
{
|
||||
for (int i = 0; i < brush.weights.Length; ++i)
|
||||
{
|
||||
if (!property.Masked(i) && brush.weights[i] > 0)
|
||||
{
|
||||
float currentValue = property.Get(i);
|
||||
float sourceValue = source.Get(i);
|
||||
float delta = brush.weights[i] * brush.opacity * brush.speed * (sourceValue - currentValue);
|
||||
|
||||
property.Set(i, currentValue + delta * (modified ? -1 : 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95bb470841f42415ab256cd64adb9242
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,37 +0,0 @@
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiFloatPaintBrushMode : IObiBrushMode
|
||||
{
|
||||
ObiBlueprintFloatProperty property;
|
||||
|
||||
public ObiFloatPaintBrushMode(ObiBlueprintFloatProperty property)
|
||||
{
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public string name
|
||||
{
|
||||
get { return "Paint"; }
|
||||
}
|
||||
|
||||
public bool needsInputValue
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public void ApplyStamps(ObiBrushBase brush, bool modified)
|
||||
{
|
||||
for (int i = 0; i < brush.weights.Length; ++i)
|
||||
{
|
||||
if (!property.Masked(i) && brush.weights[i] > 0)
|
||||
{
|
||||
float currentValue = property.Get(i);
|
||||
float delta = brush.weights[i] * brush.opacity * brush.speed * (property.GetDefault() - currentValue);
|
||||
|
||||
property.Set(i, currentValue + delta * (modified ? -1 : 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb3d176006d404a508bef284d2701ab0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,55 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiFloatSmoothBrushMode : IObiBrushMode
|
||||
{
|
||||
ObiBlueprintFloatProperty property;
|
||||
|
||||
public ObiFloatSmoothBrushMode(ObiBlueprintFloatProperty property)
|
||||
{
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public string name
|
||||
{
|
||||
get { return "Smooth"; }
|
||||
}
|
||||
|
||||
public bool needsInputValue
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void ApplyStamps(ObiBrushBase brush, bool modified)
|
||||
{
|
||||
var floatProperty = (ObiBlueprintFloatProperty)property;
|
||||
|
||||
float averageValue = 0;
|
||||
float totalWeight = 0;
|
||||
|
||||
for (int i = 0; i < brush.weights.Length; ++i)
|
||||
{
|
||||
if (!property.Masked(i) && brush.weights[i] > 0)
|
||||
{
|
||||
averageValue += floatProperty.Get(i) * brush.weights[i];
|
||||
totalWeight += brush.weights[i];
|
||||
}
|
||||
|
||||
}
|
||||
averageValue /= totalWeight;
|
||||
|
||||
for (int i = 0; i < brush.weights.Length; ++i)
|
||||
{
|
||||
if (!property.Masked(i) && brush.weights[i] > 0)
|
||||
{
|
||||
float currentValue = floatProperty.Get(i);
|
||||
float delta = brush.opacity * brush.speed * (Mathf.Lerp(currentValue,averageValue,brush.weights[i]) - currentValue);
|
||||
|
||||
floatProperty.Set(i, currentValue + delta * (modified ? -1 : 1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63dad56a994af4db7bb3449382022c54
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,33 +0,0 @@
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiIntPaintBrushMode : IObiBrushMode
|
||||
{
|
||||
ObiBlueprintIntProperty property;
|
||||
|
||||
public ObiIntPaintBrushMode(ObiBlueprintIntProperty property)
|
||||
{
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public string name
|
||||
{
|
||||
get { return "Paint"; }
|
||||
}
|
||||
|
||||
public bool needsInputValue
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public void ApplyStamps(ObiBrushBase brush, bool modified)
|
||||
{
|
||||
for (int i = 0; i < brush.weights.Length; ++i)
|
||||
{
|
||||
if (!property.Masked(i) && brush.weights[i] > (1 - brush.opacity))
|
||||
{
|
||||
property.Set(i, property.GetDefault());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8882849c81104cef80b3dfdab2021c9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,39 +0,0 @@
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiMasterSlavePaintBrushMode : IObiBrushMode
|
||||
{
|
||||
ObiBlueprintIntProperty property;
|
||||
|
||||
public ObiMasterSlavePaintBrushMode(ObiBlueprintIntProperty property)
|
||||
{
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public string name
|
||||
{
|
||||
get { return "Master/Slave paint"; }
|
||||
}
|
||||
|
||||
public bool needsInputValue
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public void ApplyStamps(ObiBrushBase brush, bool modified)
|
||||
{
|
||||
for (int i = 0; i < brush.weights.Length; ++i)
|
||||
{
|
||||
if (!property.Masked(i) && brush.weights[i] > (1 - brush.opacity))
|
||||
{
|
||||
int currentValue = property.Get(i);
|
||||
|
||||
if (modified)
|
||||
currentValue &= ~(int)(1 << property.GetDefault());
|
||||
else currentValue |= (int)(1 << property.GetDefault());
|
||||
|
||||
property.Set(i, currentValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62f8e9adfc17440359a9b51005cd0948
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,33 +0,0 @@
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiSelectBrushMode : IObiBrushMode
|
||||
{
|
||||
ObiBlueprintSelected property;
|
||||
string customName;
|
||||
|
||||
public ObiSelectBrushMode(ObiBlueprintSelected property, string customName = "Select")
|
||||
{
|
||||
this.property = property;
|
||||
this.customName = customName;
|
||||
}
|
||||
|
||||
public string name
|
||||
{
|
||||
get { return customName; }
|
||||
}
|
||||
|
||||
public bool needsInputValue
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public void ApplyStamps(ObiBrushBase brush, bool modified)
|
||||
{
|
||||
for (int i = 0; i < brush.weights.Length; ++i)
|
||||
{
|
||||
if (brush.weights[i] > 0 && !property.Masked(i))
|
||||
property.Set(i,!modified);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cea7ef42253f4d2b9b5a222521cdee8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,161 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
public abstract class ObiBrushBase
|
||||
{
|
||||
static int particleBrushHash = "ObiBrushHash".GetHashCode();
|
||||
|
||||
public IObiBrushMode brushMode;
|
||||
public float radius = 1;
|
||||
public float innerRadius = 0.5f;
|
||||
public float opacity = 1;
|
||||
public float[] weights = new float[0];
|
||||
public bool drag = true;
|
||||
public float speed = 0.1f;
|
||||
|
||||
protected int controlID;
|
||||
protected Action onStrokeStart;
|
||||
protected Action onStrokeUpdate;
|
||||
protected Action onStrokeEnd;
|
||||
|
||||
public float SqrRadius
|
||||
{
|
||||
get{ return radius * radius; }
|
||||
}
|
||||
|
||||
public ObiBrushBase(Action onStrokeStart, Action onStrokeUpdate, Action onStrokeEnd)
|
||||
{
|
||||
this.onStrokeStart = onStrokeStart;
|
||||
this.onStrokeUpdate = onStrokeUpdate;
|
||||
this.onStrokeEnd = onStrokeEnd;
|
||||
}
|
||||
|
||||
protected virtual float WeightFromDistance(float distance)
|
||||
{
|
||||
// anything outside the brush should have zero weight:
|
||||
if (distance > radius)
|
||||
return 0;
|
||||
|
||||
float t = Mathf.InverseLerp(innerRadius * radius, radius, distance);
|
||||
return Mathf.SmoothStep(1, 0, t);
|
||||
}
|
||||
|
||||
protected abstract void GenerateWeights(Vector3[] positions);
|
||||
|
||||
protected virtual void OnMouseDown(Vector3[] positions)
|
||||
{
|
||||
if (Event.current.button != 0 || (Event.current.modifiers & ~EventModifiers.Shift) != EventModifiers.None)
|
||||
return;
|
||||
|
||||
GUIUtility.hotControl = controlID;
|
||||
|
||||
GenerateWeights(positions);
|
||||
|
||||
if (onStrokeStart != null)
|
||||
onStrokeStart();
|
||||
|
||||
if (brushMode != null)
|
||||
brushMode.ApplyStamps(this, (Event.current.modifiers & EventModifiers.Shift) != 0);
|
||||
|
||||
if (onStrokeUpdate != null)
|
||||
onStrokeUpdate();
|
||||
|
||||
Event.current.Use();
|
||||
}
|
||||
|
||||
protected virtual void OnMouseMove(Vector3[] positions)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual void OnMouseDrag(Vector3[] positions)
|
||||
{
|
||||
|
||||
if (GUIUtility.hotControl == controlID && drag)
|
||||
{
|
||||
|
||||
GenerateWeights(positions);
|
||||
|
||||
if (brushMode != null)
|
||||
brushMode.ApplyStamps(this, (Event.current.modifiers & EventModifiers.Shift) != 0);
|
||||
|
||||
if (onStrokeUpdate != null)
|
||||
onStrokeUpdate();
|
||||
|
||||
Event.current.Use();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnMouseUp(Vector3[] positions)
|
||||
{
|
||||
if (GUIUtility.hotControl == controlID)
|
||||
{
|
||||
|
||||
GUIUtility.hotControl = 0;
|
||||
Event.current.Use();
|
||||
|
||||
if (onStrokeEnd != null)
|
||||
onStrokeEnd();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnRepaint()
|
||||
{
|
||||
}
|
||||
|
||||
public void DoBrush(Vector3[] positions)
|
||||
{
|
||||
|
||||
Matrix4x4 cachedMatrix = Handles.matrix;
|
||||
|
||||
controlID = GUIUtility.GetControlID(particleBrushHash, FocusType.Passive);
|
||||
Array.Resize(ref weights, positions.Length);
|
||||
|
||||
switch (Event.current.GetTypeForControl(controlID))
|
||||
{
|
||||
|
||||
case EventType.MouseDown:
|
||||
|
||||
OnMouseDown(positions);
|
||||
|
||||
break;
|
||||
|
||||
case EventType.MouseMove:
|
||||
|
||||
OnMouseMove(positions);
|
||||
|
||||
SceneView.RepaintAll();
|
||||
break;
|
||||
|
||||
case EventType.MouseDrag:
|
||||
|
||||
OnMouseDrag(positions);
|
||||
|
||||
break;
|
||||
|
||||
case EventType.MouseUp:
|
||||
|
||||
OnMouseUp(positions);
|
||||
|
||||
break;
|
||||
|
||||
case EventType.Repaint:
|
||||
|
||||
Handles.matrix = Matrix4x4.identity;
|
||||
|
||||
OnRepaint();
|
||||
|
||||
Handles.matrix = cachedMatrix;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 094253962d646436792561e708e62376
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
[Serializable]
|
||||
public struct ObiBrushMirrorSettings
|
||||
{
|
||||
[Flags]
|
||||
public enum MirrorAxis
|
||||
{
|
||||
None = 0x0,
|
||||
X = 0x1,
|
||||
Y = 0x2,
|
||||
Z = 0x4
|
||||
}
|
||||
|
||||
public enum MirrorSpace
|
||||
{
|
||||
World = 0,
|
||||
Camera = 1
|
||||
}
|
||||
|
||||
public MirrorAxis axis;
|
||||
public MirrorSpace space;
|
||||
|
||||
public Vector3 ToAxis()
|
||||
{
|
||||
uint m = (uint)axis;
|
||||
|
||||
bool xMirror = (m & (uint)MirrorAxis.X) > 0;
|
||||
bool yMirror = (m & (uint)MirrorAxis.Y) > 0;
|
||||
bool zMirror = (m & (uint)MirrorAxis.Z) > 0;
|
||||
|
||||
if (axis < 0 || ((int)axis > (int)MirrorAxis.X + (int)MirrorAxis.Y + (int)MirrorAxis.Z))
|
||||
{
|
||||
return Vector3.one;
|
||||
}
|
||||
|
||||
Vector3 reflection = Vector3.one;
|
||||
|
||||
if (xMirror)
|
||||
reflection.x = -1f;
|
||||
|
||||
if (yMirror)
|
||||
reflection.y = -1f;
|
||||
|
||||
if (zMirror)
|
||||
reflection.z = -1f;
|
||||
|
||||
return reflection;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d10a9257ac23248418439eb80e02a611
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,125 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
public class ObiRaycastBrush : ObiBrushBase
|
||||
{
|
||||
public Matrix4x4 raycastTransform = Matrix4x4.identity;
|
||||
public Mesh raycastTarget = null;
|
||||
public bool drawVolume = false;
|
||||
private List<Ray> rays = new List<Ray>();
|
||||
private List<ObiRaycastHit> hits = new List<ObiRaycastHit>();
|
||||
|
||||
public ObiBrushMirrorSettings mirror;
|
||||
|
||||
public ObiRaycastBrush(Mesh raycastTarget, Action onStrokeStart, Action onStrokeUpdate, Action onStrokeEnd) : base(onStrokeStart, onStrokeUpdate, onStrokeEnd)
|
||||
{
|
||||
radius = 0.1f;
|
||||
this.raycastTarget = raycastTarget;
|
||||
rays = new List<Ray>();
|
||||
}
|
||||
|
||||
protected override void GenerateWeights(Vector3[] positions)
|
||||
{
|
||||
if (raycastTarget != null)
|
||||
{
|
||||
rays.Clear();
|
||||
hits.Clear();
|
||||
|
||||
for (int i = 0; i < positions.Length; i++)
|
||||
weights[i] = 0;
|
||||
|
||||
var vertices = raycastTarget.vertices;
|
||||
var triangles = raycastTarget.triangles;
|
||||
|
||||
Ray mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
|
||||
rays.Add(mouseRay);
|
||||
|
||||
ObiBrushMirrorSettings currentAxis = mirror;
|
||||
|
||||
if (mirror.axis != ObiBrushMirrorSettings.MirrorAxis.None)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
currentAxis.axis = (ObiBrushMirrorSettings.MirrorAxis)(1u << i);
|
||||
if (((uint)mirror.axis & (1u << i)) < 1)
|
||||
continue;
|
||||
|
||||
Vector3 mirrorVector = currentAxis.ToAxis();
|
||||
|
||||
if (currentAxis.space == ObiBrushMirrorSettings.MirrorSpace.World)
|
||||
{
|
||||
Vector3 center = raycastTarget.bounds.center;
|
||||
rays.Add(new Ray(Vector3.Scale(mouseRay.origin - center, mirrorVector) + center,
|
||||
Vector3.Scale(mouseRay.direction, mirrorVector)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Transform t = SceneView.lastActiveSceneView.camera.transform;
|
||||
Vector3 o = t.InverseTransformPoint(mouseRay.origin);
|
||||
Vector3 d = t.InverseTransformDirection(mouseRay.direction);
|
||||
rays.Add(new Ray(t.TransformPoint(Vector3.Scale(o, mirrorVector)),
|
||||
t.TransformDirection(Vector3.Scale(d, mirrorVector))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var ray in rays)
|
||||
{
|
||||
if (ObiMeshUtils.WorldRaycast(ray, raycastTransform, vertices, triangles, out ObiRaycastHit hit))
|
||||
{
|
||||
hit.position = raycastTransform.MultiplyPoint3x4(hit.position);
|
||||
hit.normal = raycastTransform.MultiplyVector(hit.normal);
|
||||
hits.Add(hit);
|
||||
|
||||
for (int i = 0; i < positions.Length; i++)
|
||||
{
|
||||
// get distance from hit position to particle position:
|
||||
float weight = WeightFromDistance(Vector3.Distance(hit.position, positions[i]));
|
||||
weights[i] = Mathf.Max(weights[i], weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(Vector3[] positions)
|
||||
{
|
||||
base.OnMouseMove(positions);
|
||||
GenerateWeights(positions);
|
||||
}
|
||||
|
||||
protected override void OnRepaint()
|
||||
{
|
||||
base.OnRepaint();
|
||||
|
||||
if (raycastTarget != null)
|
||||
{
|
||||
Color brushColor = ObiEditorSettings.GetOrCreateSettings().brushColor;
|
||||
|
||||
foreach (var hit in hits)
|
||||
{
|
||||
if (hit != null && hit.triangle >= 0)
|
||||
{
|
||||
Handles.color = brushColor;
|
||||
Handles.DrawLine(hit.position, hit.position + hit.normal.normalized * radius);
|
||||
Handles.DrawWireDisc(hit.position, hit.normal, radius);
|
||||
Handles.DrawWireDisc(hit.position, hit.normal, innerRadius * radius);
|
||||
|
||||
if (drawVolume)
|
||||
{
|
||||
Handles.color = new Color(brushColor.r, brushColor.g, brushColor.b, 0.2f);
|
||||
Handles.SphereHandleCap(0, hit.position, Quaternion.identity, radius * 2, EventType.Repaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d925323750dca4dcaa5cca91b18521b5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,61 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
public class ObiScreenSpaceBrush : ObiBrushBase
|
||||
{
|
||||
public ObiScreenSpaceBrush(Action onStrokeStart, Action onStrokeUpdate, Action onStrokeEnd) : base(onStrokeStart, onStrokeUpdate, onStrokeEnd)
|
||||
{
|
||||
radius = 32;
|
||||
}
|
||||
|
||||
protected override float WeightFromDistance(float distance)
|
||||
{
|
||||
// anything outside the brush should have zero weight:
|
||||
if (distance * EditorGUIUtility.pixelsPerPoint > radius)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
protected override void GenerateWeights(Vector3[] positions)
|
||||
{
|
||||
for (int i = 0; i < positions.Length; i++)
|
||||
{
|
||||
// get particle position in gui space:
|
||||
Vector2 pos = HandleUtility.WorldToGUIPoint(positions[i]);
|
||||
|
||||
// get distance from mouse position to particle position:
|
||||
weights[i] = WeightFromDistance(Vector3.Distance(Event.current.mousePosition, pos));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnRepaint()
|
||||
{
|
||||
base.OnRepaint();
|
||||
|
||||
Camera cam = Camera.current;
|
||||
float depth = (cam.nearClipPlane + cam.farClipPlane) * 0.5f;
|
||||
|
||||
float ppp = EditorGUIUtility.pixelsPerPoint;
|
||||
Vector2 mousePos = new Vector2(Event.current.mousePosition.x * ppp,
|
||||
cam.pixelHeight - Event.current.mousePosition.y * ppp);
|
||||
|
||||
Handles.color = ObiEditorSettings.GetOrCreateSettings().brushColor;
|
||||
Vector3 point = new Vector3(mousePos.x, mousePos.y, depth);
|
||||
Vector3 wsPoint = cam.ScreenToWorldPoint(point);
|
||||
|
||||
var p1 = cam.ScreenToWorldPoint(new Vector3(1, 0, depth));
|
||||
var p2 = cam.ScreenToWorldPoint(new Vector3(0, 0, depth));
|
||||
float units = Vector3.Distance(p1, p2);
|
||||
|
||||
Handles.DrawWireDisc(wsPoint, cam.transform.forward, radius * units);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38fc5288fb3c94ebeb7eaa88a3bc5119
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,477 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEditor;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEditor.SceneManagement;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
[CustomEditor(typeof(ObiActorBlueprint), true)]
|
||||
public class ObiActorBlueprintEditor : Editor, IObiSelectableParticleProvider
|
||||
{
|
||||
public List<ObiBlueprintEditorTool> tools = new List<ObiBlueprintEditorTool>();
|
||||
public int currentToolIndex = 0;
|
||||
|
||||
public List<ObiBlueprintPropertyBase> properties = new List<ObiBlueprintPropertyBase>();
|
||||
public int currentPropertyIndex = 0;
|
||||
|
||||
public List<ObiBlueprintRenderMode> renderModes = new List<ObiBlueprintRenderMode>();
|
||||
public int renderModeFlags = 0;
|
||||
BooleanPreference showRenderModes;
|
||||
|
||||
public bool autoGenerate = false;
|
||||
public bool editMode = false;
|
||||
public bool isEditing = false;
|
||||
protected UnityEngine.Object oldSelection;
|
||||
|
||||
//Additional status info for all particles:
|
||||
public static float dotRadiusScale = 1;
|
||||
public static int selectedCount = 0;
|
||||
public static int activeParticle = -1;
|
||||
public static bool[] selectionStatus = new bool[0];
|
||||
|
||||
public bool[] visible = new bool[0];
|
||||
public Color[] tint = new Color[0];
|
||||
protected float[] sqrDistanceToCamera = new float[0];
|
||||
public int[] sortedIndices = new int[0];
|
||||
|
||||
public ObiActorBlueprint blueprint
|
||||
{
|
||||
get { return target as ObiActorBlueprint; }
|
||||
}
|
||||
|
||||
public ObiBlueprintPropertyBase currentProperty
|
||||
{
|
||||
get { return GetProperty(currentPropertyIndex); }
|
||||
}
|
||||
|
||||
public ObiBlueprintEditorTool currentTool
|
||||
{
|
||||
get { return GetTool(currentToolIndex); }
|
||||
}
|
||||
|
||||
public override bool UseDefaultMargins()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public ObiBlueprintPropertyBase GetProperty(int index)
|
||||
{
|
||||
return (properties.Count > index && index >= 0) ? properties[index] : null;
|
||||
}
|
||||
|
||||
public ObiBlueprintEditorTool GetTool(int index)
|
||||
{
|
||||
return (tools.Count > index && index >= 0) ? tools[index] : null;
|
||||
}
|
||||
|
||||
#if (UNITY_2019_1_OR_NEWER)
|
||||
System.Action<ScriptableRenderContext, Camera> renderCallback;
|
||||
#endif
|
||||
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
properties.Clear();
|
||||
renderModes.Clear();
|
||||
tools.Clear();
|
||||
|
||||
properties.Add(new ObiBlueprintMass(this));
|
||||
properties.Add(new ObiBlueprintRadius(this));
|
||||
properties.Add(new ObiBlueprintFilterCategory(this));
|
||||
properties.Add(new ObiBlueprintFilterMask(this));
|
||||
|
||||
renderModes.Add(new ObiBlueprintRenderModeParticles(this));
|
||||
showRenderModes = new BooleanPreference($"{target.GetType()}.showRenderModes", false);
|
||||
|
||||
#if (UNITY_2019_1_OR_NEWER)
|
||||
renderCallback = new System.Action<ScriptableRenderContext, Camera>((cntxt, cam) => { DrawWithCamera(cam); });
|
||||
RenderPipelineManager.beginCameraRendering += renderCallback;
|
||||
#endif
|
||||
Camera.onPreCull += DrawWithCamera;
|
||||
SceneView.duringSceneGui += OnSceneGUI;
|
||||
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
public virtual void OnDisable()
|
||||
{
|
||||
ExitBlueprintEditMode();
|
||||
|
||||
#if (UNITY_2019_1_OR_NEWER)
|
||||
RenderPipelineManager.beginCameraRendering -= renderCallback;
|
||||
#endif
|
||||
Camera.onPreCull -= DrawWithCamera;
|
||||
SceneView.duringSceneGui -= OnSceneGUI;
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
|
||||
foreach (var tool in tools)
|
||||
{
|
||||
tool.OnDisable();
|
||||
tool.OnDestroy();
|
||||
}
|
||||
|
||||
foreach (var renderMode in renderModes)
|
||||
{
|
||||
renderMode.OnDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
void OnPlayModeStateChanged(PlayModeStateChange playmodeState)
|
||||
{
|
||||
if (playmodeState == PlayModeStateChange.ExitingEditMode)
|
||||
{
|
||||
if (StageUtility.GetCurrentStage() is ObiActorBlueprintEditorStage)
|
||||
StageUtility.GoToMainStage();
|
||||
}
|
||||
}
|
||||
|
||||
protected bool Generate()
|
||||
{
|
||||
if (!blueprint.edited)
|
||||
{
|
||||
EditorUtility.SetDirty(target);
|
||||
CoroutineJob job = new CoroutineJob();
|
||||
IEnumerator routine = job.Start(blueprint.Generate());
|
||||
EditorCoroutine.ShowCoroutineProgressBar("Generating blueprint...", routine);
|
||||
Refresh();
|
||||
EditorGUIUtility.ExitGUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Blueprint generation", "This blueprint contains manually edited data. If you regenerate the blueprint, these changes will be lost. Are you sure you want to proceed?", "Ok", "Cancel"))
|
||||
{
|
||||
EditorUtility.SetDirty(target);
|
||||
CoroutineJob job = new CoroutineJob();
|
||||
IEnumerator routine = job.Start(blueprint.Generate());
|
||||
EditorCoroutine.ShowCoroutineProgressBar("Generating blueprint...", routine);
|
||||
Refresh();
|
||||
EditorGUIUtility.ExitGUI();
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual bool ValidateBlueprint() { return true; }
|
||||
|
||||
private void DrawGenerationControls()
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
|
||||
float originalLabelWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 72;
|
||||
autoGenerate = EditorGUILayout.ToggleLeft("Auto Generate", autoGenerate, GUILayout.ExpandWidth(false));
|
||||
EditorGUIUtility.labelWidth = originalLabelWidth;
|
||||
|
||||
GUI.enabled = !autoGenerate;
|
||||
if (GUILayout.Button("Generate", GUI.skin.FindStyle("LargeButton"), GUILayout.Height(32)))
|
||||
Generate();
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
DrawBlueprintProperties();
|
||||
bool blueprintPropertiesChanged = EditorGUI.EndChangeCheck();
|
||||
bool blueprintValid = ValidateBlueprint();
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
GUI.enabled = blueprintValid;
|
||||
DrawGenerationControls();
|
||||
|
||||
GUI.enabled = (blueprint != null && !blueprint.empty && !Application.isPlaying);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
editMode = GUILayout.Toggle(editMode, editMode ? "Done" : "Edit", "Button");
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (editMode)
|
||||
EditorApplication.delayCall += EnterBlueprintEditMode;
|
||||
else
|
||||
EditorApplication.delayCall += ExitBlueprintEditMode;
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
GUI.enabled = true;
|
||||
|
||||
if (isEditing)
|
||||
DrawTools();
|
||||
|
||||
if (GUI.changed)
|
||||
{
|
||||
serializedObject.ApplyModifiedPropertiesWithoutUndo();
|
||||
|
||||
if (autoGenerate && blueprintValid && blueprintPropertiesChanged)
|
||||
blueprint.GenerateImmediate();
|
||||
|
||||
// There might be blueprint editing operations that have no undo entry, so do this to
|
||||
// ensure changes are serialized to disk by Unity.
|
||||
EditorUtility.SetDirty(target);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected virtual void DrawBlueprintProperties()
|
||||
{
|
||||
Editor.DrawPropertiesExcluding(serializedObject, "m_Script");
|
||||
}
|
||||
|
||||
private void DrawWithCamera(Camera camera)
|
||||
{
|
||||
if (editMode)
|
||||
{
|
||||
for (int i = 0; i < renderModes.Count; ++i)
|
||||
{
|
||||
if ((1 << i & renderModeFlags) != 0)
|
||||
renderModes[i].DrawWithCamera(camera);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnterBlueprintEditMode()
|
||||
{
|
||||
if (!isEditing)
|
||||
{
|
||||
ActiveEditorTracker.sharedTracker.isLocked = true;
|
||||
|
||||
string assetPath = AssetDatabase.GetAssetPath(blueprint);
|
||||
ObiActorBlueprintEditorStage stage = ObiActorBlueprintEditorStage.CreateStage(assetPath, this);
|
||||
StageUtility.GoToStage(stage, true);
|
||||
|
||||
isEditing = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ExitBlueprintEditMode()
|
||||
{
|
||||
if (isEditing)
|
||||
{
|
||||
isEditing = false;
|
||||
AssetDatabase.SaveAssets();
|
||||
StageUtility.GoToMainStage();
|
||||
}
|
||||
}
|
||||
|
||||
public void CleanupEditor()
|
||||
{
|
||||
ActiveEditorTracker.sharedTracker.isLocked = false;
|
||||
ObiParticleEditorDrawing.DestroyParticlesMesh();
|
||||
}
|
||||
|
||||
public virtual void OnSceneGUI(SceneView sceneView)
|
||||
{
|
||||
|
||||
if (!isEditing || sceneView.camera == null)
|
||||
return;
|
||||
|
||||
ResizeParticleArrays();
|
||||
|
||||
Event e = Event.current;
|
||||
|
||||
if (e.type == EventType.Repaint)
|
||||
{
|
||||
|
||||
// Update camera facing status and world space positions array:
|
||||
UpdateParticleVisibility(sceneView.camera);
|
||||
|
||||
// Generate sorted indices for back-to-front rendering:
|
||||
for (int i = 0; i < sortedIndices.Length; i++)
|
||||
sortedIndices[i] = i;
|
||||
Array.Sort<int>(sortedIndices, (a, b) => sqrDistanceToCamera[b].CompareTo(sqrDistanceToCamera[a]));
|
||||
|
||||
// render modes OnSceneRepaint:
|
||||
for (int i = 0; i < renderModes.Count; ++i)
|
||||
{
|
||||
if ((1 << i & renderModeFlags) != 0)
|
||||
renderModes[i].OnSceneRepaint(sceneView);
|
||||
}
|
||||
|
||||
// property OnSceneRepaint:
|
||||
currentProperty.OnSceneRepaint();
|
||||
|
||||
// update particle color based on visiblity, etc.
|
||||
UpdateTintColor();
|
||||
|
||||
// Draw particle handles:
|
||||
ObiParticleEditorDrawing.DrawParticles(sceneView.camera, blueprint, visible, tint, sortedIndices, dotRadiusScale);
|
||||
|
||||
}
|
||||
|
||||
if (currentTool != null)
|
||||
currentTool.OnSceneGUI(sceneView);
|
||||
|
||||
}
|
||||
|
||||
protected virtual void UpdateTintColor()
|
||||
{
|
||||
Color regularColor = ObiEditorSettings.GetOrCreateSettings().particleColor;
|
||||
Color selectedColor = ObiEditorSettings.GetOrCreateSettings().selectedParticleColor;
|
||||
Color activeColor = ObiEditorSettings.GetOrCreateSettings().activeParticleColor;
|
||||
|
||||
for (int i = 0; i < blueprint.positions.Length; i++)
|
||||
{
|
||||
// get particle color:
|
||||
if (activeParticle == i)
|
||||
tint[i] = activeColor;
|
||||
else
|
||||
tint[i] = selectionStatus[i] ? selectedColor : regularColor;
|
||||
|
||||
tint[i].a = visible[i] ? 1 : 0.15f;
|
||||
}
|
||||
}
|
||||
|
||||
protected void ResizeParticleArrays()
|
||||
{
|
||||
if (blueprint.positions != null)
|
||||
{
|
||||
activeParticle = Mathf.Min(activeParticle, blueprint.positions.Length - 1);
|
||||
Array.Resize(ref selectionStatus, blueprint.positions.Length);
|
||||
Array.Resize(ref visible, blueprint.positions.Length);
|
||||
Array.Resize(ref tint, blueprint.positions.Length);
|
||||
Array.Resize(ref sqrDistanceToCamera, blueprint.positions.Length);
|
||||
Array.Resize(ref sortedIndices, blueprint.positions.Length);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int PropertySelector(int propertyIndex, string label = "Property")
|
||||
{
|
||||
// get all particle properties:
|
||||
string[] propertyNames = new string[properties.Count];
|
||||
for (int i = 0; i < properties.Count; ++i)
|
||||
propertyNames[i] = properties[i].name;
|
||||
|
||||
// Draw a selection dropdown:
|
||||
return EditorGUILayout.Popup(label, propertyIndex, propertyNames);
|
||||
}
|
||||
|
||||
public virtual void RenderModeSelector()
|
||||
{
|
||||
showRenderModes.value = EditorGUILayout.BeginFoldoutHeaderGroup(showRenderModes, "Render modes");
|
||||
if (showRenderModes)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
for (int i = 0; i < renderModes.Count; ++i)
|
||||
{
|
||||
int value = 1 << i;
|
||||
|
||||
if (EditorGUILayout.Toggle(renderModes[i].name, (value & renderModeFlags) != 0))
|
||||
renderModeFlags |= value;
|
||||
else
|
||||
renderModeFlags &= ~value;
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
Refresh();
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
// currentProperty might be null after reloading editor during
|
||||
// asset saving.
|
||||
currentProperty?.RecalculateMinMax();
|
||||
|
||||
// refresh render modes:
|
||||
for (int i = 0; i < renderModes.Count; ++i)
|
||||
{
|
||||
if ((1 << i & renderModeFlags) != 0)
|
||||
renderModes[i].Refresh();
|
||||
}
|
||||
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
|
||||
public virtual void UpdateParticleVisibility(Camera cam)
|
||||
{
|
||||
|
||||
for (int i = 0; i < blueprint.positions.Length; i++)
|
||||
{
|
||||
if (blueprint.IsParticleActive(i))
|
||||
{
|
||||
visible[i] = true;
|
||||
|
||||
if (Camera.current != null)
|
||||
{
|
||||
Vector3 camToParticle = cam.transform.position - blueprint.positions[i];
|
||||
sqrDistanceToCamera[i] = camToParticle.sqrMagnitude;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((renderModeFlags & 1) != 0)
|
||||
Refresh();
|
||||
}
|
||||
|
||||
protected void DrawTools()
|
||||
{
|
||||
|
||||
GUIContent[] contents = new GUIContent[tools.Count];
|
||||
|
||||
for (int i = 0; i < tools.Count; ++i)
|
||||
contents[i] = new GUIContent(tools[i].icon, tools[i].name);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
GUILayout.Box(GUIContent.none, ObiEditorUtils.GetSeparatorLineStyle());
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
int newSelectedTool = ObiEditorUtils.DoToolBar(currentToolIndex, contents);
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (currentTool != null)
|
||||
currentTool.OnDisable();
|
||||
|
||||
currentToolIndex = newSelectedTool;
|
||||
|
||||
if (currentTool != null)
|
||||
currentTool.OnEnable();
|
||||
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
|
||||
if (currentTool != null)
|
||||
{
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
EditorGUILayout.LabelField(currentTool.name, EditorStyles.boldLabel);
|
||||
|
||||
string help = currentTool.GetHelpString();
|
||||
if (!help.Equals(string.Empty))
|
||||
EditorGUILayout.LabelField(help, EditorStyles.helpBox);
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
currentTool.OnInspectorGUI();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void SetSelected(int particleIndex, bool selected)
|
||||
{
|
||||
selectionStatus[particleIndex] = selected;
|
||||
}
|
||||
|
||||
public bool IsSelected(int particleIndex)
|
||||
{
|
||||
return selectionStatus[particleIndex];
|
||||
}
|
||||
|
||||
public bool Editable(int particleIndex)
|
||||
{
|
||||
return currentTool.Editable(particleIndex) && blueprint.IsParticleActive(particleIndex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e39e6eea226f4ecbbe091613ff79f85
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,72 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
class ObiActorBlueprintEditorStage : PreviewSceneStage
|
||||
{
|
||||
ObiActorBlueprintEditor m_BlueprintEditor;
|
||||
|
||||
string m_AssetPath;
|
||||
public override string assetPath { get { return m_AssetPath; } }
|
||||
|
||||
internal static ObiActorBlueprintEditorStage CreateStage(string assetPath, ObiActorBlueprintEditor avatarEditor)
|
||||
{
|
||||
ObiActorBlueprintEditorStage stage = CreateInstance<ObiActorBlueprintEditorStage>();
|
||||
stage.Init(assetPath, avatarEditor);
|
||||
return stage;
|
||||
}
|
||||
|
||||
private void Init(string modelAssetPath, ObiActorBlueprintEditor avatarEditor)
|
||||
{
|
||||
m_AssetPath = modelAssetPath;
|
||||
m_BlueprintEditor = avatarEditor;
|
||||
}
|
||||
|
||||
protected override bool OnOpenStage()
|
||||
{
|
||||
base.OnOpenStage();
|
||||
|
||||
if (!File.Exists(assetPath))
|
||||
{
|
||||
Debug.LogError("ActivateStage called on BlueprintStage with an invalid path: Blueprint file not found " + assetPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnCloseStage()
|
||||
{
|
||||
m_BlueprintEditor.CleanupEditor();
|
||||
|
||||
base.OnCloseStage();
|
||||
}
|
||||
|
||||
protected override void OnFirstTimeOpenStageInSceneView(SceneView sceneView)
|
||||
{
|
||||
// Frame in scene view
|
||||
sceneView.Frame(m_BlueprintEditor.blueprint.bounds);
|
||||
|
||||
// Setup Scene view state
|
||||
sceneView.sceneViewState.showFlares = false;
|
||||
sceneView.sceneViewState.alwaysRefresh = false;
|
||||
sceneView.sceneViewState.showFog = false;
|
||||
sceneView.sceneViewState.showSkybox = false;
|
||||
sceneView.sceneViewState.showImageEffects = false;
|
||||
sceneView.sceneViewState.showParticleSystems = false;
|
||||
sceneView.sceneLighting = true;
|
||||
}
|
||||
|
||||
protected override GUIContent CreateHeaderContent()
|
||||
{
|
||||
return new GUIContent(
|
||||
"Blueprint Editor",
|
||||
Resources.Load<Texture2D>("Icons/ObiActorBlueprint Icon"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c8d9d8042d49436c89c515b001088ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,275 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[CustomEditor(typeof(ObiMeshBasedActorBlueprint), true)]
|
||||
public abstract class ObiMeshBasedActorBlueprintEditor : ObiActorBlueprintEditor
|
||||
{
|
||||
|
||||
[Flags]
|
||||
public enum ParticleCulling
|
||||
{
|
||||
Off = 0,
|
||||
Back = 1 << 0,
|
||||
Front = 1 << 1
|
||||
}
|
||||
|
||||
protected Mesh visualizationMesh;
|
||||
protected Mesh visualizationWireMesh;
|
||||
public ParticleCulling particleCulling = ParticleCulling.Back;
|
||||
|
||||
protected Material gradientMaterial;
|
||||
protected Material textureExportMaterial;
|
||||
protected Material paddingMaterial;
|
||||
|
||||
public override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
gradientMaterial = Resources.Load<Material>("PropertyGradientMaterial");
|
||||
textureExportMaterial = Resources.Load<Material>("UVSpaceColorMaterial");
|
||||
paddingMaterial = Resources.Load<Material>("PaddingMaterial");
|
||||
}
|
||||
|
||||
public abstract Mesh sourceMesh
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
protected void NonReadableMeshWarning(Mesh mesh)
|
||||
{
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
Texture2D icon = EditorGUIUtility.Load("icons/console.erroricon.png") as Texture2D;
|
||||
EditorGUILayout.LabelField(new GUIContent("The input mesh is not readable. Read/Write must be enabled in the mesh import settings.", icon), EditorStyles.wordWrappedMiniLabel);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button("Fix now", GUILayout.MaxWidth(100), GUILayout.MinHeight(32)))
|
||||
{
|
||||
string assetPath = AssetDatabase.GetAssetPath(mesh);
|
||||
ModelImporter modelImporter = AssetImporter.GetAtPath(assetPath) as ModelImporter;
|
||||
if (modelImporter != null)
|
||||
{
|
||||
modelImporter.isReadable = true;
|
||||
}
|
||||
modelImporter.SaveAndReimport();
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
protected override bool ValidateBlueprint()
|
||||
{
|
||||
if (sourceMesh != null)
|
||||
{
|
||||
if (!sourceMesh.isReadable)
|
||||
{
|
||||
NonReadableMeshWarning(sourceMesh);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract int VertexToParticle(int vertexIndex);
|
||||
|
||||
public override void UpdateParticleVisibility(Camera cam)
|
||||
{
|
||||
if (cam != null)
|
||||
{
|
||||
for (int i = 0; i < blueprint.positions.Length; i++)
|
||||
{
|
||||
if (blueprint.IsParticleActive(i))
|
||||
{
|
||||
Vector3 camToParticle = cam.transform.position - blueprint.positions[i];
|
||||
sqrDistanceToCamera[i] = camToParticle.sqrMagnitude;
|
||||
|
||||
Vector3 normal;
|
||||
|
||||
switch (particleCulling)
|
||||
{
|
||||
case ParticleCulling.Off:
|
||||
visible[i] = true;
|
||||
break;
|
||||
case ParticleCulling.Back:
|
||||
normal = blueprint.restOrientations[i] * Vector3.forward;
|
||||
visible[i] = Vector3.Dot(normal, camToParticle) > 0;
|
||||
break;
|
||||
case ParticleCulling.Front:
|
||||
normal = blueprint.restOrientations[i] * Vector3.forward;
|
||||
visible[i] = Vector3.Dot(normal, camToParticle) <= 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((renderModeFlags & 1) != 0)
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawGradientMesh(float[] vertexWeights = null, float[] wireframeWeights = null)
|
||||
{
|
||||
// Due to this Unity bug: https://issuetracker.unity3d.com/issues/drawmeshnow-is-not-drawing-mesh-immediately-dx12
|
||||
// we need to create two meshes insteaf of one :(
|
||||
if (sourceMesh == null)
|
||||
return;
|
||||
|
||||
visualizationMesh = GameObject.Instantiate(sourceMesh);
|
||||
visualizationWireMesh = GameObject.Instantiate(sourceMesh);
|
||||
|
||||
if (gradientMaterial.SetPass(0))
|
||||
{
|
||||
var matrix = Matrix4x4.TRS(Vector3.zero, (blueprint as ObiMeshBasedActorBlueprint).rotation, (blueprint as ObiMeshBasedActorBlueprint).scale);
|
||||
|
||||
Color[] colors = new Color[visualizationMesh.vertexCount];
|
||||
for (int i = 0; i < colors.Length; i++)
|
||||
{
|
||||
int particle = VertexToParticle(i);
|
||||
if (particle >= 0 && particle < blueprint.particleCount)
|
||||
{
|
||||
float weight = 1;
|
||||
if (vertexWeights != null)
|
||||
weight = vertexWeights[particle];
|
||||
|
||||
colors[i] = weight * currentProperty.ToColor(particle);
|
||||
}
|
||||
else
|
||||
colors[i] = Color.gray;
|
||||
}
|
||||
|
||||
visualizationMesh.colors = colors;
|
||||
Graphics.DrawMeshNow(visualizationMesh, matrix);
|
||||
|
||||
Color wireColor = ObiEditorSettings.GetOrCreateSettings().brushWireframeColor;
|
||||
|
||||
if (gradientMaterial.SetPass(1))
|
||||
{
|
||||
for (int i = 0; i < colors.Length; i++)
|
||||
{
|
||||
int particle = VertexToParticle(i);
|
||||
if (particle >= 0 && particle < blueprint.particleCount)
|
||||
{
|
||||
if (wireframeWeights != null)
|
||||
colors[i] = wireColor * wireframeWeights[particle];
|
||||
else
|
||||
colors[i] = wireColor;
|
||||
}
|
||||
else
|
||||
colors[i] = Color.gray;
|
||||
}
|
||||
|
||||
visualizationWireMesh.colors = colors;
|
||||
GL.wireframe = true;
|
||||
Graphics.DrawMeshNow(visualizationWireMesh, matrix);
|
||||
GL.wireframe = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GameObject.DestroyImmediate(visualizationMesh);
|
||||
GameObject.DestroyImmediate(visualizationWireMesh);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads particle data from a 2D texture. Can be used to adjust per particle mass, skin radius, etc. using
|
||||
* a texture instead of painting it in the editor.
|
||||
*
|
||||
* Will call onReadProperty once for each particle, passing the particle index and the bilinearly interpolated
|
||||
* color of the texture at its coordinate.
|
||||
*
|
||||
* Be aware that, if a particle corresponds to more than
|
||||
* one physical vertex and has multiple uv coordinates,
|
||||
* onReadProperty will be called multiple times for that particle.
|
||||
*/
|
||||
public bool ReadParticlePropertyFromTexture(Texture2D source, Action<int, Color> onReadProperty)
|
||||
{
|
||||
|
||||
if (source == null || onReadProperty == null)
|
||||
return false;
|
||||
|
||||
Vector2[] uvs = sourceMesh.uv;
|
||||
|
||||
// Iterate over all vertices in the mesh reading back colors from the texture:
|
||||
for (int i = 0; i < sourceMesh.vertexCount; ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
onReadProperty(VertexToParticle(i), source.GetPixelBilinear(uvs[i].x, uvs[i].y));
|
||||
}
|
||||
catch (UnityException e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool WriteParticlePropertyToTexture(string path, int width, int height, int padding)
|
||||
{
|
||||
|
||||
if (path == null || textureExportMaterial == null || !textureExportMaterial.SetPass(0))
|
||||
return false;
|
||||
|
||||
if (visualizationMesh == null)
|
||||
{
|
||||
visualizationMesh = GameObject.Instantiate(sourceMesh);
|
||||
}
|
||||
|
||||
RenderTexture tempRT = RenderTexture.GetTemporary(width, height, 0);
|
||||
RenderTexture paddingRT = RenderTexture.GetTemporary(width, height, 0);
|
||||
|
||||
RenderTexture old = RenderTexture.active;
|
||||
RenderTexture.active = tempRT;
|
||||
|
||||
GL.PushMatrix();
|
||||
|
||||
var proj = Matrix4x4.Ortho(0, 1, 0, 1, -1, 1);
|
||||
if (Camera.current != null) proj = proj * Camera.current.worldToCameraMatrix.inverse;
|
||||
GL.LoadProjectionMatrix(proj);
|
||||
|
||||
Color[] colors = new Color[sourceMesh.vertexCount];
|
||||
for (int i = 0; i < colors.Length; i++)
|
||||
colors[i] = currentProperty.ToColor(VertexToParticle(i));
|
||||
|
||||
visualizationMesh.colors = colors;
|
||||
Graphics.DrawMeshNow(visualizationMesh, Matrix4x4.identity);
|
||||
|
||||
GL.PopMatrix();
|
||||
|
||||
// Perform padding/edge dilation
|
||||
paddingMaterial.SetFloat("_Padding", padding);
|
||||
Graphics.Blit(tempRT, paddingRT, paddingMaterial);
|
||||
|
||||
// Read result into our Texture2D.
|
||||
RenderTexture.active = paddingRT;
|
||||
Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false);
|
||||
texture.ReadPixels(new Rect(0, 0, width, height), 0, 0);
|
||||
|
||||
RenderTexture.active = old;
|
||||
RenderTexture.ReleaseTemporary(paddingRT);
|
||||
RenderTexture.ReleaseTemporary(tempRT);
|
||||
|
||||
byte[] png = texture.EncodeToPNG();
|
||||
GameObject.DestroyImmediate(texture);
|
||||
|
||||
try
|
||||
{
|
||||
File.WriteAllBytes(path, png);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c81a94632ae434014aedb4cc241e73e2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,93 +0,0 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public static class ObiMeshUtils
|
||||
{
|
||||
// Temporary vector3 values
|
||||
static Vector3 tv1, tv2, tv3, tv4;
|
||||
|
||||
public static bool RayIntersectsTriangle(Vector3 origin,
|
||||
Vector3 dir,
|
||||
Vector3 vert0,
|
||||
Vector3 vert1,
|
||||
Vector3 vert2,
|
||||
ref float distance,
|
||||
ref Vector3 normal)
|
||||
{
|
||||
float det;
|
||||
|
||||
ObiVectorMath.Subtract(vert0, vert1, ref tv1);
|
||||
ObiVectorMath.Subtract(vert0, vert2, ref tv2);
|
||||
|
||||
ObiVectorMath.Cross(dir, tv2, ref tv4);
|
||||
det = Vector3.Dot(tv1, tv4);
|
||||
|
||||
if (det < Mathf.Epsilon)
|
||||
return false;
|
||||
|
||||
ObiVectorMath.Subtract(vert0, origin, ref tv3);
|
||||
|
||||
float u = Vector3.Dot(tv3, tv4);
|
||||
|
||||
if (u < 0f || u > det)
|
||||
return false;
|
||||
|
||||
ObiVectorMath.Cross(tv3, tv1, ref tv4);
|
||||
|
||||
float v = Vector3.Dot(dir, tv4);
|
||||
|
||||
if (v < 0f || u + v > det)
|
||||
return false;
|
||||
|
||||
distance = Vector3.Dot(tv2, tv4) * (1f / det);
|
||||
ObiVectorMath.Cross(tv1, tv2, ref normal);
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
* Find the nearest triangle intersected by InWorldRay on this mesh. InWorldRay is in world space.
* @hit contains information about the hit point. @distance limits how far from @InWorldRay.origin the hit
* point may be. @cullingMode determines what face orientations are tested (Culling.Front only tests front
* faces, Culling.Back only tests back faces, and Culling.FrontBack tests both).
* Ray origin and position values are in local space.
*/
public static bool WorldRaycast(Ray InWorldRay, Matrix4x4 transform, Vector3[] vertices, int[] triangles, out ObiRaycastHit hit, float distance = Mathf.Infinity)
{
|
||||
Ray ray = InWorldRay;
|
||||
if (transform != null)
|
||||
{
|
||||
Matrix4x4 inv = transform.inverse;
|
||||
ray.origin = inv.MultiplyPoint3x4(ray.origin);
|
||||
ray.direction = inv.MultiplyVector(ray.direction);
|
||||
}
return MeshRaycast(ray, vertices, triangles, out hit, distance);
}
/**
* Cast a ray (in model space) against a mesh.
*/
public static bool MeshRaycast(Ray InRay, Vector3[] vertices, int[] triangles, out ObiRaycastHit hit, float distance = Mathf.Infinity)
{
|
||||
Vector3 hitNormal = Vector3.zero; // vars used in loop
|
||||
Vector3 vert0, vert1, vert2;
|
||||
Vector3 origin = InRay.origin, direction = InRay.direction;
|
||||
|
||||
hit = new ObiRaycastHit(Mathf.Infinity,
|
||||
Vector3.zero,
|
||||
Vector3.zero,
|
||||
-1);
|
||||
/**
|
||||
* Iterate faces, testing for nearest hit to ray origin.
|
||||
*/
|
||||
for (int CurTri = 0; CurTri < triangles.Length; CurTri += 3)
|
||||
{
|
||||
if (CurTri + 2 >= triangles.Length) continue;
|
||||
if (triangles[CurTri + 2] >= vertices.Length) continue;
|
||||
|
||||
vert0 = vertices[triangles[CurTri + 0]];
|
||||
vert1 = vertices[triangles[CurTri + 1]];
|
||||
vert2 = vertices[triangles[CurTri + 2]];
|
||||
|
||||
// Second pass, test intersection with triangle
|
||||
if (RayIntersectsTriangle(origin, direction, vert0, vert1, vert2, ref distance, ref hitNormal))
|
||||
{
|
||||
if (distance < hit.distance)
|
||||
{
|
||||
hit.distance = distance;
|
||||
hit.triangle = CurTri / 3;
|
||||
hit.position = InRay.GetPoint(hit.distance);
|
||||
hit.normal = hitNormal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit.triangle > -1;
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d2a4dd4e807c4053b4e4af4d43db45e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,127 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiParticleEditorDrawing : MonoBehaviour
|
||||
{
|
||||
public static Mesh particlesMesh;
|
||||
public static Material particleMaterial;
|
||||
|
||||
private static void CreateParticlesMesh()
|
||||
{
|
||||
if (particlesMesh == null)
|
||||
{
|
||||
particlesMesh = new Mesh();
|
||||
particlesMesh.hideFlags = HideFlags.HideAndDontSave;
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateParticleMaterials()
|
||||
{
|
||||
if (!particleMaterial)
|
||||
{
|
||||
particleMaterial = Resources.Load<Material>("EditorParticle");
|
||||
}
|
||||
}
|
||||
|
||||
public static void DestroyParticlesMesh()
|
||||
{
|
||||
GameObject.DestroyImmediate(particlesMesh);
|
||||
}
|
||||
|
||||
public static void DrawParticles(Camera cam, ObiActorBlueprint blueprint, bool[] visible, Color[] baseColor, int[] sortedIndices, float radiusScale = 1)
|
||||
{
|
||||
CreateParticlesMesh();
|
||||
CreateParticleMaterials();
|
||||
|
||||
if (!particleMaterial.SetPass(0))
|
||||
return;
|
||||
|
||||
//because each vertex needs to be drawn as a quad.
|
||||
int particlesPerDrawcall = Constants.maxVertsPerMesh / 4;
|
||||
int drawcallCount = blueprint.particleCount / particlesPerDrawcall + 1;
|
||||
particlesPerDrawcall = Mathf.Min(particlesPerDrawcall, blueprint.particleCount);
|
||||
|
||||
List<Vector3> vertices = new List<Vector3>(blueprint.activeParticleCount* 4);
|
||||
List<Vector3> normals = new List<Vector3>(blueprint.activeParticleCount * 4);
|
||||
List<Vector4> uvs = new List<Vector4>(blueprint.activeParticleCount * 4);
|
||||
List<Color> colors = new List<Color>(blueprint.activeParticleCount * 4);
|
||||
List<int> triangles = new List<int>(blueprint.activeParticleCount * 6);
|
||||
|
||||
Vector3 particleOffset0 = new Vector3(1, 1, 0);
|
||||
Vector3 particleOffset1 = new Vector3(-1, 1, 0);
|
||||
Vector3 particleOffset2 = new Vector3(-1, -1, 0);
|
||||
Vector3 particleOffset3 = new Vector3(1, -1, 0);
|
||||
|
||||
Vector4 radius = new Vector4(1, 0, 0, 0.005f * radiusScale);
|
||||
|
||||
for (int i = 0; i < drawcallCount; ++i)
|
||||
{
|
||||
//Draw all cloth vertices:
|
||||
particlesMesh.Clear();
|
||||
vertices.Clear();
|
||||
uvs.Clear();
|
||||
normals.Clear();
|
||||
colors.Clear();
|
||||
triangles.Clear();
|
||||
|
||||
int index = 0;
|
||||
|
||||
// Run over all particles (not only active ones), since they're reordered based on distance to camera.
|
||||
// Then test if the sorted index is active or not, and skip inactive ones.
|
||||
int limit = Mathf.Min((i + 1) * particlesPerDrawcall, blueprint.particleCount);
|
||||
|
||||
for (int j = i * particlesPerDrawcall; j < limit; ++j)
|
||||
{
|
||||
int sortedIndex = sortedIndices[j];
|
||||
|
||||
// skip inactive ones:
|
||||
if (!blueprint.IsParticleActive(sortedIndex))
|
||||
continue;
|
||||
|
||||
normals.Add(particleOffset0);
|
||||
normals.Add(particleOffset1);
|
||||
normals.Add(particleOffset2);
|
||||
normals.Add(particleOffset3);
|
||||
|
||||
uvs.Add(radius);
|
||||
uvs.Add(radius);
|
||||
uvs.Add(radius);
|
||||
uvs.Add(radius);
|
||||
|
||||
vertices.Add(blueprint.positions[sortedIndex]);
|
||||
vertices.Add(blueprint.positions[sortedIndex]);
|
||||
vertices.Add(blueprint.positions[sortedIndex]);
|
||||
vertices.Add(blueprint.positions[sortedIndex]);
|
||||
|
||||
colors.Add(baseColor[sortedIndex]);
|
||||
colors.Add(baseColor[sortedIndex]);
|
||||
colors.Add(baseColor[sortedIndex]);
|
||||
colors.Add(baseColor[sortedIndex]);
|
||||
|
||||
triangles.Add(index + 2);
|
||||
triangles.Add(index + 1);
|
||||
triangles.Add(index);
|
||||
triangles.Add(index + 3);
|
||||
triangles.Add(index + 2);
|
||||
triangles.Add(index);
|
||||
|
||||
index += 4;
|
||||
}
|
||||
|
||||
particlesMesh.SetVertices(vertices);
|
||||
particlesMesh.SetNormals(normals);
|
||||
particlesMesh.SetColors(colors);
|
||||
particlesMesh.SetUVs(0, uvs);
|
||||
particlesMesh.SetTriangles(triangles,0, true);
|
||||
|
||||
Graphics.DrawMeshNow(particlesMesh, Matrix4x4.identity);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 982f73e0e40c749f09db403624bbd8e1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfda10b0e82f747998295540d5750108
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b9ba4ddc644a4bfa8ab44a5826b8007
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,24 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public abstract class ObiBlueprintBoolProperty : ObiBlueprintProperty<bool>
|
||||
{
|
||||
public override bool Equals(int firstIndex, int secondIndex)
|
||||
{
|
||||
return Get(firstIndex) == Get(secondIndex);
|
||||
}
|
||||
|
||||
public override void PropertyField()
|
||||
{
|
||||
value = EditorGUILayout.Toggle(name, value);
|
||||
}
|
||||
|
||||
public override Color ToColor(int index)
|
||||
{
|
||||
return value ? Color.white : Color.gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19cb8e21747094d6dae8dff155654066
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,31 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public abstract class ObiBlueprintColorProperty : ObiBlueprintProperty<Color>
|
||||
{
|
||||
public ObiActorBlueprintEditor editor;
|
||||
|
||||
public ObiBlueprintColorProperty(ObiActorBlueprintEditor editor)
|
||||
{
|
||||
this.editor = editor;
|
||||
}
|
||||
|
||||
public override bool Equals(int firstIndex, int secondIndex)
|
||||
{
|
||||
return Get(firstIndex) == Get(secondIndex);
|
||||
}
|
||||
|
||||
public override void PropertyField()
|
||||
{
|
||||
value = EditorGUILayout.ColorField(name, value);
|
||||
}
|
||||
|
||||
public override Color ToColor(int index)
|
||||
{
|
||||
return editor.blueprint.colors[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64ab0b4fad7614808acc3cdb75215c50
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,94 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public abstract class ObiBlueprintFloatProperty : ObiBlueprintProperty<float>
|
||||
{
|
||||
public float minVisualizationValue = 0;
|
||||
public float maxVisualizationValue = 10;
|
||||
protected float minUserVisualizationValue = 0;
|
||||
protected float maxUserVisualizationValue = 10;
|
||||
|
||||
protected float? minValue = null;
|
||||
protected float? maxValue = null;
|
||||
|
||||
public bool autoRange = true;
|
||||
public ObiActorBlueprintEditor editor;
|
||||
|
||||
public ObiBlueprintFloatProperty(ObiActorBlueprintEditor editor, float? minValue = null, float? maxValue = null)
|
||||
{
|
||||
this.editor = editor;
|
||||
this.minValue = minValue;
|
||||
this.maxValue = maxValue;
|
||||
}
|
||||
|
||||
public override bool Equals(int firstIndex, int secondIndex)
|
||||
{
|
||||
float v1 = Get(firstIndex);
|
||||
float v2 = Get(secondIndex);
|
||||
if (v1 == v2) return true;
|
||||
return Mathf.Approximately(v1,v2);
|
||||
}
|
||||
|
||||
public override void PropertyField()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
value = EditorGUILayout.FloatField(name, value);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (minValue.HasValue)
|
||||
value = Mathf.Max(minValue.Value, value);
|
||||
if (maxValue.HasValue)
|
||||
value = Mathf.Min(maxValue.Value, value);
|
||||
}
|
||||
}
|
||||
|
||||
public override void RecalculateMinMax()
|
||||
{
|
||||
if (editor != null && autoRange)
|
||||
{
|
||||
maxVisualizationValue = float.MinValue;
|
||||
minVisualizationValue = float.MaxValue;
|
||||
|
||||
for (int i = 0; i < editor.blueprint.activeParticleCount; i++)
|
||||
{
|
||||
float v = Get(i);
|
||||
maxVisualizationValue = Mathf.Max(maxVisualizationValue, v);
|
||||
minVisualizationValue = Mathf.Min(minVisualizationValue, v);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
maxVisualizationValue = maxUserVisualizationValue;
|
||||
minVisualizationValue = minUserVisualizationValue;
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisualizationOptions()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
autoRange = EditorGUILayout.Toggle("Automatic property range", autoRange);
|
||||
GUI.enabled = !autoRange;
|
||||
EditorGUI.indentLevel++;
|
||||
minUserVisualizationValue = EditorGUILayout.FloatField("Min", minUserVisualizationValue);
|
||||
maxUserVisualizationValue = EditorGUILayout.FloatField("Max", maxUserVisualizationValue);
|
||||
EditorGUI.indentLevel--;
|
||||
GUI.enabled = true;
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
RecalculateMinMax();
|
||||
editor.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public override Color ToColor(int index)
|
||||
{
|
||||
Gradient gradient = ObiEditorSettings.GetOrCreateSettings().propertyGradient;
|
||||
if (!Mathf.Approximately(minVisualizationValue, maxVisualizationValue))
|
||||
return gradient.Evaluate(Mathf.InverseLerp(minVisualizationValue, maxVisualizationValue, Get(index)));
|
||||
else return gradient.Evaluate(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be67f2576200242f080bbcc074dc598a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,41 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public abstract class ObiBlueprintIntProperty : ObiBlueprintProperty<int>
|
||||
{
|
||||
protected int? minValue = null;
|
||||
protected int? maxValue = null;
|
||||
|
||||
public ObiBlueprintIntProperty(int? minValue = null, int? maxValue = null)
|
||||
{
|
||||
this.minValue = minValue;
|
||||
this.maxValue = maxValue;
|
||||
}
|
||||
|
||||
public override bool Equals(int firstIndex, int secondIndex)
|
||||
{
|
||||
return Get(firstIndex) == Get(secondIndex);
|
||||
}
|
||||
|
||||
public override void PropertyField()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
value = EditorGUILayout.IntField(name, value);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (minValue.HasValue)
|
||||
value = Mathf.Max(minValue.Value, value);
|
||||
if (maxValue.HasValue)
|
||||
value = Mathf.Min(maxValue.Value, value);
|
||||
}
|
||||
}
|
||||
|
||||
public override Color ToColor(int index)
|
||||
{
|
||||
int colorIndex = Get(index) % ObiUtils.colorAlphabet.Length;
|
||||
return ObiUtils.colorAlphabet[colorIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8661f9e9cfd044c7bb759145c2a8d73
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,28 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public abstract class ObiBlueprintMaskProperty : ObiBlueprintIntProperty
|
||||
{
|
||||
public ObiBlueprintMaskProperty() : base(null,null)
|
||||
{
|
||||
}
|
||||
|
||||
public override void PropertyField()
|
||||
{
|
||||
value = EditorGUILayout.MaskField(name, value, ObiUtils.categoryNames);
|
||||
}
|
||||
|
||||
private int MathMod(int a, int b)
|
||||
{
|
||||
return (Mathf.Abs(a * b) + a) % b;
|
||||
}
|
||||
|
||||
public override Color ToColor(int index)
|
||||
{
|
||||
int colorIndex = MathMod(Get(index),ObiUtils.colorAlphabet.Length);
|
||||
return ObiUtils.colorAlphabet[colorIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 165ad17d69adf415ea7609a9373de001
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,79 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public abstract class ObiBlueprintPropertyBase
|
||||
{
|
||||
protected List<IObiBrushMode> brushModes = new List<IObiBrushMode>();
|
||||
private int selectedBrushMode;
|
||||
|
||||
public abstract string name
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public abstract void PropertyField();
|
||||
public virtual void VisualizationOptions(){}
|
||||
public virtual void OnSceneRepaint(){}
|
||||
|
||||
public abstract bool Equals(int firstIndex, int secondIndex);
|
||||
|
||||
public abstract void GetDefaultFromIndex(int index);
|
||||
public abstract void SetDefaultToIndex(int index);
|
||||
public virtual bool Masked(int index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void RecalculateMinMax() { }
|
||||
public virtual Color ToColor(int index) { return Color.white; }
|
||||
|
||||
protected void Initialize(ObiBrushBase paintBrush)
|
||||
{
|
||||
// Initialize the brush if there's no brush mode set:
|
||||
if (paintBrush.brushMode == null && brushModes.Count > 0)
|
||||
{
|
||||
selectedBrushMode = 0;
|
||||
paintBrush.brushMode = brushModes[selectedBrushMode];
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSelect(ObiBrushBase paintBrush)
|
||||
{
|
||||
// Upon selecting the property, change to the last selected brush mode:
|
||||
if (brushModes.Count > selectedBrushMode)
|
||||
paintBrush.brushMode = brushModes[selectedBrushMode];
|
||||
|
||||
}
|
||||
|
||||
public void BrushModes(ObiBrushBase paintBrush)
|
||||
{
|
||||
Initialize(paintBrush);
|
||||
|
||||
GUIContent[] contents = new GUIContent[brushModes.Count];
|
||||
for (int i = 0; i < brushModes.Count; ++i)
|
||||
contents[i] = new GUIContent(brushModes[i].name);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
selectedBrushMode = ObiEditorUtils.DoToolBar(selectedBrushMode, contents);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
paintBrush.brushMode = brushModes[selectedBrushMode];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ObiBlueprintProperty<T> : ObiBlueprintPropertyBase
|
||||
{
|
||||
protected T value;
|
||||
|
||||
public T GetDefault() { return value; }
|
||||
public override void GetDefaultFromIndex(int index) { value = Get(index); }
|
||||
public override void SetDefaultToIndex(int index) { Set(index, value); }
|
||||
|
||||
public abstract T Get(int index);
|
||||
public abstract void Set(int index, T value);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60a83ba184caf4a1aba4da6754776a1d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,13 +0,0 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public interface IObiSelectableParticleProvider
|
||||
{
|
||||
void SetSelected(int particleIndex, bool selected);
|
||||
bool IsSelected(int particleIndex);
|
||||
bool Editable(int particleIndex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c3a2643915854763af75d63fa1ec0c9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,33 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiBlueprintColor : ObiBlueprintColorProperty
|
||||
{
|
||||
public ObiBlueprintColor(ObiActorBlueprintEditor editor) : base(editor)
|
||||
{
|
||||
brushModes.Add(new ObiColorPaintBrushMode(this));
|
||||
brushModes.Add(new ObiColorSmoothBrushMode(this));
|
||||
}
|
||||
|
||||
public override string name
|
||||
{
|
||||
get { return "Color"; }
|
||||
}
|
||||
|
||||
public override Color Get(int index)
|
||||
{
|
||||
return editor.blueprint.colors[index];
|
||||
}
|
||||
public override void Set(int index, Color value)
|
||||
{
|
||||
editor.blueprint.colors[index] = value;
|
||||
editor.blueprint.edited = true;
|
||||
}
|
||||
public override bool Masked(int index)
|
||||
{
|
||||
return !editor.Editable(index);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 810c95482e60a44209c5ece07e287153
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,32 +0,0 @@
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiBlueprintFilterCategory : ObiBlueprintIntProperty
|
||||
{
|
||||
public ObiActorBlueprintEditor editor;
|
||||
|
||||
public ObiBlueprintFilterCategory(ObiActorBlueprintEditor editor) : base(ObiUtils.MinCategory, ObiUtils.MaxCategory)
|
||||
{
|
||||
this.editor = editor;
|
||||
brushModes.Add(new ObiIntPaintBrushMode(this));
|
||||
}
|
||||
|
||||
public override string name
|
||||
{
|
||||
get { return "Category"; }
|
||||
}
|
||||
|
||||
public override int Get(int index)
|
||||
{
|
||||
return ObiUtils.GetCategoryFromFilter(editor.blueprint.filters[index]);
|
||||
}
|
||||
public override void Set(int index, int value)
|
||||
{
|
||||
editor.blueprint.filters[index] = ObiUtils.MakeFilter(ObiUtils.GetMaskFromFilter(editor.blueprint.filters[index]), value);
|
||||
editor.blueprint.edited = true;
|
||||
}
|
||||
public override bool Masked(int index)
|
||||
{
|
||||
return !editor.Editable(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08502999496e54f49bb9dee0e0855794
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,32 +0,0 @@
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiBlueprintFilterMask : ObiBlueprintMaskProperty
|
||||
{
|
||||
public ObiActorBlueprintEditor editor;
|
||||
|
||||
public ObiBlueprintFilterMask(ObiActorBlueprintEditor editor)
|
||||
{
|
||||
this.editor = editor;
|
||||
brushModes.Add(new ObiIntPaintBrushMode(this));
|
||||
}
|
||||
|
||||
public override string name
|
||||
{
|
||||
get { return "Collides with"; }
|
||||
}
|
||||
|
||||
public override int Get(int index)
|
||||
{
|
||||
return ObiUtils.GetMaskFromFilter(editor.blueprint.filters[index]);
|
||||
}
|
||||
public override void Set(int index, int value)
|
||||
{
|
||||
editor.blueprint.filters[index] = ObiUtils.MakeFilter(value,ObiUtils.GetCategoryFromFilter(editor.blueprint.filters[index]));
|
||||
editor.blueprint.edited = true;
|
||||
}
|
||||
public override bool Masked(int index)
|
||||
{
|
||||
return !editor.Editable(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ead8a00c964834718a2411be5d7361f3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,33 +0,0 @@
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiBlueprintMass : ObiBlueprintFloatProperty
|
||||
{
|
||||
|
||||
public ObiBlueprintMass(ObiActorBlueprintEditor editor) : base(editor,0)
|
||||
{
|
||||
brushModes.Add(new ObiFloatPaintBrushMode(this));
|
||||
brushModes.Add(new ObiFloatAddBrushMode(this));
|
||||
brushModes.Add(new ObiFloatCopyBrushMode(this, this));
|
||||
brushModes.Add(new ObiFloatSmoothBrushMode(this));
|
||||
}
|
||||
|
||||
public override string name
|
||||
{
|
||||
get { return "Mass"; }
|
||||
}
|
||||
|
||||
public override float Get(int index)
|
||||
{
|
||||
return ObiUtils.InvMassToMass(editor.blueprint.invMasses[index]);
|
||||
}
|
||||
public override void Set(int index, float value)
|
||||
{
|
||||
editor.blueprint.invMasses[index] = ObiUtils.MassToInvMass(value);
|
||||
editor.blueprint.edited = true;
|
||||
}
|
||||
public override bool Masked(int index)
|
||||
{
|
||||
return !editor.Editable(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd39fbd4c226542e58dc8ecceb5f8f14
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,37 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiBlueprintRadius : ObiBlueprintFloatProperty
|
||||
{
|
||||
|
||||
public ObiBlueprintRadius(ObiActorBlueprintEditor editor) : base(editor,0.0000001f)
|
||||
{
|
||||
brushModes.Add(new ObiFloatPaintBrushMode(this));
|
||||
brushModes.Add(new ObiFloatAddBrushMode(this));
|
||||
brushModes.Add(new ObiFloatCopyBrushMode(this, this));
|
||||
brushModes.Add(new ObiFloatSmoothBrushMode(this));
|
||||
}
|
||||
|
||||
public override string name
|
||||
{
|
||||
get { return "Radius"; }
|
||||
}
|
||||
|
||||
public override float Get(int index)
|
||||
{
|
||||
return editor.blueprint.principalRadii[index][0];
|
||||
}
|
||||
public override void Set(int index, float value)
|
||||
{
|
||||
value = Mathf.Max(0.0000001f, value);
|
||||
float ratio = value / Get(index);
|
||||
editor.blueprint.principalRadii[index] = editor.blueprint.principalRadii[index] * ratio;
|
||||
editor.blueprint.edited = true;
|
||||
}
|
||||
public override bool Masked(int index)
|
||||
{
|
||||
return !editor.Editable(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5c61b50f6f4a468aa246f01e5268831
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,29 +0,0 @@
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiBlueprintSelected : ObiBlueprintBoolProperty
|
||||
{
|
||||
public IObiSelectableParticleProvider provider;
|
||||
public ObiBlueprintSelected(IObiSelectableParticleProvider provider)
|
||||
{
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public override string name
|
||||
{
|
||||
get { return "Selected"; }
|
||||
}
|
||||
|
||||
public override bool Get(int index)
|
||||
{
|
||||
return provider.IsSelected(index);
|
||||
}
|
||||
public override void Set(int index, bool value)
|
||||
{
|
||||
provider.SetSelected(index,value);
|
||||
}
|
||||
public override bool Masked(int index)
|
||||
{
|
||||
return !provider.Editable(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 270971958421b4fec9e5a5ba95699518
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be5de82c95ded480d881176f73fc19b7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,25 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public abstract class ObiBlueprintRenderMode
|
||||
{
|
||||
protected ObiActorBlueprintEditor editor;
|
||||
public abstract string name
|
||||
{
|
||||
get;
|
||||
}
|
||||
public ObiBlueprintRenderMode(ObiActorBlueprintEditor editor)
|
||||
{
|
||||
this.editor = editor;
|
||||
}
|
||||
|
||||
public virtual void DrawWithCamera(Camera camera) {}
|
||||
public virtual void OnSceneRepaint(SceneView sceneView) {}
|
||||
public virtual void Refresh(){}
|
||||
|
||||
public virtual void OnDestroy() { }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d60f616a126974e6d8be81fbbe459bac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,63 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiBlueprintRenderModeAerodynamicConstraints : ObiBlueprintRenderMode
|
||||
{
|
||||
public override string name
|
||||
{
|
||||
get { return "Aerodynamic constraints"; }
|
||||
}
|
||||
|
||||
public ObiMeshBasedActorBlueprintEditor meshBasedEditor
|
||||
{
|
||||
get { return editor as ObiMeshBasedActorBlueprintEditor; }
|
||||
}
|
||||
|
||||
public ObiBlueprintRenderModeAerodynamicConstraints(ObiMeshBasedActorBlueprintEditor editor) : base(editor)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnSceneRepaint(SceneView sceneView)
|
||||
{
|
||||
var meshEditor = editor as ObiMeshBasedActorBlueprintEditor;
|
||||
if (meshEditor != null)
|
||||
{
|
||||
// Get per-particle normals:
|
||||
Vector3[] normals = meshEditor.sourceMesh.normals;
|
||||
Vector3[] particleNormals = new Vector3[meshEditor.blueprint.particleCount];
|
||||
for (int i = 0; i < normals.Length; ++i)
|
||||
{
|
||||
int welded = meshEditor.VertexToParticle(i);
|
||||
particleNormals[welded] = normals[i];
|
||||
}
|
||||
|
||||
using (new Handles.DrawingScope(Color.blue, Matrix4x4.identity))
|
||||
{
|
||||
var constraints = editor.blueprint.GetConstraintsByType(Oni.ConstraintType.Aerodynamics) as ObiConstraints<ObiAerodynamicConstraintsBatch>;
|
||||
if (constraints != null)
|
||||
{
|
||||
Vector3[] lines = new Vector3[constraints.GetActiveConstraintCount() * 2];
|
||||
int lineIndex = 0;
|
||||
|
||||
foreach (var batch in constraints.batches)
|
||||
{
|
||||
for (int i = 0; i < batch.activeConstraintCount; ++i)
|
||||
{
|
||||
int particleIndex = batch.particleIndices[i];
|
||||
Vector3 position = editor.blueprint.GetParticlePosition(particleIndex);
|
||||
lines[lineIndex++] = position;
|
||||
lines[lineIndex++] = position + particleNormals[particleIndex] * 0.025f;
|
||||
}
|
||||
}
|
||||
|
||||
Handles.DrawLines(lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18881e26e784d47aaa8aa27c93fe0b49
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,44 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiBlueprintRenderModeBendConstraints : ObiBlueprintRenderMode
|
||||
{
|
||||
public override string name
|
||||
{
|
||||
get { return "Bend constraints"; }
|
||||
}
|
||||
|
||||
public ObiBlueprintRenderModeBendConstraints(ObiActorBlueprintEditor editor) : base(editor)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnSceneRepaint(SceneView sceneView)
|
||||
{
|
||||
using (new Handles.DrawingScope(Color.magenta, Matrix4x4.identity))
|
||||
{
|
||||
var constraints = editor.blueprint.GetConstraintsByType(Oni.ConstraintType.Bending) as ObiConstraints<ObiBendConstraintsBatch>;
|
||||
if (constraints != null)
|
||||
{
|
||||
Vector3[] lines = new Vector3[constraints.GetActiveConstraintCount() * 2];
|
||||
int lineIndex = 0;
|
||||
|
||||
foreach (var batch in constraints.batches)
|
||||
{
|
||||
for (int i = 0; i < batch.activeConstraintCount; ++i)
|
||||
{
|
||||
lines[lineIndex++] = editor.blueprint.GetParticlePosition(batch.particleIndices[i * 3]);
|
||||
lines[lineIndex++] = editor.blueprint.GetParticlePosition(batch.particleIndices[i * 3 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
Handles.DrawLines(lines);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15e21bc6bea1c4320948413c8d7334bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,44 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiBlueprintRenderModeDistanceConstraints : ObiBlueprintRenderMode
|
||||
{
|
||||
public override string name
|
||||
{
|
||||
get { return "Distance constraints"; }
|
||||
}
|
||||
|
||||
public ObiBlueprintRenderModeDistanceConstraints(ObiActorBlueprintEditor editor) : base(editor)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnSceneRepaint(SceneView sceneView)
|
||||
{
|
||||
|
||||
using (new Handles.DrawingScope(Color.green, Matrix4x4.identity))
|
||||
{
|
||||
var constraints = editor.blueprint.GetConstraintsByType(Oni.ConstraintType.Distance) as ObiConstraints<ObiDistanceConstraintsBatch>;
|
||||
if (constraints != null)
|
||||
{
|
||||
Vector3[] lines = new Vector3[constraints.GetActiveConstraintCount() * 2];
|
||||
int lineIndex = 0;
|
||||
|
||||
foreach (var batch in constraints.batches)
|
||||
{
|
||||
for (int i = 0; i < batch.activeConstraintCount; ++i)
|
||||
{
|
||||
lines[lineIndex++] = editor.blueprint.GetParticlePosition(batch.particleIndices[i * 2]);
|
||||
lines[lineIndex++] = editor.blueprint.GetParticlePosition(batch.particleIndices[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
Handles.DrawLines(lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac734c05a2b994f148fd43cd5829b1be
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,46 +0,0 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiBlueprintRenderModeMesh : ObiBlueprintRenderMode
|
||||
{
|
||||
public override string name
|
||||
{
|
||||
get { return "Mesh"; }
|
||||
}
|
||||
|
||||
public ObiMeshBasedActorBlueprintEditor meshBasedEditor
|
||||
{
|
||||
get { return editor as ObiMeshBasedActorBlueprintEditor; }
|
||||
}
|
||||
|
||||
public ObiBlueprintRenderModeMesh(ObiMeshBasedActorBlueprintEditor editor) : base(editor)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnSceneRepaint(SceneView sceneView)
|
||||
{
|
||||
if (meshBasedEditor.currentTool is ObiPaintBrushEditorTool)
|
||||
{
|
||||
ObiPaintBrushEditorTool paintTool = (ObiPaintBrushEditorTool)meshBasedEditor.currentTool;
|
||||
|
||||
float[] weights = new float[ObiActorBlueprintEditor.selectionStatus.Length];
|
||||
for (int i = 0; i < weights.Length; i++)
|
||||
{
|
||||
if (paintTool.selectionMask && !ObiActorBlueprintEditor.selectionStatus[i])
|
||||
weights[i] = 0;
|
||||
else
|
||||
weights[i] = 1;
|
||||
}
|
||||
|
||||
float[] wireframeWeights = new float[paintTool.paintBrush.weights.Length];
|
||||
for (int i = 0; i < wireframeWeights.Length; i++)
|
||||
wireframeWeights[i] = paintTool.paintBrush.weights[i];
|
||||
|
||||
meshBasedEditor.DrawGradientMesh(weights, wireframeWeights);
|
||||
}
|
||||
else
|
||||
meshBasedEditor.DrawGradientMesh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dbcd302f71d6446cd976f736b365c7ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,65 +0,0 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiBlueprintRenderModeParticles : ObiBlueprintRenderMode
|
||||
{
|
||||
public override string name
|
||||
{
|
||||
get { return "Particles"; }
|
||||
}
|
||||
|
||||
private Shader shader;
|
||||
private Material material;
|
||||
private ParticleImpostorRendering impostorDrawer;
|
||||
private MaterialPropertyBlock mpb;
|
||||
|
||||
public ObiBlueprintRenderModeParticles(ObiActorBlueprintEditor editor) :base(editor)
|
||||
{
|
||||
impostorDrawer = new ParticleImpostorRendering();
|
||||
impostorDrawer.UpdateMeshes(editor.blueprint);
|
||||
mpb = new MaterialPropertyBlock();
|
||||
}
|
||||
|
||||
void CreateMaterialIfNeeded()
|
||||
{
|
||||
if (shader == null)
|
||||
{
|
||||
shader = Shader.Find("Obi/EditorParticles");
|
||||
if (shader != null)
|
||||
{
|
||||
if (!shader.isSupported)
|
||||
Debug.LogWarning("Particle rendering shader not suported.");
|
||||
|
||||
if (material == null || material.shader != shader)
|
||||
{
|
||||
GameObject.DestroyImmediate(material);
|
||||
material = new Material(shader);
|
||||
material.hideFlags = HideFlags.HideAndDontSave;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawWithCamera(Camera camera)
|
||||
{
|
||||
CreateMaterialIfNeeded();
|
||||
mpb.SetFloat("_RadiusScale", 1);
|
||||
mpb.SetColor("_ParticleColor", Color.white);
|
||||
foreach (Mesh mesh in impostorDrawer.Meshes)
|
||||
Graphics.DrawMesh(mesh, Matrix4x4.identity, material, 0, camera, 0, mpb);
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
impostorDrawer.UpdateMeshes(editor.blueprint, editor.visible, editor.tint);
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
GameObject.DestroyImmediate(material);
|
||||
impostorDrawer.ClearMeshes();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b51ea2becbebe48ba9d77e9d28403f51
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,54 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiBlueprintRenderModeShapeMatchingConstraints : ObiBlueprintRenderMode
|
||||
{
|
||||
public override string name
|
||||
{
|
||||
get { return "Shape matching clusters"; }
|
||||
}
|
||||
|
||||
public ObiBlueprintRenderModeShapeMatchingConstraints(ObiActorBlueprintEditor editor) : base(editor)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnSceneRepaint(SceneView sceneView)
|
||||
{
|
||||
|
||||
using (new Handles.DrawingScope(Color.cyan, Matrix4x4.identity))
|
||||
{
|
||||
var constraints = editor.blueprint.GetConstraintsByType(Oni.ConstraintType.ShapeMatching) as ObiConstraints<ObiShapeMatchingConstraintsBatch>;
|
||||
if (constraints != null)
|
||||
{
|
||||
List<Vector3> lines = new List<Vector3>();
|
||||
|
||||
foreach (var batch in constraints.batches)
|
||||
{
|
||||
for (int i = 0; i < batch.activeConstraintCount; ++i)
|
||||
{
|
||||
int first = batch.firstIndex[i];
|
||||
Vector3 p1 = editor.blueprint.GetParticlePosition(batch.particleIndices[first]);
|
||||
|
||||
for (int j = 1; j < batch.numIndices[i]; ++j)
|
||||
{
|
||||
|
||||
int index = first + j;
|
||||
Vector3 p2 = editor.blueprint.GetParticlePosition(batch.particleIndices[index]);
|
||||
|
||||
lines.Add(p1);
|
||||
lines.Add(p2);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Handles.DrawLines(lines.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e5ff128cfebee45ffb8266eb3e75522e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,43 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiBlueprintRenderModeTetherConstraints : ObiBlueprintRenderMode
|
||||
{
|
||||
public override string name
|
||||
{
|
||||
get { return "Tether constraints"; }
|
||||
}
|
||||
|
||||
public ObiBlueprintRenderModeTetherConstraints(ObiActorBlueprintEditor editor) : base(editor)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnSceneRepaint(SceneView sceneView)
|
||||
{
|
||||
using (new Handles.DrawingScope(Color.yellow, Matrix4x4.identity))
|
||||
{
|
||||
var constraints = editor.blueprint.GetConstraintsByType(Oni.ConstraintType.Tether) as ObiConstraints<ObiTetherConstraintsBatch>;
|
||||
if (constraints != null)
|
||||
{
|
||||
Vector3[] lines = new Vector3[constraints.GetActiveConstraintCount() * 2];
|
||||
int lineIndex = 0;
|
||||
|
||||
foreach (var batch in constraints.batches)
|
||||
{
|
||||
for (int i = 0; i < batch.activeConstraintCount; ++i)
|
||||
{
|
||||
lines[lineIndex++] = editor.blueprint.GetParticlePosition(batch.particleIndices[i * 2]);
|
||||
lines[lineIndex++] = editor.blueprint.GetParticlePosition(batch.particleIndices[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
Handles.DrawLines(lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63054cbedb75c4aa7906bf1c24552085
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5759f1c7beafc485489fb47abffaa269
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,110 +0,0 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
[CustomEditor(typeof(ObiColliderBase), true), CanEditMultipleObjects]
|
||||
public class ObiColliderEditor : Editor
|
||||
{
|
||||
|
||||
ObiColliderBase collider;
|
||||
SerializedProperty collisionFilter;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
collider = (ObiColliderBase)target;
|
||||
collisionFilter = serializedObject.FindProperty("filter");
|
||||
}
|
||||
|
||||
protected void NonReadableMeshWarning(Mesh mesh)
|
||||
{
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
Texture2D icon = EditorGUIUtility.Load("icons/console.erroricon.png") as Texture2D;
|
||||
EditorGUILayout.LabelField(new GUIContent("The input mesh is not readable. Read/Write must be enabled in the mesh import settings.", icon), EditorStyles.wordWrappedMiniLabel);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button("Fix now", GUILayout.MaxWidth(100), GUILayout.MinHeight(32)))
|
||||
{
|
||||
string assetPath = AssetDatabase.GetAssetPath(mesh);
|
||||
ModelImporter modelImporter = AssetImporter.GetAtPath(assetPath) as ModelImporter;
|
||||
if (modelImporter != null)
|
||||
{
|
||||
modelImporter.isReadable = true;
|
||||
}
|
||||
modelImporter.SaveAndReimport();
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
|
||||
foreach (ObiColliderBase t in targets)
|
||||
{
|
||||
ObiMeshShapeTracker meshTracker = t.Tracker as ObiMeshShapeTracker;
|
||||
if (meshTracker != null)
|
||||
{
|
||||
if (meshTracker.targetMesh != null && !meshTracker.targetMesh.isReadable)
|
||||
NonReadableMeshWarning(meshTracker.targetMesh);
|
||||
}
|
||||
}
|
||||
|
||||
var rect = EditorGUILayout.GetControlRect();
|
||||
var label = EditorGUI.BeginProperty(rect, new GUIContent("Collision category"), collisionFilter);
|
||||
rect = EditorGUI.PrefixLabel(rect, label);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newCategory = EditorGUI.Popup(rect, ObiUtils.GetCategoryFromFilter(collider.Filter), ObiUtils.categoryNames);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
foreach (ObiColliderBase t in targets)
|
||||
{
|
||||
Undo.RecordObject(t, "Set collision category");
|
||||
t.Filter = ObiUtils.MakeFilter(ObiUtils.GetMaskFromFilter(t.Filter), newCategory);
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(t);
|
||||
}
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
|
||||
rect = EditorGUILayout.GetControlRect();
|
||||
label = EditorGUI.BeginProperty(rect, new GUIContent("Collides with"), collisionFilter);
|
||||
rect = EditorGUI.PrefixLabel(rect, label);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newMask = EditorGUI.MaskField(rect, ObiUtils.GetMaskFromFilter(collider.Filter), ObiUtils.categoryNames);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
foreach (ObiColliderBase t in targets)
|
||||
{
|
||||
Undo.RecordObject(t, "Set collision mask");
|
||||
t.Filter = ObiUtils.MakeFilter(newMask, ObiUtils.GetCategoryFromFilter(t.Filter));
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(t);
|
||||
}
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
|
||||
DrawPropertiesExcluding(serializedObject, "m_Script", "CollisionMaterial", "filter", "Thickness", "Inverted");
|
||||
|
||||
foreach (ObiColliderBase t in targets)
|
||||
{
|
||||
if (!t.gameObject.isStatic)
|
||||
t.ForceUpdate();
|
||||
}
|
||||
|
||||
// Apply changes to the serializedProperty
|
||||
if (GUI.changed)
|
||||
{
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user