Add .vxl support to the asset browser.
This commit is contained in:
committed by
Paul Chote
parent
9d181e88d2
commit
fb20479379
@@ -45,6 +45,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
public interface IModelCache : IDisposable
|
||||
{
|
||||
IModel GetModel(string model);
|
||||
IModel GetModelSequence(string model, string sequence);
|
||||
bool HasModelSequence(string model, string sequence);
|
||||
IVertexBuffer<Vertex> VertexBuffer { get; }
|
||||
@@ -66,6 +67,11 @@ namespace OpenRA.Graphics
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
public IModel GetModel(string model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IModel GetModelSequence(string model, string sequence)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -86,6 +86,11 @@ namespace OpenRA.Mods.Cnc.Graphics
|
||||
return loader.Load(vxl, hva);
|
||||
}
|
||||
|
||||
public IModel GetModel(string model)
|
||||
{
|
||||
return loader.Load(model, model);
|
||||
}
|
||||
|
||||
public IModel GetModelSequence(string model, string sequence)
|
||||
{
|
||||
try { return models[model][sequence]; }
|
||||
|
||||
@@ -43,10 +43,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
string currentFilename;
|
||||
IReadOnlyPackage currentPackage;
|
||||
Sprite[] currentSprites;
|
||||
IModel currentVoxel;
|
||||
VqaPlayerWidget player = null;
|
||||
bool isVideoLoaded = false;
|
||||
bool isLoadError = false;
|
||||
int currentFrame;
|
||||
WRot modelOrientation;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
public AssetBrowserLogic(Widget widget, Action onExit, ModData modData, World world, Dictionary<string, MiniYaml> logicArgs)
|
||||
@@ -79,13 +81,24 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
spriteWidget.GetSprite = () => currentSprites != null ? currentSprites[currentFrame] : null;
|
||||
currentPalette = spriteWidget.Palette;
|
||||
spriteWidget.GetPalette = () => currentPalette;
|
||||
spriteWidget.IsVisible = () => !isVideoLoaded && !isLoadError;
|
||||
spriteWidget.IsVisible = () => !isVideoLoaded && !isLoadError && currentSprites != null;
|
||||
}
|
||||
|
||||
var playerWidget = panel.GetOrNull<VqaPlayerWidget>("PLAYER");
|
||||
if (playerWidget != null)
|
||||
playerWidget.IsVisible = () => isVideoLoaded && !isLoadError;
|
||||
|
||||
var modelWidget = panel.GetOrNull<ModelWidget>("VOXEL");
|
||||
if (modelWidget != null)
|
||||
{
|
||||
modelWidget.GetVoxel = () => currentVoxel;
|
||||
currentPalette = modelWidget.Palette;
|
||||
modelWidget.GetPalette = () => currentPalette;
|
||||
modelWidget.GetPlayerPalette = () => currentPalette;
|
||||
modelWidget.GetRotation = () => modelOrientation;
|
||||
modelWidget.IsVisible = () => !isVideoLoaded && !isLoadError && currentVoxel != null;
|
||||
}
|
||||
|
||||
var errorLabelWidget = panel.GetOrNull("ERROR");
|
||||
if (errorLabelWidget != null)
|
||||
errorLabelWidget.IsVisible = () => isLoadError;
|
||||
@@ -210,6 +223,46 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
prevButton.IsVisible = () => !isVideoLoaded;
|
||||
}
|
||||
|
||||
var voxelContainer = panel.GetOrNull("VOXEL_SELECTOR");
|
||||
if (voxelContainer != null)
|
||||
voxelContainer.IsVisible = () => currentVoxel != null;
|
||||
|
||||
var rollSlider = panel.GetOrNull<SliderWidget>("ROLL_SLIDER");
|
||||
if (rollSlider != null)
|
||||
{
|
||||
rollSlider.OnChange += x =>
|
||||
{
|
||||
var roll = (int)x;
|
||||
modelOrientation = modelOrientation.WithRoll(new WAngle(roll));
|
||||
};
|
||||
|
||||
rollSlider.GetValue = () => modelOrientation.Roll.Angle;
|
||||
}
|
||||
|
||||
var pitchSlider = panel.GetOrNull<SliderWidget>("PITCH_SLIDER");
|
||||
if (pitchSlider != null)
|
||||
{
|
||||
pitchSlider.OnChange += x =>
|
||||
{
|
||||
var pitch = (int)x;
|
||||
modelOrientation = modelOrientation.WithPitch(new WAngle(pitch));
|
||||
};
|
||||
|
||||
pitchSlider.GetValue = () => modelOrientation.Pitch.Angle;
|
||||
}
|
||||
|
||||
var yawSlider = panel.GetOrNull<SliderWidget>("YAW_SLIDER");
|
||||
if (yawSlider != null)
|
||||
{
|
||||
yawSlider.OnChange += x =>
|
||||
{
|
||||
var yaw = (int)x;
|
||||
modelOrientation = modelOrientation.WithYaw(new WAngle(yaw));
|
||||
};
|
||||
|
||||
yawSlider.GetValue = () => modelOrientation.Yaw.Angle;
|
||||
}
|
||||
|
||||
var assetBrowserModData = modData.Manifest.Get<AssetBrowser>();
|
||||
allowedExtensions = assetBrowserModData.SupportedExtensions;
|
||||
|
||||
@@ -342,12 +395,24 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
return true;
|
||||
}
|
||||
|
||||
currentSprites = world.Map.Rules.Sequences.SpriteCache[prefix + filename];
|
||||
currentFrame = 0;
|
||||
if (frameSlider != null)
|
||||
if (Path.GetExtension(filename.ToLowerInvariant()) == ".vxl")
|
||||
{
|
||||
frameSlider.MaximumValue = (float)currentSprites.Length - 1;
|
||||
frameSlider.Ticks = currentSprites.Length;
|
||||
var voxelName = Path.GetFileNameWithoutExtension(filename);
|
||||
currentVoxel = world.ModelCache.GetModel(voxelName);
|
||||
currentSprites = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentSprites = world.Map.Rules.Sequences.SpriteCache[prefix + filename];
|
||||
currentFrame = 0;
|
||||
|
||||
if (frameSlider != null)
|
||||
{
|
||||
frameSlider.MaximumValue = (float)currentSprites.Length - 1;
|
||||
frameSlider.Ticks = currentSprites.Length;
|
||||
}
|
||||
|
||||
currentVoxel = null;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
217
OpenRA.Mods.Common/Widgets/ModelWidget.cs
Normal file
217
OpenRA.Mods.Common/Widgets/ModelWidget.cs
Normal file
@@ -0,0 +1,217 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 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, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.Common.Widgets
|
||||
{
|
||||
public class ModelWidget : Widget
|
||||
{
|
||||
public string Palette = "terrain";
|
||||
public string PlayerPalette = "player";
|
||||
public string NormalsPalette = "normals";
|
||||
public string ShadowPalette = "shadow";
|
||||
public float Scale = 12f;
|
||||
public int LightPitch = 142;
|
||||
public int LightYaw = 682;
|
||||
public float[] LightAmbientColor = new float[] { 0.6f, 0.6f, 0.6f };
|
||||
public float[] LightDiffuseColor = new float[] { 0.4f, 0.4f, 0.4f };
|
||||
public WRot Rotation = WRot.None;
|
||||
public WAngle CameraAngle = WAngle.FromDegrees(40);
|
||||
|
||||
public Func<string> GetPalette;
|
||||
public Func<string> GetPlayerPalette;
|
||||
public Func<string> GetNormalsPalette;
|
||||
public Func<string> GetShadowPalette;
|
||||
public Func<float[]> GetLightAmbientColor;
|
||||
public Func<float[]> GetLightDiffuseColor;
|
||||
public Func<float> GetScale;
|
||||
public Func<int> GetLightPitch;
|
||||
public Func<int> GetLightYaw;
|
||||
public Func<IModel> GetVoxel;
|
||||
public Func<WRot> GetRotation;
|
||||
public Func<WAngle> GetCameraAngle;
|
||||
public int2 IdealPreviewSize { get; private set; }
|
||||
|
||||
protected readonly WorldRenderer WorldRenderer;
|
||||
|
||||
IFinalizedRenderable renderable;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
public ModelWidget(WorldRenderer worldRenderer)
|
||||
{
|
||||
GetPalette = () => Palette;
|
||||
GetPlayerPalette = () => PlayerPalette;
|
||||
GetNormalsPalette = () => NormalsPalette;
|
||||
GetShadowPalette = () => ShadowPalette;
|
||||
GetLightAmbientColor = () => LightAmbientColor;
|
||||
GetLightDiffuseColor = () => LightDiffuseColor;
|
||||
GetScale = () => Scale;
|
||||
GetRotation = () => Rotation;
|
||||
GetLightPitch = () => LightPitch;
|
||||
GetLightYaw = () => LightYaw;
|
||||
GetCameraAngle = () => CameraAngle;
|
||||
WorldRenderer = worldRenderer;
|
||||
}
|
||||
|
||||
protected ModelWidget(ModelWidget other)
|
||||
: base(other)
|
||||
{
|
||||
Palette = other.Palette;
|
||||
GetPalette = other.GetPalette;
|
||||
GetVoxel = other.GetVoxel;
|
||||
|
||||
WorldRenderer = other.WorldRenderer;
|
||||
}
|
||||
|
||||
public override Widget Clone()
|
||||
{
|
||||
return new ModelWidget(this);
|
||||
}
|
||||
|
||||
IModel cachedVoxel;
|
||||
string cachedPalette;
|
||||
string cachedPlayerPalette;
|
||||
string cachedNormalsPalette;
|
||||
string cachedShadowPalette;
|
||||
float cachedScale;
|
||||
WRot cachedRotation;
|
||||
float[] cachedLightAmbientColor = new float[] { 0, 0, 0 };
|
||||
float[] cachedLightDiffuseColor = new float[] { 0, 0, 0 };
|
||||
int cachedLightPitch;
|
||||
int cachedLightYaw;
|
||||
WAngle cachedCameraAngle;
|
||||
PaletteReference paletteReference;
|
||||
PaletteReference paletteReferencePlayer;
|
||||
PaletteReference paletteReferenceNormals;
|
||||
PaletteReference paletteReferenceShadow;
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
if (renderable == null)
|
||||
return;
|
||||
|
||||
renderable.Render(WorldRenderer);
|
||||
}
|
||||
|
||||
public override void PrepareRenderables()
|
||||
{
|
||||
var voxel = GetVoxel();
|
||||
var palette = GetPalette();
|
||||
var playerPalette = GetPlayerPalette();
|
||||
var normalsPalette = GetNormalsPalette();
|
||||
var shadowPalette = GetShadowPalette();
|
||||
var scale = GetScale();
|
||||
var rotation = GetRotation();
|
||||
var lightAmbientColor = GetLightAmbientColor();
|
||||
var lightDiffuseColor = GetLightDiffuseColor();
|
||||
var lightPitch = GetLightPitch();
|
||||
var lightYaw = GetLightYaw();
|
||||
var cameraAngle = GetCameraAngle();
|
||||
|
||||
if (voxel == null || palette == null)
|
||||
return;
|
||||
|
||||
if (voxel != cachedVoxel)
|
||||
cachedVoxel = voxel;
|
||||
|
||||
if (palette != cachedPalette)
|
||||
{
|
||||
if (string.IsNullOrEmpty(palette) && string.IsNullOrEmpty(playerPalette))
|
||||
return;
|
||||
|
||||
var paletteName = string.IsNullOrEmpty(palette) ? playerPalette : palette;
|
||||
paletteReference = WorldRenderer.Palette(paletteName);
|
||||
cachedPalette = paletteName;
|
||||
}
|
||||
|
||||
if (playerPalette != cachedPlayerPalette)
|
||||
{
|
||||
paletteReferencePlayer = WorldRenderer.Palette(playerPalette);
|
||||
cachedPlayerPalette = playerPalette;
|
||||
}
|
||||
|
||||
if (normalsPalette != cachedNormalsPalette)
|
||||
{
|
||||
paletteReferenceNormals = WorldRenderer.Palette(normalsPalette);
|
||||
cachedNormalsPalette = normalsPalette;
|
||||
}
|
||||
|
||||
if (shadowPalette != cachedShadowPalette)
|
||||
{
|
||||
paletteReferenceShadow = WorldRenderer.Palette(shadowPalette);
|
||||
cachedShadowPalette = shadowPalette;
|
||||
}
|
||||
|
||||
if (scale != cachedScale)
|
||||
cachedScale = scale;
|
||||
|
||||
if (rotation != cachedRotation)
|
||||
cachedRotation = rotation;
|
||||
|
||||
if (lightPitch != cachedLightPitch)
|
||||
cachedLightPitch = lightPitch;
|
||||
|
||||
if (lightYaw != cachedLightYaw)
|
||||
cachedLightYaw = lightYaw;
|
||||
|
||||
if (cachedLightAmbientColor[0] != lightAmbientColor[0] || cachedLightAmbientColor[1] != lightAmbientColor[1] || cachedLightAmbientColor[2] != lightAmbientColor[2])
|
||||
cachedLightAmbientColor = lightAmbientColor;
|
||||
|
||||
if (cachedLightDiffuseColor[0] != lightDiffuseColor[0] || cachedLightDiffuseColor[1] != lightDiffuseColor[1] || cachedLightDiffuseColor[2] != lightDiffuseColor[2])
|
||||
cachedLightDiffuseColor = lightDiffuseColor;
|
||||
|
||||
if (cameraAngle != cachedCameraAngle)
|
||||
cachedCameraAngle = cameraAngle;
|
||||
|
||||
if (cachedVoxel == null)
|
||||
return;
|
||||
|
||||
var animation = new ModelAnimation(
|
||||
cachedVoxel,
|
||||
() => WVec.Zero,
|
||||
() => cachedRotation,
|
||||
() => false,
|
||||
() => 0,
|
||||
true);
|
||||
|
||||
var animations = new ModelAnimation[] { animation };
|
||||
|
||||
ModelPreview preview = new ModelPreview(
|
||||
new ModelAnimation[] { animation }, WVec.Zero, 0,
|
||||
cachedScale,
|
||||
new WAngle(cachedLightPitch),
|
||||
new WAngle(cachedLightYaw),
|
||||
cachedLightAmbientColor,
|
||||
cachedLightDiffuseColor,
|
||||
cachedCameraAngle,
|
||||
paletteReference,
|
||||
paletteReferenceNormals,
|
||||
paletteReferenceShadow);
|
||||
|
||||
var screenBounds = animation.ScreenBounds(WPos.Zero, WorldRenderer, scale);
|
||||
IdealPreviewSize = new int2(screenBounds.Width, screenBounds.Height);
|
||||
var origin = RenderOrigin + new int2(RenderBounds.Size.Width / 2, RenderBounds.Size.Height / 2);
|
||||
|
||||
var camera = new WRot(WAngle.Zero, cachedCameraAngle - new WAngle(256), new WAngle(256));
|
||||
var modelRenderable = new UIModelRenderable(
|
||||
animations, WPos.Zero, origin, 0, camera, scale,
|
||||
WRot.None, cachedLightAmbientColor, cachedLightDiffuseColor,
|
||||
paletteReferencePlayer, paletteReferenceNormals, paletteReferenceShadow);
|
||||
|
||||
renderable = modelRenderable.PrepareRender(WorldRenderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,11 @@ Background@ASSETBROWSER_PANEL:
|
||||
Width: PARENT_RIGHT
|
||||
Height: PARENT_BOTTOM
|
||||
AspectRatio: 1
|
||||
Model@VOXEL:
|
||||
Width: PARENT_RIGHT
|
||||
Height: PARENT_BOTTOM
|
||||
Palette: colorpicker
|
||||
PlayerPalette: colorpicker
|
||||
Label@ERROR:
|
||||
Y: 1
|
||||
X: 5
|
||||
@@ -189,6 +194,55 @@ Background@ASSETBROWSER_PANEL:
|
||||
Height: 25
|
||||
Font: TinyBold
|
||||
Align: Left
|
||||
Container@VOXEL_SELECTOR:
|
||||
X: 60
|
||||
Y: 425
|
||||
Children:
|
||||
Label@ROLL:
|
||||
X: 140
|
||||
Y: 1
|
||||
Width: 40
|
||||
Height: 25
|
||||
Font: TinyBold
|
||||
Align: Left
|
||||
Text: Roll
|
||||
Slider@ROLL_SLIDER:
|
||||
X: 165
|
||||
Y: 3
|
||||
Width: 100
|
||||
Height: 20
|
||||
MinimumValue: 1
|
||||
MaximumValue: 1023
|
||||
Label@PITCH:
|
||||
X: 310
|
||||
Y: 1
|
||||
Width: 40
|
||||
Height: 25
|
||||
Font: TinyBold
|
||||
Align: Left
|
||||
Text: Pitch
|
||||
Slider@PITCH_SLIDER:
|
||||
X: 335
|
||||
Y: 3
|
||||
Width: 100
|
||||
Height: 20
|
||||
MinimumValue: 1
|
||||
MaximumValue: 1023
|
||||
Label@YAW:
|
||||
X: 480
|
||||
Y: 1
|
||||
Width: 40
|
||||
Height: 25
|
||||
Font: TinyBold
|
||||
Align: Left
|
||||
Text: Yaw
|
||||
Slider@YAW_SLIDER:
|
||||
X: 505
|
||||
Y: 3
|
||||
Width: 100
|
||||
Height: 20
|
||||
MinimumValue: 1
|
||||
MaximumValue: 1023
|
||||
Button@CLOSE_BUTTON:
|
||||
Key: escape
|
||||
X: PARENT_RIGHT - 180
|
||||
|
||||
@@ -261,7 +261,7 @@ SpriteSequenceFormat: TilesetSpecificSpriteSequence
|
||||
ModelSequenceFormat: VoxelModelSequence
|
||||
|
||||
AssetBrowser:
|
||||
SupportedExtensions: .shp, .tem, .sno, .vqa
|
||||
SupportedExtensions: .shp, .tem, .sno, .vqa, .vxl
|
||||
|
||||
GameSpeeds:
|
||||
slowest:
|
||||
|
||||
Reference in New Issue
Block a user