public void show_bulk_download_complete_dialog(List <int> loaded_ids, Dictionary <int, Dictionary <string, string> > craft_data)
        {
            KerbalXDialog dialog = show_dialog(d => {
                d.footer = true;
                GUILayout.Label("You craft have been downloaded", "h2");
                GUILayout.Label("these ones to be precise:", "small");
                dl_scroll_height = 62 * loaded_ids.Count;
                if (dl_scroll_height > 372f)
                {
                    dl_scroll_height = 372f;
                }
                dl_scroll_pos = scroll(dl_scroll_pos, 500f, dl_scroll_height, sw => {
                    foreach (int id in loaded_ids)
                    {
                        style_override = GUI.skin.GetStyle("background.dark.margin");
                        v_section(w => {
                            GUILayout.Label(craft_data[id]["name"], "h3");
                            GUILayout.Label("saved to: " + craft_data[id]["short_path"]);
                        });
                    }
                });
                section(w => {
                    GUILayout.FlexibleSpace();
                    if (GUILayout.Button("Done", "button.bold", width((150f))))
                    {
                        close_dialog();
                    }
                });
            });

            dialog.window_title = "Download Summary";
        }
예제 #2
0
        //opens a dialog window which is populated by the lambda statement passed to show_dialog ie:
        //show_dialog((d) => {
        //	GUILayout.Label("hello I'm a dialog");
        //})
        //The dialog instance is returned by show_dialog, and it's also passed into the lambda.
        protected KerbalXDialog show_dialog(DialogContent content)
        {
            KerbalXDialog dialog = gameObject.AddOrGetComponent <KerbalXDialog>();

            dialog.content = content;
            return(dialog);
        }
        public void show_new_save_dialog()
        {
            KerbalXDialog dialog = show_dialog(d => {
                GUILayout.Label("This looks like a new save", "h2");
                GUILayout.Label("Would you like to fetch your craft from KerbalX for version " + ksp_ver, "h3");
                section(w => {
                    if (GUILayout.Button("No", "button.bold"))
                    {
                        close_dialog();
                    }
                    if (GUILayout.Button("Let me pick", "button.bold"))
                    {
                        close_dialog();
                        KerbalXDownloadController.instance.fetch_users_craft();
                    }
                    if (GUILayout.Button("Yep, fetch all my " + ksp_ver + " craft", "button.bold"))
                    {
                        close_dialog();
                        KerbalXDownloadController.instance.auto_load_users_craft();
                    }
                });
            });

            dialog.window_title = "Populate new save?";
        }
        private void toggle_large_viewer()
        {
            if (large_viewer)
            {
                GameObject.Destroy(large_viewer);
            }
            else
            {
                float viewer_width = 500f;
                large_viewer = show_dialog(d => {
                    PicData pic = KerbalX.image_selector.pictures[KerbalX.image_selector.large_viewer_index];
                    v_section(viewer_width, outer => {
                        section(w2 => {
                            if (GUILayout.Button("<", "button.large.bold", width(viewer_width * 0.1f)))
                            {
                                KerbalX.image_selector.large_viewer_index--;
                                if (KerbalX.image_selector.large_viewer_index < 0)
                                {
                                    KerbalX.image_selector.large_viewer_index = 0;
                                }
                            }
                            GUILayout.FlexibleSpace();
                            if (GUILayout.Button("Add Pic", "button.large.bold", width(viewer_width * 0.6f)))
                            {
                                toggle_pic(pic);
                            }
                            GUILayout.FlexibleSpace();
                            if (GUILayout.Button(">", "button.large.bold", width(viewer_width * 0.1f)))
                            {
                                KerbalX.image_selector.large_viewer_index++;
                                if (KerbalX.image_selector.large_viewer_index > KerbalX.image_selector.pictures.Count - 1)
                                {
                                    KerbalX.image_selector.large_viewer_index = KerbalX.image_selector.pictures.Count - 1;
                                }
                            }
                            GUILayout.FlexibleSpace();
                            if (GUILayout.Button("X", "button.large.bold", width(viewer_width * 0.1f)))
                            {
                                close_dialog();
                            }
                        });

                        if (KerbalX.image_selector.loaded_pics[pic.id] != true)
                        {
                            KerbalX.log("loading pic");
                            KerbalX.image_selector.loaded_pics[pic.id] = true;
                            StartCoroutine(KerbalX.image_selector.load_image(pic.file.FullName, pic.texture));
                        }
                        GUILayout.Label("Picture " + (large_viewer_index + 1) + "/" + pictures.Count().ToString());
                        section(viewer_width, w2 => {
                            float h = pic.texture.height / (new [] { pic.texture.width, w2 }.Max() / w2);
                            GUILayout.Label(pic.texture, width(viewer_width), height(h));
                            d.window_pos.height = h + 110;
                        });
                    });
                });
                large_viewer.window_pos   = new Rect(this.window_pos.x + this.window_pos.width, KerbalX.upload_gui.window_pos.y + KerbalX.upload_gui.window_pos.height, viewer_width, 20);
                large_viewer.window_title = "Image Viewer";
            }
        }
        //Dialog box to display once an upload has compelted.
        private void show_upload_compelte_dialog(string craft_path)
        {
            KerbalXDialog dialog = show_dialog((d) => {
                v_section(w => {
                    GUILayout.Label("Your craft has uploaded!", "h1");
                    string craft_url = KerbalX.api.url_to(craft_path);
                    GUILayout.Space(10f);
                    if (GUILayout.Button(craft_url, "hyperlink.h2", width(500f)))
                    {
                        Application.OpenURL(craft_url);
                        close_dialog();
                    }
                    section(w2 => {
                        GUILayout.Space(60f);
                        if (GUILayout.Button(StyleSheet.assets["logo large"], "no_style", width(450f), height(81.32f)))
                        {
                            Application.OpenURL(craft_url);
                            close_dialog();
                        }
                    });
                    GUILayout.Label("Click the link (or logo) to view your craft.\nIf you want to change the page layout click the \"Edit Craft\" link at the top of the page.", "centered");
                    section(w3 => {
                        GUILayout.FlexibleSpace();
                        if (GUILayout.Button("close", "button.bold", width(50f), height(20f)))
                        {
                            close_dialog();
                        }
                    });
                });
            });

            dialog.window_title = "";
            dialog.window_pos   = new Rect((Screen.width / 2 - 600f / 2), Screen.height / 4, 600f, 5);
        }
 protected override void OnDestroy()
 {
     base.OnDestroy();                    //releases any UI locks on the editor
     GameEvents.onEditorRestart.Remove(this.on_editor_new);
     KerbalXActionGroupInterface.close(); //destroy action group interface (if it is open)
     KerbalXImageSelector.close();        //destroy image selector (if it is open)
     KerbalXDialog.close();               //destroy dialog (if one is open)
 }
        //reset interface
        internal void reset()
        {
            KerbalX.log("Resetting UploadInterface");
            KerbalXActionGroupInterface.close();        //destroy action group interface (if it is open)
            KerbalXImageSelector.close();               //destroy image selector (if it is open)
            KerbalXDialog.close();                      //destroy dialog (if one is open)
            pictures.Clear();                           //remove all selected pictures
            selected_style_index = 0;                   //reset selected craft style to default (Ship)
            selected_craft_id    = 0;                   //reset selected_craft_id (0 is non-value Database ID)
            update_message       = null;
            List <string> keys = new List <string>(action_groups.Keys);

            foreach (string key in keys)                 //revert all values for action groups back to empty string
            {
                action_groups[key] = "";
            }
            clear_errors();                             //remove all errors (will also call autoheight, which is why this is called last)
        }
 private void download_craft(int id, bool force_download)
 {
     if (force_download)
     {
         KerbalXDownloadController.instance.download_craft(id, craft_list[id]);
     }
     else
     {
         if (File.Exists(craft_list[id]["path"]))
         {
             KerbalXDialog dialog = show_dialog(d => {
                 style_override = GUI.skin.GetStyle("background.dark");
                 v_section(w => {
                     GUILayout.Label("A craft with this name already exists", "h2");
                     GUILayout.Label("You have a craft at: " + craft_list[id]["short_path"], "small");
                 });
                 section(w => {
                     GUILayout.FlexibleSpace();
                     if (GUILayout.Button("Cancel", "button.bold", width(w * 0.2f)))
                     {
                         close_dialog();
                     }
                     if (GUILayout.Button("Replace", "button.bold", width(w * 0.2f)))
                     {
                         KerbalXDownloadController.instance.download_craft(id, craft_list[id]);
                         close_dialog();
                     }
                 });
             });
             dialog.window_pos.width = 400f;
             dialog.window_pos.y     = Screen.height - Input.mousePosition.y - 42; //42 just seemed like the answer, for some reason.
             dialog.window_pos.x     = (window_pos.x + window_pos.width / 2) - dialog.window_pos.width / 2;
             dialog.window_title     = "Replace Existing?";
         }
         else
         {
             KerbalXDownloadController.instance.download_craft(id, craft_list[id]);
         }
     }
 }
        protected override void WindowContent(int win_id)
        {
            if (mode == "url_entry")
            {
                v_section(w => {
                    section(w2 => {
                        GUILayout.Label("Enter the URL to your image", "h2", width(w2 - 100f));
                        if (GUILayout.Button("close", width(100f), height(30)))
                        {
                            this.hide();
                        }
                    });
                    GUILayout.Label("note: one of 'em urls what end with an extension ie .jpg");

                    section(w2 => {
                        pic_url = GUILayout.TextField(pic_url, width(w2 - 100f));
                        if (GUILayout.Button("Add url", width(100f)))
                        {
                            show_content_type_error = false;
//                            HTTP.verify_image(pic_url, (content_type) =>{
//                                Debug.Log("resp: " + content_type);
//                                if(content_type.StartsWith("image/")){
//                                    PicData pic = new PicData();
//                                    pic.url = pic_url;
//                                    KerbalX.upload_gui.add_picture(pic);
//                                    this.hide();
//                                } else{
//                                    show_content_type_error = true;
//                                }
//                            });
                        }
                        ;
                    });

                    if (show_content_type_error)
                    {
                        GUILayout.Label("The entered URL does not return the content-type for an image", "alert");
                    }

                    if (GUILayout.Button("or pic a pic from your pics.", height(40f)))
                    {
                        change_mode("pic_selector");
                    }
                });
            }
            else
            {
                if (!minimized)
                {
                    section(w => {
                        v_section(w - 100f, w2 => {
                            GUILayout.Label("Select a picture for your craft", "h2", width(w2));
                            GUILayout.Label("Click on pics below to add them", width(w2));
                        });
                        v_section(100f, w2 => {
                            if (GUILayout.Button("or enter a url", width(w2), height(30)))
                            {
                                change_mode("url_entry");
                            }
                            if (GUILayout.Button("close", width(w2), height(30)))
                            {
                                this.hide();
                            }
                        });
                    });
                }

                section(w => {
                    if (GUILayout.Button("Take Screenshot now", "button.large", width(w - 40f)))
                    {
                        grab_screenshot();
                    }
                    if (GUILayout.Button((minimized ? ">>" : "<<"), "button.large.bold", width(40f)))
                    {
                        minimized = !minimized;
                        if (minimized)
                        {
                            minimize();
                        }
                        else
                        {
                            maximize();
                        }
                    }
                });

                if (!minimized)
                {
                    GUILayout.Label("Grabs a screen shot of the current view (KX windows will hide while taking the pic).", "small");
                }
                section(w => {
                    GUILayout.Label("pics directory: " + KerbalX.screenshot_dir.Replace(KSPUtil.ApplicationRootPath, ""), width(w - 20f));
                    if (GUILayout.Button("?", width(20f)))
                    {
                        if (tip)
                        {
                            GameObject.Destroy(tip);
                        }
                        else
                        {
                            tip = show_dialog(d => {
                                GUILayout.Label("The default location for loading and saving pictures is the Screenshots folder in your KSP install directory.");
                                GUILayout.Label("You can change where the KerbalX mod will save and load pictures from by changing the path in the settings.cfg file in GameData/KerbalX");
                                section(w2 => {
                                    GUILayout.FlexibleSpace();
                                    if (GUILayout.Button("close", width(50f)))
                                    {
                                        close_dialog();
                                    }
                                });
                            });
                            tip.window_title = "Picture Location";
                            tip.window_pos   = new Rect(this.window_pos.x + this.window_pos.width, Screen.height - Input.mousePosition.y, 400, 30);
                        }
                    }
                });


                //Display picture selector - scrolling container of selectable pictures.
                //picture files will have already been selected and sorted (by prepare_pics()) and then grouped into rows of 4 pics per row (by group_pics())
                //but the files won't have been read yet, so the picture textures haven't been set.  Trying to load all picture textures on load is very time consuming.
                //so instead pictures are loaded and have their texture set row by row, on demand as the user scrolls down.
                if (pictures.Count == 0 && !minimized)
                {
                    GUILayout.Label("You don't have any screen shots in your screen shots folder", "h3");
                    GUILayout.Label("Click Take Screenshot to take one now");
                }
                if (pictures.Count > 0 && !minimized)
                {
                    int n = 0;
                    foreach (bool p in loaded_pics)
                    {
                        if (p)
                        {
                            n++;
                        }
                    }

                    List <string> files = new List <string>();
                    foreach (PicData selected_pic in KerbalX.upload_gui.pictures)
                    {
                        files.Add(selected_pic.file.FullName);
                    }

                    section(w => {
                        GUILayout.Label("loaded " + n + " of " + pictures.Count.ToString() + " pictures");
                        if (GUILayout.Button("large viewer", width(100f)))
                        {
                            toggle_large_viewer();
                        }

                        if (GUILayout.Button("refresh", width(100f)))
                        {
                            prepare_pics();
                        }
                    });

                    pics_scroll_height = pictures.Count <= 4 ? 150f : 300f; //adjust image selector height if 4 or less images


                    scroll_pos = scroll(scroll_pos, 620f, pics_scroll_height, w => {
                        int row_n = 1;
                        foreach (List <PicData> row in groups)
                        {
                            //On demand loading of textures.  As each row comes into focus it's picture's textures are loaded
                            //row_n * 150 (the height of each row) defines it's bottom offset. when that value minus the current scroll pos is less than
                            //the threshold (height of scroll container 300, plus 100 so images load before their in full view), then load the pictures on this row.
                            if ((row_n * 150) - scroll_pos.y <= 400)
                            {
                                foreach (PicData pic in row)
                                {
                                    if (loaded_pics[pic.id] != true)
                                    {
                                        loaded_pics[pic.id] = true;                                 //bool array used to track which pictures have been loaded. checking the texture isn't good enough because of the coroutine
                                        StartCoroutine(load_image(pic.file.FullName, pic.texture)); //Use a Coroutine to load the picture texture with as little interface lag as possible.
                                    }
                                }
                            }
                            row_n++;//increment row count

                            //Draw each row, regardless of wheter picture textures have been loaded (will prob add a 'not yet loaded' texture in at some point TODO)
                            style_override = GUI.skin.GetStyle("background.dark");
                            section(600f, sw => {    //horizontal section....sorry, BeginHorizontal container for the row (slightly narrower than outter container to account for scroll bar)
                                foreach (PicData pic in row)
                                {
                                    v_section(150f, w2 => {                                                      //vertical section, ahem, BeginVertical container for each pic.  Contains two restyled buttons, each will call select_pic.
                                        var style = (hover_ele == pic.file.FullName ? "pic.hover" : "pic.link"); //flip-flop style depending on hover_ele, being == to file name (because I can't figure out how to make style.hover work yet)

                                        if (files.Contains(pic.file.FullName))
                                        {
                                            style = (hover_ele == pic.file.FullName ? "pic.selected.highlighted" : "pic.selected");
                                        }

                                        if (GUILayout.Button(pic.texture, style, width(w2), height(w2 * 0.75f)))
                                        {
                                            toggle_pic(pic);
                                        }
                                        if (GUILayout.Button(pic.name, style, width(w2), height(37.5f)))
                                        {
                                            toggle_pic(pic);
                                        }
                                    });
                                    Vector2 mouse_pos = Input.mousePosition;
                                    mouse_pos.y       = Screen.height - mouse_pos.y;
                                    if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition) && mouse_pos.y < window_pos.y + window_pos.height) //detect if mouse is over the last vertical section
                                    {
                                        KerbalX.log("image hover");
                                        hover_ele = pic.file.FullName;                                        //and hover_ele to that pics filename. used to set on hover style
                                        KerbalX.image_selector.large_viewer_index = pictures.IndexOf(pic);
                                    }
                                }
                            });
                        }
                    });
                }
            }
        }
