コード例 #1
0
        internal static AICanvas Deserialize(AIUI host, string data)
        {
            var canvasElement = SerializationMaster.Deserialize(data);

            var canvas = new AICanvas
            {
                offset = canvasElement.ValueOrDefault <Vector2>(ElementName.Offset),
                zoom   = canvasElement.ValueOrDefault(ElementName.Zoom, 1f)
            };

            var selectorViews = canvasElement.Elements(ElementName.SelectorView);

            foreach (var sve in selectorViews)
            {
                var sv = ReadSelectorView(sve, host);
                canvas.views.Add(sv);
            }

            var linkViews = canvasElement.Elements(ElementName.AILinkView);

            foreach (var lve in linkViews)
            {
                var lv = ReadAILinkView(lve, host);
                canvas.views.Add(lv);
            }

            return(canvas);
        }
コード例 #2
0
        private static void DeserializeAILinkViews(StageElement[] viewElements, AIUI targetUI, Vector2 referencePos, Vector2 mousePos, List <TopLevelView> newViews)
        {
            for (int i = 0; i < viewElements.Length; i++)
            {
                var lv = ReadAILinkView(viewElements[i], targetUI);

                //We only add an AI link if it does not already exist. Having two links to the same AI does not make sense.
                var existing = targetUI.FindAILink(other => other.aiId == lv.aiId);
                if (existing != null)
                {
                    continue;
                }

                // first treat the top-left-most selector as the origin point (reference pos)
                lv.viewArea.position -= referencePos;

                // secondly add the mouse offset to the position so as to paste it in where the mouse is at
                lv.viewArea.position += mousePos;

                targetUI.canvas.views.Add(lv);
                newViews.Add(lv);

                targetUI.undoRedo.Do(new AddAILinkOperation(targetUI, lv));
            }
        }
コード例 #3
0
        private static SelectorView ReadSelectorView(StageElement sve, AIUI parent)
        {
            var sv = new SelectorView
            {
                name        = sve.ValueOrDefault <string>(ElementName.Name),
                description = sve.ValueOrDefault <string>(ElementName.Description),
                viewArea    = sve.ValueOrDefault <Rect>(ElementName.ViewArea),
                parent      = parent
            };

            var defQv = sve.Element(ElementName.DefaultQualifier);

            sv.defaultQualifierView = defQv != null?ReadQualifierView(defQv, sv) : new QualifierView
            {
                parent = sv
            };

            var qualifierViews = sve.Elements(ElementName.QualifierView);

            foreach (var qve in qualifierViews)
            {
                var qv = ReadQualifierView(qve, sv);
                sv.qualifierViews.Add(qv);
            }

            return(sv);
        }
コード例 #4
0
        private void DrawAIUI(AIUI aiui)
        {
            HeaderHandler headerRects;

            if (EditorApplication.isPlaying)
            {
                headerRects = HeaderHandler.GetHeaderRects(0);
            }
            else
            {
                headerRects = HeaderHandler.GetHeaderRects(1);

                if (GUI.Button(headerRects.Next, SharedStyles.deleteTooltip, SharedStyles.BuiltIn.deleteButtonSmall))
                {
                    GUI.changed = false;
                    if (DisplayHelper.ConfirmDelete("AI", true))
                    {
                        AIEditorWindow.activeInstance.DeleteAI();
                        return;
                    }
                }
            }

            GUI.Label(headerRects.Next, string.Concat(_state.currentAIUI.name, " | APEX AI"), EditorStyling.Skinned.inspectorTitle);
        }
コード例 #5
0
ファイル: AIUI.cs プロジェクト: xwf20050250/Apex-Game-Tools
        internal static AIUI Create(string name)
        {
            var gui = new AIUI();

            gui.InitNew(name);
            gui.InitAI();

            return(gui);
        }
コード例 #6
0
        internal static void ShowCanvasMenu(AIUI ui, Vector2 mousePos)
        {
            var menu      = new GenericMenu();
            var screenPos = EditorGUIUtility.GUIToScreenPoint(mousePos);

            menu.AddItem(new GUIContent("Add Selector"), false, () => AIEntitySelectorWindow.Get <Selector>(screenPos, (selectorType) => { ui.AddSelector(mousePos, selectorType); }));
            menu.AddItem(new GUIContent("Add AI Link"), false, () => AISelectorWindow.Get(screenPos, (storedAI) => { ui.AddAILink(mousePos, storedAI.aiId); }));

            AddSharedItems(menu, ui, true, mousePos);
        }
