added in-game SHP viewer with frame slider
This commit is contained in:
@@ -18,13 +18,15 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
public static class FileSystem
|
||||
{
|
||||
static List<IFolder> mountedFolders = new List<IFolder>();
|
||||
static List<IFolder> MountedFolders = new List<IFolder>();
|
||||
|
||||
static Cache<uint, List<IFolder>> allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() );
|
||||
|
||||
public static List<string> FolderPaths = new List<string>();
|
||||
|
||||
static void MountInner(IFolder folder)
|
||||
{
|
||||
mountedFolders.Add(folder);
|
||||
MountedFolders.Add(folder);
|
||||
|
||||
foreach (var hash in folder.AllFileHashes())
|
||||
{
|
||||
@@ -78,6 +80,9 @@ namespace OpenRA.FileFormats
|
||||
if (name.StartsWith("^"))
|
||||
name = Platform.SupportDir+name.Substring(1);
|
||||
|
||||
if (Directory.Exists(name))
|
||||
FolderPaths.Add(name);
|
||||
|
||||
var a = (Action)(() => FileSystem.MountInner(OpenPackage(name)));
|
||||
|
||||
if (optional)
|
||||
@@ -89,18 +94,19 @@ namespace OpenRA.FileFormats
|
||||
|
||||
public static void UnmountAll()
|
||||
{
|
||||
mountedFolders.Clear();
|
||||
MountedFolders.Clear();
|
||||
FolderPaths.Clear();
|
||||
allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() );
|
||||
}
|
||||
|
||||
public static bool Unmount(IFolder mount)
|
||||
{
|
||||
return (mountedFolders.RemoveAll(f => f == mount) > 0);
|
||||
return (MountedFolders.RemoveAll(f => f == mount) > 0);
|
||||
}
|
||||
|
||||
public static void Mount(IFolder mount)
|
||||
{
|
||||
if (!mountedFolders.Contains(mount)) mountedFolders.Add(mount);
|
||||
if (!MountedFolders.Contains(mount)) MountedFolders.Add(mount);
|
||||
}
|
||||
|
||||
public static void LoadFromManifest(Manifest manifest)
|
||||
@@ -139,7 +145,7 @@ namespace OpenRA.FileFormats
|
||||
|
||||
foreach (var ext in exts)
|
||||
{
|
||||
var folder = mountedFolders
|
||||
var folder = MountedFolders
|
||||
.Where(x => x.Exists(filename + ext))
|
||||
.OrderByDescending(x => x.Priority)
|
||||
.FirstOrDefault();
|
||||
@@ -151,7 +157,7 @@ namespace OpenRA.FileFormats
|
||||
throw new FileNotFoundException("File not found: {0}".F(filename), filename);
|
||||
}
|
||||
|
||||
public static bool Exists(string filename) { return mountedFolders.Any(f => f.Exists(filename)); }
|
||||
public static bool Exists(string filename) { return MountedFolders.Any(f => f.Exists(filename)); }
|
||||
|
||||
static Dictionary<string, Assembly> assemblyCache = new Dictionary<string, Assembly>();
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace OpenRA.Widgets
|
||||
public string Image = "";
|
||||
public int Frame = 0;
|
||||
public string Palette = "chrome";
|
||||
public bool LoopAnimation = false;
|
||||
|
||||
public Func<string> GetImage;
|
||||
public Func<int> GetFrame;
|
||||
@@ -32,6 +33,7 @@ namespace OpenRA.Widgets
|
||||
GetImage = () => { return Image; };
|
||||
GetFrame = () => { return Frame; };
|
||||
GetPalette = () => { return Palette; };
|
||||
|
||||
this.worldRenderer = worldRenderer;
|
||||
}
|
||||
|
||||
@@ -41,9 +43,12 @@ namespace OpenRA.Widgets
|
||||
Image = other.Image;
|
||||
Frame = other.Frame;
|
||||
Palette = other.Palette;
|
||||
LoopAnimation = other.LoopAnimation;
|
||||
|
||||
GetImage = other.GetImage;
|
||||
GetFrame = other.GetFrame;
|
||||
GetPalette = other.GetPalette;
|
||||
|
||||
worldRenderer = other.worldRenderer;
|
||||
}
|
||||
|
||||
@@ -68,5 +73,32 @@ namespace OpenRA.Widgets
|
||||
|
||||
Game.Renderer.SpriteRenderer.DrawSprite(sprite, RenderOrigin, worldRenderer, palette);
|
||||
}
|
||||
|
||||
public int FrameCount
|
||||
{
|
||||
get { return Game.modData.SpriteLoader.LoadAllSprites(Image).Length-1; }
|
||||
}
|
||||
|
||||
public void RenderNextFrame()
|
||||
{
|
||||
if (Frame < FrameCount)
|
||||
Frame++;
|
||||
else
|
||||
Frame = 0;
|
||||
}
|
||||
|
||||
public void RenderPreviousFrame()
|
||||
{
|
||||
if (Frame > 0)
|
||||
Frame--;
|
||||
else
|
||||
Frame = FrameCount;
|
||||
}
|
||||
|
||||
public override void Tick()
|
||||
{
|
||||
if (LoopAnimation)
|
||||
RenderNextFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,15 @@ namespace OpenRA.Widgets
|
||||
public float MinimumValue = 0;
|
||||
public float MaximumValue = 1;
|
||||
public float Value = 0;
|
||||
public Func<float> GetValue;
|
||||
|
||||
protected bool isMoving = false;
|
||||
|
||||
public SliderWidget() : base() {}
|
||||
public SliderWidget()
|
||||
: base()
|
||||
{
|
||||
GetValue = () => Value;
|
||||
}
|
||||
|
||||
public SliderWidget(SliderWidget other)
|
||||
: base(other)
|
||||
@@ -38,6 +43,7 @@ namespace OpenRA.Widgets
|
||||
MaximumValue = other.MaximumValue;
|
||||
Value = other.Value;
|
||||
TrackHeight = other.TrackHeight;
|
||||
GetValue = other.GetValue;
|
||||
}
|
||||
|
||||
void UpdateValue(float newValue)
|
||||
@@ -99,6 +105,8 @@ namespace OpenRA.Widgets
|
||||
if (!IsVisible())
|
||||
return;
|
||||
|
||||
Value = GetValue();
|
||||
|
||||
var tr = ThumbRect;
|
||||
var rb = RenderBounds;
|
||||
var trackWidth = rb.Width;
|
||||
|
||||
@@ -436,6 +436,7 @@
|
||||
<Compile Include="Widgets\ColorMixerWidget.cs" />
|
||||
<Compile Include="Widgets\HueSliderWidget.cs" />
|
||||
<Compile Include="Render\WithTurret.cs" />
|
||||
<Compile Include="Widgets\Logic\AssetBrowserLogic.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
||||
|
||||
124
OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs
Normal file
124
OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
{
|
||||
public class AssetBrowserLogic
|
||||
{
|
||||
Widget panel;
|
||||
|
||||
ShpImageWidget spriteImage;
|
||||
TextFieldWidget filenameInput;
|
||||
SliderWidget frameSlider;
|
||||
ButtonWidget playButton;
|
||||
ButtonWidget pauseButton;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
public AssetBrowserLogic(Widget widget, Action onExit, World world)
|
||||
{
|
||||
panel = widget;
|
||||
|
||||
spriteImage = panel.Get<ShpImageWidget>("SPRITE");
|
||||
|
||||
filenameInput = panel.Get<TextFieldWidget>("FILENAME_INPUT");
|
||||
filenameInput.Text = spriteImage.Image;
|
||||
filenameInput.OnEnterKey = () => LoadAsset(filenameInput.Text);
|
||||
|
||||
var assetList = panel.Get<ScrollPanelWidget>("ASSET_LIST");
|
||||
var template = panel.Get<ScrollItemWidget>("ASSET_TEMPLATE");
|
||||
|
||||
assetList.RemoveChildren();
|
||||
foreach (var folder in FileSystem.FolderPaths)
|
||||
{
|
||||
if (Directory.Exists(folder))
|
||||
{
|
||||
var shps = Directory.GetFiles(folder, "*.shp");
|
||||
foreach (var shp in shps)
|
||||
AddAsset(assetList, shp, template);
|
||||
}
|
||||
}
|
||||
|
||||
frameSlider = panel.Get<SliderWidget>("FRAME_SLIDER");
|
||||
frameSlider.MaximumValue = (float)spriteImage.FrameCount;
|
||||
frameSlider.Ticks = spriteImage.FrameCount+1;
|
||||
frameSlider.OnChange += x => { spriteImage.Frame = (int)Math.Round(x); };
|
||||
frameSlider.GetValue = () => spriteImage.Frame;
|
||||
|
||||
panel.Get<LabelWidget>("FRAME_COUNT").GetText = () => spriteImage.Frame.ToString();
|
||||
|
||||
playButton = panel.Get<ButtonWidget>("BUTTON_PLAY");
|
||||
playButton.OnClick = () =>
|
||||
{
|
||||
spriteImage.LoopAnimation = true;
|
||||
playButton.Visible = false;
|
||||
pauseButton.Visible = true;
|
||||
};
|
||||
pauseButton = panel.Get<ButtonWidget>("BUTTON_PAUSE");
|
||||
pauseButton.OnClick = () =>
|
||||
{
|
||||
spriteImage.LoopAnimation = false;
|
||||
playButton.Visible = true;
|
||||
pauseButton.Visible = false;
|
||||
};
|
||||
|
||||
panel.Get<ButtonWidget>("BUTTON_STOP").OnClick = () =>
|
||||
{
|
||||
spriteImage.LoopAnimation = false;
|
||||
frameSlider.Value = 0;
|
||||
spriteImage.Frame = 0;
|
||||
playButton.Visible = true;
|
||||
pauseButton.Visible = false;
|
||||
};
|
||||
|
||||
panel.Get<ButtonWidget>("BUTTON_NEXT").OnClick = () => { spriteImage.RenderNextFrame(); };
|
||||
panel.Get<ButtonWidget>("BUTTON_PREV").OnClick = () => { spriteImage.RenderPreviousFrame(); };
|
||||
|
||||
panel.Get<ButtonWidget>("LOAD_BUTTON").OnClick = () =>
|
||||
{
|
||||
LoadAsset(filenameInput.Text);
|
||||
};
|
||||
|
||||
panel.Get<ButtonWidget>("CLOSE_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };
|
||||
}
|
||||
|
||||
void AddAsset(ScrollPanelWidget list, string filepath, ScrollItemWidget template)
|
||||
{
|
||||
var sprite = Path.GetFileNameWithoutExtension(filepath);
|
||||
|
||||
var item = ScrollItemWidget.Setup(template,
|
||||
() => spriteImage != null && spriteImage.Image == sprite,
|
||||
() => LoadAsset(sprite));
|
||||
item.Get<LabelWidget>("TITLE").GetText = () => sprite;
|
||||
|
||||
list.AddChild(item);
|
||||
}
|
||||
|
||||
bool LoadAsset(string filename)
|
||||
{
|
||||
if (filename == null)
|
||||
return false;
|
||||
|
||||
filenameInput.Text = filename;
|
||||
spriteImage.Frame = 0;
|
||||
spriteImage.Image = filename;
|
||||
frameSlider.MaximumValue = (float)spriteImage.FrameCount;
|
||||
frameSlider.Ticks = spriteImage.FrameCount+1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
@@ -14,7 +14,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
{
|
||||
public class MainMenuButtonsLogic
|
||||
{
|
||||
|
||||
enum MenuType { Main, None }
|
||||
MenuType Menu = MenuType.Main;
|
||||
|
||||
@@ -73,6 +72,15 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
});
|
||||
};
|
||||
|
||||
widget.Get<ButtonWidget>("MAINMENU_BUTTON_ASSET_BROWSER").OnClick = () =>
|
||||
{
|
||||
Menu = MenuType.None;
|
||||
Game.OpenWindow("ASSETBROWSER_BG", new WidgetArgs()
|
||||
{
|
||||
{ "onExit", () => Menu = MenuType.Main }
|
||||
});
|
||||
};
|
||||
|
||||
widget.Get<ButtonWidget>("MAINMENU_BUTTON_QUIT").OnClick = () => Game.Exit();
|
||||
}
|
||||
|
||||
|
||||
196
mods/ra/chrome/assetbrowser.yaml
Normal file
196
mods/ra/chrome/assetbrowser.yaml
Normal file
@@ -0,0 +1,196 @@
|
||||
Background@ASSETBROWSER_BG:
|
||||
Logic:AssetBrowserLogic
|
||||
X:(WINDOW_RIGHT - WIDTH)/2
|
||||
Y:(WINDOW_BOTTOM - HEIGHT)/2
|
||||
Width:700
|
||||
Height:410
|
||||
Children:
|
||||
Label@ASSETBROWSER_TITLE:
|
||||
X:0
|
||||
Y:20
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Text:Game Asset Viewer & Converter
|
||||
Align:Center
|
||||
Font:Bold
|
||||
DropDownButton@SOURCE_SELECTOR:
|
||||
X:40
|
||||
Y:45
|
||||
Width:160
|
||||
Height:25
|
||||
Font:Bold
|
||||
Text:Folders
|
||||
ScrollPanel@ASSET_LIST:
|
||||
X:40
|
||||
Y:80
|
||||
Width:160
|
||||
Height:190
|
||||
Children:
|
||||
ScrollItem@ASSET_TEMPLATE:
|
||||
Width:PARENT_RIGHT-27
|
||||
Height:25
|
||||
X:2
|
||||
Y:0
|
||||
Visible:false
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X:10
|
||||
Width:PARENT_RIGHT-20
|
||||
Height:25
|
||||
TextField@FILENAME_INPUT:
|
||||
X:40
|
||||
Y:280
|
||||
Width:140
|
||||
Height:25
|
||||
Button@LOAD_BUTTON:
|
||||
X:40
|
||||
Y:310
|
||||
Width:140
|
||||
Height:25
|
||||
Text:Load
|
||||
Font:Bold
|
||||
Key:return
|
||||
Label@PREVIEW_TITLE:
|
||||
X:320
|
||||
Y:45
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Text:Preview
|
||||
Background@SPRITE_BG:
|
||||
X:220
|
||||
Y:80
|
||||
Width:250
|
||||
Height:250
|
||||
Background:dialog3
|
||||
Children:
|
||||
ShpImage@SPRITE:
|
||||
X:80
|
||||
Y:80
|
||||
Width:246
|
||||
Height:246
|
||||
Image:fact
|
||||
Palette:player
|
||||
Label@ACTIONS_TITLE:
|
||||
X:PARENT_RIGHT - 150
|
||||
Y:45
|
||||
Width:PARENT_RIGHT
|
||||
Height:25
|
||||
Text:Actions
|
||||
Button@REMAP_BUTTON:
|
||||
X:PARENT_RIGHT - 200
|
||||
Y:PARENT_BOTTOM - 305
|
||||
Width:160
|
||||
Height:25
|
||||
Text:Change Palette
|
||||
Font:Bold
|
||||
Button@IMPORT_BUTTON:
|
||||
X:PARENT_RIGHT - 200
|
||||
Y:PARENT_BOTTOM - 270
|
||||
Width:160
|
||||
Height:25
|
||||
Text:Import from PNG
|
||||
Font:Bold
|
||||
Button@EXTRACT_BUTTON:
|
||||
X:PARENT_RIGHT - 200
|
||||
Y:PARENT_BOTTOM - 235
|
||||
Width:160
|
||||
Height:25
|
||||
Text:Extract to Folder
|
||||
Font:Bold
|
||||
Button@EXPORT_BUTTON:
|
||||
X:PARENT_RIGHT - 200
|
||||
Y:PARENT_BOTTOM - 200
|
||||
Width:160
|
||||
Height:25
|
||||
Text:Export as PNG
|
||||
Font:Bold
|
||||
Button@CLOSE_BUTTON:
|
||||
X:PARENT_RIGHT - 200
|
||||
Y:PARENT_BOTTOM - 115
|
||||
Width:160
|
||||
Height:25
|
||||
Text:Close
|
||||
Font:Bold
|
||||
Key:escape
|
||||
Container@FRAME_SELECTOR:
|
||||
X:45
|
||||
Y:360
|
||||
Children:
|
||||
Button@BUTTON_PREV:
|
||||
X:0
|
||||
Y:0
|
||||
Width:25
|
||||
Height:25
|
||||
Children:
|
||||
Image@IMAGE_PREV:
|
||||
X:0
|
||||
Y:0
|
||||
Width:25
|
||||
Height:25
|
||||
ImageCollection:music
|
||||
ImageName:prev
|
||||
Button@BUTTON_PLAY:
|
||||
X:35
|
||||
Y:0
|
||||
Width:25
|
||||
Height:25
|
||||
Children:
|
||||
Image@IMAGE_PLAY:
|
||||
X:0
|
||||
Y:0
|
||||
Width:25
|
||||
Height:25
|
||||
ImageCollection:music
|
||||
ImageName:play
|
||||
Button@BUTTON_PAUSE:
|
||||
Visible: no
|
||||
X:35
|
||||
Y:0
|
||||
Width:25
|
||||
Height:25
|
||||
Children:
|
||||
Image@IMAGE_PAUSE:
|
||||
X:0
|
||||
Y:0
|
||||
Width:25
|
||||
Height:25
|
||||
ImageCollection:music
|
||||
ImageName:pause
|
||||
Button@BUTTON_STOP:
|
||||
X:70
|
||||
Y:0
|
||||
Width:25
|
||||
Height:25
|
||||
Children:
|
||||
Image@IMAGE_STOP:
|
||||
X:0
|
||||
Y:0
|
||||
Width:25
|
||||
Height:25
|
||||
ImageCollection:music
|
||||
ImageName:stop
|
||||
Button@BUTTON_NEXT:
|
||||
X:105
|
||||
Y:0
|
||||
Width:25
|
||||
Height:25
|
||||
Children:
|
||||
Image@IMAGE_NEXT:
|
||||
X:0
|
||||
Y:0
|
||||
Width:25
|
||||
Height:25
|
||||
ImageCollection:music
|
||||
ImageName:next
|
||||
Slider@FRAME_SLIDER:
|
||||
X:175
|
||||
Y:0
|
||||
Width:410
|
||||
Height:20
|
||||
MinimumValue: 0
|
||||
Label@FRAME_COUNT:
|
||||
X:610
|
||||
Y:0
|
||||
Width:25
|
||||
Height:25
|
||||
Font:Bold
|
||||
@@ -23,7 +23,7 @@ Container@MAINMENU:
|
||||
X:(WINDOW_RIGHT - WIDTH)/8
|
||||
Y:(WINDOW_BOTTOM - HEIGHT)/2
|
||||
Width:250
|
||||
Height:505
|
||||
Height:555
|
||||
Logic:MainMenuButtonsLogic
|
||||
Children:
|
||||
Label@MAINMENU_LABEL_TITLE:
|
||||
@@ -83,11 +83,18 @@ Container@MAINMENU:
|
||||
Height:35
|
||||
Text:Replay Viewer
|
||||
Font:Bold
|
||||
Button@MAINMENU_BUTTON_QUIT:
|
||||
Button@MAINMENU_BUTTON_ASSET_BROWSER:
|
||||
X:45
|
||||
Y:430
|
||||
Width:160
|
||||
Height:35
|
||||
Text:Asset Browser
|
||||
Font:Bold
|
||||
Button@MAINMENU_BUTTON_QUIT:
|
||||
X:45
|
||||
Y:480
|
||||
Width:160
|
||||
Height:35
|
||||
Text:Quit
|
||||
Font:Bold
|
||||
Background@PERF_BG:
|
||||
|
||||
@@ -73,6 +73,7 @@ ChromeLayout:
|
||||
mods/ra/chrome/cheats.yaml
|
||||
mods/ra/chrome/musicplayer.yaml
|
||||
mods/ra/chrome/tooltips.yaml
|
||||
mods/ra/chrome/assetbrowser.yaml
|
||||
|
||||
Weapons:
|
||||
mods/ra/weapons.yaml
|
||||
|
||||
Reference in New Issue
Block a user