Crafter.Graphics/implementations/Crafter.Graphics-Window.cpp

137 lines
6.7 KiB
C++
Raw Normal View History

2025-11-25 02:21:06 +01:00
/*
Crafter®.Graphics
Copyright (C) 2025 Catcrafts®
catcrafts.net
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 3.0 as published by the Free Software Foundation;
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
module Crafter.Graphics:Window_impl;
import :Window;
2025-11-25 20:30:54 +01:00
import :Transform;
2025-11-25 02:21:06 +01:00
import std;
using namespace Crafter;
2025-11-26 18:48:58 +01:00
Window::Window(std::int_fast32_t width, std::int_fast32_t height) : width(width), height(height) {
2025-11-25 02:21:06 +01:00
2025-11-25 18:52:32 +01:00
}
void Window::ScaleElement(Transform& element) {
element.scaled.width = MappedToPixel(element.relativeWidth, width);
element.scaled.height = MappedToPixel(element.relativeHeight, height);
element.scaled.x = MappedToPixel(element.anchorX, width) - MappedToPixel(element.anchorOffsetX, element.scaled.width);
element.scaled.y = MappedToPixel(element.anchorY, height) - MappedToPixel(element.anchorOffsetY, element.scaled.height);
}
void Window::ScaleElement(Transform& element, Transform& parent) {
element.scaled.width = MappedToPixel(element.relativeWidth, parent.scaled.width);
element.scaled.height = MappedToPixel(element.relativeHeight, parent.scaled.height);
element.scaled.x = MappedToPixel(element.anchorX, parent.scaled.width) - MappedToPixel(element.anchorOffsetX, element.scaled.width) + parent.scaled.x;
element.scaled.y = MappedToPixel(element.anchorY, parent.scaled.height) - MappedToPixel(element.anchorOffsetY, element.scaled.height) + parent.scaled.y;
}
void Window::ScaleMouse(Transform& element, Transform& parent) {
std::int_fast32_t boundlessWidth = PixelToMappedBoundless(parent.scaled.width, width);
std::int_fast32_t boundlessHeight = PixelToMappedBoundless(parent.scaled.height, height);
element.scaled.width = BoundToBoundless(MappedToPixel(element.relativeWidth, PixelToMapped(parent.scaled.width, width)));
element.scaled.height = BoundToBoundless(MappedToPixel(element.relativeHeight, PixelToMapped(parent.scaled.height, height)));
element.scaled.x = MappedToPixelBoundless(element.anchorX, boundlessWidth) - MappedToPixelBoundless(element.anchorOffsetX, element.scaled.width) + PixelToMappedBoundless(parent.scaled.x, width);
element.scaled.y = MappedToPixelBoundless(element.anchorY, boundlessHeight) - MappedToPixelBoundless(element.anchorOffsetY, element.scaled.height) + PixelToMappedBoundless(parent.scaled.y, height);
}
2025-11-25 19:43:40 +01:00
void Window::ScaleMouse(Transform& element) {
// std::int_fast32_t boundlessWidth = PixelToMappedBoundless(parent.scaled.width, width);
// std::int_fast32_t boundlessHeight = PixelToMappedBoundless(parent.scaled.height, height);
// element.scaled.width = BoundToBoundless(MappedToPixel(element.relativeWidth, width));
// element.scaled.height = BoundToBoundless(MappedToPixel(element.relativeHeight, height));
// element.scaled.x = MappedToPixelBoundless(element.anchorX, boundlessWidth) - MappedToPixelBoundless(element.anchorOffsetX, element.scaled.width) + PixelToMappedBoundless(parent.scaled.x, width);
// element.scaled.y = MappedToPixelBoundless(element.anchorY, boundlessHeight) - MappedToPixelBoundless(element.anchorOffsetY, element.scaled.height) + PixelToMappedBoundless(parent.scaled.y, height);
}
2025-11-25 23:29:48 +01:00
#ifdef CRAFTER_TIMING
void Window::LogTiming() {
std::cout << std::format("Update: {}", duration_cast<std::chrono::milliseconds>(totalUpdate)) << std::endl;
for (const std::pair<const EventListener<FrameTime>*, std::chrono::nanoseconds>& entry : updateTimings) {
std::cout << std::format("\t{} {}", reinterpret_cast<const void*>(entry.first), duration_cast<std::chrono::microseconds>(entry.second)) << std::endl;
}
std::cout << std::format("Render: {}", duration_cast<std::chrono::milliseconds>(totalRender)) << std::endl;
for (const std::tuple<const RenderingElement*, std::uint_fast32_t, std::uint_fast32_t, std::chrono::nanoseconds>& entry : renderTimings) {
std::cout << std::format("\t{} {}x{} {}", reinterpret_cast<const void*>(std::get<0>(entry)), std::get<1>(entry), std::get<2>(entry), duration_cast<std::chrono::microseconds>(std::get<3>(entry))) << std::endl;
}
2025-11-25 23:36:43 +01:00
std::cout << std::format("Total: {}", duration_cast<std::chrono::milliseconds>(totalUpdate+totalRender)) << std::endl;
2025-11-25 23:29:48 +01:00
std::cout << std::format("Vblank: {}", duration_cast<std::chrono::milliseconds>(vblank)) << std::endl;
2025-11-25 23:36:43 +01:00
// Add 100-frame average and min-max timing info
if (!frameTimes.empty()) {
// Calculate average
std::chrono::nanoseconds sum(0);
for (const auto& frameTime : frameTimes) {
sum += frameTime;
}
auto average = sum / frameTimes.size();
// Find min and max
auto min = frameTimes.front();
auto max = frameTimes.front();
for (const auto& frameTime : frameTimes) {
if (frameTime < min) min = frameTime;
if (frameTime > max) max = frameTime;
}
std::cout << std::format("Last 100 Frame Times - Avg: {}, Min: {}, Max: {}",
duration_cast<std::chrono::milliseconds>(average),
duration_cast<std::chrono::milliseconds>(min),
duration_cast<std::chrono::milliseconds>(max)) << std::endl;
}
2025-11-25 23:29:48 +01:00
}
2025-11-26 18:48:58 +01:00
#endif
2025-11-26 20:15:25 +01:00
void Window::AddDirtyRect(ScaleData scale) {
ClipRect rect {
.left = std::max(scale.x, std::int_fast32_t(0)),
.right = std::min(scale.x + scale.width, width),
.top = std::max(scale.y, std::int_fast32_t(0)),
.bottom = std::min(scale.y + scale.height, height),
};
2025-11-26 18:48:58 +01:00
2025-11-26 20:15:25 +01:00
if (rect.left >= rect.right || rect.top >= rect.bottom) {
return;
}
2025-11-26 23:36:08 +01:00
for(ClipRect existing : dirtyRects) {
//fully enclosed
if(rect.left >= existing.left && rect.right <= existing.right && rect.top >= existing.top && rect.bottom <= existing.bottom) {
return;
}
//horizontal line
if(rect.top == existing.top && rect.bottom == existing.bottom) {
existing.left = std::min(rect.left, existing.left);
existing.right = std::max(rect.right, existing.right);
return;
}
//vertical line
if(rect.left == existing.left && rect.right == existing.right) {
existing.top = std::min(rect.top, existing.top);
existing.bottom = std::max(rect.bottom, existing.bottom);
return;
}
}
//no overlap
2025-11-26 20:15:25 +01:00
dirtyRects.push_back(rect);
2025-11-26 18:48:58 +01:00
}