コード例 #7
0
        private static AILinkView ReadAILinkView(StageElement lve, AIUI parent)
        {
            var lv = new AILinkView
            {
                name        = lve.ValueOrDefault <string>(ElementName.Name),
                description = lve.ValueOrDefault <string>(ElementName.Description),
                viewArea    = lve.ValueOrDefault <Rect>(ElementName.ViewArea),
                aiId        = lve.AttributeValue <Guid>(AttributeName.Id),
                parent      = parent
            };

            return(lv);
        }
コード例 #8
0
ファイル: AIUI.cs プロジェクト: xwf20050250/Apex-Game-Tools
        internal static AIUI Load(AIStorage ai, bool refreshState)
        {
            var gui = new AIUI();

            gui.name = ai.name;

            if (!gui.LoadFrom(ai, refreshState))
            {
                return(null);
            }

            return(gui);
        }
コード例 #9
0
 internal static void CopyToClipboard(AIUI sourceUI)
 {
     if (sourceUI.currentAction != null)
     {
         EditorGUIUtility.systemCopyBuffer = GuiSerializer.Serialize(sourceUI.currentAction);
     }
     else if (sourceUI.currentQualifier != null)
     {
         EditorGUIUtility.systemCopyBuffer = GuiSerializer.Serialize(sourceUI.currentQualifier);
     }
     else if (sourceUI.selectedViews.Count > 0)
     {
         EditorGUIUtility.systemCopyBuffer = GuiSerializer.Serialize(sourceUI.selectedViews);
     }
 }
コード例 #10
0
        internal static SelectorView Create(Type selectorType, AIUI parent, Rect viewArea)
        {
            if (!selectorType.IsSubclassOf(typeof(Selector)))
            {
                throw new ArgumentException("The proposed type is not a Selector.", "selectorType");
            }

            var sv = new SelectorView(viewArea);

            sv.parent               = parent;
            sv.selector             = Activator.CreateInstance(selectorType) as Selector;
            sv.defaultQualifierView = new QualifierView
            {
                qualifier = sv.selector.defaultQualifier,
                parent    = sv
            };

            return(sv);
        }
コード例 #11
0
        internal static void PasteFromClipboard(AIUI targetUi, Vector2 mousePos)
        {
            if (string.IsNullOrEmpty(EditorGUIUtility.systemCopyBuffer))
            {
                // nothing in the clipboard
                Debug.LogWarning("Could not paste from clipboard; clipboard is empty.");
                return;
            }

            try
            {
                GuiSerializer.DeserializeSnippet(EditorGUIUtility.systemCopyBuffer, targetUi, mousePos, true);
                targetUi.isDirty = true;
            }
            catch
            {
                Debug.LogWarning("Could not paste from clipboard; invalid data detected.");
            }
        }
コード例 #12
0
        internal static void CutToClipboard(AIUI sourceUI)
        {
            if (sourceUI.currentAction != null)
            {
                EditorGUIUtility.systemCopyBuffer = GuiSerializer.Serialize(sourceUI.currentAction);
                sourceUI.RemoveAction(sourceUI.currentAction);
            }
            else if (sourceUI.currentQualifier != null)
            {
                if (sourceUI.currentQualifier.isDefault)
                {
                    EditorUtility.DisplayDialog("Invalid Action", "The default qualifier cannot be cut. Use copy instead.", "Ok");
                    return;
                }

                EditorGUIUtility.systemCopyBuffer = GuiSerializer.Serialize(sourceUI.currentQualifier);
                sourceUI.RemoveQualifier(sourceUI.currentQualifier);
            }
            else if (sourceUI.selectedViews.Count > 0)
            {
                var selectedViews = sourceUI.selectedViews;
                var cutCount      = selectedViews.Count;
                for (int i = 0; i < cutCount; i++)
                {
                    var sv = selectedViews[i] as SelectorView;
                    if (sv != null && object.ReferenceEquals(sourceUI.rootSelector, sv.selector))
                    {
                        EditorUtility.DisplayDialog("Invalid Action", "The root selector can not be part of a cut operation.", "Ok");
                        return;
                    }
                }

                EditorGUIUtility.systemCopyBuffer = GuiSerializer.Serialize(sourceUI.selectedViews);

                using (sourceUI.undoRedo.bulkOperation)
                {
                    for (int i = cutCount - 1; i >= 0; i--)
                    {
                        sourceUI.RemoveView(selectedViews[i]);
                    }
                }
            }
        }
