247 lines
11 KiB
C#
247 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace Ingvar.LiveWatch.Editor
|
|
{
|
|
[Serializable]
|
|
public class VariableCellGUI
|
|
{
|
|
public bool IsSelected { get; set; }
|
|
public int RowIndex { get; set; }
|
|
public int SelectedColumnIndex { get; set; }
|
|
public bool IsNarrowMode { get; set; }
|
|
public float ValueColumnWidth { get; set; }
|
|
public WatchVariable Variable { get; set; }
|
|
public Rect ValuesRect { get; set; }
|
|
public VariableSelectedFitInfo SelectedFitInfo { get; set; }
|
|
public bool PreferRightSelection { get; set; }
|
|
public List<int> IndicesToDisplay { get; set; }
|
|
|
|
private VariableSelectedFitInfo _currentFitInfo = new();
|
|
|
|
private float currentSideOffset;
|
|
private bool isRightSelection => PreferRightSelection ? SelectedFitInfo.CanFitRight : !SelectedFitInfo.CanFitLeft;
|
|
|
|
public void DrawValueCellSegment(Rect rect, string value, List<int> contentIndices, float progress)
|
|
{
|
|
if (Event.current.type is not EventType.Repaint)
|
|
return;
|
|
|
|
currentSideOffset = 0;
|
|
|
|
if (value == string.Empty)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var isSelected = contentIndices.Contains(SelectedColumnIndex);
|
|
|
|
EditorGUI.DrawRect(rect.Extrude(ExtrudeFlags.All, -1f), Colors.SegmentFrame);
|
|
EditorGUI.DrawRect(rect.Extrude(ExtrudeFlags.All, -2.5f), RowIndex % 2 == 0 ? Colors.Background : Colors.BackgroundOdd);
|
|
|
|
var innerRect = rect.Extrude(ExtrudeFlags.All, -4f);
|
|
currentSideOffset = 4;
|
|
|
|
var progressPixels = Mathf.FloorToInt(Mathf.Clamp(progress * innerRect.height, 2, innerRect.height));
|
|
var progressRect = innerRect.CropFromPositionWithSize(CropEdge.BottomLocal, 0.5f, progressPixels);
|
|
var progressColor = RowIndex % 2 == 0 ? Colors.SegmentFill : Colors.SegmentFillOdd;
|
|
|
|
DrawFormatCells(progressRect, contentIndices, progressColor);
|
|
DrawDividerCells(progressRect.Extrude(ExtrudeFlags.Left | ExtrudeFlags.Right, 4f), contentIndices);
|
|
|
|
if (isSelected)
|
|
return;
|
|
|
|
var estimatedSize = Styles.VariableValue.CalcSize(WatchEditorServices.GUICache.GetContent(value));
|
|
estimatedSize.x -= 4;
|
|
var valueRect = innerRect;
|
|
|
|
if (estimatedSize.x > valueRect.width)
|
|
{
|
|
var dotsRect = valueRect
|
|
.CropFromPositionWithSize(CropEdge.RightLocal, 0, 7)
|
|
.CropFromPositionWithSize(CropEdge.BottomLocal, valueRect.height/2f - 6, 3);
|
|
|
|
GUI.DrawTexture(dotsRect,
|
|
Textures.Dots);
|
|
valueRect = valueRect.Extrude(ExtrudeFlags.Right, -6);
|
|
}
|
|
|
|
if (valueRect.width > 5)
|
|
{
|
|
var style = estimatedSize.x > valueRect.width ? Styles.VariableValueLeft : Styles.VariableValue;
|
|
DrawLabelWitchSearchResult(valueRect, Variable.GetValueText(contentIndices[0]), contentIndices[0], style);
|
|
}
|
|
}
|
|
|
|
public void DrawSelectedCell(Rect rect, string value, int index)
|
|
{
|
|
if (Event.current.type is not (EventType.Repaint or EventType.Layout))
|
|
return;
|
|
|
|
var availableRect = rect.Extrude(ExtrudeFlags.All, -1);
|
|
var estimatedSize = Styles.VariableValueSelected.CalcSize(WatchEditorServices.GUICache.GetContent(value))
|
|
+ Vector2.right * 10;
|
|
var resultWidth = Mathf.Max(availableRect.width, estimatedSize.x);
|
|
|
|
if (Event.current.type is not EventType.Repaint)
|
|
{
|
|
var cellRectRight = availableRect.CropFromStartToPosition(CropEdge.LeftLocal, resultWidth);
|
|
_currentFitInfo.CanFitRight = cellRectRight.xMax <= ValuesRect.xMax;
|
|
|
|
var cellRectLeft = availableRect.CropFromStartToPosition(CropEdge.RightLocal, resultWidth);
|
|
_currentFitInfo.CanFitLeft = cellRectLeft.xMin >= ValuesRect.xMin;
|
|
|
|
SelectedFitInfo.MergeWith(_currentFitInfo);
|
|
return;
|
|
}
|
|
|
|
var edge = PreferRightSelection
|
|
? SelectedFitInfo.CanFitRight ? CropEdge.LeftLocal : CropEdge.RightLocal
|
|
: SelectedFitInfo.CanFitLeft ? CropEdge.RightLocal : CropEdge.LeftLocal;
|
|
|
|
var distToValuesEdge = edge == CropEdge.LeftLocal
|
|
? ValuesRect.xMax - availableRect.xMin
|
|
: availableRect.xMax - ValuesRect.xMin;
|
|
|
|
if (distToValuesEdge > 40)
|
|
resultWidth = Mathf.Min(resultWidth, distToValuesEdge - 5);
|
|
|
|
var cellBackRect = availableRect.CropFromStartToPosition(edge, resultWidth);
|
|
|
|
if (IsNarrowMode)
|
|
{
|
|
cellBackRect = cellBackRect.OffsetByX(Mathf.Max(rect.width, Constants.VariableSelectionLineMinWidth)
|
|
* (edge == CropEdge.LeftLocal ? 1 : - 1));
|
|
cellBackRect = cellBackRect.Extrude(
|
|
ExtrudeFlags.Top | ExtrudeFlags.Bottom,
|
|
-Mathf.Abs(cellBackRect.height - estimatedSize.y)/2f);
|
|
}
|
|
|
|
EditorGUI.DrawRect(cellBackRect, IsNarrowMode ? Colors.CellBackgroundSelectedGraph : Colors.CellBackgroundSelected);
|
|
|
|
DrawPreviewTriangles(cellBackRect);
|
|
DrawSelectedCelLine(rect);
|
|
|
|
var cellValueRect = cellBackRect;
|
|
var isTextFit = estimatedSize.x < cellValueRect.width;
|
|
var textStyle = isTextFit ? Styles.VariableValueSelected : Styles.VariableValueSelectedLeft;
|
|
cellValueRect = cellValueRect.CropFromPositionToEnd(CropEdge.LeftLocal, isTextFit ? 0 : 5);
|
|
DrawLabelWitchSearchResult(cellValueRect, value, index, textStyle);
|
|
}
|
|
|
|
public void DrawSelectedCelLine(Rect rect)
|
|
{
|
|
if (Event.current.type is not EventType.Repaint)
|
|
return;
|
|
|
|
var edge = PreferRightSelection
|
|
? SelectedFitInfo.CanFitRight ? CropEdge.LeftLocal : CropEdge.RightLocal
|
|
: SelectedFitInfo.CanFitLeft ? CropEdge.RightLocal : CropEdge.LeftLocal;
|
|
|
|
var lineRect = IsNarrowMode
|
|
? rect
|
|
: rect.CropFromPositionWithSize(edge, 1, 3);
|
|
|
|
if (IsNarrowMode && lineRect.width < Constants.VariableSelectionLineMinWidth)
|
|
{
|
|
lineRect = new Rect(
|
|
lineRect.center.x - Constants.VariableSelectionLineMinWidth / 2,
|
|
lineRect.y,
|
|
Constants.VariableSelectionLineMinWidth,
|
|
lineRect.height);
|
|
}
|
|
|
|
EditorGUI.DrawRect(lineRect, IsNarrowMode ? Colors.CellSelectionLineGraph : Colors.CellSelectionLine);
|
|
}
|
|
|
|
private void DrawLabelWitchSearchResult(Rect labelRect, string text, int index, GUIStyle style, bool forceFullSelection = false)
|
|
{
|
|
if (Event.current.type is not EventType.Repaint)
|
|
return;
|
|
|
|
if (labelRect.width > ValueColumnWidth)
|
|
labelRect = labelRect.FitInRect(ValuesRect);
|
|
style.Draw(labelRect, WatchEditorServices.GUICache.GetContent(text), -1);
|
|
}
|
|
|
|
private void DrawFormatCells(Rect rect, List<int> contentIndices, Color fallbackColor)
|
|
{
|
|
{
|
|
TryDrawFormatRect(rect
|
|
);
|
|
return;
|
|
}
|
|
|
|
void TryDrawFormatRect(Rect formatRect
|
|
)
|
|
{
|
|
if (fallbackColor != Color.clear)
|
|
EditorGUI.DrawRect(formatRect, fallbackColor);
|
|
}
|
|
}
|
|
|
|
private void DrawDividerCells(Rect rect, List<int> contentIndices)
|
|
{
|
|
WatchEditorServices.CellDividerDrawer.Draw(rect, Mathf.FloorToInt(ValueColumnWidth));
|
|
}
|
|
|
|
|
|
private Rect GetCellRect(int index, Rect rect, List<int> contentIndices)
|
|
{
|
|
var cellWidth = ValueColumnWidth;
|
|
|
|
if (index == 0)
|
|
cellWidth -= currentSideOffset;
|
|
|
|
if (index == contentIndices.Count - 1)
|
|
cellWidth -= currentSideOffset;
|
|
|
|
var cellRect = rect.CropFromPositionWithSize(
|
|
CropEdge.LeftLocal,
|
|
index * ValueColumnWidth + (index == 0 ? 0 : -currentSideOffset),
|
|
cellWidth);
|
|
|
|
return cellRect;
|
|
}
|
|
|
|
private void DrawPreviewTriangles(Rect rect)
|
|
{
|
|
var isSelectedNumberValid = Variable.IsValidNumberValue(SelectedColumnIndex, out var selectedNumberValue);
|
|
|
|
if (Variable.Values.IsOriginalAt(SelectedColumnIndex))
|
|
{
|
|
var prevToSelectedIndex = IndicesToDisplay.IndexOf(SelectedColumnIndex) - 1;
|
|
|
|
if (prevToSelectedIndex >= 0)
|
|
{
|
|
var isPrevNumberValid = Variable.IsValidNumberValue(IndicesToDisplay[prevToSelectedIndex], out var prevNumberValue);
|
|
var isTopAngle = isPrevNumberValid && prevNumberValue >= selectedNumberValue;
|
|
var isNextToSearchResult = false;
|
|
var triangleLeftRect = rect
|
|
.CropFromPositionWithSize(CropEdge.LeftLocal, IsNarrowMode ? 1 : (isRightSelection ? 3 : 0), 4)
|
|
.CropFromPositionWithSize(isTopAngle ? CropEdge.TopLocal : CropEdge.BottomLocal, IsSelected && !IsNarrowMode ? 3 : 0, 4);
|
|
GUI.DrawTexture(triangleLeftRect, isTopAngle
|
|
? (isNextToSearchResult ? Textures.BlueTriangleTopLeft : Textures.WhiteTriangleTopLeft)
|
|
: (isNextToSearchResult ? Textures.BlueTriangleBottomLeft : Textures.WhiteTriangleBottomLeft));
|
|
}
|
|
}
|
|
|
|
var nextToSelectedIndex = IndicesToDisplay.IndexOf(SelectedColumnIndex) + 1;
|
|
if (nextToSelectedIndex < IndicesToDisplay.Count && Variable.Values.IsOriginalAt(IndicesToDisplay[nextToSelectedIndex]))
|
|
{
|
|
var isNextNumberValid = Variable.IsValidNumberValue(IndicesToDisplay[nextToSelectedIndex], out var nextNumberValue);
|
|
var isTopAngle = isNextNumberValid && nextNumberValue >= selectedNumberValue;
|
|
var isNextToSearchResult = false;
|
|
var triangleRightRect = rect
|
|
.CropFromPositionWithSize(CropEdge.RightLocal, isRightSelection || IsNarrowMode ? 0 : 3, 4)
|
|
.CropFromPositionWithSize(isTopAngle ? CropEdge.TopLocal : CropEdge.BottomLocal, IsSelected && !IsNarrowMode ? 3 : 0, 4);
|
|
GUI.DrawTexture(triangleRightRect, isTopAngle
|
|
? (isNextToSearchResult ? Textures.BlueTriangleTopRight : Textures.WhiteTriangleTopRight)
|
|
: (isNextToSearchResult ? Textures.BlueTriangleBottomRight : Textures.WhiteTriangleBottomRight));
|
|
}
|
|
}
|
|
}
|
|
} |