Unstable 0.17.0.0
This commit is contained in:
@@ -0,0 +1,694 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.IO;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using ItemOrPackage = Barotrauma.Either<Steamworks.Ugc.Item, Barotrauma.ContentPackage>;
|
||||
|
||||
namespace Barotrauma.Steam
|
||||
{
|
||||
public partial class WorkshopMenu
|
||||
{
|
||||
private string ExtractTitle(ItemOrPackage itemOrPackage)
|
||||
=> itemOrPackage.TryGet(out ContentPackage package)
|
||||
? package.Name
|
||||
: ((Steamworks.Ugc.Item)itemOrPackage).Title;
|
||||
|
||||
private void CreateWorkshopItemDetailContainer(
|
||||
GUIFrame parent,
|
||||
out GUIListBox outerContainer,
|
||||
Action<ItemOrPackage, GUIFrame> onSelected,
|
||||
Action onDeselected,
|
||||
out Action<ItemOrPackage> select,
|
||||
out Action deselect)
|
||||
{
|
||||
ItemOrPackage? selectedItemOrPackage = null;
|
||||
|
||||
GUIListBox outContainer = new GUIListBox(new RectTransform(Vector2.One, parent.RectTransform),
|
||||
isHorizontal: true,
|
||||
style: null)
|
||||
{
|
||||
ScrollBarEnabled = false,
|
||||
ScrollBarVisible = false,
|
||||
HoverCursor = CursorState.Default
|
||||
};
|
||||
outerContainer = outContainer;
|
||||
|
||||
var selectedLayout =
|
||||
new GUILayoutGroup(new RectTransform(Vector2.One, outerContainer.Content.RectTransform));
|
||||
var selectedHeaderLayout =
|
||||
new GUILayoutGroup(new RectTransform((1.0f, 0.05f), selectedLayout.RectTransform),
|
||||
isHorizontal: true,
|
||||
childAnchor: Anchor.CenterLeft);
|
||||
|
||||
void deselectMethod()
|
||||
{
|
||||
if (selectedItemOrPackage is null) { return; }
|
||||
selectedItemOrPackage = null;
|
||||
onDeselected();
|
||||
}
|
||||
|
||||
deselect = deselectMethod;
|
||||
|
||||
var backButton =
|
||||
new GUIButton(new RectTransform((0.04f, 1.0f), selectedHeaderLayout.RectTransform),
|
||||
style: "GUIButtonToggleLeft")
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
deselectMethod();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
var padding = new GUIFrame(new RectTransform((1.0f, 0.005f), selectedLayout.RectTransform), style: null);
|
||||
var selectedFrame = new GUIFrame(new RectTransform((1.0f, 0.945f), selectedLayout.RectTransform),
|
||||
style: null);
|
||||
|
||||
var selectionScroller = new GUICustomComponent(
|
||||
new RectTransform(Vector2.Zero, outerContainer.Parent.RectTransform),
|
||||
onUpdate: (deltaTime, component) =>
|
||||
{
|
||||
float targetScroll = selectedItemOrPackage is null
|
||||
? 0.0f
|
||||
: 1.0f;
|
||||
outContainer.ScrollBar.BarScroll
|
||||
= MathUtils.NearlyEqual(targetScroll, outContainer.ScrollBar.BarScroll)
|
||||
? targetScroll
|
||||
: MathHelper.Lerp(outContainer.ScrollBar.BarScroll, targetScroll, 0.3f);
|
||||
});
|
||||
|
||||
select = itemOrPackage =>
|
||||
{
|
||||
//showInSteamButton.Visible = itemOrPackage.TryGet(out Steamworks.Ugc.Item _);
|
||||
//selectedItem = itemOrPackage;
|
||||
//selectedTitle.Text = ExtractTitle(itemOrPackage);
|
||||
selectedFrame.ClearChildren();
|
||||
|
||||
//Jank to fix mouserect not clamping properly
|
||||
//when shifting all elements to the left
|
||||
var dropdowns = outContainer.Content.GetAllChildren<GUIDropDown>().ToArray();
|
||||
var allChildren = outContainer.Content.GetAllChildren()
|
||||
.Concat(selectedFrame.GetAllChildren());
|
||||
allChildren.ForEach(c =>
|
||||
{
|
||||
//c.CascadingMouseRectClamp = !dropdowns.Any(dd => dd.IsParentOf(c) || dd.ListBox.IsParentOf(c));
|
||||
//c.CanBeFocused = c.CanBeFocused || !c.CascadingMouseRectClamp;
|
||||
c.ClampMouseRectToParent = !(c.Parent?.Parent is GUIDropDown);
|
||||
}
|
||||
);
|
||||
|
||||
selectedItemOrPackage = itemOrPackage;
|
||||
onSelected(itemOrPackage, selectedFrame);
|
||||
};
|
||||
}
|
||||
|
||||
private void CreateWorkshopItemList(
|
||||
GUIFrame parent,
|
||||
out GUIListBox outerContainer,
|
||||
out GUIListBox workshopItemList,
|
||||
Action<Steamworks.Ugc.Item, GUIFrame> onSelected)
|
||||
=> CreateWorkshopItemOrPackageList(
|
||||
parent,
|
||||
out outerContainer,
|
||||
out workshopItemList,
|
||||
onSelected: (ItemOrPackage itemOrPackage, GUIFrame frame)
|
||||
=> onSelected((Steamworks.Ugc.Item)itemOrPackage, frame));
|
||||
|
||||
private GUIButton CreateShowInSteamButton(Steamworks.Ugc.Item workshopItem, RectTransform rectT)
|
||||
=> new GUIButton(
|
||||
rectT,
|
||||
TextManager.Get("WorkshopShowItemInSteam"), style: "GUIButtonSmall")
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
SteamManager.OverlayCustomURL(workshopItem.Url);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
private GUIButton? CreateShowInSteamButton(ItemOrPackage itemOrPackage)
|
||||
=> itemOrPackage.TryGet(out Steamworks.Ugc.Item workshopItem)
|
||||
? CreateShowInSteamButton(workshopItem)
|
||||
: null;
|
||||
|
||||
private void CreateWorkshopItemOrPackageList(
|
||||
GUIFrame parent,
|
||||
out GUIListBox outerContainer,
|
||||
out GUIListBox workshopItemList,
|
||||
Action<ItemOrPackage, GUIFrame> onSelected)
|
||||
{
|
||||
GUIListBox? itemList = null;
|
||||
|
||||
CreateWorkshopItemDetailContainer(
|
||||
parent,
|
||||
out outerContainer,
|
||||
onSelected: onSelected,
|
||||
onDeselected: () => itemList?.Deselect(),
|
||||
out var select, out var deselect);
|
||||
|
||||
itemList = new GUIListBox(new RectTransform(Vector2.One, outerContainer.Content.RectTransform));
|
||||
itemList.RectTransform.SetAsFirstChild();
|
||||
workshopItemList = itemList;
|
||||
|
||||
var deselectCarrier
|
||||
= CreateActionCarrier(outerContainer.Content, nameof(deselect).ToIdentifier(), deselect);
|
||||
|
||||
itemList.OnSelected = (component, userData) =>
|
||||
{
|
||||
//Don't select if hitting the subscribe button
|
||||
if (GUI.MouseOn.Parent != itemList.Content) { return false; }
|
||||
|
||||
if (!(userData is ItemOrPackage itemOrPackage)) { return false; }
|
||||
|
||||
select(itemOrPackage);
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
private void AddUnpublishedMods(ISet<Steamworks.Ugc.Item> workshopItems)
|
||||
{
|
||||
//Users that don't have a proper license cannot publish Workshop items
|
||||
//(see https://partner.steamgames.com/doc/features/workshop#15)
|
||||
void clearWithMessage(LocalizedString message)
|
||||
{
|
||||
selfModsList.ClearChildren();
|
||||
var messageFrame = new GUIFrame(new RectTransform(Vector2.One, selfModsList.Content.RectTransform),
|
||||
style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
new GUITextBlock(new RectTransform((0.5f, 1.0f), messageFrame.RectTransform, Anchor.Center),
|
||||
text: message,
|
||||
textAlignment: Alignment.Center,
|
||||
wrap: true,
|
||||
font: GUIStyle.Font);
|
||||
}
|
||||
|
||||
if (SteamManager.IsFreeWeekend())
|
||||
{
|
||||
clearWithMessage(TextManager.Get("FreeWeekendCantPublish"));
|
||||
return;
|
||||
}
|
||||
if (SteamManager.IsFamilyShared())
|
||||
{
|
||||
clearWithMessage(TextManager.Get("FamilySharedCantPublish"));
|
||||
return;
|
||||
}
|
||||
|
||||
DateTime getEditTime(ContentPackage p)
|
||||
=> File.GetLastWriteTime(Path.GetDirectoryName(p.Path)!);
|
||||
|
||||
//Find local packages associated with the Workshop items if available
|
||||
(Steamworks.Ugc.Item WorkshopItem, ContentPackage? LocalPackage)[] publishedItems = workshopItems
|
||||
.Select(item => (item,
|
||||
(ContentPackage?)ContentPackageManager.LocalPackages.FirstOrDefault(p
|
||||
=> p.SteamWorkshopId != 0 && p.SteamWorkshopId == item.Id)))
|
||||
//Sort the pairs by last local edit time if available
|
||||
.OrderBy(t => t.Item2 == null)
|
||||
.ThenByDescending(t => t.Item2 is { } p ? getEditTime(p) : t.Item1.LatestUpdateTime)
|
||||
.ToArray();
|
||||
|
||||
int indexOfUserDataInPublishedItemsArray(object userData)
|
||||
=> publishedItems.IndexOf(t
|
||||
=> t.WorkshopItem.Id == ((Steamworks.Ugc.Item)(userData as ItemOrPackage)).Id);
|
||||
|
||||
//Take the existing GUI items that are in the list and sort to match the order of publishedItems
|
||||
var publishedGuiComponents = selfModsList.Content.Children.OrderBy(c => indexOfUserDataInPublishedItemsArray(c.UserData)).ToArray();
|
||||
|
||||
//Get mods that haven't been published and add them to the list
|
||||
var unpublishedMods = ContentPackageManager.LocalPackages
|
||||
.Where(p => p.SteamWorkshopId == 0 || !publishedItems.Any(item => item.WorkshopItem.Id == p.SteamWorkshopId))
|
||||
.OrderByDescending(getEditTime).ToArray();
|
||||
|
||||
if (unpublishedMods.Any())
|
||||
{
|
||||
var unpublishedHeader
|
||||
= new GUITextBlock(new RectTransform((1.0f, 1.0f / 11.0f), selfModsList.Content.RectTransform),
|
||||
TextManager.Get("UnpublishedModsHeader"), font: GUIStyle.SubHeadingFont) { CanBeFocused = false };
|
||||
}
|
||||
|
||||
foreach (var unpublishedMod in unpublishedMods)
|
||||
{
|
||||
var unpublishedFrame = new GUIFrame(
|
||||
new RectTransform((1.0f, 1.0f / 5.5f), selfModsList.Content.RectTransform),
|
||||
style: "ListBoxElement")
|
||||
{
|
||||
UserData = (ItemOrPackage)unpublishedMod
|
||||
};
|
||||
var unpublishedLayout
|
||||
= new GUILayoutGroup(new RectTransform(Vector2.One, unpublishedFrame.RectTransform),
|
||||
isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
var unpublishedPadding
|
||||
= new GUIFrame(
|
||||
new RectTransform(Vector2.One, unpublishedLayout.RectTransform,
|
||||
scaleBasis: ScaleBasis.BothHeight), style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var unpublishedTextBlock
|
||||
= new GUITextBlock(new RectTransform(Vector2.One, unpublishedLayout.RectTransform),
|
||||
$"{unpublishedMod.Name}\n\n" +
|
||||
TextManager.GetWithVariable("LastLocalEditTime",
|
||||
"[datetime]",
|
||||
getEditTime(unpublishedMod).ToString()),
|
||||
font: GUIStyle.Font)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
|
||||
if (publishedGuiComponents.Any())
|
||||
{
|
||||
var publishedHeader
|
||||
= new GUITextBlock(new RectTransform((1.0f, 1.0f / 11.0f), selfModsList.Content.RectTransform),
|
||||
TextManager.Get("PublishedModsHeader"), font: GUIStyle.SubHeadingFont) { CanBeFocused = false };
|
||||
}
|
||||
|
||||
foreach (var c in publishedGuiComponents)
|
||||
{
|
||||
c.SetAsLastChild();
|
||||
var textBlock = (c.FindChild(b => b is GUITextBlock, recursive: true) as GUITextBlock)!;
|
||||
textBlock.Text += $"\n";
|
||||
|
||||
int index = indexOfUserDataInPublishedItemsArray(c.UserData);
|
||||
(Steamworks.Ugc.Item workshopItem, ContentPackage? localMod) = publishedItems[index];
|
||||
if (localMod != null)
|
||||
{
|
||||
textBlock.Text += $"\n" + TextManager.GetWithVariable("LastLocalEditTime", "[datetime]", getEditTime(localMod).ToString());
|
||||
}
|
||||
textBlock.Text += $"\n" + TextManager.GetWithVariable("LatestPublishTime", "[datetime]", workshopItem.LatestUpdateTime.ToLocalTime().ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private static (GUIButton Button, GUIFrame Sprite) CreatePaddedButton(RectTransform rectT, string style, float spriteScale)
|
||||
{
|
||||
var button = new GUIButton(
|
||||
rectT,
|
||||
style: null);
|
||||
|
||||
var sprite = new GUIFrame(
|
||||
new RectTransform(Vector2.One * spriteScale, button.RectTransform, Anchor.Center),
|
||||
style: style)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
return (button, sprite);
|
||||
}
|
||||
|
||||
private static void CreateSubscribeButton(Steamworks.Ugc.Item workshopItem, RectTransform rectT, float spriteScale)
|
||||
{
|
||||
const string plusButton = "GUIPlusButton";
|
||||
const string minusButton = "GUIMinusButton";
|
||||
|
||||
LocalizedString subscribeTooltip = TextManager.Get("DownloadButton");
|
||||
LocalizedString unsubscribeTooptip = TextManager.Get("WorkshopItemUnsubscribe");
|
||||
|
||||
var (subscribeButton, subscribeButtonSprite) = CreatePaddedButton(rectT, plusButton, spriteScale);
|
||||
subscribeButton.ToolTip = subscribeTooltip;
|
||||
|
||||
subscribeButton.OnClicked = (button, o) =>
|
||||
{
|
||||
if (!workshopItem.IsSubscribed)
|
||||
{
|
||||
workshopItem.Subscribe();
|
||||
TaskPool.Add($"DownloadSubscribedItem{workshopItem.Id}",
|
||||
SteamManager.Workshop.ForceRedownload(workshopItem),
|
||||
t => { });
|
||||
}
|
||||
else
|
||||
{
|
||||
workshopItem.Unsubscribe();
|
||||
SteamManager.Workshop.Uninstall(workshopItem);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
var buttonStyleUpdater = new GUICustomComponent(
|
||||
new RectTransform(Vector2.Zero, subscribeButton.RectTransform),
|
||||
onUpdate: (deltaTime, component) =>
|
||||
{
|
||||
if (subscribeButtonSprite.Style is { Identifier: { } styleId })
|
||||
{
|
||||
if (workshopItem.IsSubscribed && styleId != minusButton)
|
||||
{
|
||||
subscribeButtonSprite.ApplyStyle(GUIStyle.GetComponentStyle(minusButton));
|
||||
subscribeButton.ToolTip = unsubscribeTooptip;
|
||||
}
|
||||
if (!workshopItem.IsSubscribed && styleId != plusButton)
|
||||
{
|
||||
subscribeButtonSprite.ApplyStyle(GUIStyle.GetComponentStyle(plusButton));
|
||||
subscribeButton.ToolTip = subscribeTooltip;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
float displayedDownloadAmount = workshopItem.DownloadAmount;
|
||||
var downloadProgressBar = new GUICustomComponent(
|
||||
new RectTransform((1.22f, 1.22f), subscribeButtonSprite.RectTransform, Anchor.Center),
|
||||
onDraw: (spriteBatch, component) =>
|
||||
{
|
||||
bool visible = workshopItem.IsSubscribed
|
||||
&& (workshopItem.IsDownloading
|
||||
|| workshopItem.IsDownloadPending
|
||||
|| !MathUtils.NearlyEqual(workshopItem.DownloadAmount, displayedDownloadAmount));
|
||||
if (!visible) { return; }
|
||||
|
||||
void drawSection(float amount, Color color, float thickness)
|
||||
=> GUI.DrawDonutSection(
|
||||
spriteBatch,
|
||||
component.Rect.Center.ToVector2() + (0, 1),
|
||||
new Range<float>(component.Rect.Width * 0.55f - thickness * 0.5f, component.Rect.Width * 0.55f + thickness * 0.5f),
|
||||
amount * MathF.PI * 2.0f,
|
||||
color);
|
||||
|
||||
void drawSectionFuzzy(float amount, Color color, float thickness)
|
||||
{
|
||||
drawSection(amount, color, thickness);
|
||||
drawSection(amount, color * 0.6f, thickness + 0.5f);
|
||||
drawSection(amount, color * 0.3f, thickness + 1.0f);
|
||||
}
|
||||
|
||||
drawSectionFuzzy(1.0f, Color.Lerp(Color.Black, GUIStyle.Blue, 0.2f), component.Rect.Width * 0.25f);
|
||||
drawSectionFuzzy(1.0f, Color.Black, component.Rect.Width * 0.15f);
|
||||
drawSectionFuzzy(displayedDownloadAmount, GUIStyle.Green, component.Rect.Width * 0.08f);
|
||||
},
|
||||
onUpdate: (deltaTime, component) =>
|
||||
{
|
||||
displayedDownloadAmount = Math.Min(
|
||||
workshopItem.DownloadAmount,
|
||||
MathHelper.Lerp(displayedDownloadAmount, workshopItem.DownloadAmount, 0.05f));
|
||||
})
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
|
||||
private void PopulateItemList(GUIListBox itemListBox, Task<ISet<Steamworks.Ugc.Item>> items, bool includeSubscribeButton, Action<ISet<Steamworks.Ugc.Item>>? onFill = null)
|
||||
{
|
||||
itemListBox.ClearChildren();
|
||||
itemListBox.Deselect();
|
||||
itemListBox.ScrollBar.BarScroll = 0.0f;
|
||||
TaskPool.Add("PopulateTabWithItemList", items,
|
||||
(t) =>
|
||||
{
|
||||
taskCancelSrc = taskCancelSrc.IsCancellationRequested ? new CancellationTokenSource() : taskCancelSrc;
|
||||
itemListBox.ClearChildren();
|
||||
var workshopItems = ((Task<ISet<Steamworks.Ugc.Item>>)t).Result;
|
||||
foreach (var workshopItem in workshopItems)
|
||||
{
|
||||
var itemFrame = new GUIFrame(
|
||||
new RectTransform((1.0f, 1.0f / 5.5f), itemListBox.Content.RectTransform),
|
||||
style: "ListBoxElement")
|
||||
{
|
||||
UserData = (ItemOrPackage)workshopItem
|
||||
};
|
||||
var itemLayout = new GUILayoutGroup(
|
||||
new RectTransform(Vector2.One, itemFrame.RectTransform),
|
||||
isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
var thumbnailContainer
|
||||
= CreateThumbnailContainer(itemLayout, Vector2.One, ScaleBasis.BothHeight);
|
||||
CreateItemThumbnail(workshopItem, taskCancelSrc.Token, thumbnailContainer);
|
||||
thumbnailContainer.CanBeFocused = false;
|
||||
thumbnailContainer.GetAllChildren().ForEach(c => c.CanBeFocused = false);
|
||||
|
||||
var title = new GUITextBlock(
|
||||
new RectTransform(Vector2.One, itemLayout.RectTransform),
|
||||
workshopItem.Title, font: GUIStyle.Font)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
if (includeSubscribeButton)
|
||||
{
|
||||
CreateSubscribeButton(workshopItem, new RectTransform(Vector2.One, itemLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), spriteScale: 0.4f);
|
||||
}
|
||||
}
|
||||
onFill?.Invoke(workshopItems);
|
||||
});
|
||||
}
|
||||
|
||||
private GUIFrame CreateThumbnailContainer(
|
||||
GUIComponent parent,
|
||||
Vector2 relativeSize,
|
||||
ScaleBasis scaleBasis)
|
||||
=> new GUIFrame(new RectTransform(relativeSize, parent.RectTransform, scaleBasis: scaleBasis),
|
||||
style: "GUIFrameListBox");
|
||||
|
||||
private SteamManager.Workshop.ItemThumbnail CreateItemThumbnail(
|
||||
in Steamworks.Ugc.Item workshopItem,
|
||||
CancellationToken cancellationToken,
|
||||
GUIFrame thumbnailContainer)
|
||||
{
|
||||
var thumbnail = new SteamManager.Workshop.ItemThumbnail(workshopItem, cancellationToken);
|
||||
itemThumbnails.Add(thumbnail);
|
||||
CreateAsyncThumbnailComponent(thumbnailContainer, () => thumbnail.Texture, () => thumbnail.Loading);
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
private GUICustomComponent CreateAsyncThumbnailComponent(GUIFrame thumbnailContainer, Func<Texture2D?> textureGetter, Func<bool> throbberEnabled)
|
||||
{
|
||||
int randomThrobberOffset = Rand.Range(0, 10, Rand.RandSync.Unsynced);
|
||||
return new GUICustomComponent(
|
||||
new RectTransform(Vector2.One, thumbnailContainer.RectTransform, Anchor.Center),
|
||||
onDraw: (spriteBatch, component) =>
|
||||
{
|
||||
Rectangle rect = component.Rect;
|
||||
Texture2D? texture = textureGetter();
|
||||
if (texture != null)
|
||||
{
|
||||
rect.Location += (4, 4);
|
||||
rect.Size -= (8, 8);
|
||||
Point destinationSizeMaxWidth = (rect.Width, rect.Width * texture.Height / texture.Width);
|
||||
Point destinationSizeMaxHeight = (rect.Height * texture.Width / texture.Height, rect.Height);
|
||||
Point destinationSize = destinationSizeMaxHeight.X > rect.Width
|
||||
? destinationSizeMaxWidth
|
||||
: destinationSizeMaxHeight;
|
||||
Rectangle destinationRectangle = new Rectangle(
|
||||
rect.Center.X - destinationSize.X / 2,
|
||||
rect.Center.Y - destinationSize.Y / 2,
|
||||
destinationSize.X,
|
||||
destinationSize.Y);
|
||||
spriteBatch.Draw(texture, destinationRectangle, Color.White);
|
||||
}
|
||||
else if (throbberEnabled())
|
||||
{
|
||||
var sheet = GUIStyle.GenericThrobber;
|
||||
Vector2 pos = rect.Center.ToVector2() - Vector2.One * rect.Height * 0.4f;
|
||||
sheet.Draw(spriteBatch, ((int)Math.Floor(Timing.TotalTime * 24.0f) + randomThrobberOffset) % sheet.FrameCount, pos, Color.White,
|
||||
origin: Vector2.Zero, rotate: 0.0f,
|
||||
scale: Vector2.One * component.Rect.Height / sheet.FrameSize.ToVector2() * 0.8f);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private GUIListBox CreateTagsList(IEnumerable<Identifier> tags, RectTransform rectT, bool canBeFocused)
|
||||
{
|
||||
var tagsList
|
||||
= new GUIListBox(rectT, style: null, isHorizontal: false)
|
||||
{
|
||||
UseGridLayout = true,
|
||||
ScrollBarEnabled = false,
|
||||
ScrollBarVisible = false,
|
||||
HideChildrenOutsideFrame = false,
|
||||
Spacing = GUI.IntScale(4)
|
||||
};
|
||||
tagsList.Content.ClampMouseRectToParent = false;
|
||||
foreach (Identifier tag in tags)
|
||||
{
|
||||
var tagBtn = new GUIButton(
|
||||
new RectTransform(new Vector2(0.25f, 1.0f / 8.0f), tagsList.Content.RectTransform,
|
||||
anchor: Anchor.TopLeft),
|
||||
TextManager.Get($"workshop.contenttag.{tag.Value.RemoveWhitespace()}")
|
||||
.Fallback(tag.Value.CapitaliseFirstInvariant()), style: "GUIButtonRound")
|
||||
{
|
||||
CanBeFocused = canBeFocused,
|
||||
Selected = !canBeFocused,
|
||||
UserData = tag
|
||||
};
|
||||
tagBtn.RectTransform.NonScaledSize
|
||||
= tagBtn.Font.MeasureString(tagBtn.Text).ToPoint() + new Point(GUI.IntScale(5));
|
||||
tagBtn.RectTransform.IsFixedSize = true;
|
||||
tagBtn.ClampMouseRectToParent = false;
|
||||
}
|
||||
|
||||
return tagsList;
|
||||
}
|
||||
|
||||
private void PopulateFrameWithItemInfo(Steamworks.Ugc.Item workshopItem, GUIFrame parentFrame)
|
||||
{
|
||||
taskCancelSrc = taskCancelSrc.IsCancellationRequested ? new CancellationTokenSource() : taskCancelSrc;
|
||||
|
||||
var verticalLayout = new GUILayoutGroup(new RectTransform(Vector2.One, parentFrame.RectTransform));
|
||||
|
||||
var headerLayout = new GUILayoutGroup(new RectTransform((1.0f, 0.1f), verticalLayout.RectTransform),
|
||||
isHorizontal: true) { Stretch = true };
|
||||
|
||||
var titleAndAuthorLayout = new GUILayoutGroup(new RectTransform(Vector2.One, headerLayout.RectTransform));
|
||||
|
||||
var selectedTitle =
|
||||
new GUITextBlock(new RectTransform((1.0f, 0.5f), titleAndAuthorLayout.RectTransform), workshopItem.Title,
|
||||
font: GUIStyle.LargeFont);
|
||||
|
||||
var author = workshopItem.Owner;
|
||||
var authorButton = new GUIButton(new RectTransform((1.0f, 0.5f),
|
||||
titleAndAuthorLayout.RectTransform),
|
||||
style: null,
|
||||
textAlignment: Alignment.CenterLeft)
|
||||
{
|
||||
ForceUpperCase = ForceUpperCase.No,
|
||||
Font = GUIStyle.SubHeadingFont,
|
||||
TextColor = GUIStyle.TextColorNormal,
|
||||
HoverTextColor = Color.White,
|
||||
SelectedTextColor = GUIStyle.TextColorNormal,
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
SteamManager.OverlayCustomURL(
|
||||
$"https://steamcommunity.com/profiles/{author.Id}/myworkshopfiles/?appid={SteamManager.AppID}");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
var authorPadding = authorButton.GetChild<GUITextBlock>().Padding;
|
||||
|
||||
RectTransform rightSideButtonRectT()
|
||||
=> new RectTransform(Vector2.One, headerLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight);
|
||||
|
||||
var (reinstallButton, reinstallSprite) = CreatePaddedButton(
|
||||
rightSideButtonRectT(),
|
||||
"GUIReloadButton",
|
||||
spriteScale: 0.8f);
|
||||
reinstallButton.ToolTip = TextManager.Get("WorkshopItemReinstall");
|
||||
reinstallButton.OnClicked += (button, o) =>
|
||||
{
|
||||
SteamManager.Workshop.Uninstall(workshopItem);
|
||||
TaskPool.Add($"Reinstall{workshopItem.Id}", SteamManager.Workshop.ForceRedownload(workshopItem), t => { });
|
||||
return false;
|
||||
};
|
||||
var reinstallButtonUpdater = new GUICustomComponent(
|
||||
new RectTransform(Vector2.Zero, reinstallButton.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
{
|
||||
reinstallButton.Visible = workshopItem.IsSubscribed;
|
||||
reinstallButton.Enabled = !workshopItem.IsDownloading && !workshopItem.IsDownloadPending &&
|
||||
!SteamManager.Workshop.IsInstalling(workshopItem);
|
||||
reinstallSprite.Color = reinstallButton.Enabled
|
||||
? reinstallSprite.Style.Color
|
||||
: Color.DimGray;
|
||||
});
|
||||
CreateSubscribeButton(workshopItem,
|
||||
rightSideButtonRectT(),
|
||||
spriteScale: 0.8f);
|
||||
|
||||
var padding = new GUIFrame(new RectTransform((1.0f, 0.015f), verticalLayout.RectTransform), style: null);
|
||||
|
||||
var horizontalLayout = new GUILayoutGroup(new RectTransform((1.0f, 0.45f), verticalLayout.RectTransform),
|
||||
isHorizontal: true)
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
TaskPool.Add($"Request username for {author.Id}", author.RequestInfoAsync(), (t) =>
|
||||
{
|
||||
authorButton.Text = author.Name;
|
||||
authorButton.RectTransform.NonScaledSize =
|
||||
((int)(authorButton.Font.MeasureString(author.Name).X + authorPadding.X + authorPadding.Z),
|
||||
authorButton.RectTransform.NonScaledSize.Y);
|
||||
});
|
||||
|
||||
var thumbnailSuperContainer = new GUIFrame(
|
||||
new RectTransform(Vector2.One, horizontalLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
style: null);
|
||||
GUIFrame thumbnailContainer = CreateThumbnailContainer(thumbnailSuperContainer, Vector2.One,
|
||||
scaleBasis: ScaleBasis.BothHeight);
|
||||
CreateItemThumbnail(workshopItem, taskCancelSrc.Token, thumbnailContainer);
|
||||
thumbnailContainer.RectTransform.Anchor = Anchor.Center;
|
||||
thumbnailContainer.RectTransform.Pivot = Pivot.Center;
|
||||
|
||||
var statsBox = new GUIFrame(new RectTransform((0.6f, 1.0f), horizontalLayout.RectTransform),
|
||||
style: "GUIFrameListBox");
|
||||
|
||||
#region Stats box
|
||||
var statsHorizontalLayout = new GUILayoutGroup(new RectTransform(Vector2.One, statsBox.RectTransform), isHorizontal: true);
|
||||
var statsVertical0
|
||||
= new GUILayoutGroup(new RectTransform((1.0f, 1.0f), statsHorizontalLayout.RectTransform));
|
||||
|
||||
statFrame("", ""); //padding
|
||||
|
||||
var scoreFrame = new GUIFrame(new RectTransform((1.0f, 0.12f), statsVertical0.RectTransform), style: null);
|
||||
var scoreLabel = new GUITextBlock(new RectTransform((0.4f, 1.0f), scoreFrame.RectTransform),
|
||||
TextManager.Get("WorkshopItemScore"), font: GUIStyle.SubHeadingFont);
|
||||
var scoreStarContainer
|
||||
= new GUILayoutGroup(
|
||||
new RectTransform((0.6f, 1.0f), scoreFrame.RectTransform, Anchor.CenterRight),
|
||||
isHorizontal: true,
|
||||
childAnchor: Anchor.CenterLeft) { Stretch = true };
|
||||
var starColor = Color.Lerp(
|
||||
Color.Lerp(Color.Red, Color.Yellow, Math.Min(workshopItem.Score * 2.0f, 1.0f)),
|
||||
Color.Lime, Math.Max(0.0f, (workshopItem.Score - 0.5f) * 2.0f));
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
bool isStarLit = i <= Round(workshopItem.Score * 5.0f);
|
||||
var star = new GUIFrame(new RectTransform(Vector2.One, scoreStarContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
style: isStarLit ? "GUIStarIconBright" : "GUIStarIconDark");
|
||||
if (isStarLit)
|
||||
{
|
||||
star.Color = starColor;
|
||||
star.HoverColor = starColor;
|
||||
star.SelectedColor = starColor;
|
||||
}
|
||||
}
|
||||
var scoreVoteCountPadding = new GUIFrame(new RectTransform((0.5f, 1.0f), scoreStarContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
style: null);
|
||||
var scoreVoteCount = new GUITextBlock(
|
||||
new RectTransform(Vector2.One, scoreStarContainer.RectTransform),
|
||||
TextManager.GetWithVariable("WorkshopItemVotes", "[VoteCount]",
|
||||
(workshopItem.VotesUp + workshopItem.VotesDown).ToString()), textAlignment: Alignment.CenterLeft)
|
||||
{
|
||||
Padding = Vector4.Zero
|
||||
};
|
||||
|
||||
void statFrame(LocalizedString labelText, LocalizedString dataText)
|
||||
{
|
||||
var frame = new GUIFrame(new RectTransform((1.0f, 0.12f), statsVertical0!.RectTransform), style: null);
|
||||
var label = new GUITextBlock(new RectTransform((0.4f, 1.0f), frame.RectTransform),
|
||||
labelText, font: GUIStyle.SubHeadingFont);
|
||||
var data = new GUITextBlock(new RectTransform((0.6f, 1.0f), frame.RectTransform, Anchor.CenterRight),
|
||||
dataText, font: GUIStyle.Font)
|
||||
{
|
||||
Padding = Vector4.Zero
|
||||
};
|
||||
}
|
||||
|
||||
statFrame(TextManager.Get("WorkshopItemFileSize"), MathUtils.GetBytesReadable(workshopItem.SizeOfFileInBytes));
|
||||
statFrame(TextManager.Get("WorkshopItemCreationDate"), workshopItem.Created.ToShortDateString());
|
||||
statFrame(TextManager.Get("WorkshopItemModificationDate"), workshopItem.Updated.ToShortDateString());
|
||||
|
||||
var tagsLabel = new GUITextBlock(new RectTransform((1.0f, 0.12f), statsVertical0.RectTransform),
|
||||
TextManager.Get("WorkshopItemTags"), font: GUIStyle.SubHeadingFont);
|
||||
CreateTagsList(workshopItem.Tags.ToIdentifiers(), new RectTransform((1.0f, 0.3f), statsVertical0.RectTransform), canBeFocused: false);
|
||||
#endregion
|
||||
|
||||
var descriptionListBox = new GUIListBox(new RectTransform((1.0f, 0.38f), verticalLayout.RectTransform));
|
||||
CreateBBCodeElement(workshopItem.Description, descriptionListBox);
|
||||
|
||||
var showInSteamContainer
|
||||
= new GUIFrame(new RectTransform((1.0f, 0.05f), verticalLayout.RectTransform), style: null);
|
||||
CreateShowInSteamButton(workshopItem, new RectTransform((0.2f, 1.0f), showInSteamContainer.RectTransform, Anchor.CenterRight));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user