@@ -553,6 +553,30 @@ module ChannelThings =
553
553
554
554
open Aardvark.Service
555
555
556
+ type RenderCommand < 'msg > =
557
+ | Clear of color : Option<aval<C4f>> * depth : Option<aval<float>> * stencil : Option<aval<int>>
558
+ | SceneGraph of sg : ISg<'msg>
559
+
560
+ member x.Compile ( values : ClientValues ) =
561
+ match x with
562
+ | RenderCommand.Clear( color, depth, stencil) ->
563
+ match color, depth, stencil with
564
+ | Some c, Some d, Some s -> values.runtime.CompileClear( values.signature, c, d, s)
565
+ | None, Some d, Some s -> values.runtime.CompileClearDepthStencil( values.signature, d, s)
566
+ | Some c, None, Some s -> values.runtime.CompileClear( values.signature, ( c, s) ||> AVal.map2 ( fun c s -> clear { color c; stencil s }))
567
+ | None, None, Some s -> values.runtime.CompileClearStencil( values.signature, s)
568
+ | Some c, Some d, None -> values.runtime.CompileClear( values.signature, c, d)
569
+ | None, Some d, None -> values.runtime.CompileClearDepth( values.signature, d)
570
+ | Some c, None, None -> values.runtime.CompileClear( values.signature, c)
571
+ | None, None, None -> RenderTask.empty
572
+ | RenderCommand.SceneGraph sg ->
573
+ let sg =
574
+ sg
575
+ |> Sg.viewTrafo values.viewTrafo
576
+ |> Sg.projTrafo values.projTrafo
577
+ |> Sg.uniform " ViewportSize" values.size
578
+ values.runtime.CompileRender( values.signature, sg)
579
+
556
580
type IApp < 'model , 'msg , 'outer > =
557
581
abstract member ToOuter : 'model * 'msg -> seq < 'outer >
558
582
abstract member ToInner : 'model * 'outer -> seq < 'msg >
@@ -1004,6 +1028,215 @@ and DomNode private() =
1004
1028
static member RenderControl ( camera : aval < Camera >, scene : ClientValues -> ISg < 'msg >, config : RenderControlConfig , ? htmlChildren : DomNode < _ >) : DomNode < 'msg > =
1005
1029
DomNode.RenderControl( AttributeMap.empty, camera, scene, config, htmlChildren)
1006
1030
1031
+ static member RenderControl ( attributes : AttributeMap < 'msg >, camera : aval < Camera >, sgs : ClientValues -> alist < RenderCommand < 'msg >>, htmlChildren : Option < DomNode < _ >>) =
1032
+
1033
+ let getState ( c : Aardvark.Service.ClientInfo ) =
1034
+ let cam = camera.GetValue( c.token)
1035
+ let cam = { cam with frustum = cam.frustum |> Frustum.withAspect ( float c.size.X / float c.size.Y) }
1036
+
1037
+ {
1038
+ viewTrafo = CameraView.viewTrafo cam.cameraView
1039
+ projTrafo = Frustum.projTrafo cam.frustum
1040
+ }
1041
+
1042
+ let trees = AVal.init AList.empty
1043
+ let globalPicks = AVal.init ASet.empty
1044
+
1045
+ let scene =
1046
+ Scene.custom ( fun values ->
1047
+
1048
+ let sgs = sgs values
1049
+
1050
+ let t =
1051
+ sgs |> AList.choose ( function RenderCommand.Clear _ -> None | SceneGraph sg -> PickTree.ofSg sg |> Some)
1052
+ let g =
1053
+ sgs |> AList.toASet |> ASet.choose ( function RenderCommand.Clear _ -> None | SceneGraph sg -> sg.GlobalPicks( Ag.Scope.Root) |> Some)
1054
+
1055
+ transact ( fun _ -> trees.Value <- t; globalPicks.Value <- g)
1056
+
1057
+ let mutable reader : IOpReader < IndexList < IRenderTask >, IndexListDelta < IRenderTask >> =
1058
+ let mutable state = IndexList.empty
1059
+ let input = sgs.GetReader()
1060
+ { new AbstractReader< IndexList< IRenderTask>, IndexListDelta< IRenderTask>>( IndexList.trace) with
1061
+ member x.Compute( token) =
1062
+ input.GetChanges token |> IndexListDelta.choose ( fun index op ->
1063
+ match op with
1064
+ | Set v ->
1065
+ match x.State.TryGet index with
1066
+ | Some o -> o.Dispose()
1067
+ | None -> ()
1068
+ let task = v.Compile( values)
1069
+ Some ( Set task)
1070
+
1071
+ | Remove ->
1072
+ match x.State.TryGet index with
1073
+ | Some o ->
1074
+ o.Dispose()
1075
+ Some Remove
1076
+ | None -> None
1077
+
1078
+ )
1079
+ } :> _
1080
+ //new AList.Readers.MapUseReader<_,_>(Ag.getContext(), sgs,invoke, (fun d -> d.Dispose()))
1081
+ //let mutable state = IndexList.empty
1082
+
1083
+ let update ( t : AdaptiveToken ) =
1084
+ let ops = reader.GetChanges t
1085
+ ()
1086
+
1087
+ { new AbstractRenderTask() with
1088
+ override x.PerformUpdate ( t , rt ) =
1089
+ update t
1090
+ override x.Perform ( t , rt , o ) =
1091
+ update t
1092
+ for task in reader.State do
1093
+ task.Run( t, rt, o)
1094
+ override x.Release () =
1095
+ for task in reader.State do
1096
+ task.Dispose()
1097
+ reader <- Unchecked.defaultof<_>
1098
+
1099
+ override x.Use f = f ()
1100
+ override x.FramebufferSignature = Some values.signature
1101
+ override x.Runtime = Some values.runtime
1102
+ } :> IRenderTask)
1103
+
1104
+ let globalNeeded = ASet.bind id globalPicks |> ASet.collect AMap.keys
1105
+ let treeNeeded = AList.bind id trees |> AList.toASet |> ASet.collect ( fun t -> t.Needed)
1106
+ let needed = ASet.union globalNeeded treeNeeded
1107
+
1108
+
1109
+ let rec pickTrees ( trees : list < PickTree < 'msg >>) ( evt ) =
1110
+ match trees with
1111
+ | [] -> false , Seq.empty
1112
+ | x:: xs ->
1113
+ let consumed , msgs = pickTrees xs evt
1114
+ if consumed then true , msgs
1115
+ else
1116
+ let consumed , other = x.Perform evt
1117
+ consumed, Seq.append msgs other
1118
+
1119
+ let proc =
1120
+ { new SceneEventProcessor< 'msg>() with
1121
+ member x.NeededEvents = needed
1122
+ member x.Process ( source : Guid , evt : SceneEvent ) =
1123
+ let trees = trees |> AVal.force
1124
+ let trees = trees.Content |> AVal.force |> IndexList.toList
1125
+ let globalPicks = globalPicks |> AVal.force
1126
+
1127
+ seq {
1128
+ for perScene in globalPicks.Content |> AVal.force do
1129
+ let picks = perScene.Content |> AVal.force
1130
+ match picks |> HashMap.tryFind evt.kind with
1131
+ | Some cb ->
1132
+ yield ! cb evt
1133
+ | None ->
1134
+ ()
1135
+ }
1136
+ }
1137
+
1138
+ DomNode.RenderControl( attributes, proc, getState, scene, htmlChildren)
1139
+
1140
+ static member RenderControl ( attributes : AttributeMap < 'msg >, camera : aval < Camera >, sgs : alist < RenderCommand < 'msg >>, htmlChildren : Option < DomNode < _ >>) =
1141
+ let getState ( c : Aardvark.Service.ClientInfo ) =
1142
+ let cam = camera.GetValue( c.token)
1143
+ let cam = { cam with frustum = cam.frustum |> Frustum.withAspect ( float c.size.X / float c.size.Y) }
1144
+
1145
+ {
1146
+ viewTrafo = CameraView.viewTrafo cam.cameraView
1147
+ projTrafo = Frustum.projTrafo cam.frustum
1148
+ }
1149
+
1150
+
1151
+ let scene =
1152
+ Scene.custom ( fun values ->
1153
+ let mutable reader : IOpReader < IndexList < IRenderTask >, IndexListDelta < IRenderTask >> =
1154
+ let mutable state = IndexList.empty
1155
+ let input = sgs.GetReader()
1156
+ { new AbstractReader< IndexList< IRenderTask>, IndexListDelta< IRenderTask>>( IndexList.trace) with
1157
+ member x.Compute( token) =
1158
+ input.GetChanges token |> IndexListDelta.choose ( fun index op ->
1159
+ match op with
1160
+ | Set v ->
1161
+ match x.State.TryGet index with
1162
+ | Some o -> o.Dispose()
1163
+ | None -> ()
1164
+ let task = v.Compile( values)
1165
+ Some ( Set task)
1166
+
1167
+ | Remove ->
1168
+ match x.State.TryGet index with
1169
+ | Some o ->
1170
+ o.Dispose()
1171
+ Some Remove
1172
+ | None -> None
1173
+
1174
+ )
1175
+ } :> _
1176
+
1177
+ let update ( t : AdaptiveToken ) =
1178
+ let ops = reader.GetChanges t
1179
+ ()
1180
+
1181
+ { new AbstractRenderTask() with
1182
+ override x.PerformUpdate ( t , rt ) =
1183
+ update t
1184
+ override x.Perform ( t , rt , o ) =
1185
+ update t
1186
+ for task in reader.State do
1187
+ task.Run( t, rt, o)
1188
+ override x.Release () =
1189
+ for t in reader.State do
1190
+ t.Dispose()
1191
+ reader <- Unchecked.defaultof<_>
1192
+
1193
+
1194
+ override x.Use f = f ()
1195
+ override x.FramebufferSignature = Some values.signature
1196
+ override x.Runtime = Some values.runtime
1197
+ } :> IRenderTask
1198
+
1199
+ )
1200
+
1201
+ let trees = sgs |> AList.choose ( function Clear _ -> None | SceneGraph sg -> PickTree.ofSg sg |> Some)
1202
+ let globalPicks = sgs |> AList.toASet |> ASet.choose ( function Clear _ -> None | SceneGraph sg -> sg.GlobalPicks( Ag.Scope.Root) |> Some)
1203
+
1204
+ let globalNeeded = globalPicks |> ASet.collect AMap.keys
1205
+ let treeNeeded = trees |> AList.toASet |> ASet.collect ( fun t -> t.Needed)
1206
+ let needed = ASet.union globalNeeded treeNeeded
1207
+
1208
+
1209
+ let rec pickTrees ( trees : list < PickTree < 'msg >>) ( evt ) =
1210
+ match trees with
1211
+ | [] -> false , Seq.empty
1212
+ | x:: xs ->
1213
+ let consumed , msgs = pickTrees xs evt
1214
+ if consumed then true , msgs
1215
+ else
1216
+ let consumed , other = x.Perform evt
1217
+ consumed, Seq.append msgs other
1218
+
1219
+ let proc =
1220
+ { new SceneEventProcessor< 'msg>() with
1221
+ member x.NeededEvents = needed
1222
+ member x.Process ( source : Guid , evt : SceneEvent ) =
1223
+ let trees = trees.Content |> AVal.force |> IndexList.toList
1224
+ seq {
1225
+ let consumed , msgs = pickTrees trees evt
1226
+ yield ! msgs
1227
+
1228
+ for perScene in globalPicks.Content |> AVal.force do
1229
+ let picks = perScene.Content |> AVal.force
1230
+ match picks |> HashMap.tryFind evt.kind with
1231
+ | Some cb ->
1232
+ yield ! cb evt
1233
+ | None ->
1234
+ ()
1235
+ }
1236
+ }
1237
+
1238
+ DomNode.RenderControl( attributes, proc, getState, scene, htmlChildren)
1239
+
1007
1240
1008
1241
type Unpersist < 'model , 'mmodel > =
1009
1242
{
0 commit comments