Commit 62d5a31f authored by Unicorn369's avatar Unicorn369 Committed by fallenstardust

fix

parent f9b63108
#include "sound_manager.h"
#include "config.h"
#ifdef IRRKLANG_STATIC
#include "../ikpmp3/ikpMP3.h"
#endif
namespace ygo {
......@@ -13,23 +10,10 @@ bool SoundManager::Init(double sounds_volume, double music_volume, bool sounds_e
bgm_scene = -1;
RefreshBGMList();
RefreshChantsList();
#ifdef YGOPRO_USE_IRRKLANG
soundEngine = irrklang::createIrrKlangDevice();
if(!soundEngine) {
return soundsEnabled = musicEnabled = false;
} else {
#ifdef IRRKLANG_STATIC
irrklang::ikpMP3Init(soundEngine);
#endif
sfxVolume = sounds_volume;
bgmVolume = music_volume;
return true;
}
#else
try {
openal = std::make_unique<YGOpen::OpenALSingleton>();
sfx = std::make_unique<YGOpen::OpenALSoundLayer>(openal);
bgm = std::make_unique<YGOpen::OpenALSoundLayer>(openal);
openal = Utils::make_unique<YGOpen::OpenALSingleton>();
sfx = Utils::make_unique<YGOpen::OpenALSoundLayer>(openal);
bgm = Utils::make_unique<YGOpen::OpenALSoundLayer>(openal);
sfx->setVolume(sounds_volume);
bgm->setVolume(music_volume);
return true;
......@@ -37,15 +21,6 @@ bool SoundManager::Init(double sounds_volume, double music_volume, bool sounds_e
catch (std::runtime_error& e) {
return soundsEnabled = musicEnabled = false;
}
#endif // YGOPRO_USE_IRRKLANG
}
SoundManager::~SoundManager() {
#ifdef YGOPRO_USE_IRRKLANG
if (soundBGM)
soundBGM->drop();
if (soundEngine)
soundEngine->drop();
#endif
}
void SoundManager::RefreshBGMList() {
Utils::Makedirectory(TEXT("./sound/BGM/"));
......@@ -109,39 +84,17 @@ void SoundManager::PlaySoundEffect(SFX sound) {
{CHAT, "./sound/chatmessage.wav"}
};
if (!soundsEnabled) return;
#ifdef YGOPRO_USE_IRRKLANG
if (soundEngine) {
auto sfx = soundEngine->play2D(fx.at(sound), false, true);
sfx->setVolume(sfxVolume);
sfx->setIsPaused(false);
}
#else
if (sfx) sfx->play(fx.at(sound), false);
#endif
}
void SoundManager::PlayMusic(const std::string& song, bool loop) {
if(!musicEnabled) return;
#ifdef YGOPRO_USE_IRRKLANG
if(!soundBGM || soundBGM->getSoundSource()->getName() != song) {
StopBGM();
if (soundEngine) {
soundBGM = soundEngine->play2D(song.c_str(), loop, false, true);
soundBGM->setVolume(bgmVolume);
}
}
#else
StopBGM();
if (bgm) bgmCurrent = bgm->play(song, loop);
#endif
}
void SoundManager::PlayBGM(BGM scene) {
auto& list = BGMList[scene];
int count = list.size();
#ifdef YGOPRO_USE_IRRKLANG
if(musicEnabled && (scene != bgm_scene || (soundBGM && soundBGM->isFinished()) || !soundBGM) && count > 0) {
#else
if (musicEnabled && (scene != bgm_scene || !bgm->exists(bgmCurrent)) && count > 0) {
#endif
bgm_scene = scene;
int bgm = (std::uniform_int_distribution<>(0, count - 1))(rnd);
std::string BGMName = "./sound/BGM/" + list[bgm];
......@@ -149,45 +102,20 @@ void SoundManager::PlayBGM(BGM scene) {
}
}
void SoundManager::StopBGM() {
#ifdef YGOPRO_USE_IRRKLANG
if(soundBGM) {
soundBGM->stop();
soundBGM->drop();
soundBGM = nullptr;
}
#else
bgm->stopAll();
#endif
}
bool SoundManager::PlayChant(unsigned int code) {
if(ChantsList.count(code)) {
#ifdef YGOPRO_USE_IRRKLANG
if (soundEngine && !soundEngine->isCurrentlyPlaying(("./sound/chants/" + ChantsList[code]).c_str())) {
auto chant = soundEngine->play2D(("./sound/chants/" + ChantsList[code]).c_str());
chant->setVolume(sfxVolume);
chant->setIsPaused(false);
}
#else
if (bgm) bgm->play("./sound/chants/" + ChantsList[code], false);
#endif
return true;
}
return false;
}
void SoundManager::SetSoundVolume(double volume) {
#ifdef YGOPRO_USE_IRRKLANG
sfxVolume = volume;
#else
if (sfx) sfx->setVolume(volume);
#endif
}
void SoundManager::SetMusicVolume(double volume) {
#ifdef YGOPRO_USE_IRRKLANG
if (soundBGM) soundBGM->setVolume(volume);
bgmVolume = volume;
#else
if (bgm) bgm->setVolume(volume);
#endif
}
void SoundManager::EnableSounds(bool enable) {
soundsEnabled = enable;
......@@ -195,16 +123,7 @@ void SoundManager::EnableSounds(bool enable) {
void SoundManager::EnableMusic(bool enable) {
musicEnabled = enable;
if(!musicEnabled) {
#ifdef YGOPRO_USE_IRRKLANG
if(soundBGM){
if(!soundBGM->isFinished())
soundBGM->stop();
soundBGM->drop();
soundBGM = nullptr;
}
#else
StopBGM();
#endif
}
}
......
......@@ -2,11 +2,7 @@
#define SOUNDMANAGER_H
#include <random>
#ifdef YGOPRO_USE_IRRKLANG
#include <irrKlang.h>
#else
#include "sound_openal.h"
#endif
#include "utils.h"
namespace ygo {
......@@ -49,10 +45,6 @@ public:
WIN,
LOSE
};
#ifndef YGOPRO_USE_IRRKLANG
SoundManager() : openal(nullptr), sfx(nullptr) {}
#endif
~SoundManager();
bool Init(double sounds_volume, double music_volume, bool sounds_enabled, bool music_enabled, void* payload = nullptr);
void RefreshBGMList();
void PlaySoundEffect(SFX sound);
......@@ -70,17 +62,10 @@ private:
std::map<unsigned int, std::string> ChantsList;
int bgm_scene = -1;
std::mt19937 rnd;
#ifdef YGOPRO_USE_IRRKLANG
irrklang::ISoundEngine* soundEngine;
irrklang::ISound* soundBGM;
double sfxVolume = 1.0;
double bgmVolume = 1.0;
#else
std::unique_ptr<YGOpen::OpenALSingleton> openal;
std::unique_ptr<YGOpen::OpenALSoundLayer> sfx;
std::unique_ptr<YGOpen::OpenALSoundLayer> bgm;
int bgmCurrent = -1;
#endif
void RefreshBGMDir(path_string path, BGM scene);
void RefreshChantsList();
bool soundsEnabled = false;
......
......@@ -4,11 +4,6 @@
#include "bufferio.h"
#ifdef _WIN32
#include "../irrlicht/src/CIrrDeviceWin32.h"
#elif defined(__linux__)
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#elif defined(__APPLE__)
#include "osx_menu.h"
#endif
namespace ygo {
bool Utils::Makedirectory(const path_string& path) {
......@@ -125,128 +120,6 @@ namespace ygo {
image->drop();
}
}
void Utils::ToggleFullscreen() {
#ifdef _WIN32
static RECT nonFullscreenSize;
static std::vector<RECT> monitors;
static bool maximized = false;
if(monitors.empty()) {
EnumDisplayMonitors(0, 0, [](HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData) -> BOOL {
auto monitors = reinterpret_cast<std::vector<RECT>*>(pData);
monitors->push_back(*lprcMonitor);
return TRUE;
}, (LPARAM)&monitors);
}
mainGame->is_fullscreen = !mainGame->is_fullscreen;
HWND hWnd;
irr::video::SExposedVideoData exposedData = mainGame->driver->getExposedVideoData();
if(mainGame->driver->getDriverType() == irr::video::EDT_DIRECT3D9)
hWnd = reinterpret_cast<HWND>(exposedData.D3D9.HWnd);
else
hWnd = reinterpret_cast<HWND>(exposedData.OpenGLWin32.HWnd);
LONG_PTR style = WS_POPUP;
RECT clientSize = {};
if(mainGame->is_fullscreen) {
if(GetWindowLong(hWnd, GWL_STYLE) & WS_MAXIMIZE) {
maximized = true;
}
GetWindowRect(hWnd, &nonFullscreenSize);
style = WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
for(auto& rect : monitors) {
POINT windowCenter = { (nonFullscreenSize.left + (nonFullscreenSize.right - nonFullscreenSize.left) / 2), (nonFullscreenSize.top + (nonFullscreenSize.bottom - nonFullscreenSize.top) / 2) };
if(PtInRect(&rect, windowCenter)) {
clientSize = rect;
break;
}
}
} else {
style = WS_THICKFRAME | WS_SYSMENU | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
clientSize = nonFullscreenSize;
if(maximized) {
style |= WS_MAXIMIZE;
maximized = false;
}
}
if(!SetWindowLongPtr(hWnd, GWL_STYLE, style))
mainGame->ErrorLog("Could not change window style.");
const s32 width = clientSize.right - clientSize.left;
const s32 height = clientSize.bottom - clientSize.top;
SetWindowPos(hWnd, HWND_TOP, clientSize.left, clientSize.top, width, height, SWP_FRAMECHANGED | SWP_SHOWWINDOW);
static_cast<irr::CIrrDeviceWin32::CCursorControl*>(mainGame->device->getCursorControl())->updateBorderSize(mainGame->is_fullscreen, true);
#elif defined(__linux__)
struct {
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long inputMode;
unsigned long status;
} hints = {};
Display* display = XOpenDisplay(NULL);;
Window window;
static bool wasHorizontalMaximized = false, wasVerticalMaximized = false;
Window child;
int revert;
mainGame->is_fullscreen = !mainGame->is_fullscreen;
XGetInputFocus(display, &window, &revert);
Atom wm_state = XInternAtom(display, "_NET_WM_STATE", false);
Atom max_horz = XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_HORZ", false);
Atom max_vert = XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_VERT", false);
auto checkMaximized = [&]() {
long maxLength = 1024;
Atom actualType;
int actualFormat;
unsigned long i, numItems, bytesAfter;
unsigned char *propertyValue = NULL;
if(XGetWindowProperty(display, window, wm_state,
0l, maxLength, false, XA_ATOM, &actualType,
&actualFormat, &numItems, &bytesAfter,
&propertyValue) == Success) {
Atom* atoms = (Atom *)propertyValue;
for(i = 0; i < numItems; ++i) {
if(atoms[i] == max_vert) {
wasVerticalMaximized = true;
} else if(atoms[i] == max_horz) {
wasHorizontalMaximized = true;
}
}
XFree(propertyValue);
}
};
if(mainGame->is_fullscreen)
checkMaximized();
if(!wasHorizontalMaximized && !wasVerticalMaximized) {
XEvent xev = {};
xev.type = ClientMessage;
xev.xclient.window = window;
xev.xclient.message_type = wm_state;
xev.xclient.format = 32;
xev.xclient.data.l[0] = mainGame->is_fullscreen ? 1 : 0;
int i = 1;
if(!wasHorizontalMaximized)
xev.xclient.data.l[i++] = max_horz;
if(!wasVerticalMaximized)
xev.xclient.data.l[i++] = max_vert;
if(i == 2)
xev.xclient.data.l[i] = 0;
XSendEvent(display, DefaultRootWindow(display), False, SubstructureNotifyMask, &xev);
}
Atom property = XInternAtom(display, "_MOTIF_WM_HINTS", true);
hints.flags = 2;
hints.decorations = mainGame->is_fullscreen ? 0 : 1;
XChangeProperty(display, window, property, property, 32, PropModeReplace, (unsigned char*)&hints, 5);
XMapWindow(display, window);
XFlush(display);
#elif defined(__APPLE__)
EDOPRO_ToggleFullScreen();
#endif
}
void Utils::changeCursor(irr::gui::ECURSOR_ICON icon) {
irr::gui::ICursorControl* cursor = mainGame->device->getCursorControl();
......@@ -481,19 +354,19 @@ namespace ygo {
#ifdef UNICODE
return input;
#else
return BufferIO::EncodeUTF8s(input);
return Utils::EncodeUTF8s(input);
#endif
}
path_string Utils::ParseFilename(const std::string& input) {
#ifdef UNICODE
return BufferIO::DecodeUTF8s(input);
return Utils::DecodeUTF8s(input);
#else
return input;
#endif
}
std::string Utils::ToUTF8IfNeeded(const path_string& input) {
#ifdef UNICODE
return BufferIO::EncodeUTF8s(input);
return Utils::EncodeUTF8s(input);
#else
return input;
#endif
......@@ -502,7 +375,7 @@ namespace ygo {
#ifdef UNICODE
return input;
#else
return BufferIO::DecodeUTF8s(input);
return Utils::DecodeUTF8s(input);
#endif
}
void Utils::IrrArchiveHelper::ParseList(irr::io::IFileArchive* _archive) {
......
......@@ -50,6 +50,82 @@ namespace ygo {
static std::string GetFileExtension(std::string file);
static std::string GetFilePath(std::string file);
static std::string GetFileName(std::string file);
template<typename T, typename... Ts>
static std::unique_ptr<T> make_unique(Ts&&... params)
{
return std::unique_ptr<T>(new T(std::forward<Ts>(params)...));
}
// UTF-8 to UTF-16/UTF-32
static std::string EncodeUTF8s(const std::wstring& source) {
std::string res;
res.reserve(source.size() * 3);
for(size_t i = 0; i < source.size(); i++) {
auto c = source[i];
if (c < 0x80) {
res += ((char)c);
} else if (c < 0x800) {
res += ((char)(((c >> 6) & 0x1f) | 0xc0));
res += ((char)((c & 0x3f) | 0x80));
} else if (c < 0x10000 && (c < 0xd800 || c > 0xdfff)) {
res += ((char)(((c >> 12) & 0xf) | 0xe0));
res += ((char)(((c >> 6) & 0x3f) | 0x80));
res += ((char)(((c) & 0x3f) | 0x80));
} else {
#ifdef _WIN32
unsigned unicode = 0;
unicode |= (c & 0x3ff) << 10;
c = source[++i];
unicode |= c & 0x3ff;
unicode += 0x10000;
res += ((char)(((unicode >> 18) & 0x7) | 0xf0));
res += ((char)(((unicode >> 12) & 0x3f) | 0x80));
res += ((char)(((unicode >> 6) & 0x3f) | 0x80));
res += ((char)(((unicode) & 0x3f) | 0x80));
#else
res += ((char)(((c >> 18) & 0x7) | 0xf0));
res += ((char)(((c >> 12) & 0x3f) | 0x80));
res += ((char)(((c >> 6) & 0x3f) | 0x80));
res += ((char)(((c) & 0x3f) | 0x80));
#endif
}
}
res.shrink_to_fit();
return res;
}
// UTF-8 to UTF-16/UTF-32
static std::wstring DecodeUTF8s(const std::string& source) {
std::wstring res;
res.reserve(source.size());
for (size_t i = 0; i < source.size();) {
auto c = source[i];
if ((c & 0x80) == 0) {
res += ((wchar_t)c);
i++;
} else if ((c & 0xe0) == 0xc0) {
res += ((wchar_t)((((unsigned)c & 0x1f) << 6) | ((unsigned)source[i + 1] & 0x3f)));
i += 2;
} else if ((c & 0xf0) == 0xe0) {
res += ((wchar_t)((((unsigned)c & 0xf) << 12) | (((unsigned)source[i + 1] & 0x3f) << 6) | ((unsigned)source[i + 2] & 0x3f)));
i += 3;
} else if ((c & 0xf8) == 0xf0) {
#ifdef _WIN32
unsigned unicode = (((unsigned)c & 0x7) << 18) | (((unsigned)source[i + 1] & 0x3f) << 12) | (((unsigned)source[i + 2] & 0x3f) << 6) | ((unsigned)source[i + 3] & 0x3f);
unicode -= 0x10000;
res += ((wchar_t)((unicode >> 10) | 0xd800));
res += ((wchar_t)((unicode & 0x3ff) | 0xdc00));
#else
res += ((wchar_t)((((unsigned)c & 0x7) << 18) | (((unsigned)source[i + 1] & 0x3f) << 12) | (((unsigned)source[i + 2] & 0x3f) << 6) | ((unsigned)source[i + 3] & 0x3f)));
#endif // _WIN32
i += 4;
} else {
i++;
}
}
res.shrink_to_fit();
return res;
}
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment