Asset_Create_Sprite_ShouldRecreateSpriteAssetFileWithTheSameAssetId_WhenSpriteAssetFileAlreadyExists_GivenTextureAssetFilePath_And_KeepAssetId()
        {
            // Arrange
            var pngFilePathToCopy    = Utils.GetPathUnderTestDirectory(@"Assets\TestTexture.png");
            var pngFilePathInTempDir = Path.Combine(_temporaryDirectory.Path, "TestTexture.png");

            File.Copy(pngFilePathToCopy, pngFilePathInTempDir);

            var textureAssetFilePathToCopy    = Utils.GetPathUnderTestDirectory(AssetFileUtils.AppendExtension(@"Assets\TestTexture"));
            var textureAssetFilePathInTempDir = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("TestTexture"));

            File.Copy(textureAssetFilePathToCopy, textureAssetFilePathInTempDir);

            var spriteAssetFilePath = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("TestTexture.sprite"));

            RunGeishaCli($"asset create sprite \"{textureAssetFilePathInTempDir}\"");

            var originalAssetData = AssetData.Load(spriteAssetFilePath);
            var modifiedAssetData = AssetData.CreateWithJsonContent(originalAssetData.AssetId, originalAssetData.AssetType, new SpriteAssetContent());

            modifiedAssetData.Save(spriteAssetFilePath);

            // Act
            RunGeishaCli($"asset create sprite \"{textureAssetFilePathInTempDir}\" --keep-asset-id");

            // Assert
            var actualAssetData = AssetData.Load(spriteAssetFilePath);

            Assert.That(actualAssetData.AssetId, Is.EqualTo(originalAssetData.AssetId));
            Assert.That(actualAssetData.ReadJsonContent <SpriteAssetContent>().TextureAssetId, Is.EqualTo(AssetsIds.TestTexture.Value));
        }
        public void Asset_Create_SpriteAnimation_ShouldCreateSpriteAnimationAssetFileInSpecifiedDirectory_GivenPathToDirectoryAndFiles()
        {
            // Arrange
            CopyAnimationFiles();

            // Act
            RunGeishaCli(
                $"asset create sprite-animation \"{_temporaryDirectory.Path}\" --files \"{Path.Combine(_temporaryDirectory.Path, "Sprite3.sprite.geisha-asset")}\" \"{Path.Combine(_temporaryDirectory.Path, "Sprite1.sprite.geisha-asset")}\"");

            // Assert
            var spriteAnimationAssetFilePath =
                Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension(new DirectoryInfo(_temporaryDirectory.Path).Name));

            Assert.That(File.Exists(spriteAnimationAssetFilePath), Is.True, "Sprite animation asset file was not created.");

            var assetData = AssetData.Load(spriteAnimationAssetFilePath);

            Assert.That(assetData.AssetId, Is.Not.EqualTo(Guid.Empty));
            Assert.That(assetData.AssetType, Is.EqualTo(AnimationAssetTypes.SpriteAnimation));

            var spriteAnimationAssetContent = assetData.ReadJsonContent <SpriteAnimationAssetContent>();

            Assert.That(spriteAnimationAssetContent.DurationTicks, Is.EqualTo(TimeSpan.FromSeconds(1).Ticks));
            Assert.That(spriteAnimationAssetContent.Frames, Has.Length.EqualTo(2));
            Debug.Assert(spriteAnimationAssetContent.Frames != null, "spriteAnimationAssetContent.Frames != null");
            var frame1 = spriteAnimationAssetContent.Frames[0];
            var frame2 = spriteAnimationAssetContent.Frames[1];

            Assert.That(frame1.SpriteAssetId, Is.EqualTo(AssetsIds.TestSpriteAnimationFrame3.Value));
            Assert.That(frame1.Duration, Is.EqualTo(1.0));
            Assert.That(frame2.SpriteAssetId, Is.EqualTo(AssetsIds.TestSpriteAnimationFrame1.Value));
            Assert.That(frame2.Duration, Is.EqualTo(1.0));
        }
        public void Asset_Create_Texture_ShouldCreateTextureAssetFileInTheSameDirectoryAsTextureFile_GivenTextureFilePath()
        {
            // Arrange
            var pngFilePathToCopy    = Utils.GetPathUnderTestDirectory(@"Assets\TestTexture.png");
            var pngFilePathInTempDir = Path.Combine(_temporaryDirectory.Path, "TestTexture.png");

            File.Copy(pngFilePathToCopy, pngFilePathInTempDir);

            // Act
            RunGeishaCli($"asset create texture \"{pngFilePathInTempDir}\"");

            // Assert
            var textureAssetFilePath = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("TestTexture"));

            Assert.That(File.Exists(textureAssetFilePath), Is.True, "Texture asset file was not created.");

            var assetData = AssetData.Load(textureAssetFilePath);

            Assert.That(assetData.AssetId, Is.Not.EqualTo(Guid.Empty));
            Assert.That(assetData.AssetType, Is.EqualTo(RenderingAssetTypes.Texture));

            var textureAssetContent = assetData.ReadJsonContent <TextureAssetContent>();

            Assert.That(textureAssetContent.TextureFilePath, Is.EqualTo("TestTexture.png"));
        }
        public void Asset_Create_Sound_ShouldRecreateSoundAssetFileWithTheSameAssetId_WhenSoundAssetFileAlreadyExists_GivenKeepAssetId()
        {
            // Arrange
            var mp3FilePathToCopy    = Utils.GetPathUnderTestDirectory(@"Assets\TestSound.mp3");
            var mp3FilePathInTempDir = Path.Combine(_temporaryDirectory.Path, "TestSound.mp3");

            File.Copy(mp3FilePathToCopy, mp3FilePathInTempDir);

            var soundAssetFilePath = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("TestSound"));

            RunGeishaCli($"asset create sound \"{mp3FilePathInTempDir}\"");

            var originalAssetData = AssetData.Load(soundAssetFilePath);
            var modifiedAssetData = AssetData.CreateWithJsonContent(originalAssetData.AssetId, originalAssetData.AssetType, new SoundAssetContent());

            modifiedAssetData.Save(soundAssetFilePath);

            // Act
            RunGeishaCli($"asset create sound \"{mp3FilePathInTempDir}\" --keep-asset-id");

            // Assert
            var actualAssetData = AssetData.Load(soundAssetFilePath);

            Assert.That(actualAssetData.AssetId, Is.EqualTo(originalAssetData.AssetId));
            Assert.That(actualAssetData.ReadJsonContent <SoundAssetContent>().SoundFilePath, Is.EqualTo("TestSound.mp3"));
        }
        public void Asset_Create_Sound_ShouldCreateSoundAssetFileInTheSameDirectoryAsSoundFile_GivenSoundFilePath()
        {
            // Arrange
            var mp3FilePathToCopy    = Utils.GetPathUnderTestDirectory(@"Assets\TestSound.mp3");
            var mp3FilePathInTempDir = Path.Combine(_temporaryDirectory.Path, "TestSound.mp3");

            File.Copy(mp3FilePathToCopy, mp3FilePathInTempDir);

            // Act
            RunGeishaCli($"asset create sound \"{mp3FilePathInTempDir}\"");

            // Assert
            var soundAssetFilePath = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("TestSound"));

            Assert.That(File.Exists(soundAssetFilePath), Is.True, "Sound asset file was not created.");

            var assetData = AssetData.Load(soundAssetFilePath);

            Assert.That(assetData.AssetId, Is.Not.EqualTo(Guid.Empty));
            Assert.That(assetData.AssetType, Is.EqualTo(AudioAssetTypes.Sound));

            var soundAssetContent = assetData.ReadJsonContent <SoundAssetContent>();

            Assert.That(soundAssetContent.SoundFilePath, Is.EqualTo("TestSound.mp3"));
        }
