diff --git a/include/scratchcpp/igraphicseffect.h b/include/scratchcpp/igraphicseffect.h index 7520cfc4..cc3a58eb 100644 --- a/include/scratchcpp/igraphicseffect.h +++ b/include/scratchcpp/igraphicseffect.h @@ -17,6 +17,9 @@ class LIBSCRATCHCPP_EXPORT IGraphicsEffect /*! Returns the name of the graphics effect. */ virtual std::string name() const = 0; + + /*! Returns the clamped value of the graphic effect. */ + virtual double clamp(double value) const = 0; }; } // namespace libscratchcpp diff --git a/src/scratch/sound.cpp b/src/scratch/sound.cpp index e4270b72..eca5e8b9 100644 --- a/src/scratch/sound.cpp +++ b/src/scratch/sound.cpp @@ -11,11 +11,6 @@ using namespace libscratchcpp; -static std::unordered_map> EFFECT_RANGE = { - { Sound::Effect::Pitch, { -360, 360 } }, // -3 to 3 octaves - { Sound::Effect::Pan, { -100, 100 } } // // 100% left to 100% right -}; - /*! Constructs Sound. */ Sound::Sound(const std::string &name, const std::string &id, const std::string &format) : Asset(name, id, format), @@ -56,13 +51,6 @@ void Sound::setVolume(double volume) /*! Sets the value of the given sound effect. */ void Sound::setEffect(Effect effect, double value) { - auto it = EFFECT_RANGE.find(effect); - - if (it == EFFECT_RANGE.cend()) - return; - - value = std::clamp(value, it->second.first, it->second.second); - switch (effect) { case Effect::Pitch: { // Convert from linear diff --git a/src/scratch/target.cpp b/src/scratch/target.cpp index 5da5129e..d2b25da0 100644 --- a/src/scratch/target.cpp +++ b/src/scratch/target.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -16,6 +17,11 @@ using namespace libscratchcpp; static const std::unordered_set RESERVED_NAMES = { "_mouse_", "_stage_", "_edge_", "_myself_", "_random_" }; +static std::unordered_map> SOUND_EFFECT_RANGE = { + { Sound::Effect::Pitch, { -360, 360 } }, // -3 to 3 octaves + { Sound::Effect::Pan, { -100, 100 } } // // 100% left to 100% right +}; + /*! Constructs target. */ Target::Target() : impl(spimpl::make_unique_impl()) @@ -436,6 +442,12 @@ double Target::soundEffectValue(Sound::Effect effect) const /*! Sets the value of the given sound effect. */ void Target::setSoundEffectValue(Sound::Effect effect, double value) { + auto it = SOUND_EFFECT_RANGE.find(effect); + + if (it == SOUND_EFFECT_RANGE.cend()) + return; + + value = std::clamp(value, it->second.first, it->second.second); impl->soundEffects[effect] = value; for (auto sound : impl->sounds) { @@ -540,7 +552,8 @@ double Target::graphicsEffectValue(IGraphicsEffect *effect) const /*! Sets the value of the given graphics effect. */ void Target::setGraphicsEffectValue(IGraphicsEffect *effect, double value) { - impl->graphicsEffects[effect] = value; + assert(effect); + impl->graphicsEffects[effect] = effect->clamp(value); } /*! Sets the value of all graphics effects to 0 (clears them). */ diff --git a/test/assets/sound_test.cpp b/test/assets/sound_test.cpp index 5fd8c636..dc13e0f7 100644 --- a/test/assets/sound_test.cpp +++ b/test/assets/sound_test.cpp @@ -84,9 +84,6 @@ TEST_F(SoundTest, SetEffect) Sound sound("sound1", "a", "wav"); // Pitch - EXPECT_CALL(*m_player, setPitch(0.125)); - sound.setEffect(Sound::Effect::Pitch, -400); - EXPECT_CALL(*m_player, setPitch(0.125)); sound.setEffect(Sound::Effect::Pitch, -360); @@ -102,13 +99,7 @@ TEST_F(SoundTest, SetEffect) EXPECT_CALL(*m_player, setPitch(8)); sound.setEffect(Sound::Effect::Pitch, 360); - EXPECT_CALL(*m_player, setPitch(8)); - sound.setEffect(Sound::Effect::Pitch, 400); - // Pan - EXPECT_CALL(*m_player, setPan(-1)); - sound.setEffect(Sound::Effect::Pan, -150); - EXPECT_CALL(*m_player, setPan(-1)); sound.setEffect(Sound::Effect::Pan, -100); @@ -123,9 +114,6 @@ TEST_F(SoundTest, SetEffect) EXPECT_CALL(*m_player, setPan(1)); sound.setEffect(Sound::Effect::Pan, 100); - - EXPECT_CALL(*m_player, setPan(1)); - sound.setEffect(Sound::Effect::Pan, 150); } TEST_F(SoundTest, Start) diff --git a/test/blocks/looks_blocks_test.cpp b/test/blocks/looks_blocks_test.cpp index c5fa40ef..6e691c76 100644 --- a/test/blocks/looks_blocks_test.cpp +++ b/test/blocks/looks_blocks_test.cpp @@ -22,6 +22,8 @@ using namespace libscratchcpp; using ::testing::Return; +using ::testing::ReturnArg; +using ::testing::_; class LooksBlocksTest : public testing::Test { @@ -857,6 +859,14 @@ static void initEffects() LooksBlocks::m_mosaicEffect = ScratchConfiguration::getGraphicsEffect("mosaic"); LooksBlocks::m_brightnessEffect = ScratchConfiguration::getGraphicsEffect("brightness"); LooksBlocks::m_ghostEffect = ScratchConfiguration::getGraphicsEffect("ghost"); + + EXPECT_CALL(*colorEffect, clamp(_)).WillRepeatedly(ReturnArg<0>()); + EXPECT_CALL(*fisheyeEffect, clamp(_)).WillRepeatedly(ReturnArg<0>()); + EXPECT_CALL(*whirlEffect, clamp(_)).WillRepeatedly(ReturnArg<0>()); + EXPECT_CALL(*pixelateEffect, clamp(_)).WillRepeatedly(ReturnArg<0>()); + EXPECT_CALL(*mosaicEffect, clamp(_)).WillRepeatedly(ReturnArg<0>()); + EXPECT_CALL(*brightnessEffect, clamp(_)).WillRepeatedly(ReturnArg<0>()); + EXPECT_CALL(*ghostEffect, clamp(_)).WillRepeatedly(ReturnArg<0>()); } static void removeEffects() @@ -888,6 +898,8 @@ TEST_F(LooksBlocksTest, ChangeEffectByImpl) static Value constValues[] = { 0, 55.15, 1, -40.54, 1.2, 2.3, -3.4, -4.5, 0.5, -8.54, 0.01 }; GraphicsEffectMock effect1, effect2; + EXPECT_CALL(effect1, clamp(_)).WillRepeatedly(ReturnArg<0>()); + EXPECT_CALL(effect2, clamp(_)).WillRepeatedly(ReturnArg<0>()); Target target; target.setGraphicsEffectValue(&effect1, 12.5); @@ -1164,6 +1176,8 @@ TEST_F(LooksBlocksTest, SetEffectToImpl) static Value constValues[] = { 0, 55.15, 1, -40.54, 1.2, 2.3, -3.4, -4.5, 0.5, -8.54, 0.01 }; GraphicsEffectMock effect1, effect2; + EXPECT_CALL(effect1, clamp(_)).WillRepeatedly(ReturnArg<0>()); + EXPECT_CALL(effect2, clamp(_)).WillRepeatedly(ReturnArg<0>()); Target target; target.setGraphicsEffectValue(&effect1, 12.5); @@ -1283,6 +1297,8 @@ TEST_F(LooksBlocksTest, ClearGraphicEffectsImpl) Target target; GraphicsEffectMock effect1, effect2; + EXPECT_CALL(effect1, clamp(_)).WillRepeatedly(ReturnArg<0>()); + EXPECT_CALL(effect2, clamp(_)).WillRepeatedly(ReturnArg<0>()); target.setGraphicsEffectValue(&effect1, 48.21); target.setGraphicsEffectValue(&effect2, -107.08); diff --git a/test/mocks/graphicseffectmock.h b/test/mocks/graphicseffectmock.h index 49500ac2..7ddc71ce 100644 --- a/test/mocks/graphicseffectmock.h +++ b/test/mocks/graphicseffectmock.h @@ -9,4 +9,6 @@ class GraphicsEffectMock : public IGraphicsEffect { public: MOCK_METHOD(std::string, name, (), (const, override)); + + MOCK_METHOD(double, clamp, (double), (const, override)); }; diff --git a/test/scratch_classes/sprite_test.cpp b/test/scratch_classes/sprite_test.cpp index 23c778d6..1003c730 100644 --- a/test/scratch_classes/sprite_test.cpp +++ b/test/scratch_classes/sprite_test.cpp @@ -853,24 +853,22 @@ TEST(SpriteTest, GraphicsEffects) EngineMock engine; sprite.setEngine(&engine); - EXPECT_CALL(engine, requestRedraw()).Times(3); + EXPECT_CALL(engine, requestRedraw()).Times(4); GraphicsEffectMock effect1, effect2; + EXPECT_CALL(effect1, clamp(48.21)).WillOnce(Return(48.21)); sprite.setGraphicsEffectValue(&effect1, 48.21); ASSERT_EQ(sprite.graphicsEffectValue(&effect1), 48.21); ASSERT_EQ(sprite.graphicsEffectValue(&effect2), 0); + EXPECT_CALL(effect2, clamp(-107.08)).WillOnce(Return(-107.08)); sprite.setGraphicsEffectValue(&effect2, -107.08); ASSERT_EQ(sprite.graphicsEffectValue(&effect1), 48.21); ASSERT_EQ(sprite.graphicsEffectValue(&effect2), -107.08); - sprite.clearGraphicsEffects(); - ASSERT_EQ(sprite.graphicsEffectValue(&effect1), 0); - ASSERT_EQ(sprite.graphicsEffectValue(&effect2), 0); - - sprite.setVisible(false); - sprite.setGraphicsEffectValue(&effect2, -107.08); - ASSERT_EQ(sprite.graphicsEffectValue(&effect1), 0); + EXPECT_CALL(effect1, clamp(300)).WillOnce(Return(101.5)); + sprite.setGraphicsEffectValue(&effect1, 300); + ASSERT_EQ(sprite.graphicsEffectValue(&effect1), 101.5); ASSERT_EQ(sprite.graphicsEffectValue(&effect2), -107.08); sprite.clearGraphicsEffects(); diff --git a/test/scratch_classes/stage_test.cpp b/test/scratch_classes/stage_test.cpp index ee69c187..22851a51 100644 --- a/test/scratch_classes/stage_test.cpp +++ b/test/scratch_classes/stage_test.cpp @@ -248,17 +248,24 @@ TEST(StageTest, GraphicsEffects) EngineMock engine; stage.setEngine(&engine); - EXPECT_CALL(engine, requestRedraw()).Times(3); + EXPECT_CALL(engine, requestRedraw()).Times(4); GraphicsEffectMock effect1, effect2; + EXPECT_CALL(effect1, clamp(48.21)).WillOnce(Return(48.21)); stage.setGraphicsEffectValue(&effect1, 48.21); ASSERT_EQ(stage.graphicsEffectValue(&effect1), 48.21); ASSERT_EQ(stage.graphicsEffectValue(&effect2), 0); + EXPECT_CALL(effect2, clamp(-107.08)).WillOnce(Return(-107.08)); stage.setGraphicsEffectValue(&effect2, -107.08); ASSERT_EQ(stage.graphicsEffectValue(&effect1), 48.21); ASSERT_EQ(stage.graphicsEffectValue(&effect2), -107.08); + EXPECT_CALL(effect1, clamp(300)).WillOnce(Return(101.5)); + stage.setGraphicsEffectValue(&effect1, 300); + ASSERT_EQ(stage.graphicsEffectValue(&effect1), 101.5); + ASSERT_EQ(stage.graphicsEffectValue(&effect2), -107.08); + stage.clearGraphicsEffects(); ASSERT_EQ(stage.graphicsEffectValue(&effect1), 0); ASSERT_EQ(stage.graphicsEffectValue(&effect2), 0); diff --git a/test/scratch_classes/target_test.cpp b/test/scratch_classes/target_test.cpp index 3b39ed28..932b78d6 100644 --- a/test/scratch_classes/target_test.cpp +++ b/test/scratch_classes/target_test.cpp @@ -519,13 +519,36 @@ TEST(TargetTest, SoundEffects) ASSERT_EQ(target.soundEffectValue(Sound::Effect::Pan), 0); auto s1 = std::make_shared(); + EXPECT_CALL(*s1, setVolume); + target.addSound(s1); + + EXPECT_CALL(*s1, setEffect(Sound::Effect::Pitch, -360)); + target.setSoundEffectValue(Sound::Effect::Pitch, -400); + ASSERT_EQ(target.soundEffectValue(Sound::Effect::Pitch), -360); + + EXPECT_CALL(*s1, setEffect(Sound::Effect::Pitch, 360)); + target.setSoundEffectValue(Sound::Effect::Pitch, 400); + ASSERT_EQ(target.soundEffectValue(Sound::Effect::Pitch), 360); + + EXPECT_CALL(*s1, setEffect(Sound::Effect::Pan, -100)); + target.setSoundEffectValue(Sound::Effect::Pan, -200); + ASSERT_EQ(target.soundEffectValue(Sound::Effect::Pan), -100); + + EXPECT_CALL(*s1, setEffect(Sound::Effect::Pan, 100)); + target.setSoundEffectValue(Sound::Effect::Pan, 200); + ASSERT_EQ(target.soundEffectValue(Sound::Effect::Pan), 100); + + EXPECT_CALL(*s1, setEffect(Sound::Effect::Pitch, 0)); + EXPECT_CALL(*s1, setEffect(Sound::Effect::Pan, 0)); + target.clearSoundEffects(); + ASSERT_EQ(target.soundEffectValue(Sound::Effect::Pitch), 0); + ASSERT_EQ(target.soundEffectValue(Sound::Effect::Pan), 0); + auto s2 = std::make_shared(); auto s3 = std::make_shared(); - EXPECT_CALL(*s1, setVolume); EXPECT_CALL(*s2, setVolume); EXPECT_CALL(*s3, setVolume); - target.addSound(s1); target.addSound(s2); target.addSound(s3); @@ -727,14 +750,21 @@ TEST(TargetTest, GraphicsEffects) target.setEngine(&engine); GraphicsEffectMock effect1, effect2; + EXPECT_CALL(effect1, clamp(48.21)).WillOnce(Return(48.21)); target.setGraphicsEffectValue(&effect1, 48.21); ASSERT_EQ(target.graphicsEffectValue(&effect1), 48.21); ASSERT_EQ(target.graphicsEffectValue(&effect2), 0); + EXPECT_CALL(effect2, clamp(-107.08)).WillOnce(Return(-107.08)); target.setGraphicsEffectValue(&effect2, -107.08); ASSERT_EQ(target.graphicsEffectValue(&effect1), 48.21); ASSERT_EQ(target.graphicsEffectValue(&effect2), -107.08); + EXPECT_CALL(effect1, clamp(300)).WillOnce(Return(101.5)); + target.setGraphicsEffectValue(&effect1, 300); + ASSERT_EQ(target.graphicsEffectValue(&effect1), 101.5); + ASSERT_EQ(target.graphicsEffectValue(&effect2), -107.08); + target.clearGraphicsEffects(); ASSERT_EQ(target.graphicsEffectValue(&effect1), 0); ASSERT_EQ(target.graphicsEffectValue(&effect2), 0);