升级obi
@@ -85,7 +85,7 @@ namespace Obi
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
meshBasedEditor.particleCulling = (ObiMeshBasedActorBlueprintEditor.ParticleCulling)EditorGUILayout.EnumPopup("Culling", meshBasedEditor.particleCulling);
|
||||
if (editor.selectedCount == 0)
|
||||
if (ObiActorBlueprintEditor.selectedCount == 0)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Select at least one particle to use selection mask.", MessageType.Info);
|
||||
selectionMask = false;
|
||||
@@ -111,13 +111,16 @@ namespace Obi
|
||||
|
||||
public override bool Editable(int index)
|
||||
{
|
||||
return editor.visible[index] && (!selectionMask || editor.selectionStatus[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);
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ namespace Obi
|
||||
|
||||
public override string GetHelpString()
|
||||
{
|
||||
if (editor.selectedCount > 0)
|
||||
return "" + editor.selectedCount + " selected particles.";
|
||||
if (ObiActorBlueprintEditor.selectedCount > 0)
|
||||
return "" + ObiActorBlueprintEditor.selectedCount + " selected particles.";
|
||||
else
|
||||
return "No particles selected. Click and drag over particles to select them.";
|
||||
}
|
||||
@@ -65,12 +65,12 @@ namespace Obi
|
||||
{
|
||||
if ((Event.current.modifiers & EventModifiers.Shift) == 0)
|
||||
{
|
||||
for (int p = 0; p < editor.selectionStatus.Length; p++)
|
||||
editor.selectionStatus[p] = false;
|
||||
for (int p = 0; p < ObiActorBlueprintEditor.selectionStatus.Length; p++)
|
||||
ObiActorBlueprintEditor.selectionStatus[p] = false;
|
||||
}
|
||||
|
||||
foreach (int p in group.particleIndices)
|
||||
editor.selectionStatus[p] = true;
|
||||
ObiActorBlueprintEditor.selectionStatus[p] = true;
|
||||
|
||||
UpdateSelection();
|
||||
}
|
||||
@@ -78,9 +78,9 @@ namespace Obi
|
||||
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 < editor.selectionStatus.Length; p++)
|
||||
for (int p = 0; p < ObiActorBlueprintEditor.selectionStatus.Length; p++)
|
||||
{
|
||||
if (editor.selectionStatus[p])
|
||||
if (ObiActorBlueprintEditor.selectionStatus[p])
|
||||
group.particleIndices.Add(p);
|
||||
}
|
||||
}
|
||||
@@ -95,9 +95,9 @@ namespace Obi
|
||||
|
||||
var group = editor.blueprint.AppendNewParticleGroup("new group");
|
||||
|
||||
for (int i = 0; i < editor.selectionStatus.Length; i++)
|
||||
for (int i = 0; i < ObiActorBlueprintEditor.selectionStatus.Length; i++)
|
||||
{
|
||||
if (editor.selectionStatus[i])
|
||||
if (ObiActorBlueprintEditor.selectionStatus[i])
|
||||
group.particleIndices.Add(i);
|
||||
}
|
||||
|
||||
@@ -116,33 +116,33 @@ namespace Obi
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button(new GUIContent(Resources.Load<Texture2D>("InvertButton"), "Invert selection"), GUILayout.MaxHeight(24), GUILayout.MaxWidth(48)))
|
||||
{
|
||||
for (int i = 0; i < editor.selectionStatus.Length; i++)
|
||||
for (int i = 0; i < ObiActorBlueprintEditor.selectionStatus.Length; i++)
|
||||
{
|
||||
if (editor.blueprint.IsParticleActive(i))
|
||||
editor.selectionStatus[i] = !editor.selectionStatus[i];
|
||||
ObiActorBlueprintEditor.selectionStatus[i] = !ObiActorBlueprintEditor.selectionStatus[i];
|
||||
}
|
||||
UpdateSelection();
|
||||
}
|
||||
|
||||
GUI.enabled = editor.selectedCount > 0;
|
||||
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 < editor.selectionStatus.Length; i++)
|
||||
editor.selectionStatus[i] = false;
|
||||
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 editor.selectionStatus);
|
||||
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 editor.selectionStatus, false);
|
||||
editor.blueprint.RemoveSelectedParticles(ref ObiActorBlueprintEditor.selectionStatus, false);
|
||||
editor.Refresh();
|
||||
}
|
||||
GUI.enabled = true;
|
||||
@@ -175,12 +175,12 @@ namespace Obi
|
||||
maxSelectionValue = EditorGUILayout.FloatField("Maximum " + property.name, maxSelectionValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
for (int i = 0; i < editor.selectionStatus.Length; i++)
|
||||
for (int i = 0; i < ObiActorBlueprintEditor.selectionStatus.Length; i++)
|
||||
{
|
||||
if (editor.blueprint.IsParticleActive(i))
|
||||
{
|
||||
var value = property.Get(i);
|
||||
editor.selectionStatus[i] = value >= minSelectionValue && value <= maxSelectionValue;
|
||||
ObiActorBlueprintEditor.selectionStatus[i] = value >= minSelectionValue && value <= maxSelectionValue;
|
||||
}
|
||||
}
|
||||
UpdateSelection();
|
||||
@@ -244,9 +244,9 @@ namespace Obi
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(editor.blueprint, "Set particle property");
|
||||
for (int i = 0; i < editor.selectionStatus.Length; i++)
|
||||
for (int i = 0; i < ObiActorBlueprintEditor.selectionStatus.Length; i++)
|
||||
{
|
||||
if (!editor.selectionStatus[i]) continue;
|
||||
if (!ObiActorBlueprintEditor.selectionStatus[i]) continue;
|
||||
editor.currentProperty.SetDefaultToIndex(i);
|
||||
}
|
||||
editor.Refresh();
|
||||
@@ -287,7 +287,7 @@ namespace Obi
|
||||
EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins);
|
||||
|
||||
editor.RenderModeSelector();
|
||||
editor.dotRadiusScale = EditorGUILayout.Slider(new GUIContent("Particle dot size"), editor.dotRadiusScale, 0, 5);
|
||||
ObiActorBlueprintEditor.dotRadiusScale = EditorGUILayout.Slider(new GUIContent("Particle dot size"), ObiActorBlueprintEditor.dotRadiusScale, 0, 5);
|
||||
editor.currentProperty.VisualizationOptions();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
@@ -301,31 +301,31 @@ namespace Obi
|
||||
|
||||
protected void UpdateSelection()
|
||||
{
|
||||
editor.selectedCount = 0;
|
||||
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 < editor.selectionStatus.Length; i++)
|
||||
for (int i = 0; i < ObiActorBlueprintEditor.selectionStatus.Length; i++)
|
||||
{
|
||||
if (editor.blueprint.IsParticleActive(i) && editor.selectionStatus[i])
|
||||
if (editor.blueprint.IsParticleActive(i) && ObiActorBlueprintEditor.selectionStatus[i])
|
||||
{
|
||||
editor.selectedCount++;
|
||||
ObiActorBlueprintEditor.selectedCount++;
|
||||
|
||||
if (editor.activeParticle >= 0)
|
||||
if (ObiActorBlueprintEditor.activeParticle >= 0)
|
||||
{
|
||||
if (!editor.currentProperty.Equals(editor.activeParticle, i))
|
||||
if (!editor.currentProperty.Equals(ObiActorBlueprintEditor.activeParticle, i))
|
||||
mixedPropertyValue = true;
|
||||
}
|
||||
else
|
||||
editor.activeParticle = i;
|
||||
ObiActorBlueprintEditor.activeParticle = i;
|
||||
}
|
||||
else if (editor.activeParticle == i)
|
||||
editor.activeParticle = -1;
|
||||
else if (ObiActorBlueprintEditor.activeParticle == i)
|
||||
ObiActorBlueprintEditor.activeParticle = -1;
|
||||
}
|
||||
|
||||
// Set initial property value:
|
||||
if (!mixedPropertyValue && editor.activeParticle >= 0)
|
||||
editor.currentProperty.GetDefaultFromIndex(editor.activeParticle);
|
||||
if (!mixedPropertyValue && ObiActorBlueprintEditor.activeParticle >= 0)
|
||||
editor.currentProperty.GetDefaultFromIndex(ObiActorBlueprintEditor.activeParticle);
|
||||
|
||||
editor.Repaint();
|
||||
SceneView.RepaintAll();
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Obi
|
||||
|
||||
private void FloatFromTexture(int i, Color color)
|
||||
{
|
||||
if (!selectionMask || editor.selectionStatus[i])
|
||||
if (!selectionMask || ObiActorBlueprintEditor.selectionStatus[i])
|
||||
{
|
||||
float value = minPropertyValue + color[(int)textureChannel] * (maxPropertyValue - minPropertyValue);
|
||||
floatProperty.Set(i, value);
|
||||
@@ -61,7 +61,7 @@ namespace Obi
|
||||
|
||||
private void ColorFromTexture(int i, Color color)
|
||||
{
|
||||
if (!selectionMask || editor.selectionStatus[i])
|
||||
if (!selectionMask || ObiActorBlueprintEditor.selectionStatus[i])
|
||||
colorProperty.Set(i, color);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,20 +57,20 @@ namespace Obi
|
||||
if (GUILayout.Button("Generate tethers",GUILayout.MinHeight(32)))
|
||||
{
|
||||
// Select all particles in the tethered groups:
|
||||
for (int i = 0; i < editor.selectionStatus.Length; ++i)
|
||||
for (int i = 0; i < ObiActorBlueprintEditor.selectionStatus.Length; ++i)
|
||||
{
|
||||
editor.selectionStatus[i] = false;
|
||||
ObiActorBlueprintEditor.selectionStatus[i] = false;
|
||||
for (int j = 0; j < tetheredGroups.Length; ++j)
|
||||
{
|
||||
if (tetheredGroups[j] && editor.blueprint.groups[j].ContainsParticle(i))
|
||||
{
|
||||
editor.selectionStatus[i] = true;
|
||||
ObiActorBlueprintEditor.selectionStatus[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
editor.blueprint.GenerateTethers(editor.selectionStatus);
|
||||
editor.blueprint.GenerateTethers(ObiActorBlueprintEditor.selectionStatus);
|
||||
editor.Refresh();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Obi
|
||||
protected override float WeightFromDistance(float distance)
|
||||
{
|
||||
// anything outside the brush should have zero weight:
|
||||
if (distance > radius)
|
||||
if (distance * EditorGUIUtility.pixelsPerPoint > radius)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -14,29 +14,27 @@ namespace Obi
|
||||
[CustomEditor(typeof(ObiActorBlueprint), true)]
|
||||
public class ObiActorBlueprintEditor : Editor, IObiSelectableParticleProvider
|
||||
{
|
||||
protected IEnumerator routine;
|
||||
|
||||
public List<ObiBlueprintEditorTool> tools = new List<ObiBlueprintEditorTool>();
|
||||
public int currentToolIndex = 0;
|
||||
|
||||
protected List<ObiBlueprintPropertyBase> properties = new List<ObiBlueprintPropertyBase>();
|
||||
public List<ObiBlueprintPropertyBase> properties = new List<ObiBlueprintPropertyBase>();
|
||||
public int currentPropertyIndex = 0;
|
||||
|
||||
protected List<ObiBlueprintRenderMode> renderModes = new List<ObiBlueprintRenderMode>();
|
||||
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 List<SceneStateCache> m_SceneStates;
|
||||
protected SceneSetup[] oldSetup;
|
||||
protected UnityEngine.Object oldSelection;
|
||||
|
||||
//Additional status info for all particles:
|
||||
public float dotRadiusScale = 1;
|
||||
public int selectedCount = 0;
|
||||
public int activeParticle = -1;
|
||||
public bool[] selectionStatus = new bool[0];
|
||||
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];
|
||||
@@ -78,6 +76,10 @@ namespace Obi
|
||||
|
||||
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));
|
||||
@@ -88,11 +90,12 @@ namespace Obi
|
||||
|
||||
#if (UNITY_2019_1_OR_NEWER)
|
||||
renderCallback = new System.Action<ScriptableRenderContext, Camera>((cntxt, cam) => { DrawWithCamera(cam); });
|
||||
RenderPipelineManager.beginCameraRendering -= renderCallback;
|
||||
RenderPipelineManager.beginCameraRendering += renderCallback;
|
||||
#endif
|
||||
Camera.onPreCull -= DrawWithCamera;
|
||||
Camera.onPreCull += DrawWithCamera;
|
||||
SceneView.duringSceneGui += OnSceneGUI;
|
||||
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
public virtual void OnDisable()
|
||||
@@ -103,8 +106,8 @@ namespace Obi
|
||||
RenderPipelineManager.beginCameraRendering -= renderCallback;
|
||||
#endif
|
||||
Camera.onPreCull -= DrawWithCamera;
|
||||
|
||||
ObiParticleEditorDrawing.DestroyParticlesMesh();
|
||||
SceneView.duringSceneGui -= OnSceneGUI;
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
|
||||
foreach (var tool in tools)
|
||||
{
|
||||
@@ -116,51 +119,77 @@ namespace Obi
|
||||
{
|
||||
renderMode.OnDestroy();
|
||||
}
|
||||
|
||||
properties.Clear();
|
||||
renderModes.Clear();
|
||||
}
|
||||
|
||||
protected void Generate()
|
||||
void OnPlayModeStateChanged(PlayModeStateChange playmodeState)
|
||||
{
|
||||
if (blueprint.empty)
|
||||
if (playmodeState == PlayModeStateChange.ExitingEditMode)
|
||||
{
|
||||
if (StageUtility.GetCurrentStage() is ObiActorBlueprintEditorStage)
|
||||
StageUtility.GoToMainStage();
|
||||
}
|
||||
}
|
||||
|
||||
protected bool Generate()
|
||||
{
|
||||
if (!blueprint.edited)
|
||||
{
|
||||
EditorUtility.SetDirty(target);
|
||||
CoroutineJob job = new CoroutineJob();
|
||||
routine = job.Start(blueprint.Generate());
|
||||
EditorCoroutine.ShowCoroutineProgressBar("Generating blueprint...", ref routine);
|
||||
IEnumerator routine = job.Start(blueprint.Generate());
|
||||
EditorCoroutine.ShowCoroutineProgressBar("Generating blueprint...", routine);
|
||||
Refresh();
|
||||
EditorGUIUtility.ExitGUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Blueprint generation", "This blueprint already contains data. Are you sure you want to re-generate this blueprint from scratch?", "Ok", "Cancel"))
|
||||
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();
|
||||
routine = job.Start(blueprint.Generate());
|
||||
EditorCoroutine.ShowCoroutineProgressBar("Generating blueprint...", ref routine);
|
||||
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 = ValidateBlueprint();
|
||||
if (GUILayout.Button("Generate", GUI.skin.FindStyle("LargeButton"), GUILayout.Height(32)))
|
||||
Generate();
|
||||
|
||||
GUI.enabled = blueprintValid;
|
||||
DrawGenerationControls();
|
||||
|
||||
GUI.enabled = (blueprint != null && !blueprint.empty && !Application.isPlaying);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
@@ -180,7 +209,10 @@ namespace Obi
|
||||
|
||||
if (GUI.changed)
|
||||
{
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
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.
|
||||
@@ -206,51 +238,17 @@ namespace Obi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
protected class SceneStateCache
|
||||
{
|
||||
public SceneView view;
|
||||
public SceneView.SceneViewState state;
|
||||
}
|
||||
|
||||
void EnterBlueprintEditMode()
|
||||
{
|
||||
if (!isEditing)
|
||||
{
|
||||
#if (UNITY_2019_1_OR_NEWER)
|
||||
SceneView.duringSceneGui -= this.OnSceneGUI;
|
||||
SceneView.duringSceneGui += this.OnSceneGUI;
|
||||
#else
|
||||
SceneView.onSceneGUIDelegate -= this.OnSceneGUI;
|
||||
SceneView.onSceneGUIDelegate += this.OnSceneGUI;
|
||||
#endif
|
||||
ActiveEditorTracker.sharedTracker.isLocked = true;
|
||||
|
||||
oldSelection = Selection.activeObject;
|
||||
if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
|
||||
{
|
||||
ActiveEditorTracker.sharedTracker.isLocked = true;
|
||||
string assetPath = AssetDatabase.GetAssetPath(blueprint);
|
||||
ObiActorBlueprintEditorStage stage = ObiActorBlueprintEditorStage.CreateStage(assetPath, this);
|
||||
StageUtility.GoToStage(stage, true);
|
||||
|
||||
oldSetup = EditorSceneManager.GetSceneManagerSetup();
|
||||
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
||||
|
||||
// Set properties for all scene views:
|
||||
m_SceneStates = new List<SceneStateCache>();
|
||||
foreach (SceneView s in SceneView.sceneViews)
|
||||
{
|
||||
m_SceneStates.Add(new SceneStateCache { state = new SceneView.SceneViewState(s.sceneViewState), view = s });
|
||||
s.sceneViewState.showFlares = false;
|
||||
s.sceneViewState.alwaysRefresh = false;
|
||||
s.sceneViewState.showFog = false;
|
||||
s.sceneViewState.showSkybox = false;
|
||||
s.sceneViewState.showImageEffects = false;
|
||||
s.sceneViewState.showParticleSystems = false;
|
||||
s.Frame(blueprint.bounds);
|
||||
}
|
||||
|
||||
isEditing = true;
|
||||
Repaint();
|
||||
}
|
||||
isEditing = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,52 +256,18 @@ namespace Obi
|
||||
{
|
||||
if (isEditing)
|
||||
{
|
||||
|
||||
isEditing = false;
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
// Reset all scene views:
|
||||
foreach (var state in m_SceneStates)
|
||||
{
|
||||
if (state.view == null)
|
||||
continue;
|
||||
|
||||
state.view.sceneViewState.showFog = state.state.showFog;
|
||||
state.view.sceneViewState.showFlares = state.state.showFlares;
|
||||
state.view.sceneViewState.alwaysRefresh = state.state.alwaysRefresh;
|
||||
state.view.sceneViewState.showSkybox = state.state.showSkybox;
|
||||
state.view.sceneViewState.showImageEffects = state.state.showImageEffects;
|
||||
state.view.sceneViewState.showParticleSystems = state.state.showParticleSystems;
|
||||
}
|
||||
|
||||
ActiveEditorTracker.sharedTracker.isLocked = false;
|
||||
|
||||
if (SceneManager.GetActiveScene().path.Length <= 0)
|
||||
{
|
||||
if (oldSetup != null && oldSetup.Length > 0)
|
||||
{
|
||||
EditorSceneManager.RestoreSceneManagerSetup(oldSetup);
|
||||
oldSetup = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects);
|
||||
}
|
||||
}
|
||||
|
||||
Selection.activeObject = oldSelection;
|
||||
|
||||
#if (UNITY_2019_1_OR_NEWER)
|
||||
SceneView.duringSceneGui -= this.OnSceneGUI;
|
||||
#else
|
||||
SceneView.onSceneGUIDelegate -= this.OnSceneGUI;
|
||||
#endif
|
||||
|
||||
Repaint();
|
||||
StageUtility.GoToMainStage();
|
||||
}
|
||||
}
|
||||
|
||||
public void CleanupEditor()
|
||||
{
|
||||
ActiveEditorTracker.sharedTracker.isLocked = false;
|
||||
ObiParticleEditorDrawing.DestroyParticlesMesh();
|
||||
}
|
||||
|
||||
public virtual void OnSceneGUI(SceneView sceneView)
|
||||
{
|
||||
|
||||
@@ -318,7 +282,7 @@ namespace Obi
|
||||
{
|
||||
|
||||
// Update camera facing status and world space positions array:
|
||||
UpdateParticleVisibility();
|
||||
UpdateParticleVisibility(sceneView.camera);
|
||||
|
||||
// Generate sorted indices for back-to-front rendering:
|
||||
for (int i = 0; i < sortedIndices.Length; i++)
|
||||
@@ -339,7 +303,7 @@ namespace Obi
|
||||
UpdateTintColor();
|
||||
|
||||
// Draw particle handles:
|
||||
ObiParticleEditorDrawing.DrawParticles(sceneView.camera, blueprint, activeParticle, visible, tint, sortedIndices, dotRadiusScale);
|
||||
ObiParticleEditorDrawing.DrawParticles(sceneView.camera, blueprint, visible, tint, sortedIndices, dotRadiusScale);
|
||||
|
||||
}
|
||||
|
||||
@@ -370,6 +334,7 @@ namespace Obi
|
||||
{
|
||||
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);
|
||||
@@ -413,7 +378,9 @@ namespace Obi
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
currentProperty.RecalculateMinMax();
|
||||
// currentProperty might be null after reloading editor during
|
||||
// asset saving.
|
||||
currentProperty?.RecalculateMinMax();
|
||||
|
||||
// refresh render modes:
|
||||
for (int i = 0; i < renderModes.Count; ++i)
|
||||
@@ -425,7 +392,7 @@ namespace Obi
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
|
||||
public virtual void UpdateParticleVisibility()
|
||||
public virtual void UpdateParticleVisibility(Camera cam)
|
||||
{
|
||||
|
||||
for (int i = 0; i < blueprint.positions.Length; i++)
|
||||
@@ -436,7 +403,7 @@ namespace Obi
|
||||
|
||||
if (Camera.current != null)
|
||||
{
|
||||
Vector3 camToParticle = Camera.current.transform.position - blueprint.positions[i];
|
||||
Vector3 camToParticle = cam.transform.position - blueprint.positions[i];
|
||||
sqrDistanceToCamera[i] = camToParticle.sqrMagnitude;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
class ObiActorBlueprintEditorStage : PreviewSceneStage
|
||||
{
|
||||
ObiActorBlueprintEditor m_BlueprintEditor;
|
||||
|
||||
string m_AssetPath;
|
||||
public override string assetPath { get { return m_AssetPath; } }
|
||||
|
||||
internal static ObiActorBlueprintEditorStage CreateStage(string assetPath, ObiActorBlueprintEditor avatarEditor)
|
||||
{
|
||||
ObiActorBlueprintEditorStage stage = CreateInstance<ObiActorBlueprintEditorStage>();
|
||||
stage.Init(assetPath, avatarEditor);
|
||||
return stage;
|
||||
}
|
||||
|
||||
private void Init(string modelAssetPath, ObiActorBlueprintEditor avatarEditor)
|
||||
{
|
||||
m_AssetPath = modelAssetPath;
|
||||
m_BlueprintEditor = avatarEditor;
|
||||
}
|
||||
|
||||
protected override bool OnOpenStage()
|
||||
{
|
||||
base.OnOpenStage();
|
||||
|
||||
if (!File.Exists(assetPath))
|
||||
{
|
||||
Debug.LogError("ActivateStage called on BlueprintStage with an invalid path: Blueprint file not found " + assetPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnCloseStage()
|
||||
{
|
||||
m_BlueprintEditor.CleanupEditor();
|
||||
|
||||
base.OnCloseStage();
|
||||
}
|
||||
|
||||
protected override void OnFirstTimeOpenStageInSceneView(SceneView sceneView)
|
||||
{
|
||||
// Frame in scene view
|
||||
sceneView.Frame(m_BlueprintEditor.blueprint.bounds);
|
||||
|
||||
// Setup Scene view state
|
||||
sceneView.sceneViewState.showFlares = false;
|
||||
sceneView.sceneViewState.alwaysRefresh = false;
|
||||
sceneView.sceneViewState.showFog = false;
|
||||
sceneView.sceneViewState.showSkybox = false;
|
||||
sceneView.sceneViewState.showImageEffects = false;
|
||||
sceneView.sceneViewState.showParticleSystems = false;
|
||||
sceneView.sceneLighting = true;
|
||||
}
|
||||
|
||||
protected override GUIContent CreateHeaderContent()
|
||||
{
|
||||
return new GUIContent(
|
||||
"Blueprint Editor",
|
||||
Resources.Load<Texture2D>("Icons/ObiActorBlueprint Icon"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7971633b9741349f3add282a07b0d69b
|
||||
guid: 4c8d9d8042d49436c89c515b001088ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -18,6 +18,7 @@ namespace Obi
|
||||
}
|
||||
|
||||
protected Mesh visualizationMesh;
|
||||
protected Mesh visualizationWireMesh;
|
||||
public ParticleCulling particleCulling = ParticleCulling.Back;
|
||||
|
||||
protected Material gradientMaterial;
|
||||
@@ -75,46 +76,50 @@ namespace Obi
|
||||
|
||||
public abstract int VertexToParticle(int vertexIndex);
|
||||
|
||||
public override void UpdateParticleVisibility()
|
||||
public override void UpdateParticleVisibility(Camera cam)
|
||||
{
|
||||
if (sourceMesh != null && Camera.current != null)
|
||||
if (cam != null)
|
||||
{
|
||||
Vector3[] meshNormals = sourceMesh.normals;
|
||||
for (int i = 0; i < sourceMesh.vertexCount; i++)
|
||||
for (int i = 0; i < blueprint.positions.Length; i++)
|
||||
{
|
||||
int particle = VertexToParticle(i);
|
||||
|
||||
if (particle >= 0 && particle < blueprint.positions.Length)
|
||||
if (blueprint.IsParticleActive(i))
|
||||
{
|
||||
Vector3 camToParticle = Camera.current.transform.position - blueprint.positions[particle];
|
||||
Vector3 camToParticle = cam.transform.position - blueprint.positions[i];
|
||||
sqrDistanceToCamera[i] = camToParticle.sqrMagnitude;
|
||||
|
||||
sqrDistanceToCamera[particle] = camToParticle.sqrMagnitude;
|
||||
Vector3 normal;
|
||||
|
||||
switch (particleCulling)
|
||||
{
|
||||
case ParticleCulling.Off:
|
||||
visible[particle] = true;
|
||||
visible[i] = true;
|
||||
break;
|
||||
case ParticleCulling.Back:
|
||||
visible[particle] = Vector3.Dot(meshNormals[i], camToParticle) > 0;
|
||||
normal = blueprint.restOrientations[i] * Vector3.forward;
|
||||
visible[i] = Vector3.Dot(normal, camToParticle) > 0;
|
||||
break;
|
||||
case ParticleCulling.Front:
|
||||
visible[particle] = Vector3.Dot(meshNormals[i], camToParticle) <= 0;
|
||||
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))
|
||||
{
|
||||
@@ -157,15 +162,16 @@ namespace Obi
|
||||
colors[i] = Color.gray;
|
||||
}
|
||||
|
||||
visualizationMesh.colors = colors;
|
||||
visualizationWireMesh.colors = colors;
|
||||
GL.wireframe = true;
|
||||
Graphics.DrawMeshNow(visualizationMesh, matrix);
|
||||
Graphics.DrawMeshNow(visualizationWireMesh, matrix);
|
||||
GL.wireframe = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GameObject.DestroyImmediate(visualizationMesh);
|
||||
GameObject.DestroyImmediate(visualizationWireMesh);
|
||||
}
|
||||
|
||||
|
||||
@@ -223,7 +229,8 @@ namespace Obi
|
||||
RenderTexture.active = tempRT;
|
||||
|
||||
GL.PushMatrix();
|
||||
GL.LoadProjectionMatrix(Matrix4x4.Ortho(0, 1, 0, 1, -1, 1));
|
||||
|
||||
var proj = Matrix4x4.Ortho(0, 1, 0, 1, -1, 1);
|
||||
if (Camera.current != null) proj = proj * Camera.current.worldToCameraMatrix.inverse;
|
||||
GL.LoadProjectionMatrix(proj);
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Obi
|
||||
GameObject.DestroyImmediate(particlesMesh);
|
||||
}
|
||||
|
||||
public static void DrawParticles(Camera cam, ObiActorBlueprint blueprint, int activeParticle, bool[] visible, Color[] baseColor, int[] sortedIndices, float radiusScale = 1)
|
||||
public static void DrawParticles(Camera cam, ObiActorBlueprint blueprint, bool[] visible, Color[] baseColor, int[] sortedIndices, float radiusScale = 1)
|
||||
{
|
||||
CreateParticlesMesh();
|
||||
CreateParticleMaterials();
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace Obi
|
||||
public override void Set(int index, Color value)
|
||||
{
|
||||
editor.blueprint.colors[index] = value;
|
||||
editor.blueprint.edited = true;
|
||||
}
|
||||
public override bool Masked(int index)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace Obi
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace Obi
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace Obi
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -24,10 +24,10 @@ namespace Obi
|
||||
{
|
||||
ObiPaintBrushEditorTool paintTool = (ObiPaintBrushEditorTool)meshBasedEditor.currentTool;
|
||||
|
||||
float[] weights = new float[editor.selectionStatus.Length];
|
||||
float[] weights = new float[ObiActorBlueprintEditor.selectionStatus.Length];
|
||||
for (int i = 0; i < weights.Length; i++)
|
||||
{
|
||||
if (paintTool.selectionMask && !editor.selectionStatus[i])
|
||||
if (paintTool.selectionMask && !ObiActorBlueprintEditor.selectionStatus[i])
|
||||
weights[i] = 0;
|
||||
else
|
||||
weights[i] = 1;
|
||||
|
||||
@@ -13,11 +13,13 @@ namespace Obi
|
||||
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()
|
||||
@@ -43,8 +45,10 @@ namespace Obi
|
||||
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);
|
||||
Graphics.DrawMesh(mesh, Matrix4x4.identity, material, 0, camera, 0, mpb);
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi{
|
||||
|
||||
[CustomEditor(typeof(ObiColliderBase), true), CanEditMultipleObjects]
|
||||
public class ObiColliderEditor : Editor
|
||||
{
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
[CustomEditor(typeof(ObiColliderBase), true), CanEditMultipleObjects]
|
||||
public class ObiColliderEditor : Editor
|
||||
{
|
||||
|
||||
ObiColliderBase collider;
|
||||
SerializedProperty collisionFilter;
|
||||
@@ -16,11 +17,42 @@ namespace Obi{
|
||||
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);
|
||||
@@ -56,8 +88,13 @@ namespace Obi{
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
|
||||
DrawPropertiesExcluding(serializedObject, "m_Script", "CollisionMaterial", "filter", "Thickness", "Inverted");
|
||||
|
||||
DrawPropertiesExcluding(serializedObject, "m_Script", "CollisionMaterial", "filter", "Thickness");
|
||||
foreach (ObiColliderBase t in targets)
|
||||
{
|
||||
if (!t.gameObject.isStatic)
|
||||
t.ForceUpdate();
|
||||
}
|
||||
|
||||
// Apply changes to the serializedProperty
|
||||
if (GUI.changed)
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Obi{
|
||||
EditorUtility.SetDirty(target);
|
||||
CoroutineJob job = new CoroutineJob();
|
||||
routine = job.Start( distanceField.Generate());
|
||||
EditorCoroutine.ShowCoroutineProgressBar("Generating distance field",ref routine);
|
||||
EditorCoroutine.ShowCoroutineProgressBar("Generating distance field", routine);
|
||||
UpdatePreview();
|
||||
EditorGUIUtility.ExitGUI();
|
||||
}
|
||||
|
||||
30
Assets/Obi/Editor/Common/Collisions/ObiForceZoneEditor.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
/**
|
||||
* Custom inspector for ObiForceZone component.
|
||||
*/
|
||||
|
||||
[CustomEditor(typeof(ObiForceZone)), CanEditMultipleObjects]
|
||||
public class ObiForceZoneEditor : Editor
|
||||
{
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
|
||||
DrawPropertiesExcluding(serializedObject, "m_Script");
|
||||
|
||||
// Apply changes to the serializedProperty
|
||||
if (GUI.changed)
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e97d151316d5f4d16ac5ae6e68acccb6
|
||||
guid: 724435a7a84154b27bb0c8ea49b611df
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -24,10 +24,20 @@ namespace Obi
|
||||
GUI.Box(position,"",ObiEditorUtils.GetToggleablePropertyGroupStyle());
|
||||
GUI.enabled = true;
|
||||
|
||||
// Draw main constraint toggle:
|
||||
enabled.boolValue = EditorGUI.ToggleLeft(contRect, label.text, enabled.boolValue, EditorStyles.boldLabel);
|
||||
// Draw main constraint toggle:
|
||||
EditorGUI.BeginProperty(position, label, enabled);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newEnabled = EditorGUI.ToggleLeft(contRect, label.text, enabled.boolValue, EditorStyles.boldLabel);
|
||||
// Only assign the value back if it was actually changed by the user.
|
||||
// Otherwise a single value will be assigned to all objects when multi-object editing,
|
||||
// even when the user didn't touch the control.
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
enabled.boolValue = newEnabled;
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
|
||||
if (enabled.boolValue){
|
||||
if (enabled.boolValue){
|
||||
|
||||
Rect evalRect = new Rect(position.x+padding, position.y+propHeight+padding, position.width-padding*2, propHeight);
|
||||
Rect iterRect = new Rect(position.x+padding, position.y+propHeight*2+padding, position.width-padding*2, propHeight);
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
class ObiEditorSettings : ScriptableObject
|
||||
{
|
||||
public const string m_ObiEditorSettingsPath = "Assets/ObiEditorSettings.asset";
|
||||
|
||||
[SerializeField] private Color m_ParticleBrush;
|
||||
[SerializeField] private Color m_BrushWireframe;
|
||||
[SerializeField] private Color m_Particle;
|
||||
[SerializeField] private Color m_SelectedParticle;
|
||||
[SerializeField] private Color m_ActiveParticle;
|
||||
[SerializeField] private Gradient m_PropertyGradient;
|
||||
|
||||
public Color brushColor
|
||||
{
|
||||
get { return m_ParticleBrush; }
|
||||
}
|
||||
public Color brushWireframeColor
|
||||
{
|
||||
get { return m_BrushWireframe; }
|
||||
}
|
||||
public Color particleColor
|
||||
{
|
||||
get { return m_Particle; }
|
||||
}
|
||||
public Color selectedParticleColor
|
||||
{
|
||||
get { return m_SelectedParticle; }
|
||||
}
|
||||
public Color activeParticleColor
|
||||
{
|
||||
get { return m_ActiveParticle; }
|
||||
}
|
||||
public Gradient propertyGradient
|
||||
{
|
||||
get { return m_PropertyGradient; }
|
||||
}
|
||||
|
||||
internal static ObiEditorSettings GetOrCreateSettings()
|
||||
{
|
||||
var settings = AssetDatabase.LoadAssetAtPath<ObiEditorSettings>(m_ObiEditorSettingsPath);
|
||||
if (settings == null)
|
||||
{
|
||||
settings = ScriptableObject.CreateInstance<ObiEditorSettings>();
|
||||
settings.m_ParticleBrush = new Color32(243, 77, 43, 255);
|
||||
settings.m_BrushWireframe = new Color32(0, 0, 0, 128);
|
||||
settings.m_Particle = new Color32(240, 240, 240, 255);
|
||||
settings.m_SelectedParticle = new Color32(243, 77, 43, 255);
|
||||
settings.m_ActiveParticle = new Color32(243, 243, 43, 255);
|
||||
settings.m_PropertyGradient = new Gradient();
|
||||
|
||||
// Populate the color keys at the relative time 0 and 1 (0 and 100%)
|
||||
var colorKey = new GradientColorKey[2];
|
||||
colorKey[0].color = Color.grey * 0.7f;
|
||||
colorKey[0].time = 0.0f;
|
||||
colorKey[1].color = Color.white;
|
||||
colorKey[1].time = 1.0f;
|
||||
|
||||
// Populate the alpha keys at relative time 0 and 1 (0 and 100%)
|
||||
var alphaKey = new GradientAlphaKey[2];
|
||||
alphaKey[0].alpha = 1.0f;
|
||||
alphaKey[0].time = 0.0f;
|
||||
alphaKey[1].alpha = 1.0f;
|
||||
alphaKey[1].time = 1.0f;
|
||||
|
||||
settings.m_PropertyGradient.SetKeys(colorKey, alphaKey);
|
||||
|
||||
AssetDatabase.CreateAsset(settings, m_ObiEditorSettingsPath);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
internal static SerializedObject GetSerializedSettings()
|
||||
{
|
||||
return new SerializedObject(GetOrCreateSettings());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public class ObiOniInitialize
|
||||
{
|
||||
private static BuildTargetGroup[] supportedBuildTargetGroups =
|
||||
{
|
||||
BuildTargetGroup.Standalone,
|
||||
BuildTargetGroup.Android,
|
||||
BuildTargetGroup.iOS
|
||||
};
|
||||
|
||||
static ObiOniInitialize()
|
||||
{
|
||||
|
||||
foreach(var group in supportedBuildTargetGroups)
|
||||
{
|
||||
var defines = GetDefinesList(group);
|
||||
if (!defines.Contains("OBI_ONI_SUPPORTED"))
|
||||
{
|
||||
defines.Add("OBI_ONI_SUPPORTED");
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(group, string.Join(";", defines.ToArray()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<string> GetDefinesList(BuildTargetGroup group)
|
||||
{
|
||||
return new List<string>(PlayerSettings.GetScriptingDefineSymbolsForGroup(group).Split(';'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,9 @@ namespace Obi
|
||||
public static GUIContent brushWireframe = new GUIContent("Brush wireframe");
|
||||
public static GUIContent particle = new GUIContent("Particle");
|
||||
public static GUIContent selectedParticle = new GUIContent("Selected particle");
|
||||
public static GUIContent activeParticle = new GUIContent("Active particle");
|
||||
public static GUIContent propertyGradient = new GUIContent("Property gradient");
|
||||
public static GUIContent particlePicking = new GUIContent("Particle GO picking");
|
||||
}
|
||||
|
||||
const string m_ObiEditorSettingsPath = "Assets/ObiEditorSettings.asset";
|
||||
@@ -52,7 +54,11 @@ namespace Obi
|
||||
EditorGUILayout.PropertyField(m_ObiSettings.FindProperty("m_BrushWireframe"),Styles.brushWireframe);
|
||||
EditorGUILayout.PropertyField(m_ObiSettings.FindProperty("m_Particle"),Styles.particle);
|
||||
EditorGUILayout.PropertyField(m_ObiSettings.FindProperty("m_SelectedParticle"),Styles.selectedParticle);
|
||||
EditorGUILayout.PropertyField(m_ObiSettings.FindProperty("m_ActiveParticle"), Styles.activeParticle);
|
||||
EditorGUILayout.PropertyField(m_ObiSettings.FindProperty("m_PropertyGradient"), Styles.propertyGradient);
|
||||
|
||||
EditorGUILayout.LabelField("Scene view", EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(m_ObiSettings.FindProperty("m_ParticlePicking"), Styles.particlePicking);
|
||||
}
|
||||
|
||||
// Register the SettingsProvider
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEditorInternal;
|
||||
using System;
|
||||
using System.Collections;
|
||||
@@ -40,13 +41,34 @@ namespace Obi
|
||||
ObiSolver solver;
|
||||
|
||||
SerializedProperty backend;
|
||||
SerializedProperty substeps;
|
||||
SerializedProperty maxStepsPerFrame;
|
||||
SerializedProperty synchronization;
|
||||
SerializedProperty simulateWhenInvisible;
|
||||
SerializedProperty parameters;
|
||||
SerializedProperty gravity;
|
||||
SerializedProperty gravitySpace;
|
||||
SerializedProperty ambientWind;
|
||||
SerializedProperty windSpace;
|
||||
SerializedProperty useLimits;
|
||||
SerializedProperty boundaryLimits;
|
||||
SerializedProperty killOffLimitsParticles;
|
||||
SerializedProperty worldLinearInertiaScale;
|
||||
SerializedProperty worldAngularInertiaScale;
|
||||
|
||||
SerializedProperty foamSubsteps;
|
||||
SerializedProperty foamMinNeighbors;
|
||||
SerializedProperty foamCollisions;
|
||||
SerializedProperty foamRadiusScale;
|
||||
SerializedProperty foamVolumeDensity;
|
||||
SerializedProperty foamAmbientDensity;
|
||||
SerializedProperty foamScatterColor;
|
||||
SerializedProperty foamAmbientColor;
|
||||
SerializedProperty maxFoamVelocityStretch;
|
||||
SerializedProperty foamFade;
|
||||
SerializedProperty foamAccelAgingRange;
|
||||
SerializedProperty foamAccelAging;
|
||||
|
||||
SerializedProperty distanceConstraintParameters;
|
||||
SerializedProperty bendingConstraintParameters;
|
||||
SerializedProperty particleCollisionConstraintParameters;
|
||||
@@ -58,37 +80,72 @@ namespace Obi
|
||||
SerializedProperty shapeMatchingConstraintParameters;
|
||||
SerializedProperty tetherConstraintParameters;
|
||||
SerializedProperty pinConstraintParameters;
|
||||
SerializedProperty pinholeConstraintParameters;
|
||||
SerializedProperty stitchConstraintParameters;
|
||||
SerializedProperty densityConstraintParameters;
|
||||
SerializedProperty stretchShearConstraintParameters;
|
||||
SerializedProperty bendTwistConstraintParameters;
|
||||
SerializedProperty chainConstraintParameters;
|
||||
|
||||
SerializedProperty maxSurfaceChunks;
|
||||
SerializedProperty maxQueryResults;
|
||||
SerializedProperty maxFoamParticles;
|
||||
SerializedProperty maxParticleNeighbors;
|
||||
SerializedProperty maxParticleContacts;
|
||||
|
||||
BooleanPreference solverFoldout;
|
||||
BooleanPreference simulationFoldout;
|
||||
BooleanPreference advectionFoldout;
|
||||
BooleanPreference collisionsFoldout;
|
||||
BooleanPreference constraintsFoldout;
|
||||
BooleanPreference memoryFoldout;
|
||||
|
||||
GUIContent constraintLabelContent;
|
||||
|
||||
BoxBoundsHandle limitsBoxHandle;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
solver = (ObiSolver)target;
|
||||
constraintLabelContent = new GUIContent();
|
||||
limitsBoxHandle = new BoxBoundsHandle();
|
||||
|
||||
solverFoldout = new BooleanPreference($"{target.GetType()}.solverFoldout", true);
|
||||
simulationFoldout = new BooleanPreference($"{target.GetType()}.simulationFoldout", false);
|
||||
advectionFoldout = new BooleanPreference($"{target.GetType()}.advectionFoldout", false);
|
||||
collisionsFoldout = new BooleanPreference($"{target.GetType()}.collisionsFoldout", false);
|
||||
constraintsFoldout = new BooleanPreference($"{target.GetType()}.constraintsFoldout", false);
|
||||
memoryFoldout = new BooleanPreference($"{target.GetType()}.memoryFoldout", false);
|
||||
|
||||
backend = serializedObject.FindProperty("m_Backend");
|
||||
substeps = serializedObject.FindProperty("substeps");
|
||||
maxStepsPerFrame = serializedObject.FindProperty("maxStepsPerFrame");
|
||||
synchronization = serializedObject.FindProperty("synchronization");
|
||||
simulateWhenInvisible = serializedObject.FindProperty("simulateWhenInvisible");
|
||||
parameters = serializedObject.FindProperty("parameters");
|
||||
gravity = serializedObject.FindProperty("gravity");
|
||||
gravitySpace = serializedObject.FindProperty("gravitySpace");
|
||||
ambientWind = serializedObject.FindProperty("ambientWind");
|
||||
windSpace = serializedObject.FindProperty("windSpace");
|
||||
useLimits = serializedObject.FindProperty("useLimits");
|
||||
boundaryLimits = serializedObject.FindProperty("boundaryLimits");
|
||||
killOffLimitsParticles = serializedObject.FindProperty("killOffLimitsParticles");
|
||||
worldLinearInertiaScale = serializedObject.FindProperty("worldLinearInertiaScale");
|
||||
worldAngularInertiaScale = serializedObject.FindProperty("worldAngularInertiaScale");
|
||||
|
||||
foamSubsteps = serializedObject.FindProperty("foamSubsteps");
|
||||
foamMinNeighbors = serializedObject.FindProperty("foamMinNeighbors");
|
||||
foamCollisions = serializedObject.FindProperty("foamCollisions");
|
||||
foamRadiusScale = serializedObject.FindProperty("foamRadiusScale");
|
||||
foamVolumeDensity = serializedObject.FindProperty("foamVolumeDensity");
|
||||
foamAmbientDensity = serializedObject.FindProperty("foamAmbientDensity");
|
||||
foamScatterColor = serializedObject.FindProperty("foamScatterColor");
|
||||
foamAmbientColor = serializedObject.FindProperty("foamAmbientColor");
|
||||
maxFoamVelocityStretch = serializedObject.FindProperty("maxFoamVelocityStretch");
|
||||
foamFade = serializedObject.FindProperty("foamFade");
|
||||
foamAccelAgingRange = serializedObject.FindProperty("foamAccelAgingRange");
|
||||
foamAccelAging = serializedObject.FindProperty("foamAccelAging");
|
||||
|
||||
distanceConstraintParameters = serializedObject.FindProperty("distanceConstraintParameters");
|
||||
bendingConstraintParameters = serializedObject.FindProperty("bendingConstraintParameters");
|
||||
particleCollisionConstraintParameters = serializedObject.FindProperty("particleCollisionConstraintParameters");
|
||||
@@ -100,19 +157,45 @@ namespace Obi
|
||||
shapeMatchingConstraintParameters = serializedObject.FindProperty("shapeMatchingConstraintParameters");
|
||||
tetherConstraintParameters = serializedObject.FindProperty("tetherConstraintParameters");
|
||||
pinConstraintParameters = serializedObject.FindProperty("pinConstraintParameters");
|
||||
pinholeConstraintParameters = serializedObject.FindProperty("pinholeConstraintParameters");
|
||||
stitchConstraintParameters = serializedObject.FindProperty("stitchConstraintParameters");
|
||||
densityConstraintParameters = serializedObject.FindProperty("densityConstraintParameters");
|
||||
stretchShearConstraintParameters = serializedObject.FindProperty("stretchShearConstraintParameters");
|
||||
bendTwistConstraintParameters = serializedObject.FindProperty("bendTwistConstraintParameters");
|
||||
chainConstraintParameters = serializedObject.FindProperty("chainConstraintParameters");
|
||||
|
||||
maxSurfaceChunks = serializedObject.FindProperty("m_MaxSurfaceChunks");
|
||||
maxQueryResults = serializedObject.FindProperty("maxQueryResults");
|
||||
maxFoamParticles = serializedObject.FindProperty("maxFoamParticles");
|
||||
maxParticleNeighbors = serializedObject.FindProperty("maxParticleNeighbors");
|
||||
maxParticleContacts = serializedObject.FindProperty("maxParticleContacts");
|
||||
}
|
||||
|
||||
public void OnSceneGUI()
|
||||
{
|
||||
if (solver.useLimits)
|
||||
{
|
||||
using (new Handles.DrawingScope(Color.red, solver.transform.localToWorldMatrix))
|
||||
{
|
||||
limitsBoxHandle.center = solver.boundaryLimits.center;
|
||||
limitsBoxHandle.size = solver.boundaryLimits.size;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
limitsBoxHandle.DrawHandle();
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
solver.boundaryLimits = new Bounds(limitsBoxHandle.center, limitsBoxHandle.size);
|
||||
EditorUtility.SetDirty(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
EditorGUILayout.HelpBox("Particles:" + solver.allocParticleCount +"\n"+
|
||||
"Simplices:" + solver.simplexCounts.simplexCount+"\n" +
|
||||
EditorGUILayout.HelpBox("Particles:" + solver.allocParticleCount + "\n" +
|
||||
"Simplices:" + solver.simplexCounts.simplexCount + "\n" +
|
||||
"Contacts:" + solver.contactCount + "\n" +
|
||||
"Simplex contacts:" + solver.particleContactCount, MessageType.None);
|
||||
|
||||
@@ -123,13 +206,14 @@ namespace Obi
|
||||
EditorGUILayout.PropertyField(backend);
|
||||
|
||||
#if !(OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
|
||||
if (backend.enumValueIndex == (int)ObiSolver.BackendType.Burst)
|
||||
EditorGUILayout.HelpBox("The Burst backend depends on the following packages: Mathematics, Collections, Jobs and Burst. The default backend (Oni) will be used instead, if possible.", MessageType.Warning);
|
||||
#endif
|
||||
#if !(OBI_ONI_SUPPORTED)
|
||||
if (backend.enumValueIndex == (int)ObiSolver.BackendType.Oni)
|
||||
EditorGUILayout.HelpBox("The Oni backend is not compatible with the target platform. Please switch to a compatible platform, or use the Burst backend instead.", MessageType.Warning);
|
||||
if (backend.enumValueIndex == (int)ObiSolver.BackendType.Burst)
|
||||
EditorGUILayout.HelpBox("The Burst backend depends on the following packages: Mathematics, Collections, Jobs and Burst. Please install the required dependencies. The solver will try to fall back to the Compute backend instead.", MessageType.Warning);
|
||||
#endif
|
||||
if (!SystemInfo.supportsComputeShaders)
|
||||
{
|
||||
EditorGUILayout.HelpBox("This platform doesn't support compute shaders. Please switch to the Burst backend.", MessageType.Error);
|
||||
}
|
||||
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
@@ -138,9 +222,11 @@ namespace Obi
|
||||
(t as ObiSolver).UpdateBackend();
|
||||
}
|
||||
|
||||
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("mode"));
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("interpolation"));
|
||||
EditorGUILayout.PropertyField(synchronization);
|
||||
EditorGUILayout.PropertyField(substeps);
|
||||
EditorGUILayout.PropertyField(maxStepsPerFrame);
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
|
||||
@@ -149,24 +235,57 @@ namespace Obi
|
||||
{
|
||||
EditorGUILayout.PropertyField(gravitySpace);
|
||||
EditorGUILayout.PropertyField(gravity);
|
||||
EditorGUILayout.PropertyField(windSpace);
|
||||
EditorGUILayout.PropertyField(ambientWind);
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("sleepThreshold"));
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("maxVelocity"));
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("maxAngularVelocity"));
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("damping"));
|
||||
EditorGUILayout.PropertyField(worldLinearInertiaScale);
|
||||
EditorGUILayout.PropertyField(worldAngularInertiaScale);
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("maxAnisotropy"));
|
||||
EditorGUILayout.PropertyField(simulateWhenInvisible);
|
||||
EditorGUILayout.PropertyField(useLimits);
|
||||
if (useLimits.boolValue)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.PropertyField(killOffLimitsParticles);
|
||||
EditorGUILayout.PropertyField(boundaryLimits);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
|
||||
advectionFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(advectionFoldout, "Foam settings");
|
||||
if (advectionFoldout)
|
||||
{
|
||||
EditorGUILayout.PropertyField(foamSubsteps);
|
||||
EditorGUILayout.PropertyField(foamMinNeighbors);
|
||||
EditorGUILayout.PropertyField(foamCollisions, new GUIContent("Foam Collisions (Compute only)"));
|
||||
EditorGUILayout.PropertyField(foamRadiusScale);
|
||||
EditorGUILayout.PropertyField(foamVolumeDensity);
|
||||
EditorGUILayout.PropertyField(foamAmbientDensity);
|
||||
EditorGUILayout.PropertyField(foamScatterColor);
|
||||
EditorGUILayout.PropertyField(foamAmbientColor);
|
||||
EditorGUILayout.PropertyField(maxFoamVelocityStretch);
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("foamGravityScale"));
|
||||
EditorGUILayout.PropertyField(foamFade);
|
||||
EditorGUILayout.PropertyField(foamAccelAgingRange);
|
||||
EditorGUILayout.PropertyField(foamAccelAging);
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
|
||||
collisionsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(collisionsFoldout, "Collision settings");
|
||||
if (collisionsFoldout)
|
||||
{
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("continuousCollisionDetection"));
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("colliderCCD"));
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("particleCCD"));
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("collisionMargin"));
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("maxDepenetration"));
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("shockPropagation"));
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("surfaceCollisionIterations"));
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("surfaceCollisionTolerance"));
|
||||
EditorGUILayout.PropertyField(parameters.FindPropertyRelative("diffusionMask"));
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
|
||||
@@ -206,6 +325,9 @@ namespace Obi
|
||||
constraintLabelContent.text = "Pin";
|
||||
EditorGUILayout.PropertyField(pinConstraintParameters, constraintLabelContent);
|
||||
|
||||
constraintLabelContent.text = "Pinhole";
|
||||
EditorGUILayout.PropertyField(pinholeConstraintParameters, constraintLabelContent);
|
||||
|
||||
constraintLabelContent.text = "Stitch";
|
||||
EditorGUILayout.PropertyField(stitchConstraintParameters, constraintLabelContent);
|
||||
|
||||
@@ -223,13 +345,46 @@ namespace Obi
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
|
||||
memoryFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(memoryFoldout, "Memory budget");
|
||||
if (memoryFoldout)
|
||||
{
|
||||
EditorGUILayout.PropertyField(maxQueryResults);
|
||||
EditorGUILayout.PropertyField(maxFoamParticles);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(maxSurfaceChunks);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
foreach (var t in targets)
|
||||
(t as ObiSolver).dirtyRendering |= (int)Oni.RenderingSystemType.Fluid;
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(maxParticleNeighbors);
|
||||
EditorGUILayout.PropertyField(maxParticleContacts);
|
||||
|
||||
uint usedChunks = solver.usedSurfaceChunks;
|
||||
float usagePercentage = usedChunks / (float)maxSurfaceChunks.intValue;
|
||||
uint foamParticles = solver.initialized ? solver.implementation.activeFoamParticleCount : 0;
|
||||
|
||||
// memory consumption per chunk:
|
||||
// (8 + 12 + 64*4 + 64*6*4 + 64*16) = 2836 bytes
|
||||
EditorGUILayout.HelpBox("Active foam particles: " + foamParticles + "/" + maxFoamParticles.intValue + "\n"+
|
||||
"Surface memory (Mb): " + string.Format("{0:N2}", maxSurfaceChunks.intValue * 0.002836f)+ "\n"+
|
||||
"Used surface chunks: "+ usedChunks + "/"+ maxSurfaceChunks.intValue + ", hashtable usage "+ string.Format("{0:N1}", usagePercentage * 100) + "%", MessageType.None);
|
||||
|
||||
if (usagePercentage >= 0.5f)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Hashtable usage should be below 50% for best performance. Increase max surface chunks if % is too high.", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
|
||||
// Apply changes to the serializedProperty
|
||||
if (GUI.changed)
|
||||
{
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
solver.PushSolverParameters();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -237,15 +392,12 @@ namespace Obi
|
||||
[DrawGizmo(GizmoType.InSelectionHierarchy | GizmoType.Selected)]
|
||||
static void DrawGizmoForSolver(ObiSolver solver, GizmoType gizmoType)
|
||||
{
|
||||
|
||||
if ((gizmoType & GizmoType.InSelectionHierarchy) != 0)
|
||||
{
|
||||
|
||||
Gizmos.color = new Color(1, 1, 1, 0.5f);
|
||||
Bounds bounds = solver.Bounds;
|
||||
var bounds = solver.bounds;
|
||||
Gizmos.DrawWireCube(bounds.center, bounds.size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using UnityEngine.SceneManagement;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using System.IO;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Obi{
|
||||
|
||||
@@ -127,17 +128,7 @@ namespace Obi{
|
||||
public static GameObject CreateNewSolver()
|
||||
{
|
||||
// Root for the actors.
|
||||
var root = new GameObject("Obi Solver");
|
||||
ObiSolver solver = root.AddComponent<ObiSolver>();
|
||||
|
||||
// Try to find a fixed updater in the scene (though other kinds of updaters can exist, updating in FixedUpdate is the preferred option).
|
||||
ObiFixedUpdater updater = StageUtility.GetCurrentStageHandle().FindComponentOfType<ObiFixedUpdater>();
|
||||
// If we could not find an fixed updater in the scene, add one to the solver object.
|
||||
if (updater == null)
|
||||
updater = root.AddComponent<ObiFixedUpdater>();
|
||||
|
||||
// Add the solver to the updater:
|
||||
updater.solvers.Add(solver);
|
||||
var root = new GameObject("Obi Solver", typeof(ObiSolver));
|
||||
|
||||
// Works for all stages.
|
||||
StageUtility.PlaceGameObjectInCurrentStage(root);
|
||||
@@ -230,7 +221,34 @@ namespace Obi{
|
||||
// Return the currently selected item's index
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawArrowHandle(Vector3 posA, Vector3 posB, float headAngle = 30, float headLength = 0.18f)
|
||||
{
|
||||
Handles.DrawLine(posA, posB);
|
||||
|
||||
var look = Quaternion.LookRotation(posA - posB, Camera.current.transform.forward);
|
||||
var one = look * Quaternion.Euler(0, 180 + headAngle, 0) * new Vector3(0, 0, 1);
|
||||
var two = look * Quaternion.Euler(0, 180 - headAngle, 0) * new Vector3(0, 0, 1);
|
||||
|
||||
var sizeA = HandleUtility.GetHandleSize(posA) * headLength;
|
||||
Handles.DrawLine(posA, posA + one * sizeA);
|
||||
Handles.DrawLine(posA, posA + two * sizeA);
|
||||
|
||||
var sizeB = HandleUtility.GetHandleSize(posB) * headLength;
|
||||
Handles.DrawLine(posB, posB - one * sizeB);
|
||||
Handles.DrawLine(posB, posB - two * sizeB);
|
||||
}
|
||||
|
||||
public static Material GetDefaultMaterial()
|
||||
{
|
||||
if (GraphicsSettings.defaultRenderPipeline != null)
|
||||
{
|
||||
return GraphicsSettings.defaultRenderPipeline.defaultMaterial;
|
||||
}
|
||||
else
|
||||
{
|
||||
return AssetDatabase.GetBuiltinExtraResource<Material>("Default-Diffuse.mat");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
Assets/Obi/Editor/Common/Utils/ObiFoamGeneratorEditor.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
[CustomEditor(typeof(ObiFoamGenerator)), CanEditMultipleObjects]
|
||||
public class ObiFoamGeneratorEditor : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
|
||||
DrawPropertiesExcluding(serializedObject, "m_Script");
|
||||
|
||||
// Apply changes to the serializedProperty
|
||||
if (GUI.changed)
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9656e2c54d9e4c478c74ca6d97428f8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -15,6 +15,7 @@ namespace Obi
|
||||
SerializedProperty targetTransform;
|
||||
SerializedProperty particleGroup;
|
||||
SerializedProperty attachmentType;
|
||||
SerializedProperty projectPosition;
|
||||
SerializedProperty constrainOrientation;
|
||||
SerializedProperty compliance;
|
||||
SerializedProperty breakThreshold;
|
||||
@@ -28,9 +29,10 @@ namespace Obi
|
||||
targetTransform = serializedObject.FindProperty("m_Target");
|
||||
particleGroup = serializedObject.FindProperty("m_ParticleGroup");
|
||||
attachmentType = serializedObject.FindProperty("m_AttachmentType");
|
||||
projectPosition = serializedObject.FindProperty("m_Projection");
|
||||
constrainOrientation = serializedObject.FindProperty("m_ConstrainOrientation");
|
||||
compliance = serializedObject.FindProperty("m_Compliance");
|
||||
breakThreshold = serializedObject.FindProperty("m_BreakThreshold");
|
||||
breakThreshold = serializedObject.FindProperty("breakThreshold");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
@@ -55,7 +57,16 @@ namespace Obi
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(targetTransform, new GUIContent("Target"));
|
||||
EditorGUI.BeginChangeCheck();
|
||||
Transform trget = EditorGUILayout.ObjectField("Target", attachment.target, typeof(Transform), true) as Transform;
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(attachment, "Set target");
|
||||
attachment.target = trget;
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(attachment);
|
||||
}
|
||||
|
||||
|
||||
var blueprint = attachment.actor.sourceBlueprint;
|
||||
|
||||
if (blueprint != null)
|
||||
@@ -89,6 +100,7 @@ namespace Obi
|
||||
|
||||
if (attachment.attachmentType == ObiParticleAttachment.AttachmentType.Dynamic)
|
||||
{
|
||||
EditorGUILayout.PropertyField(projectPosition, new GUIContent("Projection"));
|
||||
EditorGUILayout.PropertyField(compliance, new GUIContent("Compliance"));
|
||||
EditorGUILayout.PropertyField(breakThreshold, new GUIContent("Break threshold"));
|
||||
}
|
||||
|
||||
@@ -42,6 +42,9 @@ namespace Obi{
|
||||
if (EditorGUI.EndChangeCheck()){
|
||||
Undo.RecordObject(stitcher, "Set first actor");
|
||||
stitcher.Actor1 = actor1;
|
||||
if (actor1 != null)
|
||||
sewingToolHandle1 = actor1.transform.position;
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(stitcher);
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
@@ -49,7 +52,10 @@ namespace Obi{
|
||||
if (EditorGUI.EndChangeCheck()){
|
||||
Undo.RecordObject(stitcher, "Set second actor");
|
||||
stitcher.Actor2 = actor2;
|
||||
}
|
||||
if (actor2 != null)
|
||||
sewingToolHandle2 = actor2.transform.position;
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(stitcher);
|
||||
}
|
||||
|
||||
if (stitcher.Actor1 != null && stitcher.Actor2 != null && stitcher.Actor1.solver != stitcher.Actor2.solver){
|
||||
EditorGUILayout.HelpBox("Both actors must be managed by the same solver.",MessageType.Error);
|
||||
@@ -63,14 +69,13 @@ namespace Obi{
|
||||
|
||||
if (editing){
|
||||
|
||||
EditorGUILayout.HelpBox("Remember that when working with the sewing tool, you can use Unity's snap to vertex feature by pressing 'V' in your keyboard.",MessageType.Info);
|
||||
|
||||
// Clear all stitches
|
||||
if (GUILayout.Button("Clear all stitches")){
|
||||
if (EditorUtility.DisplayDialog("Clearing stitches","Are you sure you want to remove all stitches?","Ok","Cancel")){
|
||||
Undo.RecordObject(stitcher, "Clear all stitches");
|
||||
stitcher.Clear();
|
||||
}
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(stitcher);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove selected stitches
|
||||
@@ -93,19 +98,22 @@ namespace Obi{
|
||||
foreach(int i in removedStitches.OrderByDescending(i => i)){
|
||||
stitcher.RemoveStitch(i);
|
||||
}
|
||||
}
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(stitcher);
|
||||
}
|
||||
}
|
||||
|
||||
// Add stitch:
|
||||
if (GUILayout.Button("Add Stitch")){
|
||||
Undo.RecordObject(stitcher, "Add stitch");
|
||||
if (GUILayout.Button("Add Stitch"))
|
||||
{
|
||||
FindClosestParticles(out int particle1, out int particle2);
|
||||
|
||||
int particle1 = 0;
|
||||
int particle2 = 0;
|
||||
UseSewingTool(ref particle1, ref particle2);
|
||||
|
||||
stitcher.AddStitch(particle1,particle2);
|
||||
}
|
||||
if (particle1 >= 0 && particle2 >= 0)
|
||||
{
|
||||
Undo.RecordObject(stitcher, "Add stitch");
|
||||
stitcher.AddStitch(particle1, particle2);
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(stitcher);
|
||||
}
|
||||
}
|
||||
}
|
||||
GUI.enabled = true;
|
||||
|
||||
@@ -120,16 +128,28 @@ namespace Obi{
|
||||
|
||||
}
|
||||
|
||||
public void UseSewingTool(ref int particle1, ref int particle2){
|
||||
public void FindClosestParticles(out int particle1, out int particle2)
|
||||
{
|
||||
particle1 = -1;
|
||||
particle2 = -1;
|
||||
float minDistance = float.MaxValue;
|
||||
|
||||
float minDistance = float.MaxValue;
|
||||
if (stitcher.Actor1 == null || stitcher.Actor2 == null)
|
||||
return;
|
||||
|
||||
if (stitcher.Actor1 == stitcher.Actor2){
|
||||
var handle1 = HandleUtility.WorldToGUIPointWithDepth(sewingToolHandle1);
|
||||
var handle2 = HandleUtility.WorldToGUIPointWithDepth(sewingToolHandle2);
|
||||
|
||||
if (stitcher.Actor1 == stitcher.Actor2)
|
||||
{
|
||||
float minDistance2 = float.MaxValue;
|
||||
for (int i = 0; i < stitcher.Actor1.particleCount;++i){
|
||||
for (int i = 0; i < stitcher.Actor1.activeParticleCount;++i)
|
||||
{
|
||||
Vector3 pos = stitcher.Actor1.GetParticlePosition(stitcher.Actor1.solverIndices[i]);
|
||||
float distance1 = (pos - sewingToolHandle1).sqrMagnitude;
|
||||
float distance2 = (pos - sewingToolHandle2).sqrMagnitude;
|
||||
pos = HandleUtility.WorldToGUIPointWithDepth(pos);
|
||||
|
||||
float distance1 = (pos - handle1).sqrMagnitude;
|
||||
float distance2 = (pos - handle2).sqrMagnitude;
|
||||
if (distance1 < minDistance){
|
||||
minDistance = distance1;
|
||||
particle1 = i;
|
||||
@@ -142,24 +162,28 @@ namespace Obi{
|
||||
}else{
|
||||
|
||||
// find closest particle to each end of the sewing tool:
|
||||
for (int i = 0; i < stitcher.Actor1.particleCount;++i){
|
||||
for (int i = 0; i < stitcher.Actor1.activeParticleCount; ++i)
|
||||
{
|
||||
Vector3 pos = stitcher.Actor1.GetParticlePosition(stitcher.Actor1.solverIndices[i]);
|
||||
float distance1 = (pos - sewingToolHandle1).sqrMagnitude;
|
||||
float distance2 = (pos - sewingToolHandle2).sqrMagnitude;
|
||||
float min = Mathf.Min(distance1,distance2);
|
||||
if (min < minDistance){
|
||||
pos = HandleUtility.WorldToGUIPointWithDepth(pos);
|
||||
|
||||
float min = (pos - handle1).sqrMagnitude;
|
||||
if (min < minDistance)
|
||||
{
|
||||
minDistance = min;
|
||||
particle1 = i;
|
||||
}
|
||||
}
|
||||
|
||||
minDistance = float.MaxValue;
|
||||
for (int i = 0; i < stitcher.Actor2.particleCount;++i){
|
||||
for (int i = 0; i < stitcher.Actor2.activeParticleCount; ++i)
|
||||
{
|
||||
Vector3 pos = stitcher.Actor2.GetParticlePosition(stitcher.Actor2.solverIndices[i]);
|
||||
float distance1 = (pos - sewingToolHandle1).sqrMagnitude;
|
||||
float distance2 = (pos - sewingToolHandle2).sqrMagnitude;
|
||||
float min = Mathf.Min(distance1,distance2);
|
||||
if (min < minDistance){
|
||||
pos = HandleUtility.WorldToGUIPointWithDepth(pos);
|
||||
|
||||
float min = (pos - handle2).sqrMagnitude;
|
||||
if (min < minDistance)
|
||||
{
|
||||
minDistance = min;
|
||||
particle2 = i;
|
||||
}
|
||||
@@ -167,10 +191,32 @@ namespace Obi{
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawSewingTool(){
|
||||
var fmh_171_72_639027316145683117 = Quaternion.identity; sewingToolHandle1 = Handles.FreeMoveHandle(sewingToolHandle1,HandleUtility.GetHandleSize(sewingToolHandle1)*0.05f,new Vector3(.5f,.5f,.5f),Handles.RectangleHandleCap);
|
||||
var fmh_172_66_639027316145718628 = Quaternion.identity; sewingToolHandle2 = Handles.FreeMoveHandle(sewingToolHandle2,HandleUtility.GetHandleSize(sewingToolHandle2)*0.05f,new Vector3(.5f,.5f,.5f),Handles.RectangleHandleCap);
|
||||
Handles.DrawDottedLine(sewingToolHandle1,sewingToolHandle2,2);
|
||||
public void DrawSewingTool()
|
||||
{
|
||||
|
||||
FindClosestParticles(out int particle1, out int particle2);
|
||||
|
||||
if (particle1 >= 0 && particle2 >= 0)
|
||||
{
|
||||
sewingToolHandle1 = stitcher.Actor1.GetParticlePosition(stitcher.Actor1.solverIndices[particle1]);
|
||||
sewingToolHandle2 = stitcher.Actor2.GetParticlePosition(stitcher.Actor2.solverIndices[particle2]);
|
||||
|
||||
float radius1 = stitcher.Actor1.GetParticleMaxRadius(stitcher.Actor1.solverIndices[particle1]);
|
||||
float radius2 = stitcher.Actor2.GetParticleMaxRadius(stitcher.Actor2.solverIndices[particle2]);
|
||||
|
||||
Handles.color = Color.white;
|
||||
#if (UNITY_2022_1_OR_NEWER)
|
||||
sewingToolHandle1 = Handles.FreeMoveHandle(sewingToolHandle1, radius1 * 2, new Vector3(.5f,.5f,.5f),Handles.SphereHandleCap);
|
||||
sewingToolHandle2 = Handles.FreeMoveHandle(sewingToolHandle2, radius2 * 2, new Vector3(.5f,.5f,.5f),Handles.SphereHandleCap);
|
||||
#else
|
||||
sewingToolHandle1 = Handles.FreeMoveHandle(sewingToolHandle1, Quaternion.identity, radius1 * 2, new Vector3(.5f, .5f, .5f), Handles.SphereHandleCap);
|
||||
sewingToolHandle2 = Handles.FreeMoveHandle(sewingToolHandle2, Quaternion.identity, radius2 * 2, new Vector3(.5f, .5f, .5f), Handles.SphereHandleCap);
|
||||
#endif
|
||||
|
||||
Vector3 direction = Vector3.Normalize(sewingToolHandle2 - sewingToolHandle1);
|
||||
Handles.color = Color.yellow;
|
||||
ObiEditorUtils.DrawArrowHandle(sewingToolHandle1 + direction*(radius1 + 0.05f), sewingToolHandle2 - direction*(radius2+0.05f));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +267,7 @@ namespace Obi{
|
||||
}
|
||||
break;
|
||||
case EventType.Repaint:
|
||||
Handles.color = selectionStatus[i]?Color.red:Color.green;
|
||||
Handles.color = selectionStatus[i]?Color.red:Color.cyan;
|
||||
Handles.DrawDottedLine(pos1,pos2,2);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -81,8 +81,8 @@ Material:
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _AABBMax: {r: 1.3624613, g: 1.3624613, b: 1.3624613, a: 0}
|
||||
- _AABBMin: {r: -1.3624613, g: -1.3624613, b: -1.3624613, a: 0}
|
||||
- _AABBMax: {r: 1.1746451, g: 1.1746451, b: 1.1746451, a: 0}
|
||||
- _AABBMin: {r: -1.1746451, g: -1.1746451, b: -1.1746451, a: 0}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _InsideColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
#pragma fragment frag
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
|
||||
#include "../../Resources/ObiMaterials/ObiEllipsoids.cginc"
|
||||
#include "../../Resources/ObiMaterials/ObiUtils.cginc"
|
||||
#include "../../Resources/ObiMaterials/Common/ObiEllipsoids.cginc"
|
||||
#include "../../Resources/ObiMaterials/Common/ObiUtils.cginc"
|
||||
|
||||
fixed4 _Color;
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
float3 lightDir : TEXCOORD2;
|
||||
float3 a2 : TEXCOORD3;
|
||||
float3 a3 : TEXCOORD4;
|
||||
//float3x3 P : TEXCOORD5;
|
||||
};
|
||||
|
||||
struct fout
|
||||
@@ -65,6 +66,7 @@
|
||||
o.mapping = float4(v.corner.xy,1/length(eye),radius); // A[1]
|
||||
o.viewRay = mul((float3x3)UNITY_MATRIX_V,view); // A[0]
|
||||
o.color = v.color * _Color;
|
||||
//o.P = float3x3(v.t0.xyz,v.t1.xyz,v.t2.xyz);
|
||||
|
||||
BuildAuxiliaryNormalVectors(v.vertex,worldPos,view,P,IP,o.a2,o.a3);
|
||||
|
||||
@@ -86,6 +88,19 @@
|
||||
// clip space position:
|
||||
float4 pos = mul(UNITY_MATRIX_P,float4(p,1.0));
|
||||
|
||||
// local space normal, use to calculate UVs
|
||||
/*float3 ln = mul(mul((float3x3)i.P,UNITY_MATRIX_I_V) ,n);
|
||||
|
||||
float2 uv = float2(
|
||||
// atan returns a value between -pi and pi
|
||||
// so we divide by pi * 2 to get -0.5 to 0.5
|
||||
atan2(ln.x, ln.y) / (3.1415 * 2.0),
|
||||
// acos returns 0.0 at the top, pi at the bottom
|
||||
// so we flip the y to align with Unity's OpenGL style
|
||||
// texture UVs so 0.0 is at the bottom
|
||||
acos(-ln.z) / 3.1415
|
||||
);*/
|
||||
|
||||
// simple lighting: ambient
|
||||
float3 modelUp = mul (UNITY_MATRIX_IT_MV,float3(0,1,0));
|
||||
float vecHemi = dot(n, modelUp) * 0.5f + 0.5f;
|
||||
|
||||
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
BIN
Assets/Obi/Editor/Resources/Icons/ObiFoamGenerator Icon.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
@@ -1,12 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e2c952f509ae40bdaf836136058d487
|
||||
guid: b7cec6e680e3a479ca03a89eccd4e052
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 5
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
@@ -21,6 +21,10 @@ TextureImporter:
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
@@ -29,12 +33,12 @@ TextureImporter:
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
@@ -52,11 +56,15 @@ TextureImporter:
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
@@ -67,7 +75,8 @@ TextureImporter:
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
@@ -78,19 +87,9 @@ TextureImporter:
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Android
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
@@ -100,6 +99,7 @@ TextureImporter:
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
@@ -107,11 +107,16 @@ TextureImporter:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
BIN
Assets/Obi/Editor/Resources/Icons/ObiPathSmoother Icon.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
@@ -1,17 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 092f06332c018434b8c8ea86164ef4fd
|
||||
timeCreated: 1482503923
|
||||
licenseType: Store
|
||||
guid: 8791eecf125744cbeadea65319c29d5a
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 4
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
@@ -20,6 +21,10 @@ TextureImporter:
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
@@ -27,10 +32,13 @@ TextureImporter:
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
@@ -39,54 +47,76 @@ TextureImporter:
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Standalone
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Android
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Obi/Editor/Resources/Icons/ObiPinhole Icon.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
@@ -1,17 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b6e7fb3568d24300be305b5d1d7554d
|
||||
timeCreated: 1454660299
|
||||
licenseType: Store
|
||||
guid: 214df93f7c2ed4c1094bb6105c050575
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 4
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 0
|
||||
linearTexture: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
@@ -20,17 +21,24 @@ TextureImporter:
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
@@ -39,54 +47,76 @@ TextureImporter:
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Standalone
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Android
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
BIN
Assets/Obi/Editor/Resources/Icons/ObiVoidZone Icon.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
122
Assets/Obi/Editor/Resources/Icons/ObiVoidZone Icon.png.meta
Normal file
@@ -0,0 +1,122 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eac6271e2e50d4b2dbf2dfeff9b65604
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
Pass {
|
||||
|
||||
Offset 0, -50
|
||||
Cull Back
|
||||
Offset -0.5, -0.5
|
||||
Cull Back
|
||||
Fog { Mode Off }
|
||||
|
||||
CGPROGRAM
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
Pass {
|
||||
|
||||
Offset 0, -100
|
||||
Offset -1, -1
|
||||
Cull Back
|
||||
ZWrite Off
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 931c48569a82e4dae84d4702bf6da199
|
||||
timeCreated: 1478802054
|
||||
licenseType: Store
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 1
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
@@ -20,40 +21,78 @@ TextureImporter:
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 7
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
allowsAlphaSplitting: 0
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
buildTargetSettings: []
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 1
|
||||
pSDShowRemoveMatteOption: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@@ -33,6 +33,10 @@ namespace Obi
|
||||
SerializedProperty plasticYield;
|
||||
SerializedProperty plasticCreep;
|
||||
|
||||
SerializedProperty aerodynamicsEnabled;
|
||||
SerializedProperty drag;
|
||||
SerializedProperty lift;
|
||||
|
||||
SerializedProperty fixRoot;
|
||||
SerializedProperty stretchBones;
|
||||
SerializedProperty ignored;
|
||||
@@ -69,6 +73,9 @@ namespace Obi
|
||||
plasticYield = serializedObject.FindProperty("_plasticYield");
|
||||
plasticCreep = serializedObject.FindProperty("_plasticCreep");
|
||||
|
||||
aerodynamicsEnabled = serializedObject.FindProperty("_aerodynamicsEnabled");
|
||||
drag = serializedObject.FindProperty("_drag");
|
||||
lift = serializedObject.FindProperty("_lift");
|
||||
}
|
||||
|
||||
public void OnDisable()
|
||||
@@ -144,6 +151,12 @@ namespace Obi
|
||||
EditorGUILayout.PropertyField(plasticCreep, new GUIContent("Plastic creep"));
|
||||
});
|
||||
|
||||
ObiEditorUtils.DoToggleablePropertyGroup(aerodynamicsEnabled, new GUIContent("Aerodynamics", Resources.Load<Texture2D>("Icons/ObiAerodynamicConstraints Icon")),
|
||||
() => {
|
||||
EditorGUILayout.PropertyField(drag, new GUIContent("Drag"));
|
||||
EditorGUILayout.PropertyField(lift, new GUIContent("Lift"));
|
||||
});
|
||||
|
||||
if (GUI.changed)
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
|
||||
@@ -2,12 +2,38 @@ using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.EditorTools;
|
||||
using System;
|
||||
using UnityEditor.Overlays;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[EditorTool("Obi Path Editor Tool",typeof(ObiRopeBase))]
|
||||
public class ObiPathEditor : EditorTool
|
||||
{
|
||||
|
||||
[Overlay(typeof(SceneView), "Obi Path Editor", "Obi Path Editor", "Obi Path Editor", true)]
|
||||
[Icon("Assets/Obi/Editor/Resources/EditCurves.psd")]
|
||||
class PathEditorOverlay : Overlay, ITransientOverlay
|
||||
{
|
||||
public static ObiPathEditor editor;
|
||||
|
||||
public override VisualElement CreatePanelContent()
|
||||
{
|
||||
var root = new VisualElement();
|
||||
root.Add(new IMGUIContainer(editor.DrawToolPanel));
|
||||
return root;
|
||||
}
|
||||
|
||||
// Use the visible property to hide or show this instance from within the class.
|
||||
public bool visible
|
||||
{
|
||||
get
|
||||
{
|
||||
return ToolManager.activeToolType == typeof(ObiPathEditor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum PathEditorTool
|
||||
{
|
||||
TranslatePoints,
|
||||
@@ -64,6 +90,7 @@ namespace Obi
|
||||
{
|
||||
this.useOrientation = target is ObiRod;
|
||||
selectedStatus = new bool[0];
|
||||
PathEditorOverlay.editor = this;
|
||||
}
|
||||
|
||||
public void ResizeCPArrays()
|
||||
@@ -71,7 +98,6 @@ namespace Obi
|
||||
Array.Resize(ref selectedStatus, path.ControlPointCount);
|
||||
}
|
||||
|
||||
int windowId;
|
||||
public override void OnToolGUI(EditorWindow window)
|
||||
{
|
||||
needsRepaint = false;
|
||||
@@ -82,11 +108,7 @@ namespace Obi
|
||||
|
||||
ResizeCPArrays();
|
||||
|
||||
HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
|
||||
|
||||
// get a window ID:
|
||||
if (Event.current.type != EventType.Used)
|
||||
windowId = GUIUtility.GetControlID(FocusType.Passive);
|
||||
HandleUtility.AddDefaultControl(GUIUtility.GetControlID("PathEditor".GetHashCode(), FocusType.Passive));
|
||||
|
||||
Matrix4x4 prevMatrix = Handles.matrix;
|
||||
Handles.matrix = matrix;
|
||||
@@ -98,9 +120,6 @@ namespace Obi
|
||||
needsRepaint |= DrawControlPoint(i);
|
||||
}
|
||||
|
||||
// Control point selection handle:
|
||||
needsRepaint |= ObiPathHandles.SplineCPSelector(path, selectedStatus);
|
||||
|
||||
// Count selected and calculate average position:
|
||||
selectionAverage = GetControlPointAverage(out lastSelected, out selectedCount);
|
||||
|
||||
@@ -110,10 +129,8 @@ namespace Obi
|
||||
if (showThicknessHandles)
|
||||
needsRepaint |= DoThicknessHandles(thicknessScale);
|
||||
|
||||
// Sceneview GUI:
|
||||
Handles.BeginGUI();
|
||||
GUILayout.Window(windowId, new Rect(10, 28, 0, 0), DrawUIWindow, "Path editor");
|
||||
Handles.EndGUI();
|
||||
// Control point selection handle:
|
||||
needsRepaint |= ObiPathHandles.SplineCPSelector(path, selectedStatus);
|
||||
|
||||
Handles.matrix = prevMatrix;
|
||||
|
||||
@@ -545,7 +562,7 @@ namespace Obi
|
||||
return false;
|
||||
}
|
||||
|
||||
public void DrawUIWindow(int windowID)
|
||||
public void DrawToolPanel()
|
||||
{
|
||||
|
||||
DrawToolButtons();
|
||||
@@ -1056,7 +1073,7 @@ namespace Obi
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
color = EditorGUILayout.ColorField("Color", color, GUILayout.MinWidth(94));
|
||||
color = EditorGUILayout.ColorField(new GUIContent("Color"), color, true, true, true, GUILayout.MinWidth(94));
|
||||
EditorGUI.showMixedValue = false;
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
@@ -1153,7 +1170,7 @@ namespace Obi
|
||||
|
||||
for (int index = 0; index < 4; ++index)
|
||||
{
|
||||
int controlId = GUIUtility.GetControlID("ObiPathThicknessHandle".GetHashCode(), FocusType.Keyboard);
|
||||
int controlId = GUIUtility.GetControlID("ObiPathThicknessHandle".GetHashCode(), FocusType.Passive);
|
||||
Vector3 position1 = position + radius * vector3Array[index];
|
||||
bool changed = GUI.changed;
|
||||
GUI.changed = false;
|
||||
@@ -1197,7 +1214,7 @@ namespace Obi
|
||||
Vector2 currentPoint = HandleUtility.WorldToGUIPoint(path.m_Points.Evaluate(_p, p, p_, p__, i * step));
|
||||
|
||||
float mu;
|
||||
float distance = Vector2.SqrMagnitude((Vector2)ObiUtils.ProjectPointLine(screenPoint, lastPoint, currentPoint, out mu) - screenPoint);
|
||||
float distance = Vector2.SqrMagnitude((Vector2)ObiUtils.ProjectPointLine(lastPoint, currentPoint, screenPoint, out mu) - screenPoint);
|
||||
|
||||
if (distance < minDistance)
|
||||
{
|
||||
|
||||
@@ -28,27 +28,9 @@ namespace Obi
|
||||
// select vertex on mouse click:
|
||||
switch (Event.current.GetTypeForControl(controlID))
|
||||
{
|
||||
|
||||
case EventType.MouseDown:
|
||||
{
|
||||
|
||||
if ((Event.current.modifiers & EventModifiers.Control) == 0 &&
|
||||
(HandleUtility.nearestControl != controlID || Event.current.button != 0)) break;
|
||||
|
||||
startPos = Event.current.mousePosition;
|
||||
marquee.Set(0, 0, 0, 0);
|
||||
|
||||
// If the user is pressing shift, accumulate selection.
|
||||
if ((Event.current.modifiers & EventModifiers.Shift) == 0 && (Event.current.modifiers & EventModifiers.Alt) == 0)
|
||||
{
|
||||
for (int i = 0; i < selectionStatus.Length; i++)
|
||||
selectionStatus[i] = false;
|
||||
}
|
||||
|
||||
// If the user is holding down control, dont allow selection of other objects and use marquee tool.
|
||||
if ((Event.current.modifiers & EventModifiers.Control) != 0)
|
||||
GUIUtility.hotControl = controlID;
|
||||
|
||||
case EventType.Layout:
|
||||
case EventType.MouseMove:
|
||||
|
||||
float minSqrDistance = System.Single.MaxValue;
|
||||
float sqrMinSelectionDistance = minSelectionDistance * minSelectionDistance;
|
||||
|
||||
@@ -59,50 +41,94 @@ namespace Obi
|
||||
Vector2 pos = HandleUtility.WorldToGUIPoint(path.points[i].position);
|
||||
|
||||
// get distance from mouse position to particle position:
|
||||
float sqrDistance = Vector2.SqrMagnitude(startPos - pos);
|
||||
float sqrDistance = Vector2.SqrMagnitude(Event.current.mousePosition - pos);
|
||||
|
||||
// check if this control point is closer to the cursor that any previously considered point.
|
||||
if (sqrDistance < sqrMinSelectionDistance && sqrDistance < minSqrDistance)
|
||||
{
|
||||
{
|
||||
minSqrDistance = sqrDistance;
|
||||
selectedCPIndex = i;
|
||||
}
|
||||
|
||||
}
|
||||
HandleUtility.AddControl(controlID, Mathf.Sqrt(minSqrDistance));
|
||||
|
||||
break;
|
||||
|
||||
if (selectedCPIndex >= 0)
|
||||
{ // toggle particle selection status.
|
||||
case EventType.MouseDown:
|
||||
|
||||
marquee.Set(0, 0, 0, 0);
|
||||
startPos = Event.current.mousePosition;
|
||||
|
||||
selectionStatus[selectedCPIndex] = !selectionStatus[selectedCPIndex];
|
||||
selectionStatusChanged = true;
|
||||
if (Event.current.button == 0)
|
||||
{
|
||||
|
||||
// Prevent spline deselection if we have selected a particle:
|
||||
GUIUtility.hotControl = controlID;
|
||||
Event.current.Use();
|
||||
if (HandleUtility.nearestControl == controlID)
|
||||
{
|
||||
GUIUtility.hotControl = controlID;
|
||||
|
||||
// If the user is pressing shift or ctrl, accumulate selection.
|
||||
if ((Event.current.modifiers & (EventModifiers.Shift | EventModifiers.Control)) == 0 && (Event.current.modifiers & EventModifiers.Alt) == 0)
|
||||
{
|
||||
for (int i = 0; i < selectionStatus.Length; i++)
|
||||
selectionStatus[i] = false;
|
||||
|
||||
selectionStatusChanged = true;
|
||||
}
|
||||
|
||||
minSqrDistance = System.Single.MaxValue;
|
||||
sqrMinSelectionDistance = minSelectionDistance * minSelectionDistance;
|
||||
|
||||
for (int i = 0; i < path.ControlPointCount; i++)
|
||||
{
|
||||
|
||||
// get particle position in gui space:
|
||||
Vector2 pos = HandleUtility.WorldToGUIPoint(path.points[i].position);
|
||||
|
||||
// get distance from mouse position to particle position:
|
||||
float sqrDistance = Vector2.SqrMagnitude(startPos - pos);
|
||||
|
||||
// check if this control point is closer to the cursor that any previously considered point.
|
||||
if (sqrDistance < sqrMinSelectionDistance && sqrDistance < minSqrDistance)
|
||||
{
|
||||
minSqrDistance = sqrDistance;
|
||||
selectedCPIndex = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (selectedCPIndex >= 0)
|
||||
{ // toggle particle selection status.
|
||||
|
||||
selectionStatus[selectedCPIndex] = !selectionStatus[selectedCPIndex];
|
||||
selectionStatusChanged = true;
|
||||
|
||||
// Prevent spline deselection if we have selected a particle:
|
||||
Event.current.Use();
|
||||
|
||||
}
|
||||
}
|
||||
else if ((Event.current.modifiers & (EventModifiers.Shift | EventModifiers.Control)) == 0 && (Event.current.modifiers & EventModifiers.Alt) == 0)
|
||||
{
|
||||
for (int i = 0; i < selectionStatus.Length; i++)
|
||||
selectionStatus[i] = false;
|
||||
|
||||
selectionStatusChanged = true;
|
||||
}
|
||||
}
|
||||
else if (Event.current.modifiers == EventModifiers.None)
|
||||
{ // deselect all particles:
|
||||
for (int i = 0; i < selectionStatus.Length; i++)
|
||||
selectionStatus[i] = false;
|
||||
|
||||
selectionStatusChanged = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EventType.MouseDrag:
|
||||
|
||||
if (GUIUtility.hotControl == controlID)
|
||||
if (Event.current.button == 0 && (Event.current.modifiers & EventModifiers.Alt) == 0)
|
||||
{
|
||||
|
||||
currentPos = Event.current.mousePosition;
|
||||
if (!dragging && Vector2.Distance(startPos, currentPos) > 5)
|
||||
{
|
||||
dragging = true;
|
||||
}
|
||||
else
|
||||
|
||||
if (dragging)
|
||||
{
|
||||
GUIUtility.hotControl = controlID;
|
||||
Event.current.Use();
|
||||
@@ -161,34 +187,6 @@ namespace Obi
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case EventType.Layout:
|
||||
{
|
||||
|
||||
float minSqrDistance = System.Single.MaxValue;
|
||||
float sqrMinSelectionDistance = minSelectionDistance * minSelectionDistance;
|
||||
|
||||
for (int i = 0; i < path.ControlPointCount; i++)
|
||||
{
|
||||
|
||||
// get particle position in gui space:
|
||||
Vector2 pos = HandleUtility.WorldToGUIPoint(path.points[i].position);
|
||||
|
||||
// get distance from mouse position to particle position:
|
||||
float sqrDistance = Vector2.SqrMagnitude(Event.current.mousePosition - pos);
|
||||
|
||||
// check if this control point is closer to the cursor that any previously considered point.
|
||||
if (sqrDistance < sqrMinSelectionDistance && sqrDistance < minSqrDistance)
|
||||
{ //magic number 900 = 30*30, where 30 is min distance in pixels to select a particle.
|
||||
minSqrDistance = sqrDistance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HandleUtility.AddControl(controlID, Mathf.Sqrt(minSqrDistance));
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return selectionStatusChanged;
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace Obi
|
||||
static void CreateObiRod(MenuCommand menuCommand)
|
||||
{
|
||||
GameObject go = new GameObject("Obi Rod", typeof(ObiRod), typeof(ObiRopeExtrudedRenderer));
|
||||
var renderer = go.GetComponent<ObiRopeExtrudedRenderer>();
|
||||
renderer.material = ObiEditorUtils.GetDefaultMaterial();
|
||||
ObiEditorUtils.PlaceActorRoot(go, menuCommand);
|
||||
}
|
||||
|
||||
@@ -26,7 +28,8 @@ namespace Obi
|
||||
|
||||
SerializedProperty collisionMaterial;
|
||||
SerializedProperty selfCollisions;
|
||||
SerializedProperty surfaceCollisions;
|
||||
SerializedProperty surfaceCollisions;
|
||||
SerializedProperty massScale;
|
||||
|
||||
SerializedProperty stretchShearConstraintsEnabled;
|
||||
SerializedProperty stretchCompliance;
|
||||
@@ -40,6 +43,10 @@ namespace Obi
|
||||
SerializedProperty plasticYield;
|
||||
SerializedProperty plasticCreep;
|
||||
|
||||
SerializedProperty aerodynamicsEnabled;
|
||||
SerializedProperty drag;
|
||||
SerializedProperty lift;
|
||||
|
||||
SerializedProperty chainConstraintsEnabled;
|
||||
SerializedProperty tightness;
|
||||
|
||||
@@ -54,6 +61,7 @@ namespace Obi
|
||||
collisionMaterial = serializedObject.FindProperty("m_CollisionMaterial");
|
||||
selfCollisions = serializedObject.FindProperty("m_SelfCollisions");
|
||||
surfaceCollisions = serializedObject.FindProperty("m_SurfaceCollisions");
|
||||
massScale = serializedObject.FindProperty("m_MassScale");
|
||||
|
||||
stretchShearConstraintsEnabled = serializedObject.FindProperty("_stretchShearConstraintsEnabled");
|
||||
stretchCompliance = serializedObject.FindProperty("_stretchCompliance");
|
||||
@@ -67,6 +75,10 @@ namespace Obi
|
||||
plasticYield = serializedObject.FindProperty("_plasticYield");
|
||||
plasticCreep = serializedObject.FindProperty("_plasticCreep");
|
||||
|
||||
aerodynamicsEnabled = serializedObject.FindProperty("_aerodynamicsEnabled");
|
||||
drag = serializedObject.FindProperty("_drag");
|
||||
lift = serializedObject.FindProperty("_lift");
|
||||
|
||||
chainConstraintsEnabled = serializedObject.FindProperty("_chainConstraintsEnabled");
|
||||
tightness = serializedObject.FindProperty("_tightness");
|
||||
}
|
||||
@@ -110,8 +122,30 @@ namespace Obi
|
||||
|
||||
using (new EditorGUI.DisabledScope(ToolManager.activeToolType == typeof(ObiPathEditor)))
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
EditorGUILayout.PropertyField(rodBlueprint, new GUIContent("Blueprint"));
|
||||
|
||||
if (actor.rodBlueprint == null)
|
||||
{
|
||||
if (GUILayout.Button("Create", EditorStyles.miniButton, GUILayout.MaxWidth(80)))
|
||||
{
|
||||
string path = EditorUtility.SaveFilePanel("Save blueprint", "Assets/", "RodBlueprint", "asset");
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
path = FileUtil.GetProjectRelativePath(path);
|
||||
ObiRodBlueprint asset = ScriptableObject.CreateInstance<ObiRodBlueprint>();
|
||||
|
||||
AssetDatabase.CreateAsset(asset, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
actor.rodBlueprint = asset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
foreach (var t in targets)
|
||||
@@ -123,8 +157,12 @@ namespace Obi
|
||||
foreach (var t in targets)
|
||||
(t as ObiRod).AddToSolver();
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(massScale, new GUIContent("m_MassScale"));
|
||||
|
||||
DoEditButton();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
@@ -150,6 +188,12 @@ namespace Obi
|
||||
EditorGUILayout.PropertyField(plasticCreep, new GUIContent("Plastic creep"));
|
||||
});
|
||||
|
||||
ObiEditorUtils.DoToggleablePropertyGroup(aerodynamicsEnabled, new GUIContent("Aerodynamics", Resources.Load<Texture2D>("Icons/ObiAerodynamicConstraints Icon")),
|
||||
() => {
|
||||
EditorGUILayout.PropertyField(drag, new GUIContent("Drag"));
|
||||
EditorGUILayout.PropertyField(lift, new GUIContent("Lift"));
|
||||
});
|
||||
|
||||
ObiEditorUtils.DoToggleablePropertyGroup(chainConstraintsEnabled, new GUIContent("Chain Constraints", Resources.Load<Texture2D>("Icons/ObiChainConstraints Icon")),
|
||||
() => {
|
||||
EditorGUILayout.PropertyField(tightness, new GUIContent("Tightness"));
|
||||
|
||||
@@ -15,8 +15,27 @@ namespace Obi{
|
||||
public void OnEnable(){
|
||||
renderer = (ObiRopeChainRenderer)target;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI() {
|
||||
|
||||
[MenuItem("CONTEXT/ObiRopeChainRenderer/Bake mesh")]
|
||||
static void Bake(MenuCommand command)
|
||||
{
|
||||
ObiRopeChainRenderer renderer = (ObiRopeChainRenderer)command.context;
|
||||
|
||||
if (renderer.actor.isLoaded)
|
||||
{
|
||||
var system = renderer.actor.solver.GetRenderSystem<ObiRopeChainRenderer>() as ObiChainRopeRenderSystem;
|
||||
|
||||
if (system != null)
|
||||
{
|
||||
var mesh = new Mesh();
|
||||
system.BakeMesh(renderer, ref mesh, true);
|
||||
ObiEditorUtils.SaveMesh(mesh, "Save chain mesh", "chain mesh");
|
||||
GameObject.DestroyImmediate(mesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI() {
|
||||
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
|
||||
@@ -25,12 +44,7 @@ namespace Obi{
|
||||
// Apply changes to the serializedProperty
|
||||
if (GUI.changed){
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
renderer.ClearChainLinkInstances();
|
||||
renderer.CreateChainLinkInstances(renderer.GetComponent<ObiRopeBase>());
|
||||
renderer.UpdateRenderer(renderer.GetComponent<ObiRopeBase>());
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -65,17 +65,19 @@ namespace Obi
|
||||
private static void DrawGizmos(ObiRopeCursor cursor, GizmoType gizmoType)
|
||||
{
|
||||
var rope = cursor.GetComponent<ObiRope>();
|
||||
if (rope.solver != null)
|
||||
if (rope.isLoaded)
|
||||
{
|
||||
Gizmos.color = new Color(1, 0.5f, 0, 0.75f);
|
||||
Handles.matrix = rope.solver.transform.localToWorldMatrix;
|
||||
Handles.color = new Color(1, 0.5f, 0.2f, 1);
|
||||
|
||||
// draw source particle:
|
||||
int sourceIndex = cursor.sourceParticleIndex;
|
||||
|
||||
if (sourceIndex >= 0 && rope.IsParticleActive(rope.solver.particleToActor[sourceIndex].indexInActor))
|
||||
{
|
||||
Vector3 pos = rope.GetParticlePosition(sourceIndex);
|
||||
Gizmos.DrawWireSphere(pos, HandleUtility.GetHandleSize(pos) * 0.4f);
|
||||
Vector3 pos = rope.solver.positions[sourceIndex];
|
||||
float size = HandleUtility.GetHandleSize(pos) * 0.15f;
|
||||
Handles.SphereHandleCap(0, pos, Quaternion.identity, size, EventType.Repaint);
|
||||
}
|
||||
|
||||
// draw cursor:
|
||||
@@ -83,13 +85,12 @@ namespace Obi
|
||||
|
||||
if (element != null && element.particle1 != element.particle2)
|
||||
{
|
||||
Vector3 pos = rope.GetParticlePosition(cursor.direction ? element.particle1 : element.particle2);
|
||||
Vector3 pos2 = rope.GetParticlePosition(cursor.direction ? element.particle2 : element.particle1);
|
||||
Vector3 pos = rope.solver.positions[cursor.direction ? element.particle1 : element.particle2];
|
||||
Vector3 pos2 = rope.solver.positions[cursor.direction ? element.particle2 : element.particle1];
|
||||
Vector3 direction = pos2 - pos;
|
||||
|
||||
float size = HandleUtility.GetHandleSize(pos) * 0.4f;
|
||||
Gizmos.matrix = Matrix4x4.TRS(pos, Quaternion.LookRotation(direction), Vector3.one * size);
|
||||
DrawArrow();
|
||||
float size = HandleUtility.GetHandleSize(pos) * 0.25f;
|
||||
Handles.ConeHandleCap(0, pos + Vector3.Normalize(direction)*size*0.5f, Quaternion.LookRotation(direction), size, EventType.Repaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
using UnityEditor;
|
||||
using UnityEditor.EditorTools;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
@@ -18,6 +13,8 @@ namespace Obi
|
||||
static void CreateObiRope(MenuCommand menuCommand)
|
||||
{
|
||||
GameObject go = new GameObject("Obi Rope", typeof(ObiRope), typeof(ObiRopeExtrudedRenderer));
|
||||
var renderer = go.GetComponent<ObiRopeExtrudedRenderer>();
|
||||
renderer.material = ObiEditorUtils.GetDefaultMaterial();
|
||||
ObiEditorUtils.PlaceActorRoot(go, menuCommand);
|
||||
}
|
||||
|
||||
@@ -28,6 +25,7 @@ namespace Obi
|
||||
SerializedProperty collisionMaterial;
|
||||
SerializedProperty selfCollisions;
|
||||
SerializedProperty surfaceCollisions;
|
||||
SerializedProperty massScale;
|
||||
|
||||
SerializedProperty distanceConstraintsEnabled;
|
||||
SerializedProperty stretchingScale;
|
||||
@@ -40,6 +38,10 @@ namespace Obi
|
||||
SerializedProperty plasticYield;
|
||||
SerializedProperty plasticCreep;
|
||||
|
||||
SerializedProperty aerodynamicsEnabled;
|
||||
SerializedProperty drag;
|
||||
SerializedProperty lift;
|
||||
|
||||
SerializedProperty tearingEnabled;
|
||||
SerializedProperty tearResistanceMultiplier;
|
||||
SerializedProperty tearRate;
|
||||
@@ -55,6 +57,7 @@ namespace Obi
|
||||
collisionMaterial = serializedObject.FindProperty("m_CollisionMaterial");
|
||||
selfCollisions = serializedObject.FindProperty("m_SelfCollisions");
|
||||
surfaceCollisions = serializedObject.FindProperty("m_SurfaceCollisions");
|
||||
massScale = serializedObject.FindProperty("m_MassScale");
|
||||
|
||||
distanceConstraintsEnabled = serializedObject.FindProperty("_distanceConstraintsEnabled");
|
||||
stretchingScale = serializedObject.FindProperty("_stretchingScale");
|
||||
@@ -67,6 +70,10 @@ namespace Obi
|
||||
plasticYield = serializedObject.FindProperty("_plasticYield");
|
||||
plasticCreep = serializedObject.FindProperty("_plasticCreep");
|
||||
|
||||
aerodynamicsEnabled = serializedObject.FindProperty("_aerodynamicsEnabled");
|
||||
drag = serializedObject.FindProperty("_drag");
|
||||
lift = serializedObject.FindProperty("_lift");
|
||||
|
||||
tearingEnabled = serializedObject.FindProperty("tearingEnabled");
|
||||
tearResistanceMultiplier = serializedObject.FindProperty("tearResistanceMultiplier");
|
||||
tearRate = serializedObject.FindProperty("tearRate");
|
||||
@@ -112,8 +119,29 @@ namespace Obi
|
||||
|
||||
using (new EditorGUI.DisabledScope(ToolManager.activeToolType == typeof(ObiPathEditor)))
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
EditorGUILayout.PropertyField(ropeBlueprint, new GUIContent("Blueprint"));
|
||||
|
||||
if (actor.ropeBlueprint == null)
|
||||
{
|
||||
if (GUILayout.Button("Create", EditorStyles.miniButton, GUILayout.MaxWidth(80)))
|
||||
{
|
||||
string path = EditorUtility.SaveFilePanel("Save blueprint", "Assets/", "RopeBlueprint", "asset");
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
path = FileUtil.GetProjectRelativePath(path);
|
||||
ObiRopeBlueprint asset = ScriptableObject.CreateInstance<ObiRopeBlueprint>();
|
||||
|
||||
AssetDatabase.CreateAsset(asset, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
actor.ropeBlueprint = asset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
foreach (var t in targets)
|
||||
@@ -125,8 +153,14 @@ namespace Obi
|
||||
foreach (var t in targets)
|
||||
(t as ObiRope).AddToSolver();
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
GUI.enabled = !Application.isPlaying;
|
||||
EditorGUILayout.PropertyField(massScale, new GUIContent("Mass scale"));
|
||||
GUI.enabled = true;
|
||||
|
||||
DoEditButton();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
@@ -159,6 +193,11 @@ namespace Obi
|
||||
EditorGUILayout.PropertyField(plasticCreep, new GUIContent("Plastic creep"));
|
||||
});
|
||||
|
||||
ObiEditorUtils.DoToggleablePropertyGroup(aerodynamicsEnabled, new GUIContent("Aerodynamics", Resources.Load<Texture2D>("Icons/ObiAerodynamicConstraints Icon")),
|
||||
() => {
|
||||
EditorGUILayout.PropertyField(drag, new GUIContent("Drag"));
|
||||
EditorGUILayout.PropertyField(lift, new GUIContent("Lift"));
|
||||
});
|
||||
|
||||
if (GUI.changed)
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
@@ -16,22 +16,28 @@ namespace Obi{
|
||||
renderer = (ObiRopeExtrudedRenderer)target;
|
||||
}
|
||||
|
||||
private void BakeMesh()
|
||||
[MenuItem("CONTEXT/ObiRopeExtrudedRenderer/Bake mesh")]
|
||||
static void Bake(MenuCommand command)
|
||||
{
|
||||
if (renderer != null && renderer.extrudedMesh != null)
|
||||
ObiRopeExtrudedRenderer renderer = (ObiRopeExtrudedRenderer)command.context;
|
||||
|
||||
if (renderer.actor.isLoaded)
|
||||
{
|
||||
ObiEditorUtils.SaveMesh(renderer.extrudedMesh, "Save extruded mesh", "rope mesh");
|
||||
var system = renderer.actor.solver.GetRenderSystem<ObiRopeExtrudedRenderer>() as ObiExtrudedRopeRenderSystem;
|
||||
|
||||
if (system != null)
|
||||
{
|
||||
var mesh = new Mesh();
|
||||
system.BakeMesh(renderer, ref mesh, true);
|
||||
ObiEditorUtils.SaveMesh(mesh, "Save rope mesh", "rope mesh");
|
||||
GameObject.DestroyImmediate(mesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI() {
|
||||
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
|
||||
if (GUILayout.Button("BakeMesh"))
|
||||
{
|
||||
BakeMesh();
|
||||
}
|
||||
|
||||
Editor.DrawPropertiesExcluding(serializedObject,"m_Script");
|
||||
|
||||
@@ -40,8 +46,6 @@ namespace Obi{
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
renderer.UpdateRenderer(renderer.GetComponent<ObiRopeBase>());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Obi{
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
renderer.UpdateRenderer(null);
|
||||
//renderer.UpdateRenderer(null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi{
|
||||
|
||||
@@ -11,28 +8,34 @@ namespace Obi{
|
||||
{
|
||||
|
||||
ObiRopeMeshRenderer renderer;
|
||||
|
||||
public void OnEnable(){
|
||||
renderer = (ObiRopeMeshRenderer)target;
|
||||
}
|
||||
|
||||
private void BakeMesh()
|
||||
[MenuItem("CONTEXT/ObiRopeMeshRenderer/Bake mesh")]
|
||||
static void Bake(MenuCommand command)
|
||||
{
|
||||
if (renderer != null && renderer.deformedMesh != null)
|
||||
ObiRopeMeshRenderer renderer = (ObiRopeMeshRenderer)command.context;
|
||||
|
||||
if (renderer.actor.isLoaded)
|
||||
{
|
||||
ObiEditorUtils.SaveMesh(renderer.deformedMesh, "Save deformed mesh", "rope mesh");
|
||||
var system = renderer.actor.solver.GetRenderSystem<ObiRopeMeshRenderer>() as ObiMeshRopeRenderSystem;
|
||||
|
||||
if (system != null)
|
||||
{
|
||||
var mesh = new Mesh();
|
||||
system.BakeMesh(renderer, ref mesh, true);
|
||||
ObiEditorUtils.SaveMesh(mesh, "Save rope mesh", "rope mesh");
|
||||
GameObject.DestroyImmediate(mesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnEnable(){
|
||||
renderer = (ObiRopeMeshRenderer)target;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI() {
|
||||
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
|
||||
if (GUILayout.Button("BakeMesh"))
|
||||
{
|
||||
BakeMesh();
|
||||
}
|
||||
|
||||
Editor.DrawPropertiesExcluding(serializedObject,"m_Script");
|
||||
|
||||
// Apply changes to the serializedProperty
|
||||
@@ -40,8 +43,6 @@ namespace Obi{
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
renderer.UpdateRenderer(renderer.GetComponent<ObiRopeBase>());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
8
Assets/Obi/Editor/RopeAndRod/Utils.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 72e3dd3ad91bf485099095b5e59ff81b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
169
Assets/Obi/Editor/RopeAndRod/Utils/ObiPinholeEditor.cs
Normal file
@@ -0,0 +1,169 @@
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
[CustomEditor(typeof(ObiPinhole))]
|
||||
public class ObiPinholeEditor : Editor
|
||||
{
|
||||
|
||||
SerializedProperty targetTransform;
|
||||
SerializedProperty position;
|
||||
SerializedProperty limitRange;
|
||||
SerializedProperty range;
|
||||
SerializedProperty compliance;
|
||||
SerializedProperty friction;
|
||||
SerializedProperty motorSpeed;
|
||||
SerializedProperty motorForce;
|
||||
SerializedProperty clamp;
|
||||
SerializedProperty breakThreshold;
|
||||
|
||||
ObiPinhole pinhole;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
|
||||
pinhole = target as ObiPinhole;
|
||||
targetTransform = serializedObject.FindProperty("m_Target");
|
||||
position = serializedObject.FindProperty("m_Position");
|
||||
limitRange = serializedObject.FindProperty("m_LimitRange");
|
||||
range = serializedObject.FindProperty("m_Range");
|
||||
friction = serializedObject.FindProperty("m_Friction");
|
||||
motorSpeed = serializedObject.FindProperty("m_MotorSpeed");
|
||||
motorForce = serializedObject.FindProperty("m_MotorForce");
|
||||
compliance = serializedObject.FindProperty("m_Compliance");
|
||||
clamp = serializedObject.FindProperty("m_ClampAtEnds");
|
||||
breakThreshold = serializedObject.FindProperty("breakThreshold");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
|
||||
// warn about incorrect setups:
|
||||
if (!targetTransform.hasMultipleDifferentValues)
|
||||
{
|
||||
var targetValue = targetTransform.objectReferenceValue as UnityEngine.Component;
|
||||
if (targetValue != null)
|
||||
{
|
||||
var collider = targetValue.GetComponent<ObiColliderBase>();
|
||||
if (collider == null)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Pinholes require the target object to have a ObiCollider component. Please add one.", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
Transform trget = EditorGUILayout.ObjectField("Target", pinhole.target, typeof(Transform), true) as Transform;
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(pinhole, "Set target");
|
||||
pinhole.target = trget;
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(pinhole);
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(position, new GUIContent("Position"));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
pinhole.CalculateMu();
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(limitRange, new GUIContent("Limit Range"));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
pinhole.CalculateRange();
|
||||
}
|
||||
|
||||
if (limitRange.boolValue)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(range, new GUIContent("Range"));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
pinhole.CalculateRange();
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
EditorGUILayout.PropertyField(clamp, new GUIContent("Clamp at ends"));
|
||||
EditorGUILayout.PropertyField(friction, new GUIContent("Friction"));
|
||||
EditorGUILayout.PropertyField(motorSpeed, new GUIContent("Motor Target Speed"));
|
||||
EditorGUILayout.PropertyField(motorForce, new GUIContent("Motor Max Force"));
|
||||
EditorGUILayout.PropertyField(compliance, new GUIContent("Compliance"));
|
||||
EditorGUILayout.PropertyField(breakThreshold, new GUIContent("Break threshold"));
|
||||
|
||||
if (GUI.changed)
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.Selected)]
|
||||
private static void DrawGizmos(ObiPinhole pinhole, GizmoType gizmoType)
|
||||
{
|
||||
var rope = pinhole.GetComponent<ObiRope>();
|
||||
|
||||
var ropeBlueprint = rope.sharedBlueprint as ObiRopeBlueprintBase;
|
||||
if (rope.isLoaded && ropeBlueprint != null && ropeBlueprint.deformableEdges != null)
|
||||
{
|
||||
Handles.color = new Color(1, 0.5f, 0.2f, 1);
|
||||
Handles.matrix = rope.solver.transform.localToWorldMatrix;
|
||||
|
||||
// draw limits:
|
||||
if (pinhole.limitRange)
|
||||
{
|
||||
for (int i = pinhole.firstEdge.edgeIndex; i <= pinhole.lastEdge.edgeIndex; ++i)
|
||||
{
|
||||
if (i >= 0 && i < ropeBlueprint.deformableEdges.Length)
|
||||
{
|
||||
int p1 = ropeBlueprint.deformableEdges[i * 2];
|
||||
int p2 = ropeBlueprint.deformableEdges[i * 2 + 1];
|
||||
var pos1 = rope.solver.positions[rope.solverIndices[p1]];
|
||||
var pos2 = rope.solver.positions[rope.solverIndices[p2]];
|
||||
|
||||
if (i == pinhole.firstEdge.edgeIndex)
|
||||
{
|
||||
pos1 = Vector4.Lerp(pos1, pos2, pinhole.firstEdge.coordinate);
|
||||
Handles.DrawSolidDisc(pos1, pos2 - pos1, HandleUtility.GetHandleSize(pos1) * 0.05f);
|
||||
}
|
||||
if (i == pinhole.lastEdge.edgeIndex)
|
||||
{
|
||||
pos2 = Vector4.Lerp(pos1, pos2, pinhole.lastEdge.coordinate);
|
||||
Handles.DrawSolidDisc(pos2, pos1 - pos2, HandleUtility.GetHandleSize(pos2) * 0.05f);
|
||||
}
|
||||
|
||||
Handles.DrawLine(pos1, pos2, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draw source particle:
|
||||
int edgeIndex = pinhole.edgeIndex;
|
||||
|
||||
if (edgeIndex >= 0 && edgeIndex < ropeBlueprint.deformableEdges.Length)
|
||||
{
|
||||
int p1 = ropeBlueprint.deformableEdges[edgeIndex * 2];
|
||||
int p2 = ropeBlueprint.deformableEdges[edgeIndex * 2 + 1];
|
||||
var pos1 = rope.solver.positions[rope.solverIndices[p1]];
|
||||
var pos2 = rope.solver.positions[rope.solverIndices[p2]];
|
||||
Vector4 pos = Vector4.Lerp(pos1, pos2, pinhole.edgeCoordinate);
|
||||
Handles.DrawWireDisc(pos, pos1 - pos2, HandleUtility.GetHandleSize(pos) * 0.1f, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
11
Assets/Obi/Editor/RopeAndRod/Utils/ObiPinholeEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f58defb5faddb428ea91cd06eecd8729
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||