[xna] Fix CRLF.

This commit is contained in:
badlogic 2020-11-13 09:32:03 +01:00
parent 2243ec9e98
commit 42b7efdcd6
5 changed files with 847 additions and 847 deletions

View File

@ -1,227 +1,227 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<ProjectGuid>{29CC4385-294A-4885-A3E8-FD4825E0CFDD}</ProjectGuid> <ProjectGuid>{29CC4385-294A-4885-A3E8-FD4825E0CFDD}</ProjectGuid>
<ProjectTypeGuids>{6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Spine</RootNamespace> <RootNamespace>Spine</RootNamespace>
<AssemblyName>spine-xna-example</AssemblyName> <AssemblyName>spine-xna-example</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile> <TargetFrameworkProfile>Client</TargetFrameworkProfile>
<XnaFrameworkVersion>v4.0</XnaFrameworkVersion> <XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
<XnaPlatform>Windows</XnaPlatform> <XnaPlatform>Windows</XnaPlatform>
<XnaProfile>HiDef</XnaProfile> <XnaProfile>HiDef</XnaProfile>
<XnaCrossPlatformGroupID>bf3b738e-f348-48d3-b35b-94bc118edb90</XnaCrossPlatformGroupID> <XnaCrossPlatformGroupID>bf3b738e-f348-48d3-b35b-94bc118edb90</XnaCrossPlatformGroupID>
<XnaOutputType>Game</XnaOutputType> <XnaOutputType>Game</XnaOutputType>
<ApplicationIcon>Game.ico</ApplicationIcon> <ApplicationIcon>Game.ico</ApplicationIcon>
<Thumbnail>GameThumbnail.png</Thumbnail> <Thumbnail>GameThumbnail.png</Thumbnail>
<IsWebBootstrapper>false</IsWebBootstrapper> <IsWebBootstrapper>false</IsWebBootstrapper>
<XnaUpgrade /> <XnaUpgrade />
<PublishUrl>publish\</PublishUrl> <PublishUrl>publish\</PublishUrl>
<Install>true</Install> <Install>true</Install>
<InstallFrom>Disk</InstallFrom> <InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled> <UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode> <UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval> <UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits> <UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically> <UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired> <UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions> <MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision> <ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion> <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust> <UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled> <BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\x86\Debug</OutputPath> <OutputPath>bin\x86\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE;WINDOWS</DefineConstants> <DefineConstants>DEBUG;TRACE;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib> <NoStdLib>true</NoStdLib>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<XnaCompressContent>True</XnaCompressContent> <XnaCompressContent>True</XnaCompressContent>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\x86\Release</OutputPath> <OutputPath>bin\x86\Release</OutputPath>
<DefineConstants>TRACE;WINDOWS</DefineConstants> <DefineConstants>TRACE;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib> <NoStdLib>true</NoStdLib>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<XnaCompressContent>True</XnaCompressContent> <XnaCompressContent>True</XnaCompressContent>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<StartupObject>Spine.ExampleProgram</StartupObject> <StartupObject>Spine.ExampleProgram</StartupObject>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> <Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> <Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> <Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="Microsoft.Xna.Framework.GamerServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> <Reference Include="Microsoft.Xna.Framework.GamerServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> <Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="Microsoft.Xna.Framework.Video, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> <Reference Include="Microsoft.Xna.Framework.Video, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="Microsoft.Xna.Framework.Avatar, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> <Reference Include="Microsoft.Xna.Framework.Avatar, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="Microsoft.Xna.Framework.Net, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> <Reference Include="Microsoft.Xna.Framework.Net, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="Microsoft.Xna.Framework.Storage, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86"> <Reference Include="Microsoft.Xna.Framework.Storage, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="mscorlib"> <Reference Include="mscorlib">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="System"> <Reference Include="System">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="System.Xml"> <Reference Include="System.Xml">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="System.Core"> <Reference Include="System.Core">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="System.Xml.Linq"> <Reference Include="System.Xml.Linq">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="System.Net"> <Reference Include="System.Net">
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="src\ExampleGame.cs" /> <Compile Include="src\ExampleGame.cs" />
<Compile Include="src\ExampleProgram.cs" /> <Compile Include="src\ExampleProgram.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="data\coin.png"> <None Include="data\coin.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="data\coin-pro.skel"> <None Include="data\coin-pro.skel">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="data\raptor.png"> <None Include="data\raptor.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="data\spineboy.png"> <None Include="data\spineboy.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="data\raptor_normals.png"> <None Include="data\raptor_normals.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<Content Include="data\tank.png"> <Content Include="data\tank.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Game.ico" /> <Content Include="Game.ico" />
<Content Include="GameThumbnail.png" /> <Content Include="GameThumbnail.png" />
<None Include="data\tank.atlas"> <None Include="data\tank.atlas">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="data\tank-pro.json"> <None Include="data\tank-pro.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="data\tank-pro.skel"> <None Include="data\tank-pro.skel">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\spine-csharp\spine-csharp.csproj"> <ProjectReference Include="..\..\spine-csharp\spine-csharp.csproj">
<Project>{94144e22-2431-4a8f-ac04-dec22f7edd8f}</Project> <Project>{94144e22-2431-4a8f-ac04-dec22f7edd8f}</Project>
<Name>spine-csharp</Name> <Name>spine-csharp</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\example-content\spine-xna-example-content.contentproj"> <ProjectReference Include="..\example-content\spine-xna-example-content.contentproj">
<Project>{D0632D20-BC92-4A73-896B-30BB687732B8}</Project> <Project>{D0632D20-BC92-4A73-896B-30BB687732B8}</Project>
<Name>spine-xna-example-content</Name> <Name>spine-xna-example-content</Name>
<XnaReferenceType>Content</XnaReferenceType> <XnaReferenceType>Content</XnaReferenceType>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\spine-xna.csproj"> <ProjectReference Include="..\spine-xna.csproj">
<Project>{7F8F2327-C016-49C8-BB4D-F3F77971961E}</Project> <Project>{7F8F2327-C016-49C8-BB4D-F3F77971961E}</Project>
<Name>spine-xna</Name> <Name>spine-xna</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client"> <BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
<Visible>False</Visible> <Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4 Client Profile %28x86 and x64%29</ProductName> <ProductName>Microsoft .NET Framework 4 Client Profile %28x86 and x64%29</ProductName>
<Install>true</Install> <Install>true</Install>
</BootstrapperPackage> </BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5"> <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible> <Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install> <Install>false</Install>
</BootstrapperPackage> </BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible> <Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName> <ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install> <Install>false</Install>
</BootstrapperPackage> </BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1"> <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible> <Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName> <ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install> <Install>true</Install>
</BootstrapperPackage> </BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Xna.Framework.4.0"> <BootstrapperPackage Include="Microsoft.Xna.Framework.4.0">
<Visible>False</Visible> <Visible>False</Visible>
<ProductName>Microsoft XNA Framework Redistributable 4.0</ProductName> <ProductName>Microsoft XNA Framework Redistributable 4.0</ProductName>
<Install>true</Install> <Install>true</Install>
</BootstrapperPackage> </BootstrapperPackage>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="data\coin.atlas"> <None Include="data\coin.atlas">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="data\coin-pro.json"> <None Include="data\coin-pro.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="data\goblins-pro.json"> <None Include="data\goblins-pro.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="data\goblins-pro.skel"> <None Include="data\goblins-pro.skel">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="data\raptor.atlas"> <None Include="data\raptor.atlas">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="data\raptor-pro.json"> <None Include="data\raptor-pro.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="data\spineboy.atlas"> <None Include="data\spineboy.atlas">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="data\spineboy-ess.json"> <None Include="data\spineboy-ess.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.targets" /> <Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.targets" />
<!-- <!--
To modify your build process, add your task inside one of the targets below and uncomment it. 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. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">
</Target> </Target>
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
</Project> </Project>

View File

@ -1,253 +1,253 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2020, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement: * conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license * http://esotericsoftware.com/spine-editor-license
* *
* Otherwise, it is permitted to integrate the Spine Runtimes into software * Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively, * or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own * "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
using System; using System;
using System.IO; using System.IO;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media; using Microsoft.Xna.Framework.Media;
using Spine; using Spine;
namespace Spine { namespace Spine {
public class Example : Microsoft.Xna.Framework.Game { public class Example : Microsoft.Xna.Framework.Game {
GraphicsDeviceManager graphics; GraphicsDeviceManager graphics;
SkeletonRenderer skeletonRenderer; SkeletonRenderer skeletonRenderer;
SkeletonDebugRenderer skeletonDebugRenderer; SkeletonDebugRenderer skeletonDebugRenderer;
Skeleton skeleton; Skeleton skeleton;
Slot headSlot; Slot headSlot;
AnimationState state; AnimationState state;
SkeletonBounds bounds = new SkeletonBounds(); SkeletonBounds bounds = new SkeletonBounds();
#if WINDOWS_STOREAPP #if WINDOWS_STOREAPP
private string assetsFolder = @"Assets\"; private string assetsFolder = @"Assets\";
#else #else
private string assetsFolder = "data/"; private string assetsFolder = "data/";
#endif #endif
public Example () { public Example () {
IsMouseVisible = true; IsMouseVisible = true;
graphics = new GraphicsDeviceManager(this); graphics = new GraphicsDeviceManager(this);
graphics.IsFullScreen = false; graphics.IsFullScreen = false;
graphics.PreferredBackBufferWidth = 800; graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 600; graphics.PreferredBackBufferHeight = 600;
} }
protected override void Initialize () { protected override void Initialize () {
// TODO: Add your initialization logic here // TODO: Add your initialization logic here
base.Initialize(); base.Initialize();
} }
protected override void LoadContent () { protected override void LoadContent () {
bool useNormalmapShader = false; bool useNormalmapShader = false;
Effect spineEffect; Effect spineEffect;
if (!useNormalmapShader) { if (!useNormalmapShader) {
// Two color tint effect. Note that you can also use the default BasicEffect instead. // Two color tint effect. Note that you can also use the default BasicEffect instead.
spineEffect = Content.Load<Effect>("spine-xna-example-content\\SpineEffect"); spineEffect = Content.Load<Effect>("spine-xna-example-content\\SpineEffect");
} }
else { else {
spineEffect = Content.Load<Effect>("spine-xna-example-content\\SpineEffectNormalmap"); spineEffect = Content.Load<Effect>("spine-xna-example-content\\SpineEffectNormalmap");
spineEffect.Parameters["Light0_Direction"].SetValue(new Vector3(-0.5265408f, 0.5735765f, -0.6275069f)); spineEffect.Parameters["Light0_Direction"].SetValue(new Vector3(-0.5265408f, 0.5735765f, -0.6275069f));
spineEffect.Parameters["Light0_Diffuse"].SetValue(new Vector3(1, 0.9607844f, 0.8078432f)); spineEffect.Parameters["Light0_Diffuse"].SetValue(new Vector3(1, 0.9607844f, 0.8078432f));
spineEffect.Parameters["Light0_Specular"].SetValue(new Vector3(1, 0.9607844f, 0.8078432f)); spineEffect.Parameters["Light0_Specular"].SetValue(new Vector3(1, 0.9607844f, 0.8078432f));
spineEffect.Parameters["Light0_SpecularExponent"].SetValue(2.0f); spineEffect.Parameters["Light0_SpecularExponent"].SetValue(2.0f);
} }
spineEffect.Parameters["World"].SetValue(Matrix.Identity); spineEffect.Parameters["World"].SetValue(Matrix.Identity);
spineEffect.Parameters["View"].SetValue(Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 1.0f), Vector3.Zero, Vector3.Up)); spineEffect.Parameters["View"].SetValue(Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 1.0f), Vector3.Zero, Vector3.Up));
skeletonRenderer = new SkeletonRenderer(GraphicsDevice); skeletonRenderer = new SkeletonRenderer(GraphicsDevice);
skeletonRenderer.PremultipliedAlpha = false; skeletonRenderer.PremultipliedAlpha = false;
skeletonRenderer.Effect = spineEffect; skeletonRenderer.Effect = spineEffect;
skeletonDebugRenderer = new SkeletonDebugRenderer(GraphicsDevice); skeletonDebugRenderer = new SkeletonDebugRenderer(GraphicsDevice);
skeletonDebugRenderer.DisableAll(); skeletonDebugRenderer.DisableAll();
skeletonDebugRenderer.DrawClipping = true; skeletonDebugRenderer.DrawClipping = true;
// String name = "spineboy-ess"; // String name = "spineboy-ess";
// String name = "goblins-pro"; // String name = "goblins-pro";
String name = "raptor-pro"; String name = "raptor-pro";
// String name = "tank-pro"; // String name = "tank-pro";
//String name = "coin-pro"; //String name = "coin-pro";
if (useNormalmapShader) if (useNormalmapShader)
name = "raptor-pro"; // we only have normalmaps for raptor name = "raptor-pro"; // we only have normalmaps for raptor
String atlasName = name.Replace("-pro", "").Replace("-ess", ""); String atlasName = name.Replace("-pro", "").Replace("-ess", "");
if (name == "goblins-pro") atlasName = "goblins-mesh"; if (name == "goblins-pro") atlasName = "goblins-mesh";
bool binaryData = false; bool binaryData = false;
Atlas atlas; Atlas atlas;
if (!useNormalmapShader) { if (!useNormalmapShader) {
atlas = new Atlas(assetsFolder + atlasName + ".atlas", new XnaTextureLoader(GraphicsDevice)); atlas = new Atlas(assetsFolder + atlasName + ".atlas", new XnaTextureLoader(GraphicsDevice));
} }
else { else {
atlas = new Atlas(assetsFolder + atlasName + ".atlas", new XnaTextureLoader(GraphicsDevice, atlas = new Atlas(assetsFolder + atlasName + ".atlas", new XnaTextureLoader(GraphicsDevice,
loadMultipleTextureLayers: true, textureSuffixes: new string[] { "", "_normals" })); loadMultipleTextureLayers: true, textureSuffixes: new string[] { "", "_normals" }));
} }
float scale = 1; float scale = 1;
if (name == "spineboy-ess") scale = 0.6f; if (name == "spineboy-ess") scale = 0.6f;
if (name == "raptor-pro") scale = 0.5f; if (name == "raptor-pro") scale = 0.5f;
if (name == "tank-pro") scale = 0.3f; if (name == "tank-pro") scale = 0.3f;
if (name == "coin-pro") scale = 1; if (name == "coin-pro") scale = 1;
SkeletonData skeletonData; SkeletonData skeletonData;
if (binaryData) { if (binaryData) {
SkeletonBinary binary = new SkeletonBinary(atlas); SkeletonBinary binary = new SkeletonBinary(atlas);
binary.Scale = scale; binary.Scale = scale;
skeletonData = binary.ReadSkeletonData(assetsFolder + name + ".skel"); skeletonData = binary.ReadSkeletonData(assetsFolder + name + ".skel");
} else { } else {
SkeletonJson json = new SkeletonJson(atlas); SkeletonJson json = new SkeletonJson(atlas);
json.Scale = scale; json.Scale = scale;
skeletonData = json.ReadSkeletonData(assetsFolder + name + ".json"); skeletonData = json.ReadSkeletonData(assetsFolder + name + ".json");
} }
skeleton = new Skeleton(skeletonData); skeleton = new Skeleton(skeletonData);
if (name == "goblins-pro") skeleton.SetSkin("goblin"); if (name == "goblins-pro") skeleton.SetSkin("goblin");
// Define mixing between animations. // Define mixing between animations.
AnimationStateData stateData = new AnimationStateData(skeleton.Data); AnimationStateData stateData = new AnimationStateData(skeleton.Data);
state = new AnimationState(stateData); state = new AnimationState(stateData);
if (name == "spineboy-ess") { if (name == "spineboy-ess") {
skeleton.SetAttachment("head-bb", "head"); skeleton.SetAttachment("head-bb", "head");
stateData.SetMix("run", "jump", 0.2f); stateData.SetMix("run", "jump", 0.2f);
stateData.SetMix("jump", "run", 0.4f); stateData.SetMix("jump", "run", 0.4f);
// Event handling for all animations. // Event handling for all animations.
state.Start += Start; state.Start += Start;
state.End += End; state.End += End;
state.Complete += Complete; state.Complete += Complete;
state.Event += Event; state.Event += Event;
state.SetAnimation(0, "run", true); state.SetAnimation(0, "run", true);
TrackEntry entry = state.AddAnimation(0, "jump", false, 0); TrackEntry entry = state.AddAnimation(0, "jump", false, 0);
entry.End += End; // Event handling for queued animations. entry.End += End; // Event handling for queued animations.
state.AddAnimation(0, "run", true, 0); state.AddAnimation(0, "run", true, 0);
} }
else if (name == "raptor-pro") { else if (name == "raptor-pro") {
state.SetAnimation(0, "walk", true); state.SetAnimation(0, "walk", true);
state.AddAnimation(1, "gun-grab", false, 2); state.AddAnimation(1, "gun-grab", false, 2);
} }
else if (name == "coin-pro") { else if (name == "coin-pro") {
state.SetAnimation(0, "animation", true); state.SetAnimation(0, "animation", true);
} }
else if (name == "tank-pro") { else if (name == "tank-pro") {
skeleton.X += 300; skeleton.X += 300;
state.SetAnimation(0, "drive", true); state.SetAnimation(0, "drive", true);
} }
else { else {
state.SetAnimation(0, "walk", true); state.SetAnimation(0, "walk", true);
} }
skeleton.X += 400; skeleton.X += 400;
skeleton.Y += GraphicsDevice.Viewport.Height; skeleton.Y += GraphicsDevice.Viewport.Height;
skeleton.UpdateWorldTransform(); skeleton.UpdateWorldTransform();
headSlot = skeleton.FindSlot("head"); headSlot = skeleton.FindSlot("head");
} }
protected override void UnloadContent () { protected override void UnloadContent () {
// TODO: Unload any non ContentManager content here // TODO: Unload any non ContentManager content here
} }
protected override void Update (GameTime gameTime) { protected override void Update (GameTime gameTime) {
// TODO: Add your update logic here // TODO: Add your update logic here
#if (!WINDOWS_STOREAPP || WINDOWS_PHONE81) && !IOS #if (!WINDOWS_STOREAPP || WINDOWS_PHONE81) && !IOS
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit(); this.Exit();
#endif #endif
base.Update(gameTime); base.Update(gameTime);
} }
protected override void Draw (GameTime gameTime) { protected override void Draw (GameTime gameTime) {
GraphicsDevice.Clear(Color.Black); GraphicsDevice.Clear(Color.Black);
state.Update(gameTime.ElapsedGameTime.Milliseconds / 1000f); state.Update(gameTime.ElapsedGameTime.Milliseconds / 1000f);
state.Apply(skeleton); state.Apply(skeleton);
skeleton.UpdateWorldTransform(); skeleton.UpdateWorldTransform();
if (skeletonRenderer.Effect is BasicEffect) { if (skeletonRenderer.Effect is BasicEffect) {
((BasicEffect)skeletonRenderer.Effect).Projection = Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 1, 0); ((BasicEffect)skeletonRenderer.Effect).Projection = Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 1, 0);
} else { } else {
skeletonRenderer.Effect.Parameters["Projection"].SetValue(Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 1, 0)); skeletonRenderer.Effect.Parameters["Projection"].SetValue(Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 1, 0));
} }
skeletonRenderer.Begin(); skeletonRenderer.Begin();
skeletonRenderer.Draw(skeleton); skeletonRenderer.Draw(skeleton);
skeletonRenderer.End(); skeletonRenderer.End();
skeletonDebugRenderer.Effect.Projection = Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 1, 0); skeletonDebugRenderer.Effect.Projection = Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 1, 0);
skeletonDebugRenderer.Begin(); skeletonDebugRenderer.Begin();
skeletonDebugRenderer.Draw(skeleton); skeletonDebugRenderer.Draw(skeleton);
skeletonDebugRenderer.End(); skeletonDebugRenderer.End();
bounds.Update(skeleton, true); bounds.Update(skeleton, true);
MouseState mouse = Mouse.GetState(); MouseState mouse = Mouse.GetState();
if (headSlot != null) { if (headSlot != null) {
headSlot.G = 1; headSlot.G = 1;
headSlot.B = 1; headSlot.B = 1;
if (bounds.AabbContainsPoint(mouse.X, mouse.Y)) { if (bounds.AabbContainsPoint(mouse.X, mouse.Y)) {
BoundingBoxAttachment hit = bounds.ContainsPoint(mouse.X, mouse.Y); BoundingBoxAttachment hit = bounds.ContainsPoint(mouse.X, mouse.Y);
if (hit != null) { if (hit != null) {
headSlot.G = 0; headSlot.G = 0;
headSlot.B = 0; headSlot.B = 0;
} }
} }
} }
base.Draw(gameTime); base.Draw(gameTime);
} }
public void Start (TrackEntry entry) { public void Start (TrackEntry entry) {
#if !WINDOWS_STOREAPP #if !WINDOWS_STOREAPP
Console.WriteLine(entry + ": start"); Console.WriteLine(entry + ": start");
#endif #endif
} }
public void End (TrackEntry entry) { public void End (TrackEntry entry) {
#if !WINDOWS_STOREAPP #if !WINDOWS_STOREAPP
Console.WriteLine(entry + ": end"); Console.WriteLine(entry + ": end");
#endif #endif
} }
public void Complete (TrackEntry entry) { public void Complete (TrackEntry entry) {
#if !WINDOWS_STOREAPP #if !WINDOWS_STOREAPP
Console.WriteLine(entry + ": complete "); Console.WriteLine(entry + ": complete ");
#endif #endif
} }
public void Event (TrackEntry entry, Event e) { public void Event (TrackEntry entry, Event e) {
#if !WINDOWS_STOREAPP #if !WINDOWS_STOREAPP
Console.WriteLine(entry + ": event " + e); Console.WriteLine(entry + ": event " + e);
#endif #endif
} }
} }
} }

