enhance editor toolbar sounds

This commit is contained in:
dobrykafe 2023-09-18 10:54:45 +02:00
parent 48a92f1eac
commit ca517f27b8
4 changed files with 168 additions and 22 deletions

View file

@ -618,7 +618,7 @@ void CSound::UnloadSample(int SampleID)
m_aSamples[SampleID].m_pData = nullptr;
}
float CSound::GetSampleDuration(int SampleID)
float CSound::GetSampleTotalTime(int SampleID)
{
if(SampleID == -1 || SampleID >= NUM_SAMPLES)
return 0.0f;
@ -626,6 +626,50 @@ float CSound::GetSampleDuration(int SampleID)
return (m_aSamples[SampleID].m_NumFrames / m_aSamples[SampleID].m_Rate);
}
float CSound::GetSampleCurrentTime(int SampleID)
{
if(SampleID == -1 || SampleID >= NUM_SAMPLES)
return 0.0f;
CSample *pSample = &m_aSamples[SampleID];
if(IsPlaying(SampleID))
{
for(auto &Voice : m_aVoices)
{
if(Voice.m_pSample == pSample)
{
return (Voice.m_Tick / pSample->m_Rate);
}
}
}
else
{
return (pSample->m_PausedAt / pSample->m_Rate);
}
}
void CSound::SetSampleCurrentTime(int SampleID, float Time)
{
if(SampleID == -1 || SampleID >= NUM_SAMPLES)
return;
CSample *pSample = &m_aSamples[SampleID];
if(IsPlaying(SampleID))
{
for(auto &Voice : m_aVoices)
{
if(Voice.m_pSample == pSample)
{
Voice.m_Tick = pSample->m_NumFrames * Time;
}
}
}
else
{
pSample->m_PausedAt = pSample->m_NumFrames * Time;
}
}
void CSound::SetChannel(int ChannelID, float Vol, float Pan)
{
m_aChannels[ChannelID].m_Vol = (int)(Vol * 255.0f);
@ -772,9 +816,18 @@ ISound::CVoiceHandle CSound::Play(int ChannelID, int SampleID, int Flags, float
m_aVoices[VoiceID].m_pSample = &m_aSamples[SampleID];
m_aVoices[VoiceID].m_pChannel = &m_aChannels[ChannelID];
if(Flags & FLAG_LOOP)
{
m_aVoices[VoiceID].m_Tick = m_aSamples[SampleID].m_PausedAt;
}
else if(Flags & FLAG_PREVIEW)
{
m_aVoices[VoiceID].m_Tick = m_aSamples[SampleID].m_PausedAt;
m_aSamples[SampleID].m_PausedAt = 0;
}
else
{
m_aVoices[VoiceID].m_Tick = 0;
}
m_aVoices[VoiceID].m_Vol = 255;
m_aVoices[VoiceID].m_Flags = Flags;
m_aVoices[VoiceID].m_X = (int)x;
@ -799,6 +852,21 @@ ISound::CVoiceHandle CSound::Play(int ChannelID, int SampleID, int Flags)
return Play(ChannelID, SampleID, Flags, 0, 0);
}
void CSound::Pause(int SampleID)
{
// TODO: a nice fade out
std::unique_lock<std::mutex> Lock(m_SoundLock);
CSample *pSample = &m_aSamples[SampleID];
for(auto &Voice : m_aVoices)
{
if(Voice.m_pSample == pSample)
{
Voice.m_pSample->m_PausedAt = Voice.m_Tick;
Voice.m_pSample = 0;
}
}
}
void CSound::Stop(int SampleID)
{
// TODO: a nice fade out

View file

@ -96,7 +96,9 @@ public:
int LoadWVFromMem(const void *pData, unsigned DataSize, bool FromEditor) override;
void UnloadSample(int SampleID) override;
float GetSampleDuration(int SampleID) override; // in s
float GetSampleTotalTime(int SampleID) override; // in s
float GetSampleCurrentTime(int SampleID) override; // in s
void SetSampleCurrentTime(int SampleID, float Time) override;
void SetChannel(int ChannelID, float Vol, float Pan) override;
void SetListenerPos(float x, float y) override;
@ -112,6 +114,7 @@ public:
CVoiceHandle Play(int ChannelID, int SampleID, int Flags, float x, float y);
CVoiceHandle PlayAt(int ChannelID, int SampleID, int Flags, float x, float y) override;
CVoiceHandle Play(int ChannelID, int SampleID, int Flags) override;
void Pause(int SampleID) override;
void Stop(int SampleID) override;
void StopAll() override;
void StopVoice(CVoiceHandle Voice) override;

View file

@ -15,7 +15,8 @@ public:
FLAG_LOOP = 1 << 0,
FLAG_POS = 1 << 1,
FLAG_NO_PANNING = 1 << 2,
FLAG_ALL = FLAG_LOOP | FLAG_POS | FLAG_NO_PANNING,
FLAG_PREVIEW = 1 << 3,
FLAG_ALL = FLAG_LOOP | FLAG_POS | FLAG_NO_PANNING | FLAG_PREVIEW,
};
enum
@ -68,7 +69,9 @@ public:
virtual int LoadWVFromMem(const void *pData, unsigned DataSize, bool FromEditor = false) = 0;
virtual void UnloadSample(int SampleID) = 0;
virtual float GetSampleDuration(int SampleID) = 0; // in s
virtual float GetSampleTotalTime(int SampleID) = 0; // in s
virtual float GetSampleCurrentTime(int SampleID) = 0; // in s
virtual void SetSampleCurrentTime(int SampleID, float Time) = 0;
virtual void SetChannel(int ChannelID, float Volume, float Panning) = 0;
virtual void SetListenerPos(float x, float y) = 0;
@ -83,6 +86,7 @@ public:
virtual CVoiceHandle PlayAt(int ChannelID, int SampleID, int Flags, float x, float y) = 0;
virtual CVoiceHandle Play(int ChannelID, int SampleID, int Flags) = 0;
virtual void Pause(int SampleID) = 0;
virtual void Stop(int SampleID) = 0;
virtual void StopAll() = 0;
virtual void StopVoice(CVoiceHandle Voice) = 0;

View file

@ -1257,35 +1257,106 @@ void CEditor::DoToolbarLayers(CUIRect ToolBar)
void CEditor::DoToolbarSounds(CUIRect ToolBar)
{
CUIRect ToolBarTop, ToolBarBottom, Button;
CUIRect ToolBarTop, ToolBarBottom, Button, SeekBar;
ToolBar.HSplitMid(&ToolBarTop, &ToolBarBottom, 5.0f);
if(m_SelectedSound >= 0 && (size_t)m_SelectedSound < m_Map.m_vpSounds.size())
{
const std::shared_ptr<CEditorSound> pSelectedSound = m_Map.m_vpSounds[m_SelectedSound];
// play/stop button
// play/pause button
{
ToolBarBottom.VSplitLeft(ToolBarBottom.h, &Button, &ToolBarBottom);
static int s_PlayStopButton;
if(DoButton_FontIcon(&s_PlayStopButton, Sound()->IsPlaying(pSelectedSound->m_SoundID) ? FONT_ICON_STOP : FONT_ICON_PLAY, 0, &Button, 0, "Play/stop audio preview", IGraphics::CORNER_ALL) ||
static int s_PlayPauseButton;
if(DoButton_FontIcon(&s_PlayPauseButton, Sound()->IsPlaying(pSelectedSound->m_SoundID) ? FONT_ICON_PAUSE : FONT_ICON_PLAY, 0, &Button, 0, "Play/pause audio preview", IGraphics::CORNER_ALL) ||
(m_Dialog == DIALOG_NONE && CLineInput::GetActiveInput() == nullptr && Input()->KeyPress(KEY_SPACE)))
{
if(Sound()->IsPlaying(pSelectedSound->m_SoundID))
Sound()->Stop(pSelectedSound->m_SoundID);
Sound()->Pause(pSelectedSound->m_SoundID);
else
Sound()->Play(CSounds::CHN_GUI, pSelectedSound->m_SoundID, 0);
Sound()->Play(CSounds::CHN_GUI, pSelectedSound->m_SoundID, ISound::FLAG_PREVIEW);
}
}
// duration
// stop button
{
ToolBarBottom.VSplitLeft(2.0f, nullptr, &ToolBarBottom);
ToolBarBottom.VSplitLeft(ToolBarBottom.h, &Button, &ToolBarBottom);
static int s_StopButton;
if(DoButton_FontIcon(&s_StopButton, FONT_ICON_STOP, 0, &Button, 0, "Stop audio preview", IGraphics::CORNER_ALL))
{
Sound()->Stop(pSelectedSound->m_SoundID);
}
}
// do seekbar
{
ToolBarBottom.VSplitLeft(5.0f, nullptr, &ToolBarBottom);
char aDuration[32];
char aDurationLabel[64];
str_time_float(Sound()->GetSampleDuration(pSelectedSound->m_SoundID), TIME_HOURS, aDuration, sizeof(aDuration));
str_format(aDurationLabel, sizeof(aDurationLabel), "Duration: %s", aDuration);
UI()->DoLabel(&ToolBarBottom, aDurationLabel, 12.0f, TEXTALIGN_ML);
ToolBarBottom.VSplitLeft(200.0f, &SeekBar, &ToolBarBottom);
const float Rounding = 5.0f;
static int s_SeekBarID = 0;
void *pId = &s_SeekBarID;
char aBuffer[64];
float CurrentTime = Sound()->GetSampleCurrentTime(pSelectedSound->m_SoundID);
float TotalTime = Sound()->GetSampleTotalTime(pSelectedSound->m_SoundID);
// draw seek bar
SeekBar.Draw(ColorRGBA(0, 0, 0, 0.5f), IGraphics::CORNER_ALL, Rounding);
// draw filled bar
float Amount = CurrentTime / TotalTime;
CUIRect FilledBar = SeekBar;
FilledBar.w = 2 * Rounding + (FilledBar.w - 2 * Rounding) * Amount;
FilledBar.Draw(ColorRGBA(1, 1, 1, 0.5f), IGraphics::CORNER_ALL, Rounding);
// draw time
char aCurrentTime[32];
str_time_float(CurrentTime, TIME_HOURS, aCurrentTime, sizeof(aCurrentTime));
char aTotalTime[32];
str_time_float(TotalTime, TIME_HOURS, aTotalTime, sizeof(aTotalTime));
str_format(aBuffer, sizeof(aBuffer), "%s / %s", aCurrentTime, aTotalTime);
UI()->DoLabel(&SeekBar, aBuffer, SeekBar.h * 0.70f, TEXTALIGN_MC);
// do the logic
const bool Inside = UI()->MouseInside(&SeekBar);
if(UI()->CheckActiveItem(pId))
{
if(!UI()->MouseButton(0))
UI()->SetActiveItem(nullptr);
else
{
static float s_PrevAmount = 0.0f;
float AmountSeek = clamp((UI()->MouseX() - SeekBar.x - Rounding) / (float)(SeekBar.w - 2 * Rounding), 0.0f, 1.0f);
if(Input()->ShiftIsPressed())
{
AmountSeek = s_PrevAmount + (AmountSeek - s_PrevAmount) * 0.05f;
if(AmountSeek >= 0.0f && AmountSeek <= 1.0f && absolute(s_PrevAmount - AmountSeek) >= 0.0001f)
{
Sound()->SetSampleCurrentTime(pSelectedSound->m_SoundID, AmountSeek);
}
}
else
{
if(AmountSeek >= 0.0f && AmountSeek <= 1.0f && absolute(s_PrevAmount - AmountSeek) >= 0.001f)
{
s_PrevAmount = AmountSeek;
Sound()->SetSampleCurrentTime(pSelectedSound->m_SoundID, AmountSeek);
}
}
}
}
else if(UI()->HotItem() == pId)
{
if(UI()->MouseButton(0))
{
UI()->SetActiveItem(pId);
}
}
if(Inside)
UI()->SetHotItem(pId);
}
}
}
@ -4689,11 +4760,11 @@ void CEditor::RenderFileDialog()
Sound()->Play(CSounds::CHN_GUI, m_FilePreviewSound, 0);
}
char aDuration[32];
char aDurationLabel[64];
str_time_float(Sound()->GetSampleDuration(m_FilePreviewSound), TIME_HOURS, aDuration, sizeof(aDuration));
str_format(aDurationLabel, sizeof(aDurationLabel), "Duration: %s", aDuration);
UI()->DoLabel(&Preview, aDurationLabel, 12.0f, TEXTALIGN_ML);
char aTotalTime[32];
char aTotalTimeLabel[64];
str_time_float(Sound()->GetSampleTotalTime(m_FilePreviewSound), TIME_HOURS, aTotalTime, sizeof(aTotalTime));
str_format(aTotalTimeLabel, sizeof(aTotalTimeLabel), "Duration: %s", aTotalTime);
UI()->DoLabel(&Preview, aTotalTimeLabel, 12.0f, TEXTALIGN_ML);
}
else if(m_FilePreviewState == PREVIEW_ERROR)
{