Build 0.18.4.0
This commit is contained in:
@@ -176,12 +176,15 @@ namespace Barotrauma.Steam
|
||||
Directory.CreateDirectory(PublishStagingDir);
|
||||
await CopyDirectory(contentPackage.Dir, contentPackage.Name, Path.GetDirectoryName(contentPackage.Path)!, PublishStagingDir, ShouldCorrectPaths.No);
|
||||
|
||||
var stagingFileListPath = Path.Combine(PublishStagingDir, ContentPackage.FileListFileName);
|
||||
ContentPackage tempPkg = ContentPackage.TryLoad(stagingFileListPath) ?? throw new Exception("Staging copy could not be loaded");
|
||||
|
||||
//Load filelist.xml and write the hash into it so anyone downloading this mod knows what it should be
|
||||
ModProject modProject = new ModProject(contentPackage)
|
||||
ModProject modProject = new ModProject(tempPkg)
|
||||
{
|
||||
ModVersion = modVersion
|
||||
};
|
||||
modProject.Save(Path.Combine(PublishStagingDir, ContentPackage.FileListFileName));
|
||||
modProject.Save(stagingFileListPath);
|
||||
}
|
||||
|
||||
public static async Task<ContentPackage?> CreateLocalCopy(ContentPackage contentPackage)
|
||||
|
||||
+6
-4
@@ -46,7 +46,10 @@ namespace Barotrauma.Steam
|
||||
regularBox.CanBeFocused = true;
|
||||
}
|
||||
}
|
||||
filterBox = CreateSearchBox(mainLayout, width: 1.0f);
|
||||
|
||||
var searchRectT = NewItemRectT(mainLayout, heightScale: 1.0f);
|
||||
searchRectT.RelativeSize = (1.0f, searchRectT.RelativeSize.Y);
|
||||
filterBox = CreateSearchBox(searchRectT);
|
||||
|
||||
Label(mainLayout, TextManager.Get("CannotChangeMods"), GUIStyle.Font);
|
||||
}
|
||||
@@ -55,9 +58,8 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
string str = filterBox.Text;
|
||||
regularList.Content.Children
|
||||
.ForEach(c => c.Visible = str.IsNullOrWhiteSpace()
|
||||
|| (c.UserData is ContentPackage p
|
||||
&& p.Name.Contains(str, StringComparison.OrdinalIgnoreCase)));
|
||||
.ForEach(c => c.Visible = !(c.UserData is ContentPackage p)
|
||||
|| ModNameMatches(p, str));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,746 @@
|
||||
#nullable enable
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ItemOrPackage = Barotrauma.Either<Steamworks.Ugc.Item, Barotrauma.ContentPackage>;
|
||||
|
||||
namespace Barotrauma.Steam
|
||||
{
|
||||
sealed partial class MutableWorkshopMenu : WorkshopMenu
|
||||
{
|
||||
private CorePackage EnabledCorePackage => enabledCoreDropdown.SelectedData as CorePackage ?? throw new Exception("Valid core package not selected");
|
||||
|
||||
private readonly GUIDropDown enabledCoreDropdown;
|
||||
private readonly GUIListBox enabledRegularModsList;
|
||||
private readonly GUIListBox disabledRegularModsList;
|
||||
private readonly Action<ItemOrPackage> onInstalledInfoButtonHit;
|
||||
private readonly GUITextBox modsListFilter;
|
||||
private readonly Dictionary<Filter, GUITickBox> modsListFilterTickboxes;
|
||||
private readonly GUIButton bulkUpdateButton;
|
||||
|
||||
private GUIComponent? draggedElement = null;
|
||||
private GUIListBox? draggedElementOrigin = null;
|
||||
|
||||
private void UpdateSubscribedModInstalls()
|
||||
{
|
||||
if (!SteamManager.IsInitialized) { return; }
|
||||
|
||||
uint numSubscribedMods = SteamManager.GetNumSubscribedItems();
|
||||
if (numSubscribedMods == memSubscribedModCount) { return; }
|
||||
memSubscribedModCount = numSubscribedMods;
|
||||
|
||||
var subscribedIds = SteamManager.GetSubscribedItems().ToHashSet();
|
||||
var installedIds = ContentPackageManager.WorkshopPackages.Select(p => p.SteamWorkshopId).ToHashSet();
|
||||
foreach (var id in subscribedIds.Where(id2 => !installedIds.Contains(id2)))
|
||||
{
|
||||
Steamworks.Ugc.Item item = new Steamworks.Ugc.Item(id);
|
||||
if (!item.IsDownloading && !SteamManager.Workshop.IsInstalling(item))
|
||||
{
|
||||
SteamManager.Workshop.DownloadModThenEnqueueInstall(item);
|
||||
}
|
||||
}
|
||||
|
||||
TaskPool.Add("RemoveUnsubscribedItems", SteamManager.Workshop.GetPublishedItems(), t =>
|
||||
{
|
||||
if (!t.TryGetResult(out ISet<Steamworks.Ugc.Item> publishedItems)) { return; }
|
||||
|
||||
var allRequiredInstalled = subscribedIds.Union(publishedItems.Select(it => it.Id)).ToHashSet();
|
||||
bool needsRefresh = false;
|
||||
foreach (var id in installedIds.Where(id2 => !allRequiredInstalled.Contains(id2)))
|
||||
{
|
||||
Steamworks.Ugc.Item item = new Steamworks.Ugc.Item(id);
|
||||
SteamManager.Workshop.Uninstall(item);
|
||||
needsRefresh = true;
|
||||
}
|
||||
|
||||
if (needsRefresh)
|
||||
{
|
||||
PopulateInstalledModLists();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static (GUILayoutGroup Left, GUIFrame center, GUILayoutGroup Right) CreateSidebars(
|
||||
GUIComponent parent,
|
||||
float leftWidth = 0.3875f,
|
||||
float centerWidth = 0.025f,
|
||||
float rightWidth = 0.5875f,
|
||||
bool split = false,
|
||||
float height = 1.0f)
|
||||
{
|
||||
GUILayoutGroup layout = new GUILayoutGroup(new RectTransform((1.0f, height), parent.RectTransform), isHorizontal: true);
|
||||
GUILayoutGroup left = new GUILayoutGroup(new RectTransform((leftWidth, 1.0f), layout.RectTransform), isHorizontal: false);
|
||||
var center = new GUIFrame(new RectTransform((centerWidth, 1.0f), layout.RectTransform), style: null);
|
||||
if (split)
|
||||
{
|
||||
new GUICustomComponent(new RectTransform(Vector2.One, center.RectTransform),
|
||||
onDraw: (sb, c) =>
|
||||
{
|
||||
sb.DrawLine((c.Rect.Center.X, c.Rect.Top), (c.Rect.Center.X, c.Rect.Bottom), GUIStyle.TextColorDim, 2f);
|
||||
});
|
||||
}
|
||||
GUILayoutGroup right = new GUILayoutGroup(new RectTransform((rightWidth, 1.0f), layout.RectTransform), isHorizontal: false);
|
||||
return (left, center, right);
|
||||
}
|
||||
|
||||
private void HandleDraggingAcrossModLists(GUIListBox from, GUIListBox to)
|
||||
{
|
||||
if (to.Rect.Contains(PlayerInput.MousePosition) && from.DraggedElement != null)
|
||||
{
|
||||
//move the dragged elements to the index determined previously
|
||||
var draggedElement = from.DraggedElement;
|
||||
|
||||
var selected = from.AllSelected.ToList();
|
||||
selected.Sort((a, b) => from.Content.GetChildIndex(a) - from.Content.GetChildIndex(b));
|
||||
|
||||
float oldCount = to.Content.CountChildren;
|
||||
float newCount = oldCount + selected.Count;
|
||||
|
||||
var offset = draggedElement.RectTransform.AbsoluteOffset;
|
||||
offset += from.Content.Rect.Location;
|
||||
offset -= to.Content.Rect.Location;
|
||||
|
||||
for (int i = 0; i < selected.Count; i++)
|
||||
{
|
||||
var c = selected[i];
|
||||
c.Parent.RemoveChild(c);
|
||||
c.RectTransform.Parent = to.Content.RectTransform;
|
||||
c.RectTransform.RepositionChildInHierarchy((int)oldCount+i);
|
||||
}
|
||||
|
||||
from.DraggedElement = null;
|
||||
from.Deselect();
|
||||
from.RecalculateChildren();
|
||||
from.RectTransform.RecalculateScale(true);
|
||||
to.RecalculateChildren();
|
||||
to.RectTransform.RecalculateScale(true);
|
||||
to.Select(selected);
|
||||
|
||||
//recalculate the dragged element's offset so it doesn't jump around
|
||||
draggedElement.RectTransform.AbsoluteOffset = offset;
|
||||
|
||||
to.DraggedElement = draggedElement;
|
||||
|
||||
to.BarScroll *= (oldCount / newCount);
|
||||
}
|
||||
}
|
||||
|
||||
private Action? currentSwapFunc = null;
|
||||
private GUISoundType? swapSoundType = null;
|
||||
|
||||
private void PlaySwapSound()
|
||||
{
|
||||
SoundPlayer.PlayUISound(swapSoundType);
|
||||
}
|
||||
|
||||
private void SetSwapFunc(GUIListBox from, GUIListBox to)
|
||||
{
|
||||
currentSwapFunc = () =>
|
||||
{
|
||||
to.Deselect();
|
||||
var selected = from.AllSelected.ToArray();
|
||||
foreach (var frame in selected)
|
||||
{
|
||||
frame.Parent.RemoveChild(frame);
|
||||
frame.RectTransform.Parent = to.Content.RectTransform;
|
||||
}
|
||||
from.RecalculateChildren();
|
||||
from.RectTransform.RecalculateScale(true);
|
||||
to.RecalculateChildren();
|
||||
to.RectTransform.RecalculateScale(true);
|
||||
to.Select(selected);
|
||||
};
|
||||
|
||||
if (to == enabledRegularModsList)
|
||||
{
|
||||
swapSoundType = GUISoundType.Increase;
|
||||
}
|
||||
else if (to == disabledRegularModsList)
|
||||
{
|
||||
swapSoundType = GUISoundType.Decrease;
|
||||
}
|
||||
else
|
||||
{
|
||||
swapSoundType = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateInstalledModsTab(
|
||||
out GUIDropDown enabledCoreDropdown,
|
||||
out GUIListBox enabledRegularModsList,
|
||||
out GUIListBox disabledRegularModsList,
|
||||
out Action<ItemOrPackage> onInstalledInfoButtonHit,
|
||||
out GUITextBox modsListFilter,
|
||||
out Dictionary<Filter, GUITickBox> modsListFilterTickboxes,
|
||||
out GUIButton bulkUpdateButton)
|
||||
{
|
||||
GUIFrame content = CreateNewContentFrame(Tab.InstalledMods);
|
||||
|
||||
CreateWorkshopItemDetailContainer(
|
||||
content,
|
||||
out var outerContainer,
|
||||
onSelected: (itemOrPackage, selectedFrame) =>
|
||||
{
|
||||
if (itemOrPackage.TryGet(out Steamworks.Ugc.Item item)) { PopulateFrameWithItemInfo(item, selectedFrame); }
|
||||
},
|
||||
onDeselected: () => PopulateInstalledModLists(),
|
||||
out onInstalledInfoButtonHit, out var deselect);
|
||||
|
||||
GUILayoutGroup mainLayout =
|
||||
new GUILayoutGroup(new RectTransform(Vector2.One, outerContainer.Content.RectTransform), childAnchor: Anchor.TopCenter);
|
||||
mainLayout.RectTransform.SetAsFirstChild();
|
||||
|
||||
var (topLeft, _, topRight) = CreateSidebars(mainLayout, centerWidth: 0.05f, leftWidth: 0.475f, rightWidth: 0.475f, height: 0.13f);
|
||||
topLeft.Stretch = true;
|
||||
Label(topLeft, TextManager.Get("enabledcore"), GUIStyle.SubHeadingFont, heightScale: 1.0f);
|
||||
enabledCoreDropdown = Dropdown<CorePackage>(topLeft,
|
||||
(p) => p.Name,
|
||||
ContentPackageManager.CorePackages.ToArray(),
|
||||
ContentPackageManager.EnabledPackages.Core!,
|
||||
(p) => { },
|
||||
heightScale: 1.0f / 13.0f);
|
||||
Label(topLeft, "", GUIStyle.SubHeadingFont, heightScale: 1.0f);
|
||||
topRight.ChildAnchor = Anchor.CenterLeft;
|
||||
|
||||
var topRightButtons = new GUILayoutGroup(new RectTransform((1.0f, 0.5f), topRight.RectTransform),
|
||||
isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
void padTopRight(float width=1.0f)
|
||||
{
|
||||
new GUIFrame(new RectTransform((width, 1.0f), topRightButtons.RectTransform), style: null);
|
||||
}
|
||||
|
||||
padTopRight();
|
||||
//TODO: put stuff here
|
||||
padTopRight(width: 3.0f);
|
||||
var refreshListsButton
|
||||
= new GUIButton(
|
||||
new RectTransform(Vector2.One, topRightButtons.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
text: "", style: "GUIReloadButton")
|
||||
{
|
||||
OnClicked = (b, o) =>
|
||||
{
|
||||
PopulateInstalledModLists();
|
||||
return false;
|
||||
},
|
||||
ToolTip = TextManager.Get("RefreshModLists")
|
||||
};
|
||||
bulkUpdateButton
|
||||
= new GUIButton(
|
||||
new RectTransform(Vector2.One, topRightButtons.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
text: "", style: "GUIUpdateButton")
|
||||
{
|
||||
OnClicked = (b, o) =>
|
||||
{
|
||||
BulkDownloader.PrepareUpdates();
|
||||
return false;
|
||||
},
|
||||
Enabled = false
|
||||
};
|
||||
padTopRight(width: 0.1f);
|
||||
|
||||
var (left, center, right) = CreateSidebars(mainLayout, centerWidth: 0.05f, leftWidth: 0.475f, rightWidth: 0.475f, height: 0.8f);
|
||||
right.ChildAnchor = Anchor.TopRight;
|
||||
|
||||
//enabled mods
|
||||
Label(left, TextManager.Get("enabledregular"), GUIStyle.SubHeadingFont);
|
||||
var enabledModsList = new GUIListBox(new RectTransform((1.0f, 0.93f), left.RectTransform))
|
||||
{
|
||||
CurrentDragMode = GUIListBox.DragMode.DragOutsideBox,
|
||||
CurrentSelectMode = GUIListBox.SelectMode.RequireShiftToSelectMultiple,
|
||||
HideDraggedElement = true,
|
||||
PlaySoundOnSelect = true,
|
||||
SoundOnDragStart = GUISoundType.Select,
|
||||
SoundOnDragStop = GUISoundType.Increase,
|
||||
};
|
||||
enabledRegularModsList = enabledModsList;
|
||||
|
||||
//disabled mods
|
||||
Label(right, TextManager.Get("disabledregular"), GUIStyle.SubHeadingFont);
|
||||
var disabledModsList = new GUIListBox(new RectTransform((1.0f, 0.93f), right.RectTransform))
|
||||
{
|
||||
CurrentDragMode = GUIListBox.DragMode.DragOutsideBox,
|
||||
CurrentSelectMode = GUIListBox.SelectMode.RequireShiftToSelectMultiple,
|
||||
HideDraggedElement = true,
|
||||
PlaySoundOnSelect = true,
|
||||
SoundOnDragStart = GUISoundType.Select,
|
||||
SoundOnDragStop = GUISoundType.Decrease,
|
||||
};
|
||||
disabledRegularModsList = disabledModsList;
|
||||
|
||||
var centerButton =
|
||||
new GUIButton(
|
||||
new RectTransform(Vector2.One * 0.95f, center.RectTransform, scaleBasis: ScaleBasis.BothWidth,
|
||||
anchor: Anchor.Center),
|
||||
style: "GUIButtonToggleLeft")
|
||||
{
|
||||
PlaySoundOnSelect = false,
|
||||
Visible = false,
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
if (currentSwapFunc != null)
|
||||
{
|
||||
PlaySwapSound();
|
||||
currentSwapFunc.Invoke();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
enabledModsList.OnSelected = (frame, o) =>
|
||||
{
|
||||
disabledModsList.Deselect();
|
||||
|
||||
centerButton.Visible = true;
|
||||
centerButton.ApplyStyle(GUIStyle.GetComponentStyle("GUIButtonToggleRight"));
|
||||
|
||||
SetSwapFunc(enabledModsList, disabledModsList);
|
||||
|
||||
return true;
|
||||
};
|
||||
disabledModsList.OnSelected = (frame, o) =>
|
||||
{
|
||||
enabledModsList.Deselect();
|
||||
|
||||
centerButton.Visible = true;
|
||||
centerButton.ApplyStyle(GUIStyle.GetComponentStyle("GUIButtonToggleLeft"));
|
||||
|
||||
SetSwapFunc(disabledModsList, enabledModsList);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
var filterContainer = new GUILayoutGroup(NewItemRectT(mainLayout, heightScale: 1.0f), isHorizontal: true)
|
||||
{ Stretch = true, RelativeSpacing = 0.01f };
|
||||
|
||||
void padFilterContainer(float width = 0.25f)
|
||||
=> new GUIFrame(new RectTransform((width, 1.0f), filterContainer!.RectTransform), style: null);
|
||||
|
||||
GUIButton filterLayoutButton(string style)
|
||||
=> new GUIButton(
|
||||
new RectTransform(Vector2.One, filterContainer!.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
"", style: style);
|
||||
|
||||
padFilterContainer(width: 0.2f);
|
||||
var loadPresetBtn = filterLayoutButton("OpenButton");
|
||||
loadPresetBtn.ToolTip = TextManager.Get("LoadModListPresetHeader");
|
||||
loadPresetBtn.OnClicked = OpenLoadPreset;
|
||||
var savePresetBtn = filterLayoutButton("SaveButton");
|
||||
savePresetBtn.ToolTip = TextManager.Get("SaveModListPresetHeader");
|
||||
savePresetBtn.OnClicked = OpenSavePreset;
|
||||
padFilterContainer(width: 0.05f);
|
||||
var searchRectT = new RectTransform((0.5f, 1.0f), filterContainer.RectTransform);
|
||||
var searchBox = CreateSearchBox(searchRectT);
|
||||
modsListFilter = searchBox;
|
||||
|
||||
var filterTickboxes = new Dictionary<Filter, GUITickBox>();
|
||||
modsListFilterTickboxes = filterTickboxes;
|
||||
|
||||
var filterTickboxesDropdown
|
||||
= filterLayoutButton("SetupVisibilityButton");
|
||||
var filterTickboxesContainer
|
||||
= new GUIFrame(new RectTransform((0.3f, 0.2f), content.RectTransform,
|
||||
scaleBasis: ScaleBasis.BothWidth), style: "InnerFrame");
|
||||
var filterTickboxesUpdater
|
||||
= new GUICustomComponent(new RectTransform(Vector2.Zero, content.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
{
|
||||
filterTickboxesContainer.Visible = filterTickboxesDropdown.Selected;
|
||||
filterTickboxesContainer.RectTransform.AbsoluteOffset
|
||||
= (filterTickboxesDropdown.Rect.Location - content.Rect.Location)
|
||||
+ (filterTickboxesDropdown.Rect.Width / 2, 0)
|
||||
- (filterTickboxesContainer.Rect.Size.ToVector2() * (0.5f, 1.0f)).ToPoint();
|
||||
filterTickboxesContainer.RectTransform.NonScaledSize
|
||||
= new Point(filterTickboxes.Select(tb => (int)tb.Value.Font.MeasureString(tb.Value.GetChild<GUITextBlock>().Text).X).Max(),
|
||||
filterTickboxes.Select(tb => tb.Value.Rect.Height).Aggregate((a,b) => a+b))
|
||||
+(filterTickboxes.Values.First().Rect.Height * 4, filterTickboxes.Values.First().Rect.Height / 2);
|
||||
if (PlayerInput.PrimaryMouseButtonClicked()
|
||||
&& !GUI.IsMouseOn(filterTickboxesDropdown)
|
||||
&& !GUI.IsMouseOn(filterTickboxesContainer))
|
||||
{
|
||||
filterTickboxesDropdown.Selected = false;
|
||||
}
|
||||
});
|
||||
|
||||
var filterTickboxesLayout
|
||||
= new GUILayoutGroup(new RectTransform(Vector2.One * 0.95f, filterTickboxesContainer.RectTransform, Anchor.Center));
|
||||
|
||||
void addFilterTickbox(Filter filter, string? style, bool selected)
|
||||
{
|
||||
var tickbox = new GUITickBox(NewItemRectT(filterTickboxesLayout!, heightScale: 0.5f), "")
|
||||
{
|
||||
Selected = selected,
|
||||
OnSelected = _ =>
|
||||
{
|
||||
UpdateModListItemVisibility();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
filterTickboxes!.Add(filter, tickbox);
|
||||
var text = new GUITextBlock(new RectTransform((1.0f, 1.0f), tickbox.RectTransform, Anchor.CenterRight)
|
||||
{
|
||||
AbsoluteOffset = (-tickbox.Box.Rect.Width * 2, 0),
|
||||
},
|
||||
TextManager.Get($"ModFilter.{filter}"))
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var icon = new GUIFrame(
|
||||
new RectTransform(Vector2.One, text.RectTransform, Anchor.CenterLeft, Pivot.CenterRight,
|
||||
scaleBasis: ScaleBasis.BothHeight), style: style)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
|
||||
addFilterTickbox(Filter.ShowLocal, "WorkshopMenu.EditButton", selected: true);
|
||||
addFilterTickbox(Filter.ShowWorkshop, "WorkshopMenu.DownloadedIcon", selected: true);
|
||||
addFilterTickbox(Filter.ShowPublished, "WorkshopMenu.PublishedIcon", selected: true);
|
||||
addFilterTickbox(Filter.ShowOnlySubs, null, selected: false);
|
||||
addFilterTickbox(Filter.ShowOnlyItemAssemblies, null, selected: false);
|
||||
|
||||
padFilterContainer();
|
||||
|
||||
new GUICustomComponent(new RectTransform(Vector2.Zero, content.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
{
|
||||
HandleDraggingAcrossModLists(enabledModsList, disabledModsList);
|
||||
HandleDraggingAcrossModLists(disabledModsList, enabledModsList);
|
||||
UpdateDraggingSounds();
|
||||
|
||||
if (PlayerInput.PrimaryMouseButtonClicked()
|
||||
&& !GUI.IsMouseOn(enabledModsList)
|
||||
&& !GUI.IsMouseOn(disabledModsList)
|
||||
&& GUIContextMenu.CurrentContextMenu is null)
|
||||
{
|
||||
enabledModsList.Deselect();
|
||||
disabledModsList.Deselect();
|
||||
}
|
||||
else if (!PlayerInput.IsCtrlDown() && !PlayerInput.IsShiftDown() && PlayerInput.DoubleClicked())
|
||||
{
|
||||
currentSwapFunc?.Invoke();
|
||||
}
|
||||
},
|
||||
onDraw: (spriteBatch, component) =>
|
||||
{
|
||||
enabledModsList.DraggedElement?.DrawManually(spriteBatch, true, true);
|
||||
disabledModsList.DraggedElement?.DrawManually(spriteBatch, true, true);
|
||||
});
|
||||
|
||||
void UpdateDraggingSounds()
|
||||
{
|
||||
if (draggedElement != null)
|
||||
{
|
||||
if (enabledModsList.DraggedElement == null && disabledModsList.DraggedElement == null)
|
||||
{
|
||||
SetDragOrigin(null);
|
||||
}
|
||||
CheckDragStopSound(enabledModsList);
|
||||
CheckDragStopSound(disabledModsList);
|
||||
}
|
||||
else if (enabledModsList.DraggedElement != null)
|
||||
{
|
||||
SetDragOrigin(enabledModsList);
|
||||
}
|
||||
else if (disabledModsList.DraggedElement != null)
|
||||
{
|
||||
SetDragOrigin(disabledModsList);
|
||||
}
|
||||
|
||||
void SetDragOrigin(GUIListBox? listBox)
|
||||
{
|
||||
draggedElement = listBox?.DraggedElement;
|
||||
draggedElementOrigin = listBox;
|
||||
}
|
||||
|
||||
void CheckDragStopSound(GUIListBox listBox)
|
||||
{
|
||||
listBox.PlaySoundOnDragStop = listBox.DraggedElement != null && draggedElementOrigin != listBox;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateModListItemVisibility()
|
||||
{
|
||||
string str = modsListFilter.Text;
|
||||
enabledRegularModsList.Content.Children.Concat(disabledRegularModsList.Content.Children)
|
||||
.ForEach(c => c.Visible = !(c.UserData is ContentPackage p)
|
||||
|| ModNameMatches(p, str) && ModMatchesTickboxes(p, c));
|
||||
}
|
||||
|
||||
private bool ModMatchesTickboxes(ContentPackage p, GUIComponent guiItem)
|
||||
{
|
||||
var iconBtn = guiItem.GetChild<GUILayoutGroup>()?.GetAllChildren<GUIButton>().Last();
|
||||
|
||||
bool matches = false;
|
||||
matches |= modsListFilterTickboxes[Filter.ShowLocal].Selected
|
||||
&& ContentPackageManager.LocalPackages.Contains(p);
|
||||
matches |= modsListFilterTickboxes[Filter.ShowPublished].Selected
|
||||
&& (ContentPackageManager.WorkshopPackages.Contains(p)
|
||||
&& iconBtn?.Style?.Identifier == "WorkshopMenu.PublishedIcon");
|
||||
matches |= modsListFilterTickboxes[Filter.ShowWorkshop].Selected
|
||||
&& (ContentPackageManager.WorkshopPackages.Contains(p)
|
||||
&& iconBtn?.Style?.Identifier != "WorkshopMenu.PublishedIcon");
|
||||
|
||||
if (modsListFilterTickboxes[Filter.ShowOnlySubs].Selected
|
||||
&& modsListFilterTickboxes[Filter.ShowOnlyItemAssemblies].Selected
|
||||
&& p.Files.All(f => f is BaseSubFile || f is ItemAssemblyFile))
|
||||
{
|
||||
//Both the subs-only tickbox and the item-assembly-only tickbox
|
||||
//are enabled, and all files match either of them so show this mod
|
||||
}
|
||||
else if (modsListFilterTickboxes[Filter.ShowOnlySubs].Selected
|
||||
&& p.Files.Any(f => !(f is BaseSubFile)))
|
||||
{
|
||||
matches = false;
|
||||
}
|
||||
else if (modsListFilterTickboxes[Filter.ShowOnlyItemAssemblies].Selected
|
||||
&& p.Files.Any(f => !(f is ItemAssemblyFile)))
|
||||
{
|
||||
matches = false;
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
private void PrepareToShowModInfo(ContentPackage mod)
|
||||
{
|
||||
TaskPool.Add($"PrepareToShow{mod.SteamWorkshopId}Info", SteamManager.Workshop.GetItem(mod.SteamWorkshopId),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out Steamworks.Ugc.Item? item)) { return; }
|
||||
if (item is null) { return; }
|
||||
onInstalledInfoButtonHit(item.Value);
|
||||
});
|
||||
}
|
||||
|
||||
public void PopulateInstalledModLists(bool forceRefreshEnabled = false, bool refreshDisabled = true)
|
||||
{
|
||||
bulkUpdateButton.Enabled = false;
|
||||
bulkUpdateButton.ToolTip = "";
|
||||
ContentPackageManager.UpdateContentPackageList();
|
||||
|
||||
SwapDropdownValues<CorePackage>(enabledCoreDropdown,
|
||||
(p) => p.Name,
|
||||
ContentPackageManager.CorePackages.ToArray(),
|
||||
ContentPackageManager.EnabledPackages.Core!,
|
||||
(p) => { });
|
||||
|
||||
void addRegularModToList(RegularPackage mod, GUIListBox list)
|
||||
{
|
||||
var modFrame = new GUIFrame(new RectTransform((1.0f, 0.08f), list.Content.RectTransform),
|
||||
style: "ListBoxElement")
|
||||
{
|
||||
UserData = mod
|
||||
};
|
||||
|
||||
var contextMenuHandler = new GUICustomComponent(new RectTransform(Vector2.Zero, modFrame.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
{
|
||||
var parentList = modFrame.Parent?.Parent?.Parent as GUIListBox; //lovely jank :)
|
||||
if (parentList is null) { return; }
|
||||
if (GUI.MouseOn == modFrame && parentList.DraggedElement is null && PlayerInput.SecondaryMouseButtonClicked())
|
||||
{
|
||||
if (!parentList.AllSelected.Contains(modFrame)) { parentList.Select(parentList.Content.GetChildIndex(modFrame)); }
|
||||
static void noop() { }
|
||||
|
||||
List<ContextMenuOption> contextMenuOptions = new List<ContextMenuOption>();
|
||||
if (ContentPackageManager.WorkshopPackages.Contains(mod))
|
||||
{
|
||||
contextMenuOptions.Add(
|
||||
new ContextMenuOption("ViewWorkshopModDetails".ToIdentifier(), isEnabled: true, onSelected: () => PrepareToShowModInfo(mod)));
|
||||
}
|
||||
|
||||
var labelConditions
|
||||
= (parentList == enabledRegularModsList, parentList.AllSelected.Count > 1);
|
||||
Identifier swapLabel = (labelConditions switch
|
||||
{
|
||||
(true, true) => "EnableSelectedWorkshopMods",
|
||||
(true, false) => "EnableWorkshopMod",
|
||||
(false, true) => "DisableSelectedWorkshopMods",
|
||||
(false, false) => "DisableWorkshopMod"
|
||||
}).ToIdentifier();
|
||||
|
||||
contextMenuOptions.Add(new ContextMenuOption(swapLabel,
|
||||
isEnabled: true, onSelected: currentSwapFunc ?? noop));
|
||||
|
||||
var selectedMods = parentList.AllSelected.Select(it => it.UserData)
|
||||
.OfType<ContentPackage>().ToArray();
|
||||
if (selectedMods.All(ContentPackageManager.LocalPackages.Contains) && selectedMods.Length > 1)
|
||||
{
|
||||
contextMenuOptions.Add(new ContextMenuOption("MergeSelectedMods".ToIdentifier(), isEnabled: true,
|
||||
onSelected: () => ModMerger.AskMerge(selectedMods)));
|
||||
}
|
||||
|
||||
GUIButton? iconBtn(GUIComponent component) => component.GetChild<GUILayoutGroup>()?.GetAllChildren<GUIButton>().Last();
|
||||
if (selectedMods.All(ContentPackageManager.WorkshopPackages.Contains)
|
||||
&& parentList.AllSelected.All(c => iconBtn(c)?.Style?.Identifier == "WorkshopMenu.DownloadedIcon")
|
||||
&& selectedMods.Length > 0)
|
||||
{
|
||||
contextMenuOptions.Add(new ContextMenuOption(
|
||||
(selectedMods.Length > 1 ? "UnsubscribeFromAllSelected" : "WorkshopItemUnsubscribe").ToIdentifier(),
|
||||
isEnabled: true,
|
||||
onSelected: () =>
|
||||
{
|
||||
TaskPool.Add($"UnsubFromSelected", Task.WhenAll(selectedMods.Select(m => SteamManager.Workshop.GetItem(m.SteamWorkshopId))),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out Steamworks.Ugc.Item?[] items)) { return; }
|
||||
items.ForEach(it =>
|
||||
{
|
||||
if (!(it is { } item)) { return; }
|
||||
|
||||
item.Unsubscribe();
|
||||
SteamManager.Workshop.Uninstall(item);
|
||||
PopulateInstalledModLists();
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
GUIContextMenu.CreateContextMenu(
|
||||
pos: PlayerInput.MousePosition,
|
||||
header: ToolBox.LimitString(mod.Name, GUIStyle.SubHeadingFont, GUI.IntScale(300f)),
|
||||
headerColor: null,
|
||||
contextMenuOptions.ToArray());
|
||||
}
|
||||
});
|
||||
|
||||
var frameContent = new GUILayoutGroup(new RectTransform((0.95f, 0.9f), modFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
var dragIndicator = new GUIButton(new RectTransform((0.5f, 0.5f), frameContent.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
style: "GUIDragIndicator")
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
var modNameScissor = new GUIScissorComponent(new RectTransform((0.8f, 1.0f), frameContent.RectTransform))
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var modName = new GUITextBlock(new RectTransform(Vector2.One, modNameScissor.Content.RectTransform),
|
||||
text: mod.Name)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
if (mod.Errors.Any())
|
||||
{
|
||||
CreateModErrorInfo(mod, modFrame, modName);
|
||||
}
|
||||
if (ContentPackageManager.LocalPackages.Contains(mod))
|
||||
{
|
||||
var editButton = new GUIButton(new RectTransform(Vector2.One, frameContent.RectTransform, scaleBasis: ScaleBasis.Smallest), "",
|
||||
style: "WorkshopMenu.EditButton")
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
ToolBox.OpenFileWithShell(mod.Dir);
|
||||
return false;
|
||||
},
|
||||
ToolTip = TextManager.Get("OpenLocalModInExplorer")
|
||||
};
|
||||
}
|
||||
else if (ContentPackageManager.WorkshopPackages.Contains(mod))
|
||||
{
|
||||
var infoButton = new GUIButton(
|
||||
new RectTransform(Vector2.One, frameContent.RectTransform, scaleBasis: ScaleBasis.Smallest), "",
|
||||
style: null)
|
||||
{
|
||||
CanBeSelected = false,
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
PrepareToShowModInfo(mod);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
if (!SteamManager.IsInitialized)
|
||||
{
|
||||
infoButton.Enabled = false;
|
||||
}
|
||||
TaskPool.Add(
|
||||
$"DetermineUpdateRequired{mod.SteamWorkshopId}",
|
||||
mod.IsUpToDate(),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out bool isUpToDate)) { return; }
|
||||
|
||||
if (!isUpToDate)
|
||||
{
|
||||
infoButton.CanBeSelected = true;
|
||||
infoButton.ApplyStyle(GUIStyle.ComponentStyles["WorkshopMenu.InfoButtonUpdate"]);
|
||||
infoButton.ToolTip = TextManager.Get("ViewModDetailsUpdateAvailable");
|
||||
bulkUpdateButton.Enabled = true;
|
||||
bulkUpdateButton.ToolTip = TextManager.Get("ModUpdatesAvailable");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void addRegularModsToList(IEnumerable<RegularPackage> mods, GUIListBox list)
|
||||
{
|
||||
list.ClearChildren();
|
||||
foreach (var mod in mods)
|
||||
{
|
||||
addRegularModToList(mod, list);
|
||||
}
|
||||
}
|
||||
|
||||
var enabledMods =
|
||||
(forceRefreshEnabled || (enabledRegularModsList.Content.CountChildren + disabledRegularModsList.Content.CountChildren == 0)
|
||||
? ContentPackageManager.EnabledPackages.Regular
|
||||
: enabledRegularModsList.Content.Children
|
||||
.Select(c => c.UserData)
|
||||
.OfType<RegularPackage>()
|
||||
.Where(p => ContentPackageManager.RegularPackages.Contains(p)))
|
||||
.ToArray();
|
||||
var disabledMods = ContentPackageManager.RegularPackages.Where(p => !enabledMods.Contains(p));
|
||||
|
||||
addRegularModsToList(enabledMods, enabledRegularModsList);
|
||||
if (refreshDisabled) { addRegularModsToList(disabledMods, disabledRegularModsList); }
|
||||
|
||||
TaskPool.Add(
|
||||
$"DetermineWorkshopModIcons",
|
||||
SteamManager.Workshop.GetPublishedItems(),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out ISet<Steamworks.Ugc.Item> items)) { return; }
|
||||
var ids = items.Select(it => it.Id).ToHashSet();
|
||||
|
||||
foreach (var child in enabledRegularModsList.Content.Children
|
||||
.Concat(disabledRegularModsList.Content.Children))
|
||||
{
|
||||
var mod = child.UserData as RegularPackage;
|
||||
if (mod is null || !ContentPackageManager.WorkshopPackages.Contains(mod)) { continue; }
|
||||
|
||||
var btn = child.GetChild<GUILayoutGroup>()?.GetAllChildren<GUIButton>().Last();
|
||||
if (btn is null) { continue; }
|
||||
if (btn.Style != null) { continue; }
|
||||
|
||||
btn.ApplyStyle(
|
||||
GUIStyle.GetComponentStyle(
|
||||
ids.Contains(mod.SteamWorkshopId)
|
||||
? "WorkshopMenu.PublishedIcon"
|
||||
: "WorkshopMenu.DownloadedIcon"));
|
||||
btn.ToolTip = TextManager.Get(
|
||||
ids.Contains(mod.SteamWorkshopId)
|
||||
? "PublishedWorkshopMod"
|
||||
: "DownloadedWorkshopMod");
|
||||
btn.HoverCursor = CursorState.Default;
|
||||
}
|
||||
});
|
||||
|
||||
UpdateModListItemVisibility();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,7 +151,10 @@ namespace Barotrauma.Steam
|
||||
onDeselected: () => itemList?.Deselect(),
|
||||
out var select, out var deselect);
|
||||
|
||||
itemList = new GUIListBox(new RectTransform(Vector2.One, outerContainer.Content.RectTransform));
|
||||
itemList = new GUIListBox(new RectTransform(Vector2.One, outerContainer.Content.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
};
|
||||
itemList.RectTransform.SetAsFirstChild();
|
||||
workshopItemList = itemList;
|
||||
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.IO;
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
readonly struct ModListPreset
|
||||
{
|
||||
public const string SavePath = "ModLists";
|
||||
|
||||
public enum ModType
|
||||
{
|
||||
Vanilla,
|
||||
Local,
|
||||
Workshop
|
||||
}
|
||||
|
||||
public readonly string Name;
|
||||
public readonly CorePackage CorePackage;
|
||||
public readonly ImmutableArray<RegularPackage> RegularPackages;
|
||||
|
||||
public ModListPreset(XDocument doc)
|
||||
{
|
||||
Name = doc.Root!.GetAttributeString("name", "");
|
||||
|
||||
CorePackage corePackage = ContentPackageManager.VanillaCorePackage!;
|
||||
List<RegularPackage> regularPackages = new List<RegularPackage>();
|
||||
void addPkg(ContentPackage pkg)
|
||||
{
|
||||
if (pkg is CorePackage core) { corePackage = core; }
|
||||
else if (pkg is RegularPackage reg) { regularPackages.Add(reg); }
|
||||
}
|
||||
|
||||
foreach (var element in doc.Root!.Elements())
|
||||
{
|
||||
ModType modType = Enum.TryParse<ModType>(element.Name.LocalName, ignoreCase: true, out var mt) ? mt : ModType.Local;
|
||||
|
||||
switch (modType)
|
||||
{
|
||||
case ModType.Vanilla:
|
||||
CorePackage = ContentPackageManager.VanillaCorePackage!;
|
||||
break;
|
||||
case ModType.Workshop:
|
||||
{
|
||||
var id = element.GetAttributeUInt64("id", 0);
|
||||
var pkg = ContentPackageManager.WorkshopPackages.FirstOrDefault(p => p.SteamWorkshopId == id);
|
||||
if (id != 0 && pkg != null)
|
||||
{
|
||||
addPkg(pkg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ModType.Local:
|
||||
{
|
||||
var name = element.GetAttributeString("name", "");
|
||||
var pkg = ContentPackageManager.LocalPackages.FirstOrDefault(p => p.NameMatches(name));
|
||||
if (!name.IsNullOrEmpty() && pkg != null)
|
||||
{
|
||||
addPkg(pkg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CorePackage = corePackage;
|
||||
RegularPackages = regularPackages.ToImmutableArray();
|
||||
}
|
||||
|
||||
public ModListPreset(string name, CorePackage corePackage, IReadOnlyList<RegularPackage> regularPackages)
|
||||
{
|
||||
Name = name;
|
||||
CorePackage = corePackage;
|
||||
RegularPackages = regularPackages.ToImmutableArray();
|
||||
}
|
||||
|
||||
public RichString GetTooltip()
|
||||
{
|
||||
LocalizedString retVal = $"‖color:gui.orange‖{Name}‖end‖" //TODO: we need a RichString builder
|
||||
+ "\n " + TextManager.AddPunctuation(':', TextManager.Get("CorePackage"))
|
||||
+ "\n - " + CorePackage.Name;
|
||||
if (RegularPackages.Any())
|
||||
{
|
||||
retVal += "\n " + TextManager.AddPunctuation(':', TextManager.Get("RegularPackages"))
|
||||
+ "\n - "
|
||||
+ LocalizedString.Join("\n - ", RegularPackages.Select(p => (LocalizedString)p.Name));
|
||||
}
|
||||
|
||||
return RichString.Rich(retVal);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
XDocument newDoc = new XDocument();
|
||||
XElement newRoot = new XElement("mods", new XAttribute("name", Name));
|
||||
newDoc.Add(newRoot);
|
||||
|
||||
ModType determineType(ContentPackage pkg)
|
||||
{
|
||||
if (pkg == ContentPackageManager.VanillaCorePackage) { return ModType.Vanilla; }
|
||||
if (ContentPackageManager.WorkshopPackages.Contains(pkg)) { return ModType.Workshop; }
|
||||
return ModType.Local;
|
||||
}
|
||||
void writePkgElem(ContentPackage pkg)
|
||||
{
|
||||
var pkgType = determineType(pkg);
|
||||
var pkgElem = new XElement(pkgType.ToString());
|
||||
switch (pkgType)
|
||||
{
|
||||
case ModType.Workshop:
|
||||
pkgElem.SetAttributeValue("name", pkg.Name);
|
||||
pkgElem.SetAttributeValue("id", pkg.SteamWorkshopId.ToString());
|
||||
break;
|
||||
case ModType.Local:
|
||||
pkgElem.SetAttributeValue("name", pkg.Name);
|
||||
break;
|
||||
}
|
||||
newRoot.Add(pkgElem);
|
||||
}
|
||||
writePkgElem(CorePackage);
|
||||
RegularPackages.ForEach(writePkgElem);
|
||||
|
||||
if (!Directory.Exists(SavePath)) { Directory.CreateDirectory(SavePath); }
|
||||
newDoc.SaveSafe(Path.Combine(SavePath, ToolBox.RemoveInvalidFileNameChars($"{Name}.xml")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Barotrauma.Steam
|
||||
{
|
||||
sealed partial class MutableWorkshopMenu : WorkshopMenu
|
||||
{
|
||||
private bool OpenLoadPreset(GUIButton _, object __)
|
||||
{
|
||||
OpenLoadPreset();
|
||||
return false;
|
||||
}
|
||||
|
||||
private void OpenLoadPreset()
|
||||
{
|
||||
var msgBox = new GUIMessageBox(
|
||||
TextManager.Get("LoadModListPresetHeader"),
|
||||
"",
|
||||
buttons: new [] { TextManager.Get("Load"), TextManager.Get("Cancel") },
|
||||
relativeSize: (0.4f, 0.6f));
|
||||
|
||||
var presetListBox = new GUIListBox(new RectTransform((1.0f, 0.7f), msgBox.Content.RectTransform));
|
||||
|
||||
(string Path, XDocument? Doc) tryLoadXml(string path)
|
||||
=> (path, XMLExtensions.TryLoadXml(path));
|
||||
|
||||
var presets = Directory.Exists(ModListPreset.SavePath)
|
||||
? Directory.GetFiles(ModListPreset.SavePath)
|
||||
.Select(tryLoadXml)
|
||||
.Where(d => d.Doc != null)
|
||||
.ToArray()
|
||||
: Array.Empty<(string Path, XDocument? Doc)>();
|
||||
|
||||
foreach (var doc in presets)
|
||||
{
|
||||
ModListPreset preset = new ModListPreset(doc.Doc!);
|
||||
var presetFrame = new GUIFrame(new RectTransform((1.0f, 0.09f), presetListBox.Content.RectTransform),
|
||||
style: "ListBoxElement")
|
||||
{
|
||||
UserData = preset,
|
||||
ToolTip = preset.GetTooltip()
|
||||
};
|
||||
new GUITextBlock(new RectTransform(Vector2.One, presetFrame.RectTransform), preset.Name)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var deleteBtn
|
||||
= new GUIButton(new RectTransform((0.2f, 1.0f), presetFrame.RectTransform, Anchor.CenterRight),
|
||||
TextManager.Get("Delete"), style: "GUIButtonSmall")
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
File.Delete(doc.Path);
|
||||
presetListBox.Content.RemoveChild(presetFrame);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (button, o) =>
|
||||
{
|
||||
if (presetListBox.SelectedData is ModListPreset preset)
|
||||
{
|
||||
var allChildren = enabledRegularModsList.Content.Children
|
||||
.Concat(disabledRegularModsList.Content.Children)
|
||||
.ToArray();
|
||||
enabledRegularModsList.ClearChildren();
|
||||
disabledRegularModsList.ClearChildren();
|
||||
var toEnable =
|
||||
allChildren.Where(c => c.UserData is RegularPackage p
|
||||
&& preset.RegularPackages.Contains(p))
|
||||
.OrderBy(c => c.UserData is RegularPackage p ? preset.RegularPackages.IndexOf(p) : int.MaxValue)
|
||||
.ToArray();
|
||||
var toDisable = allChildren.Where(c => !toEnable.Contains(c)).ToArray();
|
||||
toEnable.ForEach(c => c.RectTransform.Parent = enabledRegularModsList.Content.RectTransform);
|
||||
toDisable.ForEach(c => c.RectTransform.Parent = disabledRegularModsList.Content.RectTransform);
|
||||
|
||||
enabledCoreDropdown.SelectItem(preset.CorePackage);
|
||||
}
|
||||
msgBox.Close();
|
||||
return false;
|
||||
};
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
}
|
||||
|
||||
private bool OpenSavePreset(GUIButton _, object __)
|
||||
{
|
||||
OpenSavePreset();
|
||||
return false;
|
||||
}
|
||||
|
||||
private void OpenSavePreset()
|
||||
{
|
||||
var msgBox = new GUIMessageBox(
|
||||
TextManager.Get("SaveModListPresetHeader"),
|
||||
"",
|
||||
buttons: new [] { TextManager.Get("Save"), TextManager.Get("Cancel") },
|
||||
relativeSize: (0.4f, 0.2f));
|
||||
|
||||
var nameBox = new GUITextBox(new RectTransform((1.0f, 0.3f), msgBox.Content.RectTransform), "");
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (button, o) =>
|
||||
{
|
||||
if (nameBox.Text.IsNullOrEmpty())
|
||||
{
|
||||
nameBox.Flash(GUIStyle.Red);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (enabledCoreDropdown.SelectedData is CorePackage corePackage)
|
||||
{
|
||||
ModListPreset preset = new ModListPreset(nameBox.Text,
|
||||
corePackage,
|
||||
enabledRegularModsList.Content.Children
|
||||
.Select(c => c.UserData)
|
||||
.OfType<RegularPackage>().ToArray());
|
||||
preset.Save();
|
||||
}
|
||||
msgBox.Close();
|
||||
return false;
|
||||
};
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-504
@@ -3,9 +3,9 @@ using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ItemOrPackage = Barotrauma.Either<Steamworks.Ugc.Item, Barotrauma.ContentPackage>;
|
||||
|
||||
namespace Barotrauma.Steam
|
||||
@@ -20,20 +20,20 @@ namespace Barotrauma.Steam
|
||||
Publish
|
||||
}
|
||||
|
||||
private enum Filter
|
||||
{
|
||||
ShowLocal,
|
||||
ShowWorkshop,
|
||||
ShowPublished,
|
||||
ShowOnlySubs,
|
||||
ShowOnlyItemAssemblies
|
||||
}
|
||||
|
||||
private readonly GUILayoutGroup tabber;
|
||||
private readonly Dictionary<Tab, (GUIButton Button, GUIFrame Content)> tabContents;
|
||||
|
||||
private readonly GUIFrame contentFrame;
|
||||
|
||||
private CorePackage EnabledCorePackage => enabledCoreDropdown.SelectedData as CorePackage ?? throw new Exception("Valid core package not selected");
|
||||
|
||||
private readonly GUIDropDown enabledCoreDropdown;
|
||||
private readonly GUIListBox enabledRegularModsList;
|
||||
private readonly GUIListBox disabledRegularModsList;
|
||||
private readonly Action<ItemOrPackage> onInstalledInfoButtonHit;
|
||||
private readonly GUITextBox modsListFilter;
|
||||
private readonly GUIButton bulkUpdateButton;
|
||||
|
||||
private CancellationTokenSource taskCancelSrc = new CancellationTokenSource();
|
||||
private readonly HashSet<SteamManager.Workshop.ItemThumbnail> itemThumbnails = new HashSet<SteamManager.Workshop.ItemThumbnail>();
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Barotrauma.Steam
|
||||
private readonly GUIListBox selfModsList;
|
||||
|
||||
private uint memSubscribedModCount = 0;
|
||||
|
||||
|
||||
public MutableWorkshopMenu(GUIFrame parent) : base(parent)
|
||||
{
|
||||
var mainLayout
|
||||
@@ -62,6 +62,7 @@ namespace Barotrauma.Steam
|
||||
out disabledRegularModsList,
|
||||
out onInstalledInfoButtonHit,
|
||||
out modsListFilter,
|
||||
out modsListFilterTickboxes,
|
||||
out bulkUpdateButton);
|
||||
CreatePopularModsTab(out popularModsList);
|
||||
CreatePublishTab(out selfModsList);
|
||||
@@ -69,45 +70,6 @@ namespace Barotrauma.Steam
|
||||
SelectTab(Tab.InstalledMods);
|
||||
}
|
||||
|
||||
private void UpdateSubscribedModInstalls()
|
||||
{
|
||||
if (!SteamManager.IsInitialized) { return; }
|
||||
|
||||
uint numSubscribedMods = SteamManager.GetNumSubscribedItems();
|
||||
if (numSubscribedMods == memSubscribedModCount) { return; }
|
||||
memSubscribedModCount = numSubscribedMods;
|
||||
|
||||
var subscribedIds = SteamManager.GetSubscribedItems().ToHashSet();
|
||||
var installedIds = ContentPackageManager.WorkshopPackages.Select(p => p.SteamWorkshopId).ToHashSet();
|
||||
foreach (var id in subscribedIds.Where(id2 => !installedIds.Contains(id2)))
|
||||
{
|
||||
Steamworks.Ugc.Item item = new Steamworks.Ugc.Item(id);
|
||||
if (!item.IsDownloading && !SteamManager.Workshop.IsInstalling(item))
|
||||
{
|
||||
SteamManager.Workshop.DownloadModThenEnqueueInstall(item);
|
||||
}
|
||||
}
|
||||
|
||||
TaskPool.Add("RemoveUnsubscribedItems", SteamManager.Workshop.GetPublishedItems(), t =>
|
||||
{
|
||||
if (!t.TryGetResult(out ISet<Steamworks.Ugc.Item> publishedItems)) { return; }
|
||||
|
||||
var allRequiredInstalled = subscribedIds.Union(publishedItems.Select(it => it.Id)).ToHashSet();
|
||||
bool needsRefresh = false;
|
||||
foreach (var id in installedIds.Where(id2 => !allRequiredInstalled.Contains(id2)))
|
||||
{
|
||||
Steamworks.Ugc.Item item = new Steamworks.Ugc.Item(id);
|
||||
SteamManager.Workshop.Uninstall(item);
|
||||
needsRefresh = true;
|
||||
}
|
||||
|
||||
if (needsRefresh)
|
||||
{
|
||||
PopulateInstalledModLists();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void SwitchContent(GUIFrame newContent)
|
||||
{
|
||||
contentFrame.Children.ForEach(c => c.Visible = false);
|
||||
@@ -161,460 +123,6 @@ namespace Barotrauma.Steam
|
||||
return content;
|
||||
}
|
||||
|
||||
private static (GUILayoutGroup Left, GUIFrame center, GUILayoutGroup Right) CreateSidebars(
|
||||
GUIComponent parent,
|
||||
float leftWidth = 0.3875f,
|
||||
float centerWidth = 0.025f,
|
||||
float rightWidth = 0.5875f,
|
||||
bool split = false,
|
||||
float height = 1.0f)
|
||||
{
|
||||
GUILayoutGroup layout = new GUILayoutGroup(new RectTransform((1.0f, height), parent.RectTransform), isHorizontal: true);
|
||||
GUILayoutGroup left = new GUILayoutGroup(new RectTransform((leftWidth, 1.0f), layout.RectTransform), isHorizontal: false);
|
||||
var center = new GUIFrame(new RectTransform((centerWidth, 1.0f), layout.RectTransform), style: null);
|
||||
if (split)
|
||||
{
|
||||
new GUICustomComponent(new RectTransform(Vector2.One, center.RectTransform),
|
||||
onDraw: (sb, c) =>
|
||||
{
|
||||
sb.DrawLine((c.Rect.Center.X, c.Rect.Top), (c.Rect.Center.X, c.Rect.Bottom), GUIStyle.TextColorDim, 2f);
|
||||
});
|
||||
}
|
||||
GUILayoutGroup right = new GUILayoutGroup(new RectTransform((rightWidth, 1.0f), layout.RectTransform), isHorizontal: false);
|
||||
return (left, center, right);
|
||||
}
|
||||
|
||||
private void HandleDraggingAcrossModLists(GUIListBox from, GUIListBox to)
|
||||
{
|
||||
if (to.Rect.Contains(PlayerInput.MousePosition) && from.DraggedElement != null)
|
||||
{
|
||||
//move the dragged elements to the index determined previously
|
||||
var draggedElement = from.DraggedElement;
|
||||
|
||||
var selected = from.AllSelected.ToList();
|
||||
selected.Sort((a, b) => from.Content.GetChildIndex(a) - from.Content.GetChildIndex(b));
|
||||
|
||||
float oldCount = to.Content.CountChildren;
|
||||
float newCount = oldCount + selected.Count;
|
||||
|
||||
var offset = draggedElement.RectTransform.AbsoluteOffset;
|
||||
offset += from.Content.Rect.Location;
|
||||
offset -= to.Content.Rect.Location;
|
||||
|
||||
for (int i = 0; i < selected.Count; i++)
|
||||
{
|
||||
var c = selected[i];
|
||||
c.Parent.RemoveChild(c);
|
||||
c.RectTransform.Parent = to.Content.RectTransform;
|
||||
c.RectTransform.RepositionChildInHierarchy((int)oldCount+i);
|
||||
}
|
||||
|
||||
from.DraggedElement = null;
|
||||
from.Deselect();
|
||||
from.RecalculateChildren();
|
||||
from.RectTransform.RecalculateScale(true);
|
||||
to.RecalculateChildren();
|
||||
to.RectTransform.RecalculateScale(true);
|
||||
to.Select(selected);
|
||||
|
||||
//recalculate the dragged element's offset so it doesn't jump around
|
||||
draggedElement.RectTransform.AbsoluteOffset = offset;
|
||||
|
||||
to.DraggedElement = draggedElement;
|
||||
|
||||
to.BarScroll *= (oldCount / newCount);
|
||||
}
|
||||
}
|
||||
|
||||
private Action? currentSwapFunc = null;
|
||||
|
||||
private void SetSwapFunc(GUIListBox from, GUIListBox to)
|
||||
{
|
||||
currentSwapFunc = () =>
|
||||
{
|
||||
to.Deselect();
|
||||
var selected = from.AllSelected.ToArray();
|
||||
foreach (var frame in selected)
|
||||
{
|
||||
frame.Parent.RemoveChild(frame);
|
||||
frame.RectTransform.Parent = to.Content.RectTransform;
|
||||
}
|
||||
from.RecalculateChildren();
|
||||
from.RectTransform.RecalculateScale(true);
|
||||
to.RecalculateChildren();
|
||||
to.RectTransform.RecalculateScale(true);
|
||||
to.Select(selected);
|
||||
};
|
||||
}
|
||||
|
||||
private void CreateInstalledModsTab(
|
||||
out GUIDropDown enabledCoreDropdown,
|
||||
out GUIListBox enabledRegularModsList,
|
||||
out GUIListBox disabledRegularModsList,
|
||||
out Action<ItemOrPackage> onInstalledInfoButtonHit,
|
||||
out GUITextBox modsListFilter,
|
||||
out GUIButton bulkUpdateButton)
|
||||
{
|
||||
GUIFrame content = CreateNewContentFrame(Tab.InstalledMods);
|
||||
|
||||
CreateWorkshopItemDetailContainer(
|
||||
content,
|
||||
out var outerContainer,
|
||||
onSelected: (itemOrPackage, selectedFrame) =>
|
||||
{
|
||||
if (itemOrPackage.TryGet(out Steamworks.Ugc.Item item)) { PopulateFrameWithItemInfo(item, selectedFrame); }
|
||||
},
|
||||
onDeselected: () => PopulateInstalledModLists(),
|
||||
out onInstalledInfoButtonHit, out var deselect);
|
||||
|
||||
GUILayoutGroup mainLayout =
|
||||
new GUILayoutGroup(new RectTransform(Vector2.One, outerContainer.Content.RectTransform), childAnchor: Anchor.TopCenter);
|
||||
mainLayout.RectTransform.SetAsFirstChild();
|
||||
|
||||
var (topLeft, _, topRight) = CreateSidebars(mainLayout, centerWidth: 0.05f, leftWidth: 0.475f, rightWidth: 0.475f, height: 0.13f);
|
||||
topLeft.Stretch = true;
|
||||
Label(topLeft, TextManager.Get("enabledcore"), GUIStyle.SubHeadingFont, heightScale: 1.0f);
|
||||
enabledCoreDropdown = Dropdown<CorePackage>(topLeft,
|
||||
(p) => p.Name,
|
||||
ContentPackageManager.CorePackages.ToArray(),
|
||||
ContentPackageManager.EnabledPackages.Core!,
|
||||
(p) => { },
|
||||
heightScale: 1.0f / 13.0f);
|
||||
Label(topLeft, "", GUIStyle.SubHeadingFont, heightScale: 1.0f);
|
||||
topRight.ChildAnchor = Anchor.CenterLeft;
|
||||
|
||||
var topRightButtons = new GUILayoutGroup(new RectTransform((1.0f, 0.5f), topRight.RectTransform),
|
||||
isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
void padTopRight(float width=1.0f)
|
||||
{
|
||||
new GUIFrame(new RectTransform((width, 1.0f), topRightButtons.RectTransform), style: null);
|
||||
}
|
||||
|
||||
padTopRight();
|
||||
//TODO: put stuff here
|
||||
padTopRight(width: 3.0f);
|
||||
var refreshListsButton
|
||||
= new GUIButton(
|
||||
new RectTransform(Vector2.One, topRightButtons.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
text: "", style: "GUIReloadButton")
|
||||
{
|
||||
OnClicked = (b, o) =>
|
||||
{
|
||||
PopulateInstalledModLists();
|
||||
return false;
|
||||
},
|
||||
ToolTip = TextManager.Get("RefreshModLists")
|
||||
};
|
||||
bulkUpdateButton
|
||||
= new GUIButton(
|
||||
new RectTransform(Vector2.One, topRightButtons.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
text: "", style: "GUIUpdateButton")
|
||||
{
|
||||
OnClicked = (b, o) =>
|
||||
{
|
||||
BulkDownloader.PrepareUpdates();
|
||||
return false;
|
||||
},
|
||||
Enabled = false
|
||||
};
|
||||
padTopRight(width: 0.1f);
|
||||
|
||||
var (left, center, right) = CreateSidebars(mainLayout, centerWidth: 0.05f, leftWidth: 0.475f, rightWidth: 0.475f, height: 0.8f);
|
||||
right.ChildAnchor = Anchor.TopRight;
|
||||
|
||||
//enabled mods
|
||||
Label(left, TextManager.Get("enabledregular"), GUIStyle.SubHeadingFont);
|
||||
var enabledModsList = new GUIListBox(new RectTransform((1.0f, 0.93f), left.RectTransform))
|
||||
{
|
||||
CurrentDragMode = GUIListBox.DragMode.DragOutsideBox,
|
||||
CurrentSelectMode = GUIListBox.SelectMode.RequireShiftToSelectMultiple,
|
||||
HideDraggedElement = true
|
||||
};
|
||||
enabledRegularModsList = enabledModsList;
|
||||
|
||||
//disabled mods
|
||||
Label(right, TextManager.Get("disabledregular"), GUIStyle.SubHeadingFont);
|
||||
var disabledModsList = new GUIListBox(new RectTransform((1.0f, 0.93f), right.RectTransform))
|
||||
{
|
||||
CurrentDragMode = GUIListBox.DragMode.DragOutsideBox,
|
||||
CurrentSelectMode = GUIListBox.SelectMode.RequireShiftToSelectMultiple,
|
||||
HideDraggedElement = true
|
||||
};
|
||||
disabledRegularModsList = disabledModsList;
|
||||
|
||||
var centerButton =
|
||||
new GUIButton(
|
||||
new RectTransform(Vector2.One * 0.95f, center.RectTransform, scaleBasis: ScaleBasis.BothWidth,
|
||||
anchor: Anchor.Center),
|
||||
style: "GUIButtonToggleLeft")
|
||||
{
|
||||
Visible = false,
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
currentSwapFunc?.Invoke();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
enabledModsList.OnSelected = (frame, o) =>
|
||||
{
|
||||
disabledModsList.Deselect();
|
||||
|
||||
centerButton.Visible = true;
|
||||
centerButton.ApplyStyle(GUIStyle.GetComponentStyle("GUIButtonToggleRight"));
|
||||
|
||||
SetSwapFunc(enabledModsList, disabledModsList);
|
||||
|
||||
return true;
|
||||
};
|
||||
disabledModsList.OnSelected = (frame, o) =>
|
||||
{
|
||||
enabledModsList.Deselect();
|
||||
|
||||
centerButton.Visible = true;
|
||||
centerButton.ApplyStyle(GUIStyle.GetComponentStyle("GUIButtonToggleLeft"));
|
||||
|
||||
SetSwapFunc(disabledModsList, enabledModsList);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
var searchBox = CreateSearchBox(mainLayout, width: 0.5f);
|
||||
modsListFilter = searchBox;
|
||||
|
||||
new GUICustomComponent(new RectTransform(Vector2.Zero, content.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
{
|
||||
HandleDraggingAcrossModLists(enabledModsList, disabledModsList);
|
||||
HandleDraggingAcrossModLists(disabledModsList, enabledModsList);
|
||||
if (PlayerInput.PrimaryMouseButtonClicked()
|
||||
&& !GUI.IsMouseOn(enabledModsList)
|
||||
&& !GUI.IsMouseOn(disabledModsList)
|
||||
&& GUIContextMenu.CurrentContextMenu is null)
|
||||
{
|
||||
enabledModsList.Deselect();
|
||||
disabledModsList.Deselect();
|
||||
}
|
||||
else if (!PlayerInput.IsCtrlDown() && !PlayerInput.IsShiftDown() && PlayerInput.DoubleClicked())
|
||||
{
|
||||
currentSwapFunc?.Invoke();
|
||||
}
|
||||
},
|
||||
onDraw: (spriteBatch, component) =>
|
||||
{
|
||||
enabledModsList.DraggedElement?.DrawManually(spriteBatch, true, true);
|
||||
disabledModsList.DraggedElement?.DrawManually(spriteBatch, true, true);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void UpdateModListItemVisibility()
|
||||
{
|
||||
string str = modsListFilter.Text;
|
||||
enabledRegularModsList.Content.Children.Concat(disabledRegularModsList.Content.Children)
|
||||
.ForEach(c => c.Visible = str.IsNullOrWhiteSpace()
|
||||
|| (c.UserData is ContentPackage p
|
||||
&& p.Name.Contains(str, StringComparison.OrdinalIgnoreCase)));
|
||||
}
|
||||
|
||||
private void PrepareToShowModInfo(ContentPackage mod)
|
||||
{
|
||||
TaskPool.Add($"PrepareToShow{mod.SteamWorkshopId}Info", SteamManager.Workshop.GetItem(mod.SteamWorkshopId),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out Steamworks.Ugc.Item? item)) { return; }
|
||||
if (item is null) { return; }
|
||||
onInstalledInfoButtonHit(item.Value);
|
||||
});
|
||||
}
|
||||
|
||||
public void PopulateInstalledModLists(bool forceRefreshEnabled = false, bool refreshDisabled = true)
|
||||
{
|
||||
bulkUpdateButton.Enabled = false;
|
||||
bulkUpdateButton.ToolTip = "";
|
||||
ContentPackageManager.UpdateContentPackageList();
|
||||
|
||||
SwapDropdownValues<CorePackage>(enabledCoreDropdown,
|
||||
(p) => p.Name,
|
||||
ContentPackageManager.CorePackages.ToArray(),
|
||||
ContentPackageManager.EnabledPackages.Core!,
|
||||
(p) => { });
|
||||
|
||||
void addRegularModToList(RegularPackage mod, GUIListBox list)
|
||||
{
|
||||
var modFrame = new GUIFrame(new RectTransform((1.0f, 0.08f), list.Content.RectTransform),
|
||||
style: "ListBoxElement")
|
||||
{
|
||||
UserData = mod
|
||||
};
|
||||
|
||||
var contextMenuHandler = new GUICustomComponent(new RectTransform(Vector2.Zero, modFrame.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
{
|
||||
var parentList = modFrame.Parent?.Parent?.Parent as GUIListBox; //lovely jank :)
|
||||
if (parentList is null) { return; }
|
||||
if (GUI.MouseOn == modFrame && parentList.DraggedElement is null && PlayerInput.SecondaryMouseButtonClicked())
|
||||
{
|
||||
if (!parentList.AllSelected.Contains(modFrame)) { parentList.Select(parentList.Content.GetChildIndex(modFrame)); }
|
||||
static void noop() { }
|
||||
|
||||
List<ContextMenuOption> contextMenuOptions = new List<ContextMenuOption>();
|
||||
if (ContentPackageManager.WorkshopPackages.Contains(mod))
|
||||
{
|
||||
contextMenuOptions.Add(
|
||||
new ContextMenuOption("ViewWorkshopModDetails".ToIdentifier(), isEnabled: true, onSelected: () => PrepareToShowModInfo(mod)));
|
||||
}
|
||||
|
||||
Identifier swapLabel
|
||||
= ((parentList == enabledRegularModsList ? "Disable" : "Enable")
|
||||
+ (parentList.AllSelected.Count > 1 ? "SelectedWorkshopMods" : "WorkshopMod"))
|
||||
.ToIdentifier();
|
||||
|
||||
contextMenuOptions.Add(new ContextMenuOption(swapLabel,
|
||||
isEnabled: true, onSelected: currentSwapFunc ?? noop));
|
||||
|
||||
GUIContextMenu.CreateContextMenu(
|
||||
pos: PlayerInput.MousePosition,
|
||||
header: ToolBox.LimitString(mod.Name, GUIStyle.SubHeadingFont, GUI.IntScale(300f)),
|
||||
headerColor: null,
|
||||
contextMenuOptions.ToArray());
|
||||
}
|
||||
});
|
||||
|
||||
var frameContent = new GUILayoutGroup(new RectTransform((0.95f, 0.9f), modFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
var dragIndicator = new GUIButton(new RectTransform((0.5f, 0.5f), frameContent.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
style: "GUIDragIndicator")
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
var modNameScissor = new GUIScissorComponent(new RectTransform((0.8f, 1.0f), frameContent.RectTransform))
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var modName = new GUITextBlock(new RectTransform(Vector2.One, modNameScissor.Content.RectTransform),
|
||||
text: mod.Name)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
if (mod.Errors.Any())
|
||||
{
|
||||
CreateModErrorInfo(mod, modFrame, modName);
|
||||
}
|
||||
if (ContentPackageManager.LocalPackages.Contains(mod))
|
||||
{
|
||||
var editButton = new GUIButton(new RectTransform(Vector2.One, frameContent.RectTransform, scaleBasis: ScaleBasis.Smallest), "",
|
||||
style: "WorkshopMenu.EditButton")
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
ToolBox.OpenFileWithShell(mod.Dir);
|
||||
return false;
|
||||
},
|
||||
ToolTip = TextManager.Get("OpenLocalModInExplorer")
|
||||
};
|
||||
}
|
||||
else if (ContentPackageManager.WorkshopPackages.Contains(mod))
|
||||
{
|
||||
var infoButton = new GUIButton(
|
||||
new RectTransform(Vector2.One, frameContent.RectTransform, scaleBasis: ScaleBasis.Smallest), "",
|
||||
style: null)
|
||||
{
|
||||
CanBeSelected = false,
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
PrepareToShowModInfo(mod);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
if (!SteamManager.IsInitialized)
|
||||
{
|
||||
infoButton.Enabled = false;
|
||||
}
|
||||
TaskPool.Add(
|
||||
$"DetermineUpdateRequired{mod.SteamWorkshopId}",
|
||||
mod.IsUpToDate(),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out bool isUpToDate)) { return; }
|
||||
|
||||
if (!isUpToDate)
|
||||
{
|
||||
infoButton.CanBeSelected = true;
|
||||
infoButton.ApplyStyle(GUIStyle.ComponentStyles["WorkshopMenu.InfoButtonUpdate"]);
|
||||
infoButton.ToolTip = TextManager.Get("ViewModDetailsUpdateAvailable");
|
||||
bulkUpdateButton.Enabled = true;
|
||||
bulkUpdateButton.ToolTip = TextManager.Get("ModUpdatesAvailable");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void addRegularModsToList(IEnumerable<RegularPackage> mods, GUIListBox list)
|
||||
{
|
||||
list.ClearChildren();
|
||||
foreach (var mod in mods)
|
||||
{
|
||||
addRegularModToList(mod, list);
|
||||
}
|
||||
}
|
||||
|
||||
var enabledMods =
|
||||
(forceRefreshEnabled || (enabledRegularModsList.Content.CountChildren + disabledRegularModsList.Content.CountChildren == 0)
|
||||
? ContentPackageManager.EnabledPackages.Regular
|
||||
: enabledRegularModsList.Content.Children
|
||||
.Select(c => c.UserData)
|
||||
.OfType<RegularPackage>()
|
||||
.Where(p => ContentPackageManager.RegularPackages.Contains(p)))
|
||||
.ToArray();
|
||||
var disabledMods = ContentPackageManager.RegularPackages.Where(p => !enabledMods.Contains(p));
|
||||
|
||||
addRegularModsToList(enabledMods, enabledRegularModsList);
|
||||
if (refreshDisabled) { addRegularModsToList(disabledMods, disabledRegularModsList); }
|
||||
|
||||
TaskPool.Add(
|
||||
$"DetermineWorkshopModIcons",
|
||||
SteamManager.Workshop.GetPublishedItems(),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out ISet<Steamworks.Ugc.Item> items)) { return; }
|
||||
var ids = items.Select(it => it.Id).ToHashSet();
|
||||
|
||||
foreach (var child in enabledRegularModsList.Content.Children
|
||||
.Concat(disabledRegularModsList.Content.Children))
|
||||
{
|
||||
var mod = child.UserData as RegularPackage;
|
||||
if (mod is null || !ContentPackageManager.WorkshopPackages.Contains(mod)) { continue; }
|
||||
|
||||
var btn = child.GetChild<GUILayoutGroup>()?.GetAllChildren<GUIButton>().Last();
|
||||
if (btn is null) { continue; }
|
||||
if (btn.Style != null) { continue; }
|
||||
|
||||
btn.ApplyStyle(
|
||||
GUIStyle.GetComponentStyle(
|
||||
ids.Contains(mod.SteamWorkshopId)
|
||||
? "WorkshopMenu.PublishedIcon"
|
||||
: "WorkshopMenu.DownloadedIcon"));
|
||||
btn.ToolTip = TextManager.Get(
|
||||
ids.Contains(mod.SteamWorkshopId)
|
||||
? "PublishedWorkshopMod"
|
||||
: "DownloadedWorkshopMod");
|
||||
btn.HoverCursor = CursorState.Default;
|
||||
}
|
||||
});
|
||||
|
||||
UpdateModListItemVisibility();
|
||||
}
|
||||
|
||||
private void CreatePopularModsTab(out GUIListBox popularModsList)
|
||||
{
|
||||
GUIFrame content = CreateNewContentFrame(Tab.PopularMods);
|
||||
|
||||
@@ -106,10 +106,8 @@ namespace Barotrauma.Steam
|
||||
=> new GUIFrame(new RectTransform(Vector2.Zero, parent.RectTransform), style: null)
|
||||
{ UserData = new ActionCarrier(id, action) };
|
||||
|
||||
protected GUITextBox CreateSearchBox(GUILayoutGroup mainLayout, float width = 1.0f, float heightScale = 1.0f)
|
||||
protected GUITextBox CreateSearchBox(RectTransform searchRectT)
|
||||
{
|
||||
var searchRectT = NewItemRectT(mainLayout, heightScale: heightScale);
|
||||
searchRectT.RelativeSize = (width, searchRectT.RelativeSize.Y);
|
||||
var searchHolder = new GUIFrame(searchRectT, style: null);
|
||||
var searchBox = new GUITextBox(new RectTransform(Vector2.One, searchHolder.RectTransform), "", createClearButton: true);
|
||||
var searchTitle = new GUITextBlock(new RectTransform(Vector2.One, searchHolder.RectTransform) {Anchor = Anchor.TopLeft},
|
||||
@@ -142,7 +140,8 @@ namespace Barotrauma.Steam
|
||||
const int maxErrorsToShow = 5;
|
||||
nameText.TextColor = GUIStyle.Red;
|
||||
uiElement.ToolTip =
|
||||
TextManager.GetWithVariable("contentpackagehaserrors", "[packagename]", mod.Name) + '\n' + string.Join('\n', mod.Errors.Take(maxErrorsToShow).Select(e => e.error));
|
||||
TextManager.GetWithVariable("contentpackagehaserrors", "[packagename]", mod.Name)
|
||||
+ '\n' + string.Join('\n', mod.Errors.Take(maxErrorsToShow).Select(e => e.Message));
|
||||
if (mod.Errors.Count() > maxErrorsToShow)
|
||||
{
|
||||
uiElement.ToolTip += '\n' + TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (mod.Errors.Count() - maxErrorsToShow).ToString());
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Barotrauma.Steam
|
||||
@@ -7,5 +9,8 @@ namespace Barotrauma.Steam
|
||||
public WorkshopMenu(GUIFrame parent) { }
|
||||
|
||||
protected abstract void UpdateModListItemVisibility();
|
||||
|
||||
protected bool ModNameMatches(ContentPackage p, string query)
|
||||
=> p.Name.Contains(query, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user