private static IMGUIContainer CreateButton(DataConfigEditor editor, System.Collections.Generic.HashSet <System.Type> usedComponents, SerializedProperty source, VisualElement elements, bool noFields)
        {
            var addMenuButton = new IMGUIContainer(() => {
                GUILayoutExt.DrawAddComponentMenu(usedComponents, (type, isUsed) => {
                    if (isUsed == false)
                    {
                        usedComponents.Add(type);

                        source.serializedObject.Update();
                        ++source.arraySize;
                        var elem = source.GetArrayElementAtIndex(source.arraySize - 1);
                        elem.managedReferenceValue = System.Activator.CreateInstance(type);
                        source.serializedObject.ApplyModifiedProperties();

                        if (noFields == true)
                        {
                            editor.OnAddComponentFromRemoveList(type);
                        }
                        else
                        {
                            editor.OnAddComponent(type);
                        }
                    }
                    else
                    {
                        RemoveComponent(editor, usedComponents, source, type, noFields);
                    }

                    editor.Save();
                    BuildInspectorProperties(editor, usedComponents, source, elements, noFields);
                }, showRuntime: noFields);
            });

            addMenuButton.AddToClassList("add-component-menu-button-imgui");

            return(addMenuButton);
        }
        private static IMGUIContainer CreateTemplatesButton(DataConfigEditor editor,
                                                            System.Collections.Generic.HashSet <ME.ECS.DataConfigs.DataConfigTemplate> usedComponents,
                                                            VisualElement rootElement,
                                                            VisualElement templatesContainer,
                                                            SerializedProperty source,
                                                            SerializedObject so,
                                                            System.Action <SerializedObject, ME.ECS.DataConfigs.DataConfigTemplate> onAddTemplate,
                                                            System.Action <SerializedObject, ME.ECS.DataConfigs.DataConfigTemplate> onRemoveTemplate)
        {
            var container = new IMGUIContainer(() => {
                GUILayoutExt.DrawManageDataConfigTemplateMenu(usedComponents, (template, isUsed) => {
                    var path = AssetDatabase.GetAssetPath(template);
                    var guid = AssetDatabase.AssetPathToGUID(path);
                    if (string.IsNullOrEmpty(guid) == true)
                    {
                        return;
                    }

                    if (isUsed == true)
                    {
                        var copy          = source.Copy();
                        var i             = 0;
                        var enterChildren = true;
                        while (copy.NextVisible(enterChildren) == true)
                        {
                            enterChildren = false;

                            if (copy.propertyType != SerializedPropertyType.String)
                            {
                                continue;
                            }

                            if (copy.stringValue == guid)
                            {
                                usedComponents.Remove(template);
                                source.DeleteArrayElementAtIndex(i);
                                so.ApplyModifiedProperties();
                                onRemoveTemplate.Invoke(so, template);
                                break;
                            }

                            ++i;
                        }
                    }
                    else
                    {
                        usedComponents.Add(template);
                        onAddTemplate.Invoke(so, template);

                        ++source.arraySize;
                        var elem         = source.GetArrayElementAtIndex(source.arraySize - 1);
                        elem.stringValue = guid;
                        so.ApplyModifiedProperties();
                    }

                    editor.Save();
                    BuildContainer(editor, rootElement, so);
                });
            });

            container.AddToClassList("add-template-menu-button-imgui");

            return(container);
        }