From bc48a8f62eea706ba89dedade16f57db4d801219 Mon Sep 17 00:00:00 2001 From: Daniil Vinogradov Date: Sat, 14 Dec 2024 20:15:23 +0100 Subject: [PATCH] WIP: CGImage --- CMakeLists.txt | 4 +- Submodules/UIKit/include/CALayer.h | 12 +++ Submodules/UIKit/include/CGImage.h | 8 +- Submodules/UIKit/include/Geometry.h | 48 ++++++---- Submodules/UIKit/include/NXData.h | 8 +- Submodules/UIKit/include/UIView.h | 26 ++++- Submodules/UIKit/lib/CALayer.cpp | 76 ++++++++++++--- Submodules/UIKit/lib/CGImage.cpp | 16 ++-- Submodules/UIKit/lib/Geometry.cpp | 142 +++++++++++++++++----------- Submodules/UIKit/lib/NXData.cpp | 16 ++-- Submodules/UIKit/lib/UIView.cpp | 23 +++++ Submodules/cmake/toolchain.cmake | 2 +- app/AppDelegate.cpp | 17 +++- 13 files changed, 283 insertions(+), 115 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5539d97..d75280e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,8 @@ set(PROJECT_ICON ${CMAKE_CURRENT_SOURCE_DIR}/resources/img/moonlight_icon.jpg) set(PROJECT_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/resources) set(CMAKE_CXX_STANDARD 17) +add_libromfs(${PROJECT_NAME} ${PROJECT_RESOURCES}) + add_executable(${PROJECT_NAME} app/main.cpp app/AppDelegate.cpp @@ -23,7 +25,7 @@ add_executable(${PROJECT_NAME} setup_project() -target_link_libraries(${PROJECT_NAME} PRIVATE +target_link_libraries(${PROJECT_NAME} UIKit ) diff --git a/Submodules/UIKit/include/CALayer.h b/Submodules/UIKit/include/CALayer.h index d922393..b044b46 100644 --- a/Submodules/UIKit/include/CALayer.h +++ b/Submodules/UIKit/include/CALayer.h @@ -51,12 +51,21 @@ class CALayer: public enable_shared_from_this { void setTransform(NXTransform3D transform); [[nodiscard]] NXTransform3D transform() const { return _transform; } + void setAffineTransform(NXAffineTransform transform); + [[nodiscard]] NXAffineTransform affineTransform(); + void setMask(std::shared_ptr mask); [[nodiscard]] std::shared_ptr mask() const { return _mask; } + void setMasksToBounds(bool newValue) { _masksToBounds = newValue; } + [[nodiscard]] bool masksToBounds() { return _masksToBounds; } + void setContents(std::shared_ptr contents); [[nodiscard]] std::shared_ptr contents() { return _contents; } + void setHidden(bool hidden); + [[nodiscard]] bool isHidden() const { return _isHidden; } + NXRect getFrame(); void setFrame(NXRect frame); @@ -84,7 +93,10 @@ class CALayer: public enable_shared_from_this { std::vector> _sublayers; std::shared_ptr _mask; + bool _isHidden = false; + std::shared_ptr _contents; + bool _masksToBounds = false; // Animatable NXPoint _anchorPoint = NXPoint(0.5, 0.5); diff --git a/Submodules/UIKit/include/CGImage.h b/Submodules/UIKit/include/CGImage.h index 1f86bb9..863fcf5 100644 --- a/Submodules/UIKit/include/CGImage.h +++ b/Submodules/UIKit/include/CGImage.h @@ -16,14 +16,14 @@ class CGImage { sk_sp pointee; // CGImage(NXSize size); - CGImage(const NXData& sourceData); + CGImage(std::shared_ptr sourceData); // CGImage(SDL_Surface* surface); - CGImage(sk_sp image, std::optional sourceData); - CGImage(sk_sp image): CGImage(image, std::nullopt) {} + CGImage(sk_sp image, std::shared_ptr sourceData); + CGImage(sk_sp image): CGImage(image, nullptr) {} ~CGImage(); [[nodiscard]] NXSize size() const; private: - std::optional sourceData; + std::shared_ptr sourceData; }; } diff --git a/Submodules/UIKit/include/Geometry.h b/Submodules/UIKit/include/Geometry.h index e70f799..5ebca0a 100644 --- a/Submodules/UIKit/include/Geometry.h +++ b/Submodules/UIKit/include/Geometry.h @@ -36,6 +36,7 @@ struct NXSize { NXSize(NXFloat width, NXFloat height); bool operator==(const NXSize &rhs) const; + bool operator!=(const NXSize &rhs) const; NXSize operator+(const NXSize &first) const; NXSize operator-(const NXSize &first) const; @@ -57,33 +58,46 @@ struct NXRect { NXRect(); NXRect(NXPoint origin, NXSize size); - NXRect(NXFloat x, NXFloat y, NXFloat width, NXFloat height); + NXRect(float x, float y, float width, float height); - NXFloat width() const; - NXFloat height() const; + float width() const; + float height() const; - NXFloat minX() const; - NXFloat midX() const; - NXFloat maxX() const; + float minX() const; + float midX() const; + float maxX() const; - NXFloat minY() const; - NXFloat midY() const; - NXFloat maxY() const; + float minY() const; + float midY() const; + float maxY() const; + + void setWidth(float newValue); + void setHeight(float newValue); + + void setMinX(float newValue); + void setMidX(float newValue); + void setMaxX(float newValue); + + void setMinY(float newValue); + void setMidY(float newValue); + void setMaxY(float newValue); bool contains(NXPoint point); bool intersects(const NXRect& other) const; - NXRect intersection(const NXRect& other) const; NXRect& offsetBy(const NXPoint& offset); - NXRect& offsetBy(const NXFloat& offsetX, const NXFloat& offsetY); -// NXRect& insetBy(const UIEdgeInsets& insets); - NXRect applying(const NXAffineTransform& t) const; - NXRect applying(const NXTransform3D& t) const; + NXRect& offsetBy(const float& offsetX, const float& offsetY); - bool operator==(const NXRect& rhs); + bool operator==(const NXRect& rhs) const; + NXRect operator+(const NXRect& rhs) const; + NXRect operator-(const NXRect& rhs) const; + NXRect operator*(const float& rhs) const; - bool valid(); + NXRect applying(NXAffineTransform transform); + NXRect applying(NXTransform3D transform); + + NXRect intersection(NXRect other) const; - static NXRect zero; + bool isNull() const; static NXRect null; }; diff --git a/Submodules/UIKit/include/NXData.h b/Submodules/UIKit/include/NXData.h index 24e6b59..43a349a 100644 --- a/Submodules/UIKit/include/NXData.h +++ b/Submodules/UIKit/include/NXData.h @@ -9,15 +9,15 @@ namespace NXKit { class NXData { public: - int count() const; - uint8_t* data() const; + std::size_t count() const; + const std::byte* data() const; - NXData(uint8_t* bytes, int count, bool freeSource = false); + NXData(const std::byte* bytes, std::size_t count, bool freeSource = false); ~NXData(); static std::optional fromPath(const std::string& path); private: - std::vector _data; + std::vector _data; }; } diff --git a/Submodules/UIKit/include/UIView.h b/Submodules/UIKit/include/UIView.h index 27c3932..b7df0c0 100644 --- a/Submodules/UIKit/include/UIView.h +++ b/Submodules/UIKit/include/UIView.h @@ -8,6 +8,30 @@ class UIView: public enable_shared_from_this { public: UIView(); + void setFrame(NXRect frame); + NXRect frame() const { return _layer->getFrame(); } + + void setBounds(NXRect bounds); + NXRect bounds() const { return _layer->bounds(); } + + void setCenter(NXPoint position); + NXPoint center() const; + + void setAlpha(NXFloat alpha) { _layer->setOpacity(alpha); } + NXFloat alpha() const { return _layer->opacity(); } + + void setHidden(bool hidden) { _layer->setHidden(hidden); } + bool isHidden() const { return _layer->isHidden(); } + + void setClipsToBounds(bool clipsToBounds) { _layer->setMasksToBounds(clipsToBounds); } + bool clipsToBounds() const { return _layer->masksToBounds(); } + + void setTransform(NXAffineTransform transform) { _layer->setAffineTransform(transform); } + NXAffineTransform transform() const { return _layer->affineTransform(); } + + void setBackgroundColor(std::optional backbroundColor) { _layer->setBackgroundColor(backbroundColor); } + std::optional backgroundColor() const { return _layer->backgroundColor(); } + virtual void addSubview(std::shared_ptr view); void insertSubviewAt(std::shared_ptr view, int index); void insertSubviewBelow(std::shared_ptr view, std::shared_ptr belowSubview); @@ -27,4 +51,4 @@ class UIView: public enable_shared_from_this { void setSuperview(std::shared_ptr superview); }; -} \ No newline at end of file +} diff --git a/Submodules/UIKit/lib/CALayer.cpp b/Submodules/UIKit/lib/CALayer.cpp index d335612..78355cb 100644 --- a/Submodules/UIKit/lib/CALayer.cpp +++ b/Submodules/UIKit/lib/CALayer.cpp @@ -5,6 +5,9 @@ #include "CALayer.h" #include "include/core/SkRRect.h" +#include "include/effects/SkGradientShader.h" +#include "include/effects/SkImageFilters.h" + using namespace NXKit; bool CALayer::layerTreeIsDirty = true; @@ -59,6 +62,19 @@ void CALayer::setTransform(NXTransform3D transform) { _transform = transform; } +void CALayer::setAffineTransform(NXAffineTransform transform) { + this->setTransform(NXTransform3DMakeAffineTransform(transform)); +} + +NXAffineTransform CALayer::affineTransform() { + return NXTransform3DGetAffineTransform(_transform); +} + +void CALayer::setHidden(bool hidden) { + _isHidden = hidden; + CALayer::layerTreeIsDirty = true; +} + void CALayer::setContents(std::shared_ptr contents) { _contents = contents; CALayer::layerTreeIsDirty = true; @@ -133,6 +149,11 @@ void CALayer::skiaRender(SkCanvas* canvas) { paint.setAntiAlias(true); SkRect rect = SkRect::MakeXYWH(0, 0, _bounds.width(), _bounds.height()); + // Opacity enable + if (_opacity < 1) { + canvas->saveLayerAlphaf(nullptr, _opacity); + } + // Background color if (_backgroundColor.has_value()) { paint.setColor(_backgroundColor->color); @@ -147,20 +168,22 @@ void CALayer::skiaRender(SkCanvas* canvas) { // Content if (_contents) { auto contentsGravity = ContentsGravityTransformation(this); - canvas->drawImageRect(_contents.get()->pointee, rect, SkSamplingOptions()); -// GPU_SetAnchor(_contents->pointee, _anchorPoint.x, _anchorPoint.y); -// GPU_SetRGBA(_contents->pointee, 255, 255, 255, _opacity * 255); -// -// GPU_BlitTransform( -// _contents->pointee, -// NULL, -// renderer, -// contentsGravity.offset.x, -// contentsGravity.offset.y, -// 0, // rotation in degrees -// contentsGravity.scale.width / contentsScale, -// contentsGravity.scale.height / contentsScale -// ); + auto width = _contents->size().width * contentsGravity.scale.width / _contentsScale; + auto height = _contents->size().height * contentsGravity.scale.height / _contentsScale; + auto x = (_bounds.size.width - width) / 2.0 + contentsGravity.offset.x; + auto y = (_bounds.size.height - height) / 2.0 + contentsGravity.offset.y; + + canvas->save(); + canvas->translate(x, y); + + canvas->drawImageRect(_contents.get()->pointee, { + float(0), + float(0), + float(width), + float(height) + }, SkSamplingOptions(), nullptr); + + canvas->restore(); } // Reset Anchor to Origin matrix @@ -168,6 +191,10 @@ void CALayer::skiaRender(SkCanvas* canvas) { for (const auto& sublayer: _sublayers) { sublayer->skiaRender(canvas); } + // Opacity disable + if (_opacity < 1) { + canvas->restore(); + } canvas->restore(); } @@ -187,6 +214,27 @@ NXRect CALayer::getFrame() { transformedBounds.height()); } +void CALayer::setFrame(NXRect frame) { + setPosition(NXPoint(frame.origin.x + (frame.width() * _anchorPoint.x), + frame.origin.y + (frame.height() * _anchorPoint.y))); + + auto inverseTransformOpt = affineTransform().inverted(); + if (!inverseTransformOpt.has_value()) { +// assertionFailure("You tried to set the frame of a CALayer whose transform cannot be inverted. This is undefined behaviour."); + return; + } + auto inverseTransform = inverseTransformOpt.value(); + + + // If we are shrinking the view with a transform and then setting a + // new frame, the layer's actual `bounds` is bigger (and vice-versa): + auto nonTransformedBoundSize = frame.applying(inverseTransform).size; + + auto bounds = _bounds; + bounds.size = nonTransformedBoundSize; + setBounds(bounds); +} + void CALayer::onWillSet(std::string keyPath) { CALayer::layerTreeIsDirty = true; auto animationKey = keyPath; diff --git a/Submodules/UIKit/lib/CGImage.cpp b/Submodules/UIKit/lib/CGImage.cpp index 46a5216..df0a8ce 100644 --- a/Submodules/UIKit/lib/CGImage.cpp +++ b/Submodules/UIKit/lib/CGImage.cpp @@ -12,8 +12,8 @@ using namespace NXKit; //// GPU_SetBlendMode(pointee, GPU_BLEND_NORMAL_FACTOR_ALPHA); //} -CGImage::CGImage(sk_sp image, std::optional sourceData) { - this->sourceData = std::move(sourceData); +CGImage::CGImage(sk_sp image, std::shared_ptr sourceData) { + this->sourceData = sourceData; pointee = image; // GPU_SetSnapMode(pointee, GPU_SNAP_POSITION_AND_DIMENSIONS); @@ -21,14 +21,14 @@ CGImage::CGImage(sk_sp image, std::optional sourceData) { // GPU_SetImageFilter(pointee, GPU_FILTER_LINEAR); } -CGImage::CGImage(const NXData& sourceData) { - auto data = sourceData; - auto dataCount = data.count(); +CGImage::CGImage(std::shared_ptr sourceData) { + auto data = sourceData->data(); + auto dataCount = sourceData->count(); - auto skData = SkData::MakeFromMalloc(data.data(), data.count()); + auto skData = SkData::MakeWithoutCopy(data, dataCount); auto image = SkImages::DeferredFromEncodedData(skData); - new (this) CGImage(image, data); + new (this) CGImage(image, sourceData); } //CGImage::CGImage(SDL_Surface* surface) { @@ -39,6 +39,8 @@ CGImage::CGImage(const NXData& sourceData) { //} CGImage::~CGImage() { + sourceData = nullptr; + pointee = nullptr; // GPU_FreeTarget(pointee->target); // GPU_FreeImage(pointee); } diff --git a/Submodules/UIKit/lib/Geometry.cpp b/Submodules/UIKit/lib/Geometry.cpp index 6c8533d..d9fbaab 100644 --- a/Submodules/UIKit/lib/Geometry.cpp +++ b/Submodules/UIKit/lib/Geometry.cpp @@ -94,6 +94,10 @@ bool NXSize::operator==(const NXSize& rhs) const { return isEqual(this->width, rhs.width) && isEqual(this->height, rhs.height); } +bool NXSize::operator!=(const NXSize& rhs) const { + return !isEqual(this->width, rhs.width) || !isEqual(this->height, rhs.height); +} + NXSize NXSize::operator+(const NXSize& first) const { return NXSize(width + first.width, height + first.height); } @@ -141,68 +145,86 @@ bool NXSize::valid() { // MARK: - RECT - NXRect::NXRect(): origin(), size() { } NXRect::NXRect(NXPoint origin, NXSize size): origin(origin), size(size) { } -NXRect::NXRect(NXFloat x, NXFloat y, NXFloat width, NXFloat height): origin(x, y), size(width, height) { } +NXRect::NXRect(float x, float y, float width, float height): origin(x, y), size(width, height) { } + +float NXRect::width() const { return size.width; } +float NXRect::height() const { return size.height; } + +float NXRect::minX() const { return origin.x; } +float NXRect::midX() const { return origin.x + size.width / 2; } +float NXRect::maxX() const { return origin.x + size.width; } -NXFloat NXRect::width() const { return size.width; } -NXFloat NXRect::height() const { return size.height; } +float NXRect::minY() const { return origin.y; } +float NXRect::midY() const { return origin.y + size.height / 2; } +float NXRect::maxY() const { return origin.y + size.height; } -NXFloat NXRect::minX() const { return origin.x; } -NXFloat NXRect::midX() const { return origin.x + size.width / 2; } -NXFloat NXRect::maxX() const { return origin.x + size.width; } +void NXRect::setWidth(float newValue) { size.width = newValue; } +void NXRect::setHeight(float newValue) { size.height = newValue; } -NXFloat NXRect::minY() const { return origin.y; } -NXFloat NXRect::midY() const { return origin.y + size.height / 2; } -NXFloat NXRect::maxY() const { return origin.y + size.height; } +void NXRect::setMinX(float newValue) { origin.x = newValue; } +void NXRect::setMidX(float newValue) { origin.x = newValue - (size.width / 2); } +void NXRect::setMaxX(float newValue) { origin.x = newValue - size.width; } + +void NXRect::setMinY(float newValue) { origin.y = newValue; } +void NXRect::setMidY(float newValue) { origin.y = newValue - (size.height / 2); } +void NXRect::setMaxY(float newValue) { origin.y = newValue - size.height; } bool NXRect::contains(NXPoint point) { return - (point.x >= minX()) && (point.x < maxX()) && - (point.y >= minY()) && (point.y < maxY()); + (point.x >= minX()) && (point.x < maxX()) && + (point.y >= minY()) && (point.y < maxY()); } bool NXRect::intersects(const NXRect& other) const { return !((minX() > other.maxX() || maxX() < other.minX()) || (minY() > other.maxY() || maxY() < other.minY())); } -NXRect NXRect::intersection(const NXRect& other) const { - auto largestMinX = std::max(minX(), other.minX()); - auto largestMinY = std::max(minY(), other.minY()); - - auto smallestMaxX = std::min(maxX(), other.maxX()); - auto smallestMaxY = std::min(maxY(), other.maxY()); - - auto width = smallestMaxX - largestMinX; - auto height = smallestMaxY - largestMinY; - - if (width > 0 && height > 0) { - // The intersection rectangle has dimensions, i.e. there is an intersection: - return NXRect(largestMinX, largestMinY, width, height); - } else { - return NXRect::null; - } -} - NXRect& NXRect::offsetBy(const NXPoint& offset) { origin.x += offset.x; origin.y += offset.y; return *this; } -NXRect& NXRect::offsetBy(const NXFloat& offsetX, const NXFloat& offsetY) { +NXRect& NXRect::offsetBy(const float& offsetX, const float& offsetY) { origin.x += offsetX; origin.y += offsetY; return *this; } -//NXRect& NXRect::insetBy(const UIEdgeInsets& insets) { -// origin.x -= insets.left; -// origin.y -= insets.top; -// size.width += insets.left + insets.right; -// size.height += insets.top + insets.bottom; -// return *this; -//} +bool NXRect::operator==(const NXRect& rhs) const { + return + this->origin.x == rhs.origin.x && this->origin.y == rhs.origin.y && + this->size.width == rhs.size.width && this->size.height == rhs.size.height; +} + +NXRect NXRect::operator+(const NXRect& rhs) const { + return NXRect( + this->origin.x + rhs.origin.x, + this->origin.y + rhs.origin.y, + this->size.width + rhs.size.width, + this->size.height + rhs.size.height + ); +} + +NXRect NXRect::operator-(const NXRect& rhs) const { + return NXRect( + this->origin.x - rhs.origin.x, + this->origin.y - rhs.origin.y, + this->size.width - rhs.size.width, + this->size.height - rhs.size.height + ); +} + +NXRect NXRect::operator*(const float& rhs) const { + return NXRect( + this->origin.x * rhs, + this->origin.y * rhs, + this->size.width * rhs, + this->size.height * rhs + ); +} -NXRect NXRect::applying(const NXAffineTransform& t) const { +NXRect NXRect::applying(NXAffineTransform t) { if (t.isIdentity()) { return *this; } auto newTopLeft = NXPoint(minX(), minY()).applying(t); @@ -210,7 +232,6 @@ NXRect NXRect::applying(const NXAffineTransform& t) const { auto newBottomLeft = NXPoint(minX(), maxY()).applying(t); auto newBottomRight = NXPoint(maxX(), maxY()).applying(t); - auto newMinX = min(newTopLeft.x, newTopRight.x, newBottomLeft.x, newBottomRight.x); auto newMaxX = max(newTopLeft.x, newTopRight.x, newBottomLeft.x, newBottomRight.x); @@ -219,14 +240,13 @@ NXRect NXRect::applying(const NXAffineTransform& t) const { // XXX: What happens if the point that was furthest left is now on the right (because of a rotation)? // i.e. Should do we return a normalised rect or one with a negative width? - return NXRect( - newMinX, - newMinY, - newMaxX - newMinX, - newMaxY - newMinY); + return NXRect(newMinX, + newMinY, + newMaxX - newMinX, + newMaxY - newMinY); } -NXRect NXRect::applying(const NXTransform3D& t) const { +NXRect NXRect::applying(NXTransform3D t) { if (t == NXTransform3DIdentity) { return *this; } auto topLeft = t.transformingVector(minX(), minY(), 0); @@ -240,21 +260,29 @@ NXRect NXRect::applying(const NXTransform3D& t) const { auto newMinY = min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y); auto newMaxY = max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y); - return NXRect(newMinX, - newMinY, - newMaxX - newMinX, - newMaxY - newMinY); + return NXRect(newMinX, newMinY, newMaxX - newMinX, newMaxY - newMinY); } -bool NXRect::operator==(const NXRect& rhs) { - return - this->origin.x == rhs.origin.x && this->origin.y == rhs.origin.y && - this->size.width == rhs.size.width && this->size.height == rhs.size.height; +NXRect NXRect::intersection(NXRect other) const { + auto largestMinX = fmaxf(minX(), other.minX()); + auto largestMinY = fmaxf(minY(), other.minY()); + + auto smallestMaxX = fmaxf(maxX(), other.maxX()); + auto smallestMaxY = fmaxf(maxY(), other.maxY()); + + auto width = smallestMaxX - largestMinX; + auto height = smallestMaxY - largestMinY; + + if (width > 0 && height > 0) { + // The intersection rectangle has dimensions, i.e. there is an intersection: + return NXRect(largestMinX, largestMinY, width, height); + } else { + return null; + } } -bool NXRect::valid() { - return this->origin.valid() && this->size.valid(); +bool NXRect::isNull() const { + return *this == null; } -NXRect NXRect::zero = NXRect(); -NXRect NXRect::null = NXRect(std::numeric_limits::infinity(), std::numeric_limits::infinity(), 0, 0); +NXRect NXRect::null = NXRect(INFINITY, INFINITY, 0, 0); diff --git a/Submodules/UIKit/lib/NXData.cpp b/Submodules/UIKit/lib/NXData.cpp index c07a71c..d699d15 100644 --- a/Submodules/UIKit/lib/NXData.cpp +++ b/Submodules/UIKit/lib/NXData.cpp @@ -8,7 +8,7 @@ namespace NXKit { -NXData::NXData(uint8_t bytes[], int count, bool freeSource) { +NXData::NXData(const std::byte bytes[], std::size_t count, bool freeSource) { for (int i = 0; i < count; i++) _data.push_back(bytes[i]); @@ -16,14 +16,16 @@ NXData::NXData(uint8_t bytes[], int count, bool freeSource) { delete[] bytes; } -NXData::~NXData() = default; +NXData::~NXData() { +// _data.clear(); +} -int NXData::count() const { - return (int) _data.size(); +std::size_t NXData::count() const { + return _data.size(); } -uint8_t* NXData::data() const { - return (uint8_t*) _data.data(); +const std::byte* NXData::data() const { + return _data.data(); } std::optional NXData::fromPath(const std::string& path) { @@ -36,7 +38,7 @@ std::optional NXData::fromPath(const std::string& path) { auto fileSize = int(fileReader->size(fileReader)); - auto buffer = new uint8_t[fileSize]; + auto buffer = new std::byte[fileSize]; auto bytesRead = int(fileReader->read(fileReader, buffer, 1, fileSize)); diff --git a/Submodules/UIKit/lib/UIView.cpp b/Submodules/UIKit/lib/UIView.cpp index 989e3b8..49b6e68 100644 --- a/Submodules/UIKit/lib/UIView.cpp +++ b/Submodules/UIKit/lib/UIView.cpp @@ -7,6 +7,29 @@ UIView::UIView() { _layer->setAnchorPoint(NXPoint::zero); } +void UIView::setFrame(NXRect frame) { + if (this->frame().size != frame.size) { +// setNeedsLayout(); + } + _layer->setFrame(frame); +// setNeedsUpdateSafeAreaInsets(); +} + +void UIView::setBounds(NXRect bounds) { + if (this->bounds().size != bounds.size) { +// setNeedsLayout(); +// setNeedsUpdateSafeAreaInsets(); + } + _layer->setBounds(bounds); +} + +void UIView::setCenter(NXPoint position) { + auto frame = this->frame(); + frame.setMidX(position.x); + frame.setMidY(position.y); + setFrame(frame); +} + void UIView::addSubview(std::shared_ptr view) { bool needToNotifyViewController = false; // if (!view->_parentController.expired()) { diff --git a/Submodules/cmake/toolchain.cmake b/Submodules/cmake/toolchain.cmake index 06f9dc3..30a7c52 100644 --- a/Submodules/cmake/toolchain.cmake +++ b/Submodules/cmake/toolchain.cmake @@ -158,8 +158,8 @@ function(setup_project) add_subdirectory(${EXTERN_PATH}) add_subdirectory(${EXTERN_PATH}/UIKit) - add_libromfs(${PROJECT_NAME} ${PROJECT_RESOURCES}) add_subdirectory(${EXTERN_PATH}/libromfs EXCLUDE_FROM_ALL) + target_link_libraries(${PROJECT_NAME} ${LIBROMFS_LIBRARY}) # target_link_libraries(${PROJECT_NAME} fmt tweeny yogacore ${PLATFORM_LIBS}) endfunction() \ No newline at end of file diff --git a/app/AppDelegate.cpp b/app/AppDelegate.cpp index b7382c9..48ddbac 100644 --- a/app/AppDelegate.cpp +++ b/app/AppDelegate.cpp @@ -1,4 +1,5 @@ #include +#include "romfs/romfs.hpp" // #include // #include // #include @@ -19,15 +20,27 @@ bool UIApplicationDelegate::applicationDidFinishLaunchingWithOptions(UIApplicati auto sublayer = new_shared(); sublayer->setPosition({ 100, 100 }); - sublayer->setBounds({0, 0, 200, 44}); + sublayer->setBounds({ 0, 0, 200, 44 }); sublayer->setBackgroundColor(UIColor::tint); sublayer->setCornerRadius(10); sublayer->setAnchorPoint(NXPoint::zero); + sublayer->setOpacity(0.5); // sublayer->setTransform(NXTransform3D::identity.rotationBy(45, 0, 0, 1)); window->layer()->addSublayer(sublayer); - + auto res = romfs::get("img/star.png"); + auto data = new_shared(res.data(), (int) res.size()); + auto image = new_shared(data); + + auto imageLayer = new_shared(); + imageLayer->setContents(image); + imageLayer->setFrame({ 0, 0, 120, 120 }); + imageLayer->setBackgroundColor(UIColor::green); + imageLayer->setContentsGravity(CALayerContentsGravity::topLeft); + + sublayer->addSublayer(imageLayer); + return true; }