Пример #6
0
        public object LoadAsset(AssetInfo assetInfo, IAssetStore assetStore)
        {
            var fileStream         = _fileSystem.GetFile(assetInfo.AssetFilePath).OpenRead();
            var assetData          = AssetData.Load(fileStream);
            var spriteAssetContent = assetData.ReadJsonContent <SpriteAssetContent>();

            var textureAssetId = new AssetId(spriteAssetContent.TextureAssetId);

            return(new Sprite(
                       sourceTexture: assetStore.GetAsset <ITexture>(textureAssetId),
                       sourceUV: SerializableVector2.ToVector2(spriteAssetContent.SourceUV),
                       sourceDimensions: SerializableVector2.ToVector2(spriteAssetContent.SourceDimensions),
                       pivot: SerializableVector2.ToVector2(spriteAssetContent.Pivot),
                       pixelsPerUnit: spriteAssetContent.PixelsPerUnit));
        }
Пример #7
0
        public object LoadAsset(AssetInfo assetInfo, IAssetStore assetStore)
        {
            using var assetFileStream = _fileSystem.GetFile(assetInfo.AssetFilePath).OpenRead();
            var assetData           = AssetData.Load(assetFileStream);
            var textureAssetContent = assetData.ReadJsonContent <TextureAssetContent>();

            if (textureAssetContent.TextureFilePath == null)
            {
                throw new InvalidOperationException($"{nameof(TextureAssetContent)}.{nameof(TextureAssetContent.TextureFilePath)} cannot be null.");
            }

            var textureFilePath = PathUtils.GetSiblingPath(assetInfo.AssetFilePath, textureAssetContent.TextureFilePath);

            using var textureFileStream = _fileSystem.GetFile(textureFilePath).OpenRead();
            return(_renderer2D.CreateTexture(textureFileStream));
        }
