/// <summary> /// Draw the node, including interactions. /// </summary> public bool Draw() { // cop out if off-screen Rect screen = new Rect(MainTabWindow_ResearchTree._scrollPosition.x, MainTabWindow_ResearchTree._scrollPosition.y, Screen.width, Screen.height - 35); if (Rect.xMin > screen.xMax || Rect.xMax < screen.xMin || Rect.yMin > screen.yMax || Rect.yMax < screen.yMin) { return(false); } // set color GUI.color = !Research.PrerequisitesCompleted ? AdjustFilterAlpha(Tree.GreyedColor) : AdjustFilterAlpha(Tree.MediumColor); // mouseover highlights if (Mouse.IsOver(Rect)) { // active button GUI.DrawTexture(Rect, ResearchTree.ButtonActive); // highlight this and all prerequisites if research not completed if (!Research.IsFinished) { HighlightWithPrereqs(); } else // highlight followups { foreach (Node child in Children) { MainTabWindow_ResearchTree.highlightedConnections.Add(new Pair <Node, Node>(this, child)); child.Highlight(GenUI.MouseoverColor, false, false); } } } // filter highlights else if (_matchType.IsValidMatch()) { GUI.DrawTexture(Rect, ResearchTree.ButtonActive); if (Settings.showFilteredLinks) { HighlightWithPrereqs(); } else { Highlight(GenUI.MouseoverColor, false, false); } } // if not moused over, just draw the default button state else { GUI.DrawTexture(Rect, ResearchTree.Button); } // grey out center to create a progress bar effect, completely greying out research not started. bool warnLocked = false, warnPenalty = false; if (!Research.IsFinished) { Rect progressBarRect = Rect.ContractedBy(2f); GUI.color = AdjustFilterAlpha(Tree.GreyedColor); progressBarRect.xMin += Research.ProgressPercent * progressBarRect.width; GUI.DrawTexture(progressBarRect, BaseContent.WhiteTex); warnLocked = IsLocked(Research); warnPenalty = Research.techLevel > Faction.OfPlayer.def.techLevel; } // draw the research label GUI.color = AdjustFilterAlpha(Color.white); Text.Anchor = TextAnchor.UpperLeft; Text.WordWrap = true; Text.Font = _largeLabel ? GameFont.Tiny : GameFont.Small; Widgets.Label(LabelRect, StringExtensions.TitleCase(Research.LabelCap)); // draw research cost and icon Text.Anchor = TextAnchor.UpperRight; Text.Font = GameFont.Small; if (warnPenalty) { GUI.color = AdjustFilterAlpha(Color.yellow); } Widgets.Label(CostLabelRect, Research.CostApparent.ToStringByStyle(ToStringStyle.Integer)); GUI.color = AdjustFilterAlpha(Color.white); if (warnLocked) { GUI.DrawTexture(CostIconRect, WarningIcon); } else { GUI.DrawTexture(CostIconRect, ResearchIcon); } Text.WordWrap = true; // attach description and further info to a tooltip TooltipHandler.TipRegion(Rect, GetResearchTooltipString()); // new TipSignal( GetResearchTooltipString(), Settings.TipID ) ); // draw unlock icons List <Pair <Def, string> > unlocks = Research.GetUnlockDefsAndDescs(); for (int i = 0; i < unlocks.Count; i++) { Rect iconRect = new Rect(IconsRect.xMax - (i + 1) * (Settings.IconSize.x + 4f), IconsRect.yMin + (IconsRect.height - Settings.IconSize.y) / 2f, Settings.IconSize.x, Settings.IconSize.y); if (iconRect.xMin - Settings.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; ResearchTree.MoreIcon.DrawFittedIn(iconRect, NodeAlpha()); string 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, NodeAlpha()); // tooltip TooltipHandler.TipRegion(iconRect, unlocks[i].Second); // new TipSignal( unlocks[i].Second, Settings.TipID, TooltipPriority.Pawn ) ); // reset the color GUI.color = Color.white; } // if clicked and not yet finished, queue up this research and all prereqs. if (Widgets.ButtonInvisible(Rect)) { // LMB is queue operations, RMB is info if (Event.current.button == 0 && !Research.IsFinished) { if (Settings.debugResearch && Prefs.DevMode && Event.current.control) { List <Node> nodesToResearch = GetMissingRequiredRecursive().Concat(new List <Node>(new[] { this })).ToList(); foreach (Node n in nodesToResearch) { if (Queue.IsQueued(n)) { Queue.Dequeue(n); } if (!n.Research.IsFinished) { Find.ResearchManager.InstantFinish(n.Research, false); } } Verse.Sound.SoundStarter.PlayOneShotOnCamera(MessageTypeDefOf.PositiveEvent.sound); } else { if (!Queue.IsQueued(this)) { if (warnLocked) { Messages.Message(ResourceBank.String.RequireMissing, MessageTypeDefOf.RejectInput); } // if shift is held, add to queue, otherwise replace queue Queue.EnqueueRange(GetMissingRequiredRecursive().Concat(new List <Node> (new [] { this })), Event.current.shift); } else { Queue.Dequeue(this); } } } else if (Event.current.button == 1) { ResearchPalMod.JumpToHelp(Research); } } return(true); }
/// <summary> /// Creates text version of research description and additional unlocks/prereqs/etc sections. /// </summary> /// <returns>string description</returns> private string GetResearchTooltipString() { // start with the description var text = new StringBuilder(); text.AppendLine(Research.description); text.AppendLine(); text.AppendLine(StringExtensions.TitleCase(Research.techLevel.ToStringHuman())); text.AppendLine(); var PlayerTechLevel = Faction.OfPlayer.def.techLevel; if (Research.techLevel > PlayerTechLevel) { text.AppendLine(ResourceBank.String.ResearchLevels(Research.techLevel, PlayerTechLevel) + " " + ResourceBank.String.ResearchPenalty(Research.CostFactor(PlayerTechLevel))); text.AppendLine(); } if (Research.requiredResearchBuilding != null) { text.AppendLine(ResourceBank.String.RequireBenchLabel + " " + Research.requiredResearchBuilding.label); } if (Research.requiredResearchFacilities != null) { foreach (ThingDef rrf in Research.requiredResearchFacilities) { text.AppendLine(ResourceBank.String.RequireFacilityLabel + " " + rrf.label); } } text.AppendLine(); if (Queue.IsQueued(this)) { text.AppendLine(ResourceBank.String.LClickRemoveFromQueue); } else { text.AppendLine(ResourceBank.String.LClickReplaceQueue); text.AppendLine(ResourceBank.String.SLClickAddToQueue); } if (Settings.debugResearch && Prefs.DevMode) { text.AppendLine(ResourceBank.String.CLClickDebugInstant); } //To Help System if (ResearchPalMod.HasHelpTreeLoaded) { text.AppendLine(ResourceBank.String.RClickForDetails); } if (Prefs.DevMode) { text.AppendLine(); text.Append("Depth:" + Depth + " Genus:" + Genus + " Family:" + Family); text.Append("Position: " + this.Pos.ToString()); text.Append("Rect: " + this.Rect.ToString()); } return(text.ToString()); }
/// <summary> /// Compares a node's research, unlocks and tech-level to the current filter. Updates the node of it's match status. /// </summary> /// <param name="node"></param> /// <returns></returns> public FilterMatchType NodeIsMatch(Node node) { if (!FilterDirty) { return(FilterMatchType.NONE); } string phrase = _filterPhrase.Trim(); FilterMatchType ret = FilterMatchType.NONE; string retDesc = StringExtensions.TitleCase(node.Research.LabelCap); // default if (phrase != "") { foreach (FilterMatchType tryMatch in Enum.GetValues(typeof(FilterMatchType))) { Log.Message("trying match for " + tryMatch.ToString()); switch (tryMatch) { case FilterMatchType.RESEARCH: if (node.Research.label.Contains(phrase, StringComparison.InvariantCultureIgnoreCase)) { ret = FilterMatchType.RESEARCH; } break; case FilterMatchType.UNLOCK: { List <string> unlockDescs = node.Research.GetUnlockDefsAndDescs() .Where(unlock => unlock.First.label.Contains(phrase, StringComparison.InvariantCulture)) .Select(unlock => unlock.First.label).ToList(); if (unlockDescs.Count > 0) { retDesc = string.Format("{0} ({1})", retDesc, StringExtensions.TitleCase(string.Join(", ", unlockDescs.ToArray()))); ret = FilterMatchType.UNLOCK; } } break; case FilterMatchType.TECH_LEVEL: { if (node.Research.techLevel.ToStringHuman().Contains(phrase, StringComparison.InvariantCultureIgnoreCase)) { ret = FilterMatchType.TECH_LEVEL; } } break; default: ret = FilterMatchType.NO_MATCH; break; } if (ret != FilterMatchType.NONE) { break; } } } else { ret = FilterMatchType.NONE; } // save the result for display later if (ret.IsValidMatch()) { if (!_matchResults.ContainsKey(ret)) { _matchResults.Add(ret, new List <string>()); } _matchResults[ret].Add(retDesc); } // update the node of the result node.FilterMatch = ret; return(ret); }