Tweak the ambience/crosfade layer to fade in regardless of another sample being there
Fix music not being looped sometimes Prevent channel less than 0 from being passed Set up a new music display element with an attached music name, it displays a scrolling text of the currently playing music Fix music packet processing issues Make SFX slider responsible for all music channels besides 0 (actual music) scrolltext.cpp code recipe was taken from https://stackoverflow.com/questions/10651514/text-scrolling-marquee-in-qlabel - thanks to leemes for that one, I only adapted it for newer C++ version and tweaked some stuff.
This commit is contained in:
parent
497901e8c3
commit
842b829bee
@ -19,16 +19,19 @@ class AOMusicPlayer
|
|||||||
public:
|
public:
|
||||||
AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app);
|
AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app);
|
||||||
virtual ~AOMusicPlayer();
|
virtual ~AOMusicPlayer();
|
||||||
|
void set_volume(int p_value, int channel=-1);
|
||||||
void play(QString p_song, int channel=0, bool crossfade=false);
|
|
||||||
void stop(int channel=0);
|
|
||||||
void set_volume(int p_value, int channel=0);
|
|
||||||
void set_looping(bool toggle, int channel=0);
|
void set_looping(bool toggle, int channel=0);
|
||||||
|
|
||||||
|
const int m_channelmax = 4;
|
||||||
|
|
||||||
//These have to be public for the stupid sync thing
|
//These have to be public for the stupid sync thing
|
||||||
// QWORD loop_start = 0;
|
// QWORD loop_start = 0;
|
||||||
// QWORD loop_end = 0;
|
// QWORD loop_end = 0;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void play(QString p_song, int channel=0, bool crossfade=false);
|
||||||
|
void stop(int channel=0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWidget *m_parent;
|
QWidget *m_parent;
|
||||||
AOApplication *ao_app;
|
AOApplication *ao_app;
|
||||||
@ -36,7 +39,6 @@ private:
|
|||||||
bool m_looping = false;
|
bool m_looping = false;
|
||||||
int m_volume = 0;
|
int m_volume = 0;
|
||||||
|
|
||||||
const int m_channelmax = 4;
|
|
||||||
// Channel 0 = music
|
// Channel 0 = music
|
||||||
// Channel 1 = ambience
|
// Channel 1 = ambience
|
||||||
// Channel 2 = extra
|
// Channel 2 = extra
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "debug_functions.h"
|
#include "debug_functions.h"
|
||||||
#include "chatlogpiece.h"
|
#include "chatlogpiece.h"
|
||||||
|
#include "scrolltext.h"
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
@ -445,6 +446,9 @@ private:
|
|||||||
QListWidget *ui_area_list;
|
QListWidget *ui_area_list;
|
||||||
QListWidget *ui_music_list;
|
QListWidget *ui_music_list;
|
||||||
|
|
||||||
|
ScrollText *ui_music_name;
|
||||||
|
AOMovie *ui_music_display;
|
||||||
|
|
||||||
AOButton *ui_pair_button;
|
AOButton *ui_pair_button;
|
||||||
QListWidget *ui_pair_list;
|
QListWidget *ui_pair_list;
|
||||||
QSpinBox *ui_pair_offset_spinbox;
|
QSpinBox *ui_pair_offset_spinbox;
|
||||||
|
50
include/scrolltext.h
Normal file
50
include/scrolltext.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef SCROLLTEXT_H
|
||||||
|
#define SCROLLTEXT_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QStaticText>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
|
||||||
|
class ScrollText : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString text READ text WRITE setText)
|
||||||
|
Q_PROPERTY(QString separator READ separator WRITE setSeparator)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ScrollText(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
QString text() const;
|
||||||
|
void setText(QString text);
|
||||||
|
|
||||||
|
QString separator() const;
|
||||||
|
void setSeparator(QString separator);
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void paintEvent(QPaintEvent *);
|
||||||
|
virtual void resizeEvent(QResizeEvent *);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateText();
|
||||||
|
QString _text;
|
||||||
|
QString _separator;
|
||||||
|
QStaticText staticText;
|
||||||
|
int singleTextWidth;
|
||||||
|
QSize wholeTextSize;
|
||||||
|
int leftMargin;
|
||||||
|
bool scrollEnabled;
|
||||||
|
int scrollPos;
|
||||||
|
QImage alphaChannel;
|
||||||
|
QImage buffer;
|
||||||
|
QTimer timer;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
virtual void timer_timeout();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SCROLLTEXT_H
|
@ -18,6 +18,8 @@ AOMusicPlayer::~AOMusicPlayer()
|
|||||||
void AOMusicPlayer::play(QString p_song, int channel, bool crossfade)
|
void AOMusicPlayer::play(QString p_song, int channel, bool crossfade)
|
||||||
{
|
{
|
||||||
channel = channel % m_channelmax;
|
channel = channel % m_channelmax;
|
||||||
|
if (channel < 0) //wtf?
|
||||||
|
return;
|
||||||
QString f_path = ao_app->get_music_path(p_song);
|
QString f_path = ao_app->get_music_path(p_song);
|
||||||
// QString d_path = f_path + ".txt";
|
// QString d_path = f_path + ".txt";
|
||||||
|
|
||||||
@ -39,27 +41,33 @@ void AOMusicPlayer::play(QString p_song, int channel, bool crossfade)
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
unsigned int flags = BASS_STREAM_PRESCAN | BASS_STREAM_AUTOFREE | BASS_UNICODE | BASS_ASYNCFILE;
|
unsigned int flags = BASS_STREAM_PRESCAN | BASS_STREAM_AUTOFREE | BASS_UNICODE | BASS_ASYNCFILE;
|
||||||
|
if (m_looping)
|
||||||
|
flags |= BASS_SAMPLE_LOOP;
|
||||||
DWORD newstream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags);
|
DWORD newstream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags);
|
||||||
|
|
||||||
if (ao_app->get_audio_output_device() != "default")
|
if (ao_app->get_audio_output_device() != "default")
|
||||||
BASS_ChannelSetDevice(m_stream_list[channel], BASS_GetDevice());
|
BASS_ChannelSetDevice(m_stream_list[channel], BASS_GetDevice());
|
||||||
|
|
||||||
if (BASS_ChannelIsActive(m_stream_list[channel]) == BASS_ACTIVE_PLAYING && crossfade)
|
if (crossfade)
|
||||||
{
|
{
|
||||||
DWORD oldstream = m_stream_list[channel];
|
DWORD oldstream = m_stream_list[channel];
|
||||||
|
//Mute the new sample
|
||||||
|
BASS_ChannelSetAttribute(newstream, BASS_ATTRIB_VOL, 0);
|
||||||
|
//Crossfade time
|
||||||
|
if (BASS_ChannelIsActive(oldstream) == BASS_ACTIVE_PLAYING)
|
||||||
|
{
|
||||||
//Fade out the other sample and stop it
|
//Fade out the other sample and stop it
|
||||||
BASS_ChannelSlideAttribute(oldstream, BASS_ATTRIB_VOL|BASS_SLIDE_LOG, -1, 5000);
|
BASS_ChannelSlideAttribute(oldstream, BASS_ATTRIB_VOL|BASS_SLIDE_LOG, -1, 5000);
|
||||||
BASS_ChannelLock(oldstream, true);
|
BASS_ChannelLock(oldstream, true);
|
||||||
//Mute the new sample
|
|
||||||
BASS_ChannelSetAttribute(newstream, BASS_ATTRIB_VOL, 0);
|
|
||||||
//Sync it with the new sample
|
//Sync it with the new sample
|
||||||
BASS_ChannelSetPosition(newstream, BASS_ChannelGetPosition(oldstream, BASS_POS_BYTE), BASS_POS_BYTE);
|
BASS_ChannelSetPosition(newstream, BASS_ChannelGetPosition(oldstream, BASS_POS_BYTE), BASS_POS_BYTE);
|
||||||
|
BASS_ChannelLock(oldstream, false);
|
||||||
|
}
|
||||||
//Start it
|
//Start it
|
||||||
BASS_ChannelPlay(newstream, false);
|
BASS_ChannelPlay(newstream, false);
|
||||||
//Fade in our sample
|
//Fade in our sample
|
||||||
BASS_ChannelSlideAttribute(newstream, BASS_ATTRIB_VOL, static_cast<float>(m_volume / 100.0f), 1000);
|
BASS_ChannelSlideAttribute(newstream, BASS_ATTRIB_VOL, static_cast<float>(m_volume / 100.0f), 1000);
|
||||||
BASS_ChannelLock(oldstream, false);
|
|
||||||
m_stream_list[channel] = newstream;
|
m_stream_list[channel] = newstream;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -67,7 +75,7 @@ void AOMusicPlayer::play(QString p_song, int channel, bool crossfade)
|
|||||||
BASS_ChannelStop(m_stream_list[channel]);
|
BASS_ChannelStop(m_stream_list[channel]);
|
||||||
m_stream_list[channel] = newstream;
|
m_stream_list[channel] = newstream;
|
||||||
BASS_ChannelPlay(m_stream_list[channel], false);
|
BASS_ChannelPlay(m_stream_list[channel], false);
|
||||||
this->set_volume(m_volume);
|
this->set_volume(m_volume, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->set_looping(m_looping); //Have to do this here due to any crossfading-related changes, etc.
|
this->set_looping(m_looping); //Have to do this here due to any crossfading-related changes, etc.
|
||||||
@ -82,8 +90,18 @@ void AOMusicPlayer::set_volume(int p_value, int channel)
|
|||||||
{
|
{
|
||||||
m_volume = p_value;
|
m_volume = p_value;
|
||||||
float volume = m_volume / 100.0f;
|
float volume = m_volume / 100.0f;
|
||||||
|
if (channel < 0)
|
||||||
|
{
|
||||||
|
for (int n_stream = 0 ; n_stream < m_channelmax ; ++n_stream)
|
||||||
|
{
|
||||||
|
BASS_ChannelSetAttribute(m_stream_list[n_stream], BASS_ATTRIB_VOL, volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
BASS_ChannelSetAttribute(m_stream_list[channel], BASS_ATTRIB_VOL, volume);
|
BASS_ChannelSetAttribute(m_stream_list[channel], BASS_ATTRIB_VOL, volume);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//void CALLBACK loopProc(HSYNC handle, DWORD channel, DWORD data, void *user)
|
//void CALLBACK loopProc(HSYNC handle, DWORD channel, DWORD data, void *user)
|
||||||
//{
|
//{
|
||||||
|
@ -125,6 +125,14 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
|
|||||||
ui_area_list->hide();
|
ui_area_list->hide();
|
||||||
ui_music_list = new QListWidget(this);
|
ui_music_list = new QListWidget(this);
|
||||||
|
|
||||||
|
ui_music_display = new AOMovie(this, ao_app);
|
||||||
|
ui_music_display->set_play_once(false);
|
||||||
|
ui_music_display->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
|
||||||
|
ui_music_name = new ScrollText(ui_music_display);
|
||||||
|
ui_music_name->setText(tr("None"));
|
||||||
|
ui_music_name->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
|
||||||
ui_ic_chat_name = new QLineEdit(this);
|
ui_ic_chat_name = new QLineEdit(this);
|
||||||
ui_ic_chat_name->setFrame(false);
|
ui_ic_chat_name->setFrame(false);
|
||||||
ui_ic_chat_name->setPlaceholderText(tr("Showname"));
|
ui_ic_chat_name->setPlaceholderText(tr("Showname"));
|
||||||
@ -544,6 +552,24 @@ void Courtroom::set_widgets()
|
|||||||
set_size_and_pos(ui_area_list, "music_list");
|
set_size_and_pos(ui_area_list, "music_list");
|
||||||
set_size_and_pos(ui_music_list, "music_list");
|
set_size_and_pos(ui_music_list, "music_list");
|
||||||
|
|
||||||
|
set_size_and_pos(ui_music_name, "music_name");
|
||||||
|
|
||||||
|
ui_music_display->move(0, 0);
|
||||||
|
design_ini_result = ao_app->get_element_dimensions("music_display", "courtroom_design.ini");
|
||||||
|
|
||||||
|
if (design_ini_result.width < 0 || design_ini_result.height < 0)
|
||||||
|
{
|
||||||
|
qDebug() << "W: could not find \"music_name\" in courtroom_design.ini";
|
||||||
|
ui_music_display->hide();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui_music_display->move(design_ini_result.x, design_ini_result.y);
|
||||||
|
ui_music_display->combo_resize(design_ini_result.width, design_ini_result.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_music_display->play("music_display");
|
||||||
|
|
||||||
if (is_ao2_bg)
|
if (is_ao2_bg)
|
||||||
{
|
{
|
||||||
set_size_and_pos(ui_ic_chat_message, "ao2_ic_chat_message");
|
set_size_and_pos(ui_ic_chat_message, "ao2_ic_chat_message");
|
||||||
@ -827,6 +853,7 @@ void Courtroom::set_fonts()
|
|||||||
set_font(ui_server_chatlog, "", "server_chatlog");
|
set_font(ui_server_chatlog, "", "server_chatlog");
|
||||||
set_font(ui_music_list, "", "music_list");
|
set_font(ui_music_list, "", "music_list");
|
||||||
set_font(ui_area_list, "", "area_list");
|
set_font(ui_area_list, "", "area_list");
|
||||||
|
set_font(ui_music_name, "", "music_name");
|
||||||
|
|
||||||
set_dropdowns();
|
set_dropdowns();
|
||||||
}
|
}
|
||||||
@ -1081,7 +1108,12 @@ void Courtroom::enter_courtroom()
|
|||||||
list_music();
|
list_music();
|
||||||
list_areas();
|
list_areas();
|
||||||
|
|
||||||
music_player->set_volume(ui_music_slider->value());
|
music_player->set_volume(ui_music_slider->value(), 0); //set music
|
||||||
|
//Set the ambience and other misc. music layers
|
||||||
|
for (int i = 1; i < music_player->m_channelmax; ++i)
|
||||||
|
{
|
||||||
|
music_player->set_volume(ui_sfx_slider->value(), i);
|
||||||
|
}
|
||||||
sfx_player->set_volume(ui_sfx_slider->value());
|
sfx_player->set_volume(ui_sfx_slider->value());
|
||||||
objection_player->set_volume(ui_sfx_slider->value());
|
objection_player->set_volume(ui_sfx_slider->value());
|
||||||
blip_player->set_volume(ui_blip_slider->value());
|
blip_player->set_volume(ui_blip_slider->value());
|
||||||
@ -1145,14 +1177,12 @@ void Courtroom::list_areas()
|
|||||||
for (int n_area = 0 ; n_area < area_list.size() ; ++n_area)
|
for (int n_area = 0 ; n_area < area_list.size() ; ++n_area)
|
||||||
{
|
{
|
||||||
QString i_area = "";
|
QString i_area = "";
|
||||||
i_area.append("[");
|
|
||||||
i_area.append(QString::number(n_area));
|
|
||||||
i_area.append("] ");
|
|
||||||
|
|
||||||
i_area.append(area_list.at(n_area));
|
i_area.append(area_list.at(n_area));
|
||||||
|
|
||||||
if (ao_app->arup_enabled)
|
if (ao_app->arup_enabled)
|
||||||
{
|
{
|
||||||
|
i_area.prepend("[" + QString::number(n_area) + "] "); //Give it the index
|
||||||
|
|
||||||
i_area.append("\n ");
|
i_area.append("\n ");
|
||||||
|
|
||||||
i_area.append(arup_statuses.at(n_area));
|
i_area.append(arup_statuses.at(n_area));
|
||||||
@ -2873,30 +2903,33 @@ void Courtroom::handle_song(QStringList *p_contents)
|
|||||||
f_song_clear = f_song_clear.left(f_song_clear.lastIndexOf("."));
|
f_song_clear = f_song_clear.left(f_song_clear.lastIndexOf("."));
|
||||||
int n_char = f_contents.at(1).toInt();
|
int n_char = f_contents.at(1).toInt();
|
||||||
|
|
||||||
|
bool looping = true;
|
||||||
|
int channel = 0;
|
||||||
|
bool crossfade = false;
|
||||||
if (n_char < 0 || n_char >= char_list.size())
|
if (n_char < 0 || n_char >= char_list.size())
|
||||||
{
|
{
|
||||||
music_player->set_looping(true);
|
|
||||||
int channel = 0;
|
int channel = 0;
|
||||||
if (p_contents->length() > 3 && p_contents->at(3) != "-1")
|
if (p_contents->length() > 3 && p_contents->at(3) != "-1")
|
||||||
music_player->set_looping(false);
|
looping = false;
|
||||||
|
|
||||||
if (p_contents->length() > 4) //eyyy we want to change this song's CHANNEL huh
|
if (p_contents->length() > 4) //eyyy we want to change this song's CHANNEL huh
|
||||||
channel = p_contents->at(4).toInt(); //let the music player handle it if it's bigger than the channel list
|
channel = p_contents->at(4).toInt(); //let the music player handle it if it's bigger than the channel list
|
||||||
|
|
||||||
bool crossfade = false;
|
|
||||||
if (p_contents->length() > 5) //CROSSFADE!? Are you MAD?
|
if (p_contents->length() > 5) //CROSSFADE!? Are you MAD?
|
||||||
{
|
{
|
||||||
qDebug() << p_contents->at(5);
|
|
||||||
crossfade = p_contents->at(5) == "1"; //let the music player handle it if it's bigger than the channel list
|
crossfade = p_contents->at(5) == "1"; //let the music player handle it if it's bigger than the channel list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qDebug() << f_song << channel << p_contents->at(3) << looping;
|
||||||
|
music_player->set_looping(looping, channel);
|
||||||
music_player->play(f_song, channel, crossfade);
|
music_player->play(f_song, channel, crossfade);
|
||||||
|
if (channel == 0)
|
||||||
|
ui_music_name->setText(f_song);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QString str_char = char_list.at(n_char).name;
|
QString str_char = char_list.at(n_char).name;
|
||||||
QString str_show = char_list.at(n_char).name;
|
QString str_show = char_list.at(n_char).name;
|
||||||
music_player->set_looping(true);
|
|
||||||
|
|
||||||
if (p_contents->length() > 2)
|
if (p_contents->length() > 2)
|
||||||
{
|
{
|
||||||
@ -2905,20 +2938,15 @@ void Courtroom::handle_song(QStringList *p_contents)
|
|||||||
str_show = p_contents->at(2);
|
str_show = p_contents->at(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p_contents->length() > 3)
|
if (p_contents->length() > 3 && p_contents->at(3) != "-1")
|
||||||
{
|
{
|
||||||
//I am really confused why "-1" is "loop this song" and why anything else passes as "don't loop"
|
//I am really confused why "-1" is "loop this song" and why anything else passes as "don't loop"
|
||||||
//(if we even have this length) but alright
|
//(if we even have this length) but alright
|
||||||
if(p_contents->at(3) != "-1")
|
looping = false;
|
||||||
{
|
|
||||||
music_player->set_looping(false);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
int channel = 0;
|
|
||||||
if (p_contents->length() > 4) //eyyy we want to change this song's CHANNEL huh
|
if (p_contents->length() > 4) //eyyy we want to change this song's CHANNEL huh
|
||||||
channel = p_contents->at(4).toInt(); //let the music player handle it if it's bigger than the channel list
|
channel = p_contents->at(4).toInt(); //let the music player handle it if it's bigger than the channel list
|
||||||
|
|
||||||
bool crossfade = false;
|
|
||||||
if (p_contents->length() > 5) //CROSSFADE!? Are you MAD?
|
if (p_contents->length() > 5) //CROSSFADE!? Are you MAD?
|
||||||
crossfade = p_contents->at(5) == "1"; //let the music player handle it if it's bigger than the channel list
|
crossfade = p_contents->at(5) == "1"; //let the music player handle it if it's bigger than the channel list
|
||||||
|
|
||||||
@ -2934,7 +2962,10 @@ void Courtroom::handle_song(QStringList *p_contents)
|
|||||||
}
|
}
|
||||||
|
|
||||||
append_ic_text(f_song_clear, str_show, true);
|
append_ic_text(f_song_clear, str_show, true);
|
||||||
|
music_player->set_looping(looping, channel);
|
||||||
music_player->play(f_song, channel, crossfade);
|
music_player->play(f_song, channel, crossfade);
|
||||||
|
if (channel == 0)
|
||||||
|
ui_music_name->setText(f_song);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3915,13 +3946,18 @@ void Courtroom::on_text_color_changed(int p_color)
|
|||||||
|
|
||||||
void Courtroom::on_music_slider_moved(int p_value)
|
void Courtroom::on_music_slider_moved(int p_value)
|
||||||
{
|
{
|
||||||
music_player->set_volume(p_value);
|
music_player->set_volume(p_value, 0); //Set volume on music layer
|
||||||
ui_ic_chat_message->setFocus();
|
ui_ic_chat_message->setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Courtroom::on_sfx_slider_moved(int p_value)
|
void Courtroom::on_sfx_slider_moved(int p_value)
|
||||||
{
|
{
|
||||||
sfx_player->set_volume(p_value);
|
sfx_player->set_volume(p_value);
|
||||||
|
//Set the ambience and other misc. music layers
|
||||||
|
for (int i = 1; i < music_player->m_channelmax; ++i)
|
||||||
|
{
|
||||||
|
music_player->set_volume(p_value, i);
|
||||||
|
}
|
||||||
objection_player->set_volume(p_value);
|
objection_player->set_volume(p_value);
|
||||||
ui_ic_chat_message->setFocus();
|
ui_ic_chat_message->setFocus();
|
||||||
}
|
}
|
||||||
@ -3986,7 +4022,6 @@ void Courtroom::on_change_character_clicked()
|
|||||||
{
|
{
|
||||||
music_player->set_volume(0);
|
music_player->set_volume(0);
|
||||||
sfx_player->set_volume(0);
|
sfx_player->set_volume(0);
|
||||||
sfx_player->set_volume(0);
|
|
||||||
blip_player->set_volume(0);
|
blip_player->set_volume(0);
|
||||||
|
|
||||||
set_char_select();
|
set_char_select();
|
||||||
|
134
src/scrolltext.cpp
Normal file
134
src/scrolltext.cpp
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#include "scrolltext.h"
|
||||||
|
|
||||||
|
|
||||||
|
ScrollText::ScrollText(QWidget *parent) :
|
||||||
|
QWidget(parent), scrollPos(0)
|
||||||
|
{
|
||||||
|
staticText.setTextFormat(Qt::PlainText);
|
||||||
|
|
||||||
|
// setFixedHeight(fontMetrics().height()*2); //The theme sets this
|
||||||
|
leftMargin = height() / 3;
|
||||||
|
|
||||||
|
setSeparator(" --- ");
|
||||||
|
|
||||||
|
connect(&timer, SIGNAL(timeout()), this, SLOT(timer_timeout()));
|
||||||
|
timer.setInterval(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScrollText::text() const
|
||||||
|
{
|
||||||
|
return _text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollText::setText(QString text)
|
||||||
|
{
|
||||||
|
_text = text;
|
||||||
|
updateText();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScrollText::separator() const
|
||||||
|
{
|
||||||
|
return _separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollText::setSeparator(QString separator)
|
||||||
|
{
|
||||||
|
_separator = separator;
|
||||||
|
updateText();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollText::updateText()
|
||||||
|
{
|
||||||
|
timer.stop();
|
||||||
|
|
||||||
|
singleTextWidth = fontMetrics().horizontalAdvance(_text);
|
||||||
|
scrollEnabled = (singleTextWidth > width() - leftMargin*2);
|
||||||
|
|
||||||
|
if(scrollEnabled)
|
||||||
|
{
|
||||||
|
scrollPos = -64;
|
||||||
|
staticText.setText(_text + _separator);
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
staticText.setText(_text);
|
||||||
|
|
||||||
|
staticText.prepare(QTransform(), font());
|
||||||
|
wholeTextSize = QSize(fontMetrics().horizontalAdvance(staticText.text()), fontMetrics().height());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollText::paintEvent(QPaintEvent*)
|
||||||
|
{
|
||||||
|
QPainter p(this);
|
||||||
|
|
||||||
|
if(scrollEnabled)
|
||||||
|
{
|
||||||
|
buffer.fill(qRgba(0, 0, 0, 0));
|
||||||
|
QPainter pb(&buffer);
|
||||||
|
pb.setPen(p.pen());
|
||||||
|
pb.setFont(p.font());
|
||||||
|
|
||||||
|
int x = qMin(-scrollPos, 0) + leftMargin;
|
||||||
|
while(x < width())
|
||||||
|
{
|
||||||
|
pb.drawStaticText(QPointF(x, (height() - wholeTextSize.height()) / 2), staticText);
|
||||||
|
x += wholeTextSize.width();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Apply Alpha Channel
|
||||||
|
pb.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||||
|
pb.setClipRect(width() - 15, 0, 15, height());
|
||||||
|
pb.drawImage(0, 0, alphaChannel);
|
||||||
|
pb.setClipRect(0, 0, 15, height());
|
||||||
|
//initial situation: don't apply alpha channel in the left half of the image at all; apply it more and more until scrollPos gets positive
|
||||||
|
if(scrollPos < 0)
|
||||||
|
pb.setOpacity(static_cast<qreal>((qMax(-8, scrollPos) + 8) / 8.0));
|
||||||
|
pb.drawImage(0, 0, alphaChannel);
|
||||||
|
|
||||||
|
//pb.end();
|
||||||
|
p.drawImage(0, 0, buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p.drawStaticText(QPointF(leftMargin, (height() - wholeTextSize.height()) / 2), staticText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollText::resizeEvent(QResizeEvent*)
|
||||||
|
{
|
||||||
|
//When the widget is resized, we need to update the alpha channel.
|
||||||
|
|
||||||
|
alphaChannel = QImage(size(), QImage::Format_ARGB32_Premultiplied);
|
||||||
|
buffer = QImage(size(), QImage::Format_ARGB32_Premultiplied);
|
||||||
|
|
||||||
|
//Create Alpha Channel:
|
||||||
|
if(width() > 64)
|
||||||
|
{
|
||||||
|
//create first scanline
|
||||||
|
QRgb* scanline1 = reinterpret_cast<QRgb*>(alphaChannel.scanLine(0));
|
||||||
|
for(int x = 1; x < 16; ++x)
|
||||||
|
scanline1[x - 1] = scanline1[width() - x] = qRgba(0, 0, 0, x << 4);
|
||||||
|
for(int x = 15; x < width() - 15; ++x)
|
||||||
|
scanline1[x] = qRgb(0, 0, 0);
|
||||||
|
//copy scanline to the other ones
|
||||||
|
for(int y = 1; y < height(); ++y)
|
||||||
|
memcpy(alphaChannel.scanLine(y), scanline1, static_cast<uint>(width() * 4));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
alphaChannel.fill(qRgb(0, 0, 0));
|
||||||
|
|
||||||
|
|
||||||
|
//Update scrolling state
|
||||||
|
bool newScrollEnabled = (singleTextWidth > width() - leftMargin);
|
||||||
|
if(newScrollEnabled != scrollEnabled)
|
||||||
|
updateText();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollText::timer_timeout()
|
||||||
|
{
|
||||||
|
scrollPos = (scrollPos + 2)
|
||||||
|
% wholeTextSize.width();
|
||||||
|
update();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user