Пример #8
0
        public void SaveToStreamAndLoadFromStream_AssetData_WithStringContent()
        {
            // Arrange
            var assetData = AssetData.CreateWithStringContent(_assetId, _assetType, StringContent);

            // Act
            using var memoryStream = new MemoryStream();
            assetData.Save(memoryStream);
            memoryStream.Position = 0;
            var actual = AssetData.Load(memoryStream);

            // Assert
            Assert.That(actual.AssetId, Is.EqualTo(_assetId));
            Assert.That(actual.AssetType, Is.EqualTo(_assetType));
            Assert.That(assetData.ContentFormat, Is.EqualTo(AssetData.AssetContentFormat.String));
            Assert.That(actual.ReadStringContent(), Is.EqualTo(StringContent));
        }
        public void SaveToFileAndLoadFromFile_AssetData_WithStringContent()
        {
            // Arrange
            var assetData = AssetData.CreateWithStringContent(_assetId, _assetType, StringContent);

            // Act
            var filePath = _temporaryDirectory.GetRandomFilePath();

            assetData.Save(filePath);
            var actual = AssetData.Load(filePath);

            // Assert
            Assert.That(actual.AssetId, Is.EqualTo(_assetId));
            Assert.That(actual.AssetType, Is.EqualTo(_assetType));
            Assert.That(assetData.ContentFormat, Is.EqualTo(AssetData.AssetContentFormat.String));
            Assert.That(actual.ReadStringContent(), Is.EqualTo(StringContent));
        }
        public void SaveToFileAndLoadFromFile_AssetData_WithBinaryContent()
        {
            // Arrange
            var assetData = AssetData.CreateWithBinaryContent(_assetId, _assetType, _binaryContent);

            // Act
            var filePath = _temporaryDirectory.GetRandomFilePath();

            assetData.Save(filePath);
            var actual = AssetData.Load(filePath);

            // Assert
            Assert.That(actual.AssetId, Is.EqualTo(_assetId));
            Assert.That(actual.AssetType, Is.EqualTo(_assetType));
            Assert.That(assetData.ContentFormat, Is.EqualTo(AssetData.AssetContentFormat.Binary));
            Assert.That(ReadToEnd(actual.ReadBinaryContent()), Is.EqualTo(_buffer));
        }
Пример #11
0
        public void SaveToStreamAndLoadFromStream_AssetData_WithBinaryContent()
        {
            // Arrange
            var assetData = AssetData.CreateWithBinaryContent(_assetId, _assetType, _binaryContent);

            // Act
            using var memoryStream = new MemoryStream();
            assetData.Save(memoryStream);
            memoryStream.Position = 0;
            var actual = AssetData.Load(memoryStream);

            // Assert
            Assert.That(actual.AssetId, Is.EqualTo(_assetId));
            Assert.That(actual.AssetType, Is.EqualTo(_assetType));
            Assert.That(assetData.ContentFormat, Is.EqualTo(AssetData.AssetContentFormat.Binary));
            Assert.That(ReadToEnd(actual.ReadBinaryContent()), Is.EqualTo(_buffer));
        }
Пример #12
0
        public object LoadAsset(AssetInfo assetInfo, IAssetStore assetStore)
        {
            using var assetFileStream = _fileSystem.GetFile(assetInfo.AssetFilePath).OpenRead();
            var assetData         = AssetData.Load(assetFileStream);
            var soundAssetContent = assetData.ReadJsonContent <SoundAssetContent>();

            var relativeSiblingPath = soundAssetContent.SoundFilePath ??
                                      throw new InvalidOperationException(
                                                $"{nameof(SoundAssetContent)}.{nameof(SoundAssetContent.SoundFilePath)} cannot be null.");

            var soundFilePath = PathUtils.GetSiblingPath(assetInfo.AssetFilePath, relativeSiblingPath);
            var fileExtension = Path.GetExtension(soundFilePath);
            var soundFormat   = SoundFormatParser.ParseFromFileExtension(fileExtension);

            using var soundFileStream = _fileSystem.GetFile(soundFilePath).OpenRead();
            return(_audioBackend.CreateSound(soundFileStream, soundFormat));
        }
