mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-15 05:40:01 -05:00
Enable use of variables in duration selections
This commit is contained in:
@@ -7,24 +7,71 @@
|
||||
#include <iomanip>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
Duration::Duration(double initialValueInSeconds)
|
||||
: seconds(initialValueInSeconds)
|
||||
Duration::Duration(double initialValueInSeconds) : _value(initialValueInSeconds)
|
||||
{
|
||||
}
|
||||
|
||||
void Duration::Save(obs_data_t *obj, const char *secondsName,
|
||||
const char *unitName) const
|
||||
void Duration::Save(obs_data_t *obj, const char *name) const
|
||||
{
|
||||
obs_data_set_double(obj, secondsName, seconds);
|
||||
obs_data_set_int(obj, unitName, static_cast<int>(displayUnit));
|
||||
auto data = obs_data_create();
|
||||
_value.Save(data, "value");
|
||||
obs_data_set_int(data, "unit", static_cast<int>(_unit));
|
||||
obs_data_set_int(data, "version", 1);
|
||||
obs_data_set_obj(obj, name, data);
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void Duration::Load(obs_data_t *obj, const char *secondsName,
|
||||
const char *unitName)
|
||||
static int durationUnitToMultiplier(Duration::Unit u)
|
||||
{
|
||||
seconds = obs_data_get_double(obj, secondsName);
|
||||
displayUnit =
|
||||
static_cast<DurationUnit>(obs_data_get_int(obj, unitName));
|
||||
switch (u) {
|
||||
case Duration::Unit::SECONDS:
|
||||
return 1;
|
||||
case Duration::Unit::MINUTES:
|
||||
return 60;
|
||||
case Duration::Unit::HOURS:
|
||||
return 3600;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Duration::Load(obs_data_t *obj, const char *name)
|
||||
{
|
||||
auto data = obs_data_get_obj(obj, name);
|
||||
|
||||
// TODO: remove this fallback
|
||||
if (!data || !obs_data_has_user_value(data, "version") ||
|
||||
obs_data_get_int(data, "version") != 1) {
|
||||
bool usingDefaultArgs = strcmp("duration", name) == 0;
|
||||
if (usingDefaultArgs) {
|
||||
_value = obs_data_get_double(obj, "seconds");
|
||||
}
|
||||
if (_value.GetValue() == 0.0) {
|
||||
_value = obs_data_get_double(obj, name);
|
||||
}
|
||||
|
||||
if (usingDefaultArgs) {
|
||||
_unit = static_cast<Duration::Unit>(
|
||||
obs_data_get_int(obj, "displayUnit"));
|
||||
} else if (_value.GetValue() >= 86400) {
|
||||
_unit = (_value.GetValue() / 60 >= 86400)
|
||||
? Duration::Unit::HOURS
|
||||
: Duration::Unit::MINUTES;
|
||||
} else {
|
||||
_unit = Duration::Unit::SECONDS;
|
||||
}
|
||||
|
||||
_value = _value / durationUnitToMultiplier(_unit);
|
||||
|
||||
obs_data_release(data);
|
||||
return;
|
||||
}
|
||||
|
||||
_value.Load(data, "value");
|
||||
_unit = static_cast<Duration::Unit>(obs_data_get_int(data, "unit"));
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
bool Duration::DurationReached()
|
||||
@@ -35,7 +82,7 @@ bool Duration::DurationReached()
|
||||
|
||||
auto runTime = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::high_resolution_clock::now() - _startTime);
|
||||
return runTime.count() >= seconds * 1000;
|
||||
return runTime.count() >= Milliseconds();
|
||||
}
|
||||
|
||||
bool Duration::IsReset() const
|
||||
@@ -43,23 +90,33 @@ bool Duration::IsReset() const
|
||||
return _startTime.time_since_epoch().count() == 0;
|
||||
}
|
||||
|
||||
double Duration::Seconds() const
|
||||
{
|
||||
return _value.GetValue() * durationUnitToMultiplier(_unit);
|
||||
}
|
||||
|
||||
double Duration::Milliseconds() const
|
||||
{
|
||||
return Seconds() * 1000.0;
|
||||
}
|
||||
|
||||
double Duration::TimeRemaining() const
|
||||
{
|
||||
if (IsReset()) {
|
||||
return seconds;
|
||||
return Seconds();
|
||||
}
|
||||
auto runTime = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::high_resolution_clock::now() - _startTime);
|
||||
|
||||
if (runTime.count() >= seconds * 1000) {
|
||||
if (runTime.count() >= Milliseconds()) {
|
||||
return 0;
|
||||
}
|
||||
return (seconds * 1000 - runTime.count()) / 1000.;
|
||||
return (Milliseconds() - runTime.count()) / 1000.0;
|
||||
}
|
||||
|
||||
void Duration::SetTimeRemaining(double remaining)
|
||||
{
|
||||
long long msPassed = (seconds - remaining) * 1000;
|
||||
long long msPassed = (Seconds() - remaining) * 1000;
|
||||
_startTime = std::chrono::high_resolution_clock::now() -
|
||||
std::chrono::milliseconds(msPassed);
|
||||
}
|
||||
@@ -69,30 +126,14 @@ void Duration::Reset()
|
||||
_startTime = {};
|
||||
}
|
||||
|
||||
int durationUnitToMultiplier(DurationUnit u)
|
||||
static std::string durationUnitToString(Duration::Unit u)
|
||||
{
|
||||
switch (u) {
|
||||
case DurationUnit::SECONDS:
|
||||
return 1;
|
||||
case DurationUnit::MINUTES:
|
||||
return 60;
|
||||
case DurationUnit::HOURS:
|
||||
return 3600;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string durationUnitToString(DurationUnit u)
|
||||
{
|
||||
switch (u) {
|
||||
case DurationUnit::SECONDS:
|
||||
case Duration::Unit::SECONDS:
|
||||
return obs_module_text("AdvSceneSwitcher.unit.secends");
|
||||
case DurationUnit::MINUTES:
|
||||
case Duration::Unit::MINUTES:
|
||||
return obs_module_text("AdvSceneSwitcher.unit.minutes");
|
||||
case DurationUnit::HOURS:
|
||||
case Duration::Unit::HOURS:
|
||||
return obs_module_text("AdvSceneSwitcher.unit.hours");
|
||||
default:
|
||||
break;
|
||||
@@ -104,12 +145,22 @@ std::string durationUnitToString(DurationUnit u)
|
||||
std::string Duration::ToString() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << std::fixed << std::setprecision(2)
|
||||
<< seconds / durationUnitToMultiplier(displayUnit) << " "
|
||||
<< durationUnitToString(displayUnit);
|
||||
ss << std::fixed << std::setprecision(2) << _value.GetValue() << " "
|
||||
<< durationUnitToString(_unit);
|
||||
if (!_value.IsFixedType()) {
|
||||
ss << " [" << GetWeakVariableName(_value.GetVariable()) << "]";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void Duration::SetUnit(Unit u)
|
||||
{
|
||||
double prevMultiplier = durationUnitToMultiplier(_unit);
|
||||
double newMultiplier = durationUnitToMultiplier(u);
|
||||
_unit = u;
|
||||
_value = _value * (prevMultiplier / newMultiplier);
|
||||
}
|
||||
|
||||
static void populateUnits(QComboBox *list)
|
||||
{
|
||||
list->addItem(obs_module_text("AdvSceneSwitcher.unit.secends"));
|
||||
@@ -120,9 +171,8 @@ static void populateUnits(QComboBox *list)
|
||||
DurationSelection::DurationSelection(QWidget *parent, bool showUnitSelection,
|
||||
double minValue)
|
||||
: QWidget(parent),
|
||||
_duration(new QDoubleSpinBox(parent)),
|
||||
_unitSelection(new QComboBox()),
|
||||
_unitMultiplier(1)
|
||||
_duration(new VariableDoubleSpinBox(parent)),
|
||||
_unitSelection(new QComboBox())
|
||||
{
|
||||
_duration->setMinimum(minValue);
|
||||
_duration->setMaximum(86400); // 24 hours
|
||||
@@ -130,8 +180,11 @@ DurationSelection::DurationSelection(QWidget *parent, bool showUnitSelection,
|
||||
|
||||
populateUnits(_unitSelection);
|
||||
|
||||
QWidget::connect(_duration, SIGNAL(valueChanged(double)), this,
|
||||
SLOT(_DurationChanged(double)));
|
||||
QWidget::connect(
|
||||
_duration,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<double> &)),
|
||||
this, SLOT(_DurationChanged(const NumberVariable<double> &)));
|
||||
|
||||
QWidget::connect(_unitSelection, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(_UnitChanged(int)));
|
||||
|
||||
@@ -145,34 +198,28 @@ DurationSelection::DurationSelection(QWidget *parent, bool showUnitSelection,
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void DurationSelection::SetValue(double value)
|
||||
void DurationSelection::SetDuration(const Duration &d)
|
||||
{
|
||||
_duration->setValue(value / _unitMultiplier);
|
||||
_current = d;
|
||||
_duration->SetValue(d._value);
|
||||
const QSignalBlocker b(_unitSelection);
|
||||
_unitSelection->setCurrentIndex(static_cast<int>(d._unit));
|
||||
}
|
||||
|
||||
void DurationSelection::SetUnit(DurationUnit u)
|
||||
void DurationSelection::_DurationChanged(const NumberVariable<double> &value)
|
||||
{
|
||||
_unitSelection->setCurrentIndex(static_cast<int>(u));
|
||||
}
|
||||
|
||||
void DurationSelection::SetDuration(Duration d)
|
||||
{
|
||||
SetUnit(d.displayUnit);
|
||||
SetValue(d.seconds);
|
||||
}
|
||||
|
||||
void DurationSelection::_DurationChanged(double value)
|
||||
{
|
||||
emit DurationChanged(value * _unitMultiplier);
|
||||
_current._value = value;
|
||||
emit DurationChanged(_current);
|
||||
}
|
||||
|
||||
void DurationSelection::_UnitChanged(int idx)
|
||||
{
|
||||
DurationUnit unit = static_cast<DurationUnit>(idx);
|
||||
double prevMultiplier = _unitMultiplier;
|
||||
_unitMultiplier = durationUnitToMultiplier(unit);
|
||||
_duration->setValue(_duration->value() *
|
||||
(prevMultiplier / _unitMultiplier));
|
||||
|
||||
emit UnitChanged(unit);
|
||||
Duration::Unit unit = static_cast<Duration::Unit>(idx);
|
||||
double prevMultiplier = durationUnitToMultiplier(_current._unit);
|
||||
double newMultiplier = durationUnitToMultiplier(unit);
|
||||
_current._unit = unit;
|
||||
const QSignalBlocker b(_duration);
|
||||
_duration->SetFixedValue(_duration->Value() *
|
||||
(prevMultiplier / newMultiplier));
|
||||
emit DurationChanged(_current);
|
||||
}
|
||||
|
||||
@@ -1,41 +1,44 @@
|
||||
#pragma once
|
||||
#include "variable-spinbox.hpp"
|
||||
#include "obs-data.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QComboBox>
|
||||
#include <QPushButton>
|
||||
#include <chrono>
|
||||
|
||||
#include "obs-data.h"
|
||||
|
||||
enum class DurationUnit {
|
||||
SECONDS,
|
||||
MINUTES,
|
||||
HOURS,
|
||||
};
|
||||
|
||||
class Duration {
|
||||
public:
|
||||
Duration() = default;
|
||||
Duration(double initialValueInSeconds);
|
||||
|
||||
void Save(obs_data_t *obj, const char *secondsName = "seconds",
|
||||
const char *unitName = "displayUnit") const;
|
||||
void Load(obs_data_t *obj, const char *secondsName = "seconds",
|
||||
const char *unitName = "displayUnit");
|
||||
void Save(obs_data_t *obj, const char *name = "duration") const;
|
||||
void Load(obs_data_t *obj, const char *name = "duration");
|
||||
|
||||
bool DurationReached();
|
||||
bool IsReset() const;
|
||||
double Seconds() const;
|
||||
double Milliseconds() const;
|
||||
double TimeRemaining() const;
|
||||
void SetTimeRemaining(double);
|
||||
void Reset();
|
||||
std::string ToString() const;
|
||||
|
||||
double seconds = 0.;
|
||||
// only used for UI
|
||||
DurationUnit displayUnit = DurationUnit::SECONDS;
|
||||
enum class Unit {
|
||||
SECONDS,
|
||||
MINUTES,
|
||||
HOURS,
|
||||
};
|
||||
Unit GetUnit() const { return _unit; }
|
||||
void SetUnit(Unit u);
|
||||
|
||||
private:
|
||||
NumberVariable<double> _value = 0.;
|
||||
Unit _unit = Unit::SECONDS;
|
||||
std::chrono::high_resolution_clock::time_point _startTime;
|
||||
|
||||
friend class DurationSelection;
|
||||
};
|
||||
|
||||
class DurationSelection : public QWidget {
|
||||
@@ -43,21 +46,18 @@ class DurationSelection : public QWidget {
|
||||
public:
|
||||
DurationSelection(QWidget *parent = nullptr,
|
||||
bool showUnitSelection = true, double minValue = 0.0);
|
||||
void SetValue(double value);
|
||||
void SetUnit(DurationUnit u);
|
||||
void SetDuration(Duration d);
|
||||
QDoubleSpinBox *SpinBox() { return _duration; }
|
||||
void SetDuration(const Duration &);
|
||||
QDoubleSpinBox *SpinBox() { return _duration->SpinBox(); }
|
||||
|
||||
private slots:
|
||||
void _DurationChanged(double value);
|
||||
void _DurationChanged(const NumberVariable<double> &value);
|
||||
void _UnitChanged(int idx);
|
||||
signals:
|
||||
void DurationChanged(double value); // always reutrn value in seconds
|
||||
void UnitChanged(DurationUnit u);
|
||||
void DurationChanged(const Duration &value);
|
||||
|
||||
private:
|
||||
QDoubleSpinBox *_duration;
|
||||
VariableDoubleSpinBox *_duration;
|
||||
QComboBox *_unitSelection;
|
||||
|
||||
double _unitMultiplier;
|
||||
Duration _current;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user