/** * Go through all the data value arrays for each DieSide, resizing it when necessary. */ private void ensureDataValueCountPerSide() { DieSides dieSides = target as DieSides; for (int i = 0; i < _dieSides.arraySize; i++) { SerializedProperty dieSide = _dieSides.GetArrayElementAtIndex(i); SerializedProperty dieSideData = dieSide.FindPropertyRelative(_dieSideValuesPropertyName); //if no resizing is needed, skip if (_valueCountPerSide.intValue == dieSideData.arraySize) continue; //if it is less, just set array size this will delete the superfluous values if (_valueCountPerSide.intValue < dieSideData.arraySize) { dieSideData.arraySize = _valueCountPerSide.intValue; } else { //if required number of values is bigger than what we got, //insert empty elements at the end while (_valueCountPerSide.intValue > dieSideData.arraySize) { dieSideData.InsertArrayElementAtIndex(dieSideData.arraySize); dieSideData.GetArrayElementAtIndex(dieSideData.arraySize - 1).intValue = i; } } //data can be missing until serialized object is applied, so we need to check //whether the side is actually already there to update if (i < dieSides.dieSideCount) dieSides.GetDieSide(i).DirtyStringCache(); } }
/** * Draws debug info about the selected die: normals & values. */ void OnSceneGUI() { if (Selection.gameObjects.Length > 1 || !_debugViewOn) return; DieSides dieSides = target as DieSides; if (dieSides != null && dieSides.dieSideCount > 0) { //get the closest side match for the current orientation so we //can apply pretty colors DieSideMatchInfo dieSideMatchInfo = dieSides.GetDieSideMatchInfo(); DieSide current = dieSideMatchInfo.closestMatch; for (int i = 0; i < dieSides.dieSideCount; i++) { if (_highlightedIndex != -1 && _highlightedIndex != i) continue; DieSide dieSide = dieSides.GetDieSide(i); Vector3 worldPos = dieSides.transform.TransformPoint(dieSide.centerPoint); Vector3 worldNormal = dieSides.transform.TransformDirection(dieSide.normal); Vector3 endPos = worldPos + worldNormal * _labelDrawDistance; Color color = Color.green; Color labelColor = _labelDrawColor; //should we apply our regular red/green color scheme or should we make this //element blink because we selected it? if (_highlightedIndex == i && Math.Floor(Time.realtimeSinceStartup * 5) % 2 == 0) { color = Color.yellow; labelColor = Color.yellow; } else { color = dieSide == current ? Color.green : Color.red; } GUIStyle guiStyle = new GUIStyle(); guiStyle.fontSize = 20; guiStyle.normal.textColor = labelColor; Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual; Handles.color = color; Handles.DrawLine(worldPos, endPos); Handles.Label(endPos, "[" + i + "]=" + dieSide.ValuesAsString(), guiStyle); } } SceneView.RepaintAll(); }
/** * Show the UI that allows you to manipulate the data from the found sides or clear all data. */ private void showDataSidesManipulationUI() { _sideDataDisplayed = EditorGUILayout.Foldout( _sideDataDisplayed, //(_sideDataDisplayed ? "Hide value map" : "Show value map") + "Die sides value map" + " (" + _dieSides.arraySize + " sides)", _boldFoldout ); if (_sideDataDisplayed) { DieSides dieSides = target as DieSides; DieSideMatchInfo dieSideMatchInfo = dieSides.GetDieSideMatchInfo(); for (int i = 0; i < _dieSides.arraySize; i++) { showDataSideManipulationUI(i, dieSideMatchInfo); } //this little part allows us to change the highlight while we are tabbing //highlight is only updated if we were already highlighting if (_highlightedIndex > -1) { int currentFocus = -1; string nameOfFocusedControl = GUI.GetNameOfFocusedControl() ?? "x_x"; bool wasParseable = int.TryParse(nameOfFocusedControl.Split('_')[0], out currentFocus); if (wasParseable && _highlightedIndex != currentFocus) { _highlightedIndex = currentFocus; dieSides.transform.rotation = dieSides.GetWorldRotationFor(_highlightedIndex); } } showDataValueCountUpdateUI(); if (GUILayout.Button("Clear sides")) { if (EditorUtility.DisplayDialog("Warning", "This will delete all sides and their data. Are you sure?", "Yes", "No")) { _dieSides.arraySize = 0; _valueCountPerSide.intValue = 1; _showGenerationDebugData = false; _generationDebugData = ""; } } } }
protected virtual void Awake() { dieSides = GetComponent <DieSides>(); }
/** * For each side, show its data manipulation UI. */ private void showDataSideManipulationUI(int pSideIndex, DieSideMatchInfo pDieSideMatchInfo) { DieSides dieSides = target as DieSides; Color defaultColor = GUI.backgroundColor; EditorGUILayout.BeginHorizontal(); if (_highlightedIndex == pSideIndex) GUI.backgroundColor = Color.yellow; string sideLabel = "Side " + pSideIndex + " = "; _sideLabelStyle.normal.textColor = Color.black; if (pDieSideMatchInfo != null && pDieSideMatchInfo.closestMatch == dieSides.GetDieSide(pSideIndex)) { _sideLabelStyle.normal.textColor = pDieSideMatchInfo.isExactMatch ? darkGreen : darkBlue; } EditorGUILayout.LabelField(sideLabel, _sideLabelStyle, _sideLabelOptions); //show entry fields for all entries in the data array SerializedProperty dieSide = _dieSides.GetArrayElementAtIndex(pSideIndex); SerializedProperty dataArray = dieSide.FindPropertyRelative(_dieSideValuesPropertyName); EditorGUI.BeginChangeCheck(); SerializedProperty element; for (int i = 0; i < dataArray.arraySize; i++) { element = dataArray.GetArrayElementAtIndex(i); //set the next controlname to sideLabel so we can focus on it GUI.SetNextControlName(pSideIndex+"_"+i); //we have to do it like this unfortunately becauses the focus mechanism doesn't //work well with EditorGUILayout.IntField //string value = GUILayout.TextField("" + element.intValue, _dataValueOptions); //int intValue; //int.TryParse(value, out intValue); //element.intValue = intValue; element.intValue = EditorGUILayout.IntField(element.intValue, _dataValueOptions); } if (EditorGUI.EndChangeCheck()) { dieSides.GetDieSide(pSideIndex).DirtyStringCache(); } //show a toggle button for rotating and highlight //and update our highlight index accordingly if pressed bool currentHighLight = _highlightedIndex == pSideIndex; bool newHighLight = GUILayout.Toggle(_highlightedIndex == pSideIndex, _rotateButtonContent, "Button", _smallEditorButtonOptions); if (currentHighLight != newHighLight) { _highlightedIndex = (_highlightedIndex == pSideIndex) ? -1 : pSideIndex; if (_highlightedIndex != -1) { EditorGUI.FocusTextInControl(_highlightedIndex + "_0"); //GUI.FocusControl(_highlightedIndex + "_0"); } //rotate our die so that this value/side becomes activated dieSides.transform.rotation = dieSides.GetWorldRotationFor(pSideIndex); if (!Application.isPlaying) EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } EditorGUILayout.EndHorizontal(); GUI.backgroundColor = defaultColor; }
/** * Show the UI that allows you to trigger the side finding algorithm. */ private void showCalculateSidesUI() { EditorGUILayout.HelpBox( "There is no side info available for this object, "+ "press the 'Calculate sides' to fix this.", MessageType.Info ); _areaCutOffMultiplier = EditorGUILayout.Slider( new GUIContent( "Cut off value:", "All areas with a size that falls below " + (_areaCutOffMultiplier * 100) + "% of the maximum area size will be ignored." ), _areaCutOffMultiplier, 0, 1 ); if (GUILayout.Button("Calculate sides")) { //find all die sides through our findDieSides algorithm DieSides dieSides = target as DieSides; Mesh mesh = null; //if we have a collider, use the collider for the normals, otherwise our regular mesh MeshCollider meshCollider = dieSides.GetComponent<MeshCollider>(); if (meshCollider != null) { mesh = meshCollider.sharedMesh; } else { MeshFilter meshFilter = dieSides.GetComponent<MeshFilter>(); mesh = meshFilter.sharedMesh; } List<DieAreaFinder.DieArea> foundSides = DieAreaFinder.FindDieAreas(mesh, _areaCutOffMultiplier); //show any debug data that was generated during this process _generationDebugData = DieAreaFinder.LogContents(); _showGenerationDebugData = true; if (foundSides.Count == 0) return; _matchType.enumValueIndex = (foundSides.Count == 4) ? 1 : 0; //initialize our serialized properties with values based on the found die sides _dieSides.arraySize = foundSides.Count; for (int i = 0; i < foundSides.Count; i++) { DieAreaFinder.DieArea foundSide = foundSides[i]; SerializedProperty dieSide = _dieSides.GetArrayElementAtIndex(i); dieSide.FindPropertyRelative("_normal").vector3Value = foundSide.normal; dieSide.FindPropertyRelative("_centerPoint").vector3Value = foundSide.centerPoint; } //make sure all data values are initialized for each dieside ensureDataValueCountPerSide(); //save properties then align serializedObject.ApplyModifiedProperties(); dieSides.transform.rotation = dieSides.GetWorldRotationFor(0); } }