去掉obi,使用自写绳索

This commit is contained in:
2026-02-23 20:51:03 +08:00
parent cb636f862d
commit 91e2309eeb
2011 changed files with 2593 additions and 190578 deletions

View File

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

View File

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

View File

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

View File

@@ -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]; }
}
}

View File

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

View File

@@ -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);
}
}
}
}

View File

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

View File

@@ -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();
}
}
}

View File

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

View File

@@ -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();
}
}
}

View File

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

View File

@@ -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();
}
}
}

View File

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

View File

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

View File

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

View File

@@ -1,9 +0,0 @@
namespace Obi
{
public interface IObiBrushMode
{
string name{get;}
bool needsInputValue{ get; }
void ApplyStamps(ObiBrushBase brush, bool modified);
}
}

View File

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

View File

@@ -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));
}
}
}
}
}

View File

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

View File

@@ -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));
}
}
}
}
}

View File

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

View File

@@ -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));
}
}
}
}
}

View File

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

View File

@@ -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));
}
}
}
}
}
}

View File

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

View File

@@ -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));
}
}
}
}
}

View File

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

View File

@@ -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));
}
}
}
}
}

View File

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

View File

@@ -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());
}
}
}
}
}

View File

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

View File

@@ -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);
}
}
}
}
}

View File

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

View File

@@ -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);
}
}
}
}

View File

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

View File

@@ -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;
}
}
}
}

View File

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

View File

@@ -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;
}
}

View File

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

View File

@@ -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);
}
}
}
}
}
}
}

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

@@ -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"));
}
}
}

View File

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

View File

@@ -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;
}

View File

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

View File

@@ -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; }
}
}

View File

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

View File

@@ -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);
}
}
}
}

View File

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

View File

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

View File

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

View File

@@ -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;
}
}
}

View File

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

View File

@@ -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];
}
}
}

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

@@ -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];
}
}
}

View File

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

View File

@@ -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];
}
}
}

View File

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

View File

@@ -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);
}
}

View File

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

View File

@@ -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);
}
}

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

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

View File

@@ -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() { }
}
}

View File

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

View File

@@ -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);
}
}
}
}
}
}

View File

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

View File

@@ -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);
}
}
}
}
}

View File

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

View File

@@ -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);
}
}
}
}
}

View File

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

View File

@@ -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();
}
}
}

View File

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

View File

@@ -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();
}
}
}

View File

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

View File

@@ -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());
}
}
}
}
}

View File

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

View File

@@ -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);
}
}
}
}
}

View File

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

View File

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

View File

@@ -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