clean up signals propperly

This commit is contained in:
SimonDanisch 2016-11-14 18:25:03 +01:00
parent 22f12316ef
commit e2a4a1e2ea

View File

@ -98,8 +98,33 @@ end
# GLPlot.init() # GLPlot.init()
# end # end
const _glplot_deletes = [] const _glplot_deletes = []
function close_child_signals!(screen)
for child in screen.children
for (k, s) in child.inputs
empty!(s.actions)
end
for (k, cam) in child.cameras
for f in fieldnames(cam)
s = getfield(cam, f)
if isa(s, Signal)
close(s, false)
end
end
end
empty!(child.cameras)
close_child_signals!(child)
end
return
end
function empty_screen!(screen) function empty_screen!(screen)
if isempty(_glplot_deletes) if isempty(_glplot_deletes)
close_child_signals!(screen)
empty!(screen)
empty!(screen.cameras)
for (k, s) in screen.inputs
empty!(s.actions)
end
empty!(screen) empty!(screen)
else else
for del_signal in _glplot_deletes for del_signal in _glplot_deletes
@ -113,38 +138,67 @@ function poll_reactive()
# run_till_now blocks when message queue is empty! # run_till_now blocks when message queue is empty!
Base.n_avail(Reactive._messages) > 0 && Reactive.run_till_now() Base.n_avail(Reactive._messages) > 0 && Reactive.run_till_now()
end end
function create_window(plt::Plot{GLVisualizeBackend}, visible)
# init a screen
if isempty(GLVisualize.get_screens())
screen = GLVisualize.glscreen("Plots.jl", resolution = plt[:size], visible = visible)
Reactive.stop()
@async begin
while isopen(screen) function get_plot_screen(list::Vector, name, result = [])
tic() for elem in list
GLWindow.poll_glfw() get_plot_screen(elem, name, result)
if Base.n_avail(Reactive._messages) > 0
poll_reactive()
poll_reactive() # two times for secondary signals
GLWindow.render_frame(screen)
GLWindow.swapbuffers(screen)
end
yield()
diff = (1/60) - toq()
while diff >= 0.001
tic()
sleep(0.001) # sleep for the minimal amount of time
diff -= toq()
end
end
# empty message queue
poll_reactive()
GLWindow.destroy!(screen)
end
else
screen = GLVisualize.current_screen()
empty_screen!(screen)
end end
return result
end
function get_plot_screen(screen, name, result = [])
if screen.name == name
push!(result, screen)
return result
end
get_plot_screen(screen.children, name, result)
end
function create_window(plt::Plot{GLVisualizeBackend}, visible)
name = Symbol("Plots.jl")
screen = if isempty(GLVisualize.get_screens())
# create a fresh, new screen
parent = GLVisualize.glscreen(
"Plot",
resolution = plt[:size],
visible = visible
)
@async GLWindow.waiting_renderloop(parent)
screen = GLWindow.Screen(parent,
name = name,
area = map(identity, parent.area)
)
for (k, s) in screen.inputs # copy signals, so we can clean them up better
screen.inputs[k] = map(identity, s)
end
screen
else
plot_screens = get_plot_screen(GLVisualize.get_screens(), name)
if isempty(plot_screens)
parent = GLVisualize.current_screen()
empty!(parent)
inputs = Dict{Symbol, Any}()
for (k, s) in parent.inputs # copy signals, so we can clean them up better
inputs[k] = map(identity, s)
end
screen = GLWindow.Screen(parent,
name = name,
area = map(identity, parent.area)
)
for (k, s) in screen.inputs # copy signals, so we can clean them up better
screen.inputs[k] = map(identity, s)
end
screen
elseif length(plot_screens) == 1
plot_screens[1]
else
# okay this is silly! Lets see if we can. There is an ID we could use
# will not be fine for more than 255 screens though -.-.
error("multiple Plot screens. Please don't use any screen with the name Plots.jl")
end
end
# Since we own this window, we can do deep cleansing
empty_screen!(screen)
plt.o = screen plt.o = screen
GLWindow.set_visibility!(screen, visible) GLWindow.set_visibility!(screen, visible)
resize!(screen, plt[:size]...) resize!(screen, plt[:size]...)
@ -161,6 +215,8 @@ const _gl_marker_map = KW(
:xcross => '❌', :xcross => '❌',
:utriangle => '▲', :utriangle => '▲',
:dtriangle => '▼', :dtriangle => '▼',
:ltriangle => '◀',
:rtriangle => '▶',
:pentagon => '⬟', :pentagon => '⬟',
:octagon => '⯄', :octagon => '⯄',
:star4 => '✦', :star4 => '✦',
@ -937,12 +993,15 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
theta = _3d ? nothing : Signal(Vec3f0(0)) # surpress rotation for 2D (nothing will get usual rotation controle) theta = _3d ? nothing : Signal(Vec3f0(0)) # surpress rotation for 2D (nothing will get usual rotation controle)
GLAbstraction.PerspectiveCamera( GLAbstraction.PerspectiveCamera(
sp_screen.inputs, Vec3f0(3), Vec3f0(0), sp_screen.inputs, Vec3f0(3), Vec3f0(0),
keep=inside, theta=theta keep = inside, theta = theta
) )
end end
rel_plotarea = Plots.bbox_to_pcts(plotarea(sp), sw, sh) rel_plotarea = Plots.bbox_to_pcts(plotarea(sp), sw, sh)
model_m = map(Plots.to_modelmatrix, screen.area, sub_area, Signal(rel_plotarea), Signal(sp)) model_m = map(Plots.to_modelmatrix,
screen.area, sub_area,
Signal(rel_plotarea), Signal(sp)
)
for ann in sp[:annotations] for ann in sp[:annotations]
x, y, plot_text = ann x, y, plot_text = ann
txt_args = Dict{Symbol, Any}(:model => eye(GeometryTypes.Mat4f0)) txt_args = Dict{Symbol, Any}(:model => eye(GeometryTypes.Mat4f0))
@ -1305,9 +1364,12 @@ function label_scatter(d, w, ho)
if isa(p, GLNormalMesh) if isa(p, GLNormalMesh)
bb = GeometryTypes.AABB{Float32}(GeometryTypes.vertices(p)) bb = GeometryTypes.AABB{Float32}(GeometryTypes.vertices(p))
bbw = GeometryTypes.widths(bb) bbw = GeometryTypes.widths(bb)
if isapprox(bbw[3], 0)
bbw = Vec3f0(bbw[1], bbw[2], 1)
end
mini = minimum(bb) mini = minimum(bb)
m = GLAbstraction.translationmatrix(-mini) m = GLAbstraction.translationmatrix(-mini)
m *= GLAbstraction.scalematrix(1f0./bbw) m *= GLAbstraction.scalematrix(1 ./ bbw)
kw[:primitive] = m * p kw[:primitive] = m * p
kw[:scale] = Vec3f0(w/2) kw[:scale] = Vec3f0(w/2)
delete!(kw, :offset) delete!(kw, :offset)