From 926d968eed33e5ec8c18e423299ca0ca7c23e4c2 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sun, 19 Jul 2020 16:39:35 -0400 Subject: [PATCH] Add sfx block support --- GamecraftModdingAPI/Blocks/BlockTests.cs | 18 +++ GamecraftModdingAPI/Blocks/MusicBlock.cs | 157 +++++++++++++++++++++++ GamecraftModdingAPI/Tests/TestRoot.cs | 7 +- 3 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 GamecraftModdingAPI/Blocks/MusicBlock.cs diff --git a/GamecraftModdingAPI/Blocks/BlockTests.cs b/GamecraftModdingAPI/Blocks/BlockTests.cs index 418fa43..ed42024 100644 --- a/GamecraftModdingAPI/Blocks/BlockTests.cs +++ b/GamecraftModdingAPI/Blocks/BlockTests.cs @@ -1,5 +1,7 @@ using System; +using Gamecraft.Wires; + using GamecraftModdingAPI; using GamecraftModdingAPI.Tests; @@ -72,6 +74,22 @@ namespace GamecraftModdingAPI.Blocks if (!Assert.CloseTo(b.MinimumAngle, -180f, $"Servo.MinimumAngle {b.MinimumAngle} does not equal default value, possibly because it failed silently.", "Servo.MinimumAngle is close enough to default.")) return; if (!Assert.CloseTo(b.MaximumForce, 750f, $"Servo.MaximumForce {b.MaximumForce} does not equal default value, possibly because it failed silently.", "Servo.MaximumForce is close enough to default.")) return; } + + [APITestCase(TestType.EditMode)] + public static void TestMusicBlock() + { + Block newBlock = Block.PlaceNew(BlockIDs.MusicBlock, Unity.Mathematics.float3.zero + 2); + MusicBlock b = null; // Note: the assignment operation is a lambda, which slightly confuses the compiler + Assert.Errorless(() => { b = newBlock.Specialise(); }, "Block.Specialize() raised an exception: ", "Block.Specialize() completed without issue."); + if (!Assert.NotNull(b, "Block.Specialize() returned null, possibly because it failed silently.", "Specialized MusicBlock is not null.")) return; + if (!Assert.CloseTo(b.Volume, 100f, $"MusicBlock.Volume {b.Volume} does not equal default value, possibly because it failed silently.", "MusicBlock.Volume is close enough to default.")) return; + if (!Assert.Equal(b.TrackIndex, 0, $"MusicBlock.TrackIndex {b.TrackIndex} does not equal default value, possibly because it failed silently.", "MusicBlock.TrackIndex is equal to default.")) return; + b.IsPlaying = true; // play sfx + if (!Assert.Equal(b.IsPlaying, true, $"MusicBlock.IsPlaying {b.IsPlaying} does not equal default value, possibly because it failed silently.", "MusicBlock.IsPlaying is set properly.")) return; + if (!Assert.Equal(b.ChannelType, ChannelType.Character, $"MusicBlock.ChannelType {b.ChannelType} does not equal default value, possibly because it failed silently.", "MusicBlock.ChannelType is equal to default.")) return; + //Assert.Log(b.Track.ToString()); + if (!Assert.Equal(b.Track.ToString(), new Guid("3237ff8f-f5f2-4f84-8144-496ca280f8c0").ToString(), $"MusicBlock.Track {b.Track} does not equal default value, possibly because it failed silently.", "MusicBlock.Track is equal to default.")) return; + } } #endif } diff --git a/GamecraftModdingAPI/Blocks/MusicBlock.cs b/GamecraftModdingAPI/Blocks/MusicBlock.cs new file mode 100644 index 0000000..a7f862e --- /dev/null +++ b/GamecraftModdingAPI/Blocks/MusicBlock.cs @@ -0,0 +1,157 @@ +using System; + +using FMOD.Studio; +using FMODUnity; +using Gamecraft.Wires; +using RobocraftX.Blocks; +using Svelto.ECS; +using Unity.Mathematics; + +using GamecraftModdingAPI; +using GamecraftModdingAPI.Utility; + +namespace GamecraftModdingAPI.Blocks +{ + public class MusicBlock : Block + { + public static MusicBlock PlaceNew(float3 position, + float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0, + int uscale = 1, float3 scale = default, Player player = null) + { + if (PlacementEngine.IsInGame && GameState.IsBuildMode()) + { + EGID id = PlacementEngine.PlaceBlock(BlockIDs.MusicBlock, color, darkness, + position, uscale, scale, player, rotation); + return new MusicBlock(id); + } + + return null; + } + + public MusicBlock(EGID id) : base(id) + { + if (!BlockEngine.GetBlockInfoExists(this.Id)) + { + throw new BlockTypeException($"Block is not a {this.GetType().Name} block"); + } + } + + public MusicBlock(uint id) : base(id) + { + if (!BlockEngine.GetBlockInfoExists(this.Id)) + { + throw new BlockTypeException($"Block is not a {this.GetType().Name} block"); + } + } + + public byte TrackIndex + { + get + { + return BlockEngine.GetBlockInfo(Id).trackIndx; + } + + set + { + ref MusicBlockDataEntityStruct msdes = ref BlockEngine.GetBlockInfo(Id); + msdes.trackIndx = value; + } + } + + public Guid Track + { + get + { + ref MusicBlockDataEntityStruct msdes = ref BlockEngine.GetBlockInfo(Id); + return msdes.fmod2DEventPaths.Get(msdes.trackIndx); + } + + set + { + ref MusicBlockDataEntityStruct msdes = ref BlockEngine.GetBlockInfo(Id); + for (byte i = 0; i < msdes.fmod2DEventPaths.Count(); i++) + { + Guid track = msdes.fmod2DEventPaths.Get(i); + if (track == value) + { + msdes.trackIndx = i; + break; + } + } + } + } + + public Guid[] Tracks + { + get + { + ref MusicBlockDataEntityStruct msdes = ref BlockEngine.GetBlockInfo(Id); + Guid[] tracks = new Guid[msdes.fmod2DEventPaths.Count()]; + for (byte i = 0; i < tracks.Length; i++) + { + tracks[i] = msdes.fmod2DEventPaths.Get(i); + } + return tracks; + } + } + + public float Volume + { + get + { + return BlockEngine.GetBlockInfo(Id).tweakableVolume; + } + + set + { + ref MusicBlockDataEntityStruct msdes = ref BlockEngine.GetBlockInfo(Id); + msdes.tweakableVolume = value; + } + } + + public ChannelType ChannelType + { + get + { + return (ChannelType)BlockEngine.GetBlockInfo(Id).channelType; + } + + set + { + ref MusicBlockDataEntityStruct msdes = ref BlockEngine.GetBlockInfo(Id); + msdes.channelType = (byte)value; + } + } + + public bool IsPlaying + { + get + { + return BlockEngine.GetBlockInfo(Id).isPlaying; + } + + set + { + ref MusicBlockDataEntityStruct msdes = ref BlockEngine.GetBlockInfo(Id); + if (msdes.isPlaying == value) return; + if (value) + { + // start playing + EventInstance inst = RuntimeManager.CreateInstance(msdes.fmod2DEventPaths.Get(msdes.trackIndx)); + inst.setVolume(msdes.tweakableVolume / 100f); + inst.start(); + msdes.eventHandle = inst.handle; + } + else + { + // stop playing + EventInstance inst = default(EventInstance); + inst.handle = msdes.eventHandle; + inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); + inst.release(); + } + msdes.isPlaying = value; + } + } + } +} \ No newline at end of file diff --git a/GamecraftModdingAPI/Tests/TestRoot.cs b/GamecraftModdingAPI/Tests/TestRoot.cs index 4e9da73..f39169e 100644 --- a/GamecraftModdingAPI/Tests/TestRoot.cs +++ b/GamecraftModdingAPI/Tests/TestRoot.cs @@ -139,10 +139,9 @@ namespace GamecraftModdingAPI.Tests } yield return Yield.It; app.MyGames[0].EnterGame(); - // returning from a new game without saving will hard lock GC (it's an invalid state) - //Game newGame = Game.NewGame(); - //yield return new WaitForSecondsEnumerator(5).Continue(); // wait for sync - //newGame.EnterGame(); + /*Game newGame = Game.NewGame(); + yield return new WaitForSecondsEnumerator(5).Continue(); // wait for sync + newGame.EnterGame();*/ } private static IEnumerator GameTests()