@@ -81,65 +81,64 @@ private func padelScoreboardSettingsToEffect(_ scoreboard: SettingsWidgetPadelSc
8181 return PadelScoreboard ( home: home, away: away, score: score)
8282}
8383
84- final class ScoreboardEffect : VideoEffect {
85- private var scoreboardImage : CIImage ?
86- private var sceneWidget : SettingsSceneWidget ?
87-
88- func setSceneWidget( sceneWidget: SettingsSceneWidget ) {
89- processorPipelineQueue. async {
90- self . sceneWidget = sceneWidget
91- }
92- }
93-
94- @MainActor
95- func update( scoreboard: SettingsWidgetScoreboard ,
96- config: RemoteControlScoreboardMatchConfig ,
97- players: [ SettingsWidgetScoreboardPlayer ] )
98- {
99- switch scoreboard. sport {
100- case . padel:
101- updatePadel ( textColor: scoreboard. textColorColor,
102- primaryBackgroundColor: scoreboard. primaryBackgroundColorColor,
103- secondaryBackgroundColor: scoreboard. secondaryBackgroundColorColor,
104- padel: scoreboard. padel,
105- players: players)
106- case . generic:
107- updateGeneric ( textColor: scoreboard. textColorColor,
108- primaryBackgroundColor: scoreboard. primaryBackgroundColorColor,
109- secondaryBackgroundColor: scoreboard. secondaryBackgroundColorColor,
110- generic: scoreboard. generic)
111- default :
112- updateModular ( modular: scoreboard. modular, config: config)
113- }
114- }
84+ private struct GenericScoreboardView : View {
85+ let textColor : Color
86+ let primaryBackgroundColor : Color
87+ let secondaryBackgroundColor : Color
88+ @ObservedObject var generic : SettingsWidgetGenericScoreboard
11589
116- override func execute( _ image: CIImage , _: VideoEffectInfo ) -> CIImage {
117- guard let scoreboardImage, let sceneWidget else {
118- return image
90+ var body : some View {
91+ VStack ( alignment: . leading, spacing: 0 ) {
92+ HStack {
93+ Text ( generic. title)
94+ Spacer ( )
95+ Text ( generic. clock. format ( ) )
96+ . monospacedDigit ( )
97+ . font ( . system( size: 25 ) )
98+ }
99+ . padding ( 5 )
100+ . background ( secondaryBackgroundColor)
101+ HStack ( alignment: . center, spacing: 18 ) {
102+ VStack ( alignment: . leading) {
103+ VStack ( alignment: . leading) {
104+ Spacer ( minLength: 0 )
105+ Text ( generic. home. uppercased ( ) )
106+ Spacer ( minLength: 0 )
107+ }
108+ VStack ( alignment: . leading) {
109+ Spacer ( minLength: 0 )
110+ Text ( generic. away. uppercased ( ) )
111+ Spacer ( minLength: 0 )
112+ }
113+ }
114+ . font ( . system( size: 25 ) )
115+ Spacer ( )
116+ VStack {
117+ TeamScoreView ( score: generic. score. home)
118+ TeamScoreView ( score: generic. score. away)
119+ }
120+ . frame ( width: 28 )
121+ . font ( . system( size: 45 ) )
122+ }
123+ . padding ( [ . leading, . trailing] , 5 )
124+ . background ( primaryBackgroundColor)
125+ PoweredByMoblinView ( backgroundColor: secondaryBackgroundColor)
119126 }
120- let scale = image. extent. size. maximum ( ) / 1920
121- return scoreboardImage
122- . scaled ( x: scale, y: scale)
123- . move ( sceneWidget. layout, image. extent. size)
124- . cropped ( to: image. extent)
125- . composited ( over: image)
127+ . clipShape ( RoundedRectangle ( cornerRadius: 5 ) )
128+ . foregroundStyle ( textColor)
126129 }
130+ }
127131
128- private func setScoreboardImage( image: CIImage ? ) {
129- processorPipelineQueue. async {
130- self . scoreboardImage = image
131- }
132- }
132+ private struct PadelScoreboardView : View {
133+ let textColor : Color
134+ let primaryBackgroundColor : Color
135+ let secondaryBackgroundColor : Color
136+ let padel : SettingsWidgetPadelScoreboard
137+ let players : [ SettingsWidgetScoreboardPlayer ]
133138
134- @MainActor
135- private func updatePadel( textColor: Color ,
136- primaryBackgroundColor: Color ,
137- secondaryBackgroundColor: Color ,
138- padel: SettingsWidgetPadelScoreboard ,
139- players: [ SettingsWidgetScoreboardPlayer ] )
140- {
139+ var body : some View {
141140 let scoreboard = padelScoreboardSettingsToEffect ( padel, players)
142- let scoreBoard = VStack ( alignment: . leading, spacing: 0 ) {
141+ VStack ( alignment: . leading, spacing: 0 ) {
143142 HStack ( alignment: . center, spacing: 18 ) {
144143 VStack ( alignment: . leading) {
145144 VStack ( alignment: . leading) {
@@ -177,81 +176,12 @@ final class ScoreboardEffect: VideoEffect {
177176 }
178177 . clipShape ( RoundedRectangle ( cornerRadius: 5 ) )
179178 . foregroundStyle ( textColor)
180- let renderer = ImageRenderer ( content: scoreBoard)
181- guard let image = renderer. uiImage else {
182- return
183- }
184- setScoreboardImage ( image: CIImage ( image: image) )
185- }
186-
187- @MainActor
188- private func updateGeneric( textColor: Color ,
189- primaryBackgroundColor: Color ,
190- secondaryBackgroundColor: Color ,
191- generic: SettingsWidgetGenericScoreboard )
192- {
193- let scoreBoard = VStack ( alignment: . leading, spacing: 0 ) {
194- HStack {
195- Text ( generic. title)
196- Spacer ( )
197- Text ( generic. clock. format ( ) )
198- . monospacedDigit ( )
199- . font ( . system( size: 25 ) )
200- }
201- . padding ( 5 )
202- . background ( secondaryBackgroundColor)
203- HStack ( alignment: . center, spacing: 18 ) {
204- VStack ( alignment: . leading) {
205- VStack ( alignment: . leading) {
206- Spacer ( minLength: 0 )
207- Text ( generic. home. uppercased ( ) )
208- Spacer ( minLength: 0 )
209- }
210- VStack ( alignment: . leading) {
211- Spacer ( minLength: 0 )
212- Text ( generic. away. uppercased ( ) )
213- Spacer ( minLength: 0 )
214- }
215- }
216- . font ( . system( size: 25 ) )
217- Spacer ( )
218- VStack {
219- TeamScoreView ( score: generic. score. home)
220- TeamScoreView ( score: generic. score. away)
221- }
222- . frame ( width: 28 )
223- . font ( . system( size: 45 ) )
224- }
225- . padding ( [ . leading, . trailing] , 5 )
226- . background ( primaryBackgroundColor)
227- PoweredByMoblinView ( backgroundColor: secondaryBackgroundColor)
228- }
229- . clipShape ( RoundedRectangle ( cornerRadius: 5 ) )
230- . foregroundStyle ( textColor)
231- let renderer = ImageRenderer ( content: scoreBoard)
232- guard let image = renderer. uiImage else {
233- return
234- }
235- setScoreboardImage ( image: CIImage ( image: image) )
236179 }
180+ }
237181
238- @MainActor
239- private func updateModular(
240- modular: SettingsWidgetModularScoreboard ,
241- config: RemoteControlScoreboardMatchConfig
242- ) {
243- let content = VStack ( alignment: . center, spacing: 0 ) {
244- switch modular. layout {
245- case . sideBySide:
246- renderSideBySide ( modular: modular, config: config)
247- case . stackHistory:
248- renderStackHistory ( modular: modular, config: config)
249- default :
250- renderStacked ( modular: modular, config: config)
251- }
252- }
253- setScoreboardImage ( image: ImageRenderer ( content: content) . ciImage ( ) )
254- }
182+ private struct ModularScoreboardView : View {
183+ let modular : SettingsWidgetModularScoreboard
184+ let config : RemoteControlScoreboardMatchConfig
255185
256186 private func calculateMaxHistory( config: RemoteControlScoreboardMatchConfig ) -> Int {
257187 var maxHistory = 0
@@ -673,7 +603,7 @@ final class ScoreboardEffect: VideoEffect {
673603 . opacity ( 0.25 )
674604 . frame ( width: width, height: height)
675605 }
676- if let label = label , !label. isEmpty {
606+ if let label, !label. isEmpty {
677607 VStack ( spacing: - 2 ) {
678608 Text ( label)
679609 . font ( . system( size: size * 0.35 , weight: . bold) )
@@ -766,12 +696,114 @@ final class ScoreboardEffect: VideoEffect {
766696 }
767697
768698 private func renderTitleBlock( title: String , modular: SettingsWidgetModularScoreboard ) -> some View {
769- Text ( title)
770- . font ( . system( size: modular. fontSize ( ) * 0.7 ) )
771- . bold ( modular. isBold)
772- . foregroundStyle ( . white)
773- . padding ( . vertical, 1 )
774- . frame ( maxWidth: . infinity)
775- . background ( . black)
699+ HCenter {
700+ Text ( title)
701+ . font ( . system( size: modular. fontSize ( ) * 0.7 ) )
702+ . bold ( modular. isBold)
703+ . foregroundStyle ( . white)
704+ . padding ( . vertical, 1 )
705+ }
706+ . background ( . black)
707+ }
708+
709+ var body : some View {
710+ VStack ( spacing: 0 ) {
711+ switch modular. layout {
712+ case . sideBySide:
713+ renderSideBySide ( modular: modular, config: config)
714+ case . stackHistory:
715+ renderStackHistory ( modular: modular, config: config)
716+ default :
717+ renderStacked ( modular: modular, config: config)
718+ }
719+ }
720+ }
721+ }
722+
723+ final class ScoreboardEffect : VideoEffect {
724+ private var scoreboardImage : CIImage ?
725+ private var sceneWidget : SettingsSceneWidget ?
726+
727+ func setSceneWidget( sceneWidget: SettingsSceneWidget ) {
728+ processorPipelineQueue. async {
729+ self . sceneWidget = sceneWidget
730+ }
731+ }
732+
733+ @MainActor
734+ func update( scoreboard: SettingsWidgetScoreboard ,
735+ config: RemoteControlScoreboardMatchConfig ,
736+ players: [ SettingsWidgetScoreboardPlayer ] )
737+ {
738+ switch scoreboard. sport {
739+ case . generic:
740+ updateGeneric ( textColor: scoreboard. textColorColor,
741+ primaryBackgroundColor: scoreboard. primaryBackgroundColorColor,
742+ secondaryBackgroundColor: scoreboard. secondaryBackgroundColorColor,
743+ generic: scoreboard. generic)
744+ case . padel:
745+ updatePadel ( textColor: scoreboard. textColorColor,
746+ primaryBackgroundColor: scoreboard. primaryBackgroundColorColor,
747+ secondaryBackgroundColor: scoreboard. secondaryBackgroundColorColor,
748+ padel: scoreboard. padel,
749+ players: players)
750+ default :
751+ updateModular ( modular: scoreboard. modular, config: config)
752+ }
753+ }
754+
755+ override func execute( _ image: CIImage , _: VideoEffectInfo ) -> CIImage {
756+ guard let scoreboardImage, let sceneWidget else {
757+ return image
758+ }
759+ let scale = image. extent. size. maximum ( ) / 1920
760+ return scoreboardImage
761+ . scaled ( x: scale, y: scale)
762+ . move ( sceneWidget. layout, image. extent. size)
763+ . cropped ( to: image. extent)
764+ . composited ( over: image)
765+ }
766+
767+ private func setScoreboardImage( image: CIImage ? ) {
768+ processorPipelineQueue. async {
769+ self . scoreboardImage = image
770+ }
771+ }
772+
773+ @MainActor
774+ private func updateGeneric( textColor: Color ,
775+ primaryBackgroundColor: Color ,
776+ secondaryBackgroundColor: Color ,
777+ generic: SettingsWidgetGenericScoreboard )
778+ {
779+ let scoreboard = GenericScoreboardView ( textColor: textColor,
780+ primaryBackgroundColor: primaryBackgroundColor,
781+ secondaryBackgroundColor: secondaryBackgroundColor,
782+ generic: generic)
783+ setScoreboardImage ( image: ImageRenderer ( content: scoreboard) . ciImage ( ) )
784+ }
785+
786+ @MainActor
787+ private func updatePadel( textColor: Color ,
788+ primaryBackgroundColor: Color ,
789+ secondaryBackgroundColor: Color ,
790+ padel: SettingsWidgetPadelScoreboard ,
791+ players: [ SettingsWidgetScoreboardPlayer ] )
792+ {
793+ let scoreboard = PadelScoreboardView ( textColor: textColor,
794+ primaryBackgroundColor: primaryBackgroundColor,
795+ secondaryBackgroundColor: secondaryBackgroundColor,
796+ padel: padel,
797+ players: players)
798+ setScoreboardImage ( image: ImageRenderer ( content: scoreboard) . ciImage ( ) )
799+ }
800+
801+ @MainActor
802+ private func updateModular(
803+ modular: SettingsWidgetModularScoreboard ,
804+ config: RemoteControlScoreboardMatchConfig
805+ ) {
806+ let scoreboard = ModularScoreboardView ( modular: modular, config: config)
807+ setScoreboardImage ( image: ImageRenderer ( content: scoreboard) . ciImage ( ) )
776808 }
777809}
0 commit comments