Wavelength
Privacy-focused, cross-platform, and open-source communication application
Loading...
Searching...
No Matches
FloatingEnergySphereWidget Class Referencefinal

An OpenGL widget displaying a floating, interactive energy sphere. More...

#include <floating_energy_sphere_widget.h>

Inheritance diagram for FloatingEnergySphereWidget:
Collaboration diagram for FloatingEnergySphereWidget:

Signals

void destructionSequenceFinished ()
 Emitted when the destruction animation sequence (visual and audio) completes.
 
void konamiCodeEntered ()
 Emitted when the Konami code sequence is successfully entered. (Deprecated, destruction starts directly)
 
void widgetClosed ()
 Emitted when the widget is closed normally (not during destruction).
 

Public Member Functions

 FloatingEnergySphereWidget (bool is_first_time, QWidget *parent=nullptr)
 Constructs a FloatingEnergySphereWidget. Initializes OpenGL settings, timers, audio components, interaction variables, and sets up the window appearance (frameless, transparent background).
 
void SetClosable (bool closable)
 Sets whether the widget can be closed by the user or programmatically. Used to prevent closing during the destruction animation.
 
 ~FloatingEnergySphereWidget () override
 Destructor. Cleans up OpenGL resources (VBO, VAO, shader), stops timers, and stops audio playback/decoding.
 

Protected Member Functions

void closeEvent (QCloseEvent *event) override
 Handles the widget close event. Stops timers and audio, emits widgetClosed() if allowed (closable_ is true), otherwise ignores the event.
 
void initializeGL () override
 Initializes OpenGL resources (functions, shaders, geometry, VAO/VBO) and audio setup. Called once before the first paintGL call.
 
void keyPressEvent (QKeyEvent *event) override
 Handles key press events. Detects the Konami code sequence.
 
void mouseMoveEvent (QMouseEvent *event) override
 Handles mouse move events. Rotates the sphere based on mouse dragging when the left button is pressed. Updates angular velocity for inertia effect.
 
void mousePressEvent (QMouseEvent *event) override
 Handles mouse press events. Accepts the event, but the primary logic is in mouseMoveEvent.
 
void mouseReleaseEvent (QMouseEvent *event) override
 Handles mouse release events. Stops direct rotation tracking and allows inertia to take over.
 
void paintGL () override
 Renders the OpenGL scene. Called whenever the widget needs to be repainted. Binds shaders and VAO, sets uniforms (matrices, time, audio amplitude, impact data, destruction progress), and draws the sphere points.
 
void resizeGL (int w, int h) override
 Handles resizing of the OpenGL viewport and updates the projection matrix. Calculates the field of view dynamically to keep the sphere's clear size consistent.
 
void wheelEvent (QWheelEvent *event) override
 Handles mouse wheel events. Zooms the camera in or out by adjusting camera_distance_.
 

Private Slots

void AudioDecodingFinished () const
 Slot called by the audio decoder when it finishes decoding the entire source file.
 
void HandleAudioDecoderError ()
 Slot called when the QAudioDecoder encounters an error. Logs the error.
 
void HandleMediaPlayerError () const
 Slot called when the QMediaPlayer encounters an error. Logs the error.
 
void HandlePlayerStateChanged (QMediaPlayer::State state)
 Slot called when the QMediaPlayer's state changes (e.g., Playing, Stopped). Used to detect the end of the initial audio to start the hint timer, and the end of the destruction audio to close the widget.
 
void PlayKonamiHint () const
 Slot called by hint_timer_ after a period of inactivity to play the Konami code audio hint.
 
void ProcessAudioBuffer ()
 Slot called by the audio decoder when a new buffer of decoded audio data is ready. Calculates the RMS amplitude for the buffer and stores it. Sets audio_ready_ flag.
 
void SimulateClick ()
 Slot called periodically by click_simulation_timer_ to trigger random impacts on the sphere.
 