コード例 #13
0
        internal static void DeserializeSnippet(string data, AIUI targetUI, Vector2 mousePos, bool regenIds)
        {
            var root        = SerializationMaster.Deserialize(data);
            var snippetType = root.AttributeValue <string>(AttributeName.SnippetType);
            var aiElements  = root.Element(ElementName.AIPart).Elements().ToArray();

            if (snippetType == ElementName.ViewSnippet)
            {
                var uiPart       = root.Element(ElementName.UIPart);
                var referencePos = uiPart.ValueOrDefault(ElementName.ReferencePosition, Vector2.zero);

                var newViews = new List <TopLevelView>(uiPart.Items().Count());

                using (targetUI.undoRedo.bulkOperation)
                {
                    //Deserialize links first so that connections are not lost
                    var linkElements = uiPart.Elements(ElementName.AILinkView).ToArray();
                    DeserializeAILinkViews(linkElements, targetUI, referencePos, mousePos, newViews);

                    var selectorElements = uiPart.Elements(ElementName.SelectorView).ToArray();
                    DeserializeSelectorViews(aiElements, selectorElements, targetUI, referencePos, mousePos, newViews, regenIds);
                }

                targetUI.MultiSelectViews(newViews);
                return;
            }

            var viewElement = root.Element(ElementName.UIPart).Elements().First();

            if (snippetType == ElementName.QualifierSnippet)
            {
                DeserializeQualifier(aiElements[0], viewElement, targetUI);
            }
            else if (snippetType == ElementName.ActionSnippet)
            {
                DeserializeAction(aiElements[0], viewElement, targetUI);
            }
        }
コード例 #14
0
        internal static void ShowRuntimeViewMenu(AIUI ui, Vector2 mousePos)
        {
            if (!ui.isVisualizing)
            {
                return;
            }

            var menu      = new GenericMenu();
            var screenPos = EditorGUIUtility.GUIToScreenPoint(mousePos);

            if (ui.currentQualifier != null)
            {
                var visualizedQualifier = (IQualifierVisualizer)ui.currentQualifier.qualifier;
                if (visualizedQualifier.isBreakPoint)
                {
                    menu.AddItem(new GUIContent("Remove Breakpoint"), false, () => visualizedQualifier.isBreakPoint = false);
                }
                else
                {
                    menu.AddItem(new GUIContent("Set Breakpoint"), false, () => visualizedQualifier.isBreakPoint = true);
                }

                menu.AddItem(new GUIContent("Set Conditional Breakpoint"), false, () => BreakpointConditionWindow.Open(screenPos, visualizedQualifier));
            }
            else if (ui.currentSelector != null)
            {
                var visualizedSelector = (SelectorVisualizer)ui.currentSelector.selector;
                menu.AddItem(new GUIContent("Clear Breakpoints"), false, () => visualizedSelector.ClearBreakpoints());
            }
            else if (ui.currentAILink == null)
            {
                var visualizedAI = (UtilityAIVisualizer)ui.visualizedAI;
                menu.AddItem(new GUIContent("Clear All Breakpoints"), false, () => visualizedAI.ClearBreakpoints());
            }

            menu.ShowAsContext();
        }
コード例 #15
0
        internal bool Reconnect(Selector s)
        {
            this.selector = s;

            var defQv = this.defaultQualifierView;

            defQv.qualifier = s.defaultQualifier;
            if (defQv.actionView != null)
            {
                //If an action view is present bug the action is null, this means inconsistency between config end editor config
                //While this should not occur, we still handle it just in case.
                if (defQv.qualifier.action == null)
                {
                    defQv.actionView = null;
                }
                else
                {
                    defQv.actionView.action = defQv.qualifier.action;
                }
            }

            var qualifiers     = s.qualifiers;
            int qualifierCount = qualifiers.Count;

            if (!AIUI.VerifyCountMatch(qualifierCount, this.qualifierViews.Count))
            {
                return(false);
            }

            for (int j = 0; j < qualifierCount; j++)
            {
                var qv = this.qualifierViews[j];
                qv.Reconnect(qualifiers[j]);
            }

            return(true);
        }
