Skip to content

Commit

Permalink
Alternative visualization for pulse (#169)
Browse files Browse the repository at this point in the history
* Alternative visualization for pulse

* Made visualization style for pulse configurable (#102)

* Formatting

* Formatting

* Formatting

* Formatting

* Added config option to README

* [minor] Pulse filter visualizer extensions:

* Added functionality for visualizer component to receive non exclusive mouse input (only a few things were missing in the component manager)
* Implemented switching of visualization mode when clicked (left mouse button)

---------

Co-authored-by: rawpowerlaxity <thomas@rawpowergames.com>
  • Loading branch information
micheldebree and RawPowerLaxity authored Sep 15, 2023
1 parent 86e84a7 commit aa20727
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 35 deletions.
6 changes: 3 additions & 3 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ BraceWrapping:
AfterExternBlock: true
BeforeCatch: false
BeforeElse: true
# BeforeLambdaBody: true
BeforeLambdaBody: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
Expand All @@ -56,8 +56,8 @@ ColumnLimit: 0
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DeriveLineEnding: true
DerivePointerAlignment: false
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,14 @@ Please report issues in our [issue tracker](https://github.com/issues).
![Commits since last
release](https://img.shields.io/github/commits-since/chordian/sidfactory2/release-20221007)

- Added: [#102](https://github.com/Chordian/sidfactory2/issues/102) Visualizers for pulse width (per channel), filter cutoff and an
indication per channel if it is being filtered.
- Changed: Configuration parameter `Window.Scale` now has a range from 1.0 to 10.0, so users can blow up the screen even bigger.
Values below 1.0 were not working correctly.
- Added: [#102](https://github.com/Chordian/sidfactory2/issues/102) Visualizers
for pulse width (per channel), filter cutoff and an indication per channel if
it is being filtered.
- Added: Config option `Visualizer.PulseWidth.Style` to set the default style
for the pulse width visualizer.
- Changed: Configuration parameter `Window.Scale` now has a range from 1.0 to
10.0, so users can blow up the screen even bigger. Values below 1.0 were not
working correctly.

### Build 20221007

Expand Down
16 changes: 11 additions & 5 deletions SIDFactoryII/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// The config.ini file contains the factory default settings. You can change these if you want, but it may be overwritten
// when you download and paste the next release. This is where the user.ini file comes in handy. If you want to make sure
// that your personal settings remain sticky, copy the changed entries to the user.ini file (you may have to create the
// file first). All entries in user.ini will always override the corresponding entries in the config.ini file.
// file first). All entries in user.ini will always override the corresponding entries in the config.ini file.
//
// A genuine settings dialog box is planned for a future release of SID Factory II.
//
Expand Down Expand Up @@ -48,18 +48,18 @@ Editor.Driver.Default = "sf2driver11_04_01.prg" // This determin
Editor.Skip.Intro = 0 // If you set this to 1, the black intro screen with logo and credits will never be shown.
Editor.Follow.Play = 0 // If you set this to 1, follow play is on by default.
Editor.Follow.Play = 0 // If you set this to 1, follow play is on by default.
Editor.Sequence.Highlights = 0 // If you set this to 1, sequence highlights are on by default.
Editor.Sequence.Highlights = 0 // If you set this to 1, sequence highlights are on by default.
Editor.Confirm.QuickSave = 1 // If you set this to 1, a confirmation dialog pops up when quick saving
// If set to 0, the quick save is performed without asking for confirmation
//
// PLAYBACK OPTIONS
//
Playback.StopEmulationIfDriverStops = 1 // If the driver stops (at the end of a jingle, for instance), setting this value to non-zero
Playback.StopEmulationIfDriverStops = 1 // If the driver stops (at the end of a jingle, for instance), setting this value to non-zero
// will stop the emulation and follow play also.
// Virtual piano keyboard layout
Expand All @@ -82,6 +82,12 @@ Window.Scaling = 1.0 // Scale window contents. Pixels
Window.Scaling.Smooth = 1 // If you set this to 1, scaling will smooth pixels.
// Set to 0 will use "nearest neighbour" scaling.
//
// Visualizers
//
Visualizer.PulseWidth.Style = 0 // The way pulse width is visualized
// 0 = absolute value, 1 = alternative style
//
// OVERLAY
//
Expand Down
19 changes: 19 additions & 0 deletions SIDFactoryII/source/runtime/editor/components_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,12 @@ namespace Editor
}
}
}

// Let visualizer components consume non exclusive mouse input (if the mouse is over them)
auto* VisualComponent = GetVisualizerComponentAt(inMouse.GetPosition());

if(VisualComponent != nullptr)
VisualComponent->ConsumeNonExclusiveInput(inMouse);
}

return false;
Expand Down Expand Up @@ -635,4 +641,17 @@ namespace Editor

return nullptr;
}


VisualizerComponentBase* ComponentsManager::GetVisualizerComponentAt(const Foundation::Point& inPosition) const
{
for (auto visualizerComponent : m_VisualizerComponents)
{
if (visualizerComponent->ContainsPosition(inPosition))
return &*visualizerComponent;
}

return nullptr;
}

}
1 change: 1 addition & 0 deletions SIDFactoryII/source/runtime/editor/components_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ namespace Editor
ComponentBase* GetComponentAfter(ComponentBase* inComponent) const;
ComponentBase* GetComponentBefore(ComponentBase* inComponent) const;
ComponentBase* GetComponentAt(const Foundation::Point& inPosition) const;
VisualizerComponentBase* GetVisualizerComponentAt(const Foundation::Point& inPosition) const;

