2026-01-06

[Unity] Odin Inspector DateTime 時間屬性繪製

Odin Inspector 是一個有名的Unity Inspector Plugin,但沒有為 DateTime 建立可編輯的可視化介面,這邊簡單提供一個可用的方法 。

Odin Inspector 版本 : 3.3.1.14



DateTime 屬性繪製
#if ODIN_INSPECTOR && UNITY_EDITOR
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities;
using Sirenix.Utilities.Editor;
using System;
using UnityEditor;
using UnityEngine;

namespace Odin
{

    public class OdinDateTimeDrawer : OdinValueDrawer<DateTime>
    {
        private bool editMode = false;
        protected override void DrawPropertyLayout(GUIContent label)
        {
            Rect ctrlRect;
            Rect rect = ctrlRect = EditorGUILayout.GetControlRect();
            if (label != null)
            {
                rect = EditorGUI.PrefixLabel(rect, label);
            }
            var value = this.ValueEntry.SmartValue;
            if (!editMode)
            {
                EditorGUI.LabelField(rect.AlignLeft(rect.width - 20), value.ToString("yyyy-MM-dd HH:mm:ss"));
                editMode = GUI.Button(rect.AlignRight(24), EditorIcons.SettingsCog.ActiveGUIContent);
                return;
            }

            if (label == null)
                rect = EditorGUI.IndentedRect(rect);

            var style = new GUIStyle(EditorStyles.numberField);
            GUIHelper.PushLabelWidth(style.fontSize * 1.2f); // EditorGUIUtility.labelWidth
            int year = value.Year;
            int month = value.Month;
            int day = value.Day;
            rect.xMax -= 30;
            var yearRect = rect.AlignLeft(rect.width * 0.4f);
            var yLabel = new GUIContent("Y", "Year");
            year = EditorGUI.IntField(yearRect, yLabel, year, style);

            var monthRect = rect;
            monthRect.x = yearRect.xMax;
            monthRect.width = rect.width * 0.3f;
            var mLabel = new GUIContent("M", "Month");
            month = EditorGUI.IntField(monthRect, mLabel, month, style);

            var dayRect = rect.AlignRight(rect.width * 0.3f);
            var dLabel = new GUIContent("D", "Day");
            day = EditorGUI.IntField(dayRect, dLabel, day, style);

            editMode = !GUI.Button(ctrlRect.AlignRight(24), EditorIcons.TriangleUp.ActiveGUIContent);

            rect = EditorGUILayout.GetControlRect();
            rect.xMin = yearRect.xMin;

            int hour = value.Hour;
            int minute = value.Minute;
            int second = value.Second;
            int millisecond = value.Millisecond;

            var hourRect = rect.AlignLeft(rect.width * 0.25f);
            var hLabel = new GUIContent("H", "Hour");
            hour = EditorGUI.IntField(hourRect, hLabel, hour, style);
            var minuteRect = rect;
            minuteRect.x = hourRect.xMax;
            minuteRect.width = rect.width * 0.25f;
            var miLabel = new GUIContent("M", "Minute");
            minute = EditorGUI.IntField(minuteRect, miLabel, minute, style);
            var secondRect = rect.AlignRight(rect.width * 0.25f);

            secondRect.x = minuteRect.xMax;
            secondRect.width = rect.width * 0.25f;
            var sLabel = new GUIContent("S", "Second");
            second = EditorGUI.IntField(secondRect, sLabel, second, style);
            GUIHelper.PopLabelWidth();

            GUIHelper.PushLabelWidth(style.fontSize * 2.1f);
            var millisecondRect = rect.AlignRight(rect.width * 0.25f);
            millisecondRect.x = secondRect.xMax;
            millisecondRect.width = rect.width * 0.25f;
            var msLabel = new GUIContent("MS", "Millisecond");
            millisecond = EditorGUI.IntField(millisecondRect, msLabel, millisecond, style);
            GUIHelper.PopLabelWidth();

            value = new DateTime(year, month, day, hour, minute, second, millisecond);
            this.ValueEntry.SmartValue = value;
        }
    }
}
#endif


TimeSpan屬性繪製
#if ODIN_INSPECTOR && UNITY_EDITOR
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities;
using System;
using UnityEditor;
using UnityEngine;

namespace Odin
{
    public class OdinTimeSpanDrawer : OdinValueDrawer<TimeSpan>
    {
        private static readonly string[] units = new string[] { "tick", "ms", "sec", "min", "hour", "day" };

        private int selectedUnit = 0;
        protected override void DrawPropertyLayout(GUIContent label)
        {
            Rect ctrlRect;
            Rect rect = ctrlRect = EditorGUILayout.GetControlRect();
            if (label != null)
            {
                rect = EditorGUI.PrefixLabel(rect, label);
            }
            var value = this.ValueEntry.SmartValue;

            value = selectedUnit switch
            {
                1 => TimeSpan.FromTicks(TimeSpan.FromMilliseconds(EditorGUI.DoubleField(rect.AlignLeft(rect.width - 60), value.TotalMilliseconds)).Ticks + (value.Ticks - TimeSpan.FromMilliseconds(value.TotalMilliseconds).Ticks)),
                2 => TimeSpan.FromTicks(TimeSpan.FromSeconds(EditorGUI.DoubleField(rect.AlignLeft(rect.width - 60), value.TotalSeconds)).Ticks + (value.Ticks - TimeSpan.FromSeconds(value.TotalSeconds).Ticks)),
                3 => TimeSpan.FromTicks(TimeSpan.FromMinutes(EditorGUI.DoubleField(rect.AlignLeft(rect.width - 60), value.TotalMinutes)).Ticks + (value.Ticks - TimeSpan.FromMinutes(value.TotalMinutes).Ticks)),
                4 => TimeSpan.FromTicks(TimeSpan.FromHours(EditorGUI.DoubleField(rect.AlignLeft(rect.width - 60), value.TotalHours)).Ticks + (value.Ticks - TimeSpan.FromHours(value.TotalHours).Ticks)),
                5 => TimeSpan.FromTicks(TimeSpan.FromDays(EditorGUI.DoubleField(rect.AlignLeft(rect.width - 60), value.TotalDays)).Ticks + (value.Ticks - TimeSpan.FromDays(value.TotalDays).Ticks)),
                _ => TimeSpan.FromTicks(EditorGUI.LongField(rect.AlignLeft(rect.width - 60), value.Ticks)),
            };
            selectedUnit = EditorGUI.Popup(rect.AlignRight(55), selectedUnit, units);

            this.ValueEntry.SmartValue = value;
        }
    }
}

沒有留言:

張貼留言

[Unity] Odin Inspector DateTime 時間屬性繪製

Odin Inspector 是一個有名的Unity Inspector Plugin,但沒有為 DateTime 建立可編輯的可視化介面,這邊簡單提供一個可用的方法 。 Odin Inspector 版本 : 3.3.1.14