Add support for installing content from disk.
This commit is contained in:
@@ -17,6 +17,7 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
public class ModContent : IGlobalModData
|
public class ModContent : IGlobalModData
|
||||||
{
|
{
|
||||||
|
public enum SourceType { Disc, Install }
|
||||||
public class ModPackage
|
public class ModPackage
|
||||||
{
|
{
|
||||||
public readonly string Title;
|
public readonly string Title;
|
||||||
@@ -39,6 +40,12 @@ namespace OpenRA
|
|||||||
|
|
||||||
public class ModSource
|
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 string Title;
|
||||||
public readonly Dictionary<string, string> IDFiles;
|
public readonly Dictionary<string, string> IDFiles;
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
// List Panel
|
// List Panel
|
||||||
readonly Widget listContainer;
|
readonly Widget listContainer;
|
||||||
readonly ScrollPanelWidget listPanel;
|
readonly ScrollPanelWidget listPanel;
|
||||||
|
readonly Widget listHeaderTemplate;
|
||||||
readonly LabelWidget listTemplate;
|
readonly LabelWidget listTemplate;
|
||||||
readonly LabelWidget listLabel;
|
readonly LabelWidget listLabel;
|
||||||
|
|
||||||
@@ -84,6 +85,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
listContainer.IsVisible = () => visible == Mode.List;
|
listContainer.IsVisible = () => visible == Mode.List;
|
||||||
|
|
||||||
listPanel = listContainer.Get<ScrollPanelWidget>("LIST_PANEL");
|
listPanel = listContainer.Get<ScrollPanelWidget>("LIST_PANEL");
|
||||||
|
listHeaderTemplate = listPanel.Get("LIST_HEADER_TEMPLATE");
|
||||||
listTemplate = listPanel.Get<LabelWidget>("LIST_TEMPLATE");
|
listTemplate = listPanel.Get<LabelWidget>("LIST_TEMPLATE");
|
||||||
listPanel.RemoveChildren();
|
listPanel.RemoveChildren();
|
||||||
|
|
||||||
@@ -108,9 +110,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
message = "Searching for " + kv.Value.Title;
|
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
|
var packages = content.Packages.Values
|
||||||
.Where(p => p.Sources.Contains(kv.Key) && !p.IsInstalled())
|
.Where(p => p.Sources.Contains(kv.Key) && !p.IsInstalled())
|
||||||
@@ -122,24 +123,42 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
Game.RunAfterTick(() =>
|
Game.RunAfterTick(() =>
|
||||||
{
|
{
|
||||||
ShowList(kv.Value.Title, "The following content packages will be installed:", packages);
|
ShowList(kv.Value.Title, "The following content packages will be installed:", packages);
|
||||||
ShowContinueCancel(() => InstallFromDisc(volume, kv.Value));
|
ShowContinueCancel(() => InstallFromDisc(path, kv.Value));
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var discTitles = content.Packages.Values
|
var sources = content.Packages.Values
|
||||||
.Where(p => !p.IsInstalled())
|
.Where(p => !p.IsInstalled())
|
||||||
.SelectMany(p => p.Sources)
|
.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();
|
.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(() =>
|
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);
|
ShowBackRetry(DetectContentDisks);
|
||||||
});
|
});
|
||||||
}).Start();
|
}).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
|
try
|
||||||
{
|
{
|
||||||
@@ -427,6 +471,40 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
panel.Bounds.Height = listContainer.Bounds.Height;
|
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)
|
void ShowContinueCancel(Action continueAction)
|
||||||
{
|
{
|
||||||
primaryButton.OnClick = continueAction;
|
primaryButton.OnClick = continueAction;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ Background@CONTENT_PANEL:
|
|||||||
X: (WINDOW_RIGHT - WIDTH) / 2
|
X: (WINDOW_RIGHT - WIDTH) / 2
|
||||||
Y: (WINDOW_BOTTOM - HEIGHT) / 2
|
Y: (WINDOW_BOTTOM - HEIGHT) / 2
|
||||||
Width: 500
|
Width: 500
|
||||||
Height: 268
|
Height: 290
|
||||||
Background: panel-bg
|
Background: panel-bg
|
||||||
Children:
|
Children:
|
||||||
Background@RULE:
|
Background@RULE:
|
||||||
@@ -29,7 +29,7 @@ Background@CONTENT_PANEL:
|
|||||||
X: 30
|
X: 30
|
||||||
Y: 84
|
Y: 84
|
||||||
Width: PARENT_RIGHT - 60
|
Width: PARENT_RIGHT - 60
|
||||||
Height: 115
|
Height: 137
|
||||||
TopBottomSpacing: 4
|
TopBottomSpacing: 4
|
||||||
ItemSpacing: 2
|
ItemSpacing: 2
|
||||||
BorderWidth: 2
|
BorderWidth: 2
|
||||||
@@ -89,9 +89,9 @@ Background@CONTENT_PANEL:
|
|||||||
X: 30
|
X: 30
|
||||||
Y: PARENT_BOTTOM - 52
|
Y: PARENT_BOTTOM - 52
|
||||||
Background: button-highlighted
|
Background: button-highlighted
|
||||||
Width: 110
|
Width: 200
|
||||||
Height: 32
|
Height: 32
|
||||||
Text: Detect Disc
|
Text: Detect Disc or Installation
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Button@BACK_BUTTON:
|
Button@BACK_BUTTON:
|
||||||
X: PARENT_RIGHT - 140
|
X: PARENT_RIGHT - 140
|
||||||
@@ -230,7 +230,7 @@ Background@DISC_INSTALL_PANEL:
|
|||||||
Align: Center
|
Align: Center
|
||||||
Container@LIST:
|
Container@LIST:
|
||||||
Width: PARENT_RIGHT
|
Width: PARENT_RIGHT
|
||||||
Height: 268
|
Height: 338
|
||||||
Visible: false
|
Visible: false
|
||||||
Children:
|
Children:
|
||||||
Label@LIST_MESSAGE:
|
Label@LIST_MESSAGE:
|
||||||
@@ -242,11 +242,31 @@ Background@DISC_INSTALL_PANEL:
|
|||||||
X: 30
|
X: 30
|
||||||
Y: 99
|
Y: 99
|
||||||
Width: PARENT_RIGHT - 60
|
Width: PARENT_RIGHT - 60
|
||||||
Height: 100
|
Height: 170
|
||||||
TopBottomSpacing: 4
|
TopBottomSpacing: 4
|
||||||
ItemSpacing: 2
|
ItemSpacing: 2
|
||||||
BorderWidth: 2
|
BorderWidth: 2
|
||||||
Children:
|
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:
|
Label@LIST_TEMPLATE:
|
||||||
X: 6
|
X: 6
|
||||||
Width: PARENT_RIGHT - 16
|
Width: PARENT_RIGHT - 16
|
||||||
|
|||||||
Reference in New Issue
Block a user