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:
 | 
			
		||||
  AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app);
 | 
			
		||||
  virtual ~AOMusicPlayer();
 | 
			
		||||
 | 
			
		||||
  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_volume(int p_value, int channel=-1);
 | 
			
		||||
  void set_looping(bool toggle, int channel=0);
 | 
			
		||||
 | 
			
		||||
  const int m_channelmax = 4;
 | 
			
		||||
 | 
			
		||||
  //These have to be public for the stupid sync thing
 | 
			
		||||
//  QWORD loop_start = 0;
 | 
			
		||||
//  QWORD loop_end = 0;
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
  void play(QString p_song, int channel=0, bool crossfade=false);
 | 
			
		||||
  void stop(int channel=0);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  QWidget *m_parent;
 | 
			
		||||
  AOApplication *ao_app;
 | 
			
		||||
@ -36,7 +39,6 @@ private:
 | 
			
		||||
  bool m_looping = false;
 | 
			
		||||
  int m_volume = 0;
 | 
			
		||||
 | 
			
		||||
  const int m_channelmax = 4;
 | 
			
		||||
  // Channel 0 = music
 | 
			
		||||
  // Channel 1 = ambience
 | 
			
		||||
  // Channel 2 = extra
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,7 @@
 | 
			
		||||
#include "datatypes.h"
 | 
			
		||||
#include "debug_functions.h"
 | 
			
		||||
#include "chatlogpiece.h"
 | 
			
		||||
#include "scrolltext.h"
 | 
			
		||||
 | 
			
		||||
#include <QMainWindow>
 | 
			
		||||
#include <QLineEdit>
 | 
			
		||||
@ -445,6 +446,9 @@ private:
 | 
			
		||||
  QListWidget *ui_area_list;
 | 
			
		||||
  QListWidget *ui_music_list;
 | 
			
		||||
 | 
			
		||||
  ScrollText *ui_music_name;
 | 
			
		||||
  AOMovie *ui_music_display;
 | 
			
		||||
 | 
			
		||||
  AOButton *ui_pair_button;
 | 
			
		||||
  QListWidget *ui_pair_list;
 | 
			
		||||
  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)
 | 
			
		||||
{
 | 
			
		||||
  channel = channel % m_channelmax;
 | 
			
		||||
  if (channel < 0) //wtf?
 | 
			
		||||
      return;
 | 
			
		||||
  QString f_path = ao_app->get_music_path(p_song);
 | 
			
		||||
//  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;
 | 
			
		||||
  if (m_looping)
 | 
			
		||||
    flags |= BASS_SAMPLE_LOOP;
 | 
			
		||||
  DWORD newstream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags);
 | 
			
		||||
 | 
			
		||||
  if (ao_app->get_audio_output_device() != "default")
 | 
			
		||||
    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];
 | 
			
		||||
 | 
			
		||||
    //Fade out the other sample and stop it
 | 
			
		||||
    BASS_ChannelSlideAttribute(oldstream, BASS_ATTRIB_VOL|BASS_SLIDE_LOG, -1, 5000);
 | 
			
		||||
    BASS_ChannelLock(oldstream, true);
 | 
			
		||||
    //Mute the new sample
 | 
			
		||||
    BASS_ChannelSetAttribute(newstream, BASS_ATTRIB_VOL, 0);
 | 
			
		||||
    //Sync it with the new sample
 | 
			
		||||
    BASS_ChannelSetPosition(newstream, BASS_ChannelGetPosition(oldstream, BASS_POS_BYTE), BASS_POS_BYTE);
 | 
			
		||||
    //Crossfade time
 | 
			
		||||
    if (BASS_ChannelIsActive(oldstream) == BASS_ACTIVE_PLAYING)
 | 
			
		||||
    {
 | 
			
		||||
      //Fade out the other sample and stop it
 | 
			
		||||
      BASS_ChannelSlideAttribute(oldstream, BASS_ATTRIB_VOL|BASS_SLIDE_LOG, -1, 5000);
 | 
			
		||||
      BASS_ChannelLock(oldstream, true);
 | 
			
		||||
      //Sync it with the new sample
 | 
			
		||||
      BASS_ChannelSetPosition(newstream, BASS_ChannelGetPosition(oldstream, BASS_POS_BYTE), BASS_POS_BYTE);
 | 
			
		||||
      BASS_ChannelLock(oldstream, false);
 | 
			
		||||
    }
 | 
			
		||||
    //Start it
 | 
			
		||||
    BASS_ChannelPlay(newstream, false);
 | 
			
		||||
    //Fade in our sample
 | 
			
		||||
    BASS_ChannelSlideAttribute(newstream, BASS_ATTRIB_VOL, static_cast<float>(m_volume / 100.0f), 1000);
 | 
			
		||||
    BASS_ChannelLock(oldstream, false);
 | 
			
		||||
 | 
			
		||||
    m_stream_list[channel] = newstream;
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
@ -67,7 +75,7 @@ void AOMusicPlayer::play(QString p_song, int channel, bool crossfade)
 | 
			
		||||
    BASS_ChannelStop(m_stream_list[channel]);
 | 
			
		||||
    m_stream_list[channel] = newstream;
 | 
			
		||||
    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.
 | 
			
		||||