Пример #13
0
        public object LoadAsset(AssetInfo assetInfo, IAssetStore assetStore)
        {
            using var fileStream = _fileSystem.GetFile(assetInfo.AssetFilePath).OpenRead();
            var assetData = AssetData.Load(fileStream);
            var spriteAnimationAssetContent = assetData.ReadJsonContent <SpriteAnimationAssetContent>();

            if (spriteAnimationAssetContent.Frames == null)
            {
                throw new InvalidOperationException($"{nameof(SpriteAnimationAssetContent)}.{nameof(SpriteAnimationAssetContent.Frames)} cannot be null.");
            }

            var frames = spriteAnimationAssetContent.Frames.Select(f =>
            {
                var sprite = assetStore.GetAsset <Sprite>(new AssetId(f.SpriteAssetId));
                return(new SpriteAnimationFrame(sprite, f.Duration));
            }).ToArray();

            return(new SpriteAnimation(frames, TimeSpan.FromTicks(spriteAnimationAssetContent.DurationTicks)));
        }
        public void Asset_Create_Sprite_ShouldCreateTextureAssetFileAndSpriteAssetFileInTheSameFolderAsTextureFile_GivenTextureFilePath()
        {
            // Arrange
            var pngFilePathToCopy    = Utils.GetPathUnderTestDirectory(@"Assets\TestTexture.png");
            var pngFilePathInTempDir = Path.Combine(_temporaryDirectory.Path, "TestTexture.png");

            File.Copy(pngFilePathToCopy, pngFilePathInTempDir);

            // Act
            RunGeishaCli($"asset create sprite \"{pngFilePathInTempDir}\"");

            // Assert
            var textureAssetFilePath = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("TestTexture"));

            Assert.That(File.Exists(textureAssetFilePath), Is.True, "Texture asset file was not created.");

            var textureAssetData = AssetData.Load(textureAssetFilePath);

            Assert.That(textureAssetData.AssetId, Is.Not.EqualTo(Guid.Empty));
            Assert.That(textureAssetData.AssetType, Is.EqualTo(RenderingAssetTypes.Texture));
            var textureAssetContent = textureAssetData.ReadJsonContent <TextureAssetContent>();

            Assert.That(textureAssetContent.TextureFilePath, Is.EqualTo("TestTexture.png"));

            var spriteAssetFilePath = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("TestTexture.sprite"));

            Assert.That(File.Exists(spriteAssetFilePath), Is.True, "Sprite asset file was not created.");

            var spriteAssetData = AssetData.Load(spriteAssetFilePath);

            Assert.That(spriteAssetData.AssetId, Is.Not.EqualTo(Guid.Empty));
            Assert.That(spriteAssetData.AssetType, Is.EqualTo(RenderingAssetTypes.Sprite));
            var spriteAssetContent = spriteAssetData.ReadJsonContent <SpriteAssetContent>();

            Assert.That(spriteAssetContent.TextureAssetId, Is.EqualTo(textureAssetData.AssetId.Value));
            Assert.That(spriteAssetContent.SourceUV.X, Is.Zero);
            Assert.That(spriteAssetContent.SourceUV.Y, Is.Zero);
            Assert.That(spriteAssetContent.SourceDimensions.X, Is.EqualTo(10));
            Assert.That(spriteAssetContent.SourceDimensions.Y, Is.EqualTo(10));
            Assert.That(spriteAssetContent.Pivot.X, Is.EqualTo(5));
            Assert.That(spriteAssetContent.Pivot.Y, Is.EqualTo(5));
            Assert.That(spriteAssetContent.PixelsPerUnit, Is.EqualTo(1));
        }
