Advertisement
Guest User

Untitled

a guest
Mar 2nd, 2017
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Julia 17.82 KB | None | 0 0
  1. # Code for generating a Julia OpenGL model that plots the landscape for a fixed
  2. # value of parameter a and animated moving "ant" trajectories onto the model
  3. # from a subset of the simulations.
  4. include("ode_simulator.jl")
  5. using ODESimulator;
  6. ## Example of widgets put into container with change handler assigned
  7.  
  8. using Tk
  9. using Compat; import Compat.String
  10.  
  11.  
  12. function readVari(seq)
  13.  readV_res = []
  14.  vari = split(seq,",")
  15.  for i=1:length(vari)
  16.    push!(readV_res,replace(vari[i]," ",""))
  17.  end
  18.  return readV_res
  19. end
  20.  
  21. function readIni(seq)
  22.   resul = split(replace(seq," ",""),"=")
  23.   s_deal=replace(resul[length(resul)],"(","")
  24.   s_deal=replace(s_deal,")","")
  25.   s_deal=replace(s_deal,"[","")
  26.   s_deal=replace(s_deal,"]","")
  27.   s_dealMore=split(s_deal,",")
  28.   if contains(s_dealMore[1],".")==0
  29.      s_dealMore[1]=s_dealMore[1] * ".0"
  30.   end
  31.   if contains(s_dealMore[2],".")==0
  32.      s_dealMore[2]=s_dealMore[2] * ".0"
  33.   end
  34.   return "(" * s_dealMore[1] * "," * s_dealMore[2] * ")"
  35. end
  36.  
  37. function readPara(seq)
  38.    seq=replace(replace(seq," ",""),",","\n")
  39.    return seq
  40. end
  41.  
  42. function readInterv(seq)
  43.   resul = split(replace(seq," ",""),"=")
  44.   s_deal=replace(resul[length(resul)],"(","")
  45.   s_deal=replace(s_deal,")","")
  46.   s_dealMore=split(s_deal,",")
  47.   if contains(s_dealMore[1],".")==0
  48.      s_dealMore[1]=s_dealMore[1] * ".0"
  49.   end
  50.   if contains(s_dealMore[2],".")==0
  51.      s_dealMore[2]=s_dealMore[2] * ".0"
  52.   end
  53.   return "(" * s_dealMore[1] * "," * s_dealMore[2] * ")"
  54. end
  55.  
  56. function subinfunc(seq)
  57.    funclist=split(seq,"@")
  58. end
  59.  
  60. function replace_plus(seq,rpstr,tostr)
  61.   k=searchindex(seq,rpstr)
  62.   while k!=0
  63.      if (k>1)
  64.         if ((k-1+length(rpstr))==length(seq))
  65.           if ((isalpha(seq[k-1]) == false) & (seq[k-1] != "_"))
  66.              seq=replace(seq,rpstr,"#T#",1)
  67.            else
  68.              seq=replace(seq,rpstr,"#F#",1)
  69.           end
  70.         else
  71.           if ((isalpha(seq[k+length(rpstr)]) == false) & (seq[k+length(rpstr)] != "_") & (isalpha(seq[k-1]) == false) & (seq[k-1] != "_"))
  72.             seq=replace(seq,rpstr,"#T#",1)
  73.           else
  74.             seq=replace(seq,rpstr,"#F#",1)
  75.           end
  76.         end
  77.       else
  78.         if ((isalpha(seq[k+length(rpstr)] )== false) & (seq[k+length(rpstr)] != "_"))
  79.            seq=replace(seq,rpstr,"#T#",1)
  80.          else
  81.            seq=replace(seq,rpstr,"#F#",1)
  82.         end
  83.      end
  84.    k=searchindex(seq,rpstr)
  85.   end
  86.  
  87.   seq=replace(seq,"#T#",tostr)
  88.   seq=replace(seq,"#F#",rpstr)
  89.   return seq
  90. end
  91.  
  92. function reformatEq(dVariable,eqSet)
  93.  allEqs=[]
  94.  strDeal=""
  95.  strDealLR = []
  96.  combStr=""
  97.  combFunc=""
  98.  t_sym=[]
  99.  eqtReads=[]
  100.  dt="t"
  101.  for i = 1 : length(eqSet)
  102.     t_sym=[]
  103.     eqtReads=[]
  104.     strDeal = eqSet[i]
  105.     eqtReads=split(strDeal,"=")
  106.     t_sym=split(eqtReads[1],"/")
  107.     if length(t_sym)>1
  108.        dt = t_sym[2]
  109.        combStr = combStr * replace(strDeal," ","") * "@"
  110.      else
  111.        combFunc = combFunc * replace(strDeal," ","") * "@"
  112.     end
  113.  end
  114.  combStr=combStr[1:(length(combStr)-1)]
  115.  for c = 1:length(dVariable)
  116.     combStr=replace_plus(combStr,dVariable[c],"u[" * string(c) * "]")
  117.     combStr=replace_plus(combStr,"d"*dVariable[c],"du[" * string(c) * "]")
  118.     combStr=replace_plus(combStr,dt,"dt")
  119.     combStr=replace_plus(combStr,"/dt","")
  120.  end
  121.  print(replace(combFunc,"@","\n"))
  122.  print(replace(combStr,"@","\n"))
  123.  return replace(combFunc,"@","\n") * replace(combStr,"@","\n")
  124. end
  125.  
  126.  
  127.  
  128. w = Toplevel("DE Input", true)
  129.  
  130. ## pack in tk frame for themed widgets
  131. f = Frame(w)
  132. configure(f, @compat Dict(:padding => [3,3,2,2], :relief=>"groove"));pack(f, expand=true, fill="both")
  133. #tcl("pack", "propagate", w, false)
  134. ## widgets
  135.  
  136. Save  = Button(f, "Save")
  137.  
  138. Vari=Entry(f,"x,y") #The variables
  139. Para=Entry(f,"a=1,b=2")
  140. Bound=Entry(f,"b=(0,5)")
  141. TimeR=Entry(f,"t=(0,1000)")
  142. Itera=Entry(f,"1000")
  143. DLabel=Label(f,"Differential Equations:")
  144. Equations=Entry(f,"dx/dt=x+y dy/dt=x*y")
  145. eqt=Text(f)
  146. widgets = (Vari,Para,Bound,TimeR,Itera,DLabel,eqt, Save)
  147. pack_style = ["pack", "grid", "formlayout"][3]
  148.  
  149. if pack_style == "pack"
  150.     map(pack, widgets)
  151.     map(u -> pack_configure(u, @compat Dict(:anchor => "w")), widgets)
  152. elseif pack_style == "grid"
  153.     for i in 1:length(widgets)
  154.         grid(widgets[i], i, 1)
  155.         grid_configure(widgets[i], @compat Dict(:sticky => "we"))
  156.     end
  157. else
  158.     formlayout(Vari,"Variables:")
  159.     formlayout(Para,"Parameters:")
  160.     formlayout(Bound,"Boundary:")
  161.     formlayout(TimeR,"TimeRange:")
  162.     formlayout(Itera,"Iterations:")
  163.     formlayout(eqt,"Equations",)
  164.     formlayout(Save,"")
  165. end
  166.  
  167. function CreatModel(path)
  168.     println("PASS THE TEST")
  169.     str_vari = get_value(Vari)
  170.     str_para = get_value(Para)
  171.     str_bound = get_value(Bound)
  172.     str_time = get_value(TimeR)
  173.     str_eqt = get_value(eqt)
  174.     input_runs = get_value(Itera)
  175.     input_vari = readVari(str_vari)
  176.     input_para = readPara(str_para)
  177.     input_time = readInterv(str_time)
  178.     input_bound = readIni(str_bound)
  179.     input_eqt = reformatEq(input_vari,split(str_eqt,"\n"))
  180.     func = "function(" * "t,u,du" * ")" * "\n" * input_para *"\n" * input_eqt * "\n" * "end"
  181.     fc=eval(parse(func))
  182.     set_func(fc)
  183.     set_visible(w,false)
  184. end
  185.  
  186. bind(Save, "command" ,CreatModel)
  187. ## bind a callback to each widget
  188.  
  189. set_visible(w,false)
  190.  
  191.  
  192. F = function (t,x)
  193.   a = 0.3
  194.   n = 4
  195.   S = 0.5
  196.   k = b = 1
  197.   F1 = (x1, x2) ->
  198.     (a*(x1^n)/(S^n + x1^n) + b*S^n/(S^n + x2^n) - k*x1)
  199.   F2 = (x1, x2) ->
  200.     (a*(x2^n)/(S^n + x2^n) + b*S^n/(S^n + x1^n) - k*x2)
  201.   return [F1(x[1], x[2]), F2(x[1], x[2])]
  202. end
  203.  
  204. using DataFrames
  205. runs = 100 # Number of simulation runs
  206. n = 2 # Number of dimensions
  207. using Reactive
  208. new_data = ODESimulator.build_landscape(runs, F, 2, (0,5))
  209. new_data
  210. data_s = Signal(new_data)
  211.  
  212. function set_func(func)
  213.   global bool_click = true
  214.   global runs
  215.   new_data = ODESimulator.build_landscape(runs, func , 2, (0,5))
  216.   global data_s
  217.   println(new_data)
  218.   push!(data_s, new_data)
  219. end
  220.  
  221. using KernelDensity, Interpolations, DataFrames, Reactive;
  222.  
  223. # TODO: Button for this.
  224. #scale_factor_s = Signal(5.0) # Scale for xy grid.
  225. # TODO: Button for this.
  226. # Factor has to be between 0 and 1!
  227. ant_speed_factor = 0.1f0
  228. # TODO: Button for this?
  229. trace_length = 10
  230. # TODO: Button.
  231. #ant_count_s = Reactive.Signal(10)
  232.  
  233. # Returns the data for producing a landscape for the dimensions corresponding to
  234. # dim1 and dim2. Returns either the entire trajectory or the endpoints only,
  235. # depending on the value of is_endpoint.
  236. function getXYdata(data, is_endpoint, dim1, dim2)
  237.   if (!is_endpoint)
  238.     # Get the trajectory coordinates for plotting along the entire trajectory.
  239.     # Note: indexing at (dim+1) since first column represents the time value.
  240.     X = convert(Array{Float64},deepcopy(data[dim1+1]));
  241.     Y = convert(Array{Float64},deepcopy(data[dim2+1]));
  242.   else
  243.     # Get the endpoint trajectory coordinates.
  244.     X = Float64[]
  245.     Y = Float64[]
  246.     for i = 1:runs
  247.       # Extract the rows in the DataFrame where the run index is i.
  248.       # Note: indexing at (dim+1) since first column represents the time value.
  249.       current_run = data[data[4].==i,:]
  250.       push!(X, current_run[end, dim1+1])
  251.       push!(Y, current_run[end, dim2+1])
  252.     end
  253.   end
  254.   return X, Y
  255. end
  256.  
  257. # TODO: Specify types of X, Y
  258. # Calculates the landscape heights from X-Y simulation data. Returns a 2D array,
  259. # either the probability density or the log density, depending on the is_log
  260. # argument. It also returns the sampling grid for the X-Y axes.
  261. function get_heights(X, Y, is_log, scale_factor)
  262.   # Change to X, Y for alternative plotting.
  263.   dens= kde((X, Y))
  264.   dens_plus_background=1e-23*ones(size(dens.density))+dens.density
  265.   log_dens=-log(dens_plus_background)
  266.   log_dens=log_dens-maximum(log_dens)
  267.   gx = scale_factor*LinSpace(dens.x)
  268.   gy = scale_factor*LinSpace(dens.y)
  269.  
  270.   # Convert everything from Float64 to Float32, as required by GLVisualize.
  271.   dens = convert(Array{Float32, 2}, dens.density)
  272.   log_dens = convert(Array{Float32, 2}, log_dens)
  273.   gx = convert(LinSpace{Float32}, gx)
  274.   gy = convert(LinSpace{Float32}, gy)
  275.   return gx, gy, (is_log ? log_dens : dens)
  276. end
  277.  
  278. # Plot the landscape and animate the trajectory with ants.
  279. using GLVisualize, GLAbstraction, ModernGL, Reactive, GeometryTypes, Colors, GLWindow
  280. using Interpolations
  281. import GLVisualize: labeled_slider, mm, button, toggle_button
  282.  
  283. # Eliminate identical consecutive points and keep only one copy of each.
  284. function dedup_consecutives(traj)
  285.   if (length(traj) == 0)
  286.     return traj
  287.   end
  288.   dedup_traj = Point3f0[traj[1]]
  289.   for i = 2:length(traj)
  290.     if (traj[i] != traj[i-1])
  291.       println("push 3")
  292.       push!(dedup_traj, traj[i])
  293.     end
  294.   end
  295.   return dedup_traj
  296. end
  297.  
  298. function get_x_node_matrix(gx, gy)
  299.   repmat(gx, 1, length(gy))
  300. end
  301.  
  302. function get_y_node_matrix(gx, gy)
  303.   repmat(transpose(gy), length(gx), 1)
  304. end
  305.  
  306. # Extract ant trajectories as 2D array depending on the signals for surface,
  307. # dimensions to plot and number of ants.
  308. function get_ant_lines(data, surf, dim1, dim2, ant_count, scale_factor)
  309.   println("Updating here 2")
  310.   gx, gy, dens = surf
  311.   # Get 10 of the simulations to draw as ants.
  312.   ant_lines = []
  313.   for i = 1:ant_count
  314.     # Extract the rows in the DataFrame where the run index is i.
  315.     current_run = data[data[end].==i,:]
  316.     t_data = current_run[1]
  317.     x_data = current_run[dim1+1]
  318.     y_data = current_run[dim2+1]
  319.     x_spl = interpolate((t_data, ), x_data, Gridded(Linear()))
  320.     y_spl = interpolate((t_data, ), y_data, Gridded(Linear()))
  321.     tmin = minimum(t_data)
  322.     tmax = maximum(t_data)
  323.     # TODO: control or refine the # of interpolation points (1000 too much?)
  324.     tspan = linspace(tmin, tmax, 500)
  325.     # Extract the trajectory as an array of 3D points.
  326.     ant_line = Point3f0[]
  327.     for t in tspan
  328.       x = Float32(scale_factor*x_spl[t])
  329.       y = Float32(scale_factor*y_spl[t])
  330.       i = indmin(abs(gx-x))
  331.       j = indmin(abs(gy-y))
  332.       z = dens[i,j]
  333.       println("push 1")
  334.       push!(ant_line, Point(gx[i], gy[j], z))
  335.     end
  336.     println("push 2")
  337.     push!(ant_lines, dedup_consecutives(ant_line))
  338.   end
  339.   println("done")
  340.   return ant_lines
  341. end
  342.  
  343. function visualize_trajectory(ant_lines)
  344.   max_traj = maximum(map(length, ant_lines))
  345.   timesignal = preserve(loop((trace_length):max_traj))
  346.   return preserve(map(timesignal) do t
  347.       traj = Point3f0[]
  348.       for i = 1:length(ant_lines)
  349.         # Only add point if t is within trajectory bounds.
  350.         # If t exceeds the bound, plot last element
  351.         last_pos = (t <= length(ant_lines[i])) ? t : length(ant_lines[i])
  352.         append!(traj, [ant_lines[i][last_pos]])
  353.       end
  354.       traj
  355.     end)
  356. end
  357.  
  358. bool_click = true
  359. window = glscreen()
  360. iconsize = 8mm
  361. assets_path = string(homedir(), "/Documents/Stem-Cell-Landscapes/assets/");
  362.  
  363. # Create partitioned window for controls and view screens.
  364. editarea, viewarea = x_partition_abs(window.area, 180)
  365. # Further partition edit area to get a logo area.
  366. editarea, logoarea = y_partition(editarea, 85)
  367. logoarea
  368. edit_screen = Screen(
  369.     window, area = editarea,
  370.     color = RGBA{Float32}(0.0f0, 0.0f0, 0.0f0, 1f0))
  371. view_screen = Screen(
  372.     window, area = viewarea,
  373.     color = RGBA(255.0f0, 255.0f0, 255.0f0, 1f0),
  374.     stroke = (1f0, RGBA{Float32}(0.13f0, 0.13f0, 0.13f0, 13f0)))
  375. logo_screen = Screen(
  376.     window, area = logoarea,
  377.     color = RGBA{Float32}(0.0f0, 0.0f0, 0.0f0, 1f0))
  378.  
  379.  
  380.  
  381. iconsize = 8mm
  382. knob_size = 5mm
  383. icon_size_signal = Reactive.Signal(iconsize)
  384.  
  385. #TODO: delete this
  386. #function get_slider_length(units)
  387. #  Measures.Length{:mm,Float64}(min(max_slider_length, units*knob_size/2))
  388. #end
  389.  
  390. ant_count_v, ant_count_s = labeled_slider(1:runs, edit_screen;
  391.   slider_length = 8*iconsize,
  392.   icon_size = icon_size_signal,
  393.   knob_scale = knob_size)
  394. dim1_v, dim1_s = labeled_slider(1:n, edit_screen;
  395.   slider_length = 4*iconsize,
  396.   icon_size = icon_size_signal,
  397.   knob_scale = knob_size)
  398. dim2_v, dim2_s = labeled_slider(1:n, edit_screen;
  399.   slider_length = 4*iconsize,
  400.   icon_size = icon_size_signal,
  401.   knob_scale = knob_size)
  402. scale_factor_v, scale_factor_s = labeled_slider(0.5:0.5:5.0, edit_screen;
  403.   slider_length = 8*iconsize,
  404.   icon_size = icon_size_signal,
  405.   knob_scale = knob_size)
  406.  
  407. on_button_img = loadasset(string(assets_path, "on.png"))
  408. off_button_img = loadasset(string(assets_path, "off.png"))
  409. logo_img = loadasset(string(assets_path, "waddle.png"))
  410. button_img = loadasset(string(assets_path, "Input.png"))
  411. button_obj, button_s = GLVisualize.button(
  412.   button_img, edit_screen)
  413. endpoint_v, endpoint_s = toggle_button(
  414.   on_button_img, off_button_img, edit_screen)
  415. log_dens_v, log_dens_s = toggle_button(
  416.   on_button_img, off_button_img, edit_screen)
  417. shading_v, shading_s = toggle_button(
  418.   on_button_img, off_button_img, edit_screen)
  419.  
  420. controls = Pair[
  421.     "Endpoints only" => endpoint_v,
  422.     "Negative log density" => log_dens_v,
  423.     "Shading" => shading_v,
  424.     "Dimension 2" => dim2_v,
  425.     "Dimension 1" => dim1_v,
  426.     "Ant count" => ant_count_v,
  427.     "XY scale factor" => scale_factor_v,
  428.     "DE input" => button_obj]
  429.  
  430. _view(visualize(
  431.         controls,
  432.         text_scale = 5mm,
  433.         gap = 3mm,
  434.         width = 10iconsize), edit_screen, camera = :fixed_pixel)
  435.  
  436. size(logo_img)
  437.  
  438. click_sig = map(button_s) do clicked
  439.    if clicked
  440.      global bool_click=false
  441.      set_visible(w,true)
  442.    end
  443. end
  444.  
  445. logo_signal = map(logoarea) do a
  446.   padding = 10
  447.   img_w = size(logo_img)[1]
  448.   img_h = size(logo_img)[2]
  449.   [Point2f0(padding + img_w/2,
  450.     -padding + a.h - img_h/2)]
  451. end
  452.  
  453.  
  454.  
  455. logo_vis = visualize((SimpleRectangle(0,0,size(logo_img)[1], size(logo_img)[2]),
  456.   logo_signal), image=logo_img)
  457. #println(_value(logoarea))
  458. _view(logo_vis, logo_screen, camera=:fixed_pixel)
  459.  
  460. #logo_text = visualize(
  461. #    "Waddle",
  462. #    relative_scale=16mm,
  463. #    color = RGBA(1f0, 1f0, 1f0, 1f0))
  464. #_view(logo_vis, logo_screen, camera=:fixed_pixel)
  465. ########### Done setting up sidebar. ##########
  466.  
  467. # Signal for the XY data used for landscaping.
  468. XY_signal = map(endpoint_s, dim1_s, dim2_s, data_s) do is_endpoint, dim1, dim2, data
  469.   println("Updating 1");
  470.   getXYdata(data, is_endpoint, dim1, dim2)
  471. end
  472.  
  473. # Important to use the grid and density as a single signal that updates at the
  474. # same time. Computing ant lines replies on having the correct grid for heights.
  475. surface_signal = map(XY_signal, log_dens_s, scale_factor_s) do xy, is_log, scale
  476.   get_heights(xy[1], xy[2], is_log, scale)
  477. end
  478.  
  479. red_color = RGBA(255.0, 0.0, 0.0, 1.0)
  480.  
  481. # Obtain signal for the sphere radius, since we want to scale the ant spheres to
  482. # be proportional with the scale of the XY grid.
  483. sphere_radius_s = const_lift(*, scale_factor_s, 0.05f0)
  484. ant_sphere_s = map(sphere_radius_s) do sphere_radius
  485.   GLNormalMesh(Sphere{Float32}(Vec3f0(0), sphere_radius))
  486. end
  487.  
  488. # If the number of ants changes, we need to clear the window and re-render all
  489. # objects, since the number of ants to re-render needs to be constant, even
  490. # though positions can change.
  491. traces_obj = map(ant_count_s) do ant_count
  492.   ant_lines = const_lift(get_ant_lines, data_s, surface_signal, dim1_s, dim2_s,
  493.     ant_count, scale_factor_s)
  494.   # Get signal for ant position animation based on ant_lines and a time signal.
  495.   ant_positions_s = map(visualize_trajectory, ant_lines)
  496.   ant_positions_s = flatten(ant_positions_s,
  497.     typ=Array{FixedSizeArrays.Point{3, Float32},1})
  498.  
  499.   visualize(
  500.     (ant_sphere_s, ant_positions_s),
  501.     boundingbox=nothing,
  502.     color=red_color)
  503. end
  504.  
  505. # Code to color wells.
  506. include("landscape_colouring.jl")
  507.  
  508. # Separate the surface signal into x, y, z matrices for GLVisualize.
  509. surf_obj = map(surface_signal, shading_s) do surf, is_shaded
  510.   gx = get_x_node_matrix(surf[1], surf[2])
  511.   gy = get_y_node_matrix(surf[1], surf[2])
  512.   dens = surf[3]
  513.  
  514.   # Prepare mesh vertex positions and texture.
  515.   positions = Point3f0[Point3f0(gx[i,j], gy[i,j], dens[i,j])
  516.     for i = 1:length(surf[1]) for j = 1:length(surf[2])]
  517.   z_color, color_count = LandscapeColouring.color_landscape(surf[3],
  518.     Reactive.value(log_dens_s)) # looking for minima if log_dens_s is true
  519.  
  520.   # When shading is not on, introduce some transparency.
  521.  
  522.   transparency = is_shaded ? 1.0 : 0.8
  523.   # Get 'Rainbow' colorscheme
  524.   colors = RGBA{Float32}[
  525.     RGBA(
  526.         clamp(min(4x - 1.5, -4x + 4.5) ,0.0,1.0),
  527.         clamp(min(4x - 0.5, -4x + 3.5) ,0.0,1.0),
  528.         clamp(min(4x + 0.5, -4x + 2.5) ,0.0,1.0), transparency)
  529.     for x in linspace(0.0,1.0, color_count)]
  530.  
  531.  
  532.   #texture = RGBA{Float32}[RGBA{Float32}(colors[z_color[i]])
  533.   #  for i = 1:length(z_color)]
  534.  
  535.   l1 = size(z_color)[1]
  536.   l2 = size(z_color)[2]
  537.  
  538.   texture = map(c->colors[c], z_color)
  539.   # Plot mesh as vertices with specific colours.
  540.   visualize((Circle, positions), boundingbox=nothing)
  541.   # Plot as smooth surface with colored wells.
  542.  
  543.   #=view_screen.color = is_shaded ?
  544.     RGBA{Float32}(255.0,255.0,255.0,1.0) :
  545.     RGBA{Float32}(0.0,0.0,0.0,1.0)
  546.   view_screen.stroke = is_shaded ?
  547.     (1f0, RGBA{Float32}(255.0,255.0,255.0,1.0)) :
  548.     (1f0, RGBA{Float32}(0.13f0, 0.13f0, 0.13f0, 13f0))
  549.   visualize((gx, gy, dens), color=texture, :surface, shading=is_shaded)=#
  550. end
  551. # Re-render every time the surface or number of ants changes.
  552. preserve(map(surf_obj, traces_obj) do surf_obj, traces_obj
  553.   empty!(view_screen)
  554.   _view(surf_obj, view_screen, camera=:perspective)
  555.   _view(traces_obj, view_screen, camera=:perspective)
  556. end)
  557.  
  558.  
  559. function My_renderloop(window::Screen, framerate = 1//60)
  560.     global bool_click
  561.     while isopen(window)
  562.       if bool_click ==true
  563.         tic()
  564.         render_frame(window)
  565.         swapbuffers(window)
  566.         poll_glfw()
  567.         yield()
  568.         GLWindow.sleep_pessimistic(framerate - toq())
  569.       else #
  570.         tic()
  571.         render_frame(window)
  572.         swapbuffers(window)
  573.         poll_glfw()
  574.         yield()
  575.         GLWindow.sleep_pessimistic((framerate - toq())*100)
  576.       end
  577.     end
  578.     destroy!(window)
  579.     return
  580. end
  581.  
  582.  #
  583.  
  584. My_renderloop(window)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement