protected override async Task <bool> InitializeContextMenuOverride(ContextMenu contextMenu)
        {
            await EngineNS.Thread.AsyncDummyClass.DummyFunc();

            var textSeparatorStyle = Application.Current.MainWindow.TryFindResource(new ComponentResourceKey(typeof(ResourceLibrary.CustomResources), "TextMenuSeparatorStyle")) as System.Windows.Style;
            var menuItemStyle      = Application.Current.MainWindow.TryFindResource(new ComponentResourceKey(typeof(ResourceLibrary.CustomResources), "MenuItem_Default")) as System.Windows.Style;

            contextMenu.Items.Add(new ResourceLibrary.Controls.Menu.TextSeparator()
            {
                Text  = "Common",
                Style = textSeparatorStyle,
            });

            // 复制
            var duplicateMenuItem = new MenuItem()
            {
                Name   = "MatInsResInfo_Duplicate",
                Header = "复制",
                Style  = menuItemStyle,
            };

            duplicateMenuItem.Click += async(object sender, RoutedEventArgs e) =>
            {
                var dir      = ResourceName.GetDirectory();
                var inputWin = new InputWindow.InputWindow();
                inputWin.Title       = $"复制{ResourceName.PureName()}";
                inputWin.Description = "输入材质实例名称";
                inputWin.Value       = EditorCommon.Program.GetValidName(dir, ResourceName.PureName(), CEngineDesc.MaterialInstanceExtension);
                if (inputWin.ShowDialog((value, cultureInfo) =>
                {
                    if (value == null)
                    {
                        return(new ValidationResult(false, "内容不合法"));
                    }
                    return(ResourceNameAvailable(dir, value.ToString()));
                }) == false)
                {
                    return;
                }

                var rc = EngineNS.CEngine.Instance.RenderContext;
                // materialInstance
                var mat = await EngineNS.CEngine.Instance.MaterialManager.GetMaterialAsync(rc, this.ParentMaterialRName);

                if (mat == null)
                {
                    EditorCommon.MessageBox.Show($"没找到材质模板{this.ParentMaterialRName.Address}");
                    return;
                }
                var srcMatIns = await EngineNS.CEngine.Instance.MaterialInstanceManager.GetMaterialInstanceAsync(rc, ResourceName);

                var copyedRName  = EngineNS.RName.GetRName(EngineNS.CEngine.Instance.FileManager._GetRelativePathFromAbsPath(dir + inputWin.Value + CEngineDesc.MaterialInstanceExtension, ResourceName.GetRootFolder()), ResourceName.RNameType);
                var copyedMatIns = EngineNS.CEngine.Instance.MaterialInstanceManager.NewMaterialInstance(rc, mat, copyedRName);
                srcMatIns.SetDataToMaterialInstance(copyedMatIns);
                copyedMatIns.SaveMaterialInstance();
                // resourceInfo
                var copyedRInfo = new MaterialInstanceResourceInfo();
                copyedRInfo.ResourceName = copyedRName;
                await this.CopyResource(copyedRInfo);

                await copyedRInfo.Save();

                // snapshot
                EngineNS.CEngine.Instance.FileManager.CopyFile(this.ResourceName.Address + EditorCommon.Program.SnapshotExt, copyedRName.Address + EditorCommon.Program.SnapshotExt, true);
                await copyedRInfo.InitializeContextMenu();

                ParentBrowser.AddResourceInfo(copyedRInfo);
                ParentBrowser.SelectResourceInfo(copyedRInfo);
            };
            ResourceLibrary.Controls.Menu.MenuAssist.SetIcon(duplicateMenuItem, new BitmapImage(new System.Uri("pack://application:,,,/ResourceLibrary;component/Icons/Icons/icon_Edit_Duplicate_40x.png", UriKind.Absolute)));
            contextMenu.Items.Add(duplicateMenuItem);

            // 删除
            var menuItem = new MenuItem()
            {
                Name   = "MatInsResInfo_Delete",
                Header = "删除",
                Style  = menuItemStyle,
            };

            menuItem.Click += async(object sender, RoutedEventArgs e) =>
            {
                await DeleteResource();

                EngineNS.CEngine.Instance.MaterialInstanceManager.Materials.Remove(ResourceName);
            };
            ResourceLibrary.Controls.Menu.MenuAssist.SetIcon(menuItem, new BitmapImage(new System.Uri("pack://application:,,,/ResourceLibrary;component/Icons/Icons/icon_delete_16px.png", UriKind.Absolute)));
            contextMenu.Items.Add(menuItem);


            return(true);
        }
        protected override async Task <bool> InitializeContextMenuOverride(ContextMenu contextMenu)
        {
            await EngineNS.Thread.AsyncDummyClass.DummyFunc();

            var textSeparatorStyle = Application.Current.MainWindow.TryFindResource(new ComponentResourceKey(typeof(ResourceLibrary.CustomResources), "TextMenuSeparatorStyle")) as System.Windows.Style;
            var menuItemStyle      = Application.Current.MainWindow.TryFindResource(new ComponentResourceKey(typeof(ResourceLibrary.CustomResources), "MenuItem_Default")) as System.Windows.Style;

            contextMenu.Items.Add(new ResourceLibrary.Controls.Menu.TextSeparator()
            {
                Text  = "Common",
                Style = textSeparatorStyle,
            });

            var ciMenuItem = new MenuItem()
            {
                Name   = "MatResInfo_CreateMatIns",
                Header = "创建材质实例",
                Style  = menuItemStyle,
            };

            ciMenuItem.Click += async(object sender, RoutedEventArgs e) =>
            {
                var resInfo = new MaterialInstanceResourceInfo();

                var win = new EditorCommon.Controls.ResourceBrowser.CreateResDialog();
                win.Title        = $"创建材质实例";
                win.ResourceName = EditorCommon.Program.GetValidName(ResourceName.GetDirectory(), ResourceName.PureName() + "_ins", EngineNS.CEngineDesc.MaterialInstanceExtension);
                var data = new MaterialInstanceResourceCreateData()
                {
                    ResourceName   = win.ResourceName,
                    ParentMaterial = this.ResourceName,
                };
                win.ResCreateData = data;
                data.HostDialog   = win;
                if (win.ShowDialog((value, cultureInfo) =>
                {
                    if (value == null)
                    {
                        return(new ValidationResult(false, "内容不合法"));
                    }
                    return(resInfo.ResourceNameAvailable(ResourceName.GetDirectory(), value.ToString()));
                }) == false)
                {
                    return;
                }

                var createData = win.GetCreateData();
                createData.RNameType = ResourceName.RNameType;
                var resourceInfo = await resInfo.CreateEmptyResource(ResourceName.GetDirectory(), ResourceName.GetRootFolder(), createData);

                var pro = resourceInfo.GetType().GetProperty("ResourceType");
                pro?.SetValue(resourceInfo, EngineNS.Editor.Editor_RNameTypeAttribute.MaterialInstance);
                resourceInfo.ParentBrowser = this.ParentBrowser;
                await resourceInfo.Save(true);

                this.ParentBrowser.AddResourceInfo(resourceInfo);
                this.ParentBrowser.SelectResourceInfo(resourceInfo);
                await resourceInfo.InitializeContextMenu();
            };
            ResourceLibrary.Controls.Menu.MenuAssist.SetIcon(ciMenuItem, new BitmapImage(new System.Uri("pack://application:,,,/ResourceLibrary;component/Icons/Icons/AssetIcons/MaterialInstanceConstant_64x.png", UriKind.Absolute)));
            contextMenu.Items.Add(ciMenuItem);

            var duplicateMenuItem = new MenuItem()
            {
                Name   = "MatResInfo_Duplicate",
                Header = $"复制",
                Style  = menuItemStyle,
            };

            duplicateMenuItem.Click += async(object sender, RoutedEventArgs e) =>
            {
                var dir      = ResourceName.GetDirectory();
                var inputWin = new InputWindow.InputWindow();
                inputWin.Title       = $"复制{ResourceName.PureName()}";
                inputWin.Description = "输入材质名称";
                inputWin.Value       = EditorCommon.Program.GetValidName(dir, ResourceName.PureName(), EngineNS.CEngineDesc.MaterialExtension);
                if (inputWin.ShowDialog((value, cultureInfo) =>
                {
                    if (value == null)
                    {
                        return(new ValidationResult(false, "内容不合法"));
                    }
                    return(ResourceNameAvailable(dir, value.ToString()));
                }) == false)
                {
                    return;
                }

                var rc       = EngineNS.CEngine.Instance.RenderContext;
                var tagRName = EngineNS.RName.EditorOnly_GetRNameFromAbsFile(dir + inputWin.Value + EngineNS.CEngineDesc.MaterialExtension);
                // mat
                var mat = await EngineNS.CEngine.Instance.MaterialManager.GetMaterialAsync(rc, ResourceName);

                var matCopy = EngineNS.CEngine.Instance.MaterialManager.NewMaterial(tagRName);
                mat.CopyTo(matCopy);
                matCopy.SaveMaterial();
                // link
                var xndHolder = await EngineNS.IO.XndHolder.LoadXND(ResourceName.Address + EngineNS.Graphics.CGfxMaterial.ShaderLinkExtension);

                if (xndHolder != null)
                {
                    var container = new CodeGenerateSystem.Base.NodesContainer();
                    await container.Load(xndHolder.Node);

                    xndHolder.Node.TryReleaseHolder();

                    Controls.MaterialControl matCtrl = null;
                    foreach (var node in container.OrigionNodeControls)
                    {
                        if (node is Controls.MaterialControl)
                        {
                            node.Id = Guid.NewGuid();
                            matCtrl = node as Controls.MaterialControl;
                        }
                    }

                    System.IO.TextWriter codeFile, varFile;
                    CodeGenerator.GenerateCode(container, matCtrl, out codeFile, out varFile);

                    // var
                    System.IO.File.WriteAllText(tagRName.Address + EngineNS.Graphics.CGfxMaterial.ShaderDefineExtension, varFile.ToString());
                    // code
                    System.IO.File.WriteAllText(tagRName.Address + EngineNS.Graphics.CGfxMaterial.ShaderIncludeExtension, codeFile.ToString());
                    // link
                    var tagHolder = EngineNS.IO.XndHolder.NewXNDHolder();
                    container.Save(tagHolder.Node);
                    EngineNS.IO.XndHolder.SaveXND(tagRName.Address + EngineNS.Graphics.CGfxMaterial.ShaderLinkExtension, tagHolder);
                }
                // resInfo
                var copyedRInfo = new MaterialResourceInfo();
                copyedRInfo.ResourceName = tagRName;
                await CopyResource(copyedRInfo);

                await copyedRInfo.Save();

                // snapshot
                EngineNS.CEngine.Instance.FileManager.CopyFile(ResourceName.Address + EditorCommon.Program.SnapshotExt, tagRName.Address + EditorCommon.Program.SnapshotExt, true);
                await copyedRInfo.InitializeContextMenu();

                ParentBrowser.AddResourceInfo(copyedRInfo);
                ParentBrowser.SelectResourceInfo(copyedRInfo);
            };
            ResourceLibrary.Controls.Menu.MenuAssist.SetIcon(duplicateMenuItem, new BitmapImage(new System.Uri("pack://application:,,,/ResourceLibrary;component/Icons/Icons/icon_Edit_Duplicate_40x.png", UriKind.Absolute)));
            contextMenu.Items.Add(duplicateMenuItem);

            var menuItem = new MenuItem()
            {
                Name   = "MatResInfo_Delete",
                Header = "删除",
                Style  = menuItemStyle,
            };

            menuItem.Click += async(object sender, RoutedEventArgs e) =>
            {
                await DeleteResource();

                EngineNS.CEngine.Instance.MaterialManager.Materials.Remove(ResourceName);
            };
            ResourceLibrary.Controls.Menu.MenuAssist.SetIcon(menuItem, new BitmapImage(new System.Uri("pack://application:,,,/ResourceLibrary;component/Icons/Icons/icon_delete_16px.png", UriKind.Absolute)));
            contextMenu.Items.Add(menuItem);

            return(true);
        }