void StartDestructionSequence ()
 Initiates the destruction animation sequence. Sets the is_destroying_ flag, resets progress, plays the destruction sound, and prevents the widget from being closed prematurely.
 
void UpdateAnimation ()
 Slot called periodically by timer_ to update animation state. Advances time, updates audio amplitude interpolation, handles rotation/inertia, updates destruction progress if active, and schedules a repaint.
 

Private Member Functions

float CalculateRMSAmplitude (const QAudioBuffer &buffer) const
 Calculates the Root Mean Square (RMS) amplitude for a given audio buffer. Used to quantify the energy level in the audio signal for visualization. Handles different audio sample formats.
 
void SetupAudio ()
 Initializes audio components (QMediaPlayer, QAudioDecoder), connects signals, selects the appropriate audio file based on is_first_time_, and starts playback/decoding.
 
void SetupShaders ()
 Compiles and links the vertex and fragment shaders into shader_program_.
 
void SetupSphereGeometry (int rings, int sectors)
 Creates the vertex data (positions) for the sphere geometry using rings and sectors. Populates the vertices_ vector.
 
void TriggerImpactAtScreenPos (const QPoint &screen_position)
 Triggers a visual impact effect at a point on the sphere corresponding to a screen position. Performs ray casting from the screen position to find the intersection point on the sphere and activates an ImpactInfo entry.
 

Private Attributes

QVector3D angular_velocity_
 Current angular velocity used for inertial rotation.
 
std::vector< float > audio_amplitudes_
 Stores calculated RMS amplitude values for each decoded audio buffer.
 
qint64 audio_buffer_duration_ms_
 Duration of a single audio buffer processed by the decoder, in milliseconds.
 
QAudioDecoder * audio_decoder_
 Decoder for extracting audio data from files for amplitude analysis.
 
QAudioFormat audio_format_
 Format of the decoded audio data (sample rate, channels, etc.).
 
bool audio_ready_
 Flag indicating if audio data has been successfully decoded and is ready for visualization.
 
float camera_distance_
 Distance from the camera to the origin (center of the sphere). Used for zooming.
 
QVector3D camera_position_
 Position of the camera in world space.
 
QTimer * click_simulation_timer_
 Timer triggering simulated random clicks/impacts on the sphere.
 
bool closable_
 Flag indicating if the widget can be closed.
 
float current_audio_amplitude_
 Current audio amplitude value used for rendering (smoothed).
 
float damping_factor_
 Damping factor applied to angular velocity for inertia decay.
 
float destruction_progress_
 Progress of the destruction animation (0.0 to 1.0).
 
QElapsedTimer elapsed_timer_
 Timer used for calculating delta time between animation frames.
 
QTimer * hint_timer_
 Timer triggering the Konami code audio hints after inactivity.
 
std::vector< ImpactInfoimpacts_
 Stores information about active impact effects.
 
bool is_destroying_
 Flag indicating if the destruction animation is currently active.
 
bool is_first_time_
 Flag indicating if this is the first time the widget/app is run (affects initial audio).
 
std::deque< int > key_sequence_
 Stores the sequence of recently pressed keys for Konami code detection.
 
const QString kGoodbyeSoundFilename = "goodbye.wav"
 Filename of the audio played during the destruction sequence.
 
const std::vector< int > konami_code_
 The target key sequence for the Konami code.
 
float last_frame_time_secs_
 Timestamp of the last animation frame in seconds.
 
QPoint last_mouse_position_
 Stores the last mouse position during dragging for rotation calculation.
 
QMediaPlayer * media_player_
 Media player for playing audio files (initial sound, hint, destruction).
 
QMatrix4x4 model_matrix_
 Model matrix transforming model space to world space (includes rotation).
 
bool mouse_pressed_
 Flag indicating if the left mouse button is currently pressed.
 
int next_impact_index_
 Index of the next slot to use in the impacts_ vector (circular).
 
