Consolidate AOScene, AOMovie, and AOCharMovie into one class, add support for (c) animations, implement emote continuity, add scaling overrides to all layer types, allow for stretch-to-fill images, allow for additional effect configuration (#302)
* Rewrite AOScene and remove the need for AOMovie and AOCharMovie by consolidation * Rename AOScene to AOLayer, apply suggestions to improve functionality * Implement suggested change to allocation * Switch from pointer to field, fix ui_vp_player_char not resetting play_once * Use the variable gif_name instead of the string "gif_name" Oops. * Total rewrite of AOLayer (again) * Add support for (c) animations, do some housekeeping * allow themes to override misc chatboxes * add support for pulling InterfaceLayer elements from theme/misc * mistakes were made * move all frame fx functionality to CharLayer subclass * virtual functions are cool mkay * remove evidence of my incompetence * allow themes to override font design inis under theme/misc * Proper support for theme/misc chatbox, fixes * Fix chatbox dimensions not updating and inline color causing missingnos * rename chat markdown to chat markup * add missing misc overrides * quick hotfix for chatblank and misc overrides * Fix oversight with backgrounds causing them to be culled * Same as last commit but for FG layer * amend comment to explain impossible shenanigans * Adjust ForegroundLayer to take charname rather than miscname, allow for checking in char folder * fix an incredibly embarrassing pathing bug * add scaling overrides for all layer types, parent orphaned viewport elements to the viewport * stupid fix because themes use "custom.png" as a button * switch to .append() * Revert "Merge branch 'aoscene_rewrite' of https://github.com/AttorneyOnline/AO2-Client into aoscene_rewrite" This reverts commit bdeb1bff7639d522031aab3c133a83b0e2a291df, reversing changes made to 125ee63b97a6f6c156e69525d88fddc625e7a978. * switch to .append() (again) * move function call to fix showname length calculation error * fix nonlooping character animations being broken Again * unparent elements from the viewport and do fancy masking arithmetic instead * use override keyword * move scaling override to char.ini, allow stretching, restructure effect property loading * fix some redundancy * unparent chat_arrow from chatbox to prevent accidental masking * at no point do we want a frozen gif to display * overhaul how wtce is handled * oops * also let sounds be pulled from theme miscs * i should probably compile before i push * actually make it work * don't check a default bg * readd 1x1 stretch thing * actually the 1x1 thing was a bad idea * Add missing parenthesis * Use load_image instead of play play is a nonexistent method now * Remote shout_message and usages because it does nothing * Remove multiple redefinitions * Add in missing brackets and indent to fix build I have know idea what this does but it brings fear * fix build error * fix chat arrow and remove duped code * remove more duped code and fix misc themes * only update chat_arrow when needed * consolidate log_chatmessage and display_log_chatmessage Co-authored-by: scatterflower <marisaposs@gameboyprinter.moe> Co-authored-by: Skye Deving <76892045+skyedeving@users.noreply.github.com> Co-authored-by: oldmud0 <oldmud0@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									21b4aa5072
								
							
						
					
					
						commit
						894b2b2a0e
					
				@ -130,6 +130,7 @@ public:
 | 
				
			|||||||
  QString get_default_theme_path(QString p_file);
 | 
					  QString get_default_theme_path(QString p_file);
 | 
				
			||||||
  QString get_custom_theme_path(QString p_theme, QString p_file);
 | 
					  QString get_custom_theme_path(QString p_theme, QString p_file);
 | 
				
			||||||
  QString get_character_path(QString p_char, QString p_file);
 | 
					  QString get_character_path(QString p_char, QString p_file);
 | 
				
			||||||
 | 
					  QString get_misc_path(QString p_misc, QString p_file);
 | 
				
			||||||
  QString get_sounds_path(QString p_file);
 | 
					  QString get_sounds_path(QString p_file);
 | 
				
			||||||
  QString get_music_path(QString p_song);
 | 
					  QString get_music_path(QString p_song);
 | 
				
			||||||
  QString get_background_path(QString p_file);
 | 
					  QString get_background_path(QString p_file);
 | 
				
			||||||
@ -301,14 +302,14 @@ public:
 | 
				
			|||||||
  // Returns the color with p_identifier from p_file
 | 
					  // Returns the color with p_identifier from p_file
 | 
				
			||||||
  QColor get_color(QString p_identifier, QString p_file);
 | 
					  QColor get_color(QString p_identifier, QString p_file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Returns the markdown symbol used for specified p_identifier such as colors
 | 
					  // Returns the markup symbol used for specified p_identifier such as colors
 | 
				
			||||||
  QString get_chat_markdown(QString p_identifier, QString p_file);
 | 
					  QString get_chat_markup(QString p_identifier, QString p_file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Returns the color from the misc folder.
 | 
					  // Returns the color from the misc folder.
 | 
				
			||||||
  QColor get_chat_color(QString p_identifier, QString p_chat);
 | 
					  QColor get_chat_color(QString p_identifier, QString p_chat);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Returns the sfx with p_identifier from sounds.ini in the current theme path
 | 
					  // Returns the sfx with p_identifier from sounds.ini in the current theme path
 | 
				
			||||||
  QString get_sfx(QString p_identifier);
 | 
					  QString get_sfx(QString p_identifier, QString p_misc="default");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Figure out if we can opus this or if we should fall back to wav
 | 
					  // Figure out if we can opus this or if we should fall back to wav
 | 
				
			||||||
  QString get_sfx_suffix(QString sound_to_check);
 | 
					  QString get_sfx_suffix(QString sound_to_check);
 | 
				
			||||||
@ -380,9 +381,9 @@ public:
 | 
				
			|||||||
  // t
 | 
					  // t
 | 
				
			||||||
  QString get_effect(QString effect, QString p_char, QString p_folder);
 | 
					  QString get_effect(QString effect, QString p_char, QString p_folder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Return the effect sound associated with the fx_name in the
 | 
					  // Return p_property of fx_name. If p_property is "sound", return
 | 
				
			||||||
  // misc/effects/<char-defined>/sounds.ini, or theme/effects/sounds.ini.
 | 
					  // the value associated with fx_name, otherwise use fx_name + '_' + p_property.
 | 
				
			||||||
  QString get_effect_sound(QString fx_name, QString p_char);
 | 
					  QString get_effect_property(QString fx_name, QString p_char, QString p_property);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Returns the custom realisation used by the character.
 | 
					  // Returns the custom realisation used by the character.
 | 
				
			||||||
  QString get_custom_realization(QString p_char);
 | 
					  QString get_custom_realization(QString p_char);
 | 
				
			||||||
@ -432,6 +433,15 @@ public:
 | 
				
			|||||||
  // Returns p_char's blips (previously called their "gender")
 | 
					  // Returns p_char's blips (previously called their "gender")
 | 
				
			||||||
  QString get_blips(QString p_char);
 | 
					  QString get_blips(QString p_char);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Get a property of a given emote, or get it from "options" if emote doesn't have it
 | 
				
			||||||
 | 
					  QString get_emote_property(QString p_char, QString p_emote, QString p_property);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Return a transformation mode from a string ("smooth" for smooth, anything else for fast)
 | 
				
			||||||
 | 
					  Qt::TransformationMode get_scaling(QString p_scaling);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Returns the scaling type for p_miscname
 | 
				
			||||||
 | 
					  Qt::TransformationMode get_misc_scaling(QString p_miscname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // ======
 | 
					  // ======
 | 
				
			||||||
  // These are all casing-related settings.
 | 
					  // These are all casing-related settings.
 | 
				
			||||||
  // ======
 | 
					  // ======
 | 
				
			||||||
 | 
				
			|||||||
@ -1,125 +0,0 @@
 | 
				
			|||||||
#ifndef AOCHARMOVIE_H
 | 
					 | 
				
			||||||
#define AOCHARMOVIE_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <QDebug>
 | 
					 | 
				
			||||||
#include <QElapsedTimer>
 | 
					 | 
				
			||||||
#include <QImageReader>
 | 
					 | 
				
			||||||
#include <QLabel>
 | 
					 | 
				
			||||||
#include <QTimer>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AOApplication;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AOCharMovie : public QLabel {
 | 
					 | 
				
			||||||
  Q_OBJECT
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
  AOCharMovie(QWidget *p_parent, AOApplication *p_ao_app);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Play a hat.gif - style preanimation
 | 
					 | 
				
			||||||
  void play_pre(QString p_char, QString p_emote, int duration);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Play a (b)normal.gif - style animation (talking)
 | 
					 | 
				
			||||||
  void play_talking(QString p_char, QString p_emote);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Play an (a)normal.gif - style animation (not talking)
 | 
					 | 
				
			||||||
  void play_idle(QString p_char, QString p_emote);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Stop the movie, clearing the image
 | 
					 | 
				
			||||||
  void stop();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Set the m_flipped variable to true/false
 | 
					 | 
				
			||||||
  void set_flipped(bool p_flipped) { m_flipped = p_flipped; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Set the movie's playback speed (between 10% and 1000%)
 | 
					 | 
				
			||||||
  void set_speed(int modifier) { speed = qMax(10, qMin(modifier, 1000)); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Move the label itself around
 | 
					 | 
				
			||||||
  void move(int ax, int ay);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // This is somewhat pointless now as there's no "QMovie" object to resize, aka
 | 
					 | 
				
			||||||
  // no "combo" to speak of
 | 
					 | 
				
			||||||
  void combo_resize(int w, int h);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Return the frame delay adjusted for speed
 | 
					 | 
				
			||||||
  int get_frame_delay(int delay);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  QStringList network_strings;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  QString m_char;
 | 
					 | 
				
			||||||
  QString m_emote;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
  AOApplication *ao_app;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  QVector<QPixmap> movie_frames;
 | 
					 | 
				
			||||||
  QVector<int> movie_delays;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Effects such as sfx, screenshakes and realization flashes are stored in
 | 
					 | 
				
			||||||
  // here. QString entry format: "sfx^[sfx_name]", "shake", "flash". The program
 | 
					 | 
				
			||||||
  // uses the QVector index as reference.
 | 
					 | 
				
			||||||
  QVector<QVector<QString>> movie_effects;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  QTimer *preanim_timer;
 | 
					 | 
				
			||||||
  QTimer *ticker;
 | 
					 | 
				
			||||||
  QString last_path;
 | 
					 | 
				
			||||||
  QImageReader *m_reader = new QImageReader();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  QElapsedTimer actual_time;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Usually used to turn seconds into milliseconds such as for [Time] tag in
 | 
					 | 
				
			||||||
  // char.ini
 | 
					 | 
				
			||||||
  const int time_mod = 60;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // These are the X and Y values before they are fixed based on the sprite's
 | 
					 | 
				
			||||||
  // width.
 | 
					 | 
				
			||||||
  int x = 0;
 | 
					 | 
				
			||||||
  int y = 0;
 | 
					 | 
				
			||||||
  // These are the width and height values before they are fixed based on the
 | 
					 | 
				
			||||||
  // sprite's width.
 | 
					 | 
				
			||||||
  int f_w = 0;
 | 
					 | 
				
			||||||
  int f_h = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int frame = 0;
 | 
					 | 
				
			||||||
  int max_frames = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int speed = 100;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool m_flipped = false;
 | 
					 | 
				
			||||||
  bool play_once = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Set the movie's image to provided paths, preparing for playback.
 | 
					 | 
				
			||||||
  void load_image(QString p_char, QString p_emote, QString emote_prefix);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Start playback of the movie (if animated).
 | 
					 | 
				
			||||||
  void play();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Play a frame-specific effect, if there's any defined for that specific
 | 
					 | 
				
			||||||
  // frame.
 | 
					 | 
				
			||||||
  void play_frame_effect(int frame);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Retreive a pixmap adjused for mirroring/aspect ratio shenanigans from a
 | 
					 | 
				
			||||||
  // provided QImage
 | 
					 | 
				
			||||||
  QPixmap get_pixmap(QImage image);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Set the movie's frame to provided pixmap
 | 
					 | 
				
			||||||
  void set_frame(QPixmap f_pixmap);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Initialize the frame-specific effects from the char.ini
 | 
					 | 
				
			||||||
  void load_effects();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Initialize the frame-specific effects from the provided network_strings,
 | 
					 | 
				
			||||||
  // this is only initialized if network_strings has size more than 0.
 | 
					 | 
				
			||||||
  void load_network_effects();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
signals:
 | 
					 | 
				
			||||||
  void done();
 | 
					 | 
				
			||||||
  void shake();
 | 
					 | 
				
			||||||
  void flash();
 | 
					 | 
				
			||||||
  void play_sfx(QString sfx);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private slots:
 | 
					 | 
				
			||||||
  void preanim_done();
 | 
					 | 
				
			||||||
  void movie_ticker();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // AOCHARMOVIE_H
 | 
					 | 
				
			||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
#define AOEVIDENCEDISPLAY_H
 | 
					#define AOEVIDENCEDISPLAY_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "aoapplication.h"
 | 
					#include "aoapplication.h"
 | 
				
			||||||
#include "aomovie.h"
 | 
					#include "aolayer.h"
 | 
				
			||||||
#include "aosfxplayer.h"
 | 
					#include "aosfxplayer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QDebug>
 | 
					#include <QDebug>
 | 
				
			||||||
@ -21,7 +21,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  AOApplication *ao_app;
 | 
					  AOApplication *ao_app;
 | 
				
			||||||
  AOMovie *evidence_movie;
 | 
					  InterfaceLayer *evidence_movie;
 | 
				
			||||||
  QLabel *evidence_icon;
 | 
					  QLabel *evidence_icon;
 | 
				
			||||||
  AOSfxPlayer *sfx_player;
 | 
					  AOSfxPlayer *sfx_player;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										214
									
								
								include/aolayer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								include/aolayer.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,214 @@
 | 
				
			|||||||
 | 
					#ifndef AOLAYER_H
 | 
				
			||||||
 | 
					#define AOLAYER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QDebug>
 | 
				
			||||||
 | 
					#include <QElapsedTimer>
 | 
				
			||||||
 | 
					#include <QImageReader>
 | 
				
			||||||
 | 
					#include <QLabel>
 | 
				
			||||||
 | 
					#include <QTimer>
 | 
				
			||||||
 | 
					#include <QBitmap>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AOApplication;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AOLayer : public QLabel {
 | 
				
			||||||
 | 
					  Q_OBJECT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  AOLayer(QWidget *p_parent, AOApplication *p_ao_app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  QString filename;    // file name without extension, i.e. "witnesstestimony"
 | 
				
			||||||
 | 
					  int static_duration; // time in ms for static images to be displayed, if
 | 
				
			||||||
 | 
					                       // applicable. set to 0 for infinite
 | 
				
			||||||
 | 
					  int max_duration;    // maximum duration in ms, image will be culled if it is
 | 
				
			||||||
 | 
					                       // exceeded. set this to 0 for infinite duration
 | 
				
			||||||
 | 
					  bool play_once = false; // Whether to loop this animation or not
 | 
				
			||||||
 | 
					  bool cull_image = true; // if we're done playing this animation, should we
 | 
				
			||||||
 | 
					                          // hide it? also controls durational culling
 | 
				
			||||||
 | 
					  Qt::TransformationMode transform_mode = Qt::FastTransformation; // transformation mode to use for this image
 | 
				
			||||||
 | 
					  bool stretch = false; // Should we stretch/squash this image to fill the screen?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Set the movie's image to provided paths, preparing for playback.
 | 
				
			||||||
 | 
					  void start_playback(QString p_image);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void set_play_once(bool p_play_once);
 | 
				
			||||||
 | 
					  void set_cull_image(bool p_cull_image);
 | 
				
			||||||
 | 
					  void set_static_duration(int p_static_duration);
 | 
				
			||||||
 | 
					  void set_max_duration(int p_max_duration);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Stop the movie, clearing the image
 | 
				
			||||||
 | 
					  void stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Set the m_flipped variable to true/false
 | 
				
			||||||
 | 
					  void set_flipped(bool p_flipped) { m_flipped = p_flipped; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Set the movie's playback speed (between 10% and 1000%)
 | 
				
			||||||
 | 
					  void set_speed(int modifier) { speed = qMax(10, qMin(modifier, 1000)); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Move the label itself around
 | 
				
			||||||
 | 
					  void move(int ax, int ay);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // This is somewhat pointless now as there's no "QMovie" object to resize, aka
 | 
				
			||||||
 | 
					  // no "combo" to speak of
 | 
				
			||||||
 | 
					  void combo_resize(int w, int h);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Return the frame delay adjusted for speed
 | 
				
			||||||
 | 
					  int get_frame_delay(int delay);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // iterate through a list of paths and return the first entry that exists. if
 | 
				
			||||||
 | 
					  // none exist, return NULL (safe because we check again for existence later)
 | 
				
			||||||
 | 
					  QString find_image(QList<QString> p_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					  AOApplication *ao_app;
 | 
				
			||||||
 | 
					  QVector<QPixmap> movie_frames;
 | 
				
			||||||
 | 
					  QVector<int> movie_delays;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  QTimer *preanim_timer;
 | 
				
			||||||
 | 
					  QTimer *shfx_timer;
 | 
				
			||||||
 | 
					  QTimer *ticker;
 | 
				
			||||||
 | 
					  QString last_path;
 | 
				
			||||||
 | 
					  QImageReader m_reader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  QElapsedTimer actual_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Usually used to turn seconds into milliseconds such as for [Time] tag in
 | 
				
			||||||
 | 
					  // char.ini
 | 
				
			||||||
 | 
					  const int tick_ms = 60;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // These are the X and Y values before they are fixed based on the sprite's
 | 
				
			||||||
 | 
					  // width.
 | 
				
			||||||
 | 
					  int x = 0;
 | 
				
			||||||
 | 
					  int y = 0;
 | 
				
			||||||
 | 
					  // These are the width and height values before they are fixed based on the
 | 
				
			||||||
 | 
					  // sprite's width.
 | 
				
			||||||
 | 
					  int f_w = 0;
 | 
				
			||||||
 | 
					  int f_h = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int frame = 0;
 | 
				
			||||||
 | 
					  int max_frames = 0;
 | 
				
			||||||
 | 
					  int last_max_frames = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int speed = 100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool m_flipped = false;
 | 
				
			||||||
 | 
					  // Are we loading this from the same frame we left off on? TODO: actually make
 | 
				
			||||||
 | 
					  // this work
 | 
				
			||||||
 | 
					  bool continuous = false;
 | 
				
			||||||
 | 
					  // Whether or not to forcibly bypass the simple check done by start_playback
 | 
				
			||||||
 | 
					  // and use the existent value of continuous instead
 | 
				
			||||||
 | 
					  bool force_continuous = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int duration = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Start playback of the movie (if animated).
 | 
				
			||||||
 | 
					  void play();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Freeze the movie at the current frame.
 | 
				
			||||||
 | 
					  void freeze();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Retreive a pixmap adjused for mirroring/aspect ratio shenanigans from a
 | 
				
			||||||
 | 
					  // provided QImage
 | 
				
			||||||
 | 
					  QPixmap get_pixmap(QImage image);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Set the movie's frame to provided pixmap
 | 
				
			||||||
 | 
					  void set_frame(QPixmap f_pixmap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					signals:
 | 
				
			||||||
 | 
					  void done();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected slots:
 | 
				
			||||||
 | 
					  virtual void preanim_done();
 | 
				
			||||||
 | 
					  void shfx_timer_done();
 | 
				
			||||||
 | 
					  virtual void movie_ticker();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BackgroundLayer : public AOLayer {
 | 
				
			||||||
 | 
					  Q_OBJECT
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  BackgroundLayer(QWidget *p_parent, AOApplication *p_ao_app);
 | 
				
			||||||
 | 
					  void load_image(QString p_filename);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ForegroundLayer : public AOLayer {
 | 
				
			||||||
 | 
					  Q_OBJECT
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  ForegroundLayer(QWidget *p_parent, AOApplication *p_ao_app);
 | 
				
			||||||
 | 
					  QString miscname; //'misc' folder to search. we fetch this based on p_charname below
 | 
				
			||||||
 | 
					  void load_image(QString p_filename, QString p_charname);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CharLayer : public AOLayer {
 | 
				
			||||||
 | 
					  Q_OBJECT
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  CharLayer(QWidget *p_parent, AOApplication *p_ao_app);
 | 
				
			||||||
 | 
					  QString current_emote = ""; // name of the emote we're using
 | 
				
			||||||
 | 
					  bool is_preanim;     // equivalent to the old play_once, if true we don't want
 | 
				
			||||||
 | 
					                       // to loop this
 | 
				
			||||||
 | 
					  QString prefix = ""; // prefix, left blank if it's a preanim
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void load_image(QString p_filename, QString p_charname, int p_duration, bool p_is_preanim);
 | 
				
			||||||
 | 
					  void play(); // overloaded so we can play effects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // networked frame fx string
 | 
				
			||||||
 | 
					  QStringList network_strings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  QString last_char;        // name of the last character we used
 | 
				
			||||||
 | 
					  QString last_emote;       // name of the last animation we used
 | 
				
			||||||
 | 
					  QString last_prefix;      // prefix of the last animation we played
 | 
				
			||||||
 | 
					  bool was_preanim = false; // whether is_preanim was true last time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Effects such as sfx, screenshakes and realization flashes are stored in
 | 
				
			||||||
 | 
					  // here. QString entry format: "sfx^[sfx_name]", "shake", "flash". The program
 | 
				
			||||||
 | 
					  // uses the QVector index as reference.
 | 
				
			||||||
 | 
					  QVector<QVector<QString>> movie_effects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // used for effect loading
 | 
				
			||||||
 | 
					  QString m_char = "";
 | 
				
			||||||
 | 
					  QString m_emote = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // overloaded for effects reasons
 | 
				
			||||||
 | 
					  void start_playback(QString p_image);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Initialize the frame-specific effects from the char.ini
 | 
				
			||||||
 | 
					  void load_effects();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Initialize the frame-specific effects from the provided network_strings,
 | 
				
			||||||
 | 
					  // this is only initialized if network_strings has size more than 0.
 | 
				
			||||||
 | 
					  void load_network_effects();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Play a frame-specific effect, if there's any defined for that specific
 | 
				
			||||||
 | 
					  // frame.
 | 
				
			||||||
 | 
					  void play_frame_effect(int p_frame);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private slots:
 | 
				
			||||||
 | 
					  void preanim_done() override; // overridden so we don't accidentally cull characters
 | 
				
			||||||
 | 
					  void movie_ticker() override; // overridden so we can play effects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					signals:
 | 
				
			||||||
 | 
					  void shake();
 | 
				
			||||||
 | 
					  void flash();
 | 
				
			||||||
 | 
					  void play_sfx(QString sfx);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class InterjectionLayer : public AOLayer {
 | 
				
			||||||
 | 
					  Q_OBJECT
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  InterjectionLayer(QWidget *p_parent, AOApplication *p_ao_app);
 | 
				
			||||||
 | 
					  void load_image(QString p_filename, QString p_charname, QString p_miscname);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EffectLayer : public AOLayer {
 | 
				
			||||||
 | 
					  Q_OBJECT
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  EffectLayer(QWidget *p_parent, AOApplication *p_ao_app);
 | 
				
			||||||
 | 
					  void load_image(QString p_filename, bool p_looping);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class InterfaceLayer : public AOLayer {
 | 
				
			||||||
 | 
					  Q_OBJECT
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  InterfaceLayer(QWidget *p_parent, AOApplication *p_ao_app);
 | 
				
			||||||
 | 
					  void load_image(QString p_filename, QString p_miscname);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#endif // AOLAYER_H
 | 
				
			||||||
@ -1,36 +0,0 @@
 | 
				
			|||||||
#ifndef AOMOVIE_H
 | 
					 | 
				
			||||||
#define AOMOVIE_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <QLabel>
 | 
					 | 
				
			||||||
#include <QMovie>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Courtroom;
 | 
					 | 
				
			||||||
class AOApplication;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AOMovie : public QLabel {
 | 
					 | 
				
			||||||
  Q_OBJECT
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
  AOMovie(QWidget *p_parent, AOApplication *p_ao_app);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void set_play_once(bool p_play_once);
 | 
					 | 
				
			||||||
  void play(QString p_image, QString p_char = "", QString p_custom_theme = "",
 | 
					 | 
				
			||||||
            int default_duration = 0);
 | 
					 | 
				
			||||||
  void combo_resize(int w, int h);
 | 
					 | 
				
			||||||
  void stop();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
  QMovie *m_movie;
 | 
					 | 
				
			||||||
  AOApplication *ao_app;
 | 
					 | 
				
			||||||
  QTimer *timer;
 | 
					 | 
				
			||||||
  bool play_once = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
signals:
 | 
					 | 
				
			||||||
  void done();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private slots:
 | 
					 | 
				
			||||||
  void frame_change(int n_frame);
 | 
					 | 
				
			||||||
  void timer_done();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // AOMOVIE_H
 | 
					 | 
				
			||||||
@ -1,42 +0,0 @@
 | 
				
			|||||||
#ifndef AOSCENE_H
 | 
					 | 
				
			||||||
#define AOSCENE_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <QDebug>
 | 
					 | 
				
			||||||
#include <QLabel>
 | 
					 | 
				
			||||||
#include <QMovie>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Courtroom;
 | 
					 | 
				
			||||||
class AOApplication;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AOScene : public QLabel {
 | 
					 | 
				
			||||||
  Q_OBJECT
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
  explicit AOScene(QWidget *parent, AOApplication *p_ao_app);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void set_image(QString p_image);
 | 
					 | 
				
			||||||
  void set_legacy_desk(QString p_image);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Move the label itself around
 | 
					 | 
				
			||||||
  void move(int ax, int ay);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // This is somewhat pointless now as there's no "QMovie" object to resize, aka
 | 
					 | 
				
			||||||
  // no "combo" to speak of
 | 
					 | 
				
			||||||
  void combo_resize(int w, int h);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
  QWidget *m_parent;
 | 
					 | 
				
			||||||
  QMovie *m_movie;
 | 
					 | 
				
			||||||
  AOApplication *ao_app;
 | 
					 | 
				
			||||||
  QString last_image;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // These are the X and Y values before they are fixed based on the sprite's
 | 
					 | 
				
			||||||
  // width.
 | 
					 | 
				
			||||||
  int x = 0;
 | 
					 | 
				
			||||||
  int y = 0;
 | 
					 | 
				
			||||||
  // These are the width and height values before they are fixed based on the
 | 
					 | 
				
			||||||
  // sprite's width.
 | 
					 | 
				
			||||||
  int f_w = 0;
 | 
					 | 
				
			||||||
  int f_h = 0;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // AOSCENE_H
 | 
					 | 
				
			||||||
@ -5,17 +5,15 @@
 | 
				
			|||||||
#include "aoblipplayer.h"
 | 
					#include "aoblipplayer.h"
 | 
				
			||||||
#include "aobutton.h"
 | 
					#include "aobutton.h"
 | 
				
			||||||
#include "aocharbutton.h"
 | 
					#include "aocharbutton.h"
 | 
				
			||||||
#include "aocharmovie.h"
 | 
					 | 
				
			||||||
#include "aoemotebutton.h"
 | 
					#include "aoemotebutton.h"
 | 
				
			||||||
#include "aoevidencebutton.h"
 | 
					#include "aoevidencebutton.h"
 | 
				
			||||||
#include "aoevidencedisplay.h"
 | 
					#include "aoevidencedisplay.h"
 | 
				
			||||||
#include "aoimage.h"
 | 
					#include "aoimage.h"
 | 
				
			||||||
 | 
					#include "aolayer.h"
 | 
				
			||||||
#include "aolineedit.h"
 | 
					#include "aolineedit.h"
 | 
				
			||||||
#include "aomovie.h"
 | 
					 | 
				
			||||||
#include "aomusicplayer.h"
 | 
					#include "aomusicplayer.h"
 | 
				
			||||||
#include "aooptionsdialog.h"
 | 
					#include "aooptionsdialog.h"
 | 
				
			||||||
#include "aopacket.h"
 | 
					#include "aopacket.h"
 | 
				
			||||||
#include "aoscene.h"
 | 
					 | 
				
			||||||
#include "aosfxplayer.h"
 | 
					#include "aosfxplayer.h"
 | 
				
			||||||
#include "aotextarea.h"
 | 
					#include "aotextarea.h"
 | 
				
			||||||
#include "aotextedit.h"
 | 
					#include "aotextedit.h"
 | 
				
			||||||
@ -151,6 +149,9 @@ public:
 | 
				
			|||||||
  // reads theme inis and sets size and pos based on the identifier
 | 
					  // reads theme inis and sets size and pos based on the identifier
 | 
				
			||||||
  void set_size_and_pos(QWidget *p_widget, QString p_identifier);
 | 
					  void set_size_and_pos(QWidget *p_widget, QString p_identifier);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // reads theme and char inis and sets size and pos based on the identifier
 | 
				
			||||||
 | 
					  void set_size_and_pos(QWidget *p_widget, QString p_identifier, QString p_char);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // reads theme inis and returns the size and pos as defined by it
 | 
					  // reads theme inis and returns the size and pos as defined by it
 | 
				
			||||||
  QPoint get_theme_pos(QString p_identifier);
 | 
					  QPoint get_theme_pos(QString p_identifier);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -224,11 +225,13 @@ public:
 | 
				
			|||||||
  // Parse the chat message packet and unpack it into the m_chatmessage[ITEM] format
 | 
					  // Parse the chat message packet and unpack it into the m_chatmessage[ITEM] format
 | 
				
			||||||
  void unpack_chatmessage(QStringList p_contents);
 | 
					  void unpack_chatmessage(QStringList p_contents);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Log the message contents and information such as evidence presenting etc. into the log file
 | 
					  enum LogMode {
 | 
				
			||||||
  void log_chatmessage(QString f_message, int f_char_id, QString f_showname = "", int f_color = 0);
 | 
					    IO_ONLY,
 | 
				
			||||||
 | 
					    DISPLAY_ONLY,
 | 
				
			||||||
  // Display the message contents and information such as evidence presenting etc. in the IC logs
 | 
					    DISPLAY_AND_IO
 | 
				
			||||||
  void display_log_chatmessage(QString f_message, int f_char_id, QString f_showname = "", int f_color = 0);
 | 
					  };
 | 
				
			||||||
 | 
					  // Log the message contents and information such as evidence presenting etc. into the log file, the IC log, or both.
 | 
				
			||||||
 | 
					  void log_chatmessage(QString f_message, int f_char_id, QString f_showname = "", int f_color = 0, LogMode f_log_mode=IO_ONLY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Log the message contents and information such as evidence presenting etc. into the IC logs
 | 
					  // Log the message contents and information such as evidence presenting etc. into the IC logs
 | 
				
			||||||
  void handle_callwords();
 | 
					  void handle_callwords();
 | 
				
			||||||
@ -264,7 +267,8 @@ public:
 | 
				
			|||||||
  QString filter_ic_text(QString p_text, bool colorize = false, int pos = -1,
 | 
					  QString filter_ic_text(QString p_text, bool colorize = false, int pos = -1,
 | 
				
			||||||
                         int default_color = 0);
 | 
					                         int default_color = 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void log_ic_text(QString p_name, QString p_showname, QString p_message, QString p_action="", int p_color=0);
 | 
					  void log_ic_text(QString p_name, QString p_showname, QString p_message,
 | 
				
			||||||
 | 
					                   QString p_action = "", int p_color = 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // adds text to the IC chatlog. p_name first as bold then p_text then a newlin
 | 
					  // adds text to the IC chatlog. p_name first as bold then p_text then a newlin
 | 
				
			||||||
  // this function keeps the chatlog scrolled to the top unless there's text
 | 
					  // this function keeps the chatlog scrolled to the top unless there's text
 | 
				
			||||||
@ -380,7 +384,8 @@ private:
 | 
				
			|||||||
  // True, if log should display colors.
 | 
					  // True, if log should display colors.
 | 
				
			||||||
  bool log_colors = true;
 | 
					  bool log_colors = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // True, if the log should display the message like name<br>text instead of name: text
 | 
					  // True, if the log should display the message like name<br>text instead of
 | 
				
			||||||
 | 
					  // name: text
 | 
				
			||||||
  bool log_newline = false;
 | 
					  bool log_newline = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // True, if the log should include RP actions like interjections, showing evidence, etc.
 | 
					  // True, if the log should include RP actions like interjections, showing evidence, etc.
 | 
				
			||||||
@ -408,16 +413,21 @@ private:
 | 
				
			|||||||
  const int time_mod = 40;
 | 
					  const int time_mod = 40;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // the amount of time non-animated objection/hold it/takethat images stay
 | 
					  // the amount of time non-animated objection/hold it/takethat images stay
 | 
				
			||||||
  // onscreen for in ms
 | 
					  // onscreen for in ms, and the maximum amount of time any interjections are
 | 
				
			||||||
  const int shout_stay_time = 724;
 | 
					  // allowed to play
 | 
				
			||||||
 | 
					  const int shout_static_time = 724;
 | 
				
			||||||
 | 
					  const int shout_max_time = 1500;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // the amount of time non-animated guilty/not guilty images stay onscreen for
 | 
					  // the amount of time non-animated guilty/not guilty images stay onscreen for
 | 
				
			||||||
  // in ms
 | 
					  // in ms, and the maximum amount of time g/ng images are allowed to play
 | 
				
			||||||
  const int verdict_stay_time = 3000;
 | 
					  const int verdict_static_time = 3000;
 | 
				
			||||||
 | 
					  const int verdict_max_time = 4000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // the amount of time non-animated witness testimony/cross-examination images
 | 
					  // the amount of time non-animated witness testimony/cross-examination images
 | 
				
			||||||
  // stay onscreen for in ms
 | 
					  // stay onscreen for in ms, and the maximum time any wt/ce image is allowed to
 | 
				
			||||||
  const int wtce_stay_time = 1500;
 | 
					  // play
 | 
				
			||||||
 | 
					  const int wtce_static_time = 1500;
 | 
				
			||||||
 | 
					  const int wtce_max_time = 4000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // characters we consider punctuation
 | 
					  // characters we consider punctuation
 | 
				
			||||||
  const QString punctuation_chars = ".,?!:;";
 | 
					  const QString punctuation_chars = ".,?!:;";
 | 
				
			||||||
@ -441,7 +451,7 @@ private:
 | 
				
			|||||||
  bool is_muted = false;
 | 
					  bool is_muted = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // state of animation, 0 = objecting, 1 = preanim, 2 = talking, 3 = idle, 4 =
 | 
					  // state of animation, 0 = objecting, 1 = preanim, 2 = talking, 3 = idle, 4 =
 | 
				
			||||||
  // noniterrupting preanim
 | 
					  // noniterrupting preanim, 5 = (c) animation
 | 
				
			||||||
  int anim_state = 3;
 | 
					  int anim_state = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // whether or not current color is a talking one
 | 
					  // whether or not current color is a talking one
 | 
				
			||||||
@ -512,6 +522,7 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // is the message we're about to send supposed to present evidence?
 | 
					  // is the message we're about to send supposed to present evidence?
 | 
				
			||||||
  bool is_presenting_evidence = false;
 | 
					  bool is_presenting_evidence = false;
 | 
				
			||||||
 | 
					  bool c_played = false; // whether we've played a (c)-style postanimation yet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // have we already presented evidence for this message?
 | 
					  // have we already presented evidence for this message?
 | 
				
			||||||
  bool evidence_presented = false;
 | 
					  bool evidence_presented = false;
 | 
				
			||||||
@ -579,21 +590,20 @@ private:
 | 
				
			|||||||
  AOImage *ui_background;
 | 
					  AOImage *ui_background;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QWidget *ui_viewport;
 | 
					  QWidget *ui_viewport;
 | 
				
			||||||
  AOScene *ui_vp_background;
 | 
					  BackgroundLayer *ui_vp_background;
 | 
				
			||||||
  AOMovie *ui_vp_speedlines;
 | 
					  ForegroundLayer *ui_vp_speedlines;
 | 
				
			||||||
  AOCharMovie *ui_vp_player_char;
 | 
					  CharLayer *ui_vp_player_char;
 | 
				
			||||||
  AOCharMovie *ui_vp_sideplayer_char;
 | 
					  CharLayer *ui_vp_sideplayer_char;
 | 
				
			||||||
  AOScene *ui_vp_desk;
 | 
					  BackgroundLayer *ui_vp_desk;
 | 
				
			||||||
  AOScene *ui_vp_legacy_desk;
 | 
					 | 
				
			||||||
  AOEvidenceDisplay *ui_vp_evidence_display;
 | 
					  AOEvidenceDisplay *ui_vp_evidence_display;
 | 
				
			||||||
  AOImage *ui_vp_chatbox;
 | 
					  AOImage *ui_vp_chatbox;
 | 
				
			||||||
  QLabel *ui_vp_showname;
 | 
					  QLabel *ui_vp_showname;
 | 
				
			||||||
  AOMovie *ui_vp_chat_arrow;
 | 
					  InterfaceLayer *ui_vp_chat_arrow;
 | 
				
			||||||
  QTextEdit *ui_vp_message;
 | 
					  QTextEdit *ui_vp_message;
 | 
				
			||||||
  AOMovie *ui_vp_effect;
 | 
					  EffectLayer *ui_vp_effect;
 | 
				
			||||||
  AOMovie *ui_vp_testimony;
 | 
					  InterfaceLayer *ui_vp_testimony;
 | 
				
			||||||
  AOMovie *ui_vp_wtce;
 | 
					  InterjectionLayer *ui_vp_wtce;
 | 
				
			||||||
  AOMovie *ui_vp_objection;
 | 
					  InterjectionLayer *ui_vp_objection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QTextEdit *ui_ic_chatlog;
 | 
					  QTextEdit *ui_ic_chatlog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -605,7 +615,7 @@ private:
 | 
				
			|||||||
  QTreeWidget *ui_music_list;
 | 
					  QTreeWidget *ui_music_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ScrollText *ui_music_name;
 | 
					  ScrollText *ui_music_name;
 | 
				
			||||||
  AOMovie *ui_music_display;
 | 
					  InterfaceLayer *ui_music_display;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  AOButton *ui_pair_button;
 | 
					  AOButton *ui_pair_button;
 | 
				
			||||||
  QListWidget *ui_pair_list;
 | 
					  QListWidget *ui_pair_list;
 | 
				
			||||||
@ -759,6 +769,7 @@ private:
 | 
				
			|||||||
  void regenerate_ic_chatlog();
 | 
					  void regenerate_ic_chatlog();
 | 
				
			||||||
public slots:
 | 
					public slots:
 | 
				
			||||||
  void objection_done();
 | 
					  void objection_done();
 | 
				
			||||||
 | 
					  void effect_done();
 | 
				
			||||||
  void preanim_done();
 | 
					  void preanim_done();
 | 
				
			||||||
  void do_screenshake();
 | 
					  void do_screenshake();
 | 
				
			||||||
  void do_flash();
 | 
					  void do_flash();
 | 
				
			||||||
 | 
				
			|||||||
@ -1,332 +0,0 @@
 | 
				
			|||||||
#include "aocharmovie.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "aoapplication.h"
 | 
					 | 
				
			||||||
#include "file_functions.h"
 | 
					 | 
				
			||||||
#include "misc_functions.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AOCharMovie::AOCharMovie(QWidget *p_parent, AOApplication *p_ao_app)
 | 
					 | 
				
			||||||
    : QLabel(p_parent)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  ao_app = p_ao_app;
 | 
					 | 
				
			||||||
  preanim_timer = new QTimer(this);
 | 
					 | 
				
			||||||
  preanim_timer->setSingleShot(true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ticker = new QTimer(this);
 | 
					 | 
				
			||||||
  ticker->setTimerType(Qt::PreciseTimer);
 | 
					 | 
				
			||||||
  ticker->setSingleShot(false);
 | 
					 | 
				
			||||||
  connect(ticker, SIGNAL(timeout()), this, SLOT(movie_ticker()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  //  connect(m_movie, SIGNAL(frameChanged(int)), this,
 | 
					 | 
				
			||||||
  //  SLOT(frame_change(int)));
 | 
					 | 
				
			||||||
  connect(preanim_timer, SIGNAL(timeout()), this, SLOT(preanim_done()));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::load_image(QString p_char, QString p_emote,
 | 
					 | 
				
			||||||
                             QString emote_prefix)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
#ifdef DEBUG_CHARMOVIE
 | 
					 | 
				
			||||||
  actual_time.restart();
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
  QString emote_path;
 | 
					 | 
				
			||||||
  QList<QString> pathlist;
 | 
					 | 
				
			||||||
  pathlist = {
 | 
					 | 
				
			||||||
      ao_app->get_image_suffix(ao_app->get_character_path(
 | 
					 | 
				
			||||||
          p_char, emote_prefix + p_emote)), // Default path
 | 
					 | 
				
			||||||
      ao_app->get_image_suffix(ao_app->get_character_path(
 | 
					 | 
				
			||||||
          p_char, emote_prefix + "/" +
 | 
					 | 
				
			||||||
                      p_emote)), // Path check if it's categorized into a folder
 | 
					 | 
				
			||||||
      ao_app->get_image_suffix(ao_app->get_character_path(
 | 
					 | 
				
			||||||
          p_char, p_emote)), // Just use the non-prefixed image, animated or not
 | 
					 | 
				
			||||||
      ao_app->get_image_suffix(
 | 
					 | 
				
			||||||
          ao_app->get_theme_path("placeholder")), // Theme placeholder path
 | 
					 | 
				
			||||||
      ao_app->get_image_suffix(ao_app->get_default_theme_path(
 | 
					 | 
				
			||||||
          "placeholder")), // Default theme placeholder path
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (QString path : pathlist) {
 | 
					 | 
				
			||||||
    if (file_exists(path)) {
 | 
					 | 
				
			||||||
      emote_path = path;
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  this->clear();
 | 
					 | 
				
			||||||
  ticker->stop();
 | 
					 | 
				
			||||||
  preanim_timer->stop();
 | 
					 | 
				
			||||||
  movie_frames.clear();
 | 
					 | 
				
			||||||
  movie_delays.clear();
 | 
					 | 
				
			||||||
  movie_effects.clear();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!file_exists(emote_path))
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  m_reader->setFileName(emote_path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // set format to apng if png supports animation
 | 
					 | 
				
			||||||
  if (emote_path.endsWith("png")) {
 | 
					 | 
				
			||||||
    m_reader->setFormat("apng");
 | 
					 | 
				
			||||||
    if (!m_reader->supportsAnimation()) {
 | 
					 | 
				
			||||||
      m_reader->setFormat("png");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  QPixmap f_pixmap = this->get_pixmap(m_reader->read());
 | 
					 | 
				
			||||||
  int f_delay = m_reader->nextImageDelay();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  frame = 0;
 | 
					 | 
				
			||||||
  max_frames = m_reader->imageCount();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  this->set_frame(f_pixmap);
 | 
					 | 
				
			||||||
  this->show();
 | 
					 | 
				
			||||||
  if (max_frames > 1) {
 | 
					 | 
				
			||||||
    movie_frames.append(f_pixmap);
 | 
					 | 
				
			||||||
    movie_delays.append(f_delay);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  m_char = p_char;
 | 
					 | 
				
			||||||
  m_emote = emote_prefix + p_emote;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (network_strings.size() > 0) // our FX overwritten by networked ones
 | 
					 | 
				
			||||||
    this->load_network_effects();
 | 
					 | 
				
			||||||
  else // Use default ini FX
 | 
					 | 
				
			||||||
    this->load_effects();
 | 
					 | 
				
			||||||
#ifdef DEBUG_CHARMOVIE
 | 
					 | 
				
			||||||
  qDebug() << max_frames << "Setting image to " << emote_path
 | 
					 | 
				
			||||||
           << "Time taken to process image:" << actual_time.elapsed();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  actual_time.restart();
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::load_effects()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  movie_effects.clear();
 | 
					 | 
				
			||||||
  movie_effects.resize(max_frames);
 | 
					 | 
				
			||||||
  for (int e_frame = 0; e_frame < max_frames; ++e_frame) {
 | 
					 | 
				
			||||||
    QString effect = ao_app->get_screenshake_frame(m_char, m_emote, e_frame);
 | 
					 | 
				
			||||||
    if (effect != "") {
 | 
					 | 
				
			||||||
      movie_effects[e_frame].append("shake");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    effect = ao_app->get_flash_frame(m_char, m_emote, e_frame);
 | 
					 | 
				
			||||||
    if (effect != "") {
 | 
					 | 
				
			||||||
      movie_effects[e_frame].append("flash");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    effect = ao_app->get_sfx_frame(m_char, m_emote, e_frame);
 | 
					 | 
				
			||||||
    if (effect != "") {
 | 
					 | 
				
			||||||
      movie_effects[e_frame].append("sfx^" + effect);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::load_network_effects()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  movie_effects.clear();
 | 
					 | 
				
			||||||
  movie_effects.resize(max_frames);
 | 
					 | 
				
			||||||
  // Order is important!!!
 | 
					 | 
				
			||||||
  QStringList effects_list = {"shake", "flash", "sfx^"};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Determines which list is smaller - effects_list or network_strings - and
 | 
					 | 
				
			||||||
  // uses it as basis for the loop. This way, incomplete network_strings would
 | 
					 | 
				
			||||||
  // still be parsed, and excess/unaccounted for networked information is
 | 
					 | 
				
			||||||
  // omitted.
 | 
					 | 
				
			||||||
  int effects_size = qMin(effects_list.size(), network_strings.size());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (int i = 0; i < effects_size; ++i) {
 | 
					 | 
				
			||||||
    QString netstring = network_strings.at(i);
 | 
					 | 
				
			||||||
    QStringList emote_splits = netstring.split("^");
 | 
					 | 
				
			||||||
    foreach (QString emote, emote_splits) {
 | 
					 | 
				
			||||||
      QStringList parsed = emote.split("|");
 | 
					 | 
				
			||||||
      if (parsed.size() <= 0 || parsed.at(0) != m_emote)
 | 
					 | 
				
			||||||
        continue;
 | 
					 | 
				
			||||||
      foreach (QString frame_data, parsed) {
 | 
					 | 
				
			||||||
        QStringList frame_split = frame_data.split("=");
 | 
					 | 
				
			||||||
        if (frame_split.size() <=
 | 
					 | 
				
			||||||
            1) // We might still be hanging at the emote itself (entry 0).
 | 
					 | 
				
			||||||
          continue;
 | 
					 | 
				
			||||||
        int f_frame = frame_split.at(0).toInt();
 | 
					 | 
				
			||||||
        if (f_frame >= max_frames) {
 | 
					 | 
				
			||||||
          qDebug() << "Warning: out of bounds" << effects_list[i] << "frame"
 | 
					 | 
				
			||||||
                   << f_frame << "out of" << max_frames << "for" << m_char
 | 
					 | 
				
			||||||
                   << m_emote;
 | 
					 | 
				
			||||||
          continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        QString f_data = frame_split.at(1);
 | 
					 | 
				
			||||||
        if (f_data != "") {
 | 
					 | 
				
			||||||
          QString effect = effects_list[i];
 | 
					 | 
				
			||||||
          if (effect == "sfx^") // Currently the only frame result that feeds us
 | 
					 | 
				
			||||||
                                // data, let's yank it in.
 | 
					 | 
				
			||||||
            effect += f_data;
 | 
					 | 
				
			||||||
          qDebug() << effect << f_data << "frame" << f_frame << "for" << m_char
 | 
					 | 
				
			||||||
                   << m_emote;
 | 
					 | 
				
			||||||
          movie_effects[f_frame].append(effect);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::play()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  play_frame_effect(frame);
 | 
					 | 
				
			||||||
  if (max_frames <= 1) {
 | 
					 | 
				
			||||||
    if (play_once)
 | 
					 | 
				
			||||||
      ticker->start(60);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
    ticker->start(this->get_frame_delay(movie_delays[frame]));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::play_pre(QString p_char, QString p_emote, int duration)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  load_image(p_char, p_emote, "");
 | 
					 | 
				
			||||||
  // As much as I'd like to screw around with [Time] durations modifying the
 | 
					 | 
				
			||||||
  // animation speed, I don't think I can reliably do that, not without looping
 | 
					 | 
				
			||||||
  // through all frames in the image at least - which causes lag. So for now it
 | 
					 | 
				
			||||||
  // simply ends the preanimation early instead.
 | 
					 | 
				
			||||||
  play_once = true;
 | 
					 | 
				
			||||||
  if (duration >
 | 
					 | 
				
			||||||
      0) // It's -1 if there's no definition in [Time] for it. In which case, it
 | 
					 | 
				
			||||||
         // will let the animation run out in full. Duration 0 does the same.
 | 
					 | 
				
			||||||
    preanim_timer->start(duration *
 | 
					 | 
				
			||||||
                         time_mod); // This timer will not fire if the animation
 | 
					 | 
				
			||||||
                                    // finishes earlier than that
 | 
					 | 
				
			||||||
  play();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::play_talking(QString p_char, QString p_emote)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  play_once = false;
 | 
					 | 
				
			||||||
  load_image(p_char, p_emote, "(b)");
 | 
					 | 
				
			||||||
  play();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::play_idle(QString p_char, QString p_emote)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  play_once = false;
 | 
					 | 
				
			||||||
  load_image(p_char, p_emote, "(a)");
 | 
					 | 
				
			||||||
  play();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::play_frame_effect(int frame)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (frame < max_frames) {
 | 
					 | 
				
			||||||
    foreach (QString effect, movie_effects[frame]) {
 | 
					 | 
				
			||||||
      if (effect == "shake") {
 | 
					 | 
				
			||||||
        shake();
 | 
					 | 
				
			||||||
#ifdef DEBUG_CHARMOVIE
 | 
					 | 
				
			||||||
        qDebug() << "Attempting to play shake on frame" << frame;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (effect == "flash") {
 | 
					 | 
				
			||||||
        flash();
 | 
					 | 
				
			||||||
#ifdef DEBUG_CHARMOVIE
 | 
					 | 
				
			||||||
        qDebug() << "Attempting to play flash on frame" << frame;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (effect.startsWith("sfx^")) {
 | 
					 | 
				
			||||||
        QString sfx = effect.section("^", 1);
 | 
					 | 
				
			||||||
        play_sfx(sfx);
 | 
					 | 
				
			||||||
#ifdef DEBUG_CHARMOVIE
 | 
					 | 
				
			||||||
        qDebug() << "Attempting to play sfx" << sfx << "on frame" << frame;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::stop()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  // for all intents and purposes, stopping is the same as hiding. at no point
 | 
					 | 
				
			||||||
  // do we want a frozen gif to display
 | 
					 | 
				
			||||||
  ticker->stop();
 | 
					 | 
				
			||||||
  preanim_timer->stop();
 | 
					 | 
				
			||||||
  this->hide();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
QPixmap AOCharMovie::get_pixmap(QImage image)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  QPixmap f_pixmap;
 | 
					 | 
				
			||||||
  if (m_flipped)
 | 
					 | 
				
			||||||
    f_pixmap = QPixmap::fromImage(image.mirrored(true, false));
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
    f_pixmap = QPixmap::fromImage(image);
 | 
					 | 
				
			||||||
  //    auto aspect_ratio = Qt::KeepAspectRatio;
 | 
					 | 
				
			||||||
  auto transform_mode = Qt::FastTransformation;
 | 
					 | 
				
			||||||
  if (f_pixmap.height() > f_h) // We are downscaling, use anti-aliasing.
 | 
					 | 
				
			||||||
    transform_mode = Qt::SmoothTransformation;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  f_pixmap = f_pixmap.scaledToHeight(f_h, transform_mode);
 | 
					 | 
				
			||||||
  this->resize(f_pixmap.size());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return f_pixmap;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::set_frame(QPixmap f_pixmap)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  this->setPixmap(f_pixmap);
 | 
					 | 
				
			||||||
  QLabel::move(
 | 
					 | 
				
			||||||
      x + (f_w - f_pixmap.width()) / 2,
 | 
					 | 
				
			||||||
      y + (f_h - f_pixmap.height())); // Always center horizontally, always put
 | 
					 | 
				
			||||||
                                      // at the bottom vertically
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::combo_resize(int w, int h)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  QSize f_size(w, h);
 | 
					 | 
				
			||||||
  f_w = w;
 | 
					 | 
				
			||||||
  f_h = h;
 | 
					 | 
				
			||||||
  this->resize(f_size);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int AOCharMovie::get_frame_delay(int delay)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  return static_cast<int>(double(delay) * double(speed / 100));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::move(int ax, int ay)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  x = ax;
 | 
					 | 
				
			||||||
  y = ay;
 | 
					 | 
				
			||||||
  QLabel::move(x, y);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::movie_ticker()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  ++frame;
 | 
					 | 
				
			||||||
  if (frame >= max_frames) {
 | 
					 | 
				
			||||||
    if (play_once) {
 | 
					 | 
				
			||||||
      preanim_done();
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      frame = 0;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  //  qint64 difference = elapsed - movie_delays[frame];
 | 
					 | 
				
			||||||
  if (frame >= movie_frames.size()) {
 | 
					 | 
				
			||||||
    m_reader->jumpToImage(frame);
 | 
					 | 
				
			||||||
    movie_frames.resize(frame + 1);
 | 
					 | 
				
			||||||
    movie_frames[frame] = this->get_pixmap(m_reader->read());
 | 
					 | 
				
			||||||
    movie_delays.resize(frame + 1);
 | 
					 | 
				
			||||||
    movie_delays[frame] = m_reader->nextImageDelay();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef DEBUG_CHARMOVIE
 | 
					 | 
				
			||||||
  qDebug() << frame << movie_delays[frame]
 | 
					 | 
				
			||||||
           << "actual time taken from last frame:" << actual_time.restart();
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  this->set_frame(movie_frames[frame]);
 | 
					 | 
				
			||||||
  play_frame_effect(frame);
 | 
					 | 
				
			||||||
  ticker->setInterval(this->get_frame_delay(movie_delays[frame]));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOCharMovie::preanim_done()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  ticker->stop();
 | 
					 | 
				
			||||||
  preanim_timer->stop();
 | 
					 | 
				
			||||||
  done();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -11,7 +11,7 @@ AOEvidenceDisplay::AOEvidenceDisplay(QWidget *p_parent, AOApplication *p_ao_app)
 | 
				
			|||||||
  evidence_icon = new QLabel(this);
 | 
					  evidence_icon = new QLabel(this);
 | 
				
			||||||
  sfx_player = new AOSfxPlayer(this, ao_app);
 | 
					  sfx_player = new AOSfxPlayer(this, ao_app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  evidence_movie = new AOMovie(this, ao_app);
 | 
					  evidence_movie = new InterfaceLayer(this, ao_app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  connect(evidence_movie, SIGNAL(done()), this, SLOT(show_done()));
 | 
					  connect(evidence_movie, SIGNAL(done()), this, SLOT(show_done()));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -46,9 +46,11 @@ void AOEvidenceDisplay::show_evidence(QString p_evidence_image,
 | 
				
			|||||||
  evidence_icon->setPixmap(f_pixmap);
 | 
					  evidence_icon->setPixmap(f_pixmap);
 | 
				
			||||||
  evidence_icon->resize(f_pixmap.size());
 | 
					  evidence_icon->resize(f_pixmap.size());
 | 
				
			||||||
  evidence_icon->move(icon_dimensions.x, icon_dimensions.y);
 | 
					  evidence_icon->move(icon_dimensions.x, icon_dimensions.y);
 | 
				
			||||||
 | 
					  evidence_movie->static_duration = 320;
 | 
				
			||||||
  evidence_movie->play(gif_name);
 | 
					  evidence_movie->max_duration = 1000;
 | 
				
			||||||
  sfx_player->play(ao_app->get_sfx("evidence_present"));
 | 
					  evidence_movie->set_play_once(true);
 | 
				
			||||||
 | 
					  evidence_movie->load_image(gif_name, "");
 | 
				
			||||||
 | 
					  sfx_player->play(ao_app->get_sfx("evidence_present", "default"));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AOEvidenceDisplay::reset()
 | 
					void AOEvidenceDisplay::reset()
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										577
									
								
								src/aolayer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										577
									
								
								src/aolayer.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,577 @@
 | 
				
			|||||||
 | 
					#include "aolayer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "aoapplication.h"
 | 
				
			||||||
 | 
					#include "file_functions.h"
 | 
				
			||||||
 | 
					#include "misc_functions.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AOLayer::AOLayer(QWidget *p_parent, AOApplication *p_ao_app) : QLabel(p_parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  ao_app = p_ao_app;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // used for culling images when their max_duration is exceeded
 | 
				
			||||||
 | 
					  shfx_timer = new QTimer(this);
 | 
				
			||||||
 | 
					  shfx_timer->setTimerType(Qt::PreciseTimer);
 | 
				
			||||||
 | 
					  shfx_timer->setSingleShot(true);
 | 
				
			||||||
 | 
					  connect(shfx_timer, SIGNAL(timeout()), this, SLOT(shfx_timer_done()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ticker = new QTimer(this);
 | 
				
			||||||
 | 
					  ticker->setTimerType(Qt::PreciseTimer);
 | 
				
			||||||
 | 
					  ticker->setSingleShot(false);
 | 
				
			||||||
 | 
					  connect(ticker, SIGNAL(timeout()), this, SLOT(movie_ticker()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  preanim_timer = new QTimer(this);
 | 
				
			||||||
 | 
					  preanim_timer->setSingleShot(true);
 | 
				
			||||||
 | 
					  connect(preanim_timer, SIGNAL(timeout()), this, SLOT(preanim_done()));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BackgroundLayer::BackgroundLayer(QWidget *p_parent, AOApplication *p_ao_app)
 | 
				
			||||||
 | 
					    : AOLayer(p_parent, p_ao_app)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					ForegroundLayer::ForegroundLayer(QWidget *p_parent, AOApplication *p_ao_app)
 | 
				
			||||||
 | 
					    : AOLayer(p_parent, p_ao_app)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					CharLayer::CharLayer(QWidget *p_parent, AOApplication *p_ao_app)
 | 
				
			||||||
 | 
					    : AOLayer(p_parent, p_ao_app)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EffectLayer::EffectLayer(QWidget *p_parent, AOApplication *p_ao_app)
 | 
				
			||||||
 | 
					    : AOLayer(p_parent, p_ao_app)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					InterjectionLayer::InterjectionLayer(QWidget *p_parent, AOApplication *p_ao_app)
 | 
				
			||||||
 | 
					    : AOLayer(p_parent, p_ao_app)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					InterfaceLayer::InterfaceLayer(QWidget *p_parent, AOApplication *p_ao_app)
 | 
				
			||||||
 | 
					    : AOLayer(p_parent, p_ao_app)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QString AOLayer::find_image(QList<QString> p_list)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  QString image_path;
 | 
				
			||||||
 | 
					  for (QString path : p_list) {
 | 
				
			||||||
 | 
					#ifdef DEBUG_MOVIE
 | 
				
			||||||
 | 
					    qDebug() << "checking path " << path;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    if (file_exists(path)) {
 | 
				
			||||||
 | 
					      image_path = path;
 | 
				
			||||||
 | 
					#ifdef DEBUG_MOVIE
 | 
				
			||||||
 | 
					      qDebug() << "found    path " << path;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return image_path;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QPixmap AOLayer::get_pixmap(QImage image)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  QPixmap f_pixmap;
 | 
				
			||||||
 | 
					  if (m_flipped)
 | 
				
			||||||
 | 
					    f_pixmap = QPixmap::fromImage(image.mirrored(true, false));
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    f_pixmap = QPixmap::fromImage(image);
 | 
				
			||||||
 | 
					  //    auto aspect_ratio = Qt::KeepAspectRatio;
 | 
				
			||||||
 | 
					  if (f_pixmap.height() > f_h) // We are downscaling, use anti-aliasing.
 | 
				
			||||||
 | 
					    transform_mode = Qt::SmoothTransformation;
 | 
				
			||||||
 | 
					  if (stretch)
 | 
				
			||||||
 | 
					    f_pixmap = f_pixmap.scaled(f_w, f_h);
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    f_pixmap = f_pixmap.scaledToHeight(f_h, transform_mode);
 | 
				
			||||||
 | 
					  this->resize(f_pixmap.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return f_pixmap;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AOLayer::set_frame(QPixmap f_pixmap)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  this->setPixmap(f_pixmap);
 | 
				
			||||||
 | 
					  QLabel::move(
 | 
				
			||||||
 | 
					      x + (f_w - f_pixmap.width()) / 2,
 | 
				
			||||||
 | 
					      y + (f_h - f_pixmap.height())); // Always center horizontally, always put
 | 
				
			||||||
 | 
					                                      // at the bottom vertically
 | 
				
			||||||
 | 
					  this->setMask(
 | 
				
			||||||
 | 
					      QRegion((f_pixmap.width() - f_w) / 2, (f_pixmap.height() - f_h) / 2, f_w,
 | 
				
			||||||
 | 
					              f_h)); // make sure we don't escape the area we've been given
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AOLayer::combo_resize(int w, int h)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  QSize f_size(w, h);
 | 
				
			||||||
 | 
					  f_w = w;
 | 
				
			||||||
 | 
					  f_h = h;
 | 
				
			||||||
 | 
					  this->resize(f_size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int AOLayer::get_frame_delay(int delay)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return static_cast<int>(double(delay) * double(speed / 100));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AOLayer::move(int ax, int ay)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  x = ax;
 | 
				
			||||||
 | 
					  y = ay;
 | 
				
			||||||
 | 
					  QLabel::move(x, y);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BackgroundLayer::load_image(QString p_filename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  play_once = false;
 | 
				
			||||||
 | 
					  cull_image = false;
 | 
				
			||||||
 | 
					  QString design_path = ao_app->get_background_path("design.ini");
 | 
				
			||||||
 | 
					  transform_mode =
 | 
				
			||||||
 | 
					      ao_app->get_scaling(ao_app->read_design_ini("scaling", design_path));
 | 
				
			||||||
 | 
					  stretch = ao_app->read_design_ini("stretch", design_path).startsWith("true");
 | 
				
			||||||
 | 
					  qDebug() << "[BackgroundLayer] BG loaded: " << p_filename;
 | 
				
			||||||
 | 
					  start_playback(ao_app->get_image_suffix(ao_app->get_background_path(p_filename)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ForegroundLayer::load_image(QString p_filename, QString p_charname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  play_once = false;
 | 
				
			||||||
 | 
					  cull_image = false;
 | 
				
			||||||
 | 
					  miscname = ao_app->get_char_shouts(p_charname);
 | 
				
			||||||
 | 
					  qDebug() << "[ForegroundLayer] FG loaded: " << p_filename;
 | 
				
			||||||
 | 
					  QList<QString> pathlist = {
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_character_path(
 | 
				
			||||||
 | 
					          p_charname, p_filename)), // first check the character folder
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_theme_path(
 | 
				
			||||||
 | 
					          "misc/" + miscname + "/" +
 | 
				
			||||||
 | 
					          p_filename)), // then check our theme's misc directory
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_misc_path(
 | 
				
			||||||
 | 
					          miscname, p_filename)), // then check our global misc folder
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(
 | 
				
			||||||
 | 
					          ao_app->get_theme_path(p_filename)), // then check the user's theme
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_default_theme_path(
 | 
				
			||||||
 | 
					          p_filename))}; // and finally check the default theme
 | 
				
			||||||
 | 
					  start_playback(find_image(pathlist));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CharLayer::load_image(QString p_filename, QString p_charname,
 | 
				
			||||||
 | 
					                           int p_duration, bool p_is_preanim)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  duration = p_duration;
 | 
				
			||||||
 | 
					  cull_image = false;
 | 
				
			||||||
 | 
					  force_continuous = false;
 | 
				
			||||||
 | 
					  transform_mode = ao_app->get_scaling(
 | 
				
			||||||
 | 
					      ao_app->get_emote_property(p_charname, p_filename, "scaling"));
 | 
				
			||||||
 | 
					  stretch = ao_app->get_emote_property(p_charname, p_filename, "stretch")
 | 
				
			||||||
 | 
					                .startsWith(true);
 | 
				
			||||||
 | 
					  if ((p_charname == last_char) &&
 | 
				
			||||||
 | 
					      ((p_filename == last_emote) ||
 | 
				
			||||||
 | 
					       (p_filename.mid(3, -1) == last_emote.mid(3, -1))) &&
 | 
				
			||||||
 | 
					      (!is_preanim) && (!was_preanim)) {
 | 
				
			||||||
 | 
					    continuous = true;
 | 
				
			||||||
 | 
					    force_continuous = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    continuous = false;
 | 
				
			||||||
 | 
					    force_continuous = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  prefix = "";
 | 
				
			||||||
 | 
					  current_emote = p_filename;
 | 
				
			||||||
 | 
					  was_preanim = is_preanim;
 | 
				
			||||||
 | 
					  m_char = p_charname;
 | 
				
			||||||
 | 
					  m_emote = current_emote;
 | 
				
			||||||
 | 
					  last_char = p_charname;
 | 
				
			||||||
 | 
					  last_emote = current_emote;
 | 
				
			||||||
 | 
					  last_prefix = prefix;
 | 
				
			||||||
 | 
					  is_preanim = p_is_preanim;
 | 
				
			||||||
 | 
					  if ((p_filename.left(3) == "(a)") || (p_filename.left(3) == "(b)")) {
 | 
				
			||||||
 | 
					    prefix = p_filename.left(3);
 | 
				
			||||||
 | 
					    current_emote = p_filename.mid(3, -1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if ((duration > 0) || (p_filename.left(3) == "(c)")) {
 | 
				
			||||||
 | 
					    if (p_filename.left(3) == "(c)") {
 | 
				
			||||||
 | 
					      prefix = "(c)";
 | 
				
			||||||
 | 
					      current_emote = p_filename.mid(3, -1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    is_preanim = true;
 | 
				
			||||||
 | 
					    play_once = true;
 | 
				
			||||||
 | 
					    preanim_timer->start(duration * tick_ms);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  qDebug() << "[CharLayer] anim loaded: prefix " << prefix << " filename "
 | 
				
			||||||
 | 
					           << current_emote << " from character: " << p_charname
 | 
				
			||||||
 | 
					           << " continuous: " << continuous;
 | 
				
			||||||
 | 
					  QList<QString> pathlist = {
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_character_path(
 | 
				
			||||||
 | 
					          p_charname, prefix + current_emote)), // Default path
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_character_path(
 | 
				
			||||||
 | 
					          p_charname,
 | 
				
			||||||
 | 
					          prefix + "/" + current_emote)), // Path check if it's categorized
 | 
				
			||||||
 | 
					                                          // into a folder
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_character_path(
 | 
				
			||||||
 | 
					          p_charname,
 | 
				
			||||||
 | 
					          current_emote)), // Just use the non-prefixed image, animated or not
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(
 | 
				
			||||||
 | 
					          ao_app->get_theme_path("placeholder")), // Theme placeholder path
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_default_theme_path(
 | 
				
			||||||
 | 
					          "placeholder"))}; // Default theme placeholder path
 | 
				
			||||||
 | 
					  this->start_playback(find_image(pathlist));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void InterjectionLayer::load_image(QString p_filename, QString p_charname,
 | 
				
			||||||
 | 
					                                   QString p_miscname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  continuous = false;
 | 
				
			||||||
 | 
					  force_continuous = true;
 | 
				
			||||||
 | 
					  play_once = true;
 | 
				
			||||||
 | 
					  transform_mode = ao_app->get_misc_scaling(p_miscname);
 | 
				
			||||||
 | 
					  QList<QString> pathlist = {
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_character_path(
 | 
				
			||||||
 | 
					          p_charname, p_filename)), // Character folder
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_theme_path(
 | 
				
			||||||
 | 
					          "misc/" + p_miscname + "/" + p_filename)), // Theme misc path
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(
 | 
				
			||||||
 | 
					          ao_app->get_misc_path(p_miscname, p_filename)), // Misc path
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(
 | 
				
			||||||
 | 
					          ao_app->get_theme_path(p_filename)), // Theme path
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(
 | 
				
			||||||
 | 
					          ao_app->get_default_theme_path(p_filename)), // Default theme path
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(
 | 
				
			||||||
 | 
					          ao_app->get_theme_path("placeholder")), // Placeholder path
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_default_theme_path(
 | 
				
			||||||
 | 
					          "placeholder")), // Default placeholder path
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  QString final_image = find_image(pathlist);
 | 
				
			||||||
 | 
					  if (final_image == ao_app->get_theme_path("custom.png") ||
 | 
				
			||||||
 | 
					      final_image == ao_app->get_default_theme_path("custom.png") ||
 | 
				
			||||||
 | 
					      final_image == ao_app->get_theme_path("witnesstestimony.png") ||
 | 
				
			||||||
 | 
					      final_image == ao_app->get_default_theme_path("witnesstestimony.png") ||
 | 
				
			||||||
 | 
					      final_image == ao_app->get_theme_path("crossexamination.png") ||
 | 
				
			||||||
 | 
					      final_image == ao_app->get_default_theme_path("crossexamination.png")) 
 | 
				
			||||||
 | 
					    // stupid exceptions because themes are stupid
 | 
				
			||||||
 | 
					    final_image = find_image(
 | 
				
			||||||
 | 
					        {ao_app->get_image_suffix(ao_app->get_theme_path("placeholder")),
 | 
				
			||||||
 | 
					         ao_app->get_image_suffix(ao_app->get_default_theme_path("placeholder"))});
 | 
				
			||||||
 | 
					  start_playback(final_image);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void EffectLayer::load_image(QString p_filename, bool p_looping)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (p_looping)
 | 
				
			||||||
 | 
					    play_once = false;
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    play_once = true;
 | 
				
			||||||
 | 
					  continuous = false;
 | 
				
			||||||
 | 
					  force_continuous = true;
 | 
				
			||||||
 | 
					  start_playback(p_filename); // handled in its own file before we see it
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void InterfaceLayer::load_image(QString p_filename, QString p_miscname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  transform_mode = ao_app->get_misc_scaling(p_miscname);
 | 
				
			||||||
 | 
					  QList<QString> pathlist = {
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_theme_path(
 | 
				
			||||||
 | 
					          "misc/" + p_miscname + "/" +
 | 
				
			||||||
 | 
					          p_filename)), // first check our theme's misc directory
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_misc_path(
 | 
				
			||||||
 | 
					          p_miscname, p_filename)), // then check our global misc folder
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_theme_path(
 | 
				
			||||||
 | 
					          p_filename)), // then check the user's theme for a default image
 | 
				
			||||||
 | 
					      ao_app->get_image_suffix(ao_app->get_default_theme_path(
 | 
				
			||||||
 | 
					          p_filename))}; // and finally check the default theme
 | 
				
			||||||
 | 
					  start_playback(find_image(pathlist));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CharLayer::start_playback(QString p_image)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  movie_effects.clear();
 | 
				
			||||||
 | 
					  AOLayer::start_playback(p_image);
 | 
				
			||||||
 | 
					  if (network_strings.size() > 0) // our FX overwritten by networked ones
 | 
				
			||||||
 | 
					    load_network_effects();
 | 
				
			||||||
 | 
					  else // Use default ini FX
 | 
				
			||||||
 | 
					    load_effects();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AOLayer::start_playback(QString p_image)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifdef DEBUG_MOVIE
 | 
				
			||||||
 | 
					  actual_time.restart();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  this->clear();
 | 
				
			||||||
 | 
					  freeze();
 | 
				
			||||||
 | 
					  movie_frames.clear();
 | 
				
			||||||
 | 
					  movie_delays.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!file_exists(p_image))
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  QString scaling_override =
 | 
				
			||||||
 | 
					      ao_app->read_design_ini("scaling", p_image + ".ini");
 | 
				
			||||||
 | 
					  if (scaling_override != "")
 | 
				
			||||||
 | 
					    transform_mode = ao_app->get_scaling(scaling_override);
 | 
				
			||||||
 | 
					  QString stretch_override =
 | 
				
			||||||
 | 
					      ao_app->read_design_ini("stretch", p_image + ".ini");
 | 
				
			||||||
 | 
					  if (stretch_override != "")
 | 
				
			||||||
 | 
					    stretch = stretch_override.startsWith("true");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  qDebug() << "stretch:" << stretch << "filename:" << p_image;
 | 
				
			||||||
 | 
					  m_reader.setFileName(p_image);
 | 
				
			||||||
 | 
					  if (m_reader.loopCount() == 0)
 | 
				
			||||||
 | 
					    play_once = true;
 | 
				
			||||||
 | 
					  if ((last_path == p_image) && (!force_continuous))
 | 
				
			||||||
 | 
					    continuous = true;
 | 
				
			||||||
 | 
					  else if ((last_path != p_image) && !force_continuous)
 | 
				
			||||||
 | 
					    continuous = false;
 | 
				
			||||||
 | 
					  if (!continuous)
 | 
				
			||||||
 | 
					    frame = 0;
 | 
				
			||||||
 | 
					  force_continuous = false;
 | 
				
			||||||
 | 
					  last_max_frames = max_frames;
 | 
				
			||||||
 | 
					  max_frames = m_reader.imageCount();
 | 
				
			||||||
 | 
					  if (((continuous) && (max_frames != last_max_frames)) || max_frames == 0) {
 | 
				
			||||||
 | 
					    frame = 0;
 | 
				
			||||||
 | 
					    continuous = false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  // CANTFIX: this causes a slight hitch
 | 
				
			||||||
 | 
					  // The correct way of doing this would be to use QImageReader::jumpToImage()
 | 
				
			||||||
 | 
					  // and populate missing data in the movie ticker when it's needed. This is
 | 
				
			||||||
 | 
					  // unforunately completely impossible, because QImageReader::jumpToImage() is
 | 
				
			||||||
 | 
					  // not implemented in any image format AO2 is equipped to use. Instead, the
 | 
				
			||||||
 | 
					  // default behavior is used - that is, absolutely nothing.
 | 
				
			||||||
 | 
					  if (continuous) {
 | 
				
			||||||
 | 
					    for (int i = frame; i--;) {
 | 
				
			||||||
 | 
					      if (i <= -1)
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      QPixmap l_pixmap = this->get_pixmap(m_reader.read());
 | 
				
			||||||
 | 
					      int l_delay = m_reader.nextImageDelay();
 | 
				
			||||||
 | 
					      movie_frames.append(l_pixmap);
 | 
				
			||||||
 | 
					      movie_delays.append(l_delay);
 | 
				
			||||||
 | 
					      // qDebug() << "appending delay of " << l_delay;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  // qDebug() << "CONT: " << continuous << " MAX: " << max_frames
 | 
				
			||||||
 | 
					  //         << " LAST MAX: " << last_max_frames << " FRAME: " << frame;
 | 
				
			||||||
 | 
					  QPixmap f_pixmap = this->get_pixmap(m_reader.read());
 | 
				
			||||||
 | 
					  int f_delay = m_reader.nextImageDelay();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  this->set_frame(f_pixmap);
 | 
				
			||||||
 | 
					  this->show();
 | 
				
			||||||
 | 
					  if (max_frames > 1) {
 | 
				
			||||||
 | 
					    movie_frames.append(f_pixmap);
 | 
				
			||||||
 | 
					    movie_delays.append(f_delay);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (max_frames <= 1) {
 | 
				
			||||||
 | 
					    duration = static_duration;
 | 
				
			||||||
 | 
					    play_once = false;
 | 
				
			||||||
 | 
					#ifdef DEBUG_MOVIE
 | 
				
			||||||
 | 
					    qDebug() << "max_frames is <= 1, using static duration";
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (duration > 0 && cull_image == true)
 | 
				
			||||||
 | 
					    shfx_timer->start(duration);
 | 
				
			||||||
 | 
					  play();
 | 
				
			||||||
 | 
					#ifdef DEBUG_MOVIE
 | 
				
			||||||
 | 
					  qDebug() << max_frames << "Setting image to " << image_path
 | 
				
			||||||
 | 
					           << "Time taken to process image:" << actual_time.elapsed();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  actual_time.restart();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CharLayer::play()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  play_frame_effect(frame);
 | 
				
			||||||
 | 
					  AOLayer::play();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AOLayer::play()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (max_frames <= 1) {
 | 
				
			||||||
 | 
					    if (play_once)
 | 
				
			||||||
 | 
					      ticker->start(tick_ms);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      this->freeze();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    ticker->start(this->get_frame_delay(movie_delays[frame]));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AOLayer::set_play_once(bool p_play_once) { play_once = p_play_once; }
 | 
				
			||||||
 | 
					void AOLayer::set_cull_image(bool p_cull_image) { cull_image = p_cull_image; }
 | 
				
			||||||
 | 
					void AOLayer::set_static_duration(int p_static_duration)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  static_duration = p_static_duration;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void AOLayer::set_max_duration(int p_max_duration)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  max_duration = p_max_duration;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CharLayer::load_effects()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  movie_effects.clear();
 | 
				
			||||||
 | 
					  movie_effects.resize(max_frames);
 | 
				
			||||||
 | 
					  for (int e_frame = 0; e_frame < max_frames; ++e_frame) {
 | 
				
			||||||
 | 
					    QString effect = ao_app->get_screenshake_frame(m_char, m_emote, e_frame);
 | 
				
			||||||
 | 
					    if (effect != "") {
 | 
				
			||||||
 | 
					      movie_effects[e_frame].append("shake");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    effect = ao_app->get_flash_frame(m_char, m_emote, e_frame);
 | 
				
			||||||
 | 
					    if (effect != "") {
 | 
				
			||||||
 | 
					      movie_effects[e_frame].append("flash");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    effect = ao_app->get_sfx_frame(m_char, m_emote, e_frame);
 | 
				
			||||||
 | 
					    if (effect != "") {
 | 
				
			||||||
 | 
					      movie_effects[e_frame].append("sfx^" + effect);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CharLayer::load_network_effects()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  movie_effects.clear();
 | 
				
			||||||
 | 
					  movie_effects.resize(max_frames);
 | 
				
			||||||
 | 
					  // Order is important!!!
 | 
				
			||||||
 | 
					  QStringList effects_list = {"shake", "flash", "sfx^"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Determines which list is smaller - effects_list or network_strings - and
 | 
				
			||||||
 | 
					  // uses it as basis for the loop. This way, incomplete network_strings would
 | 
				
			||||||
 | 
					  // still be parsed, and excess/unaccounted for networked information is
 | 
				
			||||||
 | 
					  // omitted.
 | 
				
			||||||
 | 
					  int effects_size = qMin(effects_list.size(), network_strings.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (int i = 0; i < effects_size; ++i) {
 | 
				
			||||||
 | 
					    QString netstring = network_strings.at(i);
 | 
				
			||||||
 | 
					    QStringList emote_splits = netstring.split("^");
 | 
				
			||||||
 | 
					    for (const QString &emote : emote_splits) {
 | 
				
			||||||
 | 
					      QStringList parsed = emote.split("|");
 | 
				
			||||||
 | 
					      if (parsed.size() <= 0 || parsed.at(0) != m_emote)
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      foreach (QString frame_data, parsed) {
 | 
				
			||||||
 | 
					        QStringList frame_split = frame_data.split("=");
 | 
				
			||||||
 | 
					        if (frame_split.size() <=
 | 
				
			||||||
 | 
					            1) // We might still be hanging at the emote itself (entry 0).
 | 
				
			||||||
 | 
					          continue;
 | 
				
			||||||
 | 
					        int f_frame = frame_split.at(0).toInt();
 | 
				
			||||||
 | 
					        if (f_frame >= max_frames || f_frame < 0) {
 | 
				
			||||||
 | 
					          qDebug() << "Warning: out of bounds" << effects_list[i] << "frame"
 | 
				
			||||||
 | 
					                   << f_frame << "out of" << max_frames << "for" << m_emote;
 | 
				
			||||||
 | 
					          continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        QString f_data = frame_split.at(1);
 | 
				
			||||||
 | 
					        if (f_data != "") {
 | 
				
			||||||
 | 
					          QString effect = effects_list[i];
 | 
				
			||||||
 | 
					          if (effect == "sfx^") // Currently the only frame result that feeds us
 | 
				
			||||||
 | 
					                                // data, let's yank it in.
 | 
				
			||||||
 | 
					            effect += f_data;
 | 
				
			||||||
 | 
					          qDebug() << effect << f_data << "frame" << f_frame << "for"
 | 
				
			||||||
 | 
					                   << m_emote;
 | 
				
			||||||
 | 
					          movie_effects[f_frame].append(effect);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CharLayer::play_frame_effect(int p_frame)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (p_frame < max_frames) {
 | 
				
			||||||
 | 
					    foreach (QString effect, movie_effects[p_frame]) {
 | 
				
			||||||
 | 
					      if (effect == "shake") {
 | 
				
			||||||
 | 
					        shake();
 | 
				
			||||||
 | 
					#ifdef DEBUG_MOVIE
 | 
				
			||||||
 | 
					        qDebug() << "Attempting to play shake on frame" << frame;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (effect == "flash") {
 | 
				
			||||||
 | 
					        flash();
 | 
				
			||||||
 | 
					#ifdef DEBUG_MOVIE
 | 
				
			||||||
 | 
					        qDebug() << "Attempting to play flash on frame" << frame;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (effect.startsWith("sfx^")) {
 | 
				
			||||||
 | 
					        QString sfx = effect.section("^", 1);
 | 
				
			||||||
 | 
					        play_sfx(sfx);
 | 
				
			||||||
 | 
					#ifdef DEBUG_MOVIE
 | 
				
			||||||
 | 
					        qDebug() << "Attempting to play sfx" << sfx << "on frame" << frame;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AOLayer::stop()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // for all intents and purposes, stopping is the same as hiding. at no point
 | 
				
			||||||
 | 
					  // do we want a frozen gif to display
 | 
				
			||||||
 | 
					  this->freeze();
 | 
				
			||||||
 | 
					  this->hide();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AOLayer::freeze()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // aT nO pOiNt Do We WaNt A fRoZeN gIf To DiSpLaY
 | 
				
			||||||
 | 
					  ticker->stop();
 | 
				
			||||||
 | 
					  preanim_timer->stop();
 | 
				
			||||||
 | 
					  shfx_timer->stop();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CharLayer::movie_ticker()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  AOLayer::movie_ticker();
 | 
				
			||||||
 | 
					  play_frame_effect(frame);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AOLayer::movie_ticker()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  ++frame;
 | 
				
			||||||
 | 
					  if ((frame >= max_frames) && (max_frames > 1)) {
 | 
				
			||||||
 | 
					    if (play_once) {
 | 
				
			||||||
 | 
					      if (cull_image)
 | 
				
			||||||
 | 
					        this->stop();
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        this->freeze();
 | 
				
			||||||
 | 
					      preanim_done();
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      frame = 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  //  qint64 difference = elapsed - movie_delays[frame];
 | 
				
			||||||
 | 
					  if (frame >= movie_frames.size()) {
 | 
				
			||||||
 | 
					    movie_frames.append(this->get_pixmap(m_reader.read()));
 | 
				
			||||||
 | 
					    movie_delays.append(m_reader.nextImageDelay());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DEBUG_MOVIE
 | 
				
			||||||
 | 
					  qDebug() << frame << movie_delays[frame]
 | 
				
			||||||
 | 
					           << "actual time taken from last frame:" << actual_time.restart();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  this->set_frame(movie_frames[frame]);
 | 
				
			||||||
 | 
					  ticker->setInterval(this->get_frame_delay(movie_delays[frame]));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CharLayer::preanim_done()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (is_preanim)
 | 
				
			||||||
 | 
					    AOLayer::preanim_done();
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AOLayer::preanim_done()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  ticker->stop();
 | 
				
			||||||
 | 
					  preanim_timer->stop();
 | 
				
			||||||
 | 
					  done();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AOLayer::shfx_timer_done()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  this->stop();
 | 
				
			||||||
 | 
					#ifdef DEBUG_MOVIE
 | 
				
			||||||
 | 
					  qDebug() << "shfx timer signaled done";
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  // signal connected to courtroom object, let it figure out what to do
 | 
				
			||||||
 | 
					  done();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										100
									
								
								src/aomovie.cpp
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								src/aomovie.cpp
									
									
									
									
									
								
							@ -1,100 +0,0 @@
 | 
				
			|||||||
#include "aomovie.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "courtroom.h"
 | 
					 | 
				
			||||||
#include "file_functions.h"
 | 
					 | 
				
			||||||
#include "misc_functions.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AOMovie::AOMovie(QWidget *p_parent, AOApplication *p_ao_app) : QLabel(p_parent)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  ao_app = p_ao_app;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  m_movie = new QMovie();
 | 
					 | 
				
			||||||
  m_movie->setCacheMode(QMovie::CacheAll);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  this->setMovie(m_movie);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  timer = new QTimer(this);
 | 
					 | 
				
			||||||
  timer->setTimerType(Qt::PreciseTimer);
 | 
					 | 
				
			||||||
  timer->setSingleShot(true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  connect(m_movie, SIGNAL(frameChanged(int)), this, SLOT(frame_change(int)));
 | 
					 | 
				
			||||||
  connect(timer, SIGNAL(timeout()), this, SLOT(timer_done()));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOMovie::set_play_once(bool p_play_once) { play_once = p_play_once; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOMovie::play(QString p_image, QString p_char, QString p_custom_theme,
 | 
					 | 
				
			||||||
                   int duration)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  m_movie->stop();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  QString shout_path = p_image;
 | 
					 | 
				
			||||||
  if (!file_exists(p_image)) {
 | 
					 | 
				
			||||||
    QList<QString> pathlist;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pathlist = {
 | 
					 | 
				
			||||||
        ao_app->get_image_suffix(
 | 
					 | 
				
			||||||
            ao_app->get_character_path(p_char, p_image)), // Character folder
 | 
					 | 
				
			||||||
        ao_app->get_image_suffix(ao_app->get_base_path() + "misc/" +
 | 
					 | 
				
			||||||
                                 p_custom_theme + "/" + p_image), // Misc path
 | 
					 | 
				
			||||||
        ao_app->get_image_suffix(ao_app->get_custom_theme_path(
 | 
					 | 
				
			||||||
            p_custom_theme, p_image)), // Custom theme path
 | 
					 | 
				
			||||||
        ao_app->get_image_suffix(ao_app->get_theme_path(p_image)), // Theme path
 | 
					 | 
				
			||||||
        ao_app->get_image_suffix(
 | 
					 | 
				
			||||||
            ao_app->get_default_theme_path(p_image)), // Default theme path
 | 
					 | 
				
			||||||
        ao_app->get_image_suffix(
 | 
					 | 
				
			||||||
            ao_app->get_theme_path("placeholder")), // Placeholder path
 | 
					 | 
				
			||||||
        ao_app->get_image_suffix(ao_app->get_default_theme_path(
 | 
					 | 
				
			||||||
            "placeholder")), // Default placeholder path
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (QString path : pathlist) {
 | 
					 | 
				
			||||||
      if (file_exists(path)) {
 | 
					 | 
				
			||||||
        shout_path = path;
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  m_movie->setFileName(shout_path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (m_movie->loopCount() == 0)
 | 
					 | 
				
			||||||
    play_once = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  this->show();
 | 
					 | 
				
			||||||
  m_movie->start();
 | 
					 | 
				
			||||||
  if (m_movie->frameCount() == 0 && duration > 0)
 | 
					 | 
				
			||||||
    timer->start(duration);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOMovie::stop()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  m_movie->stop();
 | 
					 | 
				
			||||||
  this->hide();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOMovie::frame_change(int n_frame)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  // If it's a "static movie" (only one frame - png image), we can't change
 | 
					 | 
				
			||||||
  // frames - ignore this function (use timer instead). If the frame didn't reach
 | 
					 | 
				
			||||||
  // the last frame or the movie is continuous, don't stop the movie.
 | 
					 | 
				
			||||||
  if (m_movie->frameCount() == 0 || n_frame < (m_movie->frameCount() - 1) ||
 | 
					 | 
				
			||||||
      !play_once)
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  // we need this or else the last frame wont show
 | 
					 | 
				
			||||||
  timer->start(m_movie->nextFrameDelay());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOMovie::timer_done()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  this->stop();
 | 
					 | 
				
			||||||
  // signal connected to courtroom object, let it figure out what to do
 | 
					 | 
				
			||||||
  done();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOMovie::combo_resize(int w, int h)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  QSize f_size(w, h);
 | 
					 | 
				
			||||||
  this->resize(f_size);
 | 
					 | 
				
			||||||
  m_movie->setScaledSize(f_size);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										132
									
								
								src/aoscene.cpp
									
									
									
									
									
								
							
							
						
						
									
										132
									
								
								src/aoscene.cpp
									
									
									
									
									
								
							@ -1,132 +0,0 @@
 | 
				
			|||||||
#include "aoscene.h"
 | 
					 | 
				
			||||||
#include "courtroom.h"
 | 
					 | 
				
			||||||
#include "file_functions.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AOScene::AOScene(QWidget *parent, AOApplication *p_ao_app) : QLabel(parent)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  m_parent = parent;
 | 
					 | 
				
			||||||
  ao_app = p_ao_app;
 | 
					 | 
				
			||||||
  m_movie = new QMovie(this);
 | 
					 | 
				
			||||||
  m_movie->setCacheMode(QMovie::CacheAll);
 | 
					 | 
				
			||||||
  last_image = "";
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOScene::set_image(QString p_image)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  QString background_path =
 | 
					 | 
				
			||||||
      ao_app->get_image_suffix(ao_app->get_background_path(p_image));
 | 
					 | 
				
			||||||
  if (!file_exists(background_path)) // If image is missing, clear current image
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    this->clear();
 | 
					 | 
				
			||||||
    this->setMovie(nullptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    m_movie->stop();
 | 
					 | 
				
			||||||
    last_image = "";
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!file_exists(background_path) || background_path != last_image)
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    this->clear();
 | 
					 | 
				
			||||||
    this->setMovie(nullptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    m_movie->stop();
 | 
					 | 
				
			||||||
    m_movie->setFileName(background_path);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (m_movie->isValid() && m_movie->frameCount() > 1) {
 | 
					 | 
				
			||||||
    m_movie->jumpToNextFrame();
 | 
					 | 
				
			||||||
    float scale_factor = static_cast<float>(f_h) /
 | 
					 | 
				
			||||||
                         static_cast<float>(m_movie->frameRect().height());
 | 
					 | 
				
			||||||
    // preserve aspect ratio
 | 
					 | 
				
			||||||
    int n_w = static_cast<int>(m_movie->frameRect().width() * scale_factor);
 | 
					 | 
				
			||||||
    int n_h = static_cast<int>(m_movie->frameRect().height() * scale_factor);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    m_movie->setScaledSize(QSize(n_w, n_h));
 | 
					 | 
				
			||||||
    this->resize(m_movie->scaledSize());
 | 
					 | 
				
			||||||
    if (!file_exists(background_path) || background_path != last_image)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      this->setMovie(m_movie);
 | 
					 | 
				
			||||||
      m_movie->start();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    QLabel::move(x + (f_w - n_w) / 2, y + (f_h - n_h) / 2); // Center
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    QPixmap background(background_path);
 | 
					 | 
				
			||||||
    auto transform_mode = Qt::FastTransformation;
 | 
					 | 
				
			||||||
    if (background.height() > f_h) // We are downscaling, use anti-aliasing.
 | 
					 | 
				
			||||||
      transform_mode = Qt::SmoothTransformation;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    background = background.scaledToHeight(f_h, transform_mode);
 | 
					 | 
				
			||||||
    this->resize(background.size());
 | 
					 | 
				
			||||||
    this->setPixmap(background);
 | 
					 | 
				
			||||||
    QLabel::move(
 | 
					 | 
				
			||||||
        x + (f_w - background.width()) / 2,
 | 
					 | 
				
			||||||
        y + (f_h - background.height()) /
 | 
					 | 
				
			||||||
                2); // Always center horizontally, always center vertically
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  last_image = background_path;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOScene::set_legacy_desk(QString p_image)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  QString desk_path =
 | 
					 | 
				
			||||||
      ao_app->get_image_suffix(ao_app->get_background_path(p_image));
 | 
					 | 
				
			||||||
  if (!file_exists(desk_path)) // If image is missing, clear current image
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    this->clear();
 | 
					 | 
				
			||||||
    this->setMovie(nullptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    m_movie->stop();
 | 
					 | 
				
			||||||
    last_image = "";
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (file_exists(desk_path) && desk_path == last_image)
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  QPixmap f_desk(desk_path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // vanilla desks vary in both width and height. in order to make that work
 | 
					 | 
				
			||||||
  // with viewport rescaling, some INTENSE math is needed.
 | 
					 | 
				
			||||||
  int vp_width = m_parent->width();
 | 
					 | 
				
			||||||
  int vp_height = m_parent->height();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  double h_modifier = vp_height / 192;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int final_h = static_cast<int>(h_modifier * f_desk.height());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  this->clear();
 | 
					 | 
				
			||||||
  this->setMovie(nullptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  m_movie->stop();
 | 
					 | 
				
			||||||
  m_movie->setFileName(desk_path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  m_movie->setScaledSize(QSize(vp_width, final_h));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (m_movie->isValid() && m_movie->frameCount() > 1) {
 | 
					 | 
				
			||||||
    this->setMovie(m_movie);
 | 
					 | 
				
			||||||
    m_movie->start();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    this->resize(vp_width, final_h);
 | 
					 | 
				
			||||||
    this->setPixmap(f_desk.scaled(vp_width, final_h));
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  last_image = desk_path;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOScene::combo_resize(int w, int h)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  QSize f_size(w, h);
 | 
					 | 
				
			||||||
  f_w = w;
 | 
					 | 
				
			||||||
  f_h = h;
 | 
					 | 
				
			||||||
  this->resize(f_size);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AOScene::move(int ax, int ay)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  x = ax;
 | 
					 | 
				
			||||||
  y = ay;
 | 
					 | 
				
			||||||
  QLabel::move(x, y);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -43,21 +43,22 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
 | 
				
			|||||||
  ui_background = new AOImage(this, ao_app);
 | 
					  ui_background = new AOImage(this, ao_app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ui_viewport = new QWidget(this);
 | 
					  ui_viewport = new QWidget(this);
 | 
				
			||||||
  ui_vp_background = new AOScene(ui_viewport, ao_app);
 | 
					  ui_vp_background = new BackgroundLayer(ui_viewport, ao_app);
 | 
				
			||||||
  ui_vp_speedlines = new AOMovie(ui_viewport, ao_app);
 | 
					  ui_vp_speedlines = new ForegroundLayer(ui_viewport, ao_app);
 | 
				
			||||||
  ui_vp_speedlines->set_play_once(false);
 | 
					  ui_vp_player_char = new CharLayer(ui_viewport, ao_app);
 | 
				
			||||||
  ui_vp_player_char = new AOCharMovie(ui_viewport, ao_app);
 | 
					  ui_vp_sideplayer_char = new CharLayer(ui_viewport, ao_app);
 | 
				
			||||||
  ui_vp_sideplayer_char = new AOCharMovie(ui_viewport, ao_app);
 | 
					 | 
				
			||||||
  ui_vp_sideplayer_char->hide();
 | 
					  ui_vp_sideplayer_char->hide();
 | 
				
			||||||
  ui_vp_desk = new AOScene(ui_viewport, ao_app);
 | 
					  ui_vp_desk = new BackgroundLayer(ui_viewport, ao_app);
 | 
				
			||||||
  ui_vp_legacy_desk = new AOScene(ui_viewport, ao_app);
 | 
					
 | 
				
			||||||
 | 
					  ui_vp_effect = new EffectLayer(this, ao_app);
 | 
				
			||||||
 | 
					  ui_vp_effect->setAttribute(Qt::WA_TransparentForMouseEvents);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ui_vp_evidence_display = new AOEvidenceDisplay(ui_viewport, ao_app);
 | 
					  ui_vp_evidence_display = new AOEvidenceDisplay(ui_viewport, ao_app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ui_vp_chatbox = new AOImage(this, ao_app);
 | 
					  ui_vp_chatbox = new AOImage(this, ao_app);
 | 
				
			||||||
  ui_vp_showname = new QLabel(ui_vp_chatbox);
 | 
					  ui_vp_showname = new QLabel(ui_vp_chatbox);
 | 
				
			||||||
  ui_vp_showname->setAlignment(Qt::AlignLeft);
 | 
					  ui_vp_showname->setAlignment(Qt::AlignLeft);
 | 
				
			||||||
  ui_vp_chat_arrow = new AOMovie(ui_vp_chatbox, ao_app);
 | 
					  ui_vp_chat_arrow = new InterfaceLayer(this, ao_app);
 | 
				
			||||||
  ui_vp_chat_arrow->set_play_once(false);
 | 
					  ui_vp_chat_arrow->set_play_once(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ui_vp_message = new QTextEdit(this);
 | 
					  ui_vp_message = new QTextEdit(this);
 | 
				
			||||||
@ -66,14 +67,13 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
 | 
				
			|||||||
  ui_vp_message->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 | 
					  ui_vp_message->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 | 
				
			||||||
  ui_vp_message->setReadOnly(true);
 | 
					  ui_vp_message->setReadOnly(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ui_vp_testimony = new AOMovie(this, ao_app);
 | 
					  ui_vp_testimony = new InterfaceLayer(this, ao_app);
 | 
				
			||||||
  ui_vp_testimony->set_play_once(false);
 | 
					  ui_vp_testimony->set_play_once(false);
 | 
				
			||||||
  ui_vp_testimony->setAttribute(Qt::WA_TransparentForMouseEvents);
 | 
					  ui_vp_testimony->setAttribute(Qt::WA_TransparentForMouseEvents);
 | 
				
			||||||
  ui_vp_effect = new AOMovie(this, ao_app);
 | 
					  ui_vp_wtce = new InterjectionLayer(this, ao_app);
 | 
				
			||||||
  ui_vp_effect->setAttribute(Qt::WA_TransparentForMouseEvents);
 | 
					  ui_vp_wtce->set_play_once(true);
 | 
				
			||||||
  ui_vp_wtce = new AOMovie(this, ao_app);
 | 
					 | 
				
			||||||
  ui_vp_wtce->setAttribute(Qt::WA_TransparentForMouseEvents);
 | 
					  ui_vp_wtce->setAttribute(Qt::WA_TransparentForMouseEvents);
 | 
				
			||||||
  ui_vp_objection = new AOMovie(this, ao_app);
 | 
					  ui_vp_objection = new InterjectionLayer(this, ao_app);
 | 
				
			||||||
  ui_vp_objection->setAttribute(Qt::WA_TransparentForMouseEvents);
 | 
					  ui_vp_objection->setAttribute(Qt::WA_TransparentForMouseEvents);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ui_ic_chatlog = new QTextEdit(this);
 | 
					  ui_ic_chatlog = new QTextEdit(this);
 | 
				
			||||||
@ -113,7 +113,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
 | 
				
			|||||||
  ui_music_list->setUniformRowHeights(true);
 | 
					  ui_music_list->setUniformRowHeights(true);
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ui_music_display = new AOMovie(this, ao_app);
 | 
					  ui_music_display = new InterfaceLayer(this, ao_app);
 | 
				
			||||||
  ui_music_display->set_play_once(false);
 | 
					  ui_music_display->set_play_once(false);
 | 
				
			||||||
  ui_music_display->setAttribute(Qt::WA_TransparentForMouseEvents);
 | 
					  ui_music_display->setAttribute(Qt::WA_TransparentForMouseEvents);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -271,6 +271,8 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
 | 
				
			|||||||
  connect(keepalive_timer, SIGNAL(timeout()), this, SLOT(ping_server()));
 | 
					  connect(keepalive_timer, SIGNAL(timeout()), this, SLOT(ping_server()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  connect(ui_vp_objection, SIGNAL(done()), this, SLOT(objection_done()));
 | 
					  connect(ui_vp_objection, SIGNAL(done()), this, SLOT(objection_done()));
 | 
				
			||||||
 | 
					  connect(ui_vp_effect, SIGNAL(done()), this, SLOT(effect_done()));
 | 
				
			||||||
 | 
					  connect(ui_vp_wtce, SIGNAL(done()), this, SLOT(effect_done()));
 | 
				
			||||||
  connect(ui_vp_player_char, SIGNAL(done()), this, SLOT(preanim_done()));
 | 
					  connect(ui_vp_player_char, SIGNAL(done()), this, SLOT(preanim_done()));
 | 
				
			||||||
  connect(ui_vp_player_char, SIGNAL(shake()), this, SLOT(do_screenshake()));
 | 
					  connect(ui_vp_player_char, SIGNAL(shake()), this, SLOT(do_screenshake()));
 | 
				
			||||||
  connect(ui_vp_player_char, SIGNAL(flash()), this, SLOT(do_flash()));
 | 
					  connect(ui_vp_player_char, SIGNAL(flash()), this, SLOT(do_flash()));
 | 
				
			||||||
@ -532,13 +534,8 @@ void Courtroom::set_widgets()
 | 
				
			|||||||
  ui_vp_desk->move(0, 0);
 | 
					  ui_vp_desk->move(0, 0);
 | 
				
			||||||
  ui_vp_desk->combo_resize(ui_viewport->width(), ui_viewport->height());
 | 
					  ui_vp_desk->combo_resize(ui_viewport->width(), ui_viewport->height());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // the size of the ui_vp_legacy_desk element relies on various factors and is
 | 
					 | 
				
			||||||
  // set in set_scene()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  double y_modifier = 147.0 / 192.0;
 | 
					  double y_modifier = 147.0 / 192.0;
 | 
				
			||||||
  int final_y = static_cast<int>(y_modifier * ui_viewport->height());
 | 
					  int final_y = static_cast<int>(y_modifier * ui_viewport->height());
 | 
				
			||||||
  ui_vp_legacy_desk->move(0, final_y);
 | 
					 | 
				
			||||||
  ui_vp_legacy_desk->hide();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ui_vp_evidence_display->move(0, 0);
 | 
					  ui_vp_evidence_display->move(0, 0);
 | 
				
			||||||
  ui_vp_evidence_display->combo_resize(ui_viewport->width(),
 | 
					  ui_vp_evidence_display->combo_resize(ui_viewport->width(),
 | 
				
			||||||
@ -553,11 +550,14 @@ void Courtroom::set_widgets()
 | 
				
			|||||||
    ui_vp_chat_arrow->hide();
 | 
					    ui_vp_chat_arrow->hide();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else {
 | 
					  else {
 | 
				
			||||||
    ui_vp_chat_arrow->move(design_ini_result.x, design_ini_result.y);
 | 
					    ui_vp_chat_arrow->move(design_ini_result.x + ui_vp_chatbox->x(), design_ini_result.y + ui_vp_chatbox->y());
 | 
				
			||||||
    ui_vp_chat_arrow->combo_resize(design_ini_result.width,
 | 
					    ui_vp_chat_arrow->combo_resize(design_ini_result.width, design_ini_result.height);
 | 
				
			||||||
                                   design_ini_result.height);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // layering shenanigans with ui_vp_chatbox prevent us from doing the sensible
 | 
				
			||||||
 | 
					  // thing, which is to parent these to ui_viewport. instead, AOLayer handles
 | 
				
			||||||
 | 
					  // masking so we don't overlap parts of the UI, and they become free floating
 | 
				
			||||||
 | 
					  // widgets.
 | 
				
			||||||
  ui_vp_testimony->move(ui_viewport->x(), ui_viewport->y());
 | 
					  ui_vp_testimony->move(ui_viewport->x(), ui_viewport->y());
 | 
				
			||||||
  ui_vp_testimony->combo_resize(ui_viewport->width(), ui_viewport->height());
 | 
					  ui_vp_testimony->combo_resize(ui_viewport->width(), ui_viewport->height());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -659,18 +659,16 @@ void Courtroom::set_widgets()
 | 
				
			|||||||
    ui_music_display->combo_resize(design_ini_result.width,
 | 
					    ui_music_display->combo_resize(design_ini_result.width,
 | 
				
			||||||
                                   design_ini_result.height);
 | 
					                                   design_ini_result.height);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  ui_music_display->load_image("music_display", "");
 | 
				
			||||||
  ui_music_display->play("music_display");
 | 
					 | 
				
			||||||
  ui_music_display->set_play_once(false);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  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");
 | 
				
			||||||
    set_size_and_pos(ui_vp_chatbox, "ao2_chatbox");
 | 
					    //  set_size_and_pos(ui_vp_chatbox, "ao2_chatbox");
 | 
				
			||||||
    set_size_and_pos(ui_ic_chat_name, "ao2_ic_chat_name");
 | 
					    set_size_and_pos(ui_ic_chat_name, "ao2_ic_chat_name");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else {
 | 
					  else {
 | 
				
			||||||
    set_size_and_pos(ui_ic_chat_message, "ic_chat_message");
 | 
					    set_size_and_pos(ui_ic_chat_message, "ic_chat_message");
 | 
				
			||||||
    set_size_and_pos(ui_vp_chatbox, "chatbox");
 | 
					    //  set_size_and_pos(ui_vp_chatbox, "chatbox");
 | 
				
			||||||
    set_size_and_pos(ui_ic_chat_name, "ic_chat_name");
 | 
					    set_size_and_pos(ui_ic_chat_name, "ic_chat_name");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1120,6 +1118,24 @@ void Courtroom::set_size_and_pos(QWidget *p_widget, QString p_identifier)
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Courtroom::set_size_and_pos(QWidget *p_widget, QString p_identifier,
 | 
				
			||||||
 | 
					                                 QString p_char)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  QString filename = "courtroom_design.ini";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pos_size_type design_ini_result =
 | 
				
			||||||
 | 
					      ao_app->get_element_dimensions(p_identifier, filename, p_char);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (design_ini_result.width < 0 || design_ini_result.height < 0) {
 | 
				
			||||||
 | 
					    qDebug() << "W: could not find \"" << p_identifier << "\" in " << filename;
 | 
				
			||||||
 | 
					    p_widget->hide();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    p_widget->move(design_ini_result.x, design_ini_result.y);
 | 
				
			||||||
 | 
					    p_widget->resize(design_ini_result.width, design_ini_result.height);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Courtroom::set_taken(int n_char, bool p_taken)
 | 
					void Courtroom::set_taken(int n_char, bool p_taken)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  if (n_char >= char_list.size()) {
 | 
					  if (n_char >= char_list.size()) {
 | 
				
			||||||
@ -1219,11 +1235,11 @@ void Courtroom::set_background(QString p_background, bool display)
 | 
				
			|||||||
  is_ao2_bg = true;
 | 
					  is_ao2_bg = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (is_ao2_bg) {
 | 
					  if (is_ao2_bg) {
 | 
				
			||||||
    set_size_and_pos(ui_vp_chatbox, "ao2_chatbox");
 | 
					    // set_size_and_pos(ui_vp_chatbox, "ao2_chatbox");
 | 
				
			||||||
    set_size_and_pos(ui_ic_chat_message, "ao2_ic_chat_message");
 | 
					    set_size_and_pos(ui_ic_chat_message, "ao2_ic_chat_message");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else {
 | 
					  else {
 | 
				
			||||||
    set_size_and_pos(ui_vp_chatbox, "chatbox");
 | 
					    // set_size_and_pos(ui_vp_chatbox, "chatbox");
 | 
				
			||||||
    set_size_and_pos(ui_ic_chat_message, "ic_chat_message");
 | 
					    set_size_and_pos(ui_ic_chat_message, "ic_chat_message");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1403,6 +1419,12 @@ void Courtroom::update_character(int p_cid)
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  if (is_ao2_bg) {
 | 
				
			||||||
 | 
					    set_size_and_pos(ui_vp_chatbox, "ao2_chatbox", f_char);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    set_size_and_pos(ui_vp_chatbox, "chatbox", f_char);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (m_cid != -1) // there is no name at char_list -1, and we crash if we try
 | 
					  if (m_cid != -1) // there is no name at char_list -1, and we crash if we try
 | 
				
			||||||
                   // to find one
 | 
					                   // to find one
 | 
				
			||||||
@ -1838,7 +1860,8 @@ void Courtroom::on_chat_return_pressed()
 | 
				
			|||||||
    packet_contents.append(ui_additive->isChecked() ? "1" : "0");
 | 
					    packet_contents.append(ui_additive->isChecked() ? "1" : "0");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (ao_app->effects_enabled) {
 | 
					  if (ao_app->effects_enabled) {
 | 
				
			||||||
    QString fx_sound = ao_app->get_effect_sound(effect, current_char);
 | 
					    QString fx_sound =
 | 
				
			||||||
 | 
					        ao_app->get_effect_property(effect, current_char, "sound");
 | 
				
			||||||
    QString p_effect =
 | 
					    QString p_effect =
 | 
				
			||||||
        ao_app->read_char_ini(current_char, "effects", "Options");
 | 
					        ao_app->read_char_ini(current_char, "effects", "Options");
 | 
				
			||||||
    packet_contents.append(effect + "|" + p_effect + "|" + fx_sound);
 | 
					    packet_contents.append(effect + "|" + p_effect + "|" + fx_sound);
 | 
				
			||||||
@ -1919,12 +1942,9 @@ void Courtroom::chatmessage_enqueue(QStringList p_contents)
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Record the log I/O, log files should be accurate.
 | 
					  // Record the log I/O, log files should be accurate.
 | 
				
			||||||
  log_chatmessage(p_contents[MESSAGE], f_char_id, p_contents[SHOWNAME], p_contents[TEXT_COLOR].toInt());
 | 
					  // If desynced logs are on, display the log IC immediately.
 | 
				
			||||||
  if (ao_app->is_desyncrhonized_logs_enabled()) {
 | 
					  LogMode log_mode = ao_app->is_desyncrhonized_logs_enabled() ? DISPLAY_AND_IO : IO_ONLY;
 | 
				
			||||||
    // Display the logs immediately.
 | 
					  log_chatmessage(p_contents[MESSAGE], f_char_id, p_contents[SHOWNAME], p_contents[TEXT_COLOR].toInt(), log_mode);
 | 
				
			||||||
    display_log_chatmessage(p_contents[MESSAGE], f_char_id, p_contents[SHOWNAME], p_contents[TEXT_COLOR].toInt());
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Send this boi into the queue
 | 
					  // Send this boi into the queue
 | 
				
			||||||
  chatmessage_queue.enqueue(p_contents);
 | 
					  chatmessage_queue.enqueue(p_contents);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1939,11 +1959,12 @@ void Courtroom::chatmessage_enqueue(QStringList p_contents)
 | 
				
			|||||||
void Courtroom::chatmessage_dequeue()
 | 
					void Courtroom::chatmessage_dequeue()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  // Chat stopped being processed, indicate that the user can post their message now.
 | 
					  // Chat stopped being processed, indicate that the user can post their message now.
 | 
				
			||||||
 | 
					  QString f_custom_theme;
 | 
				
			||||||
 | 
					  if (ao_app->is_customchat_enabled()) {
 | 
				
			||||||
    QString f_char = m_chatmessage[CHAR_NAME];
 | 
					    QString f_char = m_chatmessage[CHAR_NAME];
 | 
				
			||||||
  QString f_custom_theme = ao_app->get_char_shouts(f_char);
 | 
					    f_custom_theme = ao_app->get_chat(f_char);
 | 
				
			||||||
  ui_vp_chat_arrow->play(
 | 
					  }
 | 
				
			||||||
      "chat_arrow", f_char,
 | 
					  ui_vp_chat_arrow->load_image("chat_arrow", f_custom_theme);
 | 
				
			||||||
      f_custom_theme);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Nothing to parse in the queue
 | 
					  // Nothing to parse in the queue
 | 
				
			||||||
  if (chatmessage_queue.isEmpty())
 | 
					  if (chatmessage_queue.isEmpty())
 | 
				
			||||||
@ -1975,7 +1996,7 @@ void Courtroom::unpack_chatmessage(QStringList p_contents)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (!ao_app->is_desyncrhonized_logs_enabled()) {
 | 
					  if (!ao_app->is_desyncrhonized_logs_enabled()) {
 | 
				
			||||||
    // We have logs displaying as soon as we reach the message in our queue, which is a less confusing but also less accurate experience for the user.
 | 
					    // We have logs displaying as soon as we reach the message in our queue, which is a less confusing but also less accurate experience for the user.
 | 
				
			||||||
    display_log_chatmessage(m_chatmessage[MESSAGE], m_chatmessage[CHAR_ID].toInt(), m_chatmessage[SHOWNAME], m_chatmessage[TEXT_COLOR].toInt());
 | 
					    log_chatmessage(m_chatmessage[MESSAGE], m_chatmessage[CHAR_ID].toInt(), m_chatmessage[SHOWNAME], m_chatmessage[TEXT_COLOR].toInt(), DISPLAY_ONLY);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Process the callwords for this message
 | 
					  // Process the callwords for this message
 | 
				
			||||||
@ -1994,7 +2015,7 @@ void Courtroom::unpack_chatmessage(QStringList p_contents)
 | 
				
			|||||||
    handle_ic_message();
 | 
					    handle_ic_message();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Courtroom::log_chatmessage(QString f_message, int f_char_id, QString f_showname, int f_color)
 | 
					void Courtroom::log_chatmessage(QString f_message, int f_char_id, QString f_showname, int f_color, LogMode f_log_mode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  // Display name will use the showname
 | 
					  // Display name will use the showname
 | 
				
			||||||
  QString f_displayname = f_showname;
 | 
					  QString f_displayname = f_showname;
 | 
				
			||||||
@ -2058,95 +2079,17 @@ void Courtroom::log_chatmessage(QString f_message, int f_char_id, QString f_show
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      switch (f_log_mode) {
 | 
				
			||||||
 | 
					        case IO_ONLY:
 | 
				
			||||||
          log_ic_text(f_char, f_displayname, shout_message, tr("shouts"));
 | 
					          log_ic_text(f_char, f_displayname, shout_message, tr("shouts"));
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Obtain evidence ID we're trying to work with
 | 
					 | 
				
			||||||
    int f_evi_id = m_chatmessage[EVIDENCE_ID].toInt();
 | 
					 | 
				
			||||||
    // If the evidence ID is in the valid range
 | 
					 | 
				
			||||||
    if (f_evi_id > 0 && f_evi_id <= local_evidence_list.size()) {
 | 
					 | 
				
			||||||
      // Obtain the evidence name
 | 
					 | 
				
			||||||
      QString f_evi_name = local_evidence_list.at(f_evi_id - 1).name;
 | 
					 | 
				
			||||||
      // Add the message to the logs file
 | 
					 | 
				
			||||||
      log_ic_text(f_showname, f_displayname, f_evi_name,
 | 
					 | 
				
			||||||
                  tr("has presented evidence"));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // If our current message is a blankpost, the chat log isn't empty, the chat log's last message is a blank post, and the blankpost's showname is the same as ours
 | 
					 | 
				
			||||||
  if (f_message.isEmpty() && !ic_chatlog_history.isEmpty() && ic_chatlog_history.last().get_message().isEmpty() && ic_chatlog_history.last().get_showname() == f_displayname)
 | 
					 | 
				
			||||||
    return; // Skip adding message
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Add the message to the logs file
 | 
					 | 
				
			||||||
  log_ic_text(f_showname, f_displayname, f_message, "",
 | 
					 | 
				
			||||||
              f_color);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Courtroom::display_log_chatmessage(QString f_message, int f_char_id, QString f_showname, int f_color)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  // Display name will use the showname
 | 
					 | 
				
			||||||
  QString f_displayname = f_showname;
 | 
					 | 
				
			||||||
  if (f_char_id != -1) {
 | 
					 | 
				
			||||||
    // Grab the char.ini showname
 | 
					 | 
				
			||||||
    f_showname = ao_app->get_showname(char_list.at(f_char_id).name);
 | 
					 | 
				
			||||||
    // If custom serversided shownames are not enabled
 | 
					 | 
				
			||||||
    if (!ui_showname_enable->isChecked()) {
 | 
					 | 
				
			||||||
      // Set the display name to the char.ini showname
 | 
					 | 
				
			||||||
      f_displayname = f_showname;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  // If display name is just whitespace, use the char.ini showname.
 | 
					 | 
				
			||||||
  if (f_displayname.trimmed().isEmpty())
 | 
					 | 
				
			||||||
    f_displayname = f_showname;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (log_ic_actions) {
 | 
					 | 
				
			||||||
    // Check if a custom objection is in use
 | 
					 | 
				
			||||||
    int objection_mod = 0;
 | 
					 | 
				
			||||||
    QString custom_objection = "";
 | 
					 | 
				
			||||||
    if (m_chatmessage[OBJECTION_MOD].contains("4&")) {
 | 
					 | 
				
			||||||
      objection_mod = 4;
 | 
					 | 
				
			||||||
      custom_objection = m_chatmessage[OBJECTION_MOD].split(
 | 
					 | 
				
			||||||
          "4&")[1]; // takes the name of custom objection.
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
      objection_mod = m_chatmessage[OBJECTION_MOD].toInt();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    QString f_char = m_chatmessage[CHAR_NAME];
 | 
					 | 
				
			||||||
    QString f_custom_theme = ao_app->get_char_shouts(f_char);
 | 
					 | 
				
			||||||
    if (objection_mod <= 4 && objection_mod >= 1) {
 | 
					 | 
				
			||||||
      QString shout_message;
 | 
					 | 
				
			||||||
      switch (objection_mod) {
 | 
					 | 
				
			||||||
      case 1:
 | 
					 | 
				
			||||||
        shout_message = ao_app->read_char_ini(f_char, "holdit_message", "Shouts");
 | 
					 | 
				
			||||||
        if (shout_message == "")
 | 
					 | 
				
			||||||
          shout_message = tr("HOLD IT!");
 | 
					 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
      case 2:
 | 
					        case DISPLAY_AND_IO:
 | 
				
			||||||
        shout_message = ao_app->read_char_ini(f_char, "objection_message", "Shouts");
 | 
					          log_ic_text(f_char, f_displayname, shout_message, tr("shouts"));
 | 
				
			||||||
        if (shout_message == "")
 | 
					          [[fallthrough]];
 | 
				
			||||||
          shout_message = tr("OBJECTION!");
 | 
					        case DISPLAY_ONLY:
 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      case 3:
 | 
					 | 
				
			||||||
        shout_message = ao_app->read_char_ini(f_char, "takethat_message", "Shouts");
 | 
					 | 
				
			||||||
        if (shout_message == "")
 | 
					 | 
				
			||||||
          shout_message = tr("TAKE THAT!");
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      // case 4 is AO2 only
 | 
					 | 
				
			||||||
      case 4:
 | 
					 | 
				
			||||||
        if (custom_objection != "") {
 | 
					 | 
				
			||||||
          shout_message = ao_app->read_char_ini(f_char, custom_objection.split('.')[0] + "_message", "Shouts");
 | 
					 | 
				
			||||||
          if (shout_message == "")
 | 
					 | 
				
			||||||
            shout_message = custom_objection.split('.')[0];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
          shout_message = ao_app->read_char_ini(f_char, "custom_message", "Shouts");
 | 
					 | 
				
			||||||
          if (shout_message == "")
 | 
					 | 
				
			||||||
            shout_message = tr("CUSTOM OBJECTION!");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
          append_ic_text(shout_message, f_displayname, tr("shouts"));
 | 
					          append_ic_text(shout_message, f_displayname, tr("shouts"));
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Obtain evidence ID we're trying to work with
 | 
					    // Obtain evidence ID we're trying to work with
 | 
				
			||||||
@ -2155,19 +2098,35 @@ void Courtroom::display_log_chatmessage(QString f_message, int f_char_id, QStrin
 | 
				
			|||||||
    if (f_evi_id > 0 && f_evi_id <= local_evidence_list.size()) {
 | 
					    if (f_evi_id > 0 && f_evi_id <= local_evidence_list.size()) {
 | 
				
			||||||
      // Obtain the evidence name
 | 
					      // Obtain the evidence name
 | 
				
			||||||
      QString f_evi_name = local_evidence_list.at(f_evi_id - 1).name;
 | 
					      QString f_evi_name = local_evidence_list.at(f_evi_id - 1).name;
 | 
				
			||||||
      // Append the message to the IC chatlogs in client
 | 
					      switch (f_log_mode) {
 | 
				
			||||||
 | 
					        case IO_ONLY:
 | 
				
			||||||
 | 
					          log_ic_text(f_showname, f_displayname, f_evi_name, tr("has presented evidence"));
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        case DISPLAY_AND_IO:
 | 
				
			||||||
 | 
					          log_ic_text(f_showname, f_displayname, f_evi_name, tr("has presented evidence"));
 | 
				
			||||||
 | 
					          [[fallthrough]];
 | 
				
			||||||
 | 
					        case DISPLAY_ONLY:
 | 
				
			||||||
          append_ic_text(f_evi_name, f_displayname, tr("has presented evidence"));
 | 
					          append_ic_text(f_evi_name, f_displayname, tr("has presented evidence"));
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If our current message is a blankpost, the chat log isn't empty, the chat log's last message is a blank post, and the blankpost's showname is the same as ours
 | 
					  // If the chat message isn't a blankpost, or the chatlog history is empty, or its last message isn't a blankpost
 | 
				
			||||||
  if (f_message.isEmpty() && last_ic_message == f_displayname + ":")
 | 
					  if (!f_message.isEmpty() ||
 | 
				
			||||||
    return; // Skip adding message
 | 
					      ic_chatlog_history.isEmpty() || ic_chatlog_history.last().get_message() != "") {
 | 
				
			||||||
  
 | 
					    switch (f_log_mode) {
 | 
				
			||||||
  last_ic_message = f_displayname + ":" + f_message;
 | 
					      case IO_ONLY:
 | 
				
			||||||
  // Append the message to the IC chatlogs in client
 | 
					        log_ic_text(f_showname, f_displayname, f_message, "",f_color);
 | 
				
			||||||
  append_ic_text(f_message, f_displayname, "",
 | 
					        break;
 | 
				
			||||||
                  f_color);
 | 
					      case DISPLAY_AND_IO:
 | 
				
			||||||
 | 
					        log_ic_text(f_showname, f_displayname, f_message, "",f_color);
 | 
				
			||||||
 | 
					        [[fallthrough]];
 | 
				
			||||||
 | 
					      case DISPLAY_ONLY:
 | 
				
			||||||
 | 
					        append_ic_text(f_message, f_displayname, "",f_color);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool Courtroom::handle_objection()
 | 
					bool Courtroom::handle_objection()
 | 
				
			||||||
@ -2184,64 +2143,75 @@ bool Courtroom::handle_objection()
 | 
				
			|||||||
    objection_mod = m_chatmessage[OBJECTION_MOD].toInt();
 | 
					    objection_mod = m_chatmessage[OBJECTION_MOD].toInt();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QString f_char = m_chatmessage[CHAR_NAME];
 | 
					  if (is_ao2_bg) {
 | 
				
			||||||
  QString f_custom_theme = ao_app->get_char_shouts(f_char);
 | 
					    set_size_and_pos(ui_vp_chatbox, "ao2_chatbox", m_chatmessage[CHAR_NAME]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    set_size_and_pos(ui_vp_chatbox, "chatbox", m_chatmessage[CHAR_NAME]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  set_size_and_pos(ui_vp_showname, "showname", m_chatmessage[CHAR_NAME]);
 | 
				
			||||||
 | 
					  set_size_and_pos(ui_vp_message, "message", m_chatmessage[CHAR_NAME]);
 | 
				
			||||||
 | 
					  ui_vp_message->move(ui_vp_message->x() + ui_vp_chatbox->x(),
 | 
				
			||||||
 | 
					                      ui_vp_message->y() + ui_vp_chatbox->y());
 | 
				
			||||||
 | 
					  ui_vp_message->setTextInteractionFlags(Qt::NoTextInteraction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // if an objection is used
 | 
					  // if an objection is used
 | 
				
			||||||
  if (objection_mod <= 4 && objection_mod >= 1) {
 | 
					  if (objection_mod <= 4 && objection_mod >= 1) {
 | 
				
			||||||
    QString shout_message;
 | 
					    ui_vp_objection->set_static_duration(shout_static_time);
 | 
				
			||||||
 | 
					    ui_vp_objection->set_max_duration(shout_max_time);
 | 
				
			||||||
 | 
					    QString filename;
 | 
				
			||||||
    switch (objection_mod) {
 | 
					    switch (objection_mod) {
 | 
				
			||||||
    case 1:
 | 
					    case 1:
 | 
				
			||||||
      ui_vp_objection->play("holdit_bubble", f_char, f_custom_theme, 724);
 | 
					      filename = "holdit_bubble";
 | 
				
			||||||
      objection_player->play("holdit", f_char, f_custom_theme);
 | 
					      objection_player->play("holdit", m_chatmessage[CHAR_NAME],
 | 
				
			||||||
      shout_message = ao_app->read_char_ini(f_char, "holdit_message", "Shouts");
 | 
					                             ao_app->get_char_shouts(m_chatmessage[CHAR_NAME]));
 | 
				
			||||||
      if (shout_message == "")
 | 
					 | 
				
			||||||
        shout_message = tr("HOLD IT!");
 | 
					 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    case 2:
 | 
					    case 2:
 | 
				
			||||||
      ui_vp_objection->play("objection_bubble", f_char, f_custom_theme, 724);
 | 
					      filename = "objection_bubble";
 | 
				
			||||||
      objection_player->play("objection", f_char, f_custom_theme);
 | 
					      objection_player->play("objection", m_chatmessage[CHAR_NAME],
 | 
				
			||||||
      shout_message = ao_app->read_char_ini(f_char, "objection_message", "Shouts");
 | 
					                             ao_app->get_char_shouts(m_chatmessage[CHAR_NAME]));
 | 
				
			||||||
      if (shout_message == "")
 | 
					 | 
				
			||||||
        shout_message = tr("OBJECTION!");
 | 
					 | 
				
			||||||
      if (ao_app->objection_stop_music())
 | 
					      if (ao_app->objection_stop_music())
 | 
				
			||||||
        music_player->stop();
 | 
					        music_player->stop();
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    case 3:
 | 
					    case 3:
 | 
				
			||||||
      ui_vp_objection->play("takethat_bubble", f_char, f_custom_theme, 724);
 | 
					      filename = "takethat_bubble";
 | 
				
			||||||
      objection_player->play("takethat", f_char, f_custom_theme);
 | 
					      objection_player->play("takethat", m_chatmessage[CHAR_NAME],
 | 
				
			||||||
      shout_message = ao_app->read_char_ini(f_char, "takethat_message", "Shouts");
 | 
					                             ao_app->get_char_shouts(m_chatmessage[CHAR_NAME]));
 | 
				
			||||||
      if (shout_message == "")
 | 
					 | 
				
			||||||
        shout_message = tr("TAKE THAT!");
 | 
					 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    // case 4 is AO2 only
 | 
					    // case 4 is AO2 only
 | 
				
			||||||
    case 4:
 | 
					    case 4:
 | 
				
			||||||
      if (custom_objection != "") {
 | 
					      if (custom_objection != "") {
 | 
				
			||||||
        ui_vp_objection->play("custom_objections/" + custom_objection, f_char,
 | 
					        filename = "custom_objections/" + custom_objection;
 | 
				
			||||||
                              f_custom_theme, shout_stay_time);
 | 
					        objection_player->play(
 | 
				
			||||||
        objection_player->play("custom_objections/" +
 | 
					            "custom_objections/" + custom_objection.split('.')[0],
 | 
				
			||||||
                                   custom_objection.split('.')[0],
 | 
					            m_chatmessage[CHAR_NAME],
 | 
				
			||||||
                               f_char, f_custom_theme);
 | 
					            ao_app->get_char_shouts(m_chatmessage[CHAR_NAME]));
 | 
				
			||||||
        shout_message = ao_app->read_char_ini(f_char, custom_objection.split('.')[0] + "_message", "Shouts");
 | 
					 | 
				
			||||||
        if (shout_message == "")
 | 
					 | 
				
			||||||
          shout_message = custom_objection.split('.')[0];
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      else {
 | 
					      else {
 | 
				
			||||||
        ui_vp_objection->play("custom", f_char, f_custom_theme,
 | 
					        filename = "custom";
 | 
				
			||||||
                              shout_stay_time);
 | 
					        objection_player->play(
 | 
				
			||||||
        objection_player->play("custom", f_char, f_custom_theme);
 | 
					            "custom", m_chatmessage[CHAR_NAME],
 | 
				
			||||||
        shout_message = ao_app->read_char_ini(f_char, "custom_message", "Shouts");
 | 
					            ao_app->get_char_shouts(m_chatmessage[CHAR_NAME]));
 | 
				
			||||||
        if (shout_message == "")
 | 
					 | 
				
			||||||
          shout_message = tr("CUSTOM OBJECTION!");
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
	  break;
 | 
						  break;
 | 
				
			||||||
 | 
					      m_chatmessage[EMOTE_MOD] = 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    ui_vp_objection->load_image(
 | 
				
			||||||
 | 
					        filename, m_chatmessage[CHAR_NAME],
 | 
				
			||||||
 | 
					        ao_app->get_char_shouts(m_chatmessage[CHAR_NAME]));
 | 
				
			||||||
    sfx_player->clear(); // Objection played! Cut all sfx.
 | 
					    sfx_player->clear(); // Objection played! Cut all sfx.
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					    display_character();
 | 
				
			||||||
  return false;
 | 
					  return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Courtroom::effect_done()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  ui_vp_effect->stop();
 | 
				
			||||||
 | 
					  ui_vp_wtce->stop();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Courtroom::display_character()
 | 
					void Courtroom::display_character()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  // Stop all previously playing animations, effects etc.
 | 
					  // Stop all previously playing animations, effects etc.
 | 
				
			||||||
@ -2333,26 +2303,6 @@ void Courtroom::display_pair_character(QString other_charid, QString other_offse
 | 
				
			|||||||
      ui_vp_sideplayer_char->move(ui_viewport->width() * offset_x / 100,
 | 
					      ui_vp_sideplayer_char->move(ui_viewport->width() * offset_x / 100,
 | 
				
			||||||
                                  ui_viewport->height() * offset_y / 100);
 | 
					                                  ui_viewport->height() * offset_y / 100);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Split the charid according to the ^ to determine if we have "ordering" info
 | 
					 | 
				
			||||||
      QStringList args = other_charid.split("^");
 | 
					 | 
				
			||||||
      if (args.size() >
 | 
					 | 
				
			||||||
          1) // This ugly workaround is so we don't make an extra packet just
 | 
					 | 
				
			||||||
              // for this purpose. Rewrite pairing when?
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        // Change the order of appearance based on the pair order variable
 | 
					 | 
				
			||||||
        int order = args.at(1).toInt();
 | 
					 | 
				
			||||||
        switch (order) {
 | 
					 | 
				
			||||||
        case 0: // Our character is in front
 | 
					 | 
				
			||||||
          ui_vp_sideplayer_char->stackUnder(ui_vp_player_char);
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        case 1: // Our character is behind
 | 
					 | 
				
			||||||
          ui_vp_player_char->stackUnder(ui_vp_sideplayer_char);
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Flip the pair character
 | 
					      // Flip the pair character
 | 
				
			||||||
      if (ao_app->flipping_enabled && m_chatmessage[OTHER_FLIP].toInt() == 1)
 | 
					      if (ao_app->flipping_enabled && m_chatmessage[OTHER_FLIP].toInt() == 1)
 | 
				
			||||||
        ui_vp_sideplayer_char->set_flipped(true);
 | 
					        ui_vp_sideplayer_char->set_flipped(true);
 | 
				
			||||||
@ -2360,8 +2310,9 @@ void Courtroom::display_pair_character(QString other_charid, QString other_offse
 | 
				
			|||||||
        ui_vp_sideplayer_char->set_flipped(false);
 | 
					        ui_vp_sideplayer_char->set_flipped(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Play the other pair character's idle animation
 | 
					      // Play the other pair character's idle animation
 | 
				
			||||||
      ui_vp_sideplayer_char->play_idle(m_chatmessage[OTHER_NAME],
 | 
					      QString filename = "(a)" + m_chatmessage[OTHER_EMOTE];
 | 
				
			||||||
                                        m_chatmessage[OTHER_EMOTE]);
 | 
					      ui_vp_sideplayer_char->load_image(filename, m_chatmessage[OTHER_NAME],
 | 
				
			||||||
 | 
					                                            0, false);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -2494,7 +2445,11 @@ void Courtroom::do_flash()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  QString f_char = m_chatmessage[CHAR_NAME];
 | 
					  QString f_char = m_chatmessage[CHAR_NAME];
 | 
				
			||||||
  QString f_custom_theme = ao_app->get_char_shouts(f_char);
 | 
					  QString f_custom_theme = ao_app->get_char_shouts(f_char);
 | 
				
			||||||
  ui_vp_effect->play("realizationflash", f_char, f_custom_theme, 60);
 | 
					  ui_vp_effect->stretch = true;
 | 
				
			||||||
 | 
					  ui_vp_effect->set_static_duration(60);
 | 
				
			||||||
 | 
					  ui_vp_effect->set_max_duration(60);
 | 
				
			||||||
 | 
					  ui_vp_effect->load_image(
 | 
				
			||||||
 | 
					      ao_app->get_effect("realization", f_char, f_custom_theme), false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Courtroom::do_effect(QString fx_name, QString fx_sound, QString p_char,
 | 
					void Courtroom::do_effect(QString fx_name, QString fx_sound, QString p_char,
 | 
				
			||||||
@ -2511,12 +2466,17 @@ void Courtroom::do_effect(QString fx_name, QString fx_sound, QString p_char,
 | 
				
			|||||||
  // Only check if effects are disabled after playing the sound if it exists
 | 
					  // Only check if effects are disabled after playing the sound if it exists
 | 
				
			||||||
  if (!ao_app->is_effects_enabled())
 | 
					  if (!ao_app->is_effects_enabled())
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
 | 
					  ui_vp_effect->transform_mode = ao_app->get_scaling(
 | 
				
			||||||
 | 
					      ao_app->get_effect_property(fx_name, p_char, "scaling"));
 | 
				
			||||||
 | 
					  ui_vp_effect->stretch =
 | 
				
			||||||
 | 
					      ao_app->get_effect_property(fx_name, p_char, "stretch")
 | 
				
			||||||
 | 
					          .startsWith("true");
 | 
				
			||||||
  ui_vp_effect->set_play_once(
 | 
					  ui_vp_effect->set_play_once(
 | 
				
			||||||
      false); // The effects themselves dictate whether or not they're looping.
 | 
					      false); // The effects themselves dictate whether or not they're looping.
 | 
				
			||||||
              // Static effects will linger.
 | 
					              // Static effects will linger.
 | 
				
			||||||
  ui_vp_effect->play(effect); // It will set_play_once to true if the filepath
 | 
					  ui_vp_effect->set_static_duration(0);
 | 
				
			||||||
                              // provided is not designed to loop more than once
 | 
					  ui_vp_effect->set_max_duration(0);
 | 
				
			||||||
 | 
					  ui_vp_effect->load_image(effect, false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Courtroom::play_char_sfx(QString sfx_name)
 | 
					void Courtroom::play_char_sfx(QString sfx_name)
 | 
				
			||||||
@ -2530,7 +2490,7 @@ void Courtroom::initialize_chatbox()
 | 
				
			|||||||
  if (f_charid >= 0 && f_charid < char_list.size() &&
 | 
					  if (f_charid >= 0 && f_charid < char_list.size() &&
 | 
				
			||||||
      (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) {
 | 
					      (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) {
 | 
				
			||||||
    QString real_name = char_list.at(f_charid).name;
 | 
					    QString real_name = char_list.at(f_charid).name;
 | 
				
			||||||
 | 
					  ui_vp_player_char->set_static_duration(0);
 | 
				
			||||||
    QString f_showname = ao_app->get_showname(real_name);
 | 
					    QString f_showname = ao_app->get_showname(real_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ui_vp_showname->setText(f_showname);
 | 
					    ui_vp_showname->setText(f_showname);
 | 
				
			||||||
@ -2562,13 +2522,17 @@ void Courtroom::initialize_chatbox()
 | 
				
			|||||||
    QString chatbox = ao_app->get_chat(customchar);
 | 
					    QString chatbox = ao_app->get_chat(customchar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (chatbox != "" && ao_app->is_customchat_enabled()) {
 | 
					    if (chatbox != "" && ao_app->is_customchat_enabled()) {
 | 
				
			||||||
 | 
					      chatbox_path = ao_app->get_theme_path("misc/" + chatbox + "/chat");
 | 
				
			||||||
 | 
					      if (!ui_vp_chatbox->set_chatbox(chatbox_path)) {
 | 
				
			||||||
        chatbox_path = ao_app->get_base_path() + "misc/" + chatbox + "/chat";
 | 
					        chatbox_path = ao_app->get_base_path() + "misc/" + chatbox + "/chat";
 | 
				
			||||||
        if (!ui_vp_chatbox->set_chatbox(chatbox_path))
 | 
					        if (!ui_vp_chatbox->set_chatbox(chatbox_path))
 | 
				
			||||||
          ui_vp_chatbox->set_chatbox(chatbox_path + "box");
 | 
					          ui_vp_chatbox->set_chatbox(chatbox_path + "box");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // This should probably be called only if any change from the last chat
 | 
					    // This should probably be called only if any change from the last chat
 | 
				
			||||||
    // arrow was actually detected.
 | 
					    // arrow was actually detected.
 | 
				
			||||||
 | 
					    if (current_misc != last_misc) {
 | 
				
			||||||
      pos_size_type design_ini_result = ao_app->get_element_dimensions(
 | 
					      pos_size_type design_ini_result = ao_app->get_element_dimensions(
 | 
				
			||||||
          "chat_arrow", "courtroom_design.ini", customchar);
 | 
					          "chat_arrow", "courtroom_design.ini", customchar);
 | 
				
			||||||
      if (design_ini_result.width < 0 || design_ini_result.height < 0) {
 | 
					      if (design_ini_result.width < 0 || design_ini_result.height < 0) {
 | 
				
			||||||
@ -2576,10 +2540,11 @@ void Courtroom::initialize_chatbox()
 | 
				
			|||||||
        ui_vp_chat_arrow->hide();
 | 
					        ui_vp_chat_arrow->hide();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      else {
 | 
					      else {
 | 
				
			||||||
      ui_vp_chat_arrow->move(design_ini_result.x, design_ini_result.y);
 | 
					        ui_vp_chat_arrow->move(design_ini_result.x + ui_vp_chatbox->x(), design_ini_result.y + ui_vp_chatbox->y());
 | 
				
			||||||
        ui_vp_chat_arrow->combo_resize(design_ini_result.width,
 | 
					        ui_vp_chat_arrow->combo_resize(design_ini_result.width,
 | 
				
			||||||
                                       design_ini_result.height);
 | 
					                                       design_ini_result.height);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pos_size_type default_width = ao_app->get_element_dimensions(
 | 
					    pos_size_type default_width = ao_app->get_element_dimensions(
 | 
				
			||||||
        "showname", "courtroom_design.ini", customchar);
 | 
					        "showname", "courtroom_design.ini", customchar);
 | 
				
			||||||
@ -2686,39 +2651,41 @@ void Courtroom::handle_ic_speaking()
 | 
				
			|||||||
  if (emote_mod == 5 || emote_mod == 6) {
 | 
					  if (emote_mod == 5 || emote_mod == 6) {
 | 
				
			||||||
    // Hide the desks
 | 
					    // Hide the desks
 | 
				
			||||||
    ui_vp_desk->hide();
 | 
					    ui_vp_desk->hide();
 | 
				
			||||||
    ui_vp_legacy_desk->hide();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Obtain character information for our character
 | 
					    // Obtain character information for our character
 | 
				
			||||||
    QString f_char = m_chatmessage[CHAR_NAME];
 | 
					    QString filename;
 | 
				
			||||||
    QString f_custom_theme = ao_app->get_char_shouts(f_char);
 | 
					 | 
				
			||||||
    // I still hate this hardcoding. If we're on pos pro, hlp and wit, use prosecution_speedlines. Otherwise, defense_speedlines.
 | 
					    // I still hate this hardcoding. If we're on pos pro, hlp and wit, use prosecution_speedlines. Otherwise, defense_speedlines.
 | 
				
			||||||
    if (side == "pro" || side == "hlp" || side == "wit")
 | 
					    if (side == "pro" || side == "hlp" || side == "wit")
 | 
				
			||||||
      ui_vp_speedlines->play("prosecution_speedlines", f_char, f_custom_theme);
 | 
					      filename = "prosecution_speedlines";
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      ui_vp_speedlines->play("defense_speedlines", f_char, f_custom_theme);
 | 
					      filename = "defense_speedlines";
 | 
				
			||||||
 | 
					    ui_vp_speedlines->load_image(filename, m_chatmessage[CHAR_NAME]);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Check if this is a talking color (white text, etc.)
 | 
					  // Check if this is a talking color (white text, etc.)
 | 
				
			||||||
  color_is_talking =
 | 
					  color_is_talking =
 | 
				
			||||||
      color_markdown_talking_list.at(m_chatmessage[TEXT_COLOR].toInt());
 | 
					      color_markdown_talking_list.at(m_chatmessage[TEXT_COLOR].toInt());
 | 
				
			||||||
 | 
					  QString filename;
 | 
				
			||||||
  // If color is talking, and our state isn't already talking
 | 
					  // If color is talking, and our state isn't already talking
 | 
				
			||||||
  if (color_is_talking && text_state == 1 &&
 | 
					  if (color_is_talking && text_state == 1 &&
 | 
				
			||||||
      anim_state < 2)
 | 
					      anim_state < 2)
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    // Stop the previous animation and play the talking animation
 | 
					    // Stop the previous animation and play the talking animation
 | 
				
			||||||
    ui_vp_player_char->stop();
 | 
					    ui_vp_player_char->stop();
 | 
				
			||||||
    ui_vp_player_char->play_talking(m_chatmessage[CHAR_NAME],
 | 
					    ui_vp_player_char->set_play_once(false);
 | 
				
			||||||
                                    m_chatmessage[EMOTE]);
 | 
					    filename = "(b)" + m_chatmessage[EMOTE];
 | 
				
			||||||
 | 
					    ui_vp_player_char->load_image(filename, m_chatmessage[CHAR_NAME], 0, false);
 | 
				
			||||||
    // Set the anim state accordingly
 | 
					    // Set the anim state accordingly
 | 
				
			||||||
    anim_state = 2;
 | 
					    anim_state = 2;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else if (anim_state < 3)
 | 
					  else if (anim_state < 3 &&
 | 
				
			||||||
 | 
					           anim_state != 3) // Set it to idle as we're not on that already
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    // Stop the previous animation and play the idle animation
 | 
					    // Stop the previous animation and play the idle animation
 | 
				
			||||||
    ui_vp_player_char->stop();
 | 
					    ui_vp_player_char->stop();
 | 
				
			||||||
    ui_vp_player_char->play_idle(m_chatmessage[CHAR_NAME],
 | 
					    ui_vp_player_char->set_play_once(false);
 | 
				
			||||||
                                 m_chatmessage[EMOTE]);
 | 
					    filename = "(a)" + m_chatmessage[EMOTE];
 | 
				
			||||||
 | 
					    ui_vp_player_char->load_image(filename, m_chatmessage[CHAR_NAME], 0, false);
 | 
				
			||||||
    // Set the anim state accordingly
 | 
					    // Set the anim state accordingly
 | 
				
			||||||
    anim_state = 3;
 | 
					    anim_state = 3;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -3117,7 +3084,6 @@ void Courtroom::play_preanim(bool immediate)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  QString f_char = m_chatmessage[CHAR_NAME];
 | 
					  QString f_char = m_chatmessage[CHAR_NAME];
 | 
				
			||||||
  QString f_preanim = m_chatmessage[PRE_EMOTE];
 | 
					  QString f_preanim = m_chatmessage[PRE_EMOTE];
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // all time values in char.inis are multiplied by a constant(time_mod) to get
 | 
					  // all time values in char.inis are multiplied by a constant(time_mod) to get
 | 
				
			||||||
  // the actual time
 | 
					  // the actual time
 | 
				
			||||||
  int ao2_duration = ao_app->get_ao2_preanim_duration(f_char, f_preanim);
 | 
					  int ao2_duration = ao_app->get_ao2_preanim_duration(f_char, f_preanim);
 | 
				
			||||||
@ -3143,8 +3109,9 @@ void Courtroom::play_preanim(bool immediate)
 | 
				
			|||||||
    qDebug() << "W: could not find " + anim_to_find;
 | 
					    qDebug() << "W: could not find " + anim_to_find;
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  ui_vp_player_char->set_static_duration(preanim_duration);
 | 
				
			||||||
  ui_vp_player_char->play_pre(f_char, f_preanim, preanim_duration);
 | 
					  ui_vp_player_char->set_play_once(true);
 | 
				
			||||||
 | 
					  ui_vp_player_char->load_image(f_preanim, f_char, preanim_duration, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (immediate)
 | 
					  if (immediate)
 | 
				
			||||||
    anim_state = 4;
 | 
					    anim_state = 4;
 | 
				
			||||||
@ -3161,6 +3128,7 @@ void Courtroom::play_preanim(bool immediate)
 | 
				
			|||||||
void Courtroom::preanim_done()
 | 
					void Courtroom::preanim_done()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  anim_state = 1;
 | 
					  anim_state = 1;
 | 
				
			||||||
 | 
					  qDebug() << "preanim over, anim_state set to 1";
 | 
				
			||||||
  handle_ic_speaking();
 | 
					  handle_ic_speaking();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -3232,6 +3200,8 @@ void Courtroom::start_chat_ticking()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // means text is currently ticking
 | 
					  // means text is currently ticking
 | 
				
			||||||
  text_state = 1;
 | 
					  text_state = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  c_played = false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Courtroom::chat_tick()
 | 
					void Courtroom::chat_tick()
 | 
				
			||||||
@ -3243,13 +3213,30 @@ void Courtroom::chat_tick()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // Due to our new text speed system, we always need to stop the timer now.
 | 
					  // Due to our new text speed system, we always need to stop the timer now.
 | 
				
			||||||
  chat_tick_timer->stop();
 | 
					  chat_tick_timer->stop();
 | 
				
			||||||
 | 
					  ui_vp_player_char->set_static_duration(0);
 | 
				
			||||||
 | 
					  QString filename;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (tick_pos >= f_message.size()) {
 | 
					  if (tick_pos >= f_message.size()) {
 | 
				
			||||||
    text_state = 2;
 | 
					    text_state = 2;
 | 
				
			||||||
    if (anim_state < 3) {
 | 
					    if (anim_state < 3) {
 | 
				
			||||||
 | 
					      QStringList c_paths = {
 | 
				
			||||||
 | 
					        ao_app->get_image_suffix(ao_app->get_character_path(m_chatmessage[CHAR_NAME], "(c)" + m_chatmessage[EMOTE])),
 | 
				
			||||||
 | 
					        ao_app->get_image_suffix(ao_app->get_character_path(m_chatmessage[CHAR_NAME], "(c)/" + m_chatmessage[EMOTE]))
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      // if there is a (c) animation for this emote and we haven't played it already
 | 
				
			||||||
 | 
					      if (file_exists(ui_vp_player_char->find_image(c_paths)) &&(!c_played)) {
 | 
				
			||||||
 | 
					        anim_state = 5;
 | 
				
			||||||
 | 
					        ui_vp_player_char->set_play_once(true);
 | 
				
			||||||
 | 
					        filename = "(c)" + m_chatmessage[EMOTE];
 | 
				
			||||||
 | 
					        c_played = true;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else {
 | 
				
			||||||
        anim_state = 3;
 | 
					        anim_state = 3;
 | 
				
			||||||
      ui_vp_player_char->play_idle(m_chatmessage[CHAR_NAME],
 | 
					        ui_vp_player_char->set_play_once(false);
 | 
				
			||||||
                                   m_chatmessage[EMOTE]);
 | 
					        filename = "(a)" + m_chatmessage[EMOTE];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      ui_vp_player_char->load_image(filename, m_chatmessage[CHAR_NAME], 0,
 | 
				
			||||||
 | 
					                                    false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    QString f_char;
 | 
					    QString f_char;
 | 
				
			||||||
    QString f_custom_theme;
 | 
					    QString f_custom_theme;
 | 
				
			||||||
@ -3257,6 +3244,10 @@ void Courtroom::chat_tick()
 | 
				
			|||||||
      f_char = m_chatmessage[CHAR_NAME];
 | 
					      f_char = m_chatmessage[CHAR_NAME];
 | 
				
			||||||
      f_custom_theme = ao_app->get_chat(f_char);
 | 
					      f_custom_theme = ao_app->get_chat(f_char);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    ui_vp_chat_arrow->load_image("chat_arrow",f_custom_theme); // Chat stopped being processed, indicate that.
 | 
				
			||||||
 | 
					    additive_previous =
 | 
				
			||||||
 | 
					        additive_previous +
 | 
				
			||||||
 | 
					        filter_ic_text(f_message, true, -1, m_chatmessage[TEXT_COLOR].toInt());
 | 
				
			||||||
	  QString f_message_filtered = filter_ic_text(f_message, true, -1, m_chatmessage[TEXT_COLOR].toInt());
 | 
						  QString f_message_filtered = filter_ic_text(f_message, true, -1, m_chatmessage[TEXT_COLOR].toInt());
 | 
				
			||||||
    for (int c = 0; c < max_colors; ++c) {
 | 
					    for (int c = 0; c < max_colors; ++c) {
 | 
				
			||||||
      f_message_filtered = f_message_filtered.replace("$c" + QString::number(c), char_color_rgb_list.at(c).name(QColor::HexRgb));
 | 
					      f_message_filtered = f_message_filtered.replace("$c" + QString::number(c), char_color_rgb_list.at(c).name(QColor::HexRgb));
 | 
				
			||||||
@ -3453,16 +3444,20 @@ void Courtroom::chat_tick()
 | 
				
			|||||||
               // to avoid interrupting a non-interrupted preanim)
 | 
					               // to avoid interrupting a non-interrupted preanim)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      ui_vp_player_char->stop();
 | 
					      ui_vp_player_char->stop();
 | 
				
			||||||
      ui_vp_player_char->play_talking(m_chatmessage[CHAR_NAME],
 | 
					      ui_vp_player_char->set_play_once(false);
 | 
				
			||||||
                                      m_chatmessage[EMOTE]);
 | 
					      filename = "(b)" + m_chatmessage[EMOTE];
 | 
				
			||||||
 | 
					      ui_vp_player_char->load_image(filename, m_chatmessage[CHAR_NAME], 0,
 | 
				
			||||||
 | 
					                                    false);
 | 
				
			||||||
      anim_state = 2;
 | 
					      anim_state = 2;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (!color_is_talking && anim_state < 3 &&
 | 
					    else if (!color_is_talking && anim_state < 3 &&
 | 
				
			||||||
             anim_state != 3) // Set it to idle as we're not on that already
 | 
					             anim_state != 3) // Set it to idle as we're not on that already
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      ui_vp_player_char->stop();
 | 
					      ui_vp_player_char->stop();
 | 
				
			||||||
      ui_vp_player_char->play_idle(m_chatmessage[CHAR_NAME],
 | 
					      ui_vp_player_char->set_play_once(false);
 | 
				
			||||||
                                   m_chatmessage[EMOTE]);
 | 
					      filename = "(a)" + m_chatmessage[EMOTE];
 | 
				
			||||||
 | 
					      ui_vp_player_char->load_image(filename, m_chatmessage[CHAR_NAME], 0,
 | 
				
			||||||
 | 
					                                    false);
 | 
				
			||||||
      anim_state = 3;
 | 
					      anim_state = 3;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Continue ticking
 | 
					    // Continue ticking
 | 
				
			||||||
@ -3547,19 +3542,15 @@ void Courtroom::set_scene(QString f_desk_mod, QString f_side)
 | 
				
			|||||||
    f_background = f_side;
 | 
					    f_background = f_side;
 | 
				
			||||||
    f_desk_image = f_side + "_overlay";
 | 
					    f_desk_image = f_side + "_overlay";
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  ui_vp_background->load_image(f_background);
 | 
				
			||||||
  ui_vp_background->set_image(f_background);
 | 
					  ui_vp_desk->load_image(f_desk_image);
 | 
				
			||||||
  ui_vp_desk->set_image(f_desk_image);
 | 
					 | 
				
			||||||
  ui_vp_legacy_desk->set_legacy_desk(f_desk_image);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (f_desk_mod == "0" ||
 | 
					  if (f_desk_mod == "0" ||
 | 
				
			||||||
      (f_desk_mod != "1" &&
 | 
					      (f_desk_mod != "1" &&
 | 
				
			||||||
       (f_side == "jud" || f_side == "hld" || f_side == "hlp"))) {
 | 
					       (f_side == "jud" || f_side == "hld" || f_side == "hlp"))) {
 | 
				
			||||||
    ui_vp_desk->hide();
 | 
					    ui_vp_desk->hide();
 | 
				
			||||||
    ui_vp_legacy_desk->hide();
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else {
 | 
					  else {
 | 
				
			||||||
    ui_vp_legacy_desk->hide();
 | 
					 | 
				
			||||||
    ui_vp_desk->show();
 | 
					    ui_vp_desk->show();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -3707,31 +3698,40 @@ void Courtroom::handle_song(QStringList *p_contents)
 | 
				
			|||||||
void Courtroom::handle_wtce(QString p_wtce, int variant)
 | 
					void Courtroom::handle_wtce(QString p_wtce, int variant)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QString sfx_file = "courtroom_sounds.ini";
 | 
					  QString sfx_file = "courtroom_sounds.ini";
 | 
				
			||||||
 | 
					  QString sfx_name;
 | 
				
			||||||
 | 
					  QString filename;
 | 
				
			||||||
 | 
					  ui_vp_wtce->set_static_duration(wtce_static_time);
 | 
				
			||||||
 | 
					  ui_vp_wtce->set_max_duration(wtce_max_time);
 | 
				
			||||||
  // witness testimony
 | 
					  // witness testimony
 | 
				
			||||||
  if (p_wtce == "testimony1") {
 | 
					  if (p_wtce == "testimony1") {
 | 
				
			||||||
    sfx_player->play(ao_app->get_sfx("witness_testimony"));
 | 
					    sfx_name = "witness_testimony";
 | 
				
			||||||
    ui_vp_wtce->play("witnesstestimony", "", "", 1500);
 | 
					    filename = "witnesstestimony";
 | 
				
			||||||
    ui_vp_testimony->play("testimony");
 | 
					    ui_vp_testimony->load_image("testimony", "");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  // cross examination
 | 
					  // cross examination
 | 
				
			||||||
  else if (p_wtce == "testimony2") {
 | 
					  else if (p_wtce == "testimony2") {
 | 
				
			||||||
    sfx_player->play(ao_app->get_sfx("cross_examination"));
 | 
					    sfx_name = "cross_examination";
 | 
				
			||||||
    ui_vp_wtce->play("crossexamination", "", "", 1500);
 | 
					    filename = "crossexamination";
 | 
				
			||||||
    ui_vp_testimony->stop();
 | 
					    ui_vp_testimony->stop();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else if (p_wtce == "judgeruling") {
 | 
					  else if (p_wtce == "judgeruling") {
 | 
				
			||||||
 | 
					    ui_vp_wtce->set_static_duration(verdict_static_time);
 | 
				
			||||||
 | 
					    ui_vp_wtce->set_max_duration(verdict_max_time);
 | 
				
			||||||
    if (variant == 0) {
 | 
					    if (variant == 0) {
 | 
				
			||||||
      sfx_player->play(ao_app->get_sfx("not_guilty"));
 | 
					      sfx_name = "not_guilty";
 | 
				
			||||||
      ui_vp_wtce->play("notguilty", "", "", 3000);
 | 
					      filename = "notguilty";
 | 
				
			||||||
      ui_vp_testimony->stop();
 | 
					      ui_vp_testimony->stop();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (variant == 1) {
 | 
					    else if (variant == 1) {
 | 
				
			||||||
      sfx_player->play(ao_app->get_sfx("guilty"));
 | 
					      sfx_name = "guilty";
 | 
				
			||||||
      ui_vp_wtce->play("guilty", "", "", 3000);
 | 
					      filename = "guilty";
 | 
				
			||||||
      ui_vp_testimony->stop();
 | 
					      ui_vp_testimony->stop();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  QString bg_misc = ao_app->read_design_ini("misc", ao_app->get_background_path("design.ini"));
 | 
				
			||||||
 | 
					  sfx_player->play(ao_app->get_sfx(sfx_name, bg_misc));
 | 
				
			||||||
 | 
					  ui_vp_wtce->load_image(filename, "", bg_misc);
 | 
				
			||||||
 | 
					  ui_vp_wtce->set_play_once(true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Courtroom::set_hp_bar(int p_bar, int p_state)
 | 
					void Courtroom::set_hp_bar(int p_bar, int p_state)
 | 
				
			||||||
@ -4954,18 +4954,18 @@ void Courtroom::set_text_color_dropdown()
 | 
				
			|||||||
    QColor color =
 | 
					    QColor color =
 | 
				
			||||||
        ao_app->get_chat_color("c" + QString::number(c), current_char);
 | 
					        ao_app->get_chat_color("c" + QString::number(c), current_char);
 | 
				
			||||||
    color_rgb_list.append(color);
 | 
					    color_rgb_list.append(color);
 | 
				
			||||||
    color_markdown_start_list.append(ao_app->get_chat_markdown(
 | 
					    color_markdown_start_list.append(ao_app->get_chat_markup(
 | 
				
			||||||
        "c" + QString::number(c) + "_start", current_char));
 | 
					        "c" + QString::number(c) + "_start", current_char));
 | 
				
			||||||
    color_markdown_end_list.append(ao_app->get_chat_markdown(
 | 
					    color_markdown_end_list.append(ao_app->get_chat_markup(
 | 
				
			||||||
        "c" + QString::number(c) + "_end", current_char));
 | 
					        "c" + QString::number(c) + "_end", current_char));
 | 
				
			||||||
    color_markdown_remove_list.append(
 | 
					    color_markdown_remove_list.append(
 | 
				
			||||||
        ao_app->get_chat_markdown("c" + QString::number(c) + "_remove",
 | 
					        ao_app->get_chat_markup("c" + QString::number(c) + "_remove",
 | 
				
			||||||
                                current_char) == "1");
 | 
					                                current_char) == "1");
 | 
				
			||||||
    color_markdown_talking_list.append(
 | 
					    color_markdown_talking_list.append(
 | 
				
			||||||
        ao_app->get_chat_markdown("c" + QString::number(c) + "_talking",
 | 
					        ao_app->get_chat_markup("c" + QString::number(c) + "_talking",
 | 
				
			||||||
                                current_char) != "0");
 | 
					                                current_char) != "0");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    QString color_name = ao_app->get_chat_markdown(
 | 
					    QString color_name = ao_app->get_chat_markup(
 | 
				
			||||||
        "c" + QString::number(c) + "_name", current_char);
 | 
					        "c" + QString::number(c) + "_name", current_char);
 | 
				
			||||||
    if (color_name.isEmpty()) // Not defined
 | 
					    if (color_name.isEmpty()) // Not defined
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -65,6 +65,16 @@ QString AOApplication::get_character_path(QString p_char, QString p_file)
 | 
				
			|||||||
  return get_case_sensitive_path(path);
 | 
					  return get_case_sensitive_path(path);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QString AOApplication::get_misc_path(QString p_misc, QString p_file)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  QString path = get_base_path() + "misc/" + p_misc + "/" + p_file;
 | 
				
			||||||
 | 
					#ifndef CASE_SENSITIVE_FILESYSTEM
 | 
				
			||||||
 | 
					  return path;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  return get_case_sensitive_path(path);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QString AOApplication::get_sounds_path(QString p_file)
 | 
					QString AOApplication::get_sounds_path(QString p_file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QString path = get_base_path() + "sounds/general/" + p_file;
 | 
					  QString path = get_base_path() + "sounds/general/" + p_file;
 | 
				
			||||||
 | 
				
			|||||||
@ -67,8 +67,7 @@ bool AOApplication::get_log_goes_downwards()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
bool AOApplication::get_log_newline()
 | 
					bool AOApplication::get_log_newline()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QString result =
 | 
					  QString result = configini->value("log_newline", "false").value<QString>();
 | 
				
			||||||
      configini->value("log_newline", "false").value<QString>();
 | 
					 | 
				
			||||||
  return result.startsWith("true");
 | 
					  return result.startsWith("true");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -80,8 +79,7 @@ int AOApplication::get_log_margin()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
bool AOApplication::get_log_timestamp()
 | 
					bool AOApplication::get_log_timestamp()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QString result =
 | 
					  QString result = configini->value("log_timestamp", "false").value<QString>();
 | 
				
			||||||
      configini->value("log_timestamp", "false").value<QString>();
 | 
					 | 
				
			||||||
  return result.startsWith("true");
 | 
					  return result.startsWith("true");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -282,6 +280,13 @@ QString AOApplication::read_design_ini(QString p_identifier,
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Qt::TransformationMode AOApplication::get_scaling(QString p_scaling)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (p_scaling == "smooth")
 | 
				
			||||||
 | 
					    return Qt::SmoothTransformation;
 | 
				
			||||||
 | 
					  return Qt::FastTransformation;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QPoint AOApplication::get_button_spacing(QString p_identifier, QString p_file)
 | 
					QPoint AOApplication::get_button_spacing(QString p_identifier, QString p_file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QString design_ini_path = get_theme_path(p_file);
 | 
					  QString design_ini_path = get_theme_path(p_file);
 | 
				
			||||||
@ -315,28 +320,12 @@ pos_size_type AOApplication::get_element_dimensions(QString p_identifier,
 | 
				
			|||||||
                                                    QString p_file,
 | 
					                                                    QString p_file,
 | 
				
			||||||
                                                    QString p_char)
 | 
					                                                    QString p_char)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QString char_ini_path =
 | 
					 | 
				
			||||||
      get_base_path() + "misc/" + get_chat(p_char) + "/" + p_file;
 | 
					 | 
				
			||||||
  QString design_ini_path = get_theme_path(p_file);
 | 
					 | 
				
			||||||
  QString default_path = get_default_theme_path(p_file);
 | 
					 | 
				
			||||||
  QString f_result = read_design_ini(p_identifier, char_ini_path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  pos_size_type return_value;
 | 
					  pos_size_type return_value;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  return_value.x = 0;
 | 
					  return_value.x = 0;
 | 
				
			||||||
  return_value.y = 0;
 | 
					  return_value.y = 0;
 | 
				
			||||||
  return_value.width = -1;
 | 
					  return_value.width = -1;
 | 
				
			||||||
  return_value.height = -1;
 | 
					  return_value.height = -1;
 | 
				
			||||||
 | 
					  QString f_result = get_design_element(p_identifier, p_file, p_char);
 | 
				
			||||||
  if (f_result == "") {
 | 
					 | 
				
			||||||
    f_result = read_design_ini(p_identifier, design_ini_path);
 | 
					 | 
				
			||||||
    if (f_result == "") {
 | 
					 | 
				
			||||||
      f_result = read_design_ini(p_identifier, default_path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (f_result == "")
 | 
					 | 
				
			||||||
        return return_value;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QStringList sub_line_elements = f_result.split(",");
 | 
					  QStringList sub_line_elements = f_result.split(",");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -353,17 +342,16 @@ pos_size_type AOApplication::get_element_dimensions(QString p_identifier,
 | 
				
			|||||||
QString AOApplication::get_design_element(QString p_identifier, QString p_file,
 | 
					QString AOApplication::get_design_element(QString p_identifier, QString p_file,
 | 
				
			||||||
                                          QString p_char)
 | 
					                                          QString p_char)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QString char_ini_path =
 | 
					  QStringList paths{get_theme_path("misc/" + get_chat(p_char) + "/" +
 | 
				
			||||||
      get_base_path() + "misc/" + get_chat(p_char) + "/" + p_file;
 | 
					                                   p_file), // user theme overrides base/misc
 | 
				
			||||||
  QString design_ini_path = get_theme_path(p_file);
 | 
					                    get_base_path() + "misc/" + get_chat(p_char) + "/" + p_file,
 | 
				
			||||||
  QString default_path = get_default_theme_path(p_file);
 | 
					                    get_theme_path(p_file), get_default_theme_path(p_file)};
 | 
				
			||||||
  QString f_result = read_design_ini(p_identifier, char_ini_path);
 | 
					  for (const QString &path : paths) {
 | 
				
			||||||
  if (f_result == "") {
 | 
					    QString value = read_design_ini(p_identifier, path);
 | 
				
			||||||
    f_result = read_design_ini(p_identifier, design_ini_path);
 | 
					    if (!value.isEmpty())
 | 
				
			||||||
    if (f_result == "")
 | 
					      return value;
 | 
				
			||||||
      f_result = read_design_ini(p_identifier, default_path);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return f_result;
 | 
					  return "";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
QString AOApplication::get_font_name(QString p_identifier, QString p_file)
 | 
					QString AOApplication::get_font_name(QString p_identifier, QString p_file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -483,34 +471,30 @@ QString AOApplication::get_tagged_stylesheet(QString target_tag, QString p_file)
 | 
				
			|||||||
  return f_text;
 | 
					  return f_text;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QString AOApplication::get_chat_markdown(QString p_identifier, QString p_chat)
 | 
					QString AOApplication::get_chat_markup(QString p_identifier, QString p_chat)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QString design_ini_path =
 | 
					  QStringList paths{get_theme_path("misc/" + get_chat(p_chat) + "/config.ini"),
 | 
				
			||||||
      get_base_path() + "misc/" + get_chat(p_chat) + "/config.ini";
 | 
					                    get_base_path() + "misc/" + get_chat(p_chat) +
 | 
				
			||||||
  QString default_path = get_base_path() + "misc/default/config.ini";
 | 
					                        "/config.ini",
 | 
				
			||||||
  QString f_result = read_design_ini(p_identifier, design_ini_path);
 | 
					                    get_base_path() + "misc/default/config.ini",
 | 
				
			||||||
 | 
					                    get_theme_path("misc/default/config.ini")};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (f_result == "")
 | 
					  for (const QString &path : paths) {
 | 
				
			||||||
    f_result = read_design_ini(p_identifier, default_path);
 | 
					    QString value = read_design_ini(p_identifier, path);
 | 
				
			||||||
 | 
					    if (!value.isEmpty()) {
 | 
				
			||||||
 | 
					      return value.toLatin1();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return f_result.toLatin1();
 | 
					  return "";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QColor AOApplication::get_chat_color(QString p_identifier, QString p_chat)
 | 
					QColor AOApplication::get_chat_color(QString p_identifier, QString p_chat)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QColor return_color(255, 255, 255);
 | 
					  QColor return_color(255, 255, 255);
 | 
				
			||||||
 | 
					  QString f_result = get_chat_markup(p_identifier, p_chat);
 | 
				
			||||||
  QString design_ini_path =
 | 
					 | 
				
			||||||
      get_base_path() + "misc/" + get_chat(p_chat) + "/config.ini";
 | 
					 | 
				
			||||||
  QString default_path = get_base_path() + "misc/default/config.ini";
 | 
					 | 
				
			||||||
  QString f_result = read_design_ini(p_identifier, design_ini_path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (f_result == "") {
 | 
					 | 
				
			||||||
    f_result = read_design_ini(p_identifier, default_path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (f_result == "")
 | 
					  if (f_result == "")
 | 
				
			||||||
    return return_color;
 | 
					    return return_color;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QStringList color_list = f_result.split(",");
 | 
					  QStringList color_list = f_result.split(",");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -524,23 +508,21 @@ QColor AOApplication::get_chat_color(QString p_identifier, QString p_chat)
 | 
				
			|||||||
  return return_color;
 | 
					  return return_color;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QString AOApplication::get_sfx(QString p_identifier)
 | 
					QString AOApplication::get_sfx(QString p_identifier, QString p_misc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QString design_ini_path = get_theme_path("courtroom_sounds.ini");
 | 
					  QStringList paths{get_theme_path("misc/" + p_misc + "/courtroom_sounds.ini"),
 | 
				
			||||||
  QString default_path = get_default_theme_path("courtroom_sounds.ini");
 | 
					                    get_misc_path(p_misc, "courtroom_sounds.ini"),
 | 
				
			||||||
  QString f_result = read_design_ini(p_identifier, design_ini_path);
 | 
					                    get_theme_path("courtroom_sounds.ini"),
 | 
				
			||||||
 | 
					                    get_default_theme_path("courtroom_sounds.ini")};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QString return_sfx = "";
 | 
					  QString return_sfx = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (f_result == "") {
 | 
					  for (const QString &path : paths) {
 | 
				
			||||||
    f_result = read_design_ini(p_identifier, default_path);
 | 
					    QString value = read_design_ini(p_identifier, path);
 | 
				
			||||||
 | 
					    if (!value.isEmpty()) {
 | 
				
			||||||
    if (f_result == "")
 | 
					      return value.toLatin1();
 | 
				
			||||||
      return return_sfx;
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  return_sfx = f_result;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return return_sfx;
 | 
					  return return_sfx;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -667,6 +649,31 @@ QString AOApplication::get_blips(QString p_char)
 | 
				
			|||||||
  return f_result;
 | 
					  return f_result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QString AOApplication::get_emote_property(QString p_char, QString p_emote,
 | 
				
			||||||
 | 
					                                          QString p_property)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  QString f_result =
 | 
				
			||||||
 | 
					      read_char_ini(p_char, p_emote, p_property); // per-emote override
 | 
				
			||||||
 | 
					  if (f_result == "")
 | 
				
			||||||
 | 
					    f_result = read_char_ini(p_char, p_property,
 | 
				
			||||||
 | 
					                             "Options"); // global for this character
 | 
				
			||||||
 | 
					  return f_result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Qt::TransformationMode AOApplication::get_misc_scaling(QString p_miscname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (p_miscname != "") {
 | 
				
			||||||
 | 
					    QString misc_transform_mode = read_design_ini(
 | 
				
			||||||
 | 
					        "scaling", get_theme_path("misc/" + p_miscname + "/config.ini"));
 | 
				
			||||||
 | 
					    if (misc_transform_mode == "")
 | 
				
			||||||
 | 
					      misc_transform_mode =
 | 
				
			||||||
 | 
					          read_design_ini("scaling", get_misc_path(p_miscname, "config.ini"));
 | 
				
			||||||
 | 
					    if (misc_transform_mode == "smooth")
 | 
				
			||||||
 | 
					      return Qt::SmoothTransformation;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return Qt::FastTransformation;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QString AOApplication::get_category(QString p_char)
 | 
					QString AOApplication::get_category(QString p_char)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QString f_result = read_char_ini(p_char, "category", "Options");
 | 
					  QString f_result = read_char_ini(p_char, "category", "Options");
 | 
				
			||||||
@ -904,7 +911,7 @@ QStringList AOApplication::get_theme_effects()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  QStringList lines = read_file(p_path).split("\n");
 | 
					  QStringList lines = read_file(p_path).split("\n");
 | 
				
			||||||
  foreach (QString effect, lines) {
 | 
					  foreach (QString effect, lines) {
 | 
				
			||||||
    effect = effect.split("=")[0].trimmed();
 | 
					    effect = effect.split("=")[0].trimmed().split("_")[0];
 | 
				
			||||||
    if (!effect.isEmpty() && !effects.contains(effect))
 | 
					    if (!effect.isEmpty() && !effects.contains(effect))
 | 
				
			||||||
      effects.append(effect);
 | 
					      effects.append(effect);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -922,7 +929,7 @@ QStringList AOApplication::get_effects(QString p_char)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  QStringList lines = read_file(p_path).split("\n");
 | 
					  QStringList lines = read_file(p_path).split("\n");
 | 
				
			||||||
  foreach (QString effect, lines) {
 | 
					  foreach (QString effect, lines) {
 | 
				
			||||||
    effect = effect.split("=")[0].trimmed();
 | 
					    effect = effect.split("=")[0].trimmed().split("_")[0];
 | 
				
			||||||
    if (!effect.isEmpty() && !effects.contains(effect))
 | 
					    if (!effect.isEmpty() && !effects.contains(effect))
 | 
				
			||||||
      effects.append(effect);
 | 
					      effects.append(effect);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -957,25 +964,33 @@ QString AOApplication::get_effect(QString effect, QString p_char,
 | 
				
			|||||||
  return p_path;
 | 
					  return p_path;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QString AOApplication::get_effect_sound(QString fx_name, QString p_char)
 | 
					QString AOApplication::get_effect_property(QString fx_name, QString p_char,
 | 
				
			||||||
 | 
					                                           QString p_property)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					  QString f_property;
 | 
				
			||||||
 | 
					  if (p_property == "sound")
 | 
				
			||||||
 | 
					    f_property = fx_name;
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    f_property = fx_name + "_" + p_property;
 | 
				
			||||||
  QString p_effect = read_char_ini(p_char, "effects", "Options");
 | 
					  QString p_effect = read_char_ini(p_char, "effects", "Options");
 | 
				
			||||||
  QString p_path = get_base_path() + "misc/" + p_effect + "/effects.ini";
 | 
					  QString p_path = get_base_path() + "misc/" + p_effect + "/effects.ini";
 | 
				
			||||||
  QString design_ini_path = get_theme_path("effects/effects.ini");
 | 
					  QString design_ini_path = get_theme_path("effects/effects.ini");
 | 
				
			||||||
  QString default_path = get_default_theme_path("effects/effects.ini");
 | 
					  QString default_path = get_default_theme_path("effects/effects.ini");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QString f_result = read_design_ini(fx_name, p_path);
 | 
					  QString f_result = read_design_ini(f_property, p_path);
 | 
				
			||||||
  if (f_result == "") {
 | 
					  if (f_result == "") {
 | 
				
			||||||
    f_result = read_design_ini(fx_name, design_ini_path);
 | 
					    f_result = read_design_ini(f_property, design_ini_path);
 | 
				
			||||||
    if (f_result == "") {
 | 
					    if (f_result == "") {
 | 
				
			||||||
      f_result = read_design_ini(fx_name, default_path);
 | 
					      f_result = read_design_ini(f_property, default_path);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (fx_name == "realization") {
 | 
					  if (fx_name == "realization" && p_property == "sound") {
 | 
				
			||||||
    f_result = get_custom_realization(p_char);
 | 
					    f_result = get_custom_realization(p_char);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  qDebug() << "got" << f_property << "of" << fx_name << "==" << f_result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return f_result;
 | 
					  return f_result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user