rendering element rewrite
This commit is contained in:
parent
4c286e1fd8
commit
3d40256bde
22 changed files with 799 additions and 795 deletions
|
|
@ -26,94 +26,42 @@ import std;
|
|||
|
||||
using namespace Crafter;
|
||||
|
||||
GridElement::GridElement(std::uint_fast32_t columns, std::uint_fast32_t rows,
|
||||
std::int_fast32_t spacingX, std::int_fast32_t spacingY,
|
||||
std::int_fast32_t anchorX, std::int_fast32_t anchorY,
|
||||
std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight,
|
||||
std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY,
|
||||
std::int_fast32_t z)
|
||||
: Transform(anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z),
|
||||
columns(columns), rows(rows), spacingX(spacingX), spacingY(spacingY) {
|
||||
GridElement::GridElement(std::uint_fast32_t columns, std::uint_fast32_t rows, std::int_fast32_t spacingX, std::int_fast32_t spacingY, Anchor anchor) : Transform(anchor), columns(columns), rows(rows), spacingX(spacingX), spacingY(spacingY) {
|
||||
|
||||
}
|
||||
|
||||
void GridElement::SetGridSize(std::uint_fast32_t columns, std::uint_fast32_t rows) {
|
||||
this->columns = columns;
|
||||
this->rows = rows;
|
||||
}
|
||||
|
||||
void GridElement::SetSpacing(std::int_fast32_t spacingX, std::int_fast32_t spacingY) {
|
||||
this->spacingX = spacingX;
|
||||
this->spacingY = spacingY;
|
||||
void GridElement::UpdatePositionScaled(Window& window) {
|
||||
std::int_fast32_t cellWidth = SCALE / columns;
|
||||
std::int_fast32_t cellHeight = SCALE / rows;
|
||||
|
||||
std::size_t childIndex = 0;
|
||||
for (std::uint_fast32_t row = 0; row < rows && childIndex < children.size(); ++row) {
|
||||
for (std::uint_fast32_t col = 0; col < columns && childIndex < children.size(); ++col) {
|
||||
Transform* child = children[childIndex];
|
||||
|
||||
// Calculate position for this child
|
||||
std::int_fast32_t childX = (cellWidth * col) + (spacingX * col);
|
||||
std::int_fast32_t childY = (cellHeight * row) + (spacingY * row);
|
||||
|
||||
// Apply relative positioning
|
||||
child->anchor.x = childX;
|
||||
child->anchor.y = childY;
|
||||
child->anchor.width = cellWidth;
|
||||
child->anchor.height = cellHeight;
|
||||
|
||||
// Update child position
|
||||
child->UpdatePosition(window, *this);
|
||||
childIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GridElement::UpdatePosition(Window& window) {
|
||||
window.ScaleElement(*this);
|
||||
|
||||
// Calculate grid dimensions
|
||||
std::int_fast32_t totalWidth = 0;
|
||||
std::int_fast32_t totalHeight = 0;
|
||||
|
||||
if (columns > 0 && rows > 0) {
|
||||
// Calculate the space available for children based on grid size
|
||||
std::int_fast32_t cellWidth = (relativeWidth - (columns - 1) * spacingX) / columns;
|
||||
std::int_fast32_t cellHeight = (relativeHeight - (rows - 1) * spacingY) / rows;
|
||||
|
||||
// Position each child in the grid
|
||||
std::size_t childIndex = 0;
|
||||
for (std::uint_fast32_t row = 0; row < rows && childIndex < children.size(); ++row) {
|
||||
for (std::uint_fast32_t col = 0; col < columns && childIndex < children.size(); ++col) {
|
||||
Transform* child = children[childIndex];
|
||||
|
||||
// Calculate position for this child
|
||||
std::int_fast32_t childX = anchorOffsetX + (cellWidth * col) + (spacingX * col);
|
||||
std::int_fast32_t childY = anchorOffsetY + (cellHeight * row) + (spacingY * row);
|
||||
|
||||
// Apply relative positioning
|
||||
child->anchorX = childX;
|
||||
child->anchorY = childY;
|
||||
child->relativeWidth = cellWidth;
|
||||
child->relativeHeight = cellHeight;
|
||||
|
||||
// Update child position
|
||||
child->UpdatePosition(window, *this);
|
||||
childIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdatePositionScaled(window);
|
||||
}
|
||||
|
||||
void GridElement::UpdatePosition(Window& window, Transform& parent) {
|
||||
window.ScaleElement(*this, parent);
|
||||
// Calculate grid dimensions
|
||||
std::int_fast32_t totalWidth = 0;
|
||||
std::int_fast32_t totalHeight = 0;
|
||||
|
||||
if (columns > 0 && rows > 0) {
|
||||
// Calculate the space available for children based on grid size
|
||||
std::int_fast32_t cellWidth = (relativeWidth - (columns - 1) * spacingX) / columns;
|
||||
std::int_fast32_t cellHeight = (relativeHeight - (rows - 1) * spacingY) / rows;
|
||||
|
||||
// Position each child in the grid
|
||||
std::size_t childIndex = 0;
|
||||
for (std::uint_fast32_t row = 0; row < rows && childIndex < children.size(); ++row) {
|
||||
for (std::uint_fast32_t col = 0; col < columns && childIndex < children.size(); ++col) {
|
||||
Transform* child = children[childIndex];
|
||||
|
||||
// Calculate position for this child
|
||||
std::int_fast32_t childX = anchorOffsetX + (cellWidth * col) + (spacingX * col);
|
||||
std::int_fast32_t childY = anchorOffsetY + (cellHeight * row) + (spacingY * row);
|
||||
|
||||
// Apply relative positioning
|
||||
child->anchorX = childX;
|
||||
child->anchorY = childY;
|
||||
child->relativeWidth = cellWidth;
|
||||
child->relativeHeight = cellHeight;
|
||||
|
||||
// Update child position
|
||||
child->UpdatePosition(window, *this);
|
||||
childIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdatePositionScaled(window);
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
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 as published by the Free Software Foundation; either
|
||||
version 3.0 of the License, or (at your option) any later version.
|
||||
|
||||
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;
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "../lib/stb_image.h"
|
||||
module Crafter.Graphics:ImageElement_impl;
|
||||
import :ImageElement;
|
||||
import :RenderingElement;
|
||||
import :Window;
|
||||
import :Types;
|
||||
import std;
|
||||
|
||||
using namespace Crafter;
|
||||
|
||||
ImageElement::ImageElement() : RenderingElementScaling() {
|
||||
|
||||
}
|
||||
|
||||
ImageElement::ImageElement(const std::string_view imagePath, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : RenderingElementScaling(OpaqueType::FullyOpaque, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling) {
|
||||
RenderImage(imagePath);
|
||||
}
|
||||
|
||||
void ImageElement::RenderImage(const std::string_view path) {
|
||||
std::filesystem::path abs = std::filesystem::absolute(path);
|
||||
int xSize;
|
||||
int ySize;
|
||||
unsigned char* bgData = stbi_load(abs.string().c_str(), &xSize, &ySize, nullptr, 4);
|
||||
|
||||
ResizeBuffer(xSize, ySize);
|
||||
|
||||
opaque = OpaqueType::FullyOpaque;
|
||||
|
||||
for(std::uint_fast32_t x = 0; x < xSize; x++) {
|
||||
for(std::uint_fast32_t y = 0; y < ySize; y++) {
|
||||
std::uint_fast32_t idx = (x*ySize+y)*4;
|
||||
buffer[x*ySize+y].r = bgData[idx];
|
||||
buffer[x*ySize+y].g = bgData[idx+1];
|
||||
buffer[x*ySize+y].b = bgData[idx+2];
|
||||
buffer[x*ySize+y].a = bgData[idx+3];
|
||||
}
|
||||
}
|
||||
|
||||
for(std::uint_fast32_t i = 0; i < xSize*ySize; i++) {
|
||||
if(buffer[i].a != 255) {
|
||||
opaque = OpaqueType::SemiOpaque;
|
||||
for(std::uint_fast32_t i2 = 0; i2 < xSize*ySize; i2++) {
|
||||
if(buffer[i2].a != 0 && buffer[i2].a != 255) {
|
||||
opaque = OpaqueType::Transparent;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,14 +27,15 @@ import std;
|
|||
|
||||
using namespace Crafter;
|
||||
|
||||
MouseElement::MouseElement(WindowMouse& window, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z) : Transform(anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z) {
|
||||
MouseElement::MouseElement(Anchor anchor, WindowMouse& window) : Transform(anchor) {
|
||||
window.mouseElements.push_back(this);
|
||||
}
|
||||
|
||||
MouseElement::MouseElement(std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z) : Transform(anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z) {
|
||||
MouseElement::MouseElement(Anchor anchor) : Transform(anchor) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MouseElement::UpdatePosition(Window& window) {
|
||||
window.ScaleMouse(*this);
|
||||
for(Transform* child : children) {
|
||||
|
|
|
|||
|
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
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 as published by the Free Software Foundation; either
|
||||
version 3.0 of the License, or (at your option) any later version.
|
||||
|
||||
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:RenderingElement_impl;
|
||||
import :RenderingElement;
|
||||
import :Window;
|
||||
import :Types;
|
||||
import :Font;
|
||||
import std;
|
||||
|
||||
using namespace Crafter;
|
||||
|
||||
RenderingElement::RenderingElement(OpaqueType opaque) : Transform(), opaque(opaque) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
RenderingElement::RenderingElement(OpaqueType opaque, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z) : Transform(anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z), opaque(opaque) {
|
||||
|
||||
}
|
||||
|
||||
RenderingElementPreScaled::RenderingElementPreScaled(OpaqueType opaque) : RenderingElement(opaque) {
|
||||
|
||||
}
|
||||
|
||||
RenderingElementPreScaled::RenderingElementPreScaled(OpaqueType opaque, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z) : RenderingElement(opaque, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z) {
|
||||
|
||||
}
|
||||
|
||||
RenderingElementScaling::RenderingElementScaling(OpaqueType opaque) : RenderingElement(opaque) {
|
||||
|
||||
}
|
||||
|
||||
RenderingElementScaling::RenderingElementScaling(OpaqueType opaque, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z) : RenderingElement(opaque, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z) {
|
||||
|
||||
}
|
||||
|
||||
RenderingElementScaling::RenderingElementScaling(OpaqueType opaque, std::uint_fast32_t bufferWidth, std::uint_fast32_t bufferHeight, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z) : bufferWidth(bufferWidth), bufferHeight(bufferHeight), buffer(bufferWidth*bufferHeight), RenderingElement(opaque, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RenderingElementPreScaled::UpdatePosition(Window& window) {
|
||||
ScaleData oldScale = scaled;
|
||||
window.ScaleElement(*this);
|
||||
|
||||
if(oldScale.width != scaled.width || oldScale.height != scaled.height) {
|
||||
bufferScaled.resize(scaled.width * scaled.height);
|
||||
window.AddDirtyRect(oldScale);
|
||||
window.AddDirtyRect(scaled);
|
||||
} else if(oldScale.x != scaled.x || oldScale.y != scaled.y) {
|
||||
window.AddDirtyRect(oldScale);
|
||||
window.AddDirtyRect(scaled);
|
||||
}
|
||||
|
||||
for(Transform* child : children) {
|
||||
child->UpdatePosition(window, *this);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingElementPreScaled::UpdatePosition(Window& window, Transform& parent) {
|
||||
ScaleData oldScale = scaled;
|
||||
window.ScaleElement(*this, parent);
|
||||
|
||||
if(oldScale.width != scaled.width || oldScale.height != scaled.height) {
|
||||
bufferScaled.resize(scaled.width * scaled.height);
|
||||
window.AddDirtyRect(oldScale);
|
||||
window.AddDirtyRect(scaled);
|
||||
} else if(oldScale.x != scaled.x || oldScale.y != scaled.y) {
|
||||
window.AddDirtyRect(oldScale);
|
||||
window.AddDirtyRect(scaled);
|
||||
}
|
||||
|
||||
for(Transform* child : children) {
|
||||
child->UpdatePosition(window, *this);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingElementPreScaled::CopyNearestNeighbour(Pixel_BU8_GU8_RU8_AU8* dst, std::uint_fast32_t dstWidth, std::uint_fast32_t dstHeight) const {
|
||||
for (std::uint_fast32_t y = 0; y < dstHeight; y++) {
|
||||
std::uint_fast32_t srcY = y * scaled.height / dstHeight;
|
||||
for (std::uint_fast32_t x = 0; x < dstWidth; x++) {
|
||||
std::uint_fast32_t srcX = x * scaled.width / dstWidth;
|
||||
dst[y * dstWidth + x] = bufferScaled[srcY * scaled.width + srcX];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingElementScaling::CopyNearestNeighbour(Pixel_BU8_GU8_RU8_AU8* dst, std::uint_fast32_t dstWidth, std::uint_fast32_t dstHeight) const {
|
||||
for (std::uint_fast32_t y = 0; y < dstHeight; y++) {
|
||||
std::uint_fast32_t srcY = y * bufferHeight / dstHeight;
|
||||
for (std::uint_fast32_t x = 0; x < dstWidth; x++) {
|
||||
std::uint_fast32_t srcX = x * bufferWidth / dstWidth;
|
||||
dst[y * dstWidth + x] = buffer[srcY * bufferWidth + srcX];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingElementScaling::UpdatePosition(Window& window) {
|
||||
ScaleData oldScale = scaled;
|
||||
std::cout << MappedToFractional(relativeWidth) << std::endl;
|
||||
window.ScaleElement(*this);
|
||||
std::cout << scaled.width << std::endl;
|
||||
|
||||
|
||||
if(oldScale.width != scaled.width || oldScale.height != scaled.height) {
|
||||
bufferScaled.resize(scaled.width * scaled.height);
|
||||
CopyNearestNeighbour(bufferScaled.data(), scaled.width, scaled.height);
|
||||
window.AddDirtyRect(oldScale);
|
||||
window.AddDirtyRect(scaled);
|
||||
} else if(oldScale.x != scaled.x || oldScale.y != scaled.y) {
|
||||
window.AddDirtyRect(oldScale);
|
||||
window.AddDirtyRect(scaled);
|
||||
}
|
||||
|
||||
for(Transform* child : children) {
|
||||
child->UpdatePosition(window, *this);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingElementScaling::UpdatePosition(Window& window, Transform& parent) {
|
||||
ScaleData oldScale = scaled;
|
||||
window.ScaleElement(*this, parent);
|
||||
|
||||
if(oldScale.width != scaled.width || oldScale.height != scaled.height) {
|
||||
bufferScaled.resize(scaled.width * scaled.height);
|
||||
CopyNearestNeighbour(bufferScaled.data(), scaled.width, scaled.height);
|
||||
window.AddDirtyRect(oldScale);
|
||||
window.AddDirtyRect(scaled);
|
||||
} else if(oldScale.x != scaled.x || oldScale.y != scaled.y) {
|
||||
window.AddDirtyRect(oldScale);
|
||||
window.AddDirtyRect(scaled);
|
||||
}
|
||||
|
||||
for(Transform* child : children) {
|
||||
child->UpdatePosition(window, *this);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingElementScaling::ResizeBuffer(std::uint_fast32_t width, std::uint_fast32_t height) {
|
||||
this->bufferWidth = width;
|
||||
this->bufferHeight = height;
|
||||
buffer.resize(width * height);
|
||||
}
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
/*
|
||||
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 as published by the Free Software Foundation; either
|
||||
version 3.0 of the License, or (at your option) any later version.
|
||||
|
||||
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:RenderingElementScalingRotating2D_impl;
|
||||
import :RenderingElement;
|
||||
import :Window;
|
||||
import :Types;
|
||||
import :Font;
|
||||
import std;
|
||||
|
||||
using namespace Crafter;
|
||||
|
||||
RenderingElementScalingRotating2D::RenderingElementScalingRotating2D(OpaqueType opaque) : RenderingElement(opaque), rotation(0) {
|
||||
|
||||
}
|
||||
|
||||
RenderingElementScalingRotating2D::RenderingElementScalingRotating2D(OpaqueType opaque, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z) : RenderingElement(opaque, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z), rotation(0) {
|
||||
|
||||
}
|
||||
|
||||
RenderingElementScalingRotating2D::RenderingElementScalingRotating2D(OpaqueType opaque, std::uint_fast32_t bufferWidth, std::uint_fast32_t bufferHeight, std::uint_fast32_t rotation, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z)
|
||||
: bufferWidth(bufferWidth), bufferHeight(bufferHeight), buffer(bufferWidth*bufferHeight),
|
||||
rotation(rotation),
|
||||
RenderingElement(opaque, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z) {
|
||||
}
|
||||
|
||||
void RenderingElementScalingRotating2D::ResizeBuffer(std::uint_fast32_t width, std::uint_fast32_t height) {
|
||||
this->bufferWidth = width;
|
||||
this->bufferHeight = height;
|
||||
buffer.resize(width * height);
|
||||
}
|
||||
|
||||
void RenderingElementScalingRotating2D::UpdateRotation(std::uint_fast32_t rotation) {
|
||||
rotationUpdated = true;
|
||||
this->rotation = rotation;
|
||||
}
|
||||
|
||||
void RenderingElementScalingRotating2D::UpdateScaledBuffer(ScaleData& scaled) {
|
||||
// Rotation
|
||||
const double rad = (static_cast<double>(rotation) / static_cast<double>(std::numeric_limits<std::uint_fast32_t>::max())) * 2.0 * std::numbers::pi;
|
||||
|
||||
const std::uint_fast32_t dstWidth = scaled.width;
|
||||
const std::uint_fast32_t dstHeight = scaled.height;
|
||||
|
||||
const double rotatedWidth = scaled.width * (std::abs(std::cos(rad)) + std::abs(std::sin(rad)));
|
||||
const double rotatedHeight = scaled.height * (std::abs(std::cos(rad)) + std::abs(std::sin(rad)));
|
||||
|
||||
const std::uint_fast32_t diffX = std::ceil((rotatedWidth - scaled.width)/2);
|
||||
const std::uint_fast32_t diffY = std::ceil((rotatedHeight - scaled.height)/2);
|
||||
|
||||
scaled.width += diffX + diffX;
|
||||
scaled.height += diffY + diffY;
|
||||
|
||||
scaled.x -= diffX;
|
||||
scaled.y -= diffY;
|
||||
|
||||
bufferScaled.clear();
|
||||
bufferScaled.resize(scaled.width * scaled.height);
|
||||
|
||||
// Destination center
|
||||
const double dstCx = (static_cast<double>(scaled.width) - 1.0) * 0.5;
|
||||
const double dstCy = (static_cast<double>(scaled.height) - 1.0) * 0.5;
|
||||
|
||||
// Source center
|
||||
const double srcCx = (static_cast<double>(bufferWidth) - 1.0) * 0.5;
|
||||
const double srcCy = (static_cast<double>(bufferHeight) - 1.0) * 0.5;
|
||||
|
||||
const double c = std::cos(rad);
|
||||
const double s = std::sin(rad);
|
||||
|
||||
// Scale factors (destination → source)
|
||||
const double scaleX = static_cast<double>(bufferWidth) / dstWidth;
|
||||
const double scaleY = static_cast<double>(bufferHeight) / dstHeight;
|
||||
|
||||
for (std::uint_fast32_t yB = 0; yB < scaled.height; ++yB) {
|
||||
for (std::uint_fast32_t xB = 0; xB < scaled.width; ++xB) {
|
||||
|
||||
// ---- Destination pixel relative to center ----
|
||||
const double dx = (static_cast<double>(xB) - dstCx) * scaleX;
|
||||
const double dy = (static_cast<double>(yB) - dstCy) * scaleY;
|
||||
|
||||
// ---- Inverse rotation ----
|
||||
const double sx = (c * dx - s * dy) + srcCx;
|
||||
const double sy = (s * dx + c * dy) + srcCy;
|
||||
|
||||
// ---- Nearest neighbour sampling ----
|
||||
const std::int_fast32_t srcX = static_cast<std::int_fast32_t>(std::round(sx));
|
||||
const std::int_fast32_t srcY = static_cast<std::int_fast32_t>(std::round(sy));
|
||||
|
||||
if (srcX >= 0 && srcX < bufferWidth && srcY >= 0 && srcY < bufferHeight) {
|
||||
bufferScaled[yB * scaled.width + xB] = buffer[srcY * bufferWidth + srcX];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RenderingElementScalingRotating2D::UpdatePosition(Window& window) {
|
||||
ScaleData oldScale = scaled;
|
||||
window.ScaleElement(*this);
|
||||
|
||||
if(oldScale.width != scaled.width || oldScale.height != scaled.height || rotationUpdated) {
|
||||
UpdateScaledBuffer(scaled);
|
||||
window.AddDirtyRect(oldScale);
|
||||
window.AddDirtyRect(scaled);
|
||||
rotationUpdated = false;
|
||||
} else if(oldScale.x != scaled.x || oldScale.y != scaled.y) {
|
||||
|
||||
const double rad = (static_cast<double>(rotation) / static_cast<double>(std::numeric_limits<std::uint_fast32_t>::max())) * 2.0 * std::numbers::pi;
|
||||
|
||||
const double rotatedWidth = scaled.width * (std::abs(std::cos(rad)) + std::abs(std::sin(rad)));
|
||||
const double rotatedHeight = scaled.height * (std::abs(std::cos(rad)) + std::abs(std::sin(rad)));
|
||||
|
||||
scaled.width = static_cast<std::uint_fast32_t>(std::ceil(rotatedWidth));
|
||||
scaled.height = static_cast<std::uint_fast32_t>(std::ceil(rotatedHeight));
|
||||
|
||||
window.AddDirtyRect(oldScale);
|
||||
window.AddDirtyRect(scaled);
|
||||
}
|
||||
|
||||
for(Transform* child : children) {
|
||||
child->UpdatePosition(window, *this);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingElementScalingRotating2D::UpdatePosition(Window& window, Transform& parent) {
|
||||
ScaleData oldScale = scaled;
|
||||
window.ScaleElement(*this, parent);
|
||||
|
||||
if(oldScale.width != scaled.width || oldScale.height != scaled.height || rotationUpdated) {
|
||||
UpdateScaledBuffer(scaled);
|
||||
window.AddDirtyRect(oldScale);
|
||||
window.AddDirtyRect(scaled);
|
||||
rotationUpdated = false;
|
||||
} else if(oldScale.x != scaled.x || oldScale.y != scaled.y) {
|
||||
const double rad = (static_cast<double>(rotation) / static_cast<double>(std::numeric_limits<std::uint_fast32_t>::max())) * 2.0 * std::numbers::pi;
|
||||
|
||||
const double rotatedWidth = scaled.width * (std::abs(std::cos(rad)) + std::abs(std::sin(rad)));
|
||||
const double rotatedHeight = scaled.height * (std::abs(std::cos(rad)) + std::abs(std::sin(rad)));
|
||||
|
||||
scaled.width = static_cast<std::uint_fast32_t>(std::ceil(rotatedWidth));
|
||||
scaled.height = static_cast<std::uint_fast32_t>(std::ceil(rotatedHeight));
|
||||
|
||||
window.AddDirtyRect(oldScale);
|
||||
window.AddDirtyRect(scaled);
|
||||
}
|
||||
|
||||
for(Transform* child : children) {
|
||||
child->UpdatePosition(window, *this);
|
||||
}
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ import std;
|
|||
|
||||
using namespace Crafter;
|
||||
|
||||
TextElement::TextElement(std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z) : RenderingElementPreScaled(OpaqueType::Transparent, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z) {
|
||||
TextElement::TextElement(Anchor anchor): RenderingElement<false, false, false>(anchor, OpaqueType::Transparent) {
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ void TextElement::RenderText(Window& window, const std::string_view text, float
|
|||
int baseline = (int)(font.ascent * scale);
|
||||
|
||||
// Clear the scaled buffer
|
||||
for (auto& pixel : bufferScaled) {
|
||||
for (auto& pixel : buffer) {
|
||||
pixel = {0, 0, 0, 0};
|
||||
}
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ void TextElement::RenderText(Window& window, const std::string_view text, float
|
|||
|
||||
// Only draw pixels that are within our scaled buffer bounds
|
||||
if (bufferX >= 0 && bufferX < (int)scaled.width && bufferY >= 0 && bufferY < (int)scaled.height) {
|
||||
bufferScaled[bufferY * scaled.width + bufferX] = {color.r, color.g, color.b, bitmap[j * w + i]};
|
||||
buffer[bufferY * scaled.width + bufferX] = {color.r, color.g, color.b, bitmap[j * w + i]};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -288,11 +288,11 @@ void TextElement::RenderText(Window& window, const std::string_view text, float
|
|||
for (std::uint_fast32_t y = 0; y < scaled.height; ++y) {
|
||||
for (std::uint_fast32_t x = 0; x < scaled.width; ++x) {
|
||||
std::uint_fast32_t index = y * scaled.width + x;
|
||||
if (index < bufferScaled.size()) {
|
||||
if (index < buffer.size()) {
|
||||
// Move the pixel vertically
|
||||
std::uint_fast32_t newIndex = (y + verticalOffset) * scaled.width + x;
|
||||
if (newIndex < bufferScaled.size()) {
|
||||
bufferScaled[newIndex] = bufferScaled[index];
|
||||
if (newIndex < buffer.size()) {
|
||||
buffer[newIndex] = buffer[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -355,7 +355,7 @@ void TextElement::RenderWrappedLine(const std::string_view line, float scale, in
|
|||
|
||||
// Only draw pixels that are within our scaled buffer bounds
|
||||
if (bufferX >= 0 && bufferX < (int)scaled.width && bufferY >= 0 && bufferY < (int)scaled.height) {
|
||||
bufferScaled[bufferY * scaled.width + bufferX] = {color.r, color.g, color.b, bitmap[j * w + i]};
|
||||
buffer[bufferY * scaled.width + bufferX] = {color.r, color.g, color.b, bitmap[j * w + i]};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,15 +27,20 @@ import std;
|
|||
|
||||
using namespace Crafter;
|
||||
|
||||
Transform::Transform(std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z) : anchorX(anchorX), anchorY(anchorY), relativeWidth(relativeWidth), relativeHeight(relativeHeight), anchorOffsetX(anchorOffsetX), anchorOffsetY(anchorOffsetY), z(z) {
|
||||
|
||||
Anchor::Anchor(std::int_fast32_t x, std::int_fast32_t y, std::uint_fast32_t width, std::uint_fast32_t height, std::int_fast32_t offsetX, std::int_fast32_t offsetY, std::int_fast32_t z): x(x), y(y), width(width), height(height), offsetX(offsetX), offsetY(offsetY), z(z) {
|
||||
|
||||
}
|
||||
|
||||
Transform::Transform(Anchor anchor) : anchor(anchor) {
|
||||
|
||||
}
|
||||
|
||||
void Transform::UpdatePosition(Window& window) {
|
||||
window.ScaleElement(*this);
|
||||
for(Transform* child : children) {
|
||||
child->UpdatePosition(window, *this);
|
||||
}
|
||||
child->UpdatePosition(window, *this);
|
||||
}
|
||||
}
|
||||
|
||||
void Transform::UpdatePosition(Window& window, Transform& parent) {
|
||||
|
|
|
|||
|
|
@ -29,35 +29,35 @@ Window::Window(std::int_fast32_t width, std::int_fast32_t height) : width(width)
|
|||
}
|
||||
|
||||
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);
|
||||
element.scaled.width = MappedToPixel(element.anchor.width, width);
|
||||
element.scaled.height = MappedToPixel(element.anchor.height, height);
|
||||
element.scaled.x = MappedToPixel(element.anchor.x, width) - MappedToPixel(element.anchor.offsetX, element.scaled.width);
|
||||
element.scaled.y = MappedToPixel(element.anchor.y, height) - MappedToPixel(element.anchor.offsetY, 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;
|
||||
element.scaled.width = MappedToPixel(element.anchor.width, parent.scaled.width);
|
||||
element.scaled.height = MappedToPixel(element.anchor.height, parent.scaled.height);
|
||||
element.scaled.x = MappedToPixel(element.anchor.x, parent.scaled.width) - MappedToPixel(element.anchor.offsetX, element.scaled.width) + parent.scaled.x;
|
||||
element.scaled.y = MappedToPixel(element.anchor.y, parent.scaled.height) - MappedToPixel(element.anchor.offsetY, 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);
|
||||
element.scaled.width = BoundToBoundless(MappedToPixel(element.anchor.width, PixelToMapped(parent.scaled.width, width)));
|
||||
element.scaled.height = BoundToBoundless(MappedToPixel(element.anchor.height, PixelToMapped(parent.scaled.height, height)));
|
||||
element.scaled.x = MappedToPixelBoundless(element.anchor.x, boundlessWidth) - MappedToPixelBoundless(element.anchor.offsetX, element.scaled.width) + PixelToMappedBoundless(parent.scaled.x, width);
|
||||
element.scaled.y = MappedToPixelBoundless(element.anchor.y, boundlessHeight) - MappedToPixelBoundless(element.anchor.offsetY, element.scaled.height) + PixelToMappedBoundless(parent.scaled.y, height);
|
||||
}
|
||||
|
||||
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);
|
||||
// element.scaled.width = BoundToBoundless(MappedToPixel(element.anchor.width, width));
|
||||
// element.scaled.height = BoundToBoundless(MappedToPixel(element.anchor.height, height));
|
||||
// element.scaled.x = MappedToPixelBoundless(element.anchor.x, boundlessWidth) - MappedToPixelBoundless(element.anchor.offsetX, element.scaled.width) + PixelToMappedBoundless(parent.scaled.x, width);
|
||||
// element.scaled.y = MappedToPixelBoundless(element.anchor.y, boundlessHeight) - MappedToPixelBoundless(element.anchor.offsetY, element.scaled.height) + PixelToMappedBoundless(parent.scaled.y, height);
|
||||
}
|
||||
|
||||
#ifdef CRAFTER_TIMING
|
||||
|
|
@ -107,30 +107,30 @@ void Window::AddDirtyRect(ScaleData scale) {
|
|||
.bottom = std::min(scale.y + scale.height, height),
|
||||
};
|
||||
|
||||
if (rect.left >= rect.right || rect.top >= rect.bottom) {
|
||||
return;
|
||||
}
|
||||
// if (rect.left >= rect.right || rect.top >= rect.bottom) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
for(ClipRect existing : dirtyRects) {
|
||||
//fully enclosed
|
||||
if(rect.left >= existing.left && rect.right <= existing.right && rect.top >= existing.top && rect.bottom <= existing.bottom) {
|
||||
return;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
// //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;
|
||||
}
|
||||
}
|
||||
// //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
|
||||
dirtyRects.push_back(rect);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ module;
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include "../lib/xdg-shell-client-protocol.h"
|
||||
#include "../lib/wayland-xdg-decoration-unstable-v1-client-protocol.h"
|
||||
#include <string.h>
|
||||
|
|
@ -155,7 +154,7 @@ inline void blend_pixel_optimized(Pixel_BU8_GU8_RU8_AU8& dst, const Pixel_BU8_GU
|
|||
}
|
||||
|
||||
void WindowWayland::RenderElement(Transform* transform) {
|
||||
RenderingElement* element = dynamic_cast<RenderingElement*>(transform);
|
||||
RenderingElementBase* element = dynamic_cast<RenderingElementBase*>(transform);
|
||||
if(element) {
|
||||
#ifdef CRAFTER_TIMING
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
|
@ -171,7 +170,7 @@ void WindowWayland::RenderElement(Transform* transform) {
|
|||
dirty.right = std::min(element->scaled.x+element->scaled.width, dirty.right);
|
||||
dirty.bottom = std::min(element->scaled.y+element->scaled.height, dirty.bottom);
|
||||
|
||||
const Pixel_BU8_GU8_RU8_AU8* src_buffer = element->bufferScaled.data();
|
||||
const Pixel_BU8_GU8_RU8_AU8* src_buffer = element->buffer.data();
|
||||
std::int_fast32_t src_width = element->scaled.width;
|
||||
std::int_fast32_t src_height = element->scaled.height;
|
||||
|
||||
|
|
@ -226,7 +225,7 @@ void WindowWayland::RenderElement(Transform* transform) {
|
|||
#endif
|
||||
}
|
||||
|
||||
std::sort(transform->children.begin(), transform->children.end(), [](Transform* a, Transform* b){ return a->z < b->z; });
|
||||
std::sort(transform->children.begin(), transform->children.end(), [](Transform* a, Transform* b){ return a->anchor.z < b->anchor.z; });
|
||||
for(Transform* child : transform->children) {
|
||||
this->RenderElement(child);
|
||||
}
|
||||
|
|
@ -234,87 +233,107 @@ void WindowWayland::RenderElement(Transform* transform) {
|
|||
|
||||
void WindowWayland::Render() {
|
||||
elements.erase(std::remove(elements.begin(), elements.end(), static_cast<Transform*>(nullptr)), elements.end());
|
||||
std::sort(elements.begin(), elements.end(), [](Transform* a, Transform* b){ return a->z < b->z; });
|
||||
std::sort(elements.begin(), elements.end(), [](Transform* a, Transform* b){ return a->anchor.z < b->anchor.z; });
|
||||
|
||||
std::vector<ClipRect> newClip;
|
||||
//std::vector<ClipRect> newClip;
|
||||
|
||||
for (std::uint_fast32_t i = 0; i < dirtyRects.size(); i++) {
|
||||
ClipRect rect = dirtyRects[i];
|
||||
for (std::uint_fast32_t i2 = i + 1; i2 < dirtyRects.size(); i2++) {
|
||||
ClipRect existing = dirtyRects[i2];
|
||||
if(rect.bottom >= existing.top && rect.top <= existing.top) {
|
||||
newClip.push_back({
|
||||
.left = rect.left,
|
||||
.right = rect.right,
|
||||
.top = rect.top,
|
||||
.bottom = existing.top,
|
||||
});
|
||||
//-| shape
|
||||
if(rect.right > existing.right) {
|
||||
newClip.push_back({
|
||||
.left = existing.right,
|
||||
.right = rect.right,
|
||||
.top = existing.top,
|
||||
.bottom = existing.bottom,
|
||||
});
|
||||
}
|
||||
//|- shape
|
||||
if(rect.left < existing.left) {
|
||||
newClip.push_back({
|
||||
.left = rect.left,
|
||||
.right = existing.left,
|
||||
.top = existing.top,
|
||||
.bottom = existing.bottom,
|
||||
});
|
||||
}
|
||||
//-| or |- shape where rect extends further down
|
||||
if(rect.bottom > existing.bottom) {
|
||||
newClip.push_back({
|
||||
.left = rect.left,
|
||||
.right = rect.right,
|
||||
.top = existing.bottom,
|
||||
.bottom = rect.bottom,
|
||||
});
|
||||
}
|
||||
goto inner;
|
||||
}
|
||||
if (rect.left <= existing.right && rect.right >= existing.left) {
|
||||
newClip.push_back({
|
||||
.left = rect.left,
|
||||
.right = existing.left,
|
||||
.top = rect.top,
|
||||
.bottom = rect.bottom,
|
||||
});
|
||||
if (rect.right > existing.right) {
|
||||
newClip.push_back({
|
||||
.left = existing.right,
|
||||
.right = rect.right,
|
||||
.top = rect.top,
|
||||
.bottom = rect.bottom,
|
||||
});
|
||||
}
|
||||
goto inner;
|
||||
}
|
||||
}
|
||||
newClip.push_back(rect);
|
||||
inner:;
|
||||
}
|
||||
|
||||
dirtyRects = std::move(newClip);
|
||||
|
||||
// for(uint_fast32_t i = 0; i < width*height; i++) {
|
||||
// framebuffer[i] = {0, 0, 0, 255};
|
||||
// for (std::uint_fast32_t i = 0; i < dirtyRects.size(); i++) {
|
||||
// ClipRect rect = dirtyRects[i];
|
||||
// for (std::uint_fast32_t i2 = i + 1; i2 < dirtyRects.size(); i2++) {
|
||||
// ClipRect existing = dirtyRects[i2];
|
||||
// if(rect.bottom >= existing.top && rect.top <= existing.top) {
|
||||
// newClip.push_back({
|
||||
// .left = rect.left,
|
||||
// .right = rect.right,
|
||||
// .top = rect.top,
|
||||
// .bottom = existing.top,
|
||||
// });
|
||||
// //-| shape
|
||||
// if(rect.right > existing.right) {
|
||||
// newClip.push_back({
|
||||
// .left = existing.right,
|
||||
// .right = rect.right,
|
||||
// .top = existing.top,
|
||||
// .bottom = existing.bottom,
|
||||
// });
|
||||
// }
|
||||
// //|- shape
|
||||
// if(rect.left < existing.left) {
|
||||
// newClip.push_back({
|
||||
// .left = rect.left,
|
||||
// .right = existing.left,
|
||||
// .top = existing.top,
|
||||
// .bottom = existing.bottom,
|
||||
// });
|
||||
// }
|
||||
// //-| or |- shape where rect extends further down
|
||||
// if(rect.bottom > existing.bottom) {
|
||||
// newClip.push_back({
|
||||
// .left = rect.left,
|
||||
// .right = rect.right,
|
||||
// .top = existing.bottom,
|
||||
// .bottom = rect.bottom,
|
||||
// });
|
||||
// }
|
||||
// goto inner;
|
||||
// }
|
||||
// if (rect.left <= existing.right && rect.right >= existing.left) {
|
||||
// newClip.push_back({
|
||||
// .left = rect.left,
|
||||
// .right = existing.left,
|
||||
// .top = rect.top,
|
||||
// .bottom = rect.bottom,
|
||||
// });
|
||||
// if (rect.right > existing.right) {
|
||||
// newClip.push_back({
|
||||
// .left = existing.right,
|
||||
// .right = rect.right,
|
||||
// .top = rect.top,
|
||||
// .bottom = rect.bottom,
|
||||
// });
|
||||
// }
|
||||
// goto inner;
|
||||
// }
|
||||
// }
|
||||
// newClip.push_back(rect);
|
||||
// inner:;
|
||||
// }
|
||||
|
||||
//dirtyRects = std::move(newClip);
|
||||
|
||||
// std::memset(framebuffer, 0, width*height*4);
|
||||
|
||||
// std::cout << dirtyRects.size() << std::endl;
|
||||
// for (ClipRect rect : dirtyRects) {
|
||||
// //std::cout << std::format("{}, {}, {}, {}", rect.left, rect.top, rect.right, rect.bottom) << std::endl;
|
||||
// for (std::int_fast32_t y = rect.top; y < rect.bottom; y++) {
|
||||
// for (std::int_fast32_t x = rect.left; x < rect.right; x++) {
|
||||
// framebuffer[y * width + x].r += 30;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // Color palette
|
||||
// static const std::vector<Pixel_BU8_GU8_RU8_AU8> colors = {
|
||||
// {255, 0, 0, 255}, // red
|
||||
// { 0, 255, 0, 255}, // green
|
||||
// { 0, 0, 255, 255}, // blue
|
||||
// {255, 255, 0, 255}, // yellow
|
||||
// {255, 0, 255, 255}, // magenta
|
||||
// { 0, 255, 255, 255}, // cyan
|
||||
// };
|
||||
|
||||
// std::size_t rectIndex = 0;
|
||||
|
||||
// for (const ClipRect& rect : dirtyRects) {
|
||||
// const Pixel_BU8_GU8_RU8_AU8& color = colors[rectIndex % colors.size()];
|
||||
|
||||
// std::cout << std::format(
|
||||
// "ClipRect {}: [{}, {}, {}, {}] Color = RGBA({}, {}, {}, {})",
|
||||
// rectIndex,
|
||||
// rect.left, rect.top, rect.right, rect.bottom,
|
||||
// color.r, color.g, color.b, color.a
|
||||
// ) << std::endl;
|
||||
|
||||
// for (std::int_fast32_t y = rect.top; y < rect.bottom; ++y) {
|
||||
// for (std::int_fast32_t x = rect.left; x < rect.right; ++x) {
|
||||
// framebuffer[y * width + x] = color;
|
||||
// }
|
||||
// }
|
||||
|
||||
// ++rectIndex;
|
||||
// }
|
||||
|
||||
if (!dirtyRects.empty()) {
|
||||
for (ClipRect rect : dirtyRects) {
|
||||
|
|
@ -335,11 +354,17 @@ void WindowWayland::Render() {
|
|||
dirtyRects.clear();
|
||||
}
|
||||
|
||||
dirtyRects.clear();
|
||||
wl_surface_damage(surface, 0, 0, width, height);
|
||||
|
||||
wl_surface_attach(surface, buffer, 0, 0);
|
||||
wl_surface_commit(surface);
|
||||
wl_surface_commit(surface);
|
||||
wl_surface_damage(surface, 0, 0, 10000, 100000);
|
||||
}
|
||||
|
||||
void WindowWayland::QueueRender() {
|
||||
std::cout << cb << std::endl;
|
||||
if(cb == nullptr) {
|
||||
cb = wl_surface_frame(surface);
|
||||
wl_callback_add_listener(cb, &wl_callback_listener, this);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowWayland::StartUpdate() {
|
||||
|
|
@ -396,6 +421,7 @@ void WindowWayland::wl_surface_frame_done(void* data, struct wl_callback *cb, ui
|
|||
{
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
wl_callback_destroy(cb);
|
||||
cb = nullptr;
|
||||
WindowWayland* window = reinterpret_cast<WindowWayland*>(data);
|
||||
#ifdef CRAFTER_TIMING
|
||||
window->vblank = duration_cast<std::chrono::milliseconds>(start - window->frameEnd);
|
||||
|
|
@ -413,18 +439,18 @@ void WindowWayland::wl_surface_frame_done(void* data, struct wl_callback *cb, ui
|
|||
window->totalUpdate += entry.second;
|
||||
}
|
||||
#endif
|
||||
#ifdef CRAFTER_TIMING
|
||||
auto renderStart = std::chrono::high_resolution_clock::now();
|
||||
window->renderTimings.clear();
|
||||
#endif
|
||||
window->Render();
|
||||
#ifdef CRAFTER_TIMING
|
||||
auto renderEnd = std::chrono::high_resolution_clock::now();
|
||||
window->totalRender = renderEnd - renderStart;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef CRAFTER_TIMING
|
||||
auto renderStart = std::chrono::high_resolution_clock::now();
|
||||
window->renderTimings.clear();
|
||||
#endif
|
||||
window->Render();
|
||||
#ifdef CRAFTER_TIMING
|
||||
auto renderEnd = std::chrono::high_resolution_clock::now();
|
||||
window->totalRender = renderEnd - renderStart;
|
||||
#endif
|
||||
|
||||
#ifdef CRAFTER_TIMING
|
||||
window->frameEnd = std::chrono::high_resolution_clock::now();
|
||||
|
||||
|
|
@ -557,6 +583,132 @@ void WindowWayland::keyboard_leave(void *data, wl_keyboard *keyboard, uint32_t s
|
|||
|
||||
}
|
||||
|
||||
CrafterKeys keysym_to_crafter_key(xkb_keysym_t sym)
|
||||
{
|
||||
switch (sym)
|
||||
{
|
||||
// Alphabet
|
||||
case XKB_KEY_a: return CrafterKeys::A;
|
||||
case XKB_KEY_b: return CrafterKeys::B;
|
||||
case XKB_KEY_c: return CrafterKeys::C;
|
||||
case XKB_KEY_d: return CrafterKeys::D;
|
||||
case XKB_KEY_e: return CrafterKeys::E;
|
||||
case XKB_KEY_f: return CrafterKeys::F;
|
||||
case XKB_KEY_g: return CrafterKeys::G;
|
||||
case XKB_KEY_h: return CrafterKeys::H;
|
||||
case XKB_KEY_i: return CrafterKeys::I;
|
||||
case XKB_KEY_j: return CrafterKeys::J;
|
||||
case XKB_KEY_k: return CrafterKeys::K;
|
||||
case XKB_KEY_l: return CrafterKeys::L;
|
||||
case XKB_KEY_m: return CrafterKeys::M;
|
||||
case XKB_KEY_n: return CrafterKeys::N;
|
||||
case XKB_KEY_o: return CrafterKeys::O;
|
||||
case XKB_KEY_p: return CrafterKeys::P;
|
||||
case XKB_KEY_q: return CrafterKeys::Q;
|
||||
case XKB_KEY_r: return CrafterKeys::R;
|
||||
case XKB_KEY_s: return CrafterKeys::S;
|
||||
case XKB_KEY_t: return CrafterKeys::T;
|
||||
case XKB_KEY_u: return CrafterKeys::U;
|
||||
case XKB_KEY_v: return CrafterKeys::V;
|
||||
case XKB_KEY_w: return CrafterKeys::W;
|
||||
case XKB_KEY_x: return CrafterKeys::X;
|
||||
case XKB_KEY_y: return CrafterKeys::Y;
|
||||
case XKB_KEY_z: return CrafterKeys::Z;
|
||||
|
||||
// Numbers
|
||||
case XKB_KEY_0: return CrafterKeys::_0;
|
||||
case XKB_KEY_1: return CrafterKeys::_1;
|
||||
case XKB_KEY_2: return CrafterKeys::_2;
|
||||
case XKB_KEY_3: return CrafterKeys::_3;
|
||||
case XKB_KEY_4: return CrafterKeys::_4;
|
||||
case XKB_KEY_5: return CrafterKeys::_5;
|
||||
case XKB_KEY_6: return CrafterKeys::_6;
|
||||
case XKB_KEY_7: return CrafterKeys::_7;
|
||||
case XKB_KEY_8: return CrafterKeys::_8;
|
||||
case XKB_KEY_9: return CrafterKeys::_9;
|
||||
|
||||
// Function keys
|
||||
case XKB_KEY_F1: return CrafterKeys::F1;
|
||||
case XKB_KEY_F2: return CrafterKeys::F2;
|
||||
case XKB_KEY_F3: return CrafterKeys::F3;
|
||||
case XKB_KEY_F4: return CrafterKeys::F4;
|
||||
case XKB_KEY_F5: return CrafterKeys::F5;
|
||||
case XKB_KEY_F6: return CrafterKeys::F6;
|
||||
case XKB_KEY_F7: return CrafterKeys::F7;
|
||||
case XKB_KEY_F8: return CrafterKeys::F8;
|
||||
case XKB_KEY_F9: return CrafterKeys::F9;
|
||||
case XKB_KEY_F10: return CrafterKeys::F10;
|
||||
case XKB_KEY_F11: return CrafterKeys::F11;
|
||||
case XKB_KEY_F12: return CrafterKeys::F12;
|
||||
|
||||
// Control keys
|
||||
case XKB_KEY_Escape: return CrafterKeys::Escape;
|
||||
case XKB_KEY_Tab: return CrafterKeys::Tab;
|
||||
case XKB_KEY_Return: return CrafterKeys::Enter;
|
||||
case XKB_KEY_space: return CrafterKeys::Space;
|
||||
case XKB_KEY_BackSpace: return CrafterKeys::Backspace;
|
||||
case XKB_KEY_Delete: return CrafterKeys::Delete;
|
||||
case XKB_KEY_Insert: return CrafterKeys::Insert;
|
||||
case XKB_KEY_Home: return CrafterKeys::Home;
|
||||
case XKB_KEY_End: return CrafterKeys::End;
|
||||
case XKB_KEY_Page_Up: return CrafterKeys::PageUp;
|
||||
case XKB_KEY_Page_Down: return CrafterKeys::PageDown;
|
||||
case XKB_KEY_Caps_Lock: return CrafterKeys::CapsLock;
|
||||
case XKB_KEY_Num_Lock: return CrafterKeys::NumLock;
|
||||
case XKB_KEY_Scroll_Lock:return CrafterKeys::ScrollLock;
|
||||
|
||||
// Modifiers
|
||||
case XKB_KEY_Shift_L: return CrafterKeys::LeftShift;
|
||||
case XKB_KEY_Shift_R: return CrafterKeys::RightShift;
|
||||
case XKB_KEY_Control_L: return CrafterKeys::LeftCtrl;
|
||||
case XKB_KEY_Control_R: return CrafterKeys::RightCtrl;
|
||||
case XKB_KEY_Alt_L: return CrafterKeys::LeftAlt;
|
||||
case XKB_KEY_Alt_R: return CrafterKeys::RightAlt;
|
||||
case XKB_KEY_Super_L: return CrafterKeys::LeftSuper;
|
||||
case XKB_KEY_Super_R: return CrafterKeys::RightSuper;
|
||||
|
||||
// Arrows
|
||||
case XKB_KEY_Up: return CrafterKeys::Up;
|
||||
case XKB_KEY_Down: return CrafterKeys::Down;
|
||||
case XKB_KEY_Left: return CrafterKeys::Left;
|
||||
case XKB_KEY_Right: return CrafterKeys::Right;
|
||||
|
||||
// Keypad
|
||||
case XKB_KEY_KP_0: return CrafterKeys::keypad_0;
|
||||
case XKB_KEY_KP_1: return CrafterKeys::keypad_1;
|
||||
case XKB_KEY_KP_2: return CrafterKeys::keypad_2;
|
||||
case XKB_KEY_KP_3: return CrafterKeys::keypad_3;
|
||||
case XKB_KEY_KP_4: return CrafterKeys::keypad_4;
|
||||
case XKB_KEY_KP_5: return CrafterKeys::keypad_5;
|
||||
case XKB_KEY_KP_6: return CrafterKeys::keypad_6;
|
||||
case XKB_KEY_KP_7: return CrafterKeys::keypad_7;
|
||||
case XKB_KEY_KP_8: return CrafterKeys::keypad_8;
|
||||
case XKB_KEY_KP_9: return CrafterKeys::keypad_9;
|
||||
case XKB_KEY_KP_Enter: return CrafterKeys::keypad_enter;
|
||||
case XKB_KEY_KP_Add: return CrafterKeys::keypad_plus;
|
||||
case XKB_KEY_KP_Subtract: return CrafterKeys::keypad_minus;
|
||||
case XKB_KEY_KP_Multiply: return CrafterKeys::keypad_multiply;
|
||||
case XKB_KEY_KP_Divide: return CrafterKeys::keypad_divide;
|
||||
case XKB_KEY_KP_Decimal: return CrafterKeys::keypad_decimal;
|
||||
|
||||
// Punctuation
|
||||
case XKB_KEY_grave: return CrafterKeys::grave;
|
||||
case XKB_KEY_minus: return CrafterKeys::minus;
|
||||
case XKB_KEY_equal: return CrafterKeys::equal;
|
||||
case XKB_KEY_bracketleft: return CrafterKeys::bracket_left;
|
||||
case XKB_KEY_bracketright:return CrafterKeys::bracket_right;
|
||||
case XKB_KEY_backslash: return CrafterKeys::backslash;
|
||||
case XKB_KEY_semicolon: return CrafterKeys::semicolon;
|
||||
case XKB_KEY_apostrophe: return CrafterKeys::quote;
|
||||
case XKB_KEY_comma: return CrafterKeys::comma;
|
||||
case XKB_KEY_period: return CrafterKeys::period;
|
||||
case XKB_KEY_slash: return CrafterKeys::slash;
|
||||
|
||||
default:
|
||||
return CrafterKeys::CrafterKeysMax;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowWayland::keyboard_key(void *data, wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
|
||||
WindowWayland* window = reinterpret_cast<WindowWayland*>(data);
|
||||
|
||||
|
|
@ -566,33 +718,22 @@ void WindowWayland::keyboard_key(void *data, wl_keyboard *keyboard, uint32_t ser
|
|||
|
||||
xkb_keycode_t keycode = key + 8;
|
||||
xkb_keysym_t keysym = xkb_state_key_get_one_sym(window->xkb_state, keycode);
|
||||
CrafterKeys crafterKey = keysym_to_crafter_key(keysym);
|
||||
|
||||
char utf8[8] = {0};
|
||||
int len = xkb_keysym_to_utf8(keysym, utf8, sizeof(utf8));
|
||||
if (len != 0) {
|
||||
char keypress = utf8[0];
|
||||
if(state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
if(window->heldkeys[keypress]) {
|
||||
window->onKeyHold[keypress].Invoke();
|
||||
window->onAnyKeyHold.Invoke(keypress);
|
||||
} else{
|
||||
window->heldkeys[keypress] = true;
|
||||
window->onKeyDown[keypress].Invoke();
|
||||
window->onAnyKeyDown.Invoke(keypress);
|
||||
}
|
||||
} else{
|
||||
window->heldkeys[keypress] = false;
|
||||
window->onKeyUp[keypress].Invoke();
|
||||
window->onAnyKeyUp.Invoke(keypress);
|
||||
}
|
||||
|
||||
} else {
|
||||
// // fallback for keys like Return, Escape, etc.
|
||||
// char name[64];
|
||||
// if (xkb_keysym_get_name(keysym, name, sizeof(name)) > 0) {
|
||||
// printf("Key %s pressed (non-printable or multi-char)\n", name);
|
||||
// }
|
||||
}
|
||||
if(state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
if(window->heldkeys[static_cast<std::uint8_t>(crafterKey)]) {
|
||||
window->onKeyHold[static_cast<std::uint8_t>(crafterKey)].Invoke();
|
||||
window->onAnyKeyHold.Invoke(crafterKey);
|
||||
} else{
|
||||
window->heldkeys[static_cast<std::uint8_t>(crafterKey)] = true;
|
||||
window->onKeyDown[static_cast<std::uint8_t>(crafterKey)].Invoke();
|
||||
window->onAnyKeyDown.Invoke(crafterKey);
|
||||
}
|
||||
} else{
|
||||
window->heldkeys[static_cast<std::uint8_t>(crafterKey)] = false;
|
||||
window->onKeyUp[static_cast<std::uint8_t>(crafterKey)].Invoke();
|
||||
window->onAnyKeyUp.Invoke(crafterKey);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowWayland::keyboard_modifiers(void *data, wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue