You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Sandbox/Plugins/EditorCommon/QPropertyTree/PropertyRowNumber.h

238 lines
8.2 KiB
C++

/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWNUMBER_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWNUMBER_H
#pragma once
#include "QPropertyTree.h"
#include "Serialization/MemoryWriter.h"
#include "Serialization/Decorators/Range.h"
#include "PropertyRowNumberField.h"
#include <limits.h>
#include <float.h>
#include <math.h>
template<class T>
string numberAsString(T value)
{
Serialization::MemoryWriter buf;
buf << value;
return buf.c_str();
}
inline long long stringToSignedInteger(const char* str)
{
long long value;
#ifdef _MSC_VER
value = _atoi64(str);
#else
char* endptr = (char*)str;
value = strtoll(str, &endptr, 10);
#endif
return value;
}
inline unsigned long long stringToUnsignedInteger(const char* str)
{
unsigned long long value;
if (*str == '-') {
value = 0;
}
else {
#ifdef _MSC_VER
char* endptr = (char*)str;
value = _strtoui64(str, &endptr, 10);
#else
char* endptr = (char*)str;
value = strtoull(str, &endptr, 10);
#endif
}
return value;
}
template<class Output, class Input>
Output clamp(Input value, Output min, Output max)
{
if (value < Input(min))
return min;
if (value > Input(max))
return max;
return Output(value);
}
template<class Out, class In> void clampToType(Out* out, In value) { *out = clamp(value, std::numeric_limits<Out>::lowest(), std::numeric_limits<Out>::max()); }
inline void clampedNumberFromString(char* value, const char* str) { clampToType(value, stringToSignedInteger(str)); }
inline void clampedNumberFromString(signed char* value, const char* str) { clampToType(value, stringToSignedInteger(str)); }
inline void clampedNumberFromString(short* value, const char* str) { clampToType(value, stringToSignedInteger(str)); }
inline void clampedNumberFromString(int* value, const char* str) { clampToType(value, stringToSignedInteger(str)); }
inline void clampedNumberFromString(long* value, const char* str) { clampToType(value, stringToSignedInteger(str)); }
inline void clampedNumberFromString(long long* value, const char* str) { clampToType(value, stringToSignedInteger(str)); }
inline void clampedNumberFromString(unsigned char* value, const char* str) { clampToType(value, stringToUnsignedInteger(str)); }
inline void clampedNumberFromString(unsigned short* value, const char* str) { clampToType(value, stringToUnsignedInteger(str)); }
inline void clampedNumberFromString(unsigned int* value, const char* str) { clampToType(value, stringToUnsignedInteger(str)); }
inline void clampedNumberFromString(unsigned long* value, const char* str) { clampToType(value, stringToUnsignedInteger(str)); }
inline void clampedNumberFromString(unsigned long long* value, const char* str) { clampToType(value, stringToUnsignedInteger(str)); }
inline void clampedNumberFromString(float* value, const char* str)
{
double v = atof(str);
if (v > FLT_MAX)
v = FLT_MAX;
if (v < -FLT_MAX)
v = -FLT_MAX;
*value = float(v);
}
inline void clampedNumberFromString(double* value, const char* str)
{
*value = atof(str);
}
template<class Type>
class PropertyRowNumber : public PropertyRowNumberField{
public:
PropertyRowNumber()
{
softMin_ = std::numeric_limits<Type>::lowest();
softMax_ = std::numeric_limits<Type>::max();
hardMin_ = std::numeric_limits<Type>::lowest();
hardMax_ = std::numeric_limits<Type>::max();
}
void setValue(Type value, const void* handle, const Serialization::TypeID& type)
{
value_ = value;
serializer_.setPointer((void*)handle);
serializer_.setType(type);
}
bool setValueFromString(const char* str) override{
Type value = value_;
clampedNumberFromString(&value_, str);
return value_ != value;
}
string valueAsString() const override
{
return numberAsString(Type(value_));
}
bool assignToPrimitive(void* object, [[maybe_unused]] size_t size) const override
{
*reinterpret_cast<Type*>(object) = value_;
return true;
}
void setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) override
{
Serialization::RangeDecorator<Type>* range = (Serialization::RangeDecorator<Type>*)ser.pointer();
serializer_.setPointer((void*)range->value);
serializer_.setType(Serialization::TypeID::get<Type>());
value_ = *range->value;
softMin_ = range->softMin;
softMax_ = range->softMax;
hardMin_ = range->hardMin;
hardMax_ = range->hardMax;
}
bool assignTo(const Serialization::SStruct& ser) const override
{
if (ser.type() == Serialization::TypeID::get<Serialization::RangeDecorator<Type>>()) {
Serialization::RangeDecorator<Type>* range = (Serialization::RangeDecorator<Type>*)ser.pointer();
*range->value = value_;
}
else if (ser.type() == Serialization::TypeID::get<Type>()) {
*(Type*)ser.pointer() = value_;
}
return true;
}
void serializeValue(Serialization::IArchive& ar)
{
ar(value_, "value", "Value");
ar(softMin_, "softMin", "SoftMin");
ar(softMax_, "softMax", "SoftMax");
ar(hardMin_, "hardMin", "HardMin");
ar(hardMax_, "hardMax", "HardMax");
}
void startIncrement() override
{
incrementStartValue_ = value_;
}
void endIncrement(QPropertyTree* tree) override
{
if (value_ != incrementStartValue_) {
Type value = value_;
value_ = incrementStartValue_;
value_ = value;
tree->model()->rowChanged(this, true);
}
}
void incrementLog(float screenFraction, float valueFieldFraction)
{
bool bothSoftLimitsSet = (std::numeric_limits<Type>::lowest() == 0 || softMin_ != std::numeric_limits<Type>::lowest()) && softMax_ != std::numeric_limits<Type>::max();
if (bothSoftLimitsSet)
{
Type softRange = softMax_ - softMin_;
double newValue = incrementStartValue_ + softRange * valueFieldFraction;
value_ = clamp(newValue, hardMin_, hardMax_);
}
else
{
double screenFractionMultiplier = 1000.0;
if (Serialization::TypeID::get<Type>() == Serialization::TypeID::get<float>() ||
Serialization::TypeID::get<Type>() == Serialization::TypeID::get<double>())
screenFractionMultiplier = 10.0;
double startPower = log10(fabs(double(incrementStartValue_)) + 1.0) - 3.0;
double power = startPower + fabs(screenFraction) * 10.0f;
double delta = pow(10.0, power) - pow(10.0, startPower) + screenFractionMultiplier * fabs(screenFraction);
double newValue;
if (screenFraction > 0.0f)
newValue = double(incrementStartValue_) + delta;
else
newValue = double(incrementStartValue_) - delta;
#ifdef _MSC_VER
if (_isnan(newValue)) {
#else
if (isnan(newValue)) {
#endif
if (screenFraction > 0.0f)
newValue = DBL_MAX;
else
newValue = -DBL_MAX;
}
value_ = clamp(newValue, hardMin_, hardMax_);
}
}
double sliderPosition() const override
{
if ((softMin_ == std::numeric_limits<Type>::lowest() && softMax_ == std::numeric_limits<Type>::max() && softMax_ != Type(255)) || (softMin_ >= softMax_))
return 0.0;
return clamp(double(value_ - softMin_) / (softMax_ - softMin_), 0.0, 1.0);
}
protected:
Type incrementStartValue_;
Type value_;
Type softMin_;
Type softMax_;
Type hardMin_;
Type hardMax_;
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWNUMBER_H