Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaClient/ClientSource/Screens/SteamWorkshopScreen.cs
2021-03-05 17:00:56 +02:00

1888 lines
89 KiB
C#

using Barotrauma.IO;
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.Threading.Tasks;
namespace Barotrauma
{
class SteamWorkshopScreen : Screen
{
private GUIFrame menu;
private GUIListBox subscribedItemList, topItemList;
private GUITextBox subscribedItemFilter, topItemFilter;
private GUIListBox publishedItemList, myItemList;
//shows information of a selected workshop item
private GUIFrame modsPreviewFrame, browsePreviewFrame;
//menu for creating new items
private GUIFrame createItemFrame;
//listbox that shows the files included in the item being created
private GUIListBox createItemFileList;
private System.IO.FileSystemWatcher createItemWatcher;
private readonly List<GUIButton> tabButtons = new List<GUIButton>();
private class PendingPreviewImageDownload
{
/// <summary>
/// Was the image downloaded
/// </summary>
public bool Downloaded = false;
/// <summary>
/// How many tasks are looking to create a preview image based on this download
/// </summary>
public int PendingLoads = 1;
}
private readonly Dictionary<ulong, PendingPreviewImageDownload> pendingPreviewImageDownloads = new Dictionary<ulong, PendingPreviewImageDownload>();
private readonly Dictionary<string, Sprite> itemPreviewSprites = new Dictionary<string, Sprite>();
private enum Tab
{
Mods,
Browse,
Publish
}
private GUIComponent[] tabs;
private ContentPackage itemContentPackage;
private Steamworks.Ugc.Editor? itemEditor;
private enum VisibilityType
{
Public,
FriendsOnly,
Private
}
public SteamWorkshopScreen()
{
GameMain.Instance.ResolutionChanged += CreateUI;
CreateUI();
Steamworks.SteamUGC.GlobalOnItemInstalled += OnItemInstalled;
}
private void CreateUI()
{
tabs = new GUIComponent[Enum.GetValues(typeof(Tab)).Length];
menu = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), GUI.Canvas, Anchor.Center) { MinSize = new Point(GameMain.GraphicsHeight, 0) });
var container = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), menu.RectTransform, Anchor.Center)) { Stretch = true };
var topButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.03f), container.RectTransform), isHorizontal: true);
foreach (Tab tab in Enum.GetValues(typeof(Tab)))
{
GUIButton tabButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), topButtonContainer.RectTransform),
TextManager.Get(tab.ToString() + "Tab"), style: "GUITabButton")
{
UserData = tab,
OnClicked = (btn, userData) =>
{
SelectTab((Tab)userData); return true;
}
};
tabButtons.Add(tabButton);
}
topButtonContainer.RectTransform.MinSize = new Point(0, topButtonContainer.RectTransform.Children.Max(c => c.MinSize.Y));
topButtonContainer.RectTransform.MaxSize = new Point(int.MaxValue, topButtonContainer.RectTransform.MinSize.Y);
var tabContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.7f), container.RectTransform), style: "InnerFrame");
var bottomButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), container.RectTransform), isHorizontal: true);
GUIButton backButton = new GUIButton(new RectTransform(new Vector2(0.1f, 0.9f), bottomButtonContainer.RectTransform) { MinSize = new Point(150, 0) },
TextManager.Get("Back"))
{
OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu
};
backButton.SelectedColor = backButton.Color;
topButtonContainer.RectTransform.MinSize = new Point(0, backButton.RectTransform.MinSize.Y);
topButtonContainer.RectTransform.MaxSize = new Point(int.MaxValue, backButton.RectTransform.MinSize.Y);
//-------------------------------------------------------------------------------
//Subscribed Mods tab
//-------------------------------------------------------------------------------
tabs[(int)Tab.Mods] = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.95f), tabContainer.RectTransform, Anchor.Center), isHorizontal: true)
{
Stretch = true,
RelativeSpacing = 0.02f
};
var modsContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), tabs[(int)Tab.Mods].RectTransform))
{
Stretch = true,
RelativeSpacing = 0.02f
};
subscribedItemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), modsContainer.RectTransform))
{
ScrollBarVisible = true,
OnSelected = (GUIComponent component, object userdata) =>
{
if (GUI.MouseOn is GUIButton || GUI.MouseOn?.Parent is GUIButton) { return false; }
ShowItemPreview(userdata as Steamworks.Ugc.Item?, modsPreviewFrame);
return true;
}
};
subscribedItemFilter = CreateFilterBox(modsContainer, subscribedItemList);
modsPreviewFrame = new GUIFrame(new RectTransform(new Vector2(0.6f, 1.0f), tabs[(int)Tab.Mods].RectTransform, Anchor.TopRight), style: null);
//-------------------------------------------------------------------------------
//Popular Mods tab
//-------------------------------------------------------------------------------
tabs[(int)Tab.Browse] = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.95f), tabContainer.RectTransform, Anchor.Center), isHorizontal: true)
{
Stretch = true,
RelativeSpacing = 0.02f
};
var listContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), tabs[(int)Tab.Browse].RectTransform), childAnchor: Anchor.TopCenter)
{
Stretch = true,
RelativeSpacing = 0.02f
};
topItemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.9f), listContainer.RectTransform))
{
ScrollBarVisible = true,
OnSelected = (GUIComponent component, object userdata) =>
{
ShowItemPreview(userdata as Steamworks.Ugc.Item?, browsePreviewFrame);
return true;
}
};
topItemFilter = CreateFilterBox(listContainer, topItemList);
new GUIButton(new RectTransform(new Vector2(1.0f, 0.02f), listContainer.RectTransform), TextManager.Get("FindModsButton"), style: "GUIButtonSmall")
{
OnClicked = (btn, userdata) =>
{
SteamManager.OverlayCustomURL("steam://url/SteamWorkshopPage/" + SteamManager.AppID);
return true;
}
};
browsePreviewFrame = new GUIFrame(new RectTransform(new Vector2(0.6f, 1.0f), tabs[(int)Tab.Browse].RectTransform, Anchor.TopRight), style: null);
//-------------------------------------------------------------------------------
//Publish tab
//-------------------------------------------------------------------------------
tabs[(int)Tab.Publish] = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.95f), tabContainer.RectTransform, Anchor.Center), isHorizontal: true)
{
Stretch = true,
RelativeSpacing = 0.02f
};
var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), tabs[(int)Tab.Publish].RectTransform))
{
Stretch = true,
RelativeSpacing = 0.02f
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("PublishedWorkshopItems"), font: GUI.SubHeadingFont);
publishedItemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), leftColumn.RectTransform))
{
OnSelected = (component, userdata) =>
{
if (GUI.MouseOn is GUIButton || GUI.MouseOn?.Parent is GUIButton) { return false; }
if (GUI.MouseOn is GUITickBox || GUI.MouseOn?.Parent is GUITickBox) { return false; }
myItemList.Deselect();
if (userdata is Steamworks.Ugc.Item?)
{
var item = userdata as Steamworks.Ugc.Item?;
if (!(item?.IsInstalled ?? false)) { return false; }
if (CreateWorkshopItem(item)) { ShowCreateItemFrame(); }
}
return true;
}
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("YourWorkshopItems"), font: GUI.SubHeadingFont);
myItemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), leftColumn.RectTransform))
{
OnSelected = (component, userdata) =>
{
if (GUI.MouseOn is GUIButton || GUI.MouseOn?.Parent is GUIButton) { return false; }
publishedItemList.Deselect();
if (userdata is SubmarineInfo sub)
{
CreateWorkshopItem(sub);
}
else if (userdata is ContentPackage contentPackage)
{
CreateWorkshopItem(contentPackage);
}
ShowCreateItemFrame();
return true;
}
};
createItemFrame = new GUIFrame(new RectTransform(new Vector2(0.58f, 1.0f), tabs[(int)Tab.Publish].RectTransform, Anchor.TopRight), style: null);
SelectTab(Tab.Mods);
CoroutineManager.StartCoroutine(PollSubscribedItems());
}
private GUITextBox CreateFilterBox(GUIComponent parent, GUIListBox listbox)
{
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), parent.RectTransform), isHorizontal: true)
{
Stretch = true
};
filterContainer.RectTransform.SetAsFirstChild();
var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUI.Font);
var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform, Anchor.CenterRight), font: GUI.Font, createClearButton: true);
filterContainer.RectTransform.MinSize = searchBox.RectTransform.MinSize;
searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; };
searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; };
searchBox.OnTextChanged += (textBox, text) =>
{
foreach (GUIComponent child in listbox.Content.Children)
{
if (!(child.UserData is Steamworks.Ugc.Item item)) { continue; }
child.Visible = string.IsNullOrEmpty(text) ? true : (item.Title?.ToLower().Contains(text.ToLower()) ?? false);
}
return true;
};
return searchBox;
}
public override void Select()
{
base.Select();
modsPreviewFrame.ClearChildren();
browsePreviewFrame.ClearChildren();
createItemFrame.ClearChildren();
itemContentPackage = null;
itemEditor = null;
SelectTab(Tab.Mods);
}
private void OnItemInstalled(ulong itemId)
{
RefreshSubscribedItems();
}
float subscribePollAdditionalWait = 0.0f;
private IEnumerable<object> PollSubscribedItems()
{
if (!SteamManager.IsInitialized) { yield return CoroutineStatus.Success; }
uint numSubscribed = 0;
while (true)
{
while (CoroutineManager.IsCoroutineRunning("Load")) { yield return new WaitForSeconds(1.0f); }
while (subscribePollAdditionalWait > 0.01f)
{
subscribePollAdditionalWait = Math.Min(subscribePollAdditionalWait, 3.0f);
float wait = subscribePollAdditionalWait;
yield return new WaitForSeconds(wait);
subscribePollAdditionalWait -= wait;
}
uint newNumSubscribed = Steamworks.SteamUGC.NumSubscribedItems;
if (newNumSubscribed != numSubscribed)
{
RefreshSubscribedItems();
numSubscribed = newNumSubscribed;
}
yield return new WaitForSeconds(1.0f);
}
}
private void SelectTab(Tab tab)
{
for (int i = 0; i < tabs.Length; i++)
{
tabButtons[i].Selected = tabs[i].Visible = i == (int)tab;
}
if (createItemFrame.CountChildren == 0)
{
new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.9f), createItemFrame.RectTransform, Anchor.Center),
TextManager.Get("WorkshopItemCreateHelpText"), wrap: true)
{
CanBeFocused = false
};
}
createItemWatcher?.Dispose(); createItemWatcher = null;
if (Screen.Selected == this)
{
switch (tab)
{
case Tab.Mods:
RefreshSubscribedItems();
break;
case Tab.Browse:
RefreshPopularItems();
break;
case Tab.Publish:
RefreshPublishedItems();
break;
}
}
}
public IEnumerable<object> RefreshDownloadState()
{
bool isDownloading = true;
while (true)
{
SteamManager.GetSubscribedWorkshopItems((items) =>
{
isDownloading = items.Any(it => it.IsDownloading || it.IsDownloadPending);
GameMain.MainMenuScreen.SetDownloadingModsNotification(isDownloading);
});
if (!isDownloading) { break; }
yield return new WaitForSeconds(0.5f);
}
yield return CoroutineStatus.Success;
}
private void RefreshSubscribedItems()
{
SteamManager.GetSubscribedWorkshopItems((items) =>
{
//filter out the items published by the player (they're shown in the publish tab)
var mySteamID = SteamManager.GetSteamID();
OnItemsReceived(GetVisibleItems(items.Where(it => it.Owner.Id != mySteamID)), subscribedItemList);
GameMain.MainMenuScreen.SetDownloadingModsNotification(items.Any(it => it.IsDownloading || it.IsDownloadPending));
});
}
private void RefreshPopularItems()
{
SteamManager.GetPopularWorkshopItems((items) => { OnItemsReceived(GetVisibleItems(items), topItemList); }, 20);
}
private void RefreshPublishedItems()
{
SteamManager.GetPublishedWorkshopItems((items) => { OnItemsReceived(items, publishedItemList); });
RefreshMyItemList();
}
private IEnumerable<Steamworks.Ugc.Item> GetVisibleItems(IEnumerable<Steamworks.Ugc.Item> items)
{
#if UNSTABLE
//show everything in Unstable
return items;
#else
//hide Unstable items in normal version
return items.Where(it => !it.HasTag("unstable"));
#endif
}
private void RefreshMyItemList()
{
myItemList.ClearChildren();
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), myItemList.Content.RectTransform), TextManager.Get("WorkshopLabelSubmarines"),
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont)
{
CanBeFocused = false
};
foreach (SubmarineInfo sub in SubmarineInfo.SavedSubmarines)
{
if (sub.HasTag(SubmarineTag.HideInMenus)) { continue; }
string subPath = Path.GetFullPath(sub.FilePath);
//ignore files that are part of the vanilla content package
if (GameMain.VanillaContent != null &&
GameMain.VanillaContent.Files.Any(s => Path.GetFullPath(s.Path) == subPath))
{
continue;
}
//ignore subs that are part of a workshop content package
if (ContentPackage.AllPackages.Any(cp => cp.SteamWorkshopId != 0 &&
cp.Files.Any(f => f.Type == ContentType.Submarine && Path.GetFullPath(f.Path) == subPath)))
{
continue;
}
//ignore subs that are defined in a content package with more files than just the sub
//(these will be listed in the "content packages" section)
if (ContentPackage.AllPackages.Any(cp => cp.Files.Count > 1 &&
cp.Files.Any(f => f.Type == ContentType.Submarine && Path.GetFullPath(f.Path) == subPath)))
{
continue;
}
CreateMyItemFrame(sub, myItemList);
}
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), myItemList.Content.RectTransform), TextManager.Get("WorkshopLabelContentPackages"),
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont)
{
CanBeFocused = false
};
foreach (ContentPackage contentPackage in ContentPackage.AllPackages)
{
if (contentPackage.SteamWorkshopId != 0 || contentPackage.HideInWorkshopMenu) { continue; }
if (contentPackage == GameMain.VanillaContent) { continue; }
//don't list content packages that only define one sub (they're visible in the "Submarines" section)
if (contentPackage.Files.Count == 1 && contentPackage.Files[0].Type == ContentType.Submarine) { continue; }
CreateMyItemFrame(contentPackage, myItemList);
}
}
private void OnItemsReceived(IEnumerable<Steamworks.Ugc.Item> itemDetails, GUIListBox listBox)
{
CrossThread.RequestExecutionOnMainThread(() =>
{
listBox.ClearChildren();
foreach (var item in itemDetails)
{
CreateWorkshopItemFrame(item, listBox);
}
if (itemDetails.Count() == 0 && listBox == subscribedItemList)
{
new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.9f), listBox.Content.RectTransform, Anchor.Center), TextManager.Get("NoSubscribedMods"), wrap: true)
{
CanBeFocused = false
};
}
});
}
private void CreateWorkshopItemFrame(Steamworks.Ugc.Item? item, GUIListBox listBox)
{
if (string.IsNullOrEmpty(item?.Title))
{
return;
}
string text = string.Empty;
if (listBox == subscribedItemList)
{
text = subscribedItemFilter.Text;
}
else if (listBox == topItemList)
{
text = topItemFilter.Text;
}
bool visible = string.IsNullOrEmpty(text) || (item?.Title?.ToLower().Contains(text.ToLower()) ?? false);
int prevIndex = -1;
var existingFrame = listBox.Content.FindChild((component) => { return (component.UserData is Steamworks.Ugc.Item?) && (component.UserData as Steamworks.Ugc.Item?)?.Id == item?.Id; });
if (existingFrame != null)
{
prevIndex = listBox.Content.GetChildIndex(existingFrame);
listBox.Content.RemoveChild(existingFrame);
}
var itemFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), listBox.Content.RectTransform, minSize: new Point(0, 80)),
style: "ListBoxElement")
{
UserData = item,
Visible = visible
};
if (prevIndex > -1)
{
itemFrame.RectTransform.RepositionChildInHierarchy(prevIndex);
}
var innerFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), itemFrame.RectTransform, Anchor.Center), isHorizontal: true)
{
CanBeFocused = false,
Stretch = true
};
int iconSize = innerFrame.Rect.Height;
if (itemPreviewSprites.ContainsKey(item?.PreviewImageUrl))
{
new GUIImage(new RectTransform(new Point(iconSize), innerFrame.RectTransform), itemPreviewSprites[item?.PreviewImageUrl], scaleToFit: true)
{
UserData = "previewimage",
CanBeFocused = false
};
}
else if (Screen.Selected == this)
{
new GUIImage(new RectTransform(new Point(iconSize), innerFrame.RectTransform), SteamManager.DefaultPreviewImage, scaleToFit: true)
{
UserData = "previewimage",
CanBeFocused = false
};
try
{
if (!string.IsNullOrEmpty(item?.PreviewImageUrl))
{
string imagePreviewPath = Path.Combine(SteamManager.WorkshopItemPreviewImageFolder, item?.Id + ".png");
bool isNewImage;
lock (pendingPreviewImageDownloads)
{
isNewImage = !pendingPreviewImageDownloads.ContainsKey(item.Value.Id);
if (isNewImage)
{
if (File.Exists(imagePreviewPath))
{
File.Delete(imagePreviewPath);
}
pendingPreviewImageDownloads.Add(item.Value.Id, new PendingPreviewImageDownload());
}
}
if (isNewImage)
{
Directory.CreateDirectory(SteamManager.WorkshopItemPreviewImageFolder);
Uri baseAddress = new Uri(item?.PreviewImageUrl);
Uri directory = new Uri(baseAddress, "."); // "." == current dir, like MS-DOS
string fileName = Path.GetFileName(baseAddress.LocalPath);
IRestClient client = new RestClient(directory);
var request = new RestRequest(fileName, Method.GET);
client.ExecuteAsync(request, response =>
{
OnPreviewImageDownloaded(response, imagePreviewPath,
() =>
{
lock (pendingPreviewImageDownloads)
{
pendingPreviewImageDownloads[item.Value.Id].Downloaded = true;
}
CoroutineManager.StartCoroutine(WaitForItemPreviewDownloaded(item, listBox, imagePreviewPath));
});
});
}
else
{
lock (pendingPreviewImageDownloads)
{
pendingPreviewImageDownloads[item.Value.Id].PendingLoads++;
}
CoroutineManager.StartCoroutine(WaitForItemPreviewDownloaded(item, listBox, imagePreviewPath));
}
}
}
catch (Exception e)
{
lock (pendingPreviewImageDownloads)
{
pendingPreviewImageDownloads.Remove(item.Value.Id);
}
DebugConsole.ThrowError("Downloading the preview image of the Workshop item \"" + item?.Title + "\" failed.", e);
}
}
var rightColumn = new GUILayoutGroup(new RectTransform(new Point(innerFrame.Rect.Width - iconSize, innerFrame.Rect.Height), innerFrame.RectTransform), childAnchor: Anchor.CenterLeft)
{
IsHorizontal = true,
Stretch = true,
RelativeSpacing = 0.05f,
CanBeFocused = false
};
var titleText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), rightColumn.RectTransform), item?.Title, textAlignment: Alignment.CenterLeft, wrap: true)
{
UserData = "titletext",
CanBeFocused = false
};
if ((item?.IsSubscribed ?? false) && (item?.IsInstalled ?? false) && Directory.Exists(item?.Directory))
{
bool installed = SteamManager.CheckWorkshopItemInstalled(item);
if (!installed)
{
bool? compatible = SteamManager.CheckWorkshopItemCompatibility(item);
if (compatible.HasValue && !compatible.Value)
{
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.3f), rightColumn.RectTransform),
TextManager.Get("WorkshopItemIncompatible"), textColor: GUI.Style.Red)
{
ToolTip = TextManager.Get("WorkshopItemIncompatibleTooltip")
};
}
else
{
installed = SteamManager.InstallWorkshopItem(item, out string errorMsg, Selected == this);
if (!installed)
{
DebugConsole.NewMessage(errorMsg, Color.Red);
titleText.TextColor = Color.Red;
titleText.ToolTip = itemFrame.ToolTip = TextManager.GetWithVariables("WorkshopItemUpdateFailed", new string[2] { "[itemname]", "[errormessage]" }, new string[2] { item?.Title, errorMsg });
}
}
}
if (installed)
{
bool upToDate = SteamManager.CheckWorkshopItemUpToDate(item);
if (!upToDate)
{
if (!SteamManager.UpdateWorkshopItem(item, out string errorMsg))
{
DebugConsole.NewMessage(errorMsg, Color.Red);
titleText.TextColor = Color.Red;
titleText.ToolTip = itemFrame.ToolTip = TextManager.GetWithVariables("WorkshopItemUpdateFailed", new string[2] { "[itemname]", "[errormessage]" }, new string[2] { item?.Title, errorMsg });
}
}
}
}
else if (item?.IsDownloading ?? false)
{
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.5f), rightColumn.RectTransform), TextManager.Get("WorkshopItemDownloading"));
}
else if (item?.IsDownloadPending ?? false)
{
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.5f), rightColumn.RectTransform), TextManager.Get("WorkshopItemDownloadPending"));
}
else if (!(item?.IsSubscribed ?? false) && (listBox != subscribedItemList))
{
var downloadBtn = new GUIButton(new RectTransform(new Point((int)(32 * GUI.Scale)), rightColumn.RectTransform), "", style: "GUIPlusButton")
{
ToolTip = TextManager.Get("DownloadButton"),
ForceUpperCase = true,
UserData = item
};
downloadBtn.OnClicked = (btn, userdata) => { DownloadItem(itemFrame, downloadBtn, item); return true; };
}
if ((item?.IsSubscribed ?? false) && listBox == subscribedItemList)
{
var reinstallBtn = new GUIButton(new RectTransform(new Point((int)(32 * GUI.Scale)), rightColumn.RectTransform), "", style: "GUIReloadButton")
{
ToolTip = TextManager.Get("WorkshopItemReinstall"),
ForceUpperCase = true,
UserData = "reinstall"
};
reinstallBtn.OnClicked = (btn, userdata) =>
{
var elem = subscribedItemList.Content.GetChildByUserData(item);
try
{
bool reselect = GameMain.Config.AllEnabledPackages.Any(cp => cp.SteamWorkshopId != 0 && cp.SteamWorkshopId == item?.Id);
if (!SteamManager.UninstallWorkshopItem(item, false, out string errorMsg) ||
!SteamManager.InstallWorkshopItem(item, out errorMsg, reselect, true))
{
DebugConsole.ThrowError($"Failed to reinstall \"{item?.Title}\": {errorMsg}", null, true);
elem.Flash(GUI.Style.Red);
}
}
catch (Exception e)
{
DebugConsole.ThrowError($"Failed to reinstall \"{item?.Title}\"", e, true);
elem.Flash(GUI.Style.Red);
}
return true;
};
var unsubBtn = new GUIButton(new RectTransform(new Point((int)(32 * GUI.Scale)), rightColumn.RectTransform), "", style: "GUIMinusButton")
{
ToolTip = TextManager.Get("WorkshopItemUnsubscribe"),
ForceUpperCase = true,
UserData = "unsubscribe"
};
unsubBtn.OnClicked = (btn, userdata) =>
{
subscribePollAdditionalWait += 1.0f;
item?.Unsubscribe();
SteamManager.UninstallWorkshopItem(item, true, out _);
subscribedItemList.RemoveChild(subscribedItemList.Content.GetChildByUserData(item));
return true;
};
}
innerFrame.Recalculate();
listBox.RecalculateChildren();
}
public void SetReinstallButtonStatus(Steamworks.Ugc.Item? item, bool enabled, Color? flashColor)
{
var child = subscribedItemList.Content.FindChild((component) => { return (component.UserData is Steamworks.Ugc.Item?) && (component.UserData as Steamworks.Ugc.Item?)?.Id == item?.Id; });
if (child != null)
{
var reinstallBtn = child.FindChild("reinstall", true);
if (reinstallBtn != null) { reinstallBtn.Enabled = enabled; }
var unsubBtn = child.FindChild("unsubscribe", true);
if (unsubBtn != null) { unsubBtn.Enabled = enabled; }
if (flashColor.HasValue) { child.Flash(flashColor); }
}
}
private void RemoveItemFromLists(ulong itemID)
{
RemoveItemFromList(publishedItemList);
RemoveItemFromList(subscribedItemList);
RemoveItemFromList(topItemList);
void RemoveItemFromList(GUIListBox listBox)
{
listBox.Content.RemoveChild(
listBox.Content.Children.FirstOrDefault(c => c.UserData is Steamworks.Ugc.Item? && (c.UserData as Steamworks.Ugc.Item?)?.Id == itemID));
}
}
private void CreateMyItemFrame(SubmarineInfo submarine, GUIListBox listBox)
{
var itemFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), listBox.Content.RectTransform, minSize: new Point(0, 80)),
style: "ListBoxElement")
{
UserData = submarine
};
var innerFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), itemFrame.RectTransform, Anchor.Center), isHorizontal: true)
{
RelativeSpacing = 0.1f,
Stretch = true
};
if (submarine.PreviewImage != null)
{
new GUIImage(new RectTransform(new Point(innerFrame.Rect.Height), innerFrame.RectTransform), submarine.PreviewImage, scaleToFit: true);
}
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), innerFrame.RectTransform), submarine.Name, textAlignment: Alignment.CenterLeft);
}
private void CreateMyItemFrame(ContentPackage contentPackage, GUIListBox listBox)
{
var itemFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), listBox.Content.RectTransform, minSize: new Point(0, 80)),
style: "ListBoxElement")
{
UserData = contentPackage
};
var innerFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), itemFrame.RectTransform, Anchor.Center), isHorizontal: true)
{
RelativeSpacing = 0.1f,
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), innerFrame.RectTransform), contentPackage.Name, textAlignment: Alignment.CenterLeft);
}
private void OnPreviewImageDownloaded(IRestResponse response, string previewImagePath, Action action)
{
if (response.ResponseStatus == ResponseStatus.Completed)
{
TaskPool.Add("WritePreviewImageAsync", WritePreviewImageAsync(response, previewImagePath), (task) => { action?.Invoke(); });
}
}
private async Task WritePreviewImageAsync(IRestResponse response, string previewImagePath)
{
await Task.Yield();
try
{
File.WriteAllBytes(previewImagePath, response.RawBytes);
}
catch (Exception e)
{
string errorMsg = "Failed to save workshop item preview image to \"" + previewImagePath + "\".";
GameAnalyticsManager.AddErrorEventOnce("SteamWorkshopScreen.OnItemPreviewDownloaded:WriteAllBytesFailed" + previewImagePath,
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + "\n" + e.Message);
return;
}
}
private IEnumerable<object> WaitForItemPreviewDownloaded(Steamworks.Ugc.Item? item, GUIListBox listBox, string previewImagePath)
{
while (true)
{
lock (pendingPreviewImageDownloads)
{
if (pendingPreviewImageDownloads[item.Value.Id].Downloaded){ break; }
}
yield return new WaitForSeconds(0.2f);
}
if (File.Exists(previewImagePath))
{
TaskPool.Add("LoadPreviewImageAsync", LoadPreviewImageAsync(item?.PreviewImageUrl, previewImagePath),
new Tuple<Steamworks.Ugc.Item?, GUIListBox>(item, listBox),
(task, tuple) =>
{
//must be done in the main thread because creating/removing GUI elements is not thread-safe
CrossThread.RequestExecutionOnMainThread(() =>
{
(var it, var lb) = tuple;
if (lb.Content.FindChild(item)?.GetChildByUserData("previewimage") is GUIImage previewImage)
{
previewImage.Sprite = ((Task<Sprite>)task).Result;
}
else
{
CreateWorkshopItemFrame(it, lb);
}
if (modsPreviewFrame.FindChild(it) != null)
{
ShowItemPreview(it, modsPreviewFrame);
}
if (browsePreviewFrame.FindChild(item) != null)
{
ShowItemPreview(it, browsePreviewFrame);
}
lock (pendingPreviewImageDownloads)
{
pendingPreviewImageDownloads[it.Value.Id].PendingLoads--;
if (pendingPreviewImageDownloads[it.Value.Id].PendingLoads <= 0) { pendingPreviewImageDownloads.Remove(it.Value.Id); }
}
});
});
}
yield return CoroutineStatus.Success;
}
private async Task<Sprite> LoadPreviewImageAsync(string previewImageUrl, string previewImagePath)
{
await Task.Yield();
lock (itemPreviewSprites)
{
if (itemPreviewSprites.ContainsKey(previewImageUrl))
{
return itemPreviewSprites[previewImageUrl];
}
else
{
Sprite newSprite = new Sprite(previewImagePath, sourceRectangle: null);
itemPreviewSprites.Add(previewImageUrl, newSprite);
return newSprite;
}
}
}
private bool DownloadItem(GUIComponent frame, GUIButton downloadButton, Steamworks.Ugc.Item? item)
{
if (item == null) { return false; }
var parentElement = downloadButton.Parent;
parentElement.RemoveChild(downloadButton);
var textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.5f), parentElement.RectTransform), TextManager.Get("WorkshopItemDownloading"));
SteamManager.SubscribeToWorkshopItem(item.Value.Id, () =>
{
if (SteamManager.InstallWorkshopItem(item, out _))
{
textBlock.Text = TextManager.Get("workshopiteminstalled");
frame.Flash(GUI.Style.Green);
}
else
{
frame.Flash(GUI.Style.Red);
}
RefreshSubscribedItems();
});
return true;
}
private void ShowItemPreview(Steamworks.Ugc.Item? item, GUIFrame itemPreviewFrame)
{
itemPreviewFrame.ClearChildren();
if (item == null) { return; }
var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), itemPreviewFrame.RectTransform, Anchor.Center))
{
Stretch = true,
UserData = item
};
var headerArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), content.RectTransform))
{
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerArea.RectTransform), item?.Title, textAlignment: Alignment.CenterLeft, font: GUI.LargeFont, wrap: true);
new GUITextBlock(new RectTransform(new Vector2(0.3f, 0.0f), headerArea.RectTransform), item?.Owner.Name, textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont);
var btn = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), headerArea.RectTransform, Anchor.CenterRight), TextManager.Get("WorkshopShowItemInSteam"), style: "GUIButtonSmall")
{
IgnoreLayoutGroups = true,
OnClicked = (btn, userdata) =>
{
SteamManager.OverlayCustomURL("steam://url/CommunityFilePage/" + item?.Id);
return true;
}
};
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null);
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.005f), content.RectTransform), style: "HorizontalLine");
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null);
//---------------
var centerArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), isHorizontal: true)
{
Stretch = true,
RelativeSpacing = 0.01f
};
if (itemPreviewSprites.ContainsKey(item?.PreviewImageUrl))
{
new GUIImage(new RectTransform(new Vector2(0.5f, 1.0f), centerArea.RectTransform), itemPreviewSprites[item?.PreviewImageUrl], scaleToFit: true);
}
else
{
new GUIImage(new RectTransform(new Vector2(0.5f, 0.0f), centerArea.RectTransform), SteamManager.DefaultPreviewImage, scaleToFit: true);
}
var statsFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), centerArea.RectTransform), style: "GUIFrameListBox");
var statsContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f), statsFrame.RectTransform, Anchor.Center))
{
Stretch = true,
RelativeSpacing = 0.01f
};
//score -------------------------------------
var scoreContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), statsContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
Stretch = true,
RelativeSpacing = 0.02f
};
new GUITextBlock(new RectTransform(new Vector2(0.2f, 0.0f), scoreContainer.RectTransform), TextManager.Get("WorkshopItemScore"), font: GUI.SubHeadingFont);
int starCount = (int)Math.Round((item?.Score ?? 0.0f) * 5);
for (int i = 0; i < 5; i++)
{
new GUIImage(new RectTransform(new Point(scoreContainer.Rect.Height), scoreContainer.RectTransform),
i < starCount ? "GUIStarIconBright" : "GUIStarIconDark");
}
new GUITextBlock(new RectTransform(new Vector2(0.2f, 0.0f), scoreContainer.RectTransform),
TextManager.GetWithVariable("WorkshopItemVotes", "[votecount]", (item.Value.VotesUp + item.Value.VotesDown).ToString()),
textAlignment: Alignment.CenterRight);
//tags ------------------------------------
List<string> tags = new List<string>();
for (int i = 0; i < item?.Tags.Length && i < 5; i++)
{
if (string.IsNullOrEmpty(item?.Tags[i])) { continue; }
string tag = TextManager.Get("Workshop.ContentTag." + item?.Tags[i].Replace(" ", ""), true);
if (string.IsNullOrEmpty(tag)) { tag = item?.Tags[i].CapitaliseFirstInvariant(); }
tags.Add(tag);
}
if (tags.Count > 0)
{
var tagContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), statsContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
Stretch = true,
RelativeSpacing = 0.05f,
CanBeFocused = true
};
new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), tagContainer.RectTransform), TextManager.Get("WorkshopItemTags"), font: GUI.SubHeadingFont);
var t = new GUITextBlock(new RectTransform(new Vector2(0.8f, 1.0f), tagContainer.RectTransform, Anchor.TopRight), string.Join(", ", tags), textAlignment: Alignment.CenterRight);
t.RectTransform.SizeChanged += () =>
{
t.TextScale = 1.0f;
t.AutoScaleHorizontal = true;
};
}
var fileSize = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), statsContent.RectTransform), TextManager.Get("WorkshopItemFileSize"), font: GUI.SubHeadingFont);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), fileSize.RectTransform, Anchor.TopRight), MathUtils.GetBytesReadable(item?.IsInstalled ?? false ? (long)item.Value.SizeBytes : item.Value.DownloadBytesDownloaded), textAlignment: Alignment.CenterRight);
//var dateContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), isHorizontal: true);
var creationDate = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), statsContent.RectTransform), TextManager.Get("WorkshopItemCreationDate"), font: GUI.SubHeadingFont);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), creationDate.RectTransform, Anchor.CenterRight), item?.Created.ToString("dd.MM.yyyy"), textAlignment: Alignment.CenterRight);
var modificationDate = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), statsContent.RectTransform), TextManager.Get("WorkshopItemModificationDate"), font: GUI.SubHeadingFont);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), modificationDate.RectTransform, Anchor.CenterRight), item?.Updated.ToString("dd.MM.yyyy"), textAlignment: Alignment.CenterRight);
if (item?.IsSubscribed ?? false)
{
var buttonContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), statsContent.RectTransform), style: null);
var unsubscribeButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.95f), buttonContainer.RectTransform, Anchor.Center), TextManager.Get("WorkshopItemUnsubscribe"), style: "GUIButtonSmall")
{
UserData = item,
OnClicked = (btn, userdata) =>
{
subscribePollAdditionalWait += 1.0f;
item?.Unsubscribe();
SteamManager.UninstallWorkshopItem(item, true, out _);
subscribedItemList.RemoveChild(subscribedItemList.Content.GetChildByUserData(item));
itemPreviewFrame.ClearChildren();
return true;
}
};
buttonContainer.RectTransform.MinSize = unsubscribeButton.RectTransform.MinSize;
statsContent.Recalculate();
}
//------------------
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null);
var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform)) { ScrollBarVisible = true };
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), descriptionContainer.Content.RectTransform) { MinSize = new Point(0, 5) }, style: null);
string description = item?.Description;
description = ToolBox.RemoveBBCodeTags(description);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), descriptionContainer.Content.RectTransform), description, wrap: true)
{
CanBeFocused = false
};
}
private void CreateWorkshopItem(SubmarineInfo sub)
{
string destinationFolder = Path.Combine("Mods", sub.Name.Trim());
itemContentPackage = ContentPackage.CreatePackage(sub.Name, Path.Combine(destinationFolder, SteamManager.MetadataFileName), corePackage: false);
SteamManager.CreateWorkshopItemStaging(itemContentPackage, out itemEditor);
string submarineDir = Path.GetDirectoryName(sub.FilePath);
if (submarineDir != Path.GetDirectoryName(destinationFolder))
{
string destinationPath = Path.Combine(destinationFolder, Path.GetFileName(sub.FilePath));
if (!File.Exists(destinationPath))
{
File.Move(sub.FilePath, destinationPath);
}
sub.FilePath = destinationPath;
}
itemContentPackage.AddFile(sub.FilePath, ContentType.Submarine);
itemContentPackage.Name = sub.Name;
itemContentPackage.Save(itemContentPackage.Path);
//ContentPackage.List.Add(itemContentPackage);
//GameMain.Config.SelectContentPackage(itemContentPackage);
itemEditor = itemEditor?.WithTitle(sub.Name).WithTag("Submarine").WithDescription(sub.Description);
if (sub.PreviewImage != null)
{
string previewImagePath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(itemContentPackage.Path), SteamManager.PreviewImageName));
try
{
using (System.IO.Stream s = File.Create(previewImagePath))
{
sub.PreviewImage.Texture.SaveAsPng(s, (int)sub.PreviewImage.size.X, (int)sub.PreviewImage.size.Y);
itemEditor = itemEditor?.WithPreviewFile(previewImagePath);
}
if (new FileInfo(previewImagePath).Length > 1024 * 1024)
{
new GUIMessageBox(TextManager.Get("Error"), TextManager.Get("WorkshopItemPreviewImageTooLarge"));
itemEditor = itemEditor?.WithPreviewFile(SteamManager.DefaultPreviewImagePath);
}
}
catch (Exception e)
{
DebugConsole.ThrowError("Saving submarine preview image failed.", e);
itemEditor = itemEditor?.WithPreviewFile(null);
}
}
}
private void CreateWorkshopItem(ContentPackage contentPackage)
{
//SteamManager.CreateWorkshopItemStaging(new List<ContentFile>(), out itemEditor, out itemContentPackage);
itemContentPackage = contentPackage;
SteamManager.CreateWorkshopItemStaging(itemContentPackage, out itemEditor);
itemEditor = itemEditor?.WithTitle(contentPackage.Name);
/*string modDirectory = "";
foreach (ContentFile file in contentPackage.Files)
{
itemContentPackage.AddFile(file.Path, file.Type);
//if some of the content files are in a subdirectory of the Mods folder,
//assume that directory contains mod files for this package and copy them to the staging folder
if (modDirectory == "" && ContentPackage.IsModFilePathAllowed(file.Path))
{
string directoryName = Path.GetDirectoryName(file.Path);
string[] splitPath = directoryName.Split(Path.DirectorySeparatorChar);
if (splitPath.Length >= 2 && splitPath[0] == "Mods")
{
modDirectory = splitPath[1];
}
}
}
if (!string.IsNullOrEmpty(modDirectory))
{
SaveUtil.CopyFolder(Path.Combine("Mods", modDirectory), Path.Combine(SteamManager.WorkshopItemStagingFolder, "Mods", modDirectory), copySubDirs: true);
}*/
}
private bool CreateWorkshopItem(Steamworks.Ugc.Item? item)
{
if (!(item?.IsInstalled ?? false))
{
new GUIMessageBox(TextManager.Get("Error"),
TextManager.GetWithVariable("WorkshopErrorInstallRequiredToEdit", "[itemname]", (item?.Title ?? "[NULL]")));
return false;
}
if (!SteamManager.CreateWorkshopItemStaging(item, out itemEditor, out itemContentPackage))
{
return false;
}
var tickBox = publishedItemList.Content.GetChildByUserData(item)?.GetAnyChild<GUITickBox>();
if (tickBox != null) { tickBox.Selected = true; }
return true;
}
private void ShowCreateItemFrame()
{
createItemFrame.ClearChildren();
if (itemEditor == null) { return; }
if (itemContentPackage == null)
{
string errorMsg = "Failed to edit workshop item (content package null)\n" + Environment.StackTrace.CleanupStackTrace();
DebugConsole.ThrowError(errorMsg);
GameAnalyticsManager.AddErrorEventOnce("SteamWorkshopScreen.ShowCreateItemFrame:ContentPackageNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
return;
}
var createItemContent = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.98f), createItemFrame.RectTransform, Anchor.Center))
{
Stretch = true,
RelativeSpacing = 0.02f
};
var topPanel = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.4f), createItemContent.RectTransform), isHorizontal: true)
{
Stretch = true,
RelativeSpacing = 0.01f
};
var topLeftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1.0f), topPanel.RectTransform))
{
Stretch = true,
RelativeSpacing = 0.02f
};
var topRightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 1.0f), topPanel.RectTransform))
{
Stretch = true,
RelativeSpacing = 0.02f
};
// top right column --------------------------------------------------------------------------------------
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), topRightColumn.RectTransform), TextManager.Get("WorkshopItemTitle"), font: GUI.SubHeadingFont);
var titleBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.15f), topRightColumn.RectTransform), itemEditor?.Title);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), topRightColumn.RectTransform), TextManager.Get("WorkshopItemDescription"), font: GUI.SubHeadingFont);
var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), topRightColumn.RectTransform));
var descriptionBox = new GUITextBox(new RectTransform(Vector2.One, descriptionContainer.Content.RectTransform), itemEditor?.Description,
textAlignment: Alignment.TopLeft, style: "GUITextBoxNoBorder", font: GUI.SmallFont, wrap: true);
descriptionBox.OnTextChanged += (textBox, text) =>
{
Vector2 textSize = textBox.Font.MeasureString(descriptionBox.WrappedText);
textBox.RectTransform.NonScaledSize = new Point(textBox.RectTransform.NonScaledSize.X, Math.Max(descriptionContainer.Content.Rect.Height, (int)textSize.Y + 10));
descriptionContainer.UpdateScrollBarSize();
descriptionContainer.BarScroll = 1.0f;
itemEditor = itemEditor?.WithDescription(text);
return true;
};
descriptionContainer.RectTransform.SizeChanged += () => { descriptionBox.Text = descriptionBox.Text; };
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), topRightColumn.RectTransform), TextManager.Get("WorkshopItemTags"), font: GUI.SubHeadingFont);
var tagHolder = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.17f), topRightColumn.RectTransform) { MinSize = new Point(0, 50) }, isHorizontal: true)
{
Spacing = 5
};
HashSet<string> availableTags = new HashSet<string>();
foreach (string tag in itemEditor?.Tags ?? Enumerable.Empty<string>())
{
if (!string.IsNullOrEmpty(tag)) { availableTags.Add(tag.ToLowerInvariant()); }
}
foreach (string tag in SteamManager.PopularTags)
{
if (!string.IsNullOrEmpty(tag)) { availableTags.Add(tag.ToLowerInvariant()); }
if (availableTags.Count > 10) { break; }
}
foreach (string tag in availableTags)
{
var tagBtn = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), tagHolder.Content.RectTransform, anchor: Anchor.CenterLeft),
tag.CapitaliseFirstInvariant(), style: "GUIButtonRound");
tagBtn.TextBlock.AutoScaleHorizontal = true;
tagBtn.Selected = itemEditor?.Tags?.Any(t => t.Equals(tag, StringComparison.OrdinalIgnoreCase)) ?? false;
tagBtn.OnClicked = (btn, userdata) =>
{
if (!tagBtn.Selected)
{
if (!(itemEditor?.Tags?.Any(t => t.ToLowerInvariant() == tag) ?? false)) { itemEditor = itemEditor?.WithTag(tagBtn.Text); }
tagBtn.Selected = true;
}
else
{
itemEditor?.Tags?.RemoveAll(t => t.Equals(tagBtn.Text, StringComparison.OrdinalIgnoreCase));
tagBtn.Selected = false;
}
return true;
};
}
tagHolder.UpdateScrollBarSize();
// top left column --------------------------------------------------------------------------------------
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), topLeftColumn.RectTransform), TextManager.Get("WorkshopItemPreviewImage"), font: GUI.SubHeadingFont);
var previewIcon = new GUIImage(new RectTransform(new Vector2(1.0f, 0.7f), topLeftColumn.RectTransform), SteamManager.DefaultPreviewImage, scaleToFit: true);
new GUIButton(new RectTransform(new Vector2(1.0f, 0.2f), topLeftColumn.RectTransform), TextManager.Get("WorkshopItemBrowse"), style: "GUIButtonSmall")
{
OnClicked = (btn, userdata) =>
{
FileSelection.OnFileSelected = (file) =>
{
OnPreviewImageSelected(previewIcon, file);
};
FileSelection.ClearFileTypeFilters();
FileSelection.AddFileTypeFilter("PNG", "*.png");
FileSelection.AddFileTypeFilter("JPEG", "*.jpg, *.jpeg");
FileSelection.AddFileTypeFilter("All files", "*.*");
FileSelection.SelectFileTypeFilter("*.png");
FileSelection.Open = true;
return true;
}
};
//if preview image has not been set, but there's a PreviewImage file inside the mod folder, use that by default
if (string.IsNullOrEmpty(itemEditor?.PreviewFile))
{
string previewImagePath = Path.Combine(Path.GetDirectoryName(itemContentPackage.Path), SteamManager.PreviewImageName);
if (File.Exists(previewImagePath))
{
itemEditor = itemEditor?.WithPreviewFile(Path.GetFullPath(previewImagePath));
}
}
if (!string.IsNullOrEmpty(itemEditor?.PreviewFile))
{
itemEditor = itemEditor?.WithPreviewFile(Path.GetFullPath(itemEditor?.PreviewFile));
if (itemPreviewSprites.ContainsKey(itemEditor?.PreviewFile))
{
itemPreviewSprites[itemEditor?.PreviewFile].Remove();
}
var newPreviewImage = new Sprite(itemEditor?.PreviewFile, sourceRectangle: null);
previewIcon.Sprite = newPreviewImage;
itemPreviewSprites[itemEditor?.PreviewFile] = newPreviewImage;
}
new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), topLeftColumn.RectTransform), TextManager.Get("WorkshopItemCorePackage"))
{
ToolTip = TextManager.Get("WorkshopItemCorePackageTooltip"),
Selected = itemContentPackage.IsCorePackage,
OnSelected = (tickbox) =>
{
if (tickbox.Selected)
{
if (!itemContentPackage.ContainsRequiredCorePackageFiles(out List<ContentType> missingContentTypes))
{
new GUIMessageBox(
TextManager.Get("Error"),
TextManager.GetWithVariables("ContentPackageCantMakeCorePackage", new string[2] { "[packagename]", "[missingfiletypes]" },
new string[2] { itemContentPackage.Name, string.Join(", ", missingContentTypes) }, new bool[2] { false, true }));
tickbox.Selected = false;
}
else
{
itemContentPackage.IsCorePackage = tickbox.Selected;
}
}
else
{
itemContentPackage.IsCorePackage = false;
}
return true;
}
};
// file list --------------------------------------------------------------------------------------
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), createItemContent.RectTransform), style: null);
var fileListTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), createItemContent.RectTransform), TextManager.Get("WorkshopItemFiles"), font: GUI.SubHeadingFont);
new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), fileListTitle.RectTransform, Anchor.CenterRight), TextManager.Get("WorkshopItemShowFolder"), style: "GUIButtonSmall")
{
IgnoreLayoutGroups = true,
OnClicked = (btn, userdata) => { ToolBox.OpenFileWithShell(Path.GetFullPath(Path.GetDirectoryName(itemContentPackage.Path))); return true; }
};
createItemFileList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.35f), createItemContent.RectTransform));
createItemWatcher?.Dispose();
createItemWatcher = new System.IO.FileSystemWatcher(Path.GetDirectoryName(itemContentPackage.Path))
{
Filter = "*",
NotifyFilter = System.IO.NotifyFilters.LastWrite | System.IO.NotifyFilters.FileName | System.IO.NotifyFilters.DirectoryName
};
createItemWatcher.Created += OnFileSystemChanges;
createItemWatcher.Deleted += OnFileSystemChanges;
createItemWatcher.Renamed += OnFileSystemChanges;
createItemWatcher.EnableRaisingEvents = true;
RefreshCreateItemFileList();
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), createItemContent.RectTransform), isHorizontal: true)
{
RelativeSpacing = 0.02f
};
new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonContainer.RectTransform, Anchor.TopRight), TextManager.Get("WorkshopItemRefreshFileList"), style: "GUIButtonSmall")
{
ToolTip = TextManager.Get("WorkshopItemRefreshFileListTooltip"),
OnClicked = (btn, userdata) =>
{
itemContentPackage = new ContentPackage(itemContentPackage.Path);
RefreshCreateItemFileList();
return true;
}
};
new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonContainer.RectTransform, Anchor.TopRight), TextManager.Get("WorkshopItemAddFiles"), style: "GUIButtonSmall")
{
OnClicked = (btn, userdata) =>
{
FileSelection.OnFileSelected = (file) =>
{
OnAddFilesSelected(new string[] { file });
};
FileSelection.ClearFileTypeFilters();
FileSelection.AddFileTypeFilter("PNG", "*.png");
FileSelection.AddFileTypeFilter("JPEG", "*.jpg, *.jpeg");
FileSelection.AddFileTypeFilter("OGG", "*.ogg");
FileSelection.AddFileTypeFilter("XML", "*.xml");
FileSelection.AddFileTypeFilter("TXT", "*.txt");
FileSelection.AddFileTypeFilter("All files", "*.*");
FileSelection.SelectFileTypeFilter("*.*");
FileSelection.Open = true;
return true;
}
};
//the item has been already published if it has a non-zero ID -> allow adding a changenote
if ((itemEditor?.FileId ?? 0) > 0)
{
var bottomRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), createItemContent.RectTransform), isHorizontal: true);
var changeNoteLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.7f, 1.0f), bottomRow.RectTransform));
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), changeNoteLayout.RectTransform), TextManager.Get("WorkshopItemChangenote"), font: GUI.SubHeadingFont)
{
ToolTip = TextManager.Get("WorkshopItemChangenoteTooltip")
};
var changenoteContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.75f), changeNoteLayout.RectTransform));
var changenoteBox = new GUITextBox(new RectTransform(Vector2.One, changenoteContainer.Content.RectTransform), "",
textAlignment: Alignment.TopLeft, style: "GUITextBoxNoBorder", wrap: true)
{
ToolTip = TextManager.Get("WorkshopItemChangenoteTooltip")
};
changenoteBox.OnTextChanged += (textBox, text) =>
{
Vector2 textSize = textBox.Font.MeasureString(changenoteBox.WrappedText);
textBox.RectTransform.NonScaledSize = new Point(textBox.RectTransform.NonScaledSize.X, Math.Max(changenoteContainer.Content.Rect.Height, (int)textSize.Y + 10));
changenoteContainer.UpdateScrollBarSize();
changenoteContainer.BarScroll = 1.0f;
itemEditor = itemEditor?.WithChangeLog(text);
return true;
};
}
var bottomButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.08f), createItemContent.RectTransform),
isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
RelativeSpacing = 0.03f
};
var visibilityLabel = new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), bottomButtonContainer.RectTransform), TextManager.Get("WorkshopItemVisibility"),
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont)
{
ToolTip = TextManager.Get("WorkshopItemVisibilityTooltip")
};
visibilityLabel.RectTransform.MaxSize = new Point((int)(visibilityLabel.TextSize.X * 1.1f), 0);
var visibilityDropDown = new GUIDropDown(new RectTransform(new Vector2(0.2f, 1.0f), bottomButtonContainer.RectTransform));
foreach (VisibilityType visibilityType in Enum.GetValues(typeof(VisibilityType)))
{
visibilityDropDown.AddItem(TextManager.Get("WorkshopItemVisibility." + visibilityType), visibilityType);
}
visibilityDropDown.SelectItem(itemEditor.Value.IsPublic ? VisibilityType.Public :
itemEditor.Value.IsFriendsOnly ? VisibilityType.FriendsOnly :
VisibilityType.Private);
visibilityDropDown.OnSelected = (c, ud) =>
{
if (!(ud is VisibilityType visibilityType)) { return false; }
switch (visibilityType)
{
case VisibilityType.Public:
itemEditor = itemEditor?.WithPublicVisibility();
break;
case VisibilityType.FriendsOnly:
itemEditor = itemEditor?.WithFriendsOnlyVisibility();
break;
case VisibilityType.Private:
itemEditor = itemEditor?.WithPrivateVisibility();
break;
}
return true;
};
if ((itemEditor?.FileId ?? 0) > 0)
{
new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), bottomButtonContainer.RectTransform),
TextManager.Get("WorkshopItemDelete"), style: "GUIButtonSmall")
{
ToolTip = TextManager.Get("WorkshopItemDeleteTooltip"),
TextColor = GUI.Style.Red,
OnClicked = (btn, userData) =>
{
if (itemEditor == null) { return false; }
var deleteVerification = new GUIMessageBox("", TextManager.GetWithVariable("WorkshopItemDeleteVerification", "[itemname]", itemEditor?.Title),
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
deleteVerification.Buttons[0].OnClicked = (yesBtn, userdata) =>
{
if (itemEditor == null) { return false; }
RemoveItemFromLists(itemEditor.Value.FileId);
TaskPool.Add("DeleteFileAsync", Steamworks.SteamUGC.DeleteFileAsync(itemEditor.Value.FileId),
(t) =>
{
if (t.Status == TaskStatus.Faulted)
{
TaskPool.PrintTaskExceptions(t, "Failed to delete Workshop item " + (itemEditor?.Title ?? "[NULL]"));
return;
}
});
itemEditor = null;
SelectTab(Tab.Browse);
deleteVerification.Close();
createItemFrame.ClearChildren();
itemContentPackage.SteamWorkshopId = 0;
itemContentPackage.Save(itemContentPackage.Path);
return true;
};
deleteVerification.Buttons[1].OnClicked = deleteVerification.Close;
return true;
}
};
}
var publishBtn = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), bottomButtonContainer.RectTransform, Anchor.CenterRight),
TextManager.Get((itemEditor?.FileId ?? 0) > 0 ? "WorkshopItemUpdate" : "WorkshopItemPublish"))
{
IgnoreLayoutGroups = true,
ToolTip = TextManager.Get("WorkshopItemPublishTooltip"),
OnClicked = (btn, userData) =>
{
itemEditor = itemEditor?.WithTitle(titleBox.Text);
itemEditor = itemEditor?.WithDescription(descriptionBox.Text);
if (string.IsNullOrWhiteSpace(itemEditor?.Title))
{
titleBox.Flash(GUI.Style.Red);
return false;
}
if (string.IsNullOrWhiteSpace(itemEditor?.Description))
{
descriptionBox.Flash(GUI.Style.Red);
return false;
}
if (createItemFileList.Content.CountChildren == 0)
{
createItemFileList.Flash(GUI.Style.Red);
}
if (!itemContentPackage.CheckErrors(out List<string> errorMessages))
{
new GUIMessageBox(
TextManager.GetWithVariable("workshopitempublishfailed", "[itemname]", itemEditor?.Title),
string.Join("\n", errorMessages));
return false;
}
PublishWorkshopItem();
return true;
}
};
publishBtn.TextBlock.AutoScaleHorizontal = true;
}
private void OnPreviewImageSelected(GUIImage previewImageElement, string filePath)
{
string previewImagePath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(itemContentPackage.Path), SteamManager.PreviewImageName));
if (new FileInfo(filePath).Length > 1024 * 1024)
{
new GUIMessageBox(TextManager.Get("Error"), TextManager.Get("WorkshopItemPreviewImageTooLarge"));
return;
}
if (Path.GetFullPath(filePath) != previewImagePath)
{
try
{
File.Copy(filePath, previewImagePath, overwrite: true);
}
catch (System.IO.IOException e)
{
DebugConsole.ThrowError("Failed to copy the preview image \"{previewImagePath}\" to the mod folder.", e);
return;
}
}
if (itemPreviewSprites.ContainsKey(previewImagePath))
{
itemPreviewSprites[previewImagePath].Remove();
}
var newPreviewImage = new Sprite(previewImagePath, sourceRectangle: null);
previewImageElement.Sprite = newPreviewImage;
itemPreviewSprites[previewImagePath] = newPreviewImage;
itemEditor?.WithPreviewFile(previewImagePath);
}
private void OnAddFilesSelected(string[] fileNames)
{
if (fileNames == null) { return; }
for (int i = 0; i < fileNames.Length; i++)
{
string file = fileNames[i]?.Trim();
if (string.IsNullOrEmpty(file) || !File.Exists(file)) { continue; }
string modFolder = Path.GetDirectoryName(itemContentPackage.Path);
string filePathRelativeToModFolder = UpdaterUtil.GetRelativePath(file, Path.Combine(Environment.CurrentDirectory, modFolder));
//file is not inside the mod folder, we need to move it
if (filePathRelativeToModFolder.StartsWith("..") ||
Path.GetPathRoot(Environment.CurrentDirectory) != Path.GetPathRoot(file))
{
string destinationPath = Path.Combine(modFolder, Path.GetFileName(file));
//add a number to the filename if a file with the same name already exists
i = 2;
while (File.Exists(destinationPath))
{
destinationPath = Path.Combine(modFolder, $"{Path.GetFileNameWithoutExtension(file)} ({i}){Path.GetExtension(file)}");
i++;
}
try
{
File.Copy(file, destinationPath);
}
catch (Exception e)
{
DebugConsole.ThrowError("Copying the file \"" + file + "\" to the mod folder failed.", e);
return;
}
}
}
RefreshCreateItemFileList();
}
volatile bool refreshFileList = false;
private void OnFileSystemChanges(object sender, System.IO.FileSystemEventArgs e)
{
refreshFileList = true;
}
private void RefreshCreateItemFileList()
{
createItemFileList.ClearChildren();
if (itemContentPackage == null) return;
var contentTypes = Enum.GetValues(typeof(ContentType));
List<ContentFile> files = itemContentPackage.FilesUnsaved.ToList();
for (int i = files.Count - 1; i >= 0; i--)
{
ContentFile contentFile = files[i];
bool fileExists = File.Exists(contentFile.Path);
if (contentFile.Type == ContentType.ServerExecutable)
{
fileExists |= File.Exists(Path.GetFileNameWithoutExtension(contentFile.Path) + ".dll");
}
if (!fileExists)
{
itemContentPackage.RemoveFile(contentFile);
files.RemoveAt(i);
}
}
List<ContentFile> allFiles = Directory.GetFiles(Path.GetDirectoryName(itemContentPackage.Path), "*", System.IO.SearchOption.AllDirectories)
.Select(f => new ContentFile(f, ContentType.None))
.Where(file => Path.GetFileName(file.Path) != SteamManager.MetadataFileName &&
Path.GetFileName(file.Path) != SteamManager.PreviewImageName)
.ToList();
for (int i=0;i<allFiles.Count;i++)
{
ContentFile file = allFiles[i];
ContentFile otherFile = files.Find(f => string.Equals(Path.GetFullPath(f.Path).CleanUpPath(),
Path.GetFullPath(file.Path).CleanUpPath(),
StringComparison.InvariantCultureIgnoreCase));
if (otherFile != null)
{
//replace the generated ContentFile object with the one that's present in the
//content package to determine which tickboxes should already be checked
allFiles[i] = otherFile;
files.Remove(otherFile);
}
}
allFiles.AddRange(files);
foreach (ContentFile contentFile in allFiles)
{
bool illegalPath = !ContentPackage.IsModFilePathAllowed(contentFile);
bool fileExists = File.Exists(contentFile.Path);
if (contentFile.Type == ContentType.ServerExecutable)
{
fileExists |= File.Exists(Path.GetFileNameWithoutExtension(contentFile.Path) + ".dll");
}
var fileFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.12f), createItemFileList.Content.RectTransform) { MinSize = new Point(0, 20) },
style: "ListBoxElement")
{
CanBeFocused = false,
UserData = contentFile
};
var content = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 1.0f), fileFrame.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
Stretch = true,
RelativeSpacing = 0.05f
};
var tickBox = new GUITickBox(new RectTransform(Vector2.One, content.RectTransform, scaleBasis: ScaleBasis.BothHeight), "")
{
Selected = itemContentPackage.FilesUnsaved.Contains(contentFile),
UserData = contentFile
};
tickBox.OnSelected = (tb) =>
{
ContentFile f = tb.UserData as ContentFile;
if (tb.Selected)
{
if (!itemContentPackage.FilesUnsaved.Contains(f)) { itemContentPackage.AddFile(f); }
}
else
{
if (itemContentPackage.FilesUnsaved.Contains(f)) { itemContentPackage.RemoveFile(f); }
}
return true;
};
var nameText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), content.RectTransform, Anchor.CenterLeft), contentFile.Path, font: GUI.SmallFont)
{
ToolTip = contentFile.Path
};
if (!fileExists)
{
nameText.TextColor = GUI.Style.Red;
tickBox.ToolTip = TextManager.Get("WorkshopItemFileNotFound");
}
else if (illegalPath && !ContentPackage.AllPackages.Any(cp => cp.FilesUnsaved.Any(f => Path.GetFullPath(f.Path) == Path.GetFullPath(contentFile.Path))))
{
nameText.TextColor = GUI.Style.Red;
tickBox.ToolTip = TextManager.Get("WorkshopItemIllegalPath");
}
var contentTypeSelection = new GUIDropDown(new RectTransform(new Vector2(0.4f, 1.0f), content.RectTransform, Anchor.CenterRight),
elementCount: contentTypes.Length)
{
UserData = contentFile,
};
foreach (ContentType contentType in contentTypes)
{
contentTypeSelection.AddItem(contentType.ToString(), contentType);
}
contentTypeSelection.SelectItem(contentFile.Type);
contentTypeSelection.OnSelected = (GUIComponent selected, object userdata) =>
{
((ContentFile)contentTypeSelection.UserData).Type = (ContentType)userdata;
itemContentPackage.Save(itemContentPackage.Path);
return true;
};
if (!files.Contains(contentFile)) //this prevents deletion of files not contained in the mod's path (i.e. vanilla content)
{
new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), content.RectTransform), TextManager.Get("Delete"), style: "GUIButtonSmall")
{
OnClicked = (btn, userdata) =>
{
var msgBox = new GUIMessageBox(TextManager.Get("ConfirmFileDeletionHeader"),
TextManager.GetWithVariable("ConfirmFileDeletion", "[file]", contentFile.Path),
new string[] { TextManager.Get("Yes"), TextManager.Get("Cancel") })
{
UserData = "verificationprompt"
};
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
{
try
{
File.Delete(contentFile.Path);
if (contentFile.Type == ContentType.Submarine) { SubmarineInfo.RefreshSavedSub(contentFile.Path); }
}
catch (Exception e)
{
DebugConsole.ThrowError($"Failed to delete \"${contentFile.Path}\".", e);
}
//RefreshCreateItemFileList();
RefreshMyItemList();
return true;
};
msgBox.Buttons[0].OnClicked += msgBox.Close;
msgBox.Buttons[1].OnClicked = msgBox.Close;
return true;
}
};
}
content.Recalculate();
fileFrame.RectTransform.MinSize =
new Point(0, (int)(content.RectTransform.Children.Max(c => c.MinSize.Y) / content.RectTransform.RelativeSize.Y));
nameText.Text = ToolBox.LimitString(nameText.Text, nameText.Font, maxWidth: nameText.Rect.Width);
}
itemContentPackage.Save(itemContentPackage.Path);
}
private void PublishWorkshopItem()
{
if (itemContentPackage == null || itemEditor == null) { return; }
#if UNSTABLE
var msgBox = new GUIMessageBox(TextManager.Get("warning"), TextManager.Get("unstableworkshopitempublishwarning"),
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
{
var workshopPublishStatus = SteamManager.StartPublishItem(itemContentPackage, itemEditor);
if (workshopPublishStatus != null)
{
if (!(itemEditor?.HasTag("unstable") ?? false)) { itemEditor = itemEditor?.WithTag("unstable"); }
CoroutineManager.StartCoroutine(WaitForPublish(workshopPublishStatus), "WaitForPublish");
}
msgBox.Close();
return true;
};
msgBox.Buttons[1].OnClicked += msgBox.Close;
#else
itemEditor = itemEditor?.WithoutTag("unstable");
var workshopPublishStatus = SteamManager.StartPublishItem(itemContentPackage, itemEditor);
if (workshopPublishStatus == null) { return; }
CoroutineManager.StartCoroutine(WaitForPublish(workshopPublishStatus), "WaitForPublish");
#endif
}
private IEnumerable<object> WaitForPublish(SteamManager.WorkshopPublishStatus workshopPublishStatus)
{
var item = workshopPublishStatus.Item;
var coroutine = workshopPublishStatus.Coroutine;
string pleaseWaitText = TextManager.Get("WorkshopPublishPleaseWait");
var msgBox = new GUIMessageBox(
pleaseWaitText,
TextManager.GetWithVariable("WorkshopPublishInProgress", "[itemname]", item?.Title),
new string[] { TextManager.Get("Cancel") });
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
{
CoroutineManager.StopCoroutines("WaitForPublish");
createItemFrame.ClearChildren();
SelectTab(Tab.Browse);
msgBox.Close();
return true;
};
yield return CoroutineStatus.Running;
while (CoroutineManager.IsCoroutineRunning(coroutine))
{
msgBox.Header.Text = pleaseWaitText + new string('.', ((int)Timing.TotalTime % 3 + 1));
yield return CoroutineStatus.Running;
}
msgBox.Close();
if (workshopPublishStatus.Success ?? false)
{
new GUIMessageBox("", TextManager.GetWithVariable("WorkshopItemPublished", "[itemname]", item?.Title));
}
else
{
string errorMsg = workshopPublishStatus.Result.HasValue ?
TextManager.GetWithVariable("WorkshopPublishError." + workshopPublishStatus.Result?.Result.ToString(), "[savepath]", SaveUtil.SaveFolder, returnNull: true) :
null;
if (errorMsg == null)
{
new GUIMessageBox(
TextManager.Get("Error"),
TextManager.GetWithVariable("WorkshopItemPublishFailed", "[itemname]", item?.Title) +
(workshopPublishStatus?.TaskStatus != null ?
" Task ended with status " +workshopPublishStatus?.TaskStatus?.ToString() :
" Publish failed with result "+ workshopPublishStatus.Result?.Result.ToString()));
}
else
{
new GUIMessageBox(TextManager.Get("Error"), errorMsg);
}
}
createItemFrame.ClearChildren();
SelectTab(Tab.Browse);
}
#region UI management
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
graphics.Clear(Color.CornflowerBlue);
GameMain.MainMenuScreen.DrawBackground(graphics, spriteBatch);
spriteBatch.Begin(SpriteSortMode.Deferred, null, GUI.SamplerState, null, GameMain.ScissorTestEnable);
GUI.Draw(Cam, spriteBatch);
spriteBatch.End();
}
public override void AddToGUIUpdateList()
{
menu.AddToGUIUpdateList();
}
public override void Update(double deltaTime)
{
if (refreshFileList)
{
RefreshCreateItemFileList();
refreshFileList = false;
}
}
#endregion
}
}