QMatrix4x4 projection_matrix_
 Projection matrix transforming view space to clip space.
 
QQuaternion rotation_
 Current rotation of the sphere as a quaternion.
 
QOpenGLShaderProgram * shader_program_
 The compiled and linked OpenGL shader program.
 
float target_audio_amplitude_ {}
 Target audio amplitude based on the currently playing audio buffer.
 
float time_value_
 Time value passed to shaders, incremented in UpdateAnimation.
 
QTimer timer_
 Timer driving the main animation loop (UpdateAnimation).
 
QOpenGLVertexArrayObject vao_
 OpenGL Vertex Array Object managing vertex buffer state.
 
QOpenGLBuffer vbo_
 OpenGL Vertex Buffer Object storing sphere vertex data.
 
int vertex_count_
 Total number of vertices in the sphere geometry.
 
std::vector< GLfloat > vertices_
 Raw vertex data (positions) for the sphere points.
 
QMatrix4x4 view_matrix_
 View matrix transforming world space to view space.
 

Detailed Description

An OpenGL widget displaying a floating, interactive energy sphere.

This widget renders a sphere composed of points using OpenGL shaders. The sphere deforms dynamically based on time, audio amplitude (visualizing audio playback), and simulated impacts triggered by clicks or automatically. It supports mouse interaction for rotation and zooming. It also includes an Easter egg triggered by the Konami code, which initiates a destruction animation sequence with accompanying sound. The widget plays different initial audio files based on whether it's the first time the application is run.

Constructor & Destructor Documentation

◆ FloatingEnergySphereWidget()

FloatingEnergySphereWidget::FloatingEnergySphereWidget ( bool is_first_time,
QWidget * parent = nullptr )
explicit

Constructs a FloatingEnergySphereWidget. Initializes OpenGL settings, timers, audio components, interaction variables, and sets up the window appearance (frameless, transparent background).

Parameters
is_first_timeFlag indicating if this is the first launch, affecting initial audio.
parentOptional parent widget.

◆ ~FloatingEnergySphereWidget()

FloatingEnergySphereWidget::~FloatingEnergySphereWidget ( )
override

Destructor. Cleans up OpenGL resources (VBO, VAO, shader), stops timers, and stops audio playback/decoding.

Member Function Documentation

◆ AudioDecodingFinished

void FloatingEnergySphereWidget::AudioDecodingFinished ( ) const
privateslot

Slot called by the audio decoder when it finishes decoding the entire source file.

Here is the caller graph for this function:

◆ CalculateRMSAmplitude()

float FloatingEnergySphereWidget::CalculateRMSAmplitude ( const QAudioBuffer & buffer) const
private

Calculates the Root Mean Square (RMS) amplitude for a given audio buffer. Used to quantify the energy level in the audio signal for visualization. Handles different audio sample formats.

Parameters
bufferThe QAudioBuffer containing decoded audio data.
Returns
The calculated RMS amplitude, normalized roughly to the range [0.0, 1.0].
Here is the caller graph for this function:

◆ closeEvent()

void FloatingEnergySphereWidget::closeEvent ( QCloseEvent * event)
overrideprotected

Handles the widget close event. Stops timers and audio, emits widgetClosed() if allowed (closable_ is true), otherwise ignores the event.

Parameters
eventThe close event.
Here is the call graph for this function:

◆ destructionSequenceFinished

void FloatingEnergySphereWidget::destructionSequenceFinished ( )
signal

Emitted when the destruction animation sequence (visual and audio) completes.

Here is the caller graph for this function:

◆ HandleAudioDecoderError

void FloatingEnergySphereWidget::HandleAudioDecoderError ( )
privateslot

Slot called when the QAudioDecoder encounters an error. Logs the error.

Here is the caller graph for this function:

◆ HandleMediaPlayerError

void FloatingEnergySphereWidget::HandleMediaPlayerError ( ) const
privateslot

