1028 lines
45 KiB
C#
1028 lines
45 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
using UnityEditor.SceneManagement;
|
|
using RayFire;
|
|
|
|
namespace RayFireEditor
|
|
{
|
|
[CanEditMultipleObjects]
|
|
[CustomEditor (typeof(RayfireConnectivity))]
|
|
public class RayfireConnectivityEditor : Editor
|
|
{
|
|
RayfireConnectivity conn;
|
|
static readonly Color stressColor = Color.green;
|
|
|
|
// Foldout
|
|
static bool fld_filters;
|
|
static bool fld_props_clp;
|
|
static bool fld_props_str;
|
|
static bool fld_joints;
|
|
|
|
// Minimum & Maximum ranges
|
|
const float expand_min = 0;
|
|
const float expand_max = 1f;
|
|
const float minimumArea_min = 0;
|
|
const float minimumArea_max = 1f;
|
|
const float minimumSize_min = 0;
|
|
const float minimumSize_max = 10f;
|
|
const int percentage_min = 0;
|
|
const int percentage_max = 100;
|
|
const int seed_min = 0;
|
|
const int seed_max = 100;
|
|
const int sub_thr_min = 10;
|
|
const int sub_thr_max = 999;
|
|
const int sub_cls_min = 2;
|
|
const int sub_cls_max = 99;
|
|
const int sub_deb_min = 0;
|
|
const int sub_deb_max = 60;
|
|
const int integrity_min = 1;
|
|
const int integrity_max = 99;
|
|
const int start_min = 0;
|
|
const int start_max = 99;
|
|
const int end_min = 1;
|
|
const int end_max = 100;
|
|
const int steps_min = 1;
|
|
const int steps_max = 100;
|
|
const float duration_min = 0;
|
|
const float duration_max = 60f;
|
|
const int var_min = 0;
|
|
const int var_max = 100;
|
|
const int seed_clp_min = 0;
|
|
const int seed_clp_max = 99;
|
|
const int threshold_min = 1;
|
|
const int threshold_max = 1000;
|
|
const float erosion_min = 0;
|
|
const float erosion_max = 10f;
|
|
const float interval_min = 0.1f;
|
|
const float interval_max = 10f;
|
|
const int support_min = 0;
|
|
const int support_max = 90;
|
|
const int debris_min = 0;
|
|
const int debris_max = 50;
|
|
|
|
// Connectivity Serialized properties
|
|
SerializedProperty sp_show_giz;
|
|
SerializedProperty sp_show_con;
|
|
SerializedProperty sp_show_nod;
|
|
SerializedProperty sp_type;
|
|
SerializedProperty sp_expand;
|
|
SerializedProperty sp_minimumArea;
|
|
SerializedProperty sp_minimumSize;
|
|
SerializedProperty sp_percentage;
|
|
SerializedProperty sp_seed;
|
|
SerializedProperty sp_clusterize;
|
|
SerializedProperty sp_sub_enable;
|
|
SerializedProperty sp_sub_thr;
|
|
SerializedProperty sp_sub_min;
|
|
SerializedProperty sp_sub_max;
|
|
SerializedProperty sp_sub_deb;
|
|
SerializedProperty sp_demolishable;
|
|
SerializedProperty sp_triggerCollider;
|
|
SerializedProperty sp_triggerDebris;
|
|
|
|
// Collapse Serialized properties
|
|
SerializedProperty sp_startCollapse;
|
|
SerializedProperty sp_clp_integrity;
|
|
SerializedProperty sp_clp_type;
|
|
SerializedProperty sp_start;
|
|
SerializedProperty sp_end;
|
|
SerializedProperty sp_steps;
|
|
SerializedProperty sp_duration;
|
|
SerializedProperty sp_var;
|
|
SerializedProperty sp_clp_seed;
|
|
|
|
// Stress Serialized properties
|
|
SerializedProperty sp_showStress;
|
|
SerializedProperty sp_startStress;
|
|
SerializedProperty sp_str_integrity;
|
|
SerializedProperty sp_enable;
|
|
SerializedProperty sp_threshold;
|
|
SerializedProperty sp_erosion;
|
|
SerializedProperty sp_interval;
|
|
SerializedProperty sp_support;
|
|
SerializedProperty sp_exposed;
|
|
SerializedProperty sp_bySize;
|
|
|
|
void OnEnable()
|
|
{
|
|
// Get component
|
|
conn = (RayfireConnectivity)target;
|
|
|
|
// Find Connectivity properties
|
|
sp_show_giz = serializedObject.FindProperty(nameof(conn.showGizmo));
|
|
sp_show_con = serializedObject.FindProperty(nameof(conn.showConnections));
|
|
sp_show_nod = serializedObject.FindProperty(nameof(conn.showNodes));
|
|
sp_type = serializedObject.FindProperty(nameof(conn.type));
|
|
sp_expand = serializedObject.FindProperty(nameof(conn.expand));
|
|
sp_minimumArea = serializedObject.FindProperty(nameof(conn.minimumArea));
|
|
sp_minimumSize = serializedObject.FindProperty(nameof(conn.minimumSize));
|
|
sp_percentage = serializedObject.FindProperty(nameof(conn.percentage));
|
|
sp_seed = serializedObject.FindProperty(nameof(conn.seed));
|
|
sp_clusterize = serializedObject.FindProperty(nameof(conn.clusterize));
|
|
sp_sub_enable = serializedObject.FindProperty(nameof(conn.subEnable));
|
|
sp_sub_thr = serializedObject.FindProperty(nameof(conn.subThr));
|
|
sp_sub_min = serializedObject.FindProperty(nameof(conn.subMin));
|
|
sp_sub_max = serializedObject.FindProperty(nameof(conn.subMax));
|
|
sp_sub_deb = serializedObject.FindProperty(nameof(conn.subDeb));
|
|
sp_demolishable = serializedObject.FindProperty(nameof(conn.demolishable));
|
|
sp_triggerCollider = serializedObject.FindProperty(nameof(conn.triggerCollider));
|
|
sp_triggerDebris = serializedObject.FindProperty(nameof(conn.triggerDebris));
|
|
|
|
// Find Collapse properties
|
|
sp_startCollapse = serializedObject.FindProperty(nameof(conn.startCollapse));
|
|
sp_clp_integrity = serializedObject.FindProperty(nameof(conn.collapseByIntegrity));
|
|
sp_clp_type = serializedObject.FindProperty(nameof(conn.collapse) + "." + nameof(conn.collapse.type));
|
|
sp_start = serializedObject.FindProperty(nameof(conn.collapse) + "." + nameof(conn.collapse.start));
|
|
sp_end = serializedObject.FindProperty(nameof(conn.collapse) + "." + nameof(conn.collapse.end));
|
|
sp_steps = serializedObject.FindProperty(nameof(conn.collapse) + "." + nameof(conn.collapse.steps));
|
|
sp_duration = serializedObject.FindProperty(nameof(conn.collapse) + "." + nameof(conn.collapse.duration));
|
|
sp_var = serializedObject.FindProperty(nameof(conn.collapse) + "." + nameof(conn.collapse.var));
|
|
sp_clp_seed = serializedObject.FindProperty(nameof(conn.collapse) + "." + nameof(conn.collapse.seed));
|
|
|
|
// Find Stress properties
|
|
sp_showStress = serializedObject.FindProperty(nameof(conn.showStress));
|
|
sp_startStress = serializedObject.FindProperty(nameof(conn.startStress));
|
|
sp_str_integrity = serializedObject.FindProperty(nameof(conn.stressByIntegrity));
|
|
sp_enable = serializedObject.FindProperty(nameof(conn.stress) + "." + nameof(conn.stress.enable));
|
|
sp_threshold = serializedObject.FindProperty(nameof(conn.stress) + "." + nameof(conn.stress.threshold));
|
|
sp_erosion = serializedObject.FindProperty(nameof(conn.stress) + "." + nameof(conn.stress.erosion));
|
|
sp_interval = serializedObject.FindProperty(nameof(conn.stress) + "." + nameof(conn.stress.interval));
|
|
sp_support = serializedObject.FindProperty(nameof(conn.stress) + "." + nameof(conn.stress.support));
|
|
sp_exposed = serializedObject.FindProperty(nameof(conn.stress) + "." + nameof(conn.stress.exposed));
|
|
sp_bySize = serializedObject.FindProperty(nameof(conn.stress) + "." + nameof(conn.stress.bySize));
|
|
|
|
// Foldouts
|
|
if (EditorPrefs.HasKey (TextKeys.con_fld_flt) == true) fld_filters = EditorPrefs.GetBool (TextKeys.con_fld_flt);
|
|
if (EditorPrefs.HasKey (TextKeys.con_fld_clp) == true) fld_props_clp = EditorPrefs.GetBool (TextKeys.con_fld_clp);
|
|
if (EditorPrefs.HasKey (TextKeys.con_fld_str) == true) fld_props_str = EditorPrefs.GetBool (TextKeys.con_fld_str);
|
|
if (EditorPrefs.HasKey (TextKeys.con_fld_jnt) == true) fld_joints = EditorPrefs.GetBool (TextKeys.con_fld_jnt);
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Inspector
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
// Update changed properties
|
|
serializedObject.Update();
|
|
|
|
GUI_Preview();
|
|
GUI_Info();
|
|
GUI_Connectivity();
|
|
|
|
if (conn.joints.enable == false)
|
|
{
|
|
GUI_Cluster();
|
|
GUI_Collapse();
|
|
GUI_Stress();
|
|
GUI_Trigger();
|
|
}
|
|
|
|
// TODO update
|
|
UI_Joints();
|
|
|
|
// Apply changes
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Top
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
void GUI_Preview()
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
GUICommon.Toggle (sp_show_giz, TextCnt.gui_btn_gizmo);
|
|
EditorGUILayout.BeginHorizontal();
|
|
GUICommon.Toggle (sp_show_con, TextCnt.gui_btn_cnt);
|
|
GUICommon.Toggle (sp_show_nod,TextCnt.gui_btn_nodes);
|
|
EditorGUILayout.EndHorizontal();
|
|
if (EditorGUI.EndChangeCheck())
|
|
SceneView.RepaintAll();
|
|
}
|
|
|
|
void GUI_Info()
|
|
{
|
|
if (conn.cluster.shards.Count > 0)
|
|
{
|
|
GUICommon.Space();
|
|
GUILayout.Label (TextCnt.str_setup, EditorStyles.boldLabel);
|
|
GUICommon.Space();
|
|
GUILayout.Label (TextCnt.str_shards + conn.cluster.shards.Count + "/" + conn.initShardAmount);
|
|
GUICommon.Space ();
|
|
GUILayout.Label (TextCnt.str_amount + conn.AmountIntegrity + "%");
|
|
GUICommon.Space ();
|
|
}
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Connectivity
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
void GUI_Connectivity ()
|
|
{
|
|
GUICommon.CaptionBox (TextCnt.gui_cap_conn);
|
|
GUICommon.PropertyField (sp_type, TextCnt.gui_type);
|
|
if (conn.type != ConnectivityType.ByTriangles && conn.type != ConnectivityType.ByPolygons)
|
|
GUICommon.Slider (sp_expand, expand_min, expand_max, TextCnt.gui_expand);
|
|
GUICommon.Foldout (ref fld_filters, TextKeys.con_fld_flt, TextCnt.gui_fld_filters.text);
|
|
if (fld_filters == true)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
if (conn.type != ConnectivityType.ByBoundingBox)
|
|
GUICommon.Slider (sp_minimumArea, minimumArea_min, minimumArea_max, TextCnt.gui_minimumArea);
|
|
GUICommon.Slider (sp_minimumSize, minimumSize_min, minimumSize_max, TextCnt.gui_minimumSize);
|
|
GUICommon.IntSlider (sp_percentage, percentage_min, percentage_max, TextCnt.gui_percentage);
|
|
if (conn.percentage > 0)
|
|
GUICommon.IntSlider (sp_seed, seed_min, seed_max, TextCnt.gui_seed);
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Cluster
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
void GUI_Cluster()
|
|
{
|
|
GUICommon.CaptionBox (TextCnt.gui_cap_cluster);
|
|
GUICommon.PropertyField (sp_clusterize, TextCnt.gui_clusterize);
|
|
if (conn.clusterize == true)
|
|
{
|
|
GUICommon.PropertyField (sp_sub_enable, TextCnt.gui_sub_enable);
|
|
if (conn.subEnable == true)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
GUICommon.IntSlider (sp_sub_thr, sub_thr_min, sub_thr_max, TextCnt.gui_sub_thr);
|
|
GUICommon.IntSlider (sp_sub_min, sub_cls_min, sub_cls_max, TextCnt.gui_sub_min);
|
|
GUICommon.IntSlider (sp_sub_max, sub_cls_min, sub_cls_max, TextCnt.gui_sub_max);
|
|
GUICommon.IntSlider (sp_sub_deb, sub_deb_min, sub_deb_max, TextCnt.gui_sub_deb);
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
GUICommon.PropertyField (sp_demolishable, TextCnt.gui_demolishable);
|
|
}
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Collapse
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
void GUI_Collapse()
|
|
{
|
|
GUICommon.CaptionBox (TextCnt.gui_cap_collapse);
|
|
GUICommon.PropertyField (sp_startCollapse, TextCnt.gui_startCollapse);
|
|
if (conn.startCollapse == RayfireConnectivity.RFConnInitType.ByIntegrity)
|
|
GUICommon.IntSlider (sp_clp_integrity, integrity_min, integrity_max, TextCnt.gui_integrity);
|
|
GUICommon.Foldout (ref fld_props_clp, TextKeys.con_fld_clp, TextCnt.gui_fld_props.text);
|
|
if (fld_props_clp == true)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
GUICommon.PropertyField (sp_clp_type, TextClp.gui_type);
|
|
GUICommon.IntSlider (sp_start, start_min, start_max, TextClp.gui_start);
|
|
GUICommon.IntSlider (sp_end, end_min, end_max, TextClp.gui_end);
|
|
GUICommon.IntSlider (sp_steps, steps_min, steps_max, TextClp.gui_steps);
|
|
GUICommon.Slider (sp_duration, duration_min, duration_max, TextClp.gui_duration);
|
|
if (conn.collapse.type != RFCollapse.RFCollapseType.Random)
|
|
GUICommon.IntSlider (sp_var, var_min, var_max, TextClp.gui_var);
|
|
GUICommon.IntSlider (sp_clp_seed, seed_clp_min, seed_clp_max, TextClp.gui_seed);
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
GUI_Collapse_Buttons();
|
|
GUI_Collapse_Sliders();
|
|
}
|
|
|
|
void GUI_Collapse_Buttons()
|
|
{
|
|
// Only runtime
|
|
if (Application.isPlaying == false)
|
|
return;
|
|
|
|
GUICommon.Space ();
|
|
|
|
// Show start collapse if not Start by default
|
|
if (conn.collapse.inProgress == false)
|
|
{
|
|
if (GUILayout.Button (TextCnt.gui_btn_clp_start, GUILayout.Height (25)))
|
|
foreach (var targ in targets)
|
|
if (targ as RayfireConnectivity != null)
|
|
RFCollapse.StartCollapse (targ as RayfireConnectivity);
|
|
}
|
|
|
|
// Show stop collapse if not Start by default
|
|
if (conn.collapse.inProgress == true)
|
|
{
|
|
if (GUILayout.Button (TextCnt.gui_btn_clp_stop, GUILayout.Height (25)))
|
|
foreach (var targ in targets)
|
|
if (targ as RayfireConnectivity != null)
|
|
RFCollapse.StopCollapse (targ as RayfireConnectivity);
|
|
}
|
|
}
|
|
|
|
void GUI_Collapse_Sliders()
|
|
{
|
|
// Only runtime
|
|
if (Application.isPlaying == false)
|
|
return;
|
|
|
|
GUICommon.Space ();
|
|
|
|
GUILayout.BeginHorizontal();
|
|
|
|
GUILayout.Label (TextClp.str_area, GUILayout.Width (55));
|
|
|
|
// Start check for slider change
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.cluster.areaCollapse = EditorGUILayout.Slider(conn.cluster.areaCollapse, conn.cluster.minimumArea, conn.cluster.maximumArea);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
RFCollapse.AreaCollapse (conn, conn.cluster.areaCollapse);
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
GUICommon.Space ();
|
|
|
|
GUILayout.BeginHorizontal();
|
|
|
|
GUILayout.Label (TextClp.str_size, GUILayout.Width (55));
|
|
|
|
// Start check for slider change
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.cluster.sizeCollapse = EditorGUILayout.Slider(conn.cluster.sizeCollapse, conn.cluster.minimumSize, conn.cluster.maximumSize);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
RFCollapse.SizeCollapse (conn, conn.cluster.sizeCollapse);
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
GUICommon.Space ();
|
|
|
|
GUILayout.BeginHorizontal();
|
|
|
|
GUILayout.Label (TextClp.str_rand, GUILayout.Width (55));
|
|
|
|
// Start check for slider change
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.cluster.randomCollapse = EditorGUILayout.IntSlider(conn.cluster.randomCollapse, 0, 100);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
RFCollapse.RandomCollapse (conn, conn.cluster.randomCollapse);
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Stress
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
void GUI_Stress()
|
|
{
|
|
GUICommon.CaptionBox (TextCnt.gui_cap_stress);
|
|
GUICommon.PropertyField (sp_enable, TextStr.gui_enable);
|
|
if (conn.stress.enable == true)
|
|
{
|
|
GUICommon.PropertyField (sp_showStress, TextCnt.gui_showStress);
|
|
GUICommon.PropertyField (sp_startStress, TextCnt.gui_startStress);
|
|
if (conn.startStress == RayfireConnectivity.RFConnInitType.ByIntegrity)
|
|
GUICommon.IntSlider (sp_str_integrity, integrity_min, integrity_max, TextCnt.gui_integrity);
|
|
GUICommon.Foldout (ref fld_props_str, TextKeys.con_fld_str, TextCnt.gui_fld_props.text);
|
|
if (fld_props_str == true)
|
|
GUI_Stress_Properties();
|
|
GUI_Stress_Buttons();
|
|
}
|
|
}
|
|
|
|
void GUI_Stress_Properties()
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
GUICommon.Caption (TextStr.gui_cap_conn);
|
|
GUICommon.IntSlider (sp_threshold, threshold_min, threshold_max, TextStr.gui_threshold);
|
|
GUICommon.Slider (sp_erosion, erosion_min, erosion_max, TextStr.gui_erosion);
|
|
GUICommon.Slider (sp_interval, interval_min, interval_max, TextStr.gui_interval);
|
|
GUICommon.Caption (TextStr.gui_cap_shards);
|
|
GUICommon.IntSlider (sp_support, support_min, support_max, TextStr.gui_support);
|
|
GUICommon.PropertyField (sp_exposed, TextStr.gui_exposed);
|
|
GUICommon.PropertyField (sp_bySize, TextStr.gui_bySize);
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
void GUI_Stress_Buttons()
|
|
{
|
|
if (Application.isPlaying == true)
|
|
{
|
|
GUICommon.Space();
|
|
|
|
// Show start stress if not Start by default
|
|
if (conn.stress.inProgress == false)
|
|
{
|
|
if (GUILayout.Button (TextCnt.gui_btn_str_start, GUILayout.Height (25)))
|
|
foreach (var targ in targets)
|
|
if (targ as RayfireConnectivity != null)
|
|
RFStress.StartStress (targ as RayfireConnectivity);
|
|
}
|
|
|
|
// Show stop collapse if not Start by default
|
|
if (conn.stress.inProgress == true)
|
|
{
|
|
if (GUILayout.Button (TextCnt.gui_btn_str_stop, GUILayout.Height (25)))
|
|
foreach (var targ in targets)
|
|
if (targ as RayfireConnectivity != null)
|
|
RFStress.StopStress (targ as RayfireConnectivity);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Trigger
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
// TODO update
|
|
void GUI_Trigger()
|
|
{
|
|
GUICommon.CaptionBox (TextCnt.gui_cap_fracture);
|
|
GUICommon.PropertyField (sp_triggerCollider, TextCnt.gui_triggerCollider);
|
|
if (conn.clusterize == true)
|
|
GUICommon.IntSlider (sp_triggerDebris, debris_min, debris_max, TextCnt.gui_triggerDebris);
|
|
|
|
if (Application.isPlaying == true && conn.triggerCollider != null)
|
|
{
|
|
GUICommon.Space ();
|
|
if (GUILayout.Button (TextCnt.gui_btn_fracture, GUILayout.Height (25)))
|
|
if (Application.isPlaying == true)
|
|
conn.Fracture (conn.triggerCollider, conn.triggerDebris);
|
|
}
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Joints
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
void UI_Joints()
|
|
{
|
|
GUICommon.CaptionBox (TextCnt.gui_cap_joint);
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
bool enable = EditorGUILayout.Toggle ("Enable", conn.joints.enable);
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
Undo.RecordObjects (targets, "Enable");
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.enable = enable;
|
|
SetDirty (scr);
|
|
}
|
|
}
|
|
|
|
if (conn.joints.enable == true)
|
|
{
|
|
GUICommon.Space ();
|
|
|
|
//exp_joints = EditorGUILayout.Foldout (exp_joints, "Properties", true);
|
|
//if (exp_joints == true)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
|
|
GUILayout.Label (" Break", EditorStyles.boldLabel);
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.breakType = (RFJointProperties.RFJointBreakType)EditorGUILayout.EnumPopup ("Type", conn.joints.breakType);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.breakType = conn.joints.breakType;
|
|
SetDirty (scr);
|
|
}
|
|
|
|
GUICommon.Space ();
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.breakForce = EditorGUILayout.IntSlider ("Force", conn.joints.breakForce, 0, 5000);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.breakForce = conn.joints.breakForce;
|
|
SetDirty (scr);
|
|
|
|
if (Application.isPlaying == true)
|
|
RFJointProperties.SetBreakForce (scr.joints.breakForce, scr.joints.breakForceVar, scr.joints.jointList, scr.joints.forceByMass);
|
|
}
|
|
|
|
GUICommon.Space ();
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.breakForceVar = EditorGUILayout.IntSlider ("Variation", conn.joints.breakForceVar, 0, 100);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.breakForceVar = conn.joints.breakForceVar;
|
|
SetDirty (scr);
|
|
|
|
if (Application.isPlaying == true)
|
|
RFJointProperties.SetBreakForce (scr.joints.breakForce, scr.joints.breakForceVar, scr.joints.jointList, scr.joints.forceByMass);
|
|
}
|
|
|
|
GUICommon.Space ();
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.forceByMass = EditorGUILayout.Toggle ("Force By Mass", conn.joints.forceByMass);
|
|
if (EditorGUI.EndChangeCheck())
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.forceByMass = conn.joints.forceByMass;
|
|
SetDirty (scr);
|
|
}
|
|
|
|
GUICommon.Space ();
|
|
|
|
GUILayout.Label (" Angular", EditorStyles.boldLabel);
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.angleLimit = EditorGUILayout.IntSlider ("Limit", conn.joints.angleLimit, 0, 50);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.angleLimit = conn.joints.angleLimit;
|
|
SetDirty (scr);
|
|
|
|
if (Application.isPlaying == true)
|
|
RFJointProperties.SetAngularMotion (scr.joints.angleLimit, scr.joints.angleLimitVar, scr.joints.jointList);
|
|
}
|
|
|
|
GUICommon.Space ();
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.angleLimitVar = EditorGUILayout.IntSlider ("Variation", conn.joints.angleLimitVar, 0, 100);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.angleLimitVar = conn.joints.angleLimitVar;
|
|
SetDirty (scr);
|
|
|
|
if (Application.isPlaying == true)
|
|
RFJointProperties.SetAngularMotion (scr.joints.angleLimit, scr.joints.angleLimitVar, scr.joints.jointList);
|
|
}
|
|
|
|
GUICommon.Space ();
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.damper = EditorGUILayout.IntSlider ("Damper", conn.joints.damper, 0, 10000);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.damper = conn.joints.damper;
|
|
SetDirty (scr);
|
|
|
|
if (Application.isPlaying == true)
|
|
RFJointProperties.SetSpring (scr.joints.damper, scr.joints.jointList);
|
|
}
|
|
|
|
GUICommon.Space ();
|
|
|
|
GUILayout.Label (" Deformation", EditorStyles.boldLabel);
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.deformEnable = EditorGUILayout.Toggle ("Enable", conn.joints.deformEnable);
|
|
if (EditorGUI.EndChangeCheck())
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.deformEnable = conn.joints.deformEnable;
|
|
SetDirty (scr);
|
|
}
|
|
|
|
if (conn.joints.deformEnable == true)
|
|
{
|
|
GUICommon.Space ();
|
|
|
|
// Stiffness
|
|
if (conn.joints.breakType == RFJointProperties.RFJointBreakType.Breakable)
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.stiffFrc = EditorGUILayout.Slider ("Stiffness", conn.joints.stiffFrc, 0.05f, 0.95f);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.stiffFrc = conn.joints.stiffFrc;
|
|
SetDirty (scr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.stiffAbs = EditorGUILayout.IntSlider ("Stiffness", conn.joints.stiffAbs, 1, 500);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.stiffAbs = conn.joints.stiffAbs;
|
|
SetDirty (scr);
|
|
}
|
|
}
|
|
|
|
GUICommon.Space ();
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.bend = EditorGUILayout.IntSlider ("Bending", conn.joints.bend, 0, 10);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.bend = conn.joints.bend;
|
|
SetDirty (scr);
|
|
}
|
|
|
|
GUICommon.Space ();
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.weakening = EditorGUILayout.Slider ("Weakening", conn.joints.weakening, 0, 0.9f);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.weakening = conn.joints.weakening;
|
|
SetDirty (scr);
|
|
}
|
|
|
|
GUICommon.Space ();
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.percentage = EditorGUILayout.IntSlider ("Percentage", conn.joints.percentage, 1, 100);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.percentage = conn.joints.percentage;
|
|
SetDirty (scr);
|
|
}
|
|
|
|
GUICommon.Space ();
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
conn.joints.deformCount = EditorGUILayout.IntSlider ("Iterations", conn.joints.deformCount, 1, 100);
|
|
if (EditorGUI.EndChangeCheck() == true)
|
|
foreach (RayfireConnectivity scr in targets)
|
|
{
|
|
scr.joints.deformCount = conn.joints.deformCount;
|
|
SetDirty (scr);
|
|
}
|
|
|
|
if (conn.joints.HasDeforms == true)
|
|
{
|
|
GUICommon.Space ();
|
|
GUILayout.Label ("Deformable joints: " + conn.joints.deformList.Count + "/" + conn.joints.jointList.Count);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GUILayout.Label ("CurrentForce");
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Draw
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
// Draw Connections and Nodes by act and uny states
|
|
static void ClusterDraw(RFCluster cluster, bool showNodes, bool showConnections)
|
|
{
|
|
if (showNodes == true || showConnections == true)
|
|
{
|
|
if (cluster != null && cluster.shards.Count > 0)
|
|
{
|
|
for (int i = 0; i < cluster.shards.Count; i++)
|
|
{
|
|
if (cluster.shards[i].tm != null)
|
|
{
|
|
// Color
|
|
if (cluster.shards[i].rigid == null)
|
|
SetColor (cluster.shards[i].uny, cluster.shards[i].act);
|
|
else
|
|
{
|
|
if (cluster.shards[i].rigid.objTp == ObjectType.Mesh)
|
|
SetColor (cluster.shards[i].rigid.activation.uny, cluster.shards[i].rigid.activation.atb);
|
|
else if (cluster.shards[i].rigid.objTp == ObjectType.MeshRoot ||
|
|
cluster.shards[i].rigid.objTp == ObjectType.ConnectedCluster)
|
|
SetColor (cluster.shards[i].uny, cluster.shards[i].act);
|
|
}
|
|
|
|
// Nodes
|
|
if (showNodes == true)
|
|
Gizmos.DrawWireSphere (cluster.shards[i].tm.position, cluster.shards[i].sz / 12f);
|
|
|
|
// Connection
|
|
if (showConnections == true)
|
|
{
|
|
//Debug.Log (cluster.shards[i].nIds.Count);
|
|
|
|
// Has no neibs
|
|
if (cluster.shards[i].nIds.Count == 0)
|
|
continue;
|
|
|
|
// Shard has neibs but neib shards not initialized by nIds
|
|
if (cluster.shards[i].neibShards == null)
|
|
cluster.shards[i].neibShards = new List<RFShard>();
|
|
|
|
// Reinit
|
|
if (cluster.shards[i].neibShards.Count == 0)
|
|
for (int n = 0; n < cluster.shards[i].nIds.Count; n++)
|
|
cluster.shards[i].neibShards.Add (cluster.shards[cluster.shards[i].nIds[n]]);
|
|
|
|
// Preview
|
|
for (int j = 0; j < cluster.shards[i].neibShards.Count; j++)
|
|
if (cluster.shards[i].neibShards[j].tm != null)
|
|
{
|
|
Gizmos.DrawLine (cluster.shards[i].tm.position,
|
|
(cluster.shards[i].neibShards[j].tm.position - cluster.shards[i].tm.position) / 2f + cluster.shards[i].tm.position);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Draw stressed connections
|
|
static void StressDraw (RayfireConnectivity targ)
|
|
{
|
|
if (targ.showStress == true && targ.stress != null && targ.stress.inProgress == true)
|
|
{
|
|
if (targ.cluster != null && targ.cluster.shards.Count > 0)
|
|
{
|
|
Vector3 pos;
|
|
for (int i = 0; i < targ.cluster.shards.Count; i++)
|
|
{
|
|
if (targ.cluster.shards[i].tm != null)
|
|
{
|
|
// Show Path stress
|
|
/*
|
|
if (false)
|
|
if (targ.stress.bySize == true)
|
|
{
|
|
Gizmos.color = ColorByValue (stressColor, targ.cluster.shards[i].sSt, 1f);
|
|
Gizmos.DrawWireSphere (targ.cluster.shards[i].tm.position, targ.cluster.shards[i].sz / 12f);
|
|
}
|
|
*/
|
|
|
|
if (targ.cluster.shards[i].StressState == true)
|
|
{
|
|
for (int n = 0; n < targ.cluster.shards[i].nSt.Count / 3; n++)
|
|
{
|
|
if (targ.cluster.shards[i].uny == true)
|
|
{
|
|
Gizmos.color = Color.yellow;
|
|
}
|
|
else
|
|
{
|
|
Gizmos.color = targ.cluster.shards[i].sIds.Count > 0
|
|
? Color.yellow
|
|
: ColorByValue (stressColor, targ.cluster.shards[i].nSt[n * 3], targ.stress.threshold);
|
|
}
|
|
|
|
pos = (targ.cluster.shards[i].neibShards[n].tm.position - targ.cluster.shards[i].tm.position) / 2.5f + targ.cluster.shards[i].tm.position;
|
|
Gizmos.DrawLine (targ.cluster.shards[i].tm.position, pos);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set gizmo color by uny and act states
|
|
static void SetColor (bool uny, bool act)
|
|
{
|
|
if (uny == false)
|
|
Gizmos.color = Color.green;
|
|
else
|
|
Gizmos.color = act == true ? Color.magenta : Color.red;
|
|
}
|
|
|
|
// Color by value
|
|
static Color ColorByValue(Color color, float val, float threshold)
|
|
{
|
|
val /= threshold;
|
|
color.g = 1f - val;
|
|
color.r = val;
|
|
return color;
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Methods
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
[DrawGizmo (GizmoType.Selected | GizmoType.NonSelected | GizmoType.Pickable)]
|
|
static void DrawGizmosSelected (RayfireConnectivity targ, GizmoType gizmoType)
|
|
{
|
|
// Draw bounding gizmo
|
|
GizmoDraw (targ);
|
|
|
|
// Has no shards
|
|
if (targ.cluster == null)
|
|
return;
|
|
|
|
/*
|
|
// Missing shards
|
|
// if (targ.cluster.shards.Count > 0)
|
|
{
|
|
if (RFCluster.IntegrityCheck (targ.cluster) == false)
|
|
Debug.Log ("RayFire Connectivity: " + targ.name + " has missing shards. Reset or Setup cluster.", targ.gameObject);
|
|
else
|
|
targ.integrityCheck = false;
|
|
}
|
|
*/
|
|
|
|
// Draw for MeshRoot and RigidRoot in runtime
|
|
if (Application.isPlaying == true || targ.meshRootHost != null)
|
|
{
|
|
ClusterDraw (targ.cluster, targ.showNodes, targ.showConnections);
|
|
}
|
|
|
|
// Draw for RigidRoot because Connectivity do not store same shard list
|
|
else if (targ.rigidRootHost != null)
|
|
ClusterDraw (targ.rigidRootHost.cluster, targ.showNodes, targ.showConnections);
|
|
|
|
// Draw stresses connections
|
|
StressDraw (targ);
|
|
}
|
|
|
|
static void GizmoDraw (RayfireConnectivity targ)
|
|
{
|
|
if (targ.showGizmo == true)
|
|
{
|
|
// Gizmo properties
|
|
Gizmos.color = GUICommon.color_blue;
|
|
if (targ.transform.childCount > 0)
|
|
{
|
|
Bounds bound = RFCluster.GetChildrenBound (targ.transform);
|
|
Gizmos.DrawWireCube (bound.center, bound.size);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Common
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
void SetDirty (RayfireConnectivity scr)
|
|
{
|
|
if (Application.isPlaying == false)
|
|
{
|
|
EditorUtility.SetDirty (scr);
|
|
EditorSceneManager.MarkSceneDirty (scr.gameObject.scene);
|
|
SceneView.RepaintAll();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Handle selection
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
static Vector2Int currentShardConnection;
|
|
private static int s_ButtonHash = "ConnectionHandle".GetHashCode();
|
|
|
|
void OnSceneGUI()
|
|
{
|
|
var targ = conn;
|
|
if (targ == null)
|
|
return;
|
|
|
|
if (targ.showConnections == true)
|
|
{
|
|
if (targ.cluster != null && targ.cluster.shards.Count > 0)
|
|
{
|
|
int count = targ.cluster.shards.Count;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
if (targ.cluster.shards[i].tm != null)
|
|
{
|
|
if (targ.cluster.shards[i].nIds.Count == 0)
|
|
continue;
|
|
|
|
if (targ.cluster.shards[i].neibShards != null && targ.cluster.shards[i].neibShards.Count != 0)
|
|
{
|
|
int nCount = targ.cluster.shards[i].neibShards.Count;
|
|
for (int j = 0; j < nCount; j++)
|
|
{
|
|
if (targ.cluster.shards[i].neibShards[j].tm != null)
|
|
{
|
|
Vector3 start = targ.cluster.shards[i].tm.position;
|
|
Vector3 end = start + (targ.cluster.shards[i].neibShards[j].tm.position - start) * 0.5f;
|
|
HandleClick(start, end, targ.cluster.shards[i].id, targ.cluster.shards[i].neibShards[j].id);
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void HandleClick(Vector3 start, Vector3 end, int id1, int id2)
|
|
{
|
|
int id = GUIUtility.GetControlID(s_ButtonHash, FocusType.Passive);
|
|
Event evt = Event.current;
|
|
|
|
switch (evt.GetTypeForControl(id))
|
|
{
|
|
case EventType.Layout:
|
|
{
|
|
HandleUtility.AddControl(id, HandleUtility.DistanceToLine(start, end));
|
|
break;
|
|
}
|
|
case EventType.MouseMove:
|
|
{
|
|
if (id == HandleUtility.nearestControl)
|
|
HandleUtility.Repaint();
|
|
break;
|
|
}
|
|
case EventType.MouseDown:
|
|
{
|
|
if (HandleUtility.nearestControl == id && evt.button == 0)
|
|
{
|
|
GUIUtility.hotControl = id; // Grab mouse focus
|
|
HandleClickSelection(evt, id1, id2);
|
|
evt.Use();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void HandleClickSelection(Event evt, int id1, int id2)
|
|
{
|
|
currentShardConnection.x = id1;
|
|
currentShardConnection.y = id2;
|
|
|
|
|
|
}
|
|
|
|
private void DeleteSelectedConnection()
|
|
{
|
|
var targ = conn;
|
|
if (targ.showConnections == true)
|
|
{
|
|
if (targ.cluster != null && targ.cluster.shards.Count > 0)
|
|
{
|
|
int count = targ.cluster.shards.Count;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
if (targ.cluster.shards[i].tm != null)
|
|
{
|
|
if (targ.cluster.shards[i].nIds.Count == 0)
|
|
continue;
|
|
|
|
if (targ.cluster.shards[i].neibShards != null && targ.cluster.shards[i].neibShards.Count != 0)
|
|
{
|
|
int nCount = targ.cluster.shards[i].neibShards.Count - 1;
|
|
for (int j = nCount; j >= 0; --j)
|
|
{
|
|
if (targ.cluster.shards[i].neibShards[j].tm != null)
|
|
{
|
|
var id = targ.cluster.shards[i].id;
|
|
var nId = targ.cluster.shards[i].neibShards[j].id;
|
|
if (currentShardConnection.x == id && currentShardConnection.y == nId || currentShardConnection.y == id && currentShardConnection.x == nId)
|
|
targ.cluster.shards[i].RemoveNeibAt(j);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
*/
|
|
|
|
/*
|
|
if (targ.cluster.shards[i].uny == true)
|
|
{
|
|
Gizmos.color = Color.yellow;
|
|
}
|
|
else
|
|
{
|
|
//if (targ.cluster.shards[i].sIds.Count > 0)
|
|
//{
|
|
if (targ.cluster.shards[i].neibShards[n].sIds.Contains (targ.cluster.shards[i].id) == true || targ.cluster.shards[i].sIds.Contains (targ.cluster.shards[i].neibShards[n].id) == true)
|
|
{
|
|
Gizmos.color = Color.yellow;
|
|
}
|
|
//}
|
|
else
|
|
Gizmos.color = ColorByValue (stressColor, targ.cluster.shards[i].nStr[n * 3], targ.stress.threshold);
|
|
}
|
|
|
|
|
|
|
|
|
|
if (targ.cluster.shards[i].uny == true || targ.cluster.shards[i].sIds.Count > 0)
|
|
Gizmos.color = Color.yellow;
|
|
else
|
|
Gizmos.color = ColorByValue (stressColor, targ.cluster.shards[i].nStr[n*3], targ.stress.threshold);
|
|
|
|
*/ |