switched audio from miniaudio to SDL_mixer

This commit is contained in:
anthony@rabine.fr 2024-05-14 17:18:26 +02:00
parent 9accbbeea7
commit be16a68e85
10 changed files with 231 additions and 324 deletions

View file

@ -1,301 +1,63 @@
/*
Demonstrates how to load a sound file and play it back using the low-level API.
The low-level API uses a callback to deliver audio between the application and miniaudio for playback or recording. When
in playback mode, as in this example, the application sends raw audio data to miniaudio which is then played back through
the default playback device as defined by the operating system.
This example uses the `ma_decoder` API to load a sound and play it back. The decoder is entirely decoupled from the
device and can be used independently of it. This example only plays back a single sound file, but it's possible to play
back multiple files by simple loading multiple decoders and mixing them (do not create multiple devices to do this). See
the simple_mixing example for how best to do this.
*/
#define STB_VORBIS_HEADER_ONLY
#include "stb_vorbis.c"
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
#include <functional> #include <functional>
#include <stdio.h> #include <stdio.h>
#include "audio_player.h" #include "audio_player.h"
// #define MA_NO_LIBOPUS #include <SDL3_mixer/SDL_mixer.h>
// #include "miniaudio_libvorbis.h"
// #include "miniaudio_libopus.h"
#include <stdio.h> #include <stdio.h>
#if 0
static ma_result ma_decoding_backend_init__libvorbis(void* pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend) static int audio_open = 0;
{ static Mix_Music *music = NULL;
ma_result result; static int next_track = 0;
ma_libvorbis* pVorbis;
(void)pUserData;
pVorbis = (ma_libvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
if (pVorbis == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_libvorbis_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pVorbis);
if (result != MA_SUCCESS) {
ma_free(pVorbis, pAllocationCallbacks);
return result;
}
*ppBackend = pVorbis;
return MA_SUCCESS;
}
static ma_result ma_decoding_backend_init_file__libvorbis(void* pUserData, const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
{
ma_result result;
ma_libvorbis* pVorbis;
(void)pUserData;
pVorbis = (ma_libvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
if (pVorbis == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_libvorbis_init_file(pFilePath, pConfig, pAllocationCallbacks, pVorbis);
if (result != MA_SUCCESS) {
ma_free(pVorbis, pAllocationCallbacks);
return result;
}
*ppBackend = pVorbis;
return MA_SUCCESS;
}
static void ma_decoding_backend_uninit__libvorbis(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_libvorbis* pVorbis = (ma_libvorbis*)pBackend;
(void)pUserData;
ma_libvorbis_uninit(pVorbis, pAllocationCallbacks);
ma_free(pVorbis, pAllocationCallbacks);
}
static ma_result ma_decoding_backend_get_channel_map__libvorbis(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
{
ma_libvorbis* pVorbis = (ma_libvorbis*)pBackend;
(void)pUserData;
return ma_libvorbis_get_data_format(pVorbis, NULL, NULL, NULL, pChannelMap, channelMapCap);
}
static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_libvorbis =
{
ma_decoding_backend_init__libvorbis,
ma_decoding_backend_init_file__libvorbis,
NULL, /* onInitFileW() */
NULL, /* onInitMemory() */
ma_decoding_backend_uninit__libvorbis
};
static ma_result ma_decoding_backend_init__libopus(void* pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
{
ma_result result;
ma_libopus* pOpus;
(void)pUserData;
pOpus = (ma_libopus*)ma_malloc(sizeof(*pOpus), pAllocationCallbacks);
if (pOpus == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_libopus_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pOpus);
if (result != MA_SUCCESS) {
ma_free(pOpus, pAllocationCallbacks);
return result;
}
*ppBackend = pOpus;
return MA_SUCCESS;
}
static ma_result ma_decoding_backend_init_file__libopus(void* pUserData, const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
{
ma_result result;
ma_libopus* pOpus;
(void)pUserData;
pOpus = (ma_libopus*)ma_malloc(sizeof(*pOpus), pAllocationCallbacks);
if (pOpus == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_libopus_init_file(pFilePath, pConfig, pAllocationCallbacks, pOpus);
if (result != MA_SUCCESS) {
ma_free(pOpus, pAllocationCallbacks);
return result;
}
*ppBackend = pOpus;
return MA_SUCCESS;
}
static void ma_decoding_backend_uninit__libopus(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_libopus* pOpus = (ma_libopus*)pBackend;
(void)pUserData;
ma_libopus_uninit(pOpus, pAllocationCallbacks);
ma_free(pOpus, pAllocationCallbacks);
}
static ma_result ma_decoding_backend_get_channel_map__libopus(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
{
ma_libopus* pOpus = (ma_libopus*)pBackend;
(void)pUserData;
return ma_libopus_get_data_format(pOpus, NULL, NULL, NULL, pChannelMap, channelMapCap);
}
static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_libopus =
{
ma_decoding_backend_init__libopus,
ma_decoding_backend_init_file__libopus,
NULL, /* onInitFileW() */
NULL, /* onInitMemory() */
ma_decoding_backend_uninit__libopus
};
#endif
// void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
// {
// ma_data_source* pDataSource = (ma_data_source*)pDevice->pUserData;
// if (pDataSource == NULL) {
// return;
// }
// ma_data_source_read_pcm_frames(pDataSource, pOutput, frameCount, NULL);
// (void)pInput;
// }
SDL_AudioSpec spec;
static ThreadSafeQueue<AudioCommand> g_audioQueue; static ThreadSafeQueue<AudioCommand> g_audioQueue;
static ma_decoder decoder;
static ma_device device;
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
void music_finished()
{ {
ma_decoder* pDecoder = (ma_decoder*)pDevice->pUserData; Mix_FreeMusic(music);
if (pDecoder == NULL) { music = NULL;
return; g_audioQueue.push({"end", ""});
}
ma_uint64 framesRead;
ma_result result = ma_decoder_read_pcm_frames(pDecoder, pOutput, frameCount, &framesRead);
if (result == MA_AT_END) {
g_audioQueue.push({"end", ""});
}
// if (framesRead < frameCount) {
// // Reached the end.
// ma_event_signal(&g_stopEvent);
// }
(void)pInput;
} }
static int miniaudio_play(const char* filename)
{
ma_result result;
ma_device_config deviceConfig;
short *output = NULL;
result = ma_decoder_init_file(filename, NULL, &decoder);
if (result != MA_SUCCESS)
{
printf("Could not load file: %s\n", filename);
// Try OGG (FIXME: plus tard, utiliser l'extension pour choisir le décodeur)
int channels = 0, sample_rate = 0;
int sample_count = stb_vorbis_decode_filename("chemin/vers/fichier.ogg", &channels, &sample_rate, &output);
if (sample_count == -1)
{
printf("Erreur de décodage du fichier Vorbis\n");
return -2;
}
ma_device_config deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.playback.format = ma_format_s16;
deviceConfig.playback.channels = channels;
deviceConfig.sampleRate = sample_rate;
deviceConfig.dataCallback = data_callback;
deviceConfig.pUserData = &decoder;
}
else
{
deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.playback.format = decoder.outputFormat;
deviceConfig.playback.channels = decoder.outputChannels;
deviceConfig.sampleRate = decoder.outputSampleRate;
deviceConfig.dataCallback = data_callback;
deviceConfig.pUserData = &decoder;
}
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
printf("Failed to open playback device.\n");
ma_decoder_uninit(&decoder);
if (output != NULL)
{
free(output);
}
return -3;
}
if (ma_device_start(&device) != MA_SUCCESS) {
printf("Failed to start playback device.\n");
ma_device_uninit(&device);
ma_decoder_uninit(&decoder);
if (output != NULL)
{
free(output);
}
return -4;
}
if (output != NULL)
{
free(output);
}
return 0;
}
AudioPlayer::AudioPlayer(IAudioEvent &event) AudioPlayer::AudioPlayer(IAudioEvent &event)
: m_event(event) : m_event(event)
{ {
m_audioThread = std::thread( std::bind(&AudioPlayer::AudioThread, this) ); m_audioThread = std::thread( std::bind(&AudioPlayer::AudioThread, this) );
} }
void AudioPlayer::Initialize()
{
/* Initialize variables */
spec.freq = MIX_DEFAULT_FREQUENCY;
spec.format = MIX_DEFAULT_FORMAT;
spec.channels = MIX_DEFAULT_CHANNELS;
if (Mix_Init(MIX_INIT_FLAC | MIX_INIT_MP3 | MIX_INIT_OGG) < 0) {
return ;
}
if (Mix_OpenAudio(0, &spec) < 0) {
SDL_Log("Couldn't open audio: %s\n", SDL_GetError());
return;
} else {
Mix_QuerySpec(&spec.freq, &spec.format, &spec.channels);
SDL_Log("Opened audio at %d Hz %d bit%s %s audio buffer\n", spec.freq,
(spec.format&0xFF),
(SDL_AUDIO_ISFLOAT(spec.format) ? " (float)" : ""),
(spec.channels > 2) ? "surround" : (spec.channels > 1) ? "stereo" : "mono");
}
audio_open = 1;
Mix_HookMusicFinished(music_finished);
}
void AudioPlayer::Play(const std::string &filename) void AudioPlayer::Play(const std::string &filename)
{ {
g_audioQueue.push({"play", filename}); g_audioQueue.push({"play", filename});
@ -304,6 +66,7 @@ void AudioPlayer::Play(const std::string &filename)
AudioPlayer::~AudioPlayer() AudioPlayer::~AudioPlayer()
{ {
// Quit audio thread // Quit audio thread
g_audioQueue.clear();
g_audioQueue.push({"quit", ""}); g_audioQueue.push({"quit", ""});
if (m_audioThread.joinable()) if (m_audioThread.joinable())
{ {
@ -311,11 +74,12 @@ AudioPlayer::~AudioPlayer()
} }
} }
void AudioPlayer::CloseAudio() void AudioPlayer::Stop()
{ {
ma_device_uninit(&device); g_audioQueue.clear();
ma_decoder_uninit(&decoder); g_audioQueue.push({"end", ""});
} }
#define AUDIO_STATE_WAIT_PLAY 1 #define AUDIO_STATE_WAIT_PLAY 1
#define AUDIO_STATE_WAIT_END 2 #define AUDIO_STATE_WAIT_END 2
@ -328,7 +92,8 @@ void AudioPlayer::AudioThread()
auto cmd = g_audioQueue.front(); auto cmd = g_audioQueue.front();
g_audioQueue.pop(); g_audioQueue.pop();
if (cmd.order == "quit") { if (cmd.order == "quit")
{
return; return;
} }
else if (cmd.order == "play") else if (cmd.order == "play")
@ -336,7 +101,12 @@ void AudioPlayer::AudioThread()
if (state == AUDIO_STATE_WAIT_PLAY) if (state == AUDIO_STATE_WAIT_PLAY)
{ {
state = AUDIO_STATE_WAIT_END; state = AUDIO_STATE_WAIT_END;
miniaudio_play(cmd.filename.c_str()); music = Mix_LoadMUS(cmd.filename.c_str());
if (music)
{
Mix_PlayMusic(music, 0);
}
} }
} }
else if (cmd.order == "end") else if (cmd.order == "end")
@ -344,7 +114,8 @@ void AudioPlayer::AudioThread()
if (state == AUDIO_STATE_WAIT_END) if (state == AUDIO_STATE_WAIT_END)
{ {
state = AUDIO_STATE_WAIT_PLAY; state = AUDIO_STATE_WAIT_PLAY;
CloseAudio(); Mix_HaltMusic();
Mix_FreeMusic(music);
m_event.EndOfAudio(); m_event.EndOfAudio();
} }
} }

View file

@ -1,7 +1,6 @@
#ifndef AUDIO_PLAYER_H #ifndef AUDIO_PLAYER_H
#define AUDIO_PLAYER_H #define AUDIO_PLAYER_H
#include "miniaudio.h"
#include <string> #include <string>
#include <thread> #include <thread>
#include <mutex> #include <mutex>
@ -34,6 +33,8 @@ public:
~AudioPlayer(); ~AudioPlayer();
void Play(const std::string &filename); void Play(const std::string &filename);
void Stop();
void Initialize();
private: private:
IAudioEvent &m_event; IAudioEvent &m_event;
@ -41,7 +42,7 @@ private:
std::thread m_audioThread; std::thread m_audioThread;
void AudioThread(); void AudioThread();
void CloseAudio();
}; };

View file

@ -33,6 +33,13 @@ public:
queue.pop(); queue.pop();
} }
void clear() {
std::lock_guard lock(mutex);
while(!queue.empty()) {
queue.pop();
}
}
bool try_pop(T& popped_item) { bool try_pop(T& popped_item) {
std::unique_lock lock(mutex); std::unique_lock lock(mutex);

View file

@ -126,6 +126,25 @@ FetchContent_MakeAvailable(sdl3)
include_directories(${sdl3_SOURCE_DIR}/include) include_directories(${sdl3_SOURCE_DIR}/include)
# add_subdirectory(${sdl3_SOURCE_DIR}) # add_subdirectory(${sdl3_SOURCE_DIR})
# =========================================================================================================================
# SDL3 MIXER
# =========================================================================================================================
FetchContent_Declare(
sdl3_mixer
GIT_REPOSITORY https://github.com/libsdl-org/SDL_mixer.git
GIT_TAG ace2d37796d2541123cdcbc06dce0b716a0416ad
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
GIT_SUBMODULES ""
)
set(BUILD_SHARED_LIBS TRUE)
set(SDL_PULSEAUDIO_SHARED TRUE)
set(SDL_PIPEWIRE_SHARED TRUE)
FetchContent_MakeAvailable(sdl3_mixer)
include_directories(${sdl3_mixer_SOURCE_DIR}/include)
# ========================================================================================================================= # =========================================================================================================================
# SDL3-Image # SDL3-Image
# ========================================================================================================================= # =========================================================================================================================
@ -326,6 +345,7 @@ if(UNIX)
dl dl
SDL3::SDL3 SDL3::SDL3
SDL3_image::SDL3_image SDL3_image::SDL3_image
SDL3_mixer::SDL3_mixer
libcurl_static libcurl_static
# OpenSSL::SSL OpenSSL::Crypto # OpenSSL::SSL OpenSSL::Crypto
) )

View file

@ -105,6 +105,18 @@ Gui::Gui()
std::cout << "PATH: " << m_executablePath << std::endl; std::cout << "PATH: " << m_executablePath << std::endl;
} }
static ImFont* normalFont;
// static ImFont* bigFont;
void Gui::PushBigFont()
{
// ImGui::PushFont(bigFont);
}
void Gui::PopBigFont()
{
// ImGui::PopFont();
}
bool Gui::Initialize() bool Gui::Initialize()
{ {
@ -112,11 +124,29 @@ bool Gui::Initialize()
// if (SDL_Init(SDL_INIT_EVERYTHING) != 0) // if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
// Setup SDL3 // Setup SDL3
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD) != 0) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
{ {
printf("Error: SDL_Init(): %s\n", SDL_GetError()); printf("Error: SDL_Init(): %s\n", SDL_GetError());
return -1; return false;
} }
/*
if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0)
{
int i, num_devices;
SDL_AudioDeviceID *devices = SDL_GetAudioOutputDevices(&num_devices);
if (devices) {
for (i = 0; i < num_devices; ++i) {
SDL_AudioDeviceID instance_id = devices[i];
char *name = SDL_GetAudioDeviceName(instance_id);
SDL_Log("AudioDevice %" SDL_PRIu32 ": %s\n", instance_id, name);
SDL_free(name);
}
SDL_free(devices);
}
printf("Error: SDL_InitSubSystem(): %s\n", SDL_GetError());
return false;
}*/
// Enable native IME. // Enable native IME.
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1"); SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
@ -133,13 +163,13 @@ bool Gui::Initialize()
if (window == nullptr) if (window == nullptr)
{ {
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1; return false;
} }
renderer = SDL_CreateRenderer(window, nullptr, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); renderer = SDL_CreateRenderer(window, nullptr, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
if (renderer == nullptr) if (renderer == nullptr)
{ {
SDL_Log("Error: SDL_CreateRenderer(): %s\n", SDL_GetError()); SDL_Log("Error: SDL_CreateRenderer(): %s\n", SDL_GetError());
return -1; return false;
} }
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window); SDL_ShowWindow(window);
@ -155,7 +185,9 @@ bool Gui::Initialize()
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
io.Fonts->AddFontFromFileTTF( std::string(m_executablePath + "/fonts/roboto.ttf").c_str(), 20); // bigFont = io.Fonts->AddFontFromFileTTF( std::string(m_executablePath + "/fonts/roboto.ttf").c_str(), 40);
// io.Fonts->Build();
normalFont = io.Fonts->AddFontFromFileTTF( std::string(m_executablePath + "/fonts/roboto.ttf").c_str(), 20);
{ {
ImFontConfig config; ImFontConfig config;

View file

@ -47,8 +47,12 @@ public:
static bool LoadRawImage(const std::string &filename, Image &image); static bool LoadRawImage(const std::string &filename, Image &image);
static Size GetWindowSize(); static Size GetWindowSize();
static void PushBigFont();
static void PopBigFont();
private: private:
std::string m_executablePath; std::string m_executablePath;
}; };
// namespace ImGui { // namespace ImGui {

