12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485(* Experimental *)(* We create a Box widget whose image will be a snapshot of a given room. *)(* The texture is initialized at the startup event, or upon user call. *)(* In order to achieve this, we hijack the Layout.display function, which uses
blits in layers, and render the layers to a target texture. Hence the
assumption is that the layers blits are empty. This means that creating
snapshots should NOT be done in a separate thread: the risk is to corrupt
layers in case it is called at the same time as the Bogue.render function. *)(* Just in case, we have added a mutex to the current_layer. but still... *)(* When we create the widget, the size of the box may not be the same as the
size of the widget at the time it receives the startup event... *)(* TODO: we have trouble rendering correctly when the room background has alpha
channel... ? use the new https://wiki.libsdl.org/SDL_ComposeCustomBlendMode??
*)(* Warning: a new texture is created at every update, because size might
change. TODO add an option in case we want to be fast and reuse the same
texture? *)openTsdlopenB_utilsmoduleLayout=B_layoutmoduleWidget=B_widgetmoduleVar=B_varmoduleTrigger=B_triggermoduleDraw=B_drawmoduleBox=B_boxmoduleStyle=B_stylemoduleSync=B_syncletupdatewidgetroom=letrenderer=Layout.rendererroominletw,h=Layout.get_physical_sizeroominletx,y=Layout.(getxroom,getyroom)inlettarget=Draw.create_targetrendererwhinprintddebug_graphics"Rendering snapshot...";Var.protectDraw.current_layer;(* Now we assume that the blits are empty... TODO check this and issue an
error otherwise *)Layout.display~pos0:(-x,-y)room;letsave=Draw.push_targetrenderertargetinDraw.render_all_layers(Layout.get_layerroom);Var.releaseDraw.current_layer;Draw.pop_targetrenderersave;printddebug_graphics"...rendering snapshot done.";(* essai blur *)(* let target = Draw.blur_texture renderer target 24 in *)letbox=Widget.get_boxwidgetindo_option(Var.getbox.Box.render)Draw.forget_texture;Var.setbox.Box.render(Sometarget)letcreate?borderroom=letw,h=Layout.get_sizeroominletstyle=Style.create?border()inletbox=Widget.box~w~h~style()in(* let c = Widget.connect_main box box (fun w _ _ -> update w room) *)(* [Trigger.startup] in *)(* Widget.add_connection box c; *)Sync.push(fun()->updateboxroom);box(* should be called after graphics init *)letsurfaceroom=letw,h=Layout.get_sizeroominletbox=Widget.box~w~h()inupdateboxroom;letbox=Widget.get_boxboxinletrenderer=Layout.rendererroominmatchVar.getbox.Box.renderwith|None->printd(debug_graphics+debug_error)"Cannot create surface because Box has no texture (yet).";None|Sometex->Some(Draw.surface_from_texturerenderertex)(* should be called after graphics init *)letto_cursor?hot_x?hot_yroom=map_option(surfaceroom)(funsurf->letw,h=Sdl.get_surface_sizesurfinlethot_x=defaulthot_x(w/2)inlethot_y=defaulthot_y(h/2)ingo(Sdl.create_color_cursorsurf~hot_x~hot_y))