public ParameterEditorSetupData(IParameter parameter, ILocalizationEngine localizer, IAudioParameterEditorCallbacks audioProvider, AudioGenerationParameters audioGenerationParameters, Func <string, IEnumerable <string> > autoCompleteSuggestions) { m_parameter = parameter; m_localizer = localizer; m_audioProvider = audioProvider; m_audioGenerationParameters = audioGenerationParameters; m_autoCompleteSuggestions = autoCompleteSuggestions; }
public void Setup(ParameterEditorSetupData data) { m_parameter = data.Parameter as ILocalizedStringParameter; m_localizer = data.Localizer; if (!m_parameter.Corrupted) { m_textBox.Text = m_localizer.Localize(Id <LocalizedStringType> .FromGuid(m_parameter.TypeId.Guid), m_parameter.Value); } else { m_textBox.Text = m_localizer.Localize(null, null); } if (!m_localizer.CanLocalize(Id <LocalizedStringType> .ConvertFrom(m_parameter.TypeId))) { m_textBox.InputForm = MyTextBox.InputFormEnum.None; } m_autoCompleteSuggestions = data.AutoCompleteSuggestions; }
public override ConfigureResult2 Edit(IColorScheme scheme, IConversationNodeData node, AudioGenerationParameters audioContext, Func <ParameterType, ParameterEditorSetupData, IParameterEditor> config, ILocalizationEngine localizer, IAudioParameterEditorCallbacks audioProvider, AutoCompleteSuggestionsDelegate autoCompleteSuggestions) { if (node.Parameters.Any()) { return(NodeEditor.Edit(scheme, node, audioContext, config, localizer, audioProvider, autoCompleteSuggestions)); } else { return(ConfigureResult2.NotApplicable); } }
public NodeEditor(IColorScheme scheme, IConversationNodeData data, AudioGenerationParameters audioContext, Func <ParameterType, ParameterEditorSetupData, IParameterEditor> config, ILocalizationEngine localizer, IAudioParameterEditorCallbacks audioProvider, AutoCompleteSuggestionsDelegate autoCompleteSuggestions) : this() { Scheme = scheme; m_data = data; this.SuspendLayout(); flowLayoutPanel1.SuspendLayout(); flowLayoutPanel2.SuspendLayout(); if (!string.IsNullOrEmpty(data.Description)) { int padding = 8; m_descriptionBox = new MyTextBox(panel1, () => new RectangleF(panel1.Location.Plus(padding, padding), new SizeF(panel1.Width - padding * 2, panel1.Height - padding * 2)), MyTextBox.InputFormEnum.None, null, x => new SimpleTextBoxBorderDrawer(x), 8, Fonts.Default); m_descriptionBox.Text = data.Description; MyTextBox.SetupCallbacks(panel1, m_descriptionBox); panel1.Size = m_descriptionBox.RequestedArea.ToSize(); panel1.SizeChanged += (object sender, EventArgs e) => { var requested = m_descriptionBox.RequestedArea.ToSize(); panel1.Size = new Size(requested.Width + padding * 2, requested.Height + padding * 2); }; } else { panel1.Height = 0; } //Make the panels really tall so they can visibly contain all the parameter editors. //Note the whole control won't be visible as we'll scroll them by shifting them in Y. flowLayoutPanel1.Height = 10000; flowLayoutPanel2.Height = 10000; Title = m_data.Name; foreach (Parameter p in m_data.Parameters.OrderByDescending(p => p.Name)) { var editorData = new ParameterEditorSetupData(p, localizer, audioProvider, audioContext, (s) => autoCompleteSuggestions(p, s)); if (p is UnknownParameter unknown) { UnknownParameterEditor ed = null; Label label = null; ed = UnknownParameterEditor.Make(Scheme, editorData, m_data.RemoveUnknownParameter(unknown), () => { flowLayoutPanel2.Controls.Remove(ed); flowLayoutPanel1.Controls.Remove(label); SetupScrollbar(); }); label = AddParameter(p, ed); } else { AddParameter(p, config(p.TypeId, editorData)); } } flowLayoutPanel1.ResumeLayout(); flowLayoutPanel2.ResumeLayout(); SetupScrollbar(); if (flowLayoutPanel1.Controls.Count > 0) { EventHandler SizeChanged = (a, b) => { NeedsResize.Execute(); DoResize(); }; flowLayoutPanel2.Controls[0].LocationChanged += SizeChanged; flowLayoutPanel2.Controls[0].SizeChanged += SizeChanged; panel1.SizeChanged += SizeChanged; } ; this.ResumeLayout(); this.splitContainer1.Panel2.SizeChanged += Panel2_SizeChanged; if (flowLayoutPanel2.Controls.Count > 0) { for (int i = flowLayoutPanel2.Controls.Count - 1; i >= 0; i--) { (flowLayoutPanel2.Controls[i] as Panel).TabStop = true; (flowLayoutPanel2.Controls[i] as Panel).TabIndex = flowLayoutPanel2.Controls.Count - i - 1; } } }
public virtual IEnumerable <MenuAction <ConversationNode> > GetMenuActions(IGraphEditorControl <ConversationNode> control, IProject2 project, Action <IEnumerable <IErrorListElement> > log, ILocalizationEngine localizer) { MenuAction <ConversationNode> addNodes = new MenuAction <ConversationNode>("Add Node", (n, p) => null, null, null, p => { }); AddNodeMenuItem(addNodes, control.DataSource.Nodes, control); yield return(addNodes); yield return(new MenuAction <ConversationNode>("Reset Zoom", (n, p) => null, null, null, (p) => { control.GraphScale = 1; })); yield return(new MenuAction <ConversationNode>("Paste", (n, p) => null, null, null, (p) => { control.Paste(p); })); yield return(new MenuAction <ConversationNode>("Delete", (n, p) => () => { control.CurrentFile.Remove(n.Only(), Enumerable.Empty <NodeGroup>(), localizer); }, null, null, null)); yield return(new MenuAction <ConversationNode>("Remove Links", (n, p) => () => { foreach (var c in n.Data.Connectors) { control.CurrentFile.RemoveLinks(c); } }, (i, p) => { control.CurrentFile.RemoveLinks(i); }, null, null)); yield return(new MenuAction <ConversationNode>("Copy ID", (n, p) => control.ShowIds ? () => Clipboard.SetText(n.Data.NodeId.Serialized()) : (Action)null, null, null, null)); }
public Tuple <IEnumerable <ConversationNode>, IEnumerable <NodeGroup> > InsertInto(IEnumerable <GraphAndUI <NodeUIData> > nodeData, IEnumerable <NodeGroup> groups, PointF location, ILocalizationEngine localization) { var nodes = nodeData.Select(gnu => MakeNode(gnu.GraphData, gnu.UIData)).Evaluate(); var area = NodeSet.GetArea(nodes.Concat <IRenderable <IGui> >(groups)); PointF offset = location.Take(area.Center()); foreach (var node in nodes) { node.Renderer.Offset(offset); } foreach (var group in groups) { group.Renderer.Offset(offset); } SimpleUndoPair addActions = InnerAddNodes(nodes, groups, localization); UndoableFile.Change(new GenericUndoAction(addActions, "Pasted")); return(Tuple.Create(nodes, groups)); }
public Tuple <IEnumerable <ConversationNode>, IEnumerable <NodeGroup> > InsertInto(IEnumerable <Conversation.Serialization.GraphAndUI <NodeUIData> > nodeData, IEnumerable <NodeGroup> groups, System.Drawing.PointF location, ILocalizationEngine localization) => throw new NotSupportedException();
public void Add(IEnumerable <ConversationNode> nodes, IEnumerable <NodeGroup> groups, ILocalizationEngine localization) { throw new NotImplementedException(); }
public IEnumerable <MenuAction <ConversationNode> > GetMenuActions(IGraphEditorControl <ConversationNode> control, IProject2 project, Action <IEnumerable <IErrorListElement> > log, ILocalizationEngine localizer) { yield return(new MenuAction <ConversationNode>("Reset Zoom", (n, p) => null, null, null, (p) => { control.GraphScale = 1; })); //yield return new MenuAction2<ConversationNode>("Delete", (n, p) => () => { Delete(n); }, null, null, null); //yield return new MenuAction2<ConversationNode>("Remove Links", (n, p) => null, (i, p) => { control.CurrentFile.RemoveLinks(i); }, null, null); }
Tuple <IEnumerable <TNode>, IEnumerable <NodeGroup> > IConversationEditorControlData <TNode, TTransitionUI> .InsertInto(IEnumerable <Conversation.Serialization.GraphAndUI <NodeUIData> > nodeData, IEnumerable <NodeGroup> groups, System.Drawing.PointF location, ILocalizationEngine localization) => throw new NotSupportedException();
public IEnumerable <MenuAction <ConversationNode> > GetMenuActions(IGraphEditorControl <ConversationNode> control, IProject2 project, Action <IEnumerable <IErrorListElement> > log, ILocalizationEngine localizer) { XmlGraphData <NodeUIData, ConversationEditorData> data; Assembly assembly = Assembly.GetExecutingAssembly(); using (Stream stream = assembly.GetManifestResourceStream("Clandestine.Templates.Basic Conversation.xml")) { data = SerializationUtils.ConversationDeserializer(control.DataSource).Read(stream); } yield return(new MenuAction <ConversationNode>("Basic Conversation", (a, b) => null, null, null, p => { control.Insert(p, Tuple.Create(data.Nodes, data.EditorData.Groups, new object(), true)); })); }
public bool Remove(IEnumerable <ConversationNode> nodes, IEnumerable <NodeGroup> groups, ILocalizationEngine localization) { nodes = nodes.ToList(); groups = groups.ToList(); bool removeNodes = nodes.Any(); bool removeGroups = groups.Any(); List <Action> undoActions = new List <Action>(); List <Action> redoActions = new List <Action>(); if (nodes.Any(n => !CanRemoveFromData(n, () => false))) { if (!PromptNodeDeletion()) { return(false); } } if (removeNodes) { //Make sure all the nodes are added before trying to link them foreach (var node in nodes) { var n = node; undoActions.Add(() => { m_nodes.Add(n); }); } foreach (var node in nodes) { var n = node; var actions = n.GetNodeRemoveActions(); //Ensure that the localization engine is up to date in terms of usage of localized data foreach (var parameter in n.Data.Parameters.OfType <ILocalizedStringParameter>()) { SimpleUndoPair clearLocalization = localization.ClearLocalizationAction(Id <LocalizedStringType> .ConvertFrom(parameter.TypeId), parameter.Value); undoActions.Add(clearLocalization.Undo); redoActions.Add(clearLocalization.Redo); } var containingGroups = m_groups.Where(g => g.Contents.Contains(n.Data.NodeId)).Evaluate(); undoActions.Add(() => { actions.Undo(); //Connect after adding the node foreach (var group in containingGroups) { group.Contents.Add(n.Data.NodeId); } m_audioProvider.UpdateUsage(n); }); redoActions.Add(() => { actions.Redo(); //Disconnect before removing the node m_nodes.Remove(n); foreach (var group in containingGroups) { group.Contents.Remove(n.Data.NodeId); } NodesDeleted.Execute(); }); } } if (removeGroups) { List <NodeGroup> toAdd = new List <NodeGroup>(groups); undoActions.Add(() => { m_groups.AddRange(toAdd); }); redoActions.Add(() => { m_groups.RemoveRange(toAdd); }); } Action undo = () => { using (m_audioProvider.SuppressUpdates()) foreach (Action action in undoActions) { action(); } }; Action redo = () => { using (m_audioProvider.SuppressUpdates()) foreach (Action action in redoActions) { action(); } }; string message; if (removeNodes && removeGroups) { message = "Deleted elements"; } else if (removeNodes) { message = "Deleted nodes"; } else if (removeGroups) { message = "Removed groupings"; } else { throw new InternalLogicException("Something went wrong :("); } UndoableFile.Change(new GenericUndoAction(undo, redo, message)); return(true); }
private SimpleUndoPair InnerAddNodes(IEnumerable <ConversationNode> nodes, IEnumerable <NodeGroup> groups, ILocalizationEngine localization) { List <Action> undoActions = new List <Action>(); List <Action> redoActions = new List <Action>(); //Set up actions for adding/removing the nodes foreach (var node in nodes) { var n = node; SimpleUndoPair actions = n.GetNodeRemoveActions(); //Ensure that the localization engine is up to date in terms of usage of localized data foreach (var parameter in n.Data.Parameters.OfType <ILocalizedStringParameter>()) { if (parameter.Value != null) { SimpleUndoPair clearLocalization = localization.ClearLocalizationAction(Id <LocalizedStringType> .ConvertFrom(parameter.TypeId), parameter.Value); undoActions.Add(clearLocalization.Redo); redoActions.Add(clearLocalization.Undo); } } var containingGroups = m_groups.Where(g => g.Contents.Contains(n.Data.NodeId)).Evaluate(); redoActions.Add(() => { m_nodes.Add(n); m_audioProvider.UpdateUsage(n); foreach (var group in containingGroups) { group.Contents.Add(n.Data.NodeId); } actions.Undo(); //Undo the node removal }); undoActions.Add(() => { if (CanRemoveFromData(n, PromptNodeDeletion)) { m_nodes.Remove(n); } foreach (var group in containingGroups) { group.Contents.Remove(n.Data.NodeId); } actions.Redo(); //Redo the node removal NodesDeleted.Execute(); }); } //Set up actions for adding/removing nodes from other groups that are gaining/losing their grouping due to removing/adding new groups foreach (var group in groups) { foreach (var node in group.Contents) { var n = node; var old = m_groups.SingleOrDefault(g => g.Contents.Contains(n)); if (old != null) { undoActions.Add(() => old.Contents.Add(n)); redoActions.Add(() => old.Contents.Remove(n)); } } } //Set up actions for adding/removing the groups undoActions.Add(() => { foreach (var group in groups.Reverse()) { m_groups.Remove(group); } }); redoActions.Add(() => { m_groups.AddRange(groups); }); return(new SimpleUndoPair { Undo = () => { using (m_audioProvider.SuppressUpdates()) foreach (Action action in undoActions) { action(); } }, Redo = () => { using (m_audioProvider.SuppressUpdates()) foreach (Action action in redoActions) { action(); } }, }); }
public void Add(IEnumerable <ConversationNode> nodes, IEnumerable <NodeGroup> groups, ILocalizationEngine localization) { nodes = nodes.Evaluate(); groups = groups.ToList(); SimpleUndoPair addActions = InnerAddNodes(nodes, groups, localization); bool addedNodes = nodes.Any(); bool addedGroups = groups.Any(); if (addedNodes && addedGroups) { UndoableFile.Change(new GenericUndoAction(addActions.Undo, addActions.Redo, "Added nodes and groups")); } else if (addedNodes) { UndoableFile.Change(new GenericUndoAction(addActions.Undo, addActions.Redo, "Added nodes")); } else if (addedGroups) { UndoableFile.Change(new GenericUndoAction(addActions.Undo, addActions.Redo, "Added groups")); } else { throw new InternalLogicException("why would you do this?"); } }
//TODO: Duplicate the IEditable with a new ID (must be deep copy of parameters) public Tuple <IEnumerable <ConversationNode>, IEnumerable <NodeGroup> > DuplicateInto(IEnumerable <GraphAndUI <NodeUIData> > nodeData, IEnumerable <NodeGroup> groups, PointF location, ILocalizationEngine localization) { var nodes = nodeData.Select(gnu => MakeNode(gnu.GraphData, gnu.UIData)).Evaluate(); IEnumerable <IDynamicEnumParameter> localDynamicEnumerationParameters = nodes.SelectMany(n => n.Data.Parameters.OfType <IDynamicEnumParameter>().Where(p => p.Local)); foreach (var ldep in localDynamicEnumerationParameters) { ldep.MergeInto(m_getDocumentSource(ldep)); } if (nodes.Any() || groups.Any()) { List <Action> undoActions = new List <Action>(); List <Action> redoActions = new List <Action>(); //Changes to these nodes don't need to be undoable as they're new nodes foreach (var node in nodes) { //Duplicate the id of any localized string parameters to avoid the new node using the same id(s) as the old one foreach (var p in node.Data.Parameters.OfType <LocalizedStringParameter>()) { var result = localization.DuplicateActions(p.Value); var action = p.SetValueAction(result.Item1); if (action != null) { //Don't this node is a duplicate of another. The old node's localization data is irrelevant. We should never return to it. //undoActions.Add(action.Value.Undo); redoActions.Add(action.Value.Redo); action.Value.Redo(); //Change the value immediately. The old value is irrelevant and we should never return to it. } result.Item2.Redo(); //Add the localization immediately. Otherwise when adding the node we won't know how to undo deletion of the node's localization data. undoActions.Add(result.Item2.Undo); redoActions.Add(result.Item2.Redo); } //TODO: AUDIO: Do we want to treat audio parameters like strings in that they have a meaningful value // or like localized strings in that they are a key into another system? //foreach (var p in node.Data.Parameters.OfType<IAudioParameter>()) //{ // //No need to update audio usage as this will occur when the node is added/removed // var audio = m_generateAudio(this); // var actions = p.SetValueAction(audio); //TODO: AUDIO: Investigate what happens to Audio parameter usage if you duplicate a node and then undo // undoActions.Add(actions.Value.Undo); // redoActions.Add(actions.Value.Redo); //} //foreach (var p in node.Data.Parameters.OfType<IAudioParameter>()) //{ // var action = p.SetValueAction(new Audio(Guid.NewGuid().ToString())); // if (action != null) // action.Value.Redo(); //If we undo the whole operation the parameter wont exist so no need to ever undo this value change. //} var oldID = node.Data.NodeId; node.Data.ChangeId(Id <NodeTemp> .New()); foreach (var group in groups) { if (group.Contents.Contains(oldID)) { group.Contents.Remove(oldID); group.Contents.Add(node.Data.NodeId); } } } var area = NodeSet.GetArea(nodes.Concat <IRenderable <IGui> >(groups)); PointF offset = location.Take(area.Center()); foreach (var node in nodes) { node.Renderer.Offset(offset); } foreach (var group in groups) { group.Renderer.Offset(offset); } SimpleUndoPair addActions = InnerAddNodes(nodes, groups, localization); Action undo = () => { undoActions.ForEach(a => a()); addActions.Undo(); }; Action redo = () => { redoActions.ForEach(a => a()); addActions.Redo(); }; UndoableFile.Change(new GenericUndoAction(undo, redo, "Pasted")); } return(Tuple.Create(nodes, groups)); }
public static ConfigureResult2 Edit(IColorScheme scheme, IConversationNodeData data, AudioGenerationParameters audioContext, Func <ParameterType, ParameterEditorSetupData, IParameterEditor> config, ILocalizationEngine localizer, IAudioParameterEditorCallbacks audioProvider, AutoCompleteSuggestionsDelegate autoCompleteSuggestions) { using (Form f = new Form()) { NodeEditor editor = new NodeEditor(scheme, data, audioContext, config, localizer, audioProvider, autoCompleteSuggestions); f.Text = editor.Title; bool oked = false; editor.Ok += () => { var invalid = editor.m_parameterEditors.Select(e => new { Name = e.Item2.Name, Message = e.Item1.IsValid() }).Where(e => e.Message != null); if (!invalid.Any()) { oked = true; f.Close(); } else { string message = "Invalid values specified for the following parameters:"; foreach (var i in invalid) { message += "\n"; message += i.Name + ": "; message += i.Message; } MessageBox.Show(message); } }; editor.Cancel += () => { oked = false; f.Close(); }; editor.Dock = DockStyle.Fill; int maxHeight = editor.MaximumHeight + f.Height - f.ClientSize.Height; int minHeight = editor.MinimumHeight + f.Height - f.ClientSize.Height; f.MaximumSize = new Size(999999, maxHeight); f.MinimumSize = new Size(0, minHeight); editor.NeedsResize += () => { bool resize = false; if (f.Size.Height == f.MaximumSize.Height || f.Size.Height == f.MinimumSize.Height) { resize = true; } int max = editor.MaximumHeight + f.Height - f.ClientSize.Height; int min = editor.MinimumHeight + f.Height - f.ClientSize.Height; f.MaximumSize = new Size(999999, max); f.MinimumSize = new Size(0, min); if (resize) { f.Size = new Size(f.Size.Width, max); } }; f.Size = new Size(500, 478); f.Controls.Add(editor); f.ShowDialog(); if (oked) { var updates = editor.m_parameterEditors.Select(e => e.Item1.UpdateParameterAction()); return(new ConfigureResult2(updates.ToArray())); } else { return(ConfigureResult.Cancel); } } }
public abstract ConfigureResult2 Edit(IColorScheme scheme, IConversationNodeData node, AudioGenerationParameters audioContext, Func <ParameterType, ParameterEditorSetupData, IParameterEditor> config, ILocalizationEngine localizer, IAudioParameterEditorCallbacks audioProvider, AutoCompleteSuggestionsDelegate autoCompleteSuggestions);
public LogElement(IConversationEditorControlData <ConversationNode <INodeGui>, TransitionNoduleUIInfo> file, ConversationNode <INodeGui> node, ILocalizationEngine localizer) { File = file; m_node = node; m_localize = localizer.Localize; }
public LocalizationManager(ILocalizationEngine engine) { _engine = engine ?? throw new ArgumentNullException(nameof(engine)); }
public IEnumerable <MenuAction <ConversationNode <INodeGui> > > GetMenuActions(IGraphEditorControl <ConversationNode <INodeGui> > control, IProject2 project, Action <IEnumerable <IErrorListElement> > log, ILocalizationEngine localizer) { //XmlGraphData<NodeUIData, ConversationEditorData> data; //Assembly assembly = Assembly.GetExecutingAssembly(); //using (Stream stream = assembly.GetManifestResourceStream("PluginPack.Templates.Basic Conversation.xml")) //{ // data = SerializationUtils.ConversationDeserializer(control.DataSource).Read(stream); //} yield return(new MenuAction <ConversationNode>("Find Nodes of Type", (a, b) => () => { var nodesofType = project.ConversationFilesCollection.SelectMany(f => f.Nodes.Where(n => n.Data.NodeTypeId == a.Data.NodeTypeId).Select(n => new { Node = n, File = f })); log(nodesofType.Select(n => new LogElement(n.File, n.Node, localizer))); } , null, null, null)); }
public Tuple <IEnumerable <ConversationNode>, IEnumerable <NodeGroup> > DuplicateInto(IEnumerable <Conversation.Serialization.GraphAndUI <NodeUIData> > nodeData, IEnumerable <NodeGroup> groups, System.Drawing.PointF location, ILocalizationEngine localization) { throw new NotImplementedException(); }
public override IEnumerable <MenuAction <ConversationNode> > GetMenuActions(IGraphEditorControl <ConversationNode> control, IProject2 project, Action <IEnumerable <IErrorListElement> > log, ILocalizationEngine localizer) { foreach (var action in base.GetMenuActions(control, project, log, localizer)) { yield return(action); } yield return(new MenuAction <ConversationNode>("Find References", (n, p) => () => FileReferences(n), null, null, null)); }
public bool Remove(IEnumerable <ConversationNode> nodes, IEnumerable <NodeGroup> groups, ILocalizationEngine localization) => throw new NotSupportedException();
public IEnumerable <MenuAction <ConversationNode> > GetMenuActions(IGraphEditorControl <ConversationNode> control, IProject2 project, Action <IEnumerable <IErrorListElement> > log, ILocalizationEngine localizer) { Action <ConversationNode, Point> jump = (n, p) => { if (n.Data.NodeTypeId == SpecialNodes.JumpTo) { var targetnodes = control.CurrentFile.Nodes.Where(a => a.Data.NodeTypeId == SpecialNodes.JumpTarget); var target = targetnodes.FirstOrDefault(t => GetId(t) == GetTarget(n)); if (target != null) { control.SelectNode(target); } } else if (n.Data.NodeTypeId == SpecialNodes.JumpTarget) { var sourceNodes = control.CurrentFile.Nodes.Where(a => a.Data.NodeTypeId == SpecialNodes.JumpTo); var source = sourceNodes.FirstOrDefault(t => GetTarget(t) == GetId(n)); if (source != null) { control.SelectNode(source); } } }; yield return(new MenuAction <ConversationNode>("Jump", (n, p) => (n.Data.NodeTypeId == SpecialNodes.JumpTo || n.Data.NodeTypeId == SpecialNodes.JumpTarget ? () => jump(n, p) : (Action)null), null, null, null)); }