Commit 679ea4a7 authored by Gerhard Stein's avatar Gerhard Stein

Music Cleanups, Button event improvements on virtual gamepad

parent 324d645a
......@@ -654,6 +654,16 @@ void CInput::ponder()
}
void CInput::flushFingerEvents()
{
if(!mpVirtPad)
return;
mpVirtPad->flush();
}
void CInput::pollEvents()
{
// Semaphore
......@@ -735,7 +745,7 @@ void CInput::pollEvents()
{
transMouseRelCoord(Pos, rotPt, activeArea, tiltedScreen);
if(!mpVirtPad->mouseDown(Pos))
if(!mpVirtPad->mouseFingerState(Pos, Event.tfinger, true))
{
m_EventList.add( new PointingDevEvent( Pos, PDE_BUTTONDOWN ) );
gPointDevice.mPointingState.mActionButton = 1;
......@@ -761,7 +771,7 @@ void CInput::pollEvents()
Event.tfinger.y*float(activeArea.h));
transMouseRelCoord(Pos, rotPt, activeArea, tiltedScreen);
if(!mpVirtPad->mouseUp(Pos))
if(!mpVirtPad->mouseFingerState(Pos, Event.tfinger, false))
{
passSDLEventVec = true;
m_EventList.add( new PointingDevEvent( Pos, PDE_BUTTONUP ) );
......@@ -781,13 +791,33 @@ void CInput::pollEvents()
break;
case SDL_FINGERMOTION: {
const Vector2D<int> rotPt(Event.tfinger.x, Event.tfinger.y);
transMouseRelCoord(Pos, rotPt, activeArea, tiltedScreen);
m_EventList.add(new PointingDevEvent(Pos, PDE_MOVED));
gPointDevice.mPointingState.mPos = Pos;
case SDL_FINGERMOTION:
{
Vector2D<int> rotPt(Event.tfinger.x*float(activeArea.w),
Event.tfinger.y*float(activeArea.h));
//processMouse(Event);
// If Virtual gamepad takes control...
if(gVideoDriver.VGamePadEnabled() && mpVirtPad &&
mpVirtPad->active() )
{
transMouseRelCoord(Pos, rotPt, activeArea, tiltedScreen);
if(!mpVirtPad->mouseFingerState(Pos, Event.tfinger, true))
{
m_EventList.add( new PointingDevEvent( Pos, PDE_BUTTONDOWN ) );
gPointDevice.mPointingState.mActionButton = 1;
gPointDevice.mPointingState.mPos = Pos;
}
}
else
{
const Vector2D<int> rotPt(Event.tfinger.x, Event.tfinger.y);
transMouseRelCoord(Pos, rotPt, activeArea, tiltedScreen);
m_EventList.add(new PointingDevEvent(Pos, PDE_MOVED));
gPointDevice.mPointingState.mPos = Pos;
//processMouse(Event);
}
}
break;
......
......@@ -171,6 +171,11 @@ public:
const GsRect<Uint16> &activeArea,
const bool tiltedScreen);
/**
* @brief flushFingerEvents If some registered finger get stuck, this method cleans up
*/
void flushFingerEvents();
/**
* @brief Called every logic cycle. This triggers the events that occur and process them through various functions
*/
......
......@@ -4,6 +4,7 @@
#include "graphics/GsSurface.h"
#include "graphics/GsTexture.h"
#include <set>
class stInputCommand;
......@@ -62,6 +63,25 @@ public:
bool invisible = true;
GsTexture mTexture;
#if SDL_VERSION_ATLEAST(2, 0, 0)
void clearFingers();
void insertFingerId(const SDL_FingerID fid);
void removeFingerId(const SDL_FingerID fid);
bool hasFingers() const
{
return !mFingerSet.empty();
}
//private:
std::set<SDL_FingerID> mFingerSet;
#endif
};
/**
......@@ -105,6 +125,12 @@ public:
*/
virtual bool ponder() = 0;
/**
* @brief flush
*/
virtual void flush() = 0;
/**
* @brief render is called when it's time to render this object
* @param sfc Reference to surface on which it can be rendered.
......@@ -118,11 +144,26 @@ public:
virtual bool mouseDown(const Vector2D<float> &Pos) = 0;
/**
* @brief mouseDown Mouse Up event when sent when touch event triggered or mouse sends that.
* @brief mouseUp Mouse Up event when sent when touch event triggered or mouse sends that.
* @param Pos Position of the mouse event
*/
virtual bool mouseUp(const Vector2D<float> &Pos) = 0;
#if SDL_VERSION_ATLEAST(2, 0, 0)
/**
* @brief mouseFingerState Event Fingers on touch surfaces
* @param Pos position
* @param touchFingerEvent event sent by SDL
* @return true if something was processed here
*/
virtual bool mouseFingerState(const Vector2D<float> &Pos,
const SDL_TouchFingerEvent &touchFingerEvent,
const bool down) = 0;
#endif
/**
* @brief active Checks if click events happened in the virtual dpad
* @return
......
......@@ -16,6 +16,7 @@
#include "buttonStart.h"
bool TouchButton::loadEmdbeddedPicture(const unsigned char *data,
const unsigned int size)
{
......@@ -23,6 +24,26 @@ bool TouchButton::loadEmdbeddedPicture(const unsigned char *data,
gVideoDriver.Renderer());
}
void TouchButton::clearFingers()
{
mFingerSet.clear();
}
void TouchButton::insertFingerId(const SDL_FingerID fid)
{
mFingerSet.insert(fid);
}
void TouchButton::removeFingerId(const SDL_FingerID fid)
{
auto it = mFingerSet.find(fid);
if(it != mFingerSet.end())
{
mFingerSet.erase(fid);
}
}
bool TouchButton::loadPicture(const std::string &picFile)
{
const std::string buttonFname = getResourceFilename(picFile, "", true, true);
......@@ -258,10 +279,199 @@ void VirtualKeenControl::render(GsWeakSurface &sfc)
}
void VirtualKeenControl::flush()
{
mConfirmButton.clearFingers();
mStartButton.clearFingers();
mStatusButton.clearFingers();
mShootButton.clearFingers();
mJumpButton.clearFingers();
mPogoButton.clearFingers();
mDPad.clearFingers();
}
bool VirtualKeenControl::mouseFingerState(const Vector2D<float> &Pos,
const SDL_TouchFingerEvent &touchFingerEvent,
const bool down)
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
/*
auto unbindButtonCommand = [&](const TouchButton &button,
const InputCommand &cmd)
{
gInput.setCommand(0, cmd, false);
};
unbindButtonCommand(mConfirmButton, IC_JUMP);
unbindButtonCommand(mStartButton, IC_JUMP);
unbindButtonCommand(mStatusButton, IC_STATUS);
unbindButtonCommand(mShootButton, IC_FIRE);
unbindButtonCommand(mJumpButton, IC_JUMP);
unbindButtonCommand(mPogoButton, IC_POGO);
// Always sent released first, better for VPads
SDL_Event evUp;
evUp.type = SDL_KEYUP;
evUp.key.keysym.sym = SDLK_UP; SDL_PushEvent(&evUp);
evUp.key.keysym.sym = SDLK_LEFT; SDL_PushEvent(&evUp);
evUp.key.keysym.sym = SDLK_RIGHT; SDL_PushEvent(&evUp);
evUp.key.keysym.sym = SDLK_DOWN; SDL_PushEvent(&evUp);*/
/*
if( !mPadBackground.isInside(Pos.x, Pos.y) )
return false;*/
bool ok = false;
auto bindButtonCommand = [&](TouchButton &button,
const InputCommand &cmd) -> bool
{
if(button.invisible)
return false;
if( button.Rect().HasPoint(Pos) )
{
gInput.setCommand(0, cmd, down);
if(down)
{
button.insertFingerId(touchFingerEvent.fingerId);
}
else
{
button.removeFingerId(touchFingerEvent.fingerId);
}
return true;
}
else
{
auto it = button.mFingerSet.find(touchFingerEvent.fingerId);
if( it != button.mFingerSet.end() )
{
gInput.setCommand(0, cmd, false);
button.mFingerSet.erase(it);
}
return false;
}
};
SDL_Event ev;
ev.type = (down ? SDL_KEYDOWN : SDL_KEYUP);
if( !mDPad.invisible &&
mDPad.isInside(Pos.x, Pos.y) )
{
// Size of the buttons on the dpad
const float dpadSizePieceW = 0.4f*mDPad.w;
const float dpadSizePieceH = 0.4f*mDPad.h;
// Y-Direction
// Up presses
if(Pos.y<mDPad.y+dpadSizePieceH)
{
ev.key.keysym.sym = SDLK_UP;
SDL_PushEvent(&ev);
if(down)
{
SDL_Event evUp;
evUp.type = SDL_KEYUP;
evUp.key.keysym.sym = SDLK_DOWN;
SDL_PushEvent(&evUp);
}
}
// Down presses
else if(Pos.y>=mDPad.y+mDPad.h-dpadSizePieceH)
{
ev.key.keysym.sym = SDLK_DOWN;
SDL_PushEvent(&ev);
if(down)
{
SDL_Event evUp;
evUp.type = SDL_KEYUP;
evUp.key.keysym.sym = SDLK_UP;
SDL_PushEvent(&evUp);
}
}
// X-Direction
// Left presses
if(Pos.x<mDPad.x+dpadSizePieceW)
{
ev.key.keysym.sym = SDLK_LEFT;
SDL_PushEvent(&ev);
if(down)
{
SDL_Event evUp;
evUp.type = SDL_KEYUP;
evUp.key.keysym.sym = SDLK_RIGHT;
SDL_PushEvent(&evUp);
}
}
// Right presses
else if(Pos.x>=mDPad.x+mDPad.w-dpadSizePieceW)
{
ev.key.keysym.sym = SDLK_RIGHT;
SDL_PushEvent(&ev);
if(down)
{
SDL_Event evUp;
evUp.type = SDL_KEYUP;
evUp.key.keysym.sym = SDLK_LEFT;
SDL_PushEvent(&evUp);
}
}
mDPad.insertFingerId(touchFingerEvent.fingerId);
ok |= true;
}
else
{
auto it = mDPad.mFingerSet.find(touchFingerEvent.fingerId);
if( it != mDPad.mFingerSet.end() )
{
mDPad.mFingerSet.erase(it);
SDL_Event evUp;
evUp.type = SDL_KEYUP;
evUp.key.keysym.sym = SDLK_UP; SDL_PushEvent(&evUp);
evUp.key.keysym.sym = SDLK_LEFT; SDL_PushEvent(&evUp);
evUp.key.keysym.sym = SDLK_RIGHT; SDL_PushEvent(&evUp);
evUp.key.keysym.sym = SDLK_DOWN; SDL_PushEvent(&evUp);
}
}
ok |= bindButtonCommand(mConfirmButton, IC_JUMP);
ok |= bindButtonCommand(mStartButton, IC_JUMP);
ok |= bindButtonCommand(mStatusButton, IC_STATUS);
ok |= bindButtonCommand(mShootButton, IC_FIRE);
ok |= bindButtonCommand(mJumpButton, IC_JUMP);
ok |= bindButtonCommand(mPogoButton, IC_POGO);
#endif
return ok;
}
bool VirtualKeenControl::mouseState(const Vector2D<float> &Pos, const bool down)
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
/*
auto unbindButtonCommand = [&](const TouchButton &button,
const InputCommand &cmd)
{
......@@ -283,13 +493,13 @@ bool VirtualKeenControl::mouseState(const Vector2D<float> &Pos, const bool down)
evUp.key.keysym.sym = SDLK_UP; SDL_PushEvent(&evUp);
evUp.key.keysym.sym = SDLK_LEFT; SDL_PushEvent(&evUp);
evUp.key.keysym.sym = SDLK_RIGHT; SDL_PushEvent(&evUp);
evUp.key.keysym.sym = SDLK_DOWN; SDL_PushEvent(&evUp);
evUp.key.keysym.sym = SDLK_DOWN; SDL_PushEvent(&evUp);*/
if( !mPadBackground.isInside(Pos.x, Pos.y) )
return false;
auto bindButtonCommand = [&](const TouchButton &button,
const InputCommand &cmd)
const InputCommand &cmd)
{
if(button.invisible)
return;
......
......@@ -2,6 +2,9 @@
#define VGAMEPADSIMPLE_H
#include <base/GsVirtualinput.h>
#include <base/CInput.h>
#include <utility>
#include <set>
class VirtualKeenControl : public GsVirtualInput
{
......@@ -60,6 +63,19 @@ public:
return mouseState(Pos, false);
}
/**
* @brief flush Flush stuck events
*/
void flush() override;
#if SDL_VERSION_ATLEAST(2, 0, 0)
bool mouseFingerState(const Vector2D<float> &Pos,
const SDL_TouchFingerEvent &touchFingerEvent,
const bool down) override;
#endif
/**
* @brief active Checks if click events happened in the virtual dpad
* @return
......@@ -94,6 +110,8 @@ public:
TouchButton mPogoButton;
TouchButton mStatusButton;
std::set< SDL_FingerID > mFingerSet;
#endif
};
......
......@@ -107,12 +107,12 @@ void CAudioSettings::release()
mSoundblaster = ( mpSBToggle->getSelection() == "Soundblaster" ? true : false );
gSound.unloadSoundData();
gSound.destroy();
// gSound.unloadSoundData();
// gSound.destroy();
gSound.setSettings(mAudioSpec, mSoundblaster);
gSound.init();
gMusicPlayer.reload();
// gMusicPlayer.reload();
gSettings.saveDrvCfg();
}
......
......@@ -97,8 +97,7 @@ void KeenEngine::ponder(const float deltaT)
if(!mpGameMode)
return;
if(gMusicPlayer.active() &&
gMusicPlayer.paused())
if( gMusicPlayer.paused())
{
gMusicPlayer.play();
}
......
......@@ -431,6 +431,8 @@ void CPlayGameGalaxy::pumpEvent(const CEvent *evPtr)
m_LevelPlay.setActive(true);
}
}
gInput.flushFingerEvents();
}
else if( dynamic_cast<const EventRestartLevel*>(evPtr) )
{
......
......@@ -114,11 +114,7 @@ void GalaxyEngine::ponder(const float deltaT)
if( gInput.getPressedCommand(IC_HELP) && !gMenuController.empty())
{
// Check if music is playing and pause if it is
if(gMusicPlayer.active())
{
gMusicPlayer.pause();
}
gMusicPlayer.pause();
// Episode 6 for a strange reason does not have the help screen
if(!mpComputerWrist && (ep!=6))
......@@ -151,11 +147,7 @@ void GalaxyEngine::openMainMenu()
// Check if music is playing and pause if it is
if(gMusicPlayer.active())
{
gMusicPlayer.pause();
}
gMusicPlayer.pause();
gEventManager.add( new OpenMenuEvent(
new MainMenu(mOpenedGamePlay,
......
......@@ -404,7 +404,7 @@ bool CHighScores::loadHighScoreTable()
memset(c_name, 0, 8*16*sizeof(char));
memset(c_score, 0, 8*8*sizeof(char));
memset(c_extra, 0, 8*4*sizeof(char));
memset(c_cities, 0, 8*sizeof(char));
memset(c_cities, 0, 8*sizeof(int));
ScoreTableFile.read((char*)c_name, 8*16*sizeof(char));
ScoreTableFile.seekg(8*16*sizeof(char),ios_base::cur);
......@@ -444,7 +444,7 @@ bool CHighScores::saveHighScoreTable()
memset(c_name, 0, 8*16*sizeof(char));
memset(c_score, 0, 8*8*sizeof(char));
memset(c_extra, 0, 8*4*sizeof(char));
memset(c_cities, 0, 8*sizeof(char));
memset(c_cities, 0, 8*sizeof(int));
// Format the C++ strings to C Strings
for(size_t i=0 ; i<8 ; i++)
......
......@@ -94,11 +94,7 @@ void VorticonEngine::openMainMenu()
if( !gMenuController.empty() )
return;
// Check if music is playing and pause if it is
if(gMusicPlayer.active())
{
gMusicPlayer.pause();
}
gMusicPlayer.pause();
gEventManager.add( new OpenMenuEvent(
new MainMenu(mOpenedGamePlay,
......
......@@ -272,7 +272,6 @@ void Audio::setMusicVolume(const Uint8 volume,
if(updateMixer)
{
setImfMusic(volume);
Mix_VolumeMusic(volume);
}
}
......
......@@ -26,6 +26,8 @@
class Audio : public GsSingleton<Audio>
{
friend class CIMFPlayer;
public:
Audio();
~Audio();
......
......@@ -20,7 +20,7 @@
#include <SDL_mixer.h>
CIMFPlayer::CIMFPlayer( COPLEmulator& opl_emulator ) :
CIMFPlayer::CIMFPlayer(COPLEmulator& opl_emulator) :
m_opl_emulator(opl_emulator)
{
m_samplesPerMusicTick = gSound.getAudioSpec().freq /
......@@ -119,6 +119,8 @@ void CIMFPlayer::OPLUpdate(byte *buffer, const unsigned int length)
{
auto &audioSpec = gSound.getAudioSpec();
const int vol = gSound.getMusicVolume();
if(mMixBuffer.empty())
{
gLogging.textOut("Creating enough Audio Buffer for the IMF-Player");
......@@ -146,7 +148,7 @@ void CIMFPlayer::OPLUpdate(byte *buffer, const unsigned int length)
for (unsigned int j=0; j<audioSpec.channels; j++)
{
int val = mix + audioSpec.silence;
*buf16 = static_cast<Sint16>((val*mVolume)/MIX_MAX_VOLUME);
*buf16 = static_cast<Sint16>((val*vol)/MIX_MAX_VOLUME);
buf16++;
}
}
......@@ -165,7 +167,7 @@ void CIMFPlayer::OPLUpdate(byte *buffer, const unsigned int length)
for (unsigned int j=0; j<audioSpec.channels; j++)
{
int val = mix + audioSpec.silence;
*buffer = static_cast<Sint16>((val*mVolume)/MIX_MAX_VOLUME);
*buffer = static_cast<Sint16>((val*vol)/MIX_MAX_VOLUME);
buffer++;
}
}
......@@ -228,15 +230,10 @@ void CIMFPlayer::readBuffer(Uint8* buffer,
// We still a local to file declared object from the IMFPlayer class.
// That one is only used here!
CIMFPlayer locIMFPlayer;
CIMFPlayer locIMFPlayer(gSound.getOPLEmulatorRef());
int locImfMusPos = 0;
void setImfMusic(const int vol)
{
locIMFPlayer.mVolume = vol;
}
bool loadIMFFile(const std::string &fname)
{
if(locIMFPlayer.playing())
......
......@@ -26,8 +26,9 @@ struct IMFChunkType
class CIMFPlayer : public CMusicPlayer
{
public:
CIMFPlayer( COPLEmulator& opl_emulator = gSound.getOPLEmulatorRef());
CIMFPlayer( COPLEmulator& opl_emulator);
/**
......@@ -46,8 +47,6 @@ public:
bool loadMusicTrack(const int track) override;
int mVolume = 0;
private:
......@@ -69,11 +68,6 @@ private:
// External Music hooks for the imf player
/**
* @brief setImfMusic Set volume of external player
* @param vol
*/
void setImfMusic(const int vol);
/**
* @brief loadIMFFile
......
......@@ -110,6 +110,8 @@ void CMusic::reload()
{
gSound.pauseAudio();
play();
Mix_RewindMusic();
gSound.resumeAudio();
......@@ -117,15 +119,7 @@ void CMusic::reload()
void CMusic::play()
{
if(Mix_PausedMusic())
{
Mix_ResumeMusic();
}
if(Mix_PlayingMusic())
{
Mix_HaltMusic();
}
Mix_HaltMusic();
if(!mpMixMusic)
{
......@@ -137,25 +131,19 @@ void CMusic::play()
{
gLogging.ftextOut("Mix_PlayMusic: %s\n", Mix_GetError());
// well, there's no music, but most games don't break without music...
}
}
Mix_ResumeMusic();
}
void CMusic::pause()
{
if(!Mix_PausedMusic())
{
Mix_PauseMusic();
}
Mix_PauseMusic();
}
void CMusic::stop()
{
if(Mix_PlayingMusic())
{
Mix_HaltMusic();
}
Mix_HaltMusic();
if(mpMixMusic)
{
......@@ -164,7 +152,6 @@ void CMusic::stop()
}
unhookAll();
}
......
......@@ -55,30 +55,14 @@ public:
bool paused()
{
if(!active())
{
return false;
}
return Mix_PausedMusic();
}
bool playing()
{
if(!active())
{
return false;
}