- some cosmetics on XNBValidator tool
- more work on our own ContentPipeline implementation: effect files are now imported, processed (compiled using fxc.exe) and serialized to a .xnb file. Needs testing...
This commit is contained in:
parent
9200286a83
commit
3764074514
@ -109,6 +109,8 @@
|
||||
<Compile Include="Processors\EffectProcessorDebugMode.cs" />
|
||||
<Compile Include="Processors\FontDescriptionProcessor.cs" />
|
||||
<Compile Include="Processors\FontTextureProcessor.cs" />
|
||||
<Compile Include="Processors\HLSLCompiler.cs" />
|
||||
<Compile Include="Processors\HLSLCompilerFactory.cs" />
|
||||
<Compile Include="Processors\MaterialProcessor.cs" />
|
||||
<Compile Include="Processors\MaterialProcessorDefaultEffect.cs" />
|
||||
<Compile Include="Processors\ModelBoneContent.cs" />
|
||||
@ -139,6 +141,7 @@
|
||||
<Compile Include="Serialization\Compiler\ContentWriter.cs" />
|
||||
<Compile Include="Serialization\Compiler\GenericContentTypeWriter.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Serialization\Compiler\GraphicTypeWriters\EffectWriter.cs" />
|
||||
<Compile Include="Serialization\Compiler\MathTypeWriters\BoundingBoxWriter.cs" />
|
||||
<Compile Include="Serialization\Compiler\MathTypeWriters\BoundingSphereWriter.cs" />
|
||||
<Compile Include="Serialization\Compiler\MathTypeWriters\BoundingFrustumWriter.cs" />
|
||||
|
@ -21,10 +21,23 @@ namespace ANX.Framework.Content.Pipeline
|
||||
|
||||
public AnxContentImporterContext(BuildContent buildContent, BuildItem buildItem, ContentBuildLogger logger)
|
||||
{
|
||||
|
||||
BuildContent = buildContent;
|
||||
BuildItem = buildItem;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public BuildContent BuildContent
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public BuildItem BuildItem
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public override string IntermediateDirectory
|
||||
{
|
||||
get
|
||||
|
@ -4,6 +4,8 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ANX.Framework.Graphics;
|
||||
using ANX.Framework.Content.Pipeline.Tasks;
|
||||
using System.IO;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -24,6 +26,23 @@ namespace ANX.Framework.Content.Pipeline
|
||||
private TargetPlatform targetPlatform;
|
||||
private GraphicsProfile targetProfile;
|
||||
|
||||
//public AnxContentProcessorContext(BuildCoordinator buildCoordinator, BuildItem buildItem, ContentBuildLogger logger, TargetPlatform targetPlatform, GraphicsProfile targetProfile, string buildConfiguration)
|
||||
public AnxContentProcessorContext(BuildItem buildItem, ContentBuildLogger logger, TargetPlatform targetPlatform, GraphicsProfile targetProfile, string buildConfiguration)
|
||||
{
|
||||
BuildItem = buildItem;
|
||||
this.contentBuildLogger = logger;
|
||||
this.targetPlatform = targetPlatform;
|
||||
this.targetProfile = targetProfile;
|
||||
this.buildConfiguration = buildConfiguration;
|
||||
this.intermediateDirectory = Path.GetTempPath();
|
||||
}
|
||||
|
||||
public BuildItem BuildItem
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public override string BuildConfiguration
|
||||
{
|
||||
get
|
||||
@ -50,9 +69,13 @@ namespace ANX.Framework.Content.Pipeline
|
||||
|
||||
public override string OutputDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
return outputDirectory;
|
||||
get
|
||||
{
|
||||
return outputDirectory;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
outputDirectory = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,6 +85,10 @@ namespace ANX.Framework.Content.Pipeline
|
||||
{
|
||||
return outputFilename;
|
||||
}
|
||||
internal set
|
||||
{
|
||||
outputFilename = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override OpaqueDataDictionary Parameters
|
||||
|
@ -14,9 +14,10 @@ namespace ANX.Framework.Content.Pipeline
|
||||
{
|
||||
public abstract class ContentBuildLogger
|
||||
{
|
||||
private Stack<string> files = new Stack<string>();
|
||||
|
||||
protected ContentBuildLogger()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public abstract void LogImportantMessage(string message, params Object[] messageArgs);
|
||||
@ -25,12 +26,12 @@ namespace ANX.Framework.Content.Pipeline
|
||||
|
||||
public void PopFile()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
files.Pop();
|
||||
}
|
||||
|
||||
public void PushFile(string filename)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
files.Push(filename);
|
||||
}
|
||||
|
||||
protected string GetCurrentFilename(ContentIdentity contentIdentity)
|
||||
|
@ -22,8 +22,8 @@ namespace ANX.Framework.Content.Pipeline
|
||||
public abstract string BuildConfiguration { get; }
|
||||
public abstract string IntermediateDirectory { get; }
|
||||
public abstract ContentBuildLogger Logger { get; }
|
||||
public abstract string OutputDirectory { get; }
|
||||
public abstract string OutputFilename { get; }
|
||||
public abstract string OutputDirectory { get; internal set; }
|
||||
public abstract string OutputFilename { get; internal set; }
|
||||
public abstract OpaqueDataDictionary Parameters { get; }
|
||||
public abstract TargetPlatform TargetPlatform { get; }
|
||||
public abstract GraphicsProfile TargetProfile { get; }
|
||||
|
@ -4,6 +4,8 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ANX.Framework.Content.Pipeline.Graphics;
|
||||
using System.IO;
|
||||
using System.ComponentModel;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -16,6 +18,9 @@ namespace ANX.Framework.Content.Pipeline.Processors
|
||||
[ContentProcessor]
|
||||
public class EffectProcessor : ContentProcessor<EffectContent, CompiledEffectContent>
|
||||
{
|
||||
HLSLCompilerFactory hlslCompilerFactory = new HLSLCompilerFactory();
|
||||
private string targetProfile = "fx_4_0";
|
||||
|
||||
public virtual EffectProcessorDebugMode DebugMode
|
||||
{
|
||||
get;
|
||||
@ -28,9 +33,24 @@ namespace ANX.Framework.Content.Pipeline.Processors
|
||||
set;
|
||||
}
|
||||
|
||||
[DefaultValue("fx_4_0")]
|
||||
public virtual string TargetProfile
|
||||
{
|
||||
get
|
||||
{
|
||||
return targetProfile;
|
||||
}
|
||||
set
|
||||
{
|
||||
targetProfile = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override CompiledEffectContent Process(EffectContent input, ContentProcessorContext context)
|
||||
{
|
||||
byte[] effectCompiledCode = new byte[1]; //TODO: compile effect!!!
|
||||
HLSLCompiler compiler = hlslCompilerFactory.Compilers.Last<HLSLCompiler>();
|
||||
|
||||
byte[] effectCompiledCode = compiler.Compile(input.EffectCode, DebugMode, TargetProfile);
|
||||
|
||||
return new CompiledEffectContent(effectCompiledCode)
|
||||
{
|
||||
@ -39,5 +59,7 @@ namespace ANX.Framework.Content.Pipeline.Processors
|
||||
OpaqueData = input.OpaqueData
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
192
ANX.Framework.Content.Pipeline/Processors/HLSLCompiler.cs
Normal file
192
ANX.Framework.Content.Pipeline/Processors/HLSLCompiler.cs
Normal file
@ -0,0 +1,192 @@
|
||||
#region Using Statements
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace ANX.Framework.Content.Pipeline.Processors
|
||||
{
|
||||
public class HLSLCompiler : IComparable<HLSLCompiler>, IEquatable<HLSLCompiler>
|
||||
{
|
||||
private string executable;
|
||||
private string version;
|
||||
private string helpOutput;
|
||||
private string[] profiles;
|
||||
|
||||
public HLSLCompiler(string executable)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(executable) && File.Exists(executable))
|
||||
{
|
||||
this.executable = executable;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentNullException("executable", "fxc.exe does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
public string Version
|
||||
{
|
||||
get
|
||||
{
|
||||
if (String.IsNullOrEmpty(version))
|
||||
{
|
||||
version = CompilerVersion;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> SupportedProfiles
|
||||
{
|
||||
get
|
||||
{
|
||||
if (profiles == null || profiles.Length <= 0)
|
||||
{
|
||||
const string profileStart = @"(cs|ds|fx|ps|hs|gs|vs|tx)(_)(\S+)\s?";
|
||||
|
||||
Regex pattern = new Regex(profileStart, RegexOptions.Singleline | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
|
||||
MatchCollection m = pattern.Matches(CompilerHelpOutput);
|
||||
|
||||
HashSet<String> tempProfiles = new HashSet<string>();
|
||||
foreach (Match profileMatch in m)
|
||||
{
|
||||
tempProfiles.Add(profileMatch.Value.Trim());
|
||||
}
|
||||
|
||||
profiles = tempProfiles.ToArray<String>();
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Compile(string source, EffectProcessorDebugMode debugMode, string targetProfile)
|
||||
{
|
||||
string tempInputFile = CreateTemporaryShaderFile(source);
|
||||
string tempOutputFile = Path.GetTempFileName();
|
||||
byte[] byteCode;
|
||||
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = executable,
|
||||
Arguments = String.Format("{0} {1} {2} {3}", "/Fo " + tempOutputFile, GetCompilerTargetProfile(targetProfile), GetCompilerDebugFlags(debugMode), tempInputFile),
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using (var proc = Process.Start(startInfo))
|
||||
{
|
||||
helpOutput = proc.StandardOutput.ReadToEnd();
|
||||
}
|
||||
|
||||
byteCode = File.ReadAllBytes(tempOutputFile);
|
||||
|
||||
if (File.Exists(tempInputFile))
|
||||
{
|
||||
File.Delete(tempInputFile);
|
||||
}
|
||||
|
||||
if (File.Exists(tempOutputFile))
|
||||
{
|
||||
File.Delete(tempOutputFile);
|
||||
}
|
||||
|
||||
return byteCode;
|
||||
}
|
||||
|
||||
public int CompareTo(HLSLCompiler other)
|
||||
{
|
||||
return Version.CompareTo(other.Version);
|
||||
}
|
||||
|
||||
public bool Equals(HLSLCompiler other)
|
||||
{
|
||||
return String.Equals(Version, other.Version, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Version.GetHashCode();
|
||||
}
|
||||
|
||||
private string GetCompilerDebugFlags(EffectProcessorDebugMode debugMode)
|
||||
{
|
||||
if ((debugMode == EffectProcessorDebugMode.Auto && System.Diagnostics.Debugger.IsAttached) || debugMode == EffectProcessorDebugMode.Debug)
|
||||
{
|
||||
return "/Od /Op /Zi";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "/O3 /Qstrip_debug";
|
||||
}
|
||||
}
|
||||
|
||||
private string GetCompilerTargetProfile(string targetProfile)
|
||||
{
|
||||
foreach (string profile in SupportedProfiles)
|
||||
{
|
||||
if (string.Equals(profile, targetProfile, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return String.Format("/T {0}", targetProfile);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception(String.Format("fxc.exe version {0} does not support profile {1}", CompilerVersion, targetProfile));
|
||||
}
|
||||
|
||||
private string CreateTemporaryShaderFile(string shaderSourceCode)
|
||||
{
|
||||
string file = Path.GetTempFileName();
|
||||
File.WriteAllText(file, shaderSourceCode);
|
||||
return file;
|
||||
}
|
||||
|
||||
private string CompilerHelpOutput
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(helpOutput))
|
||||
{
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = executable,
|
||||
Arguments = @"/help",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using (var proc = Process.Start(startInfo))
|
||||
{
|
||||
helpOutput = proc.StandardOutput.ReadToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
return helpOutput;
|
||||
}
|
||||
}
|
||||
|
||||
private string CompilerVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
Regex pattern = new Regex(@"\d+(\.\d+)+");
|
||||
Match m = pattern.Match(CompilerHelpOutput);
|
||||
if (m.Length > 0)
|
||||
{
|
||||
return m.Value;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
#region Using Statements
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace ANX.Framework.Content.Pipeline.Processors
|
||||
{
|
||||
public class HLSLCompilerFactory
|
||||
{
|
||||
private List<HLSLCompiler> compilers = new List<HLSLCompiler>();
|
||||
|
||||
public IEnumerable<HLSLCompiler> Compilers
|
||||
{
|
||||
get
|
||||
{
|
||||
if (compilers == null || compilers.Count <= 0)
|
||||
{
|
||||
HashSet<HLSLCompiler> tempCompilers = new HashSet<HLSLCompiler>();
|
||||
HLSLCompilerExecutables.All(x => tempCompilers.Add(x)); // deduplicate list
|
||||
compilers = new List<HLSLCompiler>(tempCompilers);
|
||||
compilers.Sort();
|
||||
}
|
||||
|
||||
foreach (HLSLCompiler compiler in compilers)
|
||||
{
|
||||
yield return compiler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<string> ExecutablePaths
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (String subdir in new String[] { "x64", "x86" })
|
||||
{
|
||||
string sdkPath = Environment.GetEnvironmentVariable("DXSDK_DIR");
|
||||
if (String.IsNullOrEmpty(sdkPath) == false)
|
||||
{
|
||||
yield return Path.Combine(sdkPath, subdir);
|
||||
}
|
||||
|
||||
foreach (String programFilesPath in new String[] { Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) })
|
||||
{
|
||||
yield return Path.Combine(Path.Combine(programFilesPath, @"Windows Kits\8.0\bin\"), subdir);
|
||||
yield return Path.Combine(Path.Combine(programFilesPath, @"Microsoft DirectX SDK (June 2010)\Utilities\bin\"), subdir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<HLSLCompiler> HLSLCompilerExecutables
|
||||
{
|
||||
get
|
||||
{
|
||||
string fxcFile;
|
||||
|
||||
foreach (string path in ExecutablePaths)
|
||||
{
|
||||
fxcFile = Path.Combine(path, @"fxc.exe");
|
||||
|
||||
if (File.Exists(fxcFile))
|
||||
{
|
||||
yield return new HLSLCompiler(fxcFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#region Using Statements
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -13,8 +14,23 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
public override string GetRuntimeReader(TargetPlatform targetPlatform)
|
||||
{
|
||||
// TODO!
|
||||
return "";
|
||||
}
|
||||
string @namespace = typeof(ContentTypeReader).Namespace;
|
||||
string text = base.GetType().Name.Replace("Writer", "Reader");
|
||||
text += base.GetGenericArgumentRuntimeTypes(targetPlatform);
|
||||
Assembly runtimeAssembly = this.RuntimeAssembly;
|
||||
if (runtimeAssembly != null)
|
||||
{
|
||||
text = text + ", " + ContentTypeWriter.GetAssemblyFullName(runtimeAssembly, targetPlatform);
|
||||
}
|
||||
return @namespace + '.' + text;
|
||||
}
|
||||
|
||||
protected virtual Assembly RuntimeAssembly
|
||||
{
|
||||
get
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,9 @@
|
||||
#region Using Statements
|
||||
using System;
|
||||
using System.IO;
|
||||
using ANX.Framework.Graphics;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -11,9 +15,100 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
public sealed class ContentCompiler
|
||||
{
|
||||
private Dictionary<Type, ContentTypeWriter> writerInstances = new Dictionary<Type, ContentTypeWriter>();
|
||||
|
||||
public ContentCompiler()
|
||||
{
|
||||
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
{
|
||||
ContentTypeWriterAttribute[] value = (ContentTypeWriterAttribute[])type.GetCustomAttributes(typeof(ContentTypeWriterAttribute), true);
|
||||
if (value.Length > 0)
|
||||
{
|
||||
if (!type.ContainsGenericParameters)
|
||||
{
|
||||
ContentTypeWriter writer = (ContentTypeWriter)Activator.CreateInstance(type);
|
||||
writerInstances[writer.TargetType] = writer;
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: implement generic writer instances...
|
||||
System.Diagnostics.Debugger.Break();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void Compile(Stream output, object value, TargetPlatform targetPlatform, GraphicsProfile targetProfile, bool compressContent, string rootDirectory, string referenceRelocationPath)
|
||||
{
|
||||
if (output == null)
|
||||
{
|
||||
throw new ArgumentNullException("output");
|
||||
}
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("value");
|
||||
}
|
||||
if (!Enum.IsDefined(typeof(TargetPlatform), targetPlatform))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("targetPlatform");
|
||||
}
|
||||
if (!Enum.IsDefined(typeof(GraphicsProfile), targetProfile))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("targetProfile");
|
||||
}
|
||||
if (string.IsNullOrEmpty(rootDirectory))
|
||||
{
|
||||
throw new ArgumentNullException("rootDirectory");
|
||||
}
|
||||
if (string.IsNullOrEmpty(referenceRelocationPath))
|
||||
{
|
||||
throw new ArgumentNullException("referenceRelocationPath");
|
||||
}
|
||||
if (compressContent)
|
||||
{
|
||||
compressContent = this.ShouldCompressContent(targetPlatform, value);
|
||||
}
|
||||
using (ContentWriter contentWriter = new ContentWriter(this, output, targetPlatform, targetProfile, compressContent, rootDirectory, referenceRelocationPath))
|
||||
{
|
||||
contentWriter.WriteObject<object>(value);
|
||||
contentWriter.FlushOutput();
|
||||
}
|
||||
}
|
||||
|
||||
public ContentTypeWriter GetTypeWriter(Type type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentNullException("type");
|
||||
}
|
||||
ContentTypeWriter typeWriterInternal = this.GetTypeWriterInternal(type);
|
||||
//TODO: this.RecordDependency(typeWriterInternal.TargetType);
|
||||
return typeWriterInternal;
|
||||
}
|
||||
|
||||
private ContentTypeWriter GetTypeWriterInternal(Type type)
|
||||
{
|
||||
ContentTypeWriter contentTypeWriter;
|
||||
if (!this.writerInstances.TryGetValue(type, out contentTypeWriter))
|
||||
{
|
||||
//contentTypeWriter = this.typeWriterFactory.CreateWriter(type);
|
||||
//this.AddTypeWriter(contentTypeWriter);
|
||||
//this.InitializeTypeWriter(contentTypeWriter);
|
||||
}
|
||||
return contentTypeWriter;
|
||||
}
|
||||
|
||||
private bool ShouldCompressContent(TargetPlatform targetPlatform, object value)
|
||||
{
|
||||
if (targetPlatform == TargetPlatform.WindowsPhone)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ContentTypeWriter typeWriterInternal = this.GetTypeWriterInternal(value.GetType());
|
||||
return typeWriterInternal.ShouldCompressContent(targetPlatform, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#region Using Statements
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -17,8 +18,87 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
|
||||
protected ContentTypeWriter(Type targetType)
|
||||
{
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
internal static string GetStrongTypeName(Type type, TargetPlatform targetPlatform)
|
||||
{
|
||||
string text = ContentTypeWriter.GetTypeName(type);
|
||||
if (!string.IsNullOrEmpty(type.Namespace))
|
||||
{
|
||||
text = type.Namespace + '.' + text;
|
||||
}
|
||||
return text + ", " + ContentTypeWriter.GetAssemblyFullName(type.Assembly, targetPlatform);
|
||||
}
|
||||
|
||||
internal static string GetAssemblyFullName(Assembly assembly, TargetPlatform targetPlatform)
|
||||
{
|
||||
AssemblyName assemblyName = assembly.GetName();
|
||||
//ContentTypeWriter.NetCFPlatformDescription[] netCFDescs = ContentTypeWriter.NetCFDescs;
|
||||
//for (int i = 0; i < netCFDescs.Length; i++)
|
||||
//{
|
||||
// ContentTypeWriter.NetCFPlatformDescription netCFPlatformDescription = netCFDescs[i];
|
||||
// if (netCFPlatformDescription.TargetPlatform == targetPlatform)
|
||||
// {
|
||||
// assemblyName = (AssemblyName)assemblyName.Clone();
|
||||
// if (ContentTypeWriter.KeysAreEqual(assemblyName.GetPublicKeyToken(), ContentTypeWriter.WindowsPublicKeyToken))
|
||||
// {
|
||||
// assemblyName.SetPublicKeyToken(netCFPlatformDescription.PublicKeyToken);
|
||||
// break;
|
||||
// }
|
||||
// string[] netCFAssemblies = netCFPlatformDescription.NetCFAssemblies;
|
||||
// for (int j = 0; j < netCFAssemblies.Length; j++)
|
||||
// {
|
||||
// string value = netCFAssemblies[j];
|
||||
// if (assemblyName.Name.Equals(value, StringComparison.InvariantCulture))
|
||||
// {
|
||||
// assemblyName.Version = netCFPlatformDescription.NetCFAssemblyVersion;
|
||||
// assemblyName.SetPublicKeyToken(netCFPlatformDescription.NetCFPublicKeyToken);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
return assemblyName.FullName;
|
||||
}
|
||||
|
||||
private static string GetTypeName(Type type)
|
||||
{
|
||||
string text = type.Name;
|
||||
Type declaringType = type.DeclaringType;
|
||||
if (declaringType != null)
|
||||
{
|
||||
text = ContentTypeWriter.GetTypeName(declaringType) + '+' + text;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
internal string GetGenericArgumentRuntimeTypes(TargetPlatform targetPlatform)
|
||||
{
|
||||
//TODO: implement
|
||||
System.Diagnostics.Debugger.Break();
|
||||
return "";
|
||||
|
||||
//if (this.genericArgumentWriters == null)
|
||||
//{
|
||||
// return string.Empty;
|
||||
//}
|
||||
//string text = string.Empty;
|
||||
//for (int i = 0; i < this.genericArgumentWriters.Count; i++)
|
||||
//{
|
||||
// if (i > 0)
|
||||
// {
|
||||
// text += ',';
|
||||
// }
|
||||
// object obj = text;
|
||||
// text = string.Concat(new object[]
|
||||
// {
|
||||
// obj,
|
||||
// '[',
|
||||
// this.genericArgumentWriters[i].GetRuntimeType(targetPlatform),
|
||||
// ']'
|
||||
// });
|
||||
//}
|
||||
//return '[' + text + ']';
|
||||
}
|
||||
|
||||
public abstract string GetRuntimeReader(TargetPlatform targetPlatform);
|
||||
|
@ -18,6 +18,27 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
private TargetPlatform targetPlatform;
|
||||
private GraphicsProfile targetProfile;
|
||||
private ContentCompiler compiler;
|
||||
private MemoryStream headerData;
|
||||
private MemoryStream contentData;
|
||||
private Stream finalOutput;
|
||||
private Boolean compressContent;
|
||||
private string rootDirectory;
|
||||
private string referenceRelocationPath;
|
||||
|
||||
internal ContentWriter(ContentCompiler compiler, Stream output, TargetPlatform targetPlatform, GraphicsProfile targetProfile, bool compressContent, string rootDirectory, string referenceRelocationPath)
|
||||
{
|
||||
this.compiler = compiler;
|
||||
this.targetPlatform = targetPlatform;
|
||||
this.targetProfile = targetProfile;
|
||||
this.compressContent = compressContent;
|
||||
this.rootDirectory = rootDirectory;
|
||||
this.referenceRelocationPath = referenceRelocationPath;
|
||||
this.finalOutput = output;
|
||||
this.headerData = new MemoryStream();
|
||||
this.contentData = new MemoryStream();
|
||||
this.OutStream = this.contentData;
|
||||
}
|
||||
|
||||
public void Write(Color value)
|
||||
{
|
||||
@ -73,15 +94,43 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
|
||||
base.Write(value.W);
|
||||
}
|
||||
|
||||
//TODO: implement -> ExternalReference<T> needed first
|
||||
//public void WriteExternalReference<T>(ExternalReference<T> reference)
|
||||
//{
|
||||
|
||||
//}
|
||||
public void WriteExternalReference<T>(ExternalReference<T> reference)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void WriteObject<T>(T value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (value == null)
|
||||
{
|
||||
base.Write7BitEncodedInt(0);
|
||||
return;
|
||||
}
|
||||
|
||||
ContentTypeWriter typeWriter = this.compiler.GetTypeWriter(value.GetType());
|
||||
|
||||
base.Write7BitEncodedInt(1);
|
||||
//if (this.recurseDetector.ContainsKey(value))
|
||||
//{
|
||||
// throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.FoundCyclicReference, new object[]
|
||||
// {
|
||||
// value
|
||||
// }));
|
||||
//}
|
||||
//this.recurseDetector.Add(value, true);
|
||||
this.InvokeWriter<T>(value, typeWriter);
|
||||
//this.recurseDetector.Remove(value);
|
||||
}
|
||||
|
||||
private void InvokeWriter<T>(T value, ContentTypeWriter writer)
|
||||
{
|
||||
ContentTypeWriter<T> contentTypeWriter = writer as ContentTypeWriter<T>;
|
||||
if (contentTypeWriter != null)
|
||||
{
|
||||
contentTypeWriter.Write(this, value);
|
||||
return;
|
||||
}
|
||||
writer.Write(this, value);
|
||||
}
|
||||
|
||||
public void WriteObject<T>(T value, ContentTypeWriter typeWriter)
|
||||
@ -104,6 +153,79 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal void FlushOutput()
|
||||
{
|
||||
//TODO: implement
|
||||
|
||||
//this.WriteSharedResources();
|
||||
this.WriteHeader();
|
||||
this.WriteFinalOutput();
|
||||
}
|
||||
|
||||
private void WriteHeader()
|
||||
{
|
||||
this.OutStream = this.headerData;
|
||||
//TODO: implement
|
||||
//base.Write7BitEncodedInt(this.typeWriters.Count);
|
||||
//foreach (ContentTypeWriter current in this.typeWriters)
|
||||
//{
|
||||
// this.Write(current.GetRuntimeReader(this.targetPlatform));
|
||||
// this.Write(current.TypeVersion);
|
||||
//}
|
||||
//base.Write7BitEncodedInt(this.sharedResourceNames.Count);
|
||||
}
|
||||
|
||||
private void WriteFinalOutput()
|
||||
{
|
||||
this.OutStream = this.finalOutput;
|
||||
this.Write('X');
|
||||
this.Write('N');
|
||||
this.Write('B');
|
||||
this.Write((byte)this.targetPlatform);
|
||||
//if (this.targetPlatform == TargetPlatform.Windows)
|
||||
//{
|
||||
// this.Write((byte)119);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// if (this.targetPlatform == TargetPlatform.XBox360)
|
||||
// {
|
||||
// this.Write((byte)120);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (this.targetPlatform != TargetPlatform.WindowsPhone)
|
||||
// {
|
||||
// throw new NotSupportedException();
|
||||
// }
|
||||
// this.Write((byte)109);
|
||||
// }
|
||||
//}
|
||||
if (this.compressContent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
//this.WriteCompressedOutput();
|
||||
return;
|
||||
}
|
||||
this.WriteUncompressedOutput();
|
||||
}
|
||||
|
||||
private void WriteUncompressedOutput()
|
||||
{
|
||||
this.WriteVersionNumber(5);
|
||||
int num = (int)this.headerData.Length;
|
||||
int num2 = (int)this.contentData.Length;
|
||||
this.Write(10 + num + num2);
|
||||
this.OutStream.Write(this.headerData.GetBuffer(), 0, num);
|
||||
this.OutStream.Write(this.contentData.GetBuffer(), 0, num2);
|
||||
}
|
||||
|
||||
private void WriteVersionNumber(ushort version)
|
||||
{
|
||||
version |= (ushort)((int)this.targetProfile << 8);
|
||||
this.Write(version);
|
||||
}
|
||||
|
||||
public TargetPlatform TargetPlatform
|
||||
{
|
||||
get
|
||||
|
@ -1,5 +1,6 @@
|
||||
#region Using Statements
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -18,9 +19,28 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
|
||||
|
||||
protected internal override void Write(ContentWriter output, object value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
this.Write(output, ContentTypeWriter<T>.CastType(value));
|
||||
}
|
||||
|
||||
protected internal abstract void Write(ContentWriter output, T value);
|
||||
|
||||
private static T CastType(object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("value");
|
||||
}
|
||||
if (!(value is T))
|
||||
{
|
||||
System.Diagnostics.Debugger.Break();
|
||||
//throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.WrongArgumentType, new object[]
|
||||
//{
|
||||
// typeof(T),
|
||||
// value.GetType()
|
||||
//}));
|
||||
}
|
||||
return (T)((object)value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
#region Using Statements
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ANX.Framework.Content.Pipeline.Processors;
|
||||
using System.Reflection;
|
||||
using ANX.Framework.Graphics;
|
||||
|
||||
#endregion
|
||||
|
||||
// This file is part of the ANX.Framework created by the
|
||||
// "ANX.Framework developer group" and released under the Ms-PL license.
|
||||
// For details see: http://anxframework.codeplex.com/license
|
||||
|
||||
namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
internal class EffectWriter : BuiltinTypeWriter<CompiledEffectContent>
|
||||
{
|
||||
protected override Assembly RuntimeAssembly
|
||||
{
|
||||
get
|
||||
{
|
||||
return typeof(Effect).Assembly;
|
||||
}
|
||||
}
|
||||
|
||||
protected internal override void Write(ContentWriter output, CompiledEffectContent value)
|
||||
{
|
||||
//TODO: implement
|
||||
//if (output.TargetPlatform == TargetPlatform.WindowsPhone)
|
||||
//{
|
||||
// throw new InvalidContentException(Resources.MobileNoEffects);
|
||||
//}
|
||||
byte[] effectCode = value.GetEffectCode();
|
||||
output.Write(effectCode.Length);
|
||||
output.Write(effectCode);
|
||||
}
|
||||
|
||||
public override string GetRuntimeType(TargetPlatform targetPlatform)
|
||||
{
|
||||
return ContentTypeWriter.GetStrongTypeName(typeof(Effect), targetPlatform);
|
||||
}
|
||||
}
|
||||
}
|
@ -9,10 +9,10 @@ using System;
|
||||
|
||||
namespace ANX.Framework.Content.Pipeline
|
||||
{
|
||||
public enum TargetPlatform
|
||||
public enum TargetPlatform : byte
|
||||
{
|
||||
Windows,
|
||||
WindowsPhone,
|
||||
XBox360,
|
||||
Windows = (byte)119,
|
||||
WindowsPhone = (byte)109,
|
||||
XBox360 = (byte)120,
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,9 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using ANX.Framework.Content.Pipeline.Serialization.Compiler;
|
||||
using ANX.Framework.Graphics;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -16,6 +19,15 @@ namespace ANX.Framework.Content.Pipeline.Tasks
|
||||
{
|
||||
private ImporterManager importerManager;
|
||||
private ProcessorManager processorManager;
|
||||
private ContentCompiler contentCompiler;
|
||||
|
||||
public BuildContent()
|
||||
{
|
||||
OutputDirectory = Environment.CurrentDirectory;
|
||||
TargetPlatform = TargetPlatform.Windows;
|
||||
CompressContent = false;
|
||||
TargetProfile = GraphicsProfile.HiDef;
|
||||
}
|
||||
|
||||
public ImporterManager ImporterManager
|
||||
{
|
||||
@ -43,6 +55,49 @@ namespace ANX.Framework.Content.Pipeline.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
public ContentCompiler ContentCompiler
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.contentCompiler == null)
|
||||
{
|
||||
this.contentCompiler = new ContentCompiler();
|
||||
}
|
||||
|
||||
return this.contentCompiler;
|
||||
}
|
||||
}
|
||||
|
||||
public string OutputDirectory
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public TargetPlatform TargetPlatform
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool CompressContent
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public GraphicsProfile TargetProfile
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public ContentBuildLogger BuildLogger
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public void Execute(IEnumerable<BuildItem> itemsToBuild)
|
||||
{
|
||||
foreach (BuildItem buildItem in itemsToBuild)
|
||||
@ -55,18 +110,20 @@ namespace ANX.Framework.Content.Pipeline.Tasks
|
||||
}
|
||||
|
||||
var buildedItem = Process(buildItem, importedObject);
|
||||
|
||||
SerializeAsset(buildItem, buildedItem);
|
||||
}
|
||||
}
|
||||
|
||||
private object ImportAsset(BuildItem item)
|
||||
{
|
||||
IContentImporter instance = this.ImporterManager.GetInstance(item.BuildRequest.ImporterName);
|
||||
ContentImporterContext context = new AnxContentImporterContext(this, item, null); //this.buildLogger);
|
||||
//this.buildLogger.LogMessage(Resources.BuildLogImporting, new object[]
|
||||
//{
|
||||
// item.BuildRequest.SourceFilename,
|
||||
// instance.GetType()
|
||||
//});
|
||||
ContentImporterContext context = new AnxContentImporterContext(this, item, BuildLogger);
|
||||
BuildLogger.LogMessage("building {0} of type {1}", new object[]
|
||||
{
|
||||
item.BuildRequest.SourceFilename,
|
||||
instance.GetType()
|
||||
});
|
||||
return instance.Import(item.BuildRequest.SourceFilename, context);
|
||||
}
|
||||
|
||||
@ -75,7 +132,9 @@ namespace ANX.Framework.Content.Pipeline.Tasks
|
||||
if (String.IsNullOrEmpty(item.BuildRequest.ProcessorName) == false)
|
||||
{
|
||||
IContentProcessor instance = this.ProcessorManager.GetInstance(item.BuildRequest.ProcessorName);
|
||||
ContentProcessorContext context = new AnxContentProcessorContext();
|
||||
ContentProcessorContext context = new AnxContentProcessorContext(item, BuildLogger, TargetPlatform, TargetProfile, "");
|
||||
context.OutputDirectory = OutputDirectory;
|
||||
context.OutputFilename = item.OutputFilename;
|
||||
return instance.Process(importedObject, context);
|
||||
}
|
||||
else
|
||||
@ -83,5 +142,18 @@ namespace ANX.Framework.Content.Pipeline.Tasks
|
||||
return importedObject;
|
||||
}
|
||||
}
|
||||
|
||||
private void SerializeAsset(BuildItem item, object assetData)
|
||||
{
|
||||
string outputFilename = Path.Combine(OutputDirectory, item.OutputFilename);
|
||||
|
||||
BuildLogger.LogMessage("serializing {0}", new object[] { item.OutputFilename });
|
||||
using (Stream stream = new FileStream(outputFilename, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
this.ContentCompiler.Compile(stream, assetData, TargetPlatform, TargetProfile, CompressContent, OutputDirectory, outputFilename);
|
||||
}
|
||||
//this.rebuiltFiles.Add(outputFilename);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -20,5 +20,10 @@ namespace ANX.Framework.Content.Pipeline.Tasks
|
||||
set;
|
||||
}
|
||||
|
||||
public string OutputFilename
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
38
Tools/ContentBuilder/ConsoleLogger.cs
Normal file
38
Tools/ContentBuilder/ConsoleLogger.cs
Normal file
@ -0,0 +1,38 @@
|
||||
#region Using Statements
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ANX.Framework.Content.Pipeline;
|
||||
|
||||
#endregion
|
||||
|
||||
// This file is part of the ANX.Framework created by the
|
||||
// "ANX.Framework developer group" and released under the Ms-PL license.
|
||||
// For details see: http://anxframework.codeplex.com/license
|
||||
|
||||
namespace ContentBuilder
|
||||
{
|
||||
public class ConsoleLogger : ContentBuildLogger
|
||||
{
|
||||
public override void LogImportantMessage(string message, params object[] messageArgs)
|
||||
{
|
||||
Write("Important", message, messageArgs);
|
||||
}
|
||||
|
||||
public override void LogMessage(string message, params object[] messageArgs)
|
||||
{
|
||||
Write("", message, messageArgs);
|
||||
}
|
||||
|
||||
public override void LogWarning(string helpLink, ContentIdentity contentIdentity, string message, params object[] messageArgs)
|
||||
{
|
||||
Write("Warning", message, messageArgs);
|
||||
}
|
||||
|
||||
private void Write(string severity, string message, params object[] messageArgs)
|
||||
{
|
||||
Console.WriteLine(String.Format("[{0}] {1}", severity, String.Format(message, messageArgs)));
|
||||
}
|
||||
}
|
||||
}
|
@ -43,6 +43,7 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ConsoleLogger.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
@ -21,6 +21,8 @@ namespace ContentBuilder
|
||||
// Generate a list of items to build and set build parameters
|
||||
//
|
||||
List<BuildItem> itemsToBuild = new List<BuildItem>();
|
||||
BuildContent buildContentTask = new BuildContent();
|
||||
buildContentTask.BuildLogger = new ConsoleLogger();
|
||||
|
||||
foreach (string arg in args)
|
||||
{
|
||||
@ -32,15 +34,27 @@ namespace ContentBuilder
|
||||
//TODO: set configured processor name
|
||||
buildItem.BuildRequest.SourceFilename = arg;
|
||||
buildItem.BuildRequest.AssetName = System.IO.Path.GetFileNameWithoutExtension(arg);
|
||||
buildItem.OutputFilename = String.Format("{0}.xnb", buildItem.BuildRequest.AssetName);
|
||||
|
||||
itemsToBuild.Add(buildItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
// parse argument
|
||||
string parameterChar1 = arg.Substring(1,1).ToLowerInvariant();
|
||||
string parameterChar2 = arg.Substring(2,1).ToLowerInvariant();
|
||||
|
||||
if (parameterChar1 == "o" && parameterChar2 == "d")
|
||||
{
|
||||
// output dir
|
||||
buildContentTask.OutputDirectory = arg.Substring(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Build the content
|
||||
//
|
||||
BuildContent buildContentTask = new BuildContent();
|
||||
buildContentTask.Execute(itemsToBuild);
|
||||
}
|
||||
}
|
||||
|
19
Tools/XNBInspector/InspectForm.Designer.cs
generated
19
Tools/XNBInspector/InspectForm.Designer.cs
generated
@ -28,6 +28,7 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InspectForm));
|
||||
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
|
||||
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
|
||||
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@ -35,7 +36,9 @@
|
||||
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
|
||||
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
|
||||
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
||||
this.menuStrip1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// statusStrip1
|
||||
@ -98,6 +101,17 @@
|
||||
this.richTextBox1.Text = "";
|
||||
this.richTextBox1.WordWrap = false;
|
||||
//
|
||||
// pictureBox1
|
||||
//
|
||||
this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.pictureBox1.BackColor = System.Drawing.Color.Transparent;
|
||||
this.pictureBox1.Image = global::ANX.Tools.XNBInspector.Properties.Resources.ANX_Framework_Logo_220x58;
|
||||
this.pictureBox1.Location = new System.Drawing.Point(552, 266);
|
||||
this.pictureBox1.Name = "pictureBox1";
|
||||
this.pictureBox1.Size = new System.Drawing.Size(220, 58);
|
||||
this.pictureBox1.TabIndex = 3;
|
||||
this.pictureBox1.TabStop = false;
|
||||
//
|
||||
// InspectForm
|
||||
//
|
||||
this.AllowDrop = true;
|
||||
@ -105,16 +119,20 @@
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.AutoScroll = true;
|
||||
this.ClientSize = new System.Drawing.Size(784, 362);
|
||||
this.Controls.Add(this.pictureBox1);
|
||||
this.Controls.Add(this.richTextBox1);
|
||||
this.Controls.Add(this.statusStrip1);
|
||||
this.Controls.Add(this.menuStrip1);
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MainMenuStrip = this.menuStrip1;
|
||||
this.Name = "InspectForm";
|
||||
this.Text = "XNB Inspector";
|
||||
this.Load += new System.EventHandler(this.InspectForm_Load);
|
||||
this.DragDrop += new System.Windows.Forms.DragEventHandler(this.dropArea_DragDrop);
|
||||
this.DragEnter += new System.Windows.Forms.DragEventHandler(this.dropArea_DragEnter);
|
||||
this.menuStrip1.ResumeLayout(false);
|
||||
this.menuStrip1.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
@ -129,6 +147,7 @@
|
||||
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
|
||||
private System.Windows.Forms.OpenFileDialog openFileDialog;
|
||||
private System.Windows.Forms.RichTextBox richTextBox1;
|
||||
private System.Windows.Forms.PictureBox pictureBox1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,6 +69,11 @@ namespace ANX.Tools.XNBInspector
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InspectForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
this.Text += " v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -126,4 +126,81 @@
|
||||
<metadata name="openFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>248, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAA
|
||||
AAoHK0S5BytEuQAAAAr///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wAAAAAKBy1EwhWS5P8VkuT/By1EwgAAAAr///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8AAAAACgctRMIVkuT/F531/xed9f8VkuT/By1EwgAAAAr///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AAAAAAoHLUTCFZLk/xed9f8XnfX/F531/xed9f8VkuT/By1EwgAAAAr///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wAAAAAKBy1EwhWS5P8XnfX/F531/xed9f8XnfX/F531/xed9f8VkuT/By1EwgAA
|
||||
AAr///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8AAAAACgctRMIVkuT/F531/xed9f8XnfX/F531/xed9f8XnfX/F531/xed
|
||||
9f8VkuT/By1EwgAAAAr///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AAAAAAoHLUTCFZLk/xed9f8XnfX/F531/xed9f8XnfX/F531/xed
|
||||
9f8XnfX/F531/xed9f8VkuT/By1EwgAAAAr///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wAAAAAKBy1EwhWS5P8XnfX/F531/xed9f8XnfX/F531/xed
|
||||
9f8XnfX/F531/xed9f8XnfX/F531/xed9f8VkuT/By1EwgAAAAr///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8AAAAACgctRMIVkuT/F531/xed9f8XnfX/F531/xed
|
||||
9f8XnfX/F531/xed9f8XnfX/F531/xed9f8XnfX/F531/xed9f8VkuT/By1EwgAAAAr///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAoHLUTCDFOb/wcvjP8HL4z/By+M/wg3
|
||||
iP8Vjt3/EXe6/xJ7wP8VkeL/EG6r/xN/x/8Tf8f/E3/H/xSH0v8XnfX/F531/xed9f8VkuT/By1EwgAA
|
||||
AAr///8A////AP///wD///8A////AP///wD///8A////AP///wAAAAAKBy1EwhWS5P8OYaz/AACA/wAA
|
||||
gP8AAID/AAF7/xJ7yf8Se7//F531/xJ8wv8Rd7r/F531/xed9f8XnfX/E3/G/xed9f8XnfX/F531/xed
|
||||
9f8VkuT/By1EwgAAAAr///8A////AP///wD///8A////AP///wD///8AAAAACgctRMIVkuT/F531/xWR
|
||||
4/8CCnT/AACA/wAAgP8AAID/DFKj/xJ6vv8XnfX/Enq+/xF3uf8XnfX/F531/xed9f8SfsT/F531/xed
|
||||
9f8XnfX/F531/xed9f8VkuT/By1EwgAAAAr///8A////AP///wD///8A////AAAAAAoHLUTCFZLk/xed
|
||||
9f8XnfX/F531/wYogf8AAID/AACA/wAAgP8GLYj/FY7e/xN/x/8UhtH/FpPm/xJ7wf8Se8H/EnvB/xJ9
|
||||
w/8XnfX/F531/xed9f8XnfX/F531/xed9f8VkuT/By1EwgAAAAr///8A////AP///wAAAAAKBy1EwhWS
|
||||
5P8XnfX/F531/xed9f8XnfX/C0ma/wAAgP8AAID/AACA/wIMc/8Wluv/F531/xed9f8Wk+b/AxFi/wIL
|
||||
cf8CC3H/Agtx/xBstv8XnfX/F531/xed9f8XnfX/F531/xed9f8VkuT/By1EwgAAAAr///8AAAAACgct
|
||||
RMIVkuT/F531/xed9f8XnfX/F531/xed9f8Qbrj/AAB9/wAAgP8AAID/AAB//w5ksP8XnfX/F531/xed
|
||||
9f8FJH3/AACA/wAAgP8AAID/C0mb/xed9f8XnfX/F531/xed9f8XnfX/F531/xed9f8VkuT/By1EwgAA
|
||||
AAoHK0S5FZLk/xed9f8XnfX/F531/xed9f8XnfX/F531/xaZ7/8CEXT/AACA/wAAgP8AAID/BSd//wpE
|
||||
l/8KQ5b/CUKV/wUeev8AAID/AACA/wAAgP8GKoP/F531/xed9f8XnfX/F531/xed9f8XnfX/F531/xed
|
||||
9f8VkuT/BytEuQcrRLkVkuT/F531/xed9f8XnfX/F531/xed9f8XnfX/F531/wcxif8AAID/AACA/wAA
|
||||
gP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/AACA/wILdP8Wkub/F531/xed9f8XnfX/F531/xed
|
||||
9f8XnfX/F531/xWS5P8HK0S5AAAACgcrRMIVkuT/F531/xed9f8XnfX/F531/xed9f8XnfX/DFKi/wAA
|
||||
gP8AAID/AACA/wAAf/8DF3f/BB18/wUhf/8GJID/AQZ6/wAAgP8AAID/AACA/w9lr/8XnfX/F531/xed
|
||||
9f8XnfX/F531/xed9f8VkuT/By1EwgAAAAr///8AAAAACgcrRMIVkuT/F531/xed9f8XnfX/F531/xed
|
||||
9f8Se8j/AAF5/wAAgP8AAID/AACA/w5dp/8XnfX/F531/xed9f8FI37/AACA/wAAgP8AAID/CkSW/xed
|
||||
9f8XnfX/F531/xed9f8XnfX/FZLk/wctRMIAAAAK////AP///wD///8AAAAACgcrQ8MVkuT/F531/xed
|
||||
9f8XnfX/F531/xed9f8EGHf/AACA/wAAgP8AAID/Bid9/xeb8v8XnfX/F531/wlAlf8AAID/AACA/wAA
|
||||
gP8FJH7/F531/xed9f8XnfX/F531/xWS5P8HLUTCAAAACv///wD///8A////AP///wD///8AAAAACgcr
|
||||
Q8MVkuT/F531/xed9f8XnfX/F531/wtJmf8AAID/AACA/wAAgP8AAH7/BSOA/wk9lf8JP5f/BimA/wAA
|
||||
gP8AAID/AACA/wEHdv8VjNv/F531/xed9f8VkuT/By1EwgAAAAr///8A////AP///wD///8A////AP//
|
||||
/wD///8AAAAACgcrQ8MVkuT/F531/xed9f8XnfX/FpLm/wITd/8AAID/AACA/wAAgP8AAID/AACA/wAA
|
||||
gP8AAID/AACA/wAAgP8AAID/AACA/w5eqf8XnfX/FZLk/wctRMIAAAAK////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8AAAAACgcrQ8MVkuT/F531/xed9f8XnfX/DFOh/wEHdv8AAID/AACA/wAA
|
||||
gP8AAID/AACA/wAAgP8AAID/AACA/wAAgP8AAID/CT6S/xWS5P8HLUTCAAAACv///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8AAAAACwcrQ8MVkuT/F531/xed9f8XnfX/FY/h/w5f
|
||||
q/8JQZT/CTuQ/wk6kP8JOY7/CDeN/wg2jP8IN43/CTmP/wk7kP8KRo7/By1EwgAAAAr///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AAAAACwcrQ8MVkuT/F531/xed
|
||||
9f8XnfX/F531/xed9f8XnfX/F531/xed9f8XnfX/F531/xed9f8XnfX/FZLk/wctRMIAAAAK////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AAAAACwcr
|
||||
QsQVkuT/F531/xed9f8XnfX/F531/xed9f8XnfX/F531/xed9f8XnfX/F531/xWS5P8HLUTCAAAACv//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8AAAAACwcrQsQVkuT/F531/xed9f8XnfX/F531/xed9f8XnfX/F531/xed9f8VkuT/By1EwgAA
|
||||
AAr///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8AAAAACwcrQsQVkuT/F531/xed9f8XnfX/F531/xed9f8XnfX/FZLk/wct
|
||||
RMIAAAAK////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8AAAAACwcqQcQVkuT/F531/xed9f8XnfX/F531/xWS
|
||||
5P8HLUTCAAAACv///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AAAAADAcqQcQVkuT/F531/xed
|
||||
9f8VkuT/By1EwgAAAAr///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8AAAAADAYp
|
||||
QcUVkuT/FZLk/wctRMIAAAAK////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8AAAAADAcpQLsHK0S5AAAACv///wD///8A////AP///wD///8A////AP///wD///8A////AP//
|
||||
/wD///8A////AP///wD///8A//5////8P///+B////AP///gB///wAP//4AB//8AAP/+AAB//AAAP/gA
|
||||
AB/wAAAP4AAAB8AAAAOAAAABAAAAAAAAAACAAAABwAAAA+AAAAfwAAAP+AAAH/wAAD/+AAB//wAA//+A
|
||||
Af//wAP//+AH///wD///+B////w////+f/8=
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: AssemblyVersion("0.2.0.0")]
|
||||
[assembly: AssemblyFileVersion("0.2.0.0")]
|
||||
|
31
Tools/XNBInspector/Properties/Resources.Designer.cs
generated
31
Tools/XNBInspector/Properties/Resources.Designer.cs
generated
@ -1,10 +1,10 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.269
|
||||
// Dieser Code wurde von einem Tool generiert.
|
||||
// Laufzeitversion:4.0.30319.269
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
|
||||
// der Code erneut generiert wird.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@ -13,12 +13,12 @@ namespace ANX.Tools.XNBInspector.Properties {
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
|
||||
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
|
||||
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
|
||||
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
@ -33,7 +33,7 @@ namespace ANX.Tools.XNBInspector.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
@ -47,8 +47,8 @@ namespace ANX.Tools.XNBInspector.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
|
||||
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
@ -59,5 +59,12 @@ namespace ANX.Tools.XNBInspector.Properties {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal static System.Drawing.Bitmap ANX_Framework_Logo_220x58 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("ANX.Framework.Logo_220x58", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
@ -60,6 +60,7 @@
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
@ -68,9 +69,10 @@
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
@ -85,9 +87,10 @@
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
@ -109,9 +112,13 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="ANX.Framework.Logo_220x58" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\ANX.Framework.Logo_220x58.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
@ -33,6 +33,9 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>anx.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
@ -84,6 +87,10 @@
|
||||
<Name>ANX.Framework</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="anx.ico" />
|
||||
<None Include="Resources\ANX.Framework.Logo_220x58.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
Loading…
x
Reference in New Issue
Block a user