コード例 #16
0
        private static void DeserializeAction(StageElement aiElement, StageElement viewElement, AIUI targetUI)
        {
            var parent = targetUI.currentQualifier;

            if (parent == null)
            {
                EditorUtility.DisplayDialog("Invalid Action", "You must select a Qualifier before pasting an Action.", "Ok");
            }
            else if (parent.actionView != null)
            {
                if (!EditorUtility.DisplayDialog("Confirm Replace", "The selected Qualifier already has an action, do you wish to replace it?", "Yes", "No"))
                {
                    return;
                }
            }

            var requiresInit = new List <IInitializeAfterDeserialization>();

            var actionView = ReadActionView(viewElement, parent);
            var action     = SerializationMaster.Unstage <IAction>(aiElement, requiresInit);

            actionView.action = action;

            //Do the post deserialize initialization here
            if (requiresInit.Count == 1)
            {
                requiresInit[0].Initialize(targetUI.ai);
            }

            targetUI.SetAction(actionView, parent);
            parent.PruneBrokenConnections();
        }
コード例 #17
0
        private static bool ExecuteCommand(string cmd, int delay)
        {
            var ais = selectedAIs.ToArray();

            if (ais.Length == 0)
            {
                return(false);
            }

            bool consumeEvent = false;

            switch (cmd)
            {
            case "Open":
            {
                _pendingAction = () =>
                {
                    for (int i = 0; i < ais.Length; i++)
                    {
                        AIEditorWindow.Open(ais[i].aiId);
                    }
                };

                consumeEvent = true;
                break;
            }

            case "Delete":
            case "SoftDelete":
            {
                //reload all windows with deleted ais
                var aisBefore = StoredAIs.AIs.ToArray();
                _pendingAction = () =>
                {
                    StoredAIs.Refresh();
                    var aisAfter   = StoredAIs.AIs.ToArray();
                    var deletedIds = aisBefore.Except(aisAfter).Select(ai => ai.aiId).ToArray();

                    AIEditorWindow.Unload(deletedIds);
                };

                break;
            }

            case "Duplicate":
            {
                //identify all additions and re-ID them.
                var aisBefore = StoredAIs.AIs.ToArray();
                _pendingAction = () =>
                {
                    StoredAIs.Refresh();
                    var aisAfter = StoredAIs.AIs.ToArray();
                    var addedAis = aisAfter.Except(aisBefore);
                    foreach (var copiedAI in addedAis)
                    {
                        var ui = AIUI.Load(copiedAI, false);
                        if (ui != null)
                        {
                            ui.ai.RegenerateIds();
                            copiedAI.aiId = ui.ai.id.ToString();
                            ui.Save(null);
                        }
                        else
                        {
                            var path = AssetDatabase.GetAssetPath(copiedAI);
                            AssetDatabase.DeleteAsset(path);
                        }
                    }
                };

                break;
            }
            }

            EditorAsync.ExecuteDelayed(
                () =>
            {
                _pendingAction();
                _pendingAction = null;
            },
                delay);

            return(consumeEvent);
        }
コード例 #18
0
        private static void DeserializeQualifier(StageElement aiElement, StageElement viewElement, AIUI targetUI)
        {
            var parent = targetUI.currentSelector;

            if (parent == null)
            {
                EditorUtility.DisplayDialog("Invalid Action", "You must select a Selector before pasting a Qualifier.", "Ok");
            }

            var requiresInit = new List <IInitializeAfterDeserialization>();

            var qualifierView = ReadQualifierView(viewElement, parent);
            var qualifier     = SerializationMaster.Unstage <IQualifier>(aiElement, requiresInit);

            qualifierView.Reconnect(qualifier);

            //Do the post deserialize initialization here
            if (requiresInit.Count == 1)
            {
                requiresInit[0].Initialize(targetUI.ai);
            }

            qualifierView.PruneBrokenConnections();

            if (qualifierView.isDefault)
            {
                if (EditorUtility.DisplayDialog("Confirm Replacement", "Do you wish to replace the current Default Qualifier?", "Yes", "No"))
                {
                    targetUI.ReplaceDefaultQualifier(qualifierView, parent);
                }
            }
            else
            {
                targetUI.AddQualifier(qualifierView, parent);
            }
        }
