protected virtual void DrawImpl(Rect position, GUIContent label) { var rowHeight = GUI.skin.font.lineHeight; rowHeight += GUI.skin.label.margin.vertical + GUI.skin.label.padding.vertical; var pos = new GUILayoutPosition(position, rowHeight); if (Target.CurrentType == SerializedTarget.Type.SerializedProperty) { using (var scope = new EditorGUI.ChangeCheckScope()) { var foldoutPos = pos.GetSplitPos(3f, 0); _foldout = EditorGUI.Foldout(foldoutPos, _foldout, label); var objFieldPos = pos.GetSplitPos(3f, 1, 2); var newObj = EditorGUI.ObjectField(objFieldPos, Target.ObjectReference, typeof(TDictionary), false); if (scope.changed) { Target.ObjectReference = newObj; } } if (!_foldout || Target.ObjectReference == null) { return; } } else { EditorGUI.LabelField(pos.Pos, label); } var assetInstance = Dictionary; if (assetInstance == null) { pos.IncrementRow(); var labelPos = pos.Pos; EditorGUI.LabelField(labelPos, "Don't Found Reference..."); return; } var SO = new SerializedObject(assetInstance); var(doApply, nextPos) = OnDrawElementsBefore(pos, SO, rowHeight); pos = nextPos; if (doApply) { return; } using (var indent1 = new EditorGUI.IndentLevelScope()) { var indentPos = pos.Indent(true); DrawElements(indentPos, SO, rowHeight); } }
/// <summary> /// Targetと引数SOが参照しているものは同じだが、場合によってTargetがポインタ型の場合があるためプロパティを変更したい場合はSOの方を使用してください。 /// </summary> /// <param name="position"></param> /// <param name="SO"></param> /// <param name="rowHeight"></param> /// <returns></returns> protected override (bool doApply, GUILayoutPosition nextPos) OnDrawElementsBefore(GUILayoutPosition position, SerializedObject SO, float rowHeight) { position.IncrementRow(); var labelPos = position.GetSplitPos(layoutPosDivideCount, 0); RectOffset offset = new RectOffset((int)(labelPos.width * -0.1f), 0, 0, 0); labelPos = offset.Add(labelPos); EditorGUI.LabelField(labelPos, "Used Type"); bool doApply = false; bool enableUpdateType = true; //UsedUnityObjectAttributeが指定されていたら型は固定し、そうでなければ選択できるようにする var instance = SO.targetObject as TDictionary; if (Target.CurrentType == SerializedTarget.Type.SerializedProperty && UsedTypeAttribute.SetTypeFromFieldInfo(Target.SerializedProperty.GetFieldInfo(), instance)) { var typeNameProp = SO.FindProperty("_typeName"); Assert.IsNotNull(typeNameProp, $"{Target.SerializedProperty.propertyPath}"); if (typeNameProp.stringValue != instance.HasType.FullName) { typeNameProp.stringValue = instance.HasType.FullName; var typeCache = GetOrCreateTypeCahce(SO, out bool _); typeCache.CurrentType = instance.HasType; doApply = true; } enableUpdateType = false; } doApply |= DrawTypePopUp(SO, position, enableUpdateType); if (doApply) { var typeNameProp = SO.FindProperty("_typeName"); if (typeNameProp.stringValue != _typeCache.CurrentType.FullName) { typeNameProp.stringValue = _typeCache.CurrentType.FullName; SO.FindProperty("_values").ClearArray(); SO.ApplyModifiedProperties(); } var inst = SO.targetObject as TDictionary; inst.Refresh(); } return(doApply, position); }
/// <summary> /// 要素の配列を表示する /// </summary> /// <param name="position"></param> /// <param name="SO"></param> /// <param name="rowHeight"></param> void DrawElements(GUILayoutPosition position, SerializedObject SO, float rowHeight) { var valuesProp = SO.FindProperty("_values"); if (valuesProp == null) { return; } bool doChanged = false; int newArraySize = -1; using (var scope = new EditorGUI.ChangeCheckScope()) { position.IncrementRow(); newArraySize = Mathf.Max(0, EditorGUI.IntField(position.Pos, "Size", valuesProp.arraySize)); if (scope.changed) { doChanged |= true; } } var nameHash = new HashSet <string>(); var endIndex = Mathf.Min(valuesProp.arraySize, (_page + 1) * ELEMENT_PER_PAGE); for (var i = _page * ELEMENT_PER_PAGE; i < endIndex; ++i) { var element = valuesProp.GetArrayElementAtIndex(i); position.IncrementRow(); // 使用する型が指定されていたらそれをKeyValueに渡す CustomGUIContent label = new CustomGUIContent(); if (Target.CurrentType == SerializedTarget.Type.SerializedProperty) { var usedTypeAttr = Target.SerializedProperty.GetFieldAttributes <UsedTypeAttribute>().FirstOrDefault(); if (usedTypeAttr != null) { label.Parameter = usedTypeAttr; } } else if (SO.targetObject is IKeyValueDictionaryWithTypeName <TKeyValue, T> ) { var inst = SO.targetObject as IKeyValueDictionaryWithTypeName <TKeyValue, T>; label.Parameter = inst.HasType; } doChanged |= EditorGUI.PropertyField(position.Pos, element, label); //キーが更新されたか? var keyProp = element.FindPropertyRelative("_key"); var doContains = nameHash.Contains(keyProp.stringValue); doChanged |= doContains; if (!doContains) { nameHash.Add(keyProp.stringValue); } } if (doChanged) { valuesProp.arraySize = newArraySize; Reflesh(valuesProp); OnApplyBefore(SO, valuesProp); if (SO.ApplyModifiedProperties()) { var instance = SO.targetObject as TDictionary; instance.Refresh(); OnApplyAfter(instance); } } //Show Pagination if (valuesProp.arraySize >= ELEMENT_PER_PAGE) { position.IncrementRow(); var maxPage = (valuesProp.arraySize / ELEMENT_PER_PAGE); maxPage += (valuesProp.arraySize % ELEMENT_PER_PAGE) == 0 ? 0 : 1; _page = EditorGUI.IntSlider(position.Pos, $"Pagination {_page + 1}/{maxPage}", _page + 1, 1, maxPage); _page = Mathf.Clamp(_page - 1, 0, maxPage); } }