bool m_Suspended;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ namespace Editor

bool VisualizerComponentBase::ContainsPosition(const Foundation::Point& inPixelPosition) const
{
return m_Rect.Contains(inPixelPosition);
Foundation::Rect Rect = { m_DrawField->GetPosition(), m_Rect.m_Dimensions };
return Rect.Contains(inPixelPosition);
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
#include "visualizer_component_pulse_filter_state.h"

#include "foundation/graphics/drawfield.h"
#include "foundation/input/mouse.h"
#include "runtime/editor/components/component_file_selector.h"
#include "runtime/editor/datasources/datasource_sidregistersbuffer.h"
#include "runtime/execution/executionhandler.h"
#include "runtime/execution/flightrecorder.h"
#include "utils/configfile.h"
#include "utils/global.h"
#include "utils/usercolors.h"

using namespace Foundation;
using namespace Utility;
using namespace Utility::Config;

namespace Editor
{
Expand All @@ -25,6 +29,8 @@ namespace Editor
: VisualizerComponentBase(inID, inDrawField, inX, inY, inWidth, inHeight)
, m_DataSource(inDataSource)
{
ConfigFile& config_file = Global::instance().GetConfig();
m_PulseWidthStyle = GetSingleConfigurationValue<ConfigValueInt>(config_file, "Visualizer.PulseWidth.Style", 0);
}


Expand All @@ -35,6 +41,12 @@ namespace Editor

bool VisualizerComponentPulseFilterState::ConsumeNonExclusiveInput(const Foundation::Mouse& inMouse)
{
if(inMouse.IsButtonPressed(Mouse::Button::Left))
{
m_PulseWidthStyle = (m_PulseWidthStyle + 1) & 1;
return true;
}

return false;
}

Expand All @@ -50,7 +62,7 @@ namespace Editor
const Color color_bar_fill_filter = ToColor(UserColor::StateBarFillColorFilter);

m_DataSource->PullDataFromSource();

m_DrawField->DrawBox(color_background, 0, 0, m_Dimensions.m_Width, m_Dimensions.m_Height);

const int bar_width = m_Dimensions.m_Width - 4;
Expand All @@ -61,31 +73,31 @@ namespace Editor
int bar_y = 2;

const auto& data_source = *m_DataSource;

const auto get_pulse_value = [&data_source](unsigned int inChannel) -> unsigned short
{
if(inChannel > 2)
if (inChannel > 2)
return 0;

const unsigned int offset = inChannel * 7;

const unsigned short pulse_high = data_source[offset + 3] & 0x0f;
const unsigned short pulse_low = data_source[offset + 2];

const unsigned short value = (pulse_high << 8) | pulse_low;
const unsigned short value = (pulse_high << 8) | pulse_low;

return value;
};

const auto is_channel_filtered = [&data_source](unsigned int inChannel) -> bool
{
if(inChannel > 2)
if (inChannel > 2)
return false;

return (data_source[0x17] & (1 << inChannel)) != 0;
};

for(unsigned int i = 0; i < 3; ++i)
for (unsigned int i = 0; i < 3; ++i)
{
DrawBarWithCenterDivider(bar_x, bar_y, bar_width, bar_height, get_pulse_value(i), 0x0fff, is_channel_filtered(i) ? color_bar_filtered_channel : color_bar, color_bar_fill, color_background);
bar_y += bar_spacing;
Expand All @@ -97,7 +109,7 @@ namespace Editor
const unsigned short filter_low = data_source[0x15] & 7;

const unsigned short value = (filter_high << 3) | filter_low;

return value;
};

Expand All @@ -118,7 +130,7 @@ namespace Editor
{
m_DrawField->DrawBox(inBarColor, inX, inY, inWidth, inHeight);

if(inValue > 0)
if (inValue > 0)
{
float width_fraction = static_cast<float>(inValue) / static_cast<float>(inMaxValue);
int width = static_cast<int>(static_cast<float>(inWidth) * (width_fraction < 0 ? 0 : (width_fraction > 1.0f ? 1.0f : width_fraction)));
Expand All @@ -141,12 +153,22 @@ namespace Editor
{
m_DrawField->DrawBox(inBarColor, inX, inY, inWidth, inHeight);

if(inValue > 0)
if (inValue > 0)
{
float width_fraction = static_cast<float>(inValue) / static_cast<float>(inMaxValue);
int width = static_cast<int>(static_cast<float>(inWidth) * (width_fraction < 0 ? 0 : (width_fraction > 1.0f ? 1.0f : width_fraction)));

m_DrawField->DrawBox(inBarColorFill, inX, inY + 1, width, inHeight - 2);
if (m_PulseWidthStyle == 1)
{
int abs_value = inValue > 0x800 ? 0x1000 - inValue : inValue;
float width_fraction = static_cast<float>(abs_value) / static_cast<float>(inMaxValue);
int width = static_cast<int>(static_cast<float>(inWidth) * (width_fraction < 0 ? 0 : (width_fraction > 1.0f ? 1.0f : width_fraction)));
int x = inValue > 0x800 ? inX + (inWidth - width) : inX;
m_DrawField->DrawBox(inBarColorFill, x, inY + 1, width, inHeight - 2);
}
else
{
float width_fraction = static_cast<float>(inValue) / static_cast<float>(inMaxValue);
int width = static_cast<int>(static_cast<float>(inWidth) * (width_fraction < 0 ? 0 : (width_fraction > 1.0f ? 1.0f : width_fraction)));
m_DrawField->DrawBox(inBarColorFill, inX, inY + 1, width, inHeight - 2);
}
}

m_DrawField->DrawVerticalLine(inDividerColor, inX + inWidth / 2, inY, inY + inHeight);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ namespace Editor
{
public:
VisualizerComponentPulseFilterState(
int inID,
Foundation::DrawField* inDrawField,
int inX,
int inY,
int inWidth,
int inID,
Foundation::DrawField* inDrawField,
int inX,
int inY,
int inWidth,
int inHeight,
std::shared_ptr<DataSourceSIDRegistersBufferAfLastDriverUpdate> inDataSource
);
Expand Down Expand Up @@ -50,7 +50,8 @@ namespace Editor
const Foundation::Color& inBarColor,
const Foundation::Color& inBarColorFill,
const Foundation::Color& inDividerColor);

std::shared_ptr<DataSourceSIDRegistersBufferAfLastDriverUpdate> m_DataSource;
int m_PulseWidthStyle;
};
}
7 changes: 7 additions & 0 deletions dist/documentation/user.default.ini
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ Window.Scaling = 1.0 // Scale window contents. Pixels
// (or accept the glitch).
Window.Scaling.Smooth = 1 // If you set this to 1, scaling will smooth pixels.
// Set to 0 will use "nearest neighbour" scaling.

//
// Visualizers
//
Visualizer.PulseWidth.Style = 0 // The way pulse width is visualized
// 0 = absolute value, 1 = alternative style

//
// OVERLAY
//
Expand Down

0 comments on commit aa20727

Please sign in to comment.