public void Render()
        {
            // Editor locking logic adapted from m4v's RCSBuildAid.

            Scene loadedScene = GUIWindow.SceneFromGameScenes(HighLogic.LoadedScene);

            if ((this.scene & loadedScene) == loadedScene)
            {
                if (this.Visible)
                {
                    GUI.skin.window.clipping = TextClipping.Clip;

                    this.window = GUILayout.Window(this.windowId, this.window, this.InternalRender, this.title);

                    foreach (GUIWindow child in this.children)
                    {
                        child.Render();
                    }

                    if (Event.current.type == EventType.Repaint)
                    {
                        this.mouseOver = GUIControls.MouseOverWindow(ref this.window);

                        if (this.mouseOver && !this.editorLocked)
                        {
                            InputLockManager.SetControlLock(GUIWindow.EditorLockControlTypes, this.editorLockToken);
                            this.editorLocked = true;
                        }
                        else if (!this.mouseOver && this.editorLocked)
                        {
                            InputLockManager.RemoveControlLock(this.editorLockToken);
                            this.editorLocked = false;
                        }
                    }
                }
                else if (this.editorLocked)
                {
                    InputLockManager.RemoveControlLock(this.editorLockToken);
                    this.editorLocked = false;
                }
            }
        }
        private void InternalRender(int renderingWindowId)
        {
            GUIControls.BeginLayout();

            try
            {
                if (GUIControls.TitleBarButton(this.window))
                {
                    this.Hide();

                    GUI.DragWindow();
                }
                else
                {
                    if (!this.renderError)
                    {
                        this.OnRender();
                    }
                    else
                    {
                        this.OnErrorRender();
                    }
                }
            }
            catch (Exception e)
            {
                this.renderError = true;

                Log.Trace("Window rendering error, details follow:");
                Debug.LogException(e);

                throw;
            }
            finally
            {
                GUIControls.EndLayout();
            }
        }
        public override void OnRender()
        {
            try
            {
                List <Part> parts = EditorLogic.fetch.ship != null ? EditorLogic.fetch.ship.Parts : new List <Part>();

                this.highlight.BeginTracking();

                GUILayout.BeginVertical();

                // If Blizzy's toolbar is available, give the user the option to pick the stock toolbar.
                if (ToolbarManager.ToolbarAvailable)
                {
                    bool stockToolbar = PartWizardPlugin.ToolbarIsStock;
                    stockToolbar = GUILayout.Toggle(stockToolbar, "Use KSP's Stock Toolbar", GUILayout.Width(200));
                    if (stockToolbar != PartWizardPlugin.ToolbarIsStock)
                    {
                        PartWizardPlugin.ToolbarTypeToggleActive = true;
                    }
                }

                #region Display Mode Control

                GUILayout.BeginHorizontal();

                this.viewType = (ViewType)GUIControls.HorizontalToggleSet((int)this.viewType, this.viewTypeContents, this.selectedViewTypeStyle, this.unselectedViewTypeStyle);

                GUILayout.EndHorizontal();

                List <Part> buyableParts = null;

                if (this.viewType == ViewType.Hidden)
                {
                    parts = parts.FindAll((p) => { return(p.partInfo.category == PartCategories.none); });
                }
                else if (this.viewType == ViewType.Unavailable)
                {
                    parts = parts.FindAll((p) => {
                        bool result = false;

                        // Get the R&D technology state for the current part.
                        ProtoTechNode techState = ResearchAndDevelopment.Instance.GetTechState(p.partInfo.TechRequired);

                        // If there is a state or the technology is locked or the part hasn't been purchased...
                        if (techState == null || techState.state != RDTech.State.Available || !techState.partsPurchased.Contains(p.partInfo))
                        {
                            // ...add it to the list.
                            result = true;
                        }

                        return(result);
                    });

                    // Stash the filtered list in to the buyable list.
                    buyableParts = parts;
                    // Create a new collection with a copy of all the buyable parts.
                    parts = new List <Part>(buyableParts);
                    // Create a hash set to act as a filter for duplicate parts.
                    HashSet <string> duplicatePartFilter = new HashSet <string>();
                    // Remove each part that has already been added to the hash filter.
                    parts.RemoveAll((p) => !duplicatePartFilter.Add(p.name));

                    // Here parts is a list of unique buyable parts and buyableParts is all of the buyable parts, including duplicates.
                }

                #endregion

                #region Part List

                GUILayout.BeginVertical(GUIControls.PanelStyle);

                this.scrollPosition = GUILayout.BeginScrollView(this.scrollPosition, false, false);

                int totalEntryCost = 0;

                foreach (Part part in parts)
                {
                    totalEntryCost += part.partInfo.entryCost;

                    GUIControls.BeginMouseOverHorizontal();

                    bool actionEditorPartButtonMouseOver = false;

                    #region Part Label

                    if (EditorLogic.fetch.editorScreen != EditorScreen.Actions)
                    {
                        GUILayout.Label(new GUIContent(part.partInfo.title, part.partInfo.name));
                    }
                    else
                    {
                        if (GUIControls.MouseOverButton(new GUIContent(part.partInfo.title, part.partInfo.name), out actionEditorPartButtonMouseOver, this.actionEditorModePartButtonStyle))
                        {
                            // Each part gets the EditorActionPartSelector added to it when the editor switches to the Actions screen. (And it
                            // gets taken away when leaving that screen.)
                            EditorActionPartSelector selector = part.GetComponent <EditorActionPartSelector>();

                            // Make sure we have it...
                            if (selector != null)
                            {
                                // ...and select it.
                                selector.Select();

                                Log.Write("Action editor selecting part {0}.", part.name);
                            }
                        }
                    }

                    #endregion

                    GUILayout.FlexibleSpace();

                    // Only enable the following buttons if there is no actively selected part, but we want to have them drawn.
                    GUI.enabled = EditorLogic.SelectedPart == null;

                    bool deleted = false;                   // Will be set to true if the delete button was pressed.
                    bool bought  = false;                   // Will be set to true if the buy button was pressed.

                    bool breakSymmetryMouseOver = false;    // Will be set to true if the mouse is over the part's break symmetry button.
                    bool deleteButtonMouseOver  = false;    // Will be set to true if the mouse is over the part's delete button.
                    bool buyButtonMouseOver     = false;    // Will be set to true if the mouse is over the part's buy button.

                    string deleteTooltip = default(string);
                    string buyTooltip    = default(string);

                    if (this.viewType == ViewType.All || this.viewType == ViewType.Hidden)
                    {
                        #region Break Symmetry Button

                        string breakabilityReport = default(string);
                        GUI.enabled = EditorLogic.SelectedPart == null && EditorLogic.fetch.editorScreen == EditorScreen.Parts && PartWizard.HasBreakableSymmetry(part, out breakabilityReport);

                        string breakSymmetryTooltip = GUI.enabled ? Localized.BreakSymmetryDescription : default(string);

                        breakSymmetryMouseOver = false;
                        if (GUIControls.MouseOverButton(new GUIContent(Localized.BreakSymmetryButtonText, breakSymmetryTooltip), out breakSymmetryMouseOver, Configuration.PartActionButtonWidth))
                        {
                            this.symmetryEditorWindow.Part = part;

                            if (!this.symmetryEditorWindow.Visible)
                            {
                                this.symmetryEditorWindow.Show(this);

                                // Short circuit the mouse over for breaking symmetry when showing the Symmetry Editor in case it appears over top of this
                                // button and immediately begins highlighting parts. This would cause *this* window's highlighting to be stuck on the part.
                                breakSymmetryMouseOver = false;
                            }
                        }

                        breakSymmetryMouseOver &= GUI.enabled;  // Clear mouse over flag if the symmetry button was disabled.

                        #endregion

                        #region Delete Button

                        GUI.enabled = EditorLogic.SelectedPart == null && EditorLogic.fetch.editorScreen == EditorScreen.Parts && PartWizard.IsDeleteable(part);

                        deleteTooltip = GUI.enabled
                            ? ((part.symmetryCounterparts.Count == 0) ? Localized.DeletePartSingularDescription : Localized.DeletePartPluralDescription)
                            : default(string);

                        if (GUIControls.MouseOverButton(new GUIContent(Localized.DeletePartButtonText, deleteTooltip), out deleteButtonMouseOver, Configuration.PartActionButtonWidth))
                        {
                            PartWizard.Delete(part);

                            // Set a flag so additional GUI logic can decide what to do in the case where a part is deleted.
                            deleted = true;
                        }

                        deleteButtonMouseOver &= GUI.enabled;   // Clear mouse over flag if the delete button was disabled.

                        #endregion
                    }
                    else // this.viewType == ViewType.Unavailable
                    {
                        #region Buy Button

                        GUI.enabled = EditorLogic.SelectedPart == null && (double)part.partInfo.entryCost <= Funding.Instance.Funds && PartWizard.IsBuyable(part);

                        buyTooltip = GUI.enabled ? string.Format(Localized.BuyPartDescriptionTextFormat, part.partInfo.entryCost) : default(string);

                        if (GUIControls.MouseOverButton(new GUIContent(Localized.BuyPartButtonText, buyTooltip), out buyButtonMouseOver, Configuration.PartActionButtonWidth))
                        {
                            Log.Write("Buying part {0}.", part.name);

                            PartWizard.Buy(part, true);

                            // Set a flag so additional GUI logic can decide what to do in the case where a part is bought.
                            bought = true;
                        }

                        buyButtonMouseOver &= GUI.enabled;  // Clear mouse over flag if the buy button was disabled.

                        #endregion
                    }

                    GUI.enabled = true;

                    bool groupMouseOver = false;
                    GUIControls.EndMouseOverHorizontal(out groupMouseOver);     // End of row for this part.

                    // If we deleted a part, then just jump out of the loop since the parts list has been modified.
                    if (deleted || bought)
                    {
                        break;
                    }

                    #region Part Highlighting Control

                    if (breakSymmetryMouseOver)
                    {
                        this.highlight.Add(part, Configuration.HighlightColorEditableSymmetryRoot, Configuration.HighlightColorEditableSymmetryCounterparts, true);
                    }
                    else if (deleteButtonMouseOver)
                    {
                        this.highlight.Add(part, Configuration.HighlightColorDeletablePart, Configuration.HighlightColorDeletableCounterparts, true);
                    }
                    else if (buyButtonMouseOver)
                    {
                        // TODO: Duplicate code!
                        buyableParts.ForEach((p) => {
                            if (part.name == p.name)
                            {
                                this.highlight.Add(p, Configuration.HighlightColorBuyablePart);
                            }
                        });
                    }
                    else if (groupMouseOver)
                    {
                        if (viewType != ViewType.Unavailable)
                        {
                            Color highlightColor            = (part == EditorLogic.RootPart) ? Configuration.HighlightColorRootPart : Configuration.HighlightColorSinglePart;
                            Color counterpartHighlightColor = Configuration.HighlightColorCounterparts;

                            if (EditorLogic.fetch.editorScreen == EditorScreen.Actions)
                            {
                                highlightColor            = Configuration.HighlightColorActionEditorTarget;
                                counterpartHighlightColor = Configuration.HighlightColorActionEditorTarget;
                            }

                            this.highlight.Add(part, highlightColor, counterpartHighlightColor, false);
                        }
                        else
                        {
                            // TODO: Duplicate code!
                            buyableParts.ForEach((p) => {
                                if (part.name == p.name)
                                {
                                    this.highlight.Add(p, Configuration.HighlightColorBuyablePart, false);
                                }
                            });
                        }
                    }
                    else if (actionEditorPartButtonMouseOver)
                    {
                        this.highlight.Add(part, Configuration.HighlightColorActionEditorTarget, Configuration.HighlightColorActionEditorTarget);
                    }

                    #endregion
                }

                GUILayout.EndScrollView();

                GUILayout.EndVertical();

                if (viewType == ViewType.Unavailable)
                {
                    int  buyableEntryCost = 0;
                    bool enableBulkBuy    = false;

                    foreach (Part p in parts)
                    {
                        buyableEntryCost += p.partInfo.entryCost;

                        enableBulkBuy |= PartWizard.IsBuyable(p);
                    }

                    GUI.enabled = parts.Count > 0 && (double)buyableEntryCost <= Funding.Instance.Funds && enableBulkBuy;

                    bool buyAllMouseOver = false;
                    if (GUIControls.MouseOverButton(new GUIContent(string.Format(Localized.BuyAllButtonTextFormat, buyableEntryCost)), out buyAllMouseOver))
                    {
                        foreach (Part part in parts)
                        {
                            Log.Write("Buying part {0}.", part.name);

                            PartWizard.Buy(part);
                        }

                        PartWizard.SaveGame();
                    }

                    // TODO: Highlight all parts that will be bought by clicking Buy All.
                    if (buyAllMouseOver)
                    {
                        buyableParts.ForEach((p) => {
                            this.highlight.Add(p, Configuration.HighlightColorBuyablePart);
                        });
                    }

                    GUI.enabled = true;
                }

                #endregion

                #region Status Area

                GUILayout.Space(3);

                string status = default(string);

                if (!string.IsNullOrEmpty(GUI.tooltip))
                {
                    if (parts.Count != 1)
                    {
                        status = string.Format(CultureInfo.CurrentCulture, Localized.StatusLabelPluralTooltipTextFormat, parts.Count, GUI.tooltip);
                    }
                    else
                    {
                        status = string.Format(CultureInfo.CurrentCulture, Localized.StatusLabelSingularTooltipTextFormat, parts.Count, GUI.tooltip);
                    }
                }
                else
                {
                    if (parts.Count != 1)
                    {
                        status = string.Format(CultureInfo.CurrentCulture, Localized.StatusLabelPluralTextFormat, parts.Count);
                    }
                    else
                    {
                        status = string.Format(CultureInfo.CurrentCulture, Localized.StatusLabelSingularTextFormat, parts.Count);
                    }
                }

                GUILayout.Label(status, this.tooltipLabelStyle);

                #endregion

                GUILayout.EndVertical();

                if (this.Visible && this.mouseOver)
                {
                    this.highlight.EndTracking();
                }
                else
                {
                    this.highlight.CancelTracking();
                }
            }
            catch (Exception e)
            {
                Log.Write("PartWizardWindow.OnRender() unexpected exception caught.");

                Log.Write(e.Message);
                Log.Write(e.StackTrace);

                this.highlight.CancelTracking();

                throw;
            }
            finally
            {
                GUI.DragWindow();
            }
        }