Пример #15
0
        public void SaveToStreamAndLoadFromStream_AssetData_WithJsonContent()
        {
            // Arrange
            var assetData = AssetData.CreateWithJsonContent(_assetId, _assetType, _jsonContent);

            // Act
            using var memoryStream = new MemoryStream();
            assetData.Save(memoryStream);
            memoryStream.Position = 0;
            var actual = AssetData.Load(memoryStream);

            // Assert
            Assert.That(actual.AssetId, Is.EqualTo(_assetId));
            Assert.That(actual.AssetType, Is.EqualTo(_assetType));
            Assert.That(assetData.ContentFormat, Is.EqualTo(AssetData.AssetContentFormat.Json));
            var actualJsonContent = actual.ReadJsonContent <JsonContent>();

            Assert.That(actualJsonContent.IntProperty, Is.EqualTo(_jsonContent.IntProperty));
            Assert.That(actualJsonContent.DoubleProperty, Is.EqualTo(_jsonContent.DoubleProperty));
            Assert.That(actualJsonContent.StringProperty, Is.EqualTo(_jsonContent.StringProperty));
        }
        public void SaveToFileAndLoadFromFile_AssetData_WithJsonContent()
        {
            // Arrange
            var assetData = AssetData.CreateWithJsonContent(_assetId, _assetType, _jsonContent);

            // Act
            var filePath = _temporaryDirectory.GetRandomFilePath();

            assetData.Save(filePath);
            var actual = AssetData.Load(filePath);

            // Assert
            Assert.That(actual.AssetId, Is.EqualTo(_assetId));
            Assert.That(actual.AssetType, Is.EqualTo(_assetType));
            Assert.That(assetData.ContentFormat, Is.EqualTo(AssetData.AssetContentFormat.Json));
            var actualJsonContent = actual.ReadJsonContent <JsonContent>();

            Assert.That(actualJsonContent.IntProperty, Is.EqualTo(_jsonContent.IntProperty));
            Assert.That(actualJsonContent.DoubleProperty, Is.EqualTo(_jsonContent.DoubleProperty));
            Assert.That(actualJsonContent.StringProperty, Is.EqualTo(_jsonContent.StringProperty));
        }
        Asset_Create_InputMapping_ShouldRecreateDefaultInputMappingAssetFileWithTheSameAssetId_WhenInputMappingAssetFileAlreadyExists_GivenKeepAssetId()
        {
            // Arrange
            var inputMappingAssetFilePath = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("DefaultInputMapping"));

            RunGeishaCli("asset create input-mapping", _temporaryDirectory.Path);

            var originalAssetData = AssetData.Load(inputMappingAssetFilePath);
            var modifiedAssetData = AssetData.CreateWithJsonContent(originalAssetData.AssetId, originalAssetData.AssetType, new InputMappingAssetContent());

            modifiedAssetData.Save(inputMappingAssetFilePath);

            // Act
            RunGeishaCli("asset create input-mapping --keep-asset-id", _temporaryDirectory.Path);

            // Assert
            var actualAssetData = AssetData.Load(inputMappingAssetFilePath);

            Assert.That(actualAssetData.AssetId, Is.EqualTo(originalAssetData.AssetId));
            Assert.That(actualAssetData.ReadJsonContent <InputMappingAssetContent>().ActionMappings, Contains.Key("Jump"));
        }
        Asset_Create_SpriteAnimation_ShouldRecreateSpriteAnimationAssetFileWithTheSameAssetId_WhenSpriteAnimationAssetFileAlreadyExists_GivenKeepAssetId()
        {
            // Arrange
            CopyAnimationFiles();

            var spriteAnimationAssetFilePath =
                Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension(new DirectoryInfo(_temporaryDirectory.Path).Name));

            RunGeishaCli($"asset create sprite-animation \"{_temporaryDirectory.Path}\"");

            var originalAssetData = AssetData.Load(spriteAnimationAssetFilePath);
            var modifiedAssetData = AssetData.CreateWithJsonContent(originalAssetData.AssetId, originalAssetData.AssetType, new SpriteAnimationAssetContent());

            modifiedAssetData.Save(spriteAnimationAssetFilePath);

            // Act
            RunGeishaCli($"asset create sprite-animation \"{_temporaryDirectory.Path}\" --keep-asset-id");

            // Assert
            var actualAssetData = AssetData.Load(spriteAnimationAssetFilePath);

            Assert.That(actualAssetData.AssetId, Is.EqualTo(originalAssetData.AssetId));
            Assert.That(actualAssetData.ReadJsonContent <SpriteAnimationAssetContent>().DurationTicks, Is.EqualTo(TimeSpan.FromSeconds(1).Ticks));
        }
        public void Asset_Create_InputMapping_ShouldCreateDefaultInputMappingAssetFileInCurrentDirectory()
        {
            // Arrange
            // Act
            RunGeishaCli("asset create input-mapping", _temporaryDirectory.Path);

            // Assert
            var inputMappingAssetFilePath = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("DefaultInputMapping"));

            Assert.That(File.Exists(inputMappingAssetFilePath), Is.True, "InputMapping asset file was not created.");

            var inputMappingAssetData = AssetData.Load(inputMappingAssetFilePath);

            Assert.That(inputMappingAssetData.AssetId, Is.Not.EqualTo(Guid.Empty));
            Assert.That(inputMappingAssetData.AssetType, Is.EqualTo(InputAssetTypes.InputMapping));

            var inputMappingAssetContent = inputMappingAssetData.ReadJsonContent <InputMappingAssetContent>();

            Assert.That(inputMappingAssetContent.ActionMappings, Contains.Key("Jump"));
            Debug.Assert(inputMappingAssetContent.ActionMappings != null, "inputMappingAssetContent.ActionMappings != null");
            var jumpAction = inputMappingAssetContent.ActionMappings["Jump"];

            Assert.That(jumpAction, Has.Length.EqualTo(2));
            Assert.That(jumpAction[0].Key, Is.EqualTo(Key.Space));
            Assert.That(jumpAction[1].Key, Is.EqualTo(Key.Up));

            Assert.That(inputMappingAssetContent.AxisMappings, Contains.Key("MoveRight"));
            Debug.Assert(inputMappingAssetContent.AxisMappings != null, "inputMappingAssetContent.AxisMappings != null");
            var moveRightAxis = inputMappingAssetContent.AxisMappings["MoveRight"];

            Assert.That(moveRightAxis, Has.Length.EqualTo(2));
            Assert.That(moveRightAxis[0].Key, Is.EqualTo(Key.Right));
            Assert.That(moveRightAxis[0].Scale, Is.EqualTo(1.0));
            Assert.That(moveRightAxis[1].Key, Is.EqualTo(Key.Left));
            Assert.That(moveRightAxis[1].Scale, Is.EqualTo(-1.0));
        }
