Skip to content

Commit

Permalink
feat: UISkinnerの循環参照チェックを追加、クリーンアップでもチェックして引っかかったら消去するようにした
Browse files Browse the repository at this point in the history
  • Loading branch information
pspkurara committed Nov 9, 2020
1 parent e2ca64e commit 9d62706
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Packages/uGUI-Skinner/Editor/EditorConst.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ public static class EditorConst
public const string MissingSkinPartsInspectorTypeMessage = "Inspector for \" {0} \" not found.\nPlease check if it is registered correctly";
public const MessageType MissingSkinPartsInspectorTypeMessageType = MessageType.Warning;

public const string CirculationReferenceMessage = "There is a circular reference.\nPlease correct to parent-child reference.";
public const MessageType CirculationReferenceMessageType = MessageType.Warning;

public static readonly GUIContent UserLogicSampleTitle = new GUIContent("Skin Parts Inspector Sample");

public static readonly GUILayoutOption SkinSelectArrowMaxWidth = GUILayout.MaxWidth(50);
Expand Down
81 changes: 81 additions & 0 deletions Packages/uGUI-Skinner/Editor/UISkinnerInspector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public static class FieldName
private GUIContent m_SkinFoldoutTitle = null;
private GUIContent m_CurrentSelectStyleTitle = null;
private GUIUniqueIdentifier m_GuiUniqueIdCounter = new GUIUniqueIdentifier();
private Stack<UISkinner> m_CirculationApplyTrace;
private EditorSkinPartsPropertry m_CirculationPropertyMapper;

#endregion

Expand Down Expand Up @@ -73,6 +75,9 @@ private void OnEnable()
m_SkinPartsProperty = new EditorSkinPartsPropertry();
m_RuntimeSkinParts = new SkinParts();

m_CirculationApplyTrace = new Stack<UISkinner>();
m_CirculationPropertyMapper = new EditorSkinPartsPropertry();

m_GuiUniqueIdCounter.ResetLastControlGuiId();
}

Expand Down Expand Up @@ -247,6 +252,12 @@ public override void OnInspectorGUI()
EditorGUILayout.HelpBox(string.Format(EditorConst.MissingSkinPartsTypeMessage, skinPartsType), EditorConst.MissingSkinPartsTypeMessageType);
}

// 循環参照していたら警告を出す
if (GetCirculationApplyTrace(m_SkinPartsProperty.objectReferenceValues))
{
EditorGUILayout.HelpBox(EditorConst.CirculationReferenceMessage, EditorConst.CirculationReferenceMessageType, true);
}

EditorGUI.indentLevel -= EditorConst.SkinPartsChildIndent;

EditorGUI.indentLevel += EditorConst.SkinStyleChildIndent;
Expand Down Expand Up @@ -464,8 +475,78 @@ private void Cleanup()
checkedSkinParts.Add(cacheParts);
}

// 循環参照チェック
if (GetCirculationApplyTrace(m_SkinPartsProperty.objectReferenceValues))
{
// している場合は大本から切り離してしまったほうがよさそう
skinPartsProperty.DeleteArrayElementAtIndex(skinPartsIndex);
}

}
}
}

/// <summary>
/// <see cref="SkinPartsPropertry.objectReferenceValues"/>が循環参照しているかを取得する
/// </summary>
/// <param name="property">探す対象のプロパティ</param>
/// <param name="applyTrace">スタックリスト (初期値は自動取得)</param>
/// <param name="propertyMapper"><see cref="EditorSkinPartsPropertry.objectReferenceValues"/>をアンパックするための変数 (初期値は自動取得)</param>
/// <returns>循環参照をしている</returns>
private bool GetCirculationApplyTrace(SerializedProperty property, Stack<UISkinner> applyTrace = null, EditorSkinPartsPropertry propertyMapper = null)
{
if (applyTrace == null) applyTrace = m_CirculationApplyTrace;
if (propertyMapper == null) propertyMapper = m_CirculationPropertyMapper;

var propertySkinner = property.serializedObject.targetObject as UISkinner;

if (applyTrace.Contains(propertySkinner))
{
return true;
}

applyTrace.Push(propertySkinner);

var skinners = property.ArrayToEnumerable()
.Where(p => !p.hasMultipleDifferentValues)
.Select(p => p.objectReferenceValue as UISkinner)
.Where(po => po != null);

bool isCirculation = false;

foreach (var skinner in skinners)
{
var childProperty = new SerializedObject(skinner);
var styles = childProperty.FindProperty(FieldName.Styles)
.ArrayToEnumerable()
.Where(p => !p.hasMultipleDifferentValues);

foreach (var style in styles)
{
var parts = style.FindPropertyRelative(FieldName.Parts)
.ArrayToEnumerable()
.Where(p => !p.hasMultipleDifferentValues);

foreach (var part in parts)
{
propertyMapper.MapProperties(part.FindPropertyRelative(FieldName.Property));
if (GetCirculationApplyTrace(propertyMapper.objectReferenceValues, applyTrace, propertyMapper))
{
isCirculation = true;
}
}

if (isCirculation) break;
}

childProperty.Dispose();

if (isCirculation) break;
}

applyTrace.Pop();

return isCirculation;
}

#endregion
Expand Down

0 comments on commit 9d62706

Please sign in to comment.