Beispiel #4
0
        public override void OnRender()
        {
            try
            {
                List <Part> parts = EditorLogic.fetch.ship != null ? EditorLogic.fetch.ship.Parts : new List <Part>();

                this.highlight.BeginTracking();

                GUILayout.BeginVertical();

#if false
                // If Blizzy's toolbar is available, give the user the option to pick the stock toolbar.
                if (ToolbarManager.ToolbarAvailable)
#endif
                {
                    //bool stockToolbar = PartWizardPlugin.ToolbarIsStock;
                    bool stockToolbar = GUILayout.Toggle(PartWizardPlugin.ToolbarIsStock, Localized.UseStockToolbar, GUILayout.Width(200));
                    if (stockToolbar != PartWizardPlugin.ToolbarIsStock)
                    {
#if false
                        PartWizardPlugin.ToolbarTypeToggleActive = true;
#endif
                        PartWizardPlugin.ToolbarIsStock = stockToolbar;
                        PartWizardPlugin.Instance.SaveToolbarConfiguration();
                    }
                }

                #region Display Mode Control

                GUILayout.BeginHorizontal();
                this.viewType = (ViewType)GUIControls.HorizontalToggleSet((int)this.viewType, this.viewTypeContents, this.selectedViewTypeStyle, this.unselectedViewTypeStyle);
                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();
                GUILayout.Label("Sort by:");
                this.sortBy = (SortBy)GUIControls.HorizontalToggleSet((int)this.sortBy, this.sortTypeContents, this.selectedViewTypeStyle, this.unselectedViewTypeStyle);
                GUILayout.EndHorizontal();

                List <Part> buyableParts = null;

                if (this.viewType == ViewType.Hidden)
                {
                    parts = parts.FindAll((p) => { return(p.partInfo.category == PartCategories.none); });
                }
                else if (this.viewType == ViewType.Unavailable)
                {
                    parts = parts.FindAll((p) => {
                        bool result = false;

                        // Get the R&D technology state for the current part.
                        ProtoTechNode techState = ResearchAndDevelopment.Instance.GetTechState(p.partInfo.TechRequired);

                        // If there is a state or the technology is locked or the part hasn't been purchased...
                        if (techState == null || techState.state != RDTech.State.Available || !techState.partsPurchased.Contains(p.partInfo))
                        {
                            // ...add it to the list.
                            result = true;
                        }

                        return(result);
                    });
                    Debug.Log("total # buyable part: " + parts.Count.ToString());
                    // Stash the filtered list in to the buyable list.
                    buyableParts = parts;
                    // Create a new collection with a copy of all the buyable parts.
                    parts = new List <Part>(buyableParts);
                    // Create a hash set to act as a filter for duplicate parts.
                    HashSet <string> duplicatePartFilter = new HashSet <string>();
                    // Remove each part that has already been added to the hash filter.
                    parts.RemoveAll((p) => !duplicatePartFilter.Add(p.name));

                    // Here parts is a list of unique buyable parts and buyableParts is all of the buyable parts, including duplicates.
                    Debug.Log("total # buyable part after dup filter: " + parts.Count.ToString());
                }

                #endregion
                if (parts != null && parts.Count > 0)
                {
                    switch (sortBy)
                    {
                    case SortBy.Name:
                        parts.Sort((p, q) => p.partInfo.title.CompareTo(q.partInfo.title));
                        break;

                    case SortBy.StageAsc:
                        if (this.viewType != ViewType.Unavailable)
                        {
                            parts.Sort((p, q) => p.inverseStage.CompareTo(q.inverseStage));
                        }
                        else
                        {
                            parts.Sort((p, q) => p.partInfo.title.CompareTo(q.partInfo.title));
                        }
                        break;

                    case SortBy.StageDesc:
                        if (this.viewType != ViewType.Unavailable)
                        {
                            parts.Sort((q, p) => p.inverseStage.CompareTo(q.inverseStage));
                        }
                        else
                        {
                            parts.Sort((p, q) => p.partInfo.title.CompareTo(q.partInfo.title));
                        }
                        break;
                    }
                }
                #region Part List

                GUILayout.BeginVertical(GUIControls.PanelStyle);

                this.scrollPosition = GUILayout.BeginScrollView(this.scrollPosition, false, false);

                int totalEntryCost   = 0;
                int visiblePartCount = 0;
                int lastStage        = 0;
                if (parts != null && parts.Count > 0)
                {
                    lastStage = parts[0].inverseStage;
                }

                if (this.viewType == ViewType.Category)
                {
                    if (GUILayout.Button(Localized.ViewAll))
                    {
                        for (int i = 0; i < visibleCategories.Length; i++)
                        {
                            visibleCategories[i] = true;
                        }
                    }
                    if (GUILayout.Button(Localized.Clear))
                    {
                        for (int i = 0; i < visibleCategories.Length; i++)
                        {
                            visibleCategories[i] = false;
                        }
                    }

                    for (PartCategories partCategories = PartCategories.Propulsion; partCategories < PartCategories.Coupling; partCategories++)
                    {
                        // Need to add one to the PartCategories because "none" is a -1, and some parts have a category = none
                        visibleCategories[(int)partCategories + 1] = GUILayout.Toggle(visibleCategories[(int)partCategories + 1], partCategories.ToString(), toggleStyle);
                    }
                }
                else if (this.viewType == ViewType.Resources)
                {
                    if (GUILayout.Button(Localized.ViewAll))
                    {
                        foreach (ResourceInfo resourceInfo in this.availableResources.Values)
                        {
                            resourceInfo.Visible = true;
                        }
                    }

                    if (GUILayout.Button(Localized.Clear))
                    {
                        foreach (ResourceInfo resourceInfo in this.availableResources.Values)
                        {
                            resourceInfo.Visible = false;
                        }
                    }

                    foreach (string availableResource in this.availableResources.Keys)
                    {
                        bool resourceVisible = GUILayout.Toggle(this.availableResources[availableResource].Visible, availableResource, toggleStyle);

                        this.availableResources[availableResource].Visible = resourceVisible;
                    }
                }
                else
                {
                    foreach (Part part in parts)
                    {
                        // Reset part name label color to default; some conditions may change the color to indicate various things.
                        labelStyle.normal.textColor = PartWizardWindow.DefaultPartNameColor;
                        // Check if this part's category is currently visible.
                        // Need to add one to the PartCategories because "none" is a -1, and some parts have a category = none
                        if (visibleCategories[(int)part.partInfo.category + 1])
                        {
                            // The part's category is visible, now check resource conditions to determine final visibility.
                            bool partVisible = false;

                            if (this.availableResources[Localized.ShowPartsWithoutResources].Visible && part.Resources.Count == 0)
                            {
                                partVisible = true;
                            }
                            else
                            {
                                foreach (PartResource partResource in part.Resources)
                                {
                                    if (this.availableResources[partResource.resourceName].Visible)
                                    {
                                        partVisible = true;
                                        break;
                                    }
                                }
                            }
                            if (partVisible)
                            {
                                totalEntryCost += part.partInfo.entryCost;
                                visiblePartCount++;

                                GUIControls.BeginMouseOverHorizontal();

                                bool actionEditorPartButtonMouseOver = false;

                                #region Part Label

                                if (sortBy == SortBy.StageAsc || sortBy == SortBy.StageDesc)
                                {
                                    if (lastStage != part.inverseStage)
                                    {
                                        lastStage = part.inverseStage;
                                    }
                                    GUILayout.Label(lastStage.ToString() + ": ");
                                }
                                if (EditorLogic.fetch.editorScreen != EditorScreen.Actions)
                                {
                                    // Check compound parts for integrity.
                                    if (part is CompoundPart)
                                    {
                                        CompoundPart compoundPart = (CompoundPart)part;
                                        if (compoundPart.attachState == CompoundPart.AttachState.Detached || compoundPart.attachState == CompoundPart.AttachState.Attaching || compoundPart.target == compoundPart.parent)
                                        {
                                            labelStyle.normal.textColor = Color.red;
                                        }
                                    }
                                    labelStyle.fixedWidth = 250;
                                    GUILayout.Label(new GUIContent(part.partInfo.title, part.partInfo.name), labelStyle);
                                }
                                else
                                {
                                    Log.Write("EditorScreen.Actions, part: " + part.partInfo.title);
                                    if (GUIControls.MouseOverButton(new GUIContent(part.partInfo.title, part.partInfo.name), out actionEditorPartButtonMouseOver, this.actionEditorModePartButtonStyle))
                                    {
                                        // Each part gets the EditorActionPartSelector added to it when the editor switches to the Actions screen. (And it
                                        // gets taken away when leaving that screen.)
                                        EditorActionPartSelector selector = part.GetComponent <EditorActionPartSelector>();

                                        // Make sure we have it...
                                        if (selector != null)
                                        {
                                            // ...and select it.
                                            selector.Select();

                                            Log.Write("Action editor selecting part {0}.", part.name);
                                        }
                                    }
                                }

                                #endregion

                                // Adds space between the part name and the buttons (if any) associated with the part.
                                GUILayout.FlexibleSpace();

                                // Only enable the following buttons if there is no actively selected part, but we want to have them drawn.
                                GUI.enabled = EditorLogic.SelectedPart == null;

                                bool deleted = false;                   // Will be set to true if the delete button was pressed.
                                bool bought  = false;                   // Will be set to true if the buy button was pressed.

                                bool breakSymmetryMouseOver = false;    // Will be set to true if the mouse is over the part's break symmetry button.
                                bool deleteButtonMouseOver  = false;    // Will be set to true if the mouse is over the part's delete button.
                                bool buyButtonMouseOver     = false;    // Will be set to true if the mouse is over the part's buy button.

                                string deleteTooltip = default(string);
                                string buyTooltip    = default(string);

                                if (this.viewType == ViewType.All || this.viewType == ViewType.Hidden)
                                {
                                    #region Break Symmetry Button

                                    string breakabilityReport = default(string);
                                    GUI.enabled = EditorLogic.SelectedPart == null && EditorLogic.fetch.editorScreen == EditorScreen.Parts && PartWizard.HasBreakableSymmetry(part, out breakabilityReport);

                                    string breakSymmetryTooltip = GUI.enabled ? Localized.BreakSymmetryDescription : default(string);

                                    breakSymmetryMouseOver = false;
                                    if (GUIControls.MouseOverButton(new GUIContent(Localized.BreakSymmetryButtonText, breakSymmetryTooltip), out breakSymmetryMouseOver, Configuration.PartActionButtonWidth))
                                    {
                                        this.symmetryEditorWindow.Part = part;

                                        if (!this.symmetryEditorWindow.Visible)
                                        {
                                            this.symmetryEditorWindow.Show(this);

                                            // Short circuit the mouse over for breaking symmetry when showing the Symmetry Editor in case it appears over top of this
                                            // button and immediately begins highlighting parts. This would cause *this* window's highlighting to be stuck on the part.
                                            breakSymmetryMouseOver = false;
                                        }
                                    }

                                    breakSymmetryMouseOver &= GUI.enabled;  // Clear mouse over flag if the symmetry button was disabled.

                                    #endregion

                                    #region Delete Button

                                    GUI.enabled = EditorLogic.SelectedPart == null && EditorLogic.fetch.editorScreen == EditorScreen.Parts && PartWizard.IsDeleteable(part);

                                    deleteTooltip = GUI.enabled
                                        ? ((part.symmetryCounterparts.Count == 0) ? Localized.DeletePartSingularDescription : Localized.DeletePartPluralDescription)
                                        : default(string);

                                    if (GUIControls.MouseOverButton(new GUIContent(Localized.DeletePartButtonText, deleteTooltip), out deleteButtonMouseOver, Configuration.PartActionButtonWidth))
                                    {
                                        PartWizard.Delete(part);

                                        // Set a flag so additional GUI logic can decide what to do in the case where a part is deleted.
                                        deleted = true;
                                    }

                                    deleteButtonMouseOver &= GUI.enabled;   // Clear mouse over flag if the delete button was disabled.

                                    #endregion
                                }
                                else // this.viewType == ViewType.Unavailable
                                {
                                    #region Buy Button

                                    GUI.enabled = EditorLogic.SelectedPart == null && (double)part.partInfo.entryCost <= Funding.Instance.Funds && PartWizard.IsBuyable(part);

                                    buyTooltip = GUI.enabled ? string.Format(Localized.BuyPartDescriptionTextFormat, part.partInfo.entryCost) : default(string);

                                    if (GUIControls.MouseOverButton(new GUIContent(Localized.BuyPartButtonText, buyTooltip), out buyButtonMouseOver, Configuration.PartActionButtonWidth))
                                    {
                                        Log.Write("Buying part {0}.", part.name);

                                        PartWizard.Buy(part, true);

                                        // Set a flag so additional GUI logic can decide what to do in the case where a part is bought.
                                        bought = true;
                                    }

                                    buyButtonMouseOver &= GUI.enabled;  // Clear mouse over flag if the buy button was disabled.

                                    #endregion
                                }

                                GUI.enabled = true;

                                bool groupMouseOver = false;
                                GUIControls.EndMouseOverHorizontal(out groupMouseOver);     // End of row for this part.

                                // If we deleted a part, then just jump out of the loop since the parts list has been modified.
                                if (deleted || bought)
                                {
                                    break;
                                }

                                #region Part Highlighting Control

                                if (breakSymmetryMouseOver)
                                {
                                    this.highlight.Add(part, Configuration.HighlightColorEditableSymmetryRoot, Configuration.HighlightColorEditableSymmetryCounterparts, true);
                                }
                                else if (deleteButtonMouseOver)
                                {
                                    this.highlight.Add(part, Configuration.HighlightColorDeletablePart, Configuration.HighlightColorDeletableCounterparts, true);
                                }
                                else if (buyButtonMouseOver)
                                {
                                    // TODO: Duplicate code!
                                    buyableParts.ForEach((p) => {
                                        if (part.name == p.name)
                                        {
                                            this.highlight.Add(p, Configuration.HighlightColorBuyablePart);
                                        }
                                    });
                                }
                                else if (groupMouseOver)
                                {
                                    if (viewType != ViewType.Unavailable)
                                    {
                                        Color highlightColor            = (part == EditorLogic.RootPart) ? Configuration.HighlightColorRootPart : Configuration.HighlightColorSinglePart;
                                        Color counterpartHighlightColor = Configuration.HighlightColorCounterparts;

                                        if (EditorLogic.fetch.editorScreen == EditorScreen.Actions)
                                        {
                                            highlightColor            = Configuration.HighlightColorActionEditorTarget;
                                            counterpartHighlightColor = Configuration.HighlightColorActionEditorTarget;
                                        }

                                        this.highlight.Add(part, highlightColor, counterpartHighlightColor, false);
                                    }
                                    else
                                    {
                                        // TODO: Duplicate code!
                                        buyableParts.ForEach((p) => {
                                            if (part.name == p.name)
                                            {
                                                Log.Write("Highlighting 2 part: " + part.partInfo.title);
                                                this.highlight.Add(p, Configuration.HighlightColorBuyablePart, false);
                                            }
                                        });
                                    }
                                }
                                else if (actionEditorPartButtonMouseOver)
                                {
                                    Log.Write("Highlighting part: " + part.partInfo.title);
                                    this.highlight.Add(part, Configuration.HighlightColorActionEditorTarget, Configuration.HighlightColorActionEditorTarget);
                                }

                                #endregion
                            }
                        }
                    }
                }

                GUILayout.EndScrollView();

                GUILayout.EndVertical();

                if (viewType == ViewType.Unavailable)
                {
                    int  buyableEntryCost = 0;
                    bool enableBulkBuy    = false;

                    foreach (Part p in parts)
                    {
                        buyableEntryCost += p.partInfo.entryCost;

                        enableBulkBuy |= PartWizard.IsBuyable(p);
                    }

                    GUI.enabled = parts.Count > 0 && (double)buyableEntryCost <= Funding.Instance.Funds && enableBulkBuy;

                    bool buyAllMouseOver = false;
                    if (GUIControls.MouseOverButton(new GUIContent(string.Format(Localized.BuyAllButtonTextFormat, buyableEntryCost)), out buyAllMouseOver))
                    {
                        foreach (Part part in parts)
                        {
                            if (PartWizard.IsBuyable(part))
                            {
                                Log.Write("Buying part {0}.", part.name);

                                PartWizard.Buy(part, false);
                            }
                        }

                        PartWizard.SaveGame();
                    }

                    // TODO: Highlight all parts that will be bought by clicking Buy All.
                    if (buyAllMouseOver)
                    {
                        buyableParts.ForEach((p) => {
                            this.highlight.Add(p, Configuration.HighlightColorBuyablePart);
                        });
                    }

                    GUI.enabled = true;
                }

                #endregion

                #region Status Area

                // Push everything above this up, otherwise it will be centered vertically.
                GUILayout.FlexibleSpace();

                if (viewType == ViewType.All || viewType == ViewType.Hidden || viewType == ViewType.Unavailable)
                {
                    string status = default(string);

                    if (!string.IsNullOrEmpty(GUI.tooltip))
                    {
                        if (parts.Count != 1)
                        {
                            status = string.Format(CultureInfo.CurrentCulture, Localized.StatusLabelPluralTooltipTextFormat, visiblePartCount, GUI.tooltip, parts.Count - visiblePartCount);
                        }
                        else
                        {
                            status = string.Format(CultureInfo.CurrentCulture, Localized.StatusLabelSingularTooltipTextFormat, visiblePartCount, GUI.tooltip, parts.Count - visiblePartCount);
                        }
                    }
                    else
                    {
                        if (parts.Count != 1)
                        {
                            status = string.Format(CultureInfo.CurrentCulture, Localized.StatusLabelPluralTextFormat, visiblePartCount, parts.Count - visiblePartCount);
                        }
                        else
                        {
                            status = string.Format(CultureInfo.CurrentCulture, Localized.StatusLabelSingularTextFormat, visiblePartCount, parts.Count - visiblePartCount);
                        }
                    }

                    GUILayout.Label(status, this.tooltipLabelStyle);
                }

                #endregion

                GUILayout.EndVertical();

                if (this.Visible && this.mouseOver)
                {
                    this.highlight.EndTracking();
                }
                else
                {
                    this.highlight.CancelTracking();
                }
            }
            catch (Exception e)
            {
                Log.Write("PartWizardWindow.OnRender() unexpected exception caught.");

                Log.Write(e.Message);
                Log.Write(e.StackTrace);

                this.highlight.CancelTracking();

                throw;
            }
            finally
            {
                GUI.DragWindow();
            }
        }