Slot called when the QMediaPlayer encounters an error. Logs the error.

Here is the caller graph for this function:

◆ HandlePlayerStateChanged

void FloatingEnergySphereWidget::HandlePlayerStateChanged ( QMediaPlayer::State state)
privateslot

Slot called when the QMediaPlayer's state changes (e.g., Playing, Stopped). Used to detect the end of the initial audio to start the hint timer, and the end of the destruction audio to close the widget.

Parameters
stateThe new media player state.
Here is the call graph for this function:

◆ initializeGL()

void FloatingEnergySphereWidget::initializeGL ( )
overrideprotected

Initializes OpenGL resources (functions, shaders, geometry, VAO/VBO) and audio setup. Called once before the first paintGL call.

Here is the call graph for this function:

◆ keyPressEvent()

void FloatingEnergySphereWidget::keyPressEvent ( QKeyEvent * event)
overrideprotected

Handles key press events. Detects the Konami code sequence.

Parameters
eventThe key event.
Here is the call graph for this function:

◆ konamiCodeEntered

void FloatingEnergySphereWidget::konamiCodeEntered ( )
signal

Emitted when the Konami code sequence is successfully entered. (Deprecated, destruction starts directly)

◆ mouseMoveEvent()

void FloatingEnergySphereWidget::mouseMoveEvent ( QMouseEvent * event)
overrideprotected

Handles mouse move events. Rotates the sphere based on mouse dragging when the left button is pressed. Updates angular velocity for inertia effect.

Parameters
eventThe mouse event.

◆ mousePressEvent()

void FloatingEnergySphereWidget::mousePressEvent ( QMouseEvent * event)
overrideprotected

Handles mouse press events. Accepts the event, but the primary logic is in mouseMoveEvent.

Parameters
eventThe mouse event.

◆ mouseReleaseEvent()

void FloatingEnergySphereWidget::mouseReleaseEvent ( QMouseEvent * event)
overrideprotected

Handles mouse release events. Stops direct rotation tracking and allows inertia to take over.

Parameters
eventThe mouse event.

◆ paintGL()

void FloatingEnergySphereWidget::paintGL ( )
overrideprotected

Renders the OpenGL scene. Called whenever the widget needs to be repainted. Binds shaders and VAO, sets uniforms (matrices, time, audio amplitude, impact data, destruction progress), and draws the sphere points.

◆ PlayKonamiHint

void FloatingEnergySphereWidget::PlayKonamiHint ( ) const
privateslot

Slot called by hint_timer_ after a period of inactivity to play the Konami code audio hint.

◆ ProcessAudioBuffer

void FloatingEnergySphereWidget::ProcessAudioBuffer ( )
privateslot

Slot called by the audio decoder when a new buffer of decoded audio data is ready. Calculates the RMS amplitude for the buffer and stores it. Sets audio_ready_ flag.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ resizeGL()

void FloatingEnergySphereWidget::resizeGL ( int w,
int h )
overrideprotected

Handles resizing of the OpenGL viewport and updates the projection matrix. Calculates the field of view dynamically to keep the sphere's clear size consistent.

Parameters
wThe new width.
hThe new height.

◆ SetClosable()

void FloatingEnergySphereWidget::SetClosable ( bool closable)

Sets whether the widget can be closed by the user or programmatically. Used to prevent closing during the destruction animation.

Parameters
closableTrue to allow closing, false to prevent it.
Here is the caller graph for this function:

◆ SetupAudio()

void FloatingEnergySphereWidget::SetupAudio ( )
private

Initializes audio components (QMediaPlayer, QAudioDecoder), connects signals, selects the appropriate audio file based on is_first_time_, and starts playback/decoding.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetupShaders()

void FloatingEnergySphereWidget::SetupShaders ( )
private

Compiles and links the vertex and fragment shaders into shader_program_.

Here is the caller graph for this function:

◆ SetupSphereGeometry()