예제 #10
0
 private void Start()
 {
     KerbalXDialog.instance = this;
     footer    = false;
     is_dialog = true;
 }
예제 #11
0
 //close instance of dialog if it exists.
 protected void close_dialog()
 {
     KerbalXDialog.close();
 }
        //Main Upload/Update interface!
        protected override void WindowContent(int win_id)
        {
            show_upload_bttn = true;
            //get the craft name from the editor field, but allow the user to set a alternative name to upload as without changing the editor field
            //but if the user changes the editor field then reset the craft_name to that. make sense? good, shutup.
            if (editor_craft_name != EditorLogic.fetch.ship.shipName)
            {
                craft_name = EditorLogic.fetch.ship.shipName;
                check_for_matching_craft_name();
            }
            editor_craft_name = EditorLogic.fetch.ship.shipName;

            //Perform checks to see if there is a craft,  its not untitled and a craft file for it exists.
            string trimmed_lowered_name = editor_craft_name.Trim().ToLower().Replace(" ", "");

            if (part_info().Count == 0)
            {
                GUILayout.Label("No craft loaded. Create or load a craft to continue.", "h3");
            }
            else if (trimmed_lowered_name == "untitledspacecraft" || trimmed_lowered_name == EditorLogic.autoShipName)
            {
                GUILayout.Label(editor_craft_name + "? Really?\nHow about you name the poor thing before uploading!", "h3");
            }
            else if (!craft_file_exists())
            {
                section(w => {
                    GUILayout.Label("This craft hasn't been saved yet\nNo craft file found for " + editor_craft_name, "h3", width(w * 0.7f));
                    if (GUILayout.Button("Save it now", width(w * 0.3f), height(40)))
                    {
                        EditorLogic.fetch.saveBtn.onClick.Invoke();
                    }
                });
            }
            else
            {
                //if checks pass continue with drawing rest of interface

                string mode_title = new CultureInfo("en-US", false).TextInfo.ToTitleCase(mode);

                if (fetching_craft)
                {
                    GUILayout.Label("Getting your craft list from KerbalX...", "h3");
                }
                else
                {
                    GUILayout.Label(mode_title + " '" + craft_name + "' " + (mode == "update" ? "on" : "to") + " KerbalX", "h3");

                    if (mode == "upload")
                    {
                        section(w => {
                            GUILayout.Label("Enter details about your craft", width(w * 0.45f));
                            GUILayout.Label("OR", "centered", width(w * 0.1f));
                            if (GUILayout.Button("Update An Existing Craft", width(w * 0.45f)))
                            {
                                change_mode("update");
                                if (matching_craft_ids.Count != 1)
                                {
                                    selected_craft_id = 0;
                                }
                            }
                        });

                        //textfield for craft name, if value is changed it is checked against existing craft (and if match, mode is switched to update).
                        section(w => {
                            string current_craft_name = craft_name; //used to detect if user changes craft_name field (GUI.changed gets triggered by above button)
                            GUILayout.Label("Craft name:", width(80f));
                            craft_name = GUILayout.TextField(craft_name, 255, width(w - 80));
                            if (craft_name != current_craft_name)
                            {
                                check_for_matching_craft_name();//check for matching existing craft
                            }
                        });
                        section(w => {
                            GUILayout.Label("#tags:", width(80f));
                            hash_tags = GUILayout.TextField(hash_tags, 255, width(w - 80));
                        });

                        //drop down select for craft type
                        section(w => {
                            GUILayout.Label("Select craft type:", width(100f));
                            combobox("craft_style_select", craft_styles, selected_style_index, 100f, 150f, this, id => {
                                selected_style_index = id;
                            });
                            if (GUILayout.Button("Edit Description"))
                            {
                                KerbalXDialog dialog = show_dialog(d => {
                                    GUILayout.Label("Edit your craft's description", "h2");
                                    GUILayout.Label("this field edits the description text stored on the craft file, this just provides a larger interface", "small");

                                    EditorLogic.fetch.shipDescriptionField.text = GUILayout.TextArea(EditorLogic.fetch.shipDescriptionField.text, height(350f));
                                    if (GUILayout.Button("Close", "button.bold"))
                                    {
                                        EditorLogic.fetch.saveBtn.onClick.Invoke();
                                        close_dialog();
                                    }
                                    GUILayout.Label("Note: closing this also saves the craft, so changes to the description are kept", "small");
                                });
                                dialog.window_pos   = new Rect(Screen.width / 2 - 300, 200, 600, 400);
                                dialog.window_title = "Edit Description";
                            }
                        });

                        //buttons for setting action groups and adding pictures.
                        section(w => {
                            if (GUILayout.Button("Edit Action Group info", width(w * 0.5f), height(30)))
                            {
                                if (KerbalX.action_group_gui)
                                {
                                    KerbalX.action_group_gui.toggle();
                                }
                                else
                                {
                                    launch("ActionGroupEditor");
                                }
                            }
                            if (GUILayout.Button("Add Pictures", width(w * 0.5f), height(30)))
                            {
                                if (KerbalX.image_selector)
                                {
                                    KerbalX.image_selector.toggle();
                                }
                                else
                                {
                                    launch("ImageSelector");
                                }
                            }
                        });

                        //Display of selected pictures (and/or image urls)
                        v_section(w => {
                            section(w2 => {
                                foreach (PicData pic in pictures)        //display selected pictures
                                {
                                    v_section(80f, w3 => {
                                        if (pic.file != null)
                                        {
                                            GUILayout.Label(pic.texture, width(w3), height(w3 * 0.75f));
                                            if (GUILayout.Button("remove"))
                                            {
                                                remove_picture(pic);
                                            }
                                        }
                                    });
                                }
                            });
                            foreach (PicData pic in pictures)            //display entered image urls.
                            {
                                section(w2 => {
                                    if (pic.url != null)
                                    {
                                        GUILayout.Label(pic.url, width(w2 - 80f));
                                        if (GUILayout.Button("remove", width(80f)))
                                        {
                                            remove_picture(pic);
                                        }
                                    }
                                });
                            }
                        });
                    }
                    else if (mode == "update")
                    {
                        if (KerbalX.existing_craft.Count == 0) //show message if the user doesn't have any craft on KerbalX yet.
                        {
                            show_upload_bttn = false;
                            GUILayout.Label("You haven't uploaded any craft yet", "h2");
                            GUILayout.Label("Once you've uploaded craft they will appear here and you'll be able to select them to update");
                            section(w => {
                                GUILayout.FlexibleSpace();
                                if (GUILayout.Button("refresh", width(60f)))
                                {
                                    fetch_existing_craft();
                                }
                            });
                            if (GUILayout.Button("Upload a Craft", height(30f)))
                            {
                                change_mode("upload");
                            }
                        }
                        else
                        {
                            //Show message if the current craft name matches the name of one of the users craft on KerbalX
                            if (matching_craft_ids.Count > 0)
                            {
                                string label_text = "This craft's name matches the name of " + (matching_craft_ids.Count == 1 ? "a" : "several") + " craft you've already uploaded.";
                                if (matching_craft_ids.Count > 1)
                                {
                                    label_text = label_text + " Select which one you want to update"; //in the case of more than one match.
                                }
                                GUILayout.Label(label_text);
                            }

                            section(w => {
                                v_section(w * 0.7f, inner_w => {
                                    section(inner_w, inner_w2 => {
                                        GUILayout.Label("Select Craft on KerbalX to update:");
                                    });
                                    combobox("craft_select", remote_craft, selected_craft_id, inner_w, 150f, this, id => {
                                        selected_craft_id = id;
                                        autoheight();
                                    });
                                });
                                section(w * 0.3f, inner_w2 => {
                                    if (GUILayout.Button("OR upload this as a new craft", "button.wrapped", height(50)))
                                    {
                                        change_mode("upload");
                                    }
                                });
                            });

                            if (selected_craft_id != 0)
                            {
                                style_override = GUI.skin.GetStyle("background.dark.margin");
                                v_section(w => {
                                    GUILayout.Label("Pressing Update will update the this craft on KerbalX:", "h3");
                                    GUILayout.Label(KerbalX.existing_craft[selected_craft_id]["name"] + " (id: " + selected_craft_id + ")", "h3");
                                    string craft_url = KerbalX.api.url_to(KerbalX.existing_craft[selected_craft_id]["url"]);
                                    if (GUILayout.Button(craft_url, "hyperlink.h3"))
                                    {
                                        Application.OpenURL(craft_url);
                                    }
                                    GUILayout.Label("Make sure this is the craft you want update!");
                                });
                            }
                        }
                    }
                }

                //Display any errors preventing upload
                if (errors.Count() > 0)
                {
                    style_override = GUI.skin.GetStyle("background.dark.margin");
                    v_section(w => {
                        foreach (string error in errors)
                        {
                            GUILayout.Label(error.Trim(), "alert", width(w));
                        }
                    });
                }

                //The great big ol' thing what you whack to make stuff happen
                if (show_upload_bttn && !fetching_craft)
                {
                    GUI.enabled = enable_upload_bttn;
                    section(w => {
                        if (GUILayout.Button(mode_title + "!", "button.upload"))
                        {
                            if (mode == "update")
                            {
                                update_craft();
                            }
                            else
                            {
                                upload_craft();
                            }
                        }
                    });
                    GUI.enabled = true;
                }

                //display some feedback to show that upload/update is happening
                if (transfer_activity != null || fetching_craft)
                {
                    v_section(w => {
                        if (transfer_activity != null)
                        {
                            GUILayout.Label(transfer_activity, "h2");
                        }
                        progress_spinner(w, 5, 20);
                    });
                }
                if (update_message != null)
                {
                    GUILayout.Label(update_message, "h2.centered");
                }
            }
        }