private void DrawSeverityBar(ref float curY, ref Rect partListViewRect, MutationLayer layer, MutationDef mutationDef, List <Hediff_AddedMutation> mutationsOfDef) { // Draw the various labels for the severity bar (need to refine this later). string stageLabelText = $"Stage {mutationsOfDef.FirstOrDefault().CurStageIndex}: {mutationsOfDef.FirstOrDefault().LabelCap}"; Rect severityLabelsRect = new Rect(partListViewRect.x, curY, partListViewRect.width, Text.CalcHeight(stageLabelText, partListViewRect.width)); Text.Anchor = TextAnchor.MiddleLeft; Widgets.Label(severityLabelsRect, stageLabelText); Text.Anchor = TextAnchor.MiddleRight; Widgets.Label(severityLabelsRect, mutationsOfDef.FirstOrDefault().Severity.ToString("n2")); Text.Anchor = TextAnchor.UpperLeft; curY += severityLabelsRect.height; // Draw the severity slider float curSeverity = mutationsOfDef.Select(n => n.Severity).Average(); float newSeverity = Widgets.HorizontalSlider(new Rect(partListViewRect.x, curY, partListViewRect.width, SLIDER_HEIGHT), curSeverity, mutationDef.minSeverity, mutationDef.maxSeverity); if (curSeverity != newSeverity) { curSeverity = newSeverity; foreach (Hediff_AddedMutation mutationOfDef in mutationsOfDef) { MutationData relevantEntry = addedMutations.MutationsByPartAndLayer(mutationOfDef.Part, layer); if (relevantEntry != null) { relevantEntry.severity = newSeverity; } else { addedMutations.AddData(mutationOfDef.Def, mutationOfDef.Part, newSeverity, mutationOfDef.ProgressionHalted, false); } mutationOfDef.Severity = newSeverity; } recachePreview = true; } curY += SLIDER_HEIGHT; }
IReadOnlyMutationData IReadOnlyAddedMutations.MutationsByPartAndLayer(BodyPartRecord part, MutationLayer layer) { return(MutationsByPartAndLayer(part, layer)); }
/// <summary> /// Finds and returns the first entry whose part and layer matches the provided part and layer. /// </summary> /// <param name="part">The part to match.</param> /// <param name="layer">The mutation layer to match.</param> /// <returns>The first entry whose part and layer matches the provied part and layer.</returns> public MutationData MutationsByPartAndLayer(BodyPartRecord part, MutationLayer layer) { return(mutationData.Where(m => m.part == part).FirstOrDefault()); }
/// <summary> /// Removes the first entry in the mutation data list whose part and layer matches the one provided. /// </summary> /// <param name="part">The body part record to filter out of the mutation data.</param> /// <param name="layer">The mutation layer to filter out of the mutation data.</param> public void RemoveByPartAndLayer(BodyPartRecord part, MutationLayer layer) { mutationData.Remove(mutationData.Where(m => m.part == part && m.mutation.RemoveComp.layer == layer).FirstOrDefault()); //mutationData = mutationData.Where(m => m.part != part && m.mutation.RemoveComp.layer != layer).ToList(); }
private void DrawPartButtons(ref float curY, Rect partListViewRect, List <Hediff_AddedMutation> mutations, List <BodyPartRecord> parts, MutationLayer layer, string label) { // Draw the main mutation selection button. It should take up the whole width if there are no mutations, otherwise it will leave a space for the edit button. float partButtonWidth = partListViewRect.width - (mutations.NullOrEmpty() ? 0 : editButtonWidth); Rect partButtonRect = new Rect(partListViewRect.x, curY, partButtonWidth, Text.CalcHeight(label, partButtonWidth - BUTTON_HORIZONTAL_PADDING)); if (Widgets.ButtonText(partButtonRect, label)) { List <FloatMenuOption> options = new List <FloatMenuOption>(); void removeMutations() { foreach (Hediff_AddedMutation mutation in mutations) { addedMutations.RemoveByPartAndLayer(mutation.Part, layer); if (cachedInitialHediffs.Select(m => m.hediff).Contains(mutation)) { addedMutations.AddData(mutation.Def, mutation.Part, mutation.Severity, mutation.ProgressionHalted, true); } pawn.health.RemoveHediff(mutation); } recachePreview = true; RecachePawnMutations(); } options.Add(new FloatMenuOption(NO_MUTATIONS_LOC_STRING.Translate(), removeMutations)); List <MutationDef> mutationDefs = cachedMutationDefsByPartDef[parts.FirstOrDefault().def]; foreach (MutationDef mutationDef in mutationDefs.Where(m => m.RemoveComp.layer == layer && (DebugSettings.godMode || m.IsTagged()))) { void addMutation() { foreach (Hediff_AddedMutation mutation in mutations) { pawn.health.RemoveHediff(mutation); } foreach (BodyPartRecord part in parts) { addedMutations.RemoveByPartAndLayer(part, layer); addedMutations.AddData(mutationDef, part, mutationDef.initialSeverity, false, false); MutationUtilities.AddMutation(pawn, mutationDef, part, ancillaryEffects: MutationUtilities.AncillaryMutationEffects.None); //don't give the green puffs } recachePreview = true; RecachePawnMutations(); } options.Add(new FloatMenuOption(mutationDef.LabelCap, addMutation)); } Find.WindowStack.Add(new FloatMenu(options)); } curY += partButtonRect.height; // If there are actually mutations, draw the edit button. if (!mutations.NullOrEmpty()) { Rect editButtonRect = new Rect(partButtonWidth, partButtonRect.y, editButtonWidth, partButtonRect.height); if (Widgets.ButtonText(editButtonRect, editButtonText)) { detailPart = (detailPart.Item1 == parts.FirstOrDefault() && detailPart.Item2 == layer) ? new Tuple <BodyPartRecord, MutationLayer>(new BodyPartRecord(), 0) : new Tuple <BodyPartRecord, MutationLayer>(parts.FirstOrDefault(), layer); } } // If the currently selected part and layer match up with the part to give details for, draw the edit area below the buttons. if (detailPart.Item1 == parts.FirstOrDefault() && detailPart.Item2 == layer) { foreach (MutationDef mutationDef in mutations.Select(m => m.Def).Distinct()) { List <Hediff_AddedMutation> mutationsOfDef = mutations.Where(m => m.Def == mutationDef).ToList(); // Draw the LabelCap of the current Def if there is more than one type of mutation in the current list. if (mutations.Select(m => m.Def).Distinct().Count() > 1) { Widgets.ListSeparator(ref curY, partListViewRect.width, mutationDef.LabelCap); } // Draw the various labels for the severity bar (need to refine this later). string stageLabelText = $"Stage {mutationsOfDef.FirstOrDefault().CurStageIndex}: {mutationsOfDef.FirstOrDefault().LabelCap}"; Rect severityLabelsRect = new Rect(partListViewRect.x, curY, partListViewRect.width, Text.CalcHeight(stageLabelText, partListViewRect.width)); Text.Anchor = TextAnchor.MiddleLeft; Widgets.Label(severityLabelsRect, stageLabelText); Text.Anchor = TextAnchor.MiddleRight; Widgets.Label(severityLabelsRect, mutationsOfDef.FirstOrDefault().Severity.ToString("n2")); Text.Anchor = TextAnchor.UpperLeft; curY += severityLabelsRect.height; // Draw the severity slider float curSeverity = mutationsOfDef.Select(n => n.Severity).Average(); float newSeverity = Widgets.HorizontalSlider(new Rect(partListViewRect.x, curY, partListViewRect.width, SLIDER_HEIGHT), curSeverity, mutationDef.minSeverity, mutationDef.maxSeverity); if (curSeverity != newSeverity) { curSeverity = newSeverity; foreach (Hediff_AddedMutation mutationOfDef in mutationsOfDef) { MutationData relevantEntry = addedMutations.MutationsByPartAndLayer(mutationOfDef.Part, layer); if (relevantEntry != null) { relevantEntry.severity = newSeverity; } else { addedMutations.AddData(mutationOfDef.Def, mutationOfDef.Part, newSeverity, mutationOfDef.ProgressionHalted, false); } mutationOfDef.Severity = newSeverity; } recachePreview = true; } curY += SLIDER_HEIGHT; // If the mutation has the ability to be paused, show the toggle for it. // This is a CheckboxMulti to handle edge cases, but likely could be replaced with a simple Checkbox. if (mutationDef.CompProps <CompProperties_MutationSeverityAdjust>() != null) { float pauseLabelWidth = partListViewRect.width - IS_PAUSED_CHECKBOX_SIZE.x; Rect pauseLabelRect = new Rect(partListViewRect.x, curY, pauseLabelWidth, Text.CalcHeight(IS_PAUSED_LOC_STRING.Translate(), partListViewRect.width)); Rect checkBoxRect = new Rect(partListViewRect.x + pauseLabelWidth, curY, IS_PAUSED_CHECKBOX_SIZE.x, IS_PAUSED_CHECKBOX_SIZE.y); MultiCheckboxState initialState = !mutationsOfDef.Select(n => n.ProgressionHalted).Contains(true) ? MultiCheckboxState.Off : !mutationsOfDef.Select(n => n.ProgressionHalted).Contains(false) ? MultiCheckboxState.On : MultiCheckboxState.Partial; Widgets.Label(pauseLabelRect, IS_PAUSED_LOC_STRING.Translate()); MultiCheckboxState newState = Widgets.CheckboxMulti(checkBoxRect, initialState); if (initialState != newState) { initialState = newState; mutationsOfDef.FirstOrDefault().SeverityAdjust.Halted = !mutationsOfDef.FirstOrDefault().SeverityAdjust.Halted; foreach (Hediff_AddedMutation mutationOfDef in mutationsOfDef) { MutationData relevantEntry = addedMutations.MutationsByPartAndLayer(mutationOfDef.Part, layer); if (cachedInitialHediffs.Select(m => m.hediff).Contains(mutationOfDef)) { bool initialHediffIsHalted = cachedInitialHediffs.Where(m => m.hediff == mutationOfDef).FirstOrDefault().isHalted; if (newState == MultiCheckboxState.On == initialHediffIsHalted) { addedMutations.RemoveByPartAndLayer(mutationOfDef.Part, layer); } } if (relevantEntry != null) { relevantEntry.isHalted = newState == MultiCheckboxState.On; } else { addedMutations.AddData(mutationOfDef.Def, mutationOfDef.Part, mutationOfDef.Severity, newState == MultiCheckboxState.On, false); } } } curY += Math.Max(pauseLabelRect.height, checkBoxRect.height); } } } // Create a zone for updating the lower description box (The one that shows details based on the currently hovered over mutation). Rect descriptionUpdateRect = new Rect(partListViewRect.x, partButtonRect.y, partListViewRect.width, curY - partButtonRect.y); if (Mouse.IsOver(descriptionUpdateRect)) { foreach (MutationDef mutation in mutations.Select(m => m.def).Distinct()) { Hediff_AddedMutation firstMutationOfDef = mutations.Where(m => m.def == mutation).FirstOrDefault(); partDescBuilder.AppendLine(firstMutationOfDef.LabelCap); partDescBuilder.AppendLine(firstMutationOfDef.Description); partDescBuilder.AppendLine(firstMutationOfDef.TipStringExtra); partDescBuilder.AppendLine(); } } }
private void DrawPartEntrySkinSyncMode(string label, List <BodyPartRecord> parts, ref float curPos, Rect rect, MutationLayer layer) { Rect labelRect = new Rect(rect.x, curPos, rect.width, Text.CalcHeight(label, rect.width)); Widgets.Label(labelRect, label); curPos += labelRect.height; List <Hediff_AddedMutation> mutations = pawn.health.hediffSet.hediffs .Where(m => m.def.GetType() == typeof(MutationDef)) .Cast <Hediff_AddedMutation>() .Where(m => parts.Contains(m.Part) && m.TryGetComp <RemoveFromPartComp>().Layer == layer) .ToList(); string partButtonText = $"{(mutations.NullOrEmpty() ? NO_MUTATIONS_LOC_STRING.Translate().ToString() : string.Join(", ", mutations.Select(m => m.LabelCap).Distinct()))}"; string editButtonText = EDIT_PARAMS_LOC_STRING.Translate(); float editButtonWidth = Text.CalcSize(editButtonText).x + BUTTON_HORIZONTAL_PADDING; float partButtonWidth = rect.width - editButtonWidth; float partButtonHeight = Text.CalcHeight(partButtonText, partButtonWidth - BUTTON_HORIZONTAL_PADDING); Rect partButtonRect = new Rect(rect.x, curPos, partButtonWidth, partButtonHeight); Rect editButtonRect = new Rect(partButtonWidth, curPos, editButtonWidth, partButtonHeight); Rect descUpdateRect = new Rect(rect.x, curPos, rect.width, partButtonHeight); if (Widgets.ButtonText(partButtonRect, partButtonText)) { List <FloatMenuOption> options = new List <FloatMenuOption>(); void removeMutations() { foreach (Hediff_AddedMutation mutation in mutations) { pawn.health.RemoveHediff(mutation); } recachePreview = true; } options.Add(new FloatMenuOption(NO_MUTATIONS_LOC_STRING.Translate(), removeMutations)); foreach (MutationDef mutationDef in cachedMutationDefsByPart[parts.First().def].Where(m => m.CompProps <RemoveFromPartCompProperties>().layer == layer)) { void addMutation() { removeMutations(); foreach (BodyPartRecord part in parts) { MutationUtilities.AddMutation(pawn, mutationDef, part); } } options.Add(new FloatMenuOption(mutationDef.LabelCap, addMutation)); } Find.WindowStack.Add(new FloatMenu(options)); } if (Widgets.ButtonText(editButtonRect, editButtonText)) { // Pop open window to modify current stage, severity, halted status, etc. } if (Mouse.IsOver(descUpdateRect)) { foreach (MutationDef mutation in mutations.Select(m => m.Def).Distinct().ToList()) { partDescBuilder.AppendLine($"{mutation.LabelCap}"); partDescBuilder.AppendLine($"{mutation.description}"); partDescBuilder.AppendLine(); } } curPos += partButtonHeight; }
/// <summary> /// Initializes a new instance of the <see cref="MutationSite"/> struct. /// </summary> /// <param name="record">The record.</param> /// <param name="layer">The layer.</param> public MutationSite(BodyPartRecord record, MutationLayer layer) { Record = record; Layer = layer; }