Пример #20
0
        public object LoadAsset(AssetInfo assetInfo, IAssetStore assetStore)
        {
            using var fileStream = _fileSystem.GetFile(assetInfo.AssetFilePath).OpenRead();
            var assetData = AssetData.Load(fileStream);
            var inputMappingAssetContent = assetData.ReadJsonContent <InputMappingAssetContent>();

            if (inputMappingAssetContent.ActionMappings == null)
            {
                throw new InvalidOperationException($"{nameof(InputMappingAssetContent)}.{nameof(InputMappingAssetContent.ActionMappings)} cannot be null.");
            }
            if (inputMappingAssetContent.AxisMappings == null)
            {
                throw new InvalidOperationException($"{nameof(InputMappingAssetContent)}.{nameof(InputMappingAssetContent.AxisMappings)} cannot be null.");
            }

            var inputMapping = new InputMapping();

            foreach (var(actionName, serializableHardwareActions) in inputMappingAssetContent.ActionMappings)
            {
                var actionMapping = new ActionMapping
                {
                    ActionName = actionName
                };

                foreach (var serializableHardwareAction in serializableHardwareActions)
                {
                    if (serializableHardwareAction.Key != null && serializableHardwareAction.MouseButton == null)
                    {
                        actionMapping.HardwareActions.Add(new HardwareAction
                        {
                            HardwareInputVariant = HardwareInputVariant.CreateKeyboardVariant(serializableHardwareAction.Key.Value)
                        });
                    }
                    else if (serializableHardwareAction.Key == null && serializableHardwareAction.MouseButton != null)
                    {
                        var mouseVariant = serializableHardwareAction.MouseButton switch
                        {
                            MouseButton.LeftButton => HardwareInputVariant.MouseVariant.LeftButton,
                            MouseButton.MiddleButton => HardwareInputVariant.MouseVariant.MiddleButton,
                            MouseButton.RightButton => HardwareInputVariant.MouseVariant.RightButton,
                            MouseButton.XButton1 => HardwareInputVariant.MouseVariant.XButton1,
                            MouseButton.XButton2 => HardwareInputVariant.MouseVariant.XButton2,
                            _ => throw new ArgumentOutOfRangeException(nameof(SerializableHardwareAction.MouseButton), serializableHardwareAction.MouseButton,
                                                                       "Unsupported mouse button found in input mapping.")
                        };

                        actionMapping.HardwareActions.Add(new HardwareAction
                        {
                            HardwareInputVariant = HardwareInputVariant.CreateMouseVariant(mouseVariant)
                        });
                    }
                    else
                    {
                        throw InvalidInputMappingAssetContentException.CreateForInvalidHardwareAction(inputMappingAssetContent);
                    }
                }

                inputMapping.ActionMappings.Add(actionMapping);
            }

            foreach (var(axisName, serializableHardwareAxes) in inputMappingAssetContent.AxisMappings)
            {
                var axisMapping = new AxisMapping
                {
                    AxisName = axisName
                };

                foreach (var serializableHardwareAxis in serializableHardwareAxes)
                {
                    if (serializableHardwareAxis.Key != null && serializableHardwareAxis.MouseAxis == null)
                    {
                        axisMapping.HardwareAxes.Add(new HardwareAxis
                        {
                            HardwareInputVariant = HardwareInputVariant.CreateKeyboardVariant(serializableHardwareAxis.Key.Value),
                            Scale = serializableHardwareAxis.Scale
                        });
                    }
                    else if (serializableHardwareAxis.Key == null && serializableHardwareAxis.MouseAxis != null)
                    {
                        var mouseVariant = serializableHardwareAxis.MouseAxis switch
                        {
                            MouseAxis.AxisX => HardwareInputVariant.MouseVariant.AxisX,
                            MouseAxis.AxisY => HardwareInputVariant.MouseVariant.AxisY,
                            _ => throw new ArgumentOutOfRangeException(nameof(SerializableHardwareAxis.MouseAxis), serializableHardwareAxis.MouseAxis,
                                                                       "Unsupported mouse axis found in input mapping.")
                        };

                        axisMapping.HardwareAxes.Add(new HardwareAxis
                        {
                            HardwareInputVariant = HardwareInputVariant.CreateMouseVariant(mouseVariant),
                            Scale = serializableHardwareAxis.Scale
                        });
                    }
                    else
                    {
                        throw InvalidInputMappingAssetContentException.CreateForInvalidHardwareAxis(inputMappingAssetContent);
                    }
                }

                inputMapping.AxisMappings.Add(axisMapping);
            }

            return(inputMapping);
        }
        public void Asset_Create_Sprite_ShouldCreateSpriteAssetFiles_GivenSpriteParameters(string parameters)
        {
            // Arrange
            var pngFilePathToCopy    = Utils.GetPathUnderTestDirectory(@"Assets\SpriteSheet\TestSpriteSheet.png");
            var pngFilePathInTempDir = Path.Combine(_temporaryDirectory.Path, "TestSpriteSheet.png");

            File.Copy(pngFilePathToCopy, pngFilePathInTempDir);

            var textureAssetFilePathToCopy    = Utils.GetPathUnderTestDirectory(AssetFileUtils.AppendExtension(@"Assets\SpriteSheet\TestSpriteSheet"));
            var textureAssetFilePathInTempDir = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("TestSpriteSheet"));

            File.Copy(textureAssetFilePathToCopy, textureAssetFilePathInTempDir);

            // Act
            RunGeishaCli($"asset create sprite \"{textureAssetFilePathInTempDir}\" {parameters}");

            // Assert
            var spriteAssetFilePath1 = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("TestSpriteSheet_0.sprite"));

            Assert.That(File.Exists(spriteAssetFilePath1), Is.True, "Sprite asset file was not created.");

            var assetData1 = AssetData.Load(spriteAssetFilePath1);

            Assert.That(assetData1.AssetId, Is.Not.EqualTo(Guid.Empty));
            Assert.That(assetData1.AssetType, Is.EqualTo(RenderingAssetTypes.Sprite));
            var spriteAssetContent1 = assetData1.ReadJsonContent <SpriteAssetContent>();

            Assert.That(spriteAssetContent1.TextureAssetId, Is.EqualTo(AssetsIds.SpriteSheet.Texture.Value));
            Assert.That(spriteAssetContent1.SourceUV.X, Is.EqualTo(25));
            Assert.That(spriteAssetContent1.SourceUV.Y, Is.EqualTo(50));
            Assert.That(spriteAssetContent1.SourceDimensions.X, Is.EqualTo(25));
            Assert.That(spriteAssetContent1.SourceDimensions.Y, Is.EqualTo(25));
            Assert.That(spriteAssetContent1.Pivot.X, Is.EqualTo(12.5));
            Assert.That(spriteAssetContent1.Pivot.Y, Is.EqualTo(12.5));
            Assert.That(spriteAssetContent1.PixelsPerUnit, Is.EqualTo(1));

            var spriteAssetFilePath2 = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("TestSpriteSheet_1.sprite"));

            Assert.That(File.Exists(spriteAssetFilePath2), Is.True, "Sprite asset file was not created.");

            var assetData2 = AssetData.Load(spriteAssetFilePath2);

            Assert.That(assetData2.AssetId, Is.Not.EqualTo(Guid.Empty));
            Assert.That(assetData2.AssetType, Is.EqualTo(RenderingAssetTypes.Sprite));
            var spriteAssetContent2 = assetData2.ReadJsonContent <SpriteAssetContent>();

            Assert.That(spriteAssetContent2.TextureAssetId, Is.EqualTo(AssetsIds.SpriteSheet.Texture.Value));
            Assert.That(spriteAssetContent2.SourceUV.X, Is.EqualTo(50));
            Assert.That(spriteAssetContent2.SourceUV.Y, Is.EqualTo(50));
            Assert.That(spriteAssetContent2.SourceDimensions.X, Is.EqualTo(25));
            Assert.That(spriteAssetContent2.SourceDimensions.Y, Is.EqualTo(25));
            Assert.That(spriteAssetContent2.Pivot.X, Is.EqualTo(12.5));
            Assert.That(spriteAssetContent2.Pivot.Y, Is.EqualTo(12.5));
            Assert.That(spriteAssetContent2.PixelsPerUnit, Is.EqualTo(1));

            var spriteAssetFilePath3 = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("TestSpriteSheet_2.sprite"));

            Assert.That(File.Exists(spriteAssetFilePath3), Is.True, "Sprite asset file was not created.");

            var assetData3 = AssetData.Load(spriteAssetFilePath3);

            Assert.That(assetData3.AssetId, Is.Not.EqualTo(Guid.Empty));
            Assert.That(assetData3.AssetType, Is.EqualTo(RenderingAssetTypes.Sprite));
            var spriteAssetContent3 = assetData3.ReadJsonContent <SpriteAssetContent>();

            Assert.That(spriteAssetContent3.TextureAssetId, Is.EqualTo(AssetsIds.SpriteSheet.Texture.Value));
            Assert.That(spriteAssetContent3.SourceUV.X, Is.EqualTo(75));
            Assert.That(spriteAssetContent3.SourceUV.Y, Is.EqualTo(50));
            Assert.That(spriteAssetContent3.SourceDimensions.X, Is.EqualTo(25));
            Assert.That(spriteAssetContent3.SourceDimensions.Y, Is.EqualTo(25));
            Assert.That(spriteAssetContent3.Pivot.X, Is.EqualTo(12.5));
            Assert.That(spriteAssetContent3.Pivot.Y, Is.EqualTo(12.5));
            Assert.That(spriteAssetContent3.PixelsPerUnit, Is.EqualTo(1));

            var spriteAssetFilePath4 = Path.Combine(_temporaryDirectory.Path, AssetFileUtils.AppendExtension("TestSpriteSheet_3.sprite"));

            Assert.That(File.Exists(spriteAssetFilePath4), Is.True, "Sprite asset file was not created.");

            var assetData4 = AssetData.Load(spriteAssetFilePath4);

            Assert.That(assetData4.AssetId, Is.Not.EqualTo(Guid.Empty));
            Assert.That(assetData4.AssetType, Is.EqualTo(RenderingAssetTypes.Sprite));
            var spriteAssetContent4 = assetData4.ReadJsonContent <SpriteAssetContent>();

            Assert.That(spriteAssetContent4.TextureAssetId, Is.EqualTo(AssetsIds.SpriteSheet.Texture.Value));
            Assert.That(spriteAssetContent4.SourceUV.X, Is.EqualTo(0));
            Assert.That(spriteAssetContent4.SourceUV.Y, Is.EqualTo(75));
            Assert.That(spriteAssetContent4.SourceDimensions.X, Is.EqualTo(25));
            Assert.That(spriteAssetContent4.SourceDimensions.Y, Is.EqualTo(25));
            Assert.That(spriteAssetContent4.Pivot.X, Is.EqualTo(12.5));
            Assert.That(spriteAssetContent4.Pivot.Y, Is.EqualTo(12.5));
            Assert.That(spriteAssetContent4.PixelsPerUnit, Is.EqualTo(1));
        }