@ -82,7 +90,17 @@ void AOMusicPlayer::set_volume(int p_value, int channel)
 | 
			
		||||
{
 | 
			
		||||
  m_volume = p_value;
 | 
			
		||||
  float volume = m_volume / 100.0f;
 | 
			
		||||
  BASS_ChannelSetAttribute(m_stream_list[channel], BASS_ATTRIB_VOL, volume);
 | 
			
		||||
  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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//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_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->setFrame(false);
 | 
			
		||||
  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_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)
 | 
			
		||||
  {
 | 
			
		||||
    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_music_list, "", "music_list");
 | 
			
		||||
  set_font(ui_area_list, "", "area_list");
 | 
			
		||||
  set_font(ui_music_name, "", "music_name");
 | 
			
		||||
 | 
			
		||||
  set_dropdowns();
 | 
			
		||||
}
 | 
			
		||||
@ -1081,7 +1108,12 @@ void Courtroom::enter_courtroom()
 | 
			
		||||
  list_music();
 | 
			
		||||
  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());
 | 
			
		||||
  objection_player->set_volume(ui_sfx_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)
 | 
			
		||||
  {
 | 
			
		||||
    QString i_area = "";
 | 
			
		||||
    i_area.append("[");
 | 
			
		||||
    i_area.append(QString::number(n_area));
 | 
			
		||||
    i_area.append("] ");
 | 
			
		||||
 | 
			
		||||
    i_area.append(area_list.at(n_area));
 | 
			
		||||
 | 
			
		||||
    if (ao_app->arup_enabled)
 | 
			
		||||
    {
 | 
			
		||||
      i_area.prepend("[" + QString::number(n_area) + "] "); //Give it the index
 | 
			
		||||
 | 
			
		||||
      i_area.append("\n  ");
 | 
			
		||||
 | 
			
		||||
      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("."));
 | 
			
		||||
  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())
 | 
			
		||||
  {
 | 
			
		||||
    music_player->set_looping(true);
 | 
			
		||||
    int channel = 0;
 | 
			
		||||
    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
 | 
			
		||||
      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?
 | 
			
		||||
    {
 | 
			
		||||
      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
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qDebug() << f_song << channel << p_contents->at(3) << looping;
 | 
			
		||||
    music_player->set_looping(looping, channel);
 | 
			
		||||
    music_player->play(f_song, channel, crossfade);
 | 
			
		||||
    if (channel == 0)
 | 
			
		||||
      ui_music_name->setText(f_song);
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    QString str_char = 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)
 | 
			
		||||
    {
 | 
			
		||||
@ -2905,20 +2938,15 @@ void Courtroom::handle_song(QStringList *p_contents)
 | 
			
		||||
          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"
 | 
			
		||||
        //(if we even have this length) but alright
 | 
			
		||||
        if(p_contents->at(3) != "-1")
 | 
			
		||||
        {
 | 
			
		||||
          music_player->set_looping(false);
 | 
			
		||||
        }
 | 
			
		||||
        looping = false;
 | 
			
		||||
    }
 | 
			
		||||
    int channel = 0;
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
    bool crossfade = false;
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
@ -2934,7 +2962,10 @@ void Courtroom::handle_song(QStringList *p_contents)
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      append_ic_text(f_song_clear, str_show, true);
 | 
			
		||||
      music_player->set_looping(looping, channel);
 | 
			
		||||
      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)
 | 
			
		||||
{
 | 
			
		||||
  music_player->set_volume(p_value);
 | 
			
		||||
  music_player->set_volume(p_value, 0); //Set volume on music layer
 | 
			
		||||
  ui_ic_chat_message->setFocus();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Courtroom::on_sfx_slider_moved(int 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);
 | 
			
		||||
  ui_ic_chat_message->setFocus();
 | 
			
		||||
}
 | 
			
		||||
@ -3986,7 +4022,6 @@ void Courtroom::on_change_character_clicked()
 | 
			
		||||
{
 | 
			
		||||
  music_player->set_volume(0);
 | 
			
		||||
  sfx_player->set_volume(0);
 | 
			
		||||
  sfx_player->set_volume(0);
 | 
			
		||||
  blip_player->set_volume(0);
 | 
			
		||||
 | 
			
		||||
  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