mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 01:10:09 +00:00
[WIP] Stickers editor
This commit is contained in:
parent
9ec01a7f24
commit
47d4d4c86c
@ -417,11 +417,11 @@ final class PremiumStickerPackAccessoryNode: SparseNode, PeekControllerAccessory
|
||||
|
||||
private func topItems(selectedEmoji: [String] = [], recommendedEmoji: [String], count: Int) -> [String] {
|
||||
var defaultItems: [String] = [
|
||||
"👍", "👎", "❤", "🔥", "🥰", "👏", "😁"
|
||||
"👍", "👎", "❤", "🔥", "🥰", "👏", "😁", "😎"
|
||||
]
|
||||
if !recommendedEmoji.isEmpty, let firstEmoji = recommendedEmoji.first {
|
||||
defaultItems.removeLast()
|
||||
defaultItems.append(firstEmoji)
|
||||
defaultItems.remove(at: defaultItems.count - 2)
|
||||
defaultItems.insert(firstEmoji, at: defaultItems.count - 1)
|
||||
}
|
||||
var result = selectedEmoji.filter { !defaultItems.contains($0) }
|
||||
result.append(contentsOf: defaultItems)
|
||||
@ -468,7 +468,7 @@ final class EmojiStickerAccessoryNode: SparseNode, PeekControllerAccessoryNode {
|
||||
subject: .stickerAlt,
|
||||
hasTrending: false,
|
||||
topReactionItems: [],
|
||||
topEmojiItems: topItems(selectedEmoji: selectedItems, recommendedEmoji: recommendedEmoji, count: 7),
|
||||
topEmojiItems: topItems(selectedEmoji: selectedItems, recommendedEmoji: recommendedEmoji, count: 8),
|
||||
areUnicodeEmojiEnabled: true,
|
||||
areCustomEmojiEnabled: false,
|
||||
chatPeerId: context.account.peerId,
|
||||
|
||||
@ -88,7 +88,6 @@ final class MediaEditorScreenComponent: Component {
|
||||
let selectedEntity: DrawingEntity?
|
||||
let entityViewForEntity: (DrawingEntity) -> DrawingEntityView?
|
||||
let openDrawing: (DrawingScreenType) -> Void
|
||||
let openTools: () -> Void
|
||||
let cutoutUndo: () -> Void
|
||||
|
||||
init(
|
||||
@ -105,7 +104,6 @@ final class MediaEditorScreenComponent: Component {
|
||||
selectedEntity: DrawingEntity?,
|
||||
entityViewForEntity: @escaping (DrawingEntity) -> DrawingEntityView?,
|
||||
openDrawing: @escaping (DrawingScreenType) -> Void,
|
||||
openTools: @escaping () -> Void,
|
||||
cutoutUndo: @escaping () -> Void
|
||||
) {
|
||||
self.context = context
|
||||
@ -121,7 +119,6 @@ final class MediaEditorScreenComponent: Component {
|
||||
self.selectedEntity = selectedEntity
|
||||
self.entityViewForEntity = entityViewForEntity
|
||||
self.openDrawing = openDrawing
|
||||
self.openTools = openTools
|
||||
self.cutoutUndo = cutoutUndo
|
||||
}
|
||||
|
||||
@ -726,7 +723,6 @@ final class MediaEditorScreenComponent: Component {
|
||||
let isTablet = environment.metrics.isTablet
|
||||
|
||||
let openDrawing = component.openDrawing
|
||||
let openTools = component.openTools
|
||||
let cutoutUndo = component.cutoutUndo
|
||||
|
||||
let buttonSideInset: CGFloat
|
||||
@ -766,8 +762,8 @@ final class MediaEditorScreenComponent: Component {
|
||||
size: CGSize(width: 33.0, height: 33.0)
|
||||
)
|
||||
),
|
||||
action: { [weak self] in
|
||||
guard let environment = self?.environment, let controller = environment.controller() as? MediaEditorScreen else {
|
||||
action: { [weak controller] in
|
||||
guard let controller else {
|
||||
return
|
||||
}
|
||||
guard !controller.node.recording.isActive else {
|
||||
@ -811,8 +807,8 @@ final class MediaEditorScreenComponent: Component {
|
||||
icon: doneButtonIcon,
|
||||
title: doneButtonTitle)),
|
||||
effectAlignment: .center,
|
||||
action: { [weak self] in
|
||||
guard let environment = self?.environment, let controller = environment.controller() as? MediaEditorScreen else {
|
||||
action: { [weak controller] in
|
||||
guard let controller else {
|
||||
return
|
||||
}
|
||||
switch controller.mode {
|
||||
@ -870,8 +866,8 @@ final class MediaEditorScreenComponent: Component {
|
||||
image: state.image(.draw),
|
||||
size: CGSize(width: 30.0, height: 30.0)
|
||||
)),
|
||||
action: { [weak self] in
|
||||
guard let environment = self?.environment, let controller = environment.controller() as? MediaEditorScreen else {
|
||||
action: { [weak controller] in
|
||||
guard let controller else {
|
||||
return
|
||||
}
|
||||
guard !controller.node.recording.isActive else {
|
||||
@ -906,8 +902,8 @@ final class MediaEditorScreenComponent: Component {
|
||||
image: state.image(.text),
|
||||
size: CGSize(width: 30.0, height: 30.0)
|
||||
)),
|
||||
action: { [weak self] in
|
||||
guard let environment = self?.environment, let controller = environment.controller() as? MediaEditorScreen else {
|
||||
action: { [weak controller] in
|
||||
guard let controller else {
|
||||
return
|
||||
}
|
||||
guard !controller.node.recording.isActive else {
|
||||
@ -943,8 +939,8 @@ final class MediaEditorScreenComponent: Component {
|
||||
)),
|
||||
tag: stickerButtonTag,
|
||||
minSize: CGSize(width: 30.0, height: 30.0),
|
||||
action: { [weak self] view, gesture in
|
||||
guard let environment = self?.environment, let controller = environment.controller() as? MediaEditorScreen else {
|
||||
action: { [weak controller] view, gesture in
|
||||
guard let controller else {
|
||||
return
|
||||
}
|
||||
guard !controller.node.recording.isActive else {
|
||||
@ -982,14 +978,14 @@ final class MediaEditorScreenComponent: Component {
|
||||
image: state.image(.tools),
|
||||
size: CGSize(width: 30.0, height: 30.0)
|
||||
)),
|
||||
action: { [weak self] in
|
||||
guard let environment = self?.environment, let controller = environment.controller() as? MediaEditorScreen else {
|
||||
action: { [weak controller] in
|
||||
guard let controller else {
|
||||
return
|
||||
}
|
||||
guard !controller.node.recording.isActive else {
|
||||
return
|
||||
}
|
||||
openTools()
|
||||
openDrawing(.tools)
|
||||
}
|
||||
)),
|
||||
environment: {},
|
||||
@ -1830,8 +1826,8 @@ final class MediaEditorScreenComponent: Component {
|
||||
mediaEditor.setAdditionalVideoOffset(offset, apply: apply)
|
||||
}
|
||||
},
|
||||
trackLongPressed: { [weak self] trackId, sourceView in
|
||||
guard let self, let controller = self.environment?.controller() as? MediaEditorScreen else {
|
||||
trackLongPressed: { [weak controller] trackId, sourceView in
|
||||
guard let controller else {
|
||||
return
|
||||
}
|
||||
controller.node.presentTrackOptions(trackId: trackId, sourceView: sourceView)
|
||||
@ -1912,14 +1908,14 @@ final class MediaEditorScreenComponent: Component {
|
||||
transition: transition,
|
||||
component: AnyComponent(CameraButton(
|
||||
content: saveContentComponent,
|
||||
action: { [weak self] in
|
||||
guard let environment = self?.environment, let controller = environment.controller() as? MediaEditorScreen else {
|
||||
action: { [weak self, weak controller] in
|
||||
guard let self, let controller else {
|
||||
return
|
||||
}
|
||||
guard !controller.node.recording.isActive else {
|
||||
return
|
||||
}
|
||||
if let view = self?.saveButton.findTaggedView(tag: saveButtonTag) as? LottieAnimationComponent.View {
|
||||
if let view = self.saveButton.findTaggedView(tag: saveButtonTag) as? LottieAnimationComponent.View {
|
||||
view.playOnce()
|
||||
}
|
||||
controller.requestSave()
|
||||
@ -1983,16 +1979,15 @@ final class MediaEditorScreenComponent: Component {
|
||||
transition: transition,
|
||||
component: AnyComponent(CameraButton(
|
||||
content: dayNightContentComponent,
|
||||
action: { [weak self, weak state, weak mediaEditor] in
|
||||
guard let environment = self?.environment, let controller = environment.controller() as? MediaEditorScreen else {
|
||||
action: { [weak controller, weak state, weak mediaEditor] in
|
||||
guard let controller, let state else {
|
||||
return
|
||||
}
|
||||
guard !controller.node.recording.isActive else {
|
||||
return
|
||||
}
|
||||
|
||||
if let mediaEditor {
|
||||
state?.dayNightDidChange = true
|
||||
state.dayNightDidChange = true
|
||||
|
||||
if let snapshotView = controller.node.previewContainerView.snapshotView(afterScreenUpdates: false) {
|
||||
controller.node.previewContainerView.addSubview(snapshotView)
|
||||
@ -2079,8 +2074,8 @@ final class MediaEditorScreenComponent: Component {
|
||||
transition: transition,
|
||||
component: AnyComponent(CameraButton(
|
||||
content: muteContentComponent,
|
||||
action: { [weak self, weak state, weak mediaEditor] in
|
||||
guard let environment = self?.environment, let controller = environment.controller() as? MediaEditorScreen else {
|
||||
action: { [weak state, weak controller] in
|
||||
guard let controller else {
|
||||
return
|
||||
}
|
||||
guard !controller.node.recording.isActive else {
|
||||
@ -2161,8 +2156,8 @@ final class MediaEditorScreenComponent: Component {
|
||||
transition: transition,
|
||||
component: AnyComponent(CameraButton(
|
||||
content: playbackContentComponent,
|
||||
action: { [weak self, weak mediaEditor, weak state] in
|
||||
guard let environment = self?.environment, let controller = environment.controller() as? MediaEditorScreen else {
|
||||
action: { [weak controller, weak mediaEditor, weak state] in
|
||||
guard let controller else {
|
||||
return
|
||||
}
|
||||
guard !controller.node.recording.isActive else {
|
||||
@ -2211,8 +2206,8 @@ final class MediaEditorScreenComponent: Component {
|
||||
content: AnyComponent(
|
||||
FlipButtonContentComponent(tag: switchCameraButtonTag)
|
||||
),
|
||||
action: { [weak self] in
|
||||
if let self, let environment = self.environment, let controller = environment.controller() as? MediaEditorScreen {
|
||||
action: { [weak self, weak controller] in
|
||||
if let self, let controller {
|
||||
controller.node.recording.togglePosition()
|
||||
|
||||
if let view = self.switchCameraButton.findTaggedView(tag: switchCameraButtonTag) as? FlipButtonContentComponent.View {
|
||||
@ -2246,8 +2241,8 @@ final class MediaEditorScreenComponent: Component {
|
||||
content: AnyComponent(
|
||||
Text(text: environment.strings.Common_Cancel, font: Font.regular(17.0), color: .white)
|
||||
),
|
||||
action: { [weak self] in
|
||||
if let self, let environment = self.environment, let controller = environment.controller() as? MediaEditorScreen {
|
||||
action: { [weak controller] in
|
||||
if let controller {
|
||||
controller.node.interaction?.endTextEditing(reset: true)
|
||||
}
|
||||
}
|
||||
@ -2275,8 +2270,8 @@ final class MediaEditorScreenComponent: Component {
|
||||
content: AnyComponent(
|
||||
Text(text: environment.strings.Common_Done, font: Font.regular(17.0), color: .white)
|
||||
),
|
||||
action: { [weak self] in
|
||||
if let self, let environment = self.environment, let controller = environment.controller() as? MediaEditorScreen {
|
||||
action: { [weak controller] in
|
||||
if let controller {
|
||||
controller.node.interaction?.endTextEditing(reset: false)
|
||||
}
|
||||
}
|
||||
@ -2303,8 +2298,8 @@ final class MediaEditorScreenComponent: Component {
|
||||
component: AnyComponent(TextSizeSliderComponent(
|
||||
value: sizeValue ?? 0.5,
|
||||
tag: nil,
|
||||
updated: { [weak self] size in
|
||||
if let self, let environment = self.environment, let controller = environment.controller() as? MediaEditorScreen, let component = self.component {
|
||||
updated: { [weak self, weak controller] size in
|
||||
if let self, let controller, let component = self.component {
|
||||
if let _ = component.selectedEntity {
|
||||
controller.node.interaction?.updateEntitySize(size)
|
||||
} else if [.cutoutErase, .cutoutRestore].contains(component.isDisplayingTool), let stickerMaskDrawingView = controller.node.stickerMaskDrawingView {
|
||||
@ -2832,51 +2827,61 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
||||
} else {
|
||||
initialValues = nil
|
||||
}
|
||||
|
||||
var isStickerEditor = false
|
||||
if case .stickerEditor = controller.mode {
|
||||
isStickerEditor = true
|
||||
}
|
||||
|
||||
if let mediaEntityView = self.entitiesView.add(mediaEntity, announce: false) as? DrawingMediaEntityView {
|
||||
let mediaEntitySize = mediaEntityView.bounds.size
|
||||
let scaledDimensions = subject.dimensions.cgSize.aspectFittedOrSmaller(CGSize(width: 1920, height: 1920))
|
||||
let maskDrawingSize = scaledDimensions.aspectFilled(mediaEntitySize)
|
||||
|
||||
let stickerMaskDrawingView = DrawingView(size: scaledDimensions, gestureView: self.previewContainerView)
|
||||
stickerMaskDrawingView.stateUpdated = { [weak self] _ in
|
||||
if let self {
|
||||
self.requestLayout(forceUpdate: true, transition: .easeInOut(duration: 0.25))
|
||||
var updateStickerMaskDrawing: (CGPoint, CGFloat, CGFloat) -> Void = { _, _, _ in }
|
||||
if isStickerEditor {
|
||||
let mediaEntitySize = mediaEntityView.bounds.size
|
||||
let scaledDimensions = subject.dimensions.cgSize.aspectFittedOrSmaller(CGSize(width: 1920, height: 1920))
|
||||
let maskDrawingSize = scaledDimensions.aspectFilled(mediaEntitySize)
|
||||
|
||||
let stickerMaskDrawingView = DrawingView(size: scaledDimensions, gestureView: self.previewContainerView)
|
||||
stickerMaskDrawingView.stateUpdated = { [weak self] _ in
|
||||
if let self {
|
||||
self.requestLayout(forceUpdate: true, transition: .easeInOut(duration: 0.25))
|
||||
}
|
||||
}
|
||||
stickerMaskDrawingView.emptyColor = .white
|
||||
stickerMaskDrawingView.updateToolState(.pen(DrawingToolState.BrushState(color: DrawingColor(color: .black), size: 0.5)))
|
||||
stickerMaskDrawingView.isUserInteractionEnabled = false
|
||||
stickerMaskDrawingView.animationsEnabled = false
|
||||
stickerMaskDrawingView.clearWithEmptyColor()
|
||||
if let filter = makeLuminanceToAlphaFilter() {
|
||||
self.stickerMaskWrapperView.layer.filters = [filter]
|
||||
}
|
||||
self.stickerMaskWrapperView.addSubview(stickerMaskDrawingView)
|
||||
self.stickerMaskWrapperView.addSubview(self.stickerMaskPreviewView)
|
||||
self.stickerMaskDrawingView = stickerMaskDrawingView
|
||||
|
||||
var initialMaskPosition = CGPoint()
|
||||
var initialMaskScale: CGFloat = 1.0
|
||||
|
||||
updateStickerMaskDrawing = { [weak stickerMaskDrawingView] position, scale, rotation in
|
||||
guard let stickerMaskDrawingView else {
|
||||
return
|
||||
}
|
||||
let maskScale = initialMaskPosition.x * 2.0 / 1080.0
|
||||
stickerMaskDrawingView.center = initialMaskPosition.offsetBy(dx: position.x * maskScale, dy: position.y * maskScale)
|
||||
stickerMaskDrawingView.transform = CGAffineTransform(scaleX: initialMaskScale * scale, y: initialMaskScale * scale).rotated(by: rotation)
|
||||
}
|
||||
|
||||
Queue.mainQueue().after(0.1) {
|
||||
let previewSize = self.previewView.bounds.size
|
||||
self.stickerMaskWrapperView.frame = CGRect(origin: .zero, size: previewSize)
|
||||
self.stickerMaskPreviewView.frame = CGRect(origin: .zero, size: previewSize)
|
||||
|
||||
let maskScale = previewSize.width / min(maskDrawingSize.width, maskDrawingSize.height)
|
||||
initialMaskScale = maskScale
|
||||
initialMaskPosition = CGPoint(x: previewSize.width / 2.0, y: previewSize.height / 2.0)
|
||||
stickerMaskDrawingView.bounds = CGRect(origin: .zero, size: maskDrawingSize)
|
||||
|
||||
updateStickerMaskDrawing(.zero, 1.0, 0.0)
|
||||
}
|
||||
}
|
||||
stickerMaskDrawingView.emptyColor = .white
|
||||
stickerMaskDrawingView.updateToolState(.pen(DrawingToolState.BrushState(color: DrawingColor(color: .black), size: 0.5)))
|
||||
stickerMaskDrawingView.isUserInteractionEnabled = false
|
||||
stickerMaskDrawingView.animationsEnabled = false
|
||||
stickerMaskDrawingView.clearWithEmptyColor()
|
||||
if let filter = makeLuminanceToAlphaFilter() {
|
||||
self.stickerMaskWrapperView.layer.filters = [filter]
|
||||
}
|
||||
self.stickerMaskWrapperView.addSubview(stickerMaskDrawingView)
|
||||
self.stickerMaskWrapperView.addSubview(self.stickerMaskPreviewView)
|
||||
self.stickerMaskDrawingView = stickerMaskDrawingView
|
||||
|
||||
var initialMaskPosition = CGPoint()
|
||||
var initialMaskScale: CGFloat = 1.0
|
||||
|
||||
func updateStickerMaskDrawing(position: CGPoint, scale: CGFloat, rotation: CGFloat) {
|
||||
let maskScale = initialMaskPosition.x * 2.0 / 1080.0
|
||||
stickerMaskDrawingView.center = initialMaskPosition.offsetBy(dx: position.x * maskScale, dy: position.y * maskScale)
|
||||
stickerMaskDrawingView.transform = CGAffineTransform(scaleX: initialMaskScale * scale, y: initialMaskScale * scale).rotated(by: rotation)
|
||||
}
|
||||
|
||||
Queue.mainQueue().after(0.1) {
|
||||
let previewSize = self.previewView.bounds.size
|
||||
self.stickerMaskWrapperView.frame = CGRect(origin: .zero, size: previewSize)
|
||||
self.stickerMaskPreviewView.frame = CGRect(origin: .zero, size: previewSize)
|
||||
|
||||
// let filledSize = maskDrawingSize.aspectFitted(previewSize)
|
||||
let maskScale = previewSize.width / min(maskDrawingSize.width, maskDrawingSize.height)
|
||||
initialMaskScale = maskScale
|
||||
initialMaskPosition = CGPoint(x: previewSize.width / 2.0, y: previewSize.height / 2.0)
|
||||
stickerMaskDrawingView.bounds = CGRect(origin: .zero, size: maskDrawingSize)
|
||||
|
||||
updateStickerMaskDrawing(position: .zero, scale: 1.0, rotation: 0.0)
|
||||
}
|
||||
|
||||
self.entitiesView.sendSubviewToBack(mediaEntityView)
|
||||
@ -2887,7 +2892,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
||||
let scaleDelta = mediaEntity.scale / initialScale
|
||||
self.mediaEditor?.setCrop(offset: positionDelta, scale: scaleDelta, rotation: rotationDelta, mirroring: false)
|
||||
|
||||
updateStickerMaskDrawing(position: positionDelta, scale: scaleDelta, rotation: rotationDelta)
|
||||
updateStickerMaskDrawing(positionDelta, scaleDelta, rotationDelta)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2897,12 +2902,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
||||
mediaEntity.scale = mediaEntity.scale * initialValues.cropScale
|
||||
}
|
||||
}
|
||||
|
||||
var isStickerEditor = false
|
||||
if case .stickerEditor = controller.mode {
|
||||
isStickerEditor = true
|
||||
}
|
||||
|
||||
|
||||
let mediaEditor = MediaEditor(context: self.context, mode: isStickerEditor ? .sticker : .default, subject: effectiveSubject.editorSubject, values: initialValues, hasHistogram: true)
|
||||
if let initialVideoPosition = controller.initialVideoPosition {
|
||||
mediaEditor.seek(initialVideoPosition, andPlay: true)
|
||||
@ -2979,7 +2979,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
||||
mediaEditor.setAdditionalVideo(additionalVideoPath, isDual: true, positionChanges: changes.map { VideoPositionChange(additional: $0.0, timestamp: $0.1) })
|
||||
mediaEditor.setAdditionalVideoPosition(videoEntity.position, scale: videoEntity.scale, rotation: videoEntity.rotation)
|
||||
if let entityView = self.entitiesView.getView(for: videoEntity.uuid) as? DrawingStickerEntityView {
|
||||
entityView.updated = { [weak videoEntity, weak self] in
|
||||
entityView.updated = { [weak self, weak videoEntity] in
|
||||
if let self, let videoEntity {
|
||||
self.mediaEditor?.setAdditionalVideoPosition(videoEntity.position, scale: videoEntity.scale, rotation: videoEntity.rotation)
|
||||
}
|
||||
@ -4528,13 +4528,13 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
||||
}
|
||||
},
|
||||
openDrawing: { [weak self] mode in
|
||||
if let self {
|
||||
if let self, let mediaEditor = self.mediaEditor {
|
||||
if self.entitiesView.hasSelection {
|
||||
self.entitiesView.selectEntity(nil)
|
||||
}
|
||||
switch mode {
|
||||
case .sticker:
|
||||
self.mediaEditor?.maybePauseVideo()
|
||||
mediaEditor.maybePauseVideo()
|
||||
|
||||
var hasInteractiveStickers = true
|
||||
if let controller = self.controller, case .stickerEditor = controller.mode {
|
||||
@ -4608,7 +4608,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
||||
self.stickerScreen = controller
|
||||
self.controller?.present(controller, in: .current)
|
||||
case .text:
|
||||
self.mediaEditor?.maybePauseVideo()
|
||||
mediaEditor.maybePauseVideo()
|
||||
self.insertTextEntity()
|
||||
|
||||
self.hasAnyChanges = true
|
||||
@ -4749,37 +4749,32 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
||||
self.animateInFromTool(inPlace: true)
|
||||
}
|
||||
}
|
||||
controller.present(cutoutController, in: .window(.root))
|
||||
self.controller?.present(cutoutController, in: .window(.root))
|
||||
self.cutoutScreen = cutoutController
|
||||
self.animateOutToTool(tool: mode, inPlace: true)
|
||||
|
||||
controller.hapticFeedback.impact(.medium)
|
||||
self.controller?.hapticFeedback.impact(.medium)
|
||||
case .tools:
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
openTools: { [weak self] in
|
||||
if let self, let mediaEditor = self.mediaEditor {
|
||||
if self.entitiesView.hasSelection {
|
||||
self.entitiesView.selectEntity(nil)
|
||||
}
|
||||
var hiddenTools: [EditorToolKey] = []
|
||||
if !self.canEnhance {
|
||||
hiddenTools.append(.enhance)
|
||||
}
|
||||
if let controller = self.controller, case .stickerEditor = controller.mode {
|
||||
hiddenTools.append(.grain)
|
||||
hiddenTools.append(.vignette)
|
||||
}
|
||||
let controller = MediaToolsScreen(context: self.context, mediaEditor: mediaEditor, hiddenTools: hiddenTools)
|
||||
controller.dismissed = { [weak self] in
|
||||
if let self {
|
||||
self.animateInFromTool()
|
||||
if self.entitiesView.hasSelection {
|
||||
self.entitiesView.selectEntity(nil)
|
||||
}
|
||||
var hiddenTools: [EditorToolKey] = []
|
||||
if !self.canEnhance {
|
||||
hiddenTools.append(.enhance)
|
||||
}
|
||||
if let controller = self.controller, case .stickerEditor = controller.mode {
|
||||
hiddenTools.append(.grain)
|
||||
hiddenTools.append(.vignette)
|
||||
}
|
||||
let controller = MediaToolsScreen(context: self.context, mediaEditor: mediaEditor, hiddenTools: hiddenTools)
|
||||
controller.dismissed = { [weak self] in
|
||||
if let self {
|
||||
self.animateInFromTool()
|
||||
}
|
||||
}
|
||||
self.controller?.present(controller, in: .window(.root))
|
||||
self.animateOutToTool(tool: .tools)
|
||||
}
|
||||
self.controller?.present(controller, in: .window(.root))
|
||||
self.animateOutToTool(tool: .tools)
|
||||
}
|
||||
},
|
||||
cutoutUndo: { [weak self, weak controller] in
|
||||
@ -4800,7 +4795,10 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
||||
self.requestLayout(forceUpdate: true, transition: .easeInOut(duration: 0.25))
|
||||
}
|
||||
} else if controller.node.isCutout {
|
||||
let action = {
|
||||
let action = { [weak self, weak mediaEditor] in
|
||||
guard let self, let mediaEditor else {
|
||||
return
|
||||
}
|
||||
let snapshotView = self.previewView.snapshotView(afterScreenUpdates: false)
|
||||
if let snapshotView {
|
||||
self.previewView.superview?.insertSubview(snapshotView, aboveSubview: self.previewView)
|
||||
|
||||
@ -60,14 +60,14 @@ final class StickerCutoutOutlineView: UIView {
|
||||
self.glowLayer.removeFromSuperlayer()
|
||||
|
||||
self.outlineLayer = CAEmitterLayer()
|
||||
self.outlineLayer.opacity = 0.77
|
||||
self.outlineLayer.opacity = 0.65
|
||||
self.outline2Layer = CAEmitterLayer()
|
||||
self.outline2Layer.opacity = 0.7
|
||||
self.outline2Layer.opacity = 0.65
|
||||
|
||||
self.glowLayer = CAEmitterLayer()
|
||||
|
||||
self.layer.addSublayer(self.outlineLayer)
|
||||
// self.layer.addSublayer(self.outline2Layer)
|
||||
self.layer.addSublayer(self.outline2Layer)
|
||||
self.layer.addSublayer(self.glowLayer)
|
||||
|
||||
let randomBeginTime = (previousBeginTime + 4) % 6
|
||||
@ -93,8 +93,8 @@ final class StickerCutoutOutlineView: UIView {
|
||||
lineEmitterCell.color = UIColor.white.cgColor
|
||||
lineEmitterCell.contents = UIImage(named: "Media Editor/ParticleDot")?.cgImage
|
||||
lineEmitterCell.lifetime = 2.2
|
||||
lineEmitterCell.birthRate = 800
|
||||
lineEmitterCell.scale = 0.18
|
||||
lineEmitterCell.birthRate = 1000
|
||||
lineEmitterCell.scale = 0.15
|
||||
lineEmitterCell.alphaSpeed = -0.4
|
||||
|
||||
self.outlineLayer.emitterCells = [lineEmitterCell]
|
||||
@ -112,7 +112,7 @@ final class StickerCutoutOutlineView: UIView {
|
||||
outline2Animation.repeatCount = .infinity
|
||||
outline2Animation.calculationMode = .paced
|
||||
outline2Animation.fillMode = .forwards
|
||||
outline2Animation.beginTime = Double(randomBeginTime) + 0.02
|
||||
outline2Animation.beginTime = Double(randomBeginTime)
|
||||
self.outline2Layer.add(outline2Animation, forKey: "emitterPosition")
|
||||
|
||||
let line2EmitterCell = CAEmitterCell()
|
||||
@ -124,14 +124,14 @@ final class StickerCutoutOutlineView: UIView {
|
||||
line2EmitterCell.color = UIColor.white.cgColor
|
||||
line2EmitterCell.contents = UIImage(named: "Media Editor/ParticleDot")?.cgImage
|
||||
line2EmitterCell.lifetime = 2.2
|
||||
line2EmitterCell.birthRate = 500
|
||||
line2EmitterCell.scale = 0.14
|
||||
line2EmitterCell.birthRate = 1000
|
||||
line2EmitterCell.scale = 0.15
|
||||
line2EmitterCell.alphaSpeed = -0.4
|
||||
|
||||
self.outline2Layer.emitterCells = [line2EmitterCell]
|
||||
self.outline2Layer.emitterMode = .points
|
||||
self.outline2Layer.emitterSize = CGSize(width: 1.5, height: 1.5)
|
||||
self.outline2Layer.emitterShape = .circle
|
||||
self.outline2Layer.emitterSize = CGSize(width: 1.33, height: 1.33)
|
||||
self.outline2Layer.emitterShape = .rectangle
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user