View File

@ -1,195 +1,195 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2020, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement: * conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license * http://esotericsoftware.com/spine-editor-license
* *
* Otherwise, it is permitted to integrate the Spine Runtimes into software * Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively, * or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own * "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
namespace Spine { namespace Spine {
public struct VertexPositionColorTextureColor : IVertexType { public struct VertexPositionColorTextureColor : IVertexType {
public Vector3 Position; public Vector3 Position;
public Color Color; public Color Color;
public Vector2 TextureCoordinate; public Vector2 TextureCoordinate;
public Color Color2; public Color Color2;
public readonly static VertexDeclaration VertexDeclaration = new VertexDeclaration public readonly static VertexDeclaration VertexDeclaration = new VertexDeclaration
( (
new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
new VertexElement(12, VertexElementFormat.Color, VertexElementUsage.Color, 0), new VertexElement(12, VertexElementFormat.Color, VertexElementUsage.Color, 0),
new VertexElement(16, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0), new VertexElement(16, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
new VertexElement(24, VertexElementFormat.Color, VertexElementUsage.Color, 1) new VertexElement(24, VertexElementFormat.Color, VertexElementUsage.Color, 1)
); );
VertexDeclaration IVertexType.VertexDeclaration { VertexDeclaration IVertexType.VertexDeclaration {
get { return VertexDeclaration; } get { return VertexDeclaration; }
} }
} }
// #region License // #region License
// /* // /*
// Microsoft Public License (Ms-PL) // Microsoft Public License (Ms-PL)
// MonoGame - Copyright <20> 2009 The MonoGame Team // MonoGame - Copyright <20> 2009 The MonoGame Team
// //
// All rights reserved. // All rights reserved.
// //
// This license governs use of the accompanying software. If you use the software, you accept this license. If you do not // This license governs use of the accompanying software. If you use the software, you accept this license. If you do not
// accept the license, do not use the software. // accept the license, do not use the software.
// //
// 1. Definitions // 1. Definitions
// The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under // The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under
// U.S. copyright law. // U.S. copyright law.
// //
// A "contribution" is the original software, or any additions or changes to the software. // A "contribution" is the original software, or any additions or changes to the software.
// A "contributor" is any person that distributes its contribution under this license. // A "contributor" is any person that distributes its contribution under this license.
// "Licensed patents" are a contributor's patent claims that read directly on its contribution. // "Licensed patents" are a contributor's patent claims that read directly on its contribution.
// //
// 2. Grant of Rights // 2. Grant of Rights
// (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, // (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3,
// each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. // each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
// (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, // (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3,
// each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. // each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
// //
// 3. Conditions and Limitations // 3. Conditions and Limitations
// (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. // (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
// (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, // (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software,
// your patent license from such contributor to the software ends automatically. // your patent license from such contributor to the software ends automatically.
// (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution // (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution
// notices that are present in the software. // notices that are present in the software.
// (D) If you distribute any portion of the software in source code form, you may do so only under this license by including // (D) If you distribute any portion of the software in source code form, you may do so only under this license by including
// a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object // a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object
// code form, you may only do so under a license that complies with this license. // code form, you may only do so under a license that complies with this license.
// (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees // (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees
// or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent // or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent
// permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular // permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular
// purpose and non-infringement. // purpose and non-infringement.
// */ // */
// #endregion License // #endregion License
// //
/// <summary>Draws batched meshes.</summary> /// <summary>Draws batched meshes.</summary>
public class MeshBatcher { public class MeshBatcher {
private readonly List<MeshItem> items; private readonly List<MeshItem> items;
private readonly Queue<MeshItem> freeItems; private readonly Queue<MeshItem> freeItems;
private VertexPositionColorTextureColor[] vertexArray = { }; private VertexPositionColorTextureColor[] vertexArray = { };
private short[] triangles = { }; private short[] triangles = { };
public MeshBatcher () { public MeshBatcher () {
items = new List<MeshItem>(256); items = new List<MeshItem>(256);
freeItems = new Queue<MeshItem>(256); freeItems = new Queue<MeshItem>(256);
EnsureCapacity(256, 512); EnsureCapacity(256, 512);
} }
/// <summary>Returns a pooled MeshItem.</summary> /// <summary>Returns a pooled MeshItem.</summary>
public MeshItem NextItem (int vertexCount, int triangleCount) { public MeshItem NextItem (int vertexCount, int triangleCount) {
MeshItem item = freeItems.Count > 0 ? freeItems.Dequeue() : new MeshItem(); MeshItem item = freeItems.Count > 0 ? freeItems.Dequeue() : new MeshItem();
if (item.vertices.Length < vertexCount) item.vertices = new VertexPositionColorTextureColor[vertexCount]; if (item.vertices.Length < vertexCount) item.vertices = new VertexPositionColorTextureColor[vertexCount];
if (item.triangles.Length < triangleCount) item.triangles = new int[triangleCount]; if (item.triangles.Length < triangleCount) item.triangles = new int[triangleCount];
item.vertexCount = vertexCount; item.vertexCount = vertexCount;
item.triangleCount = triangleCount; item.triangleCount = triangleCount;
items.Add(item); items.Add(item);
return item; return item;
} }
private void EnsureCapacity (int vertexCount, int triangleCount) { private void EnsureCapacity (int vertexCount, int triangleCount) {
if (vertexArray.Length < vertexCount) vertexArray = new VertexPositionColorTextureColor[vertexCount]; if (vertexArray.Length < vertexCount) vertexArray = new VertexPositionColorTextureColor[vertexCount];
if (triangles.Length < triangleCount) triangles = new short[triangleCount]; if (triangles.Length < triangleCount) triangles = new short[triangleCount];
} }
public void Draw (GraphicsDevice device) { public void Draw (GraphicsDevice device) {
if (items.Count == 0) return; if (items.Count == 0) return;
int itemCount = items.Count; int itemCount = items.Count;
int vertexCount = 0, triangleCount = 0; int vertexCount = 0, triangleCount = 0;
for (int i = 0; i < itemCount; i++) { for (int i = 0; i < itemCount; i++) {
MeshItem item = items[i]; MeshItem item = items[i];
vertexCount += item.vertexCount; vertexCount += item.vertexCount;
triangleCount += item.triangleCount; triangleCount += item.triangleCount;
} }
EnsureCapacity(vertexCount, triangleCount); EnsureCapacity(vertexCount, triangleCount);
vertexCount = 0; vertexCount = 0;
triangleCount = 0; triangleCount = 0;
Texture2D lastTexture = null; Texture2D lastTexture = null;
for (int i = 0; i < itemCount; i++) { for (int i = 0; i < itemCount; i++) {
MeshItem item = items[i]; MeshItem item = items[i];
int itemVertexCount = item.vertexCount; int itemVertexCount = item.vertexCount;
if (item.texture != lastTexture || vertexCount + itemVertexCount > short.MaxValue) { if (item.texture != lastTexture || vertexCount + itemVertexCount > short.MaxValue) {
FlushVertexArray(device, vertexCount, triangleCount); FlushVertexArray(device, vertexCount, triangleCount);
vertexCount = 0; vertexCount = 0;
triangleCount = 0; triangleCount = 0;
lastTexture = item.texture; lastTexture = item.texture;
device.Textures[0] = lastTexture; device.Textures[0] = lastTexture;
if (item.textureLayers != null) { if (item.textureLayers != null) {
for (int layer = 1; layer < item.textureLayers.Length; ++layer) for (int layer = 1; layer < item.textureLayers.Length; ++layer)
device.Textures[layer] = item.textureLayers[layer]; device.Textures[layer] = item.textureLayers[layer];
} }
} }
int[] itemTriangles = item.triangles; int[] itemTriangles = item.triangles;
int itemTriangleCount = item.triangleCount; int itemTriangleCount = item.triangleCount;
for (int ii = 0, t = triangleCount; ii < itemTriangleCount; ii++, t++) for (int ii = 0, t = triangleCount; ii < itemTriangleCount; ii++, t++)
triangles[t] = (short)(itemTriangles[ii] + vertexCount); triangles[t] = (short)(itemTriangles[ii] + vertexCount);
triangleCount += itemTriangleCount; triangleCount += itemTriangleCount;
Array.Copy(item.vertices, 0, vertexArray, vertexCount, itemVertexCount); Array.Copy(item.vertices, 0, vertexArray, vertexCount, itemVertexCount);
vertexCount += itemVertexCount; vertexCount += itemVertexCount;
} }
FlushVertexArray(device, vertexCount, triangleCount); FlushVertexArray(device, vertexCount, triangleCount);
} }
public void AfterLastDrawPass () { public void AfterLastDrawPass () {
int itemCount = items.Count; int itemCount = items.Count;
for (int i = 0; i < itemCount; i++) { for (int i = 0; i < itemCount; i++) {
var item = items[i]; var item = items[i];
item.texture = null; item.texture = null;
freeItems.Enqueue(item); freeItems.Enqueue(item);
} }
items.Clear(); items.Clear();
} }
private void FlushVertexArray (GraphicsDevice device, int vertexCount, int triangleCount) { private void FlushVertexArray (GraphicsDevice device, int vertexCount, int triangleCount) {
if (vertexCount == 0) return; if (vertexCount == 0) return;
device.DrawUserIndexedPrimitives( device.DrawUserIndexedPrimitives(
PrimitiveType.TriangleList, PrimitiveType.TriangleList,
vertexArray, 0, vertexCount, vertexArray, 0, vertexCount,
triangles, 0, triangleCount / 3, triangles, 0, triangleCount / 3,
VertexPositionColorTextureColor.VertexDeclaration); VertexPositionColorTextureColor.VertexDeclaration);
} }
} }
public class MeshItem { public class MeshItem {
public Texture2D texture = null; public Texture2D texture = null;
public Texture2D[] textureLayers = null; public Texture2D[] textureLayers = null;
public int vertexCount, triangleCount; public int vertexCount, triangleCount;
public VertexPositionColorTextureColor[] vertices = { }; public VertexPositionColorTextureColor[] vertices = { };
public int[] triangles = { }; public int[] triangles = { };
} }
} }

View File

@ -1,79 +1,79 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2020, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement: * conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license * http://esotericsoftware.com/spine-editor-license
* *
* Otherwise, it is permitted to integrate the Spine Runtimes into software * Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively, * or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own * "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
using System; using System;
using System.IO; using System.IO;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
#if WINDOWS_STOREAPP #if WINDOWS_STOREAPP
using System.Threading.Tasks; using System.Threading.Tasks;
using Windows.Storage; using Windows.Storage;
#endif #endif
namespace Spine { namespace Spine {
static public class Util { static public class Util {
#if WINDOWS_STOREAPP #if WINDOWS_STOREAPP
private static async Task<Texture2D> LoadFile(GraphicsDevice device, String path) { private static async Task<Texture2D> LoadFile(GraphicsDevice device, String path) {
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation; var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
var file = await folder.GetFileAsync(path).AsTask().ConfigureAwait(false); var file = await folder.GetFileAsync(path).AsTask().ConfigureAwait(false);
try { try {
return Util.LoadTexture(device, await file.OpenStreamForReadAsync().ConfigureAwait(false)); return Util.LoadTexture(device, await file.OpenStreamForReadAsync().ConfigureAwait(false));
} catch (Exception ex) { } catch (Exception ex) {
throw new Exception("Error reading texture file: " + path, ex); throw new Exception("Error reading texture file: " + path, ex);
} }
} }
static public Texture2D LoadTexture (GraphicsDevice device, String path) { static public Texture2D LoadTexture (GraphicsDevice device, String path) {
return LoadFile(device, path).Result; return LoadFile(device, path).Result;
} }
#else #else
static public Texture2D LoadTexture (GraphicsDevice device, String path) { static public Texture2D LoadTexture (GraphicsDevice device, String path) {
#if WINDOWS_PHONE #if WINDOWS_PHONE
Stream stream = Microsoft.Xna.Framework.TitleContainer.OpenStream(path); Stream stream = Microsoft.Xna.Framework.TitleContainer.OpenStream(path);
using (Stream input = stream) { using (Stream input = stream) {
#else #else
using (Stream input = new FileStream(path, FileMode.Open, FileAccess.Read)) { using (Stream input = new FileStream(path, FileMode.Open, FileAccess.Read)) {
#endif #endif
try { try {
return Util.LoadTexture(device, input); return Util.LoadTexture(device, input);
} catch (Exception ex) { } catch (Exception ex) {
throw new Exception("Error reading texture file: " + path, ex); throw new Exception("Error reading texture file: " + path, ex);
} }
} }
} }
#endif #endif
static public Texture2D LoadTexture (GraphicsDevice device, Stream input) { static public Texture2D LoadTexture (GraphicsDevice device, Stream input) {
return Texture2D.FromStream(device, input); return Texture2D.FromStream(device, input);
} }
} }
} }

View File

@ -1,94 +1,94 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2020, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement: * conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license * http://esotericsoftware.com/spine-editor-license
* *
* Otherwise, it is permitted to integrate the Spine Runtimes into software * Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively, * or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own * "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
using System; using System;
using System.IO; using System.IO;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
namespace Spine { namespace Spine {
public class XnaTextureLoader : TextureLoader { public class XnaTextureLoader : TextureLoader {
GraphicsDevice device; GraphicsDevice device;
string[] textureLayerSuffixes = null; string[] textureLayerSuffixes = null;
/// <summary> /// <summary>
/// Constructor. /// Constructor.
/// </summary> /// </summary>
/// <param name="device">The graphics device to be used.</param> /// <param name="device">The graphics device to be used.</param>
/// <param name="loadMultipleTextureLayers">If <c>true</c> multiple textures layers /// <param name="loadMultipleTextureLayers">If <c>true</c> multiple textures layers
/// (e.g. a diffuse/albedo texture and a normal map) are loaded instead of a single texture. /// (e.g. a diffuse/albedo texture and a normal map) are loaded instead of a single texture.
/// Names are constructed based on suffixes added according to the <c>textureSuffixes</c> parameter.</param> /// Names are constructed based on suffixes added according to the <c>textureSuffixes</c> parameter.</param>
/// <param name="textureSuffixes">If <c>loadMultipleTextureLayers</c> is <c>true</c>, the strings of this array /// <param name="textureSuffixes">If <c>loadMultipleTextureLayers</c> is <c>true</c>, the strings of this array
/// define the path name suffix of each layer to be loaded. Array size must be equal to the number of layers to be loaded. /// define the path name suffix of each layer to be loaded. Array size must be equal to the number of layers to be loaded.
/// The first array entry is the suffix to be <c>replaced</c> (e.g. "_albedo", or "" for a first layer without a suffix), /// The first array entry is the suffix to be <c>replaced</c> (e.g. "_albedo", or "" for a first layer without a suffix),
/// subsequent array entries contain the suffix to replace the first entry with (e.g. "_normals"). /// subsequent array entries contain the suffix to replace the first entry with (e.g. "_normals").
/// ///
/// An example would be: /// An example would be:
/// <code>new string[] { "", "_normals" }</code> for loading a base diffuse texture named "skeletonname.png" and /// <code>new string[] { "", "_normals" }</code> for loading a base diffuse texture named "skeletonname.png" and
/// a normalmap named "skeletonname_normals.png".</param> /// a normalmap named "skeletonname_normals.png".</param>
public XnaTextureLoader (GraphicsDevice device, bool loadMultipleTextureLayers = false, string[] textureSuffixes = null) { public XnaTextureLoader (GraphicsDevice device, bool loadMultipleTextureLayers = false, string[] textureSuffixes = null) {
this.device = device; this.device = device;
if (loadMultipleTextureLayers) if (loadMultipleTextureLayers)
this.textureLayerSuffixes = textureSuffixes; this.textureLayerSuffixes = textureSuffixes;
} }
public void Load (AtlasPage page, String path) { public void Load (AtlasPage page, String path) {
Texture2D texture = Util.LoadTexture(device, path); Texture2D texture = Util.LoadTexture(device, path);
page.width = texture.Width; page.width = texture.Width;
page.height = texture.Height; page.height = texture.Height;
if (textureLayerSuffixes == null) { if (textureLayerSuffixes == null) {
page.rendererObject = texture; page.rendererObject = texture;
} }
else { else {
Texture2D[] textureLayersArray = new Texture2D[textureLayerSuffixes.Length]; Texture2D[] textureLayersArray = new Texture2D[textureLayerSuffixes.Length];
textureLayersArray[0] = texture; textureLayersArray[0] = texture;
for (int layer = 1; layer < textureLayersArray.Length; ++layer) { for (int layer = 1; layer < textureLayersArray.Length; ++layer) {
string layerPath = GetLayerName(path, textureLayerSuffixes[0], textureLayerSuffixes[layer]); string layerPath = GetLayerName(path, textureLayerSuffixes[0], textureLayerSuffixes[layer]);
textureLayersArray[layer] = Util.LoadTexture(device, layerPath); textureLayersArray[layer] = Util.LoadTexture(device, layerPath);
} }
page.rendererObject = textureLayersArray; page.rendererObject = textureLayersArray;
} }
} }
public void Unload (Object texture) { public void Unload (Object texture) {
((Texture2D)texture).Dispose(); ((Texture2D)texture).Dispose();
} }
private string GetLayerName (string firstLayerPath, string firstLayerSuffix, string replacementSuffix) { private string GetLayerName (string firstLayerPath, string firstLayerSuffix, string replacementSuffix) {
int suffixLocation = firstLayerPath.LastIndexOf(firstLayerSuffix + "."); int suffixLocation = firstLayerPath.LastIndexOf(firstLayerSuffix + ".");
if (suffixLocation == -1) { if (suffixLocation == -1) {
throw new Exception(string.Concat("Error composing texture layer name: first texture layer name '", firstLayerPath, throw new Exception(string.Concat("Error composing texture layer name: first texture layer name '", firstLayerPath,
"' does not contain suffix to be replaced: '", firstLayerSuffix, "'")); "' does not contain suffix to be replaced: '", firstLayerSuffix, "'"));
} }
return firstLayerPath.Remove(suffixLocation, firstLayerSuffix.Length).Insert(suffixLocation, replacementSuffix); return firstLayerPath.Remove(suffixLocation, firstLayerSuffix.Length).Insert(suffixLocation, replacementSuffix);
} }
} }
} }