2133 lines
88 KiB
C#
2133 lines
88 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Nullframes.Intrigues.EDITOR.Utils;
|
|
using Nullframes.Intrigues.Utils;
|
|
using UnityEditor;
|
|
using UnityEditor.Experimental.GraphView;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace Nullframes.Intrigues.Graph.Nodes
|
|
{
|
|
public class IEGraphView : GraphView
|
|
{
|
|
#region VARIABLES
|
|
|
|
private readonly GraphWindow _graphWindow;
|
|
private SchemeSearchMenu schemeSearchMenu;
|
|
private RuleSearchMenu ruleSearchMenu;
|
|
private ClanSearchMenu clanSearchMenu;
|
|
private FamilySearchMenu familySearchMenu;
|
|
|
|
private MiniMap miniMap;
|
|
|
|
private List<GraphElement> copiedElements;
|
|
|
|
protected override bool canCutSelection => false;
|
|
|
|
private List<IManipulator> manipulators = new();
|
|
|
|
private GenericNodeType copiedPage;
|
|
|
|
#endregion
|
|
|
|
#region INIT
|
|
|
|
public IEGraphView(GraphWindow graphWindow)
|
|
{
|
|
_graphWindow = graphWindow;
|
|
|
|
SetupZoom(.1f, 1f, 0.05f, 1f);
|
|
this.AddManipulator(new ContentDragger());
|
|
this.AddManipulator(new SelectionDragger());
|
|
this.AddManipulator(new RectangleSelector());
|
|
|
|
AddMiniMap();
|
|
AddGridBackground();
|
|
|
|
OnElementDeleted();
|
|
OnGroupElementAdded();
|
|
OnGroupElementRemoved();
|
|
OnGraphViewChanged();
|
|
|
|
this.AddStyleSheets("Nullframes/IEGraphViewStyles.uss", "Nullframes/IENodeStyles.uss");
|
|
MiniMapStyle();
|
|
|
|
serializeGraphElements += CutCopyOperation;
|
|
unserializeAndPaste += PasteOperation;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region COPY-PASTE
|
|
|
|
private void DuplicateData(INode original, INode duplicated)
|
|
{
|
|
switch (original, duplicated)
|
|
{
|
|
case (ActorNode o, ActorNode d):
|
|
d.ActorName = o.ActorName;
|
|
d.Gender = o.Gender;
|
|
d.Age = o.Age;
|
|
d.CultureID = o.CultureID;
|
|
d.Portrait = o.Portrait;
|
|
d.State = o.State;
|
|
d.IsPlayer = o.IsPlayer;
|
|
break;
|
|
case (ObjectiveNode o, ObjectiveNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Objective = o.Objective;
|
|
break;
|
|
case (AddPolicyNode o, AddPolicyNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.PolicyID = o.PolicyID;
|
|
break;
|
|
case (AgeRuleNode o, AgeRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Age = o.Age;
|
|
break;
|
|
case (AgeNode o, AgeNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Age = o.Age;
|
|
break;
|
|
case (ChanceNode o, ChanceNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Chance = o.Chance;
|
|
break;
|
|
case (ChanceModifierNode o, ChanceModifierNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.Positive = o.Positive;
|
|
d.Negative = o.Negative;
|
|
d.Opposite = o.Opposite;
|
|
d.Mode = o.Mode;
|
|
break;
|
|
case (ChildCountRuleNode o, ChildCountRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.IncludePassiveCharacters = o.IncludePassiveCharacters;
|
|
d.Count = o.Count;
|
|
break;
|
|
case (ChildCountNode o, ChildCountNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.IncludePassiveCharacters = o.IncludePassiveCharacters;
|
|
d.Count = o.Count;
|
|
break;
|
|
case (ClanMemberNode o, ClanMemberNode d):
|
|
//
|
|
d.ActorID = o.ActorID;
|
|
d.RoleID = o.RoleID;
|
|
break;
|
|
case (ReturnClanNode o, ReturnClanNode d):
|
|
d.MethodName = o.MethodName;
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (ReturnClanRuleNode o, ReturnClanRuleNode d):
|
|
d.MethodName = o.MethodName;
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (ReturnFamilyNode o, ReturnFamilyNode d):
|
|
d.MethodName = o.MethodName;
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (ReturnFamilyRuleNode o, ReturnFamilyRuleNode d):
|
|
d.MethodName = o.MethodName;
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (ReturnActorNode o, ReturnActorNode d):
|
|
d.MethodName = o.MethodName;
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (ReturnActorRuleNode o, ReturnActorRuleNode d):
|
|
d.MethodName = o.MethodName;
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (DualActorNode o, DualActorNode d):
|
|
d.DualType = o.DualType;
|
|
d.MethodName = o.MethodName;
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (DualActorRuleNode o, DualActorRuleNode d):
|
|
d.DualType = o.DualType;
|
|
d.MethodName = o.MethodName;
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SetConspiratorNode o, SetConspiratorNode d):
|
|
d.ConspiratorID = o.ConspiratorID;
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SetTargetNode o, SetTargetNode d):
|
|
d.TargetID = o.TargetID;
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SetInheritorNode o, SetInheritorNode d):
|
|
d.Inheritor = o.Inheritor;
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (OnLoadNode o, OnLoadNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (RuleNode o, RuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.RuleID = o.RuleID;
|
|
break;
|
|
case (CultureNode o, CultureNode d):
|
|
//
|
|
d.CultureName = GenerateCultureName();
|
|
d.Description = o.Description;
|
|
d.NamesForMale = o.NamesForMale;
|
|
d.NamesForFemale = o.NamesForFemale;
|
|
break;
|
|
case (DialogueNode o, DialogueNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Title = o.Title;
|
|
d.Content = o.Content;
|
|
d.Break = o.Break;
|
|
d.Time = o.Time;
|
|
break;
|
|
case (GlobalMessageNode o, GlobalMessageNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Title = o.Title;
|
|
d.TypeWriter = o.TypeWriter;
|
|
d.Background = o.Background;
|
|
d.Content = o.Content;
|
|
break;
|
|
case (RemoveSpousesNode o, RemoveSpousesNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (FailSchemeNode o, FailSchemeNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (FamilyMemberNode o, FamilyMemberNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.ActorID = o.ActorID;
|
|
break;
|
|
case (GenderRuleNode o, GenderRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (GenderNode o, GenderNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (GetActorRuleNode o, GetActorRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.ActorID = o.ActorID;
|
|
break;
|
|
case (GetActorNode o, GetActorNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.ActorID = o.ActorID;
|
|
break;
|
|
case (GetClanRuleNode o, GetClanRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.ClanID = o.ClanID;
|
|
break;
|
|
case (GetClanNode o, GetClanNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.ClanID = o.ClanID;
|
|
break;
|
|
case (SetClanNode o, SetClanNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.ClanID = o.ClanID;
|
|
break;
|
|
case (GetCultureRuleNode o, GetCultureRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.CultureID = o.CultureID;
|
|
break;
|
|
case (GetCultureNode o, GetCultureNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.CultureID = o.CultureID;
|
|
break;
|
|
case (GetFamilyRuleNode o, GetFamilyRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.FamilyID = o.FamilyID;
|
|
break;
|
|
case (GetFamilyNode o, GetFamilyNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.FamilyID = o.FamilyID;
|
|
break;
|
|
case (GetPolicyRuleNode o, GetPolicyRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.PolicyID = o.PolicyID;
|
|
break;
|
|
case (GetPolicyNode o, GetPolicyNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.PolicyID = o.PolicyID;
|
|
break;
|
|
case (GetRoleRuleNode o, GetRoleRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.RoleID = o.RoleID;
|
|
break;
|
|
case (KeyHandlerNode o, KeyHandlerNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.KeyCode = o.KeyCode;
|
|
d.KeyType = o.KeyType;
|
|
d.TapCount = o.TapCount;
|
|
d.HoldTime = o.HoldTime;
|
|
break;
|
|
case (GetRoleNode o, GetRoleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.RoleID = o.RoleID;
|
|
break;
|
|
case (GetStateRuleNode o, GetStateRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.State = o.State;
|
|
break;
|
|
case (GetStateNode o, GetStateNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.State = o.State;
|
|
break;
|
|
case (GetVariableRuleNode o, GetVariableRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.Type = o.Type;
|
|
break;
|
|
case (GetClanVariableRuleNode o, GetClanVariableRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.Type = o.Type;
|
|
break;
|
|
case (GetFamilyVariableRuleNode o, GetFamilyVariableRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.Type = o.Type;
|
|
break;
|
|
case (GetVariableNode o, GetVariableNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.Type = o.Type;
|
|
break;
|
|
case (GetFamilyVariableNode o, GetFamilyVariableNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.Type = o.Type;
|
|
break;
|
|
case (GetClanVariableNode o, GetClanVariableNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.Type = o.Type;
|
|
break;
|
|
case (GetRelationVariableNode o, GetRelationVariableNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.Type = o.Type;
|
|
break;
|
|
case (GetRelationVariableRuleNode o, GetRelationVariableRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.Type = o.Type;
|
|
break;
|
|
case (WaitUntilNode o, WaitUntilNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.Type = o.Type;
|
|
break;
|
|
case (GetTableVariableNode o, GetTableVariableNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.Type = o.Type;
|
|
break;
|
|
case (GhostClanNode _, GhostClanNode _):
|
|
//
|
|
|
|
break;
|
|
case (GhostFamilyNode _, GhostFamilyNode _):
|
|
//
|
|
|
|
break;
|
|
case (GrandchildCountRuleNode o, GrandchildCountRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.IncludePassiveCharacters = o.IncludePassiveCharacters;
|
|
d.Count = o.Count;
|
|
break;
|
|
case (GrandchildCountNode o, GrandchildCountNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.IncludePassiveCharacters = o.IncludePassiveCharacters;
|
|
d.Count = o.Count;
|
|
break;
|
|
case (GrandparentCountRuleNode o, GrandparentCountRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.IncludePassiveCharacters = o.IncludePassiveCharacters;
|
|
d.Count = o.Count;
|
|
break;
|
|
case (GrandparentCountNode o, GrandparentCountNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.IncludePassiveCharacters = o.IncludePassiveCharacters;
|
|
d.Count = o.Count;
|
|
break;
|
|
case (InvokeNode o, InvokeNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.MethodName = o.MethodName;
|
|
break;
|
|
case (InvokeRuleNode o, InvokeRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.MethodName = o.MethodName;
|
|
break;
|
|
case (SignalNode o, SignalNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Signal = o.Signal;
|
|
break;
|
|
case (IsAIRuleNode o, IsAIRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsAINode o, IsAINode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsChildRuleNode o, IsChildRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsChildNode o, IsChildNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsGrandChildRuleNode o, IsGrandChildRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsGrandChildNode o, IsGrandChildNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsGrandParentRuleNode o, IsGrandParentRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsGrandParentNode o, IsGrandParentNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsParentRuleNode o, IsParentRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsParentNode o, IsParentNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (HasHeirNode o, HasHeirNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (HasHeirRuleNode o, HasHeirRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsRelativeRuleNode o, IsRelativeRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsRelativeNode o, IsRelativeNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsSiblingRuleNode o, IsSiblingRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsSiblingNode o, IsSiblingNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsSpouseRuleNode o, IsSpouseRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (IsSpouseNode o, IsSpouseNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (LogNode o, LogNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Message = o.Message;
|
|
break;
|
|
case (LogRuleNode o, LogRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Message = o.Message;
|
|
break;
|
|
case (AddSpouseNode o, AddSpouseNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.JoinSpouseFamily = o.JoinSpouseFamily;
|
|
break;
|
|
case (CommentLeftToRightNode o, CommentLeftToRightNode d):
|
|
d.Note = o.Note;
|
|
break;
|
|
case (CommentRightToLeftNode o, CommentRightToLeftNode d):
|
|
d.Note = o.Note;
|
|
break;
|
|
case (CommentRuleNode o, CommentRuleNode d):
|
|
d.Note = o.Note;
|
|
break;
|
|
case (ParentCountRuleNode o, ParentCountRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.IncludePassiveCharacters = o.IncludePassiveCharacters;
|
|
d.Count = o.Count;
|
|
break;
|
|
case (ParentCountNode o, ParentCountNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.IncludePassiveCharacters = o.IncludePassiveCharacters;
|
|
d.Count = o.Count;
|
|
break;
|
|
case (PolicyNode o, PolicyNode d):
|
|
d.PolicyName = GeneratePolicyName();
|
|
d.Description = o.Description;
|
|
d.PolicyIcon = o.PolicyIcon;
|
|
d.Type = o.Type;
|
|
break;
|
|
case (RandomNode o, RandomNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (RemovePolicyNode o, RemovePolicyNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.PolicyID = o.PolicyID;
|
|
break;
|
|
case (RepeaterNode o, RepeaterNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.RepetitionCount = o.RepetitionCount;
|
|
break;
|
|
case (BreakRepeaterNode o, BreakRepeaterNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (BreakSequencerNode o, BreakSequencerNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (ContinueNode o, ContinueNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (BreakNode o, BreakNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (PauseNode o, PauseNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (ResumeNode o, ResumeNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (NewFlowNode o, NewFlowNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (BackgroundWorkerNode o, BackgroundWorkerNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (ChoiceDataNode o, ChoiceDataNode d):
|
|
d.Text = o.Text;
|
|
d.Text2 = o.Text2;
|
|
break;
|
|
case (JumpNode o, JumpNode d):
|
|
d.LinkID = o.LinkID;
|
|
break;
|
|
case (LinkedNode o, LinkedNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Name = o.Name;
|
|
break;
|
|
case (RoleNode o, RoleNode d):
|
|
d.RoleName = GenerateRoleName();
|
|
d.Description = o.Description;
|
|
d.RoleSlot = o.RoleSlot;
|
|
d.Legacy = o.Legacy;
|
|
d.TitleForMale = o.TitleForMale;
|
|
d.TitleForFemale = o.TitleForFemale;
|
|
d.RoleIcon = o.RoleIcon;
|
|
d.Priority = o.Priority;
|
|
break;
|
|
case (HeirFilterNode o, HeirFilterNode d):
|
|
d.FilterName = GenerateFilterName();
|
|
d.Gender = o.Gender;
|
|
d.Age = o.Age;
|
|
d.Relatives = new List<int>(o.relativeButtons.Values);
|
|
break;
|
|
case (SameClanRuleNode o, SameClanRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SameClanNode o, SameClanNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SameCultureRuleNode o, SameCultureRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SameCultureNode o, SameCultureNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SameFamilyRuleNode o, SameFamilyRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SameFamilyNode o, SameFamilyNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SameGenderRuleNode o, SameGenderRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SameGenderNode o, SameGenderNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SequencerNode o, SequencerNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SkipSequencerNode o, SkipSequencerNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Index = o.Index;
|
|
break;
|
|
case (SetCultureNode o, SetCultureNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.CultureID = o.CultureID;
|
|
break;
|
|
case (SetRoleNode o, SetRoleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.RoleID = o.RoleID;
|
|
break;
|
|
case (SetStateNode o, SetStateNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.State = o.State;
|
|
break;
|
|
case (SchemeStateNode o, SchemeStateNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.State = o.State;
|
|
break;
|
|
case (SetVariableNode o, SetVariableNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.ObjectValue = o.ObjectValue;
|
|
d.Operation = o.Operation;
|
|
d.VariableType = o.VariableType;
|
|
break;
|
|
case (SetFamilyVariableNode o, SetFamilyVariableNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.ObjectValue = o.ObjectValue;
|
|
d.Operation = o.Operation;
|
|
d.VariableType = o.VariableType;
|
|
break;
|
|
case (SetClanVariableNode o, SetClanVariableNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.ObjectValue = o.ObjectValue;
|
|
d.Operation = o.Operation;
|
|
d.VariableType = o.VariableType;
|
|
break;
|
|
case (SetRelationVariableNode o, SetRelationVariableNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.ObjectValue = o.ObjectValue;
|
|
d.Operation = o.Operation;
|
|
d.VariableType = o.VariableType;
|
|
break;
|
|
case (SetTableVariableNode o, SetTableVariableNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
d.StringValue = o.StringValue;
|
|
d.IntegerValue = o.IntegerValue;
|
|
d.FloatValue = o.FloatValue;
|
|
d.Operation = o.Operation;
|
|
d.VariableType = o.VariableType;
|
|
break;
|
|
case (SetActorNode o, SetActorNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.VariableID = o.VariableID;
|
|
break;
|
|
case (SiblingCountRuleNode o, SiblingCountRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.IncludePassiveCharacters = o.IncludePassiveCharacters;
|
|
d.Count = o.Count;
|
|
break;
|
|
case (SiblingCountNode o, SiblingCountNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.IncludePassiveCharacters = o.IncludePassiveCharacters;
|
|
d.Count = o.Count;
|
|
break;
|
|
case (SoundNode o, SoundNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Clip = o.Clip;
|
|
d.Volume = o.Volume;
|
|
d.Pitch = o.Pitch;
|
|
d.Priority = o.Priority;
|
|
d.WaitEnd = o.WaitEnd;
|
|
d.AudioMixerGroup = o.AudioMixerGroup;
|
|
break;
|
|
case (SoundClassNode o, SoundClassNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Clip = o.Clip;
|
|
d.Volume = o.Volume;
|
|
d.FadeOut = o.FadeOut;
|
|
d.Pitch = o.Pitch;
|
|
d.Priority = o.Priority;
|
|
d.Loop = o.Loop;
|
|
d.StopWhenClosed = o.StopWhenClosed;
|
|
d.AudioMixerGroup = o.AudioMixerGroup;
|
|
break;
|
|
case (VoiceClassNode o, VoiceClassNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Clip = o.Clip;
|
|
d.Volume = o.Volume;
|
|
d.Pitch = o.Pitch;
|
|
d.Priority = o.Priority;
|
|
d.Sync = o.Sync;
|
|
d.AudioMixerGroup = o.AudioMixerGroup;
|
|
break;
|
|
case (SpouseCountRuleNode o, SpouseCountRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.IncludePassiveCharacters = o.IncludePassiveCharacters;
|
|
d.Count = o.Count;
|
|
break;
|
|
case (SpouseCountNode o, SpouseCountNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.IncludePassiveCharacters = o.IncludePassiveCharacters;
|
|
d.Count = o.Count;
|
|
break;
|
|
case (StartRuleNode o, StartRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (StartNode o, StartNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (EndNode o, EndNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SuccessRuleNode o, SuccessRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SuccessSchemeNode o, SuccessSchemeNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
break;
|
|
case (SchemeIsActiveNode o, SchemeIsActiveNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.SchemeID = o.SchemeID;
|
|
d.VerifyType = o.VerifyType;
|
|
break;
|
|
case (SchemeIsActiveRuleNode o, SchemeIsActiveRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.SchemeID = o.SchemeID;
|
|
d.VerifyType = o.VerifyType;
|
|
break;
|
|
case (ErrorRuleNode o, ErrorRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.ErrorName = GenerateErrorName();
|
|
d.Error = o.Error;
|
|
break;
|
|
case (WarningRuleNode o, WarningRuleNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.WarningName = GenerateWarningName();
|
|
d.WarningName = o.Warning;
|
|
break;
|
|
case (TriggerNode o, TriggerNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.TriggerName = o.TriggerName;
|
|
d.Value = o.Value;
|
|
break;
|
|
case (VariableNode o, VariableNode d):
|
|
d.VariableName = GenerateVariableName();
|
|
d.Value = o.Value;
|
|
d.Type = o.Type;
|
|
d.Variable = o.Variable.Duplicate();
|
|
break;
|
|
case (WaitNode o, WaitNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Delay = o.Delay;
|
|
break;
|
|
case (WaitRandomNode o, WaitRandomNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.Min = o.Min;
|
|
d.Max = o.Max;
|
|
break;
|
|
case (WaitTriggerNode o, WaitTriggerNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.TriggerName = o.TriggerName;
|
|
d.Timeout = o.Timeout;
|
|
break;
|
|
case (ValidatorNode o, ValidatorNode d):
|
|
d.Outputs = o.Outputs.CloneNodeOutputs();
|
|
d.RuleID = o.RuleID;
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException(nameof(duplicated));
|
|
}
|
|
}
|
|
|
|
private void PasteOperation(string operationname, string data)
|
|
{
|
|
if (copiedElements == null) return;
|
|
|
|
if (copiedElements.Count < 1 || copiedPage != _graphWindow.CurrentPage) return;
|
|
|
|
var copiedGroup = copiedElements.FirstOrDefault(x => x is IGroup) as IGroup;
|
|
var activeGroup = graphElements.FirstOrDefault(x => x is IGroup) as IGroup;
|
|
|
|
ClearSelection();
|
|
|
|
IGroup duplicatedGroup = null;
|
|
if (copiedGroup != null)
|
|
{
|
|
duplicatedGroup = DuplicateGroup(copiedGroup);
|
|
duplicatedGroup.selected = true;
|
|
}
|
|
|
|
var createdNodes = new List<INode>();
|
|
|
|
foreach (var graphElement in copiedElements.Where(x => x is INode))
|
|
{
|
|
var node = (INode)graphElement;
|
|
|
|
var createdNode = CreateNodeScript(node.GetType());
|
|
|
|
if (node.Group != null)
|
|
{
|
|
if (duplicatedGroup == null)
|
|
{
|
|
if (activeGroup != null)
|
|
{
|
|
activeGroup.AddElement(createdNode);
|
|
createdNode.Group = activeGroup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
duplicatedGroup.AddElement(createdNode);
|
|
createdNode.Group = duplicatedGroup;
|
|
}
|
|
}
|
|
|
|
DuplicateData(node, createdNode);
|
|
|
|
InstantiateNode(createdNode, node.GetPosition().position, false, node.ID);
|
|
|
|
//Re-position
|
|
|
|
// InstantiateNode(createdNode,
|
|
// copiedElements.Contains(node.Group) ? node.GetPosition().position : pos.position, false, node.ID);
|
|
|
|
// Rect pos;
|
|
// if (selectionGroup == null)
|
|
// {
|
|
// pos = new Rect(node.GetPosition().x + node.GetPosition().width, node.GetPosition().y,
|
|
// node.GetPosition().width, node.GetPosition().height);
|
|
// }
|
|
// else
|
|
// {
|
|
// var lastElement = selectionGroup.containedElements.Last();
|
|
// pos = new Rect(lastElement.GetPosition().x + lastElement.GetPosition().width,
|
|
// lastElement.GetPosition().y,
|
|
// lastElement.GetPosition().width, lastElement.GetPosition().height);
|
|
// }
|
|
|
|
AddToSelection(createdNode);
|
|
|
|
createdNode.SetDirty();
|
|
|
|
createdNodes.Add(createdNode);
|
|
}
|
|
|
|
var loadedNodes = new Dictionary<string, GeneratedNode>();
|
|
|
|
foreach (var graphElement in graphElements.Where(n => n is INode))
|
|
{
|
|
var node = (INode)graphElement;
|
|
// if (node.ElementType != GenericNodeType.Nexus) continue;
|
|
if (loadedNodes.ContainsKey(node.ID)) loadedNodes.Remove(node.ID);
|
|
|
|
loadedNodes.Add(node.ID, new GeneratedNode(node));
|
|
}
|
|
|
|
var regeneratedNodes = new List<INode>();
|
|
|
|
foreach (var node in createdNodes)
|
|
{
|
|
if (!node.IsDrawed) node.Draw();
|
|
foreach (var port in node.GetElements<Port>())
|
|
{
|
|
if (port.direction != Direction.Output) continue;
|
|
foreach (var dataCollection in ((OutputData)port.userData).DataCollection)
|
|
if (loadedNodes.ContainsKey(dataCollection.NextID))
|
|
{
|
|
var nextNode = loadedNodes[dataCollection.NextID];
|
|
if (!nextNode.node.IsDrawed) nextNode.node.Draw();
|
|
if (node.Group != nextNode.node.Group)
|
|
{
|
|
dataCollection.NextID = string.Empty;
|
|
dataCollection.NextName = string.Empty;
|
|
continue;
|
|
}
|
|
|
|
if (createdNodes.Contains(nextNode.node))
|
|
{
|
|
if (!nextNode.generated)
|
|
{
|
|
nextNode.node.ReGenerateID();
|
|
regeneratedNodes.Add(nextNode.node);
|
|
}
|
|
|
|
nextNode.generated = true;
|
|
dataCollection.NextID = nextNode.node.ID;
|
|
}
|
|
|
|
var nextNodeInputPort = nextNode.node.GetElements<Port>()
|
|
.First(p => p.portName == dataCollection.NextName);
|
|
var edge = port.ConnectTo(nextNodeInputPort);
|
|
AddElement(edge);
|
|
}
|
|
}
|
|
|
|
node.RefreshPorts();
|
|
}
|
|
|
|
ActorNode actorNode = null;
|
|
|
|
foreach (var createdNode in createdNodes)
|
|
{
|
|
if (regeneratedNodes.Contains(createdNode)) continue;
|
|
createdNode.ReGenerateID();
|
|
|
|
if (createdNode is ActorNode a) actorNode = a;
|
|
}
|
|
|
|
EditorRoutine.StartRoutine(0.01f, () =>
|
|
{
|
|
GraphSaveUtility.SaveCurrent();
|
|
|
|
if (actorNode != null)
|
|
{
|
|
GraphWindow.instance.SetActorKey(actorNode.ID);
|
|
GraphSaveUtility.LoadCurrent(this);
|
|
GraphWindow.instance.GoView();
|
|
}
|
|
|
|
if (duplicatedGroup == null) return;
|
|
switch (duplicatedGroup)
|
|
{
|
|
case SchemeGroup:
|
|
GraphWindow.instance.SetStoryKey(duplicatedGroup.ID);
|
|
GraphSaveUtility.LoadCurrent(this);
|
|
GraphWindow.instance.GoView();
|
|
break;
|
|
case RuleGroup:
|
|
GraphWindow.instance.SetRuleKey(duplicatedGroup.ID);
|
|
GraphSaveUtility.LoadCurrent(this);
|
|
GraphWindow.instance.GoView();
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
|
|
private string CutCopyOperation(IEnumerable<GraphElement> elements)
|
|
{
|
|
copiedElements = new List<GraphElement>();
|
|
foreach (var element in elements.Where(x => x is INode or IGroup)) copiedElements.Add(element);
|
|
|
|
copiedPage = _graphWindow.CurrentPage;
|
|
return "null";
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region MINIMAP
|
|
|
|
private void AddMiniMap()
|
|
{
|
|
miniMap = new MiniMap()
|
|
{
|
|
anchored = true
|
|
};
|
|
miniMap.SetPosition(new Rect(15, 50, 200, 180));
|
|
Add(miniMap);
|
|
|
|
miniMap.visible = false;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SEARCH
|
|
|
|
public void AddSearchWindow()
|
|
{
|
|
if (schemeSearchMenu == null)
|
|
{
|
|
schemeSearchMenu = ScriptableObject.CreateInstance<SchemeSearchMenu>();
|
|
schemeSearchMenu.Init(this);
|
|
}
|
|
|
|
if (ruleSearchMenu == null)
|
|
{
|
|
ruleSearchMenu = ScriptableObject.CreateInstance<RuleSearchMenu>();
|
|
ruleSearchMenu.Init(this);
|
|
}
|
|
|
|
if (clanSearchMenu == null)
|
|
{
|
|
clanSearchMenu = ScriptableObject.CreateInstance<ClanSearchMenu>();
|
|
clanSearchMenu.Init(this);
|
|
}
|
|
|
|
if (familySearchMenu == null)
|
|
{
|
|
familySearchMenu = ScriptableObject.CreateInstance<FamilySearchMenu>();
|
|
familySearchMenu.Init(this);
|
|
}
|
|
|
|
nodeCreationRequest = context =>
|
|
{
|
|
var page = GraphWindow.instance.CurrentPage;
|
|
if (page == GenericNodeType.Scheme)
|
|
SearchWindow.Open(new SearchWindowContext(context.screenMousePosition), schemeSearchMenu);
|
|
if (page == GenericNodeType.Rule)
|
|
SearchWindow.Open(new SearchWindowContext(context.screenMousePosition), ruleSearchMenu);
|
|
if (page == GenericNodeType.Clan)
|
|
SearchWindow.Open(new SearchWindowContext(context.screenMousePosition), clanSearchMenu);
|
|
if (page == GenericNodeType.Family)
|
|
SearchWindow.Open(new SearchWindowContext(context.screenMousePosition), familySearchMenu);
|
|
};
|
|
}
|
|
|
|
public void RemoveSearchWindow()
|
|
{
|
|
nodeCreationRequest = null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Overrided Methods
|
|
|
|
public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter)
|
|
{
|
|
var compatiblePorts = new List<Port>();
|
|
|
|
ports.ForEach(p =>
|
|
{
|
|
var startNode = (INode)startPort.node;
|
|
var targetNode = (INode)p.node;
|
|
|
|
if (startPort.portName != "[Actor]" && p.portName == "[Actor]" || startPort.portName == "[Actor]" && p.portName != "[Actor]")
|
|
return;
|
|
|
|
if (startPort.portName != "[Dual]" && p.portName == "[Dual]" || startPort.portName == "[Dual]" && p.portName != "[Dual]")
|
|
return;
|
|
|
|
if (startPort.portName != "[Clan]" && p.portName == "[Clan]" || startPort.portName == "[Clan]" && p.portName != "[Clan]")
|
|
return;
|
|
|
|
if (startPort.portName != "[Family]" && p.portName == "[Family]" || startPort.portName == "[Family]" && p.portName != "[Family]")
|
|
return;
|
|
|
|
if (startPort.portName != "[Class]" && p.portName == "[Class]" || startPort.portName == "[Class]" && p.portName != "[Class]")
|
|
return;
|
|
|
|
// var startData = (OutputData)startPort.userData;
|
|
// var targetData = (OutputData)p.userData;
|
|
if (startNode?.Group != targetNode?.Group) return;
|
|
switch (startNode)
|
|
{
|
|
case SuccessSchemeNode when targetNode is FailSchemeNode:
|
|
case FailSchemeNode when targetNode is SuccessSchemeNode:
|
|
return;
|
|
}
|
|
|
|
switch (startPort.portName)
|
|
{
|
|
case "Children" when p.portName != "Parent":
|
|
case "Spouse" when p.portName != "Spouse":
|
|
return;
|
|
}
|
|
|
|
if (startPort.portName == "Display" && p.portName != "Display") return;
|
|
if (startPort.portName != "Display" && p.portName == "Display") return;
|
|
|
|
//Chance-ChanceModifier
|
|
if (startPort.portType == typeof(double) && p.portType != typeof(double))
|
|
return;
|
|
|
|
//Chance-ChanceModifier
|
|
if (p.portType == typeof(double) && startPort.portType != typeof(double))
|
|
return;
|
|
|
|
if (startPort.direction == Direction.Output && startPort.portName == "Spouse" &&
|
|
startPort.direction == Direction.Input && p.portName != "Spouse")
|
|
return;
|
|
if (startNode is FamilyMemberNode startFamilyNode && targetNode is FamilyMemberNode targetFamilyNode)
|
|
{
|
|
if (startPort.portName == "Children" && p.portName == "Parent")
|
|
{
|
|
if (startFamilyNode.actor?.Age < targetFamilyNode.actor?.Age &&
|
|
startFamilyNode.actor.CurrentState == Actor.IState.Active) return;
|
|
if (p.connections.Count() > 1) return;
|
|
|
|
var spouseOutPortData = (OutputData)startFamilyNode.spouseContainer.GetChild<Port>().userData;
|
|
if (spouseOutPortData.DataCollection.Any(data => data.NextID == targetNode?.ID)) return;
|
|
|
|
var childs = (OutputData)targetFamilyNode.childContainer.GetChild<Port>().userData;
|
|
if (childs.DataCollection.Any(data => data.NextID == startNode?.ID)) return;
|
|
}
|
|
|
|
if (startPort.portName == "Parent" && p.portName == "Children")
|
|
{
|
|
if (targetFamilyNode.actor?.Age < startFamilyNode.actor?.Age &&
|
|
startFamilyNode.actor.CurrentState == Actor.IState.Active) return;
|
|
if (startPort.connections.Count() > 1) return;
|
|
var characterNode = startFamilyNode;
|
|
var targetCharacterNode = targetFamilyNode;
|
|
|
|
var spouseOutPortData = (OutputData)characterNode.childContainer.GetChild<Port>().userData;
|
|
if (spouseOutPortData.DataCollection.Any(data => data.NextID == targetNode?.ID)) return;
|
|
|
|
var childs = (OutputData)targetCharacterNode.spouseContainer.GetChild<Port>().userData;
|
|
if (childs.DataCollection.Any(data => data.NextID == startNode?.ID)) return;
|
|
}
|
|
|
|
if (startPort.portName == "Spouse" && p.portName == "Spouse")
|
|
{
|
|
var characterNode = startFamilyNode;
|
|
var targetCharacterNode = targetFamilyNode;
|
|
var isOutput = startPort.direction == Direction.Output;
|
|
|
|
if (characterNode.actor.Age < STATIC.MARRIAGE_AGE ||
|
|
targetCharacterNode.actor.Age < STATIC.MARRIAGE_AGE) return;
|
|
|
|
var anySpouseInput =
|
|
characterNode.spouseInputContainer.GetChild<Port>().connections.Any();
|
|
|
|
// var anySpouseOutput =
|
|
// characterNode.spouseContainer.GetChild<Port>().connections.Any();
|
|
|
|
var anyTargetSpouseInput =
|
|
targetCharacterNode.spouseInputContainer.GetChild<Port>().connections.Any();
|
|
|
|
var anyTargetSpouseOutput =
|
|
targetCharacterNode.spouseContainer.GetChild<Port>().connections.Any();
|
|
|
|
if (isOutput)
|
|
{
|
|
if (anySpouseInput) return;
|
|
if (anyTargetSpouseInput) return;
|
|
if (anyTargetSpouseOutput) return;
|
|
}
|
|
else
|
|
{
|
|
if (anyTargetSpouseInput) return;
|
|
if (anySpouseInput) return;
|
|
if (anyTargetSpouseOutput) return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (startPort == p)
|
|
return;
|
|
|
|
if (p.connections.Any(edge => startPort.connections.Contains(edge)))
|
|
return;
|
|
|
|
if (startPort.node == p.node)
|
|
return;
|
|
|
|
if (startPort.direction == p.direction)
|
|
return;
|
|
|
|
compatiblePorts.Add(p);
|
|
});
|
|
return compatiblePorts;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Manipulators
|
|
|
|
public void AddManipulators(GenericNodeType page)
|
|
{
|
|
ClearManipulators();
|
|
if (page == GenericNodeType.Scheme)
|
|
manipulators = new List<IManipulator>()
|
|
{
|
|
CreateGroupContextualMenu(),
|
|
CreateLabelContextualMenu(" "),
|
|
CreateNodeContextualMenu<CommentLeftToRightNode>("Comment(LR)"),
|
|
CreateNodeContextualMenu<CommentRightToLeftNode>("Comment(RL)"),
|
|
CreateNodeContextualMenu<DialogueNode>("Dialogue"),
|
|
CreateNodeContextualMenu<WaitNode>("Wait"),
|
|
CreateNodeContextualMenu<WaitRandomNode>("Wait(Random)"),
|
|
CreateNodeContextualMenu<SequencerNode>("Sequencer"),
|
|
CreateNodeContextualMenu<RepeaterNode>("Repeater"),
|
|
CreateNodeContextualMenu<SoundNode>("Play Sound"),
|
|
CreateNodeContextualMenu<JumpNode>("Go To"),
|
|
CreateNodeContextualMenu<LinkedNode>("Link"),
|
|
};
|
|
|
|
if (page == GenericNodeType.Clan)
|
|
manipulators = new List<IManipulator>()
|
|
{
|
|
CreateClanContextualMenu(),
|
|
CreateLabelContextualMenu(" "),
|
|
CreateNodeContextualMenu<RoleNode>("New Role"),
|
|
CreateNodeContextualMenu<HeirFilterNode>("Heir Filter")
|
|
};
|
|
|
|
if (page == GenericNodeType.Policy)
|
|
manipulators = new List<IManipulator>()
|
|
{
|
|
CreateNodeContextualMenu<PolicyNode>("New Policy"),
|
|
};
|
|
|
|
if (page == GenericNodeType.Family)
|
|
manipulators = new List<IManipulator>()
|
|
{
|
|
CreateFamilyContextualMenu(),
|
|
};
|
|
|
|
if (page == GenericNodeType.Actor)
|
|
manipulators = new List<IManipulator>()
|
|
{
|
|
CreateNodeContextualMenu<ActorNode>("New Actor")
|
|
};
|
|
|
|
if (page == GenericNodeType.Culture)
|
|
manipulators = new List<IManipulator>()
|
|
{
|
|
CreateNodeContextualMenu<CultureNode>("New Culture")
|
|
};
|
|
|
|
if (page == GenericNodeType.Variable)
|
|
manipulators = new List<IManipulator>()
|
|
{
|
|
CreateNodeContextualMenu<VariableNode>("New Variable")
|
|
};
|
|
|
|
if (page == GenericNodeType.Rule)
|
|
manipulators = new List<IManipulator>()
|
|
{
|
|
CreateRuleContextualMenu(),
|
|
CreateLabelContextualMenu(" "),
|
|
CreateNodeContextualMenu<CommentRuleNode>("Comment"),
|
|
CreateNodeContextualMenu<SuccessRuleNode>("Success"),
|
|
CreateNodeContextualMenu<ErrorRuleNode>("Error"),
|
|
CreateNodeContextualMenu<WarningRuleNode>("Warning"),
|
|
CreateLabelContextualMenu(" "),
|
|
CreateNodeContextualMenu<GetVariableRuleNode>("Get Variable"),
|
|
CreateNodeContextualMenu<GetActorRuleNode>("Get Actor"),
|
|
CreateNodeContextualMenu<GetClanRuleNode>("Get Clan"),
|
|
CreateNodeContextualMenu<GetFamilyRuleNode>("Get Family"),
|
|
CreateNodeContextualMenu<GetRoleRuleNode>("Get Role"),
|
|
CreateNodeContextualMenu<GetCultureRuleNode>("Get Culture"),
|
|
CreateLabelContextualMenu(" "),
|
|
CreateNodeContextualMenu<GetPolicyRuleNode>("Has Policy"),
|
|
CreateNodeContextualMenu<SameClanRuleNode>("Same Clan"),
|
|
CreateNodeContextualMenu<SameFamilyRuleNode>("Same Family"),
|
|
CreateNodeContextualMenu<SameCultureRuleNode>("Same Culture"),
|
|
CreateNodeContextualMenu<SameGenderRuleNode>("Same Gender"),
|
|
CreateNodeContextualMenu<AgeRuleNode>("Age"),
|
|
CreateNodeContextualMenu<GenderRuleNode>("Gender"),
|
|
CreateNodeContextualMenu<IsAIRuleNode>("Is AI"),
|
|
CreateNodeContextualMenu<GetStateRuleNode>("Get State"),
|
|
CreateLabelContextualMenu(" "),
|
|
CreateNodeContextualMenu<IsRelativeRuleNode>("Is Relative"),
|
|
CreateNodeContextualMenu<IsParentRuleNode>("Is Parent"),
|
|
CreateNodeContextualMenu<IsGrandParentRuleNode>("Is Grandparent"),
|
|
CreateNodeContextualMenu<IsGrandChildRuleNode>("Is Grandchildren"),
|
|
CreateNodeContextualMenu<IsSpouseRuleNode>("Is Spouse"),
|
|
CreateNodeContextualMenu<IsChildRuleNode>("Is Child"),
|
|
CreateNodeContextualMenu<IsSiblingRuleNode>("Is Sibling"),
|
|
CreateNodeContextualMenu<HasHeirRuleNode>("Has Heir"),
|
|
CreateLabelContextualMenu(" "),
|
|
CreateNodeContextualMenu<ParentCountRuleNode>("Parent Count"),
|
|
CreateNodeContextualMenu<GrandparentCountRuleNode>("Grandparent Count"),
|
|
CreateNodeContextualMenu<GrandchildCountRuleNode>("Grandchildren Count"),
|
|
CreateNodeContextualMenu<ChildCountRuleNode>("Children Count"),
|
|
CreateNodeContextualMenu<SpouseCountRuleNode>("Spouse Count"),
|
|
CreateNodeContextualMenu<SiblingCountRuleNode>("Sibling Count"),
|
|
};
|
|
|
|
foreach (var manipulator in manipulators) this.AddManipulator(manipulator);
|
|
}
|
|
|
|
private void ClearManipulators()
|
|
{
|
|
foreach (var manipulator in manipulators) this.RemoveManipulator(manipulator);
|
|
|
|
manipulators = new List<IManipulator>();
|
|
}
|
|
|
|
private IManipulator CreateLabelContextualMenu(string title)
|
|
{
|
|
var contextualMenuManipulator = new ContextualMenuManipulator(evnt =>
|
|
{
|
|
evnt.menu.AppendAction(title, _ => { }, DropdownMenuAction.Status.Disabled);
|
|
});
|
|
return contextualMenuManipulator;
|
|
}
|
|
|
|
private IManipulator CreateNodeContextualMenu<T>(string title) where T : INode
|
|
{
|
|
var contextualMenuManipulator = new ContextualMenuManipulator(evnt =>
|
|
evnt.menu.AppendAction(title, action =>
|
|
{
|
|
switch (_graphWindow.CurrentPage)
|
|
{
|
|
case GenericNodeType.Scheme when !graphElements.ToList()
|
|
.Exists(e => e is SchemeGroup):
|
|
NDebug.Log("You need a Scheme Group to create a Node.", NLogType.Error);
|
|
return;
|
|
// case GenericNodeType.Clan when !graphElements.ToList()
|
|
// .Exists(e => e is ClanGroup):
|
|
// NDebug.Log("You need a Clan Group to create a Node.", NLogType.Error);
|
|
// return;
|
|
case GenericNodeType.Family when !graphElements.ToList()
|
|
.Exists(e => e is FamilyGroup):
|
|
NDebug.Log("You need a Family Group to create a Node.", NLogType.Error);
|
|
return;
|
|
case GenericNodeType.Rule when !graphElements.ToList()
|
|
.Exists(e => e is RuleGroup):
|
|
NDebug.Log("You need a Rule Group to create a Node.", NLogType.Error);
|
|
return;
|
|
}
|
|
|
|
var mousePosition = GetLocalMousePosition(action.eventInfo.localMousePosition);
|
|
var node = CreateNode<T>(mousePosition, true, true);
|
|
AddElement(node);
|
|
}));
|
|
return contextualMenuManipulator;
|
|
}
|
|
|
|
private IManipulator CreateGroupContextualMenu()
|
|
{
|
|
var menuManipulator = new ContextualMenuManipulator(evnt =>
|
|
evnt.menu.AppendAction("Create Story", action =>
|
|
{
|
|
var position = GetLocalMousePosition(action.eventInfo.localMousePosition);
|
|
CreateSchemeGroup(position);
|
|
}));
|
|
return menuManipulator;
|
|
}
|
|
|
|
private IManipulator CreateClanContextualMenu()
|
|
{
|
|
var menuManipulator = new ContextualMenuManipulator(evnt =>
|
|
evnt.menu.AppendAction("New Clan", action =>
|
|
{
|
|
var position = GetLocalMousePosition(action.eventInfo.localMousePosition);
|
|
CreateClanGroup(position);
|
|
}));
|
|
return menuManipulator;
|
|
}
|
|
|
|
private IManipulator CreateRuleContextualMenu()
|
|
{
|
|
var menuManipulator = new ContextualMenuManipulator(evnt =>
|
|
evnt.menu.AppendAction("Create Rule", action =>
|
|
{
|
|
var position = GetLocalMousePosition(action.eventInfo.localMousePosition);
|
|
CreateRuleGroup(position);
|
|
}));
|
|
return menuManipulator;
|
|
}
|
|
|
|
private IManipulator CreateFamilyContextualMenu()
|
|
{
|
|
var menuManipulator = new ContextualMenuManipulator(evnt =>
|
|
evnt.menu.AppendAction("Create Family Tree", action =>
|
|
{
|
|
var position = GetLocalMousePosition(action.eventInfo.localMousePosition);
|
|
CreateFamilyGroup(position);
|
|
}));
|
|
return menuManipulator;
|
|
}
|
|
|
|
public void CreateSchemeGroup(Vector2 position)
|
|
{
|
|
var group = CreateSchemeGroup(GenerateGroupName("Intrigue ", GenericNodeType.Scheme), position,
|
|
"Description", string.Empty,
|
|
new List<NexusVariable>(), null);
|
|
group.OnCreated();
|
|
if (!group.containedElements.Cast<INode>().Any(x => x is StartNode))
|
|
{
|
|
var startNode = CreateNodeScript<StartNode>();
|
|
startNode.Group = group;
|
|
InstantiateNode(startNode, position);
|
|
}
|
|
|
|
if (!group.containedElements.Cast<INode>().Any(x => x is EndNode))
|
|
{
|
|
var endNode = CreateNodeScript<EndNode>();
|
|
endNode.Group = group;
|
|
InstantiateNode(endNode, new Vector2(position.x, position.y + 100f));
|
|
}
|
|
|
|
EditorRoutine.StartRoutine(0.01f, () =>
|
|
{
|
|
GraphSaveUtility.SaveCurrent();
|
|
GraphWindow.instance.SetStoryKey(group.ID);
|
|
GraphSaveUtility.LoadCurrent(this);
|
|
GraphWindow.instance.GoView();
|
|
});
|
|
}
|
|
|
|
public void CreateClanGroup(Vector2 position)
|
|
{
|
|
var group = CreateClanGroup(GenerateGroupName("Clan ", GenericNodeType.Clan), position, "Description", null,
|
|
string.Empty, new List<string>());
|
|
group.OnCreated();
|
|
if (!group.containedElements.Cast<INode>().Any(x => x is GhostClanNode))
|
|
{
|
|
var ghostClan = CreateNodeScript<GhostClanNode>();
|
|
ghostClan.Group = group;
|
|
InstantiateNode(ghostClan, position);
|
|
group.AddElement(ghostClan);
|
|
}
|
|
|
|
EditorRoutine.StartRoutine(0.01f, () =>
|
|
{
|
|
GraphSaveUtility.SaveCurrent();
|
|
GraphWindow.instance.SetClanKey(group.ID);
|
|
GraphSaveUtility.LoadCurrent(this);
|
|
GraphWindow.instance.GoView();
|
|
});
|
|
}
|
|
|
|
public void CreateRuleGroup(Vector2 position)
|
|
{
|
|
var group = CreateRuleGroup(GenerateGroupName("Rule ", GenericNodeType.Rule), position);
|
|
group.OnCreated();
|
|
if (!group.containedElements.Cast<INode>().Any(x => x is StartRuleNode))
|
|
{
|
|
var startRule = CreateNodeScript<StartRuleNode>();
|
|
startRule.Group = group;
|
|
InstantiateNode(startRule, position);
|
|
group.AddElement(startRule);
|
|
}
|
|
|
|
EditorRoutine.StartRoutine(0.01f, () =>
|
|
{
|
|
GraphSaveUtility.SaveCurrent();
|
|
GraphWindow.instance.SetRuleKey(group.ID);
|
|
GraphSaveUtility.LoadCurrent(this);
|
|
GraphWindow.instance.GoView();
|
|
});
|
|
}
|
|
|
|
public void CreateFamilyGroup(Vector2 position)
|
|
{
|
|
var group = CreateFamilyGroup(GenerateGroupName("Family ", GenericNodeType.Family), position, "Description",
|
|
null, string.Empty, new List<string>());
|
|
group.OnCreated();
|
|
if (!group.containedElements.Cast<INode>().Any(x => x is GhostFamilyNode))
|
|
{
|
|
var ghostFamily = CreateNodeScript<GhostFamilyNode>();
|
|
ghostFamily.Group = group;
|
|
InstantiateNode(ghostFamily, position);
|
|
group.AddElement(ghostFamily);
|
|
}
|
|
|
|
EditorRoutine.StartRoutine(0.01f, () =>
|
|
{
|
|
GraphSaveUtility.SaveCurrent();
|
|
GraphWindow.instance.SetFamilyKey(group.ID);
|
|
GraphSaveUtility.LoadCurrent(this);
|
|
GraphWindow.instance.GoView();
|
|
});
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Element Creation
|
|
|
|
public IGroup CreateSchemeGroup(string title, Vector2 position, string description, string ruleId,
|
|
List<NexusVariable> variables, Sprite icon,
|
|
bool hideIfNotCompatible = true, bool targetNotRequired = false, bool hideOnUI = false)
|
|
{
|
|
var schemeGroup = Activator.CreateInstance<SchemeGroup>();
|
|
schemeGroup.Init(title, position, description, ruleId, variables, hideIfNotCompatible, targetNotRequired, hideOnUI, icon, this);
|
|
schemeGroup.Draw();
|
|
AddElement(schemeGroup);
|
|
return schemeGroup;
|
|
}
|
|
|
|
public IGroup CreateClanGroup(string title, Vector2 position, string description, Sprite emblem,
|
|
string cultureId, List<string> policies)
|
|
{
|
|
var clanGroup = Activator.CreateInstance<ClanGroup>();
|
|
clanGroup.Init(title, position, description, cultureId, policies, emblem, this);
|
|
clanGroup.Draw();
|
|
AddElement(clanGroup);
|
|
return clanGroup;
|
|
}
|
|
|
|
public IGroup CreateRuleGroup(string title, Vector2 position)
|
|
{
|
|
var ruleGroup = Activator.CreateInstance<RuleGroup>();
|
|
ruleGroup.Init(title, position, this);
|
|
ruleGroup.Draw();
|
|
AddElement(ruleGroup);
|
|
return ruleGroup;
|
|
}
|
|
|
|
public IGroup CreateFamilyGroup(string title, Vector2 position, string description, Sprite emblem,
|
|
string cultureId, List<string> policies)
|
|
{
|
|
var familyGroup = Activator.CreateInstance<FamilyGroup>();
|
|
familyGroup.Init(title, position, description, cultureId, policies, emblem, this);
|
|
familyGroup.Draw();
|
|
AddElement(familyGroup);
|
|
return familyGroup;
|
|
}
|
|
|
|
private IGroup DuplicateGroup(IGroup originalGroup)
|
|
{
|
|
switch (originalGroup)
|
|
{
|
|
case SchemeGroup schemeGroup:
|
|
{
|
|
var _schemeGroup = Activator.CreateInstance<SchemeGroup>();
|
|
_schemeGroup.Init(GenerateGroupName("Intrigue ", GenericNodeType.Scheme),
|
|
schemeGroup.GetPosition().position,
|
|
schemeGroup.Description, schemeGroup.RuleID, schemeGroup.Variables, schemeGroup.HideIfNotCompatible, schemeGroup.TargetNotRequired, schemeGroup.HideOnUI,
|
|
schemeGroup.Icon, this);
|
|
_schemeGroup.Draw();
|
|
AddElement(_schemeGroup);
|
|
return _schemeGroup;
|
|
}
|
|
case ClanGroup clanGroup:
|
|
{
|
|
var _clanGroup = Activator.CreateInstance<ClanGroup>();
|
|
_clanGroup.Init(GenerateGroupName("Clan ", GenericNodeType.Clan), clanGroup.GetPosition().position,
|
|
clanGroup.Description, clanGroup.CultureID, clanGroup.Policies, clanGroup.Emblem, this);
|
|
_clanGroup.Draw();
|
|
AddElement(_clanGroup);
|
|
return _clanGroup;
|
|
}
|
|
case FamilyGroup familyGroup:
|
|
{
|
|
var _familyGroup = Activator.CreateInstance<FamilyGroup>();
|
|
_familyGroup.Init(GenerateGroupName("Family ", GenericNodeType.Family),
|
|
familyGroup.GetPosition().position, familyGroup.Description, familyGroup.CultureID, familyGroup.Policies,
|
|
familyGroup.Emblem, this);
|
|
_familyGroup.Draw();
|
|
AddElement(_familyGroup);
|
|
return _familyGroup;
|
|
}
|
|
case RuleGroup ruleGroup:
|
|
{
|
|
var _ruleGroup = Activator.CreateInstance<RuleGroup>();
|
|
_ruleGroup.Init(GenerateGroupName("Rule ", GenericNodeType.Rule),
|
|
ruleGroup.GetPosition().position, this);
|
|
_ruleGroup.Draw();
|
|
AddElement(_ruleGroup);
|
|
return _ruleGroup;
|
|
}
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private T CreateNodeScript<T>() where T : INode
|
|
{
|
|
return Activator.CreateInstance<T>();
|
|
}
|
|
|
|
private INode CreateNodeScript(Type type)
|
|
{
|
|
return Activator.CreateInstance(type) as INode;
|
|
}
|
|
|
|
public T CreateNode<T>(Vector2 position, bool shouldDraw = true, bool manualCreation = false)
|
|
where T : INode
|
|
{
|
|
INode node = CreateNodeScript<T>();
|
|
switch (node)
|
|
{
|
|
case PolicyNode policyNode:
|
|
policyNode.PolicyName = GeneratePolicyName();
|
|
break;
|
|
case CultureNode cultureNode:
|
|
cultureNode.CultureName = GenerateCultureName();
|
|
break;
|
|
case VariableNode variableNode:
|
|
variableNode.VariableName = GenerateVariableName();
|
|
break;
|
|
case ErrorRuleNode causeRuleNode:
|
|
causeRuleNode.ErrorName = GenerateErrorName();
|
|
break;
|
|
case RoleNode roleNode:
|
|
roleNode.RoleName = GenerateRoleName();
|
|
break;
|
|
case HeirFilterNode heirFilterNode:
|
|
heirFilterNode.FilterName = GenerateFilterName();
|
|
break;
|
|
}
|
|
|
|
InstantiateNode(node, position, shouldDraw, null, manualCreation);
|
|
|
|
return node as T;
|
|
}
|
|
|
|
private void InstantiateNode(INode node, Vector2 position, bool shouldDraw = true, string manualid = null,
|
|
bool manualCreation = false)
|
|
{
|
|
node.SetPosition(new Rect(position, Vector2.zero));
|
|
node.Pos = position;
|
|
if (manualCreation && node.IsGroupable())
|
|
{
|
|
if (IGroup.selectedGroup == null || IGroup.selectedGroup != node.Group)
|
|
{
|
|
foreach (var selectable in selection)
|
|
{
|
|
if (selectable is not Group selectedElement)
|
|
{
|
|
if (selectable is INode selectedINode)
|
|
if (selection.Count == 1 && selectedINode.Group != null)
|
|
{
|
|
selectedINode.Group.AddElement(node);
|
|
node.Group = selectedINode.Group;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
selectedElement.AddElement(node);
|
|
node.Group = (IGroup)selectedElement;
|
|
}
|
|
|
|
if (node.Group == null)
|
|
{
|
|
var lst = new List<INode>();
|
|
switch (node.GenericType)
|
|
{
|
|
case GenericNodeType.Family:
|
|
lst = graphElements.OfType<INode>().Where(e =>
|
|
e.GenericType == GenericNodeType.Family && e.IsGroupable())
|
|
.OrderBy(e => Vector2.Distance(position, e.GetPosition().position)).ToList();
|
|
break;
|
|
case GenericNodeType.Clan:
|
|
lst = graphElements.OfType<INode>().Where(e =>
|
|
e.GenericType == GenericNodeType.Clan && e.IsGroupable())
|
|
.OrderBy(e => Vector2.Distance(position, e.GetPosition().position)).ToList();
|
|
break;
|
|
case GenericNodeType.Rule:
|
|
lst = graphElements.OfType<INode>()
|
|
.Where(e => e.GenericType == GenericNodeType.Rule && e.IsGroupable())
|
|
.OrderBy(e => Vector2.Distance(position, e.GetPosition().position)).ToList();
|
|
break;
|
|
case GenericNodeType.Scheme:
|
|
lst = graphElements.OfType<INode>()
|
|
.Where(e => e.GenericType == GenericNodeType.Scheme && e.IsGroupable())
|
|
.OrderBy(e => Vector2.Distance(position, e.GetPosition().position)).ToList();
|
|
break;
|
|
}
|
|
|
|
if (lst.Count > 0)
|
|
{
|
|
var closestElement = lst[0];
|
|
var closestNode = closestElement;
|
|
|
|
closestNode.Group.AddElement(node);
|
|
node.Group = closestNode.Group;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IGroup.selectedGroup.AddElement(node);
|
|
node.Group = IGroup.selectedGroup;
|
|
}
|
|
}
|
|
|
|
node.Init(this);
|
|
if (!string.IsNullOrEmpty(manualid)) node.ID = manualid;
|
|
|
|
|
|
if (shouldDraw)
|
|
{
|
|
node.Draw();
|
|
node.OnCreated();
|
|
AddElement(node);
|
|
GraphSaveUtility.SaveCurrent();
|
|
|
|
EditorRoutine.StartRoutine(0.01f, () =>
|
|
{
|
|
if (node is ActorNode)
|
|
{
|
|
GraphWindow.instance.SetActorKey(node.ID);
|
|
GraphSaveUtility.LoadCurrent(this);
|
|
GraphWindow.instance.GoView();
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (manualid != null)
|
|
{
|
|
AddElement(node);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Element Styles
|
|
|
|
private void AddGridBackground()
|
|
{
|
|
var gridBackground = new GridBackground();
|
|
gridBackground.StretchToParentSize();
|
|
Insert(0, gridBackground);
|
|
}
|
|
|
|
private void MiniMapStyle()
|
|
{
|
|
miniMap.style.backgroundColor = new StyleColor(new Color32(29, 29, 30, 55));
|
|
miniMap.SetBorderColor(NullUtils.HTMLColor("#353535"));
|
|
miniMap.SetBorderRadius(0f);
|
|
miniMap.SetBorderWidth(2f);
|
|
}
|
|
|
|
public void ToggleMiniMap()
|
|
{
|
|
miniMap.visible = !miniMap.visible;
|
|
PlayerPrefs.SetString("IDE_Map_Open_State", miniMap.visible.ToString());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Position Correction
|
|
|
|
public Vector2 GetLocalMousePosition(Vector2 mousePosition, bool isWindow = false)
|
|
{
|
|
var worldPosition = mousePosition;
|
|
if (isWindow) worldPosition -= _graphWindow.position.position;
|
|
|
|
var localPosition = contentViewContainer.WorldToLocal(worldPosition);
|
|
return localPosition;
|
|
}
|
|
|
|
#endregion
|
|
|
|
public void Fit(Func<GraphElement, bool> condition = null)
|
|
{
|
|
var rectToFit = condition == null
|
|
? this.CalculateRectToFitAllEx(contentViewContainer)
|
|
: this.CalculateRectToFitAllEx(contentViewContainer, condition);
|
|
CalculateFrameTransform(rectToFit, layout, 30, out var frameTranslation, out var frameScaling);
|
|
Matrix4x4.TRS(frameTranslation, Quaternion.identity, frameScaling);
|
|
UpdateViewTransform(frameTranslation, frameScaling);
|
|
}
|
|
|
|
#region Callbacks
|
|
|
|
private void OnElementDeleted()
|
|
{
|
|
deleteSelection = (_, _) =>
|
|
{
|
|
var groupsToDelete = new List<IGroup>();
|
|
var edgesToDelete = new List<Edge>();
|
|
var nodesToDelete = new List<INode>();
|
|
|
|
ActorNode actorNode = null;
|
|
|
|
foreach (var selectable in selection)
|
|
{
|
|
var element = (GraphElement)selectable;
|
|
if (element is INode node)
|
|
{
|
|
if (node is ActorNode a) actorNode = a;
|
|
nodesToDelete.Add(node);
|
|
continue;
|
|
}
|
|
|
|
if (element is Edge edge)
|
|
{
|
|
edgesToDelete.Add(edge);
|
|
continue;
|
|
}
|
|
|
|
if (element is not IGroup group) continue;
|
|
|
|
groupsToDelete.Add(group);
|
|
}
|
|
|
|
SchemeGroup schemeGroup = null;
|
|
ClanGroup clanGroup = null;
|
|
FamilyGroup familyGroup = null;
|
|
RuleGroup ruleGroup = null;
|
|
foreach (var group in groupsToDelete)
|
|
{
|
|
RemoveGroup(group);
|
|
group.OnDestroy();
|
|
switch (group)
|
|
{
|
|
case SchemeGroup s:
|
|
schemeGroup = s;
|
|
break;
|
|
case ClanGroup c:
|
|
clanGroup = c;
|
|
break;
|
|
case FamilyGroup f:
|
|
familyGroup = f;
|
|
break;
|
|
case RuleGroup r:
|
|
ruleGroup = r;
|
|
break;
|
|
}
|
|
}
|
|
|
|
DeleteElements(edgesToDelete);
|
|
|
|
foreach (var node in nodesToDelete)
|
|
{
|
|
RemoveNode(node);
|
|
}
|
|
|
|
if (schemeGroup != null)
|
|
{
|
|
GraphWindow.instance.stories.Remove(schemeGroup.ID);
|
|
GraphWindow.instance.SetLastStoryKey();
|
|
GraphSaveUtility.LoadCurrent(this);
|
|
GraphWindow.instance.GoView();
|
|
}
|
|
|
|
if (clanGroup != null)
|
|
{
|
|
GraphWindow.instance.clans.Remove(clanGroup.ID);
|
|
GraphWindow.instance.SetLastClanKey();
|
|
GraphSaveUtility.LoadCurrent(this);
|
|
GraphWindow.instance.GoView();
|
|
}
|
|
|
|
if (familyGroup != null)
|
|
{
|
|
GraphWindow.instance.families.Remove(familyGroup.ID);
|
|
GraphWindow.instance.SetLastFamilyKey();
|
|
GraphSaveUtility.LoadCurrent(this);
|
|
GraphWindow.instance.GoView();
|
|
}
|
|
|
|
if (ruleGroup != null)
|
|
{
|
|
GraphWindow.instance.rules.Remove(ruleGroup.ID);
|
|
GraphWindow.instance.SetLastRuleKey();
|
|
GraphSaveUtility.LoadCurrent(this);
|
|
GraphWindow.instance.GoView();
|
|
}
|
|
|
|
if (actorNode != null)
|
|
{
|
|
GraphWindow.instance.characters.Remove(actorNode.ID);
|
|
GraphWindow.instance.SetLastActorKey();
|
|
GraphSaveUtility.LoadCurrent(this);
|
|
GraphWindow.instance.GoView();
|
|
}
|
|
};
|
|
}
|
|
|
|
private void RemoveNode(INode node)
|
|
{
|
|
if (!graphElements.Contains(node)) return;
|
|
node.Group?.RemoveElement(node);
|
|
|
|
node.DisconnectAllPorts();
|
|
RemoveElement(node);
|
|
node.OnDestroy();
|
|
}
|
|
|
|
private void RemoveGroup(IGroup group)
|
|
{
|
|
var groupNodes = new List<INode>();
|
|
foreach (var groupElement in group.containedElements)
|
|
{
|
|
if (groupElement is not INode groupNode)
|
|
continue;
|
|
|
|
groupNodes.Add(groupNode);
|
|
}
|
|
|
|
foreach (var node in groupNodes)
|
|
{
|
|
RemoveNode(node);
|
|
}
|
|
|
|
RemoveElement(group);
|
|
}
|
|
|
|
private void OnGroupElementAdded()
|
|
{
|
|
elementsAddedToGroup = (group, elements) =>
|
|
{
|
|
foreach (var element in elements)
|
|
{
|
|
if (element is not INode node)
|
|
continue;
|
|
var nodeGroup = (IGroup)group;
|
|
node.Group = nodeGroup;
|
|
}
|
|
};
|
|
}
|
|
|
|
private void OnGroupElementRemoved()
|
|
{
|
|
elementsRemovedFromGroup = (_, elements) =>
|
|
{
|
|
foreach (var element in elements)
|
|
{
|
|
if (element is not INode node)
|
|
continue;
|
|
node.DisconnectAllPorts();
|
|
RemoveElement(node);
|
|
// node.OnDestroy();
|
|
}
|
|
};
|
|
}
|
|
|
|
private void OnGraphViewChanged()
|
|
{
|
|
graphViewChanged = (changes) => {
|
|
var isChanged = false;
|
|
var actions = new List<Action>();
|
|
|
|
if (changes.movedElements != null)
|
|
{
|
|
foreach (var element in changes.movedElements)
|
|
{
|
|
if (element is INode node)
|
|
{
|
|
node.SetDirty();
|
|
node.Pos = node.GetPosition().position;
|
|
}
|
|
}
|
|
isChanged = true;
|
|
}
|
|
|
|
if (changes.edgesToCreate != null)
|
|
{
|
|
foreach (var edge in changes.edgesToCreate)
|
|
{
|
|
var nextNode = (INode)edge.input.node;
|
|
var outputNode = (INode)edge.output.node;
|
|
var outputData = (OutputData)edge.output.userData;
|
|
var data = new PortData(nextNode.ID, edge.input.portName, edge.input.userData as string ?? string.Empty);
|
|
actions.Add(() => {
|
|
outputData.DataCollection.Add(data);
|
|
});
|
|
|
|
if (GraphWindow.instance.CurrentPage == GenericNodeType.Scheme &&
|
|
edge.output.portColor != STATIC.DefaultColor && edge.input.portColor == STATIC.DefaultColor)
|
|
edge.input.portColor = edge.output.portColor;
|
|
|
|
if (outputNode is ChanceNode chanceNode && nextNode is ChoiceDataNode choiceDataNode)
|
|
{
|
|
choiceDataNode.ChanceID = chanceNode.ID;
|
|
}
|
|
|
|
nextNode.SetDirty();
|
|
outputNode.SetDirty();
|
|
|
|
if (nextNode is DialogueNode dialogueNode)
|
|
{
|
|
dialogueNode.RefreshTargetBorder(true);
|
|
}
|
|
|
|
outputNode.children.Add(nextNode);
|
|
nextNode.parents.Add(outputNode);
|
|
}
|
|
|
|
isChanged = true;
|
|
}
|
|
|
|
if (changes.elementsToRemove != null)
|
|
{
|
|
foreach (var element in changes.elementsToRemove) {
|
|
if (!graphElements.Contains(element)) continue;
|
|
if (element.GetType() != typeof(Edge)) continue;
|
|
|
|
var edge = (Edge)element;
|
|
var outputData = (OutputData)edge.output.userData;
|
|
var nextNode = (INode)edge.input.node;
|
|
var outputNode = (INode)edge.output.node;
|
|
|
|
if (outputNode is ChanceNode && nextNode is ChoiceDataNode choiceDataNode) {
|
|
choiceDataNode.ChanceID = null;
|
|
}
|
|
|
|
nextNode.SetDirty();
|
|
outputNode.SetDirty();
|
|
|
|
actions.Add(() => {
|
|
var index = outputData.DataCollection.FindIndex(d => d.NextID == nextNode.ID);
|
|
if(index != -1)
|
|
outputData.DataCollection.RemoveAt(index);
|
|
});
|
|
|
|
nextNode.RefreshPorts();
|
|
|
|
if (nextNode is DialogueNode dialogueNode) {
|
|
dialogueNode.RefreshTargetBorder(true);
|
|
}
|
|
|
|
outputNode.children.Remove(nextNode);
|
|
nextNode.parents.Remove(outputNode);
|
|
}
|
|
|
|
isChanged = true;
|
|
}
|
|
|
|
if (isChanged) {
|
|
Undo.RecordObject(GraphWindow.CurrentDatabase, "IEGraph");
|
|
foreach (var action in actions) {
|
|
action?.Invoke();
|
|
}
|
|
GraphSaveUtility.SaveCurrent(true);
|
|
}
|
|
|
|
UpdateNodeIcons();
|
|
|
|
return changes;
|
|
};
|
|
}
|
|
|
|
public void UpdateNodeIcons() {
|
|
var loadedNodes = nodes.Cast<INode>().ToList();
|
|
|
|
foreach (var iNode in loadedNodes) {
|
|
iNode.HideAllIcons();
|
|
}
|
|
|
|
foreach (var iNode in loadedNodes) {
|
|
iNode.Execute();
|
|
}
|
|
}
|
|
|
|
public void ClearGraph()
|
|
{
|
|
graphElements.ForEach(RemoveElement);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
private string GenerateGroupName(string titleText, GenericNodeType type)
|
|
{
|
|
var nameList =
|
|
(from GroupData element in GraphWindow.CurrentDatabase.groupDataList.Where(e => e.GenericType == type)
|
|
select element.Title).ToList();
|
|
|
|
var i = 1;
|
|
while (nameList.Contains($"{titleText}{i}")) i++;
|
|
|
|
return $"{titleText}{i}";
|
|
}
|
|
|
|
private string GeneratePolicyName()
|
|
{
|
|
var nameList = (from PolicyNode element in graphElements.OfType<PolicyNode>()
|
|
select element.PolicyName)
|
|
.ToList();
|
|
|
|
var policyName = "Policy";
|
|
var i = 1;
|
|
while (nameList.Contains($"{policyName}{i}")) i++;
|
|
|
|
return $"{policyName}{i}";
|
|
}
|
|
|
|
private string GenerateCultureName()
|
|
{
|
|
var nameList =
|
|
(from CultureNode element in graphElements.OfType<CultureNode>() select element.CultureName)
|
|
.ToList();
|
|
|
|
var cultureName = "Culture";
|
|
var i = 1;
|
|
while (nameList.Contains($"{cultureName}{i}")) i++;
|
|
|
|
return $"{cultureName}{i}";
|
|
}
|
|
|
|
private string GenerateErrorName()
|
|
{
|
|
var nameList =
|
|
(from ErrorRuleNode element in graphElements.OfType<ErrorRuleNode>() select element.ErrorName)
|
|
.ToList();
|
|
|
|
var errorName = "Error";
|
|
var i = 1;
|
|
while (nameList.Contains($"{errorName}{i}")) i++;
|
|
|
|
return $"{errorName}{i}";
|
|
}
|
|
|
|
private string GenerateWarningName()
|
|
{
|
|
var nameList =
|
|
(from WarningRuleNode element in graphElements.OfType<WarningRuleNode>() select element.WarningName)
|
|
.ToList();
|
|
|
|
var warningName = "Warning";
|
|
var i = 1;
|
|
while (nameList.Contains($"{warningName}{i}")) i++;
|
|
|
|
return $"{warningName}{i}";
|
|
}
|
|
|
|
private string GenerateVariableName()
|
|
{
|
|
var nameList = (from VariableNode element in graphElements.OfType<VariableNode>()
|
|
select element.VariableName)
|
|
.ToList();
|
|
|
|
var variableName = "Variable";
|
|
var i = 1;
|
|
while (nameList.Contains($"{variableName}{i}")) i++;
|
|
|
|
return $"{variableName}{i}";
|
|
}
|
|
|
|
private string GenerateRoleName()
|
|
{
|
|
var nameList = (from RoleNode element in graphElements.OfType<RoleNode>() select element.RoleName)
|
|
.ToList();
|
|
|
|
var missionName = "Engineer";
|
|
var i = 1;
|
|
while (nameList.Contains($"{missionName}{i}")) i++;
|
|
|
|
return $"{missionName}{i}";
|
|
}
|
|
|
|
private string GenerateFilterName()
|
|
{
|
|
var nameList = (from HeirFilterNode element in graphElements.OfType<HeirFilterNode>() select element.FilterName)
|
|
.ToList();
|
|
|
|
var filterName = "Filter";
|
|
var i = 1;
|
|
while (nameList.Contains($"{filterName}{i}")) i++;
|
|
|
|
return $"{filterName}{i}";
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public sealed class GeneratedNode
|
|
{
|
|
public readonly INode node;
|
|
public bool generated;
|
|
|
|
public GeneratedNode(INode node)
|
|
{
|
|
this.node = node;
|
|
}
|
|
}
|
|
} |