Add support for installing content from disk.
This commit is contained in:
@@ -17,6 +17,7 @@ namespace OpenRA
|
||||
{
|
||||
public class ModContent : IGlobalModData
|
||||
{
|
||||
public enum SourceType { Disc, Install }
|
||||
public class ModPackage
|
||||
{
|
||||
public readonly string Title;
|
||||
@@ -39,6 +40,12 @@ namespace OpenRA
|
||||
|
||||
public class ModSource
|
||||
{
|
||||
public readonly SourceType Type = SourceType.Disc;
|
||||
|
||||
// Used to find installation locations for SourceType.Install
|
||||
public readonly string RegistryKey;
|
||||
public readonly string RegistryValue;
|
||||
|
||||
public readonly string Title;
|
||||
public readonly Dictionary<string, string> IDFiles;
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
// List Panel
|
||||
readonly Widget listContainer;
|
||||
readonly ScrollPanelWidget listPanel;
|
||||
readonly Widget listHeaderTemplate;
|
||||
readonly LabelWidget listTemplate;
|
||||
readonly LabelWidget listLabel;
|
||||
|
||||
@@ -84,6 +85,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
listContainer.IsVisible = () => visible == Mode.List;
|
||||
|
||||
listPanel = listContainer.Get<ScrollPanelWidget>("LIST_PANEL");
|
||||
listHeaderTemplate = listPanel.Get("LIST_HEADER_TEMPLATE");
|
||||
listTemplate = listPanel.Get<LabelWidget>("LIST_TEMPLATE");
|
||||
listPanel.RemoveChildren();
|
||||
|
||||
@@ -108,38 +110,55 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
message = "Searching for " + kv.Value.Title;
|
||||
|
||||
foreach (var volume in volumes)
|
||||
var path = FindSourcePath(kv.Value, volumes);
|
||||
if (path != null)
|
||||
{
|
||||
if (PathIsDiscMount(volume, kv.Value))
|
||||
var packages = content.Packages.Values
|
||||
.Where(p => p.Sources.Contains(kv.Key) && !p.IsInstalled())
|
||||
.Select(p => p.Title);
|
||||
|
||||
// Ignore disc if content is already installed
|
||||
if (packages.Any())
|
||||
{
|
||||
var packages = content.Packages.Values
|
||||
.Where(p => p.Sources.Contains(kv.Key) && !p.IsInstalled())
|
||||
.Select(p => p.Title);
|
||||
|
||||
// Ignore disc if content is already installed
|
||||
if (packages.Any())
|
||||
Game.RunAfterTick(() =>
|
||||
{
|
||||
Game.RunAfterTick(() =>
|
||||
{
|
||||
ShowList(kv.Value.Title, "The following content packages will be installed:", packages);
|
||||
ShowContinueCancel(() => InstallFromDisc(volume, kv.Value));
|
||||
});
|
||||
ShowList(kv.Value.Title, "The following content packages will be installed:", packages);
|
||||
ShowContinueCancel(() => InstallFromDisc(path, kv.Value));
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var discTitles = content.Packages.Values
|
||||
var sources = content.Packages.Values
|
||||
.Where(p => !p.IsInstalled())
|
||||
.SelectMany(p => p.Sources)
|
||||
.Select(d => content.Sources[d].Title)
|
||||
.Select(d => content.Sources[d]);
|
||||
|
||||
var discs = sources
|
||||
.Where(s => s.Type == ModContent.SourceType.Disc)
|
||||
.Select(s => s.Title)
|
||||
.Distinct();
|
||||
|
||||
var options = new Dictionary<string, IEnumerable<string>>()
|
||||
{
|
||||
{ "Game Discs", discs },
|
||||
};
|
||||
|
||||
if (Platform.CurrentPlatform == PlatformType.Windows)
|
||||
{
|
||||
var installations = sources
|
||||
.Where(s => s.Type == ModContent.SourceType.Install)
|
||||
.Select(s => s.Title)
|
||||
.Distinct();
|
||||
|
||||
options.Add("Digital Installs", installations);
|
||||
}
|
||||
|
||||
Game.RunAfterTick(() =>
|
||||
{
|
||||
ShowList("Disc Content Not Found", "Please insert or mount one of the following discs and try again", discTitles);
|
||||
ShowList("Game Content Not Found", "Please insert or install one of the following content sources:", options);
|
||||
ShowBackRetry(DetectContentDisks);
|
||||
});
|
||||
}).Start();
|
||||
@@ -351,7 +370,32 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
}
|
||||
}
|
||||
|
||||
bool PathIsDiscMount(string path, ModContent.ModSource source)
|
||||
string FindSourcePath(ModContent.ModSource source, IEnumerable<string> volumes)
|
||||
{
|
||||
if (source.Type == ModContent.SourceType.Install)
|
||||
{
|
||||
if (source.RegistryKey == null)
|
||||
return null;
|
||||
|
||||
if (Platform.CurrentPlatform != PlatformType.Windows)
|
||||
return null;
|
||||
|
||||
var path = Microsoft.Win32.Registry.GetValue(source.RegistryKey, source.RegistryValue, null) as string;
|
||||
if (path == null)
|
||||
return null;
|
||||
|
||||
return IsValidSourcePath(path, source) ? path : null;
|
||||
}
|
||||
|
||||
if (source.Type == ModContent.SourceType.Disc)
|
||||
foreach (var volume in volumes)
|
||||
if (IsValidSourcePath(volume, source))
|
||||
return volume;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
bool IsValidSourcePath(string path, ModContent.ModSource source)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -427,6 +471,40 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
panel.Bounds.Height = listContainer.Bounds.Height;
|
||||
}
|
||||
|
||||
void ShowList(string title, string message, Dictionary<string, IEnumerable<string>> groups)
|
||||
{
|
||||
visible = Mode.List;
|
||||
titleLabel.Text = title;
|
||||
listLabel.Text = message;
|
||||
|
||||
listPanel.RemoveChildren();
|
||||
|
||||
foreach (var kv in groups)
|
||||
{
|
||||
if (kv.Value.Any())
|
||||
{
|
||||
var groupTitle = kv.Key;
|
||||
var headerWidget = listHeaderTemplate.Clone();
|
||||
var headerTitleWidget = headerWidget.Get<LabelWidget>("LABEL");
|
||||
headerTitleWidget.GetText = () => groupTitle;
|
||||
listPanel.AddChild(headerWidget);
|
||||
}
|
||||
|
||||
foreach (var i in kv.Value)
|
||||
{
|
||||
var item = i;
|
||||
var labelWidget = (LabelWidget)listTemplate.Clone();
|
||||
labelWidget.GetText = () => item;
|
||||
listPanel.AddChild(labelWidget);
|
||||
}
|
||||
}
|
||||
|
||||
primaryButton.Bounds.Y += listContainer.Bounds.Height - panel.Bounds.Height;
|
||||
secondaryButton.Bounds.Y += listContainer.Bounds.Height - panel.Bounds.Height;
|
||||
panel.Bounds.Y -= (listContainer.Bounds.Height - panel.Bounds.Height) / 2;
|
||||
panel.Bounds.Height = listContainer.Bounds.Height;
|
||||
}
|
||||
|
||||
void ShowContinueCancel(Action continueAction)
|
||||
{
|
||||
primaryButton.OnClick = continueAction;
|
||||
|
||||
@@ -3,7 +3,7 @@ Background@CONTENT_PANEL:
|
||||
X: (WINDOW_RIGHT - WIDTH) / 2
|
||||
Y: (WINDOW_BOTTOM - HEIGHT) / 2
|
||||
Width: 500
|
||||
Height: 268
|
||||
Height: 290
|
||||
Background: panel-bg
|
||||
Children:
|
||||
Background@RULE:
|
||||
@@ -29,7 +29,7 @@ Background@CONTENT_PANEL:
|
||||
X: 30
|
||||
Y: 84
|
||||
Width: PARENT_RIGHT - 60
|
||||
Height: 115
|
||||
Height: 137
|
||||
TopBottomSpacing: 4
|
||||
ItemSpacing: 2
|
||||
BorderWidth: 2
|
||||
@@ -89,9 +89,9 @@ Background@CONTENT_PANEL:
|
||||
X: 30
|
||||
Y: PARENT_BOTTOM - 52
|
||||
Background: button-highlighted
|
||||
Width: 110
|
||||
Width: 200
|
||||
Height: 32
|
||||
Text: Detect Disc
|
||||
Text: Detect Disc or Installation
|
||||
Font: Bold
|
||||
Button@BACK_BUTTON:
|
||||
X: PARENT_RIGHT - 140
|
||||
@@ -230,7 +230,7 @@ Background@DISC_INSTALL_PANEL:
|
||||
Align: Center
|
||||
Container@LIST:
|
||||
Width: PARENT_RIGHT
|
||||
Height: 268
|
||||
Height: 338
|
||||
Visible: false
|
||||
Children:
|
||||
Label@LIST_MESSAGE:
|
||||
@@ -242,11 +242,31 @@ Background@DISC_INSTALL_PANEL:
|
||||
X: 30
|
||||
Y: 99
|
||||
Width: PARENT_RIGHT - 60
|
||||
Height: 100
|
||||
Height: 170
|
||||
TopBottomSpacing: 4
|
||||
ItemSpacing: 2
|
||||
BorderWidth: 2
|
||||
Children:
|
||||
Container@LIST_HEADER_TEMPLATE:
|
||||
X: 6
|
||||
Width: PARENT_RIGHT - 12 - 24
|
||||
Height: 14
|
||||
Children:
|
||||
Background@TOP_RULE:
|
||||
Width: PARENT_RIGHT
|
||||
Height: 1
|
||||
Background: panel-rule
|
||||
Label@LABEL:
|
||||
Y: 3
|
||||
Width: PARENT_RIGHT
|
||||
Height: 10
|
||||
Font: TinyBold
|
||||
Align: Center
|
||||
Background@BOTTOM_RULE:
|
||||
Y: 16
|
||||
Width: PARENT_RIGHT
|
||||
Height: 1
|
||||
Background: panel-rule
|
||||
Label@LIST_TEMPLATE:
|
||||
X: 6
|
||||
Width: PARENT_RIGHT - 16
|
||||
|
||||
Reference in New Issue
Block a user