View file

@ -6,9 +6,10 @@ int main(int, char**)
{ {
MainWindow w; MainWindow w;
w.Initialize(); if (w.Initialize())
{
w.Loop(); w.Loop();
}
return 0; return 0;
} }

View file

@ -256,13 +256,15 @@ void MainWindow::DrawStatusBar()
ImGui::End(); ImGui::End();
} }
void MainWindow::DrawMainMenuBar() float MainWindow::DrawMainMenuBar()
{ {
bool showAboutPopup = false; bool showAboutPopup = false;
bool showParameters = false; bool showParameters = false;
bool showNewProject = false; bool showNewProject = false;
bool showOpenProject = false; bool showOpenProject = false;
float height = 60;
if (ImGui::BeginMainMenuBar()) if (ImGui::BeginMainMenuBar())
{ {
if (ImGui::BeginMenu("File")) if (ImGui::BeginMenu("File"))
@ -333,6 +335,8 @@ void MainWindow::DrawMainMenuBar()
ImGui::EndMenu(); ImGui::EndMenu();
} }
height = ImGui::GetFrameHeight();
ImGui::EndMainMenuBar(); ImGui::EndMainMenuBar();
} }
@ -380,21 +384,31 @@ void MainWindow::DrawMainMenuBar()
} }
ImGui::EndPopup(); ImGui::EndPopup();
} }
return height;
} }
void MainWindow::Initialize() bool MainWindow::Initialize()
{ {
bool success = false;
LoadParams(); LoadParams();
// GUI Init // GUI Init
m_gui.Initialize(); if (m_gui.Initialize())
// gui.ApplyTheme(); {
m_player.Initialize(); // Initialize audio after GUI (uses SDL)
// gui.ApplyTheme();
m_editorWindow.Initialize(); m_editorWindow.Initialize();
m_emulatorWindow.Initialize(); m_emulatorWindow.Initialize();
m_nodeEditorWindow.Initialize(); m_nodeEditorWindow.Initialize();
m_PropertiesWindow.Initialize(); m_PropertiesWindow.Initialize();
m_libraryWindow.Initialize(); m_libraryWindow.Initialize();
success = true;
}
return success;
} }
@ -591,20 +605,20 @@ void MainWindow::ProjectPropertiesPopup()
} }
auto GetImageFormat = [](int idx) -> StoryProject::ImageFormat auto GetImageFormat = [](int idx) -> Resource::ImageFormat
{ {
StoryProject::ImageFormat img{StoryProject::IMG_SAME_FORMAT}; Resource::ImageFormat img{Resource::IMG_SAME_FORMAT};
if (idx < StoryProject::IMG_FORMAT_COUNT) { if (idx < Resource::IMG_FORMAT_COUNT) {
img = static_cast<StoryProject::ImageFormat>(idx); img = static_cast<Resource::ImageFormat>(idx);
} }
return img; return img;
}; };
auto GetSoundFormat = [](int idx) -> StoryProject::SoundFormat { auto GetSoundFormat = [](int idx) -> Resource::SoundFormat {
StoryProject::SoundFormat img{StoryProject::SND_FORMAT_WAV}; Resource::SoundFormat img{Resource::SND_FORMAT_WAV};
if (idx < StoryProject::IMG_FORMAT_COUNT) { if (idx < Resource::IMG_FORMAT_COUNT) {
img = static_cast<StoryProject::SoundFormat>(idx); img = static_cast<Resource::SoundFormat>(idx);
} }
return img; return img;
@ -652,6 +666,11 @@ void MainWindow::OpenProject(const std::string &uuid)
CloseProject(); CloseProject();
m_story = m_libraryManager.GetStory(uuid); m_story = m_libraryManager.GetStory(uuid);
// DEBUG CODE !!!!!!!!!!!!! Permet si décommenter de forcer l'import, permet de tester plus facilement l'algo en ouvrant le projet
// PackArchive arch(*this);
// std::string basePath = m_libraryManager.LibraryPath() + "/" + uuid;
// arch.ConvertJsonStudioToOst(basePath, uuid, m_libraryManager.LibraryPath());
if (!m_story) if (!m_story)
{ {
Log("Cannot find story: " + uuid); Log("Cannot find story: " + uuid);
@ -712,11 +731,11 @@ void MainWindow::RefreshProjectInformation()
void MainWindow::CloseProject() void MainWindow::CloseProject()
{ {
if (m_story) // if (m_story)
{ // {
m_story->Clear(); // m_story->Clear();
m_story.reset(); // m_story.reset();
} // }
m_resources.Clear(); m_resources.Clear();
@ -736,7 +755,43 @@ void MainWindow::CloseProject()
} }
void MainWindow::DrawToolBar(float topPadding)
{
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration |
ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoScrollbar |
ImGuiWindowFlags_NoScrollWithMouse |
ImGuiWindowFlags_NoDocking;
// Définit la taille et la position de la barre d'outils
ImVec2 size = ImVec2(60, ImGui::GetIO().DisplaySize.y - topPadding); // Largeur de 60 pixels et hauteur égale à celle de l'écran
ImGui::SetNextWindowSize(size);
ImGui::SetNextWindowPos(ImVec2(0, topPadding)); // Positionné à gauche et en haut
// Création de la fenêtre pour la barre d'outils
ImGui::Begin("ToolBar", nullptr, window_flags);
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); // rouge
float old_size = ImGui::GetFont()->Scale;
ImGui::GetFont()->Scale *= 2.5;
ImGui::PushFont(ImGui::GetFont());
// Ajouter des boutons à la barre d'outils
if (ImGui::Button(ICON_MDI_SPEAKER_STOP "##stop_sound", ImVec2(-1, 50))) { // Le bouton prend toute la largeur de la fenêtre et a une hauteur de 50 pixels
m_player.Stop();
}
ImGui::GetFont()->Scale = old_size;
ImGui::PopFont();
ImGui::PopStyleColor();
// Fermeture de la fenêtre ImGui
ImGui::End();
}
#include "imgui_internal.h"
void MainWindow::Loop() void MainWindow::Loop()
{ {
// Main loop // Main loop
@ -749,14 +804,21 @@ void MainWindow::Loop()
m_gui.StartFrame(); m_gui.StartFrame();
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()); auto vp = ImGui::GetMainViewport();
DrawMainMenuBar();
auto pos = vp->WorkPos;
auto size = vp->WorkSize;
pos.x += 60;
size.x -= 60;
vp->WorkPos = pos;
vp->WorkSize = size;
ImGui::DockSpaceOverViewport(vp);
float height = DrawMainMenuBar();
// DrawStatusBar(); // DrawStatusBar();
ProcessStory(); ProcessStory();
// ------------ Draw all windows // ------------ Draw all windows
m_libraryWindow.Draw(); m_libraryWindow.Draw();
@ -771,6 +833,12 @@ void MainWindow::Loop()
m_PropertiesWindow.SetSelectedNode(m_nodeEditorWindow.GetSelectedNode()); m_PropertiesWindow.SetSelectedNode(m_nodeEditorWindow.GetSelectedNode());
m_PropertiesWindow.Draw(); m_PropertiesWindow.Draw();
// static ImGuiAxis toolbar2_axis = ImGuiAxis_Y;
// DockingToolbar("Toolbar2", &toolbar2_axis);
DrawToolBar(height);
} }
ProjectPropertiesPopup(); ProjectPropertiesPopup();
@ -863,7 +931,7 @@ void MainWindow::Build(bool compileonly)
if (!compileonly) if (!compileonly)
{ {
// 3. Convert all media to desired type format // 3. Convert all media to desired type format
m_resources.ConvertResources(m_story->AssetsPath(), ""); // pas de répertoire de destination m_resources.ConvertResources(m_story->AssetsPath(), "", m_story->GetImageFormat(), m_story->GetSoundFormat()); // pas de répertoire de destination
} }
Chip32::Assembler::Error err; Chip32::Assembler::Error err;

View file

@ -69,7 +69,7 @@ public:
MainWindow(); MainWindow();
~MainWindow(); ~MainWindow();
void Initialize(); bool Initialize();
void Loop(); void Loop();
private: private:
@ -155,8 +155,9 @@ private:
void SaveParams(); void SaveParams();
void LoadParams(); void LoadParams();
void DrawMainMenuBar(); float DrawMainMenuBar();
bool ShowQuitConfirm(); bool ShowQuitConfirm();
void DrawToolBar(float topPadding);
void SaveProject(); void SaveProject();
void CloseProject(); void CloseProject();

View file

@ -37,7 +37,9 @@ NodeEditorWindow::~NodeEditorWindow()
void NodeEditorWindow::Initialize() void NodeEditorWindow::Initialize()
{ {
ed::Config config; ed::Config config;
config.SettingsFile = "Widgets.json"; config.SettingsFile = nullptr;
config.SaveSettings = nullptr;
config.LoadSettings = nullptr;
m_context = ed::CreateEditor(&config); m_context = ed::CreateEditor(&config);
ed::SetCurrentEditor(m_context); ed::SetCurrentEditor(m_context);