void FloatingEnergySphereWidget::SetupSphereGeometry ( int rings,
int sectors )
private

Creates the vertex data (positions) for the sphere geometry using rings and sectors. Populates the vertices_ vector.

Parameters
ringsNumber of horizontal rings.
sectorsNumber of vertical sectors.
Here is the caller graph for this function:

◆ SimulateClick

void FloatingEnergySphereWidget::SimulateClick ( )
privateslot

Slot called periodically by click_simulation_timer_ to trigger random impacts on the sphere.

Here is the call graph for this function:

◆ StartDestructionSequence

void FloatingEnergySphereWidget::StartDestructionSequence ( )
privateslot

Initiates the destruction animation sequence. Sets the is_destroying_ flag, resets progress, plays the destruction sound, and prevents the widget from being closed prematurely.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ TriggerImpactAtScreenPos()

void FloatingEnergySphereWidget::TriggerImpactAtScreenPos ( const QPoint & screen_position)
private

Triggers a visual impact effect at a point on the sphere corresponding to a screen position. Performs ray casting from the screen position to find the intersection point on the sphere and activates an ImpactInfo entry.

Parameters
screen_positionThe position on the widget where the impact should originate.
Here is the caller graph for this function:

◆ UpdateAnimation

void FloatingEnergySphereWidget::UpdateAnimation ( )
privateslot

Slot called periodically by timer_ to update animation state. Advances time, updates audio amplitude interpolation, handles rotation/inertia, updates destruction progress if active, and schedules a repaint.

◆ wheelEvent()

void FloatingEnergySphereWidget::wheelEvent ( QWheelEvent * event)
overrideprotected

Handles mouse wheel events. Zooms the camera in or out by adjusting camera_distance_.

Parameters
eventThe wheel event.

◆ widgetClosed

void FloatingEnergySphereWidget::widgetClosed ( )
signal

Emitted when the widget is closed normally (not during destruction).

Here is the caller graph for this function:

Member Data Documentation

◆ angular_velocity_

QVector3D FloatingEnergySphereWidget::angular_velocity_
private

Current angular velocity used for inertial rotation.

◆ audio_amplitudes_

std::vector<float> FloatingEnergySphereWidget::audio_amplitudes_
private

Stores calculated RMS amplitude values for each decoded audio buffer.

◆ audio_buffer_duration_ms_

qint64 FloatingEnergySphereWidget::audio_buffer_duration_ms_
private

Duration of a single audio buffer processed by the decoder, in milliseconds.

◆ audio_decoder_

QAudioDecoder* FloatingEnergySphereWidget::audio_decoder_
private

Decoder for extracting audio data from files for amplitude analysis.

◆ audio_format_

QAudioFormat FloatingEnergySphereWidget::audio_format_
private

Format of the decoded audio data (sample rate, channels, etc.).

◆ audio_ready_

bool FloatingEnergySphereWidget::audio_ready_
private

Flag indicating if audio data has been successfully decoded and is ready for visualization.

◆ camera_distance_

float FloatingEnergySphereWidget::camera_distance_
private

Distance from the camera to the origin (center of the sphere). Used for zooming.

◆ camera_position_

QVector3D FloatingEnergySphereWidget::camera_position_
private

Position of the camera in world space.

◆ click_simulation_timer_

QTimer* FloatingEnergySphereWidget::click_simulation_timer_
private

Timer triggering simulated random clicks/impacts on the sphere.

◆ closable_

bool FloatingEnergySphereWidget::closable_
private

Flag indicating if the widget can be closed.

◆ current_audio_amplitude_

float FloatingEnergySphereWidget::current_audio_amplitude_
private

Current audio amplitude value used for rendering (smoothed).

◆ damping_factor_

float FloatingEnergySphereWidget::damping_factor_
private

Damping factor applied to angular velocity for inertia decay.

◆ destruction_progress_

float FloatingEnergySphereWidget::destruction_progress_
private