Beispiel #5
0
        public override void OnRender()
        {
            try
            {
                GUILayout.BeginVertical();

                this.scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, false);

                this.highlight.BeginTracking();

                if (this.mouseOver)
                {
                    this.highlight.Add(this.part, Configuration.HighlightColorSymmetryEditor, Configuration.HighlightColorSymmetryEditor);
                }

                for (int index = 0; index < this.symmetryGroups.Count; index++)
                {
                    PartGroup group = this.symmetryGroups[index];

                    GUIControls.BeginMouseOverVertical(GUIControls.PanelStyle);

                    GUILayout.BeginHorizontal();

                    GUILayout.Label(new GUIContent(string.Format(CultureInfo.CurrentCulture, Localized.GroupLabelText, index + 1)));

                    // Don't allow group removal if there is only one group.
                    GUI.enabled = (this.symmetryGroups.Count > 1);

                    if (GUILayout.Button(SymmetryEditorWindow.RemoveGroupButtonText))
                    {
                        // If there's a group above, use it. If not, then use the one below.
                        PartGroup destinationGroup = (index > 0) ? this.symmetryGroups[index - 1] : this.symmetryGroups[index + 1];

                        destinationGroup.MergeFrom(group);

                        this.symmetryGroups.Remove(group);

                        break;
                    }

                    GUILayout.EndHorizontal();

                    GUI.enabled = true;

                    bool mouseOverPart = false;

                    foreach (Part groupPart in group.Parts)
                    {
                        GUIControls.BeginMouseOverHorizontal();

                        GUILayout.Label(new GUIContent(groupPart.partInfo.title));

                        GUI.enabled = index < this.symmetryGroups.Count - 1;

                        if (GUILayout.Button(SymmetryEditorWindow.MoveDownButtonText, Configuration.PartActionButtonWidth))
                        {
                            PartGroup nextGroup = this.symmetryGroups[index + 1];

                            group.MoveTo(groupPart, nextGroup);

                            break;
                        }

                        GUI.enabled = index > 0;

                        if (GUILayout.Button(SymmetryEditorWindow.MoveUpButtonText, Configuration.PartActionButtonWidth))
                        {
                            PartGroup previousGroup = this.symmetryGroups[index - 1];

                            group.MoveTo(groupPart, previousGroup);

                            break;
                        }

                        GUI.enabled = true;

                        bool mouseOverPartArea = false;
                        GUIControls.EndMouseOverVertical(out mouseOverPartArea);

                        if (mouseOverPartArea)
                        {
                            // First add the group with the child part color, recursively.
                            this.highlight.Add(group, Configuration.HighlightColorEditableSymmetryChildParts, true);
                            // Next add the group with the counterparts highlighted, non-recursively.
                            this.highlight.Add(group, Configuration.HighlightColorCounterparts, false);
                            // Last add the specific part, non-recursively.
                            this.highlight.Add(groupPart, Configuration.HighlightColorSinglePart, false);

                            mouseOverPart = true;
                        }
                    }

                    bool groupMouseOver = false;
                    GUIControls.EndMouseOverVertical(out groupMouseOver);

                    if (!mouseOverPart && groupMouseOver)
                    {
                        this.highlight.Add(group, Configuration.HighlightColorEditableSymmetryCounterparts, true);
                    }
                }

                // Enable the Add Group button only if there is enough symmetrical parts to fill it.
                GUI.enabled = (this.symmetryGroups.Count < (this.part.symmetryCounterparts.Count + 1));

                if (GUILayout.Button(SymmetryEditorWindow.AddGroupButtonText))
                {
                    this.symmetryGroups.Add(new PartGroup());
                }

                GUI.enabled = true;

                GUILayout.EndScrollView();

                GUILayout.Space(4);

                GUILayout.BeginHorizontal();

                #region OK Button

                if (GUILayout.Button(Localized.OK))
                {
                    int symmetricGroupsCreated = 0;
                    int partsProcessed         = 0;

                    foreach (PartGroup group in this.symmetryGroups)
                    {
                        if (group.Parts.Count > 0)
                        {
                            partsProcessed += group.Count;

                            Part symmetricRoot = group.Extract(0);

                            PartWizard.CreateSymmetry(symmetricRoot, group.Parts);

                            symmetricGroupsCreated++;

#if DEBUG
                            Log.WriteSymmetryReport(symmetricRoot);
#endif
                        }
                    }

                    Log.Write("Modified symmetry for {0}, creating {1} symmetric group(s) from {2} parts.", part.name, symmetricGroupsCreated, partsProcessed);

                    this.Hide();
                }

                #endregion

                #region Cancel Button

                if (GUILayout.Button(Localized.Cancel))
                {
                    this.Hide();
                }

                #endregion

                GUILayout.EndHorizontal();

                GUILayout.EndVertical();
            }
            catch (Exception)
            {
                highlight.CancelTracking();

                throw;
            }
            finally
            {
                GUI.DragWindow();

                if (this.Visible && this.mouseOver)
                {
                    this.highlight.EndTracking();
                }
                else
                {
                    this.highlight.CancelTracking();
                }
            }
        }