32 std::array<uint32_t, 4> result;
38 }
else if (len == 1) {
41 throw CommandException(
"Expected either 1 or 4 values.");
48 if (propName ==
"-rgba") {
49 std::array<uint32_t, 4> newRGBA = get4(interp, value);
51 }
else if (propName ==
"-rgb") {
52 std::array<uint32_t, 4> newRGB = get4(interp, value);
53 std::array<uint32_t, 4> newRGBA;
55 newRGBA[i] = (rgba[i] & 0x000000ff) |
56 ((newRGB[i] << 8) & 0xffffff00);
59 }
else if (propName ==
"-alpha") {
60 std::array<uint32_t, 4> newAlpha = get4(interp, value);
61 std::array<uint32_t, 4> newRGBA;
63 newRGBA[i] = (rgba[i] & 0xffffff00) |
64 (newAlpha[i] & 0x000000ff);
67 }
else if (propName ==
"-fadePeriod") {
68 updateCurrentFadeValue();
70 }
else if (propName ==
"-fadeTarget") {
71 updateCurrentFadeValue();
73 }
else if (propName ==
"-fadeCurrent") {
76 }
else if (propName ==
"-scrollSpeed") {
79 }
else if (propName ==
"-scrollPauseLeft") {
81 }
else if (propName ==
"-scrollPauseRight") {
83 }
else if (propName ==
"-query-size") {
90void OSDImageBasedWidget::setRGBA(std::span<const uint32_t, 4> newRGBA)
99static void set4(std::span<const uint32_t, 4> rgba, uint32_t mask,
unsigned shift, TclObject& result)
102 result = (rgba[0] & mask) >> shift;
105 return int((rgba[i] & mask) >> shift);
111 if (propName ==
"-rgba") {
112 set4(rgba, 0xffffffff, 0, result);
113 }
else if (propName ==
"-rgb") {
114 set4(rgba, 0xffffff00, 8, result);
115 }
else if (propName ==
"-alpha") {
116 set4(rgba, 0x000000ff, 0, result);
117 }
else if (propName ==
"-fadePeriod") {
119 }
else if (propName ==
"-fadeTarget") {
121 }
else if (propName ==
"-fadeCurrent") {
122 result = getCurrentFadeValue();
123 }
else if (propName ==
"-scrollSpeed") {
124 result = scrollSpeed;
125 }
else if (propName ==
"-scrollPauseLeft") {
126 result = scrollPauseLeft;
127 }
else if (propName ==
"-scrollPauseRight") {
128 result = scrollPauseRight;
129 }
else if (propName ==
"-query-size") {
137std::optional<float> OSDImageBasedWidget::getScrollWidth()
const
139 if (scrollSpeed == 0.0f)
return {};
142 if (!parentImage)
return {};
145 if (!output)
return {};
147 vec2 parentPos, parentSize;
148 parentImage->getBoundingBox(*output, parentPos, parentSize);
149 auto parentWidth = parentSize[0] / narrow<float>(
getScaleFactor(*output));
152 auto scrollWidth = thisWidth - parentWidth;
153 if (scrollWidth <= 0.0f)
return {};
158bool OSDImageBasedWidget::isAnimating()
const
160 return static_cast<bool>(getScrollWidth());
163[[nodiscard]]
static float smootherStep(
float x)
167 return ((6.0f * x - 15.0f) * x + 10.0f) * x * x * x;
175 auto width = getScrollWidth();
176 if (!width)
return result;
178 auto scrollTime = *width / scrollSpeed;
179 auto animationTime = 2.0f * scrollTime + scrollPauseLeft + scrollPauseRight;
182 auto now = narrow_cast<float>(
Timer::getTime() - startScrollTime) / 1'000'000.0f;
183 auto t = fmodf(now, animationTime);
186 float relOffsetX = [&]{
187 if (
t < scrollPauseLeft) {
190 }
else if (
t < (scrollPauseLeft + scrollTime)) {
192 return smootherStep((
t - scrollPauseLeft) / scrollTime);
193 }
else if (
t < (scrollPauseLeft + scrollTime + scrollPauseRight)) {
198 return smootherStep(1.0f - ((
t - scrollPauseLeft - scrollTime - scrollPauseRight) / scrollTime));
201 result[0] -= *width * relOffsetX;
220bool OSDImageBasedWidget::isFading()
const
222 return (startFadeValue != fadeTarget) && (fadePeriod != 0.0f);
227 if (isFading())
return true;
231float OSDImageBasedWidget::getCurrentFadeValue()
const
234 return startFadeValue;
239float OSDImageBasedWidget::getCurrentFadeValue(uint64_t now)
const
241 assert(now >= startFadeTime);
243 auto diff = narrow<int>(now - startFadeTime);
244 assert(fadePeriod != 0.0f);
245 float delta = narrow_cast<float>(diff) / (1000000.0f * fadePeriod);
246 if (startFadeValue < fadeTarget) {
247 float tmp = startFadeValue + delta;
248 if (tmp >= fadeTarget) {
249 startFadeValue = fadeTarget;
250 return startFadeValue;
254 float tmp = startFadeValue - delta;
255 if (tmp <= fadeTarget) {
256 startFadeValue = fadeTarget;
257 return startFadeValue;
263void OSDImageBasedWidget::updateCurrentFadeValue()
267 startFadeValue = getCurrentFadeValue(now);
302 paint(output,
false);
330 "Can't query size: no window visible");
335 vec2 imageSize = [&] {
349void OSDImageBasedWidget::paint(
OutputSurface& output,
bool openGL)
354 assert(openGL ==
getDisplay().getOSDGUI().isOpenGL()); (void)openGL;
358 if ((fadedAlpha != 0) &&
image) {
359 ivec2 drawPos = round(getTransformedPos(output));
360 image->draw(output, drawPos, fadedAlpha);
Represents the output window/screen of openMSX.
OutputSurface * getOutputSurface()
const OSDTopWidget & getTopWidget() const
A frame buffer where pixels can be written to.
unsigned getListLength(Interpreter &interp) const
TclObject getListIndex(Interpreter &interp, unsigned index) const
float getFloat(Interpreter &interp) const
void addListElement(const T &t)
int getInt(Interpreter &interp) const
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
constexpr vecN< N, T > clamp(const vecN< N, T > &x, const vecN< N, T > &minVal, const vecN< N, T > &maxVal)
uint64_t getTime()
Get current (real) time in us.
This file implemented 3 utility functions:
constexpr void fill(ForwardRange &&range, const T &value)
bool all_equal(InputRange &&range, Proj proj={})
auto copy(InputRange &&range, OutputIter out)
bool equal(InputRange1 &&range1, InputRange2 &&range2, Pred pred={}, Proj1 proj1={}, Proj2 proj2={})
size_t size(std::string_view utf8)
constexpr auto transform(Range &&range, UnaryOp op)
constexpr auto xrange(T e)