Guest User

Supermassive - Dialog Node Editor

a guest
Aug 10th, 2015
315
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #pragma strict
  2. import System.Collections.Generic;
  3. import System.Xml;
  4. import System.Xml.Serialization;
  5. import System.IO;
  6. import System.Text;
  7.  
  8.  
  9. //@XmlRoot("TextNodeCollection")
  10. class NodeEditor extends EditorWindow {
  11.  
  12. //  @XmlArray("Bubbles")
  13. //  @XmlArrayItem("Bubble")
  14.     var bubbles:List.<TextBubble>;
  15.     var conditions:List.<CCondition>;
  16.     var enterNode:TextBubble;
  17.     private var condOptions:String[];
  18.  
  19.     private var evt:Event;
  20.     private var selectedBubble:TextBubble;
  21.     private var reservedWinMin:int = 10;
  22.     private var menuRect:Rect;
  23.     private var bgSize:int = 10000;
  24.     private var panX:int = -bgSize*0.5;
  25.     private var panY:int = -bgSize*0.5;
  26.  
  27.  
  28.     @MenuItem("Window/Node editor")
  29.     static function ShowEditor() {
  30.         var editor:NodeEditor = EditorWindow.GetWindow.<NodeEditor>();
  31.         editor.Init();
  32.     }
  33.  
  34.     function Init(){
  35.         bubbles = new List.<TextBubble>();
  36.         conditions = new List.<CCondition>();
  37.     }
  38.  
  39.     function OnGUI() {
  40.         evt = Event.current;
  41.         if(evt.type == EventType.ContextClick)DrawMainContextMenu();
  42.         var winPos:Rect = this.position;
  43.         menuRect = Rect(winPos.width - 300 - panX, 0 - panY, 300, winPos.height);
  44.         var didPan = false;
  45.         if (Event.current.type == EventType.MouseDrag) {
  46.             didPan = PanBackground();
  47.         }
  48.         GUI.BeginGroup(new Rect(  panX,   panY, bgSize, bgSize),"qwe");
  49.         BeginWindows();
  50.        
  51.        
  52.             for (bubble in bubbles){
  53.                 var prefix:String;
  54.                 if(bubble == enterNode) prefix  = "enter - ";
  55.                 bubble.rect = GUI.Window(bubble.id, bubble.rect, DrawBubbleWindow, prefix + bubble.actor+" #"+bubble.id); //bubble.OnGUI();
  56.                
  57.                 for (var link in bubble.links)DrawNodeCurve(bubble, link.id);
  58.             }
  59.             GUI.Window(-1, menuRect, DrawMenuWindow, "Main Menu");
  60.             //for (bubble in bubbles)//DrawNodeCurve(bubble);
  61.            
  62.        
  63.             GUI.BringWindowToFront(-1);
  64.         EndWindows();
  65.         //GUI.EndGroup();
  66.        
  67.        
  68.             GUI.EndGroup();
  69.         if (didPan) Repaint();
  70.        
  71.     }
  72.    
  73.     function PanBackground():boolean{
  74.         var mouseDelta = Vector2(panX, panY);
  75.         for(var bubble in bubbles){//check nodes
  76.             if (bubble.rect.Contains(Event.current.mousePosition - mouseDelta)) return false;
  77.         }
  78.         if (menuRect.Contains(Event.current.mousePosition - mouseDelta)) return false;
  79.         panX += Event.current.delta.x;
  80.         panY += Event.current.delta.y;
  81.        
  82.         //Debug.Log(panX);
  83.         return true;
  84.     }
  85.  
  86.     function DrawMenuWindow(id:int) { //side menu
  87.         if(selectedBubble)DrawBubbleControllMenu();
  88.         GUILayout.FlexibleSpace();
  89.         DrowConditionParamsMenu();
  90.         DrowIOMenu();
  91.     }
  92.    
  93.     function DrawBubbleControllMenu(){ //node controll menu part
  94.         EditorGUILayout.LabelField("Selected node: "+selectedBubble.id);
  95.         EditorGUILayout.BeginHorizontal();
  96.         EditorGUILayout.LabelField("Actor:");
  97.         selectedBubble.actor = EditorGUILayout.TextField(selectedBubble.actor);
  98.         EditorGUILayout.EndHorizontal();
  99.         EditorGUILayout.LabelField("Text:");
  100.         //EditorStyles.textField.wordWrap;
  101.         EditorGUILayout.BeginVertical();
  102.         selectedBubble.text = EditorGUILayout.TextField(selectedBubble.text);
  103.         EditorGUILayout.EndVertical();
  104.         DrawLinksMenu();
  105.         DrawNodeOptionsMenu();
  106.     }
  107.    
  108.     function DrawNodeOptionsMenu(){
  109.         GUILayout.BeginHorizontal();
  110.         GUILayout.FlexibleSpace();
  111.         if ( GUILayout.Button("Set as start") ) SetNodeAsStart();
  112.         if ( GUILayout.Button("Remove node") ) RemoveNode();
  113.         GUILayout.EndHorizontal();
  114.     }
  115.    
  116.     function RemoveNode(){
  117.         bubbles.Remove(selectedBubble);
  118.     }
  119.    
  120.     function SetNodeAsStart(){
  121.         enterNode = selectedBubble;
  122.     }
  123.    
  124.     function DrowIOMenu(){
  125.         GUILayout.BeginHorizontal();
  126.        
  127.         if ( GUILayout.Button("Save Sheet") ) SaveSheet();
  128.         if(GUILayout.Button("Load Sheet")) LoadSheet();
  129.         GUILayout.EndHorizontal();
  130.     }
  131.    
  132.     function DrawLinksMenu(){
  133.         for (link in selectedBubble.links){
  134.             GUILayout.BeginHorizontal();
  135.             GUILayout.Label("Link id:");
  136.             link.id = int.Parse(GUILayout.TextField(link.id.ToString()));
  137.             GUILayout.Space(50);
  138.             var conditionName = link.condition ? link.condition.name : "None";
  139.             if(GUILayout.Button("Condition: " + conditionName))DrawConditionsContextMenu(link);
  140.             if(GUILayout.Button("Remove"))RemoveLink(link, selectedBubble.links);
  141.             //link.conditionIndex = EditorGUILayout.Popup(link.conditionIndex, condOptions);
  142.             GUILayout.EndHorizontal();
  143.         }
  144.         if(GUILayout.Button("Add link"))selectedBubble.AddLink();
  145.     }
  146.    
  147.     function RemoveLink(link:TextBubble.CLink, list:List.<TextBubble.CLink>){
  148.         list.Remove(link);
  149.     }
  150.    
  151.     function DrawConditionsContextMenu(link:TextBubble.CLink){
  152.         var menu : GenericMenu = new GenericMenu ();
  153.         menu.AddItem (new GUIContent ("None"), false, AddNullPositionToConditionsMenu, link);
  154.         menu.AddSeparator ("");
  155.         for (var condition in conditions)
  156.             menu.AddItem (new GUIContent (condition.name), false, AddPositionToConditionsMenu, new KeyValuePair.<TextBubble.CLink,CCondition>(link, condition));
  157.         //menu.AddItem (new GUIContent ("Connect bubble"), false, ConnectBubble);
  158.        
  159.         //menu.AddItem (new GUIContent ("Debug"), false, DebugInfo);
  160.         menu.ShowAsContext ();
  161.         evt.Use();
  162.     }
  163.    
  164.     function AddNullPositionToConditionsMenu(link:TextBubble.CLink){
  165.         link.condition = null;
  166.     }
  167.    
  168.     function AddPositionToConditionsMenu(pair:KeyValuePair.<TextBubble.CLink,CCondition>){
  169.         pair.Key.condition = pair.Value;
  170.     }
  171.    
  172.     function DrowConditionParamsMenu(){
  173.         GUILayout.BeginHorizontal();
  174.         //GUI.SetNextControlName ("MyTextField");
  175.         if(GUILayout.Button("Add condition"))AddCondition();
  176.         //if(GUILayout.Button("Update"))RebuildConditionOptions();
  177.         GUILayout.EndHorizontal();
  178.         for (condition in conditions){
  179.             GUILayout.BeginHorizontal();
  180.             if(GUILayout.Button("Remove"))conditions.Remove(condition);
  181.             GUILayout.Label("Name:");
  182.             condition.name = GUILayout.TextField(condition.name);
  183.             GUILayout.EndHorizontal();
  184.         }
  185.     }
  186.    
  187.     function GetBubble(idP:int):TextBubble{
  188.         return bubbles.Find( function(bubble) bubble.id == idP );
  189.     }
  190.    
  191.     function DrawBubbleWindow(id:int) {
  192.            
  193.         //GUI.skin.window.
  194.         var bubble = GetBubble(id);
  195.         EditorStyles.label.wordWrap = true;
  196.         GUI.SetNextControlName ("MyTextField");
  197.         EditorGUILayout.SelectableLabel(bubble.text);
  198.         if(evt.type == EventType.mouseDown && evt.button == 0) {
  199.             var window = EditorWindow.GetWindow.<NodeEditor>();
  200.             window.UpdateMenu(bubble);
  201.             if(GUI.GetNameOfFocusedControl() != "MyTextField")
  202.                 //Debug.Log(GUI.GetNameOfFocusedControl().ToString());
  203.             EditorGUI.FocusTextInControl ("MyTextField");
  204.         }//else if(evt.type == EventType.mouseDown && evt.button == 1)ConnectBubble();
  205.  
  206.         GUI.DragWindow();
  207.         //
  208.     }
  209.    
  210.     function AddCondition(){
  211.         conditions.Add(new CCondition());
  212.         //RebuildConditionOptions();
  213.     }
  214.  
  215.     function DrawNodeCurve(bubble:TextBubble, link:int) {
  216.         var target = GetBubble(link);
  217.         if(target == null)return; //check if target connected
  218.         var start = bubble.rect;
  219.         var end = target.rect;
  220.         var startPos = new Vector3(start.x + start.width, start.y + start.height / 2, 0);
  221.         var endPos = new Vector3(end.x, end.y + end.height / 2, 0);
  222.         var startTan = startPos + Vector3.right * 50;
  223.         var endTan = endPos + Vector3.left * 50;
  224.         var shadowCol = new Color(0, 0, 0, 0.06f);
  225.         for (var i = 0; i < 3; i++) // Draw a shadow
  226.             Handles.DrawBezier(startPos, endPos, startTan, endTan, shadowCol, null, (i + 1) * 5);
  227.         Handles.DrawBezier(startPos, endPos, startTan, endTan, Color.black, null, 1);
  228.     }
  229.  
  230.     function DrawMainContextMenu(){
  231.         var menu : GenericMenu = new GenericMenu ();
  232.         menu.AddItem (new GUIContent ("Add new node"), false, AddNewNode);
  233.         //menu.AddItem (new GUIContent ("Connect bubble"), false, ConnectBubble);
  234.         menu.AddSeparator ("");
  235.         //menu.AddItem (new GUIContent ("Debug"), false, DebugInfo);
  236.         menu.ShowAsContext ();
  237.         evt.Use();
  238.     }
  239.  
  240.     function AddNewNode(){
  241.         var mPos = evt.mousePosition;
  242.         var rect = new Rect(mPos.x-panX, mPos.y-panY, 200, 80);
  243.         var id = GetNewId();
  244.         var bubble = new TextBubble(id, rect);
  245.         bubbles.Add(bubble);
  246.     }
  247.  
  248.     function ConnectBubble(){
  249.         Debug.Log(evt.mousePosition);
  250.     }
  251.  
  252.     function GetNewId():int{
  253.         var max:int;
  254.         for(var bubble in bubbles) if(bubble.id > max)max = bubble.id;
  255.         return max+1;
  256.     }
  257.  
  258.     function DebugInfo(){
  259.         Debug.Log(this.position);
  260.     }
  261.  
  262.     function UpdateMenu(bubble:TextBubble){
  263.         selectedBubble = bubble;
  264.     }
  265.    
  266.  
  267.    
  268.  
  269.    
  270.    
  271.     function SaveSheet(){
  272.         var path = EditorUtility.SaveFilePanelInProject("Save dialogue as dialogue", "dialogue", "xml", "Please enter a file name to save the dialogue to");
  273.         if (!path) return;
  274.         if(!enterNode)Debug.Log("enter node not selected");
  275. //      var sw = new StreamWriter( new FileStream(path, FileMode.Create, FileAccess.ReadWrite),  Encoding.UTF8);
  276. //      sw.Write(dialog.ToString());
  277. //      sw.Close();
  278.  
  279. //      var sw:StreamWriter = new StreamWriter(path, false, Encoding.UTF8)) {
  280. //        sw.Write(sb.ToString());
  281. //        sw.Close();
  282.        
  283.        
  284.         var container = new SaveFile(enterNode, bubbles, conditions);
  285.         var serializer : XmlSerializer = new XmlSerializer(SaveFile);
  286.        
  287.         var stream : StreamWriter = new StreamWriter(path, false, Encoding.UTF8);
  288.         //var stream : Stream = new FileStream(path, FileMode.Create);
  289.        
  290.         serializer.Serialize(stream, container);
  291.         stream.Close();
  292.        
  293.        
  294.     }
  295.    
  296.     function SaveSheet_obsolate(){
  297.    
  298. //      var sw = new StreamWriter( new FileStream(temporaryFilePath, FileMode.Create, FileAccess.ReadWrite),  Encoding.UTF8) {
  299. //                sw.Write(sb.ToString());
  300. //            }
  301.  
  302.  
  303.    
  304.    
  305.    
  306.         var path = EditorUtility.SaveFilePanelInProject("Save dialogue as dialogue", "dialogue", "xml", "Please enter a file name to save the dialogue to");
  307.         if (!path) return;
  308.         var container = new SaveFile(enterNode, bubbles, conditions);
  309.         var serializer : XmlSerializer = new XmlSerializer(SaveFile);
  310.         var stream : Stream = new FileStream(path, FileMode.Create);
  311.         serializer.Serialize(stream, container);
  312.         stream.Close();
  313.     }
  314.    
  315.     function LoadSheet(){
  316.         var path = EditorUtility.OpenFilePanel("Load file", "assets", "xml");
  317.         if (!path) return;
  318.         var serializer : XmlSerializer = new XmlSerializer(SaveFile);
  319.         var stream : Stream = new FileStream(path, FileMode.Open);
  320.         var container : SaveFile = serializer.Deserialize(stream) as SaveFile;
  321.         stream.Close();
  322.         bubbles = container.bubbles;
  323.         conditions = container.conditions;
  324.         enterNode = GetBubble(container.startNode);
  325.     }
  326. }
  327.  
  328.     class CCondition {
  329.         var name:String = "";
  330.         //var state:boolean;
  331.         function CCondition(){
  332.            
  333.         }
  334.     }
  335.  
  336. public class TextBubble {
  337.         public var text:String = "";
  338.         public var actor:String = "";
  339.         @XmlAttribute("id")
  340.         public var id:int;
  341.         var rect:Rect;
  342.         var links:List.<CLink>;
  343.        
  344.         function TextBubble(){}
  345.         function TextBubble(newID:int, newRect:Rect){
  346.             id = newID;
  347.             rect = newRect;
  348.             links = new List.<CLink>();
  349.             //style = new GUIStyle();
  350.         }
  351.        
  352.         function AddLink(){
  353.             links.Add(new CLink());
  354.         }
  355.        
  356.         class CLink{
  357.             var id:int;
  358.             var condition:CCondition;
  359.             function CLink(){};
  360. //          function CLink(linkP:int, nameP:String, index:int){
  361. //              //id = linkP;
  362. //              //conditionName = nameP;
  363. //              //conditionIndex = index;
  364. //          }
  365.         }
  366.     }
  367.    
  368.     @XmlRoot("TextNodeCollection")
  369.     public class SaveFile{
  370.         public var startNode:int;
  371.         @XmlArray("Bubbles")
  372.         @XmlArrayItem("Bubble")
  373.         public var bubbles:List.<TextBubble>;
  374.         @XmlArray("Conditions")
  375.         @XmlArrayItem("Conditions")
  376.         public var conditions:List.<CCondition>;
  377.         function SaveFile(){}
  378.         function SaveFile (enterNode:TextBubble, bubblesInp:List.<TextBubble>, conditionsInp:List.<CCondition> ) {
  379.             startNode = enterNode.id;//bubblesInp.IndexOf(enterNode);
  380.             bubbles = bubblesInp;
  381.             conditions = conditionsInp;
  382.         }
  383.     }
Advertisement
Add Comment
Please, Sign In to add comment