public void UpdateSubList(IEnumerable <Submarine> submarines) { #if DEBUG var subsToShow = submarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus)); #else var subsToShow = submarines; #endif subList.ClearChildren(); foreach (Submarine sub in subsToShow) { var textBlock = new GUITextBlock( new RectTransform(new Vector2(1, 0.1f), subList.Content.RectTransform) { AbsoluteOffset = new Point(10, 0) }, ToolBox.LimitString(sub.Name, GUI.Font, subList.Rect.Width - 65), style: "ListBoxElement") { ToolTip = sub.Description, UserData = sub }; var infoButton = new GUIButton(new RectTransform(new Vector2(0.12f, 0.8f), textBlock.RectTransform, Anchor.CenterRight), text: "?") { UserData = sub }; infoButton.OnClicked += (component, userdata) => { // TODO: use relative size ((Submarine)userdata).CreatePreviewWindow(new GUIMessageBox("", "", 550, 400)); return(true); }; if (sub.HasTag(SubmarineTag.Shuttle)) { textBlock.TextColor = textBlock.TextColor * 0.85f; var shuttleText = new GUITextBlock(new RectTransform(new Point(100, textBlock.Rect.Height), textBlock.RectTransform, Anchor.CenterRight) { IsFixedSize = false, RelativeOffset = new Vector2(infoButton.RectTransform.RelativeSize.X + 0.01f, 0) }, TextManager.Get("Shuttle"), textAlignment: Alignment.Right, font: GUI.SmallFont) { TextColor = textBlock.TextColor * 0.8f, ToolTip = textBlock.ToolTip }; } } if (Submarine.SavedSubmarines.Any()) { var nonShuttles = subsToShow.Where(s => !s.HasTag(SubmarineTag.Shuttle)).ToList(); if (nonShuttles.Count > 0) { subList.Select(nonShuttles[Rand.Int(nonShuttles.Count)]); } } }
private void UpdateSubList() { var subsToShow = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus)); subList.ClearChildren(); foreach (Submarine sub in subsToShow) { var textBlock = new GUITextBlock( new Rectangle(0, 0, 0, 25), ToolBox.LimitString(sub.Name, GUI.Font, subList.Rect.Width - 65), "ListBoxElement", Alignment.Left, Alignment.Left, subList) { Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f), ToolTip = sub.Description, UserData = sub }; if (sub.HasTag(SubmarineTag.Shuttle)) { textBlock.TextColor = textBlock.TextColor * 0.85f; var shuttleText = new GUITextBlock(new Rectangle(0, 0, 0, 25), "Shuttle", "", Alignment.Left, Alignment.CenterY | Alignment.Right, textBlock, false, GUI.SmallFont); shuttleText.TextColor = textBlock.TextColor * 0.8f; shuttleText.ToolTip = textBlock.ToolTip; } } if (Submarine.SavedSubmarines.Count > 0) { subList.Select(Submarine.SavedSubmarines[0]); } }
private bool SelectServer(GUIComponent component, object obj) { if (obj == null || waitingForRefresh || (!(obj is ServerInfo))) { return(false); } if (!string.IsNullOrWhiteSpace(clientNameBox.Text)) { joinButton.Enabled = true; } else { clientNameBox.Flash(); joinButton.Enabled = false; } ServerInfo serverInfo; try { serverInfo = (ServerInfo)obj; ipBox.UserData = serverInfo; ipBox.Text = ToolBox.LimitString(serverInfo.ServerName, ipBox.Font, ipBox.Rect.Width); } catch (InvalidCastException) { return(false); } return(true); }
private void AddPreviouslyUsed(MapEntityPrefab mapEntityPrefab) { if (previouslyUsedList == null || mapEntityPrefab == null) { return; } previouslyUsedList.Deselect(); if (previouslyUsedList.CountChildren == PreviouslyUsedCount) { previouslyUsedList.RemoveChild(previouslyUsedList.children.Last()); } var existing = previouslyUsedList.FindChild(mapEntityPrefab); if (existing != null) { previouslyUsedList.RemoveChild(existing); } string name = ToolBox.LimitString(mapEntityPrefab.Name, 15); var textBlock = new GUITextBlock( new Rectangle(0, 0, 0, 15), ToolBox.LimitString(name, GUI.SmallFont, previouslyUsedList.Rect.Width), "", Alignment.TopLeft, Alignment.CenterLeft, previouslyUsedList, false, GUI.SmallFont); textBlock.UserData = mapEntityPrefab; previouslyUsedList.RemoveChild(textBlock); previouslyUsedList.children.Insert(0, textBlock); }
private void UpdateLevelObjectsList() { editorContainer.ClearChildren(); levelObjectList.Content.ClearChildren(); int objectsPerRow = (int)Math.Ceiling(levelObjectList.Content.Rect.Width / Math.Max(150 * GUI.Scale, 100)); float relWidth = 1.0f / objectsPerRow; foreach (LevelObjectPrefab levelObjPrefab in LevelObjectPrefab.List) { var frame = new GUIFrame(new RectTransform( new Vector2(relWidth, relWidth * ((float)levelObjectList.Content.Rect.Width / levelObjectList.Content.Rect.Height)), levelObjectList.Content.RectTransform) { MinSize = new Point(0, 60) }, style: "GUITextBox") { UserData = levelObjPrefab }; var paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), frame.RectTransform, Anchor.Center), style: null); GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform, Anchor.BottomCenter), text: ToolBox.LimitString(levelObjPrefab.Name, GUI.SmallFont, paddedFrame.Rect.Width), textAlignment: Alignment.Center, font: GUI.SmallFont) { CanBeFocused = false, }; Sprite sprite = levelObjPrefab.Sprite ?? levelObjPrefab.DeformableSprite?.Sprite; GUIImage img = new GUIImage(new RectTransform(new Point(paddedFrame.Rect.Height, paddedFrame.Rect.Height - textBlock.Rect.Height), paddedFrame.RectTransform, Anchor.TopCenter), sprite, scaleToFit: true) { CanBeFocused = false }; } }
public override void Draw(SpriteBatch spriteBatch) { if (!isRunning || GUI.DisableHUD || GUI.DisableUpperHUD) { return; } if (Submarine.MainSub == null) { return; } Submarine leavingSub = GetLeavingSub(); if (leavingSub == null) { endRoundButton.Visible = false; } else if (leavingSub.AtEndPosition) { endRoundButton.Text = ToolBox.LimitString(TextManager.Get("EnterLocation").Replace("[locationname]", Map.SelectedLocation.Name), endRoundButton.Font, endRoundButton.Rect.Width - 5); endRoundButton.Visible = true; } else if (leavingSub.AtStartPosition) { endRoundButton.Text = ToolBox.LimitString(TextManager.Get("EnterLocation").Replace("[locationname]", Map.CurrentLocation.Name), endRoundButton.Font, endRoundButton.Rect.Width - 5); endRoundButton.Visible = true; } else { endRoundButton.Visible = false; } endRoundButton.DrawManually(spriteBatch); }
private static void UpdateHighlightedListBox(List <MapEntity> highlightedEntities) { if (highlightedEntities == null || highlightedEntities.Count < 2) { highlightedListBox = null; return; } if (highlightedListBox != null) { if (GUI.MouseOn == highlightedListBox || highlightedListBox.IsParentOf(GUI.MouseOn)) { return; } if (highlightedEntities.SequenceEqual(highlightedList)) { return; } } highlightedList = highlightedEntities; highlightedListBox = new GUIListBox(new RectTransform(new Point(180, highlightedEntities.Count * 18 + 5), GUI.Canvas) { ScreenSpaceOffset = PlayerInput.MousePosition.ToPoint() + new Point(15) }, style: "GUIToolTip"); foreach (MapEntity entity in highlightedEntities) { var textBlock = new GUITextBlock(new RectTransform(new Point(highlightedListBox.Content.Rect.Width, 15), highlightedListBox.Content.RectTransform), ToolBox.LimitString(entity.Name, GUI.SmallFont, 140), font: GUI.SmallFont) { UserData = entity }; } highlightedListBox.OnSelected = (GUIComponent component, object obj) => { MapEntity entity = obj as MapEntity; if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl)) { if (selectedList.Contains(entity)) { selectedList.Remove(entity); } else { selectedList.Add(entity); } } else { SelectEntity(entity); } return(true); }; }
private static void UpdateHighlightedListBox(List <MapEntity> highlightedEntities) { if (highlightedEntities == null || highlightedEntities.Count < 2) { highlightedListBox = null; return; } if (highlightedListBox != null) { if (GUIComponent.MouseOn == highlightedListBox || highlightedListBox.IsParentOf(GUIComponent.MouseOn)) { return; } if (highlightedEntities.SequenceEqual(highlightedList)) { return; } } highlightedList = highlightedEntities; highlightedListBox = new GUIListBox( new Rectangle((int)PlayerInput.MousePosition.X + 15, (int)PlayerInput.MousePosition.Y + 15, 150, highlightedEntities.Count * 18 + 5), null, Alignment.TopLeft, "GUIToolTip", null, false); foreach (MapEntity entity in highlightedEntities) { var textBlock = new GUITextBlock( new Rectangle(0, 0, highlightedListBox.Rect.Width, 18), ToolBox.LimitString(entity.Name, GUI.SmallFont, 140), "", Alignment.TopLeft, Alignment.CenterLeft, highlightedListBox, false, GUI.SmallFont); textBlock.UserData = entity; } highlightedListBox.OnSelected = (GUIComponent component, object obj) => { MapEntity entity = obj as MapEntity; if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl)) { if (selectedList.Contains(entity)) { selectedList.Remove(entity); } else { selectedList.Add(entity); } } else { SelectEntity(entity); } return(true); }; }
private void OnResolutionChanged() { menu.RectTransform.MinSize = new Point(GameMain.GraphicsHeight, 0); labelHolder.RectTransform.MaxSize = new Point(serverList.Content.Rect.Width, int.MaxValue); foreach (GUITextBlock labelText in labelTexts) { labelText.Text = ToolBox.LimitString(labelText.ToolTip, labelText.Font, labelText.Rect.Width); } }
public void UpdateSubList(IEnumerable <SubmarineInfo> submarines) { var subsToShow = submarines.Where(s => s.IsCampaignCompatibleIgnoreClass).ToList(); subsToShow.Sort((s1, s2) => { int p1 = s1.Price > CampaignMode.MaxInitialSubmarinePrice ? 10 : 0; int p2 = s2.Price > CampaignMode.MaxInitialSubmarinePrice ? 10 : 0; return(p1.CompareTo(p2) * 100 + s1.Name.CompareTo(s2.Name)); }); subList.ClearChildren(); foreach (SubmarineInfo sub in subsToShow) { var textBlock = new GUITextBlock( new RectTransform(new Vector2(1, 0.1f), subList.Content.RectTransform) { MinSize = new Point(0, 30) }, ToolBox.LimitString(sub.DisplayName, GUI.Font, subList.Rect.Width - 65), style: "ListBoxElement") { ToolTip = sub.Description, UserData = sub }; if (!sub.RequiredContentPackagesInstalled) { textBlock.TextColor = Color.Lerp(textBlock.TextColor, Color.DarkRed, .5f); textBlock.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + textBlock.RawToolTip; } var priceText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textBlock.RectTransform, Anchor.CenterRight), TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", sub.Price)), textAlignment: Alignment.CenterRight, font: GUI.SmallFont) { TextColor = sub.Price > CampaignMode.MaxInitialSubmarinePrice ? GUI.Style.Red : textBlock.TextColor * 0.8f, ToolTip = textBlock.ToolTip }; #if !DEBUG if (sub.Price > CampaignMode.MaxInitialSubmarinePrice && !GameMain.DebugDraw) { textBlock.CanBeFocused = false; } #endif } if (SubmarineInfo.SavedSubmarines.Any()) { var nonShuttles = subsToShow.Where(s => s.Type == SubmarineType.Player && !s.HasTag(SubmarineTag.Shuttle) && s.Price <= CampaignMode.MaxInitialSubmarinePrice).ToList(); if (nonShuttles.Count > 0) { subList.Select(nonShuttles[Rand.Int(nonShuttles.Count)]); } } }
public void UpdateSubList(IEnumerable <SubmarineInfo> submarines) { #if !DEBUG var subsToShow = submarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus)); #else var subsToShow = submarines; #endif subList.ClearChildren(); foreach (SubmarineInfo sub in subsToShow) { var textBlock = new GUITextBlock( new RectTransform(new Vector2(1, 0.1f), subList.Content.RectTransform) { MinSize = new Point(0, 30) }, ToolBox.LimitString(sub.DisplayName, GUI.Font, subList.Rect.Width - 65), style: "ListBoxElement") { ToolTip = sub.Description, UserData = sub }; if (!sub.RequiredContentPackagesInstalled) { textBlock.TextColor = Color.Lerp(textBlock.TextColor, Color.DarkRed, .5f); textBlock.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + textBlock.RawToolTip; } if (sub.HasTag(SubmarineTag.Shuttle)) { textBlock.TextColor = textBlock.TextColor * 0.85f; var shuttleText = new GUITextBlock(new RectTransform(new Point(100, textBlock.Rect.Height), textBlock.RectTransform, Anchor.CenterRight) { IsFixedSize = false }, TextManager.Get("Shuttle", fallBackTag: "RespawnShuttle"), textAlignment: Alignment.Right, font: GUI.SmallFont) { TextColor = textBlock.TextColor * 0.8f, ToolTip = textBlock.RawToolTip }; } } if (SubmarineInfo.SavedSubmarines.Any()) { var nonShuttles = subsToShow.Where(s => !s.HasTag(SubmarineTag.Shuttle)).ToList(); if (nonShuttles.Count > 0) { subList.Select(nonShuttles[Rand.Int(nonShuttles.Count)]); } } }
public void CreateCrewFrame(List <Character> crew, GUIFrame crewFrame) { List <byte> teamIDs = crew.Select(c => c.TeamID).Distinct().ToList(); if (!teamIDs.Any()) { teamIDs.Add(0); } int listBoxHeight = 300 / teamIDs.Count; int y = 20; for (int i = 0; i < teamIDs.Count; i++) { if (teamIDs.Count > 1) { new GUITextBlock(new Rectangle(0, y - 20, 100, 20), CombatMission.GetTeamName(teamIDs[i]), "", crewFrame); } GUIListBox crewList = new GUIListBox(new Rectangle(0, y, 280, listBoxHeight), Color.White * 0.7f, "", crewFrame); crewList.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f); crewList.OnSelected = (component, obj) => { SelectCrewCharacter(component.UserData as Character, crewList); return(true); }; foreach (Character character in crew.FindAll(c => c.TeamID == teamIDs[i])) { GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 40), Color.Transparent, "ListBoxElement", crewList); frame.UserData = character; frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); frame.Color = (GameMain.NetworkMember != null && GameMain.NetworkMember.Character == character) ? Color.Gold * 0.2f : Color.Transparent; GUITextBlock textBlock = new GUITextBlock( new Rectangle(40, 0, 0, 25), ToolBox.LimitString(character.Info.Name + " (" + character.Info.Job.Name + ")", GUI.Font, frame.Rect.Width - 20), null, null, Alignment.Left, Alignment.Left, "", frame); textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f); new GUIImage(new Rectangle(-10, 0, 0, 0), character.AnimController.Limbs[0].sprite, Alignment.Left, frame); } y += crewList.Rect.Height + 30; } }
public void UpdateSubList() { var subsToShow = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus)); subList.ClearChildren(); foreach (Submarine sub in subsToShow) { var textBlock = new GUITextBlock( new Rectangle(0, 0, 0, 25), ToolBox.LimitString(sub.Name, GUI.Font, subList.Rect.Width - 65), "ListBoxElement", Alignment.Left, Alignment.Left, subList) { Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f), ToolTip = sub.Description, UserData = sub }; if (sub.HasTag(SubmarineTag.Shuttle)) { textBlock.TextColor = textBlock.TextColor * 0.85f; var shuttleText = new GUITextBlock(new Rectangle(-20, 0, 0, 25), TextManager.Get("Shuttle"), "", Alignment.CenterRight, Alignment.CenterRight, textBlock, false, GUI.SmallFont); shuttleText.TextColor = textBlock.TextColor * 0.8f; shuttleText.ToolTip = textBlock.ToolTip; } GUIButton infoButton = new GUIButton(new Rectangle(0, 0, 20, 20), "?", Alignment.CenterRight, "", textBlock); infoButton.UserData = sub; infoButton.OnClicked += (component, userdata) => { var msgBox = new GUIMessageBox("", "", 550, 350); ((Submarine)userdata).CreatePreviewWindow(msgBox.InnerFrame); return(true); }; } if (Submarine.SavedSubmarines.Count > 0) { subList.Select(Submarine.SavedSubmarines[0]); } }
public override void Draw(SpriteBatch spriteBatch) { if (!isRunning || GUI.DisableHUD) { return; } CrewManager.Draw(spriteBatch); if (Submarine.MainSub == null) { return; } Submarine leavingSub = GetLeavingSub(); if (leavingSub == null) { endShiftButton.Visible = false; } else if (leavingSub.AtEndPosition) { endShiftButton.Text = ToolBox.LimitString("Enter " + Map.SelectedLocation.Name, endShiftButton.Font, endShiftButton.Rect.Width - 5); endShiftButton.UserData = leavingSub; endShiftButton.Visible = true; } else if (leavingSub.AtStartPosition) { endShiftButton.Text = ToolBox.LimitString("Enter " + Map.CurrentLocation.Name, endShiftButton.Font, endShiftButton.Rect.Width - 5); endShiftButton.UserData = leavingSub; endShiftButton.Visible = true; } else { endShiftButton.Visible = false; } endShiftButton.Draw(spriteBatch); }
private GUIComponent CreateItemFrame(PurchasedItem pi, PriceInfo priceInfo, GUIListBox listBox, int width) { GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, (int)(GUI.Scale * 50)), listBox.Content.RectTransform), style: "ListBoxElement") { UserData = pi, ToolTip = pi.ItemPrefab.Description }; var content = new GUILayoutGroup(new RectTransform(Vector2.One, frame.RectTransform), isHorizontal: true) { RelativeSpacing = 0.02f, Stretch = true }; ScalableFont font = listBox.Rect.Width < 280 ? GUI.SmallFont : GUI.Font; Sprite itemIcon = pi.ItemPrefab.InventoryIcon ?? pi.ItemPrefab.sprite; if (itemIcon != null) { GUIImage img = new GUIImage(new RectTransform(new Point((int)(content.Rect.Height * 0.8f)), content.RectTransform, Anchor.CenterLeft), itemIcon, scaleToFit: true) { Color = itemIcon == pi.ItemPrefab.InventoryIcon ? pi.ItemPrefab.InventoryIconColor : pi.ItemPrefab.SpriteColor }; img.RectTransform.MaxSize = img.Rect.Size; //img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f); } GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), content.RectTransform), pi.ItemPrefab.Name, font: font) { ToolTip = pi.ItemPrefab.Description }; new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), content.RectTransform), priceInfo.BuyPrice.ToString(), font: font, textAlignment: Alignment.CenterRight) { ToolTip = pi.ItemPrefab.Description }; //If its the store menu, quantity will always be 0 GUINumberInput amountInput = null; if (pi.Quantity > 0) { amountInput = new GUINumberInput(new RectTransform(new Vector2(0.3f, 1.0f), content.RectTransform), GUINumberInput.NumberType.Int) { MinValueInt = 0, MaxValueInt = 100, UserData = pi, IntValue = pi.Quantity }; amountInput.OnValueChanged += (numberInput) => { PurchasedItem purchasedItem = numberInput.UserData as PurchasedItem; //Attempting to buy if (numberInput.IntValue > purchasedItem.Quantity) { int quantity = numberInput.IntValue - purchasedItem.Quantity; //Cap the numberbox based on the amount we can afford. quantity = Campaign.Money <= 0 ? 0 : Math.Min((int)(Campaign.Money / (float)priceInfo.BuyPrice), quantity); for (int i = 0; i < quantity; i++) { BuyItem(numberInput, purchasedItem); } numberInput.IntValue = purchasedItem.Quantity; } //Attempting to sell else { int quantity = purchasedItem.Quantity - numberInput.IntValue; for (int i = 0; i < quantity; i++) { SellItem(numberInput, purchasedItem); } } }; } listBox.RecalculateChildren(); content.Recalculate(); content.RectTransform.RecalculateChildren(true, true); amountInput?.LayoutGroup.Recalculate(); textBlock.Text = ToolBox.LimitString(textBlock.Text, textBlock.Font, textBlock.Rect.Width); content.RectTransform.IsFixedSize = true; content.RectTransform.Children.ForEach(c => c.IsFixedSize = true); return(frame); }
private void CreateCharacterElement(CharacterInfo characterInfo, GUIListBox listBox) { GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, GUI.IntScale(45)), listBox.Content.RectTransform), style: "ListBoxElement") { CanBeFocused = false, UserData = characterInfo, Color = (Character.Controlled?.Info == characterInfo) ? TabMenu.OwnCharacterBGColor : Color.Transparent }; var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true) { AbsoluteSpacing = 2, Stretch = true }; new GUICustomComponent(new RectTransform(new Point(jobColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform, Anchor.Center), onDraw: (sb, component) => characterInfo.DrawJobIcon(sb, component.Rect)) { ToolTip = characterInfo.Job.Name ?? "", HoverColor = Color.White, SelectedColor = Color.White }; GUITextBlock characterNameBlock = new GUITextBlock(new RectTransform(new Point(characterColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform), ToolBox.LimitString(characterInfo.Name, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: characterInfo.Job.Prefab.UIColor); string statusText = TextManager.Get("StatusOK"); Color statusColor = GUI.Style.Green; Character character = characterInfo.Character; if (character == null || character.IsDead) { if (character == null && characterInfo.IsNewHire) { statusText = TextManager.Get("CampaignCrew.NewHire"); statusColor = GUI.Style.Blue; } else if (characterInfo.CauseOfDeath == null) { statusText = TextManager.Get("CauseOfDeathDescription.Unknown"); statusColor = Color.DarkRed; } else if (characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction && characterInfo.CauseOfDeath.Affliction == null) { string errorMsg = "Character \"" + characterInfo.Name + "\" had an invalid cause of death (the type of the cause of death was Affliction, but affliction was not specified)."; DebugConsole.ThrowError(errorMsg); GameAnalyticsManager.AddErrorEventOnce("RoundSummary:InvalidCauseOfDeath", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); statusText = TextManager.Get("CauseOfDeathDescription.Unknown"); statusColor = GUI.Style.Red; } else { statusText = characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction ? characterInfo.CauseOfDeath.Affliction.CauseOfDeathDescription : TextManager.Get("CauseOfDeathDescription." + characterInfo.CauseOfDeath.Type.ToString()); statusColor = Color.DarkRed; } } else { if (character.IsUnconscious) { statusText = TextManager.Get("Unconscious"); statusColor = Color.DarkOrange; } else if (character.Vitality / character.MaxVitality < 0.8f) { statusText = TextManager.Get("Injured"); statusColor = Color.DarkOrange; } } GUITextBlock statusBlock = new GUITextBlock(new RectTransform(new Point(statusColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform), ToolBox.LimitString(statusText, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: statusColor); }
public ServerListScreen() { GameMain.Instance.OnResolutionChanged += OnResolutionChanged; menu = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.85f), GUI.Canvas, Anchor.Center) { MinSize = new Point(GameMain.GraphicsHeight, 0) }); var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.97f, 0.95f), menu.RectTransform, Anchor.Center)) { RelativeSpacing = 0.02f, Stretch = true }; //------------------------------------------------------------------------------------- //Top row //------------------------------------------------------------------------------------- var topRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform)) { Stretch = true }; var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.33f), topRow.RectTransform), TextManager.Get("JoinServer"), font: GUI.LargeFont) { Padding = Vector4.Zero, ForceUpperCase = true, AutoScale = true }; var infoHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.33f), topRow.RectTransform), isHorizontal: true) { RelativeSpacing = 0.05f, Stretch = true }; var clientNameHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), infoHolder.RectTransform)) { RelativeSpacing = 0.05f }; new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), clientNameHolder.RectTransform), TextManager.Get("YourName")); clientNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.5f), clientNameHolder.RectTransform), "") { Text = GameMain.Config.PlayerName, MaxTextLength = Client.MaxNameLength, OverflowClip = true }; if (string.IsNullOrEmpty(clientNameBox.Text)) { clientNameBox.Text = SteamManager.GetUsername(); } var ipBoxHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), infoHolder.RectTransform)) { RelativeSpacing = 0.05f }; new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), ipBoxHolder.RectTransform), TextManager.Get("ServerIP")); ipBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.5f), ipBoxHolder.RectTransform), ""); ipBox.OnTextChanged += (textBox, text) => { joinButton.Enabled = !string.IsNullOrEmpty(text); return(true); }; ipBox.OnSelected += (sender, key) => { if (sender.UserData is ServerInfo) { sender.Text = ""; sender.UserData = null; } }; //------------------------------------------------------------------------------------- // Bottom row //------------------------------------------------------------------------------------- var bottomRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f - topRow.RectTransform.RelativeSize.Y), paddedFrame.RectTransform, Anchor.CenterRight)) { Stretch = true }; var serverListHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), bottomRow.RectTransform), isHorizontal: true) { Stretch = true }; // filters ------------------------------------------- var filters = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), serverListHolder.RectTransform, Anchor.Center), style: null) { Color = new Color(12, 14, 15, 255) * 0.5f, OutlineColor = Color.Black }; var filterToggle = new GUIButton(new RectTransform(new Vector2(0.02f, 1.0f), serverListHolder.RectTransform, Anchor.CenterRight) { MinSize = new Point(20, 0) }, style: "UIToggleButton") { OnClicked = (btn, userdata) => { filters.RectTransform.RelativeSize = new Vector2(0.25f, 1.0f); filters.Visible = !filters.Visible; filters.IgnoreLayoutGroups = !filters.Visible; serverListHolder.Recalculate(); btn.Children.ForEach(c => c.SpriteEffects = !filters.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally); return(true); } }; filterToggle.Children.ForEach(c => c.SpriteEffects = SpriteEffects.FlipHorizontally); var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.99f), filters.RectTransform, Anchor.Center)) { Stretch = true, RelativeSpacing = 0.015f }; var filterTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), filterContainer.RectTransform), TextManager.Get("FilterServers"), font: GUI.LargeFont) { Padding = Vector4.Zero, AutoScale = true }; float elementHeight = 0.05f; var searchHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, elementHeight), filterContainer.RectTransform), isHorizontal: true) { Stretch = true }; var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), searchHolder.RectTransform), TextManager.Get("Search") + "..."); searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), searchHolder.RectTransform), ""); searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; }; searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; }; searchBox.OnTextChanged += (txtBox, txt) => { FilterServers(); return(true); }; var filterHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform)) { RelativeSpacing = 0.005f }; List <GUITextBlock> filterTextList = new List <GUITextBlock>(); filterPassword = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filterHolder.RectTransform), TextManager.Get("FilterPassword")) { ToolTip = TextManager.Get("FilterPassword"), OnSelected = (tickBox) => { FilterServers(); return(true); } }; filterTextList.Add(filterPassword.TextBlock); filterIncompatible = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filterHolder.RectTransform), TextManager.Get("FilterIncompatibleServers")) { ToolTip = TextManager.Get("FilterIncompatibleServers"), OnSelected = (tickBox) => { FilterServers(); return(true); } }; filterTextList.Add(filterIncompatible.TextBlock); filterFull = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filterHolder.RectTransform), TextManager.Get("FilterFullServers")) { ToolTip = TextManager.Get("FilterFullServers"), OnSelected = (tickBox) => { FilterServers(); return(true); } }; filterTextList.Add(filterFull.TextBlock); filterEmpty = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filterHolder.RectTransform), TextManager.Get("FilterEmptyServers")) { ToolTip = TextManager.Get("FilterEmptyServers"), OnSelected = (tickBox) => { FilterServers(); return(true); } }; filterTextList.Add(filterEmpty.TextBlock); filterContainer.RectTransform.SizeChanged += () => { filterContainer.RectTransform.RecalculateChildren(true, true); filterTextList.ForEach(t => t.Text = t.ToolTip); GUITextBlock.AutoScaleAndNormalize(filterTextList); if (filterTextList[0].TextScale < 0.8f) { filterTextList.ForEach(t => t.TextScale = 1.0f); filterTextList.ForEach(t => t.Text = ToolBox.LimitString(t.Text, t.Font, (int)(filterContainer.Rect.Width * 0.8f))); } }; // server list --------------------------------------------------------------------- var serverListContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), serverListHolder.RectTransform)) { Stretch = true }; labelHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.99f, 0.05f), serverListContainer.RectTransform) { MinSize = new Point(0, 15) }, isHorizontal: true) { Stretch = true }; for (int i = 0; i < columnRelativeWidth.Length; i++) { var btn = new GUIButton(new RectTransform(new Vector2(columnRelativeWidth[i], 1.0f), labelHolder.RectTransform), text: TextManager.Get(columnLabel[i]), textAlignment: Alignment.Center, style: null) { Color = new Color(12, 14, 15, 255) * 0.5f, HoverColor = new Color(12, 14, 15, 255) * 2.5f, SelectedColor = Color.Gray * 0.7f, PressedColor = Color.Gray * 0.7f, OutlineColor = Color.Black, ToolTip = TextManager.Get(columnLabel[i]), ForceUpperCase = true, UserData = columnLabel[i], OnClicked = SortList }; labelTexts.Add(btn.TextBlock); new GUIImage(new RectTransform(new Vector2(0.5f, 0.3f), btn.RectTransform, Anchor.BottomCenter, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonVerticalArrow", scaleToFit: true) { CanBeFocused = false, UserData = "arrowup", Visible = false }; new GUIImage(new RectTransform(new Vector2(0.5f, 0.3f), btn.RectTransform, Anchor.BottomCenter, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonVerticalArrow", scaleToFit: true) { CanBeFocused = false, UserData = "arrowdown", SpriteEffects = SpriteEffects.FlipVertically, Visible = false }; } serverList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), serverListContainer.RectTransform, Anchor.Center)) { ScrollBarVisible = true, OnSelected = (btn, obj) => { if (obj is ServerInfo serverInfo) { joinButton.Enabled = true; ipBox.UserData = serverInfo; ipBox.Text = serverInfo.ServerName; if (!serverPreview.Visible) { serverPreview.RectTransform.RelativeSize = new Vector2(0.3f, 1.0f); serverPreviewToggleButton.Visible = true; serverPreviewToggleButton.IgnoreLayoutGroups = false; serverPreview.Visible = true; serverPreview.IgnoreLayoutGroups = false; serverListHolder.Recalculate(); } serverInfo.CreatePreviewWindow(serverPreview); btn.Children.ForEach(c => c.SpriteEffects = serverPreview.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally); } return(true); } }; //server preview panel -------------------------------------------------- serverPreviewToggleButton = new GUIButton(new RectTransform(new Vector2(0.02f, 1.0f), serverListHolder.RectTransform, Anchor.CenterRight) { MinSize = new Point(20, 0) }, style: "UIToggleButton") { Visible = false, OnClicked = (btn, userdata) => { serverPreview.RectTransform.RelativeSize = new Vector2(0.25f, 1.0f); serverPreview.Visible = !serverPreview.Visible; serverPreview.IgnoreLayoutGroups = !serverPreview.Visible; serverListHolder.Recalculate(); btn.Children.ForEach(c => c.SpriteEffects = serverPreview.Visible ? SpriteEffects.None : SpriteEffects.FlipHorizontally); return(true); } }; serverPreview = new GUIFrame(new RectTransform(new Vector2(0.3f, 1.0f), serverListHolder.RectTransform, Anchor.Center), style: null) { Color = new Color(12, 14, 15, 255) * 0.5f, OutlineColor = Color.Black, IgnoreLayoutGroups = true, Visible = false }; // Spacing new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), bottomRow.RectTransform), style: null); var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.075f), bottomRow.RectTransform, Anchor.Center), isHorizontal: true) { RelativeSpacing = 0.02f, Stretch = true }; GUIButton button = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), TextManager.Get("Back"), style: "GUIButtonLarge") { OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu }; new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), TextManager.Get("ServerListRefresh"), style: "GUIButtonLarge") { OnClicked = (btn, userdata) => { RefreshServers(); return(true); } }; /*var directJoinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), * TextManager.Get("serverlistdirectjoin"), style: "GUIButtonLarge") * { * OnClicked = (btn, userdata) => { ShowDirectJoinPrompt(); return true; } * };*/ joinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), TextManager.Get("ServerListJoin"), style: "GUIButtonLarge") { OnClicked = (btn, userdata) => { if (ipBox.UserData is ServerInfo selectedServer) { if (selectedServer.LobbyID == 0) { JoinServer(selectedServer.IP + ":" + selectedServer.Port, selectedServer.ServerName); } else { Steam.SteamManager.JoinLobby(selectedServer.LobbyID, true); } } else if (!string.IsNullOrEmpty(ipBox.Text)) { JoinServer(ipBox.Text, ""); } return(true); }, Enabled = false }; //-------------------------------------------------------- bottomRow.Recalculate(); serverListHolder.Recalculate(); serverListContainer.Recalculate(); labelHolder.RectTransform.MaxSize = new Point(serverList.Content.Rect.Width, int.MaxValue); labelHolder.Recalculate(); serverList.Content.RectTransform.SizeChanged += () => { labelHolder.RectTransform.MaxSize = new Point(serverList.Content.Rect.Width, int.MaxValue); labelHolder.Recalculate(); foreach (GUITextBlock labelText in labelTexts) { labelText.Text = ToolBox.LimitString(labelText.ToolTip, labelText.Font, labelText.Rect.Width); } }; button.SelectedColor = button.Color; refreshDisableTimer = DateTime.Now; }
private void CreateCharacterPreviewFrame(GUIListBox listBox, GUIFrame characterFrame, CharacterInfo characterInfo) { Pivot pivot = listBox == hireableList ? Pivot.TopLeft : Pivot.TopRight; Point absoluteOffset = new Point( pivot == Pivot.TopLeft ? listBox.Parent.Parent.Rect.Right + 5 : listBox.Parent.Parent.Rect.Left - 5, characterFrame.Rect.Top); int frameSize = (int)(GUI.Scale * 300); if (GameMain.GraphicsHeight - (absoluteOffset.Y + frameSize) < 0) { pivot = listBox == hireableList ? Pivot.BottomLeft : Pivot.BottomRight; absoluteOffset.Y = characterFrame.Rect.Bottom; } characterPreviewFrame = new GUIFrame(new RectTransform(new Point(frameSize), parent: campaignUI.GetTabContainer(CampaignMode.InteractionType.Crew).Parent.RectTransform, pivot: pivot) { AbsoluteOffset = absoluteOffset }, style: "InnerFrame") { UserData = characterInfo }; GUILayoutGroup mainGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f), characterPreviewFrame.RectTransform, anchor: Anchor.Center)) { RelativeSpacing = 0.01f }; // Character info GUILayoutGroup infoGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.475f), mainGroup.RectTransform), isHorizontal: true); GUILayoutGroup infoLabelGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), infoGroup.RectTransform)) { Stretch = true }; GUILayoutGroup infoValueGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 1.0f), infoGroup.RectTransform)) { Stretch = true }; float blockHeight = 1.0f / 4; new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("name")); GUITextBlock nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), ""); string name = listBox == hireableList ? characterInfo.OriginalName : characterInfo.Name; nameBlock.Text = ToolBox.LimitString(name, nameBlock.Font, nameBlock.Rect.Width); if (characterInfo.HasGenders) { new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("gender")); new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), TextManager.Get(characterInfo.Gender.ToString())); } if (characterInfo.Job is Job job) { new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("tabmenu.job")); new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), job.Name); } if (characterInfo.PersonalityTrait is NPCPersonalityTrait trait) { new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("PersonalityTrait")); new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), TextManager.Get("personalitytrait." + trait.Name.Replace(" ", ""))); } infoLabelGroup.Recalculate(); infoValueGroup.Recalculate(); new GUIImage(new RectTransform(new Vector2(1.0f, 0.05f), mainGroup.RectTransform), "HorizontalLine"); // Skills GUILayoutGroup skillGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.475f), mainGroup.RectTransform), isHorizontal: true); GUILayoutGroup skillNameGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1.0f), skillGroup.RectTransform)); GUILayoutGroup skillLevelGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.2f, 1.0f), skillGroup.RectTransform)); List <Skill> characterSkills = characterInfo.Job.Skills; blockHeight = 1.0f / characterSkills.Count; foreach (Skill skill in characterSkills) { new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), skillNameGroup.RectTransform), TextManager.Get("SkillName." + skill.Identifier)); new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), skillLevelGroup.RectTransform), ((int)skill.Level).ToString(), textAlignment: Alignment.Right); } }
public override void Draw(SpriteBatch spriteBatch) { if (overlayColor.A > 0) { if (overlaySprite != null) { GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * (overlayColor.A / 255.0f), isFilled: true); float scale = Math.Max(GameMain.GraphicsWidth / overlaySprite.size.X, GameMain.GraphicsHeight / overlaySprite.size.Y); overlaySprite.Draw(spriteBatch, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2, overlayColor, overlaySprite.size / 2, scale: scale); } else { GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), overlayColor, isFilled: true); } if (!string.IsNullOrEmpty(overlayText) && overlayTextColor.A > 0) { var backgroundSprite = GUI.Style.GetComponentStyle("CommandBackground").GetDefaultSprite(); Vector2 centerPos = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2; string wrappedText = ToolBox.WrapText(overlayText, GameMain.GraphicsWidth / 3, GUI.Font); Vector2 textSize = GUI.Font.MeasureString(wrappedText); Vector2 textPos = centerPos - textSize / 2; backgroundSprite.Draw(spriteBatch, centerPos, Color.White * (overlayTextColor.A / 255.0f), origin: backgroundSprite.size / 2, rotate: 0.0f, scale: new Vector2(GameMain.GraphicsWidth / 2 / backgroundSprite.size.X, textSize.Y / backgroundSprite.size.Y * 1.5f)); GUI.DrawString(spriteBatch, textPos + Vector2.One, wrappedText, Color.Black * (overlayTextColor.A / 255.0f)); GUI.DrawString(spriteBatch, textPos, wrappedText, overlayTextColor); if (!string.IsNullOrEmpty(overlayTextBottom)) { Vector2 bottomTextPos = centerPos + new Vector2(0.0f, textSize.Y / 2 + 40 * GUI.Scale) - GUI.Font.MeasureString(overlayTextBottom) / 2; GUI.DrawString(spriteBatch, bottomTextPos + Vector2.One, overlayTextBottom, Color.Black * (overlayTextColor.A / 255.0f)); GUI.DrawString(spriteBatch, bottomTextPos, overlayTextBottom, overlayTextColor); } } } if (GUI.DisableHUD || GUI.DisableUpperHUD || ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition")) { endRoundButton.Visible = false; if (ReadyCheckButton != null) { ReadyCheckButton.Visible = false; } return; } if (Submarine.MainSub == null || Level.Loaded == null) { return; } endRoundButton.Visible = false; var availableTransition = GetAvailableTransition(out _, out Submarine leavingSub); string buttonText = ""; switch (availableTransition) { case TransitionType.ProgressToNextLocation: case TransitionType.ProgressToNextEmptyLocation: if (Level.Loaded.EndOutpost == null || !Level.Loaded.EndOutpost.DockedTo.Contains(leavingSub)) { string textTag = availableTransition == TransitionType.ProgressToNextLocation ? "EnterLocation" : "EnterEmptyLocation"; buttonText = TextManager.GetWithVariable(textTag, "[locationname]", Level.Loaded.EndLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; } break; case TransitionType.LeaveLocation: buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; break; case TransitionType.ReturnToPreviousLocation: case TransitionType.ReturnToPreviousEmptyLocation: if (Level.Loaded.StartOutpost == null || !Level.Loaded.StartOutpost.DockedTo.Contains(leavingSub)) { string textTag = availableTransition == TransitionType.ReturnToPreviousLocation ? "EnterLocation" : "EnterEmptyLocation"; buttonText = TextManager.GetWithVariable(textTag, "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; } break; case TransitionType.None: default: if (Level.Loaded.Type == LevelData.LevelType.Outpost && (Character.Controlled?.Submarine?.Info.Type == SubmarineType.Player || (Character.Controlled?.CurrentHull?.OutpostModuleTags.Contains("airlock") ?? false))) { buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; } else { endRoundButton.Visible = false; } break; } if (ReadyCheckButton != null) { ReadyCheckButton.Visible = endRoundButton.Visible; } if (endRoundButton.Visible) { if (!AllowedToEndRound()) { buttonText = TextManager.Get("map"); } else if (prevCampaignUIAutoOpenType != availableTransition && (availableTransition == TransitionType.ProgressToNextEmptyLocation || availableTransition == TransitionType.ReturnToPreviousEmptyLocation)) { HintManager.OnAvailableTransition(availableTransition); //opening the campaign map pauses the game and prevents HintManager from running -> update it manually to get the hint to show up immediately HintManager.Update(); Map.SelectLocation(-1); endRoundButton.OnClicked(EndRoundButton, null); prevCampaignUIAutoOpenType = availableTransition; } endRoundButton.Text = ToolBox.LimitString(buttonText, endRoundButton.Font, endRoundButton.Rect.Width - 5); if (endRoundButton.Text != buttonText) { endRoundButton.ToolTip = buttonText; } if (Character.Controlled?.CharacterHealth?.SuicideButton?.Visible ?? false) { endRoundButton.RectTransform.ScreenSpaceOffset = new Point(0, Character.Controlled.CharacterHealth.SuicideButton.Rect.Height); } else if (GameMain.Client != null && GameMain.Client.IsFollowSubTickBoxVisible) { endRoundButton.RectTransform.ScreenSpaceOffset = new Point(0, HUDLayoutSettings.Padding + GameMain.Client.FollowSubTickBox.Rect.Height); } else { endRoundButton.RectTransform.ScreenSpaceOffset = Point.Zero; } } endRoundButton.DrawManually(spriteBatch); if (this is MultiPlayerCampaign && ReadyCheckButton != null) { ReadyCheckButton.RectTransform.ScreenSpaceOffset = endRoundButton.RectTransform.ScreenSpaceOffset; ReadyCheckButton.DrawManually(spriteBatch); } }
private void CreateMultiplayerCampaignSubList(RectTransform parent) { GUILayoutGroup subHolder = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.725f), parent)) { RelativeSpacing = 0.005f, Stretch = true }; var subLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), subHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Get("purchasablesubmarines", fallBackTag: "workshoplabelsubmarines"), font: GUI.SubHeadingFont); var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), subHolder.RectTransform), isHorizontal: true) { Stretch = true }; var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUI.Font); var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform, Anchor.CenterRight), font: GUI.Font, createClearButton: true); filterContainer.RectTransform.MinSize = searchBox.RectTransform.MinSize; searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; }; searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; }; searchBox.OnTextChanged += (textBox, text) => { foreach (GUIComponent child in subList.Content.Children) { if (!(child.UserData is SubmarineInfo sub)) { continue; } child.Visible = string.IsNullOrEmpty(text) ? true : sub.DisplayName.ToLower().Contains(text.ToLower()); } return(true); }; subList = new GUIListBox(new RectTransform(Vector2.One, subHolder.RectTransform)); subTickBoxes = new List <GUITickBox>(); for (int i = 0; i < GameMain.Client.ServerSubmarines.Count; i++) { SubmarineInfo sub = GameMain.Client.ServerSubmarines[i]; if (!sub.IsCampaignCompatible) { continue; } var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), subList.Content.RectTransform) { MinSize = new Point(0, 20) }, style: "ListBoxElement") { ToolTip = sub.Description, UserData = sub }; int buttonSize = (int)(frame.Rect.Height * 0.8f); GUITickBox tickBox = new GUITickBox(new RectTransform(new Vector2(0.8f, 1.0f), frame.RectTransform, Anchor.CenterLeft), ToolBox.LimitString(sub.DisplayName, GUI.Font, subList.Content.Rect.Width - 65)) { UserData = sub, OnSelected = (GUITickBox box) => { GameMain.Client.RequestCampaignSub(box.UserData as SubmarineInfo, box.Selected); return(true); } }; subTickBoxes.Add(tickBox); tickBox.Selected = GameMain.NetLobbyScreen.CampaignSubmarines.Contains(sub); frame.RectTransform.MinSize = new Point(0, tickBox.RectTransform.MinSize.Y); var subTextBlock = tickBox.TextBlock; var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name && s.MD5Hash?.Hash == sub.MD5Hash?.Hash); if (matchingSub == null) { matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name); } if (matchingSub == null) { subTextBlock.TextColor = new Color(subTextBlock.TextColor, 0.5f); frame.ToolTip = TextManager.Get("SubNotFound"); } else if (matchingSub?.MD5Hash == null || matchingSub.MD5Hash?.Hash != sub.MD5Hash?.Hash) { subTextBlock.TextColor = new Color(subTextBlock.TextColor, 0.5f); frame.ToolTip = TextManager.Get("SubDoesntMatch"); } if (!sub.RequiredContentPackagesInstalled) { subTextBlock.TextColor = Color.Lerp(subTextBlock.TextColor, Color.DarkRed, 0.5f); frame.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + frame.RawToolTip; } var classText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight), TextManager.Get($"submarineclass.{sub.SubmarineClass}"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont) { TextColor = subTextBlock.TextColor * 0.8f, ToolTip = subTextBlock.RawToolTip }; } }
private static void UpdateHighlightedListBox(List <MapEntity> highlightedEntities, bool wiringMode) { if (highlightedEntities == null || highlightedEntities.Count < 2) { highlightedListBox = null; return; } if (highlightedListBox != null) { if (GUI.MouseOn == highlightedListBox || highlightedListBox.IsParentOf(GUI.MouseOn)) { return; } if (highlightedEntities.SequenceEqual(highlightedList)) { return; } } highlightedList = highlightedEntities; highlightedListBox = new GUIListBox(new RectTransform(new Point(180, highlightedEntities.Count * 18 + 5), GUI.Canvas) { MaxSize = new Point(int.MaxValue, 256), ScreenSpaceOffset = PlayerInput.MousePosition.ToPoint() + new Point(15) }, style: "GUIToolTip"); foreach (MapEntity entity in highlightedEntities) { var tooltip = string.Empty; if (wiringMode && entity is Item item) { var wire = item.GetComponent <Wire>(); if (wire?.Connections != null) { for (var i = 0; i < wire.Connections.Length; i++) { var conn = wire.Connections[i]; if (conn != null) { string[] tags = { "[item]", "[pin]" }; string[] values = { conn.Item?.Name, conn.Name }; tooltip += TextManager.GetWithVariables("wirelistformat", tags, values); } if (i != wire.Connections.Length - 1) { tooltip += '\n'; } } } } var textBlock = new GUITextBlock(new RectTransform(new Point(highlightedListBox.Content.Rect.Width, 15), highlightedListBox.Content.RectTransform), ToolBox.LimitString(entity.Name, GUI.SmallFont, 140), font: GUI.SmallFont) { ToolTip = tooltip, UserData = entity }; } highlightedListBox.OnSelected = (GUIComponent component, object obj) => { MapEntity entity = obj as MapEntity; if (PlayerInput.IsCtrlDown() && !wiringMode) { if (selectedList.Contains(entity)) { RemoveSelection(entity); } else { AddSelection(entity); } return(true); } SelectEntity(entity); return(true); }; }
public LevelEditorScreen() { cam = new Camera() { MinZoom = 0.01f, MaxZoom = 1.0f }; leftPanel = new GUIFrame(new RectTransform(new Vector2(0.125f, 0.8f), Frame.RectTransform) { MinSize = new Point(150, 0) }); var paddedLeftPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), leftPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.02f, 0.0f) }) { Stretch = true, RelativeSpacing = 0.01f }; paramsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), paddedLeftPanel.RectTransform)); paramsList.OnSelected += (GUIComponent component, object obj) => { selectedParams = obj as LevelGenerationParams; editorContainer.ClearChildren(); SortLevelObjectsList(selectedParams); new SerializableEntityEditor(editorContainer.Content.RectTransform, selectedParams, false, true, elementHeight: 20); return(true); }; var ruinTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.ruinparams"), font: GUI.SubHeadingFont); ruinParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedLeftPanel.RectTransform)); ruinParamsList.OnSelected += (GUIComponent component, object obj) => { var ruinGenerationParams = obj as RuinGenerationParams; editorContainer.ClearChildren(); new SerializableEntityEditor(editorContainer.Content.RectTransform, ruinGenerationParams, false, true, elementHeight: 20); return(true); }; var outpostTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.outpostparams"), font: GUI.SubHeadingFont); GUITextBlock.AutoScaleAndNormalize(ruinTitle, outpostTitle); outpostParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), paddedLeftPanel.RectTransform)); outpostParamsList.OnSelected += (GUIComponent component, object obj) => { var outpostGenerationParams = obj as OutpostGenerationParams; editorContainer.ClearChildren(); var outpostParamsEditor = new SerializableEntityEditor(editorContainer.Content.RectTransform, outpostGenerationParams, false, true, elementHeight: 20); // location type ------------------------- var locationTypeGroup = new GUILayoutGroup(new RectTransform(new Point(editorContainer.Content.Rect.Width, 20)), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true }; new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), locationTypeGroup.RectTransform), TextManager.Get("outpostmoduleallowedlocationtypes"), textAlignment: Alignment.CenterLeft); HashSet <string> availableLocationTypes = new HashSet <string> { "any" }; foreach (LocationType locationType in LocationType.List) { availableLocationTypes.Add(locationType.Identifier); } var locationTypeDropDown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1f), locationTypeGroup.RectTransform), text: string.Join(", ", outpostGenerationParams.AllowedLocationTypes.Select(lt => TextManager.Capitalize(lt)) ?? "any".ToEnumerable()), selectMultiple: true); foreach (string locationType in availableLocationTypes) { locationTypeDropDown.AddItem(TextManager.Capitalize(locationType), locationType); if (outpostGenerationParams.AllowedLocationTypes.Contains(locationType)) { locationTypeDropDown.SelectItem(locationType); } } if (!outpostGenerationParams.AllowedLocationTypes.Any()) { locationTypeDropDown.SelectItem("any"); } locationTypeDropDown.OnSelected += (_, __) => { outpostGenerationParams.SetAllowedLocationTypes(locationTypeDropDown.SelectedDataMultiple.Cast <string>()); locationTypeDropDown.Text = ToolBox.LimitString(locationTypeDropDown.Text, locationTypeDropDown.Font, locationTypeDropDown.Rect.Width); return(true); }; locationTypeGroup.RectTransform.MinSize = new Point(locationTypeGroup.Rect.Width, locationTypeGroup.RectTransform.Children.Max(c => c.MinSize.Y)); outpostParamsEditor.AddCustomContent(locationTypeGroup, 100); // module count ------------------------- var moduleLabel = new GUITextBlock(new RectTransform(new Point(editorContainer.Content.Rect.Width, (int)(70 * GUI.Scale))), TextManager.Get("submarinetype.outpostmodules"), font: GUI.SubHeadingFont); outpostParamsEditor.AddCustomContent(moduleLabel, 100); foreach (KeyValuePair <string, int> moduleCount in outpostGenerationParams.ModuleCounts) { var moduleCountGroup = new GUILayoutGroup(new RectTransform(new Point(editorContainer.Content.Rect.Width, (int)(25 * GUI.Scale))), isHorizontal: true, childAnchor: Anchor.CenterLeft); new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), moduleCountGroup.RectTransform), TextManager.Capitalize(moduleCount.Key), textAlignment: Alignment.CenterLeft); new GUINumberInput(new RectTransform(new Vector2(0.5f, 1f), moduleCountGroup.RectTransform), GUINumberInput.NumberType.Int) { MinValueInt = 0, MaxValueInt = 100, IntValue = moduleCount.Value, OnValueChanged = (numInput) => { outpostGenerationParams.SetModuleCount(moduleCount.Key, numInput.IntValue); if (numInput.IntValue == 0) { outpostParamsList.Select(outpostParamsList.SelectedData); } } }; moduleCountGroup.RectTransform.MinSize = new Point(moduleCountGroup.Rect.Width, moduleCountGroup.RectTransform.Children.Max(c => c.MinSize.Y)); outpostParamsEditor.AddCustomContent(moduleCountGroup, 100); } // add module count ------------------------- var addModuleCountGroup = new GUILayoutGroup(new RectTransform(new Point(editorContainer.Content.Rect.Width, (int)(40 * GUI.Scale))), isHorizontal: true, childAnchor: Anchor.Center); HashSet <string> availableFlags = new HashSet <string>(); foreach (string flag in OutpostGenerationParams.Params.SelectMany(p => p.ModuleCounts.Select(m => m.Key))) { availableFlags.Add(flag); } foreach (var sub in SubmarineInfo.SavedSubmarines) { if (sub.OutpostModuleInfo == null) { continue; } foreach (string flag in sub.OutpostModuleInfo.ModuleFlags) { availableFlags.Add(flag); } } var moduleTypeDropDown = new GUIDropDown(new RectTransform(new Vector2(0.8f, 0.8f), addModuleCountGroup.RectTransform), text: TextManager.Get("leveleditor.addmoduletype")); foreach (string flag in availableFlags) { if (outpostGenerationParams.ModuleCounts.Any(mc => mc.Key.Equals(flag, StringComparison.OrdinalIgnoreCase))) { continue; } moduleTypeDropDown.AddItem(TextManager.Capitalize(flag), flag); } moduleTypeDropDown.OnSelected += (_, userdata) => { outpostGenerationParams.SetModuleCount(userdata as string, 1); outpostParamsList.Select(outpostParamsList.SelectedData); return(true); }; addModuleCountGroup.RectTransform.MinSize = new Point(addModuleCountGroup.Rect.Width, addModuleCountGroup.RectTransform.Children.Max(c => c.MinSize.Y)); outpostParamsEditor.AddCustomContent(addModuleCountGroup, 100); return(true); }; var createLevelObjButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.createlevelobj")) { OnClicked = (btn, obj) => { Wizard.Instance.Create(); return(true); } }; GUITextBlock.AutoScaleAndNormalize(createLevelObjButton.TextBlock); lightingEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.lightingenabled")); cursorLightEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.cursorlightenabled")); new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.reloadtextures")) { OnClicked = (btn, obj) => { Level.Loaded?.ReloadTextures(); return(true); } }; new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform), TextManager.Get("editor.saveall")) { OnClicked = (btn, obj) => { SerializeAll(); return(true); } }; rightPanel = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), Frame.RectTransform, Anchor.TopRight) { MinSize = new Point(450, 0) }); var paddedRightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), rightPanel.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.02f, 0.0f) }) { Stretch = true, RelativeSpacing = 0.01f }; editorContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), paddedRightPanel.RectTransform)); var seedContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), paddedRightPanel.RectTransform), isHorizontal: true); new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), seedContainer.RectTransform), TextManager.Get("leveleditor.levelseed")); seedBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), seedContainer.RectTransform), ToolBox.RandomSeed(8)); new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedRightPanel.RectTransform), TextManager.Get("leveleditor.generate")) { OnClicked = (btn, obj) => { Submarine.Unload(); GameMain.LightManager.ClearLights(); LevelData levelData = LevelData.CreateRandom(seedBox.Text, generationParams: selectedParams); levelData.ForceOutpostGenerationParams = outpostParamsList.SelectedData as OutpostGenerationParams; Level.Generate(levelData, mirror: false); GameMain.LightManager.AddLight(pointerLightSource); cam.Position = new Vector2(Level.Loaded.Size.X / 2, Level.Loaded.Size.Y / 2); foreach (GUITextBlock param in paramsList.Content.Children) { param.TextColor = param.UserData == selectedParams ? GUI.Style.Green : param.Style.TextColor; } seedBox.Deselect(); return(true); } }; new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedRightPanel.RectTransform), TextManager.Get("leveleditor.test")) { OnClicked = (btn, obj) => { if (Level.Loaded?.LevelData == null) { return(false); } GameMain.GameScreen.Select(); var currEntities = Entity.GetEntities().ToList(); if (Submarine.MainSub != null) { var toRemove = Entity.GetEntities().Where(e => e.Submarine == Submarine.MainSub).ToList(); foreach (Entity ent in toRemove) { ent.Remove(); } Submarine.MainSub.Remove(); } //TODO: hacky workaround to check for wrecks and outposts, refactor SubmarineInfo and ContentType at some point var nonPlayerFiles = ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.Wreck).ToList(); nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.Outpost)); nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.OutpostModule)); SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name.Equals(GameMain.Config.QuickStartSubmarineName, StringComparison.InvariantCultureIgnoreCase)); subInfo ??= SubmarineInfo.SavedSubmarines.GetRandom(s => s.IsPlayer && !s.HasTag(SubmarineTag.Shuttle) && !nonPlayerFiles.Any(f => f.Path.CleanUpPath().Equals(s.FilePath.CleanUpPath(), StringComparison.InvariantCultureIgnoreCase))); GameSession gameSession = new GameSession(subInfo, "", GameModePreset.TestMode, null); gameSession.StartRound(Level.Loaded.LevelData); (gameSession.GameMode as TestGameMode).OnRoundEnd = () => { GameMain.LevelEditorScreen.Select(); Submarine.MainSub.Remove(); var toRemove = Entity.GetEntities().Where(e => !currEntities.Contains(e)).ToList(); foreach (Entity ent in toRemove) { ent.Remove(); } Submarine.MainSub = null; }; GameMain.GameSession = gameSession; return(true); } }; bottomPanel = new GUIFrame(new RectTransform(new Vector2(0.75f, 0.22f), Frame.RectTransform, Anchor.BottomLeft) { MaxSize = new Point(GameMain.GraphicsWidth - rightPanel.Rect.Width, 1000) }, style: "GUIFrameBottom"); levelObjectList = new GUIListBox(new RectTransform(new Vector2(0.99f, 0.85f), bottomPanel.RectTransform, Anchor.Center)) { UseGridLayout = true }; levelObjectList.OnSelected += (GUIComponent component, object obj) => { selectedLevelObject = obj as LevelObjectPrefab; CreateLevelObjectEditor(selectedLevelObject); return(true); }; spriteEditDoneButton = new GUIButton(new RectTransform(new Point(200, 30), anchor: Anchor.BottomRight) { AbsoluteOffset = new Point(20, 20) }, TextManager.Get("leveleditor.spriteeditdone")) { OnClicked = (btn, userdata) => { editingSprite = null; return(true); } }; topPanel = new GUIFrame(new RectTransform(new Point(400, 100), GUI.Canvas) { RelativeOffset = new Vector2(leftPanel.RectTransform.RelativeSize.X * 2, 0.0f) }, style: "GUIFrameTop"); }
public override void Draw(SpriteBatch spriteBatch) { if (overlayColor.A > 0) { if (overlaySprite != null) { GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * (overlayColor.A / 255.0f), isFilled: true); float scale = Math.Max(GameMain.GraphicsWidth / overlaySprite.size.X, GameMain.GraphicsHeight / overlaySprite.size.Y); overlaySprite.Draw(spriteBatch, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2, overlayColor, overlaySprite.size / 2, scale: scale); } else { GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), overlayColor, isFilled: true); } if (!string.IsNullOrEmpty(overlayText) && overlayTextColor.A > 0) { var backgroundSprite = GUI.Style.GetComponentStyle("CommandBackground").GetDefaultSprite(); Vector2 centerPos = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2; backgroundSprite.Draw(spriteBatch, centerPos, Color.White * (overlayTextColor.A / 255.0f), origin: backgroundSprite.size / 2, rotate: 0.0f, scale: new Vector2(1.5f, 0.7f) * (GameMain.GraphicsWidth / 3 / backgroundSprite.size.X)); string wrappedText = ToolBox.WrapText(overlayText, GameMain.GraphicsWidth / 3, GUI.Font); Vector2 textSize = GUI.Font.MeasureString(wrappedText); Vector2 textPos = centerPos - textSize / 2; GUI.DrawString(spriteBatch, textPos + Vector2.One, wrappedText, Color.Black * (overlayTextColor.A / 255.0f)); GUI.DrawString(spriteBatch, textPos, wrappedText, overlayTextColor); if (!string.IsNullOrEmpty(overlayTextBottom)) { Vector2 bottomTextPos = centerPos + new Vector2(0.0f, textSize.Y + 30 * GUI.Scale) - GUI.Font.MeasureString(overlayTextBottom) / 2; GUI.DrawString(spriteBatch, bottomTextPos + Vector2.One, overlayTextBottom, Color.Black * (overlayTextColor.A / 255.0f)); GUI.DrawString(spriteBatch, bottomTextPos, overlayTextBottom, overlayTextColor); } } } if (GUI.DisableHUD || GUI.DisableUpperHUD || ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition")) { endRoundButton.Visible = false; if (ReadyCheckButton != null) { ReadyCheckButton.Visible = false; } return; } if (Submarine.MainSub == null) { return; } endRoundButton.Visible = false; var availableTransition = GetAvailableTransition(out _, out Submarine leavingSub); string buttonText = ""; switch (availableTransition) { case TransitionType.ProgressToNextLocation: case TransitionType.ProgressToNextEmptyLocation: if (Level.Loaded.EndOutpost == null || !Level.Loaded.EndOutpost.DockedTo.Contains(leavingSub)) { buttonText = TextManager.GetWithVariable("EnterLocation", "[locationname]", Level.Loaded.EndLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; } break; case TransitionType.LeaveLocation: buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; break; case TransitionType.ReturnToPreviousLocation: case TransitionType.ReturnToPreviousEmptyLocation: if (Level.Loaded.StartOutpost == null || !Level.Loaded.StartOutpost.DockedTo.Contains(leavingSub)) { buttonText = TextManager.GetWithVariable("EnterLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; } break; case TransitionType.None: default: if (Level.Loaded.Type == LevelData.LevelType.Outpost && (Character.Controlled?.Submarine?.Info.Type == SubmarineType.Player || (Character.Controlled?.CurrentHull?.OutpostModuleTags?.Contains("airlock") ?? false))) { buttonText = TextManager.GetWithVariable("LeaveLocation", "[locationname]", Level.Loaded.StartLocation?.Name ?? "[ERROR]"); endRoundButton.Visible = !ForceMapUI && !ShowCampaignUI; } else { endRoundButton.Visible = false; } break; } if (ReadyCheckButton != null) { ReadyCheckButton.Visible = endRoundButton.Visible; } if (endRoundButton.Visible) { if (!AllowedToEndRound()) { buttonText = TextManager.Get("map"); } endRoundButton.Text = ToolBox.LimitString(buttonText, endRoundButton.Font, endRoundButton.Rect.Width - 5); if (endRoundButton.Text != buttonText) { endRoundButton.ToolTip = buttonText; } if (Character.Controlled?.ViewTarget is Item item) { Turret turret = item.GetComponent <Turret>(); endRoundButton.RectTransform.ScreenSpaceOffset = turret == null ? Point.Zero : new Point(0, (int)(turret.UIElementHeight * 1.25f)); } else if (Character.Controlled?.CharacterHealth?.SuicideButton?.Visible ?? false) { endRoundButton.RectTransform.ScreenSpaceOffset = new Point(0, Character.Controlled.CharacterHealth.SuicideButton.Rect.Height); } else { endRoundButton.RectTransform.ScreenSpaceOffset = Point.Zero; } } endRoundButton.DrawManually(spriteBatch); if (this is MultiPlayerCampaign) { ReadyCheckButton?.DrawManually(spriteBatch); } }
private void CreateCharacterFrame(CharacterInfo characterInfo, GUIListBox listBox) { Skill skill = null; Color?jobColor = null; if (characterInfo.Job != null) { skill = characterInfo.Job?.PrimarySkill ?? characterInfo.Job.Skills.OrderByDescending(s => s.Level).FirstOrDefault(); jobColor = characterInfo.Job.Prefab.UIColor; } GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, 55), parent: listBox.Content.RectTransform), "ListBoxElement") { UserData = new Tuple <CharacterInfo, float>(characterInfo, skill != null ? skill.Level : 0.0f) }; GUILayoutGroup mainGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), frame.RectTransform, anchor: Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true }; float portraitWidth = (0.8f * mainGroup.Rect.Height) / mainGroup.Rect.Width; new GUICustomComponent(new RectTransform(new Vector2(portraitWidth, 0.8f), mainGroup.RectTransform), onDraw: (sb, component) => characterInfo.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2())) { CanBeFocused = false }; GUILayoutGroup nameAndJobGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.4f - portraitWidth, 0.8f), mainGroup.RectTransform)); GUITextBlock nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), nameAndJobGroup.RectTransform), characterInfo.Name, textColor: jobColor, textAlignment: Alignment.BottomLeft) { CanBeFocused = false }; nameBlock.Text = ToolBox.LimitString(nameBlock.Text, nameBlock.Font, nameBlock.Rect.Width); GUITextBlock jobBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), nameAndJobGroup.RectTransform), characterInfo.Job.Name, textColor: Color.White, font: GUI.SmallFont, textAlignment: Alignment.TopLeft) { CanBeFocused = false }; jobBlock.Text = ToolBox.LimitString(jobBlock.Text, jobBlock.Font, jobBlock.Rect.Width); float width = 0.6f / 3; if (characterInfo.Job != null) { GUILayoutGroup skillGroup = new GUILayoutGroup(new RectTransform(new Vector2(width, 0.6f), mainGroup.RectTransform), isHorizontal: true); float iconWidth = (float)skillGroup.Rect.Height / skillGroup.Rect.Width; GUIImage skillIcon = new GUIImage(new RectTransform(new Vector2(iconWidth, 1.0f), skillGroup.RectTransform), skill.Icon) { CanBeFocused = false }; if (jobColor.HasValue) { skillIcon.Color = jobColor.Value; } new GUITextBlock(new RectTransform(new Vector2(1.0f - iconWidth, 1.0f), skillGroup.RectTransform), ((int)skill.Level).ToString(), textAlignment: Alignment.CenterLeft) { CanBeFocused = false }; } if (listBox != crewList) { new GUITextBlock(new RectTransform(new Vector2(width, 1.0f), mainGroup.RectTransform), FormatCurrency(characterInfo.Salary), textAlignment: Alignment.Center) { CanBeFocused = false }; } if (listBox == hireableList) { var hireButton = new GUIButton(new RectTransform(new Vector2(width, 0.9f), mainGroup.RectTransform), style: "CrewManagementAddButton") { UserData = characterInfo, Enabled = HasPermission, OnClicked = (b, o) => AddPendingHire(o as CharacterInfo) }; hireButton.OnAddedToGUIUpdateList += (GUIComponent btn) => { if (PendingHires.Count + campaign.CrewManager.GetCharacterInfos().Count() >= CrewManager.MaxCrewSize) { if (btn.Enabled) { btn.ToolTip = TextManager.Get("canthiremorecharacters"); btn.Enabled = false; } } else if (!btn.Enabled) { btn.ToolTip = string.Empty; btn.Enabled = true; } }; } else if (listBox == pendingList) { new GUIButton(new RectTransform(new Vector2(width, 0.9f), mainGroup.RectTransform), style: "CrewManagementRemoveButton") { UserData = characterInfo, Enabled = HasPermission, OnClicked = (b, o) => RemovePendingHire(o as CharacterInfo) }; } else if (listBox == crewList && campaign != null) { var currentCrew = GameMain.GameSession.CrewManager.GetCharacterInfos(); new GUIButton(new RectTransform(new Vector2(width, 0.9f), mainGroup.RectTransform), style: "CrewManagementFireButton") { UserData = characterInfo, //can't fire if there's only one character in the crew Enabled = currentCrew.Contains(characterInfo) && currentCrew.Count() > 1 && HasPermission, OnClicked = (btn, obj) => { var confirmDialog = new GUIMessageBox( TextManager.Get("FireWarningHeader"), TextManager.GetWithVariable("FireWarningText", "[charactername]", ((CharacterInfo)obj).Name), new string[] { TextManager.Get("Yes"), TextManager.Get("No") }); confirmDialog.Buttons[0].UserData = (CharacterInfo)obj; confirmDialog.Buttons[0].OnClicked = FireCharacter; confirmDialog.Buttons[0].OnClicked += confirmDialog.Close; confirmDialog.Buttons[1].OnClicked = confirmDialog.Close; return(true); } }; } }
private bool CreateLoadScreen() { if (characterMode) { ToggleCharacterMode(); } if (wiringMode) { ToggleWiringMode(); } Submarine.RefreshSavedSubs(); int width = 300, height = 400; loadFrame = new GUIFrame(new Rectangle(GameMain.GraphicsWidth / 2 - width / 2, GameMain.GraphicsHeight / 2 - height / 2, width, height), "", null); loadFrame.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f); var subList = new GUIListBox(new Rectangle(0, 0, 0, height - 50), Color.White, "", loadFrame); subList.OnSelected = (GUIComponent selected, object userData) => { var deleteBtn = loadFrame.FindChild("delete") as GUIButton; if (deleteBtn != null) { deleteBtn.Enabled = true; } return(true); }; foreach (Submarine sub in Submarine.SavedSubmarines) { GUITextBlock textBlock = new GUITextBlock( new Rectangle(0, 0, 0, 25), ToolBox.LimitString(sub.Name, GUI.Font, subList.Rect.Width - 80), "", Alignment.Left, Alignment.CenterY | Alignment.Left, subList); textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f); textBlock.UserData = sub; textBlock.ToolTip = sub.FilePath; if (sub.HasTag(SubmarineTag.Shuttle)) { var shuttleText = new GUITextBlock(new Rectangle(0, 0, 0, 25), "Shuttle", "", Alignment.Left, Alignment.CenterY | Alignment.Right, textBlock, false, GUI.SmallFont); shuttleText.TextColor = textBlock.TextColor * 0.8f; shuttleText.ToolTip = textBlock.ToolTip; } } var deleteButton = new GUIButton(new Rectangle(0, 0, 70, 20), "Delete", Alignment.BottomLeft, "", loadFrame); deleteButton.Enabled = false; deleteButton.UserData = "delete"; deleteButton.OnClicked = (btn, userdata) => { if (subList.Selected != null) { TryDeleteSub(subList.Selected.UserData as Submarine); } deleteButton.Enabled = false; return(true); }; var loadButton = new GUIButton(new Rectangle(-90, 0, 80, 20), "Load", Alignment.Right | Alignment.Bottom, "", loadFrame); loadButton.OnClicked = LoadSub; var cancelButton = new GUIButton(new Rectangle(0, 0, 80, 20), "Cancel", Alignment.Right | Alignment.Bottom, "", loadFrame); cancelButton.OnClicked = (GUIButton btn, object userdata) => { loadFrame = null; return(true); }; return(true); }
public void UpdateSubList(IEnumerable <SubmarineInfo> submarines) { List <SubmarineInfo> subsToShow; if (subFilter != CategoryFilter.All) { subsToShow = submarines.Where(s => s.IsCampaignCompatibleIgnoreClass && s.IsVanillaSubmarine() == (subFilter == CategoryFilter.Vanilla)).ToList(); } else { string downloadFolder = Path.GetFullPath(SaveUtil.SubmarineDownloadFolder); subsToShow = submarines.Where(s => s.IsCampaignCompatibleIgnoreClass && Path.GetDirectoryName(Path.GetFullPath(s.FilePath)) != downloadFolder).ToList(); } subsToShow.Sort((s1, s2) => { int p1 = s1.Price > CampaignMode.InitialMoney ? 10 : 0; int p2 = s2.Price > CampaignMode.InitialMoney ? 10 : 0; return(p1.CompareTo(p2) * 100 + s1.Name.CompareTo(s2.Name)); }); subList.ClearChildren(); foreach (SubmarineInfo sub in subsToShow) { var textBlock = new GUITextBlock( new RectTransform(new Vector2(1, 0.1f), subList.Content.RectTransform) { MinSize = new Point(0, 30) }, ToolBox.LimitString(sub.DisplayName, GUI.Font, subList.Rect.Width - 65), style: "ListBoxElement") { ToolTip = sub.Description, UserData = sub }; if (!sub.RequiredContentPackagesInstalled) { textBlock.TextColor = Color.Lerp(textBlock.TextColor, Color.DarkRed, .5f); textBlock.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + textBlock.RawToolTip; } var priceText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textBlock.RectTransform, Anchor.CenterRight), TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", sub.Price)), textAlignment: Alignment.CenterRight, font: GUI.SmallFont) { TextColor = sub.Price > CampaignMode.InitialMoney ? GUI.Style.Red : textBlock.TextColor * 0.8f, ToolTip = textBlock.ToolTip }; #if !DEBUG if (!GameMain.DebugDraw) { if (sub.Price > CampaignMode.InitialMoney || !sub.IsCampaignCompatible) { textBlock.CanBeFocused = false; textBlock.TextColor *= 0.5f; } } #endif } if (SubmarineInfo.SavedSubmarines.Any()) { var validSubs = subsToShow.Where(s => s.IsCampaignCompatible && s.Price <= CampaignMode.InitialMoney).ToList(); if (validSubs.Count > 0) { subList.Select(validSubs[Rand.Int(validSubs.Count)]); } } }
private void CreateItemFrame(PurchasedItem pi, PriceInfo priceInfo, GUIListBox listBox, int width) { GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Rect.Width, 50), listBox.Content.RectTransform), style: "ListBoxElement") { UserData = pi, ToolTip = pi.ItemPrefab.Description }; ScalableFont font = listBox.Rect.Width < 280 ? GUI.SmallFont : GUI.Font; GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Point(listBox.Rect.Width - (pi.Quantity > 0 ? 160 : 120), 25), frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(40, 0), }, pi.ItemPrefab.Name, font: font) { ToolTip = pi.ItemPrefab.Description }; textBlock.Text = ToolBox.LimitString(textBlock.Text, textBlock.Font, textBlock.Rect.Width); Sprite itemIcon = pi.ItemPrefab.InventoryIcon ?? pi.ItemPrefab.sprite; if (itemIcon != null) { GUIImage img = new GUIImage(new RectTransform(new Point(40, 40), frame.RectTransform, Anchor.CenterLeft), itemIcon) { Color = itemIcon == pi.ItemPrefab.InventoryIcon ? pi.ItemPrefab.InventoryIconColor : pi.ItemPrefab.SpriteColor }; img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f); } textBlock = new GUITextBlock(new RectTransform(new Point(60, 25), frame.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(pi.Quantity > 0 ? 70 : 25, 0) }, priceInfo.BuyPrice.ToString(), font: font, textAlignment: Alignment.CenterRight) { ToolTip = pi.ItemPrefab.Description }; //If its the store menu, quantity will always be 0 if (pi.Quantity > 0) { var amountInput = new GUINumberInput(new RectTransform(new Point(50, 40), frame.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(20, 0) }, GUINumberInput.NumberType.Int) { MinValueInt = 0, MaxValueInt = 1000, UserData = pi, IntValue = pi.Quantity }; amountInput.OnValueChanged += (numberInput) => { PurchasedItem purchasedItem = numberInput.UserData as PurchasedItem; //Attempting to buy if (numberInput.IntValue > purchasedItem.Quantity) { int quantity = numberInput.IntValue - purchasedItem.Quantity; //Cap the numberbox based on the amount we can afford. quantity = Campaign.Money <= 0 ? 0 : Math.Min((int)(Campaign.Money / (float)priceInfo.BuyPrice), quantity); for (int i = 0; i < quantity; i++) { BuyItem(numberInput, purchasedItem); } numberInput.IntValue = purchasedItem.Quantity; } //Attempting to sell else { int quantity = purchasedItem.Quantity - numberInput.IntValue; for (int i = 0; i < quantity; i++) { SellItem(numberInput, purchasedItem); } } }; } }
public GUIComponent CreateInfoFrame(GUIFrame frame, bool returnParent, Sprite permissionIcon = null) { var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.874f, 0.58f), frame.RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.05f) }) { RelativeSpacing = 0.05f //Stretch = true }; var headerArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.322f), paddedFrame.RectTransform), isHorizontal: true); new GUICustomComponent(new RectTransform(new Vector2(0.425f, 1.0f), headerArea.RectTransform), onDraw: (sb, component) => DrawInfoFrameCharacterIcon(sb, component.Rect)); ScalableFont font = paddedFrame.Rect.Width < 280 ? GUI.SmallFont : GUI.Font; var headerTextArea = new GUILayoutGroup(new RectTransform(new Vector2(0.575f, 1.0f), headerArea.RectTransform)) { RelativeSpacing = 0.02f, Stretch = true }; Color?nameColor = null; if (Job != null) { nameColor = Job.Prefab.UIColor; } GUITextBlock characterNameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), ToolBox.LimitString(Name, GUI.Font, headerTextArea.Rect.Width), textColor: nameColor, font: GUI.Font) { ForceUpperCase = true, Padding = Vector4.Zero }; if (permissionIcon != null) { Point iconSize = permissionIcon.SourceRect.Size; int iconWidth = (int)((float)characterNameBlock.Rect.Height / iconSize.Y * iconSize.X); new GUIImage(new RectTransform(new Point(iconWidth, characterNameBlock.Rect.Height), characterNameBlock.RectTransform) { AbsoluteOffset = new Point(-iconWidth - 2, 0) }, permissionIcon) { IgnoreLayoutGroups = true }; } if (Job != null) { new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), Job.Name, textColor: Job.Prefab.UIColor, font: font) { Padding = Vector4.Zero }; } if (personalityTrait != null) { new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), TextManager.Get("personalitytrait." + personalityTrait.Name.Replace(" ", ""))), font: font) { Padding = Vector4.Zero }; } if (Job != null && (Character == null || !Character.IsDead)) { var skillsArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.63f), paddedFrame.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter)) { Stretch = true }; var skills = Job.Skills; skills.Sort((s1, s2) => - s1.Level.CompareTo(s2.Level)); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillsArea.RectTransform), TextManager.AddPunctuation(':', TextManager.Get("skills"), string.Empty), font: font) { Padding = Vector4.Zero }; foreach (Skill skill in skills) { Color textColor = Color.White * (0.5f + skill.Level / 200.0f); var skillName = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), skillsArea.RectTransform), TextManager.Get("SkillName." + skill.Identifier), textColor: textColor, font: font) { Padding = Vector4.Zero }; float modifiedSkillLevel = skill.Level; if (Character != null) { modifiedSkillLevel = Character.GetSkillLevel(skill.Identifier); } if (!MathUtils.NearlyEqual(MathF.Round(modifiedSkillLevel), MathF.Round(skill.Level))) { int skillChange = (int)MathF.Round(modifiedSkillLevel - skill.Level); string changeText = $"{(skillChange > 0 ? "+" : "") + skillChange}"; new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), skillName.RectTransform), $"{(int)skill.Level} ({changeText})", textColor: textColor, font: font, textAlignment: Alignment.CenterRight); } else { new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), skillName.RectTransform), ((int)skill.Level).ToString(), textColor: textColor, font: font, textAlignment: Alignment.CenterRight); } } } else if (Character != null && Character.IsDead) { var deadArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.63f), paddedFrame.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter)) { Stretch = true }; string deadDescription = TextManager.AddPunctuation(':', TextManager.Get("deceased") + "\n" + Character.CauseOfDeath.Affliction?.CauseOfDeathDescription ?? TextManager.AddPunctuation(':', TextManager.Get("CauseOfDeath"), TextManager.Get("CauseOfDeath." + Character.CauseOfDeath.Type.ToString()))); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), deadArea.RectTransform), deadDescription, textColor: GUI.Style.Red, font: font, textAlignment: Alignment.TopLeft) { Padding = Vector4.Zero }; } if (returnParent) { return(frame); } else { return(paddedFrame); } }
private bool SelectSaveFile(GUIComponent component, object obj) { string fileName = (string)obj; XDocument doc = SaveUtil.LoadGameSessionDoc(fileName); if (doc?.Root == null) { DebugConsole.ThrowError("Error loading save file \"" + fileName + "\". The file may be corrupted."); return(false); } loadGameButton.Enabled = SaveUtil.IsSaveFileCompatible(doc); RemoveSaveFrame(); string subName = doc.Root.GetAttributeString("submarine", ""); string saveTime = doc.Root.GetAttributeString("savetime", "unknown"); if (long.TryParse(saveTime, out long unixTime)) { DateTime time = ToolBox.Epoch.ToDateTime(unixTime); saveTime = time.ToString(); } string mapseed = doc.Root.GetAttributeString("mapseed", "unknown"); var saveFileFrame = new GUIFrame(new RectTransform(new Vector2(0.45f, 0.6f), loadGameContainer.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.1f) }, style: "InnerFrame") { UserData = "savefileframe" }; var titleText = new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.2f), saveFileFrame.RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0, 0.05f) }, Path.GetFileNameWithoutExtension(fileName), font: GUI.LargeFont, textAlignment: Alignment.Center); titleText.Text = ToolBox.LimitString(titleText.Text, titleText.Font, titleText.Rect.Width); var layoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.5f), saveFileFrame.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0, 0.1f) }); new GUITextBlock(new RectTransform(new Vector2(1, 0), layoutGroup.RectTransform), $"{TextManager.Get("Submarine")} : {subName}", font: GUI.SmallFont); new GUITextBlock(new RectTransform(new Vector2(1, 0), layoutGroup.RectTransform), $"{TextManager.Get("LastSaved")} : {saveTime}", font: GUI.SmallFont); new GUITextBlock(new RectTransform(new Vector2(1, 0), layoutGroup.RectTransform), $"{TextManager.Get("MapSeed")} : {mapseed}", font: GUI.SmallFont); new GUIButton(new RectTransform(new Vector2(0.4f, 0.15f), saveFileFrame.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0, 0.1f) }, TextManager.Get("Delete"), style: "GUIButtonSmall") { UserData = fileName, OnClicked = DeleteSave }; return(true); }