1
1
package baaahs.glshaders
2
2
3
3
import baaahs.Logger
4
- import baaahs.OpenPatch
5
- import baaahs.OpenPatchy
6
4
import baaahs.show.*
7
5
import baaahs.show.live.LiveShaderInstance
6
+ import baaahs.show.live.OpenPatch
7
+ import baaahs.show.live.OpenPatchHolder
8
+ import baaahs.show.mutable.*
8
9
import baaahs.unknown
9
10
10
11
class AutoWirer (val plugins : Plugins ) {
11
12
private val glslAnalyzer = GlslAnalyzer ()
12
13
13
- fun autoWire (vararg shaders : Shader ): UnresolvedPatchEditor {
14
- return autoWire(shaders.map { glslAnalyzer.asShader(it.src) })
14
+ fun autoWire (
15
+ vararg shaders : Shader ,
16
+ focus : Shader ? = null
17
+ ): UnresolvedPatch {
18
+ val openShaders = shaders.associate { it to glslAnalyzer.asShader(it.src) }
19
+ return autoWire(openShaders.values, focus?.let { openShaders[it] })
15
20
}
16
21
17
- fun autoWire (vararg shaders : OpenShader ): UnresolvedPatchEditor {
18
- return autoWire(shaders.toList())
22
+ fun autoWire (
23
+ vararg shaders : OpenShader ,
24
+ focus : OpenShader ? = null
25
+ ): UnresolvedPatch {
26
+ return autoWire(shaders.toList(), focus)
19
27
}
20
28
21
- fun autoWire (shaders : List <OpenShader >, shaderChannel : ShaderChannel = ShaderChannel .Main ): UnresolvedPatchEditor {
22
- val locallyAvailable: MutableMap <ContentType , MutableList <LinkEditor .Port >> = mutableMapOf ()
29
+ fun autoWire (
30
+ shaders : Collection <OpenShader >,
31
+ focus : OpenShader ? = null,
32
+ shaderChannel : ShaderChannel = ShaderChannel .Main
33
+ ): UnresolvedPatch {
34
+ val locallyAvailable: MutableMap <ContentType , MutableSet <MutableLink .Port >> = mutableMapOf ()
23
35
24
36
// First pass: gather shader output ports.
25
37
val shaderInstances = shaders.associate { openShader ->
26
- val unresolvedShaderInstance = UnresolvedShaderInstanceEditor (
27
- ShaderEditor (openShader.shader),
28
- openShader.inputPorts.map { it.id }.associateWith { arrayListOf< LinkEditor .Port >() },
38
+ val unresolvedShaderInstance = UnresolvedShaderInstance (
39
+ MutableShader (openShader.shader),
40
+ openShader.inputPorts.map { it.id }.associateWith { hashSetOf< MutableLink .Port >() },
29
41
shaderChannel
30
42
)
31
43
32
- locallyAvailable.getOrPut(openShader.outputPort.contentType) { mutableListOf () }
33
- .add(UnresolvedShaderOutPortEditor (unresolvedShaderInstance, openShader.outputPort.id))
44
+ locallyAvailable.getOrPut(openShader.outputPort.contentType) { mutableSetOf () }
45
+ .add(UnresolvedShaderOutPort (unresolvedShaderInstance, openShader.outputPort.id))
34
46
35
47
openShader.shaderType.defaultUpstreams.forEach { (contentType, shaderChannel) ->
36
- locallyAvailable.getOrPut(contentType) { mutableListOf () }
37
- .add(ShaderChannelEditor (shaderChannel))
48
+ locallyAvailable.getOrPut(contentType) { mutableSetOf () }
49
+ .add(MutableShaderChannel (shaderChannel))
38
50
}
39
51
40
52
openShader to unresolvedShaderInstance
41
53
}
42
54
43
55
// Second pass: link datasources/output ports to input ports.
56
+ val shaderInstancesOfInterest = if (focus == null ) {
57
+ shaderInstances
58
+ } else {
59
+ mapOf (focus to (shaderInstances[focus] ? : error(" missing shader editor?" )))
60
+ }
61
+
44
62
val dataSources = hashSetOf<DataSource >()
45
- val unresolvedShaderInstances = shaderInstances .map { (openShader, unresolvedShaderInstance) ->
63
+ val unresolvedShaderInstances = shaderInstancesOfInterest .map { (openShader, unresolvedShaderInstance) ->
46
64
openShader.inputPorts.forEach { inputPort ->
47
- val localSuggestions: List < LinkEditor .Port >? = locallyAvailable[inputPort.contentType]
65
+ val localSuggestions: Set < MutableLink .Port >? = locallyAvailable[inputPort.contentType]
48
66
val suggestions = localSuggestions ? : plugins.suggestDataSources(inputPort).map {
49
67
dataSources.add(it)
50
- DataSourceEditor (it)
68
+ MutableDataSource (it)
51
69
}
52
70
unresolvedShaderInstance.incomingLinksOptions[inputPort.id]!! .addAll(suggestions)
53
71
}
54
72
unresolvedShaderInstance
55
73
}
56
- return UnresolvedPatchEditor (unresolvedShaderInstances, dataSources.toList())
74
+ return UnresolvedPatch (unresolvedShaderInstances, dataSources.toList())
57
75
}
58
76
59
- data class UnresolvedShaderOutPortEditor (
60
- val unresolvedShaderInstance : UnresolvedShaderInstanceEditor ,
77
+ data class UnresolvedShaderOutPort (
78
+ val unresolvedShaderInstance : UnresolvedShaderInstance ,
61
79
val portId : String
62
- ) : LinkEditor .Port {
80
+ ) : MutableLink .Port {
63
81
override fun toRef (showBuilder : ShowBuilder ): PortRef = TODO (" not implemented" )
64
82
override fun displayName (): String = TODO (" not implemented" )
65
83
}
66
84
67
- data class UnresolvedShaderInstanceEditor (
68
- val shader : ShaderEditor ,
69
- val incomingLinksOptions : Map <String , MutableList < LinkEditor .Port >>,
85
+ data class UnresolvedShaderInstance (
86
+ val mutableShader : MutableShader ,
87
+ val incomingLinksOptions : Map <String , MutableSet < MutableLink .Port >>,
70
88
var shaderChannel : ShaderChannel ? = null
71
89
) {
72
90
fun isAmbiguous () = incomingLinksOptions.values.any { it.size > 1 }
73
91
92
+ fun describeAmbiguity (): String {
93
+ return mutableShader.title + " : " +
94
+ incomingLinksOptions
95
+ .filter { (_, links) -> links.size > 1 }
96
+ .map { (portId, links) ->
97
+ " $portId ->(${links.joinToString(" ," ) { it.displayName() }} "
98
+ }
99
+ }
100
+
74
101
fun acceptSymbolicChannelLinks () {
75
102
incomingLinksOptions.values.forEach { options ->
76
- val shaderChannelOptions = options.filterIsInstance<ShaderChannelEditor >()
103
+ val shaderChannelOptions = options.filterIsInstance<MutableShaderChannel >()
77
104
if (options.size > 1 && shaderChannelOptions.size == 1 ) {
78
105
options.clear()
79
106
options.add(shaderChannelOptions.first())
@@ -82,10 +109,10 @@ class AutoWirer(val plugins: Plugins) {
82
109
}
83
110
}
84
111
85
- fun merge (vararg patchies : OpenPatchy ): Map <Surfaces , LinkedPatch > {
112
+ fun merge (vararg patchHolders : OpenPatchHolder ): Map <Surfaces , LinkedPatch > {
86
113
val patchesBySurfaces = mutableMapOf<Surfaces , MutableList <OpenPatch >>()
87
- patchies .forEach { openPatchy ->
88
- openPatchy .patches.forEach { patch ->
114
+ patchHolders .forEach { openPatchHolder ->
115
+ openPatchHolder .patches.forEach { patch ->
89
116
patchesBySurfaces.getOrPut(patch.surfaces) { arrayListOf () }
90
117
.add(patch)
91
118
}
@@ -119,7 +146,7 @@ class AutoWirer(val plugins: Plugins) {
119
146
class PortDiagram {
120
147
private var surfaces: Surfaces ? = null
121
148
private var level = 0
122
- private val patchEditor = PatchEditor ()
149
+ private val mutablePatch = MutablePatch ()
123
150
private val candidates = hashMapOf<Pair <ShaderChannel , ContentType >, MutableList <ChannelEntry >>()
124
151
private val resolved = hashMapOf<Pair <ShaderChannel , ContentType >, LiveShaderInstance > ()
125
152
@@ -131,7 +158,7 @@ class AutoWirer(val plugins: Plugins) {
131
158
fun add (patch : OpenPatch ) {
132
159
if (surfaces == null ) {
133
160
surfaces = patch.surfaces
134
- patchEditor .surfaces = patch.surfaces
161
+ mutablePatch .surfaces = patch.surfaces
135
162
} else if (surfaces != patch.surfaces) {
136
163
error(" Surface mismatch: $surfaces != ${patch.surfaces} " )
137
164
}
@@ -205,21 +232,25 @@ class AutoWirer(val plugins: Plugins) {
205
232
}
206
233
}
207
234
208
- data class UnresolvedPatchEditor (
209
- private val unresolvedShaderInstances : List <UnresolvedShaderInstanceEditor >,
235
+ data class UnresolvedPatch (
236
+ private val unresolvedShaderInstances : List <UnresolvedShaderInstance >,
210
237
private val dataSources : List <DataSource >
211
238
) {
212
239
fun isAmbiguous () = unresolvedShaderInstances.any { it.isAmbiguous() }
213
240
214
- fun resolve (): PatchEditor {
241
+ fun resolve (): MutablePatch {
215
242
if (isAmbiguous()) {
216
- error(" ambiguous! ${unresolvedShaderInstances.filter { it.isAmbiguous() }} " )
243
+ error(" ambiguous! " +
244
+ unresolvedShaderInstances
245
+ .filter { it.isAmbiguous() }
246
+ .map { it.describeAmbiguity() }
247
+ )
217
248
}
218
249
219
250
// First pass: create a shader instance editor for each shader.
220
251
val shaderInstances = unresolvedShaderInstances.associate {
221
- it.shader .shader to ShaderInstanceEditor (
222
- it.shader ,
252
+ it.mutableShader .shader to MutableShaderInstance (
253
+ it.mutableShader ,
223
254
it.incomingLinksOptions.mapValues { (_, fromPortOptions) ->
224
255
fromPortOptions.first()
225
256
}.toMutableMap(),
@@ -230,20 +261,26 @@ class AutoWirer(val plugins: Plugins) {
230
261
// Second pass: resolve references between shaders to the correct instance editor.
231
262
shaderInstances.values.forEach { shaderInstance ->
232
263
shaderInstance.incomingLinks.forEach { (toPortId, fromPort) ->
233
- if (fromPort is UnresolvedShaderOutPortEditor ) {
234
- val fromShader = fromPort.unresolvedShaderInstance.shader .shader
264
+ if (fromPort is UnresolvedShaderOutPort ) {
265
+ val fromShader = fromPort.unresolvedShaderInstance.mutableShader .shader
235
266
val fromShaderInstance = shaderInstances[fromShader]
236
267
? : error(unknown(" shader instance editor" , fromShader, shaderInstances.keys))
237
268
shaderInstance.incomingLinks[toPortId] =
238
- ShaderOutPortEditor (fromShaderInstance, fromPort.portId)
269
+ MutableShaderOutPort (
270
+ fromShaderInstance,
271
+ fromPort.portId
272
+ )
239
273
}
240
274
}
241
275
}
242
276
243
- return PatchEditor (shaderInstances.values.toList(), Surfaces .AllSurfaces )
277
+ return MutablePatch (
278
+ shaderInstances.values.toList(),
279
+ Surfaces .AllSurfaces
280
+ )
244
281
}
245
282
246
- fun acceptSymbolicChannelLinks (): UnresolvedPatchEditor {
283
+ fun acceptSymbolicChannelLinks (): UnresolvedPatch {
247
284
unresolvedShaderInstances.forEach { it.acceptSymbolicChannelLinks() }
248
285
return this
249
286
}
0 commit comments