コード例 #19
0
        private static void DeserializeSelectorViews(StageElement[] aiElements, StageElement[] viewElements, AIUI targetUI, Vector2 referencePos, Vector2 mousePos, List <TopLevelView> newViews, bool regenIds)
        {
            var requiresInit = new List <IInitializeAfterDeserialization>();

            var selectorViews = new List <SelectorView>(aiElements.Length);

            for (int i = 0; i < aiElements.Length; i++)
            {
                var selectorView = ReadSelectorView(viewElements[i], targetUI);
                var selector     = SerializationMaster.Unstage <Selector>(aiElements[i], requiresInit);

                targetUI.canvas.views.Add(selectorView);
                targetUI.ai.AddSelector(selector);

                selectorView.Reconnect(selector);

                selectorViews.Add(selectorView);
                newViews.Add(selectorView);

                targetUI.undoRedo.Do(new AddSelectorOperation(targetUI, selectorView));
            }

            //Set the root if pasting to a blank canvas
            if (targetUI.ai.rootSelector == null)
            {
                targetUI.ai.rootSelector = selectorViews[0].selector;
                targetUI.undoRedo.Do(new SetRootOperation(targetUI, null, selectorViews[0].selector));
            }

            //Do the post deserialize initialization here
            var count = requiresInit.Count;

            for (int i = 0; i < count; i++)
            {
                requiresInit[i].Initialize(targetUI.ai);
            }

            //Finally adjust the positioning of pasted elements and prune broken connections, i.e. SelectorAction that no longer points to a selector
            for (int i = 0; i < aiElements.Length; i++)
            {
                var selectorView = selectorViews[i];

                selectorView.PruneBrokenConnections();

                if (regenIds)
                {
                    //We also regen the id since this allows for pasting the same copy multiple times
                    selectorView.selector.RegenerateId();
                }

                // first treat the top-left-most selector as the origin point (reference pos)
                selectorView.viewArea.position -= referencePos;

                // secondly add the mouse offset to the position so as to paste it in where the mouse is at
                selectorView.viewArea.position += mousePos;
            }
        }
コード例 #20
0
        private static void AddSharedItems(GenericMenu menu, AIUI ui, bool allowDelete, Vector2 mousePos)
        {
            if (menu.GetItemCount() > 0)
            {
                menu.AddSeparator(string.Empty);
            }

            if (ui.undoRedo.canUndo)
            {
                menu.AddItem(new GUIContent(string.Concat("Undo (", ctrlOrCmd, " + Shift + Z)")), false, () => ui.undoRedo.Undo());
            }
            else
            {
                menu.AddDisabledItem(new GUIContent(string.Concat("Undo (", ctrlOrCmd, " + Shift + Z)")));
            }

            if (ui.undoRedo.canRedo)
            {
                menu.AddItem(new GUIContent(string.Concat("Redo (", ctrlOrCmd, " + Shift + Y)")), false, () => ui.undoRedo.Redo());
            }
            else
            {
                menu.AddDisabledItem(new GUIContent(string.Concat("Redo (", ctrlOrCmd, " + Shift + Y)")));
            }

            menu.AddSeparator(string.Empty);
            var hasSelection = ui.selectedViews.Count > 0 || ui.currentAction != null || ui.currentQualifier != null || ui.currentSelector != null;

            if (hasSelection)
            {
                menu.AddItem(new GUIContent(string.Concat("Cut (", ctrlOrCmd, " + X)")), false, () => ClipboardService.CutToClipboard(ui));
                menu.AddItem(new GUIContent(string.Concat("Copy (", ctrlOrCmd, " + C)")), false, () => ClipboardService.CopyToClipboard(ui));
                menu.AddItem(new GUIContent(string.Concat("Duplicate (", ctrlOrCmd, " + D)")), false, () => ClipboardService.Duplicate(ui, mousePos));
            }
            else
            {
                menu.AddDisabledItem(new GUIContent(string.Concat("Cut (", ctrlOrCmd, " + X)")));
                menu.AddDisabledItem(new GUIContent(string.Concat("Copy (", ctrlOrCmd, " + C)")));
                menu.AddDisabledItem(new GUIContent(string.Concat("Duplicate (", ctrlOrCmd, " + D)")));
            }

            if (!string.IsNullOrEmpty(EditorGUIUtility.systemCopyBuffer))
            {
                menu.AddItem(new GUIContent(string.Concat("Paste (", ctrlOrCmd, " + V)")), false, () => ClipboardService.PasteFromClipboard(ui, mousePos));
            }
            else
            {
                menu.AddDisabledItem(new GUIContent(string.Concat("Paste (", ctrlOrCmd, " + V)")));
            }

            menu.AddSeparator(string.Empty);
            menu.AddItem(new GUIContent(string.Concat("Select All (", ctrlOrCmd, " + A)")), false, () => ui.MultiSelectViews(ui.canvas.views));

            if (allowDelete)
            {
                menu.AddSeparator(string.Empty);
                if (hasSelection)
                {
                    menu.AddItem(new GUIContent("Delete (Del)"), false, () => ui.RemoveSelected());
                }
                else
                {
                    menu.AddDisabledItem(new GUIContent("Delete (Del)"));
                }
            }

            menu.ShowAsContext();
        }
