38f1ddb...178a853: v0.8.9.1, removed content folder
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Tutorials;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -14,11 +15,20 @@ namespace Barotrauma
|
||||
private GUIListBox saveList;
|
||||
|
||||
private GUITextBox saveNameBox, seedBox;
|
||||
private GUITickBox contextualTutorialBox;
|
||||
|
||||
private GUIButton loadGameButton;
|
||||
|
||||
public Action<Submarine, string, string> StartNewGame;
|
||||
public Action<string> LoadGame;
|
||||
public bool TutorialSelected
|
||||
{
|
||||
get
|
||||
{
|
||||
if (contextualTutorialBox == null) return false;
|
||||
return contextualTutorialBox.Selected;
|
||||
}
|
||||
}
|
||||
|
||||
private bool isMultiplayer;
|
||||
|
||||
@@ -27,84 +37,108 @@ namespace Barotrauma
|
||||
this.isMultiplayer = isMultiplayer;
|
||||
this.newGameContainer = newGameContainer;
|
||||
this.loadGameContainer = loadGameContainer;
|
||||
|
||||
var columnContainer = new GUILayoutGroup(new RectTransform(Vector2.One, newGameContainer.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 0, 0, 30), TextManager.Get("SelectedSub") + ":", null, null, Alignment.Left, "", newGameContainer);
|
||||
subList = new GUIListBox(new Rectangle(0, 30, 230, newGameContainer.Rect.Height - 100), "", newGameContainer);
|
||||
var leftColumn = new GUILayoutGroup(new RectTransform(Vector2.One, columnContainer.RectTransform))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
var rightColumn = new GUILayoutGroup(new RectTransform(Vector2.One, columnContainer.RectTransform))
|
||||
{
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
// New game left side
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), leftColumn.RectTransform), TextManager.Get("SelectedSub") + ":", textAlignment: Alignment.BottomLeft);
|
||||
subList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.65f), leftColumn.RectTransform));
|
||||
|
||||
UpdateSubList();
|
||||
|
||||
new GUITextBlock(new Rectangle((int)(subList.Rect.Width + 20), 0, 100, 20),
|
||||
TextManager.Get("SaveName") + ": ", "", Alignment.Left, Alignment.Left, newGameContainer);
|
||||
// New game right side
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), rightColumn.RectTransform), TextManager.Get("SaveName") + ":", textAlignment: Alignment.BottomLeft);
|
||||
saveNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.1f), rightColumn.RectTransform), string.Empty);
|
||||
|
||||
saveNameBox = new GUITextBox(new Rectangle((int)(subList.Rect.Width + 30), 30, 180, 20),
|
||||
Alignment.TopLeft, "", newGameContainer);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), rightColumn.RectTransform), TextManager.Get("MapSeed") + ":", textAlignment: Alignment.BottomLeft);
|
||||
seedBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.1f), rightColumn.RectTransform), ToolBox.RandomSeed(8));
|
||||
|
||||
new GUITextBlock(new Rectangle((int)(subList.Rect.Width + 20), 60, 100, 20),
|
||||
TextManager.Get("MapSeed") + ": ", "", Alignment.Left, Alignment.Left, newGameContainer);
|
||||
|
||||
seedBox = new GUITextBox(new Rectangle((int)(subList.Rect.Width + 30), 90, 180, 20),
|
||||
Alignment.TopLeft, "", newGameContainer);
|
||||
seedBox.Text = ToolBox.RandomSeed(8);
|
||||
|
||||
var startButton = new GUIButton(new Rectangle(0, 0, 100, 30), TextManager.Get("StartCampaignButton"), Alignment.BottomRight, "", newGameContainer);
|
||||
startButton.OnClicked = (GUIButton btn, object userData) =>
|
||||
if (!isMultiplayer)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(saveNameBox.Text))
|
||||
{
|
||||
saveNameBox.Flash(Color.Red);
|
||||
return false;
|
||||
}
|
||||
|
||||
Submarine selectedSub = subList.SelectedData as Submarine;
|
||||
if (selectedSub == null) return false;
|
||||
|
||||
if (string.IsNullOrEmpty(selectedSub.MD5Hash.Hash))
|
||||
{
|
||||
((GUITextBlock)subList.Selected).TextColor = Color.DarkRed * 0.8f;
|
||||
subList.Selected.CanBeFocused = false;
|
||||
subList.Deselect();
|
||||
return false;
|
||||
}
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), rightColumn.RectTransform), "Tutorial active" + ":", textAlignment: Alignment.BottomLeft);
|
||||
contextualTutorialBox = new GUITickBox(new RectTransform(new Point(30, 30), rightColumn.RectTransform), string.Empty);
|
||||
UpdateTutorialSelection();
|
||||
}
|
||||
|
||||
string savePath = SaveUtil.CreateSavePath(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer, saveNameBox.Text);
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !selectedSub.CompatibleContentPackages.Contains(GameMain.SelectedPackage.Name))
|
||||
var startButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.13f), rightColumn.RectTransform, Anchor.BottomRight), TextManager.Get("StartCampaignButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
OnClicked = (GUIButton btn, object userData) =>
|
||||
{
|
||||
if (!selectedSub.CompatibleContentPackages.Contains(GameMain.SelectedPackage.Name))
|
||||
if (string.IsNullOrWhiteSpace(saveNameBox.Text))
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ContentPackageMismatch"),
|
||||
TextManager.Get("ContentPackageMismatchWarning")
|
||||
.Replace("[selectedcontentpackage]", GameMain.SelectedPackage.Name),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
msgBox.Buttons[0].OnClicked = msgBox.Close;
|
||||
msgBox.Buttons[0].OnClicked += (button, obj) =>
|
||||
{
|
||||
if (GUIMessageBox.MessageBoxes.Count == 0) StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text);
|
||||
return true;
|
||||
};
|
||||
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
}
|
||||
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle))
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ShuttleSelected"),
|
||||
TextManager.Get("ShuttleWarning"),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (button, obj) => { StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text); return true; };
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
saveNameBox.Flash(Color.Red);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text);
|
||||
}
|
||||
|
||||
return true;
|
||||
Submarine selectedSub = subList.SelectedData as Submarine;
|
||||
if (selectedSub == null) return false;
|
||||
|
||||
if (string.IsNullOrEmpty(selectedSub.MD5Hash.Hash))
|
||||
{
|
||||
((GUITextBlock)subList.SelectedComponent).TextColor = Color.DarkRed * 0.8f;
|
||||
subList.SelectedComponent.CanBeFocused = false;
|
||||
subList.Deselect();
|
||||
return false;
|
||||
}
|
||||
|
||||
string savePath = SaveUtil.CreateSavePath(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer, saveNameBox.Text);
|
||||
bool hasRequiredContentPackages = selectedSub.RequiredContentPackages.All(cp => GameMain.SelectedPackages.Any(cp2 => cp2.Name == cp));
|
||||
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
||||
{
|
||||
if (!hasRequiredContentPackages)
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ContentPackageMismatch"),
|
||||
TextManager.Get("ContentPackageMismatchWarning")
|
||||
.Replace("[requiredcontentpackages]", string.Join(", ", selectedSub.RequiredContentPackages)),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
msgBox.Buttons[0].OnClicked = msgBox.Close;
|
||||
msgBox.Buttons[0].OnClicked += (button, obj) =>
|
||||
{
|
||||
if (GUIMessageBox.MessageBoxes.Count == 0) StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text);
|
||||
return true;
|
||||
};
|
||||
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
}
|
||||
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle))
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ShuttleSelected"),
|
||||
TextManager.Get("ShuttleWarning"),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (button, obj) => { StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text); return true; };
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
UpdateLoadMenu();
|
||||
@@ -118,41 +152,63 @@ namespace Barotrauma
|
||||
|
||||
public void UpdateSubList()
|
||||
{
|
||||
#if DEBUG
|
||||
var subsToShow = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus));
|
||||
#else
|
||||
var subsToShow = Submarine.SavedSubmarines;
|
||||
#endif
|
||||
|
||||
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)
|
||||
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: "?")
|
||||
{
|
||||
Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f),
|
||||
ToolTip = sub.Description,
|
||||
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 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;
|
||||
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)]);
|
||||
}
|
||||
|
||||
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, 400);
|
||||
((Submarine)userdata).CreatePreviewWindow(msgBox.InnerFrame);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
if (Submarine.SavedSubmarines.Any()) subList.Select(Submarine.SavedSubmarines.First());
|
||||
}
|
||||
|
||||
public void UpdateLoadMenu()
|
||||
@@ -160,31 +216,86 @@ namespace Barotrauma
|
||||
loadGameContainer.ClearChildren();
|
||||
|
||||
string[] saveFiles = SaveUtil.GetSaveFiles(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer);
|
||||
|
||||
saveList = new GUIListBox(new Rectangle(0, 0, 200, loadGameContainer.Rect.Height - 80), Color.White, "", loadGameContainer);
|
||||
saveList.OnSelected = SelectSaveFile;
|
||||
|
||||
saveList = new GUIListBox(new RectTransform(new Vector2(0.5f, 1.0f), loadGameContainer.RectTransform, Anchor.CenterLeft))
|
||||
{
|
||||
OnSelected = SelectSaveFile
|
||||
};
|
||||
|
||||
foreach (string saveFile in saveFiles)
|
||||
{
|
||||
GUITextBlock textBlock = new GUITextBlock(
|
||||
new Rectangle(0, 0, 0, 25),
|
||||
Path.GetFileNameWithoutExtension(saveFile),
|
||||
"ListBoxElement",
|
||||
Alignment.Left,
|
||||
Alignment.Left,
|
||||
saveList);
|
||||
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
|
||||
textBlock.UserData = saveFile;
|
||||
XDocument doc = SaveUtil.LoadGameSessionDoc(saveFile);
|
||||
var saveFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), saveList.Content.RectTransform), style: "ListBoxElement")
|
||||
{
|
||||
UserData = saveFile
|
||||
};
|
||||
|
||||
var nameText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), saveFrame.RectTransform),
|
||||
text: Path.GetFileNameWithoutExtension(saveFile));
|
||||
if (doc?.Root == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error loading save file \"" + saveFile + "\". The file may be corrupted.");
|
||||
nameText.Color = Color.Red;
|
||||
continue;
|
||||
}
|
||||
|
||||
string submarineName = doc.Root.GetAttributeString("submarine", "");
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), saveFrame.RectTransform, Anchor.BottomLeft),
|
||||
text: submarineName, font: GUI.SmallFont)
|
||||
{
|
||||
UserData = saveFile
|
||||
};
|
||||
|
||||
string saveTime = doc.Root.GetAttributeString("savetime", "");
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), saveFrame.RectTransform),
|
||||
text: saveTime, textAlignment: Alignment.Right, font: GUI.SmallFont)
|
||||
{
|
||||
UserData = saveFile
|
||||
};
|
||||
}
|
||||
|
||||
loadGameButton = new GUIButton(new Rectangle(0, 0, 100, 30), TextManager.Get("LoadButton"), Alignment.Right | Alignment.Bottom, "", loadGameContainer);
|
||||
loadGameButton.OnClicked = (btn, obj) =>
|
||||
saveList.Content.RectTransform.SortChildren((c1, c2) =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(saveList.SelectedData as string)) return false;
|
||||
LoadGame?.Invoke(saveList.SelectedData as string);
|
||||
return true;
|
||||
string file1 = c1.GUIComponent.UserData as string;
|
||||
string file2 = c2.GUIComponent.UserData as string;
|
||||
DateTime file1WriteTime = DateTime.MinValue;
|
||||
DateTime file2WriteTime = DateTime.MinValue;
|
||||
try
|
||||
{
|
||||
file1WriteTime = File.GetLastWriteTime(file1);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//do nothing - DateTime.MinValue will be used and the element will get sorted at the bottom of the list
|
||||
};
|
||||
try
|
||||
{
|
||||
file2WriteTime = File.GetLastWriteTime(file2);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//do nothing - DateTime.MinValue will be used and the element will get sorted at the bottom of the list
|
||||
};
|
||||
return file2WriteTime.CompareTo(file1WriteTime);
|
||||
});
|
||||
|
||||
loadGameButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.12f), loadGameContainer.RectTransform, Anchor.BottomRight), TextManager.Get("LoadButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(saveList.SelectedData as string)) return false;
|
||||
LoadGame?.Invoke(saveList.SelectedData as string);
|
||||
return true;
|
||||
},
|
||||
Enabled = false
|
||||
};
|
||||
loadGameButton.Enabled = false;
|
||||
}
|
||||
|
||||
public void UpdateTutorialSelection()
|
||||
{
|
||||
if (isMultiplayer) return;
|
||||
Tutorial contextualTutorial = Tutorial.Tutorials.Find(t => t is ContextualTutorial);
|
||||
contextualTutorialBox.Selected = (contextualTutorial != null) ? !GameMain.Config.CompletedTutorialNames.Contains(contextualTutorial.Name) : true;
|
||||
}
|
||||
|
||||
private bool SelectSaveFile(GUIComponent component, object obj)
|
||||
@@ -192,7 +303,6 @@ namespace Barotrauma
|
||||
string fileName = (string)obj;
|
||||
|
||||
XDocument doc = SaveUtil.LoadGameSessionDoc(fileName);
|
||||
|
||||
if (doc == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error loading save file \"" + fileName + "\". The file may be corrupted.");
|
||||
@@ -207,24 +317,37 @@ namespace Barotrauma
|
||||
string saveTime = doc.Root.GetAttributeString("savetime", "unknown");
|
||||
string mapseed = doc.Root.GetAttributeString("mapseed", "unknown");
|
||||
|
||||
GUIFrame saveFileFrame = new GUIFrame(new Rectangle((int)(saveList.Rect.Width + 20), 0, 200, 230), Color.Black * 0.4f, "", loadGameContainer);
|
||||
saveFileFrame.UserData = "savefileframe";
|
||||
saveFileFrame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
|
||||
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"
|
||||
};
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 0, 0, 20), Path.GetFileNameWithoutExtension(fileName), "", Alignment.TopLeft, Alignment.TopLeft, saveFileFrame, false, GUI.LargeFont);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1, 0.2f), saveFileFrame.RectTransform, Anchor.TopCenter)
|
||||
{
|
||||
RelativeOffset = new Vector2(0, 0.05f)
|
||||
},
|
||||
Path.GetFileNameWithoutExtension(fileName), font: GUI.LargeFont, textAlignment: Alignment.Center);
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 35, 0, 20), TextManager.Get("Submarine") + ":", "", saveFileFrame).Font = GUI.SmallFont;
|
||||
new GUITextBlock(new Rectangle(15, 52, 0, 20), subName, "", saveFileFrame).Font = GUI.SmallFont;
|
||||
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 Rectangle(0, 70, 0, 20), TextManager.Get("LastSaved") + ":", "", saveFileFrame).Font = GUI.SmallFont;
|
||||
new GUITextBlock(new Rectangle(15, 85, 0, 20), saveTime, "", saveFileFrame).Font = GUI.SmallFont;
|
||||
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 GUITextBlock(new Rectangle(0, 105, 0, 20), TextManager.Get("MapSeed") + ":", "", saveFileFrame).Font = GUI.SmallFont;
|
||||
new GUITextBlock(new Rectangle(15, 120, 0, 20), mapseed, "", saveFileFrame).Font = GUI.SmallFont;
|
||||
|
||||
var deleteSaveButton = new GUIButton(new Rectangle(0, 0, 100, 20), TextManager.Get("Delete"), Alignment.BottomCenter, "", saveFileFrame);
|
||||
deleteSaveButton.UserData = fileName;
|
||||
deleteSaveButton.OnClicked = DeleteSave;
|
||||
new GUIButton(new RectTransform(new Vector2(0.4f, 0.15f), saveFileFrame.RectTransform, Anchor.BottomCenter)
|
||||
{
|
||||
RelativeOffset = new Vector2(0, 0.1f)
|
||||
}, TextManager.Get("Delete"))
|
||||
{
|
||||
UserData = fileName,
|
||||
OnClicked = DeleteSave
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -245,7 +368,7 @@ namespace Barotrauma
|
||||
private void RemoveSaveFrame()
|
||||
{
|
||||
GUIComponent prevFrame = null;
|
||||
foreach (GUIComponent child in loadGameContainer.children)
|
||||
foreach (GUIComponent child in loadGameContainer.Children)
|
||||
{
|
||||
if (child.UserData as string != "savefileframe") continue;
|
||||
|
||||
|
||||
@@ -9,279 +9,532 @@ namespace Barotrauma
|
||||
{
|
||||
class CampaignUI
|
||||
{
|
||||
public enum Tab { Crew = 0, Map = 1, Store = 2 }
|
||||
|
||||
public enum Tab { Map, Crew, Store }
|
||||
private Tab selectedTab;
|
||||
private GUIFrame[] tabs;
|
||||
|
||||
private GUIButton startButton;
|
||||
|
||||
private GUIFrame topPanel;
|
||||
|
||||
private Tab selectedTab;
|
||||
private GUIListBox characterList;
|
||||
|
||||
private GUIListBox characterList, hireList;
|
||||
|
||||
private GUIListBox selectedItemList;
|
||||
private GUIListBox myItemList;
|
||||
private GUIListBox storeItemList;
|
||||
|
||||
private CampaignMode campaign;
|
||||
private GUIComponent missionPanel;
|
||||
private GUIComponent selectedLocationInfo;
|
||||
private GUIListBox selectedMissionInfo;
|
||||
|
||||
private GUIFrame characterPreviewFrame;
|
||||
|
||||
private Level selectedLevel;
|
||||
|
||||
private float mapZoom = 3.0f;
|
||||
private List<GUIButton> tabButtons = new List<GUIButton>();
|
||||
private List<GUIButton> itemCategoryButtons = new List<GUIButton>();
|
||||
private List<GUITickBox> missionTickBoxes = new List<GUITickBox>();
|
||||
|
||||
public Action StartRound;
|
||||
public Action<Location, LocationConnection> OnLocationSelected;
|
||||
|
||||
public Level SelectedLevel
|
||||
{
|
||||
get { return selectedLevel; }
|
||||
}
|
||||
public Level SelectedLevel { get; private set; }
|
||||
|
||||
public GUIComponent MapContainer { get; private set; }
|
||||
|
||||
public CampaignMode Campaign { get; }
|
||||
|
||||
public CampaignMode Campaign
|
||||
{
|
||||
get { return campaign; }
|
||||
}
|
||||
|
||||
public CampaignUI(CampaignMode campaign, GUIFrame container)
|
||||
{
|
||||
this.campaign = campaign;
|
||||
this.Campaign = campaign;
|
||||
|
||||
tabs = new GUIFrame[3];
|
||||
|
||||
tabs[(int)Tab.Crew] = new GUIFrame(Rectangle.Empty, null, container);
|
||||
tabs[(int)Tab.Crew].Padding = Vector4.One * 10.0f;
|
||||
|
||||
//new GUITextBlock(new Rectangle(0, 0, 200, 25), "Crew:", Color.Transparent, Color.White, Alignment.Left, "", bottomPanel[(int)PanelTab.Crew]);
|
||||
|
||||
int crewColumnWidth = Math.Min(300, (container.Rect.Width - 40) / 2);
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 0, 100, 20), TextManager.Get("Crew") + ":", "", tabs[(int)Tab.Crew], GUI.LargeFont);
|
||||
characterList = new GUIListBox(new Rectangle(0, 40, crewColumnWidth, 0), "", tabs[(int)Tab.Crew]);
|
||||
characterList.OnSelected = SelectCharacter;
|
||||
|
||||
hireList = new GUIListBox(new Rectangle(0, 40, 300, 0), "", Alignment.Right, tabs[(int)Tab.Crew]);
|
||||
new GUITextBlock(new Rectangle(0, 0, 300, 20), TextManager.Get("Hire") + ":", "", Alignment.Right, Alignment.Left, tabs[(int)Tab.Crew], false, GUI.LargeFont);
|
||||
hireList.OnSelected = SelectCharacter;
|
||||
|
||||
//---------------------------------------
|
||||
|
||||
tabs[(int)Tab.Map] = new GUIFrame(Rectangle.Empty, null, container);
|
||||
tabs[(int)Tab.Map].Padding = Vector4.One * 10.0f;
|
||||
|
||||
if (GameMain.Client == null)
|
||||
MapContainer = new GUICustomComponent(new RectTransform(Vector2.One, container.RectTransform), DrawMap, UpdateMap);
|
||||
new GUIFrame(new RectTransform(Vector2.One, MapContainer.RectTransform), style: "InnerGlow", color: Color.Black * 0.9f)
|
||||
{
|
||||
startButton = new GUIButton(new Rectangle(0, 0, 100, 30), TextManager.Get("StartCampaignButton"),
|
||||
Alignment.BottomRight, "", tabs[(int)Tab.Map]);
|
||||
startButton.OnClicked = (GUIButton btn, object obj) => { StartRound?.Invoke(); return true; };
|
||||
startButton.Enabled = false;
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
// top panel -------------------------------------------------------------------------
|
||||
|
||||
topPanel = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.15f), container.RectTransform, Anchor.TopCenter), style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var topPanelContent = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), topPanel.RectTransform, Anchor.BottomCenter), style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
var outpostBtn = new GUIButton(new RectTransform(new Vector2(0.15f, 0.55f), topPanelContent.RectTransform),
|
||||
TextManager.Get("Outpost"), textAlignment: Alignment.Center, style: "GUISlopedHeader")
|
||||
{
|
||||
OnClicked = (btn, userdata) => { SelectTab(Tab.Map); return true; }
|
||||
};
|
||||
outpostBtn.TextBlock.Font = GUI.LargeFont;
|
||||
outpostBtn.TextBlock.AutoScale = true;
|
||||
|
||||
var tabButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 0.3f), topPanelContent.RectTransform, Anchor.BottomLeft), isHorizontal: true);
|
||||
|
||||
int i = 0;
|
||||
var tabValues = Enum.GetValues(typeof(Tab));
|
||||
foreach (Tab tab in tabValues)
|
||||
{
|
||||
var tabButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), tabButtonContainer.RectTransform),
|
||||
TextManager.Get(tab.ToString()),
|
||||
textAlignment: Alignment.Center,
|
||||
style: i == 0 ? "GUISlopedTabButtonLeft" : (i == tabValues.Length - 1 ? "GUISlopedTabButtonRight" : "GUISlopedTabButtonMid"))
|
||||
{
|
||||
UserData = tab,
|
||||
OnClicked = (btn, userdata) => { SelectTab((Tab)userdata); return true; },
|
||||
Selected = tab == Tab.Map
|
||||
};
|
||||
var buttonSprite = tabButton.Style.Sprites[GUIComponent.ComponentState.None][0];
|
||||
tabButton.RectTransform.MaxSize = new Point(
|
||||
(int)(tabButton.Rect.Height * (buttonSprite.Sprite.size.X / buttonSprite.Sprite.size.Y)), int.MaxValue);
|
||||
tabButtons.Add(tabButton);
|
||||
tabButton.Font = GUI.LargeFont;
|
||||
i++;
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
// crew tab -------------------------------------------------------------------------
|
||||
|
||||
tabs[(int)Tab.Store] = new GUIFrame(Rectangle.Empty, null, container);
|
||||
tabs[(int)Tab.Store].Padding = Vector4.One * 10.0f;
|
||||
tabs = new GUIFrame[Enum.GetValues(typeof(Tab)).Length];
|
||||
tabs[(int)Tab.Crew] = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.7f), container.RectTransform, Anchor.TopLeft)
|
||||
{
|
||||
RelativeOffset = new Vector2(0.0f, topPanel.RectTransform.RelativeSize.Y)
|
||||
}, color: Color.Black * 0.7f);
|
||||
new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), tabs[(int)Tab.Crew].RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black * 0.7f)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
int sellColumnWidth = (tabs[(int)Tab.Store].Rect.Width - 40) / 2 - 20;
|
||||
characterList = new GUIListBox(new RectTransform(new Vector2(0.9f, 0.95f), tabs[(int)Tab.Crew].RectTransform, Anchor.Center))
|
||||
{
|
||||
OnSelected = SelectCharacter
|
||||
};
|
||||
|
||||
selectedItemList = new GUIListBox(new Rectangle(0, 30, sellColumnWidth, tabs[(int)Tab.Store].Rect.Height - 80), Color.White * 0.7f, "", tabs[(int)Tab.Store]);
|
||||
//selectedItemList.OnSelected = SellItem;
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), characterList.Content.RectTransform),
|
||||
TextManager.Get("CampaignMenuCrew"), font: GUI.LargeFont)
|
||||
{
|
||||
UserData = "mycrew",
|
||||
CanBeFocused = false,
|
||||
AutoScale = true
|
||||
};
|
||||
if (campaign is SinglePlayerCampaign)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), characterList.Content.RectTransform),
|
||||
TextManager.Get("CampaignMenuHireable"), font: GUI.LargeFont)
|
||||
{
|
||||
UserData = "hire",
|
||||
CanBeFocused = false,
|
||||
AutoScale = true
|
||||
};
|
||||
}
|
||||
|
||||
storeItemList = new GUIListBox(new Rectangle(0, 30, sellColumnWidth, tabs[(int)Tab.Store].Rect.Height - 80), Color.White * 0.7f, Alignment.TopRight, "", tabs[(int)Tab.Store]);
|
||||
storeItemList.OnSelected = BuyItem;
|
||||
|
||||
int x = storeItemList.Rect.X - storeItemList.Parent.Rect.X;
|
||||
// store tab -------------------------------------------------------------------------
|
||||
|
||||
tabs[(int)Tab.Store] = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.7f), container.RectTransform, Anchor.TopLeft)
|
||||
{
|
||||
RelativeOffset = new Vector2(0.1f, topPanel.RectTransform.RelativeSize.Y)
|
||||
}, color: Color.Black * 0.7f);
|
||||
new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), tabs[(int)Tab.Store].RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black * 0.7f)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
List<MapEntityCategory> itemCategories = Enum.GetValues(typeof(MapEntityCategory)).Cast<MapEntityCategory>().ToList();
|
||||
//don't show categories with no buyable items
|
||||
itemCategories.RemoveAll(c => !MapEntityPrefab.List.Any(ep => ep.Price > 0.0f && ep.Category.HasFlag(c)));
|
||||
itemCategories.RemoveAll(c =>
|
||||
!MapEntityPrefab.List.Any(ep => ep.Category.HasFlag(c) && (ep is ItemPrefab) && ((ItemPrefab)ep).CanBeBought));
|
||||
|
||||
int buttonWidth = Math.Min(sellColumnWidth / itemCategories.Count, 100);
|
||||
var storeContent = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), tabs[(int)Tab.Store].RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), storeContent.RectTransform), "", font: GUI.LargeFont)
|
||||
{
|
||||
TextGetter = GetMoney
|
||||
};
|
||||
|
||||
var storeItemLists = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.8f), storeContent.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
myItemList = new GUIListBox(new RectTransform(new Vector2(0.5f, 1.0f), storeItemLists.RectTransform));
|
||||
storeItemList = new GUIListBox(new RectTransform(new Vector2(0.5f, 1.0f), storeItemLists.RectTransform))
|
||||
{
|
||||
OnSelected = BuyItem
|
||||
};
|
||||
|
||||
var categoryButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.1f, 0.9f), tabs[(int)Tab.Store].RectTransform, Anchor.CenterLeft, Pivot.CenterRight))
|
||||
{
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
foreach (MapEntityCategory category in itemCategories)
|
||||
{
|
||||
var categoryButton = new GUIButton(new Rectangle(x, 0, buttonWidth, 20), category.ToString(), "", tabs[(int)Tab.Store]);
|
||||
categoryButton.UserData = category;
|
||||
categoryButton.OnClicked = SelectItemCategory;
|
||||
|
||||
if (category == MapEntityCategory.Equipment)
|
||||
var categoryButton = new GUIButton(new RectTransform(new Point(categoryButtonContainer.Rect.Width), categoryButtonContainer.RectTransform),
|
||||
"", style: "ItemCategory" + category.ToString())
|
||||
{
|
||||
SelectItemCategory(categoryButton, category);
|
||||
}
|
||||
x += buttonWidth;
|
||||
UserData = category,
|
||||
OnClicked = (btn, userdata) => { SelectItemCategory((MapEntityCategory)userdata); return true; }
|
||||
};
|
||||
itemCategoryButtons.Add(categoryButton);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.25f), categoryButton.RectTransform, Anchor.BottomCenter),
|
||||
TextManager.Get("MapEntityCategory." + category), textAlignment: Alignment.Center, textColor: categoryButton.TextColor)
|
||||
{
|
||||
AutoScale = true,
|
||||
Color = Color.Transparent,
|
||||
HoverColor = Color.Transparent,
|
||||
PressedColor = Color.Transparent,
|
||||
SelectedColor = Color.Transparent,
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
SelectItemCategory(MapEntityCategory.Equipment);
|
||||
|
||||
// mission info -------------------------------------------------------------------------
|
||||
|
||||
missionPanel = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.5f), container.RectTransform, Anchor.TopRight)
|
||||
{
|
||||
RelativeOffset = new Vector2(0.0f, topPanel.RectTransform.RelativeSize.Y)
|
||||
}, color: Color.Black * 0.7f)
|
||||
{
|
||||
Visible = false
|
||||
};
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), missionPanel.RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black * 0.7f)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.15f), missionPanel.RectTransform, Anchor.TopRight, Pivot.BottomRight)
|
||||
{ RelativeOffset = new Vector2(0.1f, -0.05f) }, TextManager.Get("Mission"),
|
||||
textAlignment: Alignment.Center, font: GUI.LargeFont, style: "GUISlopedHeader")
|
||||
{
|
||||
AutoScale = true
|
||||
};
|
||||
var missionPanelContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), missionPanel.RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
selectedLocationInfo = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.75f), missionPanelContent.RectTransform))
|
||||
{
|
||||
RelativeSpacing = 0.02f,
|
||||
Stretch = true
|
||||
};
|
||||
selectedMissionInfo = new GUIListBox(new RectTransform(new Vector2(0.9f, 0.25f), missionPanel.RectTransform, Anchor.BottomRight, Pivot.TopRight))
|
||||
{
|
||||
Visible = false
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
topPanel.RectTransform.SetAsLastChild();
|
||||
|
||||
SelectTab(Tab.Map);
|
||||
|
||||
UpdateLocationTab(campaign.Map.CurrentLocation);
|
||||
UpdateLocationView(campaign.Map.CurrentLocation);
|
||||
|
||||
campaign.Map.OnLocationSelected += SelectLocation;
|
||||
campaign.Map.OnLocationChanged += (location) => UpdateLocationTab(location);
|
||||
campaign.CargoManager.OnItemsChanged += RefreshItemTab;
|
||||
campaign.Map.OnLocationChanged += (prevLocation, newLocation) => UpdateLocationView(newLocation);
|
||||
campaign.Map.OnMissionSelected += (connection, mission) =>
|
||||
{
|
||||
var selectedTickBox = missionTickBoxes.Find(tb => tb.UserData == mission);
|
||||
if (selectedTickBox != null)
|
||||
{
|
||||
selectedTickBox.Selected = true;
|
||||
}
|
||||
};
|
||||
campaign.CargoManager.OnItemsChanged += RefreshMyItems;
|
||||
}
|
||||
|
||||
private void UpdateLocationTab(Location location)
|
||||
private void UpdateLocationView(Location location)
|
||||
{
|
||||
if (characterPreviewFrame != null)
|
||||
{
|
||||
characterPreviewFrame.Parent.RemoveChild(characterPreviewFrame);
|
||||
characterPreviewFrame = null;
|
||||
}
|
||||
|
||||
if (location.HireManager == null)
|
||||
{
|
||||
hireList.ClearChildren();
|
||||
hireList.Enabled = false;
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 0, 0, 0), TextManager.Get("HireUnavailable"), Color.Transparent, Color.LightGray, Alignment.Center, Alignment.Center, "", hireList);
|
||||
return;
|
||||
}
|
||||
|
||||
hireList.Enabled = true;
|
||||
hireList.ClearChildren();
|
||||
|
||||
foreach (CharacterInfo c in location.HireManager.availableCharacters)
|
||||
{
|
||||
var frame = c.CreateCharacterFrame(hireList, c.Name + " (" + c.Job.Name + ")", c);
|
||||
|
||||
new GUITextBlock(
|
||||
new Rectangle(0, 0, 0, 25),
|
||||
c.Salary.ToString(),
|
||||
null, null,
|
||||
Alignment.TopRight, "", frame);
|
||||
}
|
||||
|
||||
RefreshItemTab();
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
mapZoom += PlayerInput.ScrollWheelSpeed / 1000.0f;
|
||||
mapZoom = MathHelper.Clamp(mapZoom, 1.0f, 4.0f);
|
||||
|
||||
if (GameMain.GameSession?.Map != null)
|
||||
if (Campaign is SinglePlayerCampaign)
|
||||
{
|
||||
GameMain.GameSession.Map.Update(deltaTime, new Rectangle(
|
||||
tabs[(int)selectedTab].Rect.X + 20,
|
||||
tabs[(int)selectedTab].Rect.Y + 20,
|
||||
tabs[(int)selectedTab].Rect.Width - 310,
|
||||
tabs[(int)selectedTab].Rect.Height - 40), mapZoom);
|
||||
var hireableCharacters = location.GetHireableCharacters();
|
||||
foreach (GUIComponent child in characterList.Content.Children.ToList())
|
||||
{
|
||||
if (child.UserData is CharacterInfo character)
|
||||
{
|
||||
if (GameMain.GameSession.CrewManager.GetCharacterInfos().Contains(character)) { continue; }
|
||||
}
|
||||
else if (child.UserData as string == "mycrew" || child.UserData as string == "hire")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
characterList.RemoveChild(child);
|
||||
}
|
||||
if (!hireableCharacters.Any())
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), characterList.Content.RectTransform), TextManager.Get("HireUnavailable"), textAlignment: Alignment.Center)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (CharacterInfo c in hireableCharacters)
|
||||
{
|
||||
var frame = c.CreateCharacterFrame(characterList.Content, c.Name + " (" + c.Job.Name + ")", c);
|
||||
new GUITextBlock(new RectTransform(Vector2.One, frame.RectTransform, Anchor.TopRight), c.Salary.ToString(), textAlignment: Alignment.CenterRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
characterList.UpdateScrollBarSize();
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch)
|
||||
RefreshMyItems();
|
||||
|
||||
bool purchaseableItemsFound = false;
|
||||
foreach (MapEntityPrefab mapEntityPrefab in MapEntityPrefab.List)
|
||||
{
|
||||
var itemPrefab = mapEntityPrefab as ItemPrefab;
|
||||
if (itemPrefab == null) { continue; }
|
||||
|
||||
PriceInfo priceInfo = itemPrefab.GetPrice(Campaign.Map.CurrentLocation);
|
||||
if (priceInfo != null) { purchaseableItemsFound = true; break; }
|
||||
}
|
||||
|
||||
//disable store tab if there's nothing to buy
|
||||
tabButtons.Find(btn => (Tab)btn.UserData == Tab.Store).Enabled = purchaseableItemsFound;
|
||||
|
||||
if (selectedTab == Tab.Store && !purchaseableItemsFound)
|
||||
{
|
||||
//switch out from store tab if there's nothing to buy
|
||||
SelectTab(Tab.Map);
|
||||
}
|
||||
else
|
||||
{
|
||||
//refresh store view
|
||||
SelectItemCategory(MapEntityCategory.Equipment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void DrawMap(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
|
||||
{
|
||||
if (selectedTab == Tab.Map && GameMain.GameSession?.Map != null)
|
||||
{
|
||||
GameMain.GameSession.Map.Draw(spriteBatch, new Rectangle(
|
||||
tabs[(int)selectedTab].Rect.X + 20,
|
||||
tabs[(int)selectedTab].Rect.Y + 20,
|
||||
tabs[(int)selectedTab].Rect.Width - 310,
|
||||
tabs[(int)selectedTab].Rect.Height - 40), mapZoom);
|
||||
}
|
||||
GameMain.GameSession?.Map?.Draw(spriteBatch, mapContainer);
|
||||
}
|
||||
|
||||
private void UpdateMap(float deltaTime, GUICustomComponent mapContainer)
|
||||
{
|
||||
GameMain.GameSession?.Map?.Update(deltaTime, mapContainer);
|
||||
}
|
||||
|
||||
public void UpdateCharacterLists()
|
||||
{
|
||||
characterList.ClearChildren();
|
||||
foreach (CharacterInfo c in GameMain.GameSession.CrewManager.GetCharacterInfos())
|
||||
//remove the player's crew from the listbox (everything between the "mycrew" and "hire" labels)
|
||||
foreach (GUIComponent child in characterList.Content.Children.ToList())
|
||||
{
|
||||
c.CreateCharacterFrame(characterList, c.Name + " (" + c.Job.Name + ") ", c);
|
||||
if (child.UserData as string == "mycrew")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (child.UserData as string == "hire")
|
||||
{
|
||||
break;
|
||||
}
|
||||
characterList.RemoveChild(child);
|
||||
}
|
||||
foreach (CharacterInfo c in GameMain.GameSession.CrewManager.GetCharacterInfos().Reverse())
|
||||
{
|
||||
var frame = c.CreateCharacterFrame(characterList.Content, c.Name + " (" + c.Job.Name + ") ", c);
|
||||
//add after the "mycrew" label
|
||||
frame.RectTransform.RepositionChildInHierarchy(1);
|
||||
}
|
||||
characterList.UpdateScrollBarSize();
|
||||
}
|
||||
|
||||
public void SelectLocation(Location location, LocationConnection connection)
|
||||
{
|
||||
GUIComponent locationPanel = tabs[(int)Tab.Map].GetChild("selectedlocation");
|
||||
|
||||
if (locationPanel != null) tabs[(int)Tab.Map].RemoveChild(locationPanel);
|
||||
|
||||
locationPanel = new GUIFrame(new Rectangle(0, 0, 250, 190), Color.Transparent, Alignment.TopRight, null, tabs[(int)Tab.Map]);
|
||||
locationPanel.UserData = "selectedlocation";
|
||||
|
||||
if (location == null) return;
|
||||
|
||||
var titleText = new GUITextBlock(new Rectangle(0, 0, 250, 0), location.Name, "", Alignment.TopLeft, Alignment.TopCenter, locationPanel, true, GUI.LargeFont);
|
||||
|
||||
if (GameMain.GameSession.Map.SelectedConnection != null && GameMain.GameSession.Map.SelectedConnection.Mission != null)
|
||||
selectedLocationInfo.ClearChildren();
|
||||
missionPanel.Visible = location != null;
|
||||
|
||||
if (location == null) { return; }
|
||||
|
||||
var container = selectedLocationInfo;
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), location.Name, font: GUI.LargeFont)
|
||||
{
|
||||
var mission = GameMain.GameSession.Map.SelectedConnection.Mission;
|
||||
AutoScale = true
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), location.Type.DisplayName);
|
||||
|
||||
new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 20, 0, 20), TextManager.Get("Mission") + ": " + mission.Name, "", locationPanel);
|
||||
new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 40, 0, 20), TextManager.Get("Reward") + ": " + mission.Reward + " " + TextManager.Get("Credits"), "", locationPanel);
|
||||
new GUITextBlock(new Rectangle(0, titleText.Rect.Height + 70, 0, 0), mission.Description, "", Alignment.TopLeft, Alignment.TopLeft, locationPanel, true, GUI.SmallFont);
|
||||
Sprite portrait = location.Type.GetPortrait(location.PortraitId);
|
||||
new GUIImage(new RectTransform(new Vector2(1.0f, 0.6f),
|
||||
container.RectTransform), portrait, scaleToFit: true);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), "Select a mission", font: GUI.LargeFont)
|
||||
{
|
||||
AutoScale = true
|
||||
};
|
||||
|
||||
var missionFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.3f), container.RectTransform), style: "InnerFrame");
|
||||
var missionContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), missionFrame.RectTransform, Anchor.Center))
|
||||
{
|
||||
RelativeSpacing = 0.02f,
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
SelectedLevel = connection?.Level;
|
||||
if (connection != null)
|
||||
{
|
||||
Point maxTickBoxSize = new Point(int.MaxValue, missionContent.Rect.Height / 4) ;
|
||||
List<Mission> availableMissions = Campaign.Map.CurrentLocation.GetMissionsInConnection(connection).ToList();
|
||||
if (!availableMissions.Contains(null)) { availableMissions.Add(null); }
|
||||
|
||||
Mission selectedMission = Campaign.Map.CurrentLocation.SelectedMission != null && availableMissions.Contains(Campaign.Map.CurrentLocation.SelectedMission) ?
|
||||
Campaign.Map.CurrentLocation.SelectedMission : null;
|
||||
missionTickBoxes.Clear();
|
||||
foreach (Mission mission in availableMissions)
|
||||
{
|
||||
var tickBox = new GUITickBox(new RectTransform(new Vector2(0.1f, 0.1f), missionContent.RectTransform) { MaxSize = maxTickBoxSize },
|
||||
mission?.Name ?? TextManager.Get("NoMission"))
|
||||
{
|
||||
UserData = mission,
|
||||
Enabled = GameMain.Client == null || GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign),
|
||||
Selected = mission == selectedMission,
|
||||
OnSelected = (tb) =>
|
||||
{
|
||||
if (!tb.Selected) { return false; }
|
||||
RefreshMissionTab(tb.UserData as Mission);
|
||||
Campaign.Map.OnMissionSelected?.Invoke(connection, mission);
|
||||
if (GameMain.Client != null && GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
|
||||
{
|
||||
GameMain.Client?.SendCampaignState();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
missionTickBoxes.Add(tickBox);
|
||||
}
|
||||
GUITickBox.CreateRadioButtonGroup(missionTickBoxes);
|
||||
RefreshMissionTab(selectedMission);
|
||||
|
||||
startButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.7f), missionContent.RectTransform, Anchor.CenterRight),
|
||||
TextManager.Get("StartCampaignButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
OnClicked = (GUIButton btn, object obj) => { StartRound?.Invoke(); return true; },
|
||||
Enabled = true
|
||||
};
|
||||
}
|
||||
|
||||
if (startButton != null) startButton.Enabled = true;
|
||||
|
||||
selectedLevel = connection.Level;
|
||||
|
||||
OnLocationSelected?.Invoke(location, connection);
|
||||
}
|
||||
|
||||
private void CreateItemFrame(PurchasedItem pi, GUIListBox listBox, int width)
|
||||
{
|
||||
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 50), "ListBoxElement", listBox);
|
||||
frame.UserData = pi;
|
||||
frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
|
||||
|
||||
frame.ToolTip = pi.itemPrefab.Description;
|
||||
public void RefreshMissionTab(Mission selectedMission)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(
|
||||
selectedMission == null ||
|
||||
(GameMain.GameSession.Map?.SelectedConnection != null &&
|
||||
GameMain.GameSession.Map.CurrentLocation.AvailableMissions.Contains(selectedMission)));
|
||||
|
||||
GameMain.GameSession.Map.CurrentLocation.SelectedMission = selectedMission;
|
||||
|
||||
selectedMissionInfo.ClearChildren();
|
||||
var container = selectedMissionInfo.Content;
|
||||
selectedMissionInfo.Visible = selectedMission != null;
|
||||
selectedMissionInfo.Spacing = 10;
|
||||
if (selectedMission == null) { return; }
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform),
|
||||
selectedMission.Name, font: GUI.LargeFont)
|
||||
{
|
||||
AutoScale = true,
|
||||
CanBeFocused = false
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform),
|
||||
TextManager.Get("Reward").Replace("[reward]", selectedMission.Reward.ToString()))
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform),
|
||||
selectedMission.Description, wrap: true)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
if (startButton != null) { startButton.Enabled = true; }
|
||||
}
|
||||
|
||||
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 Rectangle(50, 0, 0, 25),
|
||||
pi.itemPrefab.Name,
|
||||
null, null,
|
||||
Alignment.Left, Alignment.CenterX | Alignment.Left,
|
||||
"", frame);
|
||||
textBlock.Font = font;
|
||||
textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
|
||||
textBlock.ToolTip = pi.itemPrefab.Description;
|
||||
|
||||
if (pi.itemPrefab.sprite != null)
|
||||
GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Point(listBox.Rect.Width - 50, 25), frame.RectTransform, Anchor.CenterLeft)
|
||||
{
|
||||
GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), pi.itemPrefab.sprite, Alignment.CenterLeft, frame);
|
||||
img.Color = pi.itemPrefab.SpriteColor;
|
||||
AbsoluteOffset = new Point(40, 0)
|
||||
}, pi.ItemPrefab.Name, font: font)
|
||||
{
|
||||
ToolTip = pi.ItemPrefab.Description
|
||||
};
|
||||
|
||||
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 Rectangle(width - 160, 0, 80, 25),
|
||||
pi.itemPrefab.Price.ToString(),
|
||||
null, null, Alignment.TopLeft,
|
||||
Alignment.TopLeft, "", frame);
|
||||
textBlock.Font = font;
|
||||
textBlock.ToolTip = pi.itemPrefab.Description;
|
||||
textBlock = new GUITextBlock(new RectTransform(new Point(120, 25), frame.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(20, 0) },
|
||||
priceInfo.BuyPrice.ToString(), font: font)
|
||||
{
|
||||
ToolTip = pi.ItemPrefab.Description
|
||||
};
|
||||
|
||||
|
||||
//If its the store menu, quantity will always be 0
|
||||
if (pi.quantity > 0)
|
||||
if (pi.Quantity > 0)
|
||||
{
|
||||
var amountInput = new GUINumberInput(new Rectangle(width - 80, 0, 50, 40), "", GUINumberInput.NumberType.Int, frame);
|
||||
amountInput.MinValueInt = 0;
|
||||
amountInput.MaxValueInt = 1000;
|
||||
amountInput.UserData = pi;
|
||||
amountInput.IntValue = pi.quantity;
|
||||
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)
|
||||
if (numberInput.IntValue > purchasedItem.Quantity)
|
||||
{
|
||||
int quantity = 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)purchasedItem.itemPrefab.Price), quantity);
|
||||
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;
|
||||
numberInput.IntValue = purchasedItem.Quantity;
|
||||
}
|
||||
//Attempting to sell
|
||||
else
|
||||
{
|
||||
int quantity = purchasedItem.quantity - numberInput.IntValue;
|
||||
int quantity = purchasedItem.Quantity - numberInput.IntValue;
|
||||
for (int i = 0; i < quantity; i++)
|
||||
{
|
||||
SellItem(numberInput, purchasedItem);
|
||||
@@ -294,16 +547,17 @@ namespace Barotrauma
|
||||
private bool BuyItem(GUIComponent component, object obj)
|
||||
{
|
||||
PurchasedItem pi = obj as PurchasedItem;
|
||||
if (pi == null || pi.itemPrefab == null) return false;
|
||||
if (pi == null || pi.ItemPrefab == null) return false;
|
||||
|
||||
if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pi.itemPrefab.Price > campaign.Money) return false;
|
||||
|
||||
campaign.CargoManager.PurchaseItem(pi.itemPrefab, 1);
|
||||
PriceInfo priceInfo = pi.ItemPrefab.GetPrice(Campaign.Map.CurrentLocation);
|
||||
if (priceInfo == null || priceInfo.BuyPrice > Campaign.Money) return false;
|
||||
|
||||
Campaign.CargoManager.PurchaseItem(pi.ItemPrefab, 1);
|
||||
GameMain.Client?.SendCampaignState();
|
||||
|
||||
return false;
|
||||
@@ -312,115 +566,143 @@ namespace Barotrauma
|
||||
private bool SellItem(GUIComponent component, object obj)
|
||||
{
|
||||
PurchasedItem pi = obj as PurchasedItem;
|
||||
if (pi == null || pi.itemPrefab == null) return false;
|
||||
if (pi == null || pi.ItemPrefab == null) return false;
|
||||
|
||||
if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
campaign.CargoManager.SellItem(pi.itemPrefab,1);
|
||||
Campaign.CargoManager.SellItem(pi, 1);
|
||||
GameMain.Client?.SendCampaignState();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void RefreshItemTab()
|
||||
private void RefreshMyItems()
|
||||
{
|
||||
selectedItemList.ClearChildren();
|
||||
foreach (PurchasedItem pi in campaign.CargoManager.PurchasedItems)
|
||||
myItemList.Content.ClearChildren();
|
||||
|
||||
foreach (PurchasedItem ip in Campaign.CargoManager.PurchasedItems)
|
||||
{
|
||||
CreateItemFrame(pi, selectedItemList, selectedItemList.Rect.Width);
|
||||
CreateItemFrame(ip, ip.ItemPrefab.GetPrice(Campaign.Map.CurrentLocation), myItemList, myItemList.Rect.Width);
|
||||
}
|
||||
selectedItemList.children.Sort((x, y) => (x.UserData as PurchasedItem).itemPrefab.Name.CompareTo((y.UserData as PurchasedItem).itemPrefab.Name));
|
||||
selectedItemList.children.Sort((x, y) => (x.UserData as PurchasedItem).itemPrefab.Category.CompareTo((y.UserData as PurchasedItem).itemPrefab.Category));
|
||||
selectedItemList.UpdateScrollBarSize();
|
||||
myItemList.Content.RectTransform.SortChildren((x, y) =>
|
||||
(x.GUIComponent.UserData as PurchasedItem).ItemPrefab.Name.CompareTo((y.GUIComponent.UserData as PurchasedItem).ItemPrefab.Name));
|
||||
myItemList.Content.RectTransform.SortChildren((x, y) =>
|
||||
(x.GUIComponent.UserData as PurchasedItem).ItemPrefab.Category.CompareTo((y.GUIComponent.UserData as PurchasedItem).ItemPrefab.Category));
|
||||
myItemList.UpdateScrollBarSize();
|
||||
}
|
||||
|
||||
public void SelectTab(Tab tab)
|
||||
{
|
||||
selectedTab = tab;
|
||||
for (int i = 0; i< tabs.Length; i++)
|
||||
for (int i = 0; i < tabs.Length; i++)
|
||||
{
|
||||
tabs[i].Visible = (int)selectedTab == i;
|
||||
if (tabs[i] != null)
|
||||
{
|
||||
tabs[i].Visible = (int)selectedTab == i;
|
||||
}
|
||||
}
|
||||
foreach (GUIButton button in tabButtons)
|
||||
{
|
||||
button.Selected = (Tab)button.UserData == tab;
|
||||
}
|
||||
}
|
||||
|
||||
private bool SelectItemCategory(GUIButton button, object selection)
|
||||
private bool SelectItemCategory(MapEntityCategory category)
|
||||
{
|
||||
if (!(selection is MapEntityCategory)) return false;
|
||||
|
||||
storeItemList.ClearChildren();
|
||||
|
||||
MapEntityCategory category = (MapEntityCategory)selection;
|
||||
var items = MapEntityPrefab.List.FindAll(ep => ep.Price > 0.0f && ep.Category.HasFlag(category) && ep is ItemPrefab);
|
||||
|
||||
int width = storeItemList.Rect.Width;
|
||||
|
||||
foreach (ItemPrefab ep in items)
|
||||
foreach (MapEntityPrefab mapEntityPrefab in MapEntityPrefab.List)
|
||||
{
|
||||
CreateItemFrame(new PurchasedItem((ItemPrefab)ep,0), storeItemList, width);
|
||||
var itemPrefab = mapEntityPrefab as ItemPrefab;
|
||||
if (itemPrefab == null || !itemPrefab.Category.HasFlag(category)) continue;
|
||||
|
||||
PriceInfo priceInfo = itemPrefab.GetPrice(Campaign.Map.CurrentLocation);
|
||||
if (priceInfo == null) continue;
|
||||
|
||||
CreateItemFrame(new PurchasedItem(itemPrefab, 0), priceInfo, storeItemList, width);
|
||||
}
|
||||
|
||||
storeItemList.children.Sort((x, y) => (x.UserData as PurchasedItem).itemPrefab.Name.CompareTo((y.UserData as PurchasedItem).itemPrefab.Name));
|
||||
storeItemList.Content.RectTransform.SortChildren(
|
||||
(x, y) => (x.GUIComponent.UserData as PurchasedItem).ItemPrefab.Name.CompareTo((y.GUIComponent.UserData as PurchasedItem).ItemPrefab.Name));
|
||||
|
||||
foreach (GUIComponent child in button.Parent.children)
|
||||
foreach (GUIButton btn in itemCategoryButtons)
|
||||
{
|
||||
var otherButton = child as GUIButton;
|
||||
if (child.UserData is MapEntityCategory && otherButton != button)
|
||||
{
|
||||
otherButton.Selected = false;
|
||||
}
|
||||
btn.Selected = (MapEntityCategory)btn.UserData == category;
|
||||
}
|
||||
|
||||
button.Selected = true;
|
||||
storeItemList.BarScroll = 0.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public string GetMoney()
|
||||
{
|
||||
return TextManager.Get("Credits") + ": " + ((GameMain.GameSession == null) ? "0" : string.Format(CultureInfo.InvariantCulture, "{0:N0}", campaign.Money));
|
||||
return TextManager.Get("PlayerCredits").Replace("[credits]",
|
||||
((GameMain.GameSession == null) ? "0" : string.Format(CultureInfo.InvariantCulture, "{0:N0}", Campaign.Money)));
|
||||
}
|
||||
|
||||
private bool SelectCharacter(GUIComponent component, object selection)
|
||||
{
|
||||
GUIComponent prevInfoFrame = null;
|
||||
foreach (GUIComponent child in tabs[(int)selectedTab].children)
|
||||
foreach (GUIComponent child in tabs[(int)selectedTab].Children)
|
||||
{
|
||||
if (!(child.UserData is CharacterInfo)) continue;
|
||||
if (!(child.UserData is CharacterInfo)) { continue; }
|
||||
|
||||
prevInfoFrame = child;
|
||||
}
|
||||
|
||||
if (prevInfoFrame != null) tabs[(int)selectedTab].RemoveChild(prevInfoFrame);
|
||||
|
||||
if (prevInfoFrame != null) { tabs[(int)selectedTab].RemoveChild(prevInfoFrame); }
|
||||
|
||||
CharacterInfo characterInfo = selection as CharacterInfo;
|
||||
if (characterInfo == null) return false;
|
||||
|
||||
characterList.Deselect();
|
||||
hireList.Deselect();
|
||||
|
||||
if (Character.Controlled != null && characterInfo == Character.Controlled.Info) return false;
|
||||
if (characterInfo == null) { return false; }
|
||||
if (Character.Controlled != null && characterInfo == Character.Controlled.Info) { return false; }
|
||||
|
||||
if (characterPreviewFrame == null || characterPreviewFrame.UserData != characterInfo)
|
||||
{
|
||||
int width = Math.Min(300, tabs[(int)Tab.Crew].Rect.Width - hireList.Rect.Width - characterList.Rect.Width - 50);
|
||||
|
||||
characterPreviewFrame = new GUIFrame(new Rectangle(0, 60, width, 300),
|
||||
new Color(0.0f, 0.0f, 0.0f, 0.8f),
|
||||
Alignment.TopCenter, "", tabs[(int)selectedTab]);
|
||||
characterPreviewFrame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
|
||||
characterPreviewFrame.UserData = characterInfo;
|
||||
characterPreviewFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.5f), tabs[(int)selectedTab].RectTransform, Anchor.TopRight, Pivot.TopLeft))
|
||||
{
|
||||
UserData = characterInfo
|
||||
};
|
||||
|
||||
characterInfo.CreateInfoFrame(characterPreviewFrame);
|
||||
}
|
||||
|
||||
if (component.Parent == hireList)
|
||||
var currentCrew = GameMain.GameSession.CrewManager.GetCharacterInfos();
|
||||
if (currentCrew.Contains(characterInfo))
|
||||
{
|
||||
GUIButton hireButton = new GUIButton(new Rectangle(0, 0, 100, 20), TextManager.Get("HireButton"), Alignment.BottomCenter, "", characterPreviewFrame);
|
||||
hireButton.Enabled = campaign.Money >= characterInfo.Salary;
|
||||
hireButton.UserData = characterInfo;
|
||||
hireButton.OnClicked = HireCharacter;
|
||||
new GUIButton(new RectTransform(new Vector2(0.5f, 0.1f), characterPreviewFrame.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0.0f, 0.05f) },
|
||||
TextManager.Get("FireButton"))
|
||||
{
|
||||
Color = Color.Red,
|
||||
UserData = characterInfo,
|
||||
Enabled = currentCrew.Count() > 1, //can't fire if there's only one character in the crew
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
var confirmDialog = new GUIMessageBox(
|
||||
TextManager.Get("FireWarningHeader"),
|
||||
TextManager.Get("FireWarningText").Replace("[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;
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(0.5f, 0.1f), characterPreviewFrame.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0.0f, 0.05f) },
|
||||
TextManager.Get("HireButton"))
|
||||
{
|
||||
Enabled = Campaign.Money >= characterInfo.Salary,
|
||||
UserData = characterInfo,
|
||||
OnClicked = HireCharacter
|
||||
};
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -429,25 +711,44 @@ namespace Barotrauma
|
||||
private bool HireCharacter(GUIButton button, object selection)
|
||||
{
|
||||
CharacterInfo characterInfo = selection as CharacterInfo;
|
||||
if (characterInfo == null) return false;
|
||||
if (characterInfo == null) { return false; }
|
||||
|
||||
SinglePlayerCampaign spCampaign = campaign as SinglePlayerCampaign;
|
||||
SinglePlayerCampaign spCampaign = Campaign as SinglePlayerCampaign;
|
||||
if (spCampaign == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Characters can only be hired in the single player campaign.\n" + Environment.StackTrace);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (spCampaign.TryHireCharacter(GameMain.GameSession.Map.CurrentLocation.HireManager, characterInfo))
|
||||
if (spCampaign.TryHireCharacter(GameMain.GameSession.Map.CurrentLocation, characterInfo))
|
||||
{
|
||||
UpdateLocationTab(GameMain.GameSession.Map.CurrentLocation);
|
||||
UpdateLocationView(GameMain.GameSession.Map.CurrentLocation);
|
||||
SelectCharacter(null, null);
|
||||
characterList.Content.RemoveChild(characterList.Content.FindChild(characterInfo));
|
||||
UpdateCharacterLists();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool FireCharacter(GUIButton button, object selection)
|
||||
{
|
||||
CharacterInfo characterInfo = selection as CharacterInfo;
|
||||
if (characterInfo == null) return false;
|
||||
|
||||
SinglePlayerCampaign spCampaign = Campaign as SinglePlayerCampaign;
|
||||
if (spCampaign == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Characters can only be fired in the single player campaign.\n" + Environment.StackTrace);
|
||||
return false;
|
||||
}
|
||||
|
||||
spCampaign.FireCharacter(characterInfo);
|
||||
SelectCharacter(null, null);
|
||||
UpdateCharacterLists();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,52 +2,72 @@ using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using FarseerPhysics;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class GameScreen : Screen
|
||||
{
|
||||
private Color waterColor = new Color(0.75f, 0.8f, 0.9f, 1.0f);
|
||||
|
||||
private BlurEffect lightBlur;
|
||||
|
||||
readonly RenderTarget2D renderTargetBackground;
|
||||
readonly RenderTarget2D renderTarget;
|
||||
readonly RenderTarget2D renderTargetWater;
|
||||
readonly RenderTarget2D renderTargetFinal;
|
||||
private RenderTarget2D renderTargetBackground;
|
||||
private RenderTarget2D renderTarget;
|
||||
private RenderTarget2D renderTargetWater;
|
||||
private RenderTarget2D renderTargetFinal;
|
||||
|
||||
private Effect damageEffect;
|
||||
private Effect postProcessEffect;
|
||||
|
||||
private Texture2D damageStencil;
|
||||
private Texture2D damageStencil;
|
||||
private Texture2D distortTexture;
|
||||
|
||||
public Effect PostProcessEffect
|
||||
{
|
||||
get { return postProcessEffect; }
|
||||
}
|
||||
|
||||
|
||||
public GameScreen(GraphicsDevice graphics, ContentManager content)
|
||||
{
|
||||
cam = new Camera();
|
||||
cam.Translate(new Vector2(-10.0f, 50.0f));
|
||||
|
||||
renderTargetBackground = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
renderTarget = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents);
|
||||
renderTargetWater = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
renderTargetFinal = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight, false, SurfaceFormat.Color, DepthFormat.None);
|
||||
CreateRenderTargets(graphics);
|
||||
GameMain.Instance.OnResolutionChanged += () =>
|
||||
{
|
||||
CreateRenderTargets(graphics);
|
||||
};
|
||||
|
||||
|
||||
#if LINUX
|
||||
var blurEffect = content.Load<Effect>("blurshader_opengl");
|
||||
damageEffect = content.Load<Effect>("damageshader_opengl");
|
||||
#if LINUX || OSX
|
||||
var blurEffect = content.Load<Effect>("Effects/blurshader_opengl");
|
||||
damageEffect = content.Load<Effect>("Effects/damageshader_opengl");
|
||||
postProcessEffect = content.Load<Effect>("Effects/postprocess_opengl");
|
||||
#else
|
||||
var blurEffect = content.Load<Effect>("blurshader");
|
||||
damageEffect = content.Load<Effect>("damageshader");
|
||||
var blurEffect = content.Load<Effect>("Effects/blurshader");
|
||||
damageEffect = content.Load<Effect>("Effects/damageshader");
|
||||
postProcessEffect = content.Load<Effect>("Effects/postprocess");
|
||||
#endif
|
||||
|
||||
damageStencil = TextureLoader.FromFile("Content/Map/walldamage.png");
|
||||
damageEffect.Parameters["xStencil"].SetValue(damageStencil);
|
||||
damageEffect.Parameters["aMultiplier"].SetValue(50.0f);
|
||||
damageEffect.Parameters["cMultiplier"].SetValue(200.0f);
|
||||
|
||||
lightBlur = new BlurEffect(blurEffect, 0.001f, 0.001f);
|
||||
|
||||
distortTexture = TextureLoader.FromFile("Content/Effects/distortnormals.png");
|
||||
postProcessEffect.Parameters["xDistortTexture"].SetValue(distortTexture);
|
||||
}
|
||||
|
||||
|
||||
private void CreateRenderTargets(GraphicsDevice graphics)
|
||||
{
|
||||
renderTarget?.Dispose();
|
||||
renderTargetBackground?.Dispose();
|
||||
renderTargetWater?.Dispose();
|
||||
renderTargetFinal?.Dispose();
|
||||
renderTarget = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents);
|
||||
renderTargetBackground = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
renderTargetWater = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
renderTargetFinal = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight, false, SurfaceFormat.Color, DepthFormat.None);
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null && Character.Controlled.CanInteractWith(Character.Controlled.SelectedConstruction))
|
||||
@@ -65,15 +85,17 @@ namespace Barotrauma
|
||||
cam.UpdateTransform(true);
|
||||
Submarine.CullEntities(cam);
|
||||
|
||||
DrawMap(graphics, spriteBatch);
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, GameMain.ScissorTestEnable);
|
||||
DrawMap(graphics, spriteBatch, deltaTime);
|
||||
|
||||
if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null && Character.Controlled.CanInteractWith(Character.Controlled.SelectedConstruction))
|
||||
{
|
||||
Character.Controlled.SelectedConstruction.DrawHUD(spriteBatch, cam, Character.Controlled);
|
||||
}
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("DrawMap", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, GameMain.ScissorTestEnable);
|
||||
|
||||
if (Character.Controlled != null && cam != null) Character.Controlled.DrawHUD(spriteBatch, cam);
|
||||
|
||||
if (GameMain.GameSession != null) GameMain.GameSession.Draw(spriteBatch);
|
||||
@@ -86,16 +108,23 @@ namespace Barotrauma
|
||||
if (Level.Loaded != null && Submarine.MainSubs[i].WorldPosition.Y < Level.MaxEntityDepth) continue;
|
||||
|
||||
Color indicatorColor = i == 0 ? Color.LightBlue * 0.5f : Color.Red * 0.5f;
|
||||
DrawSubmarineIndicator(spriteBatch, Submarine.MainSubs[i], indicatorColor);
|
||||
GUI.DrawIndicator(
|
||||
spriteBatch, Submarine.MainSubs[i].WorldPosition, cam,
|
||||
Math.Max(Submarine.MainSub.Borders.Width, Submarine.MainSub.Borders.Height),
|
||||
GUI.SubmarineIcon, indicatorColor);
|
||||
}
|
||||
}
|
||||
|
||||
GUI.Draw((float)deltaTime, spriteBatch, cam);
|
||||
GUI.Draw(cam, spriteBatch);
|
||||
|
||||
spriteBatch.End();
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("DrawHUD", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
}
|
||||
|
||||
public void DrawMap(GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||
public void DrawMap(GraphicsDevice graphics, SpriteBatch spriteBatch, double deltaTime)
|
||||
{
|
||||
foreach (Submarine sub in Submarine.Loaded)
|
||||
{
|
||||
@@ -106,12 +135,28 @@ namespace Barotrauma
|
||||
|
||||
GameMain.LightManager.ObstructVision = Character.Controlled != null && Character.Controlled.ObstructVision;
|
||||
|
||||
GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam, lightBlur.Effect);
|
||||
if (Character.Controlled != null)
|
||||
{
|
||||
GameMain.LightManager.UpdateObstructVision(graphics, spriteBatch, cam, Character.Controlled.CursorWorldPosition);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
graphics.SetRenderTarget(renderTarget);
|
||||
graphics.Clear(Color.Transparent);
|
||||
//Draw resizeable background structures (= background walls) and wall background sprites
|
||||
//(= the background texture that's revealed when a wall is destroyed) into the background render target
|
||||
//These will be visible through the LOS effect.
|
||||
//Could be drawn with one Submarine.DrawBack call, but we can avoid sorting by depth by doing it like this.
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.None, null, null, cam.Transform);
|
||||
Submarine.DrawBack(spriteBatch, false, s => s is Structure && s.ResizeVertical && s.ResizeHorizontal);
|
||||
Submarine.DrawBack(spriteBatch, false, s => s is Structure && !(s.ResizeVertical && s.ResizeHorizontal) && ((Structure)s).Prefab.BackgroundSprite != null);
|
||||
spriteBatch.End();
|
||||
|
||||
graphics.SetRenderTarget(null);
|
||||
GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam, renderTarget);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
graphics.SetRenderTarget(renderTargetBackground);
|
||||
if (Level.Loaded == null)
|
||||
{
|
||||
@@ -124,51 +169,63 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
//draw alpha blended particles that are in water and behind subs
|
||||
#if LINUX
|
||||
#if LINUX || OSX
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
|
||||
#else
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.None, null, null, cam.Transform);
|
||||
#endif
|
||||
GameMain.ParticleManager.Draw(spriteBatch, true, false, Particles.ParticleBlendState.AlphaBlend);
|
||||
spriteBatch.End();
|
||||
|
||||
//draw additive particles that are in water and behind subs
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.None, null, null, cam.Transform);
|
||||
GameMain.ParticleManager.Draw(spriteBatch, true, false, Particles.ParticleBlendState.Additive);
|
||||
spriteBatch.End();
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.None, null, null, cam.Transform);
|
||||
Submarine.DrawBack(spriteBatch, false, s => s is Structure && ((Structure)s).ResizeVertical && ((Structure)s).ResizeHorizontal);
|
||||
foreach (Structure s in Structure.WallList)
|
||||
{
|
||||
if ((s.ResizeVertical != s.ResizeHorizontal) && s.CastShadow)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, new Vector2(s.DrawPosition.X-s.WorldRect.Width/2,-s.DrawPosition.Y-s.WorldRect.Height/2), new Vector2(s.WorldRect.Width, s.WorldRect.Height), Color.Black, true);
|
||||
}
|
||||
}
|
||||
spriteBatch.End();
|
||||
graphics.SetRenderTarget(renderTarget);
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.None, null, null, null);
|
||||
spriteBatch.Draw(renderTargetBackground, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
|
||||
spriteBatch.End();
|
||||
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, DepthStencilState.None, null, null, cam.Transform);
|
||||
Submarine.DrawBack(spriteBatch, false, s => !(s is Structure));
|
||||
Submarine.DrawBack(spriteBatch, false, s => s is Structure && !(((Structure)s).ResizeVertical && ((Structure)s).ResizeHorizontal));
|
||||
foreach (Character c in Character.CharacterList) c.Draw(spriteBatch);
|
||||
|
||||
//draw additive particles that are in water and behind subs
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.None, null, null, cam.Transform);
|
||||
GameMain.ParticleManager.Draw(spriteBatch, true, false, Particles.ParticleBlendState.Additive);
|
||||
spriteBatch.End();
|
||||
//Draw resizeable background structures (= background walls) and wall background sprites
|
||||
//(= the background texture that's revealed when a wall is destroyed) into the background render target
|
||||
//These will be visible through the LOS effect.
|
||||
//Could be drawn with one Submarine.DrawBack call, but we can avoid sorting by depth by doing it like this.
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.None);
|
||||
spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
|
||||
spriteBatch.End();
|
||||
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, null, null, cam.Transform);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//Start drawing to the normal render target (stuff that can't be seen through the LOS effect)
|
||||
graphics.SetRenderTarget(renderTarget);
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.None, null, null, null);
|
||||
spriteBatch.Draw(renderTargetBackground, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
|
||||
spriteBatch.End();
|
||||
//Draw the rest of the structures, characters and front structures
|
||||
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, DepthStencilState.None, null, null, cam.Transform);
|
||||
Submarine.DrawBack(spriteBatch, false, s => !(s is Structure) || !(s.ResizeVertical && s.ResizeHorizontal));
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.AnimController.Limbs.Any(l => l.DeformSprite != null)) continue;
|
||||
c.Draw(spriteBatch, Cam);
|
||||
}
|
||||
Submarine.DrawFront(spriteBatch, false, null);
|
||||
spriteBatch.End();
|
||||
|
||||
//draw the rendertarget and particles that are only supposed to be drawn in water into renderTargetWater
|
||||
graphics.SetRenderTarget(renderTargetWater);
|
||||
//draw characters with deformable limbs last, because they can't be batched into SpriteBatch
|
||||
//pretty hacky way of preventing draw order issues between normal and deformable sprites
|
||||
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, DepthStencilState.None, null, null, cam.Transform);
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.AnimController.Limbs.All(l => l.DeformSprite == null)) continue;
|
||||
c.Draw(spriteBatch, Cam);
|
||||
}
|
||||
spriteBatch.End();
|
||||
|
||||
//draw the rendertarget and particles that are only supposed to be drawn in water into renderTargetWater
|
||||
graphics.SetRenderTarget(renderTargetWater);
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque);
|
||||
spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), waterColor);
|
||||
spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);// waterColor);
|
||||
spriteBatch.End();
|
||||
|
||||
//draw alpha blended particles that are inside a sub
|
||||
#if LINUX
|
||||
#if LINUX || OSX
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.DepthRead, null, null, cam.Transform);
|
||||
#else
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.DepthRead, null, null, cam.Transform);
|
||||
@@ -179,7 +236,7 @@ namespace Barotrauma
|
||||
graphics.SetRenderTarget(renderTarget);
|
||||
|
||||
//draw alpha blended particles that are not in water
|
||||
#if LINUX
|
||||
#if LINUX || OSX
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.DepthRead, null, null, cam.Transform);
|
||||
#else
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.DepthRead, null, null, cam.Transform);
|
||||
@@ -191,20 +248,17 @@ namespace Barotrauma
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.None, null, null, cam.Transform);
|
||||
GameMain.ParticleManager.Draw(spriteBatch, false, null, Particles.ParticleBlendState.Additive);
|
||||
spriteBatch.End();
|
||||
|
||||
graphics.DepthStencilState = DepthStencilState.DepthRead;
|
||||
graphics.SetRenderTarget(renderTargetFinal);
|
||||
|
||||
WaterRenderer.Instance.ResetBuffers();
|
||||
Hull.UpdateVertices(graphics, cam, WaterRenderer.Instance);
|
||||
WaterRenderer.Instance.RenderWater(spriteBatch, renderTargetWater, cam);
|
||||
WaterRenderer.Instance.RenderAir(graphics, cam, renderTarget, Cam.ShaderTransform);
|
||||
graphics.DepthStencilState = DepthStencilState.None;
|
||||
|
||||
graphics.SetRenderTarget(renderTargetFinal);
|
||||
Hull.renderer.RenderBack(spriteBatch, renderTargetWater);
|
||||
|
||||
Array.Clear(Hull.renderer.vertices, 0, Hull.renderer.vertices.Length);
|
||||
Hull.renderer.PositionInBuffer = 0;
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
hull.Render(graphics, cam);
|
||||
}
|
||||
|
||||
Hull.renderer.Render(graphics, cam, renderTarget, Cam.ShaderTransform);
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate,
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate,
|
||||
BlendState.NonPremultiplied, SamplerState.LinearWrap,
|
||||
null, null,
|
||||
damageEffect,
|
||||
@@ -215,47 +269,108 @@ namespace Barotrauma
|
||||
//draw additive particles that are inside a sub
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.Default, null, null, cam.Transform);
|
||||
GameMain.ParticleManager.Draw(spriteBatch, true, true, Particles.ParticleBlendState.Additive);
|
||||
spriteBatch.End();
|
||||
foreach (var discharger in Items.Components.ElectricalDischarger.List)
|
||||
{
|
||||
discharger.DrawElectricity(spriteBatch);
|
||||
}
|
||||
spriteBatch.End();
|
||||
if (GameMain.LightManager.LightingEnabled)
|
||||
{
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, Lights.CustomBlendStates.Multiplicative, null, DepthStencilState.None, null, null, null);
|
||||
spriteBatch.Draw(GameMain.LightManager.lightMap, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
|
||||
spriteBatch.Draw(GameMain.LightManager.LightMap, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap, DepthStencilState.None, null, null, cam.Transform);
|
||||
foreach (Character c in Character.CharacterList) c.DrawFront(spriteBatch, cam);
|
||||
|
||||
if (Level.Loaded != null) Level.Loaded.DrawFront(spriteBatch);
|
||||
spriteBatch.End();
|
||||
if (Level.Loaded != null) Level.Loaded.DrawFront(spriteBatch, cam);
|
||||
if (GameMain.DebugDraw && GameMain.GameSession?.EventManager != null)
|
||||
{
|
||||
GameMain.GameSession.EventManager.DebugDraw(spriteBatch);
|
||||
}
|
||||
|
||||
graphics.SetRenderTarget(null);
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, SamplerState.PointClamp, DepthStencilState.None, null, null, null);
|
||||
spriteBatch.Draw(renderTargetFinal, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
|
||||
spriteBatch.End();
|
||||
spriteBatch.End();
|
||||
|
||||
if (GameMain.LightManager.LosEnabled && Character.Controlled!=null)
|
||||
{
|
||||
if (GameMain.LightManager.LosEnabled && GameMain.LightManager.LosMode != LosMode.None && Character.Controlled != null)
|
||||
{
|
||||
GameMain.LightManager.LosEffect.CurrentTechnique = GameMain.LightManager.LosEffect.Techniques["LosShader"];
|
||||
#if LINUX
|
||||
GameMain.LightManager.LosEffect.Parameters["TextureSampler+xTexture"].SetValue(renderTargetBackground);
|
||||
GameMain.LightManager.LosEffect.Parameters["LosSampler+xLosTexture"].SetValue(GameMain.LightManager.losTexture);
|
||||
#else
|
||||
|
||||
GameMain.LightManager.LosEffect.Parameters["xTexture"].SetValue(renderTargetBackground);
|
||||
GameMain.LightManager.LosEffect.Parameters["xLosTexture"].SetValue(GameMain.LightManager.losTexture);
|
||||
#endif
|
||||
//convert the los color to HLS and make sure the luminance of the color is always the same
|
||||
//as the luminance of the ambient light color
|
||||
float r = Math.Min(CharacterHUD.damageOverlayTimer * 0.5f, 0.5f);
|
||||
Vector3 ambientLightHls = GameMain.LightManager.AmbientLight.RgbToHLS();
|
||||
Vector3 losColorHls = Color.Lerp(GameMain.LightManager.AmbientLight, Color.Red, r).RgbToHLS();
|
||||
losColorHls.Y = ambientLightHls.Y;
|
||||
Color losColor = ToolBox.HLSToRGB(losColorHls);
|
||||
GameMain.LightManager.LosEffect.Parameters["xLosTexture"].SetValue(GameMain.LightManager.LosTexture);
|
||||
|
||||
Color losColor;
|
||||
if (GameMain.LightManager.LosMode == LosMode.Transparent)
|
||||
{
|
||||
//convert the los color to HLS and make sure the luminance of the color is always the same
|
||||
//as the luminance of the ambient light color
|
||||
float r = Character.Controlled?.CharacterHealth == null ?
|
||||
0.0f : Math.Min(Character.Controlled.CharacterHealth.DamageOverlayTimer * 0.5f, 0.5f);
|
||||
Vector3 ambientLightHls = GameMain.LightManager.AmbientLight.RgbToHLS();
|
||||
Vector3 losColorHls = Color.Lerp(GameMain.LightManager.AmbientLight, Color.Red, r).RgbToHLS();
|
||||
losColorHls.Y = ambientLightHls.Y;
|
||||
losColor = ToolBox.HLSToRGB(losColorHls);
|
||||
}
|
||||
else
|
||||
{
|
||||
losColor = Color.Black;
|
||||
}
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null, GameMain.LightManager.LosEffect, null);
|
||||
spriteBatch.Draw(renderTargetBackground, new Rectangle(0, 0, spriteBatch.GraphicsDevice.Viewport.Width, spriteBatch.GraphicsDevice.Viewport.Height), losColor);
|
||||
spriteBatch.End();
|
||||
spriteBatch.End();
|
||||
}
|
||||
graphics.SetRenderTarget(null);
|
||||
|
||||
float BlurStrength = 0.0f;
|
||||
float DistortStrength = 0.0f;
|
||||
Vector3 chromaticAberrationStrength = GameMain.Config.ChromaticAberrationEnabled ?
|
||||
new Vector3(-0.02f, -0.01f, 0.0f) : Vector3.Zero;
|
||||
|
||||
if (Character.Controlled != null)
|
||||
{
|
||||
BlurStrength = Character.Controlled.BlurStrength * 0.005f;
|
||||
DistortStrength = Character.Controlled.DistortStrength;
|
||||
chromaticAberrationStrength -= Vector3.One * Character.Controlled.RadialDistortStrength;
|
||||
chromaticAberrationStrength += new Vector3(-0.03f, -0.015f, 0.0f) * Character.Controlled.ChromaticAberrationStrength;
|
||||
}
|
||||
else
|
||||
{
|
||||
BlurStrength = 0.0f;
|
||||
DistortStrength = 0.0f;
|
||||
}
|
||||
|
||||
string postProcessTechnique = "";
|
||||
if (BlurStrength > 0.0f)
|
||||
{
|
||||
postProcessTechnique += "Blur";
|
||||
postProcessEffect.Parameters["blurDistance"].SetValue(BlurStrength);
|
||||
}
|
||||
if (chromaticAberrationStrength != Vector3.Zero)
|
||||
{
|
||||
postProcessTechnique += "ChromaticAberration";
|
||||
postProcessEffect.Parameters["chromaticAberrationStrength"].SetValue(chromaticAberrationStrength);
|
||||
}
|
||||
if (DistortStrength > 0.0f)
|
||||
{
|
||||
postProcessTechnique += "Distort";
|
||||
postProcessEffect.Parameters["distortScale"].SetValue(Vector2.One * DistortStrength);
|
||||
postProcessEffect.Parameters["distortUvOffset"].SetValue(WaterRenderer.Instance.WavePos * 0.001f);
|
||||
postProcessEffect.Parameters["xTexture"].SetValue(renderTargetFinal);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(postProcessTechnique))
|
||||
{
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, SamplerState.PointClamp, DepthStencilState.None);
|
||||
}
|
||||
else
|
||||
{
|
||||
postProcessEffect.CurrentTechnique = postProcessEffect.Techniques[postProcessTechnique];
|
||||
postProcessEffect.CurrentTechnique.Passes[0].Apply();
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, SamplerState.PointClamp, DepthStencilState.None, effect: postProcessEffect);
|
||||
}
|
||||
spriteBatch.Draw(DistortStrength > 0.0f ? distortTexture : renderTargetFinal, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
|
||||
spriteBatch.End();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,689 @@
|
||||
using Barotrauma.Lights;
|
||||
using Barotrauma.RuinGeneration;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class LevelEditorScreen : Screen
|
||||
{
|
||||
private readonly Camera cam;
|
||||
public override Camera Cam
|
||||
{
|
||||
get { return cam; }
|
||||
}
|
||||
|
||||
private GUIFrame leftPanel, rightPanel, bottomPanel, topPanel;
|
||||
|
||||
private LevelGenerationParams selectedParams;
|
||||
private LevelObjectPrefab selectedLevelObject;
|
||||
|
||||
private GUIListBox paramsList, ruinParamsList, levelObjectList;
|
||||
private GUIListBox editorContainer;
|
||||
|
||||
private GUIButton spriteEditDoneButton;
|
||||
|
||||
private GUITextBox seedBox;
|
||||
|
||||
private GUITickBox lightingEnabled, cursorLightEnabled;
|
||||
|
||||
private Sprite editingSprite;
|
||||
|
||||
private LightSource pointerLightSource;
|
||||
|
||||
public LevelEditorScreen()
|
||||
{
|
||||
cam = new Camera()
|
||||
{
|
||||
MinZoom = 0.01f,
|
||||
MaxZoom = 1.0f
|
||||
};
|
||||
|
||||
leftPanel = new GUIFrame(new RectTransform(new Vector2(0.07f, 0.8f), Frame.RectTransform) { MinSize = new Point(150, 0) },
|
||||
style: "GUIFrameLeft");
|
||||
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;
|
||||
};
|
||||
|
||||
ruinParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), 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;
|
||||
};
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform),
|
||||
"Create Level Object")
|
||||
{
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
Wizard.Instance.Create();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
lightingEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform),
|
||||
TextManager.Get("LevelEditorLightingEnabled"));
|
||||
|
||||
cursorLightEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform),
|
||||
TextManager.Get("LevelEditorCursorLightEnabled"));
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform),
|
||||
TextManager.Get("LevelEditorReloadTextures"))
|
||||
{
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
Level.Loaded?.ReloadTextures();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform),
|
||||
TextManager.Get("LevelEditorSaveAll"))
|
||||
{
|
||||
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) },
|
||||
style: "GUIFrameRight");
|
||||
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("LevelEditorLevelSeed"));
|
||||
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("LevelEditorGenerate"))
|
||||
{
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
Submarine.Unload();
|
||||
GameMain.LightManager.ClearLights();
|
||||
Level.CreateRandom(seedBox.Text, generationParams: selectedParams).Generate(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 ? Color.LightGreen : param.Style.textColor;
|
||||
}
|
||||
seedBox.Deselect();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
bottomPanel = new GUIFrame(new RectTransform(new Vector2(0.75f, 0.2f), 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("LevelEditorSpriteEditDone"))
|
||||
{
|
||||
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 Select()
|
||||
{
|
||||
base.Select();
|
||||
|
||||
pointerLightSource = new LightSource(Vector2.Zero, 1000.0f, Color.White, submarine: null);
|
||||
GameMain.LightManager.AddLight(pointerLightSource);
|
||||
topPanel.ClearChildren();
|
||||
new SerializableEntityEditor(topPanel.RectTransform, pointerLightSource.LightSourceParams, false, true);
|
||||
|
||||
editingSprite = null;
|
||||
UpdateParamsList();
|
||||
UpdateRuinParamsList();
|
||||
UpdateLevelObjectsList();
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
{
|
||||
base.Deselect();
|
||||
pointerLightSource?.Remove();
|
||||
pointerLightSource = null;
|
||||
}
|
||||
|
||||
private void UpdateParamsList()
|
||||
{
|
||||
editorContainer.ClearChildren();
|
||||
paramsList.Content.ClearChildren();
|
||||
|
||||
foreach (LevelGenerationParams genParams in LevelGenerationParams.LevelParams)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), paramsList.Content.RectTransform) { MinSize = new Point(0, 20) },
|
||||
genParams.Name)
|
||||
{
|
||||
Padding = Vector4.Zero,
|
||||
UserData = genParams
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateRuinParamsList()
|
||||
{
|
||||
editorContainer.ClearChildren();
|
||||
ruinParamsList.Content.ClearChildren();
|
||||
|
||||
foreach (RuinGenerationParams genParams in RuinGenerationParams.List)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), ruinParamsList.Content.RectTransform) { MinSize = new Point(0, 20) },
|
||||
genParams.Name)
|
||||
{
|
||||
Padding = Vector4.Zero,
|
||||
UserData = genParams
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateLevelObjectEditor(LevelObjectPrefab levelObjectPrefab)
|
||||
{
|
||||
editorContainer.ClearChildren();
|
||||
|
||||
var editor = new SerializableEntityEditor(editorContainer.Content.RectTransform, levelObjectPrefab, false, true, elementHeight: 20);
|
||||
|
||||
if (selectedParams != null)
|
||||
{
|
||||
var commonnessContainer = new GUILayoutGroup(new RectTransform(new Point(editor.Rect.Width, 70)), isHorizontal: false, childAnchor: Anchor.TopCenter)
|
||||
{
|
||||
AbsoluteSpacing = 5,
|
||||
Stretch = true
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), commonnessContainer.RectTransform),
|
||||
TextManager.Get("LevelEditorLevelObjCommonness").Replace("[leveltype]", selectedParams.Name), textAlignment: Alignment.Center);
|
||||
new GUINumberInput(new RectTransform(new Vector2(0.5f, 0.4f), commonnessContainer.RectTransform), GUINumberInput.NumberType.Float)
|
||||
{
|
||||
MinValueFloat = 0,
|
||||
MaxValueFloat = 100,
|
||||
FloatValue = levelObjectPrefab.GetCommonness(selectedParams.Name),
|
||||
OnValueChanged = (numberInput) =>
|
||||
{
|
||||
levelObjectPrefab.OverrideCommonness[selectedParams.Name] = numberInput.FloatValue;
|
||||
}
|
||||
};
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), commonnessContainer.RectTransform), style: null);
|
||||
editor.AddCustomContent(commonnessContainer, 1);
|
||||
}
|
||||
|
||||
Sprite sprite = levelObjectPrefab.Sprite ?? levelObjectPrefab.DeformableSprite?.Sprite;
|
||||
if (sprite != null)
|
||||
{
|
||||
editor.AddCustomContent(new GUIButton(new RectTransform(new Point(editor.Rect.Width / 2, 20)),
|
||||
TextManager.Get("LevelEditorEditSprite"))
|
||||
{
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
GameMain.SpriteEditorScreen.RefreshLists();
|
||||
editingSprite = sprite;
|
||||
GameMain.SpriteEditorScreen.SelectSprite(editingSprite);
|
||||
return true;
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
|
||||
if (levelObjectPrefab.DeformableSprite != null)
|
||||
{
|
||||
var deformEditor = levelObjectPrefab.DeformableSprite.CreateEditor(editor, levelObjectPrefab.SpriteDeformations, levelObjectPrefab.Name);
|
||||
deformEditor.GetChild<GUIDropDown>().OnSelected += (selected, userdata) =>
|
||||
{
|
||||
CreateLevelObjectEditor(selectedLevelObject);
|
||||
return true;
|
||||
};
|
||||
editor.AddCustomContent(deformEditor, editor.ContentCount);
|
||||
}
|
||||
//child object editing
|
||||
new GUITextBlock(new RectTransform(new Point(editor.Rect.Width, 40), editorContainer.Content.RectTransform),
|
||||
TextManager.Get("LevelEditorChildObjects"), textAlignment: Alignment.BottomCenter);
|
||||
foreach (LevelObjectPrefab.ChildObject childObj in levelObjectPrefab.ChildObjects)
|
||||
{
|
||||
var childObjFrame = new GUIFrame(new RectTransform(new Point(editor.Rect.Width, 30)));
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), childObjFrame.RectTransform, Anchor.Center), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
var selectedChildObj = childObj;
|
||||
var dropdown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1.0f), paddedFrame.RectTransform), elementCount: 10, selectMultiple: true);
|
||||
foreach (LevelObjectPrefab objPrefab in LevelObjectPrefab.List)
|
||||
{
|
||||
dropdown.AddItem(objPrefab.Name, objPrefab);
|
||||
if (childObj.AllowedNames.Contains(objPrefab.Name)) dropdown.SelectItem(objPrefab);
|
||||
}
|
||||
dropdown.OnSelected = (selected, obj) =>
|
||||
{
|
||||
childObj.AllowedNames = dropdown.SelectedDataMultiple.Select(d => ((LevelObjectPrefab)d).Name).ToList();
|
||||
return true;
|
||||
};
|
||||
new GUINumberInput(new RectTransform(new Vector2(0.2f, 1.0f), paddedFrame.RectTransform), GUINumberInput.NumberType.Int)
|
||||
{
|
||||
MinValueInt = 0,
|
||||
MaxValueInt = 10,
|
||||
OnValueChanged = (numberInput) =>
|
||||
{
|
||||
selectedChildObj.MinCount = numberInput.IntValue;
|
||||
selectedChildObj.MaxCount = Math.Max(selectedChildObj.MaxCount, selectedChildObj.MinCount);
|
||||
}
|
||||
}.IntValue = childObj.MinCount;
|
||||
new GUINumberInput(new RectTransform(new Vector2(0.2f, 1.0f), paddedFrame.RectTransform), GUINumberInput.NumberType.Int)
|
||||
{
|
||||
MinValueInt = 0,
|
||||
MaxValueInt = 10,
|
||||
OnValueChanged = (numberInput) =>
|
||||
{
|
||||
selectedChildObj.MaxCount = numberInput.IntValue;
|
||||
selectedChildObj.MinCount = Math.Min(selectedChildObj.MaxCount, selectedChildObj.MinCount);
|
||||
}
|
||||
}.IntValue = childObj.MaxCount;
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), paddedFrame.RectTransform), "X")
|
||||
{
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
selectedLevelObject.ChildObjects.Remove(selectedChildObj);
|
||||
CreateLevelObjectEditor(selectedLevelObject);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
childObjFrame.RectTransform.Parent = editorContainer.Content.RectTransform;
|
||||
}
|
||||
|
||||
new GUIButton(new RectTransform(new Point(editor.Rect.Width / 2, 20), editorContainer.Content.RectTransform),
|
||||
TextManager.Get("LevelEditorAddChildObject"))
|
||||
{
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
selectedLevelObject.ChildObjects.Add(new LevelObjectPrefab.ChildObject());
|
||||
CreateLevelObjectEditor(selectedLevelObject);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//light editing
|
||||
new GUITextBlock(new RectTransform(new Point(editor.Rect.Width, 40), editorContainer.Content.RectTransform),
|
||||
TextManager.Get("LevelEditorLightSources"), textAlignment: Alignment.BottomCenter);
|
||||
foreach (LightSourceParams lightSourceParams in selectedLevelObject.LightSourceParams)
|
||||
{
|
||||
new SerializableEntityEditor(editorContainer.Content.RectTransform, lightSourceParams, inGame: false, showName: true);
|
||||
}
|
||||
new GUIButton(new RectTransform(new Point(editor.Rect.Width / 2, 20), editorContainer.Content.RectTransform),
|
||||
TextManager.Get("LevelEditorAddLightSource"))
|
||||
{
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
selectedLevelObject.LightSourceTriggerIndex.Add(-1);
|
||||
selectedLevelObject.LightSourceParams.Add(new LightSourceParams(100.0f, Color.White));
|
||||
CreateLevelObjectEditor(selectedLevelObject);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void SortLevelObjectsList(LevelGenerationParams selectedParams)
|
||||
{
|
||||
//fade out levelobjects that don't spawn in this type of level
|
||||
foreach (GUIComponent levelObjFrame in levelObjectList.Content.Children)
|
||||
{
|
||||
var levelObj = levelObjFrame.UserData as LevelObjectPrefab;
|
||||
Color color = levelObj.GetCommonness(selectedParams.Name) > 0.0f ? Color.White : Color.White * 0.3f;
|
||||
levelObjFrame.Color = color;
|
||||
levelObjFrame.GetAnyChild<GUIImage>().Color = color;
|
||||
}
|
||||
|
||||
//sort the levelobjects according to commonness in this level
|
||||
levelObjectList.Content.RectTransform.SortChildren((c1, c2) =>
|
||||
{
|
||||
var levelObj1 = c1.GUIComponent.UserData as LevelObjectPrefab;
|
||||
var levelObj2 = c2.GUIComponent.UserData as LevelObjectPrefab;
|
||||
return Math.Sign(levelObj2.GetCommonness(selectedParams.Name) - levelObj1.GetCommonness(selectedParams.Name));
|
||||
});
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
base.AddToGUIUpdateList();
|
||||
rightPanel.Visible = leftPanel.Visible = bottomPanel.Visible = editingSprite == null;
|
||||
if (editingSprite != null)
|
||||
{
|
||||
GameMain.SpriteEditorScreen.TopPanel.AddToGUIUpdateList();
|
||||
spriteEditDoneButton.AddToGUIUpdateList();
|
||||
}
|
||||
else if (lightingEnabled.Selected && cursorLightEnabled.Selected)
|
||||
{
|
||||
topPanel.AddToGUIUpdateList();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||
{
|
||||
if (lightingEnabled.Selected)
|
||||
{
|
||||
GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam);
|
||||
}
|
||||
graphics.Clear(Color.Black);
|
||||
|
||||
if (Level.Loaded != null)
|
||||
{
|
||||
Level.Loaded.DrawBack(graphics, spriteBatch, cam);
|
||||
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, SamplerState.LinearWrap, DepthStencilState.DepthRead, transformMatrix: cam.Transform);
|
||||
Level.Loaded.DrawFront(spriteBatch, cam);
|
||||
Submarine.Draw(spriteBatch, false);
|
||||
Submarine.DrawFront(spriteBatch);
|
||||
Submarine.DrawDamageable(spriteBatch, null);
|
||||
spriteBatch.End();
|
||||
|
||||
if (lightingEnabled.Selected)
|
||||
{
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate, Lights.CustomBlendStates.Multiplicative, null, DepthStencilState.None, null, null, null);
|
||||
spriteBatch.Draw(GameMain.LightManager.LightMap, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
|
||||
spriteBatch.End();
|
||||
}
|
||||
}
|
||||
|
||||
if (editingSprite != null)
|
||||
{
|
||||
GameMain.SpriteEditorScreen.Draw(deltaTime, graphics, spriteBatch);
|
||||
}
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
|
||||
GUI.Draw(Cam, spriteBatch);
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
pointerLightSource.Position = cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
pointerLightSource.Enabled = cursorLightEnabled.Selected;
|
||||
pointerLightSource.IsBackground = true;
|
||||
cam.MoveCamera((float)deltaTime, allowZoom: GUI.MouseOn == null);
|
||||
cam.UpdateTransform();
|
||||
Level.Loaded?.Update((float)deltaTime, cam);
|
||||
|
||||
if (editingSprite != null)
|
||||
{
|
||||
GameMain.SpriteEditorScreen.Update(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
private void SerializeAll()
|
||||
{
|
||||
XmlWriterSettings settings = new XmlWriterSettings
|
||||
{
|
||||
Indent = true,
|
||||
NewLineOnAttributes = true
|
||||
};
|
||||
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelGenerationParameters))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(configFile);
|
||||
if (doc == null || doc.Root == null) continue;
|
||||
|
||||
foreach (LevelGenerationParams genParams in LevelGenerationParams.LevelParams)
|
||||
{
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
{
|
||||
if (element.Name.ToString().ToLowerInvariant() != genParams.Name.ToLowerInvariant()) continue;
|
||||
SerializableProperty.SerializeProperties(genParams, element, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
using (var writer = XmlWriter.Create(configFile, settings))
|
||||
{
|
||||
doc.WriteTo(writer);
|
||||
writer.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
settings.NewLineOnAttributes = false;
|
||||
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelObjectPrefabs))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(configFile);
|
||||
if (doc == null || doc.Root == null) continue;
|
||||
|
||||
foreach (LevelObjectPrefab levelObjPrefab in LevelObjectPrefab.List)
|
||||
{
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
{
|
||||
if (element.Name.ToString().ToLowerInvariant() != levelObjPrefab.Name.ToLowerInvariant()) continue;
|
||||
levelObjPrefab.Save(element);
|
||||
break;
|
||||
}
|
||||
}
|
||||
using (var writer = XmlWriter.Create(configFile, settings))
|
||||
{
|
||||
doc.WriteTo(writer);
|
||||
writer.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
RuinGenerationParams.SaveAll();
|
||||
}
|
||||
|
||||
private void Serialize(LevelGenerationParams genParams)
|
||||
{
|
||||
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelGenerationParameters))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(configFile);
|
||||
if (doc == null || doc.Root == null) continue;
|
||||
|
||||
bool elementFound = false;
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
{
|
||||
if (element.Name.ToString().ToLowerInvariant() != genParams.Name.ToLowerInvariant()) continue;
|
||||
SerializableProperty.SerializeProperties(genParams, element, true);
|
||||
elementFound = true;
|
||||
}
|
||||
|
||||
if (elementFound)
|
||||
{
|
||||
XmlWriterSettings settings = new XmlWriterSettings
|
||||
{
|
||||
Indent = true,
|
||||
NewLineOnAttributes = true
|
||||
};
|
||||
|
||||
using (var writer = XmlWriter.Create(configFile, settings))
|
||||
{
|
||||
doc.WriteTo(writer);
|
||||
writer.Flush();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region LevelObject Wizard
|
||||
private class Wizard
|
||||
{
|
||||
private LevelObjectPrefab newPrefab;
|
||||
|
||||
private static Wizard instance;
|
||||
public static Wizard Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new Wizard();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddToGUIUpdateList()
|
||||
{
|
||||
//activeView?.Box.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public GUIMessageBox Create()
|
||||
{
|
||||
var box = new GUIMessageBox(TextManager.Get("LevelEditorCreateLevelObj"), string.Empty,
|
||||
new string[] { TextManager.Get("Cancel"), TextManager.Get("Done") }, GameMain.GraphicsWidth / 2, (int)(GameMain.GraphicsHeight * 0.8f));
|
||||
|
||||
box.Content.ChildAnchor = Anchor.TopCenter;
|
||||
box.Content.AbsoluteSpacing = 20;
|
||||
int elementSize = 30;
|
||||
var listBox = new GUIListBox(new RectTransform(new Vector2(1, 0.9f), box.Content.RectTransform));
|
||||
|
||||
new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform),
|
||||
TextManager.Get("LevelEditorLevelObjName")) { CanBeFocused = false };
|
||||
var nameBox = new GUITextBox(new RectTransform(new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform));
|
||||
|
||||
new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform),
|
||||
TextManager.Get("LevelEditorLevelObjTexturePath")) { CanBeFocused = false };
|
||||
var texturePathBox = new GUITextBox(new RectTransform(new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform));
|
||||
foreach (LevelObjectPrefab prefab in LevelObjectPrefab.List)
|
||||
{
|
||||
if (prefab.Sprite == null) continue;
|
||||
texturePathBox.Text = Path.GetDirectoryName(prefab.Sprite.FilePath);
|
||||
break;
|
||||
}
|
||||
|
||||
newPrefab = new LevelObjectPrefab(null);
|
||||
|
||||
new SerializableEntityEditor(listBox.Content.RectTransform, newPrefab, false, false);
|
||||
|
||||
box.Buttons[0].OnClicked += (b, d) =>
|
||||
{
|
||||
box.Close();
|
||||
return true;
|
||||
};
|
||||
// Next
|
||||
box.Buttons[1].OnClicked += (b, d) =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(nameBox.Text))
|
||||
{
|
||||
nameBox.Flash(Color.Red);
|
||||
GUI.AddMessage(TextManager.Get("LevelEditorLevelObjNameEmpty"), Color.Red);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LevelObjectPrefab.List.Any(obj => obj.Name.ToLower() == nameBox.Text.ToLower()))
|
||||
{
|
||||
nameBox.Flash(Color.Red);
|
||||
GUI.AddMessage(TextManager.Get("LevelEditorLevelObjNameTaken"), Color.Red);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!File.Exists(texturePathBox.Text))
|
||||
{
|
||||
texturePathBox.Flash(Color.Red);
|
||||
GUI.AddMessage(TextManager.Get("LevelEditorLevelObjTextureNotFound"), Color.Red);
|
||||
return false;
|
||||
}
|
||||
|
||||
newPrefab.Name = nameBox.Text;
|
||||
|
||||
XmlWriterSettings settings = new XmlWriterSettings { Indent = true };
|
||||
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelObjectPrefabs))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(configFile);
|
||||
if (doc?.Root == null) continue;
|
||||
var newElement = new XElement(newPrefab.Name);
|
||||
newPrefab.Save(newElement);
|
||||
newElement.Add(new XElement("Sprite",
|
||||
new XAttribute("texture", texturePathBox.Text),
|
||||
new XAttribute("sourcerect", "0,0,100,100"),
|
||||
new XAttribute("origin", "0.5,0.5")));
|
||||
|
||||
doc.Root.Add(newElement);
|
||||
using (var writer = XmlWriter.Create(configFile, settings))
|
||||
{
|
||||
doc.WriteTo(writer);
|
||||
writer.Flush();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
LevelObjectPrefab.List.Add(newPrefab);
|
||||
GameMain.LevelEditorScreen.UpdateLevelObjectsList();
|
||||
|
||||
box.Close();
|
||||
return true;
|
||||
};
|
||||
return box;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,8 @@ namespace Barotrauma
|
||||
class LobbyScreen : Screen
|
||||
{
|
||||
private CampaignUI campaignUI;
|
||||
|
||||
private GUIFrame topPanel, bottomPanel;
|
||||
|
||||
private GUITextBlock locationTitle;
|
||||
private GUIFrame campaignUIContainer;
|
||||
|
||||
private CrewManager CrewManager
|
||||
{
|
||||
@@ -27,46 +25,7 @@ namespace Barotrauma
|
||||
|
||||
public LobbyScreen()
|
||||
{
|
||||
Rectangle panelRect = new Rectangle(
|
||||
40, 40,
|
||||
GameMain.GraphicsWidth - 80,
|
||||
100);
|
||||
|
||||
topPanel = new GUIFrame(panelRect, "");
|
||||
topPanel.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
|
||||
|
||||
locationTitle = new GUITextBlock(new Rectangle(0, 0, 200, 25),
|
||||
"", Color.Transparent, Color.White, Alignment.TopLeft, "", topPanel);
|
||||
locationTitle.Font = GUI.LargeFont;
|
||||
|
||||
|
||||
GUITextBlock moneyText = new GUITextBlock(new Rectangle(0, 0, 0, 25), "", "",
|
||||
Alignment.BottomLeft, Alignment.BottomLeft, topPanel);
|
||||
moneyText.TextGetter = GetMoney;
|
||||
|
||||
GUIButton button = new GUIButton(new Rectangle(-240, 0, 100, 30), TextManager.Get("Map"), null, Alignment.BottomRight, "", topPanel);
|
||||
button.UserData = CampaignUI.Tab.Map;
|
||||
button.OnClicked = SelectTab;
|
||||
SelectTab(button, button.UserData);
|
||||
|
||||
button = new GUIButton(new Rectangle(-120, 0, 100, 30), TextManager.Get("Crew"), null, Alignment.BottomRight, "", topPanel);
|
||||
button.UserData = CampaignUI.Tab.Crew;
|
||||
button.OnClicked = SelectTab;
|
||||
|
||||
button = new GUIButton(new Rectangle(0, 0, 100, 30), TextManager.Get("Store"), null, Alignment.BottomRight, "", topPanel);
|
||||
button.UserData = CampaignUI.Tab.Store;
|
||||
button.OnClicked = SelectTab;
|
||||
|
||||
//---------------------------------------------------------------
|
||||
//---------------------------------------------------------------
|
||||
|
||||
panelRect = new Rectangle(
|
||||
40,
|
||||
panelRect.Bottom + 40,
|
||||
panelRect.Width,
|
||||
GameMain.GraphicsHeight - 120 - panelRect.Height);
|
||||
|
||||
bottomPanel = new GUIFrame(panelRect);
|
||||
campaignUIContainer = new GUIFrame(new RectTransform(Vector2.One, Frame.RectTransform, Anchor.Center), style: null);
|
||||
}
|
||||
|
||||
public override void Select()
|
||||
@@ -74,109 +33,31 @@ namespace Barotrauma
|
||||
base.Select();
|
||||
|
||||
CampaignMode campaign = GameMain.GameSession.GameMode as CampaignMode;
|
||||
|
||||
if (campaign == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
locationTitle.Text = TextManager.Get("Location") + ": " + campaign.Map.CurrentLocation.Name;
|
||||
if (campaign == null) { return; }
|
||||
|
||||
campaign.Map.SelectLocation(-1);
|
||||
|
||||
bottomPanel.ClearChildren();
|
||||
campaignUI = new CampaignUI(campaign, bottomPanel);
|
||||
campaignUI.StartRound = StartRound;
|
||||
campaignUI.OnLocationSelected = SelectLocation;
|
||||
campaignUIContainer.ClearChildren();
|
||||
campaignUI = new CampaignUI(campaign, campaignUIContainer)
|
||||
{
|
||||
StartRound = StartRound,
|
||||
OnLocationSelected = SelectLocation
|
||||
};
|
||||
campaignUI.UpdateCharacterLists();
|
||||
|
||||
GameAnalyticsManager.SetCustomDimension01("singleplayer");
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
base.AddToGUIUpdateList();
|
||||
|
||||
topPanel.AddToGUIUpdateList();
|
||||
bottomPanel.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
|
||||
topPanel.Update((float)deltaTime);
|
||||
bottomPanel.Update((float)deltaTime);
|
||||
|
||||
campaignUI.Update((float)deltaTime);
|
||||
|
||||
/* mapZoom += PlayerInput.ScrollWheelSpeed / 1000.0f;
|
||||
mapZoom = MathHelper.Clamp(mapZoom, 1.0f, 4.0f);
|
||||
|
||||
GameMain.GameSession.Map.Update((float)deltaTime, new Rectangle(
|
||||
bottomPanel[selectedRightPanel].Rect.X + 20,
|
||||
bottomPanel[selectedRightPanel].Rect.Y + 20,
|
||||
bottomPanel[selectedRightPanel].Rect.Width - 310,
|
||||
bottomPanel[selectedRightPanel].Rect.Height - 40), mapZoom);*/
|
||||
}
|
||||
|
||||
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||
{
|
||||
/*if (characterList.CountChildren != CrewManager.CharacterInfos.Count)
|
||||
{
|
||||
UpdateCharacterLists();
|
||||
}*/
|
||||
|
||||
graphics.Clear(Color.Black);
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, GameMain.ScissorTestEnable);
|
||||
|
||||
Sprite backGround = GameMain.GameSession.Map.CurrentLocation.Type.Background;
|
||||
spriteBatch.Draw(backGround.Texture, Vector2.Zero, null, Color.White, 0.0f, Vector2.Zero,
|
||||
Math.Max((float)GameMain.GraphicsWidth / backGround.SourceRect.Width, (float)GameMain.GraphicsHeight / backGround.SourceRect.Height), SpriteEffects.None, 0.0f);
|
||||
|
||||
topPanel.Draw(spriteBatch);
|
||||
bottomPanel.Draw(spriteBatch);
|
||||
|
||||
campaignUI.Draw(spriteBatch);
|
||||
|
||||
/* if (selectedRightPanel == (int)PanelTab.Map)
|
||||
{
|
||||
GameMain.GameSession.Map.Draw(spriteBatch, new Rectangle(
|
||||
bottomPanel[selectedRightPanel].Rect.X + 20,
|
||||
bottomPanel[selectedRightPanel].Rect.Y + 20,
|
||||
bottomPanel[selectedRightPanel].Rect.Width - 310,
|
||||
bottomPanel[selectedRightPanel].Rect.Height - 40), mapZoom);
|
||||
}
|
||||
|
||||
if (topPanel.UserData as Location != GameMain.GameSession.Map.CurrentLocation)
|
||||
{
|
||||
UpdateLocationTab(GameMain.GameSession.Map.CurrentLocation);
|
||||
}*/
|
||||
|
||||
GUI.Draw((float)deltaTime, spriteBatch, null);
|
||||
GUI.DrawBackgroundSprite(spriteBatch,
|
||||
GameMain.GameSession.Map.CurrentLocation.Type.GetPortrait(GameMain.GameSession.Map.CurrentLocation.PortraitId));
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
|
||||
GUI.Draw(Cam, spriteBatch);
|
||||
spriteBatch.End();
|
||||
|
||||
}
|
||||
|
||||
public bool SelectTab(GUIButton button, object selection)
|
||||
{
|
||||
if (campaignUI == null) return false;
|
||||
|
||||
if (button != null)
|
||||
{
|
||||
button.Selected = true;
|
||||
foreach (GUIComponent child in topPanel.children)
|
||||
{
|
||||
GUIButton otherButton = child as GUIButton;
|
||||
if (otherButton == null || otherButton == button) continue;
|
||||
otherButton.Selected = false;
|
||||
}
|
||||
}
|
||||
campaignUI.SelectTab((CampaignUI.Tab)selection);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SelectLocation(Location location, LocationConnection locationConnection)
|
||||
|
||||
@@ -1,128 +1,237 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Tutorials;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class MainMenuScreen : Screen
|
||||
{
|
||||
public enum Tab { NewGame = 1, LoadGame = 2, HostServer = 3, Settings = 4 }
|
||||
public enum Tab { NewGame = 1, LoadGame = 2, HostServer = 3, Settings = 4, Tutorials = 5 }
|
||||
|
||||
private GUIFrame buttonsTab;
|
||||
private GUIComponent buttonsParent;
|
||||
|
||||
private GUIFrame[] menuTabs;
|
||||
|
||||
private CampaignSetupUI campaignSetupUI;
|
||||
|
||||
private GUITextBox serverNameBox, portBox, passwordBox, maxPlayersBox;
|
||||
private GUITextBox serverNameBox, portBox, queryPortBox, passwordBox, maxPlayersBox;
|
||||
private GUITickBox isPublicBox, useUpnpBox;
|
||||
|
||||
private GUIButton joinServerButton, hostServerButton, steamWorkshopButton;
|
||||
|
||||
private GameMain game;
|
||||
|
||||
private Tab selectedTab;
|
||||
|
||||
public MainMenuScreen(GameMain game)
|
||||
{
|
||||
buttonsParent = new GUILayoutGroup(new RectTransform(new Vector2(0.15f, 0.5f), parent: Frame.RectTransform, anchor: Anchor.BottomLeft)
|
||||
{
|
||||
RelativeOffset = new Vector2(0, 0.1f),
|
||||
AbsoluteOffset = new Point(50, 0)
|
||||
})
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
//debug button for quickly starting a new round
|
||||
#if DEBUG
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonsParent.RectTransform, Anchor.TopCenter, Pivot.BottomCenter) { AbsoluteOffset = new Point(0, -40) },
|
||||
"Quickstart (dev)", style: "GUIButtonLarge", color: Color.Red)
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
OnClicked = (tb, userdata) =>
|
||||
{
|
||||
Submarine selectedSub = null;
|
||||
string subName = GameMain.Config.QuickStartSubmarineName;
|
||||
if (!string.IsNullOrEmpty(subName))
|
||||
{
|
||||
DebugConsole.NewMessage($"Loading the predefined quick start sub \"{subName}\"", Color.White);
|
||||
selectedSub = Submarine.SavedSubmarines.FirstOrDefault(s =>
|
||||
s.Name.ToLower() == subName.ToLower());
|
||||
|
||||
if (selectedSub == null)
|
||||
{
|
||||
DebugConsole.NewMessage($"Cannot find a sub that matches the name \"{subName}\".", Color.Red);
|
||||
}
|
||||
}
|
||||
if (selectedSub == null)
|
||||
{
|
||||
DebugConsole.NewMessage("Loading a random sub.", Color.White);
|
||||
var subs = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.Shuttle) && !s.HasTag(SubmarineTag.HideInMenus));
|
||||
selectedSub = subs.ElementAt(Rand.Int(subs.Count()));
|
||||
}
|
||||
var gamesession = new GameSession(
|
||||
selectedSub,
|
||||
"Data/Saves/test.xml",
|
||||
GameModePreset.List.Find(gm => gm.Identifier == "devsandbox"),
|
||||
missionPrefab: null);
|
||||
//(gamesession.GameMode as SinglePlayerCampaign).GenerateMap(ToolBox.RandomSeed(8));
|
||||
gamesession.StartRound(ToolBox.RandomSeed(8));
|
||||
GameMain.GameScreen.Select();
|
||||
|
||||
string[] jobIdentifiers = new string[] { "captain", "engineer", "mechanic" };
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
var spawnPoint = WayPoint.GetRandom(SpawnType.Human, null, Submarine.MainSub);
|
||||
if (spawnPoint == null)
|
||||
{
|
||||
DebugConsole.ThrowError("No spawnpoints found in the selected submarine. Quickstart failed.");
|
||||
GameMain.MainMenuScreen.Select();
|
||||
return true;
|
||||
}
|
||||
var characterInfo = new CharacterInfo(
|
||||
Character.HumanConfigFile,
|
||||
jobPrefab: JobPrefab.List.Find(j => j.Identifier == jobIdentifiers[i]));
|
||||
if (characterInfo.Job == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to find the job \"" + jobIdentifiers[i] + "\"!");
|
||||
}
|
||||
|
||||
var newCharacter = Character.Create(Character.HumanConfigFile, spawnPoint.WorldPosition, ToolBox.RandomSeed(8), characterInfo);
|
||||
newCharacter.GiveJobItems(spawnPoint);
|
||||
gamesession.CrewManager.AddCharacter(newCharacter);
|
||||
Character.Controlled = newCharacter;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
var minButtonSize = new Point(120, 20);
|
||||
var maxButtonSize = new Point(240, 40);
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonsParent.RectTransform), TextManager.Get("TutorialButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
UserData = Tab.Tutorials,
|
||||
OnClicked = SelectTab,
|
||||
Enabled = false
|
||||
};
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), buttonsParent.RectTransform), style: null); //spacing
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonsParent.RectTransform), TextManager.Get("NewGameButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
UserData = Tab.NewGame,
|
||||
OnClicked = SelectTab
|
||||
};
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonsParent.RectTransform), TextManager.Get("LoadGameButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
UserData = Tab.LoadGame,
|
||||
OnClicked = SelectTab
|
||||
};
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), buttonsParent.RectTransform), style: null); //spacing
|
||||
|
||||
joinServerButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonsParent.RectTransform), TextManager.Get("JoinServerButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
OnClicked = JoinServerClicked
|
||||
};
|
||||
hostServerButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonsParent.RectTransform), TextManager.Get("HostServerButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
UserData = Tab.HostServer,
|
||||
OnClicked = SelectTab
|
||||
};
|
||||
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), buttonsParent.RectTransform), style: null); //spacing
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonsParent.RectTransform), TextManager.Get("SubEditorButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
OnClicked = (btn, userdata) => { GameMain.SubEditorScreen.Select(); return true; }
|
||||
};
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonsParent.RectTransform), TextManager.Get("CharacterEditorButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
Submarine.MainSub = null;
|
||||
GameMain.CharacterEditorScreen.Select();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
if (Steam.SteamManager.USE_STEAM)
|
||||
{
|
||||
steamWorkshopButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonsParent.RectTransform), TextManager.Get("SteamWorkshopButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
OnClicked = SteamWorkshopClicked
|
||||
};
|
||||
}
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), buttonsParent.RectTransform), style: null); //spacing
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonsParent.RectTransform), TextManager.Get("SettingsButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
UserData = Tab.Settings,
|
||||
OnClicked = SelectTab
|
||||
};
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonsParent.RectTransform), TextManager.Get("QuitButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
OnClicked = QuitClicked
|
||||
};
|
||||
|
||||
|
||||
/* var buttons = GUI.CreateButtons(9, new Vector2(1, 0.04f), buttonsParent.RectTransform, anchor: Anchor.BottomLeft,
|
||||
minSize: minButtonSize, maxSize: maxButtonSize, relativeSpacing: 0.005f, extraSpacing: i => i % 2 == 0 ? 20 : 0);
|
||||
buttons.ForEach(b => b.Color *= 0.8f);
|
||||
SetupButtons(buttons);
|
||||
buttons.ForEach(b => b.TextBlock.SetTextPos());*/
|
||||
|
||||
var relativeSize = new Vector2(0.5f, 0.5f);
|
||||
var minSize = new Point(600, 400);
|
||||
var maxSize = new Point(900, 600);
|
||||
var anchor = Anchor.Center;
|
||||
var pivot = Pivot.Center;
|
||||
menuTabs = new GUIFrame[Enum.GetValues(typeof(Tab)).Length + 1];
|
||||
|
||||
menuTabs[(int)Tab.NewGame] = new GUIFrame(new RectTransform(relativeSize, Frame.RectTransform, anchor, pivot, minSize, maxSize));
|
||||
var paddedNewGame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), menuTabs[(int)Tab.NewGame].RectTransform, Anchor.Center), style: null);
|
||||
menuTabs[(int)Tab.LoadGame] = new GUIFrame(new RectTransform(relativeSize, Frame.RectTransform, anchor, pivot, minSize, maxSize));
|
||||
var paddedLoadGame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), menuTabs[(int)Tab.LoadGame].RectTransform, Anchor.Center), style: null);
|
||||
|
||||
campaignSetupUI = new CampaignSetupUI(false, paddedNewGame, paddedLoadGame)
|
||||
{
|
||||
LoadGame = LoadGame,
|
||||
StartNewGame = StartGame
|
||||
};
|
||||
|
||||
buttonsTab = new GUIFrame(new Rectangle(0, 0, 0, 0), Color.Transparent, Alignment.Left | Alignment.CenterY);
|
||||
buttonsTab.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
|
||||
var hostServerScale = new Vector2(0.7f, 1.0f);
|
||||
menuTabs[(int)Tab.HostServer] = new GUIFrame(new RectTransform(
|
||||
Vector2.Multiply(relativeSize, hostServerScale), Frame.RectTransform, anchor, pivot, minSize.Multiply(hostServerScale), maxSize.Multiply(hostServerScale)));
|
||||
|
||||
int y = (int)(GameMain.GraphicsHeight * 0.3f);
|
||||
|
||||
Rectangle panelRect = new Rectangle(
|
||||
290, y,
|
||||
500, 360);
|
||||
|
||||
GUIButton button = new GUIButton(new Rectangle(50, y, 200, 30), TextManager.Get("TutorialButton"), null, Alignment.TopLeft, Alignment.Left, "", buttonsTab);
|
||||
|
||||
button.Color = button.Color * 0.8f;
|
||||
button.OnClicked = TutorialButtonClicked;
|
||||
|
||||
button = new GUIButton(new Rectangle(50, y + 60, 200, 30), TextManager.Get("NewGameButton"), null, Alignment.TopLeft, Alignment.Left, "", buttonsTab);
|
||||
button.Color = button.Color * 0.8f;
|
||||
button.UserData = Tab.NewGame;
|
||||
button.OnClicked = SelectTab;
|
||||
|
||||
button = new GUIButton(new Rectangle(50, y + 100, 200, 30), TextManager.Get("LoadGameButton"), null, Alignment.TopLeft, Alignment.Left, "", buttonsTab);
|
||||
button.Color = button.Color * 0.8f;
|
||||
button.UserData = Tab.LoadGame;
|
||||
button.OnClicked = SelectTab;
|
||||
|
||||
button = new GUIButton(new Rectangle(50, y + 160, 200, 30), TextManager.Get("JoinServerButton"), null, Alignment.TopLeft, Alignment.Left, "", buttonsTab);
|
||||
button.Color = button.Color * 0.8f;
|
||||
//button.UserData = (int)Tabs.JoinServer;
|
||||
button.OnClicked = JoinServerClicked;
|
||||
|
||||
button = new GUIButton(new Rectangle(50, y + 200, 200, 30), TextManager.Get("HostServerButton"), null, Alignment.TopLeft, Alignment.Left, "", buttonsTab);
|
||||
button.Color = button.Color * 0.8f;
|
||||
button.UserData = Tab.HostServer;
|
||||
button.OnClicked = SelectTab;
|
||||
|
||||
button = new GUIButton(new Rectangle(50, y + 260, 200, 30), TextManager.Get("SubEditorButton"), null, Alignment.TopLeft, Alignment.Left, "", buttonsTab);
|
||||
button.Color = button.Color * 0.8f;
|
||||
button.OnClicked = (GUIButton btn, object userdata) => { GameMain.SubEditorScreen.Select(); return true; };
|
||||
|
||||
button = new GUIButton(new Rectangle(50, y + 320, 200, 30), TextManager.Get("SettingsButton"), null, Alignment.TopLeft, Alignment.Left, "", buttonsTab);
|
||||
button.Color = button.Color * 0.8f;
|
||||
button.UserData = Tab.Settings;
|
||||
button.OnClicked = SelectTab;
|
||||
|
||||
button = new GUIButton(new Rectangle(0, 0, 150, 30), TextManager.Get("QuitButton"), Alignment.BottomRight, "", buttonsTab);
|
||||
button.Color = button.Color * 0.8f;
|
||||
button.OnClicked = QuitClicked;
|
||||
|
||||
panelRect.Y += 10;
|
||||
CreateHostServerFields();
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
menuTabs[(int)Tab.NewGame] = new GUIFrame(panelRect, "");
|
||||
menuTabs[(int)Tab.NewGame].Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
|
||||
menuTabs[(int)Tab.Tutorials] = new GUIFrame(new RectTransform(relativeSize, Frame.RectTransform, anchor, pivot, minSize, maxSize));
|
||||
|
||||
menuTabs[(int)Tab.LoadGame] = new GUIFrame(panelRect, "");
|
||||
//PLACEHOLDER
|
||||
var tutorialList = new GUIListBox(
|
||||
new RectTransform(new Vector2(0.95f, 0.85f), menuTabs[(int)Tab.Tutorials].RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.1f) },
|
||||
false, null, "");
|
||||
foreach (Tutorial tutorial in Tutorial.Tutorials)
|
||||
{
|
||||
var tutorialText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), tutorialList.Content.RectTransform), tutorial.Name, textAlignment: Alignment.Center, font: GUI.LargeFont)
|
||||
{
|
||||
UserData = tutorial
|
||||
};
|
||||
}
|
||||
tutorialList.OnSelected += (component, obj) =>
|
||||
{
|
||||
TutorialMode.StartTutorial(obj as Tutorial);
|
||||
return true;
|
||||
};
|
||||
|
||||
campaignSetupUI = new CampaignSetupUI(false, menuTabs[(int)Tab.NewGame], menuTabs[(int)Tab.LoadGame]);
|
||||
campaignSetupUI.LoadGame = LoadGame;
|
||||
campaignSetupUI.StartNewGame = StartGame;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
menuTabs[(int)Tab.HostServer] = new GUIFrame(panelRect, "");
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 0, 100, 30), TextManager.Get("ServerName"), "", Alignment.TopLeft, Alignment.Left, menuTabs[(int)Tab.HostServer]);
|
||||
serverNameBox = new GUITextBox(new Rectangle(160, 0, 200, 30), null, null, Alignment.TopLeft, Alignment.Left, "", menuTabs[(int)Tab.HostServer]);
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 50, 100, 30), TextManager.Get("ServerPort"), "", Alignment.TopLeft, Alignment.Left, menuTabs[(int)Tab.HostServer]);
|
||||
portBox = new GUITextBox(new Rectangle(160, 50, 200, 30), null, null, Alignment.TopLeft, Alignment.Left, "", menuTabs[(int)Tab.HostServer]);
|
||||
portBox.Text = NetConfig.DefaultPort.ToString();
|
||||
portBox.ToolTip = "Server port";
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 100, 100, 30), TextManager.Get("MaxPlayers"), "", Alignment.TopLeft, Alignment.Left, menuTabs[(int)Tab.HostServer]);
|
||||
maxPlayersBox = new GUITextBox(new Rectangle(195, 100, 30, 30), null, null, Alignment.TopLeft, Alignment.Center, "", menuTabs[(int)Tab.HostServer]);
|
||||
maxPlayersBox.Text = "8";
|
||||
maxPlayersBox.Enabled = false;
|
||||
|
||||
var minusPlayersBox = new GUIButton(new Rectangle(160, 100, 30, 30), "-", "", menuTabs[(int)Tab.HostServer]);
|
||||
minusPlayersBox.UserData = -1;
|
||||
minusPlayersBox.OnClicked = ChangeMaxPlayers;
|
||||
|
||||
var plusPlayersBox = new GUIButton(new Rectangle(230, 100, 30, 30), "+", "", menuTabs[(int)Tab.HostServer]);
|
||||
plusPlayersBox.UserData = 1;
|
||||
plusPlayersBox.OnClicked = ChangeMaxPlayers;
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 150, 100, 30), TextManager.Get("Password"), "", Alignment.TopLeft, Alignment.Left, menuTabs[(int)Tab.HostServer]);
|
||||
passwordBox = new GUITextBox(new Rectangle(160, 150, 200, 30), null, null, Alignment.TopLeft, Alignment.Left, "", menuTabs[(int)Tab.HostServer]);
|
||||
|
||||
isPublicBox = new GUITickBox(new Rectangle(10, 200, 20, 20), TextManager.Get("PublicServer"), Alignment.TopLeft, menuTabs[(int)Tab.HostServer]);
|
||||
isPublicBox.ToolTip = TextManager.Get("PublicServerToolTip");
|
||||
|
||||
useUpnpBox = new GUITickBox(new Rectangle(10, 250, 20, 20), TextManager.Get("AttemptUPnP"), Alignment.TopLeft, menuTabs[(int)Tab.HostServer]);
|
||||
useUpnpBox.ToolTip = TextManager.Get("AttemptUPnPToolTip");
|
||||
|
||||
GUIButton hostButton = new GUIButton(new Rectangle(0, 0, 100, 30), TextManager.Get("StartServerButton"), Alignment.BottomRight, "", menuTabs[(int)Tab.HostServer]);
|
||||
hostButton.OnClicked = HostServerClicked;
|
||||
UpdateTutorialList();
|
||||
|
||||
this.game = game;
|
||||
}
|
||||
@@ -139,6 +248,8 @@ namespace Barotrauma
|
||||
|
||||
Submarine.Unload();
|
||||
|
||||
UpdateTutorialList();
|
||||
|
||||
campaignSetupUI.UpdateSubList();
|
||||
|
||||
SelectTab(null, 0);
|
||||
@@ -148,18 +259,18 @@ namespace Barotrauma
|
||||
|
||||
public bool SelectTab(GUIButton button, object obj)
|
||||
{
|
||||
try
|
||||
if (obj is Tab)
|
||||
{
|
||||
SelectTab((Tab)obj);
|
||||
}
|
||||
catch
|
||||
{
|
||||
else
|
||||
{
|
||||
selectedTab = 0;
|
||||
}
|
||||
|
||||
if (button != null) button.Selected = true;
|
||||
|
||||
foreach (GUIComponent child in buttonsTab.children)
|
||||
|
||||
foreach (GUIComponent child in buttonsParent.Children)
|
||||
{
|
||||
GUIButton otherButton = child as GUIButton;
|
||||
if (otherButton == null || otherButton == button) continue;
|
||||
@@ -196,6 +307,7 @@ namespace Barotrauma
|
||||
{
|
||||
case Tab.NewGame:
|
||||
campaignSetupUI.CreateDefaultSaveName();
|
||||
campaignSetupUI.UpdateTutorialSelection();
|
||||
break;
|
||||
case Tab.LoadGame:
|
||||
campaignSetupUI.UpdateLoadMenu();
|
||||
@@ -207,16 +319,28 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTutorialList()
|
||||
{
|
||||
var tutorialList = menuTabs[(int)Tab.Tutorials].GetChild<GUIListBox>();
|
||||
foreach (GUITextBlock tutorialText in tutorialList.Content.Children)
|
||||
{
|
||||
if (((Tutorial)tutorialText.UserData).Completed)
|
||||
{
|
||||
tutorialText.TextColor = Color.LightGreen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ApplySettings(GUIButton button, object userData)
|
||||
{
|
||||
GameMain.Config.Save("config.xml");
|
||||
|
||||
if (userData is Tab) SelectTab((Tab)userData);
|
||||
GameMain.Config.Save();
|
||||
|
||||
if (userData is Tab) SelectTab((Tab)userData);
|
||||
|
||||
if (GameMain.GraphicsWidth != GameMain.Config.GraphicsWidth || GameMain.GraphicsHeight != GameMain.Config.GraphicsHeight)
|
||||
{
|
||||
new GUIMessageBox(
|
||||
TextManager.Get("RestartRequiredLabel"),
|
||||
TextManager.Get("RestartRequiredLabel"),
|
||||
TextManager.Get("RestartRequiredText"));
|
||||
}
|
||||
|
||||
@@ -230,27 +354,22 @@ namespace Barotrauma
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private bool TutorialButtonClicked(GUIButton button, object obj)
|
||||
|
||||
private bool JoinServerClicked(GUIButton button, object obj)
|
||||
{
|
||||
//!!!!!!!!!!!!!!!!!! placeholder
|
||||
TutorialMode.StartTutorial(Tutorials.TutorialType.TutorialTypes[0]);
|
||||
|
||||
GameMain.ServerListScreen.Select();
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool JoinServerClicked(GUIButton button, object obj)
|
||||
{
|
||||
GameMain.ServerListScreen.Select();
|
||||
private bool SteamWorkshopClicked(GUIButton button, object obj)
|
||||
{
|
||||
GameMain.SteamWorkshopScreen.Select();
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ChangeMaxPlayers(GUIButton button, object obj)
|
||||
{
|
||||
int currMaxPlayers = 8;
|
||||
|
||||
int.TryParse(maxPlayersBox.Text, out currMaxPlayers);
|
||||
int.TryParse(maxPlayersBox.Text, out int currMaxPlayers);
|
||||
currMaxPlayers = (int)MathHelper.Clamp(currMaxPlayers + (int)button.UserData, 1, NetConfig.MaxPlayers);
|
||||
|
||||
maxPlayersBox.Text = currMaxPlayers.ToString();
|
||||
@@ -267,8 +386,7 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
int port;
|
||||
if (!int.TryParse(portBox.Text, out port) || port < 0 || port > 65535)
|
||||
if (!int.TryParse(portBox.Text, out int port) || port < 0 || port > 65535)
|
||||
{
|
||||
portBox.Text = NetConfig.DefaultPort.ToString();
|
||||
portBox.Flash();
|
||||
@@ -276,11 +394,21 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
GameMain.NetLobbyScreen = new NetLobbyScreen();
|
||||
int queryPort = 0;
|
||||
if (Steam.SteamManager.USE_STEAM)
|
||||
{
|
||||
if (!int.TryParse(queryPortBox.Text, out queryPort) || queryPort < 0 || queryPort > 65535)
|
||||
{
|
||||
portBox.Text = NetConfig.DefaultQueryPort.ToString();
|
||||
portBox.Flash();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
GameMain.NetLobbyScreen = new NetLobbyScreen();
|
||||
try
|
||||
{
|
||||
GameMain.NetworkMember = new GameServer(name, port, isPublicBox.Selected, passwordBox.Text, useUpnpBox.Selected, int.Parse(maxPlayersBox.Text));
|
||||
GameMain.NetworkMember = new GameServer(name, port, queryPort, isPublicBox.Selected, passwordBox.Text, useUpnpBox.Selected, int.Parse(maxPlayersBox.Text));
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
@@ -289,35 +417,43 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
GameMain.NetLobbyScreen.IsServer = true;
|
||||
//Game1.NetLobbyScreen.Select();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private bool QuitClicked(GUIButton button, object obj)
|
||||
{
|
||||
game.Exit();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
buttonsTab.AddToGUIUpdateList();
|
||||
if (selectedTab > 0) menuTabs[(int)selectedTab].AddToGUIUpdateList();
|
||||
Frame.AddToGUIUpdateList(ignoreChildren: true);
|
||||
buttonsParent.AddToGUIUpdateList();
|
||||
if (selectedTab > 0)
|
||||
{
|
||||
menuTabs[(int)selectedTab].AddToGUIUpdateList();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
buttonsTab.Update((float)deltaTime);
|
||||
|
||||
if (selectedTab>0) menuTabs[(int)selectedTab].Update((float)deltaTime);
|
||||
|
||||
GameMain.TitleScreen.TitlePosition =
|
||||
Vector2.Lerp(GameMain.TitleScreen.TitlePosition, new Vector2(
|
||||
GameMain.TitleScreen.TitleSize.X / 2.0f * GameMain.TitleScreen.Scale + 30.0f,
|
||||
GameMain.TitleScreen.TitleSize.Y / 2.0f * GameMain.TitleScreen.Scale + 30.0f),
|
||||
0.1f);
|
||||
GameMain.TitleScreen.TitleSize.Y / 2.0f * GameMain.TitleScreen.Scale + 30.0f),
|
||||
0.1f);
|
||||
#if !DEBUG
|
||||
if (Steam.SteamManager.USE_STEAM)
|
||||
{
|
||||
if (GameMain.Config.UseSteamMatchmaking)
|
||||
{
|
||||
joinServerButton.Enabled = Steam.SteamManager.IsInitialized;
|
||||
hostServerButton.Enabled = Steam.SteamManager.IsInitialized;
|
||||
}
|
||||
steamWorkshopButton.Enabled = Steam.SteamManager.IsInitialized;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||
@@ -327,15 +463,10 @@ namespace Barotrauma
|
||||
GameMain.TitleScreen.DrawLoadingText = false;
|
||||
GameMain.TitleScreen.Draw(spriteBatch, graphics, (float)deltaTime);
|
||||
|
||||
//Game1.GameScreen.DrawMap(graphics, spriteBatch);
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, GameMain.ScissorTestEnable);
|
||||
|
||||
buttonsTab.Draw(spriteBatch);
|
||||
if (selectedTab>0) menuTabs[(int)selectedTab].Draw(spriteBatch);
|
||||
|
||||
GUI.Draw((float)deltaTime, spriteBatch, null);
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, GameMain.ScissorTestEnable);
|
||||
|
||||
GUI.Draw(Cam, spriteBatch);
|
||||
|
||||
#if DEBUG
|
||||
GUI.Font.DrawString(spriteBatch, "Barotrauma v" + GameMain.Version + " (debug build)", new Vector2(10, GameMain.GraphicsHeight - 20), Color.White);
|
||||
#else
|
||||
@@ -356,7 +487,7 @@ namespace Barotrauma
|
||||
new GUIMessageBox("Save name already in use", "Please choose another name for the save file");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (selectedSub == null)
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("SubNotSelected"), TextManager.Get("SelectSubRequest"));
|
||||
@@ -384,23 +515,26 @@ namespace Barotrauma
|
||||
|
||||
selectedSub = new Submarine(Path.Combine(SaveUtil.TempPath, selectedSub.Name + ".sub"), "");
|
||||
|
||||
GameMain.GameSession = new GameSession(selectedSub, saveName, GameModePreset.list.Find(gm => gm.Name == "Single Player"));
|
||||
ContextualTutorial.Selected = campaignSetupUI.TutorialSelected;
|
||||
GameMain.GameSession = new GameSession(selectedSub, saveName,
|
||||
GameModePreset.List.Find(g => g.Identifier == "singleplayercampaign"));
|
||||
(GameMain.GameSession.GameMode as CampaignMode).GenerateMap(mapSeed);
|
||||
|
||||
|
||||
GameMain.LobbyScreen.Select();
|
||||
}
|
||||
|
||||
|
||||
private void LoadGame(string saveFile)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(saveFile)) return;
|
||||
|
||||
try
|
||||
{
|
||||
SaveUtil.LoadGame(saveFile);
|
||||
SaveUtil.LoadGame(saveFile);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Loading save \""+saveFile+"\" failed", e);
|
||||
DebugConsole.ThrowError("Loading save \"" + saveFile + "\" failed", e);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -408,5 +542,89 @@ namespace Barotrauma
|
||||
GameMain.LobbyScreen.Select();
|
||||
}
|
||||
|
||||
#region UI Methods
|
||||
|
||||
private void CreateHostServerFields()
|
||||
{
|
||||
Vector2 textLabelSize = new Vector2(1.0f, 0.1f);
|
||||
Alignment textAlignment = Alignment.CenterLeft;
|
||||
Vector2 textFieldSize = new Vector2(0.5f, 1.0f);
|
||||
Vector2 tickBoxSize = new Vector2(0.4f, 0.07f);
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.85f, 0.75f), menuTabs[(int)Tab.HostServer].RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.05f) })
|
||||
{
|
||||
RelativeSpacing = 0.02f,
|
||||
Stretch = true
|
||||
};
|
||||
GUIComponent parent = paddedFrame;
|
||||
|
||||
new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("HostServerButton"), textAlignment: Alignment.Center, font: GUI.LargeFont);
|
||||
|
||||
var label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerName"), textAlignment: textAlignment);
|
||||
serverNameBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment);
|
||||
|
||||
label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerPort"), textAlignment: textAlignment);
|
||||
portBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment)
|
||||
{
|
||||
Text = NetConfig.DefaultPort.ToString(),
|
||||
ToolTip = TextManager.Get("ServerPortToolTip")
|
||||
};
|
||||
|
||||
if (Steam.SteamManager.USE_STEAM)
|
||||
{
|
||||
label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerQueryPort"), textAlignment: textAlignment);
|
||||
queryPortBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment)
|
||||
{
|
||||
Text = NetConfig.DefaultQueryPort.ToString(),
|
||||
ToolTip = TextManager.Get("ServerQueryPortToolTip")
|
||||
};
|
||||
}
|
||||
|
||||
var maxPlayersLabel = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("MaxPlayers"), textAlignment: textAlignment);
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(textFieldSize, maxPlayersLabel.RectTransform, Anchor.CenterRight), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.1f
|
||||
};
|
||||
new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonContainer.RectTransform), "-", textAlignment: Alignment.Center)
|
||||
{
|
||||
UserData = -1,
|
||||
OnClicked = ChangeMaxPlayers
|
||||
};
|
||||
|
||||
maxPlayersBox = new GUITextBox(new RectTransform(new Vector2(0.6f, 1.0f), buttonContainer.RectTransform), textAlignment: Alignment.Center)
|
||||
{
|
||||
Text = "8",
|
||||
Enabled = false
|
||||
};
|
||||
new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonContainer.RectTransform), "+", textAlignment: Alignment.Center)
|
||||
{
|
||||
UserData = 1,
|
||||
OnClicked = ChangeMaxPlayers
|
||||
};
|
||||
|
||||
label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("Password"), textAlignment: textAlignment);
|
||||
passwordBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment);
|
||||
|
||||
isPublicBox = new GUITickBox(new RectTransform(tickBoxSize, parent.RectTransform), TextManager.Get("PublicServer"))
|
||||
{
|
||||
ToolTip = TextManager.Get("PublicServerToolTip")
|
||||
};
|
||||
|
||||
useUpnpBox = new GUITickBox(new RectTransform(tickBoxSize, parent.RectTransform), TextManager.Get("AttemptUPnP"))
|
||||
{
|
||||
ToolTip = TextManager.Get("AttemptUPnPToolTip")
|
||||
};
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(0.4f, 0.1f), menuTabs[(int)Tab.HostServer].RectTransform, Anchor.BottomRight)
|
||||
{
|
||||
RelativeOffset = new Vector2(0.05f, 0.05f)
|
||||
}, TextManager.Get("StartServerButton"), style: "GUIButtonLarge")
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
OnClicked = HostServerClicked
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,333 @@
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Dynamics.Joints;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class OldCharacterEditorScreen : Screen
|
||||
{
|
||||
private Camera cam;
|
||||
|
||||
private GUIComponent GUIpanel;
|
||||
private GUIButton physicsButton;
|
||||
|
||||
private GUIListBox limbList, jointList;
|
||||
|
||||
private GUIFrame limbPanel;
|
||||
|
||||
private Character editingCharacter;
|
||||
private Limb editingLimb;
|
||||
|
||||
private List<Texture2D> textures;
|
||||
private List<string> texturePaths;
|
||||
|
||||
private bool physicsEnabled;
|
||||
|
||||
public override Camera Cam
|
||||
{
|
||||
get { return cam; }
|
||||
}
|
||||
|
||||
public override void Select()
|
||||
{
|
||||
base.Select();
|
||||
|
||||
GameMain.DebugDraw = true;
|
||||
|
||||
cam = new Camera();
|
||||
|
||||
/*GUIpanel = new GUIFrame(new Rectangle(0, 0, 300, GameMain.GraphicsHeight), "");
|
||||
//GUIpanel.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
|
||||
|
||||
physicsButton = new GUIButton(new Rectangle(0, 50, 200, 25), "Physics", Alignment.Left, "", GUIpanel);
|
||||
physicsButton.OnClicked += TogglePhysics;
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 80, 0, 25), "Limbs:", "", GUIpanel);
|
||||
limbList = new GUIListBox(new Rectangle(0, 110, 0, 250), Color.White * 0.7f, "", GUIpanel);
|
||||
limbList.OnSelected = SelectLimb;
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 360, 0, 25), "Joints:", "", GUIpanel);
|
||||
jointList = new GUIListBox(new Rectangle(0, 390, 0, 250), Color.White * 0.7f, "", GUIpanel);*/
|
||||
|
||||
while (Character.CharacterList.Count > 1)
|
||||
{
|
||||
Character.CharacterList.First().Remove();
|
||||
}
|
||||
|
||||
if (Character.CharacterList.Count == 1)
|
||||
{
|
||||
if (editingCharacter != Character.CharacterList[0]) UpdateLimbLists(Character.CharacterList[0]);
|
||||
editingCharacter = Character.CharacterList[0];
|
||||
|
||||
Vector2 camPos = editingCharacter.AnimController.Limbs[0].body.SimPosition;
|
||||
camPos = ConvertUnits.ToDisplayUnits(camPos);
|
||||
camPos.Y = -camPos.Y;
|
||||
cam.TargetPos = camPos;
|
||||
|
||||
if (physicsEnabled)
|
||||
{
|
||||
editingCharacter.Control(1.0f, cam);
|
||||
}
|
||||
else
|
||||
{
|
||||
cam.TargetPos = Vector2.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
textures = new List<Texture2D>();
|
||||
texturePaths = new List<string>();
|
||||
foreach (Limb limb in editingCharacter.AnimController.Limbs)
|
||||
{
|
||||
if (limb.ActiveSprite==null || texturePaths.Contains(limb.ActiveSprite.FilePath)) continue;
|
||||
textures.Add(limb.ActiveSprite.Texture);
|
||||
texturePaths.Add(limb.ActiveSprite.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows the game to run logic such as updating the world,
|
||||
/// checking for collisions, gathering input, and playing audio.
|
||||
/// </summary>
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
cam.MoveCamera((float)deltaTime);
|
||||
|
||||
GUIpanel.UpdateManually((float)deltaTime);
|
||||
|
||||
if (physicsEnabled)
|
||||
{
|
||||
Character.UpdateAnimAll((float)deltaTime);
|
||||
|
||||
Ragdoll.UpdateAll((float)deltaTime, cam);
|
||||
|
||||
GameMain.World.Step((float)deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
GUIpanel.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called when the game should draw itself.
|
||||
/// </summary>
|
||||
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||
{
|
||||
//cam.UpdateTransform();
|
||||
|
||||
graphics.Clear(Color.CornflowerBlue);
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.BackToFront,
|
||||
BlendState.AlphaBlend,
|
||||
null, null, null, null,
|
||||
cam.Transform);
|
||||
|
||||
Submarine.Draw(spriteBatch, true);
|
||||
|
||||
spriteBatch.End();
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.BackToFront,
|
||||
BlendState.AlphaBlend,
|
||||
null, null, null, null,
|
||||
cam.Transform);
|
||||
|
||||
//if (EntityPrefab.Selected != null) EntityPrefab.Selected.UpdatePlacing(spriteBatch, cam);
|
||||
|
||||
//Entity.DrawSelecting(spriteBatch, cam);
|
||||
|
||||
if (editingCharacter!=null)
|
||||
editingCharacter.Draw(spriteBatch, Cam);
|
||||
|
||||
spriteBatch.End();
|
||||
|
||||
//-------------------- HUD -----------------------------
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, GameMain.ScissorTestEnable);
|
||||
|
||||
GUIpanel.DrawManually(spriteBatch);
|
||||
|
||||
EditLimb(spriteBatch);
|
||||
|
||||
|
||||
int y = 0;
|
||||
for (int i = 0; i < textures.Count; i++ )
|
||||
{
|
||||
int x = GameMain.GraphicsWidth - textures[i].Width;
|
||||
spriteBatch.Draw(textures[i], new Vector2(x, y), Color.White);
|
||||
|
||||
foreach (Limb limb in editingCharacter.AnimController.Limbs)
|
||||
{
|
||||
if (limb.ActiveSprite == null || limb.ActiveSprite.FilePath != texturePaths[i]) continue;
|
||||
Rectangle rect = limb.ActiveSprite.SourceRect;
|
||||
rect.X += x;
|
||||
rect.Y += y;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, rect, Color.Red);
|
||||
|
||||
Vector2 limbBodyPos = new Vector2(
|
||||
rect.X + limb.ActiveSprite.Origin.X,
|
||||
rect.Y + limb.ActiveSprite.Origin.Y);
|
||||
|
||||
DrawJoints(spriteBatch, limb, limbBodyPos);
|
||||
|
||||
//if (limb.BodyShapeTexture == null) continue;
|
||||
|
||||
//spriteBatch.Draw(limb.BodyShapeTexture, limbBodyPos,
|
||||
// null, Color.White, 0.0f,
|
||||
// new Vector2(limb.BodyShapeTexture.Width, limb.BodyShapeTexture.Height) / 2,
|
||||
// 1.0f, SpriteEffects.None, 0.0f);
|
||||
|
||||
GUI.DrawLine(spriteBatch, limbBodyPos + Vector2.UnitY * 5.0f, limbBodyPos - Vector2.UnitY * 5.0f, Color.White);
|
||||
GUI.DrawLine(spriteBatch, limbBodyPos + Vector2.UnitX * 5.0f, limbBodyPos - Vector2.UnitX * 5.0f, Color.White);
|
||||
|
||||
if (Vector2.Distance(PlayerInput.MousePosition, limbBodyPos)<5.0f && PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
limb.ActiveSprite.Origin += PlayerInput.MouseSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
y += textures[i].Height;
|
||||
}
|
||||
|
||||
|
||||
GUI.Draw(Cam, spriteBatch);
|
||||
|
||||
//EntityPrefab.DrawList(spriteBatch, new Vector2(20,50));
|
||||
|
||||
//Entity.Edit(spriteBatch, cam);
|
||||
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
private void UpdateLimbLists(Character character)
|
||||
{
|
||||
limbList.ClearChildren();
|
||||
/*foreach (Limb limb in character.AnimController.Limbs)
|
||||
{
|
||||
GUITextBlock textBlock = new GUITextBlock(
|
||||
new Rectangle(0,0,0,25),
|
||||
limb.type.ToString(),
|
||||
Color.Transparent,
|
||||
Color.White,
|
||||
Alignment.Left, null,
|
||||
limbList);
|
||||
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
|
||||
textBlock.UserData = limb;
|
||||
}
|
||||
|
||||
jointList.ClearChildren();
|
||||
foreach (RevoluteJoint joint in character.AnimController.LimbJoints)
|
||||
{
|
||||
Limb limb1 = (Limb)(joint.BodyA.UserData);
|
||||
Limb limb2 = (Limb)(joint.BodyB.UserData);
|
||||
|
||||
GUITextBlock textBlock = new GUITextBlock(
|
||||
new Rectangle(0, 0, 0, 25),
|
||||
limb1.type.ToString() + " - " + limb2.type.ToString(),
|
||||
Color.Transparent,
|
||||
Color.White,
|
||||
Alignment.Left, null,
|
||||
jointList);
|
||||
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
|
||||
textBlock.UserData = joint;
|
||||
}*/
|
||||
}
|
||||
|
||||
private void DrawJoints(SpriteBatch spriteBatch, Limb limb, Vector2 limbBodyPos)
|
||||
{
|
||||
foreach (var joint in editingCharacter.AnimController.LimbJoints)
|
||||
{
|
||||
Vector2 jointPos = Vector2.Zero;
|
||||
|
||||
if (joint.BodyA == limb.body.FarseerBody)
|
||||
{
|
||||
jointPos = ConvertUnits.ToDisplayUnits(joint.LocalAnchorA);
|
||||
|
||||
}
|
||||
else if (joint.BodyB == limb.body.FarseerBody)
|
||||
{
|
||||
jointPos = ConvertUnits.ToDisplayUnits(joint.LocalAnchorB);
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector2 tformedJointPos = jointPos /= limb.Scale;
|
||||
tformedJointPos.Y = -tformedJointPos.Y;
|
||||
tformedJointPos += limbBodyPos;
|
||||
|
||||
if (joint.BodyA == limb.body.FarseerBody)
|
||||
{
|
||||
float a1 = joint.UpperLimit - MathHelper.PiOver2;
|
||||
float a2 = joint.LowerLimit - MathHelper.PiOver2;
|
||||
float a3 = (a1 + a2) / 2.0f;
|
||||
GUI.DrawLine(spriteBatch, tformedJointPos, tformedJointPos + new Vector2((float)Math.Cos(a1), -(float)Math.Sin(a1)) * 30.0f, Color.Green);
|
||||
GUI.DrawLine(spriteBatch, tformedJointPos, tformedJointPos + new Vector2((float)Math.Cos(a2), -(float)Math.Sin(a2)) * 30.0f, Color.DarkGreen);
|
||||
|
||||
GUI.DrawLine(spriteBatch, tformedJointPos, tformedJointPos + new Vector2((float)Math.Cos(a3), -(float)Math.Sin(a3)) * 30.0f, Color.LightGray);
|
||||
}
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, tformedJointPos, new Vector2(5.0f, 5.0f), Color.Red, true);
|
||||
if (Vector2.Distance(PlayerInput.MousePosition, tformedJointPos) < 10.0f)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, tformedJointPos + Vector2.One*10.0f, jointPos.ToString(), Color.White, Color.Black * 0.5f);
|
||||
GUI.DrawRectangle(spriteBatch, tformedJointPos - new Vector2(3.0f, 3.0f), new Vector2(11.0f, 11.0f), Color.Red, false);
|
||||
if (PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
Vector2 speed = ConvertUnits.ToSimUnits(PlayerInput.MouseSpeed);
|
||||
speed.Y = -speed.Y;
|
||||
if (joint.BodyA == limb.body.FarseerBody)
|
||||
{
|
||||
joint.LocalAnchorA += speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
joint.LocalAnchorB += speed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool SelectLimb(GUIComponent component, object selection)
|
||||
{
|
||||
/*try
|
||||
{
|
||||
editingLimb = (Limb)selection;
|
||||
limbPanel = new GUIFrame(new Rectangle(300, 0, 500, 100), Color.Gray*0.8f);
|
||||
//limbPanel.Padding = new Vector4(10.0f,10.0f,10.0f,10.0f);
|
||||
new GUITextBlock(new Rectangle(0, 0, 200, 25), editingLimb.type.ToString(), Color.Transparent, Color.Black, Alignment.Left, null, limbPanel);
|
||||
|
||||
//spriteOrigin = new GUITextBlock(new Rectangle(0, 25, 200, 25), "Sprite origin: ", Color.White, Color.Black, Alignment.Left, limbPanel);
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}*/
|
||||
return true;
|
||||
}
|
||||
|
||||
private void EditLimb(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (editingLimb == null) return;
|
||||
|
||||
limbPanel.DrawManually(spriteBatch);
|
||||
}
|
||||
|
||||
private bool TogglePhysics(GUIButton button, object selection)
|
||||
{
|
||||
physicsEnabled = !physicsEnabled;
|
||||
|
||||
physicsButton.Text = (physicsEnabled) ? "Disable physics" : "Enable physics";
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private GUIComponent guiRoot;
|
||||
private GUIComponent rightPanel, leftPanel;
|
||||
|
||||
private GUIListBox prefabList;
|
||||
@@ -86,39 +85,57 @@ namespace Barotrauma
|
||||
{
|
||||
cam = new Camera();
|
||||
|
||||
guiRoot = new GUIFrame(Rectangle.Empty, null, null);
|
||||
|
||||
leftPanel = new GUIFrame(new Rectangle(0, 0, 150, GameMain.GraphicsHeight), "GUIFrameLeft", guiRoot);
|
||||
leftPanel.Padding = new Vector4(10.0f, 20.0f, 10.0f, 20.0f);
|
||||
|
||||
rightPanel = new GUIFrame(new Rectangle(0, 0, 450, GameMain.GraphicsHeight), null, Alignment.Right, "GUIFrameRight", guiRoot);
|
||||
rightPanel.Padding = new Vector4(10.0f, 20.0f, 0.0f, 20.0f);
|
||||
|
||||
var saveAllButton = new GUIButton(new Rectangle(leftPanel.Rect.Right + 20, 10, 150, 20), "Save all", "", guiRoot);
|
||||
saveAllButton.OnClicked += (btn, obj) =>
|
||||
leftPanel = new GUIFrame(new RectTransform(new Vector2(0.07f, 1.0f), Frame.RectTransform) { MinSize = new Point(150,0) },
|
||||
style: "GUIFrameLeft");
|
||||
var paddedLeftPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), leftPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.02f, 0.0f) })
|
||||
{
|
||||
SerializeAll();
|
||||
return true;
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
var serializeToClipBoardButton = new GUIButton(new Rectangle(leftPanel.Rect.Right + 20, 10, 150, 20), "Copy to clipboard", "", guiRoot);
|
||||
serializeToClipBoardButton.OnClicked += (btn, obj) =>
|
||||
rightPanel = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), Frame.RectTransform, Anchor.TopRight) { MinSize = new Point(450, 0) },
|
||||
style: "GUIFrameRight");
|
||||
var paddedRightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), rightPanel.RectTransform, Anchor.Center) {RelativeOffset = new Vector2(0.02f, 0.0f) })
|
||||
{
|
||||
SerializeToClipboard(selectedPrefab);
|
||||
return true;
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.01f
|
||||
};
|
||||
|
||||
var saveAllButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.03f), paddedRightPanel.RectTransform),
|
||||
TextManager.Get("ParticleEditorSaveAll"))
|
||||
{
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
SerializeAll();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var serializeToClipBoardButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.03f), paddedRightPanel.RectTransform),
|
||||
TextManager.Get("ParticleEditorCopyToClipboard"))
|
||||
{
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
SerializeToClipboard(selectedPrefab);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
emitter = new Emitter();
|
||||
var emitterEditor = new SerializableEntityEditor(emitter, false, rightPanel, true);
|
||||
var emitterEditorContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), paddedRightPanel.RectTransform), style: null);
|
||||
var emitterEditor = new SerializableEntityEditor(emitterEditorContainer.RectTransform, emitter, false, true, elementHeight: 20);
|
||||
emitterEditor.RectTransform.RelativeSize = Vector2.One;
|
||||
emitterEditorContainer.RectTransform.Resize(new Point(emitterEditorContainer.RectTransform.NonScaledSize.X, emitterEditor.ContentHeight), false);
|
||||
|
||||
var listBox = new GUIListBox(new Rectangle(0, emitterEditor.Rect.Height + 20, 0, 0), "", rightPanel);
|
||||
var listBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.6f), paddedRightPanel.RectTransform));
|
||||
|
||||
prefabList = new GUIListBox(new Rectangle(0, 50, 0, 0), "", leftPanel);
|
||||
prefabList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.8f), paddedLeftPanel.RectTransform));
|
||||
prefabList.OnSelected += (GUIComponent component, object obj) =>
|
||||
{
|
||||
selectedPrefab = obj as ParticlePrefab;
|
||||
listBox.ClearChildren();
|
||||
particlePrefabEditor = new SerializableEntityEditor(selectedPrefab, false, listBox, true);
|
||||
particlePrefabEditor = new SerializableEntityEditor(listBox.Content.RectTransform, selectedPrefab, false, true, elementHeight: 20);
|
||||
//listBox.Content.RectTransform.NonScaledSize = particlePrefabEditor.RectTransform.NonScaledSize;
|
||||
//listBox.UpdateScrollBarSize();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
@@ -126,9 +143,16 @@ namespace Barotrauma
|
||||
public override void Select()
|
||||
{
|
||||
base.Select();
|
||||
GameMain.ParticleManager.Camera = cam;
|
||||
RefreshPrefabList();
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
{
|
||||
base.Deselect();
|
||||
GameMain.ParticleManager.Camera = GameMain.GameScreen.Cam;
|
||||
}
|
||||
|
||||
private void RefreshPrefabList()
|
||||
{
|
||||
prefabList.ClearChildren();
|
||||
@@ -136,17 +160,15 @@ namespace Barotrauma
|
||||
var particlePrefabs = GameMain.ParticleManager.GetPrefabList();
|
||||
foreach (ParticlePrefab particlePrefab in particlePrefabs)
|
||||
{
|
||||
var prefabText = new GUITextBlock(new Rectangle(0, 0, 0, 20), particlePrefab.Name, "", prefabList);
|
||||
prefabText.Padding = Vector4.Zero;
|
||||
prefabText.UserData = particlePrefab;
|
||||
var prefabText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), prefabList.Content.RectTransform) { MinSize = new Point(0, 20) },
|
||||
particlePrefab.Name)
|
||||
{
|
||||
Padding = Vector4.Zero,
|
||||
UserData = particlePrefab
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
guiRoot.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
private void Emit(Vector2 position)
|
||||
{
|
||||
float angle = MathHelper.ToRadians(Rand.Range(emitter.AngleRange.X, emitter.AngleRange.Y));
|
||||
@@ -162,7 +184,7 @@ namespace Barotrauma
|
||||
|
||||
private void SerializeAll()
|
||||
{
|
||||
foreach (string configFile in GameMain.Config.SelectedContentPackage.GetFilesOfType(ContentType.Particles))
|
||||
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.Particles))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(configFile);
|
||||
if (doc == null || doc.Root == null) continue;
|
||||
@@ -216,10 +238,8 @@ namespace Barotrauma
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
cam.MoveCamera((float)deltaTime, true, GUIComponent.MouseOn == null);
|
||||
|
||||
guiRoot.Update((float)deltaTime);
|
||||
|
||||
cam.MoveCamera((float)deltaTime, true, GUI.MouseOn == null);
|
||||
|
||||
if (selectedPrefab != null)
|
||||
{
|
||||
emitter.EmitTimer += (float)deltaTime;
|
||||
@@ -257,7 +277,7 @@ namespace Barotrauma
|
||||
|
||||
//-------------------------------------------------------
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.BackToFront,
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred,
|
||||
BlendState.AlphaBlend,
|
||||
null, null, null, null,
|
||||
cam.Transform);
|
||||
@@ -269,7 +289,7 @@ namespace Barotrauma
|
||||
|
||||
spriteBatch.End();
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.BackToFront,
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred,
|
||||
BlendState.Additive,
|
||||
null, null, null, null,
|
||||
cam.Transform);
|
||||
@@ -281,11 +301,9 @@ namespace Barotrauma
|
||||
|
||||
//-------------------------------------------------------
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, GameMain.ScissorTestEnable);
|
||||
|
||||
guiRoot.Draw(spriteBatch);
|
||||
|
||||
GUI.Draw((float)deltaTime, spriteBatch, cam);
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, GameMain.ScissorTestEnable);
|
||||
|
||||
GUI.Draw(Cam, spriteBatch);
|
||||
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
@@ -7,8 +7,28 @@ namespace Barotrauma
|
||||
{
|
||||
partial class Screen
|
||||
{
|
||||
private GUIFrame frame;
|
||||
public GUIFrame Frame
|
||||
{
|
||||
get
|
||||
{
|
||||
if (frame == null)
|
||||
{
|
||||
frame = new GUIFrame(new RectTransform(Vector2.One, GUICanvas.Instance), style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// By default, creates a new frame for the screen and adds all elements to the gui update list.
|
||||
/// </summary>
|
||||
public virtual void AddToGUIUpdateList()
|
||||
{
|
||||
Frame.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public virtual void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||
@@ -43,26 +63,6 @@ namespace Barotrauma
|
||||
GUI.ScreenOverlayColor = to;
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
protected void DrawSubmarineIndicator(SpriteBatch spriteBatch, Submarine submarine, Color color)
|
||||
{
|
||||
Vector2 subDiff = submarine.WorldPosition - Cam.WorldViewCenter;
|
||||
|
||||
if (Math.Abs(subDiff.X) > Cam.WorldView.Width || Math.Abs(subDiff.Y) > Cam.WorldView.Height)
|
||||
{
|
||||
Vector2 normalizedSubDiff = Vector2.Normalize(subDiff);
|
||||
|
||||
Vector2 iconPos =
|
||||
Cam.WorldToScreen(Cam.WorldViewCenter) +
|
||||
new Vector2(normalizedSubDiff.X * GameMain.GraphicsWidth * 0.4f, -normalizedSubDiff.Y * GameMain.GraphicsHeight * 0.4f);
|
||||
|
||||
GUI.SubmarineIcon.Draw(spriteBatch, iconPos, color);
|
||||
|
||||
Vector2 arrowOffset = normalizedSubDiff * GUI.SubmarineIcon.size.X * 0.7f;
|
||||
arrowOffset.Y = -arrowOffset.Y;
|
||||
GUI.Arrow.Draw(spriteBatch, iconPos + arrowOffset, color, MathUtils.VectorToAngle(arrowOffset) + MathHelper.PiOver2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,21 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Steam;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using RestSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class ServerListScreen : Screen
|
||||
{
|
||||
struct ServerInfo
|
||||
{
|
||||
public string IP;
|
||||
public string Port;
|
||||
public string ServerName;
|
||||
public bool GameStarted;
|
||||
public int PlayerCount;
|
||||
public int MaxPlayers;
|
||||
public bool HasPassword;
|
||||
}
|
||||
|
||||
//how often the client is allowed to refresh servers
|
||||
private TimeSpan AllowedRefreshInterval = new TimeSpan(0, 0, 3);
|
||||
|
||||
@@ -35,18 +30,19 @@ namespace Barotrauma
|
||||
private bool masterServerResponded;
|
||||
private IRestResponse masterServerResponse;
|
||||
|
||||
private int[] columnX;
|
||||
private float[] columnRelativeWidth;
|
||||
|
||||
//filters
|
||||
private GUITextBox searchBox;
|
||||
private GUITickBox filterPassword;
|
||||
private GUITickBox filterIncompatible;
|
||||
private GUITickBox filterFull;
|
||||
private GUITickBox filterEmpty;
|
||||
|
||||
//a timer for
|
||||
private DateTime refreshDisableTimer;
|
||||
private bool waitingForRefresh;
|
||||
|
||||
|
||||
public ServerListScreen()
|
||||
{
|
||||
int width = Math.Min(GameMain.GraphicsWidth - 160, 1000);
|
||||
@@ -54,67 +50,104 @@ namespace Barotrauma
|
||||
|
||||
Rectangle panelRect = new Rectangle(0, 0, width, height);
|
||||
|
||||
menu = new GUIFrame(panelRect, null, Alignment.Center, "");
|
||||
menu.Padding = new Vector4(40.0f, 40.0f, 40.0f, 20.0f);
|
||||
menu = new GUIFrame(new RectTransform(new Point(width, height), GUI.Canvas, Anchor.Center));
|
||||
|
||||
new GUITextBlock(new Rectangle(0, -25, 0, 30), TextManager.Get("JoinServer"), "", Alignment.CenterX, Alignment.CenterX, menu, false, GUI.LargeFont);
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.95f, 0.133f), menu.RectTransform, Anchor.TopCenter),
|
||||
TextManager.Get("JoinServer"), textAlignment: Alignment.Left, font: GUI.LargeFont);
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 30, 0, 30), TextManager.Get("YourName"), "", menu);
|
||||
clientNameBox = new GUITextBox(new Rectangle(0, 60, 200, 30), "", menu);
|
||||
clientNameBox.Text = GameMain.Config.DefaultPlayerName;
|
||||
var paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), menu.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.03f) }, style: null);
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 100, 0, 30), TextManager.Get("ServerIP"), "", menu);
|
||||
ipBox = new GUITextBox(new Rectangle(0, 130, 200, 30), "", menu)
|
||||
//-------------------------------------------------------------------------------------
|
||||
//left column
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.25f, 0.92f), paddedFrame.RectTransform, Anchor.TopLeft));
|
||||
|
||||
//spacing
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.03f), leftColumn.RectTransform), style: null);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("YourName"));
|
||||
clientNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.045f), leftColumn.RectTransform), "")
|
||||
{
|
||||
//max IPv6 address length + port
|
||||
MaxTextLength = 45 + 6
|
||||
Text = GameMain.Config.DefaultPlayerName
|
||||
};
|
||||
clientNameBox.OnTextChanged += RefreshJoinButtonState;
|
||||
|
||||
int middleX = (int)(width * 0.35f);
|
||||
|
||||
serverList = new GUIListBox(new Rectangle(middleX, 60, 0, height - 160), "", menu);
|
||||
serverList.OnSelected = SelectServer;
|
||||
|
||||
float[] columnRelativeX = new float[] { 0.15f, 0.5f, 0.15f, 0.2f };
|
||||
columnX = new int[columnRelativeX.Length];
|
||||
for (int n = 0; n < columnX.Length; n++)
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("ServerIP"));
|
||||
// TODO: Show IP on server info window
|
||||
ipBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.045f), leftColumn.RectTransform), "");
|
||||
ipBox.OnTextChanged += RefreshJoinButtonState;
|
||||
ipBox.OnSelected += (sender, key) =>
|
||||
{
|
||||
columnX[n] = (int)(columnRelativeX[n] * serverList.Rect.Width);
|
||||
if (n > 0) columnX[n] += columnX[n - 1];
|
||||
}
|
||||
if (sender.UserData is ServerInfo)
|
||||
{
|
||||
sender.Text = "";
|
||||
sender.UserData = null;
|
||||
}
|
||||
};
|
||||
|
||||
//spacing
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.45f), leftColumn.RectTransform), style: null);
|
||||
|
||||
ScalableFont font = GUI.SmallFont; // serverList.Rect.Width < 400 ? GUI.SmallFont : GUI.Font;
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("FilterServers"));
|
||||
searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), "");
|
||||
|
||||
new GUITextBlock(new Rectangle(middleX, 30, 0, 30), TextManager.Get("Password"), "", menu).Font = font;
|
||||
//spacing
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.03f), leftColumn.RectTransform), style: null);
|
||||
|
||||
new GUITextBlock(new Rectangle(middleX + columnX[0], 30, 0, 30), TextManager.Get("ServerListName"), "", menu).Font = font;
|
||||
new GUITextBlock(new Rectangle(middleX + columnX[1], 30, 0, 30), TextManager.Get("ServerListPlayers"), "", menu).Font = font;
|
||||
new GUITextBlock(new Rectangle(middleX + columnX[2], 30, 0, 30), TextManager.Get("ServerListRoundStarted"), "", menu).Font = font;
|
||||
|
||||
joinButton = new GUIButton(new Rectangle(-170, 0, 150, 30), TextManager.Get("ServerListRefresh"), Alignment.BottomRight, "", menu);
|
||||
joinButton.OnClicked = RefreshServers;
|
||||
|
||||
joinButton = new GUIButton(new Rectangle(0,0,150,30), TextManager.Get("ServerListJoin"), Alignment.BottomRight, "", menu);
|
||||
joinButton.OnClicked = JoinServer;
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
int y = 180;
|
||||
|
||||
new GUITextBlock(new Rectangle(0, y, 200, 30), TextManager.Get("FilterServers"), "", menu);
|
||||
searchBox = new GUITextBox(new Rectangle(0, y + 30, 200, 30), "", menu);
|
||||
searchBox.OnTextChanged += (txtBox, txt) => { FilterServers(); return true; };
|
||||
filterPassword = new GUITickBox(new Rectangle(0, y + 60, 30, 30), TextManager.Get("FilterPassword"), Alignment.TopLeft, menu);
|
||||
filterPassword = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("FilterPassword"));
|
||||
filterPassword.OnSelected += (tickBox) => { FilterServers(); return true; };
|
||||
filterFull = new GUITickBox(new Rectangle(0, y + 90, 30, 30), TextManager.Get("FilterFullServers"), Alignment.TopLeft, menu);
|
||||
filterIncompatible = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("FilterIncompatibleServers"));
|
||||
filterIncompatible.OnSelected += (tickBox) => { FilterServers(); return true; };
|
||||
|
||||
filterFull = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("FilterFullServers"));
|
||||
filterFull.OnSelected += (tickBox) => { FilterServers(); return true; };
|
||||
filterEmpty = new GUITickBox(new Rectangle(0, y + 120, 30, 30), TextManager.Get("FilterEmptyServers"), Alignment.TopLeft, menu);
|
||||
filterEmpty = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("FilterEmptyServers"));
|
||||
filterEmpty.OnSelected += (tickBox) => { FilterServers(); return true; };
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
//right column
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(1.0f - leftColumn.RectTransform.RelativeSize.X - 0.017f, 0.97f),
|
||||
paddedFrame.RectTransform, Anchor.TopRight))
|
||||
{
|
||||
RelativeSpacing = 0.02f,
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
serverList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.85f), rightColumn.RectTransform, Anchor.Center))
|
||||
{
|
||||
OnSelected = SelectServer
|
||||
};
|
||||
|
||||
columnRelativeWidth = new float[] { 0.04f, 0.02f, 0.044f, 0.77f, 0.02f, 0.075f, 0.06f };
|
||||
|
||||
var buttonContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.075f), rightColumn.RectTransform), style: null);
|
||||
|
||||
GUIButton button = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform, Anchor.TopLeft),
|
||||
TextManager.Get("Back"), style: "GUIButtonLarge")
|
||||
{
|
||||
OnClicked = GameMain.MainMenuScreen.SelectTab
|
||||
};
|
||||
|
||||
var refreshButton = new GUIButton(new RectTransform(new Vector2(buttonContainer.Rect.Height / (float)buttonContainer.Rect.Width, 0.9f), buttonContainer.RectTransform, Anchor.Center),
|
||||
"", style: "GUIButtonRefresh") {
|
||||
|
||||
ToolTip = TextManager.Get("ServerListRefresh"),
|
||||
OnClicked = RefreshServers
|
||||
};
|
||||
|
||||
joinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform, Anchor.TopRight),
|
||||
TextManager.Get("ServerListJoin"), style: "GUIButtonLarge")
|
||||
{
|
||||
OnClicked = JoinServer,
|
||||
Enabled = false
|
||||
};
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
GUIButton button = new GUIButton(new Rectangle(-20, -20, 100, 30), TextManager.Get("Back"), Alignment.TopLeft, "", menu);
|
||||
button.OnClicked = GameMain.MainMenuScreen.SelectTab;
|
||||
button.SelectedColor = button.Color;
|
||||
|
||||
refreshDisableTimer = DateTime.Now;
|
||||
@@ -128,42 +161,77 @@ namespace Barotrauma
|
||||
|
||||
private void FilterServers()
|
||||
{
|
||||
serverList.RemoveChild(serverList.FindChild("noresults"));
|
||||
serverList.Content.RemoveChild(serverList.Content.FindChild("noresults"));
|
||||
|
||||
foreach (GUIComponent child in serverList.children)
|
||||
foreach (GUIComponent child in serverList.Content.Children)
|
||||
{
|
||||
if (!(child.UserData is ServerInfo)) continue;
|
||||
ServerInfo serverInfo = (ServerInfo)child.UserData;
|
||||
|
||||
bool incompatible =
|
||||
(!serverInfo.ContentPackageHashes.Any() && serverInfo.ContentPackagesMatch(GameMain.Config.SelectedContentPackages)) ||
|
||||
(!string.IsNullOrEmpty(serverInfo.GameVersion) && serverInfo.GameVersion != GameMain.Version.ToString());
|
||||
|
||||
child.Visible =
|
||||
serverInfo.ServerName.ToLowerInvariant().Contains(searchBox.Text.ToLowerInvariant()) &&
|
||||
(!filterPassword.Selected || !serverInfo.HasPassword) &&
|
||||
(!filterIncompatible.Selected || !incompatible) &&
|
||||
(!filterFull.Selected || serverInfo.PlayerCount < serverInfo.MaxPlayers) &&
|
||||
(!filterEmpty.Selected || serverInfo.PlayerCount > 0);
|
||||
}
|
||||
|
||||
if (serverList.children.All(c => !c.Visible))
|
||||
if (serverList.Content.Children.All(c => !c.Visible))
|
||||
{
|
||||
new GUITextBlock(new Rectangle(0, 0, 0, 20), TextManager.Get("NoMatchingServers"), "", serverList).UserData = "noresults";
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverList.Content.RectTransform),
|
||||
TextManager.Get("NoMatchingServers"))
|
||||
{
|
||||
UserData = "noresults"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private bool RefreshJoinButtonState(GUIComponent component, object obj)
|
||||
{
|
||||
if (obj == null || waitingForRefresh) return false;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(clientNameBox.Text) && !string.IsNullOrWhiteSpace(ipBox.Text))
|
||||
{
|
||||
joinButton.Enabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
joinButton.Enabled = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool SelectServer(GUIComponent component, object obj)
|
||||
{
|
||||
if (obj == null || waitingForRefresh) 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 = serverInfo.ServerName;
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ipBox.Text = serverInfo.IP + ":" + serverInfo.Port;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -172,7 +240,11 @@ namespace Barotrauma
|
||||
if (waitingForRefresh) return false;
|
||||
serverList.ClearChildren();
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 0, 0, 20), TextManager.Get("RefreshingServerList"), "", serverList);
|
||||
ipBox.Text = null;
|
||||
joinButton.Enabled = false;
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverList.Content.RectTransform),
|
||||
TextManager.Get("RefreshingServerList"));
|
||||
|
||||
CoroutineManager.StartCoroutine(WaitForRefresh());
|
||||
|
||||
@@ -187,7 +259,20 @@ namespace Barotrauma
|
||||
yield return new WaitForSeconds((float)(refreshDisableTimer - DateTime.Now).TotalSeconds);
|
||||
}
|
||||
|
||||
CoroutineManager.StartCoroutine(SendMasterServerRequest());
|
||||
if (GameMain.Config.UseSteamMatchmaking)
|
||||
{
|
||||
serverList.ClearChildren();
|
||||
if (!SteamManager.GetServers(AddToServerList, UpdateServerInfo, ServerQueryFinished))
|
||||
{
|
||||
serverList.ClearChildren();
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverList.Content.RectTransform),
|
||||
TextManager.Get("ServerListNoSteamConnection"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CoroutineManager.StartCoroutine(SendMasterServerRequest());
|
||||
}
|
||||
|
||||
waitingForRefresh = false;
|
||||
|
||||
@@ -199,38 +284,33 @@ namespace Barotrauma
|
||||
private void UpdateServerList(string masterServerData)
|
||||
{
|
||||
serverList.ClearChildren();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(masterServerData))
|
||||
{
|
||||
new GUITextBlock(new Rectangle(0, 0, 0, 20), TextManager.Get("NoServers"), "", serverList);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (masterServerData.Substring(0, 5).ToLowerInvariant() == "error")
|
||||
{
|
||||
DebugConsole.ThrowError("Error while connecting to master server (" + masterServerData + ")!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
string[] lines = masterServerData.Split('\n');
|
||||
|
||||
List<ServerInfo> serverInfos = new List<ServerInfo>();
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
string[] arguments = lines[i].Split('|');
|
||||
if (arguments.Length < 3) continue;
|
||||
|
||||
string ip = arguments[0];
|
||||
string port = arguments[1];
|
||||
string serverName = arguments[2];
|
||||
bool gameStarted = arguments.Length > 3 && arguments[3] == "1";
|
||||
string currPlayersStr = (arguments.Length > 4) ? arguments[4] : "";
|
||||
string maxPlayersStr = (arguments.Length > 5) ? arguments[5] : "";
|
||||
bool hasPassWord = arguments.Length > 6 && arguments[6] == "1";
|
||||
string ip = arguments[0];
|
||||
string port = arguments[1];
|
||||
string serverName = arguments[2];
|
||||
bool gameStarted = arguments.Length > 3 && arguments[3] == "1";
|
||||
string currPlayersStr = arguments.Length > 4 ? arguments[4] : "";
|
||||
string maxPlayersStr = arguments.Length > 5 ? arguments[5] : "";
|
||||
bool hasPassWord = arguments.Length > 6 && arguments[6] == "1";
|
||||
string gameVersion = arguments.Length > 7 ? arguments[7] : "";
|
||||
string contentPackageNames = arguments.Length > 8 ? arguments[8] : "";
|
||||
string contentPackageHashes = arguments.Length > 9 ? arguments[9] : "";
|
||||
|
||||
int playerCount = 0, maxPlayers = 1;
|
||||
int.TryParse(currPlayersStr, out playerCount);
|
||||
int.TryParse(maxPlayersStr, out maxPlayers);
|
||||
int.TryParse(currPlayersStr, out int playerCount);
|
||||
int.TryParse(maxPlayersStr, out int maxPlayers);
|
||||
|
||||
var serverInfo = new ServerInfo()
|
||||
{
|
||||
@@ -240,28 +320,182 @@ namespace Barotrauma
|
||||
GameStarted = gameStarted,
|
||||
PlayerCount = playerCount,
|
||||
MaxPlayers = maxPlayers,
|
||||
HasPassword = hasPassWord
|
||||
HasPassword = hasPassWord,
|
||||
GameVersion = gameVersion
|
||||
};
|
||||
foreach (string contentPackageName in contentPackageNames.Split(','))
|
||||
{
|
||||
if (string.IsNullOrEmpty(contentPackageName)) continue;
|
||||
serverInfo.ContentPackageNames.Add(contentPackageName);
|
||||
}
|
||||
foreach (string contentPackageHash in contentPackageHashes.Split(','))
|
||||
{
|
||||
if (string.IsNullOrEmpty(contentPackageHash)) continue;
|
||||
serverInfo.ContentPackageHashes.Add(contentPackageHash);
|
||||
}
|
||||
|
||||
var serverFrame = new GUIFrame(new Rectangle(0, 0, 0, 30), (i % 2 == 0) ? Color.Transparent : Color.White * 0.2f, "ListBoxElement", serverList);
|
||||
serverFrame.UserData = serverInfo;
|
||||
serverInfos.Add(serverInfo);
|
||||
}
|
||||
|
||||
var passwordBox = new GUITickBox(new Rectangle(columnX[0] / 2, 0, 20, 20), "", Alignment.CenterLeft, serverFrame);
|
||||
passwordBox.Selected = hasPassWord;
|
||||
passwordBox.Enabled = false;
|
||||
passwordBox.UserData = "password";
|
||||
serverList.Content.ClearChildren();
|
||||
if (serverInfos.Count() == 0)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverList.Content.RectTransform),
|
||||
TextManager.Get("NoServers"));
|
||||
return;
|
||||
}
|
||||
foreach (ServerInfo serverInfo in serverInfos)
|
||||
{
|
||||
AddToServerList(serverInfo);
|
||||
}
|
||||
}
|
||||
|
||||
new GUITextBlock(new Rectangle(columnX[0], 0, 0, 0), serverName, "", Alignment.TopLeft, Alignment.CenterLeft, serverFrame);
|
||||
new GUITextBlock(new Rectangle(columnX[1], 0, 0, 0), playerCount + "/" + maxPlayers, "", Alignment.TopLeft, Alignment.CenterLeft, serverFrame);
|
||||
private void AddToServerList(ServerInfo serverInfo)
|
||||
{
|
||||
var serverFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.06f), serverList.Content.RectTransform) { MinSize = new Point(0, 20) },
|
||||
style: "InnerFrame", color: Color.White * 0.5f)
|
||||
{
|
||||
UserData = serverInfo
|
||||
};
|
||||
var serverContent = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 1.0f), serverFrame.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
UpdateServerInfo(serverInfo);
|
||||
}
|
||||
|
||||
var gameStartedBox = new GUITickBox(new Rectangle(columnX[2] + (columnX[3] - columnX[2]) / 2, 0, 20, 20), "", Alignment.CenterRight, serverFrame);
|
||||
gameStartedBox.Selected = gameStarted;
|
||||
gameStartedBox.Enabled = false;
|
||||
private void UpdateServerInfo(ServerInfo serverInfo)
|
||||
{
|
||||
var serverFrame = serverList.Content.FindChild(serverInfo);
|
||||
if (serverFrame == null) return;
|
||||
|
||||
var serverContent = serverFrame.Children.First();
|
||||
serverContent.ClearChildren();
|
||||
|
||||
var compatibleBox = new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[0], 0.9f), serverContent.RectTransform, Anchor.Center), label: "")
|
||||
{
|
||||
Enabled = false,
|
||||
Selected =
|
||||
serverInfo.GameVersion == GameMain.Version.ToString() &&
|
||||
serverInfo.ContentPackagesMatch(GameMain.SelectedPackages),
|
||||
UserData = "compatible"
|
||||
};
|
||||
|
||||
var passwordBox = new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[1], 0.5f), serverContent.RectTransform, Anchor.Center), label: "", style: "GUIServerListPasswordTickBox")
|
||||
{
|
||||
ToolTip = TextManager.Get((serverInfo.HasPassword) ? "ServerListHasPassword" : "FilterPassword"),
|
||||
Selected = serverInfo.HasPassword,
|
||||
Enabled = false,
|
||||
UserData = "password"
|
||||
};
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(columnRelativeWidth[2], 0.8f), serverContent.RectTransform, Anchor.Center), style: "GUIButtonServerListInfo") {
|
||||
ToolTip = TextManager.Get("ServerListInfo"),
|
||||
OnClicked = (btn, obj) => {
|
||||
SelectServer(null, serverInfo);
|
||||
var msgBox = new GUIMessageBox("", "", new string[] { TextManager.Get("Cancel"), TextManager.Get("ServerListJoin") }, 550, 400);
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
msgBox.Buttons[1].OnClicked += JoinServer;
|
||||
msgBox.Buttons[1].OnClicked += msgBox.Close;
|
||||
serverInfo.CreatePreviewWindow(msgBox);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var serverName = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[3], 1.0f), serverContent.RectTransform), serverInfo.ServerName, style: "GUIServerListTextBox");
|
||||
|
||||
var gameStartedBox = new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[4], 0.4f), serverContent.RectTransform, Anchor.Center),
|
||||
label: "", style: "GUIServerListRoundStartedTickBox") {
|
||||
ToolTip = TextManager.Get((serverInfo.GameStarted) ? "ServerListRoundStarted" : "ServerListRoundNotStarted"),
|
||||
Selected = serverInfo.GameStarted,
|
||||
Enabled = false
|
||||
};
|
||||
|
||||
var serverPlayers = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[5], 1.0f), serverContent.RectTransform),
|
||||
serverInfo.PlayerCount + "/" + serverInfo.MaxPlayers, style: "GUIServerListTextBox", textAlignment: Alignment.Right)
|
||||
{
|
||||
ToolTip = TextManager.Get("ServerListPlayers")
|
||||
};
|
||||
|
||||
var serverPingText = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[6], 1.0f), serverContent.RectTransform), "?",
|
||||
style: "GUIServerListTextBox", textColor: Color.White * 0.5f, textAlignment: Alignment.Right)
|
||||
{
|
||||
ToolTip = TextManager.Get("ServerListPing")
|
||||
};
|
||||
|
||||
if (serverInfo.PingChecked)
|
||||
{
|
||||
serverPingText.Text = serverInfo.Ping > -1 ? serverInfo.Ping.ToString() : "?";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(serverInfo.IP))
|
||||
{
|
||||
try
|
||||
{
|
||||
GetServerPing(serverInfo, serverPingText);
|
||||
}
|
||||
catch (NullReferenceException ex)
|
||||
{
|
||||
DebugConsole.ThrowError("Ping is null", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.Config.UseSteamMatchmaking && serverInfo.RespondedToSteamQuery.HasValue && serverInfo.RespondedToSteamQuery.Value == false)
|
||||
{
|
||||
string toolTip = TextManager.Get("ServerListNoSteamQueryResponse");
|
||||
compatibleBox.Selected = false;
|
||||
serverContent.Children.ForEach(c => c.ToolTip = toolTip);
|
||||
serverName.TextColor *= 0.8f;
|
||||
serverPlayers.TextColor *= 0.8f;
|
||||
}
|
||||
else if (string.IsNullOrEmpty(serverInfo.GameVersion) || !serverInfo.ContentPackageHashes.Any())
|
||||
{
|
||||
compatibleBox.Selected = false;
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), compatibleBox.Box.RectTransform, Anchor.Center), " ? ", Color.Yellow * 0.85f, textAlignment: Alignment.Center)
|
||||
{
|
||||
ToolTip = TextManager.Get(string.IsNullOrEmpty(serverInfo.GameVersion) ?
|
||||
"ServerListUnknownVersion" :
|
||||
"ServerListUnknownContentPackage")
|
||||
};
|
||||
}
|
||||
else if (!compatibleBox.Selected)
|
||||
{
|
||||
string toolTip = "";
|
||||
if (serverInfo.GameVersion != GameMain.Version.ToString())
|
||||
toolTip = TextManager.Get("ServerListIncompatibleVersion").Replace("[version]", serverInfo.GameVersion);
|
||||
|
||||
for (int i = 0; i < serverInfo.ContentPackageNames.Count; i++)
|
||||
{
|
||||
if (!GameMain.SelectedPackages.Any(cp => cp.MD5hash.Hash == serverInfo.ContentPackageHashes[i]))
|
||||
{
|
||||
if (toolTip != "") toolTip += "\n";
|
||||
toolTip += TextManager.Get("ServerListIncompatibleContentPackage")
|
||||
.Replace("[contentpackage]", serverInfo.ContentPackageNames[i])
|
||||
.Replace("[hash]", Md5Hash.GetShortHash(serverInfo.ContentPackageHashes[i]));
|
||||
}
|
||||
}
|
||||
|
||||
serverContent.Children.ForEach(c => c.ToolTip = toolTip);
|
||||
|
||||
serverName.TextColor *= 0.5f;
|
||||
serverPlayers.TextColor *= 0.5f;
|
||||
}
|
||||
|
||||
FilterServers();
|
||||
}
|
||||
|
||||
private void ServerQueryFinished()
|
||||
{
|
||||
if (serverList.Content.Children.All(c => !c.Visible))
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverList.Content.RectTransform),
|
||||
TextManager.Get("NoMatchingServers"))
|
||||
{
|
||||
UserData = "noresults"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<object> SendMasterServerRequest()
|
||||
{
|
||||
RestClient client = null;
|
||||
@@ -291,16 +525,7 @@ namespace Barotrauma
|
||||
{
|
||||
serverList.ClearChildren();
|
||||
restRequestHandle.Abort();
|
||||
if (string.IsNullOrEmpty(GameMain.SteamVersionUrl))
|
||||
{
|
||||
//Steam version is out and could not reach the master server
|
||||
// -> assume legacy master server has been deprecated
|
||||
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"), TextManager.Get("MasterServerTimeOutError"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowMasterServerDeprecatedMessage();
|
||||
}
|
||||
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"), TextManager.Get("MasterServerTimeOutError"));
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
yield return CoroutineStatus.Running;
|
||||
@@ -311,7 +536,6 @@ namespace Barotrauma
|
||||
serverList.ClearChildren();
|
||||
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"), TextManager.Get("MasterServerErrorException").Replace("[error]", masterServerResponse.ErrorException.ToString()));
|
||||
}
|
||||
|
||||
else if (masterServerResponse.StatusCode != System.Net.HttpStatusCode.OK)
|
||||
{
|
||||
serverList.ClearChildren();
|
||||
@@ -319,20 +543,11 @@ namespace Barotrauma
|
||||
switch (masterServerResponse.StatusCode)
|
||||
{
|
||||
case System.Net.HttpStatusCode.NotFound:
|
||||
//Steam version is out and server file wasn't found on the legacy master server
|
||||
// -> assume legacy master server has been deprecated
|
||||
if (string.IsNullOrEmpty(GameMain.SteamVersionUrl))
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"),
|
||||
TextManager.Get("MasterServerError404")
|
||||
.Replace("[masterserverurl]", NetConfig.MasterServerUrl)
|
||||
.Replace("[statuscode]", masterServerResponse.StatusCode.ToString())
|
||||
.Replace("[statusdescription]", masterServerResponse.StatusDescription));
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowMasterServerDeprecatedMessage();
|
||||
}
|
||||
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"),
|
||||
TextManager.Get("MasterServerError404")
|
||||
.Replace("[masterserverurl]", NetConfig.MasterServerUrl)
|
||||
.Replace("[statuscode]", masterServerResponse.StatusCode.ToString())
|
||||
.Replace("[statusdescription]", masterServerResponse.StatusDescription));
|
||||
break;
|
||||
case System.Net.HttpStatusCode.ServiceUnavailable:
|
||||
new GUIMessageBox(TextManager.Get("MasterServerErrorLabel"),
|
||||
@@ -357,18 +572,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
private void ShowMasterServerDeprecatedMessage()
|
||||
{
|
||||
serverList.ClearChildren();
|
||||
new GUITextBlock(new Rectangle(0, 0, (int)(serverList.Rect.Width * 0.8f), (int)(serverList.Rect.Height * 0.8f)),
|
||||
"This version of Barotrauma is no longer supported and the legacy server list is no longer available.",
|
||||
alignment: Alignment.Center, textAlignment: Alignment.Center,
|
||||
style: "", parent: serverList, wrap: true)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
|
||||
private void MasterServerCallBack(IRestResponse response)
|
||||
@@ -382,16 +586,27 @@ namespace Barotrauma
|
||||
if (string.IsNullOrWhiteSpace(clientNameBox.Text))
|
||||
{
|
||||
clientNameBox.Flash();
|
||||
joinButton.Enabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
GameMain.Config.DefaultPlayerName = clientNameBox.Text;
|
||||
GameMain.Config.Save();
|
||||
|
||||
string ip = ipBox.Text;
|
||||
string ip = null;
|
||||
if (ipBox.UserData is ServerInfo serverInfo)
|
||||
{
|
||||
ip = serverInfo.IP + ":" + serverInfo.Port;
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(ipBox.Text))
|
||||
{
|
||||
ip = ipBox.Text;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ip))
|
||||
{
|
||||
ipBox.Flash();
|
||||
joinButton.Enabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -399,12 +614,7 @@ namespace Barotrauma
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*public void JoinServer(string ip, bool hasPassword, string msg = "Password required")
|
||||
{
|
||||
CoroutineManager.StartCoroutine(ConnectToServer(ip));
|
||||
}*/
|
||||
|
||||
|
||||
private IEnumerable<object> ConnectToServer(string ip)
|
||||
{
|
||||
try
|
||||
@@ -422,6 +632,99 @@ namespace Barotrauma
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
public void GetServerPing(ServerInfo serverInfo, GUITextBlock serverPingText)
|
||||
{
|
||||
serverInfo.PingChecked = false;
|
||||
serverInfo.Ping = -1;
|
||||
|
||||
var pingThread = new Thread(() => { PingServer(serverInfo, 1000); })
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
pingThread.Start();
|
||||
|
||||
CoroutineManager.StartCoroutine(UpdateServerPingText(serverInfo, serverPingText, 1000));
|
||||
}
|
||||
|
||||
private IEnumerable<object> UpdateServerPingText(ServerInfo serverInfo, GUITextBlock serverPingText, int timeOut)
|
||||
{
|
||||
DateTime timeOutTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, milliseconds: timeOut);
|
||||
while (DateTime.Now < timeOutTime)
|
||||
{
|
||||
if (serverInfo.PingChecked)
|
||||
{
|
||||
if (serverInfo.Ping != -1)
|
||||
{
|
||||
if (serverInfo.Ping < 50)
|
||||
{
|
||||
serverPingText.TextColor = Color.Green * 1.75f;
|
||||
}
|
||||
else if (serverInfo.Ping < 150)
|
||||
{
|
||||
serverPingText.TextColor = Color.Yellow * 0.85f;
|
||||
}
|
||||
else
|
||||
{
|
||||
serverPingText.TextColor = Color.Red * 0.75f;
|
||||
}
|
||||
}
|
||||
serverPingText.Text = serverInfo.Ping > -1 ? serverInfo.Ping.ToString() : "?";
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
public void PingServer(ServerInfo serverInfo, int timeOut)
|
||||
{
|
||||
if (serverInfo?.IP == null)
|
||||
{
|
||||
serverInfo.PingChecked = true;
|
||||
serverInfo.Ping = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
long rtt = -1;
|
||||
IPAddress address = IPAddress.Parse(serverInfo.IP);
|
||||
if (address != null)
|
||||
{
|
||||
//don't attempt to ping if the address is IPv6 and it's not supported
|
||||
if (address.AddressFamily != AddressFamily.InterNetworkV6 || Socket.OSSupportsIPv6)
|
||||
{
|
||||
Ping ping = new Ping();
|
||||
byte[] buffer = new byte[32];
|
||||
try
|
||||
{
|
||||
PingReply pingReply = ping.Send(address, timeOut, buffer, new PingOptions(128, true));
|
||||
|
||||
if (pingReply != null)
|
||||
{
|
||||
switch (pingReply.Status)
|
||||
{
|
||||
case IPStatus.Success:
|
||||
rtt = pingReply.RoundtripTime;
|
||||
break;
|
||||
default:
|
||||
rtt = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (PingException ex)
|
||||
{
|
||||
string errorMsg = "Failed to ping a server (" + serverInfo.ServerName + ", " + serverInfo.IP + ") - " + ex.Message;
|
||||
GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + serverInfo.IP, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
DebugConsole.NewMessage(errorMsg, Color.Red);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serverInfo.PingChecked = true;
|
||||
serverInfo.Ping = (int)rtt;
|
||||
}
|
||||
|
||||
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||
{
|
||||
graphics.Clear(Color.CornflowerBlue);
|
||||
@@ -429,11 +732,9 @@ namespace Barotrauma
|
||||
GameMain.TitleScreen.DrawLoadingText = false;
|
||||
GameMain.TitleScreen.Draw(spriteBatch, graphics, (float)deltaTime);
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, GameMain.ScissorTestEnable);
|
||||
|
||||
menu.Draw(spriteBatch);
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, GameMain.ScissorTestEnable);
|
||||
|
||||
GUI.Draw((float)deltaTime, spriteBatch, null);
|
||||
GUI.Draw(Cam, spriteBatch);
|
||||
|
||||
spriteBatch.End();
|
||||
}
|
||||
@@ -442,10 +743,6 @@ namespace Barotrauma
|
||||
{
|
||||
menu.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
menu.Update((float)deltaTime);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,747 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class SpriteEditorScreen : Screen
|
||||
{
|
||||
private GUIListBox textureList, spriteList;
|
||||
|
||||
private GUIFrame topPanel;
|
||||
private GUIFrame leftPanel;
|
||||
private GUIFrame rightPanel;
|
||||
private GUIFrame bottomPanel;
|
||||
private GUIFrame backgroundColorPanel;
|
||||
|
||||
private GUIFrame topPanelContents;
|
||||
private GUITextBlock texturePathText;
|
||||
private GUITextBlock xmlPathText;
|
||||
private GUIScrollBar zoomBar;
|
||||
private List<Sprite> selectedSprites = new List<Sprite>();
|
||||
private List<Sprite> dirtySprites = new List<Sprite>();
|
||||
private Texture2D selectedTexture;
|
||||
private Sprite lastSelected;
|
||||
private Rectangle textureRect;
|
||||
private float zoom = 1;
|
||||
private float minZoom = 0.25f;
|
||||
private float maxZoom;
|
||||
private int spriteCount;
|
||||
|
||||
private bool editBackgroundColor;
|
||||
private Color backgroundColor = new Color(0.051f, 0.149f, 0.271f, 1.0f);
|
||||
|
||||
private readonly Camera cam;
|
||||
public override Camera Cam
|
||||
{
|
||||
get { return cam; }
|
||||
}
|
||||
|
||||
public GUIComponent TopPanel
|
||||
{
|
||||
get { return topPanel; }
|
||||
}
|
||||
|
||||
public SpriteEditorScreen()
|
||||
{
|
||||
cam = new Camera();
|
||||
CreateGUIElements();
|
||||
}
|
||||
|
||||
#region Initialization
|
||||
private void CreateGUIElements()
|
||||
{
|
||||
topPanel = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), Frame.RectTransform) { MinSize = new Point(0, 60) }, "GUIFrameTop");
|
||||
topPanelContents = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.8f), topPanel.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(0.12f, 0.4f), topPanelContents.RectTransform, Anchor.TopLeft)
|
||||
{
|
||||
RelativeOffset = new Vector2(0, 0.1f)
|
||||
}, "Reload Texture")
|
||||
{
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
if (!(textureList.SelectedData is Texture2D selectedTexture)) { return false; }
|
||||
var selected = selectedSprites;
|
||||
Sprite firstSelected = selected.First();
|
||||
selected.ForEach(s => s.ReloadTexture());
|
||||
RefreshLists();
|
||||
textureList.Select(firstSelected.Texture, autoScroll: false);
|
||||
selected.ForEachMod(s => spriteList.Select(s, autoScroll: false));
|
||||
texturePathText.Text = "Textures reloaded from " + firstSelected.FilePath;
|
||||
texturePathText.TextColor = Color.LightGreen;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
new GUIButton(new RectTransform(new Vector2(0.12f, 0.4f), topPanelContents.RectTransform, Anchor.BottomLeft)
|
||||
{
|
||||
RelativeOffset = new Vector2(0, 0.1f)
|
||||
}, "Reset Changes")
|
||||
{
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
if (selectedTexture == null) { return false; }
|
||||
foreach (Sprite sprite in loadedSprites)
|
||||
{
|
||||
if (sprite.Texture != selectedTexture) { continue; }
|
||||
var element = sprite.SourceElement;
|
||||
if (element == null) { continue; }
|
||||
// Not all sprites have a sourcerect defined, in which case we'll want to use the current source rect instead of an empty rect.
|
||||
sprite.SourceRect = element.GetAttributeRect("sourcerect", sprite.SourceRect);
|
||||
sprite.RelativeOrigin = element.GetAttributeVector2("origin", new Vector2(0.5f, 0.5f));
|
||||
}
|
||||
ResetWidgets();
|
||||
xmlPathText.Text = "Changes successfully reset";
|
||||
xmlPathText.TextColor = Color.LightGreen;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
new GUIButton(new RectTransform(new Vector2(0.12f, 0.4f), topPanelContents.RectTransform, Anchor.TopLeft)
|
||||
{
|
||||
RelativeOffset = new Vector2(0.15f, 0.1f)
|
||||
}, "Save Selected Sprites")
|
||||
{
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
return SaveSprites(selectedSprites);
|
||||
}
|
||||
};
|
||||
new GUIButton(new RectTransform(new Vector2(0.12f, 0.4f), topPanelContents.RectTransform, Anchor.BottomLeft)
|
||||
{
|
||||
RelativeOffset = new Vector2(0.15f, 0.1f)
|
||||
}, "Save All Sprites")
|
||||
{
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
return SaveSprites(loadedSprites);
|
||||
}
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.2f, 0.2f), topPanelContents.RectTransform, Anchor.TopCenter, Pivot.CenterRight) { RelativeOffset = new Vector2(0, 0.3f) }, "Zoom: ");
|
||||
zoomBar = new GUIScrollBar(new RectTransform(new Vector2(0.2f, 0.35f), topPanelContents.RectTransform, Anchor.TopCenter, Pivot.CenterRight)
|
||||
{
|
||||
RelativeOffset = new Vector2(0.05f, 0.3f)
|
||||
}, barSize: 0.1f)
|
||||
{
|
||||
BarScroll = GetBarScrollValue(),
|
||||
Step = 0.01f,
|
||||
OnMoved = (scrollBar, value) =>
|
||||
{
|
||||
zoom = MathHelper.Lerp(minZoom, maxZoom, value);
|
||||
viewAreaOffset = Point.Zero;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
new GUIButton(new RectTransform(new Vector2(0.05f, 0.35f), topPanelContents.RectTransform, Anchor.TopCenter, Pivot.CenterLeft) { RelativeOffset = new Vector2(0.055f, 0.3f) }, "Reset Zoom")
|
||||
{
|
||||
OnClicked = (box, data) =>
|
||||
{
|
||||
ResetZoom();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
texturePathText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.4f), topPanelContents.RectTransform, Anchor.Center, Pivot.BottomCenter) { RelativeOffset = new Vector2(0.4f, 0) }, "", Color.LightGray);
|
||||
xmlPathText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.4f), topPanelContents.RectTransform, Anchor.Center, Pivot.TopCenter) { RelativeOffset = new Vector2(0.4f, 0) }, "", Color.LightGray);
|
||||
|
||||
leftPanel = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f - topPanel.RectTransform.RelativeSize.Y), Frame.RectTransform, Anchor.BottomLeft)
|
||||
{ MinSize = new Point(150, 0) }, style: "GUIFrameLeft");
|
||||
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 };
|
||||
textureList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), paddedLeftPanel.RectTransform))
|
||||
{
|
||||
OnSelected = (listBox, userData) =>
|
||||
{
|
||||
var previousTexture = selectedTexture;
|
||||
selectedTexture = userData as Texture2D;
|
||||
if (previousTexture != selectedTexture)
|
||||
{
|
||||
ResetZoom();
|
||||
}
|
||||
foreach (GUIComponent child in spriteList.Content.Children)
|
||||
{
|
||||
var textBlock = (GUITextBlock)child;
|
||||
var sprite = (Sprite)textBlock.UserData;
|
||||
textBlock.TextColor = new Color(textBlock.TextColor, sprite.Texture == selectedTexture ? 1.0f : 0.4f);
|
||||
}
|
||||
if (selectedSprites.None(s => s.Texture == selectedTexture))
|
||||
{
|
||||
spriteList.Select(loadedSprites.First(s => s.Texture == selectedTexture), autoScroll: false);
|
||||
UpdateScrollBar(spriteList);
|
||||
}
|
||||
texturePathText.TextColor = Color.LightGray;
|
||||
topPanelContents.Visible = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
rightPanel = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f - topPanel.RectTransform.RelativeSize.Y), Frame.RectTransform, Anchor.BottomRight) { MinSize = new Point(150, 0) }, style: "GUIFrameRight");
|
||||
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
|
||||
};
|
||||
spriteList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), paddedRightPanel.RectTransform))
|
||||
{
|
||||
OnSelected = (listBox, userData) =>
|
||||
{
|
||||
Sprite sprite = userData as Sprite;
|
||||
if (sprite == null) return false;
|
||||
if (selectedSprites.Any(s => s.Texture != selectedTexture))
|
||||
{
|
||||
ResetWidgets();
|
||||
}
|
||||
if (Widget.EnableMultiSelect)
|
||||
{
|
||||
if (selectedSprites.Contains(sprite))
|
||||
{
|
||||
selectedSprites.Remove(sprite);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedSprites.Add(sprite);
|
||||
dirtySprites.Add(sprite);
|
||||
lastSelected = sprite;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedSprites.Clear();
|
||||
selectedSprites.Add(sprite);
|
||||
dirtySprites.Add(sprite);
|
||||
lastSelected = sprite;
|
||||
}
|
||||
if (selectedTexture != sprite.Texture)
|
||||
{
|
||||
textureList.Select(sprite.Texture, autoScroll: false);
|
||||
UpdateScrollBar(textureList);
|
||||
}
|
||||
xmlPathText.Text = string.Empty;
|
||||
foreach (var s in selectedSprites)
|
||||
{
|
||||
texturePathText.Text = s.FilePath;
|
||||
var element = s.SourceElement;
|
||||
if (element != null)
|
||||
{
|
||||
string xmlPath = element.ParseContentPathFromUri();
|
||||
if (!xmlPathText.Text.Contains(xmlPath))
|
||||
{
|
||||
xmlPathText.Text += "\n" + xmlPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlPathText.TextColor = Color.LightGray;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Background color
|
||||
bottomPanel = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.05f), Frame.RectTransform, Anchor.BottomCenter), style: null, color: Color.Black * 0.5f);
|
||||
new GUITickBox(new RectTransform(new Vector2(0.2f, 0.5f), bottomPanel.RectTransform, Anchor.Center), "Edit Background Color")
|
||||
{
|
||||
Selected = editBackgroundColor,
|
||||
OnSelected = box =>
|
||||
{
|
||||
editBackgroundColor = box.Selected;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
backgroundColorPanel = new GUIFrame(new RectTransform(new Point(400, 80), Frame.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0, 0.1f) }, style: null, color: Color.Black * 0.4f);
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.2f, 1), backgroundColorPanel.RectTransform) { MinSize = new Point(80, 26) }, "Background \nColor:", textColor: Color.WhiteSmoke);
|
||||
var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.7f, 1), backgroundColorPanel.RectTransform, Anchor.TopRight)
|
||||
{
|
||||
AbsoluteOffset = new Point(20, 0)
|
||||
}, isHorizontal: true, childAnchor: Anchor.CenterRight)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.01f
|
||||
};
|
||||
var fields = new GUIComponent[4];
|
||||
string[] colorComponentLabels = { "R", "G", "B" };
|
||||
for (int i = 2; i >= 0; i--)
|
||||
{
|
||||
var element = new GUIFrame(new RectTransform(new Vector2(0.2f, 1), inputArea.RectTransform)
|
||||
{
|
||||
MinSize = new Point(40, 0),
|
||||
MaxSize = new Point(100, 50)
|
||||
}, style: null, color: Color.Black * 0.6f);
|
||||
var colorLabel = new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), element.RectTransform, Anchor.CenterLeft), colorComponentLabels[i],
|
||||
font: GUI.SmallFont, textAlignment: Alignment.CenterLeft);
|
||||
GUINumberInput numberInput = new GUINumberInput(new RectTransform(new Vector2(0.7f, 1), element.RectTransform, Anchor.CenterRight),
|
||||
GUINumberInput.NumberType.Int)
|
||||
{
|
||||
Font = GUI.SmallFont
|
||||
};
|
||||
numberInput.MinValueInt = 0;
|
||||
numberInput.MaxValueInt = 255;
|
||||
numberInput.Font = GUI.SmallFont;
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
colorLabel.TextColor = Color.Red;
|
||||
numberInput.IntValue = backgroundColor.R;
|
||||
numberInput.OnValueChanged += (numInput) => backgroundColor.R = (byte)(numInput.IntValue);
|
||||
break;
|
||||
case 1:
|
||||
colorLabel.TextColor = Color.LightGreen;
|
||||
numberInput.IntValue = backgroundColor.G;
|
||||
numberInput.OnValueChanged += (numInput) => backgroundColor.G = (byte)(numInput.IntValue);
|
||||
break;
|
||||
case 2:
|
||||
colorLabel.TextColor = Color.DeepSkyBlue;
|
||||
numberInput.IntValue = backgroundColor.B;
|
||||
numberInput.OnValueChanged += (numInput) => backgroundColor.B = (byte)(numInput.IntValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private HashSet<Sprite> loadedSprites = new HashSet<Sprite>();
|
||||
private void LoadSprites()
|
||||
{
|
||||
loadedSprites.ForEach(s => s.Remove());
|
||||
loadedSprites.Clear();
|
||||
//foreach (string filePath in ContentPackage.GetAllContentFiles(GameMain.SelectedPackages))
|
||||
//{
|
||||
// XDocument doc = XMLExtensions.TryLoadXml(filePath);
|
||||
// if (doc != null && doc.Root != null)
|
||||
// {
|
||||
// LoadSprites(doc.Root);
|
||||
// }
|
||||
//}
|
||||
|
||||
foreach (string filePath in Directory.GetFiles("Content/", "*.xml", SearchOption.AllDirectories))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(filePath);
|
||||
if (doc != null && doc.Root != null)
|
||||
{
|
||||
LoadSprites(doc.Root);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadSprites(XElement element)
|
||||
{
|
||||
element.Elements("sprite").ForEach(s => CreateSprite(s));
|
||||
element.Elements("Sprite").ForEach(s => CreateSprite(s));
|
||||
element.Elements("brokensprite").ForEach(s => CreateSprite(s));
|
||||
element.Elements("BrokenSprite").ForEach(s => CreateSprite(s));
|
||||
element.Elements("containedsprite").ForEach(s => CreateSprite(s));
|
||||
element.Elements("ContainedSprite").ForEach(s => CreateSprite(s));
|
||||
//decorativesprites don't necessarily have textures (can be used to hide/disable other sprites)
|
||||
element.Elements("decorativesprite").ForEach(s => { if (s.Attribute("texture") != null) CreateSprite(s); });
|
||||
element.Elements("DecorativeSprite").ForEach(s => { if (s.Attribute("texture") != null) CreateSprite(s); });
|
||||
element.Elements().ForEach(e => LoadSprites(e));
|
||||
}
|
||||
|
||||
void CreateSprite(XElement element)
|
||||
{
|
||||
string spriteFolder = "";
|
||||
string textureElement = element.GetAttributeString("texture", "");
|
||||
// TODO: parse and create
|
||||
if (textureElement.Contains("[GENDER]") || textureElement.Contains("[HEADID]") || textureElement.Contains("[RACE]")) { return; }
|
||||
if (!textureElement.Contains("/"))
|
||||
{
|
||||
spriteFolder = Path.GetDirectoryName(element.ParseContentPathFromUri());
|
||||
}
|
||||
// Uncomment if we do multiple passes -> there can be duplicates
|
||||
//string identifier = Sprite.GetID(element);
|
||||
//if (loadedSprites.None(s => s.ID == identifier))
|
||||
//{
|
||||
// loadedSprites.Add(new Sprite(element, spriteFolder));
|
||||
//}
|
||||
loadedSprites.Add(new Sprite(element, spriteFolder));
|
||||
}
|
||||
}
|
||||
|
||||
private bool SaveSprites(IEnumerable<Sprite> sprites)
|
||||
{
|
||||
if (selectedTexture == null) { return false; }
|
||||
if (sprites.None()) { return false; }
|
||||
HashSet<XDocument> docsToSave = new HashSet<XDocument>();
|
||||
foreach (Sprite sprite in sprites)
|
||||
{
|
||||
if (sprite.Texture != selectedTexture) { continue; }
|
||||
var element = sprite.SourceElement;
|
||||
if (element == null) { continue; }
|
||||
element.SetAttributeValue("sourcerect", XMLExtensions.RectToString(sprite.SourceRect));
|
||||
element.SetAttributeValue("origin", XMLExtensions.Vector2ToString(sprite.RelativeOrigin));
|
||||
docsToSave.Add(element.Document);
|
||||
}
|
||||
xmlPathText.Text = "All changes saved to:";
|
||||
foreach (XDocument doc in docsToSave)
|
||||
{
|
||||
string xmlPath = doc.ParseContentPathFromUri();
|
||||
xmlPathText.Text += "\n" + xmlPath;
|
||||
doc.Save(xmlPath);
|
||||
}
|
||||
xmlPathText.TextColor = Color.LightGreen;
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
leftPanel.AddToGUIUpdateList();
|
||||
rightPanel.AddToGUIUpdateList();
|
||||
topPanel.AddToGUIUpdateList();
|
||||
bottomPanel.AddToGUIUpdateList();
|
||||
if (editBackgroundColor)
|
||||
{
|
||||
backgroundColorPanel.AddToGUIUpdateList();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
Widget.EnableMultiSelect = PlayerInput.KeyDown(Keys.LeftControl);
|
||||
spriteList.SelectMultiple = Widget.EnableMultiSelect;
|
||||
// Select rects with the mouse
|
||||
if (Widget.selectedWidgets.None() || Widget.EnableMultiSelect)
|
||||
{
|
||||
if (selectedTexture != null)
|
||||
{
|
||||
foreach (Sprite sprite in loadedSprites)
|
||||
{
|
||||
if (sprite.Texture != selectedTexture) continue;
|
||||
if (PlayerInput.LeftButtonClicked())
|
||||
{
|
||||
var scaledRect = new Rectangle(textureRect.Location + sprite.SourceRect.Location.Multiply(zoom), sprite.SourceRect.Size.Multiply(zoom));
|
||||
if (scaledRect.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
spriteList.Select(sprite, autoScroll: false);
|
||||
UpdateScrollBar(spriteList);
|
||||
UpdateScrollBar(textureList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (GUI.MouseOn == null)
|
||||
{
|
||||
if (PlayerInput.ScrollWheelSpeed != 0)
|
||||
{
|
||||
zoom = MathHelper.Clamp(zoom + PlayerInput.ScrollWheelSpeed * (float)deltaTime * 0.05f * zoom, minZoom, maxZoom);
|
||||
zoomBar.BarScroll = GetBarScrollValue();
|
||||
}
|
||||
widgets.Values.ForEach(w => w.Update((float)deltaTime));
|
||||
if (PlayerInput.MidButtonHeld())
|
||||
{
|
||||
// "Camera" Pan
|
||||
Vector2 moveSpeed = PlayerInput.MouseSpeed * (float)deltaTime * 100.0f;
|
||||
viewAreaOffset += moveSpeed.ToPoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||
{
|
||||
graphics.Clear(backgroundColor);
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable, samplerState: SamplerState.PointClamp);
|
||||
|
||||
var viewArea = GetViewArea;
|
||||
|
||||
if (selectedTexture != null)
|
||||
{
|
||||
textureRect = new Rectangle(
|
||||
(int)(viewArea.Center.X - selectedTexture.Bounds.Width / 2f * zoom),
|
||||
(int)(viewArea.Center.Y - selectedTexture.Bounds.Height / 2f * zoom),
|
||||
(int)(selectedTexture.Bounds.Width * zoom),
|
||||
(int)(selectedTexture.Bounds.Height * zoom));
|
||||
|
||||
spriteBatch.Draw(selectedTexture,
|
||||
viewArea.Center.ToVector2(),
|
||||
sourceRectangle: null,
|
||||
color: Color.White,
|
||||
rotation: 0.0f,
|
||||
origin: new Vector2(selectedTexture.Bounds.Width / 2.0f, selectedTexture.Bounds.Height / 2.0f),
|
||||
scale: zoom,
|
||||
effects: SpriteEffects.None,
|
||||
layerDepth: 0);
|
||||
|
||||
//GUI.DrawRectangle(spriteBatch, viewArea, Color.Green, isFilled: false);
|
||||
GUI.DrawRectangle(spriteBatch, textureRect, Color.Gray, isFilled: false);
|
||||
|
||||
foreach (GUIComponent element in spriteList.Content.Children)
|
||||
{
|
||||
Sprite sprite = element.UserData as Sprite;
|
||||
if (sprite == null) { continue; }
|
||||
if (sprite.Texture != selectedTexture) continue;
|
||||
spriteCount++;
|
||||
|
||||
Rectangle sourceRect = new Rectangle(
|
||||
textureRect.X + (int)(sprite.SourceRect.X * zoom),
|
||||
textureRect.Y + (int)(sprite.SourceRect.Y * zoom),
|
||||
(int)(sprite.SourceRect.Width * zoom),
|
||||
(int)(sprite.SourceRect.Height * zoom));
|
||||
|
||||
bool isSelected = selectedSprites.Contains(sprite);
|
||||
GUI.DrawRectangle(spriteBatch, sourceRect, isSelected ? Color.Yellow : Color.Red * 0.5f, thickness: isSelected ? 2 : 1);
|
||||
|
||||
string id = sprite.ID;
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
{
|
||||
int widgetSize = 10;
|
||||
Vector2 GetTopLeft() => sprite.SourceRect.Location.ToVector2();
|
||||
Vector2 GetTopRight() => new Vector2(GetTopLeft().X + sprite.SourceRect.Width, GetTopLeft().Y);
|
||||
Vector2 GetBottomRight() => new Vector2(GetTopRight().X, GetTopRight().Y + sprite.SourceRect.Height);
|
||||
var originWidget = GetWidget($"{id}_origin", sprite, widgetSize, Widget.Shape.Cross, initMethod: w =>
|
||||
{
|
||||
w.tooltip = $"Origin: {sprite.RelativeOrigin.FormatDoubleDecimal()}";
|
||||
w.MouseHeld += dTime =>
|
||||
{
|
||||
w.DrawPos = PlayerInput.MousePosition.Clamp(textureRect.Location.ToVector2() + GetTopLeft() * zoom, textureRect.Location.ToVector2() + GetBottomRight() * zoom);
|
||||
sprite.Origin = (w.DrawPos - textureRect.Location.ToVector2() - sprite.SourceRect.Location.ToVector2() * zoom) / zoom;
|
||||
w.tooltip = $"Origin: {sprite.RelativeOrigin.FormatDoubleDecimal()}";
|
||||
};
|
||||
w.refresh = () =>
|
||||
w.DrawPos = (textureRect.Location.ToVector2() + (sprite.Origin + sprite.SourceRect.Location.ToVector2()) * zoom)
|
||||
.Clamp(textureRect.Location.ToVector2() + GetTopLeft() * zoom, textureRect.Location.ToVector2() + GetBottomRight() * zoom);
|
||||
});
|
||||
var positionWidget = GetWidget($"{id}_position", sprite, widgetSize, Widget.Shape.Rectangle, initMethod: w =>
|
||||
{
|
||||
w.tooltip = $"Position: {sprite.SourceRect.Location}";
|
||||
w.MouseHeld += dTime =>
|
||||
{
|
||||
w.DrawPos = PlayerInput.MousePosition;
|
||||
sprite.SourceRect = new Rectangle(((w.DrawPos + new Vector2(w.size / 2) - textureRect.Location.ToVector2()) / zoom).ToPoint(), sprite.SourceRect.Size);
|
||||
if (spriteList.SelectedComponent is GUITextBlock textBox)
|
||||
{
|
||||
// TODO: cache the sprite name?
|
||||
textBox.Text = GetSpriteName(sprite) + " " + sprite.SourceRect;
|
||||
}
|
||||
w.tooltip = $"Position: {sprite.SourceRect.Location}";
|
||||
};
|
||||
w.refresh = () => w.DrawPos = textureRect.Location.ToVector2() + sprite.SourceRect.Location.ToVector2() * zoom - new Vector2(w.size / 2);
|
||||
});
|
||||
var sizeWidget = GetWidget($"{id}_size", sprite, widgetSize, Widget.Shape.Rectangle, initMethod: w =>
|
||||
{
|
||||
w.tooltip = $"Size: {sprite.SourceRect.Size}";
|
||||
w.MouseHeld += dTime =>
|
||||
{
|
||||
w.DrawPos = PlayerInput.MousePosition;
|
||||
sprite.SourceRect = new Rectangle(sprite.SourceRect.Location, ((w.DrawPos - new Vector2(w.size) - positionWidget.DrawPos) / zoom).ToPoint());
|
||||
// TODO: allow to lock the origin
|
||||
sprite.RelativeOrigin = sprite.RelativeOrigin;
|
||||
if (spriteList.SelectedComponent is GUITextBlock textBox)
|
||||
{
|
||||
// TODO: cache the sprite name?
|
||||
textBox.Text = GetSpriteName(sprite) + " " + sprite.SourceRect;
|
||||
}
|
||||
w.tooltip = $"Size: {sprite.SourceRect.Size}";
|
||||
};
|
||||
w.refresh = () => w.DrawPos = textureRect.Location.ToVector2() + new Vector2(sprite.SourceRect.Right, sprite.SourceRect.Bottom) * zoom + new Vector2(w.size / 2);
|
||||
});
|
||||
if (isSelected)
|
||||
{
|
||||
positionWidget.Draw(spriteBatch, (float)deltaTime);
|
||||
sizeWidget.Draw(spriteBatch, (float)deltaTime);
|
||||
originWidget.Draw(spriteBatch, (float)deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GUI.Draw(Cam, spriteBatch);
|
||||
|
||||
spriteCount = 0;
|
||||
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
public override void Select()
|
||||
{
|
||||
base.Select();
|
||||
LoadSprites();
|
||||
RefreshLists();
|
||||
// Store the reference, because lastSelected is reassigned when the texture is selected.
|
||||
Sprite lastSprite = lastSelected;
|
||||
// Select the last selected texture if any.
|
||||
// TODO: Does not work if the texture has been disposed. This happens when it's not used by any sprite -> is there a better way to identify the textures? id or something?
|
||||
if (selectedTexture != null && textureList.Content.Children.Any(c => c.UserData as Texture2D == selectedTexture))
|
||||
{
|
||||
textureList.Select(selectedTexture, autoScroll: false);
|
||||
UpdateScrollBar(textureList);
|
||||
// Select the last selected sprite if any
|
||||
if (lastSprite != null && spriteList.Content.Children.FirstOrDefault(c => c.UserData is Sprite s && s.ID == lastSprite.ID)?.UserData is Sprite sprite)
|
||||
{
|
||||
spriteList.Select(sprite, autoScroll: false);
|
||||
UpdateScrollBar(spriteList);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
spriteList.Select(0, autoScroll: false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
{
|
||||
base.Deselect();
|
||||
loadedSprites.ForEach(s => s.Remove());
|
||||
loadedSprites.Clear();
|
||||
ResetWidgets();
|
||||
// Automatically reload all sprites that have been selected at least once (and thus might have been edited)
|
||||
var reloadedSprites = new List<Sprite>();
|
||||
foreach (var sprite in dirtySprites)
|
||||
{
|
||||
foreach (var s in Sprite.LoadedSprites)
|
||||
{
|
||||
if (s.Texture == sprite.Texture && !reloadedSprites.Contains(s))
|
||||
{
|
||||
s.ReloadXML();
|
||||
reloadedSprites.Add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
dirtySprites.Clear();
|
||||
}
|
||||
|
||||
public void SelectSprite(Sprite sprite)
|
||||
{
|
||||
ResetWidgets();
|
||||
textureList.Select(sprite.Texture);
|
||||
ResetZoom();
|
||||
selectedSprites.Clear();
|
||||
selectedSprites.Add(sprite);
|
||||
}
|
||||
|
||||
public void RefreshLists()
|
||||
{
|
||||
//selectedTexture = null;
|
||||
selectedSprites.Clear();
|
||||
textureList.ClearChildren();
|
||||
spriteList.ClearChildren();
|
||||
ResetWidgets();
|
||||
HashSet<string> textures = new HashSet<string>();
|
||||
// Create texture list
|
||||
foreach (Sprite sprite in loadedSprites.OrderBy(s => Path.GetFileNameWithoutExtension(s.FilePath)))
|
||||
{
|
||||
//ignore sprites that don't have a file path (e.g. submarine pics)
|
||||
if (string.IsNullOrEmpty(sprite.FilePath)) continue;
|
||||
string normalizedFilePath = Path.GetFullPath(sprite.FilePath);
|
||||
if (!textures.Contains(normalizedFilePath))
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), textureList.Content.RectTransform) { MinSize = new Point(0, 20) },
|
||||
Path.GetFileName(sprite.FilePath))
|
||||
{
|
||||
Padding = Vector4.Zero,
|
||||
ToolTip = sprite.FilePath,
|
||||
UserData = sprite.Texture
|
||||
};
|
||||
textures.Add(normalizedFilePath);
|
||||
}
|
||||
}
|
||||
// Create sprite list
|
||||
// TODO: allow the user to choose whether to sort by file name or by texture sheet
|
||||
//foreach (Sprite sprite in loadedSprites.OrderBy(s => GetSpriteName(s)))
|
||||
foreach (Sprite sprite in loadedSprites.OrderBy(s => s.SourceElement.GetAttributeString("texture", string.Empty)))
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), spriteList.Content.RectTransform) { MinSize = new Point(0, 20) }, GetSpriteName(sprite) + " " + sprite.SourceRect)
|
||||
{
|
||||
Padding = Vector4.Zero,
|
||||
UserData = sprite
|
||||
};
|
||||
}
|
||||
topPanelContents.Visible = false;
|
||||
}
|
||||
|
||||
public void ResetZoom()
|
||||
{
|
||||
var viewArea = GetViewArea;
|
||||
float width = viewArea.Width / (float)selectedTexture.Width;
|
||||
float height = viewArea.Height / (float)selectedTexture.Height;
|
||||
maxZoom = 10; // TODO: user-definable?
|
||||
zoom = Math.Min(1, Math.Min(width, height));
|
||||
zoomBar.BarScroll = GetBarScrollValue();
|
||||
viewAreaOffset = Point.Zero;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
private Point viewAreaOffset;
|
||||
private Rectangle GetViewArea
|
||||
{
|
||||
get
|
||||
{
|
||||
int margin = 20;
|
||||
var viewArea = new Rectangle(leftPanel.Rect.Right + margin + viewAreaOffset.X, topPanel.Rect.Bottom + margin + viewAreaOffset.Y, rightPanel.Rect.Left - leftPanel.Rect.Right - margin * 2, Frame.Rect.Height - topPanel.Rect.Height - margin * 2);
|
||||
return viewArea;
|
||||
}
|
||||
}
|
||||
|
||||
private float GetBarScrollValue() => MathHelper.Lerp(0, 1, MathUtils.InverseLerp(minZoom, maxZoom, zoom));
|
||||
|
||||
private string GetSpriteName(Sprite sprite)
|
||||
{
|
||||
var sourceElement = sprite.SourceElement;
|
||||
if (sourceElement == null) { return string.Empty; }
|
||||
string name = sprite.Name;
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
name = sourceElement.Parent.GetAttributeString("identifier", string.Empty);
|
||||
}
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
name = sourceElement.Parent.GetAttributeString("name", string.Empty);
|
||||
}
|
||||
return string.IsNullOrEmpty(name) ? Path.GetFileNameWithoutExtension(sprite.FilePath) : name;
|
||||
}
|
||||
|
||||
private void UpdateScrollBar(GUIListBox listBox)
|
||||
{
|
||||
var sb = listBox.ScrollBar;
|
||||
sb.BarScroll = MathHelper.Clamp(MathHelper.Lerp(0, 1, MathUtils.InverseLerp(0, listBox.Content.CountChildren - 1, listBox.SelectedIndex)), sb.MinValue, sb.MaxValue);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Widgets
|
||||
private Dictionary<string, Widget> widgets = new Dictionary<string, Widget>();
|
||||
|
||||
private Widget GetWidget(string id, Sprite sprite, int size = 5, Widget.Shape shape = Widget.Shape.Rectangle, Action<Widget> initMethod = null)
|
||||
{
|
||||
if (!widgets.TryGetValue(id, out Widget widget))
|
||||
{
|
||||
int selectedSize = (int)Math.Round(size * 1.5f);
|
||||
widget = new Widget(id, size, shape)
|
||||
{
|
||||
data = sprite,
|
||||
color = Color.Yellow,
|
||||
secondaryColor = Color.Gray,
|
||||
tooltipOffset = new Vector2(selectedSize / 2 + 5, -10)
|
||||
};
|
||||
widget.PreDraw += (sp, dTime) =>
|
||||
{
|
||||
if (!widget.IsControlled)
|
||||
{
|
||||
widget.refresh();
|
||||
}
|
||||
};
|
||||
widget.PreUpdate += dTime => widget.Enabled = selectedSprites.Contains(sprite);
|
||||
widget.PostUpdate += dTime =>
|
||||
{
|
||||
widget.inputAreaMargin = widget.IsControlled ? 1000 : 0;
|
||||
widget.size = widget.IsSelected ? selectedSize : size;
|
||||
widget.isFilled = widget.IsControlled;
|
||||
};
|
||||
widgets.Add(id, widget);
|
||||
initMethod?.Invoke(widget);
|
||||
}
|
||||
return widget;
|
||||
}
|
||||
|
||||
private void ResetWidgets()
|
||||
{
|
||||
widgets.Clear();
|
||||
Widget.selectedWidgets.Clear();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user