From 1a51f9a0e0fb109191432e771389218b81ffbfbc Mon Sep 17 00:00:00 2001 From: shima11 Date: Sun, 3 Mar 2024 01:11:12 +0900 Subject: [PATCH 1/2] update --- Dev/Brightroom.xcodeproj/project.pbxproj | 4 + .../xcshareddata/swiftpm/Package.resolved | 73 +----------- Dev/Sources/SwiftUIDemo/DemoCropView2.swift | 110 ++++++++++++++++++ .../Crop/CropView.CropOutsideOverlay.swift | 58 ++++++++- .../Components/Crop/SwiftUICropView.swift | 35 +++++- .../PhotosCropRotating.swift | 4 +- 6 files changed, 208 insertions(+), 76 deletions(-) create mode 100644 Dev/Sources/SwiftUIDemo/DemoCropView2.swift diff --git a/Dev/Brightroom.xcodeproj/project.pbxproj b/Dev/Brightroom.xcodeproj/project.pbxproj index 5599cfc5..bfbb877e 100644 --- a/Dev/Brightroom.xcodeproj/project.pbxproj +++ b/Dev/Brightroom.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 0451857F2B8F4A9E00A74713 /* DemoCropView2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0451857E2B8F4A9E00A74713 /* DemoCropView2.swift */; }; 4B135F6E26136B5D003B5152 /* RendererOrientationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B135F6D26136B5D003B5152 /* RendererOrientationTests.swift */; }; 4B2324E42B763D4A00662EB8 /* GeometryPlayground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B2324E32B763D4A00662EB8 /* GeometryPlayground.swift */; }; 4B2A1107266B7B3000B0C885 /* test-image-10 in Resources */ = {isa = PBXBuildFile; fileRef = 4B2A10FA266B7B3000B0C885 /* test-image-10 */; }; @@ -568,6 +569,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0451857E2B8F4A9E00A74713 /* DemoCropView2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoCropView2.swift; sourceTree = ""; }; 4B135F6D26136B5D003B5152 /* RendererOrientationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RendererOrientationTests.swift; sourceTree = ""; }; 4B2324E32B763D4A00662EB8 /* GeometryPlayground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeometryPlayground.swift; sourceTree = ""; }; 4B254FE6260BB32600F77E9A /* orientation_left_mirrored.HEIC */ = {isa = PBXFileReference; lastKnownFileType = file; path = orientation_left_mirrored.HEIC; sourceTree = ""; }; @@ -1254,6 +1256,7 @@ 4B8CAF6825FFCD720075032A /* IsolatedEditingView.swift */, 4B8CAF7225FFD13D0075032A /* BlurryMaskingViewWrapper.swift */, 4B75113F25F13276002D804A /* DemoCropView.swift */, + 0451857E2B8F4A9E00A74713 /* DemoCropView2.swift */, 4B98CCC425EFF31400E4F61F /* Info.plist */, 4B98CCC125EFF31400E4F61F /* Preview Content */, 4BB9180B25F5460000C446B8 /* Launch Screen.storyboard */, @@ -2430,6 +2433,7 @@ 4BA9896F2B70BF2000EB7983 /* RenderedResultView.swift in Sources */, 4B98CCBE25EFF31300E4F61F /* ContentView.swift in Sources */, 4B75114025F13276002D804A /* DemoCropView.swift in Sources */, + 0451857F2B8F4A9E00A74713 /* DemoCropView2.swift in Sources */, 4B9325832B6A923400DDABAC /* RotateScrollView.swift in Sources */, 4B98CCBC25EFF31300E4F61F /* SwiftUIDemoApp.swift in Sources */, 4B98CCE725EFF4EF00E4F61F /* Mocks.swift in Sources */, diff --git a/Dev/Brightroom.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Dev/Brightroom.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index aa65d018..88a8f20c 100644 --- a/Dev/Brightroom.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Dev/Brightroom.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,48 +1,12 @@ { "pins" : [ - { - "identity" : "assetspicker", - "kind" : "remoteSourceControl", - "location" : "https://github.com/eure/AssetsPicker.git", - "state" : { - "branch" : "master", - "revision" : "7908a947243c9fb8014ab8ce85095f61edf2b113" - } - }, - { - "identity" : "descriptors", - "kind" : "remoteSourceControl", - "location" : "https://github.com/FluidGroup/Descriptors", - "state" : { - "revision" : "f41ce2605a76c5d378fe8c5e8c5c98b544dfd108", - "version" : "0.2.3" - } - }, - { - "identity" : "glossbuttonnode", - "kind" : "remoteSourceControl", - "location" : "https://github.com/FluidGroup/GlossButtonNode", - "state" : { - "branch" : "main", - "revision" : "725ffe6041691e4533558253c77db01555eda0a9" - } - }, - { - "identity" : "mondrianlayout", - "kind" : "remoteSourceControl", - "location" : "https://github.com/muukii/MondrianLayout.git", - "state" : { - "revision" : "5f00b13984fe08316fc5b5be06e2f41c14a3befa", - "version" : "0.10.0" - } - }, { "identity" : "precisionlevelslider", "kind" : "remoteSourceControl", "location" : "https://github.com/FluidGroup/PrecisionLevelSlider", "state" : { - "revision" : "6a6d1cbe962225d097012f47038f536c72e26c91", - "version" : "2.0.2" + "revision" : "3e460c1cea5ec916f7185948bc0a4e093e20f7a5", + "version" : "2.1.0" } }, { @@ -99,37 +63,10 @@ "version" : "1.2.0" } }, - { - "identity" : "swiftui-support", - "kind" : "remoteSourceControl", - "location" : "https://github.com/FluidGroup/swiftui-support.git", - "state" : { - "revision" : "c610c1e46c14c4660beb4ef7fe0241941dbecdc6", - "version" : "0.5.0" - } - }, - { - "identity" : "texture", - "kind" : "remoteSourceControl", - "location" : "https://github.com/FluidGroup/Texture.git", - "state" : { - "revision" : "68df47f0d26522da76b06f22e9a97e4d4ab58dad", - "version" : "3.0.2" - } - }, - { - "identity" : "textureswiftsupport", - "kind" : "remoteSourceControl", - "location" : "https://github.com/FluidGroup/TextureSwiftSupport", - "state" : { - "branch" : "main", - "revision" : "5bae50cab3798dccb8b98c3ffbc70320ae66b45a" - } - }, { "identity" : "transitionpatch", "kind" : "remoteSourceControl", - "location" : "https://github.com/muukii/TransitionPatch.git", + "location" : "https://github.com/FluidGroup/TransitionPatch.git", "state" : { "revision" : "88aac5305fe568ef62f73a3cf19f0b8392ffb52c", "version" : "1.0.5" @@ -140,8 +77,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/VergeGroup/Verge.git", "state" : { - "revision" : "790f1ef9af22f62fc7944f924ef4466dde071c2a", - "version" : "12.1.0" + "revision" : "a338c22b82c9a686a7131b54fa84ddad773f5c2a", + "version" : "12.0.0-beta.4" } } ], diff --git a/Dev/Sources/SwiftUIDemo/DemoCropView2.swift b/Dev/Sources/SwiftUIDemo/DemoCropView2.swift new file mode 100644 index 00000000..fa26f373 --- /dev/null +++ b/Dev/Sources/SwiftUIDemo/DemoCropView2.swift @@ -0,0 +1,110 @@ +// +// DemoCropView2.swift +// SwiftUIDemo +// +// Created by Jinsei Shima on 2024/02/28. +// Copyright © 2024 muukii. All rights reserved. +// + +import BrightroomEngine +import BrightroomUI +import BrightroomUIPhotosCrop +import SwiftUI +import UIKit +import SwiftUISupport + +struct DemoCropView2: View { + + @StateObject var editingStack: EditingStack + @State var resultImage: ResultImage? + + init( + editingStack: @escaping () -> EditingStack + ) { + self._editingStack = .init(wrappedValue: editingStack()) + } + + var body: some View { + ZStack { + + VStack { + + Spacer() + + SwiftUICropView( + editingStack: editingStack, + isGuideInteractionEnabled: false, + contentInset: .init(top: 20, left: 20, bottom: 20, right: 20), + cropInsideOverlay: { kind in + ViewHost(instantiated: CropView.RuleOfThirdsView(lineColor: .white)) + .overlay { + Rectangle() + .fill(kind == nil ? Color.white : Color.white.opacity(0.6)) + .overlay { + RoundedRectangle(cornerRadius: 24, style: .continuous) + .blendMode(.destinationOut) + } + .compositingGroup() + } + }, + cropOutsideOverlay: { kind in + Rectangle() + .fill(kind == nil ? Color.white : Color.white.opacity(0.6)) + } + ) + .frame(height: 500) + .clipped() + + Spacer() + + } + + VStack { + HStack { + Spacer() + Button("Done") { + let image = try! editingStack.makeRenderer().render().cgImage + self.resultImage = .init(cgImage: image) + } + .buttonStyle(.borderedProminent) + .buttonBorderShape(.capsule) + .tint(.yellow) + .foregroundColor(.black) + } + Spacer() + } + .padding(.horizontal, 30) + .padding(.vertical, 15) + .ignoresSafeArea() + + } + .onAppear { + editingStack.start() + } + .sheet(item: $resultImage) { + RenderedResultView(result: $0) + } + } + +} + +#Preview("local") { + DemoCropView2( + editingStack: { Mocks.makeEditingStack(image: Mocks.imageHorizontal()) } + ) +} + +#Preview("remote") { + DemoCropView2( + editingStack: { + EditingStack( + imageProvider: .init( + editableRemoteURL: URL( + string: + "https://images.unsplash.com/photo-1604456930969-37f67bcd6e1e?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1" + )! + ) + ) + } + ) +} diff --git a/Sources/BrightroomUI/Shared/Components/Crop/CropView.CropOutsideOverlay.swift b/Sources/BrightroomUI/Shared/Components/Crop/CropView.CropOutsideOverlay.swift index 794084b6..70ab638c 100644 --- a/Sources/BrightroomUI/Shared/Components/Crop/CropView.CropOutsideOverlay.swift +++ b/Sources/BrightroomUI/Shared/Components/Crop/CropView.CropOutsideOverlay.swift @@ -7,11 +7,12 @@ // import UIKit +import SwiftUI extension CropView { open class CropOutsideOverlayBase: PixelEditorCodeBasedView { - + open func didBeginAdjustment(kind: CropView.State.AdjustmentKind) { } @@ -74,4 +75,59 @@ extension CropView { } } + @available(iOS 14, *) + open class SwiftUICropOutsideOverlay: CropOutsideOverlayBase { + + private let controller: UIHostingController + private let proxy: Proxy + + public init(@ViewBuilder content: @escaping (CropView.State.AdjustmentKind?) -> Content) { + + self.proxy = .init() + self.controller = .init(rootView: Container(proxy: proxy, content: content)) + + controller.view.backgroundColor = .clear + controller.view.preservesSuperviewLayoutMargins = false + + super.init(frame: .zero) + + addSubview(controller.view) + AutoLayoutTools.setEdge(controller.view, self) + } + + open override func didBeginAdjustment(kind: CropView.State.AdjustmentKind) { + proxy.activeKind = kind + } + + open override func didEndAdjustment(kind: CropView.State.AdjustmentKind) { + proxy.activeKind = nil + } + + private final class Proxy: ObservableObject { + + @Published var activeKind: CropView.State.AdjustmentKind? + + } + + private struct Container: View { + + @ObservedObject var proxy: Proxy + + private let content: (CropView.State.AdjustmentKind?) -> Content + + public init( + proxy: Proxy, + content: @escaping (CropView.State.AdjustmentKind?) -> Content + ) { + self.content = content + self.proxy = proxy + } + + var body: some View { + content(proxy.activeKind) + } + } + + } + } diff --git a/Sources/BrightroomUI/Shared/Components/Crop/SwiftUICropView.swift b/Sources/BrightroomUI/Shared/Components/Crop/SwiftUICropView.swift index a122592a..4c938005 100644 --- a/Sources/BrightroomUI/Shared/Components/Crop/SwiftUICropView.swift +++ b/Sources/BrightroomUI/Shared/Components/Crop/SwiftUICropView.swift @@ -70,6 +70,8 @@ public struct SwiftUICropView: UIViewControllerRepresentable { public typealias UIViewControllerType = _PixelEditor_WrapperViewController private let cropInsideOverlay: ((CropView.State.AdjustmentKind?) -> AnyView)? + private let cropOutsideOverlay: ((CropView.State.AdjustmentKind?) -> AnyView)? + private let editingStack: EditingStack private var _rotation: EditingCrop.Rotation? @@ -78,38 +80,61 @@ public struct SwiftUICropView: UIViewControllerRepresentable { private var _resetAction: ResetAction? private let stateHandler: @MainActor (Verge.Changes) -> Void + private let isGuideInteractionEnabled: Bool + private let contentInset: UIEdgeInsets? - public init( + public init( editingStack: EditingStack, + isGuideInteractionEnabled: Bool = true, + contentInset: UIEdgeInsets? = nil, @ViewBuilder cropInsideOverlay: @escaping (CropView.State.AdjustmentKind?) -> InsideOverlay, + @ViewBuilder cropOutsideOverlay: @escaping (CropView.State.AdjustmentKind?) -> OutsideOverlay, stateHandler: @escaping @MainActor (Verge.Changes) -> Void = { _ in } ) { self.editingStack = editingStack + self.isGuideInteractionEnabled = isGuideInteractionEnabled + self.contentInset = contentInset self.cropInsideOverlay = { AnyView(cropInsideOverlay($0)) } + self.cropOutsideOverlay = { AnyView(cropOutsideOverlay($0)) } self.stateHandler = stateHandler } public init( editingStack: EditingStack, + isGuideInteractionEnabled: Bool = true, + contentInset: UIEdgeInsets? = nil, stateHandler: @escaping @MainActor (Verge.Changes) -> Void = { _ in } ) { self.cropInsideOverlay = nil + self.cropOutsideOverlay = nil self.editingStack = editingStack + self.isGuideInteractionEnabled = isGuideInteractionEnabled + self.contentInset = contentInset self.stateHandler = stateHandler } public func makeUIViewController(context: Context) -> _PixelEditor_WrapperViewController { - let view = CropView(editingStack: editingStack) + let view: CropView + if let contentInset { + view = .init(editingStack: editingStack, contentInset: contentInset) + } else { + view = .init(editingStack: editingStack) + } view.isAutoApplyEditingStackEnabled = true + view.isGuideInteractionEnabled = isGuideInteractionEnabled - let controller = _PixelEditor_WrapperViewController.init(bodyView: view) - - if let cropInsideOverlay = cropInsideOverlay { + if let cropInsideOverlay { view.setCropInsideOverlay(CropView.SwiftUICropInsideOverlay(content: cropInsideOverlay)) } + if let cropOutsideOverlay { + view.setCropOutsideOverlay(CropView.SwiftUICropOutsideOverlay(content: cropOutsideOverlay)) + } + + let controller = _PixelEditor_WrapperViewController.init(bodyView: view) + return controller } diff --git a/Sources/BrightroomUIPhotosCrop/PhotosCropRotating/PhotosCropRotating.swift b/Sources/BrightroomUIPhotosCrop/PhotosCropRotating/PhotosCropRotating.swift index 1d43e20a..ab8090ae 100644 --- a/Sources/BrightroomUIPhotosCrop/PhotosCropRotating/PhotosCropRotating.swift +++ b/Sources/BrightroomUIPhotosCrop/PhotosCropRotating/PhotosCropRotating.swift @@ -212,7 +212,7 @@ public struct PhotosCropRotating: View { source.rounded(.toNearestOrEven) } ), - centerLevel: { value in + centerLevel: { value, _ in HStack { Spacer() VStack { @@ -225,7 +225,7 @@ public struct PhotosCropRotating: View { } .foregroundStyle(.tint) }, - track: { value in + track: { value, _ in VStack { HStack { Spacer() From ae87989e67ed699c13a31b56c4c1d1959089fb64 Mon Sep 17 00:00:00 2001 From: shima11 Date: Sun, 3 Mar 2024 01:29:02 +0900 Subject: [PATCH 2/2] update --- .../xcshareddata/swiftpm/Package.resolved | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/Dev/Brightroom.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Dev/Brightroom.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 88a8f20c..b05bb2f6 100644 --- a/Dev/Brightroom.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Dev/Brightroom.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,41 @@ { "pins" : [ + { + "identity" : "assetspicker", + "kind" : "remoteSourceControl", + "location" : "https://github.com/eure/AssetsPicker.git", + "state" : { + "branch" : "master", + "revision" : "7908a947243c9fb8014ab8ce85095f61edf2b113" + } + }, + { + "identity" : "descriptors", + "kind" : "remoteSourceControl", + "location" : "https://github.com/FluidGroup/Descriptors", + "state" : { + "revision" : "f41ce2605a76c5d378fe8c5e8c5c98b544dfd108", + "version" : "0.2.3" + } + }, + { + "identity" : "glossbuttonnode", + "kind" : "remoteSourceControl", + "location" : "https://github.com/FluidGroup/GlossButtonNode", + "state" : { + "branch" : "main", + "revision" : "725ffe6041691e4533558253c77db01555eda0a9" + } + }, + { + "identity" : "mondrianlayout", + "kind" : "remoteSourceControl", + "location" : "https://github.com/muukii/MondrianLayout.git", + "state" : { + "revision" : "5f00b13984fe08316fc5b5be06e2f41c14a3befa", + "version" : "0.10.0" + } + }, { "identity" : "precisionlevelslider", "kind" : "remoteSourceControl", @@ -63,10 +99,37 @@ "version" : "1.2.0" } }, + { + "identity" : "swiftui-support", + "kind" : "remoteSourceControl", + "location" : "https://github.com/FluidGroup/swiftui-support.git", + "state" : { + "revision" : "c610c1e46c14c4660beb4ef7fe0241941dbecdc6", + "version" : "0.5.0" + } + }, + { + "identity" : "texture", + "kind" : "remoteSourceControl", + "location" : "https://github.com/FluidGroup/Texture.git", + "state" : { + "revision" : "68df47f0d26522da76b06f22e9a97e4d4ab58dad", + "version" : "3.0.2" + } + }, + { + "identity" : "textureswiftsupport", + "kind" : "remoteSourceControl", + "location" : "https://github.com/FluidGroup/TextureSwiftSupport", + "state" : { + "branch" : "main", + "revision" : "5bae50cab3798dccb8b98c3ffbc70320ae66b45a" + } + }, { "identity" : "transitionpatch", "kind" : "remoteSourceControl", - "location" : "https://github.com/FluidGroup/TransitionPatch.git", + "location" : "https://github.com/muukii/TransitionPatch.git", "state" : { "revision" : "88aac5305fe568ef62f73a3cf19f0b8392ffb52c", "version" : "1.0.5"