コード例 #21
0
        internal static void ShowViewMenu(AIUI ui, Vector2 mousePos)
        {
            var  menu        = new GenericMenu();
            var  screenPos   = EditorGUIUtility.GUIToScreenPoint(mousePos);
            bool allowDelete = true;

            if (ui.currentAction != null)
            {
                var           qv = ui.currentQualifier;
                Action <Type> cb = (t) =>
                {
                    var newInstance = (IAction)Activator.CreateInstance(t);
                    ui.ReplaceAction(qv, newInstance);
                };

                menu.AddItem(new GUIContent("Change Type"), false, () => AIEntitySelectorWindow.Get <IAction>(screenPos, cb));
            }
            else if (ui.currentQualifier != null)
            {
                string label = (ui.currentAction == null && ui.currentQualifier.actionView == null) ? "Add Action" : "Replace Action";
                menu.AddItem(new GUIContent(label), false, () => AIEntitySelectorWindow.Get <IAction>(screenPos, (actionType) => { ui.SetAction(actionType); }));
                menu.AddItem(new GUIContent("Add Qualifier (sibling)"), false, () => AIEntitySelectorWindow.Get <IQualifier>(screenPos, (qualifierType) => { ui.AddQualifier(qualifierType); }));

                var qv = ui.currentQualifier;
                if (qv.isDefault)
                {
                    allowDelete = false;
                }
                else
                {
                    Action <Type> cb = (t) =>
                    {
                        var newInstance = (IQualifier)Activator.CreateInstance(t);
                        ui.ReplaceQualifier(qv, newInstance);
                    };

                    menu.AddSeparator(string.Empty);
                    menu.AddItem(new GUIContent("Change Type"), false, () => AIEntitySelectorWindow.Get <IQualifier>(screenPos, cb));
                }
            }
            else if (ui.currentSelector != null)
            {
                var sv = ui.currentSelector;
                menu.AddItem(new GUIContent("Add Qualifier"), false, () => AIEntitySelectorWindow.Get <IQualifier>(screenPos, (qualifierType) => { ui.AddQualifier(qualifierType); }));
                menu.AddSeparator(string.Empty);

                if (sv.isRoot)
                {
                    allowDelete = false;
                }
                else
                {
                    menu.AddItem(new GUIContent("Set as Root"), false, () => ui.SetRoot(sv.selector));
                }

                Action <Type> cb = (t) =>
                {
                    var newInstance = (Selector)Activator.CreateInstance(t);
                    ui.ReplaceSelector(sv, newInstance);
                };

                menu.AddItem(new GUIContent("Change Type"), false, () => AIEntitySelectorWindow.Get <Selector>(screenPos, cb));
            }
            else if (ui.currentAILink != null)
            {
                var alv = ui.currentAILink;
                Action <AIStorage> cb = (ai) =>
                {
                    ui.ChangeAILink(alv, new Guid(ai.aiId));
                };

                menu.AddItem(new GUIContent("Change AI"), false, () => AISelectorWindow.Get(screenPos, cb));
            }

            AddSharedItems(menu, ui, allowDelete, mousePos);
        }
コード例 #22
0
 internal static void Duplicate(AIUI sourceUI, Vector2 mousePos)
 {
     CopyToClipboard(sourceUI);
     PasteFromClipboard(sourceUI, mousePos);
 }