public override void ExposeData() { // store research defs as these are the defining elements if (Scribe.mode == LoadSaveMode.Saving) { _saveableQueue = _queue.Select(node => node.Research).ToList(); } Scribe_Collections.Look(ref _saveableQueue, "Queue", LookMode.Def); if (Scribe.mode == LoadSaveMode.PostLoadInit) { // initialize the tree if not initialized if (!ResearchTree.Initialized) { ResearchTree.Initialize(); } // initialize the queue foreach (ResearchProjectDef research in _saveableQueue) { // find a node that matches the research - or null if none found Node node = ResearchTree.Forest.FirstOrDefault(n => n.Research == research); // enqueue the node if (node != null) { Enqueue(node, true); } } } }
/// <summary> /// Draw the node, including interactions. /// </summary> public override void Draw(Rect visibleRect, bool forceDetailedMode = false) { if (!IsVisible(visibleRect)) { Highlighted = false; return; } var detailedMode = forceDetailedMode || MainTabWindow_ResearchTree.Instance.ZoomLevel < DetailedModeZoomLevelCutoff; var mouseOver = Mouse.IsOver(Rect); if (Event.current.type == EventType.Repaint) { // researches that are completed or could be started immediately, and that have the required building(s) available GUI.color = mouseOver ? GenUI.MouseoverColor : Color; if (mouseOver || Highlighted) { GUI.DrawTexture(Rect, Assets.ButtonActive); } else { GUI.DrawTexture(Rect, Assets.Button); } // grey out center to create a progress bar effect, completely greying out research not started. if (Available) { var progressBarRect = Rect.ContractedBy(3f); GUI.color = Assets.ColorAvailable[Research.techLevel]; progressBarRect.xMin += Research.ProgressPercent * progressBarRect.width; GUI.DrawTexture(progressBarRect, BaseContent.WhiteTex); } Highlighted = false; // draw the research label if (!Completed && !Available) { GUI.color = Color.grey; } else { GUI.color = Color.white; } if (detailedMode) { Text.Anchor = TextAnchor.UpperLeft; Text.WordWrap = false; Text.Font = _largeLabel ? GameFont.Tiny : GameFont.Small; Widgets.Label(LabelRect, Research.LabelCap); } else { Text.Anchor = TextAnchor.MiddleCenter; Text.WordWrap = false; Text.Font = GameFont.Medium; Widgets.Label(Rect, Research.LabelCap); } // draw research cost and icon if (detailedMode) { Text.Anchor = TextAnchor.UpperRight; Text.Font = Research.CostApparent > 1000000 ? GameFont.Tiny : GameFont.Small; Widgets.Label(CostLabelRect, Research.CostApparent.ToStringByStyle(ToStringStyle.Integer)); GUI.DrawTexture(CostIconRect, !Completed && !Available ? Assets.Lock : Assets.ResearchIcon, ScaleMode.ScaleToFit); } Text.WordWrap = true; // attach description and further info to a tooltip TooltipHandler.TipRegion(Rect, GetResearchTooltipString, Research.GetHashCode()); if (!BuildingPresent()) { TooltipHandler.TipRegion(Rect, ResourceBank.String.MissingFacilities(string.Join(", ", MissingFacilities().Select(td => td.LabelCap).ToArray()))); } else if (!TechprintAvailable()) { TooltipHandler.TipRegion(Rect, ResourceBank.String.MissingTechprints(Research.TechprintsApplied, Research.techprintCount)); } // draw unlock icons if (detailedMode) { var unlocks = Research.GetUnlockDefsAndDescs(); for (var i = 0; i < unlocks.Count; i++) { var iconRect = new Rect( IconsRect.xMax - (i + 1) * (IconSize.x + 4f), IconsRect.yMin + (IconsRect.height - IconSize.y) / 2f, IconSize.x, IconSize.y); if (iconRect.xMin - IconSize.x < IconsRect.xMin && i + 1 < unlocks.Count) { // stop the loop if we're about to overflow and have 2 or more unlocks yet to print. iconRect.x = IconsRect.x + 4f; GUI.DrawTexture(iconRect, Assets.MoreIcon, ScaleMode.ScaleToFit); var tip = string.Join("\n", unlocks.GetRange(i, unlocks.Count - i).Select(p => p.Second) .ToArray()); TooltipHandler.TipRegion(iconRect, tip); // new TipSignal( tip, Settings.TipID, TooltipPriority.Pawn ) ); break; } // draw icon unlocks[i].First.DrawColouredIcon(iconRect); // tooltip TooltipHandler.TipRegion(iconRect, unlocks[i].Second); } } if (mouseOver) { // highlight prerequisites if research available if (Available) { Highlighted = true; foreach (var prerequisite in GetMissingRequiredRecursive()) { prerequisite.Highlighted = true; } } // highlight children if completed else if (Completed) { foreach (var child in Children) { child.Highlighted = true; } } } } // if clicked and not yet finished, queue up this research and all prereqs. if (Widgets.ButtonInvisible(Rect) && Available) { // LMB is queue operations, RMB is info if (Event.current.button == 0 && !Research.IsFinished) { if (DebugSettings.godMode && Event.current.control) { var nodes = GetMissingRequiredRecursive() .Concat(new List <ResearchNode>(new[] { this })) .Distinct().Reverse(); foreach (ResearchNode n in nodes) { if (Queue.IsQueued(n)) { Queue.Dequeue(n); } if (!n.Research.IsFinished) { Find.ResearchManager.FinishProject(n.Research, false); } } if (nodes.Any()) { Messages.Message(ResourceBank.String.FinishedResearch(Research.LabelCap), MessageTypeDefOf.SilentInput, false); Queue.Notify_InstantFinished(); } } else if (!Queue.IsQueued(this)) { // if shift is held, add to queue, otherwise replace queue var queue = GetMissingRequiredRecursive() .Concat(new List <ResearchNode>(new[] { this })) .Distinct(); Queue.EnqueueRange(queue, Event.current.shift); } else { Queue.Dequeue(this); } } else if (Event.current.button == 1) { ResearchTree.JumpToHelp(Research); } } }
public void DrawTree(Rect canvas) { // get total size of Research Tree int maxDepth = 0, totalWidth = 0; if (ResearchTree.Trees.Any()) { maxDepth = ResearchTree.Trees.Max(tree => tree.MaxDepth); totalWidth = ResearchTree.Trees.Sum(tree => tree.Width); } maxDepth = Math.Max(maxDepth, ResearchTree.Orphans.MaxDepth); totalWidth += ResearchTree.Orphans.Width; float width = (maxDepth + 1) * (Settings.NodeSize.x + Settings.NodeMargins.x); // zero based float height = totalWidth * (Settings.NodeSize.y + Settings.NodeMargins.y); // main view rect Rect view = new Rect(0f, 0f, width, height); Widgets.BeginScrollView(canvas, ref _scrollPosition, view); GUI.BeginGroup(view); Text.Anchor = TextAnchor.MiddleCenter; // draw regular connections, not done first to better highlight done. foreach (Pair <Node, Node> connection in connections.Where(pair => !pair.Second.Research.IsFinished)) { ResearchTree.DrawLine(connection, connection.First.Tree.GreyedColor); } // draw connections from completed nodes foreach (Pair <Node, Node> connection in connections.Where(pair => pair.Second.Research.IsFinished)) { ResearchTree.DrawLine(connection, connection.First.Tree.MediumColor); } connections.Clear(); // draw highlight connections on top foreach (Pair <Node, Node> connection in highlightedConnections) { ResearchTree.DrawLine(connection, GenUI.MouseoverColor, true); } highlightedConnections.Clear(); // draw nodes on top of lines foreach (Node node in nodes) { node.Draw(); } nodes.Clear(); // register hub tooltips foreach (KeyValuePair <Rect, List <string> > pair in hubTips) { string text = string.Join("\n", pair.Value.ToArray()); TooltipHandler.TipRegion(pair.Key, text); } hubTips.Clear(); // draw Queue labels Queue.DrawLabels(); // reset anchor Text.Anchor = TextAnchor.UpperLeft; GUI.EndGroup(); Widgets.EndScrollView(); }
public void DrawTree(Rect canvas) { // get total size of Research Tree int maxDepth = 0, totalWidth = 0; if (ResearchTree.Trees.Any()) { maxDepth = ResearchTree.Trees.Max(tree => tree.MaxDepth); totalWidth = ResearchTree.Trees.Sum(tree => tree.Width); } maxDepth = Math.Max(maxDepth, ResearchTree.Orphans.MaxDepth); totalWidth += ResearchTree.Orphans.Width; float width = (maxDepth + 1) * (Settings.NodeSize.x + Settings.NodeMargins.x); // zero based float height = (totalWidth - 1) * (Settings.NodeSize.y + Settings.NodeMargins.y); // main view rect Rect view = new Rect(0f, 0f, width, height); // create the scroll area below the search box (plus a small margin) so it stays on top Widgets.BeginScrollView(new Rect(canvas.x, canvas.y + filterManager.Height + Settings.NodeMargins.y, canvas.width, canvas.height - filterManager.Height - Settings.NodeMargins.y), ref _scrollPosition, view); GUI.BeginGroup(view); Text.Anchor = TextAnchor.MiddleCenter; // draw regular connections, not done first to better highlight done. foreach (Pair <Node, Node> connection in connections.Where(pair => !pair.Second.Research.IsFinished)) { ResearchTree.DrawLine(connection, filterManager.FilterPhrase.NullOrEmpty() ? connection.First.Tree.GreyedColor : ColorHelper.AdjustAlpha(connection.First.Tree.GreyedColor, Settings.FilterNonMatchAlpha)); } // draw connections from completed nodes foreach (Pair <Node, Node> connection in connections.Where(pair => pair.Second.Research.IsFinished)) { if (!filterManager.FilterPhrase.NullOrEmpty()) { ResearchTree.DrawLine(connection, ColorHelper.AdjustAlpha(connection.First.Tree.GreyedColor, Settings.FilterNonMatchAlpha)); } else { ResearchTree.DrawLine(connection, connection.First.Tree.MediumColor); } } connections.Clear(); // draw highlight connections on top foreach (Pair <Node, Node> connection in highlightedConnections) { ResearchTree.DrawLine(connection, GenUI.MouseoverColor, true); } highlightedConnections.Clear(); // draw nodes on top of lines bool reqScroll = true; Node scrollToNode = null; foreach (Node node in nodes) { // draw the node bool visible = node.Draw(); // ensure that at least one matching node is visible, prioritize highest on the screen if (filterManager.FilterDirty) { if (node.FilterMatch.IsValidMatch()) { if (!reqScroll) { continue; } // this node is a match and is currently visible, we don't need to scroll if (visible) { reqScroll = false; scrollToNode = null; } else { // this node is a match, but isn't visible. if it's the highest node then we'll scroll to it if (scrollToNode == null || node.Pos.z < scrollToNode.Pos.z) { scrollToNode = node; } } } } } if (filterManager.FilterDirty) { // scroll to a matching node if necessary if (scrollToNode != null) { // scale the focus area to ensure it all fits on the screen Rect r = scrollToNode.Rect.ScaledBy(2.0f); _scrollPosition = new Vector2(r.xMin, r.yMin); } else if (filterManager.FilterPhrase == "") { _scrollPosition = Vector2.zero; } } nodes.Clear(); // register hub tooltips foreach (KeyValuePair <Rect, List <string> > pair in hubTips) { string text = string.Join("\n", pair.Value.ToArray()); TooltipHandler.TipRegion(pair.Key, text); } hubTips.Clear(); // draw Queue labels Queue.DrawLabels(); // reset anchor Text.Anchor = TextAnchor.UpperLeft; GUI.EndGroup(); Widgets.EndScrollView(); }