Progress of the destruction animation (0.0 to 1.0).

◆ elapsed_timer_

QElapsedTimer FloatingEnergySphereWidget::elapsed_timer_
private

Timer used for calculating delta time between animation frames.

◆ hint_timer_

QTimer* FloatingEnergySphereWidget::hint_timer_
private

Timer triggering the Konami code audio hints after inactivity.

◆ impacts_

std::vector<ImpactInfo> FloatingEnergySphereWidget::impacts_
private

Stores information about active impact effects.

◆ is_destroying_

bool FloatingEnergySphereWidget::is_destroying_
private

Flag indicating if the destruction animation is currently active.

◆ is_first_time_

bool FloatingEnergySphereWidget::is_first_time_
private

Flag indicating if this is the first time the widget/app is run (affects initial audio).

◆ key_sequence_

std::deque<int> FloatingEnergySphereWidget::key_sequence_
private

Stores the sequence of recently pressed keys for Konami code detection.

◆ kGoodbyeSoundFilename

const QString FloatingEnergySphereWidget::kGoodbyeSoundFilename = "goodbye.wav"
private

Filename of the audio played during the destruction sequence.

◆ konami_code_

const std::vector<int> FloatingEnergySphereWidget::konami_code_
private

The target key sequence for the Konami code.

◆ last_frame_time_secs_

float FloatingEnergySphereWidget::last_frame_time_secs_
private

Timestamp of the last animation frame in seconds.

◆ last_mouse_position_

QPoint FloatingEnergySphereWidget::last_mouse_position_
private

Stores the last mouse position during dragging for rotation calculation.

◆ media_player_

QMediaPlayer* FloatingEnergySphereWidget::media_player_
private

Media player for playing audio files (initial sound, hint, destruction).

◆ model_matrix_

QMatrix4x4 FloatingEnergySphereWidget::model_matrix_
private

Model matrix transforming model space to world space (includes rotation).

◆ mouse_pressed_

bool FloatingEnergySphereWidget::mouse_pressed_
private

Flag indicating if the left mouse button is currently pressed.

◆ next_impact_index_

int FloatingEnergySphereWidget::next_impact_index_
private

Index of the next slot to use in the impacts_ vector (circular).

◆ projection_matrix_

QMatrix4x4 FloatingEnergySphereWidget::projection_matrix_
private

Projection matrix transforming view space to clip space.

◆ rotation_

QQuaternion FloatingEnergySphereWidget::rotation_
private

Current rotation of the sphere as a quaternion.

◆ shader_program_

QOpenGLShaderProgram* FloatingEnergySphereWidget::shader_program_
private

The compiled and linked OpenGL shader program.

◆ target_audio_amplitude_

float FloatingEnergySphereWidget::target_audio_amplitude_ {}
private

Target audio amplitude based on the currently playing audio buffer.

◆ time_value_

float FloatingEnergySphereWidget::time_value_
private

Time value passed to shaders, incremented in UpdateAnimation.

◆ timer_

QTimer FloatingEnergySphereWidget::timer_
private

Timer driving the main animation loop (UpdateAnimation).

◆ vao_

QOpenGLVertexArrayObject FloatingEnergySphereWidget::vao_
private

OpenGL Vertex Array Object managing vertex buffer state.

◆ vbo_

QOpenGLBuffer FloatingEnergySphereWidget::vbo_
private

OpenGL Vertex Buffer Object storing sphere vertex data.

◆ vertex_count_

int FloatingEnergySphereWidget::vertex_count_
private

Total number of vertices in the sphere geometry.

◆ vertices_

std::vector<GLfloat> FloatingEnergySphereWidget::vertices_
private

Raw vertex data (positions) for the sphere points.

◆ view_matrix_

QMatrix4x4 FloatingEnergySphereWidget::view_matrix_
private

View matrix transforming world space to view space.


The documentation for this class was generated from the following files: