
* Remove get_static_image_suffix (webp, gif etc. can be non-animated) Replace QList<QString> with QStringList * forgot to remove static image from aoimage * Simplify get_theme_path, get_custom_theme_path and get_default_theme_path all into a single get_theme_path func Add a default_theme variable which defines the currently recognized default theme Add a new "get_asset_path" that will be used to simplify asset resolution considerably * Simplify AOImage set_image function to use get_asset_path Begin working on the subtheme system * Add p_default_theme for get_asset_path Implement get_asset_path for AOButton * Condense aolayer path lookups into the get_asset_path function * Get rid of get_font_name due to underuse (and it just does the same thing as get_design_element anyway) Get rid of get_char_shouts (use chat= instead) Use get_subtheme() instead of subtheme (because get_subtheme() can perform overrides based on the user's settings) Make get_color() use get_asset_path() Make get_design_element() use get_asset_path() * Adapt a whole bunch of text_file_functions to the get_asset_path method, fixing an enormous amount of invalid path resolutions Unfortunately I have to keep backwards compatibility for the backwards ass config.ini method for the chat markup (new way is chat_config.ini) Get rid of get_theme_effects and implement the stacking behavior into get_effects instead * Program doesn't run, color lists stop generating for some reason Also implement safety checks for the asset path generator * Fix a really tricky issue that popped up regarding char_color_rgb_list not being generated, causing segfaults * Address the sfx player path resolution being really, really stupid and resolve major inconsistencies (such as the bug where objection sfx wouldn't be playing despite the default theme or default misc folder having them) * Fix sfx path resolution being funky (apparently D:/Qt/Projects/AO2-Client/bin/base/themes/default//objection.wav is a valid qt5 path...) * Implement: get_asset_paths - Return an untested list of universal paths from the provided args get_asset_path - Loop through the list of provided asset paths and return the first valid file get_image_path - Loop through the list of provided asset paths, apply get_image_suffix and return the first valid image file get_sfx_path - Loop through the list of provided asset paths, apply get_sfx_suffix and return the first valid sound file get_asset - return an asset (must contain file extension) from the get_asset_path() applied on the get_asset_paths() get_image - return an image with get_image_suffix() applied on the get_image_path() for the get_asset_paths() get_sfx - return a sfx from provided args with the uniquely constructed asset path list for sounds Rename old get_sfx to get_court_sfx for better clarity of its function This replaces previous asset stuff I implemented, as I think this is a better solution lol * Add a new get_config_value that obtains a value from the config that matches identifier Adjust all calls to get_asset() to actually look for a config identifier value instead, so even if a config.ini is found if it doesn't contain the identifier we want we keep looking * Fix effects.ini sounds not working Remove debug text * Make it so even if you miss the required asset, and don't have a missingno, the viewport still doesn't freeze up due to waiting on Objections etc. due to signals. * Implement default_theme option for courtroom_design.ini, allowing you to make themes that inherit from other themes that are not default. * move sounds folder lower in sfx pathlist * fix realization sfx not being fetched from config * Make aosfxplayer actually use get_sfx I made Move sounds folder path check last in get_sfx * I thought this would fix QSettings::value: Empty key passed but I guess not, that annoying error will keep pestering us :((( * Remove silly .png exception for SplashLayer Fix static image Objections freezing the viewport due to done(); signal that never arrives * Make WTCE cooler by including a stop method for witness testimony indicator, and add support for custom WTCE * Reduce code duplication for get_sfx * Fix the program hanging/entering an infinite loop/segfaults/a number of nasty issues due to done(); signal being sent as soon as playback begins if the image is invalid. This is done by removing the file_exists check, and letting the rest of the functionality handle this case - the system is robust enough and treats an invalid image as a static image. * Fix segfaults with AOLayers by sanity checking using max_frames Fix "Pixmap is null" console spam * You'll hate me for this. Make it possible to have fully animated AOButton and AOImage * Add a settings option to toggle animated themes on or off * Add a setting for animated theme elements Add a "static image" toggle for get_image_suffix * Fix custom chat and generally the chat boxes not having consistent behaivor with subthemes Add a settings option for subthemes Have AOImage keep track of its last valid path * Add SubTheme (ST) packet. Pass subtheme as arg0, and "1" if you want the client's theme to be reloaded. ST packet sets ao_app->subtheme no matter what. It will not reload theme unless the user has their subtheme set to "server". Fix showname widths by rearranging font metrics to do its calculations *after* the showname font is set, and not before (making it lag behind the correct display size by 1 msg) Co-authored-by: in1tiate <radwoodward@vikings.grayson.edu>
239 lines
7.5 KiB
C++
239 lines
7.5 KiB
C++
#ifndef AOLAYER_H
|
|
#define AOLAYER_H
|
|
|
|
#include <QDebug>
|
|
#include <QElapsedTimer>
|
|
#include <QImageReader>
|
|
#include <QLabel>
|
|
#include <QTimer>
|
|
#include <QBitmap>
|
|
|
|
class AOApplication;
|
|
|
|
// "Brief" explanation of what the hell this is:
|
|
//
|
|
// AOLayer handles all animations both inside and outside
|
|
// the viewport. It was originally devised as a layering
|
|
// system, but turned into a full refactor of the existing
|
|
// animation code.
|
|
//
|
|
// AOLayer has six subclasses, all of which differ mainly in
|
|
// how they handle path resolution.
|
|
//
|
|
// - BackgroundLayer: self-explanatory, handles files found in base/background
|
|
// - CharLayer: handles all the "wonderful" quirks of character path resolution
|
|
// - SplashLayer: handles elements that can either be provided by a misc/ directory
|
|
// or by the theme - speedlines, shouts, WT/CE, et cetera
|
|
// - EffectLayer: this is basically a dummy layer since effects do their own wonky
|
|
// path resolution in a different file
|
|
// - InterfaceLayer: handles UI elements like the chat arrow and the music display
|
|
// - StickerLayer: Crystalwarrior really wanted this. Handles "stickers," whatever those are.
|
|
//
|
|
// For questions comments or concerns, bother someone else
|
|
|
|
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
|
|
// Are we loading this from the same frame we left off on?
|
|
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;
|
|
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);
|
|
|
|
// Move the label and center it
|
|
void move_and_center(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(QStringList 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 (which is no longer used)
|
|
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;
|
|
|
|
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);
|
|
// Center the QLabel in the viewport based on the dimensions of f_pixmap
|
|
void center_pixmap(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 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 SplashLayer : public AOLayer {
|
|
Q_OBJECT
|
|
public:
|
|
SplashLayer(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);
|
|
};
|
|
|
|
class StickerLayer : public AOLayer {
|
|
Q_OBJECT
|
|
public:
|
|
StickerLayer(QWidget *p_parent, AOApplication *p_ao_app);
|
|
void load_image(QString p_charname);
|
|
};
|
